From 5a1fff50302d648bd1cb838c0607f0a7663290ff Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Sat, 4 Jul 2026 14:19:56 +0200 Subject: [PATCH 1/6] =?UTF-8?q?chore(skills):=20drop=20find-skills=20?= =?UTF-8?q?=E2=80=94=20unused,=20and=20its=20update=20step=20began=20timin?= =?UTF-8?q?g=20out?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RC fix (soak day 1): `make update` step 7.5 failed on a 300s clone timeout of alchaincyf/find-skills. The skill (search the skills.sh registry from Claude) was never used; the discovery case stays reachable manually via `npx -y skills find `. Removed from install-plugins.sh (install list + summary + comment), update-all.sh (refresh list), link.sh (NPX_EXTERNAL_SKILLS), lib/toggle-external.sh (MANAGED_TOOLS + case arms), plugin-advisor.md, .gitignore; local skills/find-skills symlink deleted. Memory-registry and test-fixture mentions kept — append-only history. toggle-external `list` verified post-removal; suites 8/8. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01XpphkdTosUzokBDNG7PToS --- .gitignore | 1 - CHANGELOG.md | 3 +++ agents/plugin-advisor.md | 6 +++--- install-plugins.sh | 4 +--- lib/toggle-external.sh | 11 +++++------ link.sh | 2 +- update-all.sh | 1 - 7 files changed, 13 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 1f2bfe5..cd80599 100644 --- a/.gitignore +++ b/.gitignore @@ -68,7 +68,6 @@ skills/impeccable # External skills installed via `npx skills add` — auto-created by link.sh skills/darwin-skill -skills/find-skills # Context7 docs-lookup skill — installed by `ctx7 setup --claude --cli` # (install-plugins.sh Step 6, when absent) into ~/.claude/skills (a symlink to diff --git a/CHANGELOG.md b/CHANGELOG.md index a153cf7..ab1b498 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,9 @@ Format follows [Keep a Changelog](https://keepachangelog.com/). - `gitflow_finish` ignored its ` ` arguments and always merged the checked-out branch — naming a different branch silently merged the wrong one. The arguments are now an optional safety assertion: if given and not equal to the current branch, `finish` refuses with a clear error instead of merging. No-argument calls (the only real caller) are unchanged. - `doctor.sh` false-warnings removed (a check that cries wolf is one you learn to ignore): `cargo` absence no longer claims "RTK unavailable" (RTK ships as a prebuilt binary); `check_symlink` no longer flags files reached through directory-level symlinks (e.g. `hooks/session-start.sh`); the GStack check counts the per-skill symlinks instead of a `skills/gstack` link that `link.sh` deliberately removes; the token-budget estimate is measured against the ~200k context window instead of a mis-framed "~11k session budget" that produced a false "92% CRITICAL". +### Removed +- **find-skills** (alchaincyf) — skill-discovery helper dropped from the toolchain (install/update/link/toggle/advisor). Never used, and its `make update` refresh step had started failing on clone timeouts. The discovery use case stays reachable manually: `npx -y skills find `. + ## [4.0.0] — 2026-06-30 ### Added diff --git a/agents/plugin-advisor.md b/agents/plugin-advisor.md index 701aa0b..35998a6 100644 --- a/agents/plugin-advisor.md +++ b/agents/plugin-advisor.md @@ -19,7 +19,7 @@ Detect active plugins and project signals. Recommend enable/disable. Apply compa claude plugin list 2>/dev/null || echo "plugin-list-unavailable" # External (non-marketplace) tools status — gstack, emil-design-eng, -# darwin-skill, find-skills. Managed by lib/toggle-external.sh since +# darwin-skill. Managed by lib/toggle-external.sh since # `claude plugin enable|disable` does not apply to them. bash "$HOME/.claude/lib/toggle-external.sh" list 2>/dev/null || echo "toggle-external-unavailable" @@ -353,8 +353,8 @@ RULE: IF `complex-arch` signal (multiple services, event bus, distributed system ## TOGGLING EXTERNAL TOOLS Marketplace plugins toggle via `claude plugin enable|disable @`. -Non-marketplace tools (gstack per-skill symlinks, emil-design-eng, darwin-skill, -find-skills) toggle via `bash $HOME/.claude/lib/toggle-external.sh enable|disable `. +Non-marketplace tools (gstack per-skill symlinks, emil-design-eng, darwin-skill) +toggle via `bash $HOME/.claude/lib/toggle-external.sh enable|disable `. When a recommendation flips the state of one of those tools, emit the exact command — never write files directly. diff --git a/install-plugins.sh b/install-plugins.sh index 4f501ab..d492991 100644 --- a/install-plugins.sh +++ b/install-plugins.sh @@ -832,7 +832,6 @@ echo "" NPX_SKILLS=( "alchaincyf/darwin-skill" - "alchaincyf/find-skills" ) # `skills add` resolves its target (.agents/skills/, skills-lock.json) RELATIVE @@ -985,7 +984,7 @@ echo "" # STEP 10 — REFRESH SYMLINKS (final, so this script is self-sufficient) # ============================================================ # Steps 2/8/8.5 INSTALL skills (gstack submodule, emil/frontend/motion, npx -# darwin/find-skills) that link.sh must symlink into ~/.claude/skills/. Since +# darwin-skill) that link.sh must symlink into ~/.claude/skills/. Since # link.sh runs BEFORE this script in install.sh, those symlinks would be missing # on a fresh run until link.sh is run again by hand. Re-run it here so # `make plugin` (and `make install`) finish complete — nothing left to do. @@ -1023,7 +1022,6 @@ echo " 🔄 frontend-design — distinctive frontend interfaces, anti-AI- echo " 🔄 impeccable — /impeccable design verbs + 45-rule deterministic detector (npx impeccable detect)" echo " 🔄 design-motion-principles — motion/animation design, 3-designer lens (kylezantos)" echo " 🔄 darwin-skill — autonomous skill optimizer (npx skills, ~/.agents/skills/)" -echo " 🔄 find-skills — skill discovery helper (npx skills, ~/.agents/skills/)" echo " 🔄 magic MCP — 21st-dev UI generation MCP (toggle: lib/toggle-external.sh enable magic)" echo "" echo " All plugins installed at: user scope (~/.claude/plugins/)" diff --git a/lib/toggle-external.sh b/lib/toggle-external.sh index ca76e63..c291439 100755 --- a/lib/toggle-external.sh +++ b/lib/toggle-external.sh @@ -20,7 +20,6 @@ # gstack — per-skill symlinks populated by gstack's own setup # emil-design-eng — single symlink → skills-external/emil-design-eng # darwin-skill — single symlink → ~/.agents/skills/darwin-skill -# find-skills — single symlink → ~/.agents/skills/find-skills # magic — 21st-dev Magic MCP server (API key in .env) # # For fine-grained activation (only design skills, only qa skills, only @@ -41,7 +40,7 @@ warn() { echo -e "${YELLOW}⚠${NC} $1"; } err() { echo -e "${RED}✗${NC} $1"; } # All non-plugin tools this script can toggle. -MANAGED_TOOLS=(gstack emil-design-eng darwin-skill find-skills magic) +MANAGED_TOOLS=(gstack emil-design-eng darwin-skill magic) # Load MAGIC_API_KEY (and any other secrets) from $REPO/.env if present. # Called only by the magic branch — other tools don't need env vars. @@ -81,7 +80,7 @@ status_tool() { [ -d "$REPO/skills-external/emil-design-eng" ] || { echo "missing"; return; } [ -e "$SKILLS_DIR/emil-design-eng" ] && echo "enabled" || echo "disabled" ;; - darwin-skill|find-skills) + darwin-skill) [ -d "$HOME/.agents/skills/$tool" ] || { echo "missing"; return; } [ -e "$SKILLS_DIR/$tool" ] && echo "enabled" || echo "disabled" ;; @@ -116,7 +115,7 @@ disable_tool() { done < <(gstack_skills) ok "gstack disabled ($moved symlinks moved)" ;; - emil-design-eng|darwin-skill|find-skills) + emil-design-eng|darwin-skill) if [ -e "$SKILLS_DIR/$tool" ]; then rm -rf "${DISABLED_DIR:?}/${tool:?}" mv "$SKILLS_DIR/$tool" "$DISABLED_DIR/$tool" @@ -158,11 +157,11 @@ enable_tool() { ok "gstack enabled ($moved symlinks restored)" fi ;; - emil-design-eng|darwin-skill|find-skills) + emil-design-eng|darwin-skill) local src case "$tool" in emil-design-eng) src="$REPO/skills-external/$tool" ;; - darwin-skill|find-skills) src="$HOME/.agents/skills/$tool" ;; + darwin-skill) src="$HOME/.agents/skills/$tool" ;; esac if [ -e "$DISABLED_DIR/$tool" ]; then rm -rf "${SKILLS_DIR:?}/${tool:?}" diff --git a/link.sh b/link.sh index f46590b..d7ffc99 100644 --- a/link.sh +++ b/link.sh @@ -90,7 +90,7 @@ done # absolute paths so the link stays valid regardless of where the # repo is cloned (relative ../../ paths broke on repos deeper than # one level below $HOME). -NPX_EXTERNAL_SKILLS=(darwin-skill find-skills) +NPX_EXTERNAL_SKILLS=(darwin-skill) for _ext in "${NPX_EXTERNAL_SKILLS[@]}"; do _target="$HOME/.agents/skills/$_ext" _link="$REPO/skills/$_ext" diff --git a/update-all.sh b/update-all.sh index 2a0b5d2..ba40d72 100644 --- a/update-all.sh +++ b/update-all.sh @@ -388,7 +388,6 @@ echo "── Updating external skills (npx skills)..." if command -v npx &>/dev/null; then NPX_SKILLS=( "alchaincyf/darwin-skill" - "alchaincyf/find-skills" ) for _src in "${NPX_SKILLS[@]}"; do _name="${_src##*/}" From ce07e55e9815642723a06bf7f844c6ef46b0fbfa Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Sat, 4 Jul 2026 14:24:25 +0200 Subject: [PATCH 2/6] =?UTF-8?q?fix(update):=20TTY-guard=20the=20gstack=20p?= =?UTF-8?q?rompt=20=E2=80=94=20non-interactive=20runs=20died=20at=20EOF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RC fix (soak day 1, #3). `read -r` on the "Proceed with GStack update?" prompt hits EOF in any non-TTY run (cron, CI, background shell) and kills the whole update under set -e — every later step (rtk, gsd, ctx7, semgrep, npx skills) silently never ran. Guard on [ -t 0 ]: interactive behavior unchanged, non-TTY defaults to the safe N and continues. Proven end-to-end: before = Error 1 at the prompt; after = full run exit 0 through step 7.5. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01XpphkdTosUzokBDNG7PToS --- update-all.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/update-all.sh b/update-all.sh index ba40d72..b7063f1 100644 --- a/update-all.sh +++ b/update-all.sh @@ -65,8 +65,16 @@ echo "" echo "── Updating GStack submodule..." warn "GStack tracks branch = main (no commit hash). Review upstream commits before updating." echo "" -printf " Proceed with GStack update? [y/N] " -read -r _gstack_confirm +# TTY guard: in a non-interactive run (cron, CI, background shell) `read` +# hits EOF and dies under set -e — the whole update aborted mid-script. +# Default to the safe N and keep going; interactive behavior unchanged. +if [ -t 0 ]; then + printf " Proceed with GStack update? [y/N] " + read -r _gstack_confirm +else + info "Non-interactive run — skipping GStack update (run in a terminal to be prompted)" + _gstack_confirm="n" +fi if [[ "$_gstack_confirm" =~ ^[Yy]$ ]]; then # Capture gstack state before the update so we can restore it after # ./setup runs (setup re-creates every symlink; without this, an From 3049250150389fe5e72a07aa23ad70ff43a1db28 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Sat, 4 Jul 2026 15:00:44 +0200 Subject: [PATCH 3/6] =?UTF-8?q?fix(update):=20rtk=20step=20=E2=80=94=20sou?= =?UTF-8?q?rce=20cargo=20env=20+=20install-by-tag=20version=20guard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RC fix (soak day 1, #4). Two stacked defects: (1) update-all.sh never sourced ~/.cargo/env (unlike install-plugins.sh), so on a profile that lost the cargo PATH line the rtk step printed "Cargo not available" forever — rtk never updated via make update (BLK-016 class). (2) once cargo was found, the "latest" branch ran a bare `cargo install --git` (default-branch HEAD) and would have recompiled Rust on EVERY update: upstream's HEAD Cargo.toml (0.42.4) trails its newest stable tag (v0.43.0), so any tag-vs-installed comparison never converges against a HEAD build. Fix: source cargo env before concluding cargo is absent; resolve the newest STABLE tag by name (sed anchored on refs/tags/v?N.N.N$ — dev-N.N.N-rc.* pre-releases excluded; a naive version grep had picked dev-0.44.0-rc.308), install BY TAG, and skip when installed == target. Proven live both ways: run 1 compiled v0.43.0 (?tag=v0.43.0#5a7880d4), run 2 skipped ("already at latest tag (0.43.0)"). Pinned-version branch gets the same skip-on-match guard. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01XpphkdTosUzokBDNG7PToS --- update-all.sh | 50 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/update-all.sh b/update-all.sh index b7063f1..318bde5 100644 --- a/update-all.sh +++ b/update-all.sh @@ -125,6 +125,13 @@ fi # ── 3. Update RTK (if pinned version available) ── echo "" echo "── Updating RTK..." +# cargo lives in ~/.cargo/bin, which hand-managed profiles lose (BLK-016 +# class) — source cargo env, as install-plugins.sh does, before concluding +# cargo is absent. Without this the step silently never updated rtk. +if ! command -v cargo &>/dev/null && [ -f "$HOME/.cargo/env" ]; then + # shellcheck disable=SC1091 + source "$HOME/.cargo/env" +fi if command -v cargo &>/dev/null; then RTK_VERSION="" if [ -f "$REPO/plugins.lock.json" ] && command -v python3 &>/dev/null; then @@ -136,21 +143,44 @@ print(d.get('rtk',{}).get('version','')) " 2>/dev/null || true) fi + # Version-jump guard: a cargo build takes minutes — only pay it when the + # target (pin, or the newest remote tag for "latest") differs from what is + # installed. Same pin-honored/skip-on-match shape as the semgrep step. + RTK_CUR=$(rtk --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true) + [ -z "$RTK_CUR" ] && RTK_CUR=$("$HOME/.cargo/bin/rtk" --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true) + if [ -n "$RTK_VERSION" ] && [ "$RTK_VERSION" != "latest" ]; then - info "Pinned version: $RTK_VERSION" - info "Compiling from source — this may take a few minutes..." - if cargo install --git https://github.com/rtk-ai/rtk --tag "$RTK_VERSION" --force; then - ok "RTK updated to $RTK_VERSION" + if [ "${RTK_VERSION#v}" = "$RTK_CUR" ]; then + ok "rtk already at pinned $RTK_CUR" else - warn "RTK update failed" + info "Pinned version: $RTK_VERSION (installed: ${RTK_CUR:-none})" + info "Compiling from source — this may take a few minutes..." + if cargo install --git https://github.com/rtk-ai/rtk --tag "$RTK_VERSION" --force; then + ok "RTK updated to $RTK_VERSION" + else + warn "RTK update failed" + fi fi else - info "No pinned version — installing latest" - info "Compiling from source — this may take a few minutes..." - if cargo install --git https://github.com/rtk-ai/rtk --force; then - ok "RTK updated (latest)" + # "latest" = newest release TAG, resolved by name and installed BY TAG. + # (A bare `cargo install --git` builds the default-branch HEAD, whose + # Cargo.toml version can trail the newest tag — the guard would then + # never converge and recompile on every run.) + RTK_TIP_TAG=$(git ls-remote --tags https://github.com/rtk-ai/rtk 2>/dev/null \ + | sed -n 's|.*refs/tags/\(v\{0,1\}[0-9][0-9.]*\)$|\1|p' | sort -V | tail -1 || true) + RTK_TIP="${RTK_TIP_TAG#v}" + if [ -n "$RTK_TIP" ] && [ "$RTK_TIP" = "$RTK_CUR" ]; then + ok "rtk already at latest tag ($RTK_CUR)" else - warn "RTK update failed" + info "No pin — latest tag: ${RTK_TIP_TAG:-unknown} (installed: ${RTK_CUR:-none})" + info "Compiling from source — this may take a few minutes..." + if [ -n "$RTK_TIP_TAG" ] && cargo install --git https://github.com/rtk-ai/rtk --tag "$RTK_TIP_TAG" --force; then + ok "RTK updated to $RTK_TIP_TAG" + elif [ -z "$RTK_TIP_TAG" ] && cargo install --git https://github.com/rtk-ai/rtk --force; then + ok "RTK updated (latest HEAD — no tag resolvable)" + else + warn "RTK update failed" + fi fi fi else From 82ce02cf28f678351fa65249746efd7d262daf37 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Sat, 4 Jul 2026 15:01:12 +0200 Subject: [PATCH 4/6] chore(skills): sync design-motion-principles from upstream (make update) Vendored-skill content refreshed by update-all.sh step 8 during the soak update runs: demo-shell + output-format reworked upstream, new report-template.html reference. Content-only, no wiring change. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01XpphkdTosUzokBDNG7PToS --- .../references/demo-shell.html | 365 +++--- .../references/output-format.md | 561 ++++----- .../references/report-template.html | 1006 +++++++++++++++++ 3 files changed, 1431 insertions(+), 501 deletions(-) create mode 100644 skills-external/design-motion-principles/references/report-template.html diff --git a/skills-external/design-motion-principles/references/demo-shell.html b/skills-external/design-motion-principles/references/demo-shell.html index 647755c..0914dd7 100644 --- a/skills-external/design-motion-principles/references/demo-shell.html +++ b/skills-external/design-motion-principles/references/demo-shell.html @@ -1,63 +1,77 @@ @@ -65,144 +79,197 @@ Demo Shell — design-motion-principles + + + -
-
↻ looping
-
Recommended motion title
-
300ms · ease-out
-
+
+ + + +
+
+ Recommended motion title + 300ms · ease-out +
+
+
+ + + +
+ ↻ +
+
+
- - (motion preview renders here per finding) - + a card, an icon, a row of items for stagger demos, a number, + a badge, etc.). All inner UI primitives use the stage tokens + (--st-fg / --st-bg / --st-line / --st-dim) — NEVER page tokens. --> +
+
+
Placeholder
+
+ + (motion preview renders here per finding) +
+
+
-
+ diff --git a/skills-external/design-motion-principles/references/output-format.md b/skills-external/design-motion-principles/references/output-format.md index 124d538..f0ea8c9 100644 --- a/skills-external/design-motion-principles/references/output-format.md +++ b/skills-external/design-motion-principles/references/output-format.md @@ -1,19 +1,28 @@ # Output Format -This file defines the audit's two output modes: +The audit produces one of two outputs: -- **HTML mode (default)** — a self-contained `.html` file written to the audited project's `motion-audits/` directory and opened in the user's default browser. Each Critical or Important finding gets an auto-looping CSS demo card beside it. -- **Terminal mode (flag-triggered)** — the decorated-markdown report rendered inline in the conversation. Use when the user passes `--terminal`, `--inline`, "show the full report inline," "skip the HTML," or any natural-language equivalent. No HTML file is written. +- **HTML mode (default)** — a self-contained `.html` file written to the audited project's `motion-audits/` directory and opened in the user's default browser. Each Critical or Important finding gets a live, looping CSS demo card beside it. +- **Terminal mode (flag-triggered)** — a decorated-markdown report rendered inline in the conversation. Use when the user passes `--terminal`, `--inline`, `--no-html`, "show the full report inline," or any natural-language equivalent. No HTML file is written. -The two modes contain the same audit content; only the rendering differs. Do not summarize — users want full per-lens perspectives. +Both modes carry the same audit content; only the rendering differs. Do not summarize — users want full per-lens perspectives. --- ## HTML mode +### Canonical references + +| File | Role | +|---|---| +| `references/report-template.html` | **Source of truth.** Full worked example (fictional "Tally" habit tracker, React + Framer Motion). Every section, every token, every pattern. When in doubt about layout, structure, or styling, READ this file. | +| `references/demo-shell.html` | Minimal isolated example of a single demo card with the per-finding slot pattern. Used as a per-finding template snippet. | + +The agent builds the report by reading these two files and adapting them to the audited project — same architecture, audit-specific content. + ### File structure -The HTML output is a single self-contained `.html` document with everything inlined — no external CSS, no external JS, no external fonts (fonts may degrade gracefully if a CDN reference is used). The file scaffolds: +Single self-contained `.html`. All CSS inlined. No external JS. Fonts loaded via Google Fonts CDN (Familjen Grotesk / Public Sans / Geist Mono) with full system-stack fallbacks so the file degrades gracefully offline. ``` @@ -22,310 +31,233 @@ The HTML output is a single self-contained `.html` document with everything inli {project-name} motion audit — {ISO date} + + + - + + - - - + + + + + + ``` -### Report's own motion posture +### Design system -The report itself has **no** entrance, scroll, or mount animations. No staggered reveals, no fade-in-on-scroll, no motion-on-mount outside the demo cards. The demo cards are the only animated elements in the document — anything else would reproduce the AI-slop patterns the skill audits against. +Neutral-default, dual-mode, severity-driven. -### Hero header +- **Neutrals.** Cool slate-graphite at hue 255, very low chroma (0.003–0.010). `--ink` is the page background; `--paper` is the foreground text. In light mode the two swap values via the `:root:has(#theme-light:checked)` override — every other token derives from these two and flips automatically. +- **Severity (FIXED, never adaptive).** Red `oklch(0.655 0.185 25)` (critical) · Amber `oklch(0.805 0.125 78)` (important) · Green `oklch(0.745 0.135 152)` (opportunity). Light-mode counterparts deepen L for contrast on white; hues stay constant. +- **Timing-budget ramp (FIXED).** Same hues as severity; used in section 02 only. Instant + responsive = green, deliberate = amber, sluggish = red. +- **Accent (NEUTRAL by default).** `--accent`, `--accent-soft`, `--accent-tint` alias to `--paper`, `--paper-dim`, and a low-alpha paper tint. The report has no chromatic primary color — severity is the only color in the document. An individual audit MAY repoint these three to a sampled brand color, but ONLY if the brand has at least ~40° hue clearance from each of the severity hues and is verified not to fall in the AI-cliché zone (neon cyan, purple-to-blue gradients). +- **Fonts.** Display = Familjen Grotesk, body = Public Sans, mono = Geist Mono. The mono carries timing values (`240ms · ease-out`) and all small labels — never substitute a more generic mono for the timing values. -Top of the document. Project name + ISO date + severity counts row + primary lens label. +### Dual theme -```html -
-

