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-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-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.
|
||||
- **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]].
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
- `/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.
|
||||
|
||||
## 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.
|
||||
- **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).
|
||||
|
||||
## 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
|
||||
|
||||
## 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)
|
||||
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).
|
||||
|
||||
@@ -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.
|
||||
- `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.
|
||||
- `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
|
||||
- **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`.
|
||||
- **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.
|
||||
- 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
|
||||
- `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
|
||||
- **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)
|
||||
|
||||
@@ -265,7 +265,7 @@ cd mon-projet-existant/
|
||||
| 4 | Graphify (si complexity ≥ 30%) | graphify-out/GRAPH_REPORT.md |
|
||||
| 5 | Analyze read-only (analyzer agent) | .onboard-audit/analyze.md |
|
||||
| 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) |
|
||||
| | — docs drift (doc-syncer) |
|
||||
| | — SEO + GEO (si public) |
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
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.
|
||||
tools: Read, Grep, Glob, Bash
|
||||
model: haiku
|
||||
memory: project
|
||||
---
|
||||
|
||||
|
||||
+40
-232
@@ -1,245 +1,53 @@
|
||||
---
|
||||
name: bugfixer
|
||||
description: Root-cause bug-fix executor — dispatched by /bugfix. Hypothesis-driven investigation, diagnosis, minimal scoped fix with regression test.
|
||||
tools: Read, Edit, Write, Bash, Grep, Glob, Agent
|
||||
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
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# BUGFIX — Structured Bug Fix
|
||||
# BUGFIXER — fix executor
|
||||
|
||||
Investigate, understand, plan, fix. No guessing. The iron law:
|
||||
understand the root cause before writing a single fix.
|
||||
You receive a CLOSED diagnosis + fix plan from the /bugfix orchestrator. The
|
||||
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
|
||||
$ARGUMENTS
|
||||
## INPUT (in the dispatch prompt)
|
||||
|
||||
---
|
||||
- `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
|
||||
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:
|
||||
## OUTPUT — end with exactly this report (your final message)
|
||||
|
||||
```
|
||||
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>
|
||||
BUGFIX-EXEC REPORT
|
||||
STATUS : DONE | NEED-DECISION | BLOCKED
|
||||
FILE(S) : <created/modified paths>
|
||||
TEST(S) : <regression test added/updated + final suite run result, verbatim line>
|
||||
SMOKE : <build/typecheck result if run, or n/a>
|
||||
NOTES : <DONE: deviations (must be none) | NEED-DECISION: the exact
|
||||
question + the options you see | BLOCKED: the blocker verbatim>
|
||||
```
|
||||
|
||||
- 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
|
||||
description: Audit codebase for dead code, style violations, and structural issues. Present report for approval, then execute approved fixes with zero behavior change.
|
||||
tools: Read, Edit, Write, Bash, Grep, Glob, AskUserQuestion
|
||||
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
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# CODE-CLEAN — Codebase Cleanup
|
||||
# CODE-CLEANER — cleanup executor (PHASE 2)
|
||||
|
||||
Two-phase cleanup: audit everything first, touch nothing until approved.
|
||||
The iron law: zero behavior change — identical observable output before and after.
|
||||
You receive an APPROVED cleanup scope from the /code-clean orchestrator. The
|
||||
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
|
||||
$ARGUMENTS
|
||||
## INPUT (in the dispatch prompt)
|
||||
|
||||
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)
|
||||
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.)
|
||||
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 style / structural items in `SCOPE`. Its own safety process runs
|
||||
(pre-report, function-by-function, test after each) — zero behavior change.
|
||||
Running inside this sonnet executor, the refactor finally runs on sonnet (the
|
||||
refactorer pin was inert under the old inline-load on the session model).
|
||||
|
||||
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**
|
||||
- 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.
|
||||
|
||||
### 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>
|
||||
```
|
||||
|
||||
---
|
||||
Re-scan only the modified files; verify no new issues were introduced; run the
|
||||
project test suite + linter/formatter if available.
|
||||
|
||||
## RULES
|
||||
|
||||
- Zero behavior change. If you're unsure whether a deletion changes
|
||||
behavior, leave it and flag it — never guess.
|
||||
- No "while we're here" scope creep. Only fix approved items.
|
||||
- Exported/public API symbols require explicit per-item user confirmation
|
||||
before deletion — even if they appear unused.
|
||||
- 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 executing.
|
||||
- No plugin check (lightweight skill, not an orchestrator).
|
||||
- If the audit reveals systemic issues requiring architecture changes,
|
||||
stop and suggest `/ship-feature` for a proper redesign.
|
||||
- Zero behavior change. Unsure a deletion is safe → leave it, record under NOTES.
|
||||
- No "while we're here" scope creep — only the APPROVED items.
|
||||
- FORBIDDEN: `git commit`, branch ops, push, merge, new dependencies, user
|
||||
questions (report instead), editing `.claude/**` or memory registries,
|
||||
attribution trailers of any kind.
|
||||
|
||||
## OUTPUT — end with exactly this report (your final message)
|
||||
|
||||
```
|
||||
CODE-CLEAN-EXEC REPORT
|
||||
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
|
||||
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
|
||||
@@ -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
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
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`,
|
||||
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
|
||||
`$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
|
||||
proceeding.
|
||||
current branch state as an edge case in the emitted plan instead of
|
||||
branching, so the dispatcher can ask the user which branch to commit on.
|
||||
|
||||
### 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
|
||||
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
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
```
|
||||
COMMIT PLAN — <N> step(s) from working tree
|
||||
|
||||
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
|
||||
**Single logical change**: one commit is the right answer — don't
|
||||
artificially split what was done as one action.
|
||||
|
||||
### 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
|
||||
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
|
||||
- **Only staged changes**: respect what's already staged — ask if the
|
||||
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
|
||||
Inspect the reconstructed steps as a whole and draft candidates, same
|
||||
criteria as the standalone `/capitalize` flow:
|
||||
|
||||
### Phase 4: Capitalize (memory registries)
|
||||
|
||||
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
|
||||
- Any step that represents a **design/architecture choice** (new dependency,
|
||||
refactor with rationale, API shape decision) → draft an entry for
|
||||
`.claude/memory/decisions.md` (BDR-XXX) with pre-filled alternatives.
|
||||
- Any commit that resolves a **non-trivial bug with a root cause** → propose
|
||||
an entry in `.claude/memory/blockers.md` (BLK-XXX, status: resolved).
|
||||
- Any commit whose content taught something **reusable beyond the immediate fix**
|
||||
(a pattern, a gotcha, a surprising API behaviour) → propose an entry in
|
||||
`.claude/memory/learnings.md` (LRN-XXX).
|
||||
- Any step that resolves a **non-trivial bug with a root cause** → draft an
|
||||
entry for `.claude/memory/blockers.md` (BLK-XXX, status: resolved).
|
||||
- Any step whose content taught something **reusable beyond the immediate
|
||||
fix** (a pattern, a gotcha, a surprising API behaviour) → draft an entry
|
||||
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
|
||||
[decisions.md] BDR-XXX — <titre> (ref commit <hash>)
|
||||
[blockers.md] BLK-XXX — <friction> — resolved (ref commit <hash>)
|
||||
COMMIT PLAN — <N> step(s) from working tree
|
||||
|
||||
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>
|
||||
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
|
||||
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. This is a separate commit from the Phase 3
|
||||
code commits — their hashes are already anchored inside the entries.
|
||||
- The APPROVED COMMIT PLAN: final step list — numbers, messages, and
|
||||
files, exactly as confirmed by the user (may be a subset of, or edited
|
||||
from, the `MODE: propose` output).
|
||||
- The APPROVED CAPITALIZE ENTRIES: verbatim registry text to write, or
|
||||
`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
|
||||
description: Small-feature implementer (1-5 files) — dispatched by /feat, which owns branching and gates. Light planning, direct implementation, no heavy orchestration.
|
||||
tools: Read, Edit, Write, Bash, Grep, Glob, Agent
|
||||
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
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# FEAT — Small Feature, Fast Track
|
||||
# FEATER — plan executor
|
||||
|
||||
Implement a small, well-scoped feature without the overhead of a
|
||||
full orchestrator. Direct work, light planning, quick delivery.
|
||||
You receive a CLOSED plan from the /feat orchestrator. Your job is faithful
|
||||
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
|
||||
$ARGUMENTS
|
||||
## INPUT (in the dispatch prompt)
|
||||
|
||||
---
|
||||
- `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
|
||||
```
|
||||
|
||||
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 → 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-EXEC REPORT
|
||||
STATUS : DONE | NEED-DECISION | BLOCKED
|
||||
FILES : <created/modified paths>
|
||||
TESTS : <added/updated + final suite run result, verbatim line>
|
||||
NOTES : <DONE: deviations (must be none) | NEED-DECISION: the exact
|
||||
question + the options you see | BLOCKED: the blocker verbatim>
|
||||
```
|
||||
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
|
||||
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.
|
||||
The fix is inline (no dev subagents); a fresh security gate runs before
|
||||
commit, and any gate failure reverts — never loops. Get in, fix, gate,
|
||||
get out.
|
||||
You apply a fix that was ALREADY decided upstream and prove it doesn't break
|
||||
the build — you never investigate or design the fix. Two dispatch sources,
|
||||
same job:
|
||||
|
||||
## REQUEST
|
||||
$ARGUMENTS
|
||||
- **/hotfix orchestrator** — root-cause analysis happened in its LOCATE step;
|
||||
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
|
||||
straight to the source:
|
||||
Applier path (/seo, /geo, /web-validate): no CONTRACT/LOCATED/FIX keys — the
|
||||
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
|
||||
git status
|
||||
git log --oneline -3
|
||||
```
|
||||
## EXECUTION RULES
|
||||
|
||||
- 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. Load `$HOME/.claude/agents/bugfixer.md`
|
||||
and run the BUGFIXER agent on this target."
|
||||
|
||||
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.
|
||||
- Apply the minimal change that fixes the bug. Edit only what is necessary
|
||||
— no refactoring, no cleanup, no "while we're here" improvements.
|
||||
- Stay inside the scope you were given. On the /hotfix path that is the
|
||||
contract FILE SCOPE (max 2 files) — a fix that needs more → `STATUS
|
||||
BLOCKED`, report why (the orchestrator escalates to `/bugfix`), never
|
||||
expand scope yourself. On the applier path it is the files named in the
|
||||
bundle item — apply only those.
|
||||
- If tests exist for the affected code, run them. Detection cascade:
|
||||
```bash
|
||||
# JS/TS
|
||||
@@ -101,85 +58,25 @@ Apply the minimal change that fixes the bug:
|
||||
test -f Makefile && grep -qE '^test:' Makefile && echo "make test"
|
||||
```
|
||||
Run whichever one resolves; if none → continue to smoke check below.
|
||||
- Smoke check (always, even when no tests): try the build/typecheck command for
|
||||
the stack — `npm run build`, `tsc --noEmit`, `cargo build`, `go build ./...`,
|
||||
`python -c "import <pkg>"` — to confirm the fix did not break compilation.
|
||||
- Smoke check (always, even when no tests ran): try the build/typecheck
|
||||
command for the stack — `npm run build`, `tsc --noEmit`, `cargo build`,
|
||||
`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.
|
||||
- If no tests: smoke check from STEP 2 must have passed.
|
||||
2. **Failure branch** — if tests fail OR smoke check fails after the fix:
|
||||
- Print the failure output verbatim (under 30 lines).
|
||||
- Run `git restore .` to revert the working-tree edits to the pre-flight SHA.
|
||||
(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.
|
||||
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.
|
||||
```
|
||||
HOTFIX-EXEC REPORT
|
||||
STATUS : DONE | BLOCKED
|
||||
FILE(S) : <changed files>
|
||||
FIX : <one-line description>
|
||||
SMOKE : <test/build result, verbatim line>
|
||||
NOTES : <BLOCKED: the blocker; DONE: none>
|
||||
```
|
||||
|
||||
@@ -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)"
|
||||
INC="$REPO/lib/verify-secure-loop.md"
|
||||
FEA="$REPO/agents/feater.md"
|
||||
FSK="$REPO/skills/feat/SKILL.md"
|
||||
BUG="$REPO/agents/bugfixer.md"
|
||||
BSK="$REPO/skills/bugfix/SKILL.md"
|
||||
HOT="$REPO/agents/hotfixer.md"
|
||||
HSK="$REPO/skills/hotfix/SKILL.md"
|
||||
HSKL="$REPO/skills/hotfix/SKILL.md"
|
||||
PASS=0; FAIL=0
|
||||
|
||||
tf() { # tf <label> <file> <fixed-string>
|
||||
@@ -29,6 +31,13 @@ tr_() { # tr_ <label> <file> <ERE>
|
||||
echo " FAIL $1 — no match: $3"; FAIL=$((FAIL+1))
|
||||
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) ──"
|
||||
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 "nominal cheap stated" "$INC" "one verifier dispatch + one security dispatch"
|
||||
|
||||
echo "── feater.md (feat wiring) ──"
|
||||
tf "feat contract step" "$FEA" "STEP 0.7 — CONTRACT"
|
||||
tf "feat contract-interview" "$FEA" "lib/contract-interview.md"
|
||||
tf "feat verify+secure step" "$FEA" "STEP 3 — VERIFY + SECURE"
|
||||
tf "feat uses shared include" "$FEA" "lib/verify-secure-loop.md"
|
||||
tf "feat nominal 1+1 dispatch" "$FEA" "verifier + one security dispatch"
|
||||
echo "── feat/SKILL.md (feat orchestrator wiring) ──"
|
||||
tf "feat contract step" "$FSK" "STEP 0.7 — CONTRACT"
|
||||
tf "feat contract-interview" "$FSK" "lib/contract-interview.md"
|
||||
tf "feat verify+secure step" "$FSK" "STEP 4 — VERIFY + SECURE"
|
||||
tf "feat uses shared include" "$FSK" "lib/verify-secure-loop.md"
|
||||
tf "feat nominal 1+1 dispatch" "$FSK" "verifier + one security dispatch"
|
||||
tf "feat dispatches feater" "$FSK" 'subagent_type="feater"'
|
||||
|
||||
echo "── bugfixer.md (bugfix wiring) ──"
|
||||
tf "bug contract step" "$BUG" "STEP 3.5 — CONTRACT"
|
||||
tf "bug diagnosis feeds it" "$BUG" "feeds it: REQUEST verbatim"
|
||||
tf "bug fresh gates" "$BUG" "Fresh gates (verify + secure)"
|
||||
tf "bug uses shared include" "$BUG" "lib/verify-secure-loop.md"
|
||||
echo "── skills/bugfix/SKILL.md (bugfix wiring — reflection inline) ──"
|
||||
tf "bug contract step" "$BSK" "STEP 3.5 — CONTRACT"
|
||||
tf "bug diagnosis feeds it" "$BSK" "feeds it: REQUEST verbatim"
|
||||
tf "bug fresh gates" "$BSK" "the two fresh gates per"
|
||||
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) ──"
|
||||
tr_ "hotfix has Agent tool" "$HOT" "^tools:.*Agent"
|
||||
tf "hotfix silent contract" "$HOT" "STEP 1.7 — CONTRACT (silent autofill)"
|
||||
tf "hotfix zero questions" "$HOT" "questions ever"
|
||||
tf "hotfix security gate" "$HOT" "Security gate (fresh auditor)"
|
||||
tf "hotfix block reverts" "$HOT" "failure REVERTS, never loops"
|
||||
tf "hotfix no verifier" "$HOT" "No verifier is dispatched at hotfix weight"
|
||||
echo "── agents/bugfixer.md (bugfix executor — sonnet, no Agent) ──"
|
||||
tn "bugfixer lacks Agent tool" "$BUG" "Agent"
|
||||
tf "bugfixer model sonnet" "$BUG" "model: sonnet"
|
||||
tf "bugfixer report grammar" "$BUG" "BUGFIX-EXEC REPORT"
|
||||
|
||||
echo "── hotfixer.md (hotfix executor — sonnet, no Agent) ──"
|
||||
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 dispatches hotfixer" "$HSKL" 'subagent_type="hotfixer"'
|
||||
|
||||
echo ""
|
||||
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
|
||||
finished diff into a verified, security-cleared change through two fresh
|
||||
gates and bounded loops. The dev stays inline (LRN-083: subagents =
|
||||
execution + report; loop decisions live here, in the main loop).
|
||||
gates and bounded loops. 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:
|
||||
- `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.)
|
||||
- `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** →
|
||||
STOP + human escalation with the CRITERIA table (the contract-vs-realized
|
||||
diff).
|
||||
@@ -49,8 +52,8 @@ stdout-only, no Write).
|
||||
Parse its single `SECURITY — VERDICT:` line:
|
||||
|
||||
- `PASS` → done, proceed to commit.
|
||||
- `BLOCK(n)` → hand the dev the `BLOCKING` list + the CONTRACT path. Dev
|
||||
fixes inline. Then **re-verify the REQUEST first** (GATE 1, fresh
|
||||
- `BLOCK(n)` → hand the dev the `BLOCKING` list + the CONTRACT path (inline
|
||||
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**
|
||||
(fresh auditor), in that order. **Max 3 security iterations** → STOP +
|
||||
human escalation with the BLOCKING table.
|
||||
|
||||
@@ -22,6 +22,13 @@ allowed-tools:
|
||||
|
||||
# /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.
|
||||
Per axis: **audit → approval gate → fix → re-verify → marker update**,
|
||||
strictly in that order, one axis fully closed before the next starts.
|
||||
|
||||
+245
-3
@@ -20,9 +20,251 @@ allowed-tools:
|
||||
- Agent
|
||||
---
|
||||
|
||||
Load and follow strictly:
|
||||
- $HOME/.claude/agents/bugfixer.md
|
||||
# /bugfix — root-cause orchestrator (reflection inline, execution dispatched)
|
||||
|
||||
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
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
---
|
||||
|
||||
Load and follow strictly:
|
||||
- $HOME/.claude/agents/code-cleaner.md
|
||||
# /code-clean — cleanup orchestrator (audit inline, execution dispatched)
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
---
|
||||
|
||||
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):
|
||||
- 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.
|
||||
## STEP 0 — Pre-flight (STOP conditions, before any dispatch)
|
||||
|
||||
$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
|
||||
- Grep
|
||||
- Glob
|
||||
- Agent
|
||||
---
|
||||
|
||||
Load and follow strictly:
|
||||
- $HOME/.claude/agents/doc-syncer.md
|
||||
Dispatch the doc-syncer as a subagent so its `model: sonnet` pin takes
|
||||
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):
|
||||
$ARGUMENTS
|
||||
Then commit the patched docs from THIS loop per `$HOME/.claude/lib/doc-commit.md`
|
||||
(surgical: only doc-syncer's PATCHED_FILES, never `.claude/`/`CLAUDE.md`,
|
||||
no-op if nothing patched).
|
||||
|
||||
+221
-7
@@ -1,10 +1,10 @@
|
||||
---
|
||||
name: feat
|
||||
description: |
|
||||
Small feature implementation (1-5 files). Light planning, direct
|
||||
implementation, no heavy orchestration. For features that don't
|
||||
need the full /ship-feature pipeline (no design brainstorm, no
|
||||
subagents, no plugin check gate).
|
||||
Small feature implementation (1-5 files). Reflection inline (scope,
|
||||
plan, contract — session model), execution dispatched to the
|
||||
sonnet-pinned feater executor. For features that don't need the full
|
||||
/ship-feature pipeline (no design brainstorm, no plugin check gate).
|
||||
Trigger: "feat", "small feature", "add this", "petite feature",
|
||||
"quick feature", "ajoute ca", "implement this small thing".
|
||||
For multi-file features needing design → use /ship-feature.
|
||||
@@ -20,9 +20,223 @@ allowed-tools:
|
||||
- Agent
|
||||
---
|
||||
|
||||
Load and follow strictly:
|
||||
- $HOME/.claude/agents/feater.md
|
||||
# /feat — small-feature orchestrator (reflection inline, execution dispatched)
|
||||
|
||||
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
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
|
||||
## 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
|
||||
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`
|
||||
|
||||
@@ -22,6 +22,13 @@ allowed-tools:
|
||||
|
||||
# /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
|
||||
headers + redirects + canonical + custom 404 + server configs. It
|
||||
reuses the `seo-analyzer` agent with a **strict scope filter** to avoid
|
||||
|
||||
+180
-3
@@ -18,9 +18,186 @@ allowed-tools:
|
||||
- Agent
|
||||
---
|
||||
|
||||
Load and follow strictly:
|
||||
- $HOME/.claude/agents/hotfixer.md
|
||||
# /hotfix — quick-fix orchestrator (reflection inline, execution dispatched)
|
||||
|
||||
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
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
|
||||
## 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
|
||||
$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
|
||||
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)
|
||||
If `graphify` CLI is installed AND complexity >= 30%:
|
||||
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
|
||||
|
||||
## 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
|
||||
$ARGUMENTS
|
||||
|
||||
@@ -347,7 +354,7 @@ Lire le bloc `audit_stack:` du fichier `~/.claude/lib/project-archetypes/<archet
|
||||
| Entry | Action | Livraison |
|
||||
|---|---|---|
|
||||
| `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 |
|
||||
| `doc` | Spawn subagent `doc-syncer` (auto-mode OFF, report-only) | L3a |
|
||||
| `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`).
|
||||
|
||||
#### Dispatch code-cleaner (si `code-clean` dans audit_stack)
|
||||
#### Dispatch code-clean audit (si `code-clean` dans audit_stack)
|
||||
```
|
||||
Agent(
|
||||
subagent_type="code-cleaner",
|
||||
description="Onboard — code-clean audit only",
|
||||
subagent_type="general-purpose",
|
||||
description="Onboard — code-clean audit only (read-only, big session model)",
|
||||
prompt="""
|
||||
AUDIT-ONLY mode — NO fixes, NO refactoring, NO file modifications.
|
||||
Target: <PROJECT_ROOT>. ARCHETYPE: <archetype>.
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
---
|
||||
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.'
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Edit
|
||||
- Bash
|
||||
- Grep
|
||||
- Glob
|
||||
- Agent
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
# /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.
|
||||
|
||||
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
|
||||
- `develop` is ahead of `main` and you want to publish a version.
|
||||
- "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.
|
||||
|
||||
## 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).
|
||||
2. `gitflow start release <X.Y.Z>` — forks from develop, lands on `release/<X.Y.Z>`.
|
||||
3. **Prep** on the release branch:
|
||||
- `version.txt` → `<X.Y.Z>`.
|
||||
- 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.
|
||||
- Any release-candidate fixes; commit the prep on the branch.
|
||||
- **Run the test suite** (`lib/tests/*`, gitflow-test) — RC gate; never release red.
|
||||
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.
|
||||
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.
|
||||
7. **Push — GATED (ASK).** On explicit go only ([[LRN-069]]): `git push origin main develop && git push origin v<X.Y.Z>`.
|
||||
### STEP 1 — Preconditions
|
||||
```bash
|
||||
git status --porcelain=v1 | wc -l # 0 required — clean tree
|
||||
git config user.email # must be set
|
||||
git rev-list --count main..develop # 0 → nothing to release, STOP
|
||||
```
|
||||
Any of these fail their check → STOP, tell the user what's blocking, dispatch nothing.
|
||||
|
||||
### STEP 2 — Version-number decision (judgment, stays HERE)
|
||||
Read the `## [Unreleased]` section of `CHANGELOG.md` and the commits on
|
||||
`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
|
||||
- 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
|
||||
|
||||
## 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
|
||||
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.
|
||||
|
||||
@@ -7,6 +7,13 @@ allowed-tools: Read, Write, Edit, Bash, Grep, Glob
|
||||
|
||||
# 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
|
||||
$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
|
||||
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)
|
||||
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.
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
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".'
|
||||
argument-hint: (no arguments needed)
|
||||
allowed-tools: Read, Bash, Glob, Grep
|
||||
allowed-tools: Read, Bash, Glob, Grep, Agent
|
||||
---
|
||||
|
||||
Load and follow strictly:
|
||||
- `$HOME/.claude/agents/status-reporter.md`
|
||||
Dispatch the status-reporter as a subagent so its `model: haiku` pin takes
|
||||
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
|
||||
|
||||
|
||||
+10
-2
@@ -23,6 +23,13 @@ allowed-tools:
|
||||
|
||||
# /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 →
|
||||
doc → convergence re-audit**, looping until a full pass applies zero new
|
||||
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
|
||||
|
||||
1. Dispatch a read-only cleanup audit (code-cleaner agent if available,
|
||||
else analyzer/general): dead code, unused imports/exports,
|
||||
1. Dispatch a read-only cleanup audit (analyzer or general-purpose —
|
||||
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
|
||||
`id | file:line | finding | proposed fix`.
|
||||
2. Apply **behavior-preserving** fixes only. A finding that would change
|
||||
|
||||
@@ -21,6 +21,13 @@ allowed-tools:
|
||||
|
||||
# /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 :
|
||||
|
||||
- **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
|
||||
```
|
||||
|
||||
4. On `A` : apply each bundle via `Edit` (targeted `old_string` /
|
||||
`new_string`). Never use `Write` on shared templates (risk of
|
||||
overwriting /seo or /geo content — meta tags, JSON-LD).
|
||||
5. On `B` : for each diff, show and ask yes/no/skip.
|
||||
4. On `A` : dispatch each file-group's applier at L1 (execution = sonnet;
|
||||
this loop only orchestrates), serially — one applier at a time, appliers
|
||||
share files:
|
||||
|
||||
```
|
||||
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`.
|
||||
7. On `D` : stop, leave `.claude/audits/VALIDATE.md` untouched.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user