From b4ad134d9ad8ec62b262639242095cc3409406d1 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:11:05 +0200 Subject: [PATCH 01/16] =?UTF-8?q?job2:=20F9=20acknowledge=20/model=20defau?= =?UTF-8?q?lt=20=E2=80=94=20Fable=205=20(1M)=20is=20the=20intended=20defau?= =?UTF-8?q?lt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/settings.json b/settings.json index 717a431..d559a76 100644 --- a/settings.json +++ b/settings.json @@ -1,5 +1,10 @@ { "cleanupPeriodDays": 30, + "attribution": { + "commit": "", + "pr": "", + "sessionUrl": false + }, "permissions": { "allow": [ "Bash(git status)", @@ -225,12 +230,7 @@ "disableBypassPermissionsMode": "disable", "additionalDirectories": [] }, - "model": "claude-opus-4-8[1m]", - "attribution": { - "commit": "", - "pr": "", - "sessionUrl": false - }, + "model": "claude-fable-5[1m]", "hooks": { "SessionStart": [ { @@ -315,6 +315,6 @@ }, "effortLevel": "xhigh", "remoteControlAtStartup": true, - "skipAutoPermissionPrompt": true, - "inputNeededNotifEnabled": true + "inputNeededNotifEnabled": true, + "skipAutoPermissionPrompt": true } From 860b803203a81d87057df8cd766d953e778ffb58 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:16:44 +0200 Subject: [PATCH 02/16] job2: F4 design hook ignores harness notifications; sync test oracle to job1 pointer message (3f639b3 regression) --- hooks/design-toolchain-reminder.sh | 6 ++++++ lib/tests/design-toolchain-reminder.test.sh | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/hooks/design-toolchain-reminder.sh b/hooks/design-toolchain-reminder.sh index b69bc9e..a43be4d 100755 --- a/hooks/design-toolchain-reminder.sh +++ b/hooks/design-toolchain-reminder.sh @@ -25,6 +25,12 @@ prompt="$(printf '%s' "$input" \ 2>/dev/null || true)" [ -z "$prompt" ] && prompt="$input" +# Harness-generated turns (subagent/task notifications) are not user +# requests — never fire on them (CLAUDE.md trigger = a design/UI *request*). +case "$prompt" in + ''*) exit 0 ;; +esac + lc="$(printf '%s' "$prompt" | tr '[:upper:]' '[:lower:]')" # UI/design build and review signals (FR + EN). Word boundaries (\b) avoid diff --git a/lib/tests/design-toolchain-reminder.test.sh b/lib/tests/design-toolchain-reminder.test.sh index a7d59a1..959882f 100644 --- a/lib/tests/design-toolchain-reminder.test.sh +++ b/lib/tests/design-toolchain-reminder.test.sh @@ -6,7 +6,7 @@ pass=0; fail=0 check() { if [ "$2" = "$3" ]; then pass=$((pass+1)); else fail=$((fail+1)); printf 'FAIL %s: got[%s] want[%s]\n' "$1" "$2" "$3"; fi; } # fire() -> "fire" if the hook emits the reminder, else "quiet". -fire() { if printf '{"prompt":"%s"}' "$1" | bash "$H" | grep -q "design-toolchain"; then +fire() { if printf '{"prompt":"%s"}' "$1" | bash "$H" | grep -q 'full toolchain'; then echo fire; else echo quiet; fi; } # --- Dropped/neutralized tokens must be QUIET (non-UI senses) --- @@ -19,6 +19,10 @@ check D6-frontend "$(fire 'frontend architecture')" quiet check D7-palette "$(fire 'a palette of options')" quiet check D8-dash-file "$(fire 'ecc_dashboard.py')" quiet +# --- Harness-generated inputs must be QUIET even with UI tokens --- +check D9-tasknotif "$(fire ' x add css header fonts')" quiet +check D10-notif-file "$(fire ' design-motion-principles keyframe done')" quiet + # --- Real UI signals must still FIRE --- check F1-button "$(fire 'add a button')" fire check F2-navbar "$(fire 'the navbar layout')" fire From b80df544be5d1d3c2270c1d14b4c2a2d1b29b508 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:17:11 +0200 Subject: [PATCH 03/16] =?UTF-8?q?job2:=20F5=20session-start=20header=20?= =?UTF-8?q?=E2=80=94=20declare=20the=20git=20fetch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hooks/session-start.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hooks/session-start.sh b/hooks/session-start.sh index 9a749f9..b473a0c 100644 --- a/hooks/session-start.sh +++ b/hooks/session-start.sh @@ -1,7 +1,8 @@ #!/usr/bin/env bash # ============================================================ # Claude Code — Session start plugin status -# Runs once per session. Zero API calls. Filesystem only. +# Runs once per session. Filesystem only, except one quiet +# git fetch for the version/update check near the end. # ============================================================ # ── Quick health check (filesystem only, no subprocesses) ── From 3dde43b5ded577c2be84e7da473899204525b5bd Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:18:00 +0200 Subject: [PATCH 04/16] =?UTF-8?q?job2:=20F10=20make=20test=20target=20?= =?UTF-8?q?=E2=80=94=20wire=20the=20deterministic=20suite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index dd9e79a..060411e 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help install plugin link doctor update new-skill profile profile-list profile-current profile-reset onboard +.PHONY: help install plugin link doctor update new-skill profile profile-list profile-current profile-reset onboard test help: ## Show available commands @grep -E '^[a-zA-Z_-]+:.*##' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*## "}; {printf " make %-14s %s\n", $$1, $$2}' @@ -22,6 +22,10 @@ onboard: link ## Onboard an existing project (run from the project directory) @echo "Open Claude Code in your project directory and run: /onboard" @echo "Or with hints: /onboard Python FastAPI monorepo" +test: ## Run deterministic tests (lib/tests/*.test.sh + lib/gitflow-test.sh) + @fail=0; for t in lib/tests/*.test.sh lib/gitflow-test.sh; do \ + echo "== $$t"; bash "$$t" || fail=1; done; exit $$fail + profile: ## Run profile.sh (usage: make profile cmd="set design") @bash lib/profile.sh $(cmd) From 112714fafa8395d6d19707faaa8bd383d7184df3 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:18:31 +0200 Subject: [PATCH 05/16] job2: F11 compress 3 agent descriptions --- agents/client-handover-writer.md | 2 +- agents/doc-syncer.md | 2 +- agents/seo-analyzer.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/agents/client-handover-writer.md b/agents/client-handover-writer.md index 6f5ba1e..c1a3bfc 100644 --- a/agents/client-handover-writer.md +++ b/agents/client-handover-writer.md @@ -1,6 +1,6 @@ --- name: client-handover-writer -description: Final ship-and-handover orchestrator. Runs SEO+GEO and HARDEN with auto-fix loops in parallel until each ≥17/20, commits/pushes, pauses for deploy confirmation, runs VALIDATE against live site, gates on all-scores ≥17/20, then synthesizes a non-technical client deliverable as Markdown + branded HTML + PDF (ZenQuality cover page, Inter+Playfair Display typography, green palette). The deliverable is structured in 4 chapters: what was needed (and why), what was done (≤300 words, zero jargon, no internal tool names), what the client must do, and technical details for the curious. Reads git history + .claude/memory/ registries. Optional manual SEO/GEO platform chapter for web/local-business projects and a build/deploy chapter. +description: Final ship-and-handover orchestrator — called by /client-handover. Runs SEO+GEO+HARDEN auto-fix loops to ≥17/20, gates on live VALIDATE, then writes the non-technical client deliverable (Markdown + branded HTML + PDF). tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch, WebFetch, AskUserQuestion, Agent model: opus --- diff --git a/agents/doc-syncer.md b/agents/doc-syncer.md index 69c5bbe..423f947 100644 --- a/agents/doc-syncer.md +++ b/agents/doc-syncer.md @@ -1,6 +1,6 @@ --- name: doc-syncer -description: Detect stale PUBLIC documentation by cross-referencing git history against the project's doc layout (README, INSTALL, CONFIGURE, USAGE, DEPLOY, CONTRIBUTING, CHANGELOG, SECURITY, ARCHITECTURE, LICENSE, docs/**). Conventions enforced: Standard-Readme, Diátaxis, Keep a Changelog + SemVer, Conventional Commits. Reads .claude/ for context only, never modifies or exposes it. Stack-aware deploy-doc gating (DEPLOY.md only when non-trivial). Enforces README presence. Audit, report, patch. Full audit, clean mode, and automatic (silent) mode. +description: Detect stale PUBLIC documentation by cross-referencing git history against the doc layout (README, CHANGELOG, docs/**…) — dispatched by /doc and orchestrators. Convention-aware (Diátaxis, Keep a Changelog); never touches .claude/. Audit, report, patch. tools: Read, Write, Edit, Bash, Grep, Glob model: sonnet --- diff --git a/agents/seo-analyzer.md b/agents/seo-analyzer.md index 1d8001f..4b9fdf3 100644 --- a/agents/seo-analyzer.md +++ b/agents/seo-analyzer.md @@ -1,6 +1,6 @@ --- name: seo-analyzer -description: Professional classical SEO audit agent. Targets traditional search engines (Google, Bing, DuckDuckGo). Live site audit, Core Web Vitals, on-page (meta, headings, images, video, a11y, i18n), technical (HTTP, security headers, redirects, indexability), SEO local (NAP, GMB, citations), competitive analysis, legal compliance (FR). Autonomous code fixes, scored report, prioritized action plan. GEO / AI optimization is handled by the geo-analyzer agent. +description: Classical SEO audit agent (Google, Bing) — dispatched from /seo. Live audit: Core Web Vitals, on-page, technical, local SEO, legal (FR). Autonomous fixes + scored report. AI/GEO → geo-analyzer agent. tools: Read, Edit, Write, Bash, Grep, Glob, Agent, WebFetch, WebSearch --- From 18c1b327c32753f2206873009e7a675a869556b6 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:19:08 +0200 Subject: [PATCH 06/16] job2: F12 subordinate 6 agent descriptions to their skills --- agents/bugfixer.md | 2 +- agents/commit-changer.md | 2 +- agents/feater.md | 2 +- agents/geo-analyzer.md | 2 +- agents/hotfixer.md | 2 +- agents/plugin-advisor.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/agents/bugfixer.md b/agents/bugfixer.md index 5ecfff7..283013d 100644 --- a/agents/bugfixer.md +++ b/agents/bugfixer.md @@ -1,6 +1,6 @@ --- name: bugfixer -description: Structured bug fix with root cause investigation. Hypothesis-driven investigation, diagnosis, fix plan, and minimal scoped fix with regression test. +description: Root-cause bug-fix executor — dispatched by /bugfix. Hypothesis-driven investigation, diagnosis, minimal scoped fix with regression test. tools: Read, Edit, Write, Bash, Grep, Glob, Agent --- diff --git a/agents/commit-changer.md b/agents/commit-changer.md index 32c4008..69cf4b1 100644 --- a/agents/commit-changer.md +++ b/agents/commit-changer.md @@ -1,6 +1,6 @@ --- name: commit-changer -description: Analyze all changes since the last commit and create commits that retrace the development steps — one commit per logical step, in the order work happened. +description: Retrace-and-commit engine — dispatched by /commit-change. Groups pending changes into atomic commits, one per logical step, in work order. tools: Bash, Read, Grep, Glob, Agent, AskUserQuestion --- diff --git a/agents/feater.md b/agents/feater.md index 23d54cb..c02aeba 100644 --- a/agents/feater.md +++ b/agents/feater.md @@ -1,6 +1,6 @@ --- name: feater -description: Small feature implementation (1-5 files). Light planning, direct implementation, no heavy orchestration. No design brainstorm, no subagents, no plugin check gate. +description: Small-feature implementer (1-5 files) — dispatched by /feat, which owns branching and gates. Light planning, direct implementation, no heavy orchestration. tools: Read, Edit, Write, Bash, Grep, Glob, Agent --- diff --git a/agents/geo-analyzer.md b/agents/geo-analyzer.md index 0374488..c67ff56 100644 --- a/agents/geo-analyzer.md +++ b/agents/geo-analyzer.md @@ -1,6 +1,6 @@ --- name: geo-analyzer -description: Professional GEO (Generative Engine Optimization) audit agent. Optimises sites for AI search engines — ChatGPT, Claude, Perplexity, Gemini, Google AI Overviews, Copilot. Audits AI crawlers, llms.txt, entity signals, Schema.org for AI, content shape, AI visibility. Autonomous code fixes, scored report, prioritized action plan. +description: GEO audit agent for AI search engines — dispatched by /geo and /seo. Audits AI crawlers, llms.txt, entity signals, Schema.org; autonomous fixes, scored report. Classical SEO → seo-analyzer agent. tools: Read, Edit, Write, Bash, Grep, Glob, Agent, WebFetch, WebSearch --- diff --git a/agents/hotfixer.md b/agents/hotfixer.md index b958707..20925f0 100644 --- a/agents/hotfixer.md +++ b/agents/hotfixer.md @@ -1,6 +1,6 @@ --- name: hotfixer -description: Quick fix for superficial bugs (typos, CSS issues, config errors, off-by-one, wrong variable name, missing import, broken link). Max 2 files, obvious root cause only. +description: Quick-fix executor — dispatched by /hotfix, which owns the routing and gitflow gate. Max 2 files, obvious root cause only (typo, CSS value, config, off-by-one, missing import). tools: Read, Edit, Write, Bash, Grep, Glob, Agent --- diff --git a/agents/plugin-advisor.md b/agents/plugin-advisor.md index d617a75..45dda98 100644 --- a/agents/plugin-advisor.md +++ b/agents/plugin-advisor.md @@ -1,6 +1,6 @@ --- name: plugin-advisor -description: Check active plugins vs project needs. Recommend enable/disable before starting work. Gate before init-project and ship-feature. +description: Plugin-fit checker — dispatched by /plugin-check and orchestrator gates (init-project, ship-feature). Recommends enable/disable. tools: Read, Bash, Glob, Grep model: haiku --- From 30c5803453ffad1c047c4443caeddb75114c674d Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:19:16 +0200 Subject: [PATCH 07/16] =?UTF-8?q?job2:=20F6+F12=20status-reporter=20?= =?UTF-8?q?=E2=80=94=20version=20path=20+=20subordination?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agents/status-reporter.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agents/status-reporter.md b/agents/status-reporter.md index 5c4bc9e..728898d 100644 --- a/agents/status-reporter.md +++ b/agents/status-reporter.md @@ -1,6 +1,6 @@ --- name: status-reporter -description: Consolidated project status — plugins, token budget, git state, build, tests, GSD milestone. Read-only snapshot. Use to orient quickly at session start or after a break. +description: Read-only project-status engine — dispatched by /status. Collects plugins, token budget, git state, build/tests, GSD milestone into one snapshot. tools: Read, Bash, Glob, Grep model: haiku --- @@ -17,7 +17,7 @@ No modifications. No design. No proposals. Facts only. ```bash # Config version -cat ~/.claude/version.txt 2>/dev/null || echo "unknown" +cat ~/.claude/lib/../version.txt 2>/dev/null || echo "unknown" # lib symlink resolves into the repo # Active plugins (from session-start detection) command -v rtk &>/dev/null && echo "rtk: installed" || echo "rtk: missing" From b40c702ada50e4734775cd87c3c56af136425828 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:20:02 +0200 Subject: [PATCH 08/16] job2: F7 strict-YAML frontmatters (quote descriptions/argument-hints, drop stray version field) --- skills/commit-change/SKILL.md | 1 - skills/harden/SKILL.md | 2 +- skills/init-project/SKILL.md | 2 +- skills/onboard/SKILL.md | 2 +- skills/plugin-check/SKILL.md | 2 +- skills/release-candidate/SKILL.md | 2 +- skills/ship-feature/SKILL.md | 2 +- skills/web-validate/SKILL.md | 2 +- 8 files changed, 7 insertions(+), 8 deletions(-) diff --git a/skills/commit-change/SKILL.md b/skills/commit-change/SKILL.md index 46abf8b..39fb879 100644 --- a/skills/commit-change/SKILL.md +++ b/skills/commit-change/SKILL.md @@ -1,6 +1,5 @@ --- name: commit-change -version: 1.0.0 description: | Analyze all pending changes (staged, unstaged, untracked) and create atomic commits grouped by logical unit, retracing the work. Any git diff --git a/skills/harden/SKILL.md b/skills/harden/SKILL.md index d48024f..c8d156a 100644 --- a/skills/harden/SKILL.md +++ b/skills/harden/SKILL.md @@ -8,7 +8,7 @@ description: | Triggers: "harden", "security headers", "csp", "hsts", "https/ssl audit", "redirect audit", "durcissement web", "entêtes sécurité". Meta/sitemap/CWV → /seo. llms.txt/AI → /geo. Secrets/CVE/OWASP → /cso. -argument-hint: [URL] [--fix] [--local|--full] [--no-external] +argument-hint: "[URL] [--fix] [--local|--full] [--no-external]" allowed-tools: - Read - Edit diff --git a/skills/init-project/SKILL.md b/skills/init-project/SKILL.md index 197729e..a5e566d 100644 --- a/skills/init-project/SKILL.md +++ b/skills/init-project/SKILL.md @@ -1,6 +1,6 @@ --- name: init-project -description: Use when initializing a brand-new project from scratch — needs interview, design, scaffold, and TDD implementation. Multi-agent orchestrator: plugin-advisor + interviewer + analyzer + scaffolder with two validation gates. Triggers: "init project", "new project", "start project from scratch", "scaffold project", "init-project". +description: 'Use when initializing a brand-new project from scratch — needs interview, design, scaffold, and TDD implementation. Multi-agent orchestrator: plugin-advisor + interviewer + analyzer + scaffolder with two validation gates. Triggers: "init project", "new project", "start project from scratch", "scaffold project", "init-project".' argument-hint: allowed-tools: Read, Write, Edit, Bash, Grep, Glob --- diff --git a/skills/onboard/SKILL.md b/skills/onboard/SKILL.md index 5190bc4..97588b7 100644 --- a/skills/onboard/SKILL.md +++ b/skills/onboard/SKILL.md @@ -1,6 +1,6 @@ --- 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". +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"] allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Agent, Skill --- diff --git a/skills/plugin-check/SKILL.md b/skills/plugin-check/SKILL.md index 5649964..f780fb9 100644 --- a/skills/plugin-check/SKILL.md +++ b/skills/plugin-check/SKILL.md @@ -1,6 +1,6 @@ --- name: plugin-check -description: Audit active plugins vs project needs. Read-only advisory recommending enable/disable. Triggers: "plugin-check", "quels plugins". +description: 'Audit active plugins vs project needs. Read-only advisory recommending enable/disable. Triggers: "plugin-check", "quels plugins".' argument-hint: [ex: "React + FastAPI" or "Rust CLI, no frontend"] allowed-tools: Read, Bash, Glob, Grep --- diff --git a/skills/release-candidate/SKILL.md b/skills/release-candidate/SKILL.md index 9fb279b..03c9234 100644 --- a/skills/release-candidate/SKILL.md +++ b/skills/release-candidate/SKILL.md @@ -1,6 +1,6 @@ --- name: release-candidate -description: Use when develop is ahead of main and you want to cut a versioned release — finalize version.txt + CHANGELOG, merge develop→main via the gitflow fan-out, tag it, and push. Triggers: "cut a release", "release candidate", "tag a version", "ship develop to main". NOT feature/bugfix integration (that is gitflow finish via /ship-feature) nor a hotfix. +description: 'Use when develop is ahead of main and you want to cut a versioned release — finalize version.txt + CHANGELOG, merge develop→main via the gitflow fan-out, tag it, and push. Triggers: "cut a release", "release candidate", "tag a version", "ship develop to main". NOT feature/bugfix integration (that is gitflow finish via /ship-feature) nor a hotfix.' --- # /release-candidate — cut a gitflow release (orchestrator) diff --git a/skills/ship-feature/SKILL.md b/skills/ship-feature/SKILL.md index 6ddeede..ec3490e 100644 --- a/skills/ship-feature/SKILL.md +++ b/skills/ship-feature/SKILL.md @@ -1,6 +1,6 @@ --- name: ship-feature -description: Use when shipping a new feature end-to-end — needs design brainstorm, planning, TDD implementation with subagents, error recovery, code review, and finish. Multi-agent orchestrator (9-step pipeline). Triggers: "ship feature", "ship-feature", "build and merge", "feature end-to-end", "implement and ship". +description: 'Use when shipping a new feature end-to-end — needs design brainstorm, planning, TDD implementation with subagents, error recovery, code review, and finish. Multi-agent orchestrator (9-step pipeline). Triggers: "ship feature", "ship-feature", "build and merge", "feature end-to-end", "implement and ship".' argument-hint: allowed-tools: Read, Write, Edit, Bash, Grep, Glob --- diff --git a/skills/web-validate/SKILL.md b/skills/web-validate/SKILL.md index 84dd8ac..2d3af47 100644 --- a/skills/web-validate/SKILL.md +++ b/skills/web-validate/SKILL.md @@ -7,7 +7,7 @@ description: | Triggers: "validate", "w3c", "wcag", "a11y", "accessibility", "axe", "pa11y", "accessibilité", "conformité web". CSP/HSTS/404 → /harden. Meta/sitemap → /seo. AI engines → /geo. -argument-hint: [URL] [--fix] [--local|--full] [--no-external] +argument-hint: "[URL] [--fix] [--local|--full] [--no-external]" allowed-tools: - Read - Edit From f1aa1ee7664ccc23882cbceb86744eb98ff6b143 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:20:22 +0200 Subject: [PATCH 09/16] =?UTF-8?q?job2:=20F7+F15=20refactor/status=20?= =?UTF-8?q?=E2=80=94=20quoting=20+=20routing=20boundaries?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skills/refactor/SKILL.md | 2 +- skills/status/SKILL.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/skills/refactor/SKILL.md b/skills/refactor/SKILL.md index 89a9ba8..095f5f7 100644 --- a/skills/refactor/SKILL.md +++ b/skills/refactor/SKILL.md @@ -1,6 +1,6 @@ --- name: refactor -description: Improve code quality without changing behavior — strict norm enforcement. Triggers: "refactor", "clean up code", "normaliser". +description: 'Improve code quality without changing behavior — strict norm enforcement, targeted scope (file/module). Full-codebase audit+cleanup → /code-clean. Triggers: "refactor", "clean up code", "normaliser".' argument-hint: allowed-tools: Read, Write, Edit, Grep, Glob, Bash --- diff --git a/skills/status/SKILL.md b/skills/status/SKILL.md index df3966f..142f60b 100644 --- a/skills/status/SKILL.md +++ b/skills/status/SKILL.md @@ -1,6 +1,6 @@ --- name: status -description: Consolidated project snapshot — plugins, token cost, git state, recent commits, GSD v2 milestone progress. Read-only. Run at session start or after a break. Triggers: "status", "sitrep", "where are we", "project state", "after break". +description: 'Consolidated project snapshot — plugins, token cost, git state, recent commits, GSD v2 milestone progress. Read-only. Run at session start or after a break. Open-work reconciliation (stale TODO vs real git) → /reconcile. Triggers: "status", "sitrep", "where are we", "project state", "after break".' argument-hint: (no arguments needed) allowed-tools: Read, Bash, Glob, Grep --- From 54db7eeff63bddfcc107f1693dd2cd30c135f500 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:20:35 +0200 Subject: [PATCH 10/16] =?UTF-8?q?job2:=20F13=20tour=20description=20698?= =?UTF-8?q?=E2=86=92~500=20chars?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skills/tour/SKILL.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/skills/tour/SKILL.md b/skills/tour/SKILL.md index 1d96f9f..ad3b357 100644 --- a/skills/tour/SKILL.md +++ b/skills/tour/SKILL.md @@ -4,14 +4,11 @@ description: | Use when the user wants ONE grouped pass over a whole project (or a list of projects) covering all hygiene axes together: code cleanup + security (semgrep/cso) + TODO-vs-reality check + doc sync, auto-fixing - and re-auditing until a clean pass. Use it whenever the user asks for - a "tour" of their projects, a grouped/combined audit-and-fix, or a - periodic all-axes sweep — even without naming the axes. + and re-auditing until a clean pass — even without naming the axes. NOT one axis alone (/code-clean, /cso, /audit-delta, /reconcile, /doc), one bug (/hotfix, /bugfix), dashboard (/health), branch diff (/review). Triggers: "tour", "tir groupé", "grand ménage", "fais un tour sur les - projets", "sweep", "full pass", "vérifie et corrige tout", "passe - tout au propre". + projets", "sweep", "full pass", "vérifie et corrige tout". argument-hint: "[project paths… — blank = current repo] [--report-only]" allowed-tools: - Read From 35e9bff443e15e7ab765492cbf2c2a77f0f03d73 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:20:47 +0200 Subject: [PATCH 11/16] job2: F14 graphify description leads with graphify-out precondition --- skills/graphify/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skills/graphify/SKILL.md b/skills/graphify/SKILL.md index b354243..f7e597b 100644 --- a/skills/graphify/SKILL.md +++ b/skills/graphify/SKILL.md @@ -1,6 +1,6 @@ --- name: graphify -description: "Use for any question about a codebase, its architecture, file relationships, or project content — especially when graphify-out/ exists, where the question should be treated as a graphify query first. Turns any input (code, docs, papers, images, videos) into a persistent knowledge graph with god nodes, community detection, and query/path/explain tools." +description: "Use when graphify-out/ exists (or the user asks to build a knowledge graph): questions about the codebase, its architecture, file relationships, or project content are then treated as graphify queries first. Turns any input (code, docs, papers, images, videos) into a persistent knowledge graph with god nodes, community detection, and query/path/explain tools." --- # /graphify From 5c05d6796efbc89669dd937e58ae01ed35b7ab4f Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:21:38 +0200 Subject: [PATCH 12/16] =?UTF-8?q?job2:=20F1=20cp/mv=20allow=E2=86=92ask=20?= =?UTF-8?q?(shell-level=20guardrail=20overwrite=20path=20closed)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings.json b/settings.json index d559a76..5ded42b 100644 --- a/settings.json +++ b/settings.json @@ -41,8 +41,6 @@ "Bash(uname *)", "Bash(mkdir -p *)", "Bash(touch *)", - "Bash(cp *)", - "Bash(mv *)", "Bash(jq *)", "Bash(yq *)", "Bash(awk *)", @@ -222,6 +220,8 @@ "WebFetch", "Bash(xargs *)", "Bash(sed *)", + "Bash(cp *)", + "Bash(mv *)", "Bash(git stash pop*)", "Bash(git stash drop*)", "Bash(git stash clear)" From 96deea100fdf40bc11e92eb2fa77c6f5c4e3dfd3 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:21:56 +0200 Subject: [PATCH 13/16] job2: F2 deny find -exec (arbitrary-exec mirror) --- settings.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/settings.json b/settings.json index 5ded42b..a341d83 100644 --- a/settings.json +++ b/settings.json @@ -149,6 +149,8 @@ "Bash(find * -delete*)", "Bash(find * -exec rm*)", "Bash(find * -execdir rm*)", + "Bash(find * -exec *)", + "Bash(find * -execdir *)", "Bash(perl -e *)", "Bash(ruby -e *)", "Bash(cat .env)", From 898b61c005665c0b096dd0b1ac605ed36b1b65dc Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:25:13 +0200 Subject: [PATCH 14/16] job2: F16 remove runtime-dead gitflow-migrate.sh --- lib/gitflow-migrate.sh | 95 ------------------------------------------ 1 file changed, 95 deletions(-) delete mode 100755 lib/gitflow-migrate.sh diff --git a/lib/gitflow-migrate.sh b/lib/gitflow-migrate.sh deleted file mode 100755 index 6cbc9b4..0000000 --- a/lib/gitflow-migrate.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env bash -# gitflow-migrate.sh — migrate an existing repo to the gitflow model. -# LOCAL (no token): gitflow init existing → master→main, develop, socle, hook. -# PROBE (token, READ-ONLY): identity + scope/rights, before any write. -# REMOTE (token, DESTRUCTIVE): push, default→main, protection, delete master. -# Writes ordered reversible→irreversible; DELETE master is LAST and only -# runs if every prior step succeeded. Halts on first failure. -# No `... | grep -q` under pipefail (SIGPIPE false-negative gotcha). Never echo the token. -set -uo pipefail -GITEA="${GITEA_URL:-https://git.bchanot.fr}" -OWNER="${GITEA_OWNER:-bchanot}" - -# ── LOCAL half (token-free) ────────────────────────────────────────────────── -migrate_local() { # - local repo="$1" renamed="no" - cd "$repo" || { echo " ✗ cannot cd $repo" >&2; return 1; } - [ -z "$(git status --porcelain)" ] || { echo " ✗ working tree not clean — stash/commit first" >&2; return 2; } - { [ -n "$(git config user.name)" ] && [ -n "$(git config user.email)" ]; } \ - || { echo " ✗ git identity unset (user.name/user.email) — set it before migrating $repo" >&2; return 3; } - git show-ref --verify -q refs/heads/master && renamed="yes" - bash "$HOME/.claude/lib/gitflow.sh" init || return 1 - git show-ref --verify -q refs/heads/main || { echo " ✗ no main" >&2; return 1; } - git show-ref --verify -q refs/heads/develop || { echo " ✗ no develop" >&2; return 1; } - [ "$(git config core.hooksPath)" = ".githooks" ] || { echo " ✗ hook not active" >&2; return 1; } - [ -z "$(git status --porcelain)" ] || { echo " ✗ tree dirty after init" >&2; return 1; } - echo " ✓ local: main+develop, hook active, tree clean (master→main: $renamed)" -} - -# ── Gitea API helper (token in header only; never printed) ──────────────────── -_gitea() { # [json-body] - local m="$1" p="$2" body="${3:-}" - curl -fsS -X "$m" -H "Authorization: token $GITEA_TOKEN" \ - -H "Content-Type: application/json" ${body:+-d "$body"} "$GITEA/api/v1$p" -} -_json() { python3 -c "import sys,json;$1" 2>/dev/null; } # tiny JSON field reader - -# ── PROBE (READ-ONLY: identity informational, rights = the real gate) ───────── -# /user needs read:user (cosmetic — the migration never calls it) → informational. -# The gates are the repo-scoped rights the writes actually require: admin+push on -# the repo, and admin scope confirmed by a readable branch_protections list. -gitea_probe() { # - local name="$1" me pj perm - [ -n "${GITEA_TOKEN:-}" ] || { echo " ✗ GITEA_TOKEN unset" >&2; return 1; } - - # [a] identity — INFORMATIONAL (needs read:user scope the migration never uses) - if me=$(_gitea GET "/user" 2>/dev/null | _json "print(json.load(sys.stdin).get('login','?'))") && [ -n "$me" ]; then - echo " ✓ token identity: $me" - else - echo " ⚠ token identity unavailable (no read:user scope) — cosmetic, migration is repo-scoped" - fi - - # [b] repo rights — GATE: admin AND push must be true (default_branch, protections, push) - pj=$(_gitea GET "/repos/$OWNER/$name") \ - || { echo " ✗ GET /repos/$OWNER/$name failed — token lacks repo read scope" >&2; return 1; } - perm=$(printf '%s' "$pj" | _json "p=json.load(sys.stdin).get('permissions',{});print('admin=%s push=%s pull=%s'%(p.get('admin'),p.get('push'),p.get('pull')))") - printf '%s' "$pj" | _json "p=json.load(sys.stdin).get('permissions',{});sys.exit(0 if (p.get('admin') and p.get('push')) else 1)" \ - || { echo " ✗ insufficient rights on $name ($perm) — need admin+push" >&2; return 1; } - echo " ✓ rights on $name: $perm (admin+push confirmed)" - - # [c] admin-scope canary — GATE: branch_protections readable (POST/PATCH/DELETE need repo-admin) - _gitea GET "/repos/$OWNER/$name/branch_protections" >/dev/null \ - || { echo " ✗ cannot read branch_protections — token lacks repo-admin scope; protection step would fail" >&2; return 1; } - echo " ✓ repo-admin scope confirmed (branch_protections readable → POST/PATCH/DELETE OK)" -} - -# ── REMOTE half (DESTRUCTIVE; reversible→irreversible; delete master LAST) ──── -_protect() { # (Option 1: owner-pushable) - _gitea POST "/repos/$OWNER/$1/branch_protections" \ - "{\"branch_name\":\"$2\",\"enable_push\":true,\"enable_push_whitelist\":true,\"push_whitelist_usernames\":[\"$OWNER\"]}" -} -migrate_remote() { # (cwd = the local repo) - local name="$1" - [ -n "${GITEA_TOKEN:-}" ] || { echo " ✗ GITEA_TOKEN unset" >&2; return 1; } - echo " [1/4] push main + develop (ADDITIVE/reversible)…" - git push -u origin main || { echo " ✗ push main failed (push scope?) — STOP, nothing irreversible done" >&2; return 1; } - git push -u origin develop || { echo " ✗ push develop failed — STOP" >&2; return 1; } - echo " [2/4] default_branch → main (REVERSIBLE — scope canary)…" - _gitea PATCH "/repos/$OWNER/$name" '{"default_branch":"main"}' >/dev/null \ - || { echo " ✗ PATCH default_branch failed (admin/write scope?) — STOP before protection & delete" >&2; return 1; } - echo " [3/4] branch protection main + develop (REVERSIBLE)…" - _protect "$name" main >/dev/null || { echo " ✗ protect main failed — STOP before delete" >&2; return 1; } - _protect "$name" develop >/dev/null || { echo " ✗ protect develop failed — STOP before delete" >&2; return 1; } - echo " [4/4] DELETE remote master (IRREVERSIBLE — last; default already repointed)…" - git push origin --delete master || { echo " ✗ delete master failed (left in place — safe)" >&2; return 1; } - echo " ✓ remote: default=main, main/develop protected (owner-pushable), remote master deleted" -} - -if [ "${BASH_SOURCE[0]}" = "${0}" ]; then - case "${1:-}" in - local) migrate_local "$2" ;; - probe) gitea_probe "$2" ;; - remote) migrate_remote "$2" ;; - *) echo "usage: gitflow-migrate.sh {local |probe |remote }" >&2; exit 2 ;; - esac -fi From 6a3b19700974087c8c1f98bd130c17467f97b641 Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:29:05 +0200 Subject: [PATCH 15/16] =?UTF-8?q?job2:=20F7=20residual=20=E2=80=94=20onboa?= =?UTF-8?q?rd/plugin-check=20argument-hint=20quoting=20(2nd=20pre-existing?= =?UTF-8?q?=20strict-YAML=20error=20per=20file)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skills/onboard/SKILL.md | 2 +- skills/plugin-check/SKILL.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/skills/onboard/SKILL.md b/skills/onboard/SKILL.md index 97588b7..c2d92de 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" | "add gsd" | "Next.js monorepo" | "force-archetype:wordpress"]' allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Agent, Skill --- diff --git a/skills/plugin-check/SKILL.md b/skills/plugin-check/SKILL.md index f780fb9..b50f928 100644 --- a/skills/plugin-check/SKILL.md +++ b/skills/plugin-check/SKILL.md @@ -1,7 +1,7 @@ --- name: plugin-check description: 'Audit active plugins vs project needs. Read-only advisory recommending enable/disable. Triggers: "plugin-check", "quels plugins".' -argument-hint: [ex: "React + FastAPI" or "Rust CLI, no frontend"] +argument-hint: '[ex: "React + FastAPI" or "Rust CLI, no frontend"]' allowed-tools: Read, Bash, Glob, Grep --- From 2ea21c25ba1299e9a181e86ae4340ccbfd22a40e Mon Sep 17 00:00:00 2001 From: Bastien Chanot Date: Mon, 6 Jul 2026 12:34:03 +0200 Subject: [PATCH 16/16] =?UTF-8?q?job2:=20capitalize=20execution=20?= =?UTF-8?q?=E2=80=94=20LRN-104=20(oracle=20contract=20+=20no-runner)=20+?= =?UTF-8?q?=20journal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/memory/journal.md | 1 + .claude/memory/learnings.md | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/.claude/memory/journal.md b/.claude/memory/journal.md index 016fc4e..73e2cf8 100644 --- a/.claude/memory/journal.md +++ b/.claude/memory/journal.md @@ -338,3 +338,4 @@ rules: - job2 config-smell audit shipped read-only: `.audit/job2-report.md` — surface skills/agents/hooks/plugins/settings(.local), 17 findings (3 RISK perms, 6 DRIFT, 2 BLOAT, 3 OVERLAP, 2 DEAD, 1 struct), 26 diffs base c6d5e03, 0 decision-conflicts, all fresh-context verified [[EVAL-017]]. Live catch: design hook fired on audit's own task-notifications (14/20 recent fires). - Brief premise corrected: Edit/Bash(hooks/*.sh) permission rule NEVER existed — was config-protection case arm (:37) + job1 sentinel bypasses. Phase-0 UNREFERENCED metrics 100% broken (grep -q kills -l). - User GO full execution incl. 3 RISK: cp/mv→ask, find -exec deny mirror, settings.local prune (python3 -, rtk git *). F9 fable default committed (user re-chose via /model), F16 gitflow-migrate.sh removed (git-recoverable), F8/find-docs skip (generator-owned). Executor = Sonnet subagent on chore/job2-fixes, NO finish. +- job2 EXECUTED: 15 commits chore/job2-fixes, all diffs first-try, `make test` wired + first-ever full run ALL GREEN (gitflow 71/0). Measured −309 tok/session (agents 4840→3609 chars); design hook no longer fires on task-notifications. Executor STOP exercised for real: F4 gate red → root-caused to job1 oracle regression (3f639b3), fixed as [[LRN-104]]; 2nd YAML error/file unmasked (onboard/plugin-check) → closed 6a3b197. Skips: F8 (npx skills has no re-pin verb), find-docs (ctx7). Open: F8 route, find-docs/ctx7 (couple job1-F10), merged on user GO. diff --git a/.claude/memory/learnings.md b/.claude/memory/learnings.md index 243ae4a..5420774 100644 --- a/.claude/memory/learnings.md +++ b/.claude/memory/learnings.md @@ -1058,3 +1058,11 @@ rules: - **context**: 2026-07-06, job1 audit follow-up (.audit/job1-report.md, finding F13). BLK-009 closed same session; workaround it forced ([[BDR-031]] unconditional + compressed global CLAUDE.md) no longer required by this bug specifically, though BDR-031 itself stands on its own merits pending separate review. - **future application**: before acting on ANY open upstream/tool blocker cited to justify a fix, a caveat, or a design constraint — re-probe it live if cheap, don't just trust the registry's last-recorded status. - **cousin**: [[BLK-009]] closed this session; [[BDR-031]] (the workaround this bug forced). + +## LRN-104 — a hook's output message is part of its test contract; no runner = regression invisible + +- **pattern**: job1 F14 (`3f639b3`) changed design-hook stdout to pointer-only; test oracle grepped old literal `design-toolchain` → 9 fire-checks silently red 3 days. Hook itself fine — broken oracle, not broken behavior. Caught ONLY when job2 executor ran the suite as its F4 gate; zero runner existed before (job2 F10). Fix: oracle synced to durable fragment `full toolchain` (heading BDR-021 requires the hook to quote verbatim) + `make test` target wired. +- **why**: an untested output string IS an interface — its test must anchor on the durable contract part (the mandated heading), not incidental wording. No automated runner → oracle drift accumulates unseen; "18 checks lock it" ([[LRN-091]]) protected nothing while nothing ran them. +- **2nd facet**: audit yaml.safe_load stops at FIRST error/file — fixing error #1 unmasked pre-existing error #2 (onboard/plugin-check argument-hint). Verify errors-per-file exhaustively, not error-presence. +- **future application**: change any hook/script output consumed by a test → run its test same commit. `make test` now the deterministic backstop (job2 F10). Audit parse-checks: iterate until file fully clean, count errors not booleans. +- **cousin**: [[LRN-091]] (the lock that never ran), [[LRN-096]] (a guard is code, prove it can fail), [[EVAL-017]].