<!-- lifecycle-handoff-protocol:start --> Lifecycle handoff (standalone /compound before ship): When compound runs as the pre-ship step in the implementation tail, invoke /ship next — artifacts archived here are a checkpoint, not completion. Parent orchestrators (work, one-shot) own progression when active. <!-- lifecycle-handoff-protocol:end -->
/compound
Coordinate multiple subagents working in parallel to document a recently solved problem.
Purpose
Captures problem solutions while context is fresh, creating structured documentation in knowledge-base/project/learnings/ with YAML frontmatter for searchability and future reference. Uses parallel subagents for maximum efficiency.
Why "compound"? Each documented solution compounds your team's knowledge. The first time you solve a problem takes research. Document it, and the next occurrence takes minutes. Knowledge compounds.
Usage
skill: soleur:compound # Document the most recent fix
skill: soleur:compound [brief context] # Provide additional context hint
skill: soleur:compound --headless # Headless mode: auto-approve all prompts
Headless Mode Detection
If $ARGUMENTS contains --headless, set HEADLESS_MODE=true. Strip --headless from $ARGUMENTS before processing remaining args.
Branch safety check (defense-in-depth): Run git branch --show-current. If the result is main or master, abort immediately with: "Error: compound cannot run on main/master. Checkout a feature branch first." This check fires in all modes (headless and interactive) as defense-in-depth alongside PreToolUse hooks -- it fires even if hooks are unavailable (e.g., in CI).
When HEADLESS_MODE=true, forward --headless to the compound-capture invocation (e.g., skill: soleur:compound-capture --headless).
Phase 0: Setup
Load project conventions:
# Load project conventions
if [[ -f "CLAUDE.md" ]]; then
cat CLAUDE.md
fi
Read CLAUDE.md if it exists - apply project conventions during documentation.
Phase 0.5: Session Error Inventory (MANDATORY)
HARD RULE: Before writing any learning, enumerate ALL errors encountered in this session. Output a numbered list to the user. This step cannot be skipped even if the session felt clean.
Check for session-state.md: Run git branch --show-current. If on a feat-* branch, check if knowledge-base/project/specs/feat-<name>/session-state.md exists. If it does, read it and include any forwarded errors from ### Errors in the inventory. These errors occurred in preceding pipeline phases (e.g., plan+deepen subagent) whose context was compacted.
Include:
- Errors forwarded from session-state.md (if present)
- Skill or command not found errors (e.g., wrong plugin namespace)
- Wrong file paths, directories, or branch confusion
- Failed bash commands or unexpected exit codes
- API errors or unexpected responses
- Wrong assumptions that required backtracking
- Tools or agents that returned errors
- Permission denials or hook rejections
- A framing INHERITED from a sibling artifact, pasted into a context whose premise you never re-checked. We already re-derive inherited numbers; inherited sentences get no such treatment, and they are the ones that read as established — because they were established, somewhere else. The shape recurs when a new entry joins an existing set (a fourth scanned directory, a third vendor row, a second host) and the justification is copied from a sibling entry: the words survive the move, the evidence does not. Gate: for every causal or universal claim the diff's prose ADDS, name the command that would falsify it and run it. Why: #7310 — the PR extending the ADR-166 lint (which forbids naming a cause the job did not measure) wrote "operator-facing shell gates that no lint read" into that lint's own header, reusing ADR-166's true-of-
.github/actions/framing for a directorylint-trap-tempfile-ownership.pywalks in full; and asserted a message "spent a production-recovery window" when the issue predated it by six hours. Both refuted in ~15s bygh pr view --json mergedAtand onegrep. Seeknowledge-base/project/learnings/2026-08-06-i-shipped-two-unmeasured-causal-claims-inside-the-lint-that-forbids-them.md. - Blanket search-replace sweeps (ADR renumbers, identifier renames) that rewrote files outside your own diff — scope every sweep to
git diff --name-only origin/main...HEADand assert the SENTENCE, because a residual-zero count (grep -c '<old>' == 0) is structurally blind to a new string written where it does not belong, including inside the very note explaining the rename. Why: #7162 — asedguarded by a negative lookahead on the sibling ADR's filename rewrote 10 files of other work's bareADR-159citations, and an earlier sweep turned "ADR-155 was claimed by a sibling plan" into a false sentence that the count read as green. Ordinals collided three times on one branch, each surfaced by a fetch or rebase and never by a gate — treat a branch-picked ordinal as provisional and re-check against freshly-fetchedorigin/mainimmediately before merge. Seeknowledge-base/project/learnings/workflow-issues/2026-08-03-blanket-renumber-rewrote-other-work-and-a-count-certified-it.md. - A CORRECTION sweep keyed on the claim's PHRASING rather than its SUBJECT. The sibling bullets above cover sweeps that rewrite too MUCH; this is the inverse — a remediation that rewrites too LITTLE, and whose residual-zero count certifies the miss. Grep the noun the claim is ABOUT (the resource, the anchor comment, the count's referent), read every hit, and decide each one; then replace with derived-set language so the site cannot go stale again. A residual-zero count is evidence about a string, never about a claim. Why: #7539 — having measured a fabricated "six lines beneath" as an actual gap of 138 lines, the sweep for
beneathcame back clean whiletasks.md:51said "six lines BELOW". Indexing by remembered wording is the same defect one level up from the fabrication it was correcting. Seeknowledge-base/project/learnings/2026-08-17-i-corrected-a-fabricated-claim-by-grepping-its-phrasing-and-missed-a-site.md.
If genuinely no errors occurred (including no forwarded errors), output: "Session error inventory: none detected."
This list feeds directly into the Session Errors section of the learning document. Every item on this list MUST appear in the final output unless the user explicitly excludes it.
FAILURE MODE THIS PREVENTS: Compound runs in pipeline mode, the model judges the session as "clean," and silently drops errors that happened earlier in the conversation (e.g., a skill-not-found error from one-shot Step 1 gets omitted because compound focuses only on the main implementation task).
Recurring-vs-One-Off Tech-Debt Triage (MANDATORY)
HARD RULE: Immediately after the Session Error Inventory, classify EVERY inventory item (plus any non-error friction the session hit — a flaky gate, a slow manual workaround, a surprising tool behavior) as recurring or one-off. Do not skip this even when the inventory is short. The operator should never have to ask "are there any of these we could fix now to avoid stumbling on them again?" — this step answers it by default, separating genuine recurring tech debt from one-offs.
For each item, decide:
- recurring — the same class will bite again on a future session/PR (a flaky blocking gate, a missing guard, a foot-gun in a shared script, an inaccurate comment that misleads the next reader). Then pick a disposition:
- fix-now-inline — ≤100 lines AND ≤4 files AND in a subsystem this PR already touches → fold the fix into THIS work. (The first two conjuncts mirror the cost-of-filing gate in
review/SKILL.md§5; the subsystem clause is the scope-discipline overlay — a different-subsystem defect is file-tracked, never inlined here.) - file-tracked — larger, a different subsy