{project-name} motion audit

-

{ISO date}

-

- 🔴 Critical: {N} · - 🟡 Important: {N} · - 🟢 Opportunities: {N} -

-

Primary: {Designer Name} — {Perspective Handle}

-
+Pure-CSS toggle. Two radios (`#theme-dark` default-checked, `#theme-light`) live inside `.theme-switch` at the top of `.wrap`. `:root:has(#theme-light:checked)` overrides every theme-dependent token. No JS. Selector compatibility: `:has()` is Baseline 2023, supported by all modern browsers. + +The global toggle's visual control is a segmented `Dark / Light` pill, top-right of the page, styled to match the per-demo stage segmented control. + +### The report's motion posture + +**The report itself has no entrance, scroll, or mount animation.** No staggered reveals. No fade-in-on-scroll. No motion on mount outside the demo cards. The demo cards are the only animated elements in the document — anything else would reproduce the AI-slop patterns this skill audits against. + +The one allowed transition: `border-color 0.2s ease` on lens-table rows and finding-rows for hover feedback. That's it. + +### Sections (in render order) + +#### Global theme switch +First element inside `.wrap`, right-aligned segmented `Dark / Light` pill. + +#### Header +``` +.eyebrow ("MOTION AUDIT · DESIGN-MOTION-PRINCIPLES") +h1.title ({project name} — {one-line audit framing}) +p.lede ({1–2 sentence project description}) +.meta-row (what it is · stack) +.stats (Findings · Critical · Important · Opportunities — each is an anchor link to its rec table) ``` -The severity counts pair each emoji with a text label (`Critical: N`, not just `🔴 N`) so the severity signal is readable under red-green color vision deficiency. Each count is an anchor link to the corresponding section in the body — this is the navigation affordance for long audits with many findings. +Each severity count pairs the number with a text label so the signal is readable under red-green color vision deficiency. Each count is an anchor link (`#rec-crit`, `#rec-imp`, `#rec-opp`) to the corresponding recommendation table. -### Overall Assessment +#### Overall Assessment +One short paragraph in larger display type. Does this feel polished? Too much? Too little? What's working, what's not? Wraps in `
` with a `mono-label` "OVERALL" eyebrow. -One short paragraph in larger type. Does this feel polished? Too much? Too little? What's working, what's not? +#### 01 · Lens summary +3-row table, one row per practitioner. Columns: Lens (with name and weight chip) · Verdict (`Strong` / `Concern` / `Problem` / `Mixed` with a colored dot) · One-line read. Weight chips indicate `Primary` / `Secondary` / `Selective` per audit context. -```html -
-

{one-paragraph assessment}

-
+#### 02 · Where the timings land — duration-budget diagram +Motion-native analog of thumb-first's thumb-zone diagram. A horizontal SVG (`viewBox="0 0 660 300"`) plots Tally's animations as numbered dots on a 0–600ms scale with four zone bands: + +| Zone | Range | Color | +|---|---|---| +| Instant | 0–100ms | green (`--t-good`) | +| Responsive | 100–300ms | green (`--t-good`) | +| Deliberate | 300–500ms | amber (`--t-mid`) | +| Sluggish | 500ms+ | red (`--t-slow`) | + +Animations with NO transition are plotted as hollow dashed circles at `x=40` (= 0ms). The paired key list to the right carries the action names and durations. A "What's off" block below explains the misalignments. + +The SVG uses CSS-class-driven fills (via an inline ` + + +
+ + +
+ + +
+ + +
+
+ + +
+
Motion audit · design-motion-principles
+

Tally — what to slow down, speed up, and finish

+

+ A pass over Tally's core loop — check-off, tab switches, the add-habit sheet, and the streak milestones — + read through three motion practitioners' lenses, ordered by what users feel most and the order to fix it. +

+
+
What it isHabit & streak tracker, used in quick daily bursts
+
StackMobile web · React + Framer Motion
+
+
+
7
Findings
+ + + +
+
+ + +
+ Overall +

