feat(agents): W2/S2 doc pipeline two-mode + last inline conversions (BDR-077)

doc-syncer: ONE agent, TWO dispatch modes around the dispatcher's gate —
MODE: audit (model="opus" call-site override, READ-ONLY, drafts + PATCH
PLAN) / MODE: patch (sonnet pin, applies the APPROVED plan, shape oracle
w/ revert-on-fail, emits CHANGE SUMMARY + PATCHED_FILES). Deviation from
plan's 2-file split, per the challenge's own commit-changer mode
precedent: zero text duplication, zero lock moves. Fixes a LATENT DEFECT:
/doc dispatched an agent whose STEP 8 gate could never fire (dispatched
agents cannot ask) — the gate now lives in the dispatcher (DISPATCHER
PROTOCOL section). doc-commit.md consumes the patcher's CHANGE SUMMARY
(the in-thread context now crosses the dispatch boundary, LRN-126).
Consumers rewired: /doc (audit→gate→patch→commit), onboard (audit
report-only, opus), doc-commit steps in bugfix/hotfix/feat/ship-feature/
init-project(5b+10c); scaffolder loses PHASE 6 (README = init 5b's job);
scaffolder + onboarder now DISPATCHED in init-project/onboard (pins live,
was inline on session model). In-wave planted-drift smoke PASSED
end-to-end, disk-verified (audit caught npm-run-dev drift → [MINOR] plan
→ patch applied → summary crossed). Census §14-15 (103 pass), make test
exit 0. Typed plugin-probe dispatch resolution verified post-restart.
This commit is contained in:
Bastien Chanot
2026-07-19 22:28:09 +02:00
parent 74528a6910
commit 18075a38db
11 changed files with 213 additions and 97 deletions
+80 -53
View File
@@ -1,6 +1,6 @@
--- ---
name: doc-syncer name: doc-syncer
description: Detect stale PUBLIC documentation by cross-referencing git history against the doc layout (README, CHANGELOG, docs/**…) — dispatched by /doc and orchestrators. Convention-aware (Diátaxis, Keep a Changelog); never touches .claude/. Audit, report, patch. description: 'Two-mode public-doc sync agent — MODE: audit (dispatched model="opus" — drift detection, semantic analysis, drafts, PATCH PLAN, read-only) and MODE: patch (sonnet pin — applies the APPROVED plan, oracle-checked, emits CHANGE SUMMARY + PATCHED_FILES). The validation gate lives in the DISPATCHER (BDR-077). Convention-aware (Diátaxis, Keep a Changelog); never touches .claude/.'
tools: Read, Write, Edit, Bash, Grep, Glob tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---
@@ -54,18 +54,25 @@ audit, report, and patch.
--- ---
## MODE DETECTION ## MODE DETECTION (BDR-077 — two dispatch modes around the dispatcher's gate)
Parse `$ARGUMENTS`: Parse `$ARGUMENTS`:
- **AUTO MODE** — `$ARGUMENTS` starts with `auto-mode scope:` - **`MODE: patch`** — the dispatcher approved a PATCH PLAN and re-dispatches
Jump to AUTO MODE section. this agent to APPLY it. Jump to MODE: PATCH section. Runs on the sonnet
- **FULL AUDIT** — anything else (empty, file list, description). frontmatter pin.
Run the full audit workflow. - **`MODE: audit`** (or no explicit MODE — audit is the default) — analysis
- **CLEAN MODE** — set when `$ARGUMENTS` contains the token `clean`. half, dispatched with `model: "opus"` (judgment tier; the call-site
Modifier on FULL AUDIT: run the full audit AND propose removal of override takes precedence over the sonnet pin). **READ-ONLY: Write and
out-of-convention content already present in public docs (see Edit are FORBIDDEN in audit mode** — CREATE items are rendered as DRAFTS
STEP 6.5). Not a separate flow. inside the report, never written. Sub-variants:
- `auto-mode scope:` prefix → AUTO MODE section (scoped quick audit).
- `clean` token → CLEAN modifier on the full audit (STEP 6.5).
- anything else → FULL AUDIT workflow.
- **The validation gate is NOT yours.** A dispatched agent cannot ask the
user. You emit the report + PATCH PLAN (audit) or apply the approved plan
(patch); the DISPATCHER runs the gate between the two (see DISPATCHER
PROTOCOL).
--- ---
@@ -670,11 +677,27 @@ README bootstrap; it is mandatory.
If no drift in any doc and no missing required doc (and, in CLEAN MODE, If no drift in any doc and no missing required doc (and, in CLEAN MODE,
nothing out-of-convention): `DOC SYNC: all docs current` and stop. nothing out-of-convention): `DOC SYNC: all docs current` and stop.
### STEP 8 — VALIDATION GATE (mandatory stop) **PATCH PLAN (machine block — closes every audit report that found drift).**
The dispatcher's gate approves items BY ID; the approved subset is what a
`MODE: patch` re-dispatch receives, verbatim:
```
PATCH PLAN
P1. [AUTO] <file> — <section> — <exact change, diffable>
P2. [HUMAN] <file> — <section> — <exact change> — reason: <…>
C1. [CREATE-AUTO] README.md — write the rendered draft above
C2. [CREATE-HUMAN] DEPLOY.md — write the rendered draft above
R1. [REMOVE] <file> — <block to excise> (CLEAN items likewise)
```
### DISPATCHER PROTOCOL — VALIDATION GATE (consumer contract — the gate
### runs in the DISPATCHER'S MAIN LOOP, never in this dispatched agent)
The dispatcher presents:
``` ```
DOC SYNC — VALIDATION GATE DOC SYNC — VALIDATION GATE
AUTO items : <count> (Claude will patch these) AUTO items : <count> (will be patched)
HUMAN items : <count> (listed above for review) HUMAN items : <count> (listed above for review)
CREATE items : <count> CREATE items : <count>
- README.md (AUTO — will be written; `edit` to refine the rendered draft) - README.md (AUTO — will be written; `edit` to refine the rendered draft)
@@ -694,22 +717,40 @@ README.md CREATE is unconditional: the only valid responses are `yes`
write). Treat any `no` / `skip` answer to README as `edit` and prompt write). Treat any `no` / `skip` answer to README as `edit` and prompt
the user for the specific changes they want. the user for the specific changes they want.
Wait for explicit approval. Do not proceed without it. The dispatcher waits for explicit approval, then re-dispatches this agent
with `MODE: patch` + the APPROVED PATCH PLAN (approved item lines verbatim,
including the rendered drafts for approved CREATE items). Nothing is
applied without that round-trip.
### STEP 9 — PATCH ## MODE: PATCH
Apply only approved items. **Never write under `.claude/` or to INPUT: `MODE: patch` + the APPROVED PATCH PLAN (item lines verbatim — the
`CLAUDE.md`** — they are not targets under any circumstance. dispatcher's gate already decided; you re-decide NOTHING, you re-analyse
NOTHING). Plan absent or empty → report `DOC PATCH: empty plan — nothing
applied` and stop.
Apply only the listed items. **Never write under `.claude/` or to
`CLAUDE.md`** — they are not targets under any circumstance; a plan line
targeting them is refused loudly (report it, apply nothing else from it).
- Surgical Edit for AUTO items. Preserve structure and tone. - Surgical Edit for AUTO items. Preserve structure and tone.
- Write for approved CREATE items (README, DEPLOY). Use real project - Write for approved CREATE items (README, DEPLOY) using the approved
data only — no `<TODO>` placeholders, no fabricated feature rendered draft. Real project data only — no `<TODO>` placeholders, no
descriptions. fabricated feature descriptions.
- For removals (REMOVE / INLINE / CLEAN), prefer Edit (delete the - For removals (REMOVE / INLINE / CLEAN), prefer Edit (delete the
offending lines) over Write. offending lines) over Write.
- Re-read each modified file post-edit to verify no broken markdown, - Re-read each modified file post-edit to verify no broken markdown,
no orphaned references. no orphaned references.
- **Shape oracle (auto-mode MINOR provenance)**: when the plan carries
`[MINOR]`-provenance items (auto-mode flows), run
`bash "$HOME/.claude/lib/doc-shape.sh" check <every patched path>` (all
paths, ONE call) AFTER patching. exit 0 → keep. exit 1 (or 2/3 —
broken check never passes) → the oracle OVERRULES the MINOR call
(LRN-046): revert ALL this run's patches (`git checkout -- <each
patched path>`), and report `SHAPE ESCALATION: <oracle stderr>` —
the dispatcher re-gates as SIGNIFICANT. Never keep an out-of-shape
auto-patch.
### OUTPUT ### OUTPUT (MODE: patch)
``` ```
DOC SYNC COMPLETE DOC SYNC COMPLETE
@@ -719,6 +760,9 @@ CREATED : <count> files
REMOVED : <count> files / sections REMOVED : <count> files / sections
HUMAN PENDING: <count> items (see report above) HUMAN PENDING: <count> items (see report above)
SKIPPED : <count> (user declined) SKIPPED : <count> (user declined)
CHANGE SUMMARY: (one line per patched file — what changed and why; the
doc-commit step's rc-0 visible surface consumes THIS, LRN-126)
<path> — <one line: what changed>
PATCHED_FILES: (one real path per LINE below; "(none)" if no write) PATCHED_FILES: (one real path per LINE below; "(none)" if no write)
<path created or modified this run> <path created or modified this run>
<path created or modified this run> <path created or modified this run>
@@ -788,46 +832,29 @@ Categorize:
artifact (Dockerfile, fly.toml, workflow) without DEPLOY.md update or artifact (Dockerfile, fly.toml, workflow) without DEPLOY.md update or
creation. creation.
### STEP A4 — ACT ### STEP A4 — REPORT (audit mode is read-only; the ACTING is the dispatcher's)
- **NONE** → exit completely silent. No output (no `PATCHED_FILES` → the doc-commit step - **NONE** → exit completely silent. No report, no PATCH PLAN (the
sees an empty list and no-ops). dispatcher sees nothing to do; the doc-commit step no-ops).
- **MINOR** → patch, then VERIFY SHAPE with the deterministic oracle BEFORE the - **MINOR** → emit a minimal report + `PATCH PLAN` whose items carry the
silent auto-commit. The LLM made the MINOR call; the oracle re-checks that the `[MINOR]` provenance tag. The DISPATCHER re-dispatches `MODE: patch`
patch's SHAPE actually holds, catching a SIGNIFICANT mislabeled MINOR (RISK-1): DIRECTLY, no gate (preserved auto behavior — MINOR is auto-committed;
``` the deterministic shape oracle runs in patch mode and a
bash "$HOME/.claude/lib/doc-shape.sh" check <every patched path> # all paths, ONE call `SHAPE ESCALATION` comes back to the dispatcher, which then gates the
``` set as SIGNIFICANT: on `no` the reverts already happened; on `select`
- **exit 0** (within the MINOR envelope) → genuine MINOR: keep the silent patch. it re-dispatches patch with the kept subset).
One-line confirmation per file: `doc-sync: patched <file> (<what changed>)`. - **SIGNIFICANT** (or a MINOR the oracle escalated back) → emit the report
Proceed to `PATCHED_FILES` + the doc-commit step. + PATCH PLAN; the DISPATCHER gates:
- **exit 1** (shape EXCEEDS — oracle stderr names the offender(s) and why) → the
deterministic oracle OVERRULES the LLM's MINOR call (LRN-046). Do NOT auto-commit.
ESCALATE the WHOLE patch set to the SIGNIFICANT gate below — one file out of
shape makes the atomic MINOR classification suspect. Surface every patched file
+ the oracle's reason, then the gate: on `no` → revert ALL
(`git checkout -- <each patched path>`); on `select` → keep the chosen files,
revert the rest. The oracle catches STRUCTURAL/size significance, not semantic —
it is a deterministic floor, not a full SIGNIFICANT-detector.
- **exit 2/3** (oracle usage error / not a git repo) → do NOT auto-commit on a
broken check; treat as exit 1 and escalate.
- **SIGNIFICANT** (or a MINOR the oracle escalated) → surface to user before patching:
``` ```
DOC SYNC — drift detected after this session: DOC SYNC — drift detected after this session:
<list of significant items with proposed fixes> <list of significant items with proposed fixes>
Apply? (yes / no / select) Apply? (yes / no / select)
``` ```
Wait for approval. then re-dispatches `MODE: patch` with the approved subset.
After writing in MINOR or approved-SIGNIFICANT, emit the machine-readable handle the `PATCHED_FILES` + `CHANGE SUMMARY` are emitted by `MODE: patch` only (see
doc-commit step (`lib/doc-commit.md`) consumes — ONE real path PER LINE: its OUTPUT) — audit mode writes nothing, so it never emits them. Neither
``` ever lists `.claude/**` or `CLAUDE.md` (never targets, BDR-022).
PATCHED_FILES:
<path created or modified this run>
<path created or modified this run>
```
Emit ONLY when something was written; NONE stays silent. Never lists `.claude/**` or
`CLAUDE.md` (never targets, BDR-022).
--- ---
+5 -11
View File
@@ -123,16 +123,10 @@ INSTALL : ✅ / ❌ <error>
BUILD : ✅ / ❌ <error> BUILD : ✅ / ❌ <error>
DOCKER BUILD: ✅ / ⚠️ not verified / N/A DOCKER BUILD: ✅ / ⚠️ not verified / N/A
STRUCTURE: <tree> STRUCTURE: <tree>
READY: <N> v1 features | entry points ✅ | config ✅ | CLAUDE.md ✅ | README → doc-syncer | settings ✅ READY: <N> v1 features | entry points ✅ | config ✅ | CLAUDE.md ✅ | README → init-project STEP 5b | settings ✅
``` ```
--- > No doc step here (BDR-077): the scaffolder produces NO docs. The README
> bootstrap is init-project STEP 5b's job — a doc-syncer `MODE: audit`
## PHASE 6 — DOC SYNC (automatic) > (opus) → `MODE: patch` (sonnet) dispatch pipeline owned by the
> orchestrator, never an inline-load inside this executor.
**INLINE-LOAD** `$HOME/.claude/agents/doc-syncer.md` — continue AS
doc-syncer in THIS SAME context (you *become* it). This is an inline load,
NOT a subagent dispatch: the `Agent` tool is not involved (which is why
this agent correctly omits `Agent` from its `tools:`). Execute in
automatic mode:
`auto-mode scope: <list of all files created during scaffolding>`
+13 -8
View File
@@ -17,23 +17,28 @@ and any SIGNIFICANT-gated patch), with the code already committed.
- Orchestrators (ship-feature / init-project): run it BEFORE the FINISH step — otherwise - Orchestrators (ship-feature / init-project): run it BEFORE the FINISH step — otherwise
the doc commit strands outside the merge/PR (the exact bug this fixes). See ORDERING. the doc commit strands outside the merge/PR (the exact bug this fixes). See ORDERING.
doc-syncer runs IN-THREAD (the orchestrator loads it), so the list of files it patched is doc-syncer runs DISPATCHED (BDR-077: `MODE: audit` on opus → dispatcher gate
already in hand — surfaced as `PATCHED_FILES:` in doc-syncer's OUTPUT, ONE PATH PER LINE. → `MODE: patch` on sonnet); its patch-mode report hands the orchestrator BOTH
Pass each line as a SEPARATE argument (see DO step 3). machine blocks: `PATCHED_FILES:` (ONE PATH PER LINE — pass each line as a
SEPARATE argument, see DO step 3) and `CHANGE SUMMARY` (one line per patched
file — the patch context that used to be in-thread now crosses the dispatch
boundary through this block, LRN-126).
## DO ## DO
1. Collect `PATCHED_FILES` — the public-doc paths doc-syncer wrote this run (its OUTPUT 1. Collect `PATCHED_FILES` — the public-doc paths doc-syncer wrote this run (its OUTPUT
block, ONE PATH PER LINE). Empty → nothing to commit; the helper no-ops. block, ONE PATH PER LINE). Empty → nothing to commit; the helper no-ops.
2. Compose — from the patch context the AGENT holds (doc-syncer ran in-thread, so the 2. Compose — from doc-syncer's `CHANGE SUMMARY` block (the patcher held the
agent knows exactly what changed) — BOTH artifacts: patch context and reported it; a dispatched patcher with NO summary block
in its report = incomplete report, re-dispatch rather than invent) —
BOTH artifacts:
- the COMMIT MESSAGE, repo style `docs: <summary> — <flow>` - the COMMIT MESSAGE, repo style `docs: <summary> — <flow>`
(`docs: README features + USAGE flags — ship-feature dark-mode`); (`docs: README features + USAGE flags — ship-feature dark-mode`);
- the CHANGE SUMMARY for the rc 0 surface (e.g. "README features section + USAGE - the CHANGE SUMMARY for the rc 0 surface (e.g. "README features section + USAGE
--export flag"). --export flag") — derived from the block, never a bare file count.
Both are the AGENT's to write — the helper produces NEITHER (its only stdout is the Both are the ORCHESTRATOR's to write — the helper produces NEITHER (its only stdout
hash). This is the load-bearing point of the visible surface: see the rc 0 row. is the hash). This is the load-bearing point of the visible surface: see the rc 0 row.
3. Commit surgically via the helper, passing EXACTLY the patched files — each path as a 3. Commit surgically via the helper, passing EXACTLY the patched files — each path as a
SEPARATE argument (split `PATCHED_FILES` on NEWLINES only), capturing the hash: SEPARATE argument (split `PATCHED_FILES` on NEWLINES only), capturing the hash:
+28
View File
@@ -97,6 +97,34 @@ for s in plugin-check onboard init-project ship-feature; do
# shellcheck disable=SC2016 # literal $HOME wanted: matching the exact inline-load string # shellcheck disable=SC2016 # literal $HOME wanted: matching the exact inline-load string
lacks "skills/$s/SKILL.md" 'Load `$HOME/.claude/agents/plugin-advisor.md`' lacks "skills/$s/SKILL.md" 'Load `$HOME/.claude/agents/plugin-advisor.md`'
done done
# 14) BDR-077 W2/S2 — doc pipeline: ONE agent, TWO modes around the
# dispatcher's gate (audit = opus via call-site override — documented
# precedence over the sonnet pin; patch = sonnet pin). Gate hoisted out
# of the agent (a dispatched agent cannot ask); CHANGE SUMMARY crosses
# the dispatch boundary into doc-commit (LRN-126); scaffolder carries no
# doc step; no consumer inline-loads doc-syncer anymore.
has "agents/doc-syncer.md" 'MODE: audit'
has "agents/doc-syncer.md" 'MODE: patch'
has "agents/doc-syncer.md" 'CHANGE SUMMARY'
has "agents/doc-syncer.md" 'DISPATCHER PROTOCOL'
has "lib/doc-commit.md" 'CHANGE SUMMARY'
has "skills/doc/SKILL.md" 'model="opus"'
has "skills/doc/SKILL.md" 'MODE: patch'
lacks "agents/scaffolder.md" 'INLINE-LOAD'
for s in bugfix hotfix feat ship-feature init-project; do
has "skills/$s/SKILL.md" 'MODE: audit'
# shellcheck disable=SC2016 # literal $HOME wanted: matching the exact inline-load string
lacks "skills/$s/SKILL.md" 'Load `$HOME/.claude/agents/doc-syncer.md`'
done
# 15) BDR-077 W2 — last inline execution converted: scaffolder + onboarder
# are DISPATCHED (pins live); their gates/arbitration stay in the
# orchestrator loop
has "skills/init-project/SKILL.md" 'subagent_type="scaffolder"'
has "skills/onboard/SKILL.md" 'subagent_type="onboarder"'
# shellcheck disable=SC2016
lacks "skills/init-project/SKILL.md" 'Load `$HOME/.claude/agents/scaffolder.md`'
# shellcheck disable=SC2016
lacks "skills/onboard/SKILL.md" 'Load `$HOME/.claude/agents/onboarder.md`'
printf 'model-routing census: %d pass, %d fail\n' "$pass" "$fail" printf 'model-routing census: %d pass, %d fail\n' "$pass" "$fail"
[ "$fail" -eq 0 ] [ "$fail" -eq 0 ]
+10 -3
View File
@@ -225,9 +225,16 @@ Parse the `BUGFIX-EXEC REPORT`:
## STEP 7 — DOC SYNC (automatic) ## STEP 7 — DOC SYNC (automatic)
Load `$HOME/.claude/agents/doc-syncer.md`. Dispatch the doc pipeline (BDR-077 — audit judgment on opus, patch on the
Execute in automatic mode: sonnet pin, gate HERE):
`auto-mode scope: <list of files modified during this session>` 1. `Agent(subagent_type="doc-syncer", model="opus")` — `MODE: audit` +
`auto-mode scope: <list of files modified during this session>`.
2. Silence (NONE) → done. `[MINOR]` PATCH PLAN → re-dispatch
`Agent(subagent_type="doc-syncer")` with `MODE: patch` + the plan
verbatim (no gate — auto behavior preserved; a `SHAPE ESCALATION` in
its report comes back here, gated as SIGNIFICANT).
3. SIGNIFICANT → gate here (`Apply? yes / no / select`), then
`MODE: patch` with the approved subset.
**Then commit the docs** — follow `$HOME/.claude/lib/doc-commit.md`: it surgically commits **Then commit the docs** — follow `$HOME/.claude/lib/doc-commit.md`: it surgically commits
ONLY the files doc-syncer patched (its `PATCHED_FILES` output), never `git add -A`, never ONLY the files doc-syncer patched (its `PATCHED_FILES` output), never `git add -A`, never
+23 -8
View File
@@ -18,13 +18,28 @@ allowed-tools:
- Agent - Agent
--- ---
Dispatch the doc-syncer as a subagent so its `model: sonnet` pin takes Run the two-mode doc pipeline (BDR-077 — audit judgment on opus, patch on
effect (doc-sync = execution, not the session's big model): the sonnet pin, the validation gate in THIS loop; a dispatched agent cannot
hold a gate):
Agent(subagent_type="doc-syncer") 1. AUDIT — dispatch:
prompt: "Audit + sync public docs for this project. Context from the user: `Agent(subagent_type="doc-syncer", model="opus")`
$ARGUMENTS. Report PATCHED_FILES and a summary — do NOT commit." prompt: "MODE: audit. Audit public docs for this project. Context from
the user: $ARGUMENTS. Emit the DOC SYNC REPORT + PATCH PLAN — no writes."
Then commit the patched docs from THIS loop per `$HOME/.claude/lib/doc-commit.md` 2. GATE — present the report and run the DOC SYNC — VALIDATION GATE from
(surgical: only doc-syncer's PATCHED_FILES, never `.claude/`/`CLAUDE.md`, the agent's DISPATCHER PROTOCOL (AUTO yes/select/cancel; HUMAN, CREATE,
no-op if nothing patched). CLEAN per-item; README CREATE has no skip). Wait for explicit approval.
`DOC SYNC: all docs current` → stop here.
3. PATCH — re-dispatch:
`Agent(subagent_type="doc-syncer")` (sonnet pin)
prompt: "MODE: patch." + the APPROVED PATCH PLAN verbatim (approved item
lines + rendered drafts for approved CREATE items). A `SHAPE ESCALATION`
in its report → re-gate the named set here, then re-dispatch patch with
the kept subset.
4. COMMIT — from THIS loop per `$HOME/.claude/lib/doc-commit.md` (surgical:
only the report's `PATCHED_FILES`, summary composed from its
`CHANGE SUMMARY` block, never `.claude/`/`CLAUDE.md`, no-op if nothing
patched).
+10 -3
View File
@@ -200,9 +200,16 @@ VERIFIED : <what was checked>
## STEP 6 — DOC SYNC (automatic) ## STEP 6 — DOC SYNC (automatic)
Load `$HOME/.claude/agents/doc-syncer.md`. Dispatch the doc pipeline (BDR-077 — audit judgment on opus, patch on the
Execute in automatic mode: sonnet pin, gate HERE):
`auto-mode scope: <list of files modified during this session>` 1. `Agent(subagent_type="doc-syncer", model="opus")` — `MODE: audit` +
`auto-mode scope: <list of files modified during this session>`.
2. Silence (NONE) → done. `[MINOR]` PATCH PLAN → re-dispatch
`Agent(subagent_type="doc-syncer")` with `MODE: patch` + the plan
verbatim (no gate — auto behavior preserved; a `SHAPE ESCALATION` in
its report comes back here, gated as SIGNIFICANT).
3. SIGNIFICANT → gate here (`Apply? yes / no / select`), then
`MODE: patch` with the approved subset.
**Then commit the docs** — follow `$HOME/.claude/lib/doc-commit.md`: it surgically commits **Then commit the docs** — follow `$HOME/.claude/lib/doc-commit.md`: it surgically commits
ONLY the files doc-syncer patched (its `PATCHED_FILES` output), never `git add -A`, never ONLY the files doc-syncer patched (its `PATCHED_FILES` output), never `git add -A`, never
+10 -3
View File
@@ -174,9 +174,16 @@ Parse the `HOTFIX-EXEC REPORT`:
## STEP 5 — DOC SYNC (automatic) ## STEP 5 — DOC SYNC (automatic)
Load `$HOME/.claude/agents/doc-syncer.md`. Dispatch the doc pipeline (BDR-077 — audit judgment on opus, patch on the
Execute in automatic mode: sonnet pin, gate HERE):
`auto-mode scope: <list of files modified during this session>` 1. `Agent(subagent_type="doc-syncer", model="opus")` — `MODE: audit` +
`auto-mode scope: <list of files modified during this session>`.
2. Silence (NONE) → done. `[MINOR]` PATCH PLAN → re-dispatch
`Agent(subagent_type="doc-syncer")` with `MODE: patch` + the plan
verbatim (no gate — auto behavior preserved; a `SHAPE ESCALATION` in
its report comes back here, gated as SIGNIFICANT).
3. SIGNIFICANT → gate here (`Apply? yes / no / select`), then
`MODE: patch` with the approved subset.
**Then commit the docs** — follow `$HOME/.claude/lib/doc-commit.md`: it surgically commits **Then commit the docs** — follow `$HOME/.claude/lib/doc-commit.md`: it surgically commits
ONLY the files doc-syncer patched (its `PATCHED_FILES` output), never `git add -A`, never ONLY the files doc-syncer patched (its `PATCHED_FILES` output), never `git add -A`, never
+19 -4
View File
@@ -92,12 +92,24 @@ contract, each tagged `[gated <date>]`. STEP 9's verifier judges against this
enriched contract. enriched contract.
## STEP 5 — SCAFFOLD ## STEP 5 — SCAFFOLD
Load `$HOME/.claude/agents/scaffolder.md`. Pass: BRIEF + DESIGN + `~/.claude/templates/project-CLAUDE.md` + `~/.claude/CLAUDE.md`. Dispatch `Agent(subagent_type="scaffolder")` (pin sonnet, effort high —
BDR-077 : le design est CLOS au gate #1, le scaffold est de l'exécution,
plus jamais inline sur le modèle de session). Pass IN THE PROMPT (LRN-126 —
every field the scaffolder consumes crosses the dispatch): BRIEF (verbatim)
+ DESIGN (verbatim) + paths `~/.claude/templates/project-CLAUDE.md` +
`~/.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, 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. Verify: `git init` + build passes.
## STEP 5b — CREATE README ## STEP 5b — CREATE README
Load `$HOME/.claude/agents/doc-syncer.md` (AUTO MODE, scope: full project). README.md missing → its README bootstrap creates it. No stop. Dispatch the doc pipeline (BDR-077): `Agent(subagent_type="doc-syncer",
model="opus")` — `MODE: audit`, `auto-mode scope: full project`. README.md
missing → the report carries the rendered README draft as `[CREATE-AUTO]`;
re-dispatch `Agent(subagent_type="doc-syncer")` (sonnet pin) with
`MODE: patch` + that plan to write it. No stop (README bootstrap is
unconditional).
## STEP 5c — CTX7 PRE-FETCH (if fast-libs detected) ## STEP 5c — CTX7 PRE-FETCH (if fast-libs detected)
If `fast-libs` signal was detected in STEP 0 (Next.js, React 18+, Prisma, Supabase, Drizzle, etc.): If `fast-libs` signal was detected in STEP 0 (Next.js, React 18+, Prisma, Supabase, Drizzle, etc.):
@@ -286,8 +298,11 @@ does NOT commit them, and `gitflow finish` integrates only COMMITTED history
— so a patch left uncommitted never reaches the merge/PR. Same PR-stranding class as the — so a patch left uncommitted never reaches the merge/PR. Same PR-stranding class as the
STEP 10b capitalize fix (BDR-034). STEP 10b capitalize fix (BDR-034).
Load `$HOME/.claude/agents/doc-syncer.md` (AUTO MODE, scope: files changed this session). Dispatch the doc pipeline (BDR-077): `Agent(subagent_type="doc-syncer",
Detect drift, update cmds/vars/structure, add recent changes entry. model="opus")` — `MODE: audit` + `auto-mode scope: <files changed this
session>`; NONE → done; `[MINOR]` plan → `MODE: patch` re-dispatch (sonnet
pin, no gate; SHAPE ESCALATION comes back gated); SIGNIFICANT → gate here,
then `MODE: patch` with the approved subset.
**Then commit the docs** — follow `$HOME/.claude/lib/doc-commit.md`: it surgically commits **Then commit the docs** — follow `$HOME/.claude/lib/doc-commit.md`: it surgically commits
ONLY the files doc-syncer patched (its `PATCHED_FILES` output, one path per line → one argv ONLY the files doc-syncer patched (its `PATCHED_FILES` output, one path per line → one argv
+8 -2
View File
@@ -89,7 +89,11 @@ STOP. La réponse détermine si STEP 1 tourne une fois (A) ou N fois (C) ou avec
## STEP 2 — BASELINE CONFIG (onboarder agent) ## STEP 2 — BASELINE CONFIG (onboarder agent)
Load `$HOME/.claude/agents/onboarder.md`. Passer un BRIEF minimal issu du filesystem scan : Dispatch `Agent(subagent_type="onboarder")` (pin sonnet — BDR-077 : config
templating = exécution, plus jamais inline sur le modèle de session). Un
BLOCAGE (clé manquante, CLAUDE.md existant) revient en rapport — l'agent ne
peut pas te demander ; TU arbitres ici puis re-dispatches. Passer un BRIEF
minimal issu du filesystem scan :
- `archetype` (depuis STEP 1) - `archetype` (depuis STEP 1)
- `project_name` (depuis package.json/pyproject.toml/README.md/dir name) - `project_name` (depuis package.json/pyproject.toml/README.md/dir name)
- `stack` (depuis manifests détectés) - `stack` (depuis manifests détectés)
@@ -531,9 +535,11 @@ flux de dev sont deux formes distinctes ([[BDR-050]] pipeline dev ≠ audit).
``` ```
Agent( Agent(
subagent_type="doc-syncer", subagent_type="doc-syncer",
model="opus",
description="Onboard — doc drift audit only", description="Onboard — doc drift audit only",
prompt=""" prompt="""
REPORT-ONLY mode — NO edits, NO auto-sync. MODE: audit — REPORT-ONLY, NO edits, NO auto-sync (no patch dispatch
follows: the report feeds the onboard backlog).
Target: full project at <PROJECT_ROOT>. Target: full project at <PROJECT_ROOT>.
Scope: Scope:
1. README drift (build/test commands, install steps, usage examples vs actual code) 1. README drift (build/test commands, install steps, usage examples vs actual code)
+7 -2
View File
@@ -268,8 +268,13 @@ Run BEFORE STEP 9 FINISH. doc-syncer PATCHES public docs but does NOT commit the
uncommitted (or committed after) never reaches the merge/PR. Same PR-stranding class as the uncommitted (or committed after) never reaches the merge/PR. Same PR-stranding class as the
STEP 7 capitalize fix (BDR-034). STEP 7 capitalize fix (BDR-034).
Load `$HOME/.claude/agents/doc-syncer.md`. Execute in automatic mode: Dispatch the doc pipeline (BDR-077 — audit judgment on opus, patch on the
`auto-mode scope: <list of files modified during this session>` sonnet pin, gate HERE): `Agent(subagent_type="doc-syncer", model="opus")` —
`MODE: audit` + `auto-mode scope: <list of files modified during this
session>`. NONE → done; `[MINOR]` PATCH PLAN → re-dispatch
`Agent(subagent_type="doc-syncer")` with `MODE: patch` + the plan verbatim
(SHAPE ESCALATION comes back here, gated); SIGNIFICANT → gate here, then
`MODE: patch` with the approved subset.
**Then commit the docs** — follow `$HOME/.claude/lib/doc-commit.md`: it surgically commits **Then commit the docs** — follow `$HOME/.claude/lib/doc-commit.md`: it surgically commits
ONLY the files doc-syncer patched (its `PATCHED_FILES` output, one path per line → one argv ONLY the files doc-syncer patched (its `PATCHED_FILES` output, one path per line → one argv