refactor(doctrine): C2 coherence — 30 doctrine/skill tensions resolved, doctrine wins (BDR-099)

One ask policy; mandated executors exempt from the delegation rule; skill plan satisfies the planning rule; journal line exempt from the approval gate; chore = maintenance without new behaviour; small fix on develop = bugfix; BDR-068 written as the one auto-finish exception; deploy routes to /deploy. Skills and agents follow: hotfix types by base + skips the design gate on trivial; capitalize/close create missing registries; commit-change asks the branch type; doc/seo/web-validate/refactor branch through the aiguillage; tour reports BREAKING fixes as needs-decision and runs doc-syncer two-mode; client-handover applies audit bundles from its main loop behind one gate; init-project/onboard use the 200-file graphify signal and bootstrap memory; release-candidate gates the tag push only; push wording aligned with the BDR-095 hooks; stale pointers fixed (§ Language, .gsd/ROADMAP.md, handover script path, design-gate lists).
This commit is contained in:
bastien
2026-09-24 20:25:40 +02:00
parent 1b20beccda
commit d82c06f572
29 changed files with 350 additions and 190 deletions
+4 -2
View File
@@ -272,7 +272,7 @@ A bugfix with an understood root cause is almost always worth one entry:
```
4. Append approved entries + update the Index. Add a line to today's heading in `.claude/memory/journal.md`.
**Language rule**: written entries are ALWAYS in English (see CLAUDE.md "Memory registries" § Language). The interactive gate may mirror the user's language; the appended entries must not.
**Language rule**: written entries are ALWAYS English AND caveman — fragments, articles dropped, code/IDs/quoted errors verbatim — per CLAUDE.md "Memory registries" (Always English, always caveman). The interactive gate may mirror the user's language; the appended entries must not.
If the bug was trivial and the root cause not transferable → skip with `CAPITALIZE: trivial, skip`.
@@ -287,7 +287,9 @@ hash, and no-ops if nothing was written.
- No fix without understanding the root cause first (STEP 2/3).
- Reflection (GATHER, INVESTIGATE, DIAGNOSIS, contract, loop decisions) NEVER
leaves this main loop; execution NEVER stays in it — the executor is the
sonnet-pinned bugfixer subagent (BDR-066).
sonnet-pinned bugfixer subagent (BDR-066). A skill-mandated executor is exempt from the doctrine's "don't delegate
few-tool-call work" rule (CLAUDE.md "Workflow" names that exception:
skill-mandated dispatches run as written).
- The executor is re-dispatched FRESH on every round-trip (NEED-DECISION,
ECARTS, BLOCK) — feedback travels as contract path + named
gaps/decisions, never as transcript.
+20 -14
View File
@@ -9,7 +9,7 @@ description: |
Triggers: "capitalize", "before clear/compact", "flush memory", "don't
lose this", "avant de clear/compact", "capitalise ce qui manque",
"close", "fin de journée", "checkpoint memory".
argument-hint: "[--ritual] [--no-push] (scans conversation + git + TODO against .claude/memory/; --ritual adds the 3-question reflection; --no-push holds memory on the chore branch instead of the default auto-merge+push)"
argument-hint: "[--ritual] [--no-push] (scans conversation + git + TODO against .claude/memory/; --ritual adds the 3-question reflection; --no-push holds memory on chore/<name>: pushed to origin by the hooks, NOT merged (finish skipped), merge when ready; default = auto-finish into develop)"
allowed-tools:
- Read
- Edit
@@ -65,17 +65,22 @@ ls .claude/memory/decisions.md .claude/memory/learnings.md \
ls .claude/tasks/TODO.md 2>/dev/null
```
- `.claude/memory/` missing entirely → print and STOP (do NOT create here —
that is `/onboard` / `/init-project` responsibility):
```
⚠️ .claude/memory/ absent. Lance `/onboard` (ou `/init-project`) pour créer
les registres avant de capitaliser.
- `.claude/memory/` missing entirely → create it first (CLAUDE.md "Session
start": either missing → create from the templates), then proceed:
```bash
mkdir -p .claude/memory
cp -n ~/.claude/templates/memory/{decisions,learnings,blockers,evals,journal}.md .claude/memory/
```
`/onboard` stays the fuller setup (CLAUDE.md, settings, audits) — this
bootstraps only the five registries capitalize writes to.
- Some registry files missing → name them, create each from
`~/.claude/templates/memory/<name>.md`, continue.
- `.claude/tasks/TODO.md` missing → the TODO reconcile volet (STEP 2B) is
**skipped**. Do NOT create it (same posture as the registries). Registries
still run.
- `.claude/tasks/TODO.md` missing → create a minimal one, then run the TODO
reconcile volet (STEP 2B) on it:
```bash
mkdir -p .claude/tasks
printf '# TODO\n\n## %s\n' "$(date +%Y-%m-%d)" > .claude/tasks/TODO.md
```
## STEP 1 — SCAN THE CONVERSATION
@@ -164,7 +169,7 @@ concatenated class names" entry.)
## STEP 2B — TODO RECONCILE (both modes)
Runs only if `.claude/tasks/TODO.md` exists (STEP 0). Two passes.
Runs on `.claude/tasks/TODO.md` (created minimal at STEP 0 when absent). Two passes.
**PASS A — done-detection (TODO → reality).** Detection is free — a capable
agent already spots the finished tasks from the STEP 1 git scan. The only rule
@@ -358,7 +363,7 @@ Then the closing line — pick by the STEP 5C persist result (`<mode>` = `Contex
flushed` for pre-wipe, `Session closed` for ritual):
- **auto-persisted (default — branched off develop, pushed)** → `✅ <mode> + persisted to origin/develop (<short>). Next session: read .claude/memory/ at startup.`
- **--no-push (held on branch)** → `✅ <mode> + committed on chore/<name>, NOT pushed (--no-push). Merge + push when ready.`
- **--no-push (held on branch)** → `✅ <mode> + committed on chore/<name> — pushed to origin by the hooks, NOT merged (--no-push: finish skipped). Merge when ready.`
- **push failed after merge** → `✅ <mode> + merged to develop — ⚠️ push FAILED (<reason>); merged locally, push manually.`
- **WORKING branch (rode a feature branch)** → `✅ <mode> + committed <mem_hash> on <branch>. Integrates when the branch merges.`
- **commit skipped (rc 3)** → keep the ✅ on the WRITE but make the gap loud, never
@@ -380,7 +385,7 @@ manual commit (rc 3).
- **Append-only.** Never overwrite or renumber existing registry entries.
- **Caveman English** registry bodies, always English. **The TODO is plain
prose, never caveman** — caveman is registries-only.
- **TODO reconcile runs only if TODO.md exists.** Never create it (STEP 0).
- **TODO reconcile always runs** — a missing TODO.md is created minimal at STEP 0.
- **PASS A checks only on an unambiguous task↔code/commit map.** Partial /
umbrella / vague → leave unchecked. Never on assumption.
- **PASS B captures only explicit to-dos**, deduped — never invented or
@@ -398,7 +403,8 @@ manual commit (rc 3).
WORKING branch (memory rides feature/bugfix) or rc 3 skips it. NEVER auto-finish
a branch the run did not create.
- **Skip trivial** for the 4 ID registries; journal excepted.
- `.claude/memory/` missing → STOP at STEP 0, do not create the structure here.
- `.claude/memory/` missing → STEP 0 creates the five registries from the
templates (doctrine: either missing → create first), then proceeds.
## Common mistakes
@@ -417,7 +423,7 @@ manual commit (rc 3).
| Dumping an architecture directive as a TODO task | Route orientation/policy directives to decisions.md (BDR), not the TODO. |
| Writing a ritual answer fresh without dedup | Ritual answers go through STEP 2 like any candidate; a dup shows its existing ID. |
| French/English entry text | Prompt may be French; written registry entry is always English. |
| Creating `.claude/memory/` or `.claude/tasks/TODO.md` when absent | Not this skill's job — registries STOP and point to `/onboard`; TODO volet is skipped. |
| Stopping on a missing `.claude/memory/` or `.claude/tasks/TODO.md` | Doctrine says create first — STEP 0 bootstraps the five registries + a minimal TODO from the templates, then proceeds; `/onboard` is the fuller setup. |
## Red flags — STOP
+3 -3
View File
@@ -40,8 +40,8 @@ The agent runs a **ship-and-handover pipeline** with explicit gates:
1. **PRE-FLIGHT** — Detect git repo, project root, language, project type, web sub-type, NAP signals, stack.
2. **BASELINE AUDITS** — Run /seo (SEO+GEO) and /harden in parallel. Capture initial scores (`SCORE_SEO_BEFORE`, `SCORE_GEO_BEFORE`, `SCORE_HARDEN_BEFORE`).
3. **FIX LOOPS (parallel, bounded)** — For each audit < 17/20:
- Re-invoke the audit subagent with explicit instruction to apply auto-fixes.
- Re-score.
- Apply the pending FIX BUNDLE from the MAIN loop: items the audit classed AUTO directly, then every GATED item (CSP, redirects, anything harden marks "could BREAK the site") presented to the user at ONE gate before applying.
- Re-invoke the audit subagent in audit mode: it re-scores and returns the next FIX BUNDLE; it applies nothing (a dispatched child cannot hold a gate).
- Repeat up to `MAX_ITERATIONS` (default 5).
- If still < 17/20 after cap → escalate to user with concrete remaining issues; user decides continue / stop / manual intervention.
4. **COMMIT + PUSH** — If files changed during fix loops, run /commit-change (atomic logical commits) then `git push`.
@@ -57,7 +57,7 @@ The agent runs a **ship-and-handover pipeline** with explicit gates:
- **§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.
9. **RENDER** — Write `LIVRAISON.md` (fr) or `HANDOVER.md` (en) at project root, then run `$HOME/.claude/skills/client-handover/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:
- `--skip-fix-loop` — run baseline audits once, skip auto-fix iterations.
+1 -1
View File
@@ -8,7 +8,7 @@ description: |
(that is /prune-memory).
Triggers: "close", "end session", "ferme la session", "session close",
"checkpoint memory", "what did we learn", "retro rapide", "fin de journée".
argument-hint: "[--no-push] (runs capitalize in ritual mode; --no-push holds memory on the chore branch instead of the default auto-merge+push)"
argument-hint: "[--no-push] (runs capitalize in ritual mode; --no-push holds memory on chore/<name>: pushed to origin by the hooks, NOT merged (finish skipped), merge when ready; default = auto-finish into develop)"
allowed-tools:
- Read
- Edit
+17 -5
View File
@@ -45,16 +45,28 @@ git config user.email
- `git config user.email` empty → STOP, ask the user to configure identity
first, do not dispatch.
On a protected base (`main`/`develop`) the subagent runs the gitflow
aiguillage itself inside `MODE: propose` (its Phase 0) and branches to
`chore/*` before drafting the plan — code never lands directly on a
protected branch.
On a protected base (`main`/`develop` — `bash "$HOME/.claude/lib/gitflow.sh"
protected-base`) ask the user the branch TYPE before any dispatch — a branch
name is a public name:
```
AskUserQuestion:
Protected base — branch type for these commits? (feature / bugfix / chore)
```
Suggest `chore` only when every pending path is under `.claude/**` or docs;
pending code never lands on a `chore/*` branch. Pass the answer as
`TYPE: <type>` in the STEP 1 prompt — the subagent runs the aiguillage with it
inside `MODE: propose` (its Phase 0) and branches to `<type>/*` before drafting
the plan. Code never lands directly on a protected branch. On a working
branch, omit `TYPE:` (the aiguillage is a no-op there).
## STEP 1 — Propose
```
Agent(subagent_type="commit-changer", model="opus")
prompt: "MODE: propose
TYPE: <the STEP 0 answer — feature / bugfix / chore; omit on a working branch>
$ARGUMENTS"
```
@@ -86,7 +98,7 @@ AskUserQuestion:
BDR-077 — never redrawn inline on the session model); show the redrawn
plan and re-ask.
- `skip` → exit cleanly, no commits created, no `MODE: apply` dispatch.
Note: if the propose run created a `chore/*` branch (gitflow aiguillage
Note: if the propose run created a `<type>/*` branch (gitflow aiguillage
off a protected base), that branch stays checked out with the work
uncommitted — mention it so the user isn't surprised by the branch switch.
+5 -9
View File
@@ -182,7 +182,6 @@ Author a runbook, seed the incident ledger, commit both, then proceed to STEP 1.
#!/usr/bin/env bash
# === deploy runbook (reference) — NOT run directly. Instantiated into the deploy checklist per delta. ===
# Fixed steps run every deploy; annotated steps (@delta lines) re-instantiate from the delta.
# @config push_deploy_tags=false
```
3. Scan for migration, rebuild, and dependency steps; propose `@delta:` annotations inline:
- Migration steps (`psql -f`, `migrate up`, `supabase migration`) →
@@ -219,12 +218,10 @@ Author a runbook, seed the incident ledger, commit both, then proceed to STEP 1.
| Backup command | "Backup command before migrations?" | `pg_dump "$DB" > ~/backups/pre-deploy-$(date +%F-%H%M).sql` |
| Health-check URL | "Health-check URL (expects HTTP 200)?" | `https://$DEPLOY_HOST/health` |
| Rollback note | "One-line rollback note (optional)?" | omit if blank |
| Push deploy tags | "`push_deploy_tags`? (true / false)" | `false` |
**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.
- Append the rollback note as `# ROLLBACK: <note>` at the end if provided.
→ **[GATE]** below.
@@ -427,9 +424,7 @@ Then:
The deploy succeeded. Lay the oracle and close out.
1. Read `# @config push_deploy_tags=` from the `PROCEDURE.md` header (default
`false`). Pick `date = today` (`YYYY-MM-DD`); if `deploy/<date>` exists, suffix
`-N`.
1. Pick `date = today` (`YYYY-MM-DD`); if `deploy/<date>` exists, suffix `-N`.
2. Write `.claude/deploy/STATE.json` (overwrite):
```jsonc
{ "deployed_sha": "<PENDING.target_sha>", "deployed_at": "<now ISO-8601>",
@@ -438,9 +433,10 @@ The deploy succeeded. Lay the oracle and close out.
**`deployed_sha` = `PENDING.target_sha`, NOT current HEAD** — HEAD may have
moved during the gap; the bridge's target is the deployed truth.
3. `git tag -a deploy/<date> <PENDING.target_sha> -m "<summary>"`.
4. If `push_deploy_tags=true` → `git push origin deploy/<date>` — **best-effort,
non-fatal**: a push failure logs a warning, never blocks the mark (the tag is a
bookmark; `STATE.json` is the oracle).
4. No separate tag push: the oracle commit (step 5) fires the gitflow
post-commit hook, which pushes with `--follow-tags`, so `deploy/<date>`
rides along (BDR-095). A hook `push FAILED` warning never blocks the mark
(the tag is a bookmark; `STATE.json` is the oracle).
5. Commit the oracle:
```bash
bash ~/.claude/lib/deploy-commit.sh commit "chore(deploy): mark <date> @ <short>" \
+7
View File
@@ -22,6 +22,13 @@ Run the two-mode doc pipeline (BDR-077 — audit judgment on opus, patch on
the sonnet pin, the validation gate in THIS loop; a dispatched agent cannot
hold a gate):
0. AIGUILLAGE — before any write, follow `$HOME/.claude/lib/gitflow-aiguillage.md`
— this skill's TYPE = `chore`. On `main`/`develop` it branches to
`chore/<name>` off develop so the doc patch lands on a branch; on a working
branch it proceeds in place. Never `gitflow finish`. `lib/doc-commit.md`'s
rc 5 (commit rejected by the hook on a protected base) stays as the
backstop, not the plan.
1. AUDIT — dispatch:
`Agent(subagent_type="doc-syncer", model="opus")`
prompt: "MODE: audit. Audit public docs for this project. Context from
+4 -2
View File
@@ -244,7 +244,7 @@ Valider ? (all / <IDs> / edit / skip)
Always append a 1-line entry to today's heading in `.claude/memory/journal.md`.
**Language rule**: written entries are ALWAYS in English (see CLAUDE.md "Memory registries" § Language). The interactive gate may mirror the user's language; the appended entries must not.
**Language rule**: written entries are ALWAYS English AND caveman — fragments, articles dropped, code/IDs/quoted errors verbatim — per CLAUDE.md "Memory registries" (Always English, always caveman). The interactive gate may mirror the user's language; the appended entries must not.
If no substantive capture candidate → skip with `CAPITALIZE: nothing to log`.
@@ -259,7 +259,9 @@ hash, and no-ops if nothing was written.
- Max 5 files. If more needed → `/ship-feature`.
- Reflection (scope, plan, contract, loop decisions) NEVER leaves this main
loop; execution NEVER stays in it — the executor is the sonnet-pinned
feater subagent (BDR-066).
feater subagent (BDR-066). A skill-mandated executor is exempt from the doctrine's "don't delegate
few-tool-call work" rule (CLAUDE.md "Workflow" names that exception:
skill-mandated dispatches run as written).
- The executor is dispatched FRESH on every round-trip — feedback travels
as contract path + named gaps/decisions, never as transcript.
- Design gate only (not full plugin check). See STEP 0.5.
+4 -1
View File
@@ -85,7 +85,10 @@ On a protected base, assistance skills (`feat`/`bugfix`/`hotfix`) AND the standa
memory/doc skills (`capitalize`/`close`/`prune-memory`/`reconcile`, TYPE `chore`)
call `start <type>` to branch first; on a working branch they commit in place. Same
`protected-base` predicate the out-of-skill hook uses. Caller→type map + rationale:
`lib/gitflow-aiguillage.md`.
`lib/gitflow-aiguillage.md`. `/capitalize` and `/close` auto-finish their memory-only
`chore/*` branch into develop when THEY created it this run (BDR-068; `--no-push`
opts out) — the only finish that fires without a live human signal; everything else
stays human-gated.
## Failure modes (mechanical — lib return codes are the contract)
+15 -6
View File
@@ -64,8 +64,11 @@ disposition required at hotfix weight.
Follow `$HOME/.claude/lib/design-gate.md`:
- Scan $ARGUMENTS and target files for design/UI/style signals (CSS, component, styling, animation).
- If signals found → run `design-tool-gate.sh`; if it reports INCOMPLETE,
tell the user to run `/profile design` before proceeding.
- Signals found → a hotfix is the trivial tier by definition (≤2 files, one
cosmetic value — `design-gate.md` §1): skip the gate, no toolchain. If the
signals reveal real UI work (new component, layout, motion), this is not a
hotfix → route to `/feat` or `/bugfix` instead of running
`design-tool-gate.sh`.
- If no signals → skip (zero overhead).
## STEP 1.7 — CONTRACT (silent autofill)
@@ -104,8 +107,12 @@ verify+secure loop).
## STEP 2 — PRE-FLIGHT
**Gitflow aiguillage (before dispatch):** follow `$HOME/.claude/lib/gitflow-aiguillage.md`
— your type = `hotfix`. On `main`/`develop` it branches first; on a working
branch it's a no-op (commit in place). Never `finish`.
— your type follows the base: on `main` → `hotfix` (prod incident; finish fans
out to main + develop); on `develop` → `bugfix` (the fix forks from develop — a
`hotfix/*` off main would miss develop's code and later merge to prod). Either
protected base branches first; on a working branch it's a no-op (commit in
place). The /hotfix size rules and the hotfixer executor are unchanged either
way. Never `finish`.
Snapshot current state so revert is possible:
@@ -223,7 +230,7 @@ Ask the user only when there is an actual candidate to propose.
Always append a 1-line entry to today's heading in `.claude/memory/journal.md` (even trivial hotfix — journal is timeline, not signal).
**Language rule**: the journal line and any proposed BLK/LRN entries are ALWAYS written in English (see CLAUDE.md "Memory registries" § Language).
**Language rule**: the journal line and any proposed BLK/LRN entries are ALWAYS written English AND caveman — fragments, articles dropped, code/IDs/quoted errors verbatim — per CLAUDE.md "Memory registries" (Always English, always caveman).
**Then commit the memory** — follow `$HOME/.claude/lib/capitalize-commit.md`: it
surgically commits what capitalize just wrote (`.claude/memory` + `.claude/tasks`
@@ -237,7 +244,9 @@ trivial hotfix still produces a `chore(memory): journal — …` commit (Frame 2
- Max 2 files changed. If more needed → `/bugfix`.
- Reflection (LOCATE, contract, gate decisions) NEVER leaves this main
loop; execution NEVER stays in it — the executor is the sonnet-pinned
hotfixer subagent (BDR-066).
hotfixer subagent (BDR-066). A skill-mandated executor is exempt from the doctrine's "don't delegate
few-tool-call work" rule (CLAUDE.md "Workflow" names that exception:
skill-mandated dispatches run as written).
- The executor is dispatched FRESH, once — hotfix never re-dispatches after
a failed or blocked attempt (it reverts and escalates to `/bugfix`, it
does not retry). Sole exception: a class-tagged BLOCKED answered by the
+27 -14
View File
@@ -103,7 +103,14 @@ every field the scaffolder consumes crosses the dispatch): BRIEF (verbatim)
`~/.claude/CLAUDE.md`. A STOP (missing input) comes back as its report —
resolve here, re-dispatch. The ~30s liveness pings are THIS loop's job
while waiting.
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).
Creates: CLAUDE.md, `.claude/settings.json`, `.claudeignore`, `.gitignore`, `.env.example`, empty entry points. NO README, NO features.
Then bootstrap the memory in THIS loop, before STEP 5f so the root commit embeds
it (doctrine: registries + TODO exist from day one; STEP 10b appends to them):
```bash
mkdir -p .claude/memory .claude/tasks
cp -n ~/.claude/templates/memory/{decisions,learnings,blockers,evals,journal}.md .claude/memory/
[ -f .claude/tasks/TODO.md ] || printf '# TODO\n\n## %s\n' "$(date +%Y-%m-%d)" > .claude/tasks/TODO.md
```
Verify: `git init` + build passes.
## STEP 5b — CREATE README
@@ -166,7 +173,7 @@ layout and the deterministic root commit:
bash "$HOME/.claude/lib/gitflow.sh" init "chore: scaffold <project-name>"
```
Creates `main`+`develop`, root-commits the FULL scaffold (CLAUDE.md, README,
config, `.gitignore`, deps), reconciles the `.gitignore` socle, and installs the
config, `.gitignore`, `.claude/memory/` + `.claude/tasks/TODO.md`, deps), reconciles the `.gitignore` socle, and installs the
versioned pre-commit hook — all embedded in the root commit, working tree clean.
This is the deterministic scaffold commit owner (closes BLK-010). The MVP is
implemented on a `feature/*` branch off `develop` (STEP 8).
@@ -217,14 +224,15 @@ call. The plan is closed; execution and plan-conformity review are sonnet
work. Reflection (task decomposition, review verdict arbitration) stays in
this loop.
## STEP 8b — GRAPHIFY FULL (after implementation)
If `graphify` CLI is installed AND complexity >= 30%:
1. Run full graphify on the implemented project:
```bash
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.
## STEP 8b — GRAPHIFY SIGNAL (after implementation — BDR-097)
graphify is proposed only from 200 tracked code files, and the USER decides —
never build, install or update a graph here:
```bash
bash ~/.claude/lib/graphify-gate.sh .
```
- Prints a line → carry it into the FINAL OUTPUT status table as
`GRAPHIFY: <line> — /graphify on your go`.
- Silent → `GRAPHIFY: below 200 code files, not proposed`.
## STEP 9 — VERIFY + SECURE (fresh gates, bounded loops)
Run the two fresh gates per `$HOME/.claude/lib/verify-secure-loop.md` with
@@ -284,7 +292,9 @@ capitalizes NOTHING. Do NOT fabricate a BDR to fill the step. Print
[ decisions.md ] BDR-XXX — <decision> — <1-line why>
Valider lesquels ? (all / <IDs> / edit / skip)
```
3. Append approved entries + update the Index. Append a journal line under today.
3. Append approved entries to the existing registries (bootstrapped at STEP 5,
in the root commit) + update the Index. Append a journal line under today's
heading in `.claude/memory/journal.md`.
**Hash rule — founding decisions carry NO commit hash; use path + date only.**
This is by nature, not an omission: a founding decision is made at DESIGN
@@ -295,8 +305,10 @@ that IMPLEMENTS the decision, e.g. BDR-033 → 11792cc). This is the SECOND case
where hash-anchoring does not apply — the first being a squash-merged PR, whose
anchored commit ceases to exist.
**Language rule**: written entries are ALWAYS in English (CLAUDE.md "Memory
registries"). The gate may mirror the user's language; entries must not.
**Language rule**: written entries are ALWAYS English AND caveman — fragments,
articles dropped, code/IDs/quoted errors verbatim — per CLAUDE.md "Memory
registries" (Always English, always caveman). The gate may mirror the user's
language; entries must not.
**Then commit the memory** — follow `$HOME/.claude/lib/capitalize-commit.md`: it
surgically commits the approved founding decisions (`.claude/memory` +
@@ -369,5 +381,6 @@ LOCATION: <path> | STACK: <stack> | BUILD: ✅/❌ | TESTS: ✅<N>/❌
V1 FEATURES: ✅<f> / ⚠️<f> partial: <reason>
REMAINING ISSUES: <list or none>
QUICK START: <exact cmds>
CLAUDE.md ✅ | README ✅ | SETTINGS ✅
CLAUDE.md ✅ | README ✅ | SETTINGS ✅ | MEMORY ✅
GRAPHIFY: <STEP 8b line>
```
+30 -19
View File
@@ -1,7 +1,7 @@
---
name: onboard
description: 'Use when bringing an existing repo into the claude-config framework — needs archetype detection, config install, full multi-axis audit (debt/SEO/GEO/UI-UX/perf/security/a11y/docs), and prioritized backlog. Multi-agent orchestrator. Do NOT use for repos created via /init-project. Triggers: "onboard", "onboard project", "audit existing repo", "setup existing project".'
argument-hint: '[optional hints: "Python FastAPI" | "add gsd" | "Next.js monorepo" | "force-archetype:wordpress"]'
argument-hint: '[optional hints: "Python FastAPI" | "Next.js monorepo" | "force-archetype:wordpress"]'
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Agent, Skill
---
@@ -27,7 +27,8 @@ Run `$HOME/.claude/lib/plugin-gate.md` with hint "onboarding existing project +
- PROPOSED CHANGES exist → show list, ask "Apply? (yes / no / customize)". Apply on confirm.
- OK → `✅ Plugin check passed — [active plugins] — complexity: <score>%`, continue.
Complexity score is carried forward for STEP 4 graphify decision.
Complexity score is informative here; STEP 4 graphify is gated by
`graphify-gate.sh` (200 tracked code files, BDR-097), not by this score.
---
@@ -107,7 +108,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` (généré uniquement via `/onboard add gsd` — voir Next steps)
- **Pas encore** `ROADMAP.md` (GSD multi-session : `gsd init` à la main, voir docs gsd-pi — cf. Next steps)
Si `CLAUDE.md` existe déjà : lire son contenu, ne PAS écraser — fusionner après STEP 3.
@@ -151,11 +152,13 @@ Adopter le modèle gitflow sur ce repo existant :
```bash
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 + pre-commit hook` sur main (pendant que le hook est
inactif → jamais auto-bloqué). Idempotent — un re-run est un no-op.
Sur un repo existant, cela : renomme `master`→`main` si besoin (LOCAL), pose le
socle (`.gitignore` réconcilié — additif, n'écrase jamais les règles du projet —
+ `.githooks/` versionnés) sur une branche `chore/gitflow-adopt` créée depuis
main, la merge `--no-ff` dans main (le hook pre-commit est global sur la machine
et bloque tout commit de code sur main, mais exempte les merges — BDR-095),
supprime la branche, puis crée `develop` depuis main. Idempotent — un re-run est
un no-op.
**Annoncer le renommage master→main** s'il a lieu. Le renommage est LOCAL ;
repointer la branche par défaut du remote vers `main` + la protection de branche
@@ -247,21 +250,29 @@ Pour chaque fast-lib détectée :
---
## STEP 4 — GRAPHIFY (si complexity ≥ 30% et pas déjà présent)
## STEP 4 — GRAPHIFY (proposé dès 200 fichiers code — l'utilisateur décide)
```bash
command -v graphify &>/dev/null && echo "available" || echo "not-installed"
test -f graphify-out/GRAPH_REPORT.md && echo "graph-exists"
test -f graphify-out/graph.json && echo "graph-exists"
bash ~/.claude/lib/graphify-gate.sh .
```
- **Pas installé** → skip avec message : `graphify non installé — skip audit architectural. Install : (voir graphify/SKILL.md)`
- **Complexity < 30%** → skip silencieusement, projet trop petit pour justifier.
- **Graphe déjà présent + récent** (fichier < 7j) → skip, réutiliser l'existant.
- **Sinon** → run :
- **`graph-exists`** → skip, réutiliser l'existant.
- **La gate n'imprime rien** → moins de 200 fichiers code trackés (BDR-097 :
grep + lecture suffisent). Pas de proposition ; ligne FINAL OUTPUT
`below 200 code files, not proposed`.
- **La gate imprime une ligne** (`graphify? N code files ≥ 200, no graph`) →
l'afficher et DEMANDER à l'utilisateur. Jamais de build sans oui explicite.
Sur oui :
```bash
graphify . --out graphify-out 2>&1 | tail -20
printf '.claude/\ndocs/superpowers/\n' >> .graphifyignore
grep -qxF 'graphify-out/' .gitignore || echo 'graphify-out/' >> .gitignore
graphify update .
```
Puis `test -f graphify-out/GRAPH_REPORT.md` pour valider.
Puis `test -f graphify-out/GRAPH_REPORT.md` pour valider. Sur non → skip,
ligne FINAL OUTPUT `proposed, declined`.
Print : `🔗 Knowledge graph : graphify-out/GRAPH_REPORT.md (N nodes, M edges)`.
@@ -937,7 +948,7 @@ Choix ? (A / B / C / D / E)
**STOP.** Attendre la réponse.
- **A** → stop ici, l'utilisateur relira et reviendra avec `/onboard continue`.
- **A** → stop ici, l'utilisateur relit les 4 fichiers ; le backlog (STEP 9) se génère ensuite à la demande depuis `.claude/audits/AUDIT_PROPOSALS.md`.
- **B** → continuer STEP 9 avec toutes les recommandations.
- **C** → demander les changements spécifiques, les appliquer dans .claude/audits/AUDIT_PROPOSALS.md, puis re-présenter la gate.
- **D** → continuer STEP 9 avec seulement les P0.
@@ -1020,7 +1031,7 @@ Pour démarrer : lire .claude/tasks/TODO.md, choisir une tâche P0, lancer le /s
- Si `CLAUDE.md` existe : le lire, ne pas l'écraser sans fusion après STEP 3.
- STEP 3 : ne redemande jamais ce qui est déjà dans README ou manifests.
- STEP 3.5 : si ctx7 absent + fast-libs, WARN mais ne bloque pas.
- STEP 4 : skip si complexity < 30% ou graph récent déjà présent.
- STEP 4 : graphify proposé seulement si `graphify-gate.sh` imprime une ligne (≥ 200 fichiers code, pas de graphe — BDR-097) ; l'utilisateur décide, jamais de build sans oui explicite.
- STEP 5-6 : subagents isolés (Agent tool avec subagent_type spécifique) — pas de contexte partagé entre les audits. Chaque subagent écrit son rapport dans `.onboard-audit/<name>.md`.
- STEP 6 dispatches parallélisables : regrouper dans un seul message Agent multi-calls.
- `.onboard-audit/` gitignoré automatiquement — ne jamais commiter.
@@ -1035,7 +1046,7 @@ ARCHETYPE : <name> (confiance: <niveau>)
STACK : <stack>
CONFIG : ✅ CLAUDE.md, settings.json, .claudeignore, .claude/{tasks,memory,audits}/
CTX7 CACHE : ✅ [libs] | ⚠️ not installed | — N/A
GRAPHIFY : ✅ graphify-out/ | ⚠️ not installed | — skipped (simple)
GRAPHIFY : ✅ graphify-out/ | ⚠️ not installed | — below 200 code files, not proposed | — proposed, declined
AUDITS :
✅ dette technique (.onboard-audit/analyze.md + code-clean.md)
✅ sécurité (.onboard-audit/cso.md)
@@ -1055,6 +1066,6 @@ SYNTHÈSE :
NEXT STEPS :
1. Ouvrir .claude/audits/ONBOARD_REPORT.md — overview complète
2. Démarrer par la première tâche P0 de .claude/tasks/TODO.md avec le skill indiqué
3. /onboard add gsd — générer ROADMAP.md pour multi-session si besoin
3. GSD (multi-session) : `gsd init` à la main, voir docs gsd-pi
4. .onboard-audit/ peut être supprimé (raw data consommée en synthèse)
```
+7 -4
View File
@@ -28,14 +28,17 @@ digraph pipeline {
## STEP 0: Dependencies
Check before starting. Install what's missing.
Check before starting. If something is missing, print the install
command(s) and STOP until the user has run them — `sudo` / `apt` is the
user's to run, never Claude's. The one exception: `pip install pymupdf`
inside the project's own venv may be run by Claude.
```bash
# Option A: poppler (lighter)
command -v pdftoppm && echo "OK" || echo "INSTALL: sudo apt install poppler-utils"
# Option A: poppler (lighter) — USER runs the install
command -v pdftoppm && echo "OK" || echo "USER RUNS: sudo apt install poppler-utils"
# Option B: PyMuPDF (more powerful — extracts embedded images with coordinates)
python3 -c "import fitz; print('OK')" 2>/dev/null || echo "INSTALL: pip install pymupdf"
python3 -c "import fitz; print('OK')" 2>/dev/null || echo "INSTALL: pip install pymupdf (project venv only — otherwise USER RUNS)"
```
Prefer PyMuPDF if both available — it extracts embedded images + gives page dimensions.
+6
View File
@@ -9,6 +9,12 @@ Dispatch the refactorer executor — behavior-preserving norm application is
closed execution, so it runs pinned on **sonnet** (not the big session
model). The scope you name is the only reflection; the agent applies norms.
**Gitflow aiguillage first** (the refactorer edits code): follow
`$HOME/.claude/lib/gitflow-aiguillage.md`, this skill's TYPE = `chore`. On
`main`/`develop` run `bash ~/.claude/lib/gitflow.sh start chore refactor-<slug>`
and dispatch on the new branch; on a working branch dispatch in place. Never
`gitflow finish` — integration is human-gated.
```
Agent(subagent_type="refactorer")
prompt: "Refactor to strict project norms, preserving external behavior
+10 -8
View File
@@ -24,7 +24,7 @@ The two mechanical spans (prep, finish+tag) run on the sonnet-pinned
gate needed here, dispatch does the job. This dispatcher keeps everything
the executor must never own: the version-NUMBER decision (judgment — derives
from semver change nature), and the two human gates (when to release, and
the push). A human gate sits BETWEEN the two spans by construction, so the
the tag push). A human gate sits BETWEEN the two spans by construction, so the
executor is never dispatched twice in one call.
## When to use
@@ -91,24 +91,26 @@ Parse the `RELEASE-EXEC REPORT`:
the fan-out hit), STOP — resolving a conflicted fan-out is a human call,
not an auto-retry.
### STEP 6 — Push GATE (ASK)
STOP. On explicit go only ([[LRN-069]]) — run the push HERE, in this
dispatcher, never delegated to the executor:
### STEP 6 — Tag push GATE (ASK)
`main` and `develop` are already on origin: the lib pushes every merge as
it lands (`_gitflow_merge_into` + the post-merge hook, BDR-095). Only the
tag is left. STOP. On explicit go only ([[LRN-069]]) — run the tag push
HERE, in this dispatcher, never delegated to the executor:
```
AskUserQuestion:
Push main, develop, and v<X.Y.Z> to origin? — go / hold
Push tag v<X.Y.Z> to origin? — go / hold
```
Go →
```bash
git push origin main develop && git push origin v<X.Y.Z>
git push origin v<X.Y.Z>
```
`hold` → stop; the release is fanned out and tagged locally, unpushed.
`hold` → stop; the release is on origin (main + develop), the tag stays local.
## Common mistakes
- Tagging before `gitflow finish` → tag wouldn't sit on main's merge commit. Tag AFTER, on main.
- Auto-firing finish because tests pass → finish is a HUMAN gate.
- Restarting the tag at v1.0.0 → desyncs from the CHANGELOG lineage. Continue it.
- Pushing without the ASK gate → [[LRN-069]].
- Pushing the tag without the ASK gate → [[LRN-069]].
## Validation
`RC_WORK=$(mktemp -d) RC_TAG=1 bash lib/tests/run-release-candidate.sh` → 5/5 (fan-out + tag on main). `RC_TAG=0` reds the tag assertion — proves the lib alone never tags (the gap this skill fills).
+7
View File
@@ -535,6 +535,13 @@ intent, not header wording: **AUTO** = no-confirmation items (seo batches
A/B/C · geo G1–G4/G6); **GATED** = items marked NEEDS CONFIRMATION / visible
/ structural (seo D/E · geo G5); **USER ACTIONS** = batch F / G7.
### Gitflow aiguillage (before the first edit)
Follow `$HOME/.claude/lib/gitflow-aiguillage.md` — this skill's TYPE =
`feature` (aggressive mode edits code). On `main`/`develop` branch first:
`bash ~/.claude/lib/gitflow.sh start feature seo-<slug>`; on a working
branch apply in place. Never `gitflow finish` — integration is human-gated.
### Serial by ownership (no parallel race)
The two bundles may touch the same shared template (meta vs JSON-LD). Apply
+4 -3
View File
@@ -32,7 +32,8 @@ Verify the project has a `CLAUDE.md` and print a brief orientation summary:
ls CLAUDE.md .claude/CLAUDE.md 2>/dev/null | head -1
git branch --show-current 2>/dev/null || echo "not a git repo"
git log --oneline -3 --format="%h %<(50,trunc)%s" 2>/dev/null || true
ls .gsd/ROADMAP.md 2>/dev/null | head -1
# gsd-pi ≥ 3: state in .gsd/STATE.md + gsd.db + milestones/<ID>/<ID>-ROADMAP.md (no .gsd/ROADMAP.md)
ls .gsd/ 2>/dev/null >/dev/null && head -20 .gsd/STATE.md 2>/dev/null
```
- **CLAUDE.md found** → read it silently, then print orientation header (informational, not a gate):
```
@@ -41,7 +42,7 @@ ls .gsd/ROADMAP.md 2>/dev/null | head -1
Stack : <stack from CLAUDE.md>
Branch : <current git branch>
Recent : <last 3 commit messages>
GSD : <current milestone if .gsd/ROADMAP.md exists, else "not initialized">
GSD : <current milestone read from .gsd/STATE.md if .gsd/ exists, else "not initialized">
```
Continue to STEP 1.
- **Not found** →
@@ -262,7 +263,7 @@ Feature shipped implies at least one design decision worth capturing. Run this B
4. Append approved entries to the registries. Update the Index table at the top of each file.
5. Append a one-line entry to `.claude/memory/journal.md` under today's date heading (`## YYYY-MM-DD`).
**Language rule**: written entries are ALWAYS in English (see CLAUDE.md "Memory registries" § Language). The interactive gate above may mirror the user's language; the appended entries must not.
**Language rule**: written entries are ALWAYS English AND caveman — fragments, articles dropped, code/IDs/quoted errors verbatim — per CLAUDE.md "Memory registries" (Always English, always caveman). The interactive gate above may mirror the user's language; the appended entries must not.
If nothing substantive to log → print `CAPITALIZE: nothing substantive to log` and skip.
+31 -18
View File
@@ -39,7 +39,7 @@ plus its report IS the approval gate, reviewed by the human afterwards.
Core principle: **autonomy on the working branch, never on shared
state.** The skill may edit code freely on its own branch; it may NOT
silently rewrite declared state (target TODO, memory registries) or
integrate anything (merge/finish/push).
integrate anything (merge/finish/push to `main`/`develop`).
## When NOT to use
@@ -79,8 +79,8 @@ Model discipline (the user-fixed invariant behind this mode):
must never be pinned down to an executor tier.
- Inside a runner, every dispatched agent keeps the tier this skill
already defines: security-auditor (sonnet frontmatter), the Phase B
audit (analyzer opus pin or `model="opus"`), doc-syncer (sonnet
frontmatter, its two-mode contract untouched).
audit (analyzer opus pin or `model="opus"`), doc-syncer (audit on
`model="opus"`, patch on its sonnet frontmatter — BDR-077).
Runner dispatch, one per project:
@@ -91,7 +91,7 @@ Agent(subagent_type="general-purpose",
for EXACTLY ONE project: <absolute path>. Flags: <--report-only|none>.
Skip STEP 0/0b (routing) and the global summary — the dispatcher owns
them. Every rule of the skill applies unchanged: max 3 iterations,
never merge/finish/push, scoped commits, report appended to that
never merge/finish/push main|develop, scoped commits, report appended to that
project's own .claude/audits/TOUR.md. Return EXACTLY: the project's
one-line global-summary row (STEP 3 format), then BRANCH: <name|no
branch>, then REPORT: <path>.")
@@ -156,9 +156,12 @@ honestly in the summary. Never loop past 3.
MEDIUM/LOW → fix only if local and behavior-preserving, else leave
`open`. Every fix minimal, CLAUDE.md security defaults apply.
A CRITICAL/HIGH fix that changes the API contract (new required
header/param, changed status codes, moved paths) is still applied —
but its report row and the global summary line carry a **BREAKING**
tag, so the human review cannot miss it.
header/param, changed status codes, moved paths) is NOT applied — a
breaking change is the human's call (CLAUDE.md: confirm before a
breaking change). Its report row becomes
`open — needs decision (BREAKING)` with the proposed patch attached,
and the global summary line carries the **BREAKING** count.
Behaviour-preserving CRITICAL/HIGH fixes stay auto-applied.
4. Commit scoped: `git add <files touched>` (never `-A`),
`fix(security): …`.
@@ -196,11 +199,18 @@ honestly in the summary. Never loop past 3.
`.claude/memory/`** — an inferred checkbox is exactly the lie
/reconcile exists to catch. The human applies suggestions via
`/reconcile` later.
2. **Doc sync** — dispatch doc-syncer in AUTOMATIC (silent) mode:
public docs only (README, INSTALL, USAGE, CHANGELOG…), never
`.claude/**`, never CLAUDE.md. Commit its `PATCHED_FILES:` via
`bash ~/.claude/lib/doc-commit.sh` when available, else a scoped
`docs: …` commit of exactly those paths.
2. **Doc sync** — two-mode doc-syncer, mirrors /ship-feature STEP 8
(BDR-077: audit judgment on opus, patch on the sonnet pin):
`Agent(subagent_type="doc-syncer", model="opus")` with `MODE: audit`
+ `auto-mode scope: <files this tour touched>`; public docs only
(README, INSTALL, USAGE, CHANGELOG…), never `.claude/**`, never
CLAUDE.md. NONE → done. `[MINOR]` PATCH PLAN → re-dispatch
`Agent(subagent_type="doc-syncer")` (sonnet frontmatter) with
`MODE: patch` + the plan verbatim, then commit its `PATCHED_FILES:`
via `bash ~/.claude/lib/doc-commit.sh` when available, else a scoped
`docs: …` commit of exactly those paths. SIGNIFICANT → not applied:
report row `suggested` with the plan item (the tour has no human
gate mid-run).
### End of iteration
@@ -231,15 +241,15 @@ order:
| ID | Axis | File | Sev | Finding | Status |
|----|------|------|-----|---------|--------|
| SEC-1 | security | app.py:17 | high | shell=True + concat | fixed |
| SEC-2 | security | app.py:14 | high | no authz on POST /backup | fixed — **BREAKING**: new required X-Backup-Token header |
| SEC-2 | security | app.py:14 | high | no authz on POST /backup | open — needs decision (BREAKING): new required X-Backup-Token header, patch attached |
| CLN-1 | clean | utils.py:9 | - | dead legacy_md5 | fixed |
| REC-1 | reconcile | TODO.md | - | "/health" unchecked, shipped 2d92696 | suggested |
| DOC-1 | doc | README.md | - | phantom /status endpoint | fixed |
Checks: pytest PASS, ruff PASS. Residuals: none. Commits: 5. BREAKING: 1 (SEC-2).
Checks: pytest PASS, ruff PASS. Residuals: SEC-2 (needs decision). Commits: 4. BREAKING: 1 (SEC-2).
```
Global summary inline, one line per project (append `BREAKING: n` to
any project line whose fixes changed an API contract):
any project line with contract-changing fixes left open for decision):
```
TOUR COMPLETE — 2026-07-04
@@ -257,7 +267,10 @@ without that approval — neither this repo's nor any target project's.
## Rules
- Branch via the gitflow lib; **never `gitflow finish`, never merge,
never push** — no exceptions, "the tour is green" is not a signal.
never push `main`/`develop`** — "the tour is green" is not a signal.
The chore branch's own commits are pushed by the gitflow hooks
(BDR-095); a `push FAILED` hook warning is a report residual, fixed
with a plain `git push -u origin chore/tour-<date>`.
- Scoped pathspecs only; `git add -A` is forbidden.
- Target TODO.md and target `.claude/memory/` are READ-ONLY. Reconcile
produces suggestions, not edits.
@@ -286,12 +299,12 @@ without that approval — neither this repo's nor any target project's.
| One TOUR.md for all projects in the config repo | Each project gets its own `.claude/audits/TOUR.md`. |
| Fixing a behavior-changing "cleanup" finding | That is a bug → BUGS-FOUND.md, untouched code. |
| Scratch audit files left untracked at the end | Delete them in STEP 3.2 — a dirty tree self-blocks the next tour. |
| Contract-changing security fix reported as plain "fixed" | Tag **BREAKING** in the row AND the summary line. |
| Contract-changing security fix auto-applied | Not applied: row `open — needs decision (BREAKING)` + proposed patch; **BREAKING** count in the summary line. |
## Red flags — STOP
- About to `Edit` a target project's TODO.md or `.claude/memory/*`.
- About to run `gitflow finish`, `git merge`, or `git push`.
- About to run `gitflow finish`, `git merge`, or push `main`/`develop`.
- About to `git add -A` or commit on `main`/`develop`.
- Starting iteration 4, or "just one more loop, it's almost clean".
- Security phase done without the security-auditor agent and without a
+6 -1
View File
@@ -299,7 +299,12 @@ Options :
D) Abort — keep .claude/audits/VALIDATE.md as audit report
```
4. On `A` : dispatch each file-group's applier at L1 (execution = sonnet;
4. On `A` : gitflow aiguillage FIRST — follow
`$HOME/.claude/lib/gitflow-aiguillage.md`, this skill's TYPE = `feature`
(`--fix` edits code). On `main`/`develop` branch before any edit:
`bash ~/.claude/lib/gitflow.sh start feature web-validate-<slug>`; on a
working branch apply in place. Never `gitflow finish` (human-gated).
Then dispatch each file-group's applier at L1 (execution = sonnet;
this loop only orchestrates), serially — one applier at a time, appliers
share files: