Skip to content

SPEC-4 — superpowers-native lifecycle (role-per-phase skill bundles, /fleet Lifecycle view, /fleet-implement) - #5

Merged
rz1989s merged 22 commits into
mainfrom
feat/spec-4-superpowers-lifecycle
Jul 24, 2026
Merged

rz1989s merged 22 commits into
mainfrom
feat/spec-4-superpowers-lifecycle

Conversation

@rz1989s

@rz1989s rz1989s commented Jul 24, 2026

Copy link
Copy Markdown
Member

SPEC-4 — Superpowers-native lifecycle

Implements the approved SPEC-4 design (specs/SPEC-4-superpowers-native-lifecycle.md):
a lifecycle runs a task through the superpowers pipeline
(brainstorm→plan→implement→review→finish) by spawning one child subagent per phase,
threading each phase's file artifacts into the next, and pausing for human review
(Continue/Revise/Abort) at phase boundaries by default — with an auto escape.

Decisions (7-Q&A brainstorm, locked)

  • Q1=B phase = skill bundle, no role library (reconciles PRD §8 role-per-phase vs SPEC-1 §7.3)
  • Q2=C checkpointed default + --auto escape
  • Q3=B lifecycle registry (builtins + user-authored), selection at call time
  • Q4=C default single-backend + per-phase override
  • Q5=A extend subagent with optional lifecycle param + pi-fallback default backend
  • Q6=B file-path handoff (prompt-baked Artifacts: block) + bounded Revise (max 3)
  • Q7=C one TODO per lifecycle + phase sub-entries in notes

Architecture

Additive above the SPEC-1/2/3 engine — the ChildSessionFactory/ChildSession/
BackendRegistry seam is untouched. Every phase is an ordinary subagent spawn routed
through BackendRegistry.get(agentDef.backend).factory; the lifecycle just decides which
agent + skill bundle + prompt template each phase uses, and chains them with checkpoints.

What's new

  • src/lifecycle/ — types, registry (parser + discovery, project-over-global), the default
    builtin (5 superpowers phases with locked skill bundles), prompt template renderer,
    Artifacts: block parser, lifecycle TODO helpers, and runLifecycle (the phase loop +
    checkpoint state machine).
  • subagent tool — +optional lifecycle + auto params (backward-compatible; absent ⇒
    single phaseless run unchanged). Tool-driven = auto; checkpoints are a /fleet panel feature.
  • /fleet panel — new Lifecycle tab (fleet→lifecycle→agents→backends): list, phase
    timeline detail (i:Info), r:Run-lifecycle action, interactive Continue/Revise/Abort
    checkpoint submenu.
  • /fleet-implement <task> [--lifecycle <name>] [--auto] — the done-bar slash.
  • SpawnOptions.lifecycleTodoId — per-phase spawns link to the parent lifecycle TODO and skip
    mark-done/revert (the lifecycle engine owns the lifecycle TODO's status + progress block).
  • TodoSyncPort.updateLifecycleProgress — single-source-of-truth progress block in the
    lifecycle TODO's notes.

Guards (carried forward)

todo-excluded (single-writer), concurrency=1, turn budget, Esc-abort — all SPEC-1/2/3 guards
unchanged. No new backends, no new agent types, no predetermined role library.

Verification

  • pnpm typecheck clean.
  • pnpm test:run — 165/165 pass (107 existing + 58 new SPEC-4 tests; no regressions).
  • scripts/spec-4-smoke.mts — real end-to-end lifecycle smoke (real Ollama pi phases; CC rows
    skip gracefully if claude absent). Run manually post-merge; not in the CI gate.
  • docs/SPEC-4-smoke-checklist.md — term-driven TUI smoke matrix (run after publishing v0.4.0).

Not in this SPEC (deferred, per spec §14)

worktree isolation / async-bg / concurrent child sessions → SPEC-5a; mid-run steering +
conversation viewer → SPEC-5b; cost-aware tiers / workflows-as-code / event-bus RPC → SPEC-6;
systematic-debugging + using-git-worktrees in the default lifecycle → user-addable / SPEC-5a.

Release

This is the SPEC-4 implementation. After merge: tag v0.4.0release.yml publishes
@getpipher/armory-fleet@0.4.0 + GitHub Release (mirrors the v0.2.0/v0.3.0 flow), then the
term-driven TUI smoke (install 0.4.0, /reload, /fleet → Lifecycle tab).

rz1989s added 22 commits July 24, 2026 16:52
7-decision brainstorm (2026-07-24):
- Q1=B phase = skill bundle, no role library (reconciles PRD §8 role-per-phase vs SPEC-1 §7.3)
- Q2=C checkpointed default + auto escape
- Q3=B lifecycle registry (builtins + user-authored), selection at call time
- Q4=C default single-backend + per-phase override
- Q5=A extend subagent with optional lifecycle param + pi-fallback default backend
- Q6=B file-path handoff (prompt-baked Artifacts block) + bounded Revise (max 3)
- Q7=C one TODO per lifecycle + phase sub-entries in notes

Additive above the SPEC-1/2/3 engine — ChildSessionFactory/ChildSession/BackendRegistry
seam untouched. New /fleet Lifecycle view. Done bar: /fleet-implement <task>.
…D tasks)