+ Tally has real motion personality — but it's uneven. The highest-frequency action, the check-off, + is the most over-animated; the add-habit sheet that should glide just snaps shut. Tighten the frequent + moments toward speed, finish the half-built transitions, then spend delight where it's earned: the streaks. +

+
+ + +
+
01
+

How each practitioner reads the motion

+

+ Three lenses, weighted for this context — a frequently-opened utility where most motion should get out of + the way, and a little should be memorable. The read is what each would push on hardest today. +

+ + + + + + + + + + + + + + + + + + + +
LensVerdictOne-line read
Restraint & Speed Emil KowalskiSecondaryConcernThe check-off and tab switches are over-animated for actions this frequent — durations run long.
Production Polish Jakub KrehelPrimaryProblemSeveral transitions are half-built: enters without exits, state changes that snap. Craft is uneven.
Experimentation & Delight Jhey TompkinsSelectiveStrongRestraint is mostly right. The open prize is making the streak milestones actually feel earned.
+
+ + +
+
02
+

Where the timings land

+

+ Duration is a budget. A 320ms sheet is correct — a large surface earns the time. A 600ms tab switch on an + action you fire dozens of times a session is the mistake. Each dot is one of Tally's animations, plotted + where it runs today. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 100 + 300 + 500 + 600ms + + + + + INSTANT + RESPONSIVE + DELIBERATE + SLUGGISH + + + + + 5 + + + + + 3 + + 7 + + 6 + + 4 + + 2 + + 1 + + + + + fire most often + + +
+

