Merge feature/model-routing into develop
This commit is contained in:
@@ -86,6 +86,7 @@ rules:
|
|||||||
| BDR-063 | 2026-07-10 | GSC multi-account: OAuth2 installed-app flow + label-keyed token store, explicit (account,property) args, no global state | accepted |
|
| BDR-063 | 2026-07-10 | GSC multi-account: OAuth2 installed-app flow + label-keyed token store, explicit (account,property) args, no global state | accepted |
|
||||||
| BDR-064 | 2026-07-14 | global memory split: repo file → CLAUDE.global.md (deployed name unchanged), CLAUDE.md freed for project scope; consumer/maintainer wording rule | accepted |
|
| BDR-064 | 2026-07-14 | global memory split: repo file → CLAUDE.global.md (deployed name unchanged), CLAUDE.md freed for project scope; consumer/maintainer wording rule | accepted |
|
||||||
| BDR-065 | 2026-07-14 | transient planning artifacts (superpowers spec/plan): committed during run, deleted post-merge; git history = archive; codified in project CLAUDE.md | accepted |
|
| BDR-065 | 2026-07-14 | transient planning artifacts (superpowers spec/plan): committed during run, deleted post-merge; git history = archive; codified in project CLAUDE.md | accepted |
|
||||||
|
| BDR-066 | 2026-07-15 | Model routing: reflection inline (session big model) + sonnet-pinned executors + blocking gate | accepted |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -975,3 +976,18 @@ rules:
|
|||||||
- **Why**: user call 2026-07-14 — registries already capture decisions; a stale plan describes a superseded intermediate state and misleads future readers; accumulation pollutes the repo. Precedent: gsc-crux cleanup (8a1fac0, 2026-07-10) did the same — this makes it law, not habit.
|
- **Why**: user call 2026-07-14 — registries already capture decisions; a stale plan describes a superseded intermediate state and misleads future readers; accumulation pollutes the repo. Precedent: gsc-crux cleanup (8a1fac0, 2026-07-10) did the same — this makes it law, not habit.
|
||||||
- **Alternatives rejected**: never-commit (gitignore docs/superpowers) — breaks mid-run: briefs, reviewers, other-machine checkouts need the files; superpowers brainstorming commits the spec by convention. Keep-forever — the drift + pollution complained about.
|
- **Alternatives rejected**: never-commit (gitignore docs/superpowers) — breaks mid-run: briefs, reviewers, other-machine checkouts need the files; superpowers brainstorming commits the spec by convention. Keep-forever — the drift + pollution complained about.
|
||||||
- **Reference**: project CLAUDE.md; cleanup commit this chore; precedent 8a1fac0. Linked [[BDR-064]], [[LRN-124]].
|
- **Reference**: project CLAUDE.md; cleanup commit this chore; precedent 8a1fac0. Linked [[BDR-064]], [[LRN-124]].
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## BDR-066 — Model routing: reflection inline (session big model), executors pinned sonnet, blocking gate
|
||||||
|
|
||||||
|
- **Date**: 2026-07-15
|
||||||
|
- **Status**: accepted (partial supersede of BDR-050: /feat dev no longer inline; bugfix/hotfix dev-inline CONSERVED)
|
||||||
|
- **Decision**: reflection (brainstorm, plan, contract, audit judgment, loop decisions) runs on session model (Fable; Opus fallback) — inline or inherit subagents, never pinned down. Execution (code from closed plan, fix-bundle application) runs sonnet-pinned subagents: feater + hotfixer pinned sonnet; SDD implementation+review subagents dispatched `model: "sonnet"` (ship-feature/init-project); web-validate fixes via hotfixer L1 (was inline Edit). analyzer haiku pin REMOVED (digest feeds plan = reflection tier). verifier + security-auditor STAY sonnet (job9 confirmed — procedural gates, ≤3×/loop). Blocking gate `lib/model-gate.md` (self-check + witness `lib/model-check.sh`) wired in 12 reflection orchestrators; small → STOP, unknown → fail-visible; census guard `lib/tests/model-routing.test.sh` flip-tested.
|
||||||
|
- **Why**: big-model quota burned on mechanical execution (Fable exhausted mid-job8); plan closed at dispatch → executor needs obedience not judgment; fresh sonnet gates catch executor drift.
|
||||||
|
- **Alternatives rejected**: opus pins on audit agents (session-independent) — rejected: session assumed big + blocking gate as backstop, one tier fewer; advisory gate — rejected by user, blocking; split bugfix/hotfix too — rejected: bugfix investigation interleaved w/ fix, hotfix gain marginal vs dispatch overhead.
|
||||||
|
- **Caveats**: client-handover-writer conversion (inline-load → sonnet dispatch, 11 human-gate sites to relocate) DEFERRED to own plan — its opus pin stays inert meanwhile; feater cannot ask → NEED-DECISION report = escalation valve, plan must close decisions; witness reads settings.json — lags `--model`-launched sessions (self-check compensates).
|
||||||
|
- **Caveat (execution)**: /feat re-arch broke 5 stale assertions in lib/tests/loops-light.test.sh (locked OLD feater architecture) — repointed to skills/feat/SKILL.md (FSK, mirrors HOT/HSK split) + new dispatch lock + 1-line reflow in feat SKILL for single-line grep lock (LRN-093 class).
|
||||||
|
- **Wave 2 (2026-07-15, user directive)**: wave-1 exclusion list left execution running on the big session model = the waste this split kills. REVERSES the "split hotfix rejected" alternative above (reason held for bugfix — investigation interleaved w/ fix — but NOT hotfix: LOCATE→apply is linear/separable). Changes: /hotfix split like /feat (LOCATE reflection inline + MODEL GATE, hotfixer sonnet EXECUTOR — rewritten dual-use: also the seo/geo/web-validate L1 applier; revert-not-loop preserved) → hotfix JOINS gated group, census 12→13. /commit-change dispatches sonnet commit-changer (propose→dispatcher gates→apply; grouping ON sonnet so NO model gate; AskUserQuestion dropped from agent). /release-candidate dispatches new sonnet release-executor (2 spans prep/finish; when-to-release + push + version-number decision STAY in dispatcher). /doc → doc-syncer (sonnet) dispatch; /status → status-reporter (kept HAIKU — right tier for read-only collection; win = off big model, not the tier). Gate exclusion list now = commit-change/doc/status/release-candidate. Consumer-staleness swept (LRN-113): feat Rule 1 DOWNGRADE + feat commit-split both repointed off the bare executor agents to the /hotfix + /commit-change skills.
|
||||||
|
- **Wave 3 (2026-07-15/16, user directive)**: split the last two inline execution-carrying agents like /feat. /bugfix: investigation+diagnosis+contract inline behind the gate; bugfixer = sonnet EXECUTOR (fix + regression test from a closed FIX PLAN; no Agent/AskUserQuestion; BUGFIX-EXEC REPORT). verify+secure loop stays in main loop, executor = its re-dispatched dev (verify-secure-loop.md intro now: BOTH consumers dispatched, no inline branch). FINISHES reversing the "split bugfix rejected" carve-out (hotfix went wave 2, bugfix now) — investigation↔fix coupling accepted, mitigated by structured DIAGNOSIS + verify loop. /code-clean: PHASE-1 audit + validation gate inline (reflection); code-cleaner = sonnet PHASE-2 EXECUTOR (delete approved dead code, inline-load refactorer, re-audit) — refactor NOW on sonnet (inline-load pin was inert on big model). exported-symbol per-item consent stays AT THE GATE. Consumer-staleness swept: hotfix deeper-bug escalation → /bugfix skill (not bare agent); onboard STEP 6 + tour Phase B read-only-audit → general-purpose/analyzer (big model, NEVER the sonnet executor — audit stays big). Both skills STAY gated. Also: Explore built-in kept inheriting session (search feeds reflection = big deserved; custom sonnet override created then reverted — built-in already inherits + no owned prompt). census 36→42, loops-light repointed 35/0.
|
||||||
|
- **Reference**: spec `docs/superpowers/specs/2026-07-15-model-routing-design.md` + plan `docs/superpowers/plans/2026-07-15-model-routing.md` (transient, BDR-065 lifecycle), branch `feature/model-routing`.
|
||||||
|
|||||||
@@ -381,3 +381,8 @@ rules:
|
|||||||
## 2026-07-14
|
## 2026-07-14
|
||||||
- `/ship-feature` feature/claude-global-md-rename (unmerged, human GO pending): global memory → CLAUDE.global.md + project-scope CLAUDE.md, 8 commits (a4ee7e1 docs → e9a38a0 guards). Full pipeline: analyzer + contract (17 criteria), brainstorm/spec/plan gates, SDD 5 tasks (all task reviews Approved), verifier CONFORME 17/17 (after user-arbitrated criterion-9 consumer-wording + FILE-SCOPE [gated] enrichment), security PASS (semgrep 43 rules, 0), final review "Yes" after 2 Important fixes (guard-test drift → 7/7; doctor exact-target check). Decided [[BDR-064]]; learned [[LRN-122]] (2-commit rename split), [[LRN-123]] (exact symlink target). `make test` green throughout. settings.json plugin toggles = session-scoped, NOT committed — restore (gstack/ui-ux-pro-max/frontend-design/emil-design-eng/darwin-skill/magic ON) after merge.
|
- `/ship-feature` feature/claude-global-md-rename (unmerged, human GO pending): global memory → CLAUDE.global.md + project-scope CLAUDE.md, 8 commits (a4ee7e1 docs → e9a38a0 guards). Full pipeline: analyzer + contract (17 criteria), brainstorm/spec/plan gates, SDD 5 tasks (all task reviews Approved), verifier CONFORME 17/17 (after user-arbitrated criterion-9 consumer-wording + FILE-SCOPE [gated] enrichment), security PASS (semgrep 43 rules, 0), final review "Yes" after 2 Important fixes (guard-test drift → 7/7; doctor exact-target check). Decided [[BDR-064]]; learned [[LRN-122]] (2-commit rename split), [[LRN-123]] (exact symlink target). `make test` green throughout. settings.json plugin toggles = session-scoped, NOT committed — restore (gstack/ui-ux-pro-max/frontend-design/emil-design-eng/darwin-skill/magic ON) after merge.
|
||||||
- Merges to develop: feature/claude-global-md-rename (2d54df5), chore/untrack-audit-reports (d557ee9), chore/post-merge-cleanup. /cso triage: 75 gitleaks findings → 0 real (60 git SHAs vs sourcegraph rule; gitflow-test AWS fixture; expired GitHub image JWT; presigned-URL key ids; doc placeholders; job7-purged artifacts). .gitleaks.toml → [[allowlists]] format + 8 targeted entries; `make scan-secrets` green 0+0. Makefile "safe to commit" hint root-caused → [[LRN-124]]. Transient spec+plan deleted per [[BDR-065]] (user decree, gsc-crux precedent). Mid-merge discovery: user commit 5842119 (gitignore `.audit/` + model pin fable-5) — explains the .audit-in-diff question. cso report: .gstack/security-reports/2026-07-14-secrets-triage.json.
|
- Merges to develop: feature/claude-global-md-rename (2d54df5), chore/untrack-audit-reports (d557ee9), chore/post-merge-cleanup. /cso triage: 75 gitleaks findings → 0 real (60 git SHAs vs sourcegraph rule; gitflow-test AWS fixture; expired GitHub image JWT; presigned-URL key ids; doc placeholders; job7-purged artifacts). .gitleaks.toml → [[allowlists]] format + 8 targeted entries; `make scan-secrets` green 0+0. Makefile "safe to commit" hint root-caused → [[LRN-124]]. Transient spec+plan deleted per [[BDR-065]] (user decree, gsc-crux precedent). Mid-merge discovery: user commit 5842119 (gitignore `.audit/` + model pin fable-5) — explains the .audit-in-diff question. cso report: .gstack/security-reports/2026-07-14-secrets-triage.json.
|
||||||
|
|
||||||
|
## 2026-07-15
|
||||||
|
- model routing shipped on feature/model-routing: BDR-066 (reflection inline big / executors sonnet / blocking gate), /feat re-arch, census guard. client-handover conversion deferred to plan 2.
|
||||||
|
- model routing WAVE 2 (same branch, user directive): doc/status dispatch their agent (sonnet/haiku pins effective); /hotfix split like /feat (joins gated group 12→13, hotfixer dual-use executor); /commit-change → sonnet commit-changer (propose/apply, gates relocated); /release-candidate → sonnet release-executor (human gates + version decision kept in dispatcher). Consumer-staleness swept (feat Rule 1 + commit-split). census 36/0, make test green. Branch still unmerged.
|
||||||
|
- model routing WAVE 3 (same branch): /bugfix + /code-clean split like /feat — reflection inline, sonnet executors (bugfixer, code-cleaner). code-clean refactor now runs on sonnet (inline-load pin was inert). consumers rerouted (hotfix deeper-bug→/bugfix skill; onboard/tour read-only audit→big-model agent). Explore kept built-in (inherits big). census 42/0, loops-light 35/0. Branch still unmerged.
|
||||||
|
|||||||
@@ -1241,3 +1241,10 @@ rules:
|
|||||||
- **why**: redaction removes VALUES, not INTELLIGENCE. And tool output is instruction — a hint that says "safe to commit" will eventually be obeyed by a human or an agent.
|
- **why**: redaction removes VALUES, not INTELLIGENCE. And tool output is instruction — a hint that says "safe to commit" will eventually be obeyed by a human or an agent.
|
||||||
- **future application**: derived security artifacts (scan reports, triage JSONs, audit findings) stay local/ignored; only the allowlist CONFIG (reviewable rules) is committed. When auditing tooling, grep its user-facing hints for wording that invites committing outputs.
|
- **future application**: derived security artifacts (scan reports, triage JSONs, audit findings) stay local/ignored; only the allowlist CONFIG (reviewable rules) is committed. When auditing tooling, grep its user-facing hints for wording that invites committing outputs.
|
||||||
- **cousin**: [[BDR-057]] (secrets by reference, redact at capture), [[BDR-065]] (transient planning artifacts — same "process artifacts ≠ repo content" family), [[LRN-103]] (re-probe before acting).
|
- **cousin**: [[BDR-057]] (secrets by reference, redact at capture), [[BDR-065]] (transient planning artifacts — same "process artifacts ≠ repo content" family), [[LRN-103]] (re-probe before acting).
|
||||||
|
|
||||||
|
## LRN-125 — don't make an agent dual-use across model tiers; route the audit consumer to a big-model agent, not the sonnet executor
|
||||||
|
|
||||||
|
- **pattern**: splitting `code-cleaner` into a sonnet PHASE-2 executor broke its OTHER consumers (onboard STEP 6, tour Phase B) which dispatched it read-only AUDIT-only. Reflex "keep it dual-use (audit-only OR execute)" would have run an AUDIT on the sonnet-pinned executor = silent violation of the audit=big-model principle. Fix: reroute the audit consumers to a big-model agent (general-purpose/analyzer, inherits session), never the sonnet executor.
|
||||||
|
- **why**: a dual-use agent inherits ONE pinned model. If its two uses sit on different tiers (audit=big, execution=sonnet), the pin silently mis-tiers one of them. hotfixer dual-use is fine because BOTH its uses are execution (same tier); code-cleaner's would have straddled tiers.
|
||||||
|
- **future application**: before making an agent dual-use, check both consumers are on the SAME tier. Audit/reflection consumer + execution consumer → split the routing (audit → big-model agent, execution → sonnet executor); never overload one pinned agent. Distinct from [[LRN-113]] (sweep ALL consumers on a pattern fix) — this is WHICH agent a consumer routes to, not whether you found them all.
|
||||||
|
- **cousin**: [[BDR-066]] (model routing: reflection/audit big, execution sonnet), [[LRN-113]] (consumer-staleness sweep on a pattern fix).
|
||||||
|
|||||||
@@ -1,5 +1,40 @@
|
|||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
|
## 2026-07-15 — model routing (feature/model-routing)
|
||||||
|
Spec + plan in docs/superpowers/ (transient, BDR-065). BDR-066. Branch
|
||||||
|
unmerged — human gate.
|
||||||
|
- [x] gate lib/model-check.sh + lib/model-gate.md (flip-tested) wired ×12
|
||||||
|
- [x] pins: hotfixer/feater sonnet, analyzer un-pinned; SDD model:"sonnet";
|
||||||
|
web-validate → hotfixer L1; census guard model-routing.test.sh
|
||||||
|
- [x] /feat re-arch: reflection inline → feater sonnet executor (partial
|
||||||
|
supersede BDR-050)
|
||||||
|
- [x] WAVE 2 (user directive): doc/status dispatch (sonnet/haiku pins
|
||||||
|
effective); /hotfix split like /feat (joins gated 12→13, hotfixer
|
||||||
|
dual-use executor); /commit-change → sonnet commit-changer
|
||||||
|
(propose/apply, gates relocated); /release-candidate → sonnet
|
||||||
|
release-executor (human gates + version decision kept in dispatcher);
|
||||||
|
census 36/0. Exclusion list now commit-change/doc/status/release-candidate.
|
||||||
|
- [ ] DOGFOOD (manual, next sessions): /feat live run — plan closes
|
||||||
|
decisions, dispatch carries sonnet, verify loop in main loop; gate
|
||||||
|
STOP on a sonnet session (LRN-079 class, not automatable here). Also
|
||||||
|
dogfood /hotfix split + /commit-change propose/apply + /release-candidate spans.
|
||||||
|
- [x] Explore agent: kept as built-in (inherits session = opus/fable). User
|
||||||
|
call — search feeds reflection, silent-incompleteness risk → deserves the
|
||||||
|
big model. Custom sonnet Explore.md created then reverted (built-in already
|
||||||
|
inherits + no owned prompt).
|
||||||
|
- [x] WAVE 3 (user directive): /bugfix split + /code-clean split → reflection
|
||||||
|
inline (behind existing gate), execution → sonnet executors. bugfixer =
|
||||||
|
pure fix+regression exec (BUGFIX-EXEC REPORT, no Agent/AskUserQuestion);
|
||||||
|
code-cleaner = PHASE-2 exec (refactor now runs on sonnet — inline-load pin
|
||||||
|
was inert). Both skills STAY gated. census wave-3 + loops-light repoint
|
||||||
|
(guarded). Supersedes BDR-050 bugfix carve-out.
|
||||||
|
- [ ] WAVE 4 — client-handover: DECIDED = dispatch the WHOLE writer (spec §5,
|
||||||
|
not redaction-only). Needs resumable-gate protocol (~8-11 AskUserQuestion
|
||||||
|
→ GATE NEEDED yields, dispatcher asks + SendMessage-resumes) + force-big
|
||||||
|
on nested audit dispatches (STEP 3/4/7 — else audits inherit sonnet) +
|
||||||
|
MODEL GATE on the skill. NOT yet spec'd — dedicated pass after wave-3;
|
||||||
|
read writer 1123-1774 first.
|
||||||
|
|
||||||
## 2026-07-08 — full back-merge release/1.0.0→develop (chore/backmerge-release-full)
|
## 2026-07-08 — full back-merge release/1.0.0→develop (chore/backmerge-release-full)
|
||||||
Genèse : la revue avait porté ~5/19 commits ; back-merge complet demandé. Cherry-pick par
|
Genèse : la revue avait porté ~5/19 commits ; back-merge complet demandé. Cherry-pick par
|
||||||
catégorie, 1 commit atomique/item, make test après chaque code. Branche non mergée (gate humain).
|
catégorie, 1 commit atomique/item, make test après chaque code. Branche non mergée (gate humain).
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ Format follows [Keep a Changelog](https://keepachangelog.com/).
|
|||||||
- `/deploy` checklist reshaped on first-real-run feedback, in two passes: runbook steps are **one command per line, interactive-session style** (an early step opens the ssh session; later lines run on the box; local steps say "from your machine") instead of folded `ssh host "cd … && …"` one-liners — step = comment header + command lines up to the next blank line, a `@delta:` directive governs the whole block; and the checklist is now **display-only** — `NEXT.sh` is no longer written at all (throwaway artifact; `PENDING.json` + the live runbook regenerate it in any session) and every hand-back **ends the turn with the full checklist as the final text, no tool call after it** (a checklist printed above a blocking question tool was observed never reaching the user). Template `templates/deploy/PROCEDURE.md` restyled to match.
|
- `/deploy` checklist reshaped on first-real-run feedback, in two passes: runbook steps are **one command per line, interactive-session style** (an early step opens the ssh session; later lines run on the box; local steps say "from your machine") instead of folded `ssh host "cd … && …"` one-liners — step = comment header + command lines up to the next blank line, a `@delta:` directive governs the whole block; and the checklist is now **display-only** — `NEXT.sh` is no longer written at all (throwaway artifact; `PENDING.json` + the live runbook regenerate it in any session) and every hand-back **ends the turn with the full checklist as the final text, no tool call after it** (a checklist printed above a blocking question tool was observed never reaching the user). Template `templates/deploy/PROCEDURE.md` restyled to match.
|
||||||
- `settings.json`: `inputNeededNotifEnabled: true` adopted (harness notification toggle); committed layout otherwise unchanged.
|
- `settings.json`: `inputNeededNotifEnabled: true` adopted (harness notification toggle); committed layout otherwise unchanged.
|
||||||
- gsd-pi upgraded 2.64.0 → 3.0.0 — `status-reporter` output parser adapted to the ADR-013 cutover.
|
- gsd-pi upgraded 2.64.0 → 3.0.0 — `status-reporter` output parser adapted to the ADR-013 cutover.
|
||||||
|
- `hotfixer` pinned `model: sonnet` (seo/geo/web-validate L1 applier); `analyzer` haiku pin removed (inherits the session model).
|
||||||
|
- ship-feature / init-project: SDD implementation + review subagents dispatched with `model: "sonnet"`.
|
||||||
|
- web-validate `--fix`: bundle applied via `hotfixer` at L1 instead of inline Edit (BDR-061 alignment).
|
||||||
|
- Model routing wave 2 — the pure-execution + reflection-split skills stop running execution on the big session model. `/doc` and `/status` now **dispatch** their agent (doc-syncer sonnet, status-reporter haiku) instead of inline-loading it, so the pin takes effect. `/hotfix` split like `/feat`: reflection (LOCATE root cause) inline behind the model gate, the fix applied by a `hotfixer` sonnet executor (rewritten dual-use — it is also the seo/geo/web-validate L1 applier); revert-not-loop preserved; hotfix joins the gated group (13th). `/commit-change` dispatches a sonnet `commit-changer` (propose → dispatcher-owned approval gates → apply; grouping runs on sonnet, `AskUserQuestion` removed from the agent). `/release-candidate` dispatches a new sonnet `release-executor` for the mechanical spans (prep / finish+tag), the two human gates (when-to-release, push) and the version-number decision staying in the dispatcher.
|
||||||
|
- Model routing wave 3 — the last two inline execution-carrying skills split like `/feat`. `/bugfix`: root-cause investigation, diagnosis and contract run inline behind the model gate; the fix + regression test are applied by a `bugfixer` sonnet executor (was a single inline agent), with the verify+secure loop staying in the main loop and the executor as its re-dispatched dev. `/code-clean`: the dead-code / style / structural audit and the approval gate run inline; a `code-cleaner` sonnet PHASE-2 executor then applies the approved scope — and the style/structural refactor (which inline-loads `refactorer`) now finally runs on sonnet, its pin having been inert under the old inline-load. Both skills stay gated (they keep reflection); their read-only-audit consumers (`onboard`, `tour`) reroute to a big-model agent so an audit never runs on the sonnet executor. Supersedes the BDR-050 "bugfix stays inline" carve-out. The built-in `Explore` search agent is deliberately left inheriting the session (search feeds reflection).
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
- **Magic MCP fully ask-gated** — all four `mcp__magic__*` tools (builder, refiner, inspiration, logo_search) moved to `permissions.ask` in `settings.json`; no magic call can auto-execute. The builder opens an unauthenticated local callback server (`127.0.0.1:9221+`, `Access-Control-Allow-Origin: *`, no token check) whose POST body is injected verbatim into the tool result the model consumes — the ask-gate is the mitigation on our side (BDR-059).
|
- **Magic MCP fully ask-gated** — all four `mcp__magic__*` tools (builder, refiner, inspiration, logo_search) moved to `permissions.ask` in `settings.json`; no magic call can auto-execute. The builder opens an unauthenticated local callback server (`127.0.0.1:9221+`, `Access-Control-Allow-Origin: *`, no token check) whose POST body is injected verbatim into the tool result the model consumes — the ask-gate is the mitigation on our side (BDR-059).
|
||||||
@@ -23,6 +28,8 @@ Format follows [Keep a Changelog](https://keepachangelog.com/).
|
|||||||
- **GSC + CrUX data layer for `/seo` FULL** — `lib/seo-data/` engine pulls real Google Search Console (Search Analytics + URL Inspection) and Chrome UX Report field data into the `/seo` FULL audit: CrUX p75 field metrics become the primary Core Web Vitals signal (anonymous PageSpeed lab stays the fallback), and a "Performance GSC (90 j)" section flags position 4-10 quick wins. Multi-account via OAuth2 (`make seo-connect`, one-time consent, `webmasters.readonly` scope only) with a per-label token store (0600 file / 0700 dir, atomic write, refresh tokens redacted, gitleaks-allowlisted) so two concurrent site audits never conflict. Absent credentials degrade gracefully to anonymous PageSpeed — the audit never fails. Config: `GOOGLE_OAUTH_CLIENT_ID` / `GOOGLE_OAUTH_CLIENT_SECRET` / `CRUX_API_KEY` in `~/.claude/.env`. Engine contract documented in `lib/seo-data/README.md`.
|
- **GSC + CrUX data layer for `/seo` FULL** — `lib/seo-data/` engine pulls real Google Search Console (Search Analytics + URL Inspection) and Chrome UX Report field data into the `/seo` FULL audit: CrUX p75 field metrics become the primary Core Web Vitals signal (anonymous PageSpeed lab stays the fallback), and a "Performance GSC (90 j)" section flags position 4-10 quick wins. Multi-account via OAuth2 (`make seo-connect`, one-time consent, `webmasters.readonly` scope only) with a per-label token store (0600 file / 0700 dir, atomic write, refresh tokens redacted, gitleaks-allowlisted) so two concurrent site audits never conflict. Absent credentials degrade gracefully to anonymous PageSpeed — the audit never fails. Config: `GOOGLE_OAUTH_CLIENT_ID` / `GOOGLE_OAUTH_CLIENT_SECRET` / `CRUX_API_KEY` in `~/.claude/.env`. Engine contract documented in `lib/seo-data/README.md`.
|
||||||
- **impeccable** (pbakaus, Apache-2.0) wired into the toolchain as the design counterpart of semgrep: the `/impeccable` skill (23 verbs under one command: audit, polish, bolder, quieter…) plus the 45-rule deterministic anti-pattern detector (`npx impeccable detect`, exit 0/2, `--json`). Complementary to `frontend-design` (kept — aesthetic direction at build time); impeccable adds the deterministic audit floor and per-project design context (`/impeccable init`). CLI pinned in `plugins.lock.json` (3.2.0 — a silent rules update would change audit output on unchanged code); dist is machine-owned under `skills-external/impeccable/` (gitignored, ctx7 pattern), staged-installed by `install-plugins.sh` Step 8d, refreshed pin-honored by `update-all.sh`, symlinked by `link.sh`, listed in the design/web/web-full/full profiles and the design-work routing. Requires Node ≥ 24: the install baseline is bumped from 22 to 24 LTS (NodeSource `setup_24.x` / brew `node@24`), so `make plugin` upgrades a too-old host in place; the impeccable steps still skip gracefully if Node stays below 24. Not in the design gate's GATE-BLOCK list yet — promotion deliberate, after first dogfood.
|
- **impeccable** (pbakaus, Apache-2.0) wired into the toolchain as the design counterpart of semgrep: the `/impeccable` skill (23 verbs under one command: audit, polish, bolder, quieter…) plus the 45-rule deterministic anti-pattern detector (`npx impeccable detect`, exit 0/2, `--json`). Complementary to `frontend-design` (kept — aesthetic direction at build time); impeccable adds the deterministic audit floor and per-project design context (`/impeccable init`). CLI pinned in `plugins.lock.json` (3.2.0 — a silent rules update would change audit output on unchanged code); dist is machine-owned under `skills-external/impeccable/` (gitignored, ctx7 pattern), staged-installed by `install-plugins.sh` Step 8d, refreshed pin-honored by `update-all.sh`, symlinked by `link.sh`, listed in the design/web/web-full/full profiles and the design-work routing. Requires Node ≥ 24: the install baseline is bumped from 22 to 24 LTS (NodeSource `setup_24.x` / brew `node@24`), so `make plugin` upgrades a too-old host in place; the impeccable steps still skip gracefully if Node stays below 24. Not in the design gate's GATE-BLOCK list yet — promotion deliberate, after first dogfood.
|
||||||
- `/tour` skill — grouped all-axes sweep over one or several projects: security (pinned-semgrep `security-auditor` agent + `/cso` posture when gstack is ON) → cleanup → re-verify → reconcile (report-only, never edits the target TODO/registries) → doc sync, looping until a full pass applies zero fixes (bounded at 3 iterations). Fixes land on a `chore/tour-<date>` branch the skill never merges; each project gets an append-only `.claude/audits/TOUR.md` report with BREAKING tags on contract-changing security fixes. Built TDD (superpowers:writing-skills): baseline run showed silent TODO rewrites, autonomous registry writes, grep-as-security-pass, no persistent report, scope creep and an unbounded loop — each countered and verified on a seeded fixture.
|
- `/tour` skill — grouped all-axes sweep over one or several projects: security (pinned-semgrep `security-auditor` agent + `/cso` posture when gstack is ON) → cleanup → re-verify → reconcile (report-only, never edits the target TODO/registries) → doc sync, looping until a full pass applies zero fixes (bounded at 3 iterations). Fixes land on a `chore/tour-<date>` branch the skill never merges; each project gets an append-only `.claude/audits/TOUR.md` report with BREAKING tags on contract-changing security fixes. Built TDD (superpowers:writing-skills): baseline run showed silent TODO rewrites, autonomous registry writes, grep-as-security-pass, no persistent report, scope creep and an unbounded loop — each countered and verified on a seeded fixture.
|
||||||
|
- Model routing (BDR-066): blocking model gate (`lib/model-gate.md` + `lib/model-check.sh`, flip-tested) wired into 12 reflection orchestrators; census guard `lib/tests/model-routing.test.sh`.
|
||||||
|
- `/feat` re-architected: reflection inline (scope/plan/contract), execution dispatched to the sonnet-pinned `feater` executor; verify+secure loop decided in the main loop with fresh executor re-dispatches.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- `lib/detect-plugins.sh`: `detect_security_guidance` — dead since its re-add at `45c3507`; zero callers on any surface, including the dynamic `session-start.sh` detection loop (the banner's row derives from `enabledPlugins` instead). Nothing invokes it — removal, not a breaking change.
|
- `lib/detect-plugins.sh`: `detect_security_guidance` — dead since its re-add at `45c3507`; zero callers on any surface, including the dynamic `session-start.sh` detection loop (the banner's row derives from `enabledPlugins` instead). Nothing invokes it — removal, not a breaking change.
|
||||||
|
|||||||
@@ -37,6 +37,30 @@ claude-config/
|
|||||||
- `templates/` = symlinked to `~/.claude/templates/` — copy into projects via `/onboard` or manually
|
- `templates/` = symlinked to `~/.claude/templates/` — copy into projects via `/onboard` or manually
|
||||||
- **Graphify** builds a knowledge graph of any codebase (`/graphify query`), producing a navigable wiki in `graphify-out/wiki/`. This map helps Claude understand project structure, find relevant code faster, and reason across files. Essential for large-scope tasks (multi-file features, complex bugs, architectural changes). Small tasks should skip it and read files directly.
|
- **Graphify** builds a knowledge graph of any codebase (`/graphify query`), producing a navigable wiki in `graphify-out/wiki/`. This map helps Claude understand project structure, find relevant code faster, and reason across files. Essential for large-scope tasks (multi-file features, complex bugs, architectural changes). Small tasks should skip it and read files directly.
|
||||||
|
|
||||||
|
### Agent model routing (BDR-066)
|
||||||
|
|
||||||
|
Reflection (brainstorm, plan, contract, audit judgment, loop decisions) runs
|
||||||
|
INLINE on the session model — assumed Fable/Opus, enforced by a blocking
|
||||||
|
gate (`lib/model-gate.md` + `lib/model-check.sh`) at the entry of the 13
|
||||||
|
reflection orchestrators. Execution runs on pinned subagents:
|
||||||
|
|
||||||
|
| Agent | Model | Tier |
|
||||||
|
|---|---|---|
|
||||||
|
| feater, hotfixer, bugfixer | sonnet (pinned) | executors — code from a closed plan (feat), fix from a closed diagnosis (bugfix), fix-bundle appliers |
|
||||||
|
| verifier, security-auditor | sonnet (pinned) | fresh gates (≤3×/loop) |
|
||||||
|
| commit-changer, release-executor, code-cleaner | sonnet (pinned) | dispatched execution — grouping+commit / release spans / approved cleanup (the audit + approval gate stay in the dispatcher) |
|
||||||
|
| doc-syncer, onboarder, scaffolder, refactorer, interviewer, plugin-advisor | sonnet (pinned) | workers |
|
||||||
|
| status-reporter | haiku (pinned) | mechanical collector |
|
||||||
|
| client-handover-writer | opus (pinned, currently inert — inline-loaded; sonnet conversion planned) | deliverable writer |
|
||||||
|
| analyzer, seo-analyzer, geo-analyzer, validator-analyzer | inherit session (Fable/Opus) | reflection / audit / inline playbooks |
|
||||||
|
| Explore (built-in) | inherit session (Fable/Opus) | search feeds reflection — kept on the big model, not pinned down |
|
||||||
|
|
||||||
|
The pure-execution skills `/doc`, `/status`, `/commit-change`,
|
||||||
|
`/release-candidate` **dispatch** their agent (instead of inline-loading it)
|
||||||
|
so the pin takes effect and the work leaves the big session model; `/hotfix`
|
||||||
|
was split like `/feat` (reflection inline + gate, `hotfixer` executor) and so
|
||||||
|
joins the gated group (13th).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Fresh install (new machine)
|
## Fresh install (new machine)
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ cd mon-projet-existant/
|
|||||||
| 4 | Graphify (si complexity ≥ 30%) | graphify-out/GRAPH_REPORT.md |
|
| 4 | Graphify (si complexity ≥ 30%) | graphify-out/GRAPH_REPORT.md |
|
||||||
| 5 | Analyze read-only (analyzer agent) | .onboard-audit/analyze.md |
|
| 5 | Analyze read-only (analyzer agent) | .onboard-audit/analyze.md |
|
||||||
| 6 | Audits parallèles selon archétype : | .onboard-audit/*.md (9 fichiers max) |
|
| 6 | Audits parallèles selon archétype : | .onboard-audit/*.md (9 fichiers max) |
|
||||||
| | — dette tech (code-cleaner) |
|
| | — dette tech (general-purpose, audit read-only) |
|
||||||
| | — sécurité (cso si gstack ON, sinon OWASP fallback) |
|
| | — sécurité (cso si gstack ON, sinon OWASP fallback) |
|
||||||
| | — docs drift (doc-syncer) |
|
| | — docs drift (doc-syncer) |
|
||||||
| | — SEO + GEO (si public) |
|
| | — SEO + GEO (si public) |
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
name: analyzer
|
name: analyzer
|
||||||
description: Analyze code, codebase, or problem before any modification. Produces a factual report without proposing solutions. Use proactively before any refactoring, design, or implementation.
|
description: Analyze code, codebase, or problem before any modification. Produces a factual report without proposing solutions. Use proactively before any refactoring, design, or implementation.
|
||||||
tools: Read, Grep, Glob, Bash
|
tools: Read, Grep, Glob, Bash
|
||||||
model: haiku
|
|
||||||
memory: project
|
memory: project
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+40
-232
@@ -1,245 +1,53 @@
|
|||||||
---
|
---
|
||||||
name: bugfixer
|
name: bugfixer
|
||||||
description: Root-cause bug-fix executor — dispatched by /bugfix. Hypothesis-driven investigation, diagnosis, minimal scoped fix with regression test.
|
description: Bug-fix EXECUTOR — dispatched by /bugfix with a closed DIAGNOSIS + FIX PLAN + contract. Applies the fix and a regression test, runs the suite, reports. No investigation, no questions, no commit.
|
||||||
tools: Read, Edit, Write, Bash, Grep, Glob, Agent
|
tools: Read, Edit, Write, Bash, Grep, Glob
|
||||||
|
model: sonnet
|
||||||
---
|
---
|
||||||
|
|
||||||
# BUGFIX — Structured Bug Fix
|
# BUGFIXER — fix executor
|
||||||
|
|
||||||
Investigate, understand, plan, fix. No guessing. The iron law:
|
You receive a CLOSED diagnosis + fix plan from the /bugfix orchestrator. The
|
||||||
understand the root cause before writing a single fix.
|
investigation already happened; your job is faithful execution, not analysis.
|
||||||
|
Every choice was made in the plan or is a NEED-DECISION to report.
|
||||||
|
|
||||||
## REQUEST
|
## INPUT (in the dispatch prompt)
|
||||||
$ARGUMENTS
|
|
||||||
|
|
||||||
---
|
- `CONTRACT`: path to the contract file — read it FIRST; its acceptance
|
||||||
|
criteria (symptom reproduced-then-gone + a regression test present) + FILE
|
||||||
|
SCOPE bound everything you do.
|
||||||
|
- `DIAGNOSIS`: root cause + evidence, from the orchestrator's investigation.
|
||||||
|
- `FIX PLAN`: the exact edits (file:line → change) + the regression test to add.
|
||||||
|
- `BRANCH`: verify with `git branch --show-current`; mismatch → STATUS
|
||||||
|
BLOCKED — never create or switch branches.
|
||||||
|
- `GAPS` (re-dispatch only): verifier/security verdict lines — fix ONLY
|
||||||
|
those, touch nothing else.
|
||||||
|
|
||||||
## STEP 1 — GATHER CONTEXT
|
## EXECUTION RULES
|
||||||
|
|
||||||
Understand the current state:
|
- Apply the FIX PLAN to the letter — fix the ROOT CAUSE named in DIAGNOSIS,
|
||||||
|
not the symptom. A plan hole or an open choice (naming, data shape, API
|
||||||
|
surface, dependency) → STOP, report `NEED-DECISION` with the precise
|
||||||
|
question. Never re-investigate or improvise a different fix.
|
||||||
|
- Stay inside the contract FILE SCOPE. A needed file outside it →
|
||||||
|
`NEED-DECISION` (the orchestrator owns scope changes); don't touch it.
|
||||||
|
- Add or update the regression test the plan names — it must fail before the
|
||||||
|
fix and pass after. Run the relevant suite incrementally; run it fully
|
||||||
|
before reporting.
|
||||||
|
- Follow existing code patterns and CLAUDE.md limits (function size, params,
|
||||||
|
no global state). Keep the fix minimal — no "while we're here" cleanups.
|
||||||
|
- FORBIDDEN: `git commit`, branch ops, push, merge, new dependencies,
|
||||||
|
security/verifier dispatch, editing `.claude/**` or memory registries, user
|
||||||
|
questions (you cannot ask — report instead), attribution trailers of any kind.
|
||||||
|
|
||||||
```bash
|
## OUTPUT — end with exactly this report (your final message)
|
||||||
git status
|
|
||||||
git log --oneline -5
|
|
||||||
```
|
|
||||||
|
|
||||||
Read the error message, stack trace, or bug description.
|
|
||||||
Identify:
|
|
||||||
- **What** is broken (symptom)
|
|
||||||
- **Where** it manifests (file, line, endpoint, UI element)
|
|
||||||
- **When** it started (recent commit? always? after a deploy?)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# If the user mentions "it was working before":
|
|
||||||
git log --oneline -20 --all -- <suspected files>
|
|
||||||
```
|
|
||||||
|
|
||||||
## STEP 1.5 — DESIGN GATE
|
|
||||||
|
|
||||||
Follow `$HOME/.claude/lib/design-gate.md`:
|
|
||||||
- Scan $ARGUMENTS and target files for design/UI/style signals (CSS, component, layout, animation).
|
|
||||||
- If signals found → run `design-tool-gate.sh`; if it reports INCOMPLETE,
|
|
||||||
tell the user to run `/profile design` before proceeding.
|
|
||||||
- If no signals → skip (zero overhead).
|
|
||||||
|
|
||||||
## STEP 2 — INVESTIGATE
|
|
||||||
|
|
||||||
Trace the bug from symptom to root cause:
|
|
||||||
|
|
||||||
1. Read the code path involved (follow the data flow).
|
|
||||||
2. Check recent changes to the affected files:
|
|
||||||
```bash
|
|
||||||
git log --oneline -10 -- <file>
|
|
||||||
git diff HEAD~5 -- <file> # if recent regression suspected
|
|
||||||
```
|
|
||||||
3. Look for related tests — do they pass? Do they cover
|
|
||||||
the broken case?
|
|
||||||
4. Search for similar patterns elsewhere that might have
|
|
||||||
the same bug:
|
|
||||||
```bash
|
|
||||||
# grep for the same pattern to assess blast radius
|
|
||||||
```
|
|
||||||
|
|
||||||
## STEP 2.5 — MEMORY READ-BEFORE (blockers-first)
|
|
||||||
|
|
||||||
Run the scan per `$HOME/.claude/lib/analyze-before-plan.md`, blockers-weighted: a resolved
|
|
||||||
BLK may already name THIS exact root cause; an in-force BDR may constrain the fix. Emit
|
|
||||||
RELATED MEMORY. Consumption is NATURAL — the agent emitting this IS the one writing STEP 3's
|
|
||||||
diagnosis (reader = planner, no external skill to inject into).
|
|
||||||
|
|
||||||
TEETH: STEP 3's DIAGNOSIS must name any binding prior (`PRIOR: BLK-xxx — known cause/fix`,
|
|
||||||
or `honors BDR-xxx`) OR the RELATED MEMORY line states none bears. Reading blockers then
|
|
||||||
diagnosing without naming a match is the read-then-ignore failure this prevents.
|
|
||||||
`.claude/memory/` absent → guarded no-op, proceed.
|
|
||||||
|
|
||||||
## STEP 3 — HYPOTHESIZE + PLAN
|
|
||||||
|
|
||||||
Present findings before fixing:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
BUGFIX — DIAGNOSIS
|
BUGFIX-EXEC REPORT
|
||||||
BUG : <one-line symptom>
|
STATUS : DONE | NEED-DECISION | BLOCKED
|
||||||
ROOT CAUSE: <what is actually wrong and why>
|
FILE(S) : <created/modified paths>
|
||||||
EVIDENCE: <what confirmed it — test, trace, diff>
|
TEST(S) : <regression test added/updated + final suite run result, verbatim line>
|
||||||
BLAST RADIUS: <other places affected, or "isolated">
|
SMOKE : <build/typecheck result if run, or n/a>
|
||||||
|
NOTES : <DONE: deviations (must be none) | NEED-DECISION: the exact
|
||||||
FIX PLAN:
|
question + the options you see | BLOCKED: the blocker verbatim>
|
||||||
1. <file:line> — <what to change>
|
|
||||||
2. <file:line> — <what to change>
|
|
||||||
[3. <test file> — add/update test for this case]
|
|
||||||
|
|
||||||
RISK: <low/medium — what could go wrong>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- If the root cause is still unclear after investigation,
|
|
||||||
say so explicitly. List remaining hypotheses ranked by
|
|
||||||
probability. Ask the user before proceeding.
|
|
||||||
- If the fix is trivial after investigation (1-2 lines):
|
|
||||||
proceed directly — no need to wait for approval on an
|
|
||||||
obvious fix.
|
|
||||||
- If the fix is significant (>10 lines, multiple files,
|
|
||||||
behavior change): wait for user approval.
|
|
||||||
|
|
||||||
## STEP 3.5 — CONTRACT
|
|
||||||
|
|
||||||
Run `$HOME/.claude/lib/contract-interview.md` (main loop). The DIAGNOSIS
|
|
||||||
feeds it: REQUEST verbatim = the bug report as received; ACCEPTANCE CRITERIA
|
|
||||||
= the symptom reproduced-then-gone + a regression test present and passing;
|
|
||||||
FILE SCOPE = the FIX PLAN files. Questions stay proportional (a clear,
|
|
||||||
reproduced bug → zero). It writes the contract to
|
|
||||||
`.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`; keep the path for GATE 1
|
|
||||||
(STEP 5).
|
|
||||||
|
|
||||||
## STEP 4 — FIX
|
|
||||||
|
|
||||||
**Gitflow aiguillage (before editing):** follow `$HOME/.claude/lib/gitflow-aiguillage.md`
|
|
||||||
— your type = `bugfix`. On `main`/`develop` it branches first; on a working
|
|
||||||
branch it's a no-op (commit in place). Never `finish`.
|
|
||||||
|
|
||||||
Apply the fix following the plan:
|
|
||||||
|
|
||||||
- Fix the root cause, not the symptom.
|
|
||||||
- Add or update tests to cover the bug case (regression test).
|
|
||||||
- If no test framework exists: document what you verified.
|
|
||||||
- Keep changes minimal — fix the bug, nothing else.
|
|
||||||
|
|
||||||
## STEP 5 — VERIFY + COMMIT
|
|
||||||
|
|
||||||
1. Run the full relevant test suite. Detection cascade (run the first that resolves):
|
|
||||||
```bash
|
|
||||||
# JS/TS — package.json scripts.test
|
|
||||||
test -f package.json && jq -r '.scripts.test // empty' package.json | head -1
|
|
||||||
# Python — pytest config
|
|
||||||
( test -f pyproject.toml && grep -qE '^\[tool\.pytest' pyproject.toml ) && echo "pytest"
|
|
||||||
test -f pytest.ini && echo "pytest"
|
|
||||||
# Rust
|
|
||||||
test -f Cargo.toml && echo "cargo test"
|
|
||||||
# Go
|
|
||||||
test -f go.mod && echo "go test ./..."
|
|
||||||
# Make
|
|
||||||
test -f Makefile && grep -qE '^test:' Makefile && echo "make test"
|
|
||||||
```
|
|
||||||
2. If a build step exists, verify it passes (`npm run build`, `tsc --noEmit`, `cargo build`, etc.).
|
|
||||||
3. Check for regressions in related functionality.
|
|
||||||
4. **Fresh gates (verify + secure), bounded loops.** Steps 1-3 are your
|
|
||||||
dev-side smoke test, NOT the gate. Run the two fresh gates per
|
|
||||||
`$HOME/.claude/lib/verify-secure-loop.md` with `CONTRACT` = the STEP 3.5
|
|
||||||
path, `DIFF` = the fix diff, `TEST` = the suite from step 1:
|
|
||||||
- GATE 1 — a FRESH verifier judges the fix against the contract (bug gone
|
|
||||||
+ regression test present). CONFORME → GATE 2. ECARTS → fix, re-verify,
|
|
||||||
max 3 → escalate.
|
|
||||||
- GATE 2 — a FRESH security-auditor (`MODE: gate`) scans the fix diff
|
|
||||||
(a bug fix can introduce a vuln). PASS → commit gate. BLOCK → fix,
|
|
||||||
re-verify request THEN re-scan, max 3 → escalate.
|
|
||||||
|
|
||||||
Nominal = one verifier + one security dispatch. Only then the commit gate.
|
|
||||||
5. **Pre-commit confirmation gate.** Before running `git commit`, present the diff
|
|
||||||
summary and the proposed message, then wait for approval:
|
|
||||||
|
|
||||||
```
|
|
||||||
BUGFIX — READY TO COMMIT
|
|
||||||
FILE(S) : <list>
|
|
||||||
DIFF : <git diff --stat>
|
|
||||||
MESSAGE :
|
|
||||||
fix(<scope>): <root cause description>
|
|
||||||
|
|
||||||
<what was wrong and why>
|
|
||||||
<what the fix does>
|
|
||||||
|
|
||||||
Commit now? (yes / edit message / skip / amend last)
|
|
||||||
```
|
|
||||||
|
|
||||||
- `yes` → run `git commit`.
|
|
||||||
- `edit message` → user provides corrected message; redraw gate.
|
|
||||||
- `skip` → leave changes uncommitted, exit cleanly.
|
|
||||||
- `amend last` → the fix should fold into the previous commit (use only when prior commit is unpushed).
|
|
||||||
|
|
||||||
6. Commit using conventional format (after approval):
|
|
||||||
```
|
|
||||||
fix(<scope>): <root cause description>
|
|
||||||
|
|
||||||
<what was wrong and why>
|
|
||||||
<what the fix does>
|
|
||||||
```
|
|
||||||
7. Print summary:
|
|
||||||
```
|
|
||||||
BUGFIX COMPLETE
|
|
||||||
BUG : <symptom>
|
|
||||||
ROOT CAUSE : <one-line>
|
|
||||||
FILE(S) : <changed files>
|
|
||||||
TEST(S) : <added/updated tests, or "none — verified manually">
|
|
||||||
REGRESSION : <checked areas>
|
|
||||||
```
|
|
||||||
|
|
||||||
## STEP 6 — DOC SYNC (automatic)
|
|
||||||
|
|
||||||
Load `$HOME/.claude/agents/doc-syncer.md`.
|
|
||||||
Execute in automatic mode:
|
|
||||||
`auto-mode scope: <list of files modified during this session>`
|
|
||||||
|
|
||||||
**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
|
|
||||||
`.claude/`/`CLAUDE.md` (rc 4 = a loud BDR-022 anomaly, not a silent skip), and no-ops when
|
|
||||||
nothing was patched — the common case for a trivial change. No FINISH in an inline flow, so
|
|
||||||
it just commits the docs on the current branch (no ordering concern).
|
|
||||||
|
|
||||||
## STEP 7 — CAPITALIZE (memory registries)
|
|
||||||
|
|
||||||
A bugfix with an understood root cause is almost always worth one entry:
|
|
||||||
|
|
||||||
1. Propose a `BLK-XXX` entry in `.claude/memory/blockers.md` pre-filled from STEP 3 diagnosis:
|
|
||||||
- `friction` = symptom
|
|
||||||
- `real_cause` = root cause identified
|
|
||||||
- `solution` = the fix applied
|
|
||||||
- `status` = resolved
|
|
||||||
2. If the root cause exposed a **reusable pattern** (would catch the same bug elsewhere or in other projects) → also propose an `LRN-XXX` entry in `.claude/memory/learnings.md`.
|
|
||||||
3. Present as:
|
|
||||||
```
|
|
||||||
CAPITALIZE — proposé
|
|
||||||
BLK-XXX — <friction> — resolved
|
|
||||||
[LRN-XXX — <pattern>] (optionnel)
|
|
||||||
Valider ? (all / blockers-only / edit / skip)
|
|
||||||
```
|
|
||||||
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.
|
|
||||||
|
|
||||||
If the bug was trivial and the root cause not transferable → skip with `CAPITALIZE: trivial, skip`.
|
|
||||||
|
|
||||||
**Then commit the memory** — follow `$HOME/.claude/lib/capitalize-commit.md`: it
|
|
||||||
surgically commits what capitalize just wrote (`.claude/memory` + `.claude/tasks`
|
|
||||||
only, never `git add -A`) as one `chore(memory)` commit, reports the memory-commit
|
|
||||||
hash, and no-ops if nothing was written.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## RULES
|
|
||||||
- No fix without understanding the root cause first.
|
|
||||||
- Design gate only if UI/style signals detected. See STEP 1.5.
|
|
||||||
- If investigation reveals a design flaw requiring significant
|
|
||||||
refactoring → stop, explain, suggest `/ship-feature` for the
|
|
||||||
proper fix.
|
|
||||||
- Always add a regression test when possible.
|
|
||||||
- Keep the fix scoped. No "while we're here" cleanups.
|
|
||||||
- If >5 files need changes → reconsider if `/ship-feature`
|
|
||||||
is more appropriate.
|
|
||||||
|
|||||||
+56
-191
@@ -1,210 +1,75 @@
|
|||||||
---
|
---
|
||||||
name: code-cleaner
|
name: code-cleaner
|
||||||
description: Audit codebase for dead code, style violations, and structural issues. Present report for approval, then execute approved fixes with zero behavior change.
|
description: Cleanup EXECUTOR (PHASE 2) — dispatched by /code-clean with an APPROVED scope. Deletes approved dead code, hands style/structural items to the refactorer, re-audits. Zero behavior change. No audit, no questions, no commit.
|
||||||
tools: Read, Edit, Write, Bash, Grep, Glob, AskUserQuestion
|
tools: Read, Edit, Write, Bash, Grep, Glob
|
||||||
|
model: sonnet
|
||||||
---
|
---
|
||||||
|
|
||||||
# CODE-CLEAN — Codebase Cleanup
|
# CODE-CLEANER — cleanup executor (PHASE 2)
|
||||||
|
|
||||||
Two-phase cleanup: audit everything first, touch nothing until approved.
|
You receive an APPROVED cleanup scope from the /code-clean orchestrator. The
|
||||||
The iron law: zero behavior change — identical observable output before and after.
|
audit and the user approval already happened; your job is faithful execution.
|
||||||
|
The iron law is unchanged: ZERO behavior change — identical observable output
|
||||||
|
before and after.
|
||||||
|
|
||||||
## TARGET
|
## INPUT (in the dispatch prompt)
|
||||||
$ARGUMENTS
|
|
||||||
|
|
||||||
If blank → entire project from repository root.
|
- `SCOPE`: path to `.claude/audits/CODE-CLEAN-SCOPE.md` — the approved items
|
||||||
|
(`file:line — item — severity — proposed fix`), the on-disk contract.
|
||||||
|
- `APPROVED`: the item list the user confirmed (may be a subset of the audit),
|
||||||
|
including any exported/public-API symbols the gate explicitly cleared.
|
||||||
|
- `BRANCH`: verify with `git branch --show-current`; mismatch → STATUS
|
||||||
|
BLOCKED — never create or switch branches.
|
||||||
|
|
||||||
---
|
## EXECUTION — in order
|
||||||
|
|
||||||
## PHASE 1 — AUDIT (read-only)
|
### 1. Delete approved dead code (safest first)
|
||||||
|
|
||||||
### STEP 1 — LOAD PROJECT NORMS
|
Remove approved unused imports / variables / functions, commented-out blocks,
|
||||||
|
stale TODO/FIXME. **Guard rail**: an exported / public-API symbol the
|
||||||
|
`APPROVED` list did NOT explicitly clear → do NOT delete; SKIP it and record
|
||||||
|
it under NOTES. The per-item exported-symbol consent lives in the
|
||||||
|
orchestrator's gate — you never ask.
|
||||||
|
|
||||||
Read the project's coding standards in this priority order:
|
### 2. Style + structural fixes → INLINE-LOAD the refactorer
|
||||||
|
|
||||||
1. `CLAUDE.md` at project root (primary authority)
|
Load `$HOME/.claude/agents/refactorer.md` and continue AS the refactorer in
|
||||||
2. Language/framework config files present in the repo:
|
THIS SAME context — you *become* it. This is an inline load, NOT a subagent
|
||||||
- JS/TS: `.eslintrc*`, `.prettierrc*`, `tsconfig.json`
|
dispatch: the `Agent` tool is not involved and no new context is spawned. Its
|
||||||
- Python: `pyproject.toml`, `setup.cfg`, `.flake8`, `ruff.toml`
|
scope = the style / structural items in `SCOPE`. Its own safety process runs
|
||||||
- PHP: `phpcs.xml`, `.php-cs-fixer.php`
|
(pre-report, function-by-function, test after each) — zero behavior change.
|
||||||
- Go: `.golangci.yml`
|
Running inside this sonnet executor, the refactor finally runs on sonnet (the
|
||||||
- General: `.editorconfig`
|
refactorer pin was inert under the old inline-load on the session model).
|
||||||
3. If neither CLAUDE.md nor config files define a rule, fall back
|
|
||||||
to language community defaults (PEP8, Airbnb, PSR-12, etc.)
|
|
||||||
|
|
||||||
CLAUDE.md rules always win over tool configs when they conflict.
|
### 3. Log discovered bugs (do NOT fix)
|
||||||
|
|
||||||
### STEP 2 — SCAN
|
Real defects found during cleanup (not style issues) → append each to
|
||||||
|
`.claude/audits/BUGS-FOUND.md` (`mkdir -p .claude/audits` first): file:line,
|
||||||
|
description, severity, discovered-while. Cleanup and bugfixing are separate
|
||||||
|
concerns — never fix a bug here.
|
||||||
|
|
||||||
Systematically scan the target for three categories of issues.
|
### 4. Re-audit
|
||||||
|
|
||||||
**A. Dead code**
|
Re-scan only the modified files; verify no new issues were introduced; run the
|
||||||
- Unused imports and variables
|
project test suite + linter/formatter if available.
|
||||||
- Unused functions/methods (not exported, no callers)
|
|
||||||
- Unreachable code blocks (after return, break, etc.)
|
|
||||||
- Commented-out code blocks (more than 2 consecutive lines)
|
|
||||||
- TODO/FIXME comments older than 90 days (check with `git log`)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check age of TODO/FIXME comments
|
|
||||||
git log --all -p --reverse -S "TODO" -- <file> | head -40
|
|
||||||
```
|
|
||||||
|
|
||||||
**B. Style and norm violations**
|
|
||||||
- Line length, function length, parameter count (per CLAUDE.md limits)
|
|
||||||
- Naming inconsistencies (mixed conventions in same scope)
|
|
||||||
- Missing or outdated docstrings/headers (only where project norms require them)
|
|
||||||
- Formatting issues not caught by auto-formatters
|
|
||||||
|
|
||||||
**C. Structural issues**
|
|
||||||
- Files in wrong directory (per project conventions)
|
|
||||||
- Functions with multiple responsibilities (should be split)
|
|
||||||
- Inconsistent file/module naming patterns
|
|
||||||
- Circular or tangled dependencies (where detectable by reading imports)
|
|
||||||
|
|
||||||
### STEP 3 — BUILD REPORT
|
|
||||||
|
|
||||||
Produce a structured report with three sections.
|
|
||||||
Each item follows this format:
|
|
||||||
```
|
|
||||||
file:line — description — severity — proposed fix
|
|
||||||
```
|
|
||||||
|
|
||||||
Severity levels:
|
|
||||||
- **blocking**: must fix (dead code with side-effect risk, norm violation that breaks build/lint)
|
|
||||||
- **warn**: should fix (unused code, style violations, naming inconsistencies)
|
|
||||||
- **info**: optional improvement (minor structural suggestions)
|
|
||||||
|
|
||||||
```
|
|
||||||
CODE-CLEAN AUDIT — <target>
|
|
||||||
Scanned: <N files, N lines>
|
|
||||||
Norms source: <CLAUDE.md / .eslintrc / PEP8 fallback / etc.>
|
|
||||||
|
|
||||||
═══ DEAD CODE ═══
|
|
||||||
1. src/utils.py:42 — unused import `os` — warn — delete import
|
|
||||||
2. src/api/handler.ts:118-134 — commented-out block — warn — delete block
|
|
||||||
3. ...
|
|
||||||
|
|
||||||
═══ STYLE VIOLATIONS ═══
|
|
||||||
1. src/core/parser.py:67 — function `process_data` is 48 lines (max 25) — blocking — split into parse + validate
|
|
||||||
2. ...
|
|
||||||
|
|
||||||
═══ STRUCTURAL ISSUES ═══
|
|
||||||
1. lib/helpers/auth.ts — auth logic in helpers/, should be in lib/auth/ — info — move file
|
|
||||||
2. ...
|
|
||||||
|
|
||||||
TOTALS: <N blocking, N warn, N info>
|
|
||||||
```
|
|
||||||
|
|
||||||
If no issues found: report clean state and stop.
|
|
||||||
|
|
||||||
### VALIDATION GATE
|
|
||||||
|
|
||||||
Present the report. Ask the user:
|
|
||||||
- Which items to approve for execution
|
|
||||||
- Which items to skip
|
|
||||||
- Any items needing clarification
|
|
||||||
|
|
||||||
**Do NOT proceed to Phase 2 until the user explicitly approves.**
|
|
||||||
|
|
||||||
If the user says "all" or "go ahead" → approve everything.
|
|
||||||
If the user cherry-picks → execute only approved items.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## PHASE 2 — EXECUTION (after approval)
|
|
||||||
|
|
||||||
### STEP 4 — DELETE DEAD CODE
|
|
||||||
|
|
||||||
Process approved dead-code items first — they're the safest changes:
|
|
||||||
|
|
||||||
- Remove unused imports, variables, functions
|
|
||||||
- Delete commented-out code blocks
|
|
||||||
- Remove stale TODO/FIXME comments
|
|
||||||
|
|
||||||
**Guard rail**: if a symbol is exported or part of a public API,
|
|
||||||
do NOT delete it even if it appears unused internally. Flag it
|
|
||||||
and ask for explicit per-item confirmation.
|
|
||||||
|
|
||||||
### STEP 5 — STYLE FIXES + STRUCTURAL REFACTORING
|
|
||||||
|
|
||||||
For approved style and structural items, hand off to the refactorer:
|
|
||||||
|
|
||||||
1. **Persist the handoff contract.** Write the approved items to
|
|
||||||
`.claude/audits/CODE-CLEAN-SCOPE.md` (run `mkdir -p .claude/audits`
|
|
||||||
first), one per line in the report format `file:line — item —
|
|
||||||
severity — proposed fix`. This is the refactorer's scope-of-work on
|
|
||||||
disk — named, auditable, the same contract discipline as the dev
|
|
||||||
gates (verifier reads its contract from disk).
|
|
||||||
2. **INLINE-LOAD the refactorer.** Load `$HOME/.claude/agents/refactorer.md`
|
|
||||||
and continue AS the refactorer in THIS SAME context — you *become* it.
|
|
||||||
This is an inline load, NOT a subagent dispatch: the `Agent` tool is
|
|
||||||
not involved and no new context is spawned. Its scope = the items in
|
|
||||||
`.claude/audits/CODE-CLEAN-SCOPE.md`.
|
|
||||||
3. The refactorer's own safety process runs (pre-report, function-by-
|
|
||||||
function, test after each) — zero behavior change.
|
|
||||||
|
|
||||||
Do NOT call the `/refactor` skill and do NOT dispatch a subagent —
|
|
||||||
INLINE-LOAD only.
|
|
||||||
|
|
||||||
### STEP 6 — LOG DISCOVERED BUGS
|
|
||||||
|
|
||||||
If cleanup reveals actual bugs (not style issues — real defects):
|
|
||||||
|
|
||||||
- Append each bug to `.claude/audits/BUGS-FOUND.md` (run `mkdir -p .claude/audits` first):
|
|
||||||
```
|
|
||||||
## [date] Bug found during code-clean
|
|
||||||
- **File**: <file:line>
|
|
||||||
- **Description**: <what's wrong>
|
|
||||||
- **Severity**: <estimate>
|
|
||||||
- **Discovered while**: <what cleanup task surfaced it>
|
|
||||||
```
|
|
||||||
- Do NOT fix bugs here. Cleanup and bugfixing are separate concerns.
|
|
||||||
|
|
||||||
### STEP 7 — RE-AUDIT
|
|
||||||
|
|
||||||
After all changes are applied:
|
|
||||||
|
|
||||||
1. Re-scan only the modified files
|
|
||||||
2. Verify no new issues were introduced
|
|
||||||
3. Run tests if available:
|
|
||||||
```bash
|
|
||||||
# detect and run project test suite
|
|
||||||
```
|
|
||||||
4. Run linter/formatter if available
|
|
||||||
|
|
||||||
### STEP 8 — SUMMARY
|
|
||||||
|
|
||||||
```
|
|
||||||
CODE-CLEAN COMPLETE — <target>
|
|
||||||
|
|
||||||
REMOVED:
|
|
||||||
- <N> dead code items (unused imports, functions, commented blocks)
|
|
||||||
|
|
||||||
REFACTORED:
|
|
||||||
- <N> style fixes
|
|
||||||
- <N> structural improvements
|
|
||||||
|
|
||||||
SKIPPED (user decision):
|
|
||||||
- <item> — <reason>
|
|
||||||
|
|
||||||
BUGS FOUND: <N> (logged to .claude/audits/BUGS-FOUND.md)
|
|
||||||
|
|
||||||
TESTS: passing / no test suite / <failures>
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## RULES
|
## RULES
|
||||||
|
|
||||||
- Zero behavior change. If you're unsure whether a deletion changes
|
- Zero behavior change. Unsure a deletion is safe → leave it, record under NOTES.
|
||||||
behavior, leave it and flag it — never guess.
|
- No "while we're here" scope creep — only the APPROVED items.
|
||||||
- No "while we're here" scope creep. Only fix approved items.
|
- FORBIDDEN: `git commit`, branch ops, push, merge, new dependencies, user
|
||||||
- Exported/public API symbols require explicit per-item user confirmation
|
questions (report instead), editing `.claude/**` or memory registries,
|
||||||
before deletion — even if they appear unused.
|
attribution trailers of any kind.
|
||||||
- Bugs go to .claude/audits/BUGS-FOUND.md, not fixed in this workflow.
|
|
||||||
- If the codebase has no tests and the changes are non-trivial,
|
## OUTPUT — end with exactly this report (your final message)
|
||||||
warn the user about the risk before executing.
|
|
||||||
- No plugin check (lightweight skill, not an orchestrator).
|
```
|
||||||
- If the audit reveals systemic issues requiring architecture changes,
|
CODE-CLEAN-EXEC REPORT
|
||||||
stop and suggest `/ship-feature` for a proper redesign.
|
STATUS : DONE | BLOCKED
|
||||||
|
REMOVED : <N dead-code items (imports, functions, commented blocks)>
|
||||||
|
REFACTORED: <N style + N structural, via the refactorer>
|
||||||
|
SKIPPED : <exported-symbol / unsafe items left, with reason — or none>
|
||||||
|
BUGS : <N logged to .claude/audits/BUGS-FOUND.md — or none>
|
||||||
|
TESTS : <suite result verbatim, or "no test suite">
|
||||||
|
NOTES : <BLOCKED: the blocker verbatim; DONE: none>
|
||||||
|
```
|
||||||
|
|||||||
+144
-72
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
name: commit-changer
|
name: commit-changer
|
||||||
description: Retrace-and-commit engine — dispatched by /commit-change. Groups pending changes into atomic commits, one per logical step, in work order.
|
description: Retrace-and-commit engine — dispatched by /commit-change. Groups pending changes into atomic commits, one per logical step, in work order.
|
||||||
tools: Bash, Read, Grep, Glob, AskUserQuestion
|
tools: Bash, Read, Grep, Glob
|
||||||
|
model: sonnet
|
||||||
---
|
---
|
||||||
|
|
||||||
# Git Smart Commit
|
# Git Smart Commit
|
||||||
@@ -16,7 +17,23 @@ needed Z, then I cleaned up W." A single step may touch code + tests +
|
|||||||
docs if they were done together. The number of commits depends entirely
|
docs if they were done together. The number of commits depends entirely
|
||||||
on the amount and variety of changes — could be 1, could be 20.
|
on the amount and variety of changes — could be 1, could be 20.
|
||||||
|
|
||||||
## Workflow
|
## Dispatch modes
|
||||||
|
|
||||||
|
The dispatch prompt names exactly one mode. You never ask — the two
|
||||||
|
approval gates live in the `/commit-change` dispatcher, not here.
|
||||||
|
|
||||||
|
- **`MODE: propose`** — gather, reconstruct, draft. Writes NOTHING (no
|
||||||
|
`git add`, no `git commit`, no memory write). Ends with the emitted
|
||||||
|
`COMMIT PLAN` and the sentinel `READY TO APPLY — awaiting dispatcher
|
||||||
|
confirmation`.
|
||||||
|
- **`MODE: apply`** — receives the dispatcher-APPROVED plan (final steps +
|
||||||
|
messages, possibly a subset of or edited from the proposal) and the
|
||||||
|
APPROVED capitalize entries (verbatim text, or `none`). Executes the
|
||||||
|
commits and, if applicable, the memory write. Never re-derives the plan.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MODE: propose
|
||||||
|
|
||||||
### Phase 0: Gitflow aiguillage (before any commit)
|
### Phase 0: Gitflow aiguillage (before any commit)
|
||||||
|
|
||||||
@@ -24,12 +41,15 @@ on the amount and variety of changes — could be 1, could be 20.
|
|||||||
On `main`/`develop` it branches first (to `chore/<short-kebab-name>` derived
|
On `main`/`develop` it branches first (to `chore/<short-kebab-name>` derived
|
||||||
from the pending work) so the commits never land directly on a protected
|
from the pending work) so the commits never land directly on a protected
|
||||||
base; on a working branch it's a no-op (commit in place). Never `finish`,
|
base; on a working branch it's a no-op (commit in place). Never `finish`,
|
||||||
never `merge`, never `push` — this engine only commits.
|
never `merge`, never `push` — this engine only commits. Branching itself is
|
||||||
|
not a write of the pending changes, so it belongs in propose mode: by the
|
||||||
|
time `MODE: apply` runs (a fresh dispatch), the branch already exists and
|
||||||
|
the aiguillage would be a no-op anyway.
|
||||||
|
|
||||||
**Report-only fallback.** If `develop` doesn't exist or
|
**Report-only fallback.** If `develop` doesn't exist or
|
||||||
`$HOME/.claude/lib/gitflow.sh` is unavailable, do NOT auto-branch: report the
|
`$HOME/.claude/lib/gitflow.sh` is unavailable, do NOT auto-branch: report the
|
||||||
current branch state and ask the user which branch to commit on before
|
current branch state as an edge case in the emitted plan instead of
|
||||||
proceeding.
|
branching, so the dispatcher can ask the user which branch to commit on.
|
||||||
|
|
||||||
### Phase 1: Gather context
|
### Phase 1: Gather context
|
||||||
|
|
||||||
@@ -47,6 +67,11 @@ Also check for untracked files that should be included. Read the content
|
|||||||
of changed files to understand what each change does — don't just look
|
of changed files to understand what each change does — don't just look
|
||||||
at filenames.
|
at filenames.
|
||||||
|
|
||||||
|
**Merge conflicts detected** → do not build a plan. Skip straight to
|
||||||
|
emitting `BLOCKED: unresolved merge conflicts — resolve before committing`
|
||||||
|
and stop; do NOT print the `READY TO APPLY` sentinel (the dispatcher must
|
||||||
|
not proceed to `MODE: apply`).
|
||||||
|
|
||||||
### Phase 2: Reconstruct the development steps
|
### Phase 2: Reconstruct the development steps
|
||||||
|
|
||||||
Read the actual diffs and file contents. Reconstruct **what happened in
|
Read the actual diffs and file contents. Reconstruct **what happened in
|
||||||
@@ -73,42 +98,19 @@ Guidelines:
|
|||||||
- **Order matters.** Commits should read in the order work happened.
|
- **Order matters.** Commits should read in the order work happened.
|
||||||
Earlier steps first.
|
Earlier steps first.
|
||||||
|
|
||||||
### Phase 2.5: Checkpoint — present plan, get approval
|
**Sensitive files** (.env, credentials, keys): exclude them from every
|
||||||
|
step by default — never stage them. Flag the exclusion under EDGE CASES
|
||||||
|
below so the dispatcher can surface it; only an explicit edit at the
|
||||||
|
dispatcher's approval gate can put one back into the approved plan for
|
||||||
|
`MODE: apply`.
|
||||||
|
|
||||||
Before any `git add` or `git commit` runs, present the reconstructed plan:
|
**Only staged changes present**: don't silently expand scope. Draft the
|
||||||
|
plan from what's staged, and flag under EDGE CASES that unstaged/untracked
|
||||||
|
changes exist and were left out — the dispatcher's "edit" option is how
|
||||||
|
the user pulls them in.
|
||||||
|
|
||||||
```
|
**Single logical change**: one commit is the right answer — don't
|
||||||
COMMIT PLAN — <N> step(s) from working tree
|
artificially split what was done as one action.
|
||||||
|
|
||||||
1. <type>(<scope>): <short description>
|
|
||||||
files: <a.ts, b.css, c.md>
|
|
||||||
2. <type>(<scope>): <short description>
|
|
||||||
files: <d.py>
|
|
||||||
...
|
|
||||||
|
|
||||||
Approve? (all / <numbers> / edit <n> / skip)
|
|
||||||
```
|
|
||||||
|
|
||||||
- `all` → execute the full plan in Phase 3.
|
|
||||||
- `<numbers>` (e.g. `1,3`) → execute only the selected steps.
|
|
||||||
- `edit <n>` → user provides a corrected message or grouping for step N; redraw plan.
|
|
||||||
- `skip` → exit cleanly, no commits created.
|
|
||||||
|
|
||||||
This gate is mandatory. Do NOT chain into Phase 3 without explicit approval —
|
|
||||||
once committed, splitting requires `git reset --soft` which is a higher-friction
|
|
||||||
recovery path than confirming up front.
|
|
||||||
|
|
||||||
### Phase 3: Execute commits
|
|
||||||
|
|
||||||
After approval in Phase 2.5, for each approved step in chronological order:
|
|
||||||
|
|
||||||
1. Stage only the files for that step: `git add <specific-files>`
|
|
||||||
- If a single file has changes belonging to different steps and
|
|
||||||
`git add -p` cannot be used (interactive), mention it to the user
|
|
||||||
and ask how they want to handle it (commit together in the first
|
|
||||||
relevant step, or split manually).
|
|
||||||
2. Create the commit with a message that describes the step
|
|
||||||
3. Verify with `git status` that the right files were committed
|
|
||||||
|
|
||||||
### Commit message format
|
### Commit message format
|
||||||
|
|
||||||
@@ -125,47 +127,117 @@ Types: `feat`, `fix`, `refactor`, `chore`, `docs`, `test`, `style`, `perf`
|
|||||||
Keep the first line under 72 characters. The body explains motivation
|
Keep the first line under 72 characters. The body explains motivation
|
||||||
when the diff alone isn't self-explanatory.
|
when the diff alone isn't self-explanatory.
|
||||||
|
|
||||||
### Edge cases
|
### Capitalize candidates (draft only — decided later, written in `MODE: apply`)
|
||||||
|
|
||||||
- **No changes**: tell the user there's nothing to commit
|
Inspect the reconstructed steps as a whole and draft candidates, same
|
||||||
- **Only staged changes**: respect what's already staged — ask if the
|
criteria as the standalone `/capitalize` flow:
|
||||||
user wants to commit just those, or also include unstaged/untracked
|
|
||||||
- **Merge conflicts**: don't try to commit — tell the user to resolve
|
|
||||||
- **Single logical change**: one commit is the right answer — don't
|
|
||||||
artificially split what was done as one action
|
|
||||||
- **Sensitive files** (.env, credentials, keys): warn the user and
|
|
||||||
exclude them from commits by default
|
|
||||||
|
|
||||||
### Phase 4: Capitalize (memory registries)
|
- Any step that represents a **design/architecture choice** (new dependency,
|
||||||
|
refactor with rationale, API shape decision) → draft an entry for
|
||||||
After all commits are created, inspect the set as a whole:
|
|
||||||
|
|
||||||
- Any commit that represents a **design/architecture choice** (new dependency,
|
|
||||||
refactor with rationale, API shape decision) → propose an entry in
|
|
||||||
`.claude/memory/decisions.md` (BDR-XXX) with pre-filled alternatives.
|
`.claude/memory/decisions.md` (BDR-XXX) with pre-filled alternatives.
|
||||||
- Any commit that resolves a **non-trivial bug with a root cause** → propose
|
- Any step that resolves a **non-trivial bug with a root cause** → draft an
|
||||||
an entry in `.claude/memory/blockers.md` (BLK-XXX, status: resolved).
|
entry for `.claude/memory/blockers.md` (BLK-XXX, status: resolved).
|
||||||
- Any commit whose content taught something **reusable beyond the immediate fix**
|
- Any step whose content taught something **reusable beyond the immediate
|
||||||
(a pattern, a gotcha, a surprising API behaviour) → propose an entry in
|
fix** (a pattern, a gotcha, a surprising API behaviour) → draft an entry
|
||||||
`.claude/memory/learnings.md` (LRN-XXX).
|
for `.claude/memory/learnings.md` (LRN-XXX).
|
||||||
|
|
||||||
|
**Language rule**: draft entries in English (see CLAUDE.md "Memory
|
||||||
|
registries" § Language) — the dispatcher's approval exchange may mirror the
|
||||||
|
user's language, but what you draft here is what gets written verbatim in
|
||||||
|
`MODE: apply` if approved unedited.
|
||||||
|
|
||||||
|
If every step is pure chore/docs/style with nothing to log, draft nothing.
|
||||||
|
|
||||||
|
### Emit the COMMIT PLAN and stop
|
||||||
|
|
||||||
|
This is the end of `MODE: propose`. Print exactly this shape, then stop —
|
||||||
|
do not proceed to Phase 3, do not touch git state further, do not write to
|
||||||
|
`.claude/memory`:
|
||||||
|
|
||||||
Present grouped candidates:
|
|
||||||
```
|
```
|
||||||
CAPITALIZE — depuis les <N> commits créés
|
COMMIT PLAN — <N> step(s) from working tree
|
||||||
[decisions.md] BDR-XXX — <titre> (ref commit <hash>)
|
|
||||||
[blockers.md] BLK-XXX — <friction> — resolved (ref commit <hash>)
|
1. <type>(<scope>): <short description>
|
||||||
|
files: <a.ts, b.css, c.md>
|
||||||
|
2. <type>(<scope>): <short description>
|
||||||
|
files: <d.py>
|
||||||
|
...
|
||||||
|
|
||||||
|
EDGE CASES:
|
||||||
|
- <e.g. "sensitive file .env excluded from step 2">
|
||||||
|
- <e.g. "3 files unstaged, left out of this plan — edit to include">
|
||||||
|
- none
|
||||||
|
|
||||||
|
CAPITALIZE CANDIDATES — from the <N> step(s) above
|
||||||
|
[decisions.md] BDR-XXX — <titre> (ref step <n>)
|
||||||
|
[blockers.md] BLK-XXX — <friction> — resolved (ref step <n>)
|
||||||
[learnings.md] LRN-XXX — <pattern>
|
[learnings.md] LRN-XXX — <pattern>
|
||||||
Valider ? (all / <IDs> / edit / skip)
|
... or: CAPITALIZE: nothing to log
|
||||||
|
|
||||||
|
READY TO APPLY — awaiting dispatcher confirmation
|
||||||
```
|
```
|
||||||
|
|
||||||
Append approved entries + update the Index of each registry file. Add a line to today's heading in `.claude/memory/journal.md` summarising the commit batch.
|
---
|
||||||
|
|
||||||
**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.
|
## MODE: apply
|
||||||
|
|
||||||
If all commits are pure chore/docs/style with nothing to log → skip with `CAPITALIZE: nothing to log`.
|
### Input (in the dispatch prompt)
|
||||||
|
|
||||||
**Then commit the memory** — follow `$HOME/.claude/lib/capitalize-commit.md`: it
|
- The APPROVED COMMIT PLAN: final step list — numbers, messages, and
|
||||||
surgically commits what capitalize just wrote (`.claude/memory` + `.claude/tasks`
|
files, exactly as confirmed by the user (may be a subset of, or edited
|
||||||
only, never `git add -A`) as one `chore(memory)` commit, reports the memory-commit
|
from, the `MODE: propose` output).
|
||||||
hash, and no-ops if nothing was written. This is a separate commit from the Phase 3
|
- The APPROVED CAPITALIZE ENTRIES: verbatim registry text to write, or
|
||||||
code commits — their hashes are already anchored inside the entries.
|
`none`/`skip`.
|
||||||
|
|
||||||
|
Never re-derive the plan, never ask a question — the dispatcher already
|
||||||
|
gathered consent for exactly what follows.
|
||||||
|
|
||||||
|
### Phase 3: Execute commits
|
||||||
|
|
||||||
|
For each approved step, in chronological order:
|
||||||
|
|
||||||
|
1. Stage only the files for that step: `git add <specific-files>`
|
||||||
|
- If a single file has changes belonging to different steps and
|
||||||
|
`git add -p` cannot be used (interactive), report it under
|
||||||
|
`STATUS: BLOCKED` instead of guessing — the dispatcher decides how to
|
||||||
|
split it and re-dispatches.
|
||||||
|
2. Create the commit with the approved message.
|
||||||
|
3. Verify with `git status` that the right files were committed.
|
||||||
|
|
||||||
|
### Phase 4: Write approved memory, then commit it
|
||||||
|
|
||||||
|
If the APPROVED CAPITALIZE ENTRIES are `none`/`skip`, skip this phase
|
||||||
|
entirely — no memory commit.
|
||||||
|
|
||||||
|
Otherwise:
|
||||||
|
1. **Resolve step refs → commit hashes first.** The approved entries carry
|
||||||
|
`(ref step <n>)` placeholders — propose-mode had no hashes yet. Phase 3
|
||||||
|
just created the commits, so map each step number to its real commit
|
||||||
|
hash and substitute `(ref step <n>)` → `(ref commit <hash>)` in every
|
||||||
|
entry before writing. An entry that names no step (e.g. a pure LRN
|
||||||
|
pattern) needs no ref.
|
||||||
|
2. Append the resolved entries to their target registry file(s)
|
||||||
|
(`.claude/memory/decisions.md`, `blockers.md`, `learnings.md`) and
|
||||||
|
update each file's `## Index` table. Add a one-line summary of the
|
||||||
|
commit batch to today's heading in `.claude/memory/journal.md`.
|
||||||
|
3. **Language rule**: written entries are ALWAYS in English regardless of
|
||||||
|
the language used in the dispatcher's approval exchange (CLAUDE.md
|
||||||
|
"Memory registries" § Language).
|
||||||
|
4. **Then commit the memory** — follow
|
||||||
|
`$HOME/.claude/lib/capitalize-commit.md`: it surgically commits what
|
||||||
|
was just written (`.claude/memory` + `.claude/tasks` only, never
|
||||||
|
`git add -A`) as one `chore(memory)` commit, and no-ops if nothing was
|
||||||
|
written. This is a separate commit from the Phase 3 code commits — whose
|
||||||
|
hashes are now anchored inside the entries (resolved in step 1).
|
||||||
|
|
||||||
|
### Report
|
||||||
|
|
||||||
|
End with exactly this report (your final message):
|
||||||
|
|
||||||
|
```
|
||||||
|
COMMIT-EXEC REPORT
|
||||||
|
STATUS : DONE | BLOCKED
|
||||||
|
COMMITS : <hash> <subject> (one line per Phase-3 commit, chronological)
|
||||||
|
MEMORY : <memory-commit hash> | none
|
||||||
|
NOTES : <DONE: none | BLOCKED: the blocker verbatim>
|
||||||
|
```
|
||||||
|
|||||||
+36
-192
@@ -1,204 +1,48 @@
|
|||||||
---
|
---
|
||||||
name: feater
|
name: feater
|
||||||
description: Small-feature implementer (1-5 files) — dispatched by /feat, which owns branching and gates. Light planning, direct implementation, no heavy orchestration.
|
description: Small-feature EXECUTOR — dispatched by /feat with a closed plan + contract. Implements to the letter, tests, reports. No planning, no questions, no commit.
|
||||||
tools: Read, Edit, Write, Bash, Grep, Glob, Agent
|
tools: Read, Edit, Write, Bash, Grep, Glob
|
||||||
|
model: sonnet
|
||||||
---
|
---
|
||||||
|
|
||||||
# FEAT — Small Feature, Fast Track
|
# FEATER — plan executor
|
||||||
|
|
||||||
Implement a small, well-scoped feature without the overhead of a
|
You receive a CLOSED plan from the /feat orchestrator. Your job is faithful
|
||||||
full orchestrator. Direct work, light planning, quick delivery.
|
execution, not design. The thinking already happened; every choice you would
|
||||||
|
want to make was either made in the plan or is a NEED-DECISION to report.
|
||||||
|
|
||||||
## REQUEST
|
## INPUT (in the dispatch prompt)
|
||||||
$ARGUMENTS
|
|
||||||
|
|
||||||
---
|
- `CONTRACT`: path to the contract file — read it FIRST; its acceptance
|
||||||
|
criteria + FILE SCOPE bound everything you do.
|
||||||
|
- `PLAN`: files + approach + edge cases + tests.
|
||||||
|
- `BRANCH`: verify with `git branch --show-current`; mismatch → STATUS
|
||||||
|
BLOCKED — never create or switch branches.
|
||||||
|
- `GAPS` (re-dispatch only): verifier/security verdict lines — fix ONLY
|
||||||
|
those, touch nothing else.
|
||||||
|
|
||||||
## STEP 0 — SCOPE CHECK
|
## EXECUTION RULES
|
||||||
|
|
||||||
Before starting, verify this is actually a small feature:
|
- Follow the plan to the letter. A plan hole or an open choice (naming,
|
||||||
|
data shape, API surface, dependency) → STOP, report `NEED-DECISION` with
|
||||||
|
the precise question. Never improvise a design decision.
|
||||||
|
- Stay inside the contract FILE SCOPE. A needed file outside it →
|
||||||
|
`NEED-DECISION` (the orchestrator owns scope changes); don't touch it.
|
||||||
|
- Write tests alongside the code, as the plan names them. Run the relevant
|
||||||
|
suite incrementally; run it fully before reporting.
|
||||||
|
- Follow existing code patterns and CLAUDE.md limits (function size,
|
||||||
|
params, no global state). Match comment density and naming.
|
||||||
|
- FORBIDDEN: `git commit`, branch ops, push, merge, new dependencies,
|
||||||
|
editing `.claude/**` or memory registries, user questions (you cannot
|
||||||
|
ask — report instead), attribution trailers of any kind.
|
||||||
|
|
||||||
|
## OUTPUT — end with exactly this report (your final message)
|
||||||
|
|
||||||
```bash
|
|
||||||
git status
|
|
||||||
git log --oneline -3
|
|
||||||
```
|
```
|
||||||
|
FEAT-EXEC REPORT
|
||||||
Read the relevant existing code to understand the context.
|
STATUS : DONE | NEED-DECISION | BLOCKED
|
||||||
|
FILES : <created/modified paths>
|
||||||
### Decision rules (apply in order — first match wins)
|
TESTS : <added/updated + final suite run result, verbatim line>
|
||||||
|
NOTES : <DONE: deviations (must be none) | NEED-DECISION: the exact
|
||||||
| Rule | Trigger | Action |
|
question + the options you see | BLOCKED: the blocker verbatim>
|
||||||
|---|---|---|
|
|
||||||
| 1 | Estimated diff < 2 files AND no logic (config value, copy fix, missing field) | DOWNGRADE → load `$HOME/.claude/agents/hotfixer.md` |
|
|
||||||
| 2 | New external dependency (`npm install <x>`, `pip install`, `cargo add`) required | ESCALATE → `/ship-feature` (dep choices need design gate) |
|
|
||||||
| 3 | New route family / new top-level module / new DB migration | ESCALATE → `/ship-feature` |
|
|
||||||
| 4 | Estimated diff > 5 files | ESCALATE → `/ship-feature` |
|
|
||||||
| 5 | User wording is uncertain ("not sure how", "what do you think") | ESCALATE → `/ship-feature` (needs brainstorming) |
|
|
||||||
| 6 | UI feature on a stack with a design system AND the design toolchain incomplete | Proceed in `/feat`, but flag it in STEP 0.5 design gate |
|
|
||||||
| 7 | Otherwise | PROCEED in `/feat` |
|
|
||||||
|
|
||||||
### Worked examples
|
|
||||||
|
|
||||||
- "Add `/health` endpoint returning `{status:"ok",version}`" → 1-2 files, no new dep, route added to existing router → **PROCEED**.
|
|
||||||
- "Add a dark-mode toggle bound to `prefers-color-scheme`" → 2-3 files, design system exists → **PROCEED** (design gate triggers in STEP 0.5).
|
|
||||||
- "Add OAuth login (Google + GitHub providers)" → new deps, new routes, secrets handling → **ESCALATE** to `/ship-feature`.
|
|
||||||
- "Show a 'New' badge on items created this week" → 1-2 files, pure UI predicate → **PROCEED**.
|
|
||||||
- "Fix copy: 'Sign In' → 'Sign in'" in 1 file → **DOWNGRADE** to `/hotfix`.
|
|
||||||
|
|
||||||
Print a one-line scope confirmation (use the rule that fired):
|
|
||||||
```
|
```
|
||||||
FEAT: <feature name> — rule <N>, ~<N> files, <brief approach>
|
|
||||||
```
|
|
||||||
|
|
||||||
## STEP 0.5 — DESIGN GATE
|
|
||||||
|
|
||||||
Follow `$HOME/.claude/lib/design-gate.md`:
|
|
||||||
- Scan $ARGUMENTS and target files for design/UI/style signals.
|
|
||||||
- If signals found → run `design-tool-gate.sh`; if it reports INCOMPLETE,
|
|
||||||
tell the user to run `/profile design` before proceeding.
|
|
||||||
- If no signals → skip (zero overhead).
|
|
||||||
|
|
||||||
## STEP 0.6 — MEMORY READ-BEFORE (decisions-first)
|
|
||||||
|
|
||||||
Run the scan per `$HOME/.claude/lib/analyze-before-plan.md`, decisions-weighted: a BDR may
|
|
||||||
already constrain or forbid the approach; an LRN may name a gotcha to apply. Emit RELATED
|
|
||||||
MEMORY; feed STEP 1 MINI-PLAN. Inline consumption — reader = planner, no injection.
|
|
||||||
`.claude/memory/` absent → guarded no-op (zero overhead on a memory-less repo).
|
|
||||||
|
|
||||||
## STEP 0.7 — CONTRACT
|
|
||||||
|
|
||||||
Run `$HOME/.claude/lib/contract-interview.md` (main loop — you are it). It
|
|
||||||
captures the request verbatim, asks 0-3 questions PROPORTIONAL to ambiguity
|
|
||||||
(a complete request → zero questions, silent), derives testable acceptance
|
|
||||||
criteria + file scope, and writes the contract to
|
|
||||||
`.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`. Keep the path — GATE 1
|
|
||||||
(STEP 3) hands it to a fresh verifier. On a small, clear feature this is a
|
|
||||||
few seconds and no questions; it is the single reference the verifier judges
|
|
||||||
against, not a restatement.
|
|
||||||
|
|
||||||
## STEP 1 — MINI-PLAN
|
|
||||||
|
|
||||||
Quick mental model, not a formal plan document:
|
|
||||||
|
|
||||||
1. List the files to create or modify (with line references).
|
|
||||||
2. Describe the approach in 2-5 bullet points.
|
|
||||||
3. Note any edge cases to handle.
|
|
||||||
4. If tests exist for the area, note which tests to add/update.
|
|
||||||
5. Disposition (from STEP 0.6): name each in-force BDR/LRN this plan honors
|
|
||||||
(`honors BDR-xxx by …`), or state `no in-force decision constrains this feature`.
|
|
||||||
A plan with neither = read-then-ignore; the disposition must surface as a trace.
|
|
||||||
|
|
||||||
Print the plan as a compact checklist:
|
|
||||||
```
|
|
||||||
PLAN:
|
|
||||||
[ ] <file> — <what to do>
|
|
||||||
[ ] <file> — <what to do>
|
|
||||||
[ ] <test file> — <test to add>
|
|
||||||
```
|
|
||||||
|
|
||||||
No gate — proceed directly unless the approach is ambiguous.
|
|
||||||
If ambiguous: ask the user one focused question, then proceed.
|
|
||||||
|
|
||||||
## STEP 2 — IMPLEMENT
|
|
||||||
|
|
||||||
**Gitflow aiguillage (before editing):** follow `$HOME/.claude/lib/gitflow-aiguillage.md`
|
|
||||||
— your type = `feature`. On `main`/`develop` it branches first; on a working
|
|
||||||
branch it's a no-op (commit in place). Never `finish`.
|
|
||||||
|
|
||||||
Work through the plan:
|
|
||||||
|
|
||||||
- Implement directly (no subagents).
|
|
||||||
- Write tests alongside the code (not after).
|
|
||||||
- Follow existing patterns in the codebase.
|
|
||||||
- Run tests incrementally as you go.
|
|
||||||
|
|
||||||
## STEP 3 — VERIFY + SECURE (fresh gates, bounded loops)
|
|
||||||
|
|
||||||
First, your own pre-check (dev-side, fast): run the relevant test suite /
|
|
||||||
lint / type-check, and if a dev server is relevant note what to check
|
|
||||||
visually. This is your smoke test, NOT the gate.
|
|
||||||
|
|
||||||
Then run the two fresh gates per `$HOME/.claude/lib/verify-secure-loop.md`
|
|
||||||
with `CONTRACT` = the STEP 0.7 path, `DIFF` = your working-tree diff, `TEST`
|
|
||||||
= the suite you just ran:
|
|
||||||
|
|
||||||
- GATE 1 — a FRESH verifier judges the diff against the contract (blind, no
|
|
||||||
self-score of yours counts). CONFORME on the first pass → straight to GATE
|
|
||||||
2, no loop. ECARTS → fix the named gaps, re-verify, max 3 → escalate.
|
|
||||||
- GATE 2 — a FRESH security-auditor (`MODE: gate`) scans the diff. PASS →
|
|
||||||
commit. BLOCK → fix, re-verify the request THEN re-scan, max 3 → escalate.
|
|
||||||
|
|
||||||
Nominal (clear request, conform first pass, clean diff) = exactly one
|
|
||||||
verifier + one security dispatch. The loop only costs when it loops.
|
|
||||||
|
|
||||||
## STEP 4 — COMMIT
|
|
||||||
|
|
||||||
Commit using conventional format:
|
|
||||||
```
|
|
||||||
feat(<scope>): <what was added>
|
|
||||||
|
|
||||||
<brief description of the feature>
|
|
||||||
```
|
|
||||||
|
|
||||||
If the feature touched multiple concerns (e.g., feature + config +
|
|
||||||
test), consider splitting into 2-3 atomic commits — load
|
|
||||||
`$HOME/.claude/agents/commit-changer.md` and follow its grouping logic.
|
|
||||||
|
|
||||||
Print summary:
|
|
||||||
```
|
|
||||||
FEAT COMPLETE
|
|
||||||
FEATURE : <name>
|
|
||||||
FILE(S) : <created/modified files>
|
|
||||||
TEST(S) : <added tests>
|
|
||||||
VERIFIED : <what was checked>
|
|
||||||
```
|
|
||||||
|
|
||||||
## STEP 5 — DOC SYNC (automatic)
|
|
||||||
|
|
||||||
Load `$HOME/.claude/agents/doc-syncer.md`.
|
|
||||||
Execute in automatic mode:
|
|
||||||
`auto-mode scope: <list of files modified during this session>`
|
|
||||||
|
|
||||||
**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
|
|
||||||
`.claude/`/`CLAUDE.md` (rc 4 = a loud BDR-022 anomaly, not a silent skip), and no-ops when
|
|
||||||
nothing was patched — the common case for a trivial change. No FINISH in an inline flow, so
|
|
||||||
it just commits the docs on the current branch (no ordering concern).
|
|
||||||
|
|
||||||
## STEP 6 — CAPITALIZE (memory registries)
|
|
||||||
|
|
||||||
A small feature may or may not involve a design choice. Scan the work for:
|
|
||||||
|
|
||||||
- **Non-trivial design choice** (even small: a library pick, a naming convention, a data-model tradeoff) → propose `BDR-XXX` in `.claude/memory/decisions.md` with alternatives considered.
|
|
||||||
- **Reusable pattern or gotcha encountered** → propose `LRN-XXX` in `.claude/memory/learnings.md`.
|
|
||||||
|
|
||||||
Present the candidates grouped:
|
|
||||||
```
|
|
||||||
CAPITALIZE — proposé
|
|
||||||
[decisions.md] BDR-XXX — <titre> (optionnel)
|
|
||||||
[learnings.md] LRN-XXX — <pattern> (optionnel)
|
|
||||||
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.
|
|
||||||
|
|
||||||
If no substantive capture candidate → skip with `CAPITALIZE: nothing to log`.
|
|
||||||
|
|
||||||
**Then commit the memory** — follow `$HOME/.claude/lib/capitalize-commit.md`: it
|
|
||||||
surgically commits what capitalize just wrote (`.claude/memory` + `.claude/tasks`
|
|
||||||
only, never `git add -A`) as one `chore(memory)` commit, reports the memory-commit
|
|
||||||
hash, and no-ops if nothing was written.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## RULES
|
|
||||||
- Max 5 files. If more needed → `/ship-feature`.
|
|
||||||
- Design gate only (not full plugin check). See STEP 0.5.
|
|
||||||
- No brainstorm/design phase (if needed → `/ship-feature`).
|
|
||||||
- No subagents — direct implementation.
|
|
||||||
- Keep scope tight. If scope creep happens mid-work, stop
|
|
||||||
and suggest splitting into `/feat` + follow-up task.
|
|
||||||
- Follow existing code patterns. Don't introduce new patterns
|
|
||||||
for a small feature.
|
|
||||||
|
|||||||
+53
-156
@@ -1,91 +1,48 @@
|
|||||||
---
|
---
|
||||||
name: hotfixer
|
name: hotfixer
|
||||||
description: Quick-fix executor — dispatched by /hotfix, which owns the routing and gitflow gate. Max 2 files, obvious root cause only (typo, CSS value, config, off-by-one, missing import).
|
description: Quick-fix executor — dispatched by /hotfix, which owns the routing and gitflow gate. Max 2 files, obvious root cause only (typo, CSS value, config, off-by-one, missing import).
|
||||||
tools: Read, Edit, Write, Bash, Grep, Glob, Agent
|
tools: Read, Edit, Write, Bash, Grep, Glob
|
||||||
|
model: sonnet
|
||||||
---
|
---
|
||||||
|
|
||||||
# HOTFIX — Quick Superficial Fix
|
# HOTFIXER — closed-fix executor / L1 fix-bundle applier
|
||||||
|
|
||||||
Fast-track fix for obvious bugs. No planning overhead, no plugin check.
|
You apply a fix that was ALREADY decided upstream and prove it doesn't break
|
||||||
The fix is inline (no dev subagents); a fresh security gate runs before
|
the build — you never investigate or design the fix. Two dispatch sources,
|
||||||
commit, and any gate failure reverts — never loops. Get in, fix, gate,
|
same job:
|
||||||
get out.
|
|
||||||
|
|
||||||
## REQUEST
|
- **/hotfix orchestrator** — root-cause analysis happened in its LOCATE step;
|
||||||
$ARGUMENTS
|
you get a CONTRACT + the located files + the proposed fix (see INPUT).
|
||||||
|
- **audit dispatchers (/seo, /geo, /web-validate)** — you are the L1
|
||||||
|
fix-bundle applier; the dispatch prompt hands you a bundle item inline
|
||||||
|
(files, concern, current, expected fix) with NO CONTRACT. Apply exactly
|
||||||
|
that item, self-verify, do not commit. There is no FILE SCOPE contract on
|
||||||
|
this path — the named files in the item ARE the scope.
|
||||||
|
|
||||||
---
|
## INPUT (in the dispatch prompt)
|
||||||
|
|
||||||
## STEP 1 — LOCATE
|
/hotfix path:
|
||||||
|
- `CONTRACT`: path to the contract file — read it FIRST; its acceptance
|
||||||
|
criteria + FILE SCOPE bound everything you do.
|
||||||
|
- `LOCATED`: the file(s) the orchestrator found + the confirmed root cause.
|
||||||
|
- `FIX`: the proposed minimal fix, already decided.
|
||||||
|
- `BRANCH`: verify with `git branch --show-current`; mismatch → STATUS
|
||||||
|
BLOCKED — never create or switch branches.
|
||||||
|
|
||||||
Find the bug. Use the description and any error message to go
|
Applier path (/seo, /geo, /web-validate): no CONTRACT/LOCATED/FIX keys — the
|
||||||
straight to the source:
|
bundle item in the prompt is the fix to apply. Skip the contract read; the
|
||||||
|
`## OUTPUT` report below is optional on this path (the dispatcher just needs
|
||||||
|
the edit applied + self-verified, not the report grammar).
|
||||||
|
|
||||||
```bash
|
## EXECUTION RULES
|
||||||
git status
|
|
||||||
git log --oneline -3
|
|
||||||
```
|
|
||||||
|
|
||||||
- Read the relevant file(s). Confirm the root cause is obvious
|
- Apply the minimal change that fixes the bug. Edit only what is necessary
|
||||||
and superficial (typo, wrong value, missing import, etc.).
|
— no refactoring, no cleanup, no "while we're here" improvements.
|
||||||
- If the bug turns out to be deeper than expected (unclear cause,
|
- Stay inside the scope you were given. On the /hotfix path that is the
|
||||||
multiple files involved, logic error): STOP and say:
|
contract FILE SCOPE (max 2 files) — a fix that needs more → `STATUS
|
||||||
"This looks deeper than a hotfix. Load `$HOME/.claude/agents/bugfixer.md`
|
BLOCKED`, report why (the orchestrator escalates to `/bugfix`), never
|
||||||
and run the BUGFIXER agent on this target."
|
expand scope yourself. On the applier path it is the files named in the
|
||||||
|
bundle item — apply only those.
|
||||||
OPTIONAL — memory check (exempt by default; hotfix = obvious fix, mirror of its capitalize
|
|
||||||
skip). For a RECURRING or urgent bug only, a quick blockers-only glance may save time:
|
|
||||||
|
|
||||||
[ -d .claude/memory ] && grep -nE '^## BLK-' .claude/memory/blockers.md # "déjà vu ?"
|
|
||||||
|
|
||||||
If a prior BLK names this bug, jump to its solution. Not mandatory; no RELATED MEMORY
|
|
||||||
disposition required at hotfix weight.
|
|
||||||
|
|
||||||
## STEP 1.7 — CONTRACT (silent autofill)
|
|
||||||
|
|
||||||
Run `$HOME/.claude/lib/contract-interview.md` at hotfix weight: **zero
|
|
||||||
questions ever** (a hotfix is an obvious fix by definition). Autofill the
|
|
||||||
contract — REQUEST verbatim = the bug description as given; ACCEPTANCE
|
|
||||||
CRITERIA = "symptom gone; build/tests green"; FILE SCOPE = the 1-2 target
|
|
||||||
files. It writes `.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`. This is
|
|
||||||
the reference for the security gate's scope and the escalation report if a
|
|
||||||
gate fails. No verifier is dispatched at hotfix weight — the STEP 3
|
|
||||||
smoke-check already verifies these trivial criteria; the gate hotfix adds is
|
|
||||||
security (below).
|
|
||||||
|
|
||||||
## STEP 1.5 — DESIGN GATE
|
|
||||||
|
|
||||||
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.
|
|
||||||
- If no signals → skip (zero overhead).
|
|
||||||
|
|
||||||
## STEP 2 — PRE-FLIGHT + FIX
|
|
||||||
|
|
||||||
**Gitflow aiguillage (before editing):** 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`.
|
|
||||||
|
|
||||||
### Pre-flight (mandatory)
|
|
||||||
|
|
||||||
Before editing, snapshot current state so revert is possible:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git diff HEAD --stat # confirm working tree is clean OR carries only the
|
|
||||||
# in-progress hotfix area; if unrelated dirty files are
|
|
||||||
# present, ask user whether to stash them first
|
|
||||||
git rev-parse HEAD # capture the SHA to revert to on failure
|
|
||||||
```
|
|
||||||
|
|
||||||
If the working tree contains unrelated uncommitted changes the user has not
|
|
||||||
mentioned: STOP and ask `"working tree dirty: stash and continue, or abort?"`.
|
|
||||||
|
|
||||||
### Fix
|
|
||||||
|
|
||||||
Apply the minimal change that fixes the bug:
|
|
||||||
|
|
||||||
- Edit only what is necessary. No refactoring, no cleanup.
|
|
||||||
- If tests exist for the affected code, run them. Detection cascade:
|
- If tests exist for the affected code, run them. Detection cascade:
|
||||||
```bash
|
```bash
|
||||||
# JS/TS
|
# JS/TS
|
||||||
@@ -101,85 +58,25 @@ Apply the minimal change that fixes the bug:
|
|||||||
test -f Makefile && grep -qE '^test:' Makefile && echo "make test"
|
test -f Makefile && grep -qE '^test:' Makefile && echo "make test"
|
||||||
```
|
```
|
||||||
Run whichever one resolves; if none → continue to smoke check below.
|
Run whichever one resolves; if none → continue to smoke check below.
|
||||||
- Smoke check (always, even when no tests): try the build/typecheck command for
|
- Smoke check (always, even when no tests ran): try the build/typecheck
|
||||||
the stack — `npm run build`, `tsc --noEmit`, `cargo build`, `go build ./...`,
|
command for the stack — `npm run build`, `tsc --noEmit`, `cargo build`,
|
||||||
`python -c "import <pkg>"` — to confirm the fix did not break compilation.
|
`go build ./...`, `python -c "import <pkg>"` — to confirm the fix did not
|
||||||
|
break compilation.
|
||||||
|
- Report the SMOKE result verbatim, pass or fail. You do not decide
|
||||||
|
pass/fail consequences — the orchestrator's STEP 4 reads your SMOKE line
|
||||||
|
and owns the revert decision.
|
||||||
|
- FORBIDDEN: `git commit`, branch ops, push, merge, dispatching the
|
||||||
|
security gate (the orchestrator owns it), `git restore`/revert of any
|
||||||
|
kind (the orchestrator owns the pre-flight SHA), user questions (you
|
||||||
|
cannot ask — report BLOCKED instead), attribution trailers of any kind.
|
||||||
|
|
||||||
## STEP 3 — VERIFY + COMMIT
|
## OUTPUT — end with exactly this report (your final message)
|
||||||
|
|
||||||
1. Verify the fix:
|
```
|
||||||
- Run the test suite or the specific test if available.
|
HOTFIX-EXEC REPORT
|
||||||
- If no tests: smoke check from STEP 2 must have passed.
|
STATUS : DONE | BLOCKED
|
||||||
2. **Failure branch** — if tests fail OR smoke check fails after the fix:
|
FILE(S) : <changed files>
|
||||||
- Print the failure output verbatim (under 30 lines).
|
FIX : <one-line description>
|
||||||
- Run `git restore .` to revert the working-tree edits to the pre-flight SHA.
|
SMOKE : <test/build result, verbatim line>
|
||||||
(Files were not yet staged — restore is safe.)
|
NOTES : <BLOCKED: the blocker; DONE: none>
|
||||||
- STOP and tell user: `"Hotfix introduced a regression. Reverted. Escalate to /bugfix or /analyze for deeper investigation."`
|
```
|
||||||
- Do NOT commit a broken fix.
|
|
||||||
3. **Security gate (fresh auditor) — failure REVERTS, never loops.** Dispatch
|
|
||||||
a FRESH security-auditor (`subagent_type: security-auditor`, or load
|
|
||||||
`agents/security-auditor.md`) with `MODE: gate`, `SCOPE:` the working-tree
|
|
||||||
diff vs the pre-flight SHA. Parse its `SECURITY — VERDICT:` line:
|
|
||||||
- `PASS` (or `DEGRADED` with no BLOCK) → proceed to commit.
|
|
||||||
- `BLOCK(n)` → this is hotfix: do NOT loop. Run `git restore .` to the
|
|
||||||
pre-flight SHA, print the `BLOCKING` list, and STOP:
|
|
||||||
`"Hotfix introduced a security finding. Reverted. Escalate to /bugfix
|
|
||||||
for a fix under the full verify+security loop."` The hotfix model is
|
|
||||||
one attempt; any gate failure (smoke OR security) reverts and escalates.
|
|
||||||
- Structural failure (mute / unparsable / no VERDICT line) → treat as a
|
|
||||||
failed gate: retry ONCE fresh; a 2nd structural failure → revert +
|
|
||||||
escalate. A mute auditor is never a PASS.
|
|
||||||
4. Commit using conventional format (only after verify AND security pass):
|
|
||||||
```
|
|
||||||
fix(<scope>): <what was wrong>
|
|
||||||
```
|
|
||||||
5. Print summary:
|
|
||||||
```
|
|
||||||
HOTFIX APPLIED
|
|
||||||
FILE(S) : <changed files>
|
|
||||||
FIX : <one-line description>
|
|
||||||
VERIFIED: <test name or smoke check that passed>
|
|
||||||
SECURITY: <PASS | DEGRADED (checklist only)>
|
|
||||||
```
|
|
||||||
|
|
||||||
## STEP 4 — DOC SYNC (automatic)
|
|
||||||
|
|
||||||
Load `$HOME/.claude/agents/doc-syncer.md`.
|
|
||||||
Execute in automatic mode:
|
|
||||||
`auto-mode scope: <list of files modified during this session>`
|
|
||||||
|
|
||||||
**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
|
|
||||||
`.claude/`/`CLAUDE.md` (rc 4 = a loud BDR-022 anomaly, not a silent skip), and no-ops when
|
|
||||||
nothing was patched — the common case for a trivial hotfix. No FINISH in an inline flow, so
|
|
||||||
it just commits the docs on the current branch (no ordering concern).
|
|
||||||
|
|
||||||
## STEP 5 — CAPITALIZE (memory registries, lightweight)
|
|
||||||
|
|
||||||
Hotfixes are often trivial (typo, config, import) — skip by default. But if the fix revealed something non-obvious:
|
|
||||||
|
|
||||||
- Wrong default that should never have been merged → propose `LRN-XXX` in `.claude/memory/learnings.md`.
|
|
||||||
- Bug that cost real time to locate despite being "superficial" → propose `BLK-XXX` in `.claude/memory/blockers.md` (status: resolved).
|
|
||||||
|
|
||||||
Default behaviour: `CAPITALIZE: hotfix trivial, skip` (no prompt, no output).
|
|
||||||
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).
|
|
||||||
|
|
||||||
**Then commit the memory** — follow `$HOME/.claude/lib/capitalize-commit.md`: it
|
|
||||||
surgically commits what capitalize just wrote (`.claude/memory` + `.claude/tasks`
|
|
||||||
only, never `git add -A`) as one `chore(memory)` commit, reports the memory-commit
|
|
||||||
hash, and no-ops if nothing was written. The always-on journal line means a
|
|
||||||
trivial hotfix still produces a `chore(memory): journal — …` commit (Frame 2 / F3).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## RULES
|
|
||||||
- Max 2 files changed. If more needed → `/bugfix`.
|
|
||||||
- No refactoring. No "while we're here" improvements.
|
|
||||||
- Design gate only if CSS/style signals detected. See STEP 1.5.
|
|
||||||
- If root cause is unclear → escalate to `/bugfix`.
|
|
||||||
- If fix touches >5 lines of logic → reconsider if this is
|
|
||||||
truly a hotfix.
|
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
---
|
||||||
|
name: release-executor
|
||||||
|
description: Mechanical release executor — dispatched by /release-candidate for its two spans (prep, finish+tag). Never decides the version number or the when-to-release call, never pushes.
|
||||||
|
tools: Read, Edit, Write, Bash, Grep, Glob
|
||||||
|
model: sonnet
|
||||||
|
---
|
||||||
|
|
||||||
|
# RELEASE-EXECUTOR — mechanical release spans
|
||||||
|
|
||||||
|
You execute the mechanical parts of a gitflow release. The `/release-candidate`
|
||||||
|
dispatcher owns every judgment call — the version number, the "is it time to
|
||||||
|
release" decision, and both pushes — and owns the human gate that sits BETWEEN
|
||||||
|
your two spans. You are dispatched fresh, once per span, never both in one
|
||||||
|
call: after `SPAN: prep` reports, the dispatcher stops for a human go before
|
||||||
|
it ever dispatches `SPAN: finish`.
|
||||||
|
|
||||||
|
## Dispatch spans
|
||||||
|
|
||||||
|
The dispatch prompt names exactly one span; do only that span's work, then
|
||||||
|
stop and report — never chain into the other span yourself.
|
||||||
|
|
||||||
|
- `SPAN: prep <X.Y.Z>` — branch, version bump, CHANGELOG, test gate, commit.
|
||||||
|
No merge, no tag, no push.
|
||||||
|
- `SPAN: finish <X.Y.Z>` — gitflow fan-out, then tag. Never push.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## SPAN: prep <X.Y.Z>
|
||||||
|
|
||||||
|
### Input
|
||||||
|
`<X.Y.Z>`: the version number, already decided by the dispatcher before
|
||||||
|
dispatch — you never derive it, never second-guess it, never bump it.
|
||||||
|
|
||||||
|
### Steps
|
||||||
|
1. `bash "$HOME/.claude/lib/gitflow.sh" start release <X.Y.Z>` — forks from
|
||||||
|
`develop` onto `release/<X.Y.Z>`. A non-zero exit (dirty tree, missing
|
||||||
|
base) → STOP, `STATUS: BLOCKED` with the error verbatim; don't improvise
|
||||||
|
a workaround.
|
||||||
|
2. Set `version.txt` to `<X.Y.Z>` (single line, trailing newline).
|
||||||
|
3. Rewrite `CHANGELOG.md`: the `## [Unreleased]` header becomes
|
||||||
|
`## [<X.Y.Z>] — <today, YYYY-MM-DD>`; re-open a fresh, empty
|
||||||
|
`## [Unreleased]` above it. If `<X.Y.Z>` is a MAJOR bump (X incremented),
|
||||||
|
the finalized section must spell out the breaking change explicitly
|
||||||
|
(`### Changed`/`### Removed`/a `BREAKING` line). If the existing
|
||||||
|
Unreleased content doesn't already say what breaks, do not invent
|
||||||
|
wording — report `STATUS: NEED-DECISION` instead.
|
||||||
|
4. Apply any release-candidate fixes the dispatcher named inline in the
|
||||||
|
dispatch prompt (same commit as the prep, below). None named → skip.
|
||||||
|
5. **Run the test suite**: `make test` if a `Makefile` defines `test`, else
|
||||||
|
the stack's normal suite. This is the RC gate — never let a release
|
||||||
|
proceed on red. Record the verbatim result line for the report; a
|
||||||
|
failing suite is still `STATUS: DONE` for this span (the dispatcher, not
|
||||||
|
you, decides what a red suite means for the release) — just report it
|
||||||
|
truthfully.
|
||||||
|
6. Commit the prep on the release branch:
|
||||||
|
`chore(release): <X.Y.Z> — version.txt + CHANGELOG`.
|
||||||
|
|
||||||
|
### Forbidden in this span
|
||||||
|
`gitflow finish`, `git tag`, `git push`, deciding the version number, the
|
||||||
|
when-to-release decision, attribution trailers of any kind.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## SPAN: finish <X.Y.Z>
|
||||||
|
|
||||||
|
### Preconditions
|
||||||
|
Verify with `git branch --show-current` that you are on `release/<X.Y.Z>`
|
||||||
|
before finishing. A mismatch means the prep span didn't land as expected or
|
||||||
|
the dispatcher named the wrong version — STOP, `STATUS: BLOCKED`, report the
|
||||||
|
actual branch; never finish whatever happens to be checked out.
|
||||||
|
|
||||||
|
### Steps
|
||||||
|
1. `bash "$HOME/.claude/lib/gitflow.sh" finish` — fans out: merges
|
||||||
|
`release/<X.Y.Z>` into `main`, merges into `develop`, deletes the release
|
||||||
|
branch. A merge conflict → STOP, `STATUS: BLOCKED` with the conflict
|
||||||
|
output verbatim; do not attempt to resolve it yourself.
|
||||||
|
2. **Tag AFTER finish, on `main`** — never before:
|
||||||
|
`git tag -a v<X.Y.Z> main -m "release <X.Y.Z>"` (annotated, so it lands on
|
||||||
|
main's release-merge commit).
|
||||||
|
|
||||||
|
### Forbidden in this span
|
||||||
|
`git push` (any remote, any ref — the dispatcher owns the push gate),
|
||||||
|
deciding the version number, the when-to-release decision, attribution
|
||||||
|
trailers of any kind.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## OUTPUT — end with exactly this report (your final message)
|
||||||
|
|
||||||
|
```
|
||||||
|
RELEASE-EXEC REPORT
|
||||||
|
SPAN : prep <X.Y.Z> | finish <X.Y.Z>
|
||||||
|
STATUS : DONE | NEED-DECISION | BLOCKED
|
||||||
|
BRANCH : <release/<X.Y.Z> for prep | main for finish>
|
||||||
|
TAG : <v<X.Y.Z> | n/a — prep never tags>
|
||||||
|
TESTS : <verbatim suite result | n/a — finish never runs tests>
|
||||||
|
NOTES : <DONE: none | NEED-DECISION: exact question + options |
|
||||||
|
BLOCKED: the blocker verbatim>
|
||||||
|
```
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,143 @@
|
|||||||
|
# Model routing — reflection inline (big model) / execution pinned (Sonnet) — design
|
||||||
|
|
||||||
|
**Date**: 2026-07-15 · **Status**: approved (user, 2026-07-15) · **Branch**: `feature/model-routing`
|
||||||
|
**Lifecycle**: transient planning artifact (BDR-065) — committed during the run, deleted post-merge.
|
||||||
|
|
||||||
|
## Principle
|
||||||
|
|
||||||
|
The session model is assumed to be a big reasoning model (Fable 5, or Opus when
|
||||||
|
Fable is unavailable). Everything that **thinks** — brainstorming, planning,
|
||||||
|
technical decisions, audits, loop decisions — runs INLINE in the main
|
||||||
|
conversation, or in subagents that inherit the session model. Everything that
|
||||||
|
**executes** a ready-made plan — writing code, applying fix bundles, commits,
|
||||||
|
deliverable rendering — runs on Sonnet-pinned subagents. A blocking gate
|
||||||
|
enforces the "session = big model" assumption at the entry of every reflection
|
||||||
|
orchestrator.
|
||||||
|
|
||||||
|
User verdicts baked in (2026-07-14/15):
|
||||||
|
- Scope = hybrid: ship-feature/init-project execution → sonnet; `/feat`
|
||||||
|
re-architected (plan inline → dispatch executor); bugfix/hotfix stay fully
|
||||||
|
inline (BDR-050 conserved for them).
|
||||||
|
- Gate = BLOCKING, not advisory.
|
||||||
|
- Audit agents inherit the session model (no opus pin); the gate extends to
|
||||||
|
audit orchestrators.
|
||||||
|
- verifier + security-auditor KEEP `model: sonnet` (job9 decision confirmed).
|
||||||
|
- client-handover-writer → sonnet (requires converting its inline-load to a
|
||||||
|
true dispatch; human gates relocate to the main loop).
|
||||||
|
|
||||||
|
## 1. Blocking model gate
|
||||||
|
|
||||||
|
New `lib/model-check.sh`: resolves the current session model from
|
||||||
|
`settings.json` (physical path resolution — LRN-023 class), normalizes
|
||||||
|
(`claude-fable-5[1m]` → fable, `claude-opus-*` → opus, sonnet, haiku), prints
|
||||||
|
`big|small|unknown`. Exit 0 = big, 2 = small, 3 = unknown.
|
||||||
|
|
||||||
|
New `lib/model-gate.md` snippet (same include pattern as `lib/design-gate.md`):
|
||||||
|
run the check; `small` → STOP the skill: "session model is <X> — reflection
|
||||||
|
requires Fable/Opus. Switch with /model, then relaunch." `unknown` →
|
||||||
|
fail-visible: show the raw value, ask the user to confirm or abort (BDR-025
|
||||||
|
doctrine — unknown never silently passes).
|
||||||
|
|
||||||
|
Wired as a STEP 0 line in the reflection orchestrators:
|
||||||
|
`ship-feature, init-project, feat, bugfix, onboard, seo, geo, web-validate,
|
||||||
|
harden, audit-delta, tour, code-clean`.
|
||||||
|
NOT wired in: `hotfix` (trivial by definition), `commit-change`, `doc`,
|
||||||
|
`status`, `release-candidate`.
|
||||||
|
|
||||||
|
Caveats to prove at implementation time:
|
||||||
|
- `/model` mid-session rewrites settings.json (LRN-098 observed it once —
|
||||||
|
re-prove with a live flip-test before trusting the source).
|
||||||
|
- The helper itself must be flip-tested (LRN-096: an unproven guard is a
|
||||||
|
vacuous guard).
|
||||||
|
|
||||||
|
## 2. Frontmatter pins (`agents/*.md`)
|
||||||
|
|
||||||
|
| Agent | Before | After | Rationale |
|
||||||
|
|---|---|---|---|
|
||||||
|
| feater | (inherit) | **sonnet** | executor as subagent: seo/geo L1 applier + new /feat dispatch |
|
||||||
|
| hotfixer | (inherit) | **sonnet** | L1 applier (seo/geo/web-validate); /hotfix inline unaffected (pin inert on inline load) |
|
||||||
|
| client-handover-writer | opus | **sonnet** | deliverable executor; pin becomes EFFECTIVE only with §5 dispatch conversion (today's opus pin is inert — the agent is inline-loaded) |
|
||||||
|
| analyzer | haiku | **(none — inherit)** | analysis feeds the plan = reflection; runs big via the session model |
|
||||||
|
| verifier | sonnet | keep | F1 confirmed (job9) |
|
||||||
|
| security-auditor | sonnet | keep | F1 confirmed (job9) |
|
||||||
|
| seo-analyzer, geo-analyzer, validator-analyzer | (inherit) | keep (inherit) | audit = reflection = session model; covered by the gate |
|
||||||
|
| code-cleaner | (inherit) | keep (inherit) | audit phase = reflection; fixes hand off to refactorer (sonnet) via CODE-CLEAN-SCOPE.md (job9 H1) |
|
||||||
|
| doc-syncer, onboarder, scaffolder, refactorer, interviewer, plugin-advisor | sonnet | keep | workers/executors |
|
||||||
|
| status-reporter | haiku | keep | mechanical collector |
|
||||||
|
| bugfixer, commit-changer | (inherit) | keep | inline-only playbooks — a pin would be inert |
|
||||||
|
|
||||||
|
## 3. `/feat` re-architecture (partial supersede of BDR-050 — feat only)
|
||||||
|
|
||||||
|
`skills/feat/SKILL.md` absorbs the reflection: analyze-before-plan, design
|
||||||
|
gate, MINI-PLAN, contract (`lib/contract-interview.md`) — all inline. Then
|
||||||
|
dispatches `Agent(subagent_type="feater")` (sonnet via pin) with: the
|
||||||
|
contract, the plan, the branch name, repo conventions.
|
||||||
|
|
||||||
|
`agents/feater.md` is rewritten as a pure executor: implement the plan to the
|
||||||
|
letter, run project checks, commit (no attribution trailers), return a
|
||||||
|
structured summary. No user interaction inside feater (subagents cannot ask) —
|
||||||
|
every decision must be closed pre-dispatch.
|
||||||
|
|
||||||
|
The verify-secure loop moves out of feater.md into the /feat main loop
|
||||||
|
(LRN-083 invariant: loop decisions live in the main loop): fresh verifier →
|
||||||
|
ECARTS → re-dispatch feater with the verdict deltas, bounded 3×; then the
|
||||||
|
security gate. Escalation paths unchanged.
|
||||||
|
|
||||||
|
## 4. SDD execution pinned (ship-feature STEP 4, init-project STEP 8)
|
||||||
|
|
||||||
|
One instruction line in each SKILL.md: every implementation subagent
|
||||||
|
dispatched under `superpowers:subagent-driven-development` MUST carry
|
||||||
|
`model: "sonnet"` in the Agent call. No fork of the superpowers skill — the
|
||||||
|
main loop emits the Agent calls and controls the params.
|
||||||
|
|
||||||
|
## 5. client-handover conversion (inline-load → true dispatch)
|
||||||
|
|
||||||
|
`skills/client-handover/SKILL.md`: collect params inline (URL, logo, options),
|
||||||
|
then `Agent(subagent_type="client-handover-writer")` — the sonnet pin becomes
|
||||||
|
effective. Human gates (per-axis threshold escalation, overrides) RELOCATE to
|
||||||
|
the main loop: the writer returns a structured `GATE NEEDED` status instead of
|
||||||
|
asking; the dispatcher asks the user and re-dispatches (or continues via
|
||||||
|
SendMessage) with the decision. `AskUserQuestion` is removed from the writer's
|
||||||
|
tools.
|
||||||
|
|
||||||
|
OPEN VERIFY POINT: the writer's own nested dispatches (seo/harden re-runs as
|
||||||
|
general-purpose subagents) — verify at implementation what nested children
|
||||||
|
inherit (session model vs parent model). If they inherit the sonnet parent,
|
||||||
|
the re-run audits violate the principle → force the model explicitly in those
|
||||||
|
nested dispatches or lift them to the main loop.
|
||||||
|
|
||||||
|
## 6. web-validate fixes → L1 applier
|
||||||
|
|
||||||
|
STEP 3 stops applying fixes via inline Edit; dispatches `hotfixer` (sonnet)
|
||||||
|
with the fix bundle — same pattern as seo/geo (BDR-061 alignment).
|
||||||
|
|
||||||
|
## 7. Memory / doc / tests
|
||||||
|
|
||||||
|
- New BDR: model-routing principle (reflection inline big / executors sonnet /
|
||||||
|
blocking gate); partial supersede of BDR-050 (feat only); records F1
|
||||||
|
(verifier/security stay sonnet) and the analyzer haiku→inherit change.
|
||||||
|
- README: agent-model table refresh. CHANGELOG Unreleased entry.
|
||||||
|
- Tests: flip-tests for `model-check.sh` (fable[1m] / opus / sonnet / garbage
|
||||||
|
fixtures); gate STOP proven on a small-model fixture (LRN-096); /feat smoke
|
||||||
|
on a throwaway repo (LRN-079): plan inline → dispatch carries sonnet →
|
||||||
|
verify loop decided in main loop; grep census: no executor dispatch without
|
||||||
|
an effective pin.
|
||||||
|
|
||||||
|
## Out of scope / accepted deviations
|
||||||
|
|
||||||
|
- `/doc` and `/commit-change` stay inline on the session model (judgment and
|
||||||
|
execution interleaved; converting them buys little). Revisit under quota
|
||||||
|
pressure.
|
||||||
|
- bugfix/hotfix fully inline (BDR-050 conserved).
|
||||||
|
- No per-agent "fable-else-opus" fallback exists in the harness — the session
|
||||||
|
model IS the fallback mechanism; the gate is its backstop.
|
||||||
|
|
||||||
|
## Risks
|
||||||
|
|
||||||
|
- Model strings in settings.json may change shape with CC updates →
|
||||||
|
model-check must return `unknown` (fail-visible), never guess.
|
||||||
|
- feater as a subagent loses main-conversation context → the plan becomes the
|
||||||
|
contract; weak plans cost verify-loop iterations. Mitigation:
|
||||||
|
contract-interview stays mandatory in /feat.
|
||||||
|
- Nested model inheritance under client-handover-writer unknown → §5 verify
|
||||||
|
point.
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# lib/model-check.sh — classify the persisted session model: big | small | unknown
|
||||||
|
#
|
||||||
|
# Witness for lib/model-gate.md (reflection requires a big model). Reads the
|
||||||
|
# "model" key of the user-scope settings (the file /model rewrites — LRN-098).
|
||||||
|
# Override the source with MODEL_CHECK_SETTINGS (tests use fixtures).
|
||||||
|
#
|
||||||
|
# stdout : <class>:<raw> (raw = value found, empty if none)
|
||||||
|
# exit : 0 = big (fable/opus) · 2 = small (sonnet/haiku) · 3 = unknown
|
||||||
|
set -u
|
||||||
|
|
||||||
|
SETTINGS="${MODEL_CHECK_SETTINGS:-$HOME/.claude/settings.json}"
|
||||||
|
|
||||||
|
raw=""
|
||||||
|
if [ -f "$SETTINGS" ]; then
|
||||||
|
raw="$(python3 - "$SETTINGS" 2>/dev/null <<'PY'
|
||||||
|
import json, sys
|
||||||
|
try:
|
||||||
|
v = json.load(open(sys.argv[1])).get("model", "")
|
||||||
|
print(v if isinstance(v, str) else "")
|
||||||
|
except Exception:
|
||||||
|
print("")
|
||||||
|
PY
|
||||||
|
)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
norm="$(printf '%s' "$raw" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
case "$norm" in
|
||||||
|
*opusplan*) printf 'unknown:%s\n' "$raw"; exit 3 ;; # opus-for-plan, sonnet otherwise — ambiguous
|
||||||
|
*fable*|*opus*) printf 'big:%s\n' "$raw"; exit 0 ;;
|
||||||
|
*sonnet*|*haiku*) printf 'small:%s\n' "$raw"; exit 2 ;;
|
||||||
|
*) printf 'unknown:%s\n' "$raw"; exit 3 ;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# Model gate — reflection requires a big model (BLOCKING)
|
||||||
|
|
||||||
|
Shared include. Runs FIRST in any orchestrator whose reflection —
|
||||||
|
brainstorming, planning, contract, audit judgment, loop decisions —
|
||||||
|
executes inline or in inherit-model subagents. Sonnet-pinned executors are
|
||||||
|
not what this gate protects; it protects the thinking around them (BDR-066).
|
||||||
|
|
||||||
|
## 1. Self-check
|
||||||
|
|
||||||
|
Your system prompt names the model powering this session. Fable or Opus →
|
||||||
|
big. Sonnet, Haiku, anything else → small.
|
||||||
|
|
||||||
|
## 2. Witness — deterministic check
|
||||||
|
|
||||||
|
bash "$HOME/.claude/lib/model-check.sh"
|
||||||
|
|
||||||
|
Output `<class>:<raw>`; exit 0 = big, 2 = small, 3 = unknown. The witness
|
||||||
|
reads the PERSISTED model (settings.json — the file `/model` rewrites,
|
||||||
|
LRN-098). It can lag reality (session launched with `--model`, settings not
|
||||||
|
yet rewritten) — that is why the self-check exists alongside it.
|
||||||
|
|
||||||
|
## 3. Verdict
|
||||||
|
|
||||||
|
| self-check | witness | action |
|
||||||
|
|---|---|---|
|
||||||
|
| big | big (0) | proceed, SILENT — the nominal path prints nothing |
|
||||||
|
| small | any | **STOP** |
|
||||||
|
| big | small (2) | disagreement — **STOP**, surface BOTH values; the user confirms or relaunches |
|
||||||
|
| big | unknown (3) | fail-visible: print `model gate: witness unknown (<raw>) — self-check says <model>` and ask the user to confirm before continuing (BDR-025: unknown never silently passes) |
|
||||||
|
|
||||||
|
**STOP means**: print exactly
|
||||||
|
|
||||||
|
⛔ MODEL GATE — session on <model>. Reflection steps of this skill
|
||||||
|
require Fable or Opus. Switch with /model, then relaunch the skill.
|
||||||
|
|
||||||
|
then end the turn. No later step runs, no agent is dispatched, nothing is
|
||||||
|
edited.
|
||||||
@@ -9,10 +9,12 @@ set -u
|
|||||||
|
|
||||||
REPO="$(cd "$(dirname "$0")/../.." && pwd)"
|
REPO="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||||
INC="$REPO/lib/verify-secure-loop.md"
|
INC="$REPO/lib/verify-secure-loop.md"
|
||||||
FEA="$REPO/agents/feater.md"
|
FSK="$REPO/skills/feat/SKILL.md"
|
||||||
BUG="$REPO/agents/bugfixer.md"
|
BUG="$REPO/agents/bugfixer.md"
|
||||||
|
BSK="$REPO/skills/bugfix/SKILL.md"
|
||||||
HOT="$REPO/agents/hotfixer.md"
|
HOT="$REPO/agents/hotfixer.md"
|
||||||
HSK="$REPO/skills/hotfix/SKILL.md"
|
HSK="$REPO/skills/hotfix/SKILL.md"
|
||||||
|
HSKL="$REPO/skills/hotfix/SKILL.md"
|
||||||
PASS=0; FAIL=0
|
PASS=0; FAIL=0
|
||||||
|
|
||||||
tf() { # tf <label> <file> <fixed-string>
|
tf() { # tf <label> <file> <fixed-string>
|
||||||
@@ -29,6 +31,13 @@ tr_() { # tr_ <label> <file> <ERE>
|
|||||||
echo " FAIL $1 — no match: $3"; FAIL=$((FAIL+1))
|
echo " FAIL $1 — no match: $3"; FAIL=$((FAIL+1))
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
tn() { # tn <label> <file> <fixed-string> — PASS when ABSENT (mirror of tf, inverted)
|
||||||
|
if grep -qF -- "$3" "$2" 2>/dev/null; then
|
||||||
|
echo " FAIL $1 — present (should be absent): $3"; FAIL=$((FAIL+1))
|
||||||
|
else
|
||||||
|
echo " PASS $1"; PASS=$((PASS+1))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
echo "── verify-secure-loop.md (shared include) ──"
|
echo "── verify-secure-loop.md (shared include) ──"
|
||||||
if [ -f "$INC" ]; then echo " PASS include exists"; PASS=$((PASS+1)); else echo " FAIL include missing"; FAIL=$((FAIL+1)); fi
|
if [ -f "$INC" ]; then echo " PASS include exists"; PASS=$((PASS+1)); else echo " FAIL include missing"; FAIL=$((FAIL+1)); fi
|
||||||
@@ -43,27 +52,39 @@ tf "order invariant" "$INC" "always re-checked BEFORE security"
|
|||||||
tf "mute never a pass (verify)" "$INC" "NEVER a PASS"
|
tf "mute never a pass (verify)" "$INC" "NEVER a PASS"
|
||||||
tf "nominal cheap stated" "$INC" "one verifier dispatch + one security dispatch"
|
tf "nominal cheap stated" "$INC" "one verifier dispatch + one security dispatch"
|
||||||
|
|
||||||
echo "── feater.md (feat wiring) ──"
|
echo "── feat/SKILL.md (feat orchestrator wiring) ──"
|
||||||
tf "feat contract step" "$FEA" "STEP 0.7 — CONTRACT"
|
tf "feat contract step" "$FSK" "STEP 0.7 — CONTRACT"
|
||||||
tf "feat contract-interview" "$FEA" "lib/contract-interview.md"
|
tf "feat contract-interview" "$FSK" "lib/contract-interview.md"
|
||||||
tf "feat verify+secure step" "$FEA" "STEP 3 — VERIFY + SECURE"
|
tf "feat verify+secure step" "$FSK" "STEP 4 — VERIFY + SECURE"
|
||||||
tf "feat uses shared include" "$FEA" "lib/verify-secure-loop.md"
|
tf "feat uses shared include" "$FSK" "lib/verify-secure-loop.md"
|
||||||
tf "feat nominal 1+1 dispatch" "$FEA" "verifier + one security dispatch"
|
tf "feat nominal 1+1 dispatch" "$FSK" "verifier + one security dispatch"
|
||||||
|
tf "feat dispatches feater" "$FSK" 'subagent_type="feater"'
|
||||||
|
|
||||||
echo "── bugfixer.md (bugfix wiring) ──"
|
echo "── skills/bugfix/SKILL.md (bugfix wiring — reflection inline) ──"
|
||||||
tf "bug contract step" "$BUG" "STEP 3.5 — CONTRACT"
|
tf "bug contract step" "$BSK" "STEP 3.5 — CONTRACT"
|
||||||
tf "bug diagnosis feeds it" "$BUG" "feeds it: REQUEST verbatim"
|
tf "bug diagnosis feeds it" "$BSK" "feeds it: REQUEST verbatim"
|
||||||
tf "bug fresh gates" "$BUG" "Fresh gates (verify + secure)"
|
tf "bug fresh gates" "$BSK" "the two fresh gates per"
|
||||||
tf "bug uses shared include" "$BUG" "lib/verify-secure-loop.md"
|
tf "bug uses shared include" "$BSK" "lib/verify-secure-loop.md"
|
||||||
|
tf "bug dispatches bugfixer" "$BSK" 'subagent_type="bugfixer"'
|
||||||
|
|
||||||
echo "── hotfixer.md (hotfix wiring — revert, not loop) ──"
|
echo "── agents/bugfixer.md (bugfix executor — sonnet, no Agent) ──"
|
||||||
tr_ "hotfix has Agent tool" "$HOT" "^tools:.*Agent"
|
tn "bugfixer lacks Agent tool" "$BUG" "Agent"
|
||||||
tf "hotfix silent contract" "$HOT" "STEP 1.7 — CONTRACT (silent autofill)"
|
tf "bugfixer model sonnet" "$BUG" "model: sonnet"
|
||||||
tf "hotfix zero questions" "$HOT" "questions ever"
|
tf "bugfixer report grammar" "$BUG" "BUGFIX-EXEC REPORT"
|
||||||
tf "hotfix security gate" "$HOT" "Security gate (fresh auditor)"
|
|
||||||
tf "hotfix block reverts" "$HOT" "failure REVERTS, never loops"
|
echo "── hotfixer.md (hotfix executor — sonnet, no Agent) ──"
|
||||||
tf "hotfix no verifier" "$HOT" "No verifier is dispatched at hotfix weight"
|
tn "hotfixer lacks Agent tool" "$HOT" "Agent"
|
||||||
|
tf "hotfixer model sonnet" "$HOT" "model: sonnet"
|
||||||
|
tf "hotfixer report grammar" "$HOT" "HOTFIX-EXEC REPORT"
|
||||||
|
|
||||||
|
echo "── skills/hotfix/SKILL.md (hotfix wiring — revert, not loop) ──"
|
||||||
|
tf "hotfix silent contract" "$HSKL" "STEP 1.7 — CONTRACT (silent autofill)"
|
||||||
|
tf "hotfix zero questions" "$HSKL" "questions ever"
|
||||||
|
tf "hotfix security gate" "$HSKL" "Security gate (fresh auditor)"
|
||||||
|
tf "hotfix block reverts" "$HSKL" "failure REVERTS, never loops"
|
||||||
|
tf "hotfix no verifier" "$HSKL" "No verifier is dispatched at hotfix weight"
|
||||||
tf "hotfix skill has Agent" "$HSK" " - Agent"
|
tf "hotfix skill has Agent" "$HSK" " - Agent"
|
||||||
|
tf "hotfix dispatches hotfixer" "$HSKL" 'subagent_type="hotfixer"'
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "loops-light structure locks: $PASS pass, $FAIL fail"
|
echo "loops-light structure locks: $PASS pass, $FAIL fail"
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# lib/tests/model-check.test.sh — flip-tests for lib/model-check.sh (LRN-096)
|
||||||
|
set -u
|
||||||
|
S="$(cd "$(dirname "$0")/../.." && pwd)/lib/model-check.sh"
|
||||||
|
pass=0; fail=0
|
||||||
|
check() { if [ "$2" = "$3" ]; then pass=$((pass+1)); else fail=$((fail+1));
|
||||||
|
printf 'FAIL %s: got[%s] want[%s]\n' "$1" "$2" "$3"; fi; }
|
||||||
|
T="$(mktemp -d)"; trap 'rm -rf "$T"' EXIT
|
||||||
|
|
||||||
|
fx() { printf '{"model": "%s"}' "$1" > "$T/s.json"; }
|
||||||
|
run() { MODEL_CHECK_SETTINGS="$T/s.json" bash "$S" >"$T/out" 2>&1; echo "$?"; }
|
||||||
|
|
||||||
|
fx 'claude-fable-5[1m]'; check T1-fable-exit "$(run)" 0
|
||||||
|
check T1-fable-class "$(cut -d: -f1 <"$T/out")" big
|
||||||
|
fx 'claude-opus-4-8'; check T2-opus "$(run)" 0
|
||||||
|
fx 'claude-sonnet-5'; check T3-sonnet "$(run)" 2
|
||||||
|
fx 'claude-haiku-4-5-20251001'; check T4-haiku "$(run)" 2
|
||||||
|
fx 'opusplan'; check T5-opusplan "$(run)" 3
|
||||||
|
fx 'gpt-9-mega'; check T6-foreign "$(run)" 3
|
||||||
|
printf '{"no_model": true}' > "$T/s.json"; check T7-no-key "$(run)" 3
|
||||||
|
printf '{broken' > "$T/s.json"; check T8-malformed "$(run)" 3
|
||||||
|
check T9-missing-file "$(MODEL_CHECK_SETTINGS="$T/absent.json" bash "$S" >/dev/null 2>&1; echo $?)" 3
|
||||||
|
|
||||||
|
printf 'model-check: %d pass, %d fail\n' "$pass" "$fail"
|
||||||
|
[ "$fail" -eq 0 ]
|
||||||
Executable
+53
@@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# lib/tests/model-routing.test.sh — census: gate wiring + pins + executor shape (BDR-066)
|
||||||
|
set -u
|
||||||
|
R="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||||
|
pass=0; fail=0
|
||||||
|
ok() { pass=$((pass+1)); }
|
||||||
|
ko() { fail=$((fail+1)); printf 'FAIL %s\n' "$1"; }
|
||||||
|
has() { if grep -qF "$2" "$R/$1"; then ok; else ko "$1 missing: $2"; fi; }
|
||||||
|
lacks() { if grep -qF "$2" "$R/$1"; then ko "$1 must NOT contain: $2"; else ok; fi; }
|
||||||
|
fm_lacks() { if awk 'NR<=10' "$R/$1" | grep -qF "$2"; then ko "$1 frontmatter must NOT contain: $2"; else ok; fi; }
|
||||||
|
|
||||||
|
# 1) gate wired in the 13 reflection orchestrators
|
||||||
|
for s in ship-feature init-project feat bugfix onboard seo geo web-validate harden audit-delta tour code-clean hotfix; do
|
||||||
|
has "skills/$s/SKILL.md" 'lib/model-gate.md'
|
||||||
|
done
|
||||||
|
# 2) gate NOT wired in the excluded skills (encodes the spec exclusion list)
|
||||||
|
for s in commit-change doc status release-candidate; do
|
||||||
|
lacks "skills/$s/SKILL.md" 'lib/model-gate.md'
|
||||||
|
done
|
||||||
|
# 3) executor + gate pins
|
||||||
|
has "agents/feater.md" 'model: sonnet'
|
||||||
|
has "agents/hotfixer.md" 'model: sonnet'
|
||||||
|
has "agents/verifier.md" 'model: sonnet'
|
||||||
|
has "agents/security-auditor.md" 'model: sonnet'
|
||||||
|
fm_lacks "agents/analyzer.md" 'model:'
|
||||||
|
# 4) /feat executor shape
|
||||||
|
has "skills/feat/SKILL.md" 'subagent_type="feater"'
|
||||||
|
has "skills/feat/SKILL.md" 'verify-secure-loop.md'
|
||||||
|
lacks "agents/feater.md" 'AskUserQuestion'
|
||||||
|
# 5) SDD execution pinned
|
||||||
|
has "skills/ship-feature/SKILL.md" 'model: "sonnet"'
|
||||||
|
has "skills/init-project/SKILL.md" 'model: "sonnet"'
|
||||||
|
# 6) web-validate applies via L1 applier
|
||||||
|
has "skills/web-validate/SKILL.md" 'subagent_type="hotfixer"'
|
||||||
|
# 7) wave-2 — pure-execution skills dispatch their agent (pin takes effect, off the big session model)
|
||||||
|
has "skills/doc/SKILL.md" 'subagent_type="doc-syncer"'
|
||||||
|
has "skills/status/SKILL.md" 'subagent_type="status-reporter"'
|
||||||
|
has "skills/commit-change/SKILL.md" 'subagent_type="commit-changer"'
|
||||||
|
has "skills/release-candidate/SKILL.md" 'subagent_type="release-executor"'
|
||||||
|
has "skills/hotfix/SKILL.md" 'subagent_type="hotfixer"'
|
||||||
|
has "agents/commit-changer.md" 'model: sonnet'
|
||||||
|
has "agents/release-executor.md" 'model: sonnet'
|
||||||
|
lacks "agents/commit-changer.md" 'AskUserQuestion'
|
||||||
|
# 8) wave-3 — bugfix/code-clean reflection-split executors (skills stay gated)
|
||||||
|
has "skills/bugfix/SKILL.md" 'subagent_type="bugfixer"'
|
||||||
|
has "agents/bugfixer.md" 'model: sonnet'
|
||||||
|
lacks "agents/bugfixer.md" 'AskUserQuestion'
|
||||||
|
has "skills/code-clean/SKILL.md" 'subagent_type="code-cleaner"'
|
||||||
|
has "agents/code-cleaner.md" 'model: sonnet'
|
||||||
|
lacks "agents/code-cleaner.md" 'AskUserQuestion'
|
||||||
|
|
||||||
|
printf 'model-routing census: %d pass, %d fail\n' "$pass" "$fail"
|
||||||
|
[ "$fail" -eq 0 ]
|
||||||
@@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
Runs in the ORCHESTRATOR MAIN LOOP after the dev step completes. Turns a
|
Runs in the ORCHESTRATOR MAIN LOOP after the dev step completes. Turns a
|
||||||
finished diff into a verified, security-cleared change through two fresh
|
finished diff into a verified, security-cleared change through two fresh
|
||||||
gates and bounded loops. The dev stays inline (LRN-083: subagents =
|
gates and bounded loops. Loop decisions live here, in the main loop
|
||||||
execution + report; loop decisions live here, in the main loop).
|
(LRN-083: subagents = execution + report). The dev step is a dispatched
|
||||||
|
sonnet executor (feat's `feater`, bugfix's `bugfixer`): "hand the dev"
|
||||||
|
below means re-dispatch a FRESH executor with exactly those inputs.
|
||||||
|
|
||||||
Inputs the caller must have ready:
|
Inputs the caller must have ready:
|
||||||
- `CONTRACT`: path to the contract file written by `contract-interview.md`.
|
- `CONTRACT`: path to the contract file written by `contract-interview.md`.
|
||||||
@@ -25,7 +27,8 @@ Parse its single `VERIFY — VERDICT:` line:
|
|||||||
|
|
||||||
- `CONFORME` → go to GATE 2. (First-pass conforme = no loop.)
|
- `CONFORME` → go to GATE 2. (First-pass conforme = no loop.)
|
||||||
- `ECARTS(n)` → hand the dev the CONTRACT path + the exact `CRITERIA` gap
|
- `ECARTS(n)` → hand the dev the CONTRACT path + the exact `CRITERIA` gap
|
||||||
lines (NOT-MET / out-of-scope), nothing else. Dev fixes inline, then
|
lines (NOT-MET / out-of-scope), nothing else. Inline dev fixes in place;
|
||||||
|
a dispatched dev is re-dispatched FRESH with those inputs only. Then
|
||||||
re-dispatch a FRESH verifier. Repeat. **Max 3 conformity iterations** →
|
re-dispatch a FRESH verifier. Repeat. **Max 3 conformity iterations** →
|
||||||
STOP + human escalation with the CRITERIA table (the contract-vs-realized
|
STOP + human escalation with the CRITERIA table (the contract-vs-realized
|
||||||
diff).
|
diff).
|
||||||
@@ -49,8 +52,8 @@ stdout-only, no Write).
|
|||||||
Parse its single `SECURITY — VERDICT:` line:
|
Parse its single `SECURITY — VERDICT:` line:
|
||||||
|
|
||||||
- `PASS` → done, proceed to commit.
|
- `PASS` → done, proceed to commit.
|
||||||
- `BLOCK(n)` → hand the dev the `BLOCKING` list + the CONTRACT path. Dev
|
- `BLOCK(n)` → hand the dev the `BLOCKING` list + the CONTRACT path (inline
|
||||||
fixes inline. Then **re-verify the REQUEST first** (GATE 1, fresh
|
fix, or FRESH executor re-dispatch). Then **re-verify the REQUEST first** (GATE 1, fresh
|
||||||
verifier) — a security fix can drift the behavior — **then re-run GATE 2**
|
verifier) — a security fix can drift the behavior — **then re-run GATE 2**
|
||||||
(fresh auditor), in that order. **Max 3 security iterations** → STOP +
|
(fresh auditor), in that order. **Max 3 security iterations** → STOP +
|
||||||
human escalation with the BLOCKING table.
|
human escalation with the BLOCKING table.
|
||||||
|
|||||||
@@ -22,6 +22,13 @@ allowed-tools:
|
|||||||
|
|
||||||
# /audit-delta — Incremental multi-axis code audit
|
# /audit-delta — Incremental multi-axis code audit
|
||||||
|
|
||||||
|
## MODEL GATE (blocking — run before any other step)
|
||||||
|
|
||||||
|
Run `$HOME/.claude/lib/model-gate.md`. Reflection here (planning, audit
|
||||||
|
judgment, loop decisions) requires Fable/Opus. Verdict `small` → STOP: the
|
||||||
|
gate prints the remedy; end the turn — no later step, no dispatch. Nominal
|
||||||
|
(big) path is silent.
|
||||||
|
|
||||||
Audit only what changed since the last run, on the axes the user picks.
|
Audit only what changed since the last run, on the axes the user picks.
|
||||||
Per axis: **audit → approval gate → fix → re-verify → marker update**,
|
Per axis: **audit → approval gate → fix → re-verify → marker update**,
|
||||||
strictly in that order, one axis fully closed before the next starts.
|
strictly in that order, one axis fully closed before the next starts.
|
||||||
|
|||||||
+245
-3
@@ -20,9 +20,251 @@ allowed-tools:
|
|||||||
- Agent
|
- Agent
|
||||||
---
|
---
|
||||||
|
|
||||||
Load and follow strictly:
|
# /bugfix — root-cause orchestrator (reflection inline, execution dispatched)
|
||||||
- $HOME/.claude/agents/bugfixer.md
|
|
||||||
|
|
||||||
Execute the BUGFIXER agent on the following target:
|
MODEL GATE (blocking): run `$HOME/.claude/lib/model-gate.md` BEFORE any
|
||||||
|
step below. Verdict `small` → STOP — print the gate's remedy, end the
|
||||||
|
turn, dispatch nothing.
|
||||||
|
|
||||||
|
## REQUEST
|
||||||
$ARGUMENTS
|
$ARGUMENTS
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 1 — GATHER CONTEXT
|
||||||
|
|
||||||
|
Understand the current state:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status
|
||||||
|
git log --oneline -5
|
||||||
|
```
|
||||||
|
|
||||||
|
Read the error message, stack trace, or bug description.
|
||||||
|
Identify:
|
||||||
|
- **What** is broken (symptom)
|
||||||
|
- **Where** it manifests (file, line, endpoint, UI element)
|
||||||
|
- **When** it started (recent commit? always? after a deploy?)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# If the user mentions "it was working before":
|
||||||
|
git log --oneline -20 --all -- <suspected files>
|
||||||
|
```
|
||||||
|
|
||||||
|
## STEP 1.5 — DESIGN GATE
|
||||||
|
|
||||||
|
Follow `$HOME/.claude/lib/design-gate.md`:
|
||||||
|
- Scan $ARGUMENTS and target files for design/UI/style signals (CSS, component, layout, animation).
|
||||||
|
- If signals found → run `design-tool-gate.sh`; if it reports INCOMPLETE,
|
||||||
|
tell the user to run `/profile design` before proceeding.
|
||||||
|
- If no signals → skip (zero overhead).
|
||||||
|
|
||||||
|
## STEP 2 — INVESTIGATE
|
||||||
|
|
||||||
|
Trace the bug from symptom to root cause:
|
||||||
|
|
||||||
|
1. Read the code path involved (follow the data flow).
|
||||||
|
2. Check recent changes to the affected files:
|
||||||
|
```bash
|
||||||
|
git log --oneline -10 -- <file>
|
||||||
|
git diff HEAD~5 -- <file> # if recent regression suspected
|
||||||
|
```
|
||||||
|
3. Look for related tests — do they pass? Do they cover
|
||||||
|
the broken case?
|
||||||
|
4. Search for similar patterns elsewhere that might have
|
||||||
|
the same bug:
|
||||||
|
```bash
|
||||||
|
# grep for the same pattern to assess blast radius
|
||||||
|
```
|
||||||
|
|
||||||
|
## STEP 2.5 — MEMORY READ-BEFORE (blockers-first)
|
||||||
|
|
||||||
|
Run the scan per `$HOME/.claude/lib/analyze-before-plan.md`, blockers-weighted: a resolved
|
||||||
|
BLK may already name THIS exact root cause; an in-force BDR may constrain the fix. Emit
|
||||||
|
RELATED MEMORY. Consumption is NATURAL — the reflection that emits this IS what writes STEP 3's
|
||||||
|
diagnosis (reader = planner, no external skill to inject into).
|
||||||
|
|
||||||
|
TEETH: STEP 3's DIAGNOSIS must name any binding prior (`PRIOR: BLK-xxx — known cause/fix`,
|
||||||
|
or `honors BDR-xxx`) OR the RELATED MEMORY line states none bears. Reading blockers then
|
||||||
|
diagnosing without naming a match is the read-then-ignore failure this prevents.
|
||||||
|
`.claude/memory/` absent → guarded no-op, proceed.
|
||||||
|
|
||||||
|
## STEP 3 — DIAGNOSE + PLAN
|
||||||
|
|
||||||
|
Present findings before dispatching a fix:
|
||||||
|
|
||||||
|
```
|
||||||
|
BUGFIX — DIAGNOSIS
|
||||||
|
BUG : <one-line symptom>
|
||||||
|
ROOT CAUSE: <what is actually wrong and why>
|
||||||
|
EVIDENCE: <what confirmed it — test, trace, diff>
|
||||||
|
BLAST RADIUS: <other places affected, or "isolated">
|
||||||
|
|
||||||
|
FIX PLAN:
|
||||||
|
1. <file:line> — <what to change>
|
||||||
|
2. <file:line> — <what to change>
|
||||||
|
[3. <test file> — add/update test for this case]
|
||||||
|
|
||||||
|
RISK: <low/medium — what could go wrong>
|
||||||
|
```
|
||||||
|
|
||||||
|
- If the root cause is still unclear after investigation,
|
||||||
|
say so explicitly. List remaining hypotheses ranked by
|
||||||
|
probability. Ask the user before proceeding.
|
||||||
|
- If the fix is trivial after investigation (1-2 lines):
|
||||||
|
proceed directly — no need to wait for approval on an
|
||||||
|
obvious fix.
|
||||||
|
- If the fix is significant (>10 lines, multiple files,
|
||||||
|
behavior change): wait for user approval.
|
||||||
|
|
||||||
|
## STEP 3.5 — CONTRACT
|
||||||
|
|
||||||
|
Run `$HOME/.claude/lib/contract-interview.md` (main loop). The DIAGNOSIS
|
||||||
|
feeds it: REQUEST verbatim = the bug report as received; ACCEPTANCE CRITERIA
|
||||||
|
= the symptom reproduced-then-gone + a regression test present and passing;
|
||||||
|
FILE SCOPE = the FIX PLAN files. Questions stay proportional (a clear,
|
||||||
|
reproduced bug → zero). It writes the contract to
|
||||||
|
`.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`; keep the path — the
|
||||||
|
executor reads it first and GATE 1 (STEP 6) hands it to a fresh verifier.
|
||||||
|
|
||||||
|
## STEP 4 — BRANCH
|
||||||
|
|
||||||
|
**Gitflow aiguillage (before dispatch):** follow `$HOME/.claude/lib/gitflow-aiguillage.md`
|
||||||
|
— your type = `bugfix`. On `main`/`develop` it branches first; on a working
|
||||||
|
branch it's a no-op (commit in place). Never `finish`.
|
||||||
|
|
||||||
|
## STEP 5 — DISPATCH EXECUTOR
|
||||||
|
|
||||||
|
Dispatch the executor — sonnet by frontmatter pin, do not override:
|
||||||
|
|
||||||
|
```
|
||||||
|
Agent(subagent_type="bugfixer")
|
||||||
|
prompt: "CONTRACT: <path from STEP 3.5>
|
||||||
|
DIAGNOSIS: <ROOT CAUSE + EVIDENCE from STEP 3>
|
||||||
|
FIX PLAN: <the STEP 3 FIX PLAN — exact edits + the regression test to add>
|
||||||
|
BRANCH: <current branch — verify with git branch --show-current, never switch>
|
||||||
|
Apply the fix to the letter + the regression test. No commit, no branch
|
||||||
|
ops, no security dispatch. Finish with the BUGFIX-EXEC REPORT."
|
||||||
|
```
|
||||||
|
|
||||||
|
Parse the `BUGFIX-EXEC REPORT`:
|
||||||
|
- `STATUS : DONE` → STEP 6.
|
||||||
|
- `STATUS : NEED-DECISION` → make the decision HERE (that is reflection),
|
||||||
|
append it to the plan, re-dispatch a FRESH bugfixer with plan + decision.
|
||||||
|
Max 2 decision round-trips → escalate to the user.
|
||||||
|
- `STATUS : BLOCKED` → surface the blocker to the user, stop.
|
||||||
|
|
||||||
|
## STEP 6 — VERIFY + SECURE + PRE-COMMIT GATE + COMMIT (main loop, LRN-083)
|
||||||
|
|
||||||
|
1. Run the two fresh gates per `$HOME/.claude/lib/verify-secure-loop.md` with
|
||||||
|
`CONTRACT` = the STEP 3.5 path, `DIFF` = the executor's working-tree diff,
|
||||||
|
`TEST` = the suite named in its report:
|
||||||
|
- GATE 1 — a FRESH verifier judges the fix against the contract (bug gone
|
||||||
|
+ regression test present). CONFORME on the first pass → straight to
|
||||||
|
GATE 2, no loop. ECARTS → the "dev" of the loop is the dispatched
|
||||||
|
executor: re-dispatch a FRESH bugfixer with the CONTRACT path + the
|
||||||
|
exact gap lines, nothing else. Max 3 → escalate.
|
||||||
|
- GATE 2 — a FRESH security-auditor (`MODE: gate`) scans the diff (a bug
|
||||||
|
fix can introduce a vuln). PASS → the pre-commit gate below. BLOCK →
|
||||||
|
re-dispatch a FRESH bugfixer with the BLOCKING list + the CONTRACT
|
||||||
|
path; re-verify the request THEN re-scan, max 3 → escalate.
|
||||||
|
|
||||||
|
Loop decisions stay HERE, in the main loop (LRN-083). Nominal = one
|
||||||
|
executor + one verifier + one security dispatch.
|
||||||
|
|
||||||
|
2. **Pre-commit confirmation gate.** Before running `git commit`, present the diff
|
||||||
|
summary and the proposed message, then wait for approval:
|
||||||
|
|
||||||
|
```
|
||||||
|
BUGFIX — READY TO COMMIT
|
||||||
|
FILE(S) : <list>
|
||||||
|
DIFF : <git diff --stat>
|
||||||
|
MESSAGE :
|
||||||
|
fix(<scope>): <root cause description>
|
||||||
|
|
||||||
|
<what was wrong and why>
|
||||||
|
<what the fix does>
|
||||||
|
|
||||||
|
Commit now? (yes / edit message / skip / amend last)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `yes` → run `git commit`.
|
||||||
|
- `edit message` → user provides corrected message; redraw gate.
|
||||||
|
- `skip` → leave changes uncommitted, exit cleanly.
|
||||||
|
- `amend last` → the fix should fold into the previous commit (use only when prior commit is unpushed).
|
||||||
|
|
||||||
|
3. Commit using conventional format (after approval):
|
||||||
|
```
|
||||||
|
fix(<scope>): <root cause description>
|
||||||
|
|
||||||
|
<what was wrong and why>
|
||||||
|
<what the fix does>
|
||||||
|
```
|
||||||
|
4. Print summary:
|
||||||
|
```
|
||||||
|
BUGFIX COMPLETE
|
||||||
|
BUG : <symptom>
|
||||||
|
ROOT CAUSE : <one-line>
|
||||||
|
FILE(S) : <changed files>
|
||||||
|
TEST(S) : <added/updated tests, or "none — verified manually">
|
||||||
|
REGRESSION : <checked areas>
|
||||||
|
```
|
||||||
|
|
||||||
|
## STEP 7 — DOC SYNC (automatic)
|
||||||
|
|
||||||
|
Load `$HOME/.claude/agents/doc-syncer.md`.
|
||||||
|
Execute in automatic mode:
|
||||||
|
`auto-mode scope: <list of files modified during this session>`
|
||||||
|
|
||||||
|
**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
|
||||||
|
`.claude/`/`CLAUDE.md` (rc 4 = a loud BDR-022 anomaly, not a silent skip), and no-ops when
|
||||||
|
nothing was patched — the common case for a trivial change. No FINISH in an inline flow, so
|
||||||
|
it just commits the docs on the current branch (no ordering concern).
|
||||||
|
|
||||||
|
## STEP 8 — CAPITALIZE (memory registries)
|
||||||
|
|
||||||
|
A bugfix with an understood root cause is almost always worth one entry:
|
||||||
|
|
||||||
|
1. Propose a `BLK-XXX` entry in `.claude/memory/blockers.md` pre-filled from STEP 3 diagnosis:
|
||||||
|
- `friction` = symptom
|
||||||
|
- `real_cause` = root cause identified
|
||||||
|
- `solution` = the fix applied
|
||||||
|
- `status` = resolved
|
||||||
|
2. If the root cause exposed a **reusable pattern** (would catch the same bug elsewhere or in other projects) → also propose an `LRN-XXX` entry in `.claude/memory/learnings.md`.
|
||||||
|
3. Present as:
|
||||||
|
```
|
||||||
|
CAPITALIZE — proposé
|
||||||
|
BLK-XXX — <friction> — resolved
|
||||||
|
[LRN-XXX — <pattern>] (optionnel)
|
||||||
|
Valider ? (all / blockers-only / edit / skip)
|
||||||
|
```
|
||||||
|
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.
|
||||||
|
|
||||||
|
If the bug was trivial and the root cause not transferable → skip with `CAPITALIZE: trivial, skip`.
|
||||||
|
|
||||||
|
**Then commit the memory** — follow `$HOME/.claude/lib/capitalize-commit.md`: it
|
||||||
|
surgically commits what capitalize just wrote (`.claude/memory` + `.claude/tasks`
|
||||||
|
only, never `git add -A`) as one `chore(memory)` commit, reports the memory-commit
|
||||||
|
hash, and no-ops if nothing was written.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## RULES
|
||||||
|
- 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).
|
||||||
|
- 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.
|
||||||
|
- Design gate only if UI/style signals detected. See STEP 1.5.
|
||||||
|
- If investigation reveals a design flaw requiring significant
|
||||||
|
refactoring → stop, explain, suggest `/ship-feature` for the
|
||||||
|
proper fix.
|
||||||
|
- Always add a regression test when possible.
|
||||||
|
- Keep the fix scoped. No "while we're here" cleanups.
|
||||||
|
- If >5 files need changes → reconsider if `/ship-feature`
|
||||||
|
is more appropriate.
|
||||||
|
|||||||
+186
-3
@@ -20,9 +20,192 @@ allowed-tools:
|
|||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
Load and follow strictly:
|
# /code-clean — cleanup orchestrator (audit inline, execution dispatched)
|
||||||
- $HOME/.claude/agents/code-cleaner.md
|
|
||||||
|
|
||||||
Execute the CODE-CLEANER agent on the following target:
|
MODEL GATE (blocking): run `$HOME/.claude/lib/model-gate.md` BEFORE any
|
||||||
|
step below. Verdict `small` → STOP — print the gate's remedy, end the
|
||||||
|
turn, dispatch nothing.
|
||||||
|
|
||||||
|
## TARGET
|
||||||
$ARGUMENTS
|
$ARGUMENTS
|
||||||
|
|
||||||
|
If blank → entire project from repository root.
|
||||||
|
|
||||||
|
The audit (STEPS 1-3) runs inline, on the session model — reading code and
|
||||||
|
judging severity is reflection. Once the user approves a scope (STEP 4),
|
||||||
|
execution is dispatched to the sonnet-pinned `code-cleaner` executor
|
||||||
|
(STEP 5). The iron law is unchanged across both halves: zero behavior
|
||||||
|
change — identical observable output before and after.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 1 — LOAD PROJECT NORMS
|
||||||
|
|
||||||
|
Read the project's coding standards in this priority order:
|
||||||
|
|
||||||
|
1. `CLAUDE.md` at project root (primary authority)
|
||||||
|
2. Language/framework config files present in the repo:
|
||||||
|
- JS/TS: `.eslintrc*`, `.prettierrc*`, `tsconfig.json`
|
||||||
|
- Python: `pyproject.toml`, `setup.cfg`, `.flake8`, `ruff.toml`
|
||||||
|
- PHP: `phpcs.xml`, `.php-cs-fixer.php`
|
||||||
|
- Go: `.golangci.yml`
|
||||||
|
- General: `.editorconfig`
|
||||||
|
3. If neither CLAUDE.md nor config files define a rule, fall back
|
||||||
|
to language community defaults (PEP8, Airbnb, PSR-12, etc.)
|
||||||
|
|
||||||
|
CLAUDE.md rules always win over tool configs when they conflict.
|
||||||
|
|
||||||
|
## STEP 2 — SCAN
|
||||||
|
|
||||||
|
Systematically scan the target for three categories of issues.
|
||||||
|
|
||||||
|
**A. Dead code**
|
||||||
|
- Unused imports and variables
|
||||||
|
- Unused functions/methods (not exported, no callers)
|
||||||
|
- Unreachable code blocks (after return, break, etc.)
|
||||||
|
- Commented-out code blocks (more than 2 consecutive lines)
|
||||||
|
- TODO/FIXME comments older than 90 days (check with `git log`)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check age of TODO/FIXME comments
|
||||||
|
git log --all -p --reverse -S "TODO" -- <file> | head -40
|
||||||
|
```
|
||||||
|
|
||||||
|
**B. Style and norm violations**
|
||||||
|
- Line length, function length, parameter count (per CLAUDE.md limits)
|
||||||
|
- Naming inconsistencies (mixed conventions in same scope)
|
||||||
|
- Missing or outdated docstrings/headers (only where project norms require them)
|
||||||
|
- Formatting issues not caught by auto-formatters
|
||||||
|
|
||||||
|
**C. Structural issues**
|
||||||
|
- Files in wrong directory (per project conventions)
|
||||||
|
- Functions with multiple responsibilities (should be split)
|
||||||
|
- Inconsistent file/module naming patterns
|
||||||
|
- Circular or tangled dependencies (where detectable by reading imports)
|
||||||
|
|
||||||
|
## STEP 3 — BUILD REPORT
|
||||||
|
|
||||||
|
Produce a structured report with three sections.
|
||||||
|
Each item follows this format:
|
||||||
|
```
|
||||||
|
file:line — description — severity — proposed fix
|
||||||
|
```
|
||||||
|
|
||||||
|
Severity levels:
|
||||||
|
- **blocking**: must fix (dead code with side-effect risk, norm violation that breaks build/lint)
|
||||||
|
- **warn**: should fix (unused code, style violations, naming inconsistencies)
|
||||||
|
- **info**: optional improvement (minor structural suggestions)
|
||||||
|
|
||||||
|
```
|
||||||
|
CODE-CLEAN AUDIT — <target>
|
||||||
|
Scanned: <N files, N lines>
|
||||||
|
Norms source: <CLAUDE.md / .eslintrc / PEP8 fallback / etc.>
|
||||||
|
|
||||||
|
═══ DEAD CODE ═══
|
||||||
|
1. src/utils.py:42 — unused import `os` — warn — delete import
|
||||||
|
2. src/api/handler.ts:118-134 — commented-out block — warn — delete block
|
||||||
|
3. ...
|
||||||
|
|
||||||
|
═══ STYLE VIOLATIONS ═══
|
||||||
|
1. src/core/parser.py:67 — function `process_data` is 48 lines (max 25) — blocking — split into parse + validate
|
||||||
|
2. ...
|
||||||
|
|
||||||
|
═══ STRUCTURAL ISSUES ═══
|
||||||
|
1. lib/helpers/auth.ts — auth logic in helpers/, should be in lib/auth/ — info — move file
|
||||||
|
2. ...
|
||||||
|
|
||||||
|
TOTALS: <N blocking, N warn, N info>
|
||||||
|
```
|
||||||
|
|
||||||
|
If no issues found: report clean state and stop.
|
||||||
|
|
||||||
|
## STEP 4 — VALIDATION GATE (interactive)
|
||||||
|
|
||||||
|
Present the report from STEP 3. Then ask:
|
||||||
|
|
||||||
|
```
|
||||||
|
AskUserQuestion:
|
||||||
|
Approve which items for execution? (all / <item numbers> / clarify <item>)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `all` → every item in the report is approved for execution.
|
||||||
|
- `<item numbers>` (e.g. `A1,A3,B2`) → only those items are approved; the
|
||||||
|
rest stay untouched.
|
||||||
|
- `clarify <item>` → discuss the item, then re-ask.
|
||||||
|
|
||||||
|
**Exported / public-API symbols**: any dead-code item flagged as exported or
|
||||||
|
part of a public API requires EXPLICIT per-item confirmation before it can
|
||||||
|
be approved — even if it appears unused internally. Ask for it by name; do
|
||||||
|
not fold it into a blanket `all`. This consent lives HERE, at the gate —
|
||||||
|
the dispatched executor never asks, it only executes what this step already
|
||||||
|
cleared.
|
||||||
|
|
||||||
|
**Do NOT proceed to STEP 5 until the user explicitly approves.** If nothing
|
||||||
|
is approved, stop — no dispatch.
|
||||||
|
|
||||||
|
## STEP 5 — PERSIST SCOPE + DISPATCH
|
||||||
|
|
||||||
|
1. **Persist the approved scope.** Write the approved items to
|
||||||
|
`.claude/audits/CODE-CLEAN-SCOPE.md` (run `mkdir -p .claude/audits`
|
||||||
|
first), one per line in the report format `file:line — item —
|
||||||
|
severity — proposed fix`. This is the executor's scope-of-work on
|
||||||
|
disk — named, auditable, the same contract discipline as the dev
|
||||||
|
gates (verifier reads its contract from disk).
|
||||||
|
2. **Dispatch the executor** — sonnet by frontmatter pin, do not override:
|
||||||
|
|
||||||
|
```
|
||||||
|
Agent(subagent_type="code-cleaner")
|
||||||
|
prompt: "SCOPE: .claude/audits/CODE-CLEAN-SCOPE.md
|
||||||
|
APPROVED: <the approved item list, incl. any per-item exported-symbol clears>
|
||||||
|
BRANCH: <current branch — verify with git branch --show-current, never switch>
|
||||||
|
Execute PHASE 2 on the approved scope only. Zero behavior change. No commit.
|
||||||
|
Finish with the CODE-CLEAN-EXEC REPORT."
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Parse the `CODE-CLEAN-EXEC REPORT`:
|
||||||
|
- `STATUS : DONE` → STEP 6.
|
||||||
|
- `STATUS : BLOCKED` → surface the blocker to the user, stop.
|
||||||
|
|
||||||
|
## STEP 6 — SUMMARY
|
||||||
|
|
||||||
|
Translate the executor's `CODE-CLEAN-EXEC REPORT` into the user-facing
|
||||||
|
summary:
|
||||||
|
|
||||||
|
```
|
||||||
|
CODE-CLEAN COMPLETE — <target>
|
||||||
|
|
||||||
|
REMOVED:
|
||||||
|
- <N> dead code items (unused imports, functions, commented blocks)
|
||||||
|
|
||||||
|
REFACTORED:
|
||||||
|
- <N> style fixes
|
||||||
|
- <N> structural improvements
|
||||||
|
|
||||||
|
SKIPPED (user decision):
|
||||||
|
- <item> — <reason>
|
||||||
|
|
||||||
|
BUGS FOUND: <N> (logged to .claude/audits/BUGS-FOUND.md)
|
||||||
|
|
||||||
|
TESTS: passing / no test suite / <failures>
|
||||||
|
```
|
||||||
|
|
||||||
|
No commit here — code-clean has never auto-committed. Leave the working
|
||||||
|
tree for the user, or a follow-up `/commit-change`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## RULES
|
||||||
|
|
||||||
|
- Zero behavior change. If unsure whether a deletion changes behavior,
|
||||||
|
leave it and flag it — never guess.
|
||||||
|
- No "while we're here" scope creep. Only items approved at STEP 4 reach
|
||||||
|
the executor.
|
||||||
|
- Exported/public API symbols require explicit per-item user consent AT
|
||||||
|
THE GATE (STEP 4) before approval — even if they appear unused. The
|
||||||
|
executor never asks; it only executes what the gate already cleared.
|
||||||
|
- Bugs go to `.claude/audits/BUGS-FOUND.md`, not fixed in this workflow.
|
||||||
|
- If the codebase has no tests and the changes are non-trivial, warn the
|
||||||
|
user about the risk before dispatching.
|
||||||
|
- No plugin check (lightweight skill).
|
||||||
|
- If the audit reveals systemic issues requiring architecture changes,
|
||||||
|
stop and suggest `/ship-feature` for a proper redesign.
|
||||||
|
|||||||
@@ -16,15 +16,102 @@ allowed-tools:
|
|||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
Load and follow strictly: `$HOME/.claude/agents/commit-changer.md`.
|
# /commit-change — propose → confirm → apply dispatcher
|
||||||
|
|
||||||
If unreachable, emit `Commit-changer agent missing.` and STOP. Never auto-commit blind — a wrong group is harder to undo than not committing.
|
Grouping and committing both run on the sonnet-pinned `commit-changer`
|
||||||
|
subagent (dispatch makes the pin effective). No inline reflection happens
|
||||||
|
in this dispatcher to protect, so there is no model gate. This dispatcher
|
||||||
|
owns the two approval gates that used to live inside the subagent:
|
||||||
|
commit-plan approval and capitalize approval — the subagent never asks;
|
||||||
|
`MODE: propose` only proposes, `MODE: apply` only executes what this
|
||||||
|
dispatcher confirms. Never auto-commit blind — a wrong group is harder to
|
||||||
|
undo than not committing.
|
||||||
|
|
||||||
Pre-flight checks (the agent should also perform, but flag here):
|
## STEP 0 — Pre-flight (STOP conditions, before any dispatch)
|
||||||
- Detached HEAD or unmerged conflicts → STOP, report state.
|
|
||||||
- Identity unconfigured (`git config user.email` empty) → STOP, ask user.
|
|
||||||
- On a protected base (`main`/`develop`) the agent runs the gitflow
|
|
||||||
aiguillage (Phase 0) and branches to `chore/*` before committing — code
|
|
||||||
never lands directly on a protected branch.
|
|
||||||
|
|
||||||
$ARGUMENTS
|
```bash
|
||||||
|
git rev-parse --abbrev-ref HEAD # "HEAD" = detached
|
||||||
|
git status --porcelain=v1 | grep -c '^UU\|^AA\|^DD' # unmerged conflicts
|
||||||
|
git status --porcelain=v1 | wc -l # nothing pending?
|
||||||
|
git config user.email
|
||||||
|
```
|
||||||
|
|
||||||
|
- Detached HEAD → STOP, report the state, do not dispatch.
|
||||||
|
- Any unmerged conflict entries (`UU`/`AA`/`DD`) → STOP, tell the user to
|
||||||
|
resolve conflicts first, do not dispatch.
|
||||||
|
- Nothing pending (`git status --porcelain` empty) → STOP, tell the user
|
||||||
|
there's nothing to commit.
|
||||||
|
- `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.
|
||||||
|
|
||||||
|
## STEP 1 — Propose
|
||||||
|
|
||||||
|
```
|
||||||
|
Agent(subagent_type="commit-changer")
|
||||||
|
prompt: "MODE: propose
|
||||||
|
$ARGUMENTS"
|
||||||
|
```
|
||||||
|
|
||||||
|
Read the returned `COMMIT PLAN` + `EDGE CASES` + `CAPITALIZE CANDIDATES`,
|
||||||
|
terminated by `READY TO APPLY — awaiting dispatcher confirmation`.
|
||||||
|
|
||||||
|
The subagent reported `BLOCKED: unresolved merge conflicts...` instead of a
|
||||||
|
plan (a race with STEP 0) → STOP, surface it, do not proceed.
|
||||||
|
|
||||||
|
## STEP 2 — Gate 1: commit-plan approval
|
||||||
|
|
||||||
|
Show the `COMMIT PLAN` and any `EDGE CASES` verbatim, then:
|
||||||
|
|
||||||
|
```
|
||||||
|
AskUserQuestion:
|
||||||
|
Approve the commit plan? (all / <numbers> / edit <n> / skip)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `all` → every step in the plan is approved as-is.
|
||||||
|
- `<numbers>` (e.g. `1,3`) → only those steps are approved; the rest stay
|
||||||
|
uncommitted for a later run.
|
||||||
|
- `edit <n>` → re-dispatch `commit-changer` with `MODE: propose` and the
|
||||||
|
user's correction for step N folded into the prompt, so all grouping /
|
||||||
|
message judgment stays on the sonnet subagent (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
|
||||||
|
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.
|
||||||
|
|
||||||
|
## STEP 3 — Gate 2: capitalize approval
|
||||||
|
|
||||||
|
If the STEP 1 output said `CAPITALIZE: nothing to log`, skip this gate —
|
||||||
|
treat the capitalize entries as `none` and go straight to STEP 4.
|
||||||
|
|
||||||
|
Otherwise show the `CAPITALIZE CANDIDATES` block, then:
|
||||||
|
|
||||||
|
```
|
||||||
|
AskUserQuestion:
|
||||||
|
Valider les entrées mémoire ? (all / <IDs> / skip)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `all` → every candidate entry is approved verbatim.
|
||||||
|
- `<IDs>` (e.g. `BDR-041,LRN-019`) → only those entries are approved.
|
||||||
|
- `skip` → no memory write; `MODE: apply` still runs for the code commits.
|
||||||
|
|
||||||
|
## STEP 4 — Apply
|
||||||
|
|
||||||
|
```
|
||||||
|
Agent(subagent_type="commit-changer")
|
||||||
|
prompt: "MODE: apply
|
||||||
|
APPROVED PLAN: <the STEP-2-approved steps — numbers, messages, files,
|
||||||
|
exactly as confirmed, including any edits>
|
||||||
|
APPROVED CAPITALIZE ENTRIES: <the STEP-3-approved entries verbatim, or none>"
|
||||||
|
```
|
||||||
|
|
||||||
|
Parse the `COMMIT-EXEC REPORT`:
|
||||||
|
- `STATUS: DONE` → report the `COMMITS` + `MEMORY` hashes to the user.
|
||||||
|
- `STATUS: BLOCKED` → surface the blocker verbatim and stop. Do not retry
|
||||||
|
automatically — a blocked step (e.g. one file needs an interactive
|
||||||
|
`git add -p` split) needs a human decision.
|
||||||
|
|||||||
+9
-5
@@ -15,12 +15,16 @@ allowed-tools:
|
|||||||
- Bash
|
- Bash
|
||||||
- Grep
|
- Grep
|
||||||
- Glob
|
- Glob
|
||||||
|
- Agent
|
||||||
---
|
---
|
||||||
|
|
||||||
Load and follow strictly:
|
Dispatch the doc-syncer as a subagent so its `model: sonnet` pin takes
|
||||||
- $HOME/.claude/agents/doc-syncer.md
|
effect (doc-sync = execution, not the session's big model):
|
||||||
|
|
||||||
Execute the DOC SYNCER on this project.
|
Agent(subagent_type="doc-syncer")
|
||||||
|
prompt: "Audit + sync public docs for this project. Context from the user:
|
||||||
|
$ARGUMENTS. Report PATCHED_FILES and a summary — do NOT commit."
|
||||||
|
|
||||||
Context from the user (if any):
|
Then commit the patched docs from THIS loop per `$HOME/.claude/lib/doc-commit.md`
|
||||||
$ARGUMENTS
|
(surgical: only doc-syncer's PATCHED_FILES, never `.claude/`/`CLAUDE.md`,
|
||||||
|
no-op if nothing patched).
|
||||||
|
|||||||
+221
-7
@@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
name: feat
|
name: feat
|
||||||
description: |
|
description: |
|
||||||
Small feature implementation (1-5 files). Light planning, direct
|
Small feature implementation (1-5 files). Reflection inline (scope,
|
||||||
implementation, no heavy orchestration. For features that don't
|
plan, contract — session model), execution dispatched to the
|
||||||
need the full /ship-feature pipeline (no design brainstorm, no
|
sonnet-pinned feater executor. For features that don't need the full
|
||||||
subagents, no plugin check gate).
|
/ship-feature pipeline (no design brainstorm, no plugin check gate).
|
||||||
Trigger: "feat", "small feature", "add this", "petite feature",
|
Trigger: "feat", "small feature", "add this", "petite feature",
|
||||||
"quick feature", "ajoute ca", "implement this small thing".
|
"quick feature", "ajoute ca", "implement this small thing".
|
||||||
For multi-file features needing design → use /ship-feature.
|
For multi-file features needing design → use /ship-feature.
|
||||||
@@ -20,9 +20,223 @@ allowed-tools:
|
|||||||
- Agent
|
- Agent
|
||||||
---
|
---
|
||||||
|
|
||||||
Load and follow strictly:
|
# /feat — small-feature orchestrator (reflection inline, execution dispatched)
|
||||||
- $HOME/.claude/agents/feater.md
|
|
||||||
|
|
||||||
Execute the FEATER agent on the following target:
|
MODEL GATE (blocking): run `$HOME/.claude/lib/model-gate.md` BEFORE any
|
||||||
|
step below. Verdict `small` → STOP — print the gate's remedy, end the
|
||||||
|
turn, dispatch nothing.
|
||||||
|
|
||||||
|
## REQUEST
|
||||||
$ARGUMENTS
|
$ARGUMENTS
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 0 — SCOPE CHECK
|
||||||
|
|
||||||
|
Before starting, verify this is actually a small feature:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status
|
||||||
|
git log --oneline -3
|
||||||
|
```
|
||||||
|
|
||||||
|
Read the relevant existing code to understand the context.
|
||||||
|
|
||||||
|
### Decision rules (apply in order — first match wins)
|
||||||
|
|
||||||
|
| Rule | Trigger | Action |
|
||||||
|
|---|---|---|
|
||||||
|
| 1 | Estimated diff < 2 files AND no logic (config value, copy fix, missing field) | DOWNGRADE → route to `/hotfix` (its orchestrator does LOCATE + dispatches the hotfixer executor; never load the bare agent file) |
|
||||||
|
| 2 | New external dependency (`npm install <x>`, `pip install`, `cargo add`) required | ESCALATE → `/ship-feature` (dep choices need design gate) |
|
||||||
|
| 3 | New route family / new top-level module / new DB migration | ESCALATE → `/ship-feature` |
|
||||||
|
| 4 | Estimated diff > 5 files | ESCALATE → `/ship-feature` |
|
||||||
|
| 5 | User wording is uncertain ("not sure how", "what do you think") | ESCALATE → `/ship-feature` (needs brainstorming) |
|
||||||
|
| 6 | UI feature on a stack with a design system AND the design toolchain incomplete | Proceed in `/feat`, but flag it in STEP 0.5 design gate |
|
||||||
|
| 7 | Otherwise | PROCEED in `/feat` |
|
||||||
|
|
||||||
|
### Worked examples
|
||||||
|
|
||||||
|
- "Add `/health` endpoint returning `{status:"ok",version}`" → 1-2 files, no new dep, route added to existing router → **PROCEED**.
|
||||||
|
- "Add a dark-mode toggle bound to `prefers-color-scheme`" → 2-3 files, design system exists → **PROCEED** (design gate triggers in STEP 0.5).
|
||||||
|
- "Add OAuth login (Google + GitHub providers)" → new deps, new routes, secrets handling → **ESCALATE** to `/ship-feature`.
|
||||||
|
- "Show a 'New' badge on items created this week" → 1-2 files, pure UI predicate → **PROCEED**.
|
||||||
|
- "Fix copy: 'Sign In' → 'Sign in'" in 1 file → **DOWNGRADE** to `/hotfix`.
|
||||||
|
|
||||||
|
Print a one-line scope confirmation (use the rule that fired):
|
||||||
|
```
|
||||||
|
FEAT: <feature name> — rule <N>, ~<N> files, <brief approach>
|
||||||
|
```
|
||||||
|
|
||||||
|
## STEP 0.5 — DESIGN GATE
|
||||||
|
|
||||||
|
Follow `$HOME/.claude/lib/design-gate.md`:
|
||||||
|
- Scan $ARGUMENTS and target files for design/UI/style signals.
|
||||||
|
- If signals found → run `design-tool-gate.sh`; if it reports INCOMPLETE,
|
||||||
|
tell the user to run `/profile design` before proceeding.
|
||||||
|
- If no signals → skip (zero overhead).
|
||||||
|
|
||||||
|
## STEP 0.6 — MEMORY READ-BEFORE (decisions-first)
|
||||||
|
|
||||||
|
Run the scan per `$HOME/.claude/lib/analyze-before-plan.md`, decisions-weighted: a BDR may
|
||||||
|
already constrain or forbid the approach; an LRN may name a gotcha to apply. Emit RELATED
|
||||||
|
MEMORY; feed STEP 1 PLAN. Inline consumption — reader = planner, no injection.
|
||||||
|
`.claude/memory/` absent → guarded no-op (zero overhead on a memory-less repo).
|
||||||
|
|
||||||
|
## STEP 0.7 — CONTRACT
|
||||||
|
|
||||||
|
Run `$HOME/.claude/lib/contract-interview.md` (main loop — you are it). It
|
||||||
|
captures the request verbatim, asks 0-3 questions PROPORTIONAL to ambiguity
|
||||||
|
(a complete request → zero questions, silent), derives testable acceptance
|
||||||
|
criteria + file scope, and writes the contract to
|
||||||
|
`.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`. Keep the path — the
|
||||||
|
executor reads it first and GATE 1 (STEP 4) hands it to a fresh verifier.
|
||||||
|
|
||||||
|
## STEP 1 — PLAN (dispatch-ready)
|
||||||
|
|
||||||
|
The executor follows this plan to the letter and CANNOT ask questions —
|
||||||
|
close every decision here:
|
||||||
|
|
||||||
|
1. Files to create or modify (with line references).
|
||||||
|
2. Approach in 2-5 bullets — name every choice (naming, data shape, API
|
||||||
|
surface); an open choice left here comes back as a NEED-DECISION
|
||||||
|
round-trip.
|
||||||
|
3. Edge cases to handle.
|
||||||
|
4. Tests to add/update (exact files).
|
||||||
|
5. Disposition (from STEP 0.6): name each in-force BDR/LRN this plan honors
|
||||||
|
(`honors BDR-xxx by …`), or state `no in-force decision constrains this feature`.
|
||||||
|
A plan with neither = read-then-ignore; the disposition must surface as a trace.
|
||||||
|
|
||||||
|
Print the plan as a compact checklist:
|
||||||
|
```
|
||||||
|
PLAN:
|
||||||
|
[ ] <file> — <what to do>
|
||||||
|
[ ] <file> — <what to do>
|
||||||
|
[ ] <test file> — <test to add>
|
||||||
|
```
|
||||||
|
|
||||||
|
If the approach is ambiguous: ask the user ONE focused question BEFORE
|
||||||
|
dispatching — never after (the executor cannot relay questions).
|
||||||
|
|
||||||
|
## STEP 2 — BRANCH
|
||||||
|
|
||||||
|
**Gitflow aiguillage (before dispatch):** follow `$HOME/.claude/lib/gitflow-aiguillage.md`
|
||||||
|
— your type = `feature`. On `main`/`develop` it branches first; on a working
|
||||||
|
branch it's a no-op (commit in place). Never `finish`.
|
||||||
|
|
||||||
|
## STEP 3 — DISPATCH EXECUTOR
|
||||||
|
|
||||||
|
Dispatch the executor — sonnet by frontmatter pin, do not override:
|
||||||
|
|
||||||
|
```
|
||||||
|
Agent(subagent_type="feater")
|
||||||
|
prompt: "CONTRACT: <path from STEP 0.7>
|
||||||
|
PLAN: <the STEP 1 checklist + approach bullets + edge cases, verbatim>
|
||||||
|
BRANCH: <current branch — verify with git branch --show-current, never switch>
|
||||||
|
Implement the plan to the letter. Tests alongside code. No commit, no
|
||||||
|
branch ops, no new dependencies, no files outside the contract FILE SCOPE.
|
||||||
|
Finish with the FEAT-EXEC REPORT."
|
||||||
|
```
|
||||||
|
|
||||||
|
Parse the `FEAT-EXEC REPORT`:
|
||||||
|
- `STATUS : DONE` → STEP 4.
|
||||||
|
- `STATUS : NEED-DECISION` → make the decision HERE (that is reflection),
|
||||||
|
append it to the plan, re-dispatch a FRESH feater with plan + decision.
|
||||||
|
Max 2 decision round-trips → escalate to the user.
|
||||||
|
- `STATUS : BLOCKED` → surface the blocker to the user, stop.
|
||||||
|
|
||||||
|
## STEP 4 — VERIFY + SECURE (fresh gates, bounded loops)
|
||||||
|
|
||||||
|
Run the two fresh gates per `$HOME/.claude/lib/verify-secure-loop.md` with
|
||||||
|
`CONTRACT` = the STEP 0.7 path, `DIFF` = the working-tree diff the executor
|
||||||
|
produced, `TEST` = the suite named in its report:
|
||||||
|
|
||||||
|
- GATE 1 — a FRESH verifier judges the diff against the contract (blind).
|
||||||
|
CONFORME on the first pass → straight to GATE 2, no loop. ECARTS → the
|
||||||
|
"dev" of the loop is the dispatched executor: re-dispatch a FRESH feater
|
||||||
|
with the CONTRACT path + the exact gap lines, nothing else. Max 3 →
|
||||||
|
escalate.
|
||||||
|
- GATE 2 — a FRESH security-auditor (`MODE: gate`) scans the diff. PASS →
|
||||||
|
STEP 5. BLOCK → re-dispatch a FRESH feater with the BLOCKING list + the
|
||||||
|
CONTRACT path; re-verify the request THEN re-scan, max 3 → escalate.
|
||||||
|
|
||||||
|
Loop decisions stay HERE, in the main loop (LRN-083). Nominal (clear
|
||||||
|
request, conform first pass, clean diff) = one executor + one
|
||||||
|
verifier + one security dispatch.
|
||||||
|
|
||||||
|
## STEP 5 — COMMIT
|
||||||
|
|
||||||
|
Commit using conventional format:
|
||||||
|
```
|
||||||
|
feat(<scope>): <what was added>
|
||||||
|
|
||||||
|
<brief description of the feature>
|
||||||
|
```
|
||||||
|
|
||||||
|
If the feature touched multiple concerns (e.g., feature + config +
|
||||||
|
test), consider splitting into 2-3 atomic commits grouped by logical
|
||||||
|
unit — or run `/commit-change` on the pending work (it dispatches the
|
||||||
|
sonnet commit-changer; never inline-load the bare agent, it is now a
|
||||||
|
propose/apply executor).
|
||||||
|
|
||||||
|
Print summary:
|
||||||
|
```
|
||||||
|
FEAT COMPLETE
|
||||||
|
FEATURE : <name>
|
||||||
|
FILE(S) : <created/modified files>
|
||||||
|
TEST(S) : <added tests>
|
||||||
|
VERIFIED : <what was checked>
|
||||||
|
```
|
||||||
|
|
||||||
|
## STEP 6 — DOC SYNC (automatic)
|
||||||
|
|
||||||
|
Load `$HOME/.claude/agents/doc-syncer.md`.
|
||||||
|
Execute in automatic mode:
|
||||||
|
`auto-mode scope: <list of files modified during this session>`
|
||||||
|
|
||||||
|
**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
|
||||||
|
`.claude/`/`CLAUDE.md` (rc 4 = a loud BDR-022 anomaly, not a silent skip), and no-ops when
|
||||||
|
nothing was patched — the common case for a trivial change. No FINISH in an inline flow, so
|
||||||
|
it just commits the docs on the current branch (no ordering concern).
|
||||||
|
|
||||||
|
## STEP 7 — CAPITALIZE (memory registries)
|
||||||
|
|
||||||
|
A small feature may or may not involve a design choice. Scan the work for:
|
||||||
|
|
||||||
|
- **Non-trivial design choice** (even small: a library pick, a naming convention, a data-model tradeoff) → propose `BDR-XXX` in `.claude/memory/decisions.md` with alternatives considered.
|
||||||
|
- **Reusable pattern or gotcha encountered** → propose `LRN-XXX` in `.claude/memory/learnings.md`.
|
||||||
|
|
||||||
|
Present the candidates grouped:
|
||||||
|
```
|
||||||
|
CAPITALIZE — proposé
|
||||||
|
[decisions.md] BDR-XXX — <titre> (optionnel)
|
||||||
|
[learnings.md] LRN-XXX — <pattern> (optionnel)
|
||||||
|
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.
|
||||||
|
|
||||||
|
If no substantive capture candidate → skip with `CAPITALIZE: nothing to log`.
|
||||||
|
|
||||||
|
**Then commit the memory** — follow `$HOME/.claude/lib/capitalize-commit.md`: it
|
||||||
|
surgically commits what capitalize just wrote (`.claude/memory` + `.claude/tasks`
|
||||||
|
only, never `git add -A`) as one `chore(memory)` commit, reports the memory-commit
|
||||||
|
hash, and no-ops if nothing was written.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## RULES
|
||||||
|
- 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).
|
||||||
|
- 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.
|
||||||
|
- No brainstorm/design phase (if needed → `/ship-feature`).
|
||||||
|
- Keep scope tight. If scope creep happens mid-work, stop
|
||||||
|
and suggest splitting into `/feat` + follow-up task.
|
||||||
|
- Follow existing code patterns. Don't introduce new patterns
|
||||||
|
for a small feature.
|
||||||
|
|||||||
@@ -22,6 +22,13 @@ allowed-tools:
|
|||||||
|
|
||||||
# /geo — GEO (AI-search) audit + fix dispatcher
|
# /geo — GEO (AI-search) audit + fix dispatcher
|
||||||
|
|
||||||
|
## MODEL GATE (blocking — run before any other step)
|
||||||
|
|
||||||
|
Run `$HOME/.claude/lib/model-gate.md`. Reflection here (planning, audit
|
||||||
|
judgment, loop decisions) requires Fable/Opus. Verdict `small` → STOP: the
|
||||||
|
gate prints the remedy; end the turn — no later step, no dispatch. Nominal
|
||||||
|
(big) path is silent.
|
||||||
|
|
||||||
Dispatches the `geo-analyzer` subagent (audit + fix bundle), then applies
|
Dispatches the `geo-analyzer` subagent (audit + fix bundle), then applies
|
||||||
the bundle from THIS main loop at **L1** — same shape as `/web-validate`
|
the bundle from THIS main loop at **L1** — same shape as `/web-validate`
|
||||||
and `/seo`. The analyzer never edits files: it emits a `## FIX BUNDLE`
|
and `/seo`. The analyzer never edits files: it emits a `## FIX BUNDLE`
|
||||||
|
|||||||
@@ -22,6 +22,13 @@ allowed-tools:
|
|||||||
|
|
||||||
# /harden — web hardening audit
|
# /harden — web hardening audit
|
||||||
|
|
||||||
|
## MODEL GATE (blocking — run before any other step)
|
||||||
|
|
||||||
|
Run `$HOME/.claude/lib/model-gate.md`. Reflection here (planning, audit
|
||||||
|
judgment, loop decisions) requires Fable/Opus. Verdict `small` → STOP: the
|
||||||
|
gate prints the remedy; end the turn — no later step, no dispatch. Nominal
|
||||||
|
(big) path is silent.
|
||||||
|
|
||||||
This skill orchestrates a narrow-scope hardening audit: TLS + security
|
This skill orchestrates a narrow-scope hardening audit: TLS + security
|
||||||
headers + redirects + canonical + custom 404 + server configs. It
|
headers + redirects + canonical + custom 404 + server configs. It
|
||||||
reuses the `seo-analyzer` agent with a **strict scope filter** to avoid
|
reuses the `seo-analyzer` agent with a **strict scope filter** to avoid
|
||||||
|
|||||||
+180
-3
@@ -18,9 +18,186 @@ allowed-tools:
|
|||||||
- Agent
|
- Agent
|
||||||
---
|
---
|
||||||
|
|
||||||
Load and follow strictly:
|
# /hotfix — quick-fix orchestrator (reflection inline, execution dispatched)
|
||||||
- $HOME/.claude/agents/hotfixer.md
|
|
||||||
|
|
||||||
Execute the HOTFIXER agent on the following target:
|
MODEL GATE (blocking): run `$HOME/.claude/lib/model-gate.md` BEFORE any
|
||||||
|
step below. Verdict `small` → STOP — print the gate's remedy, end the
|
||||||
|
turn, dispatch nothing.
|
||||||
|
|
||||||
|
## REQUEST
|
||||||
$ARGUMENTS
|
$ARGUMENTS
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STEP 1 — LOCATE (reflection)
|
||||||
|
|
||||||
|
Find the bug. Use the description and any error message to go
|
||||||
|
straight to the source:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status
|
||||||
|
git log --oneline -3
|
||||||
|
```
|
||||||
|
|
||||||
|
- Read the relevant file(s). Confirm the root cause is obvious
|
||||||
|
and superficial (typo, wrong value, missing import, etc.).
|
||||||
|
- If the bug turns out to be deeper than expected (unclear cause,
|
||||||
|
multiple files involved, logic error): STOP and say:
|
||||||
|
"This looks deeper than a hotfix — it needs investigation. Re-run this
|
||||||
|
as `/bugfix` (root-cause investigation, then a scoped fix)."
|
||||||
|
- Settle the proposed fix HERE — the executor cannot ask questions, so the
|
||||||
|
exact edit (what changes, in which file(s)) must be closed before dispatch.
|
||||||
|
|
||||||
|
OPTIONAL — memory check (exempt by default; hotfix = obvious fix, mirror of its capitalize
|
||||||
|
skip). For a RECURRING or urgent bug only, a quick blockers-only glance may save time:
|
||||||
|
|
||||||
|
[ -d .claude/memory ] && grep -nE '^## BLK-' .claude/memory/blockers.md # "déjà vu ?"
|
||||||
|
|
||||||
|
If a prior BLK names this bug, jump to its solution. Not mandatory; no RELATED MEMORY
|
||||||
|
disposition required at hotfix weight.
|
||||||
|
|
||||||
|
## STEP 1.5 — DESIGN GATE
|
||||||
|
|
||||||
|
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.
|
||||||
|
- If no signals → skip (zero overhead).
|
||||||
|
|
||||||
|
## STEP 1.7 — CONTRACT (silent autofill)
|
||||||
|
|
||||||
|
Run `$HOME/.claude/lib/contract-interview.md` at hotfix weight: **zero
|
||||||
|
questions ever** (a hotfix is an obvious fix by definition). Autofill the
|
||||||
|
contract — REQUEST verbatim = the bug description as given; ACCEPTANCE
|
||||||
|
CRITERIA = "symptom gone; build/tests green"; FILE SCOPE = the 1-2 target
|
||||||
|
files from STEP 1. It writes `.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`.
|
||||||
|
This is the reference the executor reads first, and the scope for STEP 4's
|
||||||
|
security gate and the escalation report if a gate fails. No verifier is
|
||||||
|
dispatched at hotfix weight — STEP 4's smoke result already verifies these
|
||||||
|
trivial criteria; the gate hotfix adds is security (STEP 4).
|
||||||
|
|
||||||
|
## 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`.
|
||||||
|
|
||||||
|
Snapshot current state so revert is possible:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git diff HEAD --stat # confirm working tree is clean OR carries only the
|
||||||
|
# in-progress hotfix area; if unrelated dirty files are
|
||||||
|
# present, ask user whether to stash them first
|
||||||
|
git rev-parse HEAD # capture the SHA to revert to on failure
|
||||||
|
```
|
||||||
|
|
||||||
|
If the working tree contains unrelated uncommitted changes the user has not
|
||||||
|
mentioned: STOP and ask `"working tree dirty: stash and continue, or abort?"`.
|
||||||
|
|
||||||
|
## STEP 3 — DISPATCH EXECUTOR
|
||||||
|
|
||||||
|
Dispatch the executor — sonnet by frontmatter pin, do not override:
|
||||||
|
|
||||||
|
```
|
||||||
|
Agent(subagent_type="hotfixer")
|
||||||
|
prompt: "CONTRACT: <path from STEP 1.7>
|
||||||
|
LOCATED: <file(s) found in STEP 1 + the confirmed root cause>
|
||||||
|
FIX: <the proposed minimal fix, closed in STEP 1>
|
||||||
|
BRANCH: <current branch — verify with git branch --show-current, never switch>
|
||||||
|
Apply the minimal fix. No refactoring, no commit, no branch ops, no
|
||||||
|
security dispatch, no revert. Finish with the HOTFIX-EXEC REPORT."
|
||||||
|
```
|
||||||
|
|
||||||
|
Parse the `HOTFIX-EXEC REPORT`:
|
||||||
|
- `STATUS : DONE` → STEP 4 (the SMOKE line in the report decides pass/fail
|
||||||
|
there; DONE here means execution completed, not that it verified clean).
|
||||||
|
- `STATUS : BLOCKED` → if any edits were made, `git restore .` to the
|
||||||
|
pre-flight SHA (STEP 2); surface the blocker to the user; STOP. One
|
||||||
|
attempt only — hotfix never re-dispatches (escalate to `/bugfix` for
|
||||||
|
deeper work).
|
||||||
|
|
||||||
|
## STEP 4 — VERIFY + SECURE + COMMIT (main loop, LRN-083)
|
||||||
|
|
||||||
|
1. Read the SMOKE line from the executor's report. **Failure branch** — if
|
||||||
|
it reports a failing test/build result:
|
||||||
|
- Print the failure output verbatim (under 30 lines).
|
||||||
|
- Run `git restore .` to revert the working-tree edits to the pre-flight
|
||||||
|
SHA (STEP 2). (Files were not yet staged — restore is safe.)
|
||||||
|
- STOP and tell user: `"Hotfix introduced a regression. Reverted.
|
||||||
|
Escalate to /bugfix or /analyze for deeper investigation."`
|
||||||
|
- Do NOT commit a broken fix.
|
||||||
|
2. **Security gate (fresh auditor) — failure REVERTS, never loops.** Dispatch
|
||||||
|
a FRESH security-auditor (`subagent_type: security-auditor`, or load
|
||||||
|
`agents/security-auditor.md`) with `MODE: gate`, `SCOPE:` the working-tree
|
||||||
|
diff vs the pre-flight SHA. Parse its `SECURITY — VERDICT:` line:
|
||||||
|
- `PASS` (or `DEGRADED` with no BLOCK) → proceed to commit.
|
||||||
|
- `BLOCK(n)` → this is hotfix: do NOT loop. Run `git restore .` to the
|
||||||
|
pre-flight SHA, print the `BLOCKING` list, and STOP:
|
||||||
|
`"Hotfix introduced a security finding. Reverted. Escalate to /bugfix
|
||||||
|
for a fix under the full verify+security loop."` The hotfix model is
|
||||||
|
one attempt; any gate failure (smoke OR security) reverts and escalates.
|
||||||
|
- Structural failure (mute / unparsable / no VERDICT line) → treat as a
|
||||||
|
failed gate: retry ONCE fresh; a 2nd structural failure → revert +
|
||||||
|
escalate. A mute auditor is never a PASS.
|
||||||
|
3. Commit using conventional format (only after smoke AND security pass):
|
||||||
|
```
|
||||||
|
fix(<scope>): <what was wrong>
|
||||||
|
```
|
||||||
|
4. Print summary:
|
||||||
|
```
|
||||||
|
HOTFIX APPLIED
|
||||||
|
FILE(S) : <changed files>
|
||||||
|
FIX : <one-line description>
|
||||||
|
VERIFIED: <test name or smoke check that passed>
|
||||||
|
SECURITY: <PASS | DEGRADED (checklist only)>
|
||||||
|
```
|
||||||
|
|
||||||
|
## STEP 5 — DOC SYNC (automatic)
|
||||||
|
|
||||||
|
Load `$HOME/.claude/agents/doc-syncer.md`.
|
||||||
|
Execute in automatic mode:
|
||||||
|
`auto-mode scope: <list of files modified during this session>`
|
||||||
|
|
||||||
|
**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
|
||||||
|
`.claude/`/`CLAUDE.md` (rc 4 = a loud BDR-022 anomaly, not a silent skip), and no-ops when
|
||||||
|
nothing was patched — the common case for a trivial hotfix. No FINISH in an inline flow, so
|
||||||
|
it just commits the docs on the current branch (no ordering concern).
|
||||||
|
|
||||||
|
## STEP 6 — CAPITALIZE (memory registries, lightweight)
|
||||||
|
|
||||||
|
Hotfixes are often trivial (typo, config, import) — skip by default. But if the fix revealed something non-obvious:
|
||||||
|
|
||||||
|
- Wrong default that should never have been merged → propose `LRN-XXX` in `.claude/memory/learnings.md`.
|
||||||
|
- Bug that cost real time to locate despite being "superficial" → propose `BLK-XXX` in `.claude/memory/blockers.md` (status: resolved).
|
||||||
|
|
||||||
|
Default behaviour: `CAPITALIZE: hotfix trivial, skip` (no prompt, no output).
|
||||||
|
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).
|
||||||
|
|
||||||
|
**Then commit the memory** — follow `$HOME/.claude/lib/capitalize-commit.md`: it
|
||||||
|
surgically commits what capitalize just wrote (`.claude/memory` + `.claude/tasks`
|
||||||
|
only, never `git add -A`) as one `chore(memory)` commit, reports the memory-commit
|
||||||
|
hash, and no-ops if nothing was written. The always-on journal line means a
|
||||||
|
trivial hotfix still produces a `chore(memory): journal — …` commit (Frame 2 / F3).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## RULES
|
||||||
|
- 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).
|
||||||
|
- The executor is dispatched FRESH, once — hotfix never re-dispatches (no
|
||||||
|
decision round-trips; a blocked or failed attempt reverts and escalates
|
||||||
|
to `/bugfix`, it does not retry).
|
||||||
|
- Design gate only if CSS/style signals detected. See STEP 1.5.
|
||||||
|
- **Revert-not-loop preserved**: smoke FAIL or security BLOCK → `git
|
||||||
|
restore .` to the pre-flight SHA + STOP + escalate to `/bugfix`; hotfix
|
||||||
|
never loops. No verifier is dispatched at hotfix weight.
|
||||||
|
- If root cause is unclear → escalate to `/bugfix` (STEP 1).
|
||||||
|
- If fix touches >5 lines of logic → reconsider if this is
|
||||||
|
truly a hotfix.
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ allowed-tools: Read, Write, Edit, Bash, Grep, Glob
|
|||||||
|
|
||||||
# ORCHESTRATOR: INIT PROJECT
|
# ORCHESTRATOR: INIT PROJECT
|
||||||
|
|
||||||
|
## MODEL GATE (blocking — run before any other step)
|
||||||
|
|
||||||
|
Run `$HOME/.claude/lib/model-gate.md`. Reflection here (planning, audit
|
||||||
|
judgment, loop decisions) requires Fable/Opus. Verdict `small` → STOP: the
|
||||||
|
gate prints the remedy; end the turn — no later step, no dispatch. Nominal
|
||||||
|
(big) path is silent.
|
||||||
|
|
||||||
## REQUEST
|
## REQUEST
|
||||||
$ARGUMENTS
|
$ARGUMENTS
|
||||||
|
|
||||||
@@ -169,6 +176,12 @@ Invoke `superpowers:subagent-driven-development` for the per-task implement loop
|
|||||||
`gitflow finish` (STEP 11). When SDD's flow reaches "Use
|
`gitflow finish` (STEP 11). When SDD's flow reaches "Use
|
||||||
finishing-a-development-branch", stop and return.
|
finishing-a-development-branch", stop and return.
|
||||||
|
|
||||||
|
**Model routing (BDR-066):** every subagent dispatched under SDD — per-task
|
||||||
|
implementers AND its reviewers — MUST carry `model: "sonnet"` in the Agent
|
||||||
|
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)
|
## STEP 8b — GRAPHIFY FULL (after implementation)
|
||||||
If `graphify` CLI is installed AND complexity >= 30%:
|
If `graphify` CLI is installed AND complexity >= 30%:
|
||||||
1. Run full graphify on the implemented project:
|
1. Run full graphify on the implemented project:
|
||||||
|
|||||||
+11
-4
@@ -7,6 +7,13 @@ allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Agent, Skill
|
|||||||
|
|
||||||
# ORCHESTRATOR: ONBOARD
|
# ORCHESTRATOR: ONBOARD
|
||||||
|
|
||||||
|
## MODEL GATE (blocking — run before any other step)
|
||||||
|
|
||||||
|
Run `$HOME/.claude/lib/model-gate.md`. Reflection here (planning, audit
|
||||||
|
judgment, loop decisions) requires Fable/Opus. Verdict `small` → STOP: the
|
||||||
|
gate prints the remedy; end the turn — no later step, no dispatch. Nominal
|
||||||
|
(big) path is silent.
|
||||||
|
|
||||||
## REQUEST
|
## REQUEST
|
||||||
$ARGUMENTS
|
$ARGUMENTS
|
||||||
|
|
||||||
@@ -347,7 +354,7 @@ Lire le bloc `audit_stack:` du fichier `~/.claude/lib/project-archetypes/<archet
|
|||||||
| Entry | Action | Livraison |
|
| Entry | Action | Livraison |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `analyze` | Déjà fait en STEP 5 | L3a |
|
| `analyze` | Déjà fait en STEP 5 | L3a |
|
||||||
| `code-clean` | Spawn subagent `code-cleaner` (audit-only) | L3a |
|
| `code-clean` | Spawn subagent `general-purpose` (audit-only, inherits session = big model) | L3a |
|
||||||
| `cso` | Si gstack ON → Skill(cso). Sinon → Agent general-purpose avec checklist OWASP + deps audit | L3a |
|
| `cso` | Si gstack ON → Skill(cso). Sinon → Agent general-purpose avec checklist OWASP + deps audit | L3a |
|
||||||
| `doc` | Spawn subagent `doc-syncer` (auto-mode OFF, report-only) | L3a |
|
| `doc` | Spawn subagent `doc-syncer` (auto-mode OFF, report-only) | L3a |
|
||||||
| `seo` | Subagents seo-analyzer + geo-analyzer en parallèle | L3b |
|
| `seo` | Subagents seo-analyzer + geo-analyzer en parallèle | L3b |
|
||||||
@@ -359,11 +366,11 @@ Lire le bloc `audit_stack:` du fichier `~/.claude/lib/project-archetypes/<archet
|
|||||||
|
|
||||||
Lancer EN PARALLÈLE (un seul message, plusieurs Agent calls) les audits correspondant aux entrées de `audit_stack:` qui sont en L3a (`code-clean`, `cso`, `doc`).
|
Lancer EN PARALLÈLE (un seul message, plusieurs Agent calls) les audits correspondant aux entrées de `audit_stack:` qui sont en L3a (`code-clean`, `cso`, `doc`).
|
||||||
|
|
||||||
#### Dispatch code-cleaner (si `code-clean` dans audit_stack)
|
#### Dispatch code-clean audit (si `code-clean` dans audit_stack)
|
||||||
```
|
```
|
||||||
Agent(
|
Agent(
|
||||||
subagent_type="code-cleaner",
|
subagent_type="general-purpose",
|
||||||
description="Onboard — code-clean audit only",
|
description="Onboard — code-clean audit only (read-only, big session model)",
|
||||||
prompt="""
|
prompt="""
|
||||||
AUDIT-ONLY mode — NO fixes, NO refactoring, NO file modifications.
|
AUDIT-ONLY mode — NO fixes, NO refactoring, NO file modifications.
|
||||||
Target: <PROJECT_ROOT>. ARCHETYPE: <archetype>.
|
Target: <PROJECT_ROOT>. ARCHETYPE: <archetype>.
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
---
|
---
|
||||||
name: release-candidate
|
name: release-candidate
|
||||||
description: 'Use when develop is ahead of main and you want to cut a versioned release — finalize version.txt + CHANGELOG, merge develop→main via the gitflow fan-out, tag it, and push. Triggers: "cut a release", "release candidate", "tag a version", "ship develop to main". NOT feature/bugfix integration (that is gitflow finish via /ship-feature) nor a hotfix.'
|
description: 'Use when develop is ahead of main and you want to cut a versioned release — finalize version.txt + CHANGELOG, merge develop→main via the gitflow fan-out, tag it, and push. Triggers: "cut a release", "release candidate", "tag a version", "ship develop to main". NOT feature/bugfix integration (that is gitflow finish via /ship-feature) nor a hotfix.'
|
||||||
|
allowed-tools:
|
||||||
|
- Read
|
||||||
|
- Write
|
||||||
|
- Edit
|
||||||
|
- Bash
|
||||||
|
- Grep
|
||||||
|
- Glob
|
||||||
|
- Agent
|
||||||
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /release-candidate — cut a gitflow release (orchestrator)
|
# /release-candidate — cut a gitflow release (orchestrator)
|
||||||
@@ -10,6 +19,14 @@ Turns the accumulated work on `develop` into a tagged release on `main`. THIN OR
|
|||||||
|
|
||||||
**Division of labour (lib = mechanic, skill = judgment):** the tag lives HERE, not in `gitflow.sh`, because it is release-specific (version + message + human decision) while the lib's fan-out is generic. **Consequence (accepted):** a release cut by calling `gitflow finish` directly, bypassing this skill, fans out but is NOT tagged — `/release-candidate` is the canonical release path.
|
**Division of labour (lib = mechanic, skill = judgment):** the tag lives HERE, not in `gitflow.sh`, because it is release-specific (version + message + human decision) while the lib's fan-out is generic. **Consequence (accepted):** a release cut by calling `gitflow finish` directly, bypassing this skill, fans out but is NOT tagged — `/release-candidate` is the canonical release path.
|
||||||
|
|
||||||
|
The two mechanical spans (prep, finish+tag) run on the sonnet-pinned
|
||||||
|
`release-executor` subagent (dispatch makes the pin effective) — no model
|
||||||
|
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
|
||||||
|
executor is never dispatched twice in one call.
|
||||||
|
|
||||||
## When to use
|
## When to use
|
||||||
- `develop` is ahead of `main` and you want to publish a version.
|
- `develop` is ahead of `main` and you want to publish a version.
|
||||||
- "cut a release", "release candidate", "tag a version", "ship develop to main".
|
- "cut a release", "release candidate", "tag a version", "ship develop to main".
|
||||||
@@ -21,19 +38,71 @@ Not for: integrating a feature/bugfix → `gitflow finish` (via /ship-feature).
|
|||||||
- The number DERIVES from the change nature (semver), not the reverse: a migration-requiring/breaking change → MAJOR; new features → MINOR; fixes → PATCH. Personal repo ⇒ "breaking" = requires a migration of your own usage. Decide the number BEFORE running.
|
- The number DERIVES from the change nature (semver), not the reverse: a migration-requiring/breaking change → MAJOR; new features → MINOR; fixes → PATCH. Personal repo ⇒ "breaking" = requires a migration of your own usage. Decide the number BEFORE running.
|
||||||
|
|
||||||
## Flow
|
## Flow
|
||||||
**REQUIRED:** `lib/gitflow.sh` (the release mechanic). Clean tree, identity set, `develop` ahead of `main`.
|
**REQUIRED:** `lib/gitflow.sh` (the release mechanic, via the `release-executor` subagent). Clean tree, identity set, `develop` ahead of `main`.
|
||||||
|
|
||||||
1. **Preconditions** — clean tree, git identity, `develop` ahead of `main` (else nothing to release).
|
### STEP 1 — Preconditions
|
||||||
2. `gitflow start release <X.Y.Z>` — forks from develop, lands on `release/<X.Y.Z>`.
|
```bash
|
||||||
3. **Prep** on the release branch:
|
git status --porcelain=v1 | wc -l # 0 required — clean tree
|
||||||
- `version.txt` → `<X.Y.Z>`.
|
git config user.email # must be set
|
||||||
- CHANGELOG: `## [Unreleased]` → `## [<X.Y.Z>] — <date>`, re-open an empty `[Unreleased]`. A MAJOR must spell out its breaking change (`### Changed`/`### Removed`/BREAKING); review the doc-syncer draft for completeness.
|
git rev-list --count main..develop # 0 → nothing to release, STOP
|
||||||
- Any release-candidate fixes; commit the prep on the branch.
|
```
|
||||||
- **Run the test suite** (`lib/tests/*`, gitflow-test) — RC gate; never release red.
|
Any of these fail their check → STOP, tell the user what's blocking, dispatch nothing.
|
||||||
4. **HUMAN GATE — WHEN to release.** STOP. Proceed only on an explicit human go (mirror /ship-feature's finish gate). Never fire on "tests pass".
|
|
||||||
5. `gitflow finish` — lib fans out: merge `release/*`→`main`, merge-back→`develop`, delete the branch.
|
### STEP 2 — Version-number decision (judgment, stays HERE)
|
||||||
6. **Tag** (the piece the lib lacks): `git tag -a v<X.Y.Z> main -m "release <X.Y.Z>"` — annotated, on main's release-merge commit, AFTER finish.
|
Read the `## [Unreleased]` section of `CHANGELOG.md` and the commits on
|
||||||
7. **Push — GATED (ASK).** On explicit go only ([[LRN-069]]): `git push origin main develop && git push origin v<X.Y.Z>`.
|
`develop` since `main`. Apply the Versioning rule above (breaking → MAJOR,
|
||||||
|
features → MINOR, fixes → PATCH) and settle `<X.Y.Z>` before dispatching
|
||||||
|
anything — the executor never derives or second-guesses this number.
|
||||||
|
|
||||||
|
### STEP 3 — Dispatch: prep
|
||||||
|
```
|
||||||
|
Agent(subagent_type="release-executor")
|
||||||
|
prompt: "SPAN: prep <X.Y.Z>
|
||||||
|
<any release-candidate fixes to fold into the prep commit, or 'none'>"
|
||||||
|
```
|
||||||
|
Parse the `RELEASE-EXEC REPORT`:
|
||||||
|
- `STATUS: DONE` → continue to STEP 4, carrying the `TESTS` line forward.
|
||||||
|
- `STATUS: NEED-DECISION` → surface the exact question to the user, STOP
|
||||||
|
(don't guess the CHANGELOG wording on its behalf). Resume note: prep may
|
||||||
|
have already run `gitflow start release` (the release branch exists) — do
|
||||||
|
NOT re-dispatch `SPAN: prep` (it would BLOCK on the existing branch);
|
||||||
|
resolve the CHANGELOG on the current release branch, commit the prep, then
|
||||||
|
resume at STEP 4.
|
||||||
|
- `STATUS: BLOCKED` → surface the blocker verbatim, STOP.
|
||||||
|
|
||||||
|
### STEP 4 — HUMAN GATE: when to release
|
||||||
|
STOP. Show the prep report's `TESTS` result, then:
|
||||||
|
```
|
||||||
|
AskUserQuestion:
|
||||||
|
Release <X.Y.Z> now? (tests: <TESTS line from STEP 3>) — go / hold
|
||||||
|
```
|
||||||
|
Proceed only on an explicit human go. **Never fire on "tests pass"** — a
|
||||||
|
green suite means ready to release, not authorized to. `hold` → stop here;
|
||||||
|
the prepped `release/<X.Y.Z>` branch stays as-is for a later run.
|
||||||
|
|
||||||
|
### STEP 5 — Dispatch: finish + tag
|
||||||
|
```
|
||||||
|
Agent(subagent_type="release-executor")
|
||||||
|
prompt: "SPAN: finish <X.Y.Z>"
|
||||||
|
```
|
||||||
|
Parse the `RELEASE-EXEC REPORT`:
|
||||||
|
- `STATUS: DONE` → continue to STEP 6, carrying the `TAG` value forward.
|
||||||
|
- `STATUS: BLOCKED` → surface the blocker verbatim (e.g. a merge conflict
|
||||||
|
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:
|
||||||
|
```
|
||||||
|
AskUserQuestion:
|
||||||
|
Push main, develop, and v<X.Y.Z> to origin? — go / hold
|
||||||
|
```
|
||||||
|
Go →
|
||||||
|
```bash
|
||||||
|
git push origin main develop && git push origin v<X.Y.Z>
|
||||||
|
```
|
||||||
|
`hold` → stop; the release is fanned out and tagged locally, unpushed.
|
||||||
|
|
||||||
## Common mistakes
|
## Common mistakes
|
||||||
- Tagging before `gitflow finish` → tag wouldn't sit on main's merge commit. Tag AFTER, on main.
|
- Tagging before `gitflow finish` → tag wouldn't sit on main's merge commit. Tag AFTER, on main.
|
||||||
|
|||||||
@@ -23,6 +23,13 @@ allowed-tools:
|
|||||||
|
|
||||||
# /seo — parallel SEO + GEO dispatcher
|
# /seo — parallel SEO + GEO dispatcher
|
||||||
|
|
||||||
|
## MODEL GATE (blocking — run before any other step)
|
||||||
|
|
||||||
|
Run `$HOME/.claude/lib/model-gate.md`. Reflection here (planning, audit
|
||||||
|
judgment, loop decisions) requires Fable/Opus. Verdict `small` → STOP: the
|
||||||
|
gate prints the remedy; end the turn — no later step, no dispatch. Nominal
|
||||||
|
(big) path is silent.
|
||||||
|
|
||||||
This skill orchestrates TWO specialist agents running in parallel, then
|
This skill orchestrates TWO specialist agents running in parallel, then
|
||||||
merges their output into a single `.claude/audits/SEO.md` report. It is the main
|
merges their output into a single `.claude/audits/SEO.md` report. It is the main
|
||||||
entry point for any SEO/GEO work on a web project.
|
entry point for any SEO/GEO work on a web project.
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ allowed-tools: Read, Write, Edit, Bash, Grep, Glob
|
|||||||
|
|
||||||
# ORCHESTRATOR: SHIP FEATURE
|
# ORCHESTRATOR: SHIP FEATURE
|
||||||
|
|
||||||
|
## MODEL GATE (blocking — run before any other step)
|
||||||
|
|
||||||
|
Run `$HOME/.claude/lib/model-gate.md`. Reflection here (planning, audit
|
||||||
|
judgment, loop decisions) requires Fable/Opus. Verdict `small` → STOP: the
|
||||||
|
gate prints the remedy; end the turn — no later step, no dispatch. Nominal
|
||||||
|
(big) path is silent.
|
||||||
|
|
||||||
## REQUEST
|
## REQUEST
|
||||||
$ARGUMENTS
|
$ARGUMENTS
|
||||||
|
|
||||||
@@ -147,6 +154,12 @@ Invoke `superpowers:subagent-driven-development` for the per-task implement loop
|
|||||||
`gitflow finish` (STEP 9). When SDD's flow reaches "Use
|
`gitflow finish` (STEP 9). When SDD's flow reaches "Use
|
||||||
finishing-a-development-branch", stop and return.
|
finishing-a-development-branch", stop and return.
|
||||||
|
|
||||||
|
**Model routing (BDR-066):** every subagent dispatched under SDD — per-task
|
||||||
|
implementers AND its reviewers — MUST carry `model: "sonnet"` in the Agent
|
||||||
|
call. The plan is closed; execution and plan-conformity review are sonnet
|
||||||
|
work. Reflection (task decomposition, review verdict arbitration) stays in
|
||||||
|
this loop.
|
||||||
|
|
||||||
## STEP 4b — ERROR RECOVERY (if STEP 4 fails)
|
## STEP 4b — ERROR RECOVERY (if STEP 4 fails)
|
||||||
If a subagent returns a build error, failing test, or type error:
|
If a subagent returns a build error, failing test, or type error:
|
||||||
1. Load `$HOME/.claude/agents/analyzer.md` in DEBUG MODE on the exact error output.
|
1. Load `$HOME/.claude/agents/analyzer.md` in DEBUG MODE on the exact error output.
|
||||||
|
|||||||
@@ -2,13 +2,15 @@
|
|||||||
name: status
|
name: status
|
||||||
description: 'Consolidated project snapshot — plugins, token cost, git state, recent commits, GSD v2 milestone progress. Read-only. Run at session start or after a break. Open-work reconciliation (stale TODO vs real git) → /reconcile. Triggers: "status", "sitrep", "where are we", "project state", "after break".'
|
description: 'Consolidated project snapshot — plugins, token cost, git state, recent commits, GSD v2 milestone progress. Read-only. Run at session start or after a break. Open-work reconciliation (stale TODO vs real git) → /reconcile. Triggers: "status", "sitrep", "where are we", "project state", "after break".'
|
||||||
argument-hint: (no arguments needed)
|
argument-hint: (no arguments needed)
|
||||||
allowed-tools: Read, Bash, Glob, Grep
|
allowed-tools: Read, Bash, Glob, Grep, Agent
|
||||||
---
|
---
|
||||||
|
|
||||||
Load and follow strictly:
|
Dispatch the status-reporter as a subagent so its `model: haiku` pin takes
|
||||||
- `$HOME/.claude/agents/status-reporter.md`
|
effect (read-only collection = cheapest tier, off the big session model):
|
||||||
|
|
||||||
Produce the full PROJECT STATUS report for the current working directory.
|
Agent(subagent_type="status-reporter")
|
||||||
|
prompt: "Produce the full PROJECT STATUS report for the current working
|
||||||
|
directory. $ARGUMENTS"
|
||||||
|
|
||||||
## Fallback when agent file missing
|
## Fallback when agent file missing
|
||||||
|
|
||||||
|
|||||||
+10
-2
@@ -23,6 +23,13 @@ allowed-tools:
|
|||||||
|
|
||||||
# /tour — grouped multi-axis sweep (clean + security + reconcile + doc)
|
# /tour — grouped multi-axis sweep (clean + security + reconcile + doc)
|
||||||
|
|
||||||
|
## MODEL GATE (blocking — run before any other step)
|
||||||
|
|
||||||
|
Run `$HOME/.claude/lib/model-gate.md`. Reflection here (planning, audit
|
||||||
|
judgment, loop decisions) requires Fable/Opus. Verdict `small` → STOP: the
|
||||||
|
gate prints the remedy; end the turn — no later step, no dispatch. Nominal
|
||||||
|
(big) path is silent.
|
||||||
|
|
||||||
One pipeline per project: **security → clean → re-verify → reconcile →
|
One pipeline per project: **security → clean → re-verify → reconcile →
|
||||||
doc → convergence re-audit**, looping until a full pass applies zero new
|
doc → convergence re-audit**, looping until a full pass applies zero new
|
||||||
fixes. Auto mode by design: fixes are committed on a dedicated
|
fixes. Auto mode by design: fixes are committed on a dedicated
|
||||||
@@ -104,8 +111,9 @@ honestly in the summary. Never loop past 3.
|
|||||||
|
|
||||||
### Phase B — CLEAN
|
### Phase B — CLEAN
|
||||||
|
|
||||||
1. Dispatch a read-only cleanup audit (code-cleaner agent if available,
|
1. Dispatch a read-only cleanup audit (analyzer or general-purpose —
|
||||||
else analyzer/general): dead code, unused imports/exports,
|
inherits the big session model; NOT the sonnet code-cleaner, which is
|
||||||
|
now a fix executor): dead code, unused imports/exports,
|
||||||
commented-out blocks, stale flags, norm violations. Findings as
|
commented-out blocks, stale flags, norm violations. Findings as
|
||||||
`id | file:line | finding | proposed fix`.
|
`id | file:line | finding | proposed fix`.
|
||||||
2. Apply **behavior-preserving** fixes only. A finding that would change
|
2. Apply **behavior-preserving** fixes only. A finding that would change
|
||||||
|
|||||||
@@ -21,6 +21,13 @@ allowed-tools:
|
|||||||
|
|
||||||
# /web-validate — web standards audit (W3C + WCAG)
|
# /web-validate — web standards audit (W3C + WCAG)
|
||||||
|
|
||||||
|
## MODEL GATE (blocking — run before any other step)
|
||||||
|
|
||||||
|
Run `$HOME/.claude/lib/model-gate.md`. Reflection here (planning, audit
|
||||||
|
judgment, loop decisions) requires Fable/Opus. Verdict `small` → STOP: the
|
||||||
|
gate prints the remedy; end the turn — no later step, no dispatch. Nominal
|
||||||
|
(big) path is silent.
|
||||||
|
|
||||||
This skill orchestrates a narrow-scope standards audit :
|
This skill orchestrates a narrow-scope standards audit :
|
||||||
|
|
||||||
- **W3C HTML validity** — validator.nu API (FULL) or `html-validate` /
|
- **W3C HTML validity** — validator.nu API (FULL) or `html-validate` /
|
||||||
@@ -271,10 +278,23 @@ Options :
|
|||||||
D) Abort — keep .claude/audits/VALIDATE.md as audit report
|
D) Abort — keep .claude/audits/VALIDATE.md as audit report
|
||||||
```
|
```
|
||||||
|
|
||||||
4. On `A` : apply each bundle via `Edit` (targeted `old_string` /
|
4. On `A` : dispatch each file-group's applier at L1 (execution = sonnet;
|
||||||
`new_string`). Never use `Write` on shared templates (risk of
|
this loop only orchestrates), serially — one applier at a time, appliers
|
||||||
overwriting /seo or /geo content — meta tags, JSON-LD).
|
share files:
|
||||||
5. On `B` : for each diff, show and ask yes/no/skip.
|
|
||||||
|
```
|
||||||
|
Agent(subagent_type="hotfixer")
|
||||||
|
prompt: "<paste the file-group's bundle items: file, issue, current,
|
||||||
|
expected fix>.
|
||||||
|
Context: web-validate fix bundle, user-approved scope — no
|
||||||
|
confirmation needed. Apply via targeted Edit (old_string/new_string);
|
||||||
|
NEVER Write whole files (shared templates carry /seo and /geo
|
||||||
|
content — meta tags, JSON-LD). Do NOT commit — apply and self-verify
|
||||||
|
only."
|
||||||
|
```
|
||||||
|
|
||||||
|
5. On `B` : for each diff, show and ask yes/no/skip; apply approved diffs
|
||||||
|
as in `A` (hotfixer dispatch).
|
||||||
6. On `C` : filter to Critique + Haute, then behave as `A`.
|
6. On `C` : filter to Critique + Haute, then behave as `A`.
|
||||||
7. On `D` : stop, leave `.claude/audits/VALIDATE.md` untouched.
|
7. On `D` : stop, leave `.claude/audits/VALIDATE.md` untouched.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user