--- name: tour 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 — 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". argument-hint: "[project paths… — blank = current repo] [--report-only]" allowed-tools: - Read - Edit - Write - Bash - Grep - Glob - Agent - AskUserQuestion --- # /tour — grouped multi-axis sweep (clean + security + reconcile + doc) ## MODEL GATE (blocking — run before any other step) Run `$HOME/.claude/lib/model-gate.md`. Reflection here (planning, audit judgment, loop decisions) requires Fable/Opus. Verdict `small` → STOP: the gate prints the remedy; end the turn — no later step, no dispatch. Nominal (big) path is silent. One pipeline per project: **security → clean → re-verify → reconcile → doc → convergence re-audit**, looping until a full pass applies zero new fixes. Auto mode by design: fixes are committed on a dedicated `chore/tour-` branch that this skill **never merges** — the branch 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 to `main`/`develop`). ## When NOT to use | Situation | Skill | |-----------|-------| | One axis only (cleanup / security / TODO / doc) | `/code-clean`, `/cso`, `/reconcile`, `/doc` | | Recurring single-axis audit scoped to the delta | `/audit-delta` | | One obvious bug | `/hotfix`, `/bugfix` | | Quality dashboard, no fixes | `/health` | | Review a branch/PR diff | `/review`, `/code-review` | | All axes, fix, loop to clean, 1..N projects | **this skill** | ## STEP 0 — ARGS & PROJECT LIST - Paths in `$ARGUMENTS` → project list. No paths → current repo only. - ONE project → run STEP 1 → STEP 3 inline in this loop (nominal path, unchanged). - TWO OR MORE projects → parallel fan-out, STEP 0b: the repos are independent working trees on independent chore branches — nothing the runners write can collide. - `--report-only` → run every audit, apply NO fix, write reports only (the flag is forwarded to every runner). - A failure in one project never aborts the tour: record it in that project's report section — or as its global-summary row when the runner itself died — and move on. ## STEP 0b — MULTI-PROJECT FAN-OUT (one runner per project, BDR-084) Dispatch ONE runner per project, ALL in a SINGLE message — sequential dispatch of independent repos defeats the purpose. Model discipline (the user-fixed invariant behind this mode): - The runner is dispatched with **NO `model` override** — it inherits the session model, already validated big by the MODEL GATE above. The runner carries this skill's reflection (fix decisions, convergence calls); it 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 (audit on `model="opus"`, patch on its sonnet frontmatter — BDR-077). Runner dispatch, one per project: ``` Agent(subagent_type="general-purpose", description="tour runner — ", prompt="Read ~/.claude/skills/tour/SKILL.md and execute STEP 1 → STEP 3 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 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: .") ``` The main loop then: 1. Collects each runner's summary row. A dead or mute runner becomes the row ` : RUNNER FAILED — | no report` — never a silent absence (a mute runner is NEVER a pass). 2. Prints the global summary (STEP 3 format) once ALL runners returned. 3. Runs the gated capitalize offer — MAIN LOOP ONLY, never inside a runner: registries are shared state, and gate decisions stay here (LRN-083). LRN-083 derogation, recorded in BDR-084: the per-project iteration loop (fix decisions, convergence) runs INSIDE its dispatched runner. Bounded because nothing a runner decides touches shared state — independent repos, per-repo chore branches, branches left UNMERGED for human review exactly as in inline mode. ## STEP 1 — PRECONDITIONS (per project) All git commands use `git -C `. Check, in order: 1. Is a git repository → else SKIP (recorded, not an error). 2. Working tree **clean** (`git status --porcelain` empty) → else this project runs **report-only**: never mix the user's WIP with tour fixes, never stash someone else's work. 3. `develop` exists and `~/.claude/lib/gitflow.sh` is available → start the working branch via the lib, never by hand: `bash ~/.claude/lib/gitflow.sh start chore tour-YYYY-MM-DD` (append `-2`, `-3`… if the branch already exists). Missing develop or lib → **report-only** + suggest `gitflow init` in the report. 4. Detect project checks once (tests, lint, build, type-check — from package.json/Makefile/CLAUDE.md). Record what exists; "none found" is itself a report line. Report file: `.claude/audits/TOUR.md` in the target project (create `.claude/audits/` if absent). Append-only — never rewrite past runs. ## STEP 2 — ITERATION LOOP (max 3 per project) Each iteration runs phases A→D in fixed order. **Convergence** = one full iteration that applies **zero fixes** and finds **zero new findings** with project checks green. Converged → STEP 3. Not converged after 3 iterations → STOP, residuals stay `open` in the report, say so honestly in the summary. Never loop past 3. ### Phase A — SECURITY (deterministic floor first) 1. Dispatch the SAST gate (fresh every iteration): ``` Agent(subagent_type="security-auditor", description="tour security — semgrep SAST", prompt="MODE: audit\nSCOPE: project (full tree, respect .gitignore)\nPROJECT: \nREPORT: .claude/audits/.tour-semgrep.md\nFollow agents/security-auditor.md exactly. Pinned rulesets, no login. Write ONLY to REPORT. End with REPORT_WRITTEN: .") ``` semgrep ABSENT → DEGRADED (checklist only) is surfaced in the report, not a silent downgrade and not a blocker. 2. gstack ON (`/cso` available) → **iteration 1 only**, dispatch a cso posture audit (deps CVE, OWASP) in audit mode; fold its findings in. 3. Fix policy (skip in `--report-only`): CRITICAL/HIGH → fix now. 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 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): …`. ### Phase B — CLEAN 1. Dispatch a read-only cleanup audit (analyzer — opus-pinned, BDR-076 — or general-purpose with `model="opus"`; NOT the sonnet code-cleaner, which is now a fix executor): dead code, unused imports/exports, commented-out blocks, stale flags, norm violations. Findings as `id | file:line | finding | proposed fix`. 2. Apply **behavior-preserving** fixes only. A finding that would change behavior is a bug, not cleanup → log to `.claude/audits/BUGS-FOUND.md`, leave the code alone. 3. Commit scoped: `chore(clean): …`. ### Phase C — RE-VERIFY (after any fix) 1. Run the project checks found in STEP 1. Lint alone is NOT verification when tests/build exist. 2. Fresh read-only subagent re-audits the files modified this iteration (same axis prompts). Pass = approved findings resolved AND zero new findings introduced. 3. Fail → fix → recheck, max 3 attempts inside the iteration; still failing → **revert this phase's commits** (fail closed), findings back to `open`, recorded in the report. ### Phase D — RECONCILE + DOC 1. **Reconcile — REPORT-ONLY, always, even in auto mode.** Confront declared state (target TODO checkboxes, registry statuses) against real state (git log, files, branches) — reuse `lib/reconcile.sh` oracles when available. Every gap goes in the report as `declared X | real Y | suggested edit`. **Never check a box, never restructure, never edit the target project's TODO.md or `.claude/memory/`** — an inferred checkbox is exactly the lie /reconcile exists to catch. The human applies suggestions via `/reconcile` later. 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 Fixes were applied (any phase) OR new findings appeared → run another iteration (fixes can invalidate earlier audits — that is the point of the loop). Otherwise → converged. ## STEP 3 — REPORT, CLEANUP & SUMMARY (per project, then global) Append to `.claude/audits/TOUR.md`, then close the run in this exact order: 1. Write the run section (template below). 2. **Delete the scratch audit files** this run created (`.claude/audits/.tour-semgrep*` and similar) — their content is folded into TOUR.md. A tree left dirty here forces the NEXT tour into report-only: the skill must not self-block. 3. Commit the report as the run's final commit (`docs(tour): report`) — EXCEPT in `--report-only` mode: no chore branch exists there, so the commit would land on the user's current branch (possibly develop — the red flag below forbids that). Report-only leaves TOUR.md uncommitted and says so in the summary. 4. Confirm `git status --porcelain` is clean (runtime junk the sandbox cannot delete, e.g. `__pycache__/`, becomes a report residual line). ```markdown ## Tour 2026-07-04 — branch chore/tour-2026-07-04 — 2 iterations — CONVERGED | 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 | 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: SEC-2 (needs decision). Commits: 4. BREAKING: 1 (SEC-2). ``` Global summary inline, one line per project (append `BREAKING: n` to any project line with contract-changing fixes left open for decision): ``` TOUR COMPLETE — 2026-07-04 ~/proj/api : CONVERGED (2 it.) — 3 fixed, 1 suggested | chore/tour-2026-07-04, 4 commits ~/proj/site : NOT CONVERGED (3 it.) — 2 open residuals | chore/tour-2026-07-04, 6 commits ~/proj/lib : report-only (dirty tree) | no branch Branches left UNMERGED — review each, then `gitflow finish` on your GO. Reconcile suggestions pending — apply via /reconcile. ``` Then offer to capitalize (gated, per CLAUDE.md): recurring cross-project patterns → learnings, tour verdict → evals. Never write registries 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 `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. - Only the four axes. No unrequested bootstrap (.gitignore, registries, configs, features) — infrastructure gaps are report lines, not work. - Security floor = security-auditor (pinned semgrep + checklist). An ad-hoc grep is never "the security pass". - Max 3 iterations per project; max 3 fix attempts per re-verify. Residuals are reported, not silently retried forever. - Dirty tree / no develop / no gitflow lib → report-only, stated in the report. Never stash, never branch by hand. - Reports append-only. One report per project, in that project. ## Common mistakes | Mistake | Fix | |---------|-----| | Checking TODO boxes "obviously done" during reconcile | Report-only. Suggested edits, human applies. | | Writing BDR/LRN/journal entries in the target project | Registries only via the gated capitalize offer, end of tour. | | grep/ruff pass = security done | security-auditor agent (pinned semgrep) is the floor, every iteration. | | Findings live only in the final chat message | TOUR.md is what the human reviews before merging. Write it. | | "Bonus hygiene" (.gitignore, templates, bootstrap) | Out of scope. Report line, not work. | | Loop "until clean" with no bound | Max 3 iterations, then honest residuals. | | Merging/finishing because everything is green | Green ≠ GO. Branch stays; human merges. | | Stashing a dirty tree to proceed | Report-only for that project. | | 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 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 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 DEGRADED notice in the report. - Creating any file the audit did not require (.gitignore, templates). - Ending a project's run with `git status --porcelain` non-empty and no residual line explaining every leftover path. ## TDD note (skill itself) Baseline-tested per writing-skills (vendored superpowers skill; 2026-07-04, seeded fixture, no skill): the agent branched correctly via gitflow and did not merge, BUT (1) silently rewrote the target TODO (checked boxes, restructured) during "reconcile"; (2) authored BDR/journal registry entries autonomously; (3) ran security as ad-hoc grep + ruff — no semgrep, no pinned rulesets; (4) left findings only in its final chat message — no persistent report to review before merge; (5) bootstrapped unrequested .gitignore + memory registries ("bonus hygiene"); (6) looped without a stated bound (converged at pass 2 by luck). Phase D.1, the registry rule, Phase A.1, STEP 3, the scope rule and the 3-iteration bound counter each observed failure. GREEN run (same day, fresh fixture, skill followed): all six gaps closed — TODO zero-diff, no registry writes, semgrep every iteration, TOUR.md committed, no scope creep, converged in 3 bounded iterations on an unmerged chore branch. Two new holes surfaced and patched (REFACTOR): scratch semgrep files left untracked (would self-block the next run — STEP 3.2) and a contract-changing security fix not flagged (BREAKING tag in template). The REFACTOR additions are template-structural and were not re-run through a third full fixture pass — re-test on first real use.