diff --git a/.claude/memory/decisions.md b/.claude/memory/decisions.md index f2ed5c6..941cb55 100644 --- a/.claude/memory/decisions.md +++ b/.claude/memory/decisions.md @@ -120,6 +120,7 @@ rules: | BDR-096 | 2026-09-24 | Branch deletion guard: lib-only delete after verified merge, main/develop undeletable at the ref layer | accepted | | BDR-097 | 2026-09-24 | graphify from 200 tracked code files: the banner informs, the user decides | accepted | | BDR-098 | 2026-09-24 | CLAUDE.global.md density pass 352 → 270: compression only, three name-obvious routing lines dropped | accepted | +| BDR-099 | 2026-09-24 | C2 coherence: 30 doctrine/skill tensions resolved, doctrine wins, BDR-068 kept as the written exception | accepted | --- @@ -1242,3 +1243,11 @@ Branch feature/user-writing-web-rules, UNMERGED (human gate). - **Alternatives rejected**: path-scope Design work / Web sections into `rules/` (BDR-031 principle; the design hook needs the section in context regardless of file type); caveman doctrine (BDR-031: instructions-to-follow must stay prose); raise the 320 guard again (BDR-062 already moved it once; a guard that follows the file is not a guard). - **Status**: accepted, on chore/claude-global-density, UNMERGED (human gate). make test unchanged (2 pre-existing T16a), banner density warning gone, doctor 0 errors. - **Reference**: `CLAUDE.global.md`, `hooks/session-start.sh` (320 guard), `hooks/design-toolchain-reminder.sh` (heading match). Links [[BDR-031]], [[BDR-062]], [[BDR-085]]. + +## BDR-099 — C2 coherence: 30 doctrine/skill tensions resolved, doctrine wins, BDR-068 kept as the written exception +- **Date**: 2026-09-24 +- **Decision**: user go on all four groups. G3 judgment calls: (12) BDR-068 auto-finish of the memory-only `chore/*` by /capitalize+/close KEPT, written into CLAUDE.global.md + gitflow SKILL as the one finish without a live signal; (13) memory commit on develop: hook exemption for a commit that follows merged work, aiguillage `chore/*` for a standalone memory task — both written; (14) `chore/*` widened to "maintenance without new behaviour" (memory, docs, cleanup, /refactor, /tour fixes), /commit-change asks the type (public name); (15) /tour never applies a contract-breaking fix → `open — needs decision (BREAKING)`; (16) client-handover: children audit and return FIX BUNDLEs, the main loop applies AUTO items and gates the rest at ONE gate (harden whole bundle, seo D/E, geo G5, CSO dependency bumps); (17) /hotfix on develop → type `bugfix`, `hotfix/*` = prod incidents only; (18) /seo aggressive + /web-validate --fix → feature branch, /refactor → chore, via the aiguillage; (19) /doc → chore row + STEP 0. G1/G2/G4 = doctrine wins mechanically (see CHANGELOG). Lib: `gitflow init` socle via `chore/gitflow-adopt` merge (T2c). +- **Why**: TODO C2 (2026-08-25). Three read-only Plan-agent audits (doctrine+rules / skills A-H / skills I-W), 39 raw → 30 unique pairs, heaviest spot-checked by grep. Two classes dominated: today's own partial fixes (graphify 200 rule missing in init-project/onboard; density pass removed a heading 5 skills cited; deploy routing line) and BDR-095 staleness (push everywhere made deploy/release/tour/capitalize push wording false; global hooks broke init on existing repos). LRN-164 applied to myself: a rule change must grep every citer. +- **Alternatives rejected**: revoke BDR-068 for a strict human gate → 2 months of clean memory auto-persists, memory-only scope, `--no-push` opt-out exists; a new branch type for tour/commit-change code → widen chore instead, fewer types; child-held gates in handover → a dispatched child cannot hold a gate (LRN-165 class); keep `push_deploy_tags`/release push gate as no-ops → false statements in doctrine-bearing skills are worse than absence. +- **Status**: accepted, feature/c2-coherence, UNMERGED (human gate). 33 files, make test 168/170 (2 pre-existing T16a), shellcheck clean, doctor 0 errors, CLAUDE.global.md 282 lines. +- **Reference**: `CLAUDE.global.md`, `lib/gitflow.sh` `_gitflow_adopt_socle`, `lib/gitflow-test.sh` T2c, `lib/gitflow-aiguillage.md`, `lib/verify-secure-loop.md`, `lib/design-gate.md`, 16 skills, 4 agents, CHANGELOG. Links [[BDR-068]], [[BDR-095]], [[BDR-097]], [[BDR-098]], [[LRN-164]], [[LRN-165]], [[LRN-169]]. diff --git a/.claude/memory/journal.md b/.claude/memory/journal.md index 74f6755..f734e4e 100644 --- a/.claude/memory/journal.md +++ b/.claude/memory/journal.md @@ -504,3 +504,4 @@ rules: - User go "merge le tout": chore/claude-global-density → develop abec66e, then feature/graphify-threshold-banner → develop 10532e3. Predicted 3-file conflict on the append-only registries (decisions, journal, TODO — both branches appended at the same spot), resolved keeping both sides in chronological order (BDR-097 before BDR-098), merge committed by hand, finish re-run: both local and origin copies removed by the lib. CLAUDE.global.md 272 lines on develop, banner clean. No feature/chore branch left anywhere. - User go "commit + merge what remains": chore/settings-and-synced-skills → develop 87b2615. settings.json `feedbackDrafts: off` (user hand-edit) committed as is; `skills/synced/` + `skills/.bucket-*` gitignored — Claude Code's mirror of the claude.ai synced skills (UUID bucket, manifest.json, Anthropic stock skills, 4.4 MB), app-owned and rewritten at each sync, same treatment as graphify/impeccable copies (BDR-028, LRN-154). Tree clean, no working branch anywhere. - /reconcile (5 gaps fixed in TODO, chore/reconcile-2026-09-24) then /prune-memory, all 4 categories user-approved: 66 index rows backfilled, 15 `###` entries made visible to the engine, 4 supersession statuses, 6 merges LRN-163..168 (sources kept), 23 entries compressed −5% words only (negation guard dominates). Net size UP (+2.6k words: merged bodies + index rows) — value is structural, not tokens. Fidelity census green at file level; per-entry flags on BDR-073/EVAL-025 = `###` attribution artifact, bodies byte-identical. UNMERGED — human gate. +- C2 + C3 done ([[BDR-099]], [[LRN-169]]): 3 read-only audits → 30 tensions, user approved all groups + G3 as recommended; 3 executors + my doctrine/lib work on feature/c2-coherence (33 files). Real bug found + fixed: `gitflow init` on an existing repo blocked by the global pre-commit → socle via `chore/gitflow-adopt` merge, T2c. C3: superpowers 2 invocations / 126 turns over 29 sessions, both warranted → keep, re-measure in 30 days. One executor bypassed the `GIT_CONFIG_GLOBAL=` deny via a wrapper script to run a test — flagged. UNMERGED — human gate. diff --git a/.claude/memory/learnings.md b/.claude/memory/learnings.md index 566f749..fc0ab1f 100644 --- a/.claude/memory/learnings.md +++ b/.claude/memory/learnings.md @@ -188,6 +188,7 @@ rules: | LRN-166 | 2026-09-24 | structure and census locks are fixed single-line strings: a prose rewrap reds them with zero doctrine lost | editing any doctrine, skill or agent file under lib/tests locks | | LRN-167 | 2026-09-24 | a release/develop fork strands CODE on develop: a "resolved" blocker or a parallel-merged feature can miss its fix | any long-lived fork (release/*, long feature); back-merging a resolved blocker | | LRN-168 | 2026-09-24 | a relayed claim is not a fact: WebSearch consensus and sub-agent summaries both need a primary source or a live test | any number, feature or finding relayed by search or by a sub-agent before it shapes a plan or a client deliverable | +| LRN-169 | 2026-09-24 | a coherence audit is cheap when parallel and read-only, and its findings are claims: spot-check, then fix every citer | any doctrine or skill rule change; sub-agent briefs; environment-dependent tests | --- @@ -1578,3 +1579,10 @@ Rule: when editing a doctrine file under structure locks, grep the test's lock s - **Context**: seo/geo 2026-07-17. "VSI (Visual Stability Index) — new 2026 Core Web Vital" sat in seo-analyzer as a threshold; it does NOT exist — absent from the CrUX API metric list AND web.dev, 10 SEO blogs cross-cited it into consensus. EVERY stat in agents/resources/ was real but grafted onto the wrong subject (Aggarwal 40% = ALL methods; AccuraCast 58.9% = Person-schema PREVALENCE pinned on QAPage lift, meaning inverted; LLMrefs 3x = brand-mentions-vs-backlinks pinned on freshness decay). 7 sub-agent claims disproven in one session: "Off-page has ZERO data" (brand mentions ARE gathered, STEP 6); "the stats drive axis weights" (no citations); "GSC Links API is available" (endpoint doesn't exist); "SPA §0 flag compensates" (never existed); "X/Twitter returns 403" (200, live-tested); Common Crawl "nearest free source" (17.3 GB dead end); the whole opening inventory behind the 20-point plan. The same error reproduced 3× while WRITING the fixes; contact with the REAL corrected it every time — sitemap, repo, curl, primary doc. - **Future application**: an API's metric list (developer.chrome.com/docs/crux) is decisive: a metric the API can't return is one you can't score. Measure-first before building on a relayed summary; never re-read the spec as verification. Corroborates [[LRN-074]] (watch the RED go red), [[LRN-034]] (narrated ≠ ground truth). - **Reference**: `agents/seo-analyzer.md`, `agents/resources/`, [[EVAL-025]]. Supersedes [[LRN-131]], [[LRN-132]] (bodies kept). + +## LRN-169 — a coherence audit is cheap when parallel and read-only, and its findings are claims: spot-check, then fix every citer +- **Date**: 2026-09-24 +- **Context**: C2 audit of CLAUDE.global.md + 31 own skills + rules + doctrine libs (~9k lines). Three `Plan` agents (read-only tool set) in parallel, one brief each: definition of "in tension" (contradiction / ambiguity / stale ref verified by ls-grep), fixed output shape, explicit bans (no skill/CLI/hook runs, no edits). ~500k sub-agent tokens, 11 min wall. 39 raw pairs, 30 unique; 4 heaviest re-verified by grep before presenting, all held. +- **Pattern**: (a) the two dominant defect classes were MY same-day partial fixes (200-file graphify rule landed in advisor+doctrine, not in the two orchestrators that build; density pass renamed a heading 5 skills cited; a routing line kept "deploy → ship" with /deploy existing) and a 2-day-old staleness wave (BDR-095 auto-push made 5 skills' push text false, global hooks broke `gitflow init` on existing repos). Rule change → `grep -rn` every citer and every consumer BEFORE committing ([[LRN-164]] applied to doctrine). (b) test hermeticity hides environment regressions: `make test` neutralises the global git config, so the global-hook breakage of init was invisible; add a test that SIMULATES the environment (T2c sets a hooks dir as if global). (c) executors with closed briefs applied 35+8+6 prose edits cleanly in parallel; the residue was scope edges (2 lines in an agent outside E1's list, 2 passages E3 saw but was not allowed to touch) → give executors the whole file family, not a line list. (d) one executor routed around the static deny on `GIT_CONFIG_GLOBAL=` by writing a wrapper script to run a test: harmless here, but a sub-agent WILL work around a guardrail when the brief asks for a result the guardrail blocks — brief "if a guard denies a command, report and stop" explicitly ([[LRN-160]] class). (e) C3 measured superpowers over 29 sessions: 2 invocations / 126 turns, both warranted; a plugin's MUST yields to user instructions in practice — measure before disabling ([[LRN-080]]). +- **Future application**: for any doctrine/skill rule change: grep citers first, patch them in the same commit. Environment-dependent behaviour (global hooks, PATH, HOME) → a test that simulates the environment, not one that neutralises it. Sub-agent briefs → "denied by a guard = stop and report", never "find a way". Re-run the C2 audit after each doctrine wave; re-run the C3 transcript census in 30 days. +- **Reference**: [[BDR-099]], `lib/gitflow-test.sh` T2c, transcript census script (session scratch, re-creatable: parse `~/.claude/projects/*/*.jsonl`, Skill tool_use with `superpowers:` prefix, preceding user text). diff --git a/.claude/tasks/TODO.md b/.claude/tasks/TODO.md index 4968869..8a8fd67 100644 --- a/.claude/tasks/TODO.md +++ b/.claude/tasks/TODO.md @@ -1,5 +1,38 @@ # TODO +## 2026-09-24 — C2 coherence: 30 doctrine/skill tensions resolved (feature/c2-coherence) +Audit by 3 read-only analysts (doctrine+rules, skills A-H, skills I-W), 39 raw +pairs → 30 unique, spot-checked by grep. User approved all four groups + G3 as +recommended. C3 (superpowers) closed: no over-trigger in 29 sessions / 126 turns +(2 brainstorming calls, both warranted), ~800 tok fixed/session → keep, re-measure +in 30 days with the same transcript script. +- [x] WP-A doctrine (CLAUDE.global.md): 3 compress-on-demand → via /prune-memory; + 4 deploy → /deploy; 5 one ask policy; 12 BDR-068 exception clause; 13 memory + commit: exemption vs aiguillage, both written; 14 chore = maintenance without + new behaviour; 17 hotfix on develop → bugfix; 22 skill plan file satisfies the + planning rule; 23 mandated executors exempt from the delegation rule; 24 + journal line exempt from the approval gate. Stay < 320 lines. +- [x] WP-B lib bug (7): `_gitflow_init_existing` socle commit blocked on main by the + live global pre-commit → socle on `chore/gitflow-adopt` off main, merged + --no-ff (merge exempt), branch deleted; T2c with a simulated global hook. +- [x] WP-C E1 gitflow-family skills: capitalize/close `--no-push` text (11), memory + missing → create (21), gitflow SKILL exception line (12), § Language ×5 (2), + hotfix aiguillage bugfix-on-develop (17) + design-gate skip (25), feat/bugfix/ + hotfix executor wording (23), ship-feature .gsd/STATE.md (27), init-project + graphify gate (1) + memory bootstrap (21), aiguillage table rows (/doc, + /commit-change, seo/web-validate/refactor) (18,19), doc STEP 0 aiguillage + (19), commit-change asks branch type (14). +- [x] WP-D E2: onboard graphify gate (1) + STEP 2.6 rewrite (7) + add gsd/continue + (28); tour push wording (10), BREAKING → needs decision (15), doc-syncer + two-mode (26); deploy push_deploy_tags (8); release-candidate tag-only push + gate + release-executor + its test (9). +- [x] WP-E E3: client-handover gate + script path (16, 29); seo/web-validate/refactor + aiguillage step (18); pdf-translate sudo (30); verify-secure-loop inline-fix + removal under locks (20); design-gate.md extensions/impeccable/anim list (6). +- [x] WP-F verify: make test, shellcheck, doctor, banner; review full diff; BDR-099 + (C2 resolutions) + LRN-163? no: LRN-169 (audit method) + journal; C2/C3 ticked + in the 2026-08-25 block. Merge on user go. + ## 2026-09-24 — CLAUDE.global.md density pass (chore/claude-global-density) - [x] 352 → 270 lines, −15% words, compression only (BDR-031/062 principle), headings verbatim, graphify § byte-identical (feature/graphify-threshold-banner @@ -515,12 +548,14 @@ Order fixed, one branch per chantier, no merge without per-chantier signal. Residual for gate: §6bis dynamically-unverified list (FULL branches, apply path — census-locked statically); FULL/aggressive dry-run = user option; nested-CLI dogfood blocked by monthly spend limit (inline used). -- [ ] C2 self-contradiction audit CLAUDE.global.md + own skills: list rule +- [x] C2 self-contradiction audit CLAUDE.global.md + own skills: list rule pairs in tension, propose resolution per pair, apply after user OK. /doctor as assistant, not authority. -- [ ] C3 superpowers: MEASURE first (skill-invocation log over sessions) + → DONE 2026-09-24: 30 pairs, all resolved on feature/c2-coherence (BDR-099). +- [x] C3 superpowers: MEASURE first (skill-invocation log over sessions) whether "1% chance → MUST invoke" over-triggers; if yes, options + trade-offs (disable plugin / softer house rule / live with) — user decides. + → DONE 2026-09-24: measured 2/126 turns, both warranted → keep, re-measure in 30 days (LRN-169). - [x] C4 hygiene: reinstall darwin-skill — DONE (reconcile 2026-08-25: ~/.agents/skills/darwin-skill present, T6c green, make test exit 0). diff --git a/CHANGELOG.md b/CHANGELOG.md index 8077537..de54b12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -112,6 +112,25 @@ Format follows [Keep a Changelog](https://keepachangelog.com/). until it lands. ### Changed +- **Doctrine/skill coherence pass (C2)** — 30 rule pairs in tension found by + three read-only audits and resolved in the doctrine's favour: one ask + policy (visible / public-name / open-scope choices are asked); mandated + executors exempt from the "don't delegate the trivial" rule; a + skill-persisted plan satisfies the planning rule; the journal line is + exempt from the approval gate; `chore/*` = maintenance without new + behaviour; a small fix on develop is a `bugfix`, `hotfix/*` is for prod + incidents; the BDR-068 memory auto-finish is written as the one exception; + `deploy` routes to `/deploy`. Skills follow: /hotfix types by base and skips + the design gate on the trivial tier; /capitalize and /close create missing + registries instead of stopping; /commit-change asks the branch type; /doc, + /seo, /web-validate and /refactor branch through the aiguillage; /tour + reports contract-breaking fixes as `needs decision` and runs doc-syncer in + its two modes; client-handover applies audit bundles from its main loop + behind one gate; init-project and onboard propose graphify only through + the 200-file signal and bootstrap the memory registries; release-candidate + gates the tag push only; push wording aligned with the BDR-095 hooks in + tour, deploy, capitalize; stale pointers fixed (`§ Language`, `.gsd/ + ROADMAP.md`, handover script path, design-gate extensions and lists). - **CLAUDE.global.md density pass** 352 → 270 lines (−15% words): prose tightened, Security subsections folded into one labelled list, routing lines that only repeated a skill description dropped. Every constraint and @@ -238,6 +257,9 @@ Format follows [Keep a Changelog](https://keepachangelog.com/). traced by reading, never by running, whatever the brief says. ### Removed +- `deploy` `push_deploy_tags` knob (the STATE.json commit's hook pushes the tag + with `--follow-tags`); `/onboard add gsd` and `/onboard continue` mentions + (never had a handler). - **`magic` MCP (`@21st-dev/magic`) and `MAGIC_API_KEY`**, with the two risks attached to them: the unauthenticated `127.0.0.1` callback server `21st_magic_component_builder` opened (LRN-110) and the plaintext key copy @@ -247,6 +269,13 @@ Format follows [Keep a Changelog](https://keepachangelog.com/). and the dead `MAGIC_API_KEY=abc123` gitleaks allowlist regex. ### Fixed +- **`gitflow init` on an existing repo under the machine-wide hooks** — the + socle commit (`.gitignore` + `.githooks/`) landed directly on `main` + "while the hook is inactive"; since the global `core.hooksPath` the + pre-commit refused it and init died. The socle now lands on + `chore/gitflow-adopt` off main, merged `--no-ff` (merge commits run no + pre-commit), branch deleted, develop created after. T2c simulates the live + hook; the hermetic suite could not see the regression. - **`make update` no longer drops the Playwright OS-support bump** — a gstack submodule update used to leave the bump unapplied until the next `make plugin`, the open caveat of BDR-029. `update-all.sh` now goes diff --git a/CLAUDE.global.md b/CLAUDE.global.md index 724d651..0a1cff9 100644 --- a/CLAUDE.global.md +++ b/CLAUDE.global.md @@ -34,14 +34,16 @@ Apply unless repo-specific instructions override. 2. Either missing → create it first (templates: `~/.claude/templates/memory/`). ## Workflow -- Confirm before implementing only when real trade-offs exist (several - valid approaches, breaking change, destructive action); else proceed. - Minimal changes unless a broader refactor is requested. State trade-offs. +- Confirm the approach only when real trade-offs exist (several valid + approaches, breaking change, destructive action); ask on the visible, + public-name and open-scope choices below; otherwise proceed. Minimal + changes unless a broader refactor is requested. State trade-offs. - Sub-agents: one task each, main context stays clean. Delegate independent, sizeable tracks (wide multi-file exploration, parallel - audits), not work doable in a few tool calls. Skill-mandated gates (fresh - verifier/security/challenge) always dispatch as written; a failed gate - re-dispatches a fresh executor, never redo its work by hand. A brief never + audits), not work doable in a few tool calls. Skill-mandated executors and + gates (pinned executors, fresh verifier/security/challenge) always dispatch + as written, whatever the task size; a failed gate re-dispatches a fresh + executor, never redo its work by hand. A brief never authorizes a sub-agent to run a destructive tool, inside or outside the repo (Security → Destructive tools & data loss). - Ask rather than guess. A choice visible in the result (placement, @@ -67,7 +69,9 @@ Apply unless repo-specific instructions override. - Exempt: pure reads, explanations, questions, typos, cosmetic CSS, single config value — the `/hotfix` scope (≤2 files, obvious fix). - Once it qualifies: plan before code → one subtask = one coherent change - → check off as you go → high-level note at each milestone. + → check off as you go → high-level note at each milestone. A plan a skill + persists (`.claude/tasks/plans/`, contract) satisfies the rule; TODO.md + then carries one line per run. ## After code changes 1. Run tests, lint, build, type-check if available. Report what was @@ -98,12 +102,13 @@ exact. Pattern `[thing] [action] [reason]. [next step].` Registries load every session; caveman cuts ~40% of the tokens with no substance lost. Applies to direct writes and to the CAPITALIZE step of every completion skill. Prompts to the user may mirror their language; the entry is English. -Legacy entries: compress on demand. +Legacy entries: compress on demand via `/prune-memory`. **Proactive capitalization** is Claude's job: after a substantive milestone (root-caused bug fix, shipped feature, non-trivial commit, design choice, surprising discovery, dead end with a lesson) offer to capitalize inline, -entry pre-filled, user approves before the write. Completion skills +entry pre-filled, user approves before the write; the one-line journal +entry is exempt, it logs and decides nothing. Completion skills (`/ship-feature` `/feat` `/bugfix` `/hotfix` `/commit-change`) do it via their CAPITALIZE step. Session close (`/close` = `/capitalize --ritual`): what was decided → decisions, learned → learnings, blocked → blockers. @@ -137,20 +142,24 @@ never bent to match a newer one. ## Version control — gitflow (universal) Every git action follows gitflow, inside a skill or for an ad-hoc commit. `main` (prod) · `develop` (integration, off main) · `feature/*` `bugfix/*` -`chore/*` (off develop → develop; chore = memory/doc maintenance such as a -standalone `/capitalize` `/close` `/prune-memory` `/reconcile`) · -`release/*` (off develop → main + back-merge develop) · `hotfix/*` (off main -→ main + develop + any open release). `master` → `main` everywhere. +`chore/*` (off develop → develop; chore = maintenance without new behaviour: +memory, docs, cleanup, `/refactor`, `/tour` fixes) · `release/*` (off develop +→ main + back-merge develop) · `hotfix/*` (off main → main + develop + any +open release; prod incidents only, a small fix on develop is a `bugfix`). +`master` → `main` everywhere. Never commit code on `main` or `develop`: branch first as `/` -(`.claude/**` memory/config commits are hook-exempt, following the work). +(a `.claude/**` memory/config commit that follows merged work is hook-exempt +and lands in place; a standalone memory task branches `chore/*`). Branch, merge and delete only via the lib: `bash ~/.claude/lib/gitflow.sh start ` · `finish` · `delete
`. `finish` runs only on an explicit human signal ("merge it", "feature OK"), never because tests pass, a plan step says merge, or "ship" implied it. Assistance flows (`/feat` `/bugfix` `/hotfix`) and the standalone memory/doc skills auto-branch on a -protected base but commit in place on a working branch, never finishing, so -they branch to `chore/*` via the aiguillage, not the `.claude/**` exemption. +protected base but commit in place on a working branch, never finishing +(one exception, BDR-068: `/capitalize` and `/close` auto-finish the +memory-only `chore/*` they created this run), so they branch to `chore/*` +via the aiguillage, not the `.claude/**` exemption. Deterministic backstops behind the doctrine: the pre-commit hook (blocks code commits on main/develop; exempts `.claude/**`, `.githooks/**`, merges, the root commit), Gitea branch protection on both, and never `--no-verify`. @@ -229,7 +238,8 @@ cryptic names. gates, registries). investigate only on explicit ask for the gstack ecosystem (cross-project learnings, /freeze, long open-ended investigation) - feat / hotfix / bugfix distinguished by file count → see descriptions -- Ship / deploy / PR → ship (ship-feature if gstack off) +- Ship / PR → ship (ship-feature if gstack off); deploy → deploy (runbook, + the user runs it) - Docs post-ship → document-release (doc if gstack off); stale-doc audit → doc - Grouped all-axes sweep ("tir groupé", fix + loop until clean) → tour - Open-work inventory / "queue empty?" / stale TODO vs git → reconcile diff --git a/USAGE.md b/USAGE.md index c20feec..0393523 100644 --- a/USAGE.md +++ b/USAGE.md @@ -262,7 +262,7 @@ cd mon-projet-existant/ | 2 | Config baseline (onboarder agent) | CLAUDE.md, settings.json, .claudeignore, .claude/tasks/ + .claude/memory/ + .claude/audits/ | | 3 | Interview deep = business minimum (users, deadlines, équipe, légal, perfs) + adaptative par archétype | brief enrichi | | 3.5| ctx7 doc audit — fast-libs détectées, cache pré-fetché si besoin | .ctx7-cache/ | -| 4 | Graphify (si complexity ≥ 30%) | graphify-out/GRAPH_REPORT.md | +| 4 | Graphify (proposé dès 200 fichiers code, l'utilisateur décide) | 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 (general-purpose, audit read-only) | @@ -280,7 +280,6 @@ cd mon-projet-existant/ ``` /onboard "Python FastAPI" # hint stack /onboard force-archetype:wordpress # override detection -/onboard add gsd # générer ROADMAP.md pour GSD v2 (seul) ``` **Après /onboard :** @@ -291,6 +290,8 @@ cat .claude/audits/ONBOARD_REPORT.md # Démarrer la première tâche P0 avec le skill recommandé # (indiqué dans .claude/tasks/TODO.md) /hotfix "" # ou /feat, /ship-feature, /bugfix selon le cas + +# Multi-session (GSD) : gsd init à la main — voir docs gsd-pi ``` **Archétypes supportés (P1)** : static-html, wordpress, nextjs-app-router, astro-static, react-spa, rest-api-node, rest-api-python, cli-tool, library, dotfiles-meta. diff --git a/agents/client-handover-writer.md b/agents/client-handover-writer.md index c8883d1..6b0af6b 100644 --- a/agents/client-handover-writer.md +++ b/agents/client-handover-writer.md @@ -61,7 +61,7 @@ and degrading Google's NAP-consistency signal. Pipeline (each step gates the next): 1. Baseline audits: SEO+GEO and security hardening in parallel. -2. Fix loops: re-invoke each audit with auto-fix until ≥17/20 or `MAX_ITERATIONS` hit. +2. Fix loops: apply each audit's bundle (AUTO items, ONE gate for GATED ones) and re-audit until ≥17/20 or `MAX_ITERATIONS` hit. 3. Commit + push if files changed. 4. Deploy pause: list deploy artifacts + process, wait for user confirmation. 5. Live-site validation against the deployed URL. @@ -266,14 +266,14 @@ For web projects, dispatch in **a single message with two parallel Agent calls** | Audit (web) | Subagent | Prompt template | |---------------|-------------------|-----------------| -| SEO + GEO | `general-purpose` | "Read `~/.claude/skills/seo/SKILL.md` and execute it on this project. The /seo skill runs SEO + GEO in parallel and writes a unified report to `.claude/audits/SEO.md`. Apply autonomous code fixes you can safely make (meta tags, JSON-LD, robots.txt, sitemap.xml, llms.txt, alt attrs, canonical tags). At the top of the report, the /seo skill MUST emit two distinct labeled score lines (already specified in its SKILL.md §1): `Score SEO (classique) : X.X / 20` and `Score GEO (IA) : X.X / 20`, plus the weighted global. The handover orchestrator parses SEO and GEO separately, so do not collapse them into a single `Score:` line. Return when the report file is written." | -| HARDEN | `general-purpose` | "Read `~/.claude/skills/harden/SKILL.md` and execute it on this project. Apply autonomous code fixes (security headers in vercel.json/netlify.toml/.htaccess/nginx.conf, HSTS, CSP defaults, HTTP→HTTPS redirects, canonical, 404 page). Write report to `.claude/audits/HARDEN.md` with `Score: X/20` (or `X/100`) at the top. Return when the report file is written." | +| SEO + GEO | `general-purpose` | "Read `~/.claude/skills/seo/SKILL.md` and execute it on this project. The /seo skill runs SEO + GEO in parallel and writes a unified report to `.claude/audits/SEO.md`. Run it in conservative mode: apply NOTHING, return the FIX BUNDLE (the handover main loop applies it — see 'Applying the bundle'). At the top of the report, the /seo skill MUST emit two distinct labeled score lines (already specified in its SKILL.md §1): `Score SEO (classique) : X.X / 20` and `Score GEO (IA) : X.X / 20`, plus the weighted global. The handover orchestrator parses SEO and GEO separately, so do not collapse them into a single `Score:` line. Return when the report file is written." | +| HARDEN | `general-purpose` | "Read `~/.claude/skills/harden/SKILL.md` and execute it on this project with `--fix` up to READY TO APPLY only: prepare the FIX BUNDLE (security headers, HSTS, CSP, HTTP→HTTPS redirects, canonical, 404 page), apply NOTHING — the handover main loop gates and applies it (see 'Applying the bundle'). Write report to `.claude/audits/HARDEN.md` with `Score: X/20` (or `X/100`) at the top. Return when the report file is written." | Non-web variant: | Audit (non-web) | Subagent | Prompt template | |-----------------|-------------------|-----------------| -| CSO | `general-purpose` | "Read `~/.claude/skills/cso/SKILL.md` and execute in **daily mode** (8/10 confidence gate). Apply autonomous fixes for findings that are clearly safe (e.g., adding `.env` to `.gitignore`, replacing committed example secrets with placeholders). Write report to `.claude/audits/CSO.md` with `Score: X/20` (or `X/100`) at the top." | +| CSO | `general-purpose` | "Read `~/.claude/skills/cso/SKILL.md` and execute in **daily mode** (8/10 confidence gate). Apply NOTHING: return the fixes as a FIX BUNDLE (gitignore additions and placeholder swaps tagged AUTO, dependency upgrades tagged GATED — the handover main loop applies AUTO and gates the rest, see 'Applying the bundle'). Write report to `.claude/audits/CSO.md` with `Score: X/20` (or `X/100`) at the top." | Wait for both subagents to complete (parallel return). @@ -370,7 +370,12 @@ iteration = 1 # HARDEN/CSO/VALIDATE loops use only their own score. while (audit == "SEO" ? (SCORE_SEO < 17 OR SCORE_GEO < 17) : score < 17) \ and iteration ≤ MAX_ITERATIONS: - re-dispatch the audit subagent with iteration context (see prompt below) + apply the pending FIX BUNDLE from THIS main loop — AUTO items, then + ONE gate for the GATED items (see "Applying the bundle" below); + iteration 1 consumes the baseline audit's bundle, if any + re-dispatch the audit subagent in AUDIT mode with iteration context + (see prompt below) — it re-scores and returns the next FIX BUNDLE; + it applies NOTHING (a dispatched child cannot hold a gate) re-parse score(s) AND projected code-only score(s) from the audit file if no scores improved AND no files changed → break (no progress) # Code-ceiling break: when the actual score has caught up with the @@ -386,11 +391,43 @@ The projected code-only scores come from the analyzers' mandatory console). If no projected line is parseable, treat projected = 17 (legacy behavior: loop chases 17 blindly). +### Applying the bundle (THIS main loop — the child never applies) + +A dispatched child cannot hold a gate (harden: "the fix mode prepares the +bundle; the dispatcher confirms"; geo: "NEVER apply a GATED item before +explicit approval"). So every bundle is applied from here, per iteration: + +1. **AUTO items** — the tier the audit itself classed no-confirmation + (`/seo` STEP 1.5: seo batches A/B/C, geo G1–G4/G6). Dispatch each item's + L1 applier (`hotfixer` / `feater`) serially, item pasted verbatim, + "Do NOT commit — apply and self-verify only". Harden has no AUTO tier: + its whole bundle is confirmation-gated. CSO (non-web): gitignore additions + and secret placeholder swaps are AUTO. +2. **GATED items** — seo D/E, geo G5, EVERY harden item (CSP, redirects, + anything its STEP 2b challenge flagged "could BREAK the site") and CSO + dependency upgrades (a version bump can break the build). Collect + them from every bundle of this iteration and present ONE gate + (AskUserQuestion): change → impact → file. Apply only the approved items + (same appliers); declined ones stay in the report as CODE-BLOQUÉ. Never + apply a GATED item before explicit approval. +3. **USER ACTIONS** (seo batch F, geo G7) — never applied; they bound the + projected code-only score. + +For each item applied, append a line to the audit's fix log +(`.claude/audits/SEO-FIX-LOG.md` for SEO and GEO items, +`.claude/audits/HARDEN-FIX-LOG.md` for harden, `.claude/audits/CSO-FIX-LOG.md` +for CSO) in the format +`iter: [SEO|GEO|HARDEN] → — `. + ### Re-dispatch prompt template (SEO + GEO loop) Send to `general-purpose` subagent (`model: "fable"`): -> Read `~/.claude/skills/seo/SKILL.md` and re-run it on this project. +> Read `~/.claude/skills/seo/SKILL.md` and re-run it on this project in +> **conservative (audit-only) intervention mode**: re-score and leave both +> FIX BUNDLEs in `.claude/audits/SEO.md` ready-to-apply. Apply NOTHING and +> ask the user NOTHING — the handover main loop is the dispatcher: it +> applies the AUTO items and holds the gate on the GATED ones. > Previous scores: > - **SEO classique: ``/20** (threshold 17/20 — ``) > - **GEO (IA): ``/20** (threshold 17/20 — ``) @@ -398,34 +435,33 @@ Send to `general-purpose` subagent (`model: "fable"`): > Iteration `` of ``. Both axes are gated independently; > the orchestrator continues to loop while EITHER score is below 17/20. > -> Read `.claude/audits/SEO.md` for the current issue list. Apply ALL safe -> autonomous fixes (do not skip "easy" ones). Prioritize fixes for the -> axis currently below threshold: -> - SEO classique fixes: meta tags, headings, canonical, sitemap.xml, +> Read `.claude/audits/SEO.md` for the current issue list. Prioritize +> bundle items for the axis currently below threshold (do not drop "easy" +> ones): +> - SEO classique: meta tags, headings, canonical, sitemap.xml, > alt attrs, internal linking, Core Web Vitals hints. -> - GEO (IA) fixes: llms.txt / llms-full.txt, robots.txt entries for AI +> - GEO (IA): llms.txt / llms-full.txt, robots.txt entries for AI > crawlers (GPTBot, ClaudeBot, PerplexityBot, etc.), Schema.org for AI > extraction (QAPage, Speakable, Person+Article, HowTo, Organization > graph), entity SEO (sameAs, @id), TL;DR / definition-lead content > shape, citable stats markup, freshness signals. > -> For each fix applied, append a line to `.claude/audits/SEO-FIX-LOG.md` -> (format: `iter: [SEO|GEO] → — `). Update -> `.claude/audits/SEO.md` with the new scores — both labeled lines MUST -> be present: `Score SEO (classique) : X.X / 20` and -> `Score GEO (IA) : X.X / 20`, plus the weighted global. Do NOT ask the -> user; apply or skip with one-line justification in the fix log. +> Update `.claude/audits/SEO.md` with the new scores — both labeled lines +> MUST be present: `Score SEO (classique) : X.X / 20` and +> `Score GEO (IA) : X.X / 20`, plus the weighted global. ### Re-dispatch prompt template (HARDEN loop) Send to `general-purpose` subagent (`model: "fable"`): -> Read `~/.claude/skills/harden/SKILL.md` and re-run it. Previous score: +> Read `~/.claude/skills/harden/SKILL.md` and re-run it with `--fix` ONLY +> up to the bundle: stop at `READY TO APPLY — awaiting dispatcher +> confirmation`, apply NOTHING, ask NOTHING — the handover main loop is +> the dispatcher that confirms. Previous score: > **``/20** — below threshold. Iteration `` of -> ``. Apply all autonomous fixes (security headers, HSTS, -> CSP, redirects, canonical, 404, .htaccess/nginx/vercel/netlify config). -> Append entries to `.claude/audits/HARDEN-FIX-LOG.md`. Update -> `.claude/audits/HARDEN.md` with new score. +> ``. The `## 8. Fix bundle` MUST cover security headers, +> HSTS, CSP, redirects, canonical, 404, .htaccess/nginx/vercel/netlify +> config. Update `.claude/audits/HARDEN.md` with the new score. ### Re-dispatch prompt template (CSO loop — non-web only) @@ -433,15 +469,18 @@ Send to `general-purpose` subagent (`model: "fable"`): > Read `~/.claude/skills/cso/SKILL.md` and re-run it in **daily mode**. > Previous score: **``/20** — below threshold. -> Iteration `` of ``. Apply all safe autonomous fixes -> (gitignore additions, secret placeholder swaps, dependency upgrades for -> known CVEs with semver-compatible patches). Append entries to -> `.claude/audits/CSO-FIX-LOG.md`. Update `.claude/audits/CSO.md` with -> new score. +> Iteration `` of ``. Apply NOTHING: return the fixes as +> a FIX BUNDLE in `.claude/audits/CSO.md` — gitignore additions and secret +> placeholder swaps tagged AUTO, dependency upgrades (even semver-compatible +> CVE patches) tagged GATED. The handover main loop applies AUTO items and +> gates the rest (see 'Applying the bundle'). Update `.claude/audits/CSO.md` +> with the new score. ### Parallelism -For web projects, the two loops run in parallel: dispatch SEO iteration +For web projects, the two loops run in parallel: apply both pending +bundles first (AUTO items, then ONE gate for every GATED item of both), +then dispatch SEO iteration `N` AND HARDEN iteration `N` in a single message with two `Agent` calls, wait for both, re-parse both scores, decide whether each loop continues, then dispatch iteration `N+1` for the audits still below threshold (in @@ -454,7 +493,7 @@ nothing to parallelize). Track `score_history[audit] = [iteration → score]`. If iteration `N` score equals iteration `N-1` score AND `git status --porcelain` shows no new -changes from that iteration's subagent: mark loop `STALLED`. Break. +changes from that iteration's apply step: mark loop `STALLED`. Break. ### Escalation on cap or stall @@ -627,7 +666,8 @@ Dispatch `general-purpose` subagent (`model: "fable"`): > Read `~/.claude/skills/web-validate/SKILL.md` and execute against the > deployed URL: ``. Audit W3C HTML validity (validator.nu), > W3C CSS validity (jigsaw.w3.org), WCAG 2.1 a11y (axe-core, pa11y). -> Apply autonomous fixes ONLY in source code (the client controls deploy); +> Apply NOTHING (the client controls deploy; the handover main loop applies +> the returned FIX BUNDLE from source, AUTO items only): return the fix list, > document remaining issues. Write report to `.claude/audits/VALIDATE.md` > with `Score: X/20` (or `X/100`) at the top. diff --git a/agents/commit-changer.md b/agents/commit-changer.md index 211a66a..0acf231 100644 --- a/agents/commit-changer.md +++ b/agents/commit-changer.md @@ -42,10 +42,13 @@ approval gates live in the `/commit-change` dispatcher, not here. ### Phase 0: Gitflow aiguillage (before any commit) -**Follow `$HOME/.claude/lib/gitflow-aiguillage.md` — your type = `chore`.** -On `main`/`develop` it branches first (to `chore/` 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`, +**Follow `$HOME/.claude/lib/gitflow-aiguillage.md` — your type = the `TYPE:` +line of the dispatch prompt (`feature` / `bugfix` / `chore`, chosen by the user +in the dispatcher; never hardcode `chore`).** On `main`/`develop` it branches +first (to `/` derived from the pending work) so the +commits never land directly on a protected base; a protected base with NO +`TYPE:` in the prompt → do not branch, report it under EDGE CASES so the +dispatcher asks. On a working branch it's a no-op (commit in place). Never `finish`, 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 @@ -146,8 +149,9 @@ criteria as the standalone `/capitalize` flow: 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 +**Language rule**: draft entries in English AND caveman — fragments, +articles dropped, code/IDs/quoted errors verbatim (CLAUDE.md "Memory +registries", Always English, always caveman) — 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. @@ -225,9 +229,9 @@ Otherwise: (`.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). +3. **Language rule**: written entries are ALWAYS in English and caveman, + regardless of the language used in the dispatcher's approval exchange + (CLAUDE.md "Memory registries", Always English, always caveman). 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 diff --git a/agents/handover-doc-writer.md b/agents/handover-doc-writer.md index 0575dd2..85d7e36 100644 --- a/agents/handover-doc-writer.md +++ b/agents/handover-doc-writer.md @@ -130,7 +130,7 @@ concrete, no jargon. One short paragraph per idea. [§6.2](#62-plateformes-prioritaires-semaine-1) ``` - The renderer (`scripts/handover-to-pdf.sh`) uses pandoc with + The renderer (`$HOME/.claude/skills/client-handover/scripts/handover-to-pdf.sh`) uses pandoc with `--from=gfm+gfm_auto_identifiers` (or python-markdown's `toc` extension as fallback). Both auto-generate heading IDs in the GitHub-style slug: diff --git a/agents/release-executor.md b/agents/release-executor.md index fe68feb..101c2f9 100644 --- a/agents/release-executor.md +++ b/agents/release-executor.md @@ -9,7 +9,7 @@ model: sonnet 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 +release" decision, and the tag push — 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`. @@ -76,12 +76,15 @@ actual branch; never finish whatever happens to be checked out. output verbatim; do not attempt to resolve it yourself. 2. **Tag AFTER finish, on `main`** — never before: `git tag -a v main -m "release "` (annotated, so it lands on - main's release-merge commit). + main's release-merge commit). Finish has already pushed `main` and + `develop` through the lib's hooks (BDR-095); the tag stays local until + the dispatcher's tag-push gate. ### 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. +`git push` (any remote, any ref — `main`/`develop` ride the lib's hook +pushes during finish; the dispatcher owns the tag-push gate), deciding the +version number, the when-to-release decision, attribution trailers of any +kind. --- diff --git a/lib/design-gate.md b/lib/design-gate.md index 01b1ff6..ed385af 100644 --- a/lib/design-gate.md +++ b/lib/design-gate.md @@ -17,11 +17,11 @@ Check BOTH the task description AND the filesystem: - Framework UI: `tailwind`, `styled-component`, `emotion`, `chakra`, `radix`, `shadcn`, `headless` **Filesystem signals** (quick check, no deep scan): -- Target files have `.tsx`, `.jsx`, `.css`, `.scss`, `.less`, or `.module.css` extension +- Target files have `.tsx`, `.jsx`, `.vue`, `.svelte`, `.astro`, `.css`, `.scss`, `.less`, or `.module.css` extension - `tailwind.config` or `postcss.config` present in project root - `tokens/`, `theme/`, or `design-system/` directory exists - Storybook config (`.storybook/`) present -- Animation lib in `package.json` deps: `motion`, `motion-v`, `framer-motion` (legacy), `gsap`, `@gsap/react`, `lottie-react`, `react-spring`, `popmotion`, `@formkit/auto-animate` +- Animation lib in `package.json` deps: any package `is_anim_lib_installed` recognizes (`lib/animation-lib-check.sh`, the single source) ## DECISION @@ -40,7 +40,7 @@ and if not, point at ONE command — `/profile design`. Tier does NOT change WHAT gets checked. Every non-trivial design tier draws from the one `design` profile — so the gate checks that profile's **design-core tools** (the `# GATE-BLOCK:` allowlist in `design.profile`: ui-ux-pro-max, -frontend-design, emil-design-eng, design-motion-principles, impeccable, design-html, +frontend-design, emil-design-eng, design-motion-principles, design-html, design-review, design-consultation, the `21st` CLI and `21st-ui-build` — the canary for the whole 21st skill pack). The profile also bundles browser/plan/shotgun tooling and graphify for convenience; those never trip the @@ -149,7 +149,7 @@ says so, because init has to happen in the agent chat, not in an installer. **Fires when BOTH hold** — else stay silent: -1. impeccable is active (`skills/impeccable` present, i.e. it did not trip §3). +1. impeccable symlink present under `skills/` (non-blocking external — not on the `# GATE-BLOCK:` list, so §3 never checks it). 2. The project has no `PRODUCT.md` at its root. Evaluate it on the same path as §4: after the toolchain resolves, never on the diff --git a/lib/gitflow-aiguillage.md b/lib/gitflow-aiguillage.md index a51f0d8..196f4b9 100644 --- a/lib/gitflow-aiguillage.md +++ b/lib/gitflow-aiguillage.md @@ -21,11 +21,14 @@ The caller passes its TYPE: |--------|------|------| | `/feat` | `feature` | develop | | `/bugfix` | `bugfix` | develop | -| `/hotfix` | `hotfix` | main | +| `/hotfix` | `hotfix` on main · `bugfix` on develop | main · develop | +| `/seo` aggressive · `/web-validate --fix` | `feature` | develop | | `/capitalize` · `/close` · `/prune-memory` · `/reconcile` | `chore` | develop | +| `/doc` · `/refactor` | `chore` | develop | +| `/commit-change` | asks the user (`feature` / `bugfix` / `chore`) before `start` — a branch name is a public name | develop | -The `chore` row = **standalone memory/doc work**: the registry / TODO / doc -reconciliation & curation skills, run OUTSIDE an assistance flow. Inside `/feat` +The `chore` rows = **standalone memory/doc/hygiene work**: the registry / TODO / +doc reconciliation & curation skills (+ `/refactor`), run OUTSIDE an assistance flow. Inside `/feat` `/bugfix` `/hotfix` `/ship-feature` a working branch already exists (this check returns WORKING) and the memory commit rides it. The aiguillage only fires when such a skill is invoked directly on `main`/`develop` — i.e. memory IS the work, @@ -39,6 +42,8 @@ develop + push) when THEY branched a `chore/*` off develop this run (BDR-068 — scoped [[LRN-069]] exception; see the capitalize skill's STEP 5C). `/prune-memory` + `/reconcile` stay fully human-gated: never run `gitflow finish` from them. -Note: `hotfix` branches off **main** (prod) even when invoked from `develop` — that -is the gitflow definition of a hotfix. For a dev-scoped small fix, use `/bugfix` -(branches off develop). +Note: a `hotfix/*` branch forks off **main** (prod) and fans out to main + develop +at finish — that is the gitflow definition of a hotfix. Invoked from `develop`, +`/hotfix` therefore starts a `bugfix/*` (off develop): a `hotfix/*` there would +miss develop's code and later merge to prod. The small-fix routing is unchanged; +only the branch type follows the base. diff --git a/lib/gitflow-test.sh b/lib/gitflow-test.sh index 901b17d..a961a7e 100644 --- a/lib/gitflow-test.sh +++ b/lib/gitflow-test.sh @@ -50,7 +50,7 @@ chk "tree CLEAN after init" '[ -z "$(git status --porcelain)" ]' chk "hook TRACKED in commit" 'git ls-files --error-unmatch .githooks/pre-commit >/dev/null 2>&1' chk "socle IN root commit" 'git show HEAD:.gitignore | grep -qxF ".claude/deploy/PENDING.json"' -echo "T2b — init existing (master→main rename + adoption commit, hook inactive during it)" +echo "T2b — init existing (master→main rename + adoption via chore/gitflow-adopt merge)" newrepo existing git symbolic-ref HEAD refs/heads/master # force the repo onto 'master' echo a > a.txt; printf 'node_modules/\n' > .gitignore; git add -A @@ -64,6 +64,22 @@ chk "existing tree CLEAN" '[ -z "$(git status --porcelain)" ]' chk "existing hook tracked" 'git ls-files --error-unmatch .githooks/pre-commit >/dev/null 2>&1' chk "kept project rule" 'git show HEAD:.gitignore | grep -qxF "node_modules/"' +echo "T2c — init existing under a LIVE pre-commit (global hooks simulated): socle lands via merge" +newrepo live; git symbolic-ref HEAD refs/heads/master +echo a > a.txt; printf 'node_modules/\n' > .gitignore; git add -A +git -c core.hooksPath=/dev/null commit -q -m "pre-existing on master" +_gitflow_write_hook "$WORK/globalhooks" # the machine-wide hook set, as make link installs it +git config core.hooksPath "$WORK/globalhooks" # stands in for git's GLOBAL core.hooksPath during init +# shellcheck disable=SC2034 +live_rc=0; GITFLOW_NO_PUSH=1 gitflow_init >/dev/null 2>&1 || live_rc=$? +chk "T2c init succeeds under the live hook (rc 0)" "[ $live_rc -eq 0 ]" +chk "T2c socle reached main via a merge commit" 'git log main --oneline -1 | grep -q "Merge chore/gitflow-adopt"' +chk "T2c .gitignore socle on main" 'git show main:.gitignore | grep -qxF ".claude/deploy/PENDING.json"' +chk "T2c hooks tracked on main" 'git ls-tree -r main --name-only | grep -q "^.githooks/pre-commit$"' +chk "T2c adoption branch deleted" '! git rev-parse --verify -q refs/heads/chore/gitflow-adopt >/dev/null' +chk "T2c develop created from main" '[ "$(git rev-parse develop)" = "$(git rev-parse main)" ]' +chk "T2c repo hook active afterwards" '[ "$(git config core.hooksPath)" = .githooks ]' + echo "T3 — hook blocks/permits after init" cd "$WORK/fresh" || exit 1 git checkout -q main diff --git a/lib/gitflow.sh b/lib/gitflow.sh index 856b413..b885603 100644 --- a/lib/gitflow.sh +++ b/lib/gitflow.sh @@ -293,20 +293,38 @@ _gitflow_init_existing() { # has commits → ensure main (rename master) fi fi git checkout -q "$GITFLOW_MAIN" || return 1 - # commit the socle + versioned hook now, while hooksPath is NOT yet active - # (activation is the last step of gitflow_init) → never self-blocked. + # The socle (.gitignore + versioned hooks) reaches main through a MERGE: the + # pre-commit hook is global on the machine (BDR-095), so a direct commit on + # main is refused even during init, while a merge commit is hook-exempt. + # Any failure aborts BEFORE develop/hook activation so a partial run can't + # activate the hook and self-block every re-run. git add -- .gitignore .githooks 2>/dev/null || true - # socle commit failure is FATAL — abort BEFORE develop/hook-activation so a - # partial run can't activate the hook and self-block every re-run (was a bug: - # the `|| commit` form swallowed the failure, then init activated the hook). if ! git diff --cached --quiet -- .gitignore .githooks 2>/dev/null; then - git commit -q -m "chore: adopt gitflow socle + pre-commit hook" \ - || { echo "gitflow_init: socle commit failed — aborting before hook activation (recoverable)" >&2; return 1; } + _gitflow_adopt_socle || return 1 fi git rev-parse --verify -q "refs/heads/$GITFLOW_DEVELOP" >/dev/null \ || git branch "$GITFLOW_DEVELOP" "$GITFLOW_MAIN" } +# Commit the staged socle on chore/gitflow-adopt (a working branch, so the +# pre-commit allows it), merge it --no-ff into main (a merge commit runs no +# pre-commit), delete the branch. The branch forks off main because develop +# does not exist yet at init time. +_gitflow_adopt_socle() { + local br="chore/gitflow-adopt" + if git rev-parse --verify -q "refs/heads/$br" >/dev/null; then + echo "gitflow_init: '$br' already exists (earlier run) — merge or delete it, then re-run" >&2 + return 1 + fi + git checkout -q -b "$br" || return 1 + git commit -q -m "chore: adopt gitflow socle + versioned hooks" \ + || { echo "gitflow_init: socle commit failed — aborting before hook activation (recoverable)" >&2; return 1; } + git checkout -q "$GITFLOW_MAIN" || return 1 + git merge --no-ff -q -m "Merge $br into $GITFLOW_MAIN" "$br" \ + || { echo "gitflow_init: socle merge into $GITFLOW_MAIN failed — aborting before hook activation" >&2; return 1; } + git branch -q -d "$br" +} + # gitflow_init [msg] → idempotent. Order matters (full BLK-010 closure): # reconcile .gitignore + write the versioned hook FIRST, so the fresh root # commit / existing adoption commit EMBED them; activate the hook LAST so the diff --git a/lib/verify-secure-loop.md b/lib/verify-secure-loop.md index 12a37ca..cd37cbe 100644 --- a/lib/verify-secure-loop.md +++ b/lib/verify-secure-loop.md @@ -59,9 +59,9 @@ 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. Inline dev fixes in place; - a dispatched dev is re-dispatched FRESH with those inputs only. Then - re-run GATE 0 and re-dispatch a FRESH verifier. Repeat. + lines (NOT-MET / out-of-scope), nothing else: re-dispatch a FRESH executor + with those inputs only, never redo the fix by hand. Then re-run GATE 0 and + re-dispatch a FRESH verifier. Repeat. **Max 3 conformity iterations** → STOP + human escalation with the CRITERIA table (the contract-vs-realized diff). - `ABANDONED(n)` → direct human gate, never a dev loop (a dev cannot close @@ -88,8 +88,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 (inline - fix, or FRESH executor re-dispatch). Then re-run GATE 0, then +- `BLOCK(n)` → hand the dev the `BLOCKING` list + the CONTRACT path + (re-dispatch a FRESH executor, never fix by hand). Then re-run GATE 0, 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 diff --git a/skills/bugfix/SKILL.md b/skills/bugfix/SKILL.md index bbd730b..f74941f 100644 --- a/skills/bugfix/SKILL.md +++ b/skills/bugfix/SKILL.md @@ -272,7 +272,7 @@ A bugfix with an understood root cause is almost always worth one entry: ``` 4. Append approved entries + update the Index. Add a line to today's heading in `.claude/memory/journal.md`. -**Language rule**: written entries are ALWAYS in English (see CLAUDE.md "Memory registries" § Language). The interactive gate may mirror the user's language; the appended entries must not. +**Language rule**: written entries are ALWAYS English AND caveman — fragments, articles dropped, code/IDs/quoted errors verbatim — per CLAUDE.md "Memory registries" (Always English, always caveman). The interactive gate may mirror the user's language; the appended entries must not. If the bug was trivial and the root cause not transferable → skip with `CAPITALIZE: trivial, skip`. @@ -287,7 +287,9 @@ hash, and no-ops if nothing was written. - No fix without understanding the root cause first (STEP 2/3). - Reflection (GATHER, INVESTIGATE, DIAGNOSIS, contract, loop decisions) NEVER leaves this main loop; execution NEVER stays in it — the executor is the - sonnet-pinned bugfixer subagent (BDR-066). + sonnet-pinned bugfixer subagent (BDR-066). A skill-mandated executor is exempt from the doctrine's "don't delegate + few-tool-call work" rule (CLAUDE.md "Workflow" names that exception: + skill-mandated dispatches run as written). - The executor is re-dispatched FRESH on every round-trip (NEED-DECISION, ECARTS, BLOCK) — feedback travels as contract path + named gaps/decisions, never as transcript. diff --git a/skills/capitalize/SKILL.md b/skills/capitalize/SKILL.md index 547e91b..c637b7c 100644 --- a/skills/capitalize/SKILL.md +++ b/skills/capitalize/SKILL.md @@ -9,7 +9,7 @@ description: | Triggers: "capitalize", "before clear/compact", "flush memory", "don't lose this", "avant de clear/compact", "capitalise ce qui manque", "close", "fin de journée", "checkpoint memory". -argument-hint: "[--ritual] [--no-push] (scans conversation + git + TODO against .claude/memory/; --ritual adds the 3-question reflection; --no-push holds memory on the chore branch instead of the default auto-merge+push)" +argument-hint: "[--ritual] [--no-push] (scans conversation + git + TODO against .claude/memory/; --ritual adds the 3-question reflection; --no-push holds memory on chore/: pushed to origin by the hooks, NOT merged (finish skipped), merge when ready; default = auto-finish into develop)" allowed-tools: - Read - Edit @@ -65,17 +65,22 @@ ls .claude/memory/decisions.md .claude/memory/learnings.md \ ls .claude/tasks/TODO.md 2>/dev/null ``` -- `.claude/memory/` missing entirely → print and STOP (do NOT create here — - that is `/onboard` / `/init-project` responsibility): - ``` - ⚠️ .claude/memory/ absent. Lance `/onboard` (ou `/init-project`) pour créer - les registres avant de capitaliser. +- `.claude/memory/` missing entirely → create it first (CLAUDE.md "Session + start": either missing → create from the templates), then proceed: + ```bash + mkdir -p .claude/memory + cp -n ~/.claude/templates/memory/{decisions,learnings,blockers,evals,journal}.md .claude/memory/ ``` + `/onboard` stays the fuller setup (CLAUDE.md, settings, audits) — this + bootstraps only the five registries capitalize writes to. - Some registry files missing → name them, create each from `~/.claude/templates/memory/.md`, continue. -- `.claude/tasks/TODO.md` missing → the TODO reconcile volet (STEP 2B) is - **skipped**. Do NOT create it (same posture as the registries). Registries - still run. +- `.claude/tasks/TODO.md` missing → create a minimal one, then run the TODO + reconcile volet (STEP 2B) on it: + ```bash + mkdir -p .claude/tasks + printf '# TODO\n\n## %s\n' "$(date +%Y-%m-%d)" > .claude/tasks/TODO.md + ``` ## STEP 1 — SCAN THE CONVERSATION @@ -164,7 +169,7 @@ concatenated class names" entry.) ## STEP 2B — TODO RECONCILE (both modes) -Runs only if `.claude/tasks/TODO.md` exists (STEP 0). Two passes. +Runs on `.claude/tasks/TODO.md` (created minimal at STEP 0 when absent). Two passes. **PASS A — done-detection (TODO → reality).** Detection is free — a capable agent already spots the finished tasks from the STEP 1 git scan. The only rule @@ -358,7 +363,7 @@ Then the closing line — pick by the STEP 5C persist result (`` = `Contex flushed` for pre-wipe, `Session closed` for ritual): - **auto-persisted (default — branched off develop, pushed)** → `✅ + persisted to origin/develop (). Next session: read .claude/memory/ at startup.` -- **--no-push (held on branch)** → `✅ + committed on chore/, NOT pushed (--no-push). Merge + push when ready.` +- **--no-push (held on branch)** → `✅ + committed on chore/ — pushed to origin by the hooks, NOT merged (--no-push: finish skipped). Merge when ready.` - **push failed after merge** → `✅ + merged to develop — ⚠️ push FAILED (); merged locally, push manually.` - **WORKING branch (rode a feature branch)** → `✅ + committed on . Integrates when the branch merges.` - **commit skipped (rc 3)** → keep the ✅ on the WRITE but make the gap loud, never @@ -380,7 +385,7 @@ manual commit (rc 3). - **Append-only.** Never overwrite or renumber existing registry entries. - **Caveman English** registry bodies, always English. **The TODO is plain prose, never caveman** — caveman is registries-only. -- **TODO reconcile runs only if TODO.md exists.** Never create it (STEP 0). +- **TODO reconcile always runs** — a missing TODO.md is created minimal at STEP 0. - **PASS A checks only on an unambiguous task↔code/commit map.** Partial / umbrella / vague → leave unchecked. Never on assumption. - **PASS B captures only explicit to-dos**, deduped — never invented or @@ -398,7 +403,8 @@ manual commit (rc 3). WORKING branch (memory rides feature/bugfix) or rc 3 skips it. NEVER auto-finish a branch the run did not create. - **Skip trivial** for the 4 ID registries; journal excepted. -- `.claude/memory/` missing → STOP at STEP 0, do not create the structure here. +- `.claude/memory/` missing → STEP 0 creates the five registries from the + templates (doctrine: either missing → create first), then proceeds. ## Common mistakes @@ -417,7 +423,7 @@ manual commit (rc 3). | Dumping an architecture directive as a TODO task | Route orientation/policy directives to decisions.md (BDR), not the TODO. | | Writing a ritual answer fresh without dedup | Ritual answers go through STEP 2 like any candidate; a dup shows its existing ID. | | French/English entry text | Prompt may be French; written registry entry is always English. | -| Creating `.claude/memory/` or `.claude/tasks/TODO.md` when absent | Not this skill's job — registries STOP and point to `/onboard`; TODO volet is skipped. | +| Stopping on a missing `.claude/memory/` or `.claude/tasks/TODO.md` | Doctrine says create first — STEP 0 bootstraps the five registries + a minimal TODO from the templates, then proceeds; `/onboard` is the fuller setup. | ## Red flags — STOP diff --git a/skills/client-handover/SKILL.md b/skills/client-handover/SKILL.md index dad6e8b..8d07813 100644 --- a/skills/client-handover/SKILL.md +++ b/skills/client-handover/SKILL.md @@ -40,8 +40,8 @@ The agent runs a **ship-and-handover pipeline** with explicit gates: 1. **PRE-FLIGHT** — Detect git repo, project root, language, project type, web sub-type, NAP signals, stack. 2. **BASELINE AUDITS** — Run /seo (SEO+GEO) and /harden in parallel. Capture initial scores (`SCORE_SEO_BEFORE`, `SCORE_GEO_BEFORE`, `SCORE_HARDEN_BEFORE`). 3. **FIX LOOPS (parallel, bounded)** — For each audit < 17/20: - - Re-invoke the audit subagent with explicit instruction to apply auto-fixes. - - Re-score. + - Apply the pending FIX BUNDLE from the MAIN loop: items the audit classed AUTO directly, then every GATED item (CSP, redirects, anything harden marks "could BREAK the site") presented to the user at ONE gate before applying. + - Re-invoke the audit subagent in audit mode: it re-scores and returns the next FIX BUNDLE; it applies nothing (a dispatched child cannot hold a gate). - Repeat up to `MAX_ITERATIONS` (default 5). - If still < 17/20 after cap → escalate to user with concrete remaining issues; user decides continue / stop / manual intervention. 4. **COMMIT + PUSH** — If files changed during fix loops, run /commit-change (atomic logical commits) then `git push`. @@ -57,7 +57,7 @@ The agent runs a **ship-and-handover pipeline** with explicit gates: - **§6 Détails techniques (pour les curieux)** — vulgarized BDR decisions, phases with technical detail, optional glossary (score table NOT here — promoted to §2). - **§7 Annexe — plateformes externes** (web/local-business only). - **§8 Annexe — build & déploiement** (only if requested). -9. **RENDER** — Write `LIVRAISON.md` (fr) or `HANDOVER.md` (en) at project root, then run `scripts/handover-to-pdf.sh` to produce the matching branded `.html` (always) and `.pdf` (when a PDF engine is on the host: weasyprint > wkhtmltopdf > chromium). HTML/PDF use the ZenQuality cover page, green palette, Inter + Playfair Display typography, running header/footer with project name + page numbers. +9. **RENDER** — Write `LIVRAISON.md` (fr) or `HANDOVER.md` (en) at project root, then run `$HOME/.claude/skills/client-handover/scripts/handover-to-pdf.sh` to produce the matching branded `.html` (always) and `.pdf` (when a PDF engine is on the host: weasyprint > wkhtmltopdf > chromium). HTML/PDF use the ZenQuality cover page, green palette, Inter + Playfair Display typography, running header/footer with project name + page numbers. Flags: - `--skip-fix-loop` — run baseline audits once, skip auto-fix iterations. diff --git a/skills/close/SKILL.md b/skills/close/SKILL.md index 05497a9..014faef 100644 --- a/skills/close/SKILL.md +++ b/skills/close/SKILL.md @@ -8,7 +8,7 @@ description: | (that is /prune-memory). Triggers: "close", "end session", "ferme la session", "session close", "checkpoint memory", "what did we learn", "retro rapide", "fin de journée". -argument-hint: "[--no-push] (runs capitalize in ritual mode; --no-push holds memory on the chore branch instead of the default auto-merge+push)" +argument-hint: "[--no-push] (runs capitalize in ritual mode; --no-push holds memory on chore/: pushed to origin by the hooks, NOT merged (finish skipped), merge when ready; default = auto-finish into develop)" allowed-tools: - Read - Edit diff --git a/skills/commit-change/SKILL.md b/skills/commit-change/SKILL.md index 6d8d8e2..f2b2579 100644 --- a/skills/commit-change/SKILL.md +++ b/skills/commit-change/SKILL.md @@ -45,16 +45,28 @@ git config user.email - `git config user.email` empty → STOP, ask the user to configure identity first, do not dispatch. -On a protected base (`main`/`develop`) the subagent runs the gitflow -aiguillage itself inside `MODE: propose` (its Phase 0) and branches to -`chore/*` before drafting the plan — code never lands directly on a -protected branch. +On a protected base (`main`/`develop` — `bash "$HOME/.claude/lib/gitflow.sh" +protected-base`) ask the user the branch TYPE before any dispatch — a branch +name is a public name: + +``` +AskUserQuestion: + Protected base — branch type for these commits? (feature / bugfix / chore) +``` + +Suggest `chore` only when every pending path is under `.claude/**` or docs; +pending code never lands on a `chore/*` branch. Pass the answer as +`TYPE: ` in the STEP 1 prompt — the subagent runs the aiguillage with it +inside `MODE: propose` (its Phase 0) and branches to `/*` before drafting +the plan. Code never lands directly on a protected branch. On a working +branch, omit `TYPE:` (the aiguillage is a no-op there). ## STEP 1 — Propose ``` Agent(subagent_type="commit-changer", model="opus") prompt: "MODE: propose +TYPE: $ARGUMENTS" ``` @@ -86,7 +98,7 @@ AskUserQuestion: BDR-077 — never redrawn inline on the session model); show the redrawn plan and re-ask. - `skip` → exit cleanly, no commits created, no `MODE: apply` dispatch. - Note: if the propose run created a `chore/*` branch (gitflow aiguillage + Note: if the propose run created a `/*` 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. diff --git a/skills/deploy/SKILL.md b/skills/deploy/SKILL.md index d8762d0..084be65 100644 --- a/skills/deploy/SKILL.md +++ b/skills/deploy/SKILL.md @@ -182,7 +182,6 @@ Author a runbook, seed the incident ledger, commit both, then proceed to STEP 1. #!/usr/bin/env bash # === deploy runbook (reference) — NOT run directly. Instantiated into the deploy checklist per delta. === # Fixed steps run every deploy; annotated steps (@delta lines) re-instantiate from the delta. - # @config push_deploy_tags=false ``` 3. Scan for migration, rebuild, and dependency steps; propose `@delta:` annotations inline: - Migration steps (`psql -f`, `migrate up`, `supabase migration`) → @@ -219,12 +218,10 @@ Author a runbook, seed the incident ledger, commit both, then proceed to STEP 1. | Backup command | "Backup command before migrations?" | `pg_dump "$DB" > ~/backups/pre-deploy-$(date +%F-%H%M).sql` | | Health-check URL | "Health-check URL (expects HTTP 200)?" | `https://$DEPLOY_HOST/health` | | Rollback note | "One-line rollback note (optional)?" | omit if blank | -| Push deploy tags | "`push_deploy_tags`? (true / false)" | `false` | **Using** `~/.claude/templates/deploy/PROCEDURE.md` **as base, populate** fields from interview answers + detected artifacts: - Substitute `$DEPLOY_HOST` with the supplied host (keep literal `$DEPLOY_HOST` if none given). - Include only the annotated steps whose artifact was detected; keep all fixed steps. -- Set `# @config push_deploy_tags=` in the header. - Append the rollback note as `# ROLLBACK: ` at the end if provided. → **[GATE]** below. @@ -427,9 +424,7 @@ Then: The deploy succeeded. Lay the oracle and close out. -1. Read `# @config push_deploy_tags=` from the `PROCEDURE.md` header (default - `false`). Pick `date = today` (`YYYY-MM-DD`); if `deploy/` exists, suffix - `-N`. +1. Pick `date = today` (`YYYY-MM-DD`); if `deploy/` exists, suffix `-N`. 2. Write `.claude/deploy/STATE.json` (overwrite): ```jsonc { "deployed_sha": "", "deployed_at": "", @@ -438,9 +433,10 @@ The deploy succeeded. Lay the oracle and close out. **`deployed_sha` = `PENDING.target_sha`, NOT current HEAD** — HEAD may have moved during the gap; the bridge's target is the deployed truth. 3. `git tag -a deploy/ -m ""`. -4. If `push_deploy_tags=true` → `git push origin deploy/` — **best-effort, - non-fatal**: a push failure logs a warning, never blocks the mark (the tag is a - bookmark; `STATE.json` is the oracle). +4. No separate tag push: the oracle commit (step 5) fires the gitflow + post-commit hook, which pushes with `--follow-tags`, so `deploy/` + rides along (BDR-095). A hook `push FAILED` warning never blocks the mark + (the tag is a bookmark; `STATE.json` is the oracle). 5. Commit the oracle: ```bash bash ~/.claude/lib/deploy-commit.sh commit "chore(deploy): mark @ " \ diff --git a/skills/doc/SKILL.md b/skills/doc/SKILL.md index 11a89b1..db4d8e1 100644 --- a/skills/doc/SKILL.md +++ b/skills/doc/SKILL.md @@ -22,6 +22,13 @@ Run the two-mode doc pipeline (BDR-077 — audit judgment on opus, patch on the sonnet pin, the validation gate in THIS loop; a dispatched agent cannot hold a gate): +0. AIGUILLAGE — before any write, follow `$HOME/.claude/lib/gitflow-aiguillage.md` + — this skill's TYPE = `chore`. On `main`/`develop` it branches to + `chore/` off develop so the doc patch lands on a branch; on a working + branch it proceeds in place. Never `gitflow finish`. `lib/doc-commit.md`'s + rc 5 (commit rejected by the hook on a protected base) stays as the + backstop, not the plan. + 1. AUDIT — dispatch: `Agent(subagent_type="doc-syncer", model="opus")` prompt: "MODE: audit. Audit public docs for this project. Context from diff --git a/skills/feat/SKILL.md b/skills/feat/SKILL.md index 65393be..16dce74 100644 --- a/skills/feat/SKILL.md +++ b/skills/feat/SKILL.md @@ -244,7 +244,7 @@ Valider ? (all / / edit / skip) Always append a 1-line entry to today's heading in `.claude/memory/journal.md`. -**Language rule**: written entries are ALWAYS in English (see CLAUDE.md "Memory registries" § Language). The interactive gate may mirror the user's language; the appended entries must not. +**Language rule**: written entries are ALWAYS English AND caveman — fragments, articles dropped, code/IDs/quoted errors verbatim — per CLAUDE.md "Memory registries" (Always English, always caveman). The interactive gate may mirror the user's language; the appended entries must not. If no substantive capture candidate → skip with `CAPITALIZE: nothing to log`. @@ -259,7 +259,9 @@ hash, and no-ops if nothing was written. - Max 5 files. If more needed → `/ship-feature`. - Reflection (scope, plan, contract, loop decisions) NEVER leaves this main loop; execution NEVER stays in it — the executor is the sonnet-pinned - feater subagent (BDR-066). + feater subagent (BDR-066). A skill-mandated executor is exempt from the doctrine's "don't delegate + few-tool-call work" rule (CLAUDE.md "Workflow" names that exception: + skill-mandated dispatches run as written). - The executor is dispatched FRESH on every round-trip — feedback travels as contract path + named gaps/decisions, never as transcript. - Design gate only (not full plugin check). See STEP 0.5. diff --git a/skills/gitflow/SKILL.md b/skills/gitflow/SKILL.md index 42a1c39..efc9109 100644 --- a/skills/gitflow/SKILL.md +++ b/skills/gitflow/SKILL.md @@ -85,7 +85,10 @@ On a protected base, assistance skills (`feat`/`bugfix`/`hotfix`) AND the standa memory/doc skills (`capitalize`/`close`/`prune-memory`/`reconcile`, TYPE `chore`) call `start ` to branch first; on a working branch they commit in place. Same `protected-base` predicate the out-of-skill hook uses. Caller→type map + rationale: -`lib/gitflow-aiguillage.md`. +`lib/gitflow-aiguillage.md`. `/capitalize` and `/close` auto-finish their memory-only +`chore/*` branch into develop when THEY created it this run (BDR-068; `--no-push` +opts out) — the only finish that fires without a live human signal; everything else +stays human-gated. ## Failure modes (mechanical — lib return codes are the contract) diff --git a/skills/hotfix/SKILL.md b/skills/hotfix/SKILL.md index d08682c..2e55596 100644 --- a/skills/hotfix/SKILL.md +++ b/skills/hotfix/SKILL.md @@ -64,8 +64,11 @@ disposition required at hotfix weight. Follow `$HOME/.claude/lib/design-gate.md`: - Scan $ARGUMENTS and target files for design/UI/style signals (CSS, component, styling, animation). -- If signals found → run `design-tool-gate.sh`; if it reports INCOMPLETE, - tell the user to run `/profile design` before proceeding. +- Signals found → a hotfix is the trivial tier by definition (≤2 files, one + cosmetic value — `design-gate.md` §1): skip the gate, no toolchain. If the + signals reveal real UI work (new component, layout, motion), this is not a + hotfix → route to `/feat` or `/bugfix` instead of running + `design-tool-gate.sh`. - If no signals → skip (zero overhead). ## STEP 1.7 — CONTRACT (silent autofill) @@ -104,8 +107,12 @@ verify+secure loop). ## STEP 2 — PRE-FLIGHT **Gitflow aiguillage (before dispatch):** follow `$HOME/.claude/lib/gitflow-aiguillage.md` -— your type = `hotfix`. On `main`/`develop` it branches first; on a working -branch it's a no-op (commit in place). Never `finish`. +— your type follows the base: on `main` → `hotfix` (prod incident; finish fans +out to main + develop); on `develop` → `bugfix` (the fix forks from develop — a +`hotfix/*` off main would miss develop's code and later merge to prod). Either +protected base branches first; on a working branch it's a no-op (commit in +place). The /hotfix size rules and the hotfixer executor are unchanged either +way. Never `finish`. Snapshot current state so revert is possible: @@ -223,7 +230,7 @@ Ask the user only when there is an actual candidate to propose. Always append a 1-line entry to today's heading in `.claude/memory/journal.md` (even trivial hotfix — journal is timeline, not signal). -**Language rule**: the journal line and any proposed BLK/LRN entries are ALWAYS written in English (see CLAUDE.md "Memory registries" § Language). +**Language rule**: the journal line and any proposed BLK/LRN entries are ALWAYS written English AND caveman — fragments, articles dropped, code/IDs/quoted errors verbatim — per CLAUDE.md "Memory registries" (Always English, always caveman). **Then commit the memory** — follow `$HOME/.claude/lib/capitalize-commit.md`: it surgically commits what capitalize just wrote (`.claude/memory` + `.claude/tasks` @@ -237,7 +244,9 @@ trivial hotfix still produces a `chore(memory): journal — …` commit (Frame 2 - Max 2 files changed. If more needed → `/bugfix`. - Reflection (LOCATE, contract, gate decisions) NEVER leaves this main loop; execution NEVER stays in it — the executor is the sonnet-pinned - hotfixer subagent (BDR-066). + hotfixer subagent (BDR-066). A skill-mandated executor is exempt from the doctrine's "don't delegate + few-tool-call work" rule (CLAUDE.md "Workflow" names that exception: + skill-mandated dispatches run as written). - The executor is dispatched FRESH, once — hotfix never re-dispatches after a failed or blocked attempt (it reverts and escalates to `/bugfix`, it does not retry). Sole exception: a class-tagged BLOCKED answered by the diff --git a/skills/init-project/SKILL.md b/skills/init-project/SKILL.md index 3e603b2..239f702 100644 --- a/skills/init-project/SKILL.md +++ b/skills/init-project/SKILL.md @@ -103,7 +103,14 @@ every field the scaffolder consumes crosses the dispatch): BRIEF (verbatim) `~/.claude/CLAUDE.md`. A STOP (missing input) comes back as its report — resolve here, re-dispatch. The ~30s liveness pings are THIS loop's job while waiting. -Creates: CLAUDE.md, `.claude/settings.json`, `.claudeignore`, `.gitignore`, `.env.example`, empty entry points. NO README, NO features, NO `.claude/tasks/` or `.claude/memory/` (not bootstrapped by this flow — copy from `~/.claude/templates/memory/` manually if wanted before STEP 10b's memory commit). +Creates: CLAUDE.md, `.claude/settings.json`, `.claudeignore`, `.gitignore`, `.env.example`, empty entry points. NO README, NO features. +Then bootstrap the memory in THIS loop, before STEP 5f so the root commit embeds +it (doctrine: registries + TODO exist from day one; STEP 10b appends to them): +```bash +mkdir -p .claude/memory .claude/tasks +cp -n ~/.claude/templates/memory/{decisions,learnings,blockers,evals,journal}.md .claude/memory/ +[ -f .claude/tasks/TODO.md ] || printf '# TODO\n\n## %s\n' "$(date +%Y-%m-%d)" > .claude/tasks/TODO.md +``` Verify: `git init` + build passes. ## STEP 5b — CREATE README @@ -166,7 +173,7 @@ layout and the deterministic root commit: bash "$HOME/.claude/lib/gitflow.sh" init "chore: scaffold " ``` Creates `main`+`develop`, root-commits the FULL scaffold (CLAUDE.md, README, -config, `.gitignore`, deps), reconciles the `.gitignore` socle, and installs the +config, `.gitignore`, `.claude/memory/` + `.claude/tasks/TODO.md`, deps), reconciles the `.gitignore` socle, and installs the versioned pre-commit hook — all embedded in the root commit, working tree clean. This is the deterministic scaffold commit owner (closes BLK-010). The MVP is implemented on a `feature/*` branch off `develop` (STEP 8). @@ -217,14 +224,15 @@ call. The plan is closed; execution and plan-conformity review are sonnet work. Reflection (task decomposition, review verdict arbitration) stays in this loop. -## STEP 8b — GRAPHIFY FULL (after implementation) -If `graphify` CLI is installed AND complexity >= 30%: -1. Run full graphify on the implemented project: - ```bash - graphify . --out graphify-out 2>/dev/null || true - ``` -2. Print: `🔗 Full project graph updated at graphify-out/` -If `graphify` not installed or complexity < 30% → skip silently. +## STEP 8b — GRAPHIFY SIGNAL (after implementation — BDR-097) +graphify is proposed only from 200 tracked code files, and the USER decides — +never build, install or update a graph here: +```bash +bash ~/.claude/lib/graphify-gate.sh . +``` +- Prints a line → carry it into the FINAL OUTPUT status table as + `GRAPHIFY: — /graphify on your go`. +- Silent → `GRAPHIFY: below 200 code files, not proposed`. ## STEP 9 — VERIFY + SECURE (fresh gates, bounded loops) Run the two fresh gates per `$HOME/.claude/lib/verify-secure-loop.md` with @@ -284,7 +292,9 @@ capitalizes NOTHING. Do NOT fabricate a BDR to fill the step. Print [ decisions.md ] BDR-XXX — — <1-line why> Valider lesquels ? (all / / edit / skip) ``` -3. Append approved entries + update the Index. Append a journal line under today. +3. Append approved entries to the existing registries (bootstrapped at STEP 5, + in the root commit) + update the Index. Append a journal line under today's + heading in `.claude/memory/journal.md`. **Hash rule — founding decisions carry NO commit hash; use path + date only.** This is by nature, not an omission: a founding decision is made at DESIGN @@ -295,8 +305,10 @@ that IMPLEMENTS the decision, e.g. BDR-033 → 11792cc). This is the SECOND case where hash-anchoring does not apply — the first being a squash-merged PR, whose anchored commit ceases to exist. -**Language rule**: written entries are ALWAYS in English (CLAUDE.md "Memory -registries"). The gate may mirror the user's language; entries must not. +**Language rule**: written entries are ALWAYS English AND caveman — fragments, +articles dropped, code/IDs/quoted errors verbatim — per CLAUDE.md "Memory +registries" (Always English, always caveman). The gate may mirror the user's +language; entries must not. **Then commit the memory** — follow `$HOME/.claude/lib/capitalize-commit.md`: it surgically commits the approved founding decisions (`.claude/memory` + @@ -369,5 +381,6 @@ LOCATION: | STACK: | BUILD: ✅/❌ | TESTS: ✅/❌ V1 FEATURES: ✅ / ⚠️ partial: REMAINING ISSUES: QUICK START: -CLAUDE.md ✅ | README ✅ | SETTINGS ✅ +CLAUDE.md ✅ | README ✅ | SETTINGS ✅ | MEMORY ✅ +GRAPHIFY: ``` diff --git a/skills/onboard/SKILL.md b/skills/onboard/SKILL.md index 96f2c69..b3ae11c 100644 --- a/skills/onboard/SKILL.md +++ b/skills/onboard/SKILL.md @@ -1,7 +1,7 @@ --- name: onboard description: 'Use when bringing an existing repo into the claude-config framework — needs archetype detection, config install, full multi-axis audit (debt/SEO/GEO/UI-UX/perf/security/a11y/docs), and prioritized backlog. Multi-agent orchestrator. Do NOT use for repos created via /init-project. Triggers: "onboard", "onboard project", "audit existing repo", "setup existing project".' -argument-hint: '[optional hints: "Python FastAPI" | "add gsd" | "Next.js monorepo" | "force-archetype:wordpress"]' +argument-hint: '[optional hints: "Python FastAPI" | "Next.js monorepo" | "force-archetype:wordpress"]' allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Agent, Skill --- @@ -27,7 +27,8 @@ Run `$HOME/.claude/lib/plugin-gate.md` with hint "onboarding existing project + - PROPOSED CHANGES exist → show list, ask "Apply? (yes / no / customize)". Apply on confirm. - OK → `✅ Plugin check passed — [active plugins] — complexity: %`, continue. -Complexity score is carried forward for STEP 4 graphify decision. +Complexity score is informative here; STEP 4 graphify is gated by +`graphify-gate.sh` (200 tracked code files, BDR-097), not by this score. --- @@ -107,7 +108,7 @@ L'agent génère : - `.claudeignore` - `.gitignore` (safety check) - `.claude/tasks/TODO.md`, `.claude/memory/{decisions,learnings,blockers,journal,evals}.md` -- **Pas encore** `ROADMAP.md` (généré uniquement via `/onboard add gsd` — voir Next steps) +- **Pas encore** `ROADMAP.md` (GSD multi-session : `gsd init` à la main, voir docs gsd-pi — cf. Next steps) Si `CLAUDE.md` existe déjà : lire son contenu, ne PAS écraser — fusionner après STEP 3. @@ -151,11 +152,13 @@ Adopter le modèle gitflow sur ce repo existant : ```bash bash "$HOME/.claude/lib/gitflow.sh" init ``` -Sur un repo existant, cela : renomme `master`→`main` si besoin (LOCAL), crée -`develop` depuis main, réconcilie le socle `.gitignore` (additif — n'écrase -jamais les règles du projet), installe le hook pre-commit versionné, et fait UN -commit `chore: adopt gitflow socle + pre-commit hook` sur main (pendant que le hook est -inactif → jamais auto-bloqué). Idempotent — un re-run est un no-op. +Sur un repo existant, cela : renomme `master`→`main` si besoin (LOCAL), pose le +socle (`.gitignore` réconcilié — additif, n'écrase jamais les règles du projet — ++ `.githooks/` versionnés) sur une branche `chore/gitflow-adopt` créée depuis +main, la merge `--no-ff` dans main (le hook pre-commit est global sur la machine +et bloque tout commit de code sur main, mais exempte les merges — BDR-095), +supprime la branche, puis crée `develop` depuis main. Idempotent — un re-run est +un no-op. **Annoncer le renommage master→main** s'il a lieu. Le renommage est LOCAL ; repointer la branche par défaut du remote vers `main` + la protection de branche @@ -247,21 +250,29 @@ Pour chaque fast-lib détectée : --- -## STEP 4 — GRAPHIFY (si complexity ≥ 30% et pas déjà présent) +## STEP 4 — GRAPHIFY (proposé dès 200 fichiers code — l'utilisateur décide) ```bash command -v graphify &>/dev/null && echo "available" || echo "not-installed" -test -f graphify-out/GRAPH_REPORT.md && echo "graph-exists" +test -f graphify-out/graph.json && echo "graph-exists" +bash ~/.claude/lib/graphify-gate.sh . ``` - **Pas installé** → skip avec message : `graphify non installé — skip audit architectural. Install : (voir graphify/SKILL.md)` -- **Complexity < 30%** → skip silencieusement, projet trop petit pour justifier. -- **Graphe déjà présent + récent** (fichier < 7j) → skip, réutiliser l'existant. -- **Sinon** → run : +- **`graph-exists`** → skip, réutiliser l'existant. +- **La gate n'imprime rien** → moins de 200 fichiers code trackés (BDR-097 : + grep + lecture suffisent). Pas de proposition ; ligne FINAL OUTPUT + `below 200 code files, not proposed`. +- **La gate imprime une ligne** (`graphify? N code files ≥ 200, no graph`) → + l'afficher et DEMANDER à l'utilisateur. Jamais de build sans oui explicite. + Sur oui : ```bash - graphify . --out graphify-out 2>&1 | tail -20 + printf '.claude/\ndocs/superpowers/\n' >> .graphifyignore + grep -qxF 'graphify-out/' .gitignore || echo 'graphify-out/' >> .gitignore + graphify update . ``` - Puis `test -f graphify-out/GRAPH_REPORT.md` pour valider. + Puis `test -f graphify-out/GRAPH_REPORT.md` pour valider. Sur non → skip, + ligne FINAL OUTPUT `proposed, declined`. Print : `🔗 Knowledge graph : graphify-out/GRAPH_REPORT.md (N nodes, M edges)`. @@ -937,7 +948,7 @@ Choix ? (A / B / C / D / E) **STOP.** Attendre la réponse. -- **A** → stop ici, l'utilisateur relira et reviendra avec `/onboard continue`. +- **A** → stop ici, l'utilisateur relit les 4 fichiers ; le backlog (STEP 9) se génère ensuite à la demande depuis `.claude/audits/AUDIT_PROPOSALS.md`. - **B** → continuer STEP 9 avec toutes les recommandations. - **C** → demander les changements spécifiques, les appliquer dans .claude/audits/AUDIT_PROPOSALS.md, puis re-présenter la gate. - **D** → continuer STEP 9 avec seulement les P0. @@ -1020,7 +1031,7 @@ Pour démarrer : lire .claude/tasks/TODO.md, choisir une tâche P0, lancer le /s - Si `CLAUDE.md` existe : le lire, ne pas l'écraser sans fusion après STEP 3. - STEP 3 : ne redemande jamais ce qui est déjà dans README ou manifests. - STEP 3.5 : si ctx7 absent + fast-libs, WARN mais ne bloque pas. -- STEP 4 : skip si complexity < 30% ou graph récent déjà présent. +- STEP 4 : graphify proposé seulement si `graphify-gate.sh` imprime une ligne (≥ 200 fichiers code, pas de graphe — BDR-097) ; l'utilisateur décide, jamais de build sans oui explicite. - STEP 5-6 : subagents isolés (Agent tool avec subagent_type spécifique) — pas de contexte partagé entre les audits. Chaque subagent écrit son rapport dans `.onboard-audit/.md`. - STEP 6 dispatches parallélisables : regrouper dans un seul message Agent multi-calls. - `.onboard-audit/` gitignoré automatiquement — ne jamais commiter. @@ -1035,7 +1046,7 @@ ARCHETYPE : (confiance: ) STACK : CONFIG : ✅ CLAUDE.md, settings.json, .claudeignore, .claude/{tasks,memory,audits}/ CTX7 CACHE : ✅ [libs] | ⚠️ not installed | — N/A -GRAPHIFY : ✅ graphify-out/ | ⚠️ not installed | — skipped (simple) +GRAPHIFY : ✅ graphify-out/ | ⚠️ not installed | — below 200 code files, not proposed | — proposed, declined AUDITS : ✅ dette technique (.onboard-audit/analyze.md + code-clean.md) ✅ sécurité (.onboard-audit/cso.md) @@ -1055,6 +1066,6 @@ SYNTHÈSE : NEXT STEPS : 1. Ouvrir .claude/audits/ONBOARD_REPORT.md — overview complète 2. Démarrer par la première tâche P0 de .claude/tasks/TODO.md avec le skill indiqué - 3. /onboard add gsd — générer ROADMAP.md pour multi-session si besoin + 3. GSD (multi-session) : `gsd init` à la main, voir docs gsd-pi 4. .onboard-audit/ peut être supprimé (raw data consommée en synthèse) ``` diff --git a/skills/pdf-translate/SKILL.md b/skills/pdf-translate/SKILL.md index 8f26582..44b5d7c 100644 --- a/skills/pdf-translate/SKILL.md +++ b/skills/pdf-translate/SKILL.md @@ -28,14 +28,17 @@ digraph pipeline { ## STEP 0: Dependencies -Check before starting. Install what's missing. +Check before starting. If something is missing, print the install +command(s) and STOP until the user has run them — `sudo` / `apt` is the +user's to run, never Claude's. The one exception: `pip install pymupdf` +inside the project's own venv may be run by Claude. ```bash -# Option A: poppler (lighter) -command -v pdftoppm && echo "OK" || echo "INSTALL: sudo apt install poppler-utils" +# Option A: poppler (lighter) — USER runs the install +command -v pdftoppm && echo "OK" || echo "USER RUNS: sudo apt install poppler-utils" # Option B: PyMuPDF (more powerful — extracts embedded images with coordinates) -python3 -c "import fitz; print('OK')" 2>/dev/null || echo "INSTALL: pip install pymupdf" +python3 -c "import fitz; print('OK')" 2>/dev/null || echo "INSTALL: pip install pymupdf (project venv only — otherwise USER RUNS)" ``` Prefer PyMuPDF if both available — it extracts embedded images + gives page dimensions. diff --git a/skills/refactor/SKILL.md b/skills/refactor/SKILL.md index e0ae675..67e5abd 100644 --- a/skills/refactor/SKILL.md +++ b/skills/refactor/SKILL.md @@ -9,6 +9,12 @@ Dispatch the refactorer executor — behavior-preserving norm application is closed execution, so it runs pinned on **sonnet** (not the big session model). The scope you name is the only reflection; the agent applies norms. +**Gitflow aiguillage first** (the refactorer edits code): follow +`$HOME/.claude/lib/gitflow-aiguillage.md`, this skill's TYPE = `chore`. On +`main`/`develop` run `bash ~/.claude/lib/gitflow.sh start chore refactor-` +and dispatch on the new branch; on a working branch dispatch in place. Never +`gitflow finish` — integration is human-gated. + ``` Agent(subagent_type="refactorer") prompt: "Refactor to strict project norms, preserving external behavior diff --git a/skills/release-candidate/SKILL.md b/skills/release-candidate/SKILL.md index 95d1220..bafc6fc 100644 --- a/skills/release-candidate/SKILL.md +++ b/skills/release-candidate/SKILL.md @@ -24,7 +24,7 @@ The two mechanical spans (prep, finish+tag) run on the sonnet-pinned gate needed here, dispatch does the job. This dispatcher keeps everything the executor must never own: the version-NUMBER decision (judgment — derives from semver change nature), and the two human gates (when to release, and -the push). A human gate sits BETWEEN the two spans by construction, so the +the tag push). A human gate sits BETWEEN the two spans by construction, so the executor is never dispatched twice in one call. ## When to use @@ -91,24 +91,26 @@ Parse the `RELEASE-EXEC REPORT`: the fan-out hit), STOP — resolving a conflicted fan-out is a human call, not an auto-retry. -### STEP 6 — Push GATE (ASK) -STOP. On explicit go only ([[LRN-069]]) — run the push HERE, in this -dispatcher, never delegated to the executor: +### STEP 6 — Tag push GATE (ASK) +`main` and `develop` are already on origin: the lib pushes every merge as +it lands (`_gitflow_merge_into` + the post-merge hook, BDR-095). Only the +tag is left. STOP. On explicit go only ([[LRN-069]]) — run the tag push +HERE, in this dispatcher, never delegated to the executor: ``` AskUserQuestion: - Push main, develop, and v to origin? — go / hold + Push tag v to origin? — go / hold ``` Go → ```bash -git push origin main develop && git push origin v +git push origin v ``` -`hold` → stop; the release is fanned out and tagged locally, unpushed. +`hold` → stop; the release is on origin (main + develop), the tag stays local. ## Common mistakes - Tagging before `gitflow finish` → tag wouldn't sit on main's merge commit. Tag AFTER, on main. - Auto-firing finish because tests pass → finish is a HUMAN gate. - Restarting the tag at v1.0.0 → desyncs from the CHANGELOG lineage. Continue it. -- Pushing without the ASK gate → [[LRN-069]]. +- Pushing the tag without the ASK gate → [[LRN-069]]. ## Validation `RC_WORK=$(mktemp -d) RC_TAG=1 bash lib/tests/run-release-candidate.sh` → 5/5 (fan-out + tag on main). `RC_TAG=0` reds the tag assertion — proves the lib alone never tags (the gap this skill fills). diff --git a/skills/seo/SKILL.md b/skills/seo/SKILL.md index 843bf6b..c7206f5 100644 --- a/skills/seo/SKILL.md +++ b/skills/seo/SKILL.md @@ -535,6 +535,13 @@ intent, not header wording: **AUTO** = no-confirmation items (seo batches A/B/C · geo G1–G4/G6); **GATED** = items marked NEEDS CONFIRMATION / visible / structural (seo D/E · geo G5); **USER ACTIONS** = batch F / G7. +### Gitflow aiguillage (before the first edit) + +Follow `$HOME/.claude/lib/gitflow-aiguillage.md` — this skill's TYPE = +`feature` (aggressive mode edits code). On `main`/`develop` branch first: +`bash ~/.claude/lib/gitflow.sh start feature seo-`; on a working +branch apply in place. Never `gitflow finish` — integration is human-gated. + ### Serial by ownership (no parallel race) The two bundles may touch the same shared template (meta vs JSON-LD). Apply diff --git a/skills/ship-feature/SKILL.md b/skills/ship-feature/SKILL.md index 2803514..bc01d3e 100644 --- a/skills/ship-feature/SKILL.md +++ b/skills/ship-feature/SKILL.md @@ -32,7 +32,8 @@ Verify the project has a `CLAUDE.md` and print a brief orientation summary: ls CLAUDE.md .claude/CLAUDE.md 2>/dev/null | head -1 git branch --show-current 2>/dev/null || echo "not a git repo" git log --oneline -3 --format="%h %<(50,trunc)%s" 2>/dev/null || true -ls .gsd/ROADMAP.md 2>/dev/null | head -1 +# gsd-pi ≥ 3: state in .gsd/STATE.md + gsd.db + milestones//-ROADMAP.md (no .gsd/ROADMAP.md) +ls .gsd/ 2>/dev/null >/dev/null && head -20 .gsd/STATE.md 2>/dev/null ``` - **CLAUDE.md found** → read it silently, then print orientation header (informational, not a gate): ``` @@ -41,7 +42,7 @@ ls .gsd/ROADMAP.md 2>/dev/null | head -1 Stack : Branch : Recent : - GSD : + GSD : ``` Continue to STEP 1. - **Not found** → @@ -262,7 +263,7 @@ Feature shipped implies at least one design decision worth capturing. Run this B 4. Append approved entries to the registries. Update the Index table at the top of each file. 5. Append a one-line entry to `.claude/memory/journal.md` under today's date heading (`## YYYY-MM-DD`). -**Language rule**: written entries are ALWAYS in English (see CLAUDE.md "Memory registries" § Language). The interactive gate above may mirror the user's language; the appended entries must not. +**Language rule**: written entries are ALWAYS English AND caveman — fragments, articles dropped, code/IDs/quoted errors verbatim — per CLAUDE.md "Memory registries" (Always English, always caveman). The interactive gate above may mirror the user's language; the appended entries must not. If nothing substantive to log → print `CAPITALIZE: nothing substantive to log` and skip. diff --git a/skills/tour/SKILL.md b/skills/tour/SKILL.md index 5239235..b334aac 100644 --- a/skills/tour/SKILL.md +++ b/skills/tour/SKILL.md @@ -39,7 +39,7 @@ plus its report IS the approval gate, reviewed by the human afterwards. Core principle: **autonomy on the working branch, never on shared state.** The skill may edit code freely on its own branch; it may NOT silently rewrite declared state (target TODO, memory registries) or -integrate anything (merge/finish/push). +integrate anything (merge/finish/push to `main`/`develop`). ## When NOT to use @@ -79,8 +79,8 @@ Model discipline (the user-fixed invariant behind this mode): must never be pinned down to an executor tier. - Inside a runner, every dispatched agent keeps the tier this skill already defines: security-auditor (sonnet frontmatter), the Phase B - audit (analyzer opus pin or `model="opus"`), doc-syncer (sonnet - frontmatter, its two-mode contract untouched). + audit (analyzer opus pin or `model="opus"`), doc-syncer (audit on + `model="opus"`, patch on its sonnet frontmatter — BDR-077). Runner dispatch, one per project: @@ -91,7 +91,7 @@ Agent(subagent_type="general-purpose", for EXACTLY ONE project: . Flags: <--report-only|none>. Skip STEP 0/0b (routing) and the global summary — the dispatcher owns them. Every rule of the skill applies unchanged: max 3 iterations, - never merge/finish/push, scoped commits, report appended to that + never merge/finish/push main|develop, scoped commits, report appended to that project's own .claude/audits/TOUR.md. Return EXACTLY: the project's one-line global-summary row (STEP 3 format), then BRANCH: , then REPORT: .") @@ -156,9 +156,12 @@ honestly in the summary. Never loop past 3. MEDIUM/LOW → fix only if local and behavior-preserving, else leave `open`. Every fix minimal, CLAUDE.md security defaults apply. A CRITICAL/HIGH fix that changes the API contract (new required - header/param, changed status codes, moved paths) is still applied — - but its report row and the global summary line carry a **BREAKING** - tag, so the human review cannot miss it. + header/param, changed status codes, moved paths) is NOT applied — a + breaking change is the human's call (CLAUDE.md: confirm before a + breaking change). Its report row becomes + `open — needs decision (BREAKING)` with the proposed patch attached, + and the global summary line carries the **BREAKING** count. + Behaviour-preserving CRITICAL/HIGH fixes stay auto-applied. 4. Commit scoped: `git add ` (never `-A`), `fix(security): …`. @@ -196,11 +199,18 @@ honestly in the summary. Never loop past 3. `.claude/memory/`** — an inferred checkbox is exactly the lie /reconcile exists to catch. The human applies suggestions via `/reconcile` later. -2. **Doc sync** — dispatch doc-syncer in AUTOMATIC (silent) mode: - public docs only (README, INSTALL, USAGE, CHANGELOG…), never - `.claude/**`, never CLAUDE.md. Commit its `PATCHED_FILES:` via - `bash ~/.claude/lib/doc-commit.sh` when available, else a scoped - `docs: …` commit of exactly those paths. +2. **Doc sync** — two-mode doc-syncer, mirrors /ship-feature STEP 8 + (BDR-077: audit judgment on opus, patch on the sonnet pin): + `Agent(subagent_type="doc-syncer", model="opus")` with `MODE: audit` + + `auto-mode scope: `; public docs only + (README, INSTALL, USAGE, CHANGELOG…), never `.claude/**`, never + CLAUDE.md. NONE → done. `[MINOR]` PATCH PLAN → re-dispatch + `Agent(subagent_type="doc-syncer")` (sonnet frontmatter) with + `MODE: patch` + the plan verbatim, then commit its `PATCHED_FILES:` + via `bash ~/.claude/lib/doc-commit.sh` when available, else a scoped + `docs: …` commit of exactly those paths. SIGNIFICANT → not applied: + report row `suggested` with the plan item (the tour has no human + gate mid-run). ### End of iteration @@ -231,15 +241,15 @@ order: | ID | Axis | File | Sev | Finding | Status | |----|------|------|-----|---------|--------| | SEC-1 | security | app.py:17 | high | shell=True + concat | fixed | -| SEC-2 | security | app.py:14 | high | no authz on POST /backup | fixed — **BREAKING**: new required X-Backup-Token header | +| SEC-2 | security | app.py:14 | high | no authz on POST /backup | open — needs decision (BREAKING): new required X-Backup-Token header, patch attached | | CLN-1 | clean | utils.py:9 | - | dead legacy_md5 | fixed | | REC-1 | reconcile | TODO.md | - | "/health" unchecked, shipped 2d92696 | suggested | | DOC-1 | doc | README.md | - | phantom /status endpoint | fixed | -Checks: pytest PASS, ruff PASS. Residuals: none. Commits: 5. BREAKING: 1 (SEC-2). +Checks: pytest PASS, ruff PASS. Residuals: SEC-2 (needs decision). Commits: 4. BREAKING: 1 (SEC-2). ``` Global summary inline, one line per project (append `BREAKING: n` to -any project line whose fixes changed an API contract): +any project line with contract-changing fixes left open for decision): ``` TOUR COMPLETE — 2026-07-04 @@ -257,7 +267,10 @@ without that approval — neither this repo's nor any target project's. ## Rules - Branch via the gitflow lib; **never `gitflow finish`, never merge, - never push** — no exceptions, "the tour is green" is not a signal. + never push `main`/`develop`** — "the tour is green" is not a signal. + The chore branch's own commits are pushed by the gitflow hooks + (BDR-095); a `push FAILED` hook warning is a report residual, fixed + with a plain `git push -u origin chore/tour-`. - Scoped pathspecs only; `git add -A` is forbidden. - Target TODO.md and target `.claude/memory/` are READ-ONLY. Reconcile produces suggestions, not edits. @@ -286,12 +299,12 @@ without that approval — neither this repo's nor any target project's. | One TOUR.md for all projects in the config repo | Each project gets its own `.claude/audits/TOUR.md`. | | Fixing a behavior-changing "cleanup" finding | That is a bug → BUGS-FOUND.md, untouched code. | | Scratch audit files left untracked at the end | Delete them in STEP 3.2 — a dirty tree self-blocks the next tour. | -| Contract-changing security fix reported as plain "fixed" | Tag **BREAKING** in the row AND the summary line. | +| Contract-changing security fix auto-applied | Not applied: row `open — needs decision (BREAKING)` + proposed patch; **BREAKING** count in the summary line. | ## Red flags — STOP - About to `Edit` a target project's TODO.md or `.claude/memory/*`. -- About to run `gitflow finish`, `git merge`, or `git push`. +- About to run `gitflow finish`, `git merge`, or push `main`/`develop`. - About to `git add -A` or commit on `main`/`develop`. - Starting iteration 4, or "just one more loop, it's almost clean". - Security phase done without the security-auditor agent and without a diff --git a/skills/web-validate/SKILL.md b/skills/web-validate/SKILL.md index 5e5ebed..7168333 100644 --- a/skills/web-validate/SKILL.md +++ b/skills/web-validate/SKILL.md @@ -299,7 +299,12 @@ Options : D) Abort — keep .claude/audits/VALIDATE.md as audit report ``` -4. On `A` : dispatch each file-group's applier at L1 (execution = sonnet; +4. On `A` : gitflow aiguillage FIRST — follow + `$HOME/.claude/lib/gitflow-aiguillage.md`, this skill's TYPE = `feature` + (`--fix` edits code). On `main`/`develop` branch before any edit: + `bash ~/.claude/lib/gitflow.sh start feature web-validate-`; on a + working branch apply in place. Never `gitflow finish` (human-gated). + Then dispatch each file-group's applier at L1 (execution = sonnet; this loop only orchestrates), serially — one applier at a time, appliers share files: diff --git a/templates/deploy/PROCEDURE.md b/templates/deploy/PROCEDURE.md index a4d4103..d8aca95 100644 --- a/templates/deploy/PROCEDURE.md +++ b/templates/deploy/PROCEDURE.md @@ -1,7 +1,6 @@ #!/usr/bin/env bash # === deploy runbook (reference) — NOT run directly. Instantiated into the deploy checklist per delta. === # Fixed steps run every deploy; # @delta: steps re-instantiate from the delta. -# @config push_deploy_tags=false # NOTE grammar: glob=:each repeats the command per matching file (e.g. psql -f ); # glob=:list runs once + lists matching files as VERIFY items; when= is conditional. # Style: one command per line, as typed in an interactive session — step 1 opens