The animations

+
    +
  1. 1Tab switch600ms
  2. +
  3. 2Check-off (bounce)450ms
  4. +
  5. 3Card hover lift80ms
  6. +
  7. 4Add-habit sheet enter320ms
  8. +
  9. 5Streak counter changenone
  10. +
  11. 6Page route250ms
  12. +
  13. 7Toast200ms
  14. +
+ +
+
Instant / Responsive · 0–300ms — where almost everything belongs. Taps, toggles, tabs, hovers.
+
Deliberate · 300–500ms — earned by large surfaces: sheets, modals, full-screen routes.
+
Sluggish · 500ms+ — feels laggy. Reserve for rare, deliberately cinematic moments — or nothing.
+
+ +
+ What's off +

The two dots furthest right — tab switch (1) and check-off (2) — are the actions that fire most. Frequency and duration are inversely related: the more often it runs, the faster it should be. And the streak counter (5) has no transition at all.

+
+
+
+
+ + +
+
03
+
+

Jakub Krehel — Production Polish

+ Primary lens +
+

Problem

+ +
+ What's working well +
    +
  • ✓Page routes use a clean opacity + 8px translate at 250ms — the right shape and duration. routes/transition.tsx:14
  • +
  • ✓Toasts enter and exit symmetrically — the exit isn't an afterthought. ui/Toast.tsx:31
  • +
+
+ +
+ Issues to address +
+ + +
+
+
CriticalJakub
+

The add-habit sheet enters, then snaps shut with no exit

+
+

WhatThe bottom sheet animates up on open (320ms, good), but on dismiss it's removed from the tree instantly — no exit. The component renders conditionally with no AnimatePresence wrapper, so Framer Motion never gets to play the exit.

+

Why it mattersA surface that glides in and vanishes reads as broken — the eye expects symmetry. It's the single most common "half-built motion" tell, and it's on the app's primary create flow.

+

Recommended motionWrap the sheet in AnimatePresence and mirror the enter: slide down + fade over 300ms with the same ease-out-quint. The demo shows the enter; the exit is its reverse.

+

screens/Habits/AddSheet.tsx:48

+
+
+
+ + + +
+
Sheet enter (mirror for exit)300ms · ease-out-quint
+
+
+ ↻ +
+
+
+
+
+
New habit
+
+ Drink water + Add +
+
+
+
+
+
+ + +
+
+
ImportantJakub
+

Streak counter jumps between values with no transition

+
+

WhatWhen a streak increments, the number is replaced in place — a hard swap. There's no transition on the value change, so the most rewarding number in the app updates with the least ceremony.

+

Why it mattersThe streak count is the payoff of the whole interaction. A snap makes a hard-won number feel like a re-render, not an achievement.

+

Recommended motionRoll the new value in: opacity + 10px translateY + a 5px blur that clears, 220ms. Subtle, but it tells the eye something changed and it's good.

