Two or more project paths dispatch one general-purpose runner per repo, all in a single message, instead of processing repos one by one. The runner inherits the session model — no pin, it carries tour's reflection (fix decisions, convergence) — and every agent inside keeps its defined tier (security-auditor sonnet, Phase B opus, doc-syncer sonnet). A dead or mute runner becomes an explicit RUNNER FAILED summary row; the gated capitalize offer stays in the main loop, never in a runner. Bounded LRN-083 derogation recorded in BDR-084: the per-project fix loop moves into its runner, but nothing a runner decides touches shared state — independent repos, per-repo chore branches, branches left unmerged for human review exactly as inline. Mechanics proven before building: nested probe, 3 sub-agent windows all overlapping, 9.1s vs ~18s sequential. Census §12: 6 locks, flip-tested. Single-project path unchanged.
16 KiB
name, description, argument-hint, allowed-tools
| name | description | argument-hint | allowed-tools | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| tour | 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". | [project paths… — blank = current repo] [--report-only] |
|
/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-<date> 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).
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
modeloverride — 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 (sonnet frontmatter, its two-mode contract untouched).
Runner dispatch, one per project:
Agent(subagent_type="general-purpose",
description="tour runner — <project basename>",
prompt="Read ~/.claude/skills/tour/SKILL.md and execute STEP 1 → STEP 3
for EXACTLY ONE project: <absolute path>. 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
project's own .claude/audits/TOUR.md. Return EXACTLY: the project's
one-line global-summary row (STEP 3 format), then BRANCH: <name|no
branch>, then REPORT: <path>.")
The main loop then:
- Collects each runner's summary row. A dead or mute runner becomes the
row
<path> : RUNNER FAILED — <reason> | no report— never a silent absence (a mute runner is NEVER a pass). - Prints the global summary (STEP 3 format) once ALL runners returned.
- 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 <project>. Check, in order:
- Is a git repository → else SKIP (recorded, not an error).
- Working tree clean (
git status --porcelainempty) → else this project runs report-only: never mix the user's WIP with tour fixes, never stash someone else's work. developexists and~/.claude/lib/gitflow.shis 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 + suggestgitflow initin the report.- 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)
- Dispatch the SAST gate (fresh every iteration):
semgrep ABSENT → DEGRADED (checklist only) is surfaced in the report, not a silent downgrade and not a blocker.
Agent(subagent_type="security-auditor", description="tour security — semgrep SAST", prompt="MODE: audit\nSCOPE: project (full tree, respect .gitignore)\nPROJECT: <path>\nREPORT: .claude/audits/.tour-semgrep.md\nFollow agents/security-auditor.md exactly. Pinned rulesets, no login. Write ONLY to REPORT. End with REPORT_WRITTEN: <path>.") - gstack ON (
/csoavailable) → iteration 1 only, dispatch a cso posture audit (deps CVE, OWASP) in audit mode; fold its findings in. - Fix policy (skip in
--report-only): CRITICAL/HIGH → fix now. MEDIUM/LOW → fix only if local and behavior-preserving, else leaveopen. 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. - Commit scoped:
git add <files touched>(never-A),fix(security): ….
Phase B — CLEAN
- 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 asid | file:line | finding | proposed fix. - 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. - Commit scoped:
chore(clean): ….
Phase C — RE-VERIFY (after any fix)
- Run the project checks found in STEP 1. Lint alone is NOT verification when tests/build exist.
- Fresh read-only subagent re-audits the files modified this iteration (same axis prompts). Pass = approved findings resolved AND zero new findings introduced.
- 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
- 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.shoracles when available. Every gap goes in the report asdeclared 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/reconcilelater. - Doc sync — dispatch doc-syncer in AUTOMATIC (silent) mode:
public docs only (README, INSTALL, USAGE, CHANGELOG…), never
.claude/**, never CLAUDE.md. Commit itsPATCHED_FILES:viabash ~/.claude/lib/doc-commit.shwhen available, else a scopeddocs: …commit of exactly those paths.
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:
- Write the run section (template below).
- 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. - Commit the report as the run's final commit (
docs(tour): report). - Confirm
git status --porcelainis clean (runtime junk the sandbox cannot delete, e.g.__pycache__/, becomes a report residual line).
## 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 | fixed — **BREAKING**: new required X-Backup-Token header |
| 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).
Global summary inline, one line per project (append BREAKING: n to
any project line whose fixes changed an API contract):
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 — no exceptions, "the tour is green" is not a signal. - Scoped pathspecs only;
git add -Ais 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 reported as plain "fixed" | Tag BREAKING in the row AND the summary line. |
Red flags — STOP
- About to
Edita target project's TODO.md or.claude/memory/*. - About to run
gitflow finish,git merge, orgit push. - About to
git add -Aor commit onmain/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 --porcelainnon-empty and no residual line explaining every leftover path.
TDD note (skill itself)
Baseline-tested per superpowers:writing-skills (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.