ship-playbook: 7th role (who writes the plan) + two-table dependency check + intake polish

- planHarness: NEW role — who WRITES the plan (native|codex|kiro). The plan agent now routes per
  planHarness (was always native). Added to args, reviewConfig, and the intake as question 1.
- Intake reordered to true execution order: who writes the plan, who reviews the plan, who writes the
  code, who reviews the code, impl review, go-live audit, map project (7 questions).
- Option ordering rule: native first (Recommended), then codex/kiro, skip as the LAST provided option
  (renders second-to-last, before the auto-added "Other"). Plan/code writing are not skippable.
- Dependency check (Phase 1 Step 1): now TWO separate tables, missing-only, with FULL install commands —
  skills via "npx skills add https://github.com/ulpi-io/skills --skill <name>"; agents via
  "npx agentshq add ulpi-io/agents@<agent-name>". Omit a table if nothing is missing.
- map-project clarified end to end: held as mapRefresh, explicitly NOT a Workflow arg (the skill runs
  it in Phase 3 after the build, since it regenerates CLAUDE.md from finished code). Noted at Q7, at the
  args list, and in success criteria.

Verified: workflow reads + consumes all 6 workflow args (planHarness/planReview/buildHarness/taskReview/
implReview/goLive); SKILL asks 7 questions and passes the 5 role args + goLive; map runs skill-side.
JS syntax OK; no dangling global-harness refs.
This commit is contained in:
Ciprian Spiridon
2026-06-19 09:26:53 +04:00
parent cbd1ab2ada
commit d5a1b4e1b9
2 changed files with 70 additions and 41 deletions
+57 -34
View File
@@ -122,9 +122,18 @@ options) what's present vs missing across:
(`codex:codex-rescue`); for **kiro**, `kiro-cli` (<https://kiro.dev/docs/cli>) plus the `kiro-review`
skill (for reviewing) and `hand-over-to-kiro` skill (for building).
Present a short table — **present ✓ / missing ** with the install command for each missing item (e.g.
`npx skills add https://github.com/ulpi-io/skills --skill <name>`; for agents, the source they come
from; for kiro-cli, the docs link). Then **offer two choices** with `AskUserQuestion`:
Present **TWO separate tables**, each listing ONLY the MISSING items (do NOT list what's already
installed), with the **full, copy-paste install command** per row (never an abbreviation):
- **Missing skills** — `npx skills add https://github.com/ulpi-io/skills --skill <name>` (complete
command per row). Covers the composed skills, stack skills, and the kiro helper skills
(`kiro-review`, `hand-over-to-kiro`). `kiro-cli` itself (if missing) goes here too as a note with its
docs link <https://kiro.dev/docs/cli>.
- **Missing agents** — `npx agentshq add ulpi-io/agents@<agent-name>` (complete command per row).
Covers the stack's `*-senior-engineer` + `*-reviewer` specialists.
If a table has no missing items, omit it (or say "all present" in one line). Then **offer two choices**
with `AskUserQuestion`:
- **Continue now** with what's installed (missing specialists fall back to `general-purpose`; missing
harness options simply won't be offered).
@@ -136,31 +145,40 @@ Record what's available — it feeds `availableAgents` and constrains which inta
### Step 2 — The prompt and the gate questions
The prompt is `$request`. Ask the gate questions (in two `AskUserQuestion` calls — up to 4 each), in
execution order, unless `$request` already pins them. **Every role independently picks its executor**
(writer and each reviewer are separate — write with codex, review with kiro is fine); reviews also
allow `skip`. Only offer `codex`/`kiro` for roles whose tooling Step 1 found installed. Defaults are
LIGHT to control token cost; the user can dial each up to full rigor or down to skip.
The prompt is `$request`. Ask the SEVEN gate questions (across two `AskUserQuestion` calls — up to 4
each), in EXECUTION order so they read like the run, unless `$request` already pins them. **Every role
independently picks its executor** (each write and each review is separate — write with codex, review
with kiro is fine). Only offer `codex`/`kiro` for roles whose tooling Step 1 found installed. Defaults
are LIGHT to control token cost; the user can dial each up to full rigor or down to skip.
1. **Code writing** — who WRITES each task (and its fixes): `native` (the plan's specialist engineer
agents — default), `codex`, or `kiro`. Passed as `buildHarness`.
2. **Plan review** — founder review of the plan: `skip`, `native` (default), `codex`, or `kiro`.
Passed as `planReview`.
3. **Per-task review** — who REVIEWS each built task: `skip` (no per-task reviewer or fix loop —
biggest token save), `native` (the matched `-reviewer` — default), `codex`, or `kiro`. Passed as
`taskReview`.
4. **Final implementation review** — the plan-vs-implementation review after the build: `skip`,
`native` (default), `codex`, or `kiro`. Passed as `implReview`.
5. **Go-live audit at the end**`no` (default), or `yes` (runs the go-live audit, only if build+impl
come back verified-clean). Passed as `goLive`.
6. **Refresh the project map at the end**`no` (default), `map-project`, or `map-project-monorepo`.
Detect the repo layout and offer the matching default. Run only in Phase 3 on a real, non-aborted run.
**Option ordering rule:** list `native` first (mark it Recommended/default), then `codex`, then
`kiro`, and put **`skip` as the LAST option you provide** (it then renders second-to-last, right before
the auto-added "Other"). Plan writing and code writing are NOT skippable (they must happen); the four
optional gates (plan review, code review, impl review, go-live audit, map) each include `skip`.
**Defaults** (light, kept safe): `buildHarness native`, `planReview native`, `taskReview native`,
`implReview native`, `goLive no`, map `no`. The user can go **full swing** (every review on, codex/kiro
where wanted, `goLive yes`), **delegate building and reviewing to harnesses** (`buildHarness codex|kiro`
+ `taskReview`/`implReview` codex|kiro — and the writer and reviewer may be DIFFERENT harnesses), or
go fast (skip the reviews). **Warn (do not block)** if BOTH `taskReview skip` AND `implReview skip`:
1. **Who WRITES the plan** — the DAG decomposition: `native` (plan-to-task-list-with-dag — default),
`codex`, or `kiro`. Passed as `planHarness`. (No skip — the plan must be written.)
2. **Who REVIEWS the plan** — founder review (scope, decomposition, phantom paths): `native` (default),
`codex`, `kiro`, or `skip`. Passed as `planReview`.
3. **Who WRITES the code** — every task + its fixes: `native` (the plan's specialist engineer agents —
default), `codex`, or `kiro`. Passed as `buildHarness`. (No skip.)
4. **Who REVIEWS the code** — each built task in the build loop: `native` (the matched `-reviewer`
default), `codex`, `kiro`, or `skip` (no per-task reviewer or fix loop — biggest token save). Passed
as `taskReview`.
5. **Implementation review after all tasks** — the plan-vs-implementation review: `native` (default),
`codex`, `kiro`, or `skip`. Passed as `implReview`.
6. **Run the go-live audit**`run` (the go-live audit, only fires if build+impl come back
verified-clean) or `skip` (default). Passed as `goLive` (run → true).
7. **Run map-project at the end**`map-project`, `map-project-monorepo`, or `skip` (default). Detect
the repo layout and recommend the matching variant. Held as `mapRefresh` — this is NOT a Workflow arg
(it isn't in the `args` object); the SKILL runs the chosen map skill itself in Phase 3, after the
Workflow returns, on a real (non-aborted) run.
**Defaults** (light, kept safe): `planHarness native`, `planReview native`, `buildHarness native`,
`taskReview native`, `implReview native`, `goLive skip`, map `skip`. The user can go **full swing**
(every review on, codex/kiro where wanted, go-live on), **delegate writing and reviewing to harnesses**
(any write/review role → codex|kiro — and the writer and reviewer may be DIFFERENT harnesses), or go
fast (skip the reviews). **Warn (do not block)** if BOTH `taskReview skip` AND `implReview skip`:
nothing then checks the build, so a clean verdict only means the engineer validates passed.
### Step 3 — Project facts, git preflight, agent list
@@ -182,10 +200,10 @@ returns `missingAgents` for anything that still slips through. Never silently su
Open a master `TodoWrite` mirroring the phases in `references/playbook-state.md`.
**Success criteria**: dependency status was shown and the user chose continue-or-restart; `buildHarness`,
`planReview`, `taskReview`, `implReview`, `goLive`, `mapRefresh`, `root` (a confirmed git work tree),
`workingBranch`, `validate`, `hardRules`, and `availableAgents` (+ `allowGeneralFallback` if gaps) are
all resolved.
**Success criteria**: dependency status was shown and the user chose continue-or-restart;
`planHarness`, `planReview`, `buildHarness`, `taskReview`, `implReview`, `goLive`, `mapRefresh`, `root`
(a confirmed git work tree), `workingBranch`, `validate`, `hardRules`, and `availableAgents`
(+ `allowGeneralFallback` if gaps) are all resolved.
## Phase 2 — Run the playbook Workflow (steps 314)
@@ -199,10 +217,14 @@ Then launch `references/workflow-template.js` via the **Workflow** tool, passing
```
Workflow({ scriptPath: ".../references/workflow-template.js",
args: { prompt, root, workingBranch, validate, hardRules, goLive,
buildHarness, planReview, taskReview, implReview,
planHarness, planReview, buildHarness, taskReview, implReview,
auditScriptPath, availableAgents, allowGeneralFallback } })
```
`mapRefresh` is deliberately NOT in `args` — it's the only intake answer the Workflow doesn't run.
The map refresh regenerates `CLAUDE.md` from the FINISHED code, so the skill runs it itself in Phase 3
after the Workflow returns (see Q7). All other gate answers go in `args` above.
**Pass `args` as a real JSON object, NOT a JSON-encoded string.** A stringified blob reaches the
script as one string, fails its `typeof args === 'object'` check, and every input silently falls to a
`FILL:` placeholder. The script hard-THROWS on that instead of returning a fake `converged:true`, so a
@@ -211,9 +233,10 @@ as an object. (Each role arg coerces to a safe default if invalid, so a typo deg
The Workflow then executes the playbook in one pass, running each gate at the level the user chose:
- **Plan (step 3)** — a planning agent follows the plan-to-task-list-with-dag methodology unattended
(mode auto-selected), grounds every path in the real repo, assigns a specialist engineer +
`-reviewer` + stack skill to each task, writes `.ulpi/plans/<name>.md`+`.json`, returns `{tasks, layers}`.
- **Plan (step 3)** — the planner (per `planHarness`: native / codex / kiro) follows the
plan-to-task-list-with-dag methodology unattended (mode auto-selected), grounds every path in the
real repo, assigns a specialist engineer + `-reviewer` + stack skill to each task, writes
`.ulpi/plans/<name>.md`+`.json`, returns `{tasks, layers}`.
- **Plan review (steps 49)** — reviewer per `planReview` (`skip` / `native` / `codex` / `kiro`). ONE
bounded loop → fix the plan (JSON-first, re-render MD; fix is always native) → re-review; exits on no
BLOCK/CONCERN (OBSERVATIONs never block) OR non-convergence, capped at `MAX_REVIEW` (2).
+13 -7
View File
@@ -14,11 +14,12 @@
// the playbook; the skill just supplies them as inputs to this script. Everything else runs here.
//
// HOW TO USE: the skill launches this with
// args = { prompt, root, workingBranch, validate, hardRules, goLive,
// args = { prompt, root, workingBranch, validate, hardRules, goLive, // execution-order roles:
// planHarness, // 'native' | 'codex' | 'kiro' (who WRITES the plan)
// planReview, // 'skip' | 'native' | 'codex' | 'kiro' (who REVIEWS the plan)
// buildHarness, // 'native' | 'codex' | 'kiro' (who WRITES each task + fixes)
// planReview, // 'skip' | 'native' | 'codex' | 'kiro'
// taskReview, // 'skip' | 'native' | 'codex' | 'kiro' (who REVIEWS each built task)
// implReview, // 'skip' | 'native' | 'codex' | 'kiro' (final plan-vs-impl review)
// implReview, // 'skip' | 'native' | 'codex' | 'kiro' (impl review after all tasks)
// auditScriptPath, availableAgents, allowGeneralFallback }
// (auditScriptPath is optional — see the comment at its CFG read below.)
// Every role picks its own executor (writer + each reviewer INDEPENDENT — write codex, review kiro is
@@ -61,8 +62,9 @@ const MAX_FIX = 3 // bounded per-task engineer↔rev
// Every role chooses its own executor: 'native' (claude / the plan's specialist agent), 'codex', or
// 'kiro'. There is NO shared global harness — writing and reviewing can use DIFFERENT harnesses
// (e.g. write codex, review kiro). Review gates additionally allow 'skip' to save tokens.
const BUILD_HARNESS = ['native', 'codex', 'kiro'].includes(CFG.buildHarness) ? CFG.buildHarness : 'native' // who WRITES each task (+ fixes)
const PLAN_HARNESS = ['native', 'codex', 'kiro'].includes(CFG.planHarness) ? CFG.planHarness : 'native' // who WRITES the plan
const PLAN_REVIEW = ['skip', 'native', 'codex', 'kiro'].includes(CFG.planReview) ? CFG.planReview : 'native' // founder review of the plan
const BUILD_HARNESS = ['native', 'codex', 'kiro'].includes(CFG.buildHarness) ? CFG.buildHarness : 'native' // who WRITES each task (+ fixes)
const TASK_REVIEW = ['skip', 'native', 'codex', 'kiro'].includes(CFG.taskReview) ? CFG.taskReview : 'native' // review of each built task
const IMPL_REVIEW = ['skip', 'native', 'codex', 'kiro'].includes(CFG.implReview) ? CFG.implReview : 'native' // final plan-vs-implementation review
@@ -440,8 +442,12 @@ await cleanupWorktrees('preflight')
// the user decides whether to run a fix round (a Workflow can't AskUserQuestion mid-run, and an
// autonomous fix-loop is what produced the multi-hour grind). Impl review (step 12) is the
// plan-vs-implementation gate and is the last work the loop used to recurse on — now it just reports.
phase('Plan') // step 3
const plan = await agent(planBrief(PROMPT), { label: 'plan', phase: 'Plan', schema: PLAN })
phase('Plan') // step 3 — writer per PLAN_HARNESS
const planAgentType = PLAN_HARNESS === 'codex' ? 'codex:codex-rescue' : 'general-purpose'
const planPrompt = PLAN_HARNESS === 'kiro'
? `Use the Kiro CLI to produce this plan; if it is unavailable, do it yourself.\n${planBrief(PROMPT)}`
: planBrief(PROMPT)
const plan = await agent(planPrompt, { label: `plan:${PLAN_HARNESS}`, phase: 'Plan', schema: PLAN, agentType: planAgentType })
if (!plan || !plan.tasks || !plan.tasks.length) {
return { converged: false, ranReal: false, aborted: 'no tasks were planned — aborted before any build (verify args/PROMPT reached the script)', goLive: GO_LIVE }
}
@@ -495,7 +501,7 @@ return {
openRegister, // verified findings = the feedback to show the user
missingAgents: [...missingAgents], // specialist agent types the plan wanted that aren't installed here → skill notifies the user
// the review/build roles this run used (so the skill can report them honestly and caveat the verdict)
reviewConfig: { buildHarness: BUILD_HARNESS, planReview: PLAN_REVIEW, taskReview: TASK_REVIEW, implReview: IMPL_REVIEW },
reviewConfig: { planHarness: PLAN_HARNESS, planReview: PLAN_REVIEW, buildHarness: BUILD_HARNESS, taskReview: TASK_REVIEW, implReview: IMPL_REVIEW },
// TRUE when NOTHING checked the build: no per-task reviewer AND no impl review. converged then means
// "engineer validates passed", not "reviewed clean" — the skill must caveat this.
noReviewGate: TASK_REVIEW === 'skip' && IMPL_REVIEW === 'skip',