Merge chore/job3-fixes into develop

This commit is contained in:
Bastien Chanot
2026-07-06 17:42:39 +02:00
29 changed files with 348 additions and 128 deletions
+10
View File
@@ -74,6 +74,7 @@ rules:
| BDR-050 | 2026-07-03 | universal pipeline (contract→dev inline→fresh verify→fresh security, loops bounded 3× in main loop) with per-flow weighting; hotfix failure = revert not loop | accepted |
| BDR-051 | 2026-07-04 | contract enrich-at-gate: the contract grows ONLY at a human micro-gate ([gated] marker); the verifier judges the ENRICHED contract, not the seed | accepted |
| BDR-052 | 2026-07-05 | /tour auto mode = branch-as-gate: no mid-run approval gates; unmerged chore branch + per-project TOUR.md = deferred human gate; reconcile report-only; loop bounded 3× | accepted |
| BDR-054 | 2026-07-06 | supersede BDR-038 NEXT.sh/hand-back artifacts — shipped impl removed both (52f6678, LRN-102) | accepted |
---
@@ -842,3 +843,12 @@ rules:
- **Rationale**: rule = ~490 tok/session session-start duplicate of the skill (job1 F10 + job2); skill self-suffices (876-char description carries the triggers, body has full CLI flow). Purge-in-installer beats one-shot rm: survives re-runs + manual `ctx7 setup`.
- **Alternatives rejected**: kill skill keep rule (rule always-on, costs every session even non-lib work; skill lazy — wrong direction); hand-trim generated files (fight the generator, LRN-039 class); hand-edit lock hash (algo undocumented).
- **Reference**: chore/ctx7-single-surface; job1 F10, job2 F8/F13. User decision 2026-07-06.
## BDR-054 — supersede BDR-038: NEXT.sh file + AskUserQuestion hand-back removed from /deploy
- **Date**: 2026-07-06
- **Status**: accepted (supersedes BDR-038 on 2 points: NEXT.sh artifact, hand-back mechanism)
- **Decision**: /deploy ships WITHOUT NEXT.sh file (checklist display-only, conversation-only) and WITHOUT AskUserQuestion hand-back (plain final-text print, turn ends, no tool call after). BDR-038's original 5-artifact list (PROCEDURE.md, INCIDENTS.md, STATE.json, PENDING.json, NEXT.sh) shrinks to 4 committed/bridge artifacts — NEXT.sh no longer written. Two-moment spine (BEFORE/AFTER), PENDING.json bridge, deploy-commit.sh atomic patch+incident — all unchanged, still current per BDR-038.
- **Why**: LRN-102 — deliverable text printed before a tool call may never render (harness guarantees only the turn's FINAL text); AskUserQuestion after the checklist swallowed it silently, live run 2026-07-05 (bchanot-cv). NEXT.sh-to-disk also useless in practice (user: throwaway once deployed) — display-only kills a stale-file-drift class for free.
- **Alternatives rejected**: keep NEXT.sh, fix hand-back only (leaves ephemeral-file-nobody-reads problem); keep AskUserQuestion, cram checklist into its options text (char-limited, brittle); revert to file+question (reproduces the exact LRN-102 bug).
- **Reference**: commits `31443ba` (inline hand-back print), `52f6678` (checklist display-only, no NEXT.sh); `skills/deploy/SKILL.md:74-77,295-297,313-318,440-441`; [[LRN-102]]; job3 docs-drift audit D6/D7/D9 (`.audit/job3-report.md`).
+10
View File
@@ -34,6 +34,7 @@ rules:
| EVAL-011 | 2026-06-30 | /reconcile build: RED contaminated→corrected (unguided control), GREEN behavioral confirmed, dogfooded on itself | keep |
| EVAL-012 | 2026-06-30 | /release-candidate build: RED (gitflow fans out, no tag) → GREEN 5/5 (tag), throwaway-repo flow replay | keep |
| EVAL-013 | 2026-06-30 | /reconcile real-usage on live repo: known gap + 2 unanticipated (header-marker drift class) + false-positive rejected off-fixture, 0 false assertion | keep |
| EVAL-018 | 2026-07-06 | job3 docs-drift audit + execution: 46/46 findings verified, 20/23 fixes shipped (B1 blocked, D2-D5+B6 skipped by decision), zero residual on re-sweep | keep |
---
@@ -169,3 +170,12 @@ rules:
- **result**: 15/17 REPRODUCED, 2 PARTIALLY (wording only: F3 "exactly 4"→4-of-54; F14 soft precondition existed). 0 discarded. Registry quotes 9/9 verbatim. Exact char counts 100% match (4840 total agents).
- **anomalies**: 3 explorer false claims, ALL about harness semantics not file content: (1) agents-explorer — `Agent` tool "non-canonical" + `memory:`/`effort:` frontmatter "invalid": wrong, all documented; (2) skills-explorer — skills/gstack/ "stray orphan": refuted by link.sh:54-57 deliberate plumbing; (3) guide agent — `[1m]` model suffix "invalid ANSI": refuted, /model writes it itself. File-content claims (counts, quotes, refs): zero errors.
- **action**: harness-semantics claims from explorers ALWAYS cross-check vs docs/live evidence; file-content claims reliable after one verify pass.
## EVAL-018 — job3 docs-drift audit + execution: 46/46 verified, 20/23 fixes shipped, zero residual
- **Date**: 2026-07-06
- **output**: `.audit/job3-report.md` — 46 findings (docs vs repo reality at defc26c), 19 diffs, execution prompt. 4 explorers (orchestrators/workflow-skills/web-skills/graphify+deploy+docs) + 6 fresh verifiers re-checked all 46 findings + 5 registry quotes (list+paths only). Then executed with user decisions injected: 20 commits on `chore/job3-fixes` (BDR-054 supersedes BDR-038 + banners, D1 deploy paths, C3 geo-analyzer path, onboard/init-project/profile/gitflow/close/client-handover/harden/seo/web-validate/depth-matrix bodies, README, session-start hook, memory templates, project-CLAUDE template, SETTINGS.md).
- **method**: verifiers blind to auditor reasoning; 3 killed mid-run by session limit, resumed from transcript, all completed. Post-fix: 3 fresh-context re-sweep verifiers (one per file group) confirmed old assertions gone + new text consistent with reality anchors; `make test` and `bash lib/tests/run-reconcile.sh` re-run to confirm no regression.
- **result**: 46/46 REPRODUCED pre-fix (3 corrected attributions). Post-fix re-sweep: 0 residual findings from job3's own edits (1 pre-existing minor abbreviation noted, informational only). `make test` all green. `run-reconcile.sh` unchanged 18 GREEN/2 RED (B1 deliberately untouched, see blocker below).
- **anomalies**: (1) B1 (reconcile fixture hermeticization) BLOCKED — `lib/tests/` is guarded by the same config-protection.sh gate as `hooks/`, and the user's sentinel pre-authorization was scoped only to `[SENTINEL-REQUIRED]` hook edits; the auto-mode classifier correctly refused the sentinel for a lib/tests/ write outside that scope. (2) Verification sweep incidentally surfaced 2 pre-existing, out-of-job3-scope drifts: `agents/client-handover-writer.md:885` still says "4-chapter structure" (contradicts its own lines 23-43 "6 chapters", predates job3); `.claude/memory/decisions.md` index has no row for BDR-053 (body exists, gap from job2).
- **action**: keep. B1 needs a follow-up session with explicit lib/tests/ sentinel authorization. The 2 incidental findings are candidates for a future audit-delta pass, not fixed here (out of scope).
+4
View File
@@ -340,3 +340,7 @@ rules:
- User GO full execution incl. 3 RISK: cp/mv→ask, find -exec deny mirror, settings.local prune (python3 -, rtk git *). F9 fable default committed (user re-chose via /model), F16 gitflow-migrate.sh removed (git-recoverable), F8/find-docs skip (generator-owned). Executor = Sonnet subagent on chore/job2-fixes, NO finish.
- job2 EXECUTED: 15 commits chore/job2-fixes, all diffs first-try, `make test` wired + first-ever full run ALL GREEN (gitflow 71/0). Measured −309 tok/session (agents 4840→3609 chars); design hook no longer fires on task-notifications. Executor STOP exercised for real: F4 gate red → root-caused to job1 oracle regression (3f639b3), fixed as [[LRN-104]]; 2nd YAML error/file unmasked (onboard/plugin-check) → closed 6a3b197. Skips: F8 (npx skills has no re-pin verb), find-docs (ctx7). Merged develop 964c5dd on user GO.
- job2 tail closed [[BDR-053]]: context7.md rule killed (file rm + installer purge, find-docs = single ctx7 surface, ~−490 tok/session more) + darwin lock entry dropped (F8). chore/ctx7-single-surface → develop, pushed. job1+job2 fully closed; total measured ≈ −800 tok/session.
- job3 docs-drift audit shipped read-only: `.audit/job3-report.md` — README/docs/templates/skill-bodies scope, 46 findings, 19 diffs base defc26c, 1 ⚠ DECISION-CONFLICT (BDR-038 vs shipped /deploy), all fresh-context verified [[EVAL-018]]. Explorer subagent ran `graphify .` mid-audit against read-only intent, self-corrected mid-run only after main-session correction — [[LRN-105]].
- User GO full execution, decisions injected: BDR-054 supersedes BDR-038 (NEXT.sh/hand-back removed) + banners on the 2 historical deploy docs; B1 reconcile-fixture hermeticization; A1/A3 trims; C4/C5 depth-matrix rewrite; B2 profile real-toggle doc. D2-D5 (graphify, generator-owned) + B6 (skills-perso allowlist) SKIPPED by decision. Executor = this session on chore/job3-fixes, NO finish.
- job3 EXECUTED: 20 commits chore/job3-fixes, all diffs first-try, `make test` all green throughout, zero regression. **B1 BLOCKED**: `lib/tests/` guarded by config-protection.sh same as `hooks/`; user's sentinel pre-auth scoped only to hooks [SENTINEL-REQUIRED], auto-mode classifier correctly refused the out-of-scope bypass — needs explicit follow-up authorization. Final re-sweep: 3 fresh verifiers, 24 modified files, ZERO residual finding; `run-reconcile.sh` unchanged 18/2 (B1 untouched, as expected). 2 incidental out-of-scope drifts surfaced (client-handover-writer.md:885 stale "4-chapter" self-contradiction, BDR-053 index-row gap) — flagged, not fixed.
- B1 UNBLOCKED same session: user explicitly authorized the `lib/tests/` sentinel. Froze `.claude/memory/blockers.md` (post-BLK-009-closure state) into `lib/tests/fixtures/blockers-snapshot.md`, pointed T2 at it instead of the live registry, updated T2b/T2c expectations (BLK-009 resolved, open={001,003}). Suite back to 20/20 GREEN, shellcheck clean — `skills/reconcile/SKILL.md:53`'s "20/20" claim is true again. `make test` reconfirmed all green. job3 now fully closed: 21 commits total, 0 items pending.
+9
View File
@@ -120,6 +120,7 @@ rules:
| LRN-099 | 2026-07-05 | auto-orchestrator autonomy boundary: git discipline transfers naturally (branch, no-merge), declared-state discipline does NOT — baseline silently rewrote target TODO + authored registries + scope-crept | designing any auto/headless flow — enumerate declared surfaces, mark each read-only or gated |
| LRN-100 | 2026-07-05 | tool gated on clean tree must clean its OWN scratch (else self-DoS next run); contract-changing auto-fix needs structural BREAKING flag in the reviewed artifact | any recurring tool w/ cleanliness precondition; any auto-fix touching an API contract |
| LRN-102 | 2026-07-05 | deliverable text placed BEFORE a tool call may never render — only the turn's FINAL text is guaranteed displayed; a checklist printed above AskUserQuestion was invisible to the user | any flow whose deliverable is conversational text (checklist, commands, report): end the turn with it, blocking questions come before, never after |
| LRN-105 | 2026-07-06 | explorer subagent ran a build tool (`graphify .`) mid read-only audit despite prose instructions to only Read/Grep/Bash-read — the runtime observed a config-protection sentinel deny message and self-corrected only after an explicit main-session correction, not from the original prompt | dispatching any "read-only audit" subagent whose toolset includes Bash: state "do not execute build/generator/mutating commands" explicitly, don't rely on "read-only" framing alone to constrain tool CHOICE |
---
@@ -1051,6 +1052,14 @@ rules:
- **future application**: designing any skill/flow output meant to be read+used from the conversation — put it LAST; never sandwich a deliverable between tool calls; prefer plain-text report requests over blocking question tools after a deliverable.
- **cousin**: [[LRN-100]] same skill lineage; CLAUDE.md communication doctrine (final message carries everything).
## LRN-105 — "read-only audit" prose does not constrain subagent tool CHOICE; state the ban explicitly
- **pattern**: job3 docs-drift audit dispatched an exploration subagent (Bash + Read/Grep, "audit BODIES — do NOT modify any file") to check graphify skill docs. It ran `graphify .` to check CLI behavior — a real build, not a read — leaving an empty `graphify-out/` dir at repo root. The prompt said "read-only" and "verify via Read/Grep/Bash (read-only)" but never named the specific command class to avoid; the agent treated "run the CLI to see what it does" as within a Bash read-only mandate.
- **why**: "read-only" is a framing about FILES, not an instruction the model maps onto every tool call by default — a subagent with Bash access will happily execute a program to observe its behavior, which is investigative but not read-only if the program writes to disk. The fix only landed after a main-session correction mid-run ("do NOT run graphify... verify by reading the installed source instead"), not from the original prompt.
- **context**: 2026-07-06, job3 audit exploration phase (`.audit/job3-report.md` A1/A2 findings, incident noted in the report header). No tracked file was touched; the stray dir was harmless but wasted a round-trip and could have mutated git-visible state on a less-guarded command.
- **future application**: any subagent dispatch framed as "read-only" / "audit" / "verify" that grants Bash — explicitly ban execution of the subject-under-test's own CLI/build/generator commands, and name the safe alternative (read installed source, grep docs) in the same sentence. Don't rely on the word "read-only" alone to scope tool use.
- **cousin**: [[LRN-100]] (tool must clean its own scratch) — same class of "prose framing ≠ enforced constraint", different failure mode.
## LRN-103 — BLK-009 was stale: re-probe confirms `paths:` frontmatter works at BOTH levels now
- **pattern**: BLK-009 (2026-06-25) recorded user-level `paths:` rules never inject (GH #21858, CC 2.1.190). job1 instruction-file audit (2026-07-06) cited it as open/broken to flag rules/README.md's documented lazy-load mechanism as self-contradicting. Fresh re-probe same day (3-file probe, `**/*.blkprobe` glob): confirmed loading now works at BOTH project-level AND user-level. Bug gone (or no longer reproducible on current CC version) — the registry's "still broken" claim was stale and was about to justify a caveat in rules/README.md warning about a bug that no longer exists.
+16 -13
View File
@@ -15,19 +15,19 @@ This repo is your personal Claude Code setup, versioned and reproducible across
claude-config/
├── CLAUDE.md # Global coding preferences (style, rules, workflow)
├── settings.json # Global permissions (deny / ask / allow rules)
├── install.sh # Bootstrap: Claude Code CLI + auth + shell env vars + link + plugins
├── install.sh # Bootstrap: Claude Code CLI + auth + submodules + link + plugins
├── install-plugins.sh # One-shot installer: prerequisites + all plugins
├── link.sh # Symlinks this repo into ~/.claude/
├── doctor.sh # Setup diagnostic
├── update-all.sh # One-command update for all components
├── Makefile # Unified entry point: make install / doctor / update
├── plugins.lock.json # Version pinning for non-marketplace dependencies
├── hooks/ # Session start, statusline, RTK rewrite
├── hooks/ # Session start, statusline, RTK rewrite, config-protection + design-toolchain guards
├── agents/ # Execution units called by skills (never invoked directly)
├── skills/ # Entry points invoked via /skill-name
├── skills-external/ # Git submodules (gstack)
├── templates/ # Per-project config templates (CLAUDE.md, settings, .claudeignore)
└── lib/ # Shared shell functions (plugin detection)
├── skills-external/ # Vendored skill packs (gstack submodule + installer-fetched design packs)
├── templates/ # Per-project templates (CLAUDE.md, settings, memory registries, deploy runbook, gitignore)
└── lib/ # Shared shell libs (gitflow, profiles, commit helpers, archetypes, tests)
```
**Architecture principle:**
@@ -55,13 +55,14 @@ bash doctor.sh
```
All scripts use their own location to find the repo — run them from anywhere.
Install output is logged to `install-YYYYMMDD-HHMMSS.log`.
The plugins step logs to `install-YYYYMMDD-HHMMSS.log`.
**Optional — Context7** (fast doc lookup for React / Next.js / Prisma…): `install.sh`
installs the `ctx7` CLI. To wire it into Claude Code:
**Optional — Context7** (fast doc lookup for React / Next.js / Prisma…): the plugins
step installs the `ctx7` CLI and wires it into Claude Code itself — single surface =
the `find-docs` skill; the generated `rules/context7.md` is purged by design
(BDR-053). If you run `ctx7 setup` manually, delete that rule or re-run `make plugin`.
```bash
ctx7 setup --claude # configure Context7 for Claude Code
ctx7 login # optional: OAuth / API key for higher rate limits
```
@@ -77,7 +78,7 @@ ctx7 login # optional: OAuth / API key for higher rate limits
| **RTK** | Plugin (always on) | Code rewrite hook. Zero passive cost. | [rtk-ai/rtk](https://github.com/rtk-ai/rtk) |
| **security-guidance** | Plugin (always on) | Security hook. Zero passive cost. | [anthropics/claude-code](https://github.com/anthropics/claude-code) |
| **ui-ux-pro-max** | Plugin (toggle) | Design system, color/typography choices. Enable for design-heavy projects. | [nextlevelbuilder/ui-ux-pro-max-skill](https://github.com/nextlevelbuilder/ui-ux-pro-max-skill) |
| **Context7** | Plugin (toggle) | Fast-evolving libs doc lookup (Next.js, React, Prisma...). Requires a free account + API key (optional Context7 step in install). | [context7.com](https://context7.com/) |
| **Context7** | Plugin (toggle) | Fast-evolving libs doc lookup (Next.js, React, Prisma...). Works anonymously; optional `ctx7 login` raises rate limits. | [context7.com](https://context7.com/) |
| **pr-review-toolkit** | Plugin (toggle) | Multi-agent PR review. | [anthropics/claude-code](https://github.com/anthropics/claude-code) |
| **Graphify** | Python CLI | Codebase → knowledge graph → navigable wiki. Helps Claude map and search projects efficiently. | [pypi: graphifyy](https://pypi.org/project/graphifyy/) |
@@ -107,7 +108,7 @@ Versions are pinned in `plugins.lock.json`. To update: edit the file, then re-ru
| `/deploy` | Run a project's deploy from its committed runbook — instantiate the delta, resume cold |
| `/graphify` | Codebase knowledge graph — navigation for large-scope tasks |
| `/plugin-check` | Check active plugins vs project needs — recommend enable/disable |
| `/health` | Run setup diagnostic |
| `/health` | Code quality dashboard (gstack) — setup diagnostic is `make doctor` |
| `/status` | Consolidated project snapshot — plugins, git, GSD milestone |
| `/skills-perso` | List personal (user-created) skills |
| `/audit-delta` | Recurring audit of changes since last run (norms, bugs, dead code, security) |
@@ -121,10 +122,11 @@ Versions are pinned in `plugins.lock.json`. To update: edit the file, then re-ru
| `/geo` | GEO-only audit — AI-search visibility (ChatGPT, Perplexity, Claude, Gemini…) |
| `/client-handover` | Final project delivery — audits + branded deliverable (Markdown / HTML / PDF) |
| `/profile` | Activate a skill profile (design / dev / qa / audit / minimal) |
| `/tour` | Grouped all-axes sweep — cleanup + security + reconcile + doc, fix and loop until clean |
> This table lists personal skills. Gstack skills (investigate, review, retro,
> office-hours, context-save, context-restore, cso…) and marketplace plugins add
> many more — run `/skills-perso` for your full list, or browse `skills/`.
> many more — run `/skills-perso` to list your hand-written skills, or browse `skills/`.
---
@@ -194,7 +196,7 @@ bash doctor.sh # full diagnostic (symlinks, plugins, permissions, t
bash update-all.sh # update all components (CLI, plugins, submodules, symlinks)
# Claude Code
/health # runs doctor.sh
/health # gstack code-quality dashboard (doctor.sh -> make doctor)
/status # project snapshot (plugins, git, GSD milestone)
/plugin-check "description" # audit plugin config vs project needs
@@ -204,6 +206,7 @@ make plugin # install plugins only
make link # create/update symlinks into ~/.claude/
make doctor # diagnostic
make update # update Claude Code, config, submodules, plugins, and verify
make test # run deterministic tests (lib/tests/*.test.sh + lib/gitflow-test.sh)
make onboard # onboard an existing project (run from its dir)
make profile cmd="set X" # activate a skill profile (design/dev/qa/audit/minimal/full)
make profile-list # list skill profiles
+3 -2
View File
@@ -806,8 +806,9 @@ without evidence = DGCCRF risk.>
========================================
```
**If called standalone via `/geo`**: write/update `GEO.md` at project
root (or merge into `SEO.md` if it already exists). Structure:
**If called standalone via `/geo`**: write/update `.claude/audits/GEO.md`
(create `.claude/audits/` first if needed; merge into `.claude/audits/SEO.md`
if it already exists). Structure:
```markdown
# Audit GEO — <Project Name>
+4
View File
@@ -1,5 +1,9 @@
# Deploy Skill — Implementation Plan
> **Superseded by BDR-054** (`52f6678`): the shipped skill has NO `NEXT.sh` file and NO
> AskUserQuestion hand-back — see `skills/deploy/SKILL.md` for current behavior. This
> plan is kept as historical record; do not implement its NEXT.sh/hand-back sections.
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Build a `deploy` skill — a per-project shell runbook that re-instantiates from the delta since the last deploy, hands control to the user for out-of-band execution, resumes cold (even in a new session), and learns from deploy errors in place.
@@ -1,5 +1,9 @@
# Deploy skill — design spec
> **Superseded by BDR-054** (`52f6678`): the shipped skill has NO `NEXT.sh` file and NO
> AskUserQuestion hand-back — see `skills/deploy/SKILL.md` for current behavior. This
> spec is kept as historical record; do not implement its NEXT.sh/hand-back sections.
- **Date:** 2026-06-27
- **Status:** Design approved (5 knobs settled). **No skill code written yet.** Next step = implementation plan.
- **Scope:** A new `deploy` skill = a per-project shell RUNBOOK that lives in `.claude/deploy/`, gets re-instantiated from the delta since the last deploy, and LEARNS from deploy errors in place.
+2 -2
View File
@@ -28,7 +28,7 @@ if [ ${#BROKEN[@]} -gt 0 ]; then
printf "│ MISSING: ~/.claude/%-30s│\n" "$b"
done
printf "│ → %-47s│\n" "$_fix_cmd"
echo "│ → /health for full diagnostic │"
echo "│ → make doctor for full diagnostic │"
echo "└───────────────────────────────────────────────────┘"
unset _repo_hint _fix_cmd
fi
@@ -220,7 +220,7 @@ fi
unset _remote_ver REPO_DIR
echo "│ 💡 /plugin-check before starting a new project │"
echo "│ 🩺 /health to run full diagnostic │"
echo "│ 🩺 make doctor full diagnostic │"
echo "└───────────────────────────────────────────────────┘"
echo ""
unset TOKEN_WARN
+192
View File
@@ -0,0 +1,192 @@
---
type: blockers_registry
entry_prefix: BLK
schema:
id: BLK-XXX
date: YYYY-MM-DD
friction: string (what was blocked)
real_cause: string (root cause, not symptom)
solution: string (workaround or fix)
status: [open | resolved | upstream]
rules:
- Open blocker when friction > 15 min wasted. Close with real cause, not "moved on".
- Link upstream issue / PR / commit when applicable.
- Cause is bug in dependency → status upstream with pointer to tracker.
---
# Blockers registry (BLK)
## Index
| ID | Date | Friction | Status |
|----|------|---------|--------|
| BLK-001 | 2026-04-22 | `rtk curl` breaks JSON pipelines | upstream |
| BLK-002 | 2026-04-23 | `rmdir` denied in sandbox on empty directory | resolved |
| BLK-003 | 2026-05-12 | `scripts/screenshot.mjs` hardcoded macOS path blocks PNG cards on Linux | upstream |
| BLK-004 | 2026-05-20 | `/ship-feature` wrapper at `~/.claude/commands/` points to deleted agent files post-refactor | resolved |
| BLK-005 | 2026-05-21 | gstack submodule rename (checkpoint→context-save) breaks profile entries | resolved |
| BLK-006 | 2026-05-21 | `profile.sh current` false-negative via `~/.claude` symlink (`cd` not `cd -P`) | resolved |
| BLK-007 | 2026-06-02 | 6 gstack source skills (ios-*, spec) unlinked post-bump — invisible to profiles + `gstack on` | resolved |
| BLK-008 | 2026-06-23 | gstack ./setup on Ubuntu 26.04: Playwright chromium unsupported → gstack browser (/browse, /qa, screenshots) silently dead | resolved (211c7d4) |
| BLK-009 | 2026-06-25 | user-level path-scoped rules (`paths:` frontmatter in `~/.claude/rules/`) never inject — broken in CC 2.1.190 (#21858) | resolved (2026-07-06) |
| BLK-010 | 2026-06-27 | init-project: scaffold (STEP 5) + bootstrap README (5b) have no deterministic commit owner; worktree `add -b` on unborn HEAD | resolved (uncommitted) |
| BLK-011 | 2026-06-27 | init-project STEP 13 GSD post-FINISH creates ROADMAP.md → stranded doc (3rd post-FINISH artifact) | resolved (STEP 12 removed) |
| BLK-012 | 2026-06-29 | gitflow_init half-applied: socle-commit failure swallowed → hook activated on partial run → re-run self-blocks | resolved |
| BLK-013 | 2026-06-30 | `make plugin` Error 127 — npm absent on apt-`nodejs` host (Step 4 gsd-pi aborts, Steps 5-10 + residual cleanup never run) | resolved (env) |
| BLK-014 | 2026-07-01 | `make install` aborts npm EEXIST on `~/.local/bin/claude` when claude already installed via native installer — no presence guard | resolved |
| BLK-015 | 2026-07-03 | `gitflow_finish` ignored its `<type> <name>` args → merged the CHECKED-OUT branch not the one named → wrong-branch merge (audit LOT3) | resolved |
---
## BLK-001 — `rtk curl` returns compressed schema in pipes
- **Date**: 2026-04-22
- **Friction**: pipelines like `rtk curl ... | python -c "json.load(sys.stdin)"` (or `jq`, `awk`) fail without clear error.
- **Real cause**: `rtk curl` auto-compresses stdout regardless of TTY — documented in `.claude/tasks/rtk-upstream-issue.md`.
- **Solution**:
- Short-term workaround: `exclude_commands=["curl"]` in `~/.config/rtk/config.toml`.
- Alternative workaround: use `rtk proxy`.
- Upstream fix: issue reported, see `.claude/tasks/rtk-upstream-issue.md`.
- **Status**: upstream (`rtk` bug, workaround applied).
## BLK-002 — `rmdir` denied in sandbox on empty directory
- **Date**: 2026-04-23
- **Friction**: couldn't delete `./tasks/` after emptying (post-migration to `.claude/tasks/`). `rmdir tasks` and `rm -r tasks` returned "Permission denied" even with empty dir and non-destructive intent.
- **Real cause**: Claude Code sandbox blocks destructive commands (`rm`, `rmdir`, `rm -rf`) by default via harness permission gate, regardless of actual semantics. `git rm` through `git` passed (commit `c721a36`) — git treated as non-destructive tool.
- **Solution**:
- This session: `git rm tasks/*.md` handled files individually (via `git rm`, cleared gate). Git auto-detected renames to `.claude/tasks/`, so `tasks/` directory removed implicitly at commit time.
- If dir persists empty after `git rm`: ask user to run `rmdir tasks` manually.
- **Status**: resolved (fixed via `git rm` + rename auto-detection; no `rmdir` needed in practice).
## BLK-003 — `scripts/screenshot.mjs` hardcoded macOS path blocks PNG cards on Linux
- **Date**: 2026-05-12
- **Friction**: `/darwin-skill` Phase 3 generates result cards via `node ~/.agents/skills/darwin-skill/scripts/screenshot.mjs <html> <png>`. On Linux: script fails immediately — `require('/Users/alchain/.npm-global/lib/node_modules/playwright/node_modules/playwright-core')` resolves to a non-existent macOS user path. No PNG cards produced; Phase 3 falls back to markdown report only.
- **Real cause**: upstream `alchaincyf/darwin-skill` author dev'd on macOS, shipped absolute path to their own homedir's global npm install of playwright. Zero portability layer (no PATH lookup, no `playwright` bare require, no fallback to `npx`).
- **Solution**:
- Workaround (used 2026-05-12): skip PNG generation, deliver markdown + HTML cards (HTML viewable in browser without playwright).
- Local patch: `npm i -g playwright` then replace `require('/Users/alchain/...')` with `require('playwright')`. Two lines edit.
- Spec-documented fallback: `npx playwright screenshot "file:///path/to/card.html#<theme>" out.png --viewport-size=960,1280 --wait-for-timeout=2000` — works without modifying the file, costs ~150MB chromium download.
- PR upstream to `github.com/alchaincyf/darwin-skill` once tested.
- **Status**: upstream (third-party skill at `~/.agents/skills/darwin-skill/scripts/screenshot.mjs`, not in any of our repos).
## BLK-004 — `/ship-feature` wrapper references 6 deleted agent files
- **Date**: 2026-05-20
- **Friction**: `/ship-feature` invocation loads wrapper at `~/.claude/commands/ship-feature.md`. Wrapper says `Load and follow strictly: .claude/agents/{ship-feature,analyzer,designer,implementer,reviewer,tester}.md`. 5 of 6 paths missing on disk (only `analyzer.md` survives). User hits blocker — wrapper without orchestrator.
- **Real cause**: refactor commits `0241e1d` ("extract skill logic into standalone agent files") + `21960e0` ("changed orchestrators into skills") migrated orchestrator from `.claude/agents/ship-feature.md` into `~/.claude/skills/ship-feature/SKILL.md` and replaced custom sub-agents (designer/implementer/reviewer/tester) with superpowers skills (brainstorming, writing-plans, subagent-driven-development, requesting-code-review, finishing-a-development-branch). Wrapper at `~/.claude/commands/ship-feature.md` never updated, never deleted. Untracked file — survived all refactor commits silently.
- **Solution**: `rm ~/.claude/commands/ship-feature.md`. Skill `~/.claude/skills/ship-feature/SKILL.md` (`name: ship-feature`, `disable-model-invocation: true`) becomes sole `/ship-feature` resolver. SKILL.md references only existing agents: `plugin-advisor.md`, `analyzer.md`, `doc-syncer.md`.
- **Status**: resolved.
## BLK-005 — `/profile set full` warns `missing: checkpoint` after gstack upstream rename
- **Date**: 2026-05-21
- **Friction**: `/profile set full` (and dev, backend, web, web-full) emits `⚠ missing: checkpoint — try: bash link.sh`. Running `bash link.sh` reports `✅ All symlinks already up to date. Next: bash install-plugins.sh` — dead-end loop. User cannot resolve the warning by following the suggested next step.
- **Real cause**: gstack upstream renamed the `checkpoint` skill to `context-save` (Claude Code now treats `/checkpoint` as a native rewind alias, shadowing the gstack skill). New skill in `skills-external/gstack/context-save/SKILL.md` carries the description `"Formerly /checkpoint — renamed because Claude Code treats /checkpoint as a native rewind alias"`. Five `lib/profiles/*.profile` files still listed the dead name. `link.sh` only symlinks repo dirs into `~/.claude/` — it cannot materialize a skill that no longer exists upstream, so its suggested action was misleading.
- **Solution**: `s/checkpoint/context-save/` in `lib/profiles/{dev,backend,full,web,web-full}.profile` (commit `69c5ded`). `CLAUDE.md:193` routing line `Save progress, checkpoint, resume → invoke context-save` updated locally, left uncommitted because the file holds unrelated in-progress graphify section work. Verify: `bash lib/profile.sh set full` now outputs `✓ enabled: context-save` with no warning.
- **Status**: resolved.
## BLK-006 — `bash lib/profile.sh current` false-negative when invoked via `~/.claude/lib/` symlink
- **Date**: 2026-05-21
- **Friction**: `bash "$HOME/.claude/lib/profile.sh" current` returns `none (all gstack skills enabled — no profile set)` even when a profile IS applied + 14 `gstack__*` entries sit in the repo's `skills-disabled/`. User cannot detect active profile via the official command. Same script invoked from inside the repo directory (`bash lib/profile.sh current`) returns the correct answer — invocation-path-dependent behavior is the worst kind of bug to diagnose.
- **Real cause**: `lib/profile.sh:43` set `REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"`. Default bash `cd` preserves symlinks (logical pathname mode, `set -P` off). When the script is invoked via the `~/.claude/lib/profile.sh` symlink (link.sh wires `~/.claude/lib -> <repo>/lib`), `$BASH_SOURCE[0]` is the symlinked path, `dirname` returns `~/.claude/lib`, `cd ..` lands at `~/.claude`, and `pwd` returns the logical path `/home/bchanot-ubuntu/.claude`. `$SKILLS_DIR="$REPO/skills"` still works because `~/.claude/skills` happens to be a symlink to the repo's `skills/`. But `$DISABLED_DIR="$REPO/skills-disabled"` resolves to `~/.claude/skills-disabled` — a real sibling directory created at some earlier point containing only 2 stale npx-skill symlinks (`darwin-skill`, `find-skills`). `cmd_current` scans this near-empty dir, finds 0 `gstack__*` entries, returns the "none" sentinel.
- **Solution**: `REPO="$(cd -P "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"` (commit `a4558ee`). `-P` forces physical-path resolution so `$REPO` is always the real repo path regardless of how the script is invoked. Verify: `bash "$HOME/.claude/lib/profile.sh" current` now returns `full (100% match, 14 gstack skills disabled)`.
- **Status**: resolved. Follow-up: `~/.claude/skills-disabled/` (real dir with only `darwin-skill`/`find-skills` symlinks) is orphaned — these npx skills are already symlinked into `<repo>/skills/` by link.sh, so the disabled-side copies serve no purpose. Could be deleted to remove confusion, but harmless as-is.
## BLK-007 — 6 gstack source skills (ios-*, spec) unlinked — invisible to profile system + `gstack on`
- **Date**: 2026-06-02
- **Friction**: `skills-external/gstack/` has 53 source skills; 6 (`ios-clean`, `ios-design-review`, `ios-fix`, `ios-qa`, `ios-sync`, `spec`) exist ONLY as source — NOT symlinked into `skills/` (enabled) nor `skills-disabled/gstack__*` (parked). So invisible to Claude AND untouched by `reset`/`gstack on` (both operate on parked `gstack__*` only). Surfaced while adding `gstack on|off`: `comm` of gstack source vs `full.profile`.
- **Real cause**: gstack submodule bump added new skills; gstack's own `./setup` (source of truth for per-skill symlinks per link.sh) not re-run → symlinks never created. Same lifecycle gap class as [[toggle-external-source-only-state]] (LRN-007). NOT a `full.profile` bug — full curated by design (BDR-017 caveat: "full excludes rarely-used gstack skills"). Initial "full omits ios = bug" flag was WRONG, self-corrected (see EVAL-002).
- **Solution applied** (NOT full `./setup` — surgical, no side effects): (1) Linked `spec` only — `mkdir skills/spec` + `ln -snf <abs>/skills-external/gstack/spec/SKILL.md skills/spec/SKILL.md`, matching gstack setup:440-476 (per-skill real dir + SKILL.md symlink, name from frontmatter). (2) Added `spec` to `full.profile` + `web-full.profile` planning sections (must be in active profile `full` else `set full` re-disables it). (3) iOS 5 skills deliberately NOT linked — Linux host, device-farm needs Mac daemon + Tailscale + iOS devices = dead skills + token cost. (4) Completed `.gitignore` gstack allowlist: added all 12 missing (`spec`, 5 `ios-*`, 6 parked `document-generate/landing-report/scrape/setup-gbrain/skillify/sync-gbrain`), removed stale `checkpoint` (BLK-005 rename). Reason: `gstack on` (BDR-018) moves parked skills into `skills/` — any gstack skill missing from allowlist = untracked git noise on enable.
- **Verified**: `profile show full`+`web-full` → spec enabled; allowlist drift recheck EMPTY; spec skill now visible to Claude.
- **Status**: resolved. iOS = intentional exclusion (re-linkable via gstack `./setup` on a Mac). See [[gstack-gitignore-allowlist-completeness]] (LRN-025).
## BLK-008 — gstack ./setup fails on Ubuntu 26.04 — Playwright chromium unsupported
- **Date**: 2026-06-23
- **Friction**: fresh Ubuntu 26.04, `make install` / `make plugin` → "Failed to install browsers / ERROR: Playwright does not support chromium on ubuntu26.04-x64" → "GStack ./setup failed". Non-fatal in our wrapper (warn only) but gstack's browser (`/browse`, `/qa`, design screenshots) is silently dead once gstack is enabled.
- **Real cause**: Playwright 1.58.2 (pinned in the gstack submodule) registry lists `ubuntu20.04/22.04/24.04` only; 26.04 released later → not in list → `getHostPlatform` errors. Pure OS-newness, not an install bug.
- **Solution**: gated `export PLAYWRIGHT_HOST_PLATFORM_OVERRIDE=ubuntu24.04-x64` (ubuntu >24.04 only) before gstack setup + persisted to `.bashrc` for runtime. Playwright then pulls a Chrome-for-Testing fallback build for ubuntu24.04. Verified on 26.04: `ldd` resolves all libs + real headless render OK.
- **Status**: resolved (commit 211c7d4). Residual: exact rev 1208 launch not in-session-tested (sandbox download hung at extraction); proved via sibling rev 1228 same-platform CfT build. Confirm on next real `make plugin`. Proper upstream fix = gstack bumps Playwright to a version that lists ubuntu26.04. See [[LRN-038]].
- **2026-06-23 UPDATE — Solution REVERTED, status downgraded to UPSTREAM/open** (commit b9c3937): the `PLAYWRIGHT_HOST_PLATFORM_OVERRIDE` solution above does NOT work on 26.04. The fallback build downloads to 100% then HANGS at extraction (chrome binary never appears, no headless-shell download starts; reproduced on real machine + sandbox) → turned a 0.5s fast-fail into an install-blocking hang (user Ctrl+C). Reverted to the fast-fail (non-fatal; gstack OFF by default, browser only for /browse,/qa,screenshots). The earlier "verified ldd + headless render" was an isolated test on a sibling already-extracted build (rev 1228) — it masked the rev-1208 install-path hang. **Real fix = upstream**: gstack bumps Playwright to a version that lists ubuntu26.04. Until then gstack's browser is unavailable on 26.04, install completes cleanly. See [[LRN-038]] correction.
- **2026-06-23 FINAL — RESOLVED** (commit 3b8ffb1): gstack browser now works on Ubuntu 26.04. Two layers fixed: (1) bumped gstack's pinned Playwright 1.58.2 → 1.61 (`bun add playwright@latest` in the submodule; 1.61 ships a native ubuntu26.04 build — chromium rev 1228), automated in the installer (`gstack_bump_playwright_if_unsupported`, idempotent, OS-gated); (2) `GSTACK_CHROMIUM_NO_SANDBOX=1` to work around the AppArmor userns restriction (`sysctl kernel.apparmor_restrict_unprivileged_userns=1`), persisted to `.bashrc` + installer Step 9 (sysctl-gated). Verified end-to-end: `browse goto https://example.com` → "Navigated (200)". Caveat: the Playwright bump is a local submodule edit, reset by `git submodule update`, re-applied by the next install. See [[BDR-029]], [[LRN-040]].
---
## BLK-009 — user-level path-scoped rules don't load (#21858) — still broken in CC 2.1.190
- **Date**: 2026-06-25
- **Friction**: tried to scope a global rule to matching files via `paths:` frontmatter in `~/.claude/rules/<name>.md` — the rule never injects, even when a matching file (`*.probe`) is read in a fresh session. Blocks any "load this guidance only for matching files" strategy at the user level.
- **Real cause**: GitHub issue #21858 — user-level (`~/.claude/rules/`) rules carrying `paths:` frontmatter are not evaluated/injected; still unfixed in 2.1.190. (Project-level path-scoped rules not tested here.)
- **Probe method**: 3-file probe — `_probe.md` (`paths: ["**/*.probe"]`, sentinel `SENTINEL_USER_RULE_LOADED`), `_probe_ctl.md` (NO `paths`, control sentinel `CONTROL_NOPATHS_LOADED`), `_probe_target.probe` (target, read in a fresh session). Result: control sentinel PRESENT in session context, path-scoped sentinel ABSENT → the path-scoped rule did not load. Probe files removed after.
- **Status**: upstream, open. Workaround: don't rely on user-level path-scoping → keep global guidance unconditional + COMPRESSED ([[BDR-031]]). Side-note: native auto-memory = "on" but writes nothing yet (fresh machine). Re-test on CC upgrades.
- **2026-07-06 UPDATE — RESOLVED**: re-probed `paths:` frontmatter lazy-load with fresh 3-file probe (`**/*.blkprobe` glob) — confirmed loading works at BOTH project-level AND user-level (`~/.claude/rules/`) rule dirs. #21858 no longer reproduces on current CC version. Status → resolved. Prior workaround (unconditional + compressed global CLAUDE.md, [[BDR-031]]) no longer forced by this bug — see [[LRN-103]].
- **Reference**: GitHub #21858. Linked to [[BDR-031]], [[LRN-044]], [[LRN-103]].
---
## BLK-010 — init-project scaffold + bootstrap README have no deterministic commit owner; worktree on unborn HEAD
- **Date**: 2026-06-27
- **Friction**: init-project scaffold (STEP 5 — CLAUDE.md, settings, config, entry points, `.gitignore`, `.env.example`, `.claude/`) + bootstrap README (STEP 5b) never get an explicit commit. Pipeline's only commits = STEP 10b memory (helper) + STEP 8 per-task implementer commits. Whether scaffold/README land in a commit = emergent: implementer-prompt.md says only "4. Commit your work", scope undefined. Greenfield deeper: STEP 8 `subagent-driven-development` requires `using-git-worktrees` → `git worktree add -b` branches from HEAD, but post-`git init` HEAD is UNBORN → add fails; the worktree skill has no unborn-HEAD path.
- **Real cause**: no deterministic commit step between `git init` (STEP 5) and FINISH (STEP 11). scaffolder + doc-syncer both write-only (zero `git commit`). implementer commit scope unspecified. `using-git-worktrees` assumes a born HEAD.
- **Solution**: open — own chantier (real technical weight: unborn HEAD + worktree). Candidate: explicit initial scaffold commit after STEP 5/5b before STEP 8, OR handle unborn HEAD in the worktree step. NOT cured by the doc-sync coupled chantier — that commits ONLY doc-sync's patched files and (correctly) excludes scaffold. Consequence: after doc-sync coupled, ship-feature fully fixed, init-project PARTIAL (doc-sync ok, scaffold/bootstrap still open).
- **Status**: resolved (2026-06-29; working tree uncommitted — durable only at the claude repo commit, cf [[BLK-012]]). Was "open"; closed by the gitflow chantier — see note below.
- **Reference**: discovered in doc-sync-coupled analysis (2026-06-27). Distinct from the doc-sync twin [[BDR-034]]. Sibling [[BLK-011]]. Surfaces via analyze-before-plan bookend on any init-project commit-flow work.
- **2026-06-29 — RESOLVED by the gitflow chantier**: `gitflow_init` fresh path (`_gitflow_init_fresh`: unborn HEAD → `git symbolic-ref HEAD refs/heads/main` → `git add -A` → deterministic root commit → `git branch develop`) wired at init-project **STEP 5f** (after scaffold STEP 5 + README STEP 5b, before STEP 8 implement). Closes all 3 components: (a) scaffold+README get a deterministic commit owner = the root commit (`git add -A` stages whole tree; SKILL.md STEP 5f + lines 141/249-250 "scaffold commit owner … BLK-010 closed"); (b) root commit + develop make HEAD BORN before STEP 8 → `gitflow start feature`/`worktree add -b` never hits unborn HEAD; (c) STEP 5f IS the deterministic commit step between `git init` and FINISH. Tested: gitflow-test.sh **T2 "init fresh (BLK-010 root commit)"** (root commit on main, socle IN root commit, hook tracked, tree clean). Residual (non-blocking): the generic `using-git-worktrees` skill still has no unborn-HEAD path — now MOOT (HEAD always born by STEP 5f, never reached), not patched in the skill itself.
## BLK-011 — init-project STEP 13 GSD post-FINISH creates ROADMAP.md → stranded doc
- **Date**: 2026-06-27
- **Friction**: init-project STEP 13 (GSD v2 init) runs post-FINISH (STEP 11). `gsd init` creates `.gsd/` + `ROADMAP.md` (a public doc). Created AFTER FINISH integrates → ROADMAP never in the merge/PR. Same PR-stranding class as the doc-sync twin, 3rd post-FINISH artifact.
- **Real cause**: artifact-producing step ordered after FINISH (= BDR-034 class). `gsd init` is a CLI mechanism distinct from doc-syncer; ROADMAP is sync-only for doc-syncer (never created by it, BDR-022 rules), so the doc-sync coupled chantier does not touch it.
- **Solution**: open — separate thread. Candidate: reorder GSD before FINISH, or commit ROADMAP after `gsd init`. Out of scope for doc-sync coupled (different mechanism). [historical candidates — NOT the route taken]
- **Resolution**: RESOLVED 2026-06-29 — by REMOVAL, not by committing the orphan. init-project STEP 12 (speculative gsd auto-bootstrap) DELETED → ROADMAP/.gsd never created post-FINISH → orphan dissolves, no commit helper built. TRUE reason: auto-bootstrapping a heavy multi-session ENGINE the sole user doesn't use, AT project-creation, is bad on its own terms. NOT the initial framing "ROADMAP redundant with TODO" — that was wrong and would have aged badly: gsd ≫ roadmap (state machine / crash-recovery / cost / parallel / worktree), and TODO ≠ gsd ROADMAP (different altitude + consumer). Reasoning trace: BOTH initial premises (gsd=only-roadmap; TODO-redundant) REFUTED on read, yet conclusion A (remove STEP 12) held for the STRONGER reason — right answer, reason corrected before engraving. Deliberate gsd use KEPT (onboarder PHASE 6 `/onboard add gsd`, plugin-advisor reco, status-reporter `.gsd/` read, USAGE `gsd init`). Removed STEP 12 + header 12→11-step + 10c note + 4 USAGE refs; coherence sweep = zero dangling refs. [[LRN-072]]
- **Status**: resolved (init-project STEP 12 removed — `skills/init-project/SKILL.md`; branch bugfix/blk-011-gsd-roadmap). Title says "STEP 13" — stale (was STEP 12 at removal per BDR-036 renumber); left per append-only.
- **Reference**: discovered in doc-sync-coupled analysis (2026-06-27). Sibling [[BLK-010]] + twin [[BDR-034]].
## BLK-012 — gitflow_init non-transactional: socle-commit failure swallowed → hook activated on partial run → re-run self-blocks
- **Date**: 2026-06-29
- **Friction**: migrating faunosteo, `migrate_local` → `gitflow_init` half-applied TWICE. Run 1: master→main renamed, develop created, socle staged, but the socle commit died — `Author identity unknown ... unable to auto-detect email address (got 'bchanot@bchanot-server.(none)')` → tree DIRTY, exit 1. Run 2 (recovery): socle commit BLOCKED by the gitflow hook itself (`gitflow pre-commit: BLOCKED — direct commit on 'main'`), yet `init` reported `exit=0` (a lie); main still at the old tip, socle uncommitted.
- **Real cause**: `_gitflow_init_existing` SWALLOWED the socle-commit failure — `git diff --cached --quiet || git commit` with no propagation, and the function's last stmt (`git branch develop`) returned 0, masking the dead commit. Init CONTINUED past the failed commit → ran `gitflow_activate_hook` though the socle was never committed → re-run then self-blocks (commit on main blocked by the now-active hook). Design's "idempotent" + "never self-blocked" claims hold ONLY for a clean single run; a partial run breaks both. Fresh-repo path already propagated its failure (`_gitflow_init_fresh`); existing-repo path did not — the asymmetry was the bug. Trigger upstream of it: git identity UNSET (global unset; faunosteo had no local identity, though its own history uses `Bastien Chanot <git@bchanot.fr>`).
- **Solution**: (1) socle commit FATAL in `_gitflow_init_existing` — `if ! git diff --cached --quiet; then git commit … || { echo …; return 1; }; fi` → aborts BEFORE develop/hook-activation; (2) identity precheck at top of `gitflow_init` (fail loud, no half-apply); (3) identity guard in `gitflow-migrate.sh:migrate_local`. Recovery: set faunosteo local identity → deactivate hook → delete premature develop → reinit (socle commits with hook inactive, as designed) → main==develop @ socle, tree clean, master renamed. Verified: shellcheck clean, 57/57 tests pass, hardened init on an identity-less repo aborts rc1 with ZERO mutation.
- **Status**: resolved (`lib/gitflow.sh` + `lib/gitflow-migrate.sh`, uncommitted working tree as of the gitflow chantier).
- **Reference**: [[LRN-068]] (transactional-bootstrap principle). Discovered mid gitflow-migration 2026-06-29. Sibling chantier learning [[LRN-067]].
## BLK-013 — `make plugin` Error 127: npm absent on apt-`nodejs` host
- **Date**: 2026-06-30
- **Friction**: `make plugin` (→ `install-plugins.sh`) aborts at Step 4 (gsd-pi): `install-plugins.sh: line 425: npm: command not found` → `make: *** [Makefile:10: plugin] Error 127`. Steps 5-10 never run, AND the post-Step-4 stray-dir cleanup (Step 8.5) never reached → the [[BDR-030]]/[[LRN-042]] residual (stray `$REPO/.agents/skills` + `$REPO/.claude/skills`, promised "auto-cleaned next `make plugin`") silently persists run after run. SessionStart banner already showed `gsd v2 ✗`.
- **Real cause**: Debian/apt `nodejs` package ships `node` WITHOUT `npm` (npm = separate apt pkg). `/usr/bin/node` present (v22.22.1); its bindir has acorn/corepack/semver but NO npm/npx — npm genuinely uninstalled, not a PATH miss. install-plugins.sh Step 1 checks `node >=22` but NEVER verifies npm — assumes npm ships with node (true for nodesource/brew/dnf paths, FALSE for plain apt).
- **Solution**: corepack (ships with node) over apt npm (apt npm could pull a divergent 2nd node). `corepack enable --install-directory "$HOME/.local/bin" npm` → npm 11.18.0 shim, no sudo, `~/.local/bin` already on PATH. Then `npm config set prefix "$HOME/.local"` — default prefix `/usr` is root-owned → `npm install -g` would EACCES; `~/.local` writable + bins land on PATH. Persisted in `~/.npmrc`. Re-run → EXIT=0, Step 4 ✓ (`gsd-pi@2.64.0`), Step 8.5 ran (`Removed stray repo-local skills dir: .agents/skills` + `.claude/skills`). Caveat: gsd-pi DEPRECATED + postinstall scripts SKIPPED (npm 11 `allow-scripts`) — `gsd --version/--help` ok, full provisioning would need `npm install -g --allow-scripts=gsd-pi,… gsd-pi`.
- **Fix-forward**: install-plugins.sh Step 1 should GUARANTEE npm on apt-`nodejs` hosts — detect missing npm + `corepack enable npm` (not just check node) → stops Error 127 recurring on any fresh apt machine.
- **Status**: resolved (env-level: corepack shim + npm prefix; zero repo change). Fix-forward (script hardening) NOT built.
- **Reference**: discovered fixing `make plugin` 2026-06-30. Distinct from [[BLK-003]] (macOS playwright hardcoded path) + the Playwright-chromium `make plugin` failure. Blocked residual = [[BDR-030]]/[[LRN-042]].
- **Update 2026-07-01**: fix-forward BUILT. install-plugins.sh Step 1 gained unconditional npm guard (`corepack enable npm` → distro `install npm` fallback → fatal `exit 1`), placed AFTER the `NODE_OK` short-circuit so a node>=22-present-but-npm-absent host no longer skips it. Now fully resolved (env-level + script). shellcheck/`bash -n` clean; fresh-apt live validation still pending. Commit `1f2c1cc`, branch `bugfix/install-plugins-npm-guard`.
---
## BLK-014 — `make install` aborts npm EEXIST when claude already present
- **Date**: 2026-07-01
- **Friction**: `make install` → install.sh Step 2 `npm install -g @anthropic-ai/claude-code@latest` fails EEXIST on `~/.local/bin/claude` when claude already installed → `else err` → `exit 1`. Bootstrap not idempotent on Claude Code step; rest (auth, symlinks, plugins) never runs.
- **Real cause**: claude installed via NATIVE installer, not npm — `~/.local/bin/claude` = symlink → `~/.local/share/claude/versions/<v>` (`npm ls -g @anthropic-ai/claude-code` = empty; `claude --version` = 2.1.197). npm prefix `~/.local` (set by [[BLK-013]]) targets same `~/.local/bin/claude` → npm won't clobber a bin it doesn't own → EEXIST. Channel conflict, not double-install. Step had NO presence guard, unlike RTK (install-plugins.sh:388) / GSD (:419) / claude check (:252).
- **Solution**: install.sh — skip-if-present guard `command -v claude` (mirror RTK/GSD), npm only fresh machine (`elif`). update-all.sh — channel-aware updater: `npm ls -g` → npm-managed uses npm, else native uses `claude update` (self-update). Never `npm --force` (would clobber native, break self-update).
- **Status**: resolved. Fix `8dc4027`, branch `bugfix/install-claude-idempotent`, pending merge validation.
- **Reference**: [[BLK-013]] npm prefix `~/.local` = contributing factor (npm bin over native bin). install-plugins.sh already pointed to code.claude.com (native) — install.sh was the npm outlier. Fresh-machine `elif npm` branch channel-consistency = open design question (potential BDR). Pattern → [[LRN-085]].
- **Update 2026-07-01**: MERGED `2393ca5` (bugfix/install-claude-idempotent → develop), pushed — supersedes "pending merge validation". The open channel-consistency question is RESOLVED by [[BDR-046]] (fresh install → native installer, npm dropped for claude); install.sh has no `elif npm` branch → nothing left to trancher.
## BLK-015 — `gitflow_finish` ignored its args, merged the CURRENT branch not the one asked
- **Date**: 2026-07-03
- **Friction**: audit 2026-07-02 — `gitflow.sh finish bugfix audit-bugs` run while checked out on `feature/audit-tokens` merged audit-tokens (LOT3), NOT audit-bugs. Final develop state identical (disjoint hunks) so no data damage, but the merge order was silently wrong. UX trap: the command LOOKS like it targets `bugfix/audit-bugs`.
- **Real cause**: CLI dispatch (`lib/gitflow.sh:257` `finish) gitflow_finish "$@"`) forwards args, but the function derived its source from `HEAD` (`git symbolic-ref`) and NEVER read `$1/$2` → the `<type> <name>` were silently dropped. Merge source = ambient state (checked-out branch), not the named target. Design intended finish to always operate on HEAD (human gate = "be on the branch"), but nothing enforced that passed args, if any, MATCH the branch you're on.
- **Solution**: `gitflow_finish [<type> <name>]` — args now an optional safety ASSERTION: present AND `"$req_type/$req_name" != "$br"` → error `operates on the current branch 'X', but you asked 'Y' — checkout 'Y' first`, rc 2. No args = behavior unchanged (only real caller `skills/gitflow/SKILL.md:36` + every test pass none → zero regression). +7 regression assertions (`gitflow-test.sh` T12, numbered to dodge collision with reconcile's own T6c).
- **Status**: resolved. Commit `d9fdd4c`, branch `bugfix/gitflow-finish-args`.
- **Reference**: journal 2026-07-02 (trap noted, not fixed) → fixed 2026-07-03. Pattern → [[LRN-089]] (pass-through wrapper deriving target from ambient state = silent contract violation).
+7 -3
View File
@@ -30,17 +30,21 @@ idx_only=$($GREP -oE '^\| LRN-[0-9]+' "$DRIFT" | $GREP -oE 'LRN-[0-9]+' | sort -
if printf '%s\n' "$idx_only" | $GREP -qx "LRN-020"; then no "T1c teeth LOST — Index path also yields LRN-020"; else ok "T1c teeth intact — Index path OMITS LRN-020 (engine reading the Index would fail T1b)"; fi
echo; echo "=== T2 BLK status — LAST block wins (the BLK-008 trap) ==="
b="$MEM/blockers.md"
# Hermetic fixture, not the live registry (job3 B1): a frozen post-BLK-009
# snapshot so this test never reds again just because a future blocker gets
# closed. Re-freeze this fixture (copy the live blockers.md) if BLK-008's
# compound-status trap or the open/resolved mix it exercises ever changes.
b="$FIX/blockers-snapshot.md"
case "$(reconcile_blk_current_status "$b" BLK-008)" in
*RESOLVED*|*resolved*) ok "T2a BLK-008 current = resolved (read FINAL, not the middle REVERTED)";;
*) no "T2a BLK-008 misread as non-resolved — fell into the compound-status trap";;
esac
case "$(reconcile_blk_current_status "$b" BLK-009)" in
*open*|*upstream*) ok "T2b BLK-009 current = upstream/open";;
*RESOLVED*|*resolved*) ok "T2b BLK-009 current = resolved (fixture frozen post-2026-07-06 closure)";;
*) no "T2b BLK-009 misread";;
esac
open_ids=$(reconcile_blk_open "$b" | cut -f1 | sort | tr '\n' ' ')
if [ "$open_ids" = "BLK-001 BLK-003 BLK-009 " ]; then ok "T2c open blockers = {001,003,009}"; else no "T2c open = [$open_ids], expected {001,003,009}"; fi
if [ "$open_ids" = "BLK-001 BLK-003 " ]; then ok "T2c open blockers = {001,003}"; else no "T2c open = [$open_ids], expected {001,003}"; fi
echo; echo "=== T3 deferral lexical sweep (HONEST LIMIT: marked-only) ==="
defer=$(reconcile_deferrals "$FIX/todo-snapshot.md" "$MEM/decisions.md")
+8 -6
View File
@@ -39,13 +39,15 @@ The agent runs a **ship-and-handover pipeline** with explicit gates:
5. **DEPLOY PAUSE** — List exact deploy artifacts: changed files since baseline, deploy hints from project (vercel.json, netlify.toml, Dockerfile, .github/workflows/deploy.yml, etc.), and the deploy process in plain words. Use AskUserQuestion: "Deploy done? (Yes / Not yet / Skip validate)". Block until Yes or Skip.
6. **/web-validate (live site)** — Run validator-analyzer against the deployed URL. Capture `SCORE_VALIDATE`.
7. **GATE — per-axis threshold ≥17/20** — Compute final `SCORE_*_AFTER` for SEO classique, GEO (IA), HARDEN, VALIDATE. If ANY < 17/20: STOP. Generate `.claude/audits/HANDOVER-ROADMAP.md` with prioritized analysis of what's blocking each below-threshold axis. Do NOT write the client deliverable. Report to user.
8. **DOC GENERATION (only if all scores ≥17/20)** — Read `.claude/memory/` registries + full git history. Ask whether to include build/deploy chapter. Synthesize the client deliverable using the 4-chapter structure:
8. **DOC GENERATION (only if all scores ≥17/20)** — Read `.claude/memory/` registries + full git history. Ask whether to include build/deploy chapter. Synthesize the client deliverable using the 6-chapter structure (BDR-013, full spec in `agents/client-handover-writer.md`):
- **§1 Ce qu'il fallait faire (et pourquoi)** — brief + motivation, 100–180 words.
- **§2 Ce qui a été fait** — lay summary, **≤300 words, zero technical jargon**, **no internal tool/skill names** (no `/seo`, `/harden`, `/web-validate`, `seo-analyzer`, etc. — replace with concept names: référencement / sécurité / conformité technique). Forbidden-token grep gate runs before write.
- **§3 Ce qui vous reste à faire** — action-only checklist grouped by cadence (one-time / monthly / quarterly / yearly / when something changes).
- **§4 Détails techniques (pour les curieux)** — score table (SEO classique + GEO + sécurité + conformité, before/after, gated independently at ≥17/20), vulgarized BDR decisions, phases with technical detail, optional glossary.
- **§5 Annexe — plateformes externes** (web/local-business only).
- **§6 Annexe — build & déploiement** (only if requested).
- **§2 Résultats — état de santé du site (avant / après)** — the score table (SEO classique + GEO + sécurité + conformité, before/after, gated independently at ≥17/20), promoted to the top of the doc for immediate impact.
- **§3 Ce qui a été fait** — lay summary, **≤300 words, zero technical jargon**, **no internal tool/skill names** (no `/seo`, `/harden`, `/web-validate`, `seo-analyzer`, etc. — replace with concept names: référencement / sécurité / conformité technique). Forbidden-token grep gate runs before write (covers chapters 1–5).
- **§4 Vos informations officielles (NAP)** — single source-of-truth table the client reuses across every external platform in §7 (web/local-business only).
- **§5 Ce qui vous reste à faire** — action-only checklist grouped by cadence (one-time / monthly / quarterly / yearly / when something changes).
- **§6 Détails techniques (pour les curieux)** — vulgarized BDR decisions, phases with technical detail, optional glossary (score table NOT here — promoted to §2).
- **§7 Annexe — plateformes externes** (web/local-business only).
- **§8 Annexe — build & déploiement** (only if requested).
9. **RENDER** — Write `LIVRAISON.md` (fr) or `HANDOVER.md` (en) at project root, then run `scripts/handover-to-pdf.sh` to produce the matching branded `.html` (always) and `.pdf` (when a PDF engine is on the host: weasyprint > wkhtmltopdf > chromium). HTML/PDF use the ZenQuality cover page, green palette, Inter + Playfair Display typography, running header/footer with project name + page numbers.
Flags:
+3 -3
View File
@@ -26,9 +26,9 @@ allowed-tools:
Invoke the `capitalize` skill now and run it in **ritual mode**: the full
pipeline (STEP 0 precheck → STEP 1 auto-scan → STEP 2 dedup → STEP 2B TODO
reconcile → STEP 3 approval gate → STEP 4 write → STEP 5 journal → STEP 6
handoff), PLUS STEP 1B's explicit 3-question reflection (what did you decide /
learn / block).
reconcile → STEP 3 approval gate → STEP 4 write → STEP 5 journal → STEP 5B
memory commit → STEP 6 handoff), PLUS STEP 1B's explicit 3-question reflection
(what did you decide / learn / block).
Ritual answers are deduped like any other candidate — a dup is dropped and its
existing ID shown, not re-logged. This is the upgrade over the legacy `/close`,
+5 -5
View File
@@ -211,7 +211,7 @@ Author a runbook, seed the incident ledger, commit both, then proceed to STEP 1.
| Rollback note | "One-line rollback note (optional)?" | omit if blank |
| Push deploy tags | "`push_deploy_tags`? (true / false)" | `false` |
**Using** `templates/deploy/PROCEDURE.md` **as base, populate** fields from interview answers + detected artifacts:
**Using** `~/.claude/templates/deploy/PROCEDURE.md` **as base, populate** fields from interview answers + detected artifacts:
- Substitute `$DEPLOY_HOST` with the supplied host (keep literal `$DEPLOY_HOST` if none given).
- Include only the annotated steps whose artifact was detected; keep all fixed steps.
- Set `# @config push_deploy_tags=<answer>` in the header.
@@ -232,7 +232,7 @@ Present the full draft `PROCEDURE.md`.
**On approve — write + seed + commit:**
1. Write `.claude/deploy/PROCEDURE.md` (Write tool — the approved draft).
2. Seed `.claude/deploy/INCIDENTS.md` from `templates/deploy/INCIDENTS.md` (Write tool).
2. Seed `.claude/deploy/INCIDENTS.md` from `~/.claude/templates/deploy/INCIDENTS.md` (Write tool).
3. Ensure the target project's `.gitignore` contains
`.claude/deploy/PENDING.json` (append if missing — the transient bridge must
not be committed).
@@ -243,7 +243,7 @@ Present the full draft `PROCEDURE.md`.
`.claude/` rule). Do NOT commit anything further.
5. Commit via the allowlist helper:
```bash
bash lib/deploy-commit.sh commit \
bash ~/.claude/lib/deploy-commit.sh commit \
"feat(deploy): bootstrap runbook" \
.claude/deploy/PROCEDURE.md .claude/deploy/INCIDENTS.md
```
@@ -350,7 +350,7 @@ changes a prod path).
**On approve — one ATOMIC commit of both files:**
```bash
bash lib/deploy-commit.sh commit \
bash ~/.claude/lib/deploy-commit.sh commit \
"docs(deploy): patch <step> — recovered from <err>" \
.claude/deploy/PROCEDURE.md .claude/deploy/INCIDENTS.md
```
@@ -395,7 +395,7 @@ The deploy succeeded. Lay the oracle and close out.
bookmark; `STATE.json` is the oracle).
5. Commit the oracle:
```bash
bash lib/deploy-commit.sh commit "chore(deploy): mark <date> @ <short>" \
bash ~/.claude/lib/deploy-commit.sh commit "chore(deploy): mark <date> @ <short>" \
.claude/deploy/STATE.json
```
6. **Delete `.claude/deploy/PENDING.json`** — the deploy is no longer in
+5 -4
View File
@@ -24,9 +24,10 @@ single-target and cannot do the directed / fan-out merges below.
## Branch model
`main` (prod) · `develop` (integration, off main) · `feature/*` and `bugfix/*`
(off develop → develop) · `release/*` (off develop → main + back-merge develop)
· `hotfix/*` (off main → main + develop [+ any open release/*]).
`main` (prod) · `develop` (integration, off main) · `feature/*`, `bugfix/*` and
`chore/*` (off develop → develop; chore = memory/doc maintenance) · `release/*`
(off develop → main + back-merge develop) · `hotfix/*` (off main → main +
develop [+ any open release/*]).
## Operations — all via the lib
@@ -41,7 +42,7 @@ bash ~/.claude/lib/gitflow.sh protected-base [br] # rc 0 on main/develop — the
| Current branch | Merges into | then |
|---|---|---|
| `feature/*` · `bugfix/*` | develop | delete |
| `feature/*` · `bugfix/*` · `chore/*` | develop | delete |
| `release/*` | main + develop | delete |
| `hotfix/*` | main + develop + any open `release/*` | delete |
+3 -3
View File
@@ -593,9 +593,9 @@ NEXT STEPS :
- **Framework awareness.** Don't recommend `.htaccess` on a Next.js /
Astro / Cloudflare Pages project. Use the framework-native mechanism
(next.config.js headers(), astro middleware, _headers).
- **Respect CLAUDE.md architecture rules.** Security headers and redirects
are non-negotiable defaults per user's global CLAUDE.md — every public
site must ship them. Flag absence as Critique, not Moyenne.
- **Security headers and redirects are non-negotiable defaults of this
skill** — every public site must ship them. Flag absence as Critique,
not Moyenne.
- **External validators are authoritative on live headers, not the code.**
If Observatory/SecurityHeaders/SSL Labs and the code audit disagree,
the external grade reflects the deployed production config — the code
+4 -14
View File
@@ -15,14 +15,14 @@ $ARGUMENTS
## PROGRESS PROTOCOL
Every STEP must announce itself with a header BEFORE its work block, so the
user always sees where they are in the 11-step pipeline:
user always sees where they are in the 12-step pipeline (STEP 0–11):
```
━━━ STEP <N>/11 — <TITLE> ━━━ (~<estimated minutes>)
why: <one sentence — what's at risk if this step is skipped>
```
Long-running steps (5 SCAFFOLD, 5d GRAPHIFY, 8 IMPLEMENT) must print a 1-line
Long-running steps (5 SCAFFOLD, 8 IMPLEMENT) must print a 1-line
liveness ping every ~30 s of agent work — `… still working: <last action>` —
so the user does not assume Claude has hung.
@@ -85,7 +85,7 @@ enriched contract.
## STEP 5 — SCAFFOLD
Load `$HOME/.claude/agents/scaffolder.md`. Pass: BRIEF + DESIGN + `~/.claude/templates/project-CLAUDE.md` + `~/.claude/CLAUDE.md`.
Creates: CLAUDE.md, settings, structure, config, empty entry points, .gitignore, .env.example, .claude/tasks/TODO.md, .claude/memory/{decisions,learnings,blockers,journal,evals}.md, .claude/audits/. NO README, NO features.
Creates: CLAUDE.md, `.claude/settings.json`, `.claudeignore`, `.gitignore`, `.env.example`, empty entry points. NO README, NO features, NO `.claude/tasks/` or `.claude/memory/` (not bootstrapped by this flow — copy from `~/.claude/templates/memory/` manually if wanted before STEP 10b's memory commit).
Verify: `git init` + build passes.
## STEP 5b — CREATE README
@@ -105,16 +105,6 @@ If `fast-libs` signal was detected in STEP 0 (Next.js, React 18+, Prisma, Supaba
4. Print: `📚 ctx7 docs pre-fetched for: <libs>. Cache at .ctx7-cache/`
If `ctx7` not installed or no fast-libs → skip silently.
## STEP 5d — GRAPHIFY SCAFFOLD (light pass)
If `graphify` CLI is installed AND complexity >= 30%:
1. Run light graphify on the scaffold:
```bash
graphify . --output graphify-out --mode quick 2>/dev/null || true
```
2. Add `graphify-out/` to `.gitignore` if not already present.
3. Print: `🔗 Scaffold graph generated at graphify-out/`
If `graphify` not installed or complexity < 30% → skip silently.
## STEP 5e — ANIMATION LIB (auto-install)
Install `motion` (ex-`framer-motion`, rebranded Nov 2024) when the stack supports it.
The scaffold has just been validated by the user, so install proceeds silently.
@@ -183,7 +173,7 @@ finishing-a-development-branch", stop and return.
If `graphify` CLI is installed AND complexity >= 30%:
1. Run full graphify on the implemented project:
```bash
graphify . --output graphify-out 2>/dev/null || true
graphify . --out graphify-out 2>/dev/null || true
```
2. Print: `🔗 Full project graph updated at graphify-out/`
If `graphify` not installed or complexity < 30% → skip silently.
+7 -7
View File
@@ -96,7 +96,7 @@ L'agent génère :
- `.claudeignore`
- `.gitignore` (safety check)
- `.claude/tasks/TODO.md`, `.claude/memory/{decisions,learnings,blockers,journal,evals}.md`
- **Pas encore** `ROADMAP.md` (décision STEP 9)
- **Pas encore** `ROADMAP.md` (généré uniquement via `/onboard add gsd` — voir Next steps)
Si `CLAUDE.md` existe déjà : lire son contenu, ne PAS écraser — fusionner après STEP 3.
@@ -122,7 +122,7 @@ Cas :
Stack: <reason>. Aucune lib d'animation détectée.
Install `<cmd>` ? (yes / skip)
```
Sur `yes` → exécuter `recommend_anim_install_cmd "$pkg"` puis confirmer.
Sur `yes` → `cmd=$(recommend_anim_install_cmd "$pkg"); eval "$cmd"` puis confirmer.
Sur `skip` → continuer silencieusement.
- **`status=eligible` AND une lib anim déjà présente** (motion, framer-motion, gsap, lottie, react-spring, popmotion, auto-animate) → log info uniquement :
@@ -143,7 +143,7 @@ bash "$HOME/.claude/lib/gitflow.sh" init
Sur un repo existant, cela : renomme `master`→`main` si besoin (LOCAL), crée
`develop` depuis main, réconcilie le socle `.gitignore` (additif — n'écrase
jamais les règles du projet), installe le hook pre-commit versionné, et fait UN
commit `chore: adopt gitflow socle + hook` sur main (pendant que le hook est
commit `chore: adopt gitflow socle + pre-commit hook` sur main (pendant que le hook est
inactif → jamais auto-bloqué). Idempotent — un re-run est un no-op.
**Annoncer le renommage master→main** s'il a lieu. Le renommage est LOCAL ;
@@ -251,7 +251,7 @@ test -f graphify-out/GRAPH_REPORT.md && echo "graph-exists"
- **Graphe déjà présent + récent** (fichier < 7j) → skip, réutiliser l'existant.
- **Sinon** → run :
```bash
graphify . --output graphify-out 2>&1 | tail -20
graphify . --out graphify-out 2>&1 | tail -20
```
Puis `test -f graphify-out/GRAPH_REPORT.md` pour valider.
@@ -630,7 +630,7 @@ Agent(
**Cas gstack ON + URL live OU dev server launchable :**
```
Skill(
skill="gstack:design-review",
skill="design-review",
args="--url <url or http://localhost:PORT> --output .onboard-audit/design.md --audit-only"
)
```
@@ -673,7 +673,7 @@ Agent(
**Cas gstack ON + URL live :**
```
Skill(
skill="gstack:browse",
skill="browse",
args="--lighthouse --url <url or http://localhost:PORT> --output .onboard-audit/perf-lighthouse.json"
)
```
@@ -715,7 +715,7 @@ Agent(
**Cas gstack ON + URL live :**
```
Skill(
skill="gstack:browse",
skill="browse",
args="--axe --url <url> --output .onboard-audit/a11y-axe.json"
)
```
+4 -3
View File
@@ -116,8 +116,9 @@ bash "$HOME/.claude/lib/profile.sh" $ARGUMENTS
- gstack skills still depend on `~/.claude/skills/gstack/bin/` for telemetry,
update-check, learnings — script doesn't touch that infra. Disabled skills
are just hidden from Claude Code's scanner; the gstack repo stays installed.
- Profile changes do NOT toggle Claude Code plugins (ui-ux-pro-max, etc.) or
MCP servers — those are advisory only. The user runs `claude plugin
enable|disable` and `claude mcp add|remove` manually.
- Profile changes DO toggle the managed Claude Code plugins (ui-ux-pro-max,
plugin-dev, pr-review-toolkit) and the `magic` MCP — see the Mechanism table
above (BDR-008). Anything outside that managed set stays manual:
`claude plugin enable|disable`, `claude mcp add|remove`.
- `set` is destructive in the sense that it disables non-listed gstack skills.
Use `apply` if the user wants additive behavior.
+2 -2
View File
@@ -421,7 +421,7 @@ PROCHAINE ÉTAPE : <highest-priority immediate action>
- **Merge, don't overwrite.** On re-run, previous SEO.md's Historique
section is preserved. Current content moves to Historique with
summary (date + score + key changes).
- **Every user action has automation options.** Per user CLAUDE.md,
mandatory from `automation-catalog.md`.
- **Every user action has automation options.** Mandatory per the agents'
spec, sourced from `automation-catalog.md`.
- **Scoring weights per user decision**: GEO = 20% local B2C, 25%
SaaS/national/content. Combined score formula is explicit in §1.
+10 -30
View File
@@ -11,20 +11,14 @@ Use this table during STEP 0 when the user has not already specified depth.
| Repository has `<lang>.html`/`hreflang` but no production URL provided | LOCAL with note | Cannot validate hreflang resolution without live URL — flag as user action. |
| `--no-external` flag set | LOCAL forced | Honour explicit override even if FULL signals present. |
# Score-weight table (out of /20)
# Score-weight table
| Axis | LOCAL weight | FULL weight |
|---|---|---|
| Meta + canonical + lang | 3 | 3 |
| JSON-LD / Schema.org | 3 | 3 |
| Sitemap + robots.txt + llms.txt | 3 | 3 |
| Headings + alt + i18n | 3 | 3 |
| Core Web Vitals | 0 | 3 |
| Security + redirects + indexability | 4 | 2 |
| External presence (GMB, citations, Wikidata) | 0 | 3 |
| Content shape (TL;DR, definition lead, citable stats) | 4 | 0 |
LOCAL caps at 20. FULL caps at 20. Never report above 20.
Owned by the agents, not this file — classical SEO weights are in
`agents/seo-analyzer.md` (STEP 9, 7 axes FULL / 4 axes LOCAL, percentage
weights varying by business type); GEO weights are in
`agents/geo-analyzer.md` (STEP 10, 6 axes FULL / 5 axes LOCAL). Combined
score formula (0.80/0.20 classical/GEO local-B2C, 0.75/0.25 SaaS/national) is
in `skills/seo/SKILL.md` (~line 273).
# Dedup rules — overlap with sibling skills
@@ -38,20 +32,6 @@ LOCAL caps at 20. FULL caps at 20. Never report above 20.
# Envelope schema for `.claude/audits/SEO.md`
```
# SEO + GEO Audit — <date>
DEPTH: LOCAL | FULL
SITE: <root path or production URL>
SCORE_CLASSICAL: <n>/20
SCORE_GEO: <n>/20
## §1 Critical alerts
## §2 Score breakdown
## §3 Classical SEO findings (meta, sitemap, JSON-LD, headings, …)
## §4 Local SEO / NAP (only if local-business)
## §5 Core Web Vitals (FULL only)
## §6 Security + indexability cross-refs (link to /harden)
## §7 GEO / AI optimisation
## §8 Fix bundle (auto-applied in aggressive mode)
## §9 User actions (manual)
```
Owned by `skills/seo/SKILL.md` (~lines 278-352, the real §0-§15 structure),
not this file — both agents' envelopes are keyed to it
(`agents/seo-analyzer.md` STEP 13, `agents/geo-analyzer.md` STEP 14).
+2 -3
View File
@@ -353,9 +353,8 @@ Install for better LOCAL coverage :
- **Framework awareness.** For SPA/JS frameworks, validate built
output (`dist/`, `_site/`, `build/`, `out/`), not JSX/TSX source.
Warn if no build dir present.
- **Respect CLAUDE.md architecture rules.** Public websites must ship
WCAG 2.1 AA per France RGAA 4.1 when in scope. Flag AA violations
as Haute, A violations as Critique.
- **Public websites must ship WCAG 2.1 AA** (France: RGAA 4.1) when in
scope. Flag AA violations as Haute, A violations as Critique.
- **External validators are authoritative on live URLs.** validator.nu
and jigsaw are the W3C backends. If a local tool disagrees with
them, trust the W3C backend; flag the divergence as a finding.
+6 -5
View File
@@ -12,6 +12,7 @@ rules:
- Open a blocker as soon as friction > 15 min wasted. Close it with a real cause, not "moved on".
- Link to upstream issue / PR / commit when applicable.
- If cause is a bug in a dependency, set status upstream with a pointer to the tracker.
- Entries in English, caveman format (BDR-009): drop articles + filler, fragments OK, technical terms exact.
---
# Blockers registry (BLK)
@@ -25,10 +26,10 @@ rules:
## BLK-XXX - <friction>
- **Date** : YYYY-MM-DD
- **Friction** : <ce qui était bloqué>
- **Cause réelle** : <cause racine>
- **Solution** : <workaround ou fix>
- **Statut** : open | resolved | upstream
- **Date**: YYYY-MM-DD
- **Friction**: <what was blocked>
- **Real cause**: <root cause>
- **Solution**: <workaround or fix>
- **Status**: open | resolved | upstream
-->
+10 -9
View File
@@ -14,6 +14,7 @@ rules:
- Append-only. Never rewrite past entries - add a new one with status superseded if needed.
- One entry per non-trivial choice. Trivial = reversible in under 10 min with no cross-file impact.
- Capture why more carefully than what - the what rots, the why lasts.
- Entries in English, caveman format (BDR-009): drop articles + filler, fragments OK, technical terms exact.
---
# Decisions registry (BDR)
@@ -25,15 +26,15 @@ rules:
<!-- Append entries below. Template:
## BDR-XXX - <titre>
## BDR-XXX - <title>
- **Date** : YYYY-MM-DD
- **Statut** : proposed | accepted | deprecated | superseded
- **Décision** : <ce qui a été choisi>
- **Pourquoi** : <motivation>
- **Alternatives rejetées** :
- Option A - <raison du rejet>
- Option B - <raison du rejet>
- **Référence** : <commit / PR / fichier>
- **Date**: YYYY-MM-DD
- **Status**: proposed | accepted | deprecated | superseded
- **Decision**: <what was chosen>
- **Why**: <motivation>
- **Rejected alternatives**:
- Option A - <why rejected>
- Option B - <why rejected>
- **Reference**: <commit / PR / file>
-->
+6 -5
View File
@@ -13,6 +13,7 @@ rules:
- Action keep - the output is fit for purpose as-is.
- Action correct - needs revision; capture what.
- Action deprecate - the approach itself is flawed; link to the decision that replaces it.
- Entries in English, caveman format (BDR-009): drop articles + filler, fragments OK, technical terms exact.
---
# Evals registry (EVAL)
@@ -26,10 +27,10 @@ rules:
## EVAL-XXX - <output>
- **Date** : YYYY-MM-DD
- **Output** : <ce qui a été produit>
- **Méthode** : <comment cela a été évalué>
- **Anomalies** : <ce qui est faux, manquant, surprenant>
- **Action** : keep | correct | deprecate
- **Date**: YYYY-MM-DD
- **Output**: <what was produced>
- **Method**: <how it was evaluated>
- **Anomalies**: <what is wrong, missing, surprising>
- **Action**: keep | correct | deprecate
-->
+4 -3
View File
@@ -7,6 +7,7 @@ rules:
- One heading per date (YYYY-MM-DD), not per session.
- Append at the end. Never edit past entries.
- Keep it terse. Details belong in decisions/learnings/blockers - this is a timeline only.
- Entries in English, caveman format (BDR-009): drop articles + filler, fragments OK, technical terms exact.
---
# Journal
@@ -15,8 +16,8 @@ rules:
## YYYY-MM-DD
- <ligne 1>
- <ligne 2>
- <ligne 3-5 max>
- <line 1>
- <line 2>
- <line 3-5 max>
-->
+6 -5
View File
@@ -11,6 +11,7 @@ rules:
- Capture learnings that apply beyond the current task.
- Abstract from the incident - the pattern is what is reusable, not the one-shot fact.
- Link to source (commit, file, PR) when possible.
- Entries in English, caveman format (BDR-009): drop articles + filler, fragments OK, technical terms exact.
---
# Learnings registry (LRN)
@@ -22,11 +23,11 @@ rules:
<!-- Append entries below. Template:
## LRN-XXX - <pattern abstrait>
## LRN-XXX - <abstract pattern>
- **Date** : YYYY-MM-DD
- **Pattern** : <ce qui a été observé, formulé de manière réutilisable>
- **Contexte** : <où et quand, concret>
- **Application future** : <quand se rappeler de ceci>
- **Date**: YYYY-MM-DD
- **Pattern**: <what was observed, phrased for reuse>
- **Context**: <where and when, concrete>
- **Future application**: <when to recall this>
-->
+1 -1
View File
@@ -1,6 +1,6 @@
# <PROJECT NAME> — CLAUDE.md
# Generated by /init-project. Single source of truth for Claude in this repo.
# Generated by /init-project or /onboard. Single source of truth for Claude in this repo.
# Global rules: ~/.claude/CLAUDE.md — this file extends or overrides them.
---
+1
View File
@@ -39,6 +39,7 @@
| `default` | Prompts on first use of each tool | Normal development |
| `acceptEdits` | Auto-accepts file edits, prompts for Bash | Trusting sessions |
| `plan` | Read-only — Claude plans, cannot execute | Code review, audit |
| `auto` | Research preview — agentic default, permission model evolving. This config's default (BDR-004) | Daily driving with guardrails |
| `bypassPermissions` | Skips all prompts — **dangerous** | CI/CD only, sandboxed env |
## Security notes