+

components/StreakBadge.tsx:22

+
+
+
+ + + +
+
Number roll-in220ms · opacity + Y + blur
+
+
+ ↻ +
+
+
+
+
Current streak
+
7 days
+
+
+
+
+ +
+
+ +
+ Opportunities +
    +
  • 💡Habit cards lean on a drop shadow that's invisible on the dark theme — a 1px border would carry the elevation on both. components/HabitCard.tsx:9
  • +
+
+ +
+ Through Jakub's lens +

The vocabulary is right; the sentences are unfinished. Pair every enter with an exit, give the streak its moment, and Tally crosses from "animated" to "polished."

+
+
+ + +
+
04
+
+

Emil Kowalski — Restraint & Speed

+ Secondary lens +
+

Concern

+ +
+ What's working well +
    +
  • ✓Card hover lift is 80ms — instant, exactly right for a passive affordance. components/HabitCard.tsx:18
  • +
  • ✓No animation on keyboard-driven navigation — keyboard users aren't taxed with motion they didn't ask for.
  • +
+
+ +
+ Issues to address +
+ + +
+
+
CriticalEmil
+

Tab switches slide for 600ms — far too slow for the most frequent action

+
+

WhatThe four bottom tabs cross-slide the full panel width over 600ms with an ease-in-out. Tabs are the app's highest-frequency navigation; a 600ms slide means every switch holds the user behind an animation.

+

Why it mattersEmil's rule: the more often an action fires, the less it should animate. At this duration the motion stops being feedback and becomes a toll. ease-in-out also adds a slow start, compounding the lag.

+

Recommended motionDrop to a 180ms opacity crossfade with a 7px slide, ease-out. Better still: consider no slide at all — a fast crossfade is plenty of orientation for a tab.

+

navigation/TabView.tsx:63

+
+
+
+ + + +
+
Quick tab crossfade180ms · ease-out
+
+
+ ↻ +
+
+
+
+
Today
+
Morning walk
+
Read 10 pages
+
+
+
+
+ + +
+
+
ImportantEmil
+

Check-off pops from scale(0) with a spring bounce

+
+

WhatTicking a habit animates the checkmark from scale(0) with a bouncy spring (~450ms to settle). It's the app's core, most-repeated gesture, and it's the showiest animation in the product.

+

Why it mattersBounce on a high-frequency confirm gets tiring fast — the overshoot draws attention to motion the user has already mentally completed. Starting from scale(0) exaggerates the distance and the time.

+

Recommended motionScale 0.9 → 1 with opacity, 200ms ease-out, no overshoot. Confident and done before the finger lifts.

+

components/HabitCheck.tsx:27

+
+
+
+ + + +
+
Calm check, no bounce200ms · ease-out
+
+
+ ↻ +
+
+
+
+
Drink water
+
+
+
+
+ +
+
+ +
+ Through Emil's lens +

Speed up everything the user touches constantly. The tab switch and the check-off should feel instant; their current durations are the difference between an app that feels fast and one that feels fussy.

+
+
+ + +
+
05
+
+

Jhey Tompkins — Experimentation & Delight

+ Selective lens +
+

Strong

+ +
+ What's working well +
    +
  • ✓Tally resists the urge to animate everything — restraint is the right default for a daily utility. Delight is rationed, which makes room for it to land where it counts.
  • +
+
+ +
+ Issues to address +
+ + +
+
+
ImportantJhey
+

Hitting a milestone streak passes by with no celebration

+
+

WhatCrossing a 7-, 30-, or 100-day streak looks identical to any other day — the number just increments. The one moment in the app that has genuinely earned a flourish gets none.

+

Why it mattersThis is where delight pays for itself. A milestone is rare, emotionally loaded, and shareable — exactly the place to spend motion the rest of the app withholds. Skipping it leaves the payoff flat.

+

Recommended motionOn a milestone only: a badge that scales 0.8 → 1 (260ms ease-out) with a short, one-shot sparkle burst. Fires once on the event — not a looping pulse.

+

components/StreakBadge.tsx:40

+
+
+
+ + + +
+
Milestone badge enter260ms · ease-out + sparkle
+
+
+ ↻ +
+
+
+
+
+ 7 + DAY +
+ + + + +
+
+
+
+ +
+
+ +
+ Opportunities +
    +
  • 💡The today-list could stagger its rows in on first paint — 30ms apart, opacity + 6px rise. One orchestrated load beats scattered micro-interactions. screens/Today.tsx:51
  • +
+
+ +
+ Through Jhey's lens +

Don't add more motion — add it in one right place. The streak milestone is the moment worth engineering; everywhere else, keeping your hands off the controls is the sophisticated move.

+
+
+ + +
+
06
+

In the order I'd fix them

+

+ Ordered by what users feel: critical (degrades the core loop on every use) → important + (real friction or a missed payoff) → opportunity (could enhance). +

+ +
+
Critical · must fix2
+ + + + + + +
IssueFileFix
Tab switch runs 600ms on the highest-frequency actionTabView.tsx:63180ms opacity crossfade + 7px slide, ease-out
Add-habit sheet has no exit — snaps shutAddSheet.tsx:48Wrap in AnimatePresence; mirror the 300ms enter on exit
+
+ +
+
Important · should fix3
+ + + + + + + +
IssueFileFix
Check-off pops from scale(0) with a bounceHabitCheck.tsx:27scale 0.9→1 + opacity, 200ms ease-out, no overshoot
Streak counter swaps with no transitionStreakBadge.tsx:22220ms opacity + translateY + blur roll-in
Milestone streaks have no celebration momentStreakBadge.tsx:40One-shot badge scale-in + sparkle, milestones only
+
+ +
+
Opportunities · could enhance2
+ + + + + + +
EnhancementWhereImpact
Habit-card elevation invisible on dark themeHabitCard.tsx:91px border carries elevation on both themes
Today-list could stagger in on first paintToday.tsx:5130ms stagger, opacity + 6px rise — one orchestrated load
+
+
+ + +
+
07
+

Which lens carried this audit

+
+ Referenced most +

Jakub Krehel — Production Polish

+

Tally's gaps are craft gaps, not taste gaps: enters without exits, state changes that snap. That's Jakub's territory — finishing what's been started — so his lens drove the ordering. Emil set the durations; Jhey marked the one place to spend.

+
    +
  • Lean EmilTreat every duration as a budget. Push tab, check, and toggle timings under 200ms and question any motion on a high-frequency action.
  • +
  • Lean JakubAudit every conditional render for a missing exit. Pair enters and exits, and give meaningful state changes a transition.
  • +
  • Lean JheyPick the single highest-emotion moment — the milestone — and over-invest there, with @property, springs, or scroll-driven touches.
  • +
+
+
+ +
+ Tally motion audit · design-motion-principles + 7 findings · 2 critical · 3 important · 2 opportunities +
+ +
+ + From fcdb157cdde8a5df28416f89d5c89a3ce2035b82 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Sat, 4 Jul 2026 15:31:51 +0200 Subject: [PATCH 5/6] =?UTF-8?q?chore(lint):=20silence=20SC1091=20info=20no?= =?UTF-8?q?tes=20=E2=80=94=20shellcheck=20health=20stack=20exits=20clean?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hooks/session-start.sh | 2 +- install-plugins.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/hooks/session-start.sh b/hooks/session-start.sh index e5b7179..4411b7f 100644 --- a/hooks/session-start.sh +++ b/hooks/session-start.sh @@ -36,7 +36,7 @@ fi # ── Load shared detection library ── _lib="$(dirname "${BASH_SOURCE[0]}")/../lib/detect-plugins.sh" if [ -f "$_lib" ]; then - # shellcheck source=../lib/detect-plugins.sh + # shellcheck source=../lib/detect-plugins.sh disable=SC1091 source "$_lib" else echo "⚠️ lib/detect-plugins.sh not found — config broken, run: bash link.sh" diff --git a/install-plugins.sh b/install-plugins.sh index d492991..d114b3f 100644 --- a/install-plugins.sh +++ b/install-plugins.sh @@ -197,6 +197,7 @@ if command -v cargo &>/dev/null; then else info "Installing Rust (rustup)..." curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path + # shellcheck source=/dev/null source "$HOME/.cargo/env" ok "Rust installed: $(cargo --version)" fi From 8397354caab583b01c1de315ef8e335e294a692e Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Wed, 8 Jul 2026 17:22:52 +0200 Subject: [PATCH 6/6] =?UTF-8?q?chore(memory):=20backmerge=20=E2=80=94=20LR?= =?UTF-8?q?N-117=20fork=20orphans=20code=20+=20consolidated=20B=20journal?= =?UTF-8?q?=20+=20backlog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/memory/journal.md | 2 ++ .claude/memory/learnings.md | 8 ++++++++ .claude/tasks/TODO.md | 26 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/.claude/memory/journal.md b/.claude/memory/journal.md index 9b8860b..3709132 100644 --- a/.claude/memory/journal.md +++ b/.claude/memory/journal.md @@ -368,3 +368,5 @@ rules: - Adversarial review of the whole 9-job series (release/1.0.0..develop) → `.audit/review-release-1.0.0.md`: 1 BLOQUANT + 5 à corriger + 5 mineurs, 10 verified false-positives. 2 sub-agent verdicts overturned (job7 gitleaks hook inert [[LRN-114]], contract tool-grant FP [[LRN-115]]). Jobs 4/5/6/8 CLEAN, validator-analyzer contract SOUND. J4-16 follow-up above CLOSED: trailer twins found in bugfixer/feater/hotfixer. - Remediation `chore/review-remediation` (unmerged, human gate): A1 trailer purge (3 templates) + whole-surface sweep; A2 gitleaks hook re-installed (`install-hook`) + negative-secret gate proven; A4 strict-YAML quote (seo/security-auditor); A5 geo own-policy (user-approved, PERMISSIVE default kept, false CLAUDE.md attribution dropped); A8 path-b PROVEN — /seo+/geo AUTO items land on disk via L1 (no silent no-op); fil-rouge `lib/tests/run-review-guards.sh` (5 guards, teeth-verified); A3 backfill LRN-098/101 + EVAL-015 + BLK-016 + PORTED rtk fix e58037c (was live-broken on develop, ~460K tokens/30d); A6 guard 280→320 + [[BDR-062]] (supersede BDR-031's 275 target). make test GREEN throughout. - Capitalized: [[LRN-113]] partial-fix+guard (structural), [[LRN-114]] hook-drift, [[LRN-115]] analyzer report-grants (FP1), [[LRN-116]] release fix missing from develop, [[BDR-062]] density realign, [[EVAL-021]] the review, [[EVAL-022]] M5 pins trace. Noted un-back-merged release chores beyond A3: e65796f (SC1091 lint silence) — left for a future reconcile. +- Full back-merge release/1.0.0→develop (`chore/backmerge-release-full`, unmerged): the RC fork had left ~6 functional fixes orphaned on develop, silently. PORTED via cherry-pick, make test green each: `095d881` drop find-skills, `a1093ca` make-update TTY-guard (proven: EOF-die exit1 → guarded exit0), `4c5e862` rtk update-path version-guard (complements the `e58037c` install bridge already ported), `c76479f` design-motion sync, `e65796f` SC1091 lint. B soak journal (find-skills day1 / TTY #3 / rtk-update #4) folded here, not cherry-picked — divergent journal tails conflict (STOP-on-conflict honored, extract-consolidate fallback). C all covered/skip: `93e43c0` attribution + `ae8ad86` model already on develop; `188a9a7` docs → /doc backlog (README missing semgrep/scan-secrets/verify+secure/ctx7). Registry (LRN-098/101, EVAL-015, BLK-016) already backfilled in the review run. Gate: 23/23 release-only commits classified, 0 orphan functional, 0 missing registry; make test GREEN, review-guards 5/0. version.txt stays 4.0.0 (fork intentional, D — `eb93050`). +- [[LRN-117]]: the fork silently orphaned functional CODE on develop (not just memory); the review back-merge caught ~half. Detecting it needs a code-level drift check (advisory, backlogged) — registry-sequence gaps alone miss it. diff --git a/.claude/memory/learnings.md b/.claude/memory/learnings.md index a9838b0..411692f 100644 --- a/.claude/memory/learnings.md +++ b/.claude/memory/learnings.md @@ -132,6 +132,7 @@ rules: | LRN-114 | 2026-07-08 | editing a hook GENERATOR (_gitflow_emit_pre_commit) does NOT update the INSTALLED hook (.githooks/pre-commit) — silent drift; T10 diffs the allow/block verdict not content, T16 emits fresh in a throwaway repo → job7 gitleaks backstop inert on the repo 8 days | after editing a template-generated artifact: reinstall (install-hook) + a gate that diffs installed==emit | | LRN-115 | 2026-07-08 | analyzer Edit/Write grants (seo/geo/validator) are NOT dead: needed to write the REPORT (VALIDATE/SEO/GEO.md); the "never edit" rule targets CODE, instruction-level (same as the patron) — verified false-positive | do NOT re-flag as a tool-grant defect; a report-only agent keeps Write for its own report | | LRN-116 | 2026-07-08 | memory backfill release→develop: a BLK marked "resolved" can have its RESOLUTION (code) missing from develop — BLK-016 resolved on release but rtk fix e58037c never back-merged → bug LIVE on develop | before backfilling a resolved blocker: verify the fix CODE is on the target branch, not just the registry entry | +| LRN-117 | 2026-07-08 | a release/develop fork silently orphans FUNCTIONAL code on develop, not just memory — RC soak fixes (find-skills, make-update TTY, rtk version-guard) lived only on release for the fork's duration; the review's memory back-merge caught only ~half | at release-finish/reconcile: list develop..release commits touching non-registry code (excl. merges/version) for back-merge review — a registry-gap check alone misses code | --- @@ -1180,3 +1181,10 @@ rules: - **fix**: ported e58037c to develop (13-line idempotent bridge), THEN backfilled BLK-016 resolved. General: before backmerging a resolved blocker, grep the target for the fix's code signature. - **future application**: gitflow divergence review — enumerate release-only COMMITS that touch code, not just memory; a feature can be parallel-merged while its RC-branch fix is orphaned. - **cousin**: [[LRN-036]] (PATH profile drift), [[LRN-047]] (silent degradation). + +## LRN-117 — A release/develop fork silently orphans functional CODE on develop, not just memory +- **pattern**: cutting release/1.0.0 and continuing on develop, the RC-branch bug fixes (find-skills drop `095d881`, make-update TTY guard `a1093ca`, rtk update-path version-guard `4c5e862`, rtk install bridge `e58037c`, SC1091 lint `e65796f`) landed ONLY on release. They were live-broken on develop for the whole fork duration (rtk compression dead, `make update` dies non-interactively). The review's memory back-merge caught the registry gaps and one code fix (rtk bridge); a full back-merge found ~5 more functional commits. +- **why it hides**: registry-sequence gaps (missing LRN/BLK/EVAL ids) are easy to detect; orphaned CODE has no sequence to check. A feature can be parallel-merged to both branches while an RC-branch fix commit is never back-merged, and nothing flags it. +- **fix**: at release-finish / in /reconcile, list `develop..release/*` commits touching functional files (exclude merges, `.claude/**`, version.txt/CHANGELOG) and present them for back-merge review. Advisory, NOT a hard make-test gate — cherry-picks land with new SHAs so the source commit stays in the range; automatic "already-ported?" equivalence is unreliable and would false-positive. Backlogged. +- **future application**: any long-lived fork (release/*, long feature) — audit CODE divergence, not just declared/registry state ([[LRN-034]] narrated ≠ ground truth, applied to branches). +- **cousin**: [[LRN-116]] (a resolved blocker's fix can be missing from develop), [[BDR-054]] (supersession-trace discipline). diff --git a/.claude/tasks/TODO.md b/.claude/tasks/TODO.md index 6f0bdbb..c3550de 100644 --- a/.claude/tasks/TODO.md +++ b/.claude/tasks/TODO.md @@ -1,5 +1,31 @@ # TODO +## 2026-07-08 — full back-merge release/1.0.0→develop (chore/backmerge-release-full) +Genèse : la revue avait porté ~5/19 commits ; back-merge complet demandé. Cherry-pick par +catégorie, 1 commit atomique/item, make test après chaque code. Branche non mergée (gate humain). +- [x] A CODE (5 cherry-picks, make test GREEN chacun) : 095d881 drop find-skills (5a1fff5), + a1093ca TTY-guard make-update (ce07e55, prouvé EOF exit1→exit0), 4c5e862 rtk version-guard + (3049250, complète le pont e58037c déjà porté — fichiers/concerns distincts), c76479f + design-motion sync (82ce02c), e65796f SC1091 lint (fcdb157, shellcheck 0 SC1091). +- [x] B JOURNAL : cherry-pick direct conflicte (tails journal divergents) → STOP honoré, + fallback note consolidée sous journal 2026-07-08. TODO /deploy ca9fa8f skip (release-specific). +- [x] C DÉCISION/DOUBLON tous skip vérifiés : 93e43c0 attribution + ae8ad86 model (opus[1m]=Opus4.8) + déjà sur develop ; a623514/74d3804/2b4e740 registres déjà backfillés (run revue) ; + 188a9a7 docs → backlog /doc ci-dessous. +- [x] D fork version 1eb5b08/eb93050 intouchés — version.txt reste 4.0.0. +- [x] GATE FINAL : 23/23 commits release-only classifiés, 0 code orphelin, 0 entrée registre + manquante ; make test GREEN + review-guards 5/0. Capitalize [[LRN-117]] structurel. + +### Backlog (issu du back-merge) +- [ ] **/doc** — README develop ne documente pas semgrep / scan-secrets / verify+secure pipeline / + ctx7 (delta de 188a9a7, non porté car base README divergente job3 + CHANGELOG version-entangled). + Une passe /doc doit combler ces sujets sur le README réécrit de develop. +- [ ] **release-drift advisory** ([[LRN-117]]) — check qui liste les commits `develop..release/*` + touchant du CODE fonctionnel (exclut merges, `.claude/**`, version.txt/CHANGELOG) pour revue + de back-merge. Advisory, PAS un gate make-test dur : les cherry-picks landent avec de nouveaux + SHA → le commit source reste dans le range → équivalence "déjà porté ?" non fiable automatiquement + (faux positifs). Cible : étape release-finish ou /reconcile, pas run-review-guards. + ## 2026-07-08 — review remediation (chore/review-remediation) Genèse : `.audit/review-release-1.0.0.md` (revue adversariale des 9 jobs). GO user, ordre imposé. Déviation justifiée : 1 branche (pas 1/EP) car le gate fil-rouge (step 6)