Task 1 lifecycle types → 2 parser → 3 discovery → 4 default builtin → 5 prompt template →
6 artifacts parser → 7 lifecycle TODO + port → 8 SpawnOptions.lifecycleTodoId → 9 runLifecycle
phase loop → 10 subagent lifecycle param → 11 /fleet Lifecycle view → 12 index wiring +
/fleet-implement slash + smoke script + TUI checklist.

Additive above the SPEC-1/2/3 engine (ChildSessionFactory/ChildSession/BackendRegistry seam
untouched). Each task is one commit, TDD (failing test → impl → pass → commit). Self-reviewed:
no placeholders, spec §1-9 covered, type names consistent across tasks.
…, routes to runLifecycle)

Also wires minimal lifecycleRegistry + lifecycleDeps into index.ts deps so the
tree stays green; full slash/panel wiring lands in Task 12.
…nt submenu + Run action)

Adds the lifecycle tab (fleet→lifecycle→agents→backends), lifecycleRow +
lifecyclePhaseTimeline row fns, i:Info phase-timeline detail, r:Run-lifecycle
inline input (task→name), and the interactive Continue/Revise/Abort checkpoint
submenu. Threads lifecycleRuns into the shared deps (tool + panel).
…ior summary, live agentRegistry, fail-loud backend resolve

- runLifecycle: revise feedback digest now uses the current phase's own prior attempt
  summary (priorAttemptSummary), not the previous phase's record (prev).
- index.ts: refresh() mutates deps.registry in place instead of replacing the reference,
  so lifecycleDeps.agentRegistry (bound once at init) stays live across refreshes.
- runLifecycle: resolveBackend throw is caught → revert todo + return a failed result with
  an actionable message (was an unhandled rejection that orphaned the lifecycle todo).
- +2 regression tests (revise-feedback correctness, backend-unavailable fail-loud).
…1=B/Q4=C), accumulate progress, checkpoint-esc guard

Code review of PR #5 found three real issues (unit tests passed because the fake
spawn ignored the lifecycle fields):

1. CRITICAL — per-phase skill bundles + per-phase backend override were computed by
   runLifecycle then discarded (`void skills`). PhaseSpawnOpts carried neither, so the real
   spawnSubagent routed by the agent's backend + loaded the agent's skills — the lifecycle's
   headline features (Q1=B skill bundles, Q4=C backend override) never reached the child.
   Fix: PhaseSpawnOpts += skills + backend; SpawnOptions += skillsOverride + backendOverride;
   spawnSubagent clones the agentDef with the merged skills + routes by the override. The three
   real spawn adapters (subagent tool, panel, /fleet-implement) thread them through. +2 regression
   tests assert the spawn receives the merged skills + the phase's backend.

2. IMPORTANT — lifecycle-todo updateProgress built a new phases array but never wrote it back,
   so the progress block didn't accumulate (completed phases reverted to [ ] on the next update).
   Fix: mutate the shared progressPhases in place. +1 accumulation regression test.

3. IMPORTANT — panel esc while a checkpoint was pending called onDone() without resolving the
   checkpoint promise → runLifecycle hung + the TODO was orphaned. Fix: esc resolves the pending
   checkpoint as abort before closing.

Also: failResult now threads the lifecycle's backend (was hardcoded 'pi'); spawn throw guarded
as a phase failure (can't orphan the lifecycle).
…egistry (mirror spec-3-smoke), thread skillsOverride/backendOverride
…trailing prompt-echo

The real-Ollama end-to-end smoke (scripts/spec-4-smoke.mts) caught two parser gaps that
unit tests (with clean synthetic finalText) missed:

1. Models wrap the Artifacts block in a fenced code block (```yaml … ```) with the
   'Artifacts:' marker INSIDE the fence. The closing fence + trailing content broke the YAML
   parse. Fix: strip a leading opening fence, truncate the block at the first closing fence OR
   thematic break (---), whichever comes first.

2. The child inherits CIPHER's prompt-echo rule from the base system prompt, so its finalText
   trails a '📌 YOUR PROMPT: …' echo that itself contains the literal 'Artifacts:' (quoting the
   phase instruction). lastIndexOf('Artifacts:') was matching the echo, not the real block.
   Fix: strip the trailing prompt-echo trailer before searching.

Also: smoke script parentModel corrected to Ollama/glm-5.2:cloud (was ollama-cloud/qwen3-coder).
Smoke now PASSES end-to-end: brainstorm→plan→implement→review→finish on real Ollama Cloud.
+3 parser regression tests (fenced, plain-fenced, prompt-echo).
@rz1989s
rz1989s merged commit 67ff9b4 into main Jul 24, 2026
1 check passed
@rz1989s
rz1989s deleted the feat/spec-4-superpowers-lifecycle branch July 24, 2026 15:14
rz1989s added a commit that referenced this pull request Jul 24, 2026
rz1989s added a commit that referenced this pull request Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant