| name | execute-backlog |
| description | Use when ready to attack the GitHub issue backlog with discipline. Scans open issues, bundles related work into an efficient execution plan, executes the bundle with verification, then closes issues + writes a retrospective that includes self-improvement notes for this skill. Trigger phrases — "execute backlog", "work the backlog", "knock down P1 issues", "ship a bundle", "/execute-backlog". |
| user-invocable | true |
Execute Backlog
Purpose: turn the GitHub issue backlog into shipped work using a deterministic loop: SCAN → BUNDLE → PLAN → EXECUTE → VERIFY → UPDATE → RETRO. Each pass closes a coherent bundle of issues, leaves the repo greener than it found it, and writes a retro that improves the skill itself.
Operating principle (Extreme Ownership): every issue in the bundle is "owned" by the executing agent for the duration of the pass. No half-finished issues. No "punted" verification. If a bundle can't ship clean, the bundle gets descoped — not the verification.
When to Use
- Backlog has ≥5 open issues with
priority:p1 or higher
- A sprint / release-gate moment: pick the next high-impact bundle
- User says "let's work the backlog", "execute audit-2026-05-21", "knock down the killswitch issues"
- Agentic team handoff: spawn one of these per worker, each owning a label-scoped bundle
Don't use for:
- One-off bug fixes (use
agent-tdd directly)
- Backlog audit / re-prioritization (use
architecture-audit)
- New feature work (use
reactive-feature-dev)
Inputs (declared by caller)
The skill MUST be invoked with at least one filter — never run unfiltered.
filter:
labels:
priority:
phase:
max_bundle_size: 5
budget_minutes: 90
Caller examples:
/execute-backlog labels=audit-2026-05-21 priority=p1
/execute-backlog labels=area:providers,phase:E
/execute-backlog labels=health-sweep,priority:p1 max_bundle_size=3
Phase 1 — SCAN
Query GitHub for candidate issues matching the filter.
rtk gh issue list \
--state open \
--label "<comma-joined labels>" \
--json number,title,labels,body,createdAt,updatedAt \
--limit 100
For each candidate, parse:
- Issue number, title
- All labels (especially
area:*, priority:*, verified)
- Primary file/location (regex from body:
**Location:** line)
- Verified-by present? (boolean —
**Verified-by:** block in body)
Filter rules:
- Drop any issue without
verified-by: evidence — file a comment asking for verification; do not execute on unverified claims (the 2026-05-21 inflation pattern is the reason this rule exists)
- Drop
phase: mismatches if phase: filter was provided
- Drop issues with the
blocked label
- Drop issues assigned to someone else
Drift check (added 2026-05-21): for any candidate carrying a verified-by command with file:line references, re-run the command. If the emitted line numbers differ from the issue body's claimed lines by >5 on any row, mark the candidate 🟡 drift detected and re-read the cited spans to confirm the semantic cast/pattern still matches. Counts can match while locations move 25+ lines — that means the surrounding logic refactored and the fix shape may no longer apply. Acceptable to proceed; not acceptable to skip the check.
Drift check addendum (added 2026-05-21 v3): semantic-equivalent pattern grep. When the issue body claims N sites but the primary grep returns fewer, the gap may be a syntactic variant of the same anti-pattern, not real drift. Before declaring 🟡 drift detected, additionally grep the known equivalence classes:
| Primary pattern | Semantic equivalents to also grep |
|---|
(x as any) | (x as unknown as {…}), (x as unknown as Record<…>) |
: any | : unknown (intentional widening), : Record<string, any>, untyped function-type Function |
as Function | (...args: any[]) => any, Callable aliases |
If the sum of equivalence-class matches reproduces the claimed count, proceed (no drift — issue author counted across both forms). If the sum still falls short, mark drift and re-read the cited spans. (Reason: 2026-05-21 #71 spawn — issue claimed 7 sites; primary grep (state as any) returned 3; the other 4 lived under as unknown as { … } narrowings. Including both forms recovered the exact 7.)
Output: candidate set, sorted by priority:p0 > p1 > p2 > p3, then by verified label (verified issues rank higher), then drift-clean before drift-detected.
Cross-package consistency probe (added 2026-05-22 v9). When the issue touches per-framework / per-platform packages providing equivalent APIs (e.g., @reactive-agents/react + @reactive-agents/svelte + @reactive-agents/vue all exporting useAgentStream-style hooks/factories), briefly diff the impl shape across siblings:
diff packages/<sibling-a>/src/<file>.ts packages/<sibling-b>/src/<file>.ts | head -40
Same name + equivalent signature + divergent behavior = latent defect. Surface in the plan's "Adjacent improvement found" section. Fix opportunistically per the test+fix combo rule (Phase 4 v9). (Reason: 2026-05-22 #82 closeout — vue's useAgentStream.StreamError branch threw + was caught by inner try/catch; svelte's equivalent branch used direct next.error = …; next.status = "error" and worked correctly. Sibling diff would have flagged the divergence before the test had to.)
Phase 2 — BUNDLE
Group candidates into one bundle (max max_bundle_size) that ships together. A bundle is coherent when ≥1 of these holds:
| Cohesion signal | Example |
|---|
Same area:* label across all members | All area:providers |
| Primary files overlap (same dir, same package) | All under packages/runtime/src/builder/ |
| Root-cause cluster | HS-06/07/08 all share "untyped state shape" |
| Cross-cutting fix shape | "Remove as any from N hook surfaces" |
| Untyped schema field needs structured access in callers | Local widening type + boundary helper inside the consuming package — see "default fix shape" below |
Default fix shape for typing issues (added 2026-05-21 v5). When the cited as any casts all narrow the same schema-typed-unknown field, default to:
- Create
<domain>-context.ts (or -state.ts) in the consuming dir.
- Define
<Domain>Context = ExecutionContext & { <field>: <ConcreteShape> } (interface mirroring runtime usage, NOT the schema source-of-truth).
- Export
as<Domain>Context(c) boundary helper — single named cast.
- Migrate each cited site through the helper; delete the cast at sources where the field was already typed (dead-cast sweep — see Phase 4).
Three shipped precedents to copy from: #71 HandlerState (packages/reactive-intelligence/src/controller/handler-state.ts), #72 typed BuilderState option groups (packages/runtime/src/builder/to-config.ts), #73 ThinkContext (packages/runtime/src/engine/phases/agent-loop/think-context.ts). The pattern keeps each fix inside its consuming package (cross-package descope gate satisfied automatically).
Bundling algorithm:
- Take the highest-priority candidate as seed
- Greedily add candidates that share ≥1 cohesion signal with the bundle
- Stop at
max_bundle_size OR when no remaining candidate has cohesion ≥1 with the bundle
- If the bundle has <2 issues after greedy growth → still proceed (singleton bundles are fine)
Hard gate (added 2026-05-21): cross-package descope. Before locking the bundle, re-grep each candidate's verified-by command and inspect the file paths it emits. If those paths span ≥2 packages (packages/<a>/… vs packages/<b>/…), descope to a per-package bundle even if the issue body's "Fix direction" suggests otherwise. The body lies; the grep doesn't. (Reason: 2026-05-21 #73 spawn — body said "type properly in the think phase" but the actual as any targets resolved to types owned by @reactive-agents/llm-service and the kernel-context shape, both other packages.)
Multi-package test-infra split (added 2026-05-22 v7). The cross-package gate isn't only for typing/refactor issues — it applies the same way when an issue cites adding tests / infra / docs to N packages. Ship N bundles (one per package), each with its own PR. Name the follow-up bundles in the seed bundle's PR description so the queue is explicit. (Reason: 2026-05-22 #82 spawn — issue cited zero tests across packages/react/, packages/svelte/, packages/vue/. Shipped bundle/react-smoke-tests first; named bundle/svelte-smoke-tests and bundle/vue-smoke-tests as follow-ups in the PR body. Disjoint scopes, independent CI, no cross-package merge conflicts.)
Output: named bundle. Pattern: <area>-<theme> (e.g., providers-untyped-hooks, runtime-builder-as-any-sweep).
Open a new GH issue or use an existing tracker as the bundle parent — link it to all members via Tracks: #N lines. Apply the tracking label.
Phase 3 — PLAN
For the bundle, write a concrete execution plan to wiki/Planning/Implementation-Plans/YYYY-MM-DD-<bundle-name>.md.
Plan must contain:
# Bundle: <name>
Date: YYYY-MM-DD
Budget: <budget_minutes> min
Issues: #N, #N, #N
## Acceptance criteria (per issue)
- #N: <one-sentence done definition tied to the verified-by claim>
## Execution units (ordered)
1. **Unit 1:** <one or two issues, ≤45 min, files touched, tests touched>
2. **Unit 2:** ...
## Risk register
- <risk> → <mitigation>
## Verification protocol (cross-cutting)
- `bun test packages/<changed>/` — full pass
- `bun run build` — green
- `bunx turbo run typecheck --filter=<changed>` — green
- Sample replay or trace test if behavior change
## Out-of-scope (explicit)
- <thing> — punt to next bundle
Plan gates:
- If total estimated effort >
budget_minutes → descope to fit; do NOT skip verification
- If any unit depends on infra not in the repo → mark
blocked on that issue, drop from bundle
- If two units conflict (same file, conflicting changes) → sequence them, never parallelize
Substrate-aware test strategy (added 2026-05-22 v8). When the bundle adds tests to a new framework/package, identify the test substrate up front. Three classes:
| Substrate | Examples | Default coverage |
|---|
| Render-bound | React hooks, Vue setup(), web components | Public-surface smoke + type contracts. Behavioral via render = follow-up bundle (justify the @testing-library/X + happy-dom investment separately). |
| Framework-agnostic | Svelte stores (writable), Solid signals, Effect.Effect | Behavioral coverage with mocked I/O (e.g., globalThis.fetch = async () => new Response(...)). No DOM/render needed. |
| Pure | Plain JS factories, helpers, parsers | Behavioral coverage directly. No mocking infrastructure beyond stub inputs. |
Picking the wrong default = scope creep (render-bound bundle pulled into the test-infra rabbit hole) or coverage gap (framework-agnostic bundle capped at smoke when behavioral was cheap). (Reason: 2026-05-22 #82 spawn — react bundle (#100) capped at 6 smoke cases due to render-context requirement; svelte bundle (#101) shipped 13 cases including 9 behavioral because stores work in any runtime. Coverage gap would have been ~half if both bundles defaulted to "smoke only".)
When in doubt, write one case at the framework-agnostic tier and see if it runs under bare bun:test. If yes, proceed behavioral. If "Invalid hook call" / setup errors → drop to smoke + name the follow-up bundle.
Read the superpowers:writing-plans skill conventions (location override: wiki/Planning/Implementation-Plans/).
Fire-site reachability check (added 2026-05-21 v4): before designing integration-style tests for any unit, grep the call graph to verify the test scenario will actually exercise the code under fix. A hook/handler/wrapper can be registered without being fired if the test scenario routes through an alternate code path (e.g., withTestScenario short-circuits the reactive loop and bypasses runner.ts:683 runPhaseHooks). Quick check:
rtk grep -rn "<wrapper-or-helper-name>\|<registered-fn-pattern>" packages/
If reachability is uncertain, default to direct-invocation tests (instantiate the helper / pull from registry / call wrapper directly) rather than full-stack agent.run() tests. Reason: 2026-05-21 #74 spawn — initial test design called agent.run() with withTestScenario + withReasoning(), expecting the harness before('think') wrapper to fire. It never did. Probes confirmed the wrapper was registered but the kernel-loop fire site was bypassed. Direct invocation via RegistrationHarness._collected pinned the unit in 6 tests, 0 flakes.
Adjacent-improvement detection at baseline (added 2026-05-25 v11). When the post-branch baseline bun test or bunx turbo run typecheck reports failures in the SAME package as the bundle, scan each failure's fix-shape against the bundle's root-cause class:
| Baseline failure type | Adjacent-improvement test |
|---|
| Typecheck red w/ identical anti-pattern as cited verified-by | Add to bundle. Same helper / fix shape. No scope creep. |
| Pre-existing test fail in untouched code path | File follow-up issue; don't block bundle. |
| Lint warning in adjacent file with shared fix recipe | Add to bundle iff ≤5 LOC delta and same package. |
If adjacent improvement adopted, update the plan doc's "Adjacent improvement found" section AND broaden the verified-by recheck command from per-file to workspace-wide (or per-package-wide). Generalization of the v9 "test+fix combo" rule. (Reason: 2026-05-25 #85 spawn — baseline typecheck flagged 5 errors in tests/controller/dispatcher-compose-bridge.test.ts with identical InterventionHandler<TDecision> contravariance root cause as the cited 9 sites in handlers/index.ts. Bundling them added 9 helper applications, 0 LOC of new design, silenced all 5 errors. Excluding them would have left a follow-up bundle with one-line diff each — wasteful.)
Phase 3.5 — BRANCH (mandatory)
Before any code edits land, create a dedicated feature branch off main for the bundle:
rtk git fetch origin main
rtk git checkout -B bundle/<bundle-name> origin/main
Naming pattern: bundle/<area>-<theme> (e.g., bundle/runtime-builder-state-typing). The branch is the unit-of-work for the entire bundle. All commits in Phase 4 land here; the Phase 6 PR ships them together.
If the working tree is dirty when this skill is invoked, stop and surface the dirt — do not stash silently. The caller decides: commit, discard, or move out of the way. (Reason: per feedback_commit_before_branch.md, exploratory state must not get mixed into bundle commits.)
Baseline capture (added 2026-05-21): immediately after branching, pin the pre-EXECUTE state:
rtk bun run build 2>&1 | tail -3
rtk bun test 2>&1 | tail -3
Stash the numbers in the plan doc under a ## Baseline heading. Phase 5 compares against these; pre-existing reds get filed as follow-up issues (see #93 pattern) rather than blocking the bundle. Without this baseline, a pre-existing failure surfaced by your edits looks like a regression and you'll burn budget chasing it.
Phase 4 — EXECUTE
For each execution unit, follow agent-tdd discipline:
RED → write/find failing test demonstrating the issue
GREEN → minimum fix that turns the test
REVIEW → run review-patterns; address findings
COMMIT → conventional commit, citing GH issue numbers
RED authority check (added 2026-05-25 v10). Before relying on a RED test to pin a missing type or field, check two harness conditions that can silently mask the RED:
- Tests excluded from typecheck. Run
rtk grep -A2 '"exclude"' packages/<X>/tsconfig.json — if "tests/**/*" is excluded, missing-type errors in the RED test will NOT fail typecheck. The "RED" passes against pre-fix state at type level.
- TaggedError / structural-type leniency. Effect's
Data.TaggedError stores any field passed to its constructor, even if the payload type doesn't declare it. expect(err.newField).toBeDefined() will pass against pre-fix state if the test constructs the error with newField. Same for plain TS structural types — passing extra properties to a struct constructor is accepted at runtime.
When either holds, the RED is post-hoc regression coverage only — it doesn't prove the pre-fix state was broken. Acceptable; just note in the plan's risk register and don't claim "test failed before fix, passes after" in the retro unless you confirmed it. To strengthen RED authority for type fields: write a temporary src/.test-types.ts smoke file that imports and destructures the new field, run tsc --noEmit on src/, then delete the smoke file before commit. Overkill for most fixes; flag only when the pre-fix RED must be authoritative.
(Reason: 2026-05-25 #75 spawn — RED test parse-error-attempts.test.ts was written expecting typecheck failure on ParseAttemptError not-yet-exported and LLMParseError.attempts not-yet-declared. Both conditions held: packages/llm-provider/tsconfig.json excludes tests; Data.TaggedError stored attempts field at runtime regardless of type declaration. The "RED" passed against pre-fix state. Fix still landed clean; lesson is to not over-claim RED→GREEN narrative in retros when these conditions hold.)
Single-area mechanical-scaffold bundle template (added 2026-05-25 v10). When N sites in one package share an identical scaffold (same imports, same control flow, same fix shape), prefer mechanical in-place edit over helper extraction. Heuristic:
| Condition | Action |
|---|
| N ≤ 10 sites, same package, identical scaffold | Mechanical push/edit at each site. Verified-by = grep -c '<new-pattern>' returns N. |
| N > 10 sites, OR scaffold spans packages, OR scaffold has 3+ divergent variants | Extract helper. Test helper directly with mocked inputs. |
Mechanical edit wins on review surface (one shape to verify N times) and ships faster. Helper extraction trades that for de-duplication; only worth it when the dup cost exceeds the abstraction cost. (Reason: 2026-05-25 #75 — 5 providers × ~50 LOC identical retry loop. In-place push of 2 lines per provider beat extracting parseStructuredWithRetry helper on budget AND eliminated SDK-mock test complexity. Verified-by grep -c parseAttempts.push → 10 caught all sites in one check.)
Dead-cast sweep (added 2026-05-21 v5). Before migrating each cited as any site through a new helper, check whether the underlying type already supports the access pattern (the schema may have been tightened since the cast was added; the cast was historic). Delete dead casts outright — lighter diff, no helper indirection, less maintenance. Procedure for each site:
(Reason: 2026-05-21 #73 spawn — 2 of 9 cited (c as any).selectedStrategy casts were dead because selectedStrategy was already Schema.optional(Schema.String) on the schema. The casts were historic from a pre-typing era and could be deleted without any helper plumbing.)
sed-after-Edit hazard (added 2026-05-25 v11). When mixing the Edit tool (precise per-site) with bulk sed -i 's/A/B/g' in the same file/session, sed's pattern may re-match Edit-wrapped sites when the post-wrap suffix overlaps the search pattern's tail. Example: wrapping fixedHandler(...) with asInterventionHandler(fixedHandler(...)), then running sed 's/registerHandler(dispatcher, fixedHandler(.*));$/.../' will re-match Edit-wrapped sites because both pre-wrap and post-wrap lines end with ));. Result: extra paren on already-wrapped sites, syntax break, lost minutes.
Procedure:
rtk grep -c "<post-state-tail>" <file>
(Reason: 2026-05-25 #85 spawn — 4 Edit-wrapped sites at lines 104, 129, 130, 131 ended up with extra ) after sed re-matched them. Caught by tsc TS1005: ';' expected within seconds; fixed with one replace_all Edit. Cheap to fix, but trivially avoidable by pre-grepping post-state.)
Same-session multi-bundle protocol (added 2026-05-21 v5). When chaining bundles in one session, each subsequent branch MUST be created from origin/main, not from the previous bundle's branch. Stacking bundles undermines the verified-by gate — a subtle regression in bundle 1 would mask in bundle 2's tests (or worse: cause bundle 2 to attribute its failures incorrectly). Each bundle:
- branches off
origin/main clean (git checkout -B bundle/<name> origin/main)
- ships its own PR
- is merged independently — never auto-merged
This session (2026-05-21 night+1) shipped #97 + #98 disjoint via this protocol; total ~1h45m. Worth pinning.
Commit message template:
fix(<package>): <short description>
Closes #N (bundle: <bundle-name>)
<one line on what changed>
<one line on what verified it>
Test-path fallback (added 2026-05-21 v4): if a planned RED integration test cannot reach the unit under fix after one debug round (e.g., wrapper registers but never fires), stop debugging the test scaffold and switch to direct invocation. Pull the registered handler/wrapper/helper from its registry (e.g., RegistrationHarness._collected, LifecycleHookRegistry.list()) and call it directly. Direct-invocation tests:
- pin the unit faster (sub-second runs vs full agent.run loops)
- isolate the fix from orthogonal config (provider, reasoning, scenario)
- match the cohesion signal: if the issue cites a single file:line, the test should hit that line without depending on a deep call chain
When in doubt, write the direct-invocation test first; expand to integration coverage only if multi-component interaction is actually under fix.
Path-aware verified-by (added 2026-05-21 v4): when a single file:line cited by an issue is fired from multiple call-graph paths (e.g., engine LifecycleHookRegistry AND harness HarnessPipeline both invoke the same hook handler), the issue's symptom may already be partially fixed by one path while the other still has the bug. Before locking the bundle scope, grep callers of the cited site and document in the plan which paths actually exhibit the symptom. The fix may be narrower than the verified-by suggests. (Reason: 2026-05-21 #74 — the engine path already escalated sync throws as defects through Effect.catchAll, surfacing them to reactive-agent.ts:549 and firing _errorHandler. Only the harness duplicate-fire path was truly silent. A naive fix targeting "all hook error paths" would have overscoped.)
Dead-code sweep (added 2026-05-22 v6). Before applying the issue's prescribed fix, check whether the cited code is dead in the current codebase state. Deletion is preferable to migration/replacement when the original purpose is already satisfied elsewhere. The check applies broadly:
| Cited surface | Dead-code check |
|---|
as any cast | does the underlying type already cover the access? → delete cast |
test.skip("RED…") placeholder | did the targeted mechanism ship ✅ KEEP per phase-1/health-sweep evidence? → delete block |
| Helper function only referenced by deleted code | grep for inbound refs → delete |
| Interface/type only used inside a deleted span | same — delete |
TODO on live code path | does the followup issue exist OR is the work obsolete? → wire or remove per HS-23 pattern |
When deletion is the right action, also confirm the issue's verified-by points at a stable external artifact (phase-1 evidence, MEMORY.md verdict, audit report) — that's what makes "delete" safe vs "replace with TBD". (Reason: 2026-05-22 #80 spawn — m1-dispatcher-validation.test.ts:65 test.skip("RED phase…") was 110 LOC of placeholder. M1 had already shipped ✅ KEEP per harness-reports/phase-1-mechanism-validation-2026-05-04.md. Pure deletion was correct; replacement would have invented coverage that doesn't exist.)
Pure-deletion verified-by (added 2026-05-22 v6). When the bundle is purely deletion (no new helper, no migration, no replacement), the standard "grep target → 0" recheck is structurally weaker than for typing/refactor bundles. Strengthen by also asserting:
- Test count delta matches expectation. If you deleted
test.skip(...), the package test runner's skip count should drop by exactly that number. Capture in retro alongside pass/fail.
- No inbound references remain. For any symbol deleted (helper fn, interface, type), grep workspace-wide for references and confirm zero matches outside the touched file itself:
grep -rn "<DeletedSymbol>" packages/ | grep -v "<touched-file>" → 0. If any inbound ref survives, your deletion shipped a compile-time break.
- No dangling imports.
grep -n "import.*<DeletedSymbol>" packages/ → 0.
Failing any of these means the deletion missed adjacent dead-code; either expand scope or undo and re-bundle.
Pause conditions (descope rather than skip):
- Build goes red → revert unit, reopen issue with new failure mode, continue with remaining units
- Test suite gains net-new failures → same as above
- Effort blows past unit estimate by 2× → mark issue
over-budget label, defer, continue
Test+fix combo bundles (added 2026-05-22 v9). When a behavioral RED test surfaces an impl bug during a test-coverage bundle, the fix lands in the same PR. The PR title combines verbs: test(X): add coverage; fix Y. Allowed when all apply:
- The fix is ≤10 lines.
- The fix mirrors an existing-working pattern in a sibling package, OR passes a code-reviewer agent for correctness.
- The fix is covered by the same test that surfaced it (test serves as regression check).
If any of those fail, descope: file the bug as a separate issue and ship the bundle with the test marked test.skip / xfail referencing the new issue. (Reason: 2026-05-22 #82 vue portion — behavioral SSE-error test failed because use-agent-stream.ts:76-78 threw inside an inner JSON.parse try/catch that swallowed it. Svelte sibling used direct assignment, no throw. 2-line mirror fix landed in PR #102 alongside the regression test. Defended over "test-only PR + separate fix PR" because the swallow is invisible to types and would have stayed latent.)
Do NOT:
- Skip tests for time pressure
- Use
as any to silence types from the very issues you're closing
- Mix unrelated changes into a single commit (test+fix combo is NOT mixed — it's one observably-correct concern)
Phase 5 — VERIFY (cross-cutting, after all units commit)
Run the bundle-wide verification gate:
rtk bun run build
rtk bun test
rtk bun run typecheck
For each issue in the bundle, re-check the original verified-by claim against the new code state:
issue #N verified-by said: `grep -c "as any" packages/X/Y.ts` → 5
new check: `grep -c "as any" packages/X/Y.ts` → 0
✅ resolved
If a verified-by check fails to come down → the fix didn't actually address the claim. Reopen the issue with the new count + commit ref.
Workspace-test-flake protocol (added 2026-05-22 v7). When bun test (workspace, run from repo root) shows failures but per-package isolation runs clean, treat as test-order / fixture-state flake. Verification is acceptable when:
- The bundle's touched package suite passes in isolation:
rtk bun test packages/<touched>/ → 0 fail.
- The failing tests live in packages NOT touched by the bundle. (
rtk bun test packages/<failing-pkg>/ → 0 fail confirms it's flake, not real.)
- The failing tests are not the verified-by recheck for any bundle issue.
Document the flake in the PR body (test name + isolation evidence). Do NOT block the bundle. CI may surface the same flake; if so, rerun the failed job. (Reason: 2026-05-22 #82 spawn — workspace bun test showed 2 fails in packages/diagnose/; rtk bun test packages/diagnose/ → 35/0. Pre-existing test-order issue, unrelated to the react smoke bundle. CI on #100 will rerun cleanly. Same pattern surfaced on #99 — httpbin.org external-network flake resolved on rerun.)
Track flakes that recur across ≥2 bundles in their own follow-up issue (e.g., "test-order flake in packages/diagnose under workspace bun test") — separately from any active bundle.
Phase 6 — UPDATE
6a — Open the PR (mandatory). Every execution session ships its bundle as one PR. No direct-to-main pushes.
rtk git push -u origin bundle/<bundle-name>
rtk gh pr create \
--base main \
--head bundle/<bundle-name> \
--title "<bundle-name>: <one-line summary>" \
--body "$(cat <<'EOF'
## Bundle: <name>
Closes #N
Closes #N
## Summary
<2-3 lines on what changed>
## Verification
- `bun run build` ✅
- `bun test` ✅ (delta: +X / -Y vs baseline)
- `bunx turbo run typecheck --filter=<changed>` ✅
- Verified-by rechecks (per issue):
- #N: `<command>` → <new result> (was <old>)
## Plan + Retro
- Plan: wiki/Planning/Implementation-Plans/YYYY-MM-DD-<bundle>.md
- Retro: wiki/Research/Debriefs/YYYY-MM-DD-<bundle>-execution-debrief.md
EOF
)"
PR body MUST include Closes #N for every issue in the bundle — GitHub auto-closes them on merge, no manual gh issue close needed. If a bundle issue was descoped mid-EXECUTE, drop its Closes #N line and explain in the PR body.
The skill's job ends at PR open. Merge is a human decision — do not auto-merge.
6b — Project board + knowledge sync. Move bundle issues to In Review column (not Done — done happens on merge). Then:
Sync local knowledge:
wiki/Hot.md — append session note (bundle name, issues closed, key learnings)
.agents/MEMORY.md — if a pattern emerged worth remembering, add a one-line entry under the relevant section
wiki/Issues/Running Issues Log.md — if any HS-NN items closed, mark them in the migration table
Phase 7 — RETRO (mandatory, self-improving)
Write a retrospective to wiki/Research/Debriefs/YYYY-MM-DD-<bundle>-execution-debrief.md:
# Execution Retro: <bundle-name>
Date: YYYY-MM-DD
Budget: <budget_minutes> min | Actual: <actual> min
## Outcomes
- Issues closed: #N, #N, ...
- Issues descoped: #N (reason)
- Net test delta: +X / -Y
- Net LOC delta: +X / -Y
## What worked
- <one-line wins; reference commits>
## What didn't
- <friction points; missed estimates; surprises>
## Skill improvements (apply on next pass)
- <concrete change to SKILL.md — phase wording, gate, bundling heuristic, verification command>
- <e.g., "Bundling missed that HS-07 and HS-08 share a root cause — add 'shared untyped shape' as cohesion signal">
## Process inflation guard (HS-18/22/31 lesson)
- Did any unit's verified-by claim turn out to be inflated? If yes, document the inflation shape so the audit-finding template can catch it next time.
Self-improvement loop: the Skill improvements section gets applied to this very file before the retro is committed. Read this SKILL.md, find the section the retro says to amend, make the edit, commit alongside the retro.
This is non-negotiable. A bundle without a retro is not finished. A retro without a SKILL.md amendment leaves regression risk on the table.
Anti-patterns to Reject
| Anti-pattern | Why it's banned |
|---|
| "Just commit and we'll verify later" | Verification IS the deliverable; deferred = skipped |
| Closing an issue without re-running its verified-by | Pattern that produced HS-18/22/31 inflation |
| Bundling >5 issues for "efficiency" | Token + attention cost grows superlinearly; correlation between bundle-size and bug-introduction is documented |
| Cross-package bundles | Higher diff conflict risk; descope to per-package bundles |
| Retro that says "everything went great, no improvements" | Either (a) untrue (b) skill is at local maximum and needs harder scope — challenge the next run |
Inputs This Skill Reads
- GH issues —
rtk gh issue list ...
- GH labels — existing taxonomy (
area:*, phase:*, priority:*, health-sweep, architecture-debt, verified, audit-2026-05-21)
wiki/Hot.md — recent state to avoid stepping on in-flight work
wiki/Issues/Running Issues Log.md — historical context for HS-NN items
- AGENTS.md, CODING_STANDARDS.md — patterns the fixes must conform to
- Skill:
agent-tdd — TDD discipline during EXECUTE
- Skill:
review-patterns — gate before COMMIT
- Skill:
writing-plans (with wiki/Planning/Implementation-Plans/ override)
- Skill:
codebase-health-sweep — for any opportunistic finding flagged during EXECUTE that wasn't in the bundle
Outputs This Skill Writes
- Commits per execution unit (conventional format, citing GH #N)
- One bundle plan at
wiki/Planning/Implementation-Plans/
- One execution retro at
wiki/Research/Debriefs/
- GH issue closes + comments
- Project-board column moves
- Self-amendment to this SKILL.md (only the "Skill improvements" section can drive this; never silent edits)
Recommended Invocation Patterns
Solo run:
/execute-backlog labels=audit-2026-05-21 priority=p1
Parallel agent team (Extreme Ownership):
Spawn one agent per area:* label with disjoint bundle scopes — each owns its area end-to-end. Coordinate via the tracker parent issue.
agent-providers: /execute-backlog labels=audit-2026-05-21,area:providers
agent-reasoning: /execute-backlog labels=audit-2026-05-21,area:reasoning
agent-harness: /execute-backlog labels=audit-2026-05-21,area:harness
Daily/weekly cadence:
Schedule via /loop — /loop 1d /execute-backlog labels=priority:p1 max_bundle_size=3 — but ONLY if budget + verification rigor is non-negotiable in the loop body.
Quick Reference Card
SCAN gh issue list --label … --json
BUNDLE greedy cohesion grow, cap at max_bundle_size
PLAN wiki/Planning/Implementation-Plans/YYYY-MM-DD-<bundle>.md
BRANCH git checkout -B bundle/<bundle-name> origin/main (clean tree only)
EXECUTE TDD per unit, conventional commits cite #N
VERIFY build + test + typecheck + re-run each verified-by
UPDATE gh pr create with Closes #N (auto-close on merge), board → In Review, Hot.md note
RETRO wiki/Research/Debriefs/, AMEND THIS SKILL.md
If any phase output is missing → the bundle is not finished. There is no "good enough."