@aperant/framework 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/CHANGELOG.md +152 -0
  2. package/dist/cli/commands/ci-watch.mjs +49 -2
  3. package/dist/cli/commands/ci-watch.mjs.map +1 -1
  4. package/dist/cli/commands/commit.mjs +3 -3
  5. package/dist/cli/commands/commit.mjs.map +1 -1
  6. package/dist/cli/commands/event.mjs +16 -16
  7. package/dist/cli/commands/event.mjs.map +1 -1
  8. package/dist/cli/commands/merge-integrate.mjs +3 -3
  9. package/dist/cli/commands/merge-integrate.mjs.map +1 -1
  10. package/dist/cli/commands/produce.d.mts +9 -0
  11. package/dist/cli/commands/produce.d.mts.map +1 -0
  12. package/dist/cli/commands/produce.mjs +1345 -0
  13. package/dist/cli/commands/produce.mjs.map +1 -0
  14. package/dist/cli/commands/task.d.mts +16 -1
  15. package/dist/cli/commands/task.d.mts.map +1 -1
  16. package/dist/cli/commands/task.mjs +434 -266
  17. package/dist/cli/commands/task.mjs.map +1 -1
  18. package/dist/cli/coordination/auto-emit-artifact-ready.mjs +5 -5
  19. package/dist/cli/coordination/auto-emit-artifact-ready.mjs.map +1 -1
  20. package/dist/cli/coordination/event-schema.d.mts +5 -3
  21. package/dist/cli/coordination/event-schema.d.mts.map +1 -1
  22. package/dist/cli/coordination/event-schema.mjs +245 -21
  23. package/dist/cli/coordination/event-schema.mjs.map +1 -1
  24. package/dist/cli/coordination/store.d.mts +2 -2
  25. package/dist/cli/coordination/store.mjs +4 -4
  26. package/dist/cli/coordination/store.mjs.map +1 -1
  27. package/dist/cli/dispatch.d.mts.map +1 -1
  28. package/dist/cli/dispatch.mjs +2 -0
  29. package/dist/cli/dispatch.mjs.map +1 -1
  30. package/dist/cli/help.d.mts.map +1 -1
  31. package/dist/cli/help.mjs +30 -0
  32. package/dist/cli/help.mjs.map +1 -1
  33. package/dist/cli/install/legacy-paths.d.mts.map +1 -1
  34. package/dist/cli/install/legacy-paths.mjs +2 -0
  35. package/dist/cli/install/legacy-paths.mjs.map +1 -1
  36. package/dist/cli/produce/blind-probe.d.mts +85 -0
  37. package/dist/cli/produce/blind-probe.d.mts.map +1 -0
  38. package/dist/cli/produce/blind-probe.mjs +217 -0
  39. package/dist/cli/produce/blind-probe.mjs.map +1 -0
  40. package/dist/cli/produce/claim.d.mts +188 -0
  41. package/dist/cli/produce/claim.d.mts.map +1 -0
  42. package/dist/cli/produce/claim.mjs +518 -0
  43. package/dist/cli/produce/claim.mjs.map +1 -0
  44. package/dist/cli/produce/done-gate.d.mts +87 -0
  45. package/dist/cli/produce/done-gate.d.mts.map +1 -0
  46. package/dist/cli/produce/done-gate.mjs +200 -0
  47. package/dist/cli/produce/done-gate.mjs.map +1 -0
  48. package/dist/cli/produce/events.d.mts +77 -0
  49. package/dist/cli/produce/events.d.mts.map +1 -0
  50. package/dist/cli/produce/events.mjs +126 -0
  51. package/dist/cli/produce/events.mjs.map +1 -0
  52. package/dist/cli/produce/evidence-oracle.d.mts +63 -0
  53. package/dist/cli/produce/evidence-oracle.d.mts.map +1 -0
  54. package/dist/cli/produce/evidence-oracle.mjs +122 -0
  55. package/dist/cli/produce/evidence-oracle.mjs.map +1 -0
  56. package/dist/cli/produce/ledger.d.mts +140 -0
  57. package/dist/cli/produce/ledger.d.mts.map +1 -0
  58. package/dist/cli/produce/ledger.mjs +272 -0
  59. package/dist/cli/produce/ledger.mjs.map +1 -0
  60. package/dist/cli/produce/probe-family.d.mts +53 -0
  61. package/dist/cli/produce/probe-family.d.mts.map +1 -0
  62. package/dist/cli/produce/probe-family.mjs +160 -0
  63. package/dist/cli/produce/probe-family.mjs.map +1 -0
  64. package/dist/cli/produce/projection.d.mts +55 -0
  65. package/dist/cli/produce/projection.d.mts.map +1 -0
  66. package/dist/cli/produce/projection.mjs +97 -0
  67. package/dist/cli/produce/projection.mjs.map +1 -0
  68. package/dist/cli/produce/run-id.d.mts +42 -0
  69. package/dist/cli/produce/run-id.d.mts.map +1 -0
  70. package/dist/cli/produce/run-id.mjs +79 -0
  71. package/dist/cli/produce/run-id.mjs.map +1 -0
  72. package/dist/cli/produce/saga.d.mts +180 -0
  73. package/dist/cli/produce/saga.d.mts.map +1 -0
  74. package/dist/cli/produce/saga.mjs +290 -0
  75. package/dist/cli/produce/saga.mjs.map +1 -0
  76. package/dist/cli/produce/scheduler.d.mts +165 -0
  77. package/dist/cli/produce/scheduler.d.mts.map +1 -0
  78. package/dist/cli/produce/scheduler.mjs +399 -0
  79. package/dist/cli/produce/scheduler.mjs.map +1 -0
  80. package/dist/cli/produce/setpoint.d.mts +52 -0
  81. package/dist/cli/produce/setpoint.d.mts.map +1 -0
  82. package/dist/cli/produce/setpoint.mjs +113 -0
  83. package/dist/cli/produce/setpoint.mjs.map +1 -0
  84. package/dist/cli/produce/verification-ttl.d.mts +75 -0
  85. package/dist/cli/produce/verification-ttl.d.mts.map +1 -0
  86. package/dist/cli/produce/verification-ttl.mjs +169 -0
  87. package/dist/cli/produce/verification-ttl.mjs.map +1 -0
  88. package/dist/cli/roadmap/{conductor-view.d.mts → showrunner-view.d.mts} +3 -3
  89. package/dist/cli/roadmap/showrunner-view.d.mts.map +1 -0
  90. package/dist/cli/roadmap/{conductor-view.mjs → showrunner-view.mjs} +7 -7
  91. package/dist/cli/roadmap/showrunner-view.mjs.map +1 -0
  92. package/dist/plugin/.claude-plugin/plugin.json +2 -1
  93. package/dist/plugin/skills/apt/SKILL.md +112 -38
  94. package/dist/plugin/skills/apt-debug/SKILL.md +14 -24
  95. package/dist/plugin/skills/apt-fan-out/SKILL.md +4 -4
  96. package/dist/plugin/skills/apt-handoff/SKILL.md +1 -1
  97. package/dist/plugin/skills/apt-plan/SKILL.md +5 -5
  98. package/dist/plugin/skills/apt-plan/adapters/{conductor.md → showrunner.md} +16 -16
  99. package/dist/plugin/skills/apt-produce/SKILL.md +606 -0
  100. package/dist/plugin/skills/apt-quick/SKILL.md +14 -22
  101. package/dist/plugin/skills/apt-run/SKILL.md +126 -3
  102. package/dist/plugin/skills/apt-ship/SKILL.md +2 -0
  103. package/dist/plugin/skills/apt-spar/SKILL.md +5 -3
  104. package/dist/plugin/skills/apt-watch-ci/SKILL.md +4 -4
  105. package/package.json +4 -4
  106. package/prompts/{conductor-framework-context.md → showrunner-framework-context.md} +1 -1
  107. package/prompts/{conductor-status-check.md → showrunner-status-check.md} +1 -1
  108. package/prompts/{conductor-sub-agent.md → showrunner-sub-agent.md} +6 -6
  109. package/prompts/{conductor-system.md → showrunner-system.md} +8 -8
  110. package/skills/apt/SKILL.md +112 -38
  111. package/skills/apt-debug/SKILL.md +14 -24
  112. package/skills/apt-fan-out/SKILL.md +4 -4
  113. package/skills/apt-handoff/SKILL.md +1 -1
  114. package/skills/apt-plan/SKILL.md +5 -5
  115. package/skills/apt-plan/adapters/{conductor.md → showrunner.md} +16 -16
  116. package/skills/apt-produce/SKILL.md +606 -0
  117. package/skills/apt-quick/SKILL.md +14 -22
  118. package/skills/apt-run/SKILL.md +126 -3
  119. package/skills/apt-ship/SKILL.md +2 -0
  120. package/skills/apt-spar/SKILL.md +5 -3
  121. package/skills/apt-watch-ci/SKILL.md +4 -4
  122. package/src/cli/commands/ci-watch.mjs +51 -2
  123. package/src/cli/commands/commit.mjs +3 -3
  124. package/src/cli/commands/event.mjs +16 -16
  125. package/src/cli/commands/merge-integrate.mjs +3 -3
  126. package/src/cli/commands/produce.mjs +1466 -0
  127. package/src/cli/commands/task.mjs +482 -285
  128. package/src/cli/coordination/auto-emit-artifact-ready.mjs +5 -5
  129. package/src/cli/coordination/event-schema.d.ts +4 -2
  130. package/src/cli/coordination/event-schema.mjs +276 -21
  131. package/src/cli/coordination/store.mjs +4 -4
  132. package/src/cli/dispatch.mjs +2 -0
  133. package/src/cli/help.mjs +30 -0
  134. package/src/cli/install/legacy-paths.mjs +2 -0
  135. package/src/cli/produce/blind-probe.mjs +245 -0
  136. package/src/cli/produce/claim.mjs +543 -0
  137. package/src/cli/produce/done-gate.mjs +238 -0
  138. package/src/cli/produce/events.mjs +131 -0
  139. package/src/cli/produce/evidence-oracle.mjs +133 -0
  140. package/src/cli/produce/ledger.mjs +284 -0
  141. package/src/cli/produce/probe-family.mjs +168 -0
  142. package/src/cli/produce/projection.mjs +105 -0
  143. package/src/cli/produce/run-id.mjs +84 -0
  144. package/src/cli/produce/saga.mjs +303 -0
  145. package/src/cli/produce/scheduler.mjs +423 -0
  146. package/src/cli/produce/setpoint.mjs +122 -0
  147. package/src/cli/produce/verification-ttl.mjs +191 -0
  148. package/src/cli/roadmap/showrunner-view.d.ts +10 -0
  149. package/src/cli/roadmap/{conductor-view.mjs → showrunner-view.mjs} +6 -6
  150. package/dist/cli/roadmap/conductor-view.d.mts.map +0 -1
  151. package/dist/cli/roadmap/conductor-view.mjs.map +0 -1
  152. package/src/cli/roadmap/conductor-view.d.ts +0 -10
@@ -17,7 +17,7 @@ execution_modes:
17
17
  - plan-mode
18
18
  - plan-only
19
19
  allowed-tools: "Bash, Read, Write, Edit, Grep, Glob, Task"
20
- argument-hint: "apt:run [task description] [--skip-review] [--phase-mode auto|agent-team|sub-agents|sequential] [--spar-gates plan[,execute]]"
20
+ argument-hint: "apt:run [task description] [--skip-review] [--phase-mode auto|agent-team|sub-agents|sequential] [--spar-gates plan[,execute]] [--full]"
21
21
  gates:
22
22
  - constitution-read
23
23
  - constitution-coverage
@@ -29,6 +29,8 @@ config_keys:
29
29
  Run the full Aperant pipeline: plan a task, execute all subtasks, verify the implementation, and optionally review the code. This is the one-command experience — from task description to verified, reviewed code.
30
30
 
31
31
  As of C32 the STANDARD and DEEP auto pipelines **terminate on review** (`plan → execute → verify → review`). Pass `--skip-review` to stop after verify; for trivial work the QUICK track still skips planning entirely.
32
+
33
+ Pass `--full` to carry a SINGLE task all the way to **merged + green**: it extends the pipeline past review through **ship** (a PR that auto-merges to main on green — never a direct push) and **watch-CI** (arm the watcher with auto-merge so the change lands once CI passes). `--full` is a thin chain over the existing `/apt:ship` + `/apt:watch-ci` skills — it forces review ON and is hard-guarded by `autonomy.allow_yolo` plus a one-time confirm (§1a). A `/apt:run` invocation WITHOUT `--full` behaves exactly as today (terminates on review).
32
34
  </objective>
33
35
 
34
36
  <your_environment>
@@ -58,7 +60,7 @@ As of C32 the STANDARD and DEEP auto pipelines **terminate on review** (`plan
58
60
 
59
61
  1. Read `AGENTS.md` if it exists
60
62
  2. Parse task description from `$ARGUMENTS` (everything before flags)
61
- 3. Parse flags: `--skip-review`, `--dry-run`, `--phase-mode <mode>`, `--spar-gates <comma-list>`.
63
+ 3. Parse flags: `--skip-review`, `--dry-run`, `--phase-mode <mode>`, `--spar-gates <comma-list>`, `--full`.
62
64
  - `--spar-gates <plan|execute|plan,execute>` (FRAMEWORK-RFC-001) — comma-separated stage list to auto-fire `/apt:spar` after. Per-invocation override of `.aperant/config.local.json` `spar.enabled`. On QUICK track, print the verbatim hard-reject line and discard the flag (Fast Path Guarantee — CLAUDE.md):
63
65
 
64
66
  ```
@@ -71,6 +73,52 @@ As of C32 the STANDARD and DEEP auto pipelines **terminate on review** (`plan
71
73
  node packages/framework/bin/apt-tools.mjs state .
72
74
  ```
73
75
 
76
+ ## 1a. `--full` flag — surface + gates
77
+
78
+ This section runs ONLY when `--full` was parsed in §1. When `--full` is absent, skip this entire section and run the pipeline exactly as today (manual mode is byte-behavior-unchanged).
79
+
80
+ **Contradiction handling (resolve in THIS precedence order — the "discard" cases win first, so a `--full` that is discarded never triggers the conflict or autonomy gates):**
81
+
82
+ 0. **QUICK track wins first (Fast Path Guarantee).** If the task is QUICK track, discard `--full` with the Fast-Path line (item 4 below) and run the QUICK one-shot path unchanged — do NOT evaluate the `--skip-review` conflict (item 1) or the autonomy gate. On QUICK, `--full` is treated as never passed.
83
+
84
+ 1. **`--full` + `--skip-review` → hard reject.** `--full` requires review before auto-ship, so the two flags are contradictory. Do NOT silently let one win — print the verbatim line and exit:
85
+
86
+ ```
87
+ [apt:run] --full and --skip-review conflict (--full requires review before auto-ship). Pick one.
88
+ ```
89
+
90
+ 2. **`--full` IMPLIES review ON.** Treat `--skip-review` as never set for the rest of the run; §6 Review always executes.
91
+
92
+ 3. **`--full` + `--dry-run` → dry-run wins.** Run the plan stage only and report (the existing §3 dry-run exit), then stop. No execute, no ship — `--full` is discarded for this run.
93
+
94
+ 4. **QUICK track → discard `--full` with the Fast-Path line.** On QUICK track `--full` is hard-exempt (CLAUDE.md Fast Path Guarantee). Print the verbatim line and run the QUICK one-shot path unchanged:
95
+
96
+ ```
97
+ [apt:run] --full ignored for QUICK track (Fast Path Guarantee)
98
+ ```
99
+
100
+ `--full` composes normally with `--phase-mode` and `--spar-gates`.
101
+
102
+ **Autonomy gate (load-bearing safety valve, ID-03):**
103
+
104
+ Auto-ship + auto-merge is YOLO-class. Read `.aperant/config.json` for `autonomy.allow_yolo` (boolean) and the autonomy `level` (0–3).
105
+
106
+ 1. **`allow_yolo` hard guard.** If `autonomy.allow_yolo !== true`, STOP before ship with the verbatim line and leave the task at `reviewing` (fully shippable by hand):
107
+
108
+ ```
109
+ [apt:run] --full needs autonomy.allow_yolo=true (auto-ship + auto-merge to main). Enable via /apt:setup or drop --full.
110
+ ```
111
+
112
+ 2. **One-time confirm at autonomy < 3.** Before opening the auto-merging PR (just before §6.1 Ship below), emit ONE confirmation when autonomy `level < 3` AND `--yolo` was not also passed:
113
+
114
+ ```
115
+ [apt:run --full] About to open a PR that auto-merges to main once CI is green. Proceed? [y/N]
116
+ ```
117
+
118
+ At autonomy 3 OR when `--yolo` is passed, degrade to silent (mirrors `/apt:ship`'s autonomy-3 degrade). On `N` / empty, STOP after review with the standard `/apt:ship` hand-off hint — the task is left at `reviewing`, fully shippable by hand.
119
+
120
+ Note: the `allow_yolo` guard + the one-time confirm are evaluated up front here (parse-time gating) and the confirm is RE-SURFACED at the ship boundary (§6.1) so the user confirms immediately before the irreversible auto-merge arm. Review always runs first, and auto-merge always waits for green.
121
+
74
122
  ## 1b. Resolve Orchestration Mode
75
123
 
76
124
  Run reconcile to determine the effective orchestration strategy for this pipeline run. Pass the task's track via `--track <quick|standard|deep>` so per-track defaults from `.aperant/config.json:orchestration.per_track` apply (roundtable 2026-05-14 R7):
@@ -338,6 +386,58 @@ Skip on `spar.enabled === true` (no pre-ship gate exists in v2 — see spec §8
338
386
 
339
387
  **This is the task review, not the PR review.** It runs inline without sub-agents. For heavy multi-agent PR review, use `/apt:pr-review` separately.
340
388
 
389
+ ## 6.1. Stage 5 — Ship (apt:ship) — `--full` only
390
+
391
+ **Run this section ONLY when `--full` was parsed (§1a) AND review passed** — "review passed" means the §6 review `assessment` is `approve`; a `request-changes` assessment STOPS here (task left at `reviewing`, no ship — see the stop-condition table in §6.2). When `--full` is absent, skip §6.1 + §6.2 entirely and go straight to §7 (manual mode — terminates on review).
392
+
393
+ Pipeline order note: the user's phrasing was *"review, verify"* but `/apt:run` runs **verify (§5) → review (§6) → ship (§6.1)**. KEEP this order — verify gates review, and review consumes `qa_signoff.json`. Do NOT silently reorder. `--full` runs `plan → execute → verify → review → ship → watch-ci`.
394
+
395
+ **Pre-ship gate (re-surface the §1a confirm at the boundary):**
396
+
397
+ 1. Re-check `autonomy.allow_yolo === true` (already validated in §1a; re-read here so a mid-run config edit cannot slip an auto-merge past the guard). If false, STOP with the §1a `allow_yolo` line; leave the task at `reviewing`.
398
+ 2. Emit the §1a one-time confirm (`[apt:run --full] About to open a PR that auto-merges to main once CI is green. Proceed? [y/N]`) when autonomy `level < 3` and `--yolo` was not passed. At autonomy 3 / `--yolo`, degrade to silent. On `N` / empty, STOP after review with the standard `/apt:ship` hand-off hint; the task stays at `reviewing`.
399
+
400
+ **Ship (Option A — PR that auto-merges to main on green; NEVER a direct push/merge):**
401
+
402
+ Invoke `/apt:ship` inline. It runs its own hard-gate (verify-approved / review-clean / consistency / gitignore), opens the PR against the task's recorded `base_branch` (main for a task forked from main), and atomically flips `reviewing → shipped-pending-merge` via `task update --pr-url` — which also arms the post-ship watcher per `ci_watch.after_ship`. `--full` MUST NEVER `git push`/`git merge` directly to main (ID-02 Option B is rejected unconditionally): "ship to main" means **a PR that auto-merges to main on green**, not a force-push.
403
+
404
+ Capture the opened PR number `{N}` from the `/apt:ship` result for §6.2.
405
+
406
+ If `/apt:ship`'s hard-gate fails, or the branch is behind and the rebase conflicts with no `resolve_merge_conflicts`, STOP — no PR is opened and the task stays at `reviewing` (see the stop-condition table below).
407
+
408
+ ## 6.2. Stage 6 — Watch-CI arm (auto-merge-on-green) — `--full` only
409
+
410
+ After the PR opens, force auto-merge for THIS run regardless of the config default (`ci_watch.auto_merge_on_green` is `false` by default per the D-08 kill-criteria). `/apt:ship` already armed the watcher via `ci_watch.after_ship`; this call PATCHES that already-armed watch's auto-merge flag to `true` (it does NOT reimplement arming and is idempotent):
411
+
412
+ ```bash
413
+ node packages/framework/bin/apt-tools.mjs ci-watch start . --pr {N} --task-id {task-id} --host {cli} --auto-merge-on-green
414
+ ```
415
+
416
+ **Branch on host cron capability.** Run host-detect and read `host_capabilities.cron`:
417
+
418
+ ```bash
419
+ node packages/framework/bin/apt-tools.mjs host-detect .
420
+ ```
421
+
422
+ - **cron-capable host** (e.g. Claude Code, `cron: true`): the watcher is armed with auto-merge ON; register the recurring tick via the host's `CronCreate` (per `/apt:watch-ci` §3). Then **EXIT — do NOT loop** (respect `/apt:watch-ci`'s single-execution-per-invocation contract). The cron beat drives the watcher to merged + green unattended. Report: watcher armed, auto-merge ON, and the deadline.
423
+ - **non-cron host** (Codex / Gemini / OpenCode): truly-unattended watching is impossible. Arm the watch state + auto-merge (the `ci-watch start --auto-merge-on-green` above) but do NOT impersonate a scheduler — NEVER fake a `while` / `sleep` loop. Print the honest manual-tick instruction:
424
+
425
+ ```
426
+ [apt:run --full] PR opened + CI watcher state created (host has no cron). Advance manually: /apt:watch-ci --tick --pr {N}. Auto-merge-on-green is set; the merge fires on the first green tick you run.
427
+ ```
428
+
429
+ **Stop conditions (every gate is reused; each STOP leaves the task in its current lifecycle state and NEVER merges). `--full` adds NO new gate — it only chains the existing ones and surfaces the stop reason in §7:**
430
+
431
+ | Stop point | Resulting state |
432
+ |---|---|
433
+ | QA `rejected` after max iters (§5) | `verifying`; no ship |
434
+ | Review `request-changes` (§6) | `reviewing`; no ship |
435
+ | Ship hard-gate fail (verify-approved / review-clean / consistency / gitignore) | `reviewing`; no PR |
436
+ | Branch behind + rebase conflict (no `resolve_merge_conflicts`) | `reviewing`; no PR |
437
+ | `allow_yolo=false` or confirm `N` (§1a / §6.1) | `reviewing`; no PR |
438
+ | CI red after 5-attempt / 4h-wall (watcher) | `shipped-pending-merge`; PR comment, NOT merged |
439
+ | Merge conflict mid-watch (`diverged-bailed`) | `shipped-pending-merge`; PR comment, NOT merged |
440
+
341
441
  ## 7. Pipeline Summary
342
442
 
343
443
  Render the phase rail panel verbatim — branch glyphs `┌─ │ └─`, status glyphs `✓` (done) / `●` (active) / `○` (pending/skipped), inline metrics per row drawn from the artifacts written across §3–§6:
@@ -359,7 +459,18 @@ Substitute live values from the on-disk artifacts: `build-progress.json.complete
359
459
  **Always end with a "What's Next" recommendation:**
360
460
 
361
461
  ```
362
- {If review assessment is "approve" and QA approved:}
462
+ {If --full ran and the PR opened (cron host):}
463
+ -> Shipped. PR #{N} opened; CI watcher armed with auto-merge-on-green (deadline {deadline}).
464
+ The cron beat drives it to merged + green. /apt:close-task runs post-merge.
465
+
466
+ {If --full ran and the PR opened (non-cron host):}
467
+ -> Shipped. PR #{N} opened; watcher state created with auto-merge-on-green.
468
+ Advance manually: /apt:watch-ci --tick --pr {N} (merge fires on the first green tick).
469
+
470
+ {If --full was requested but a gate STOPPED before ship:}
471
+ -> {stop reason}. Task left at {lifecycle state}, not merged. {remediation per the stop-condition table}
472
+
473
+ {If review assessment is "approve" and QA approved (no --full):}
363
474
  -> Recommended: /apt:ship — create PR for this task
364
475
  Also: /apt:pr-review (deep multi-agent review) | manual review
365
476
 
@@ -388,5 +499,17 @@ atomic `reviewing → shipped-pending-merge` flip. `/apt:ship` then flips
388
499
  does not need to record or drain anything beyond ensuring each child-skill
389
500
  stage runs to its success-end.
390
501
 
502
+ **`--full` full lifecycle map:** `planning → executing → verifying → reviewing
503
+ → shipped-pending-merge → (CI green + merged) → completed`. The `reviewing →
504
+ shipped-pending-merge` flip is done atomically by ship's `task update --pr-url`
505
+ (§6.1). `shipped-pending-merge → completed` is done by `/apt:close-task`
506
+ post-merge — **`--full` does NOT auto-invoke `/apt:close-task`.** On cron hosts
507
+ the merge happens asynchronously AFTER `--full` has exited, so `--full` cannot
508
+ observe it; closeout is left to the existing path (the watcher's green branch
509
+ suggests `/apt:close-task`, and the user / passive sweeper runs it). Folding
510
+ close-task into `--full` would require it to become a recurring watcher —
511
+ explicitly rejected (it would duplicate the watcher and violate the
512
+ single-execution contract).
513
+
391
514
  </process>
392
515
  </output>
@@ -578,6 +578,8 @@ suggest_mode=$(jq -r '.pr_review.suggest_after_ship // "always"' .aperant/config
578
578
 
579
579
  ### 7.2 Post-ship /apt:watch-ci hook
580
580
 
581
+ > Cross-reference: `/apt:run --full` drives this skill's §6 PR creation + §7.2 watcher arming end-to-end (review → ship → auto-merge-on-green watch). When invoked from that chain, the watcher's auto-merge is force-enabled for the run via `apt-tools ci-watch start --auto-merge-on-green` (see `apt-run/SKILL.md` §6.1–§6.2); `/apt:ship` itself behaves identically whether invoked standalone or by `--full`.
582
+
581
583
  After Section 7.1's hint resolves (whether it ran the deep review or skipped), report or interactively arm the post-ship CI watcher. The hook is controlled by `ci_watch.after_ship` in `.aperant/config.json` (tri-state: `auto` | `ask` | `never`). The default depends on host capability — `auto` on cron-capable hosts (Claude Code, Pi), `never` elsewhere.
582
584
 
583
585
  **Skip entirely** when no PR URL was captured in Section 6 (library `npm publish`-only path — same skip rule as 7.1).
@@ -186,8 +186,8 @@ The table below shows the canonical command shape per (partner × rung); the act
186
186
  | Partner | Rung | Command | Notes |
187
187
  |---|---|---|---|
188
188
  | codex | mcp | tool call: `mcp__codex-mcp__codex({prompt, model})` where `model` is the `model` field returned by `apt-tools spar-resolve-partner --partner codex` (see §5a below). | **Demoted to LAST for codex** (see the codex walk-order note in §3) — attempt this rung only when the resolver returns `available: true`. 900000ms (15 min) timeout (configurable `apt-spar.mcp_timeout_ms`); on timeout fall through to plugin then CLI. When the resolver returns `available: false`, treat the MCP rung as UNAVAILABLE and fall through to plugin/CLI — never invent a default model (the MCP server silently substitutes a stale hardcoded default model id, which is exactly the bug we are fixing). |
189
- | codex | plugin | `node "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task "$(cat <<'APT_SPAR_PROMPT_EOF' ... APT_SPAR_PROMPT_EOF\n)"` | No `--model` flag — `codex-companion.mjs` invokes `codex exec` which inherits `~/.codex/config.toml` automatically. **NO `--write`. NO `--effort` override.** Per SPAR-04 — spar is conversation, not patching. |
190
- | codex | cli | `codex exec "$(cat <<'APT_SPAR_PROMPT_EOF' ... APT_SPAR_PROMPT_EOF\n)"` | Precedent: `apt-pr-review/SKILL.md:1084`. No `--model` flag — `codex exec` inherits `~/.codex/config.toml` automatically. Verify with `codex --help`. |
189
+ | codex | plugin | `node "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task "$(cat <<'APT_SPAR_PROMPT_EOF' ... APT_SPAR_PROMPT_EOF\n)" < /dev/null` | No `--model` flag — `codex-companion.mjs` invokes `codex exec` which inherits `~/.codex/config.toml` automatically. **NO `--write`. NO `--effort` override.** Per SPAR-04 — spar is conversation, not patching. The `< /dev/null` is load-bearing — the shim forwards to `codex exec`, which wedges on stdin EOF under a no-TTY subprocess (see the wedge note below). |
190
+ | codex | cli | `codex exec --sandbox read-only "$(cat <<'APT_SPAR_PROMPT_EOF' ... APT_SPAR_PROMPT_EOF\n)" < /dev/null` | Precedent: `apt-pr-review/SKILL.md:1084`. No `--model` flag — `codex exec` inherits `~/.codex/config.toml` automatically. The `< /dev/null` un-wedges the no-TTY stdin block and `--sandbox read-only` keeps the spar read-only (see the wedge note below). Verify with `codex --help`. |
191
191
  | claude | mcp | tool call: `mcp__claude-code-mcp__claude_code({prompt})` | Preferred. Same 900000ms (15 min) timeout + fallthrough rule. |
192
192
  | claude | plugin | n/a | No plugin shim exists for Claude. Skip this rung. |
193
193
  | claude | cli | `claude -p "$(cat <<'APT_SPAR_PROMPT_EOF' ... APT_SPAR_PROMPT_EOF\n)" --output-format text` | Symmetric. Claude has no `--write` equivalent — asymmetric flags are a smell. |
@@ -195,6 +195,8 @@ The table below shows the canonical command shape per (partner × rung); the act
195
195
  | gemini | plugin | n/a | No plugin shim exists for Gemini. Skip this rung. |
196
196
  | gemini | cli | `gemini "$(cat <<'APT_SPAR_PROMPT_EOF' ... APT_SPAR_PROMPT_EOF\n)"` | No `-m` flag — gemini-cli resolves model via `--model` > `GEMINI_MODEL` env > `~/.gemini/settings.json` > built-in default per `docs/cli/model-routing.md:47-58`. Drop the flag, let the cascade work; users override per-shell via `GEMINI_MODEL=...` or per-project via `settings.json`. |
197
197
 
198
+ **Codex stdin-wedge note (load-bearing).** `codex exec` reads the positional prompt and THEN blocks on stdin EOF under a no-TTY subprocess (the Bash tool), printing `Reading additional input from stdin…` and never returning. Redirecting `< /dev/null` un-wedges it (verified: returns in ~6s instead of hanging, exit 0, and prints the resolved `model:` it used). Both codex Bash rungs (plugin shim + raw CLI) carry `< /dev/null` because the shim forwards to `codex exec`. The `--sandbox read-only` flag on the raw-CLI rung keeps the spar read-only — aligning with the SPAR-04 "NO `--write`" rule; read-only still permits the partner's investigative Read/Grep.
199
+
198
200
  Set the Bash tool's `timeout` parameter to `--timeout-ms` (default 300000).
199
201
 
200
202
  **Timeout calibration.** The 5-min Bash-rung default and 15-min MCP-rung default are sized for heavy-research partner runs — modern partner CLIs commonly spend multiple minutes doing real Read/Grep/Bash investigation before producing a round response. The two defaults are intentionally asymmetric: the Bash rungs (plugin shim, raw CLI) are capped at the Claude Code Bash tool's 600000ms (10 min) host ceiling, while the MCP rung — a structured tool call rather than a Bash invocation — has no host ceiling and can carry the worst-case 15-min Claude Code partner. For tighter budgets (e.g. CI), pass `--timeout-ms` explicitly. The MCP-rung override is downward-only: if you observe consistent partner-CLI wedges (auth handshakes, hosted-API stalls, CI lanes wanting fast failure), set `apt-spar.mcp_timeout_ms` BELOW the 15-min default in `.aperant/config.json` (e.g. `120000` for a 2-min fast-fail budget) — raising it above 15 min is unnecessary because the default already covers the documented worst case. Future versions may introduce per-partner defaults.
@@ -224,7 +226,7 @@ Follow the envelope's `recommended_walk` / `prefer_self_resolving` for the rung
224
226
  node "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task "$(cat <<'APT_SPAR_PROMPT_EOF'
225
227
  <prompt body — opaque, no shell expansion>
226
228
  APT_SPAR_PROMPT_EOF
227
- )"
229
+ )" < /dev/null
228
230
 
229
231
  # Claude direction
230
232
  claude -p "$(cat <<'APT_SPAR_PROMPT_EOF'
@@ -37,7 +37,7 @@ The locked decisions backing every section are in `.aperant/context/notes/framew
37
37
  - **Working directory:** the task's worktree (or the project root if this is a non-worktree task).
38
38
  - **State files:** `.aperant/ci-watches/{pr}.json` (per-PR state, D-04); `.aperant/ci-watches/{pr}.lock` (per-PR atomic lock, D-05). Both ephemeral — they are NOT committed.
39
39
  - **Events:** every tick appends a `ci-watch.tick` event to `.aperant/events/{today}.jsonl`; `start` appends `ci-watch.armed`; the fix-and-push path appends `ci-watch.fix-pushed`; terminal actions append `ci-watch.stopped` with a `reason`.
40
- - **CLI surface:** `apt-tools ci-watch start|stop|status|tick --pr N`. The skill body shells out to those subcommands — DO NOT re-implement the classifier in your prompt; the cmd already does it.
40
+ - **CLI surface:** `apt-tools ci-watch start|stop|status|tick --pr N`. `start` also accepts `--auto-merge-on-green` (per-run override — forces `auto_merge_on_green: true` on the snapshot without persisting `ci_watch.auto_merge_on_green` into config; on an already-armed watch it PATCHES the snapshot rather than no-opping). `/apt:run --full` uses this flag to guarantee auto-merge for a single PR after ship's config-driven arm runs first. The skill body shells out to those subcommands — DO NOT re-implement the classifier in your prompt; the cmd already does it.
41
41
 
42
42
  ---
43
43
 
@@ -87,7 +87,7 @@ For the `--tick` mode, execute exactly the following sequence — once — insid
87
87
 
88
88
  When `action ∈ {green, merged, closed, attempts-cap, wall-cap, identical-log}`:
89
89
 
90
- - **green** — print "CI green for PR {N}." If `ci_watch.auto_merge_on_green` is `true` in `.aperant/config.json`, run `gh pr merge {N} --auto --squash` then suggest `/apt:close-task`.
90
+ - **green** — print "CI green for PR {N}." If `ci_watch.auto_merge_on_green` is `true` in `.aperant/config.json`, run `gh pr merge {N} --squash` then suggest `/apt:close-task`. Use a PLAIN merge here, NOT `--auto`: the classifier has already confirmed every check is `SUCCESS`/`SKIPPED` (`stop-matrix.mjs` `allGreen`) before this branch fires, so green is gated by the watcher, not by GitHub branch protection. `--auto` bought nothing on this path — in a repo WITHOUT required status checks `gh pr merge --auto` degrades to an immediate merge anyway — and dropping it removes the classify→merge ambiguity in unprotected repos.
91
91
  - **DO NOT pass `--delete-branch`** to `gh pr merge` from this auto-merge path — ever, unconditionally. The watcher's cwd is the task worktree, where `gh`'s `--delete-branch` post-merge cleanup tries to `git switch <base>` and fails because `<base>` is checked out in the primary worktree. The remote merge has already succeeded by then; local branch + worktree cleanup is `/apt:close-task`'s job via `apt-tools task close-merged` → `computeWorktreeCleanup` (see FRAMEWORK-BUG-019).
92
92
 
93
93
  Else print the exact D-08 text:
@@ -127,7 +127,7 @@ When `action === 'fix'` (or `diverged-rebased`/`diverged-bailed`):
127
127
 
128
128
  For `diverged-rebased`: the cmd already returned the verb; the orchestrator runs `git -C {worktree} fetch && git rebase origin/{base}` BEFORE the fix step. On conflict the action becomes `diverged-bailed`.
129
129
 
130
- For `diverged-bailed`: default behavior is to exit with a PR comment summarizing the conflict. Self-heal is **opt-in** via `ci_watch.resolve_merge_conflicts` (default false) in `.aperant/config.json`. When enabled, instead of bailing, hand off to **`/apt:merge-conflict-resolution`** (`--base origin/{base}`) for the worktree; it resolves the rebase conflict inline and re-probes mergeability. On success, continue to the §5 fix-and-push step (`git push origin {branch}`) and reschedule per §3 — the watcher keeps running. On its non-convergence STOP (it aborts the rebase to a clean tree first), fall back to the bail-with-PR-comment path. The resolved branch still goes through CI; the watcher never auto-merges except via the existing config-gated `gh pr merge --auto`.
130
+ For `diverged-bailed`: default behavior is to exit with a PR comment summarizing the conflict. Self-heal is **opt-in** via `ci_watch.resolve_merge_conflicts` (default false) in `.aperant/config.json`. When enabled, instead of bailing, hand off to **`/apt:merge-conflict-resolution`** (`--base origin/{base}`) for the worktree; it resolves the rebase conflict inline and re-probes mergeability. On success, continue to the §5 fix-and-push step (`git push origin {branch}`) and reschedule per §3 — the watcher keeps running. On its non-convergence STOP (it aborts the rebase to a clean tree first), fall back to the bail-with-PR-comment path. The resolved branch still goes through CI; the watcher never auto-merges except via the existing config-gated green-branch `gh pr merge --squash` (§4).
131
131
 
132
132
  ---
133
133
 
@@ -164,5 +164,5 @@ If you find yourself wanting to add "and then wait 5 minutes and run again," STO
164
164
  ## Notes for the orchestrator
165
165
 
166
166
  - All gh CLI calls run with the host's existing auth. The watcher introduces no new secret material (per task `dimensions_covered.token-encryption.crossed: false`).
167
- - `auto_merge_on_green` is snapshotted from `.aperant/config.json` at `start` time (state file's `auto_merge_on_green` field). Changing the config mid-watch does NOT retroactively affect armed watches — re-run `start` to pick up the new value.
167
+ - `auto_merge_on_green` is snapshotted from `.aperant/config.json` at `start` time (state file's `auto_merge_on_green` field). Changing the config mid-watch does NOT retroactively affect armed watches — re-run `start` to pick up the new value. The `--auto-merge-on-green` start flag forces it `true` for one run regardless of the config default (it patches an already-armed snapshot too); this is how `/apt:run --full` drives auto-merge without flipping the global config.
168
168
  - The fix-CLI shell-out is the cleanest abstraction we have for portability. It's NOT a sub-agent. On Claude Code that means another `claude` invocation; on Codex/Gemini/OpenCode/Pi, the equivalent binary. Detection lives in `apt-tools host-detect`'s `cli` field.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aperant/framework",
3
- "version": "0.17.0",
3
+ "version": "0.19.0",
4
4
  "description": "AI coding framework — composable skills for planning, executing, verifying, and reviewing code with any LLM provider. Works as Claude Code commands, Codex tasks, or programmatically.",
5
5
  "author": "Mikalsen AI <hello@mikalsen.ai>",
6
6
  "type": "module",
@@ -44,9 +44,9 @@
44
44
  "types": "./src/cli/coordination/event-schema.d.ts",
45
45
  "import": "./src/cli/coordination/event-schema.mjs"
46
46
  },
47
- "./roadmap/conductor-view": {
48
- "types": "./src/cli/roadmap/conductor-view.d.ts",
49
- "import": "./src/cli/roadmap/conductor-view.mjs"
47
+ "./roadmap/showrunner-view": {
48
+ "types": "./src/cli/roadmap/showrunner-view.d.ts",
49
+ "import": "./src/cli/roadmap/showrunner-view.mjs"
50
50
  },
51
51
  "./design/scan": {
52
52
  "import": "./src/cli/design/scan.mjs"
@@ -1,4 +1,4 @@
1
- <!-- Conductor Framework Context (auto-injected) -->
1
+ <!-- Showrunner Framework Context (auto-injected) -->
2
2
  # Aperant framework — slash-skills dispatchable in sub-terminals
3
3
 
4
4
  Dispatch via `sendToTerminal(terminalId, '/<skill> <args>\\r', ...)`.
@@ -1,4 +1,4 @@
1
- # Conductor — Tap-on-Shoulder Status Check Template
1
+ # Showrunner — Tap-on-Shoulder Status Check Template
2
2
 
3
3
  > NOTE: Phase 1 does not inject this prompt. It is the canonical template that Phase 3's tap-on-shoulder protocol will consume. The `{request_id}` substitution is the only dynamic value.
4
4
 
@@ -1,11 +1,11 @@
1
- # Conductor Sub-Agent — Reviewer System Prompt
1
+ # Showrunner Sub-Agent — Reviewer System Prompt
2
2
 
3
- You are a **conductor sub-agent reviewer**: a single-pass parallel reviewer spawned by the Conductor's sub-agent queue (via the sparring engine) to evaluate a fleet event and recommend whether the Conductor should log an intent.
3
+ You are a **showrunner sub-agent reviewer**: a single-pass parallel reviewer spawned by the Showrunner's sub-agent queue (via the sparring engine) to evaluate a fleet event and recommend whether the Showrunner should log an intent.
4
4
 
5
5
  ## Identity
6
6
 
7
7
  - You run on a **frontier model** (Anthropic Opus 4.7 1M, OpenAI GPT-5.4/5.5 frontier, Google Gemini latest frontier). Cheap-model fallback is forbidden.
8
- - You have **no project filesystem access**. You do not call Read, Glob, or Grep. You see only the event payload, the prior context the Conductor handed you, and the cross-check tool.
8
+ - You have **no project filesystem access**. You do not call Read, Glob, or Grep. You see only the event payload, the prior context the Showrunner handed you, and the cross-check tool.
9
9
  - You return a structured `findings` blob (severity / title / body / ref) — the same shape the sparring engine's lens reviewers return.
10
10
 
11
11
  ## Your one tool: `crossCheck`
@@ -20,7 +20,7 @@ If your evaluation depends on an agent's self-reported claim ("I finished the sp
20
20
 
21
21
  ## What to evaluate
22
22
 
23
- The Conductor hands you:
23
+ The Showrunner hands you:
24
24
 
25
25
  - The triggering event (e.g. `phase.changed{ to: 'idle' }`, `artifact.ready`, `budget.exceeded`).
26
26
  - The enrolled terminal's tier (A / B / C) and current autonomy setting.
@@ -29,8 +29,8 @@ The Conductor hands you:
29
29
  Recommend one of:
30
30
 
31
31
  1. **No-op** — the event is routine; no intent needed. (severity: `low`, title: `routine event`)
32
- 2. **Suggest** — the Conductor should log an intent suggesting a follow-up action. Include the action and reasoning. (severity: `medium`, title: `<suggested action>`)
33
- 3. **Escalate** — the event signals an error / blocked state / security concern. The Conductor should surface this prominently. (severity: `high`, title: `<concern>`)
32
+ 2. **Suggest** — the Showrunner should log an intent suggesting a follow-up action. Include the action and reasoning. (severity: `medium`, title: `<suggested action>`)
33
+ 3. **Escalate** — the event signals an error / blocked state / security concern. The Showrunner should surface this prominently. (severity: `high`, title: `<concern>`)
34
34
  4. **Cross-check failed** — you called `crossCheck` and the claim did not verify. (severity: `high`, title: `cross-check failed: <claim>`)
35
35
 
36
36
  ## Output shape
@@ -1,4 +1,4 @@
1
- # Conductor — Master Orchestrator
1
+ # Showrunner — Master Orchestrator
2
2
 
3
3
  You orchestrate up to 12 parallel agent terminals. You do not write code.
4
4
  You think a lot. You output little. You replace human babysitting.
@@ -41,7 +41,7 @@ For each task you take responsibility for, drive ALL phases yourself:
41
41
  - known architecture (use `getRoadmap`, `getTaskState`)
42
42
  4. Decide:
43
43
  - **Approve** → `sendToTerminal('/apt:execute\r')` to that terminal
44
- - **Realign** → `sendToTerminal('[Conductor realignment] <terse note>\r')`.
44
+ - **Realign** → `sendToTerminal('[Showrunner realignment] <terse note>\r')`.
45
45
  Wait for fresh `artifact.ready`. Re-review. Loop up to 3 attempts.
46
46
  After 3, escalate (respawn or surface to human).
47
47
  - **Reject** → `sendToTerminal('abort\r')`; spawn replacement if task
@@ -65,14 +65,14 @@ Run multiple terminals in parallel. Track each by terminal_id.
65
65
  You are the only thing standing between agents and silent failure. Catch:
66
66
 
67
67
  - **Idle**: terminal `phase.changed{to:'idle'}` with no fresh artifact
68
- for > 5 min after a /apt:* dispatch. Poll: `sendToTerminal('[conductor]
68
+ for > 5 min after a /apt:* dispatch. Poll: `sendToTerminal('[showrunner]
69
69
  status: phase? blocker?\r')`. If still idle after another 5 min,
70
70
  escalate (realign with explicit next step, or respawn).
71
71
  - **Slacking**: agent reports completion but artifacts don't exist on
72
72
  disk OR don't match the spec. Use `crossCheck` + `reviewPlan` to verify.
73
73
  Never trust self-reports.
74
74
  - **Looping**: same `phase.changed` toggling > 6 times in 10 min. Send
75
- `[Conductor realignment] You are looping. State the blocker and stop.\r`
75
+ `[Showrunner realignment] You are looping. State the blocker and stop.\r`
76
76
  - **Cost runaway**: a terminal's `budget.exceeded` event arrives. Halt
77
77
  that terminal with `sendToTerminal('exit\r')` after persisting state.
78
78
 
@@ -108,7 +108,7 @@ Write (use when needed, no human approval gating):
108
108
 
109
109
  ## Framework knowledge
110
110
 
111
- The auto-injected `conductor-framework-context` block at the very top of
111
+ The auto-injected `showrunner-framework-context` block at the very top of
112
112
  this system prompt lists every `/apt:*` skill you can dispatch into a
113
113
  sub-terminal. Consult it BEFORE deciding which skill to send.
114
114
 
@@ -144,13 +144,13 @@ enforces required fields per op (see `coordination/event-schema.mjs`).
144
144
  Locked op set:
145
145
  `terminal.enrolled` `terminal.unenrolled` `phase.changed` `awaiting-input`
146
146
  `input-rescinded` `artifact.ready` `heartbeat` `budget.exceeded`
147
- `conductor.intent` `conductor.cross_check` `conductor.realignment`
147
+ `showrunner.intent` `showrunner.cross_check` `showrunner.realignment`
148
148
 
149
149
  Reserved meanings:
150
150
  - `phase.changed.to` ∈ {busy, idle} ONLY (PTY state). NEVER use for plan
151
151
  completion.
152
152
  - `artifact.ready{kind:'plan'}` IS the plan-completion signal. Auto-
153
- emitted by `apt-tools commit` when planner runs under a Conductor PTY
153
+ emitted by `apt-tools commit` when planner runs under a Showrunner PTY
154
154
  (`APERANT_TERMINAL_ID` set).
155
155
 
156
156
  Every action you take appends an audit envelope. The framework writes
@@ -177,7 +177,7 @@ The chat thread is a control surface, not a journal.
177
177
 
178
178
  On first turn in a NEW thread (no prior assistant messages), one line:
179
179
 
180
- `Conductor ready. Goal?`
180
+ `Showrunner ready. Goal?`
181
181
 
182
182
  Nothing else. No greeting paragraph. No tool list. The user knows what
183
183
  you are.
@@ -17,7 +17,7 @@ execution_modes:
17
17
  - plan-mode
18
18
  - plan-only
19
19
  - research
20
- allowed-tools: "Bash, Read, Grep, Glob, Write, Edit, Task"
20
+ allowed-tools: "Bash, Read, Grep, Glob, Task"
21
21
  argument-hint: "[free-text task or /apt <skill> …]"
22
22
  gates: []
23
23
  ---
@@ -234,12 +234,19 @@ Resolve the track, then create a fresh task record before invoking the skill.
234
234
  - `plan` → `STANDARD`
235
235
  - everything else with `task_context: create-new` → `STANDARD`
236
236
 
237
- Then run:
237
+ Then run the deterministic allocator (NOT raw `task create`):
238
238
 
239
239
  ```bash
240
- node packages/framework/bin/apt-tools.mjs task create . --description "{slug}" --track {track} --autonomy {autonomy} [--scope {scope}]
240
+ node packages/framework/bin/apt-tools.mjs task ensure . --description "{slug}" --intent create-new --track {track} --autonomy {autonomy} [--scope {scope}]
241
241
  ```
242
242
 
243
+ `task ensure --intent create-new` is idempotent (re-running the same
244
+ input returns the SAME task + worktree, `reused: true`) and resolves the
245
+ effective autonomy from `config.autonomy.default` BEFORE provisioning the
246
+ worktree — so allocation is host-agnostic and never depends on this prose
247
+ being followed. The `allocation_intent` here is `create-new` because the
248
+ skill's `task_context` is `create-new` (the four-value taxonomy maps 1:1).
249
+
243
250
  **Security note:** Do NOT interpolate `{skill_args}` directly into `--description "..."`. `skill_args` is verbatim user input and can contain double-quote characters that break out of the argument boundary and inject extra flags (e.g. `--autonomy`, `--scope`). The task slug is sufficient as the description; `skill_args` is passed to the skill separately after the task record is created.
244
251
 
245
252
  (Use `--scope framework` only when the user is on a framework-scoped task —
@@ -300,29 +307,41 @@ The router emitted a `classify` envelope. This is the main routing path —
300
307
  all free-text input and every flag-override (--quick/--deep/--debug) lands
301
308
  here.
302
309
 
303
- ### Brainstorm hand-off (check FIRST, before picking a skill)
304
-
305
- **Before picking a skill from the envelope,** scan the user's input for
306
- signals that they want to *explore a vision* rather than *commit to a task*.
307
- If present, dispatch to `apt:discuss --brainstorm` and stop. Don't inline
308
- the exploration the brainstorm posture lives in its own skill with its
309
- own fresh context and its own artifact shape.
310
-
311
- Signals — any one triggers the hand-off:
312
- - Vision statements: *"here's what I want to build"*, *"my goal is..."*, *"the idea is..."*
313
- - Open invitations: *"let's think about"*, *"let's brainstorm"*, *"help me figure out"*, *"what's the best way..."*
314
- - Paragraph-shaped input describing an outcome or direction, not a single work item
315
- - Explicit "before we plan, let's explore / think / brainstorm..."
316
-
317
- How to hand off:
318
- ```
319
- [APT] Detected brainstorm intent routing to /apt:discuss --brainstorm
320
- ```
321
- Then invoke the `/apt:discuss --brainstorm` skill with the user's input and stop.
322
-
323
- **Task-shaped input (continue to Step 0):** concrete work item, specific
324
- deliverable, or existing task being continued. Examples: *"add OAuth login"*,
325
- *"fix the view-tracking bug"*, *"migrate reports to JSONB"*.
310
+ ### allocation_intent the single LLM bit (decide FIRST, before picking a skill)
311
+
312
+ The ONLY allocation judgment you make on the free-text path is a single
313
+ schema-bounded `allocation_intent {create-new | require-existing |
314
+ self-managed | none}` (the SAME four-value taxonomy as skill `task_context`).
315
+ **Fail-closed default is `none`** when in doubt, allocate nothing. There is
316
+ no separate prose-only brainstorm gate that can bypass allocation; the
317
+ brainstorm decision is just the `none` outcome of this one judgment.
318
+
319
+ Map the user's input to one bit:
320
+
321
+ - **`none`** vision / exploration / investigation / status / help. The user
322
+ wants to *explore a vision* or *ask a question*, not commit to a work item.
323
+ Allocate NOTHING (no task, no worktree) and dispatch to `apt:discuss
324
+ --brainstorm` (or the picked investigative skill). Signals — any one →
325
+ `none`:
326
+ - Vision statements: *"here's what I want to build"*, *"my goal is..."*, *"the idea is..."*
327
+ - Open invitations: *"let's think about"*, *"let's brainstorm"*, *"help me figure out"*, *"what's the best way..."*
328
+ - Paragraph-shaped input describing an outcome or direction, not a single work item
329
+ - Explicit "before we plan, let's explore / think / brainstorm..."
330
+
331
+ How to hand off:
332
+ ```
333
+ [APT] allocation_intent=none (brainstorm/investigation) — routing to /apt:discuss --brainstorm
334
+ ```
335
+ Then invoke `/apt:discuss --brainstorm` with the user's input and stop.
336
+
337
+ - **`self-managed`** — the picked skill owns its own task/worktree lifecycle
338
+ (e.g. `apt:run`, `apt:pr-review`). Allocate nothing here; let the skill do it.
339
+ - **`require-existing`** — the user is continuing an existing task. Do NOT mint;
340
+ resolve the active task (Step 2 uses `task ensure --intent require-existing`).
341
+ - **`create-new`** — concrete work item / specific deliverable that needs a
342
+ fresh task + worktree. Examples: *"add OAuth login"*, *"fix the view-tracking
343
+ bug"*, *"migrate reports to JSONB"*. Continue to Step 0; Step 2 provisions
344
+ deterministically via `task ensure --intent create-new`.
326
345
 
327
346
  ### Step 0a: Flag-override fast path (envelope.track is set)
328
347
 
@@ -332,6 +351,15 @@ carries `track`, `primary_skill`, `spawn_agent`, `agent`, and `options`.
332
351
  **Skip Step 0b and Step 0c — go straight to Step 1.** These were locked
333
352
  by the user typing `--quick` / `--deep` / `--debug`, not by the host LLM.
334
353
 
354
+ **allocation_intent (flag-override is deterministic — no LLM judgment):**
355
+ map `primary_skill` → `allocation_intent`:
356
+ - `quick` → `create-new`
357
+ - `debug` → `create-new`
358
+ - `plan` → `create-new` (STANDARD / DEEP)
359
+ - a skill whose `task_context` is `self-managed` (e.g. `run`) → `self-managed`
360
+
361
+ Step 2 forwards this bit to `task ensure --intent <bit>`.
362
+
335
363
  ### Step 0b: Classify the skill (envelope.skills[] inline pick)
336
364
 
337
365
  When `classification.source: "host-model-deferred"` (free-text path),
@@ -405,15 +433,31 @@ Map choice: full auto → `execution_mode = "auto"`, step by step → `"step"`,
405
433
 
406
434
  If `needs_autonomy_prompt` is false (user passed --yolo/--autonomous), skip this — use `execution_mode` from route result.
407
435
 
408
- ### Step 2: Register Task
436
+ ### Step 2: Register Task (deterministic allocation)
437
+
438
+ Forward the `allocation_intent` decided above (Step 0a flag-override map,
439
+ or the free-text bit from the allocation_intent section) to the
440
+ deterministic, idempotent allocator — NOT raw `task create`:
409
441
 
410
442
  ```bash
411
- node packages/framework/bin/apt-tools.mjs task create . --description "{task_description}" --track {track} --autonomy {autonomy}
443
+ node packages/framework/bin/apt-tools.mjs task ensure . --description "{task_description}" --intent {allocation_intent} --track {track} --autonomy {autonomy}
412
444
  ```
413
445
 
446
+ - `--intent create-new` provisions a fresh task + worktree, idempotent on
447
+ re-run (`reused: true` returns the SAME task/worktree — re-issuing `/apt`
448
+ never duplicates). Effective autonomy is resolved from
449
+ `config.autonomy.default` BEFORE the worktree hook, so a
450
+ `from_branch: current` base is not spuriously deferred.
451
+ - `--intent require-existing` resolves the active task WITHOUT minting
452
+ (returns `requires_input` on ambiguity — fall back to the
453
+ skill-passthrough resolution chain prompt).
454
+ - `--intent none` / `--intent self-managed` allocate nothing
455
+ (`allocated: false`) — you should already have dispatched per the
456
+ allocation_intent section above and not reached Step 2.
457
+
414
458
  Parse `task_id`, `task_dir`, and (if present) `worktree.worktree_path` / `worktree.branch` / `worktree.base_branch` from the result.
415
459
 
416
- **Task-level worktree isolation:** when `task_isolation.worktree_per_task` is enabled (check via `host_capabilities.worktrees` + `task_isolation` in the route result) and `task create` returns a `worktree` block, every subsequent Bash call AND every spawned agent in this pipeline MUST use `worktree_path` as its working directory. Print:
460
+ **Task-level worktree isolation:** when `task_isolation.worktree_per_task` is enabled (check via `host_capabilities.worktrees` + `task_isolation` in the route result) and `task ensure` returns a `worktree` block, every subsequent Bash call AND every spawned agent in this pipeline MUST use `worktree_path` as its working directory. Print:
417
461
 
418
462
  ```
419
463
  [APT] Working in isolated worktree: {worktree_path}
@@ -424,7 +468,7 @@ Important nuances:
424
468
  - `task_dir` is an **absolute path** under the main repo's `.aperant/tasks/{task-id}/`. All spec/plan/progress artifacts live there and are shared across worktrees.
425
469
  - `apt-tools` commands still receive the **project root** as `<project-dir>` — they coordinate state through the main repo's `.aperant/`. The worktree only affects *code editing* cwd.
426
470
  - When spawning an agent, set its `cwd` (or prefix its Bash calls with `cd {worktree_path} &&`) to the worktree for code reads/edits. Pass `worktree_path` in the agent's context so it knows where code work happens.
427
- - Planner artifact safety: do **not** spawn `apt-planner` with host-level worktree isolation that gives it a separate copied repo. The planner must write `spec.md` and `implementation_plan.json` to the absolute main-repo `task_dir` from `task create`; `.aperant/tasks/**` is gitignored, so artifacts written under a disposable worktree can be invisible to git and lost when that worktree is cleaned.
471
+ - Planner artifact safety: do **not** spawn `apt-planner` with host-level worktree isolation that gives it a separate copied repo. The planner must write `spec.md` and `implementation_plan.json` to the absolute main-repo `task_dir` from `task ensure`; `.aperant/tasks/**` is gitignored, so artifacts written under a disposable worktree can be invisible to git and lost when that worktree is cleaned.
428
472
  - If no `worktree` block is returned, proceed in the project root as before.
429
473
 
430
474
  ### Step 3: Spawn Planner Agent
@@ -482,14 +526,44 @@ tally output. Skip silently if tokens tally errors — never block the
482
526
  pipeline on telemetry.
483
527
 
484
528
  **If `spawn_agent` is false (QUICK or DEBUG):**
485
- Both QUICK and DEBUG resolve here (single-shot, no spawned phase agent). Invoke
486
- the picked skill (`apt:quick` for QUICK, `apt:debug` for DEBUG, per
487
- `primary_skill`) directly with `task_id`, `task_dir`, AND `worktree_path` in its
488
- skill context Step 2 already created the worktree + printed the banner for this
489
- track, so thread `worktree_path` the same way the `spawn_agent: true` branch
490
- threads it into the planner. No phase marker QUICK and DEBUG are both
491
- single-shot here. (If Step 2 returned no `worktree` block, pass `worktree_path` as
492
- "none" and the skill proceeds in the project root.)
529
+ Both QUICK and DEBUG resolve here (single-shot, no spawned phase agent).
530
+
531
+ **The router itself CANNOT edit code.** Its frontmatter `allowed-tools` is
532
+ `Bash, Read, Grep, Glob, Task` it has NO `Write` / `Edit` tool. This is the
533
+ load-bearing boundary (ID-05): the router can classify, allocate
534
+ (`task ensure`), and dispatch, but it can never edit a file on `main`.
535
+
536
+ So do NOT edit inline. **INVOKE the `apt:quick` / `apt:debug` SKILL** (per
537
+ `primary_skill`) AFTER Step 2's `task ensure --intent create-new` has
538
+ provisioned the worktree. Invoking the skill establishes that skill's OWN
539
+ `allowed-tools` scope (`apt-quick` / `apt-debug` both carry
540
+ `Read, Write, Edit, Bash, Grep, Glob`), which RE-GRANTS the edit affordance —
541
+ but only once a worktree exists, so editing can never land on `main` through
542
+ the router. Pass `task_id`, `task_dir`, AND `worktree_path` into the invoked
543
+ skill's context (thread `worktree_path` the same way the `spawn_agent: true`
544
+ branch threads it into the planner). This is a SKILL invocation, NOT a `Task`
545
+ sub-agent spawn — QUICK/DEBUG stay single-agent/single-context, so the Fast
546
+ Path Guarantee is preserved. No phase marker. (If Step 2 returned no `worktree`
547
+ block, pass `worktree_path` as "none" and the skill proceeds in the project
548
+ root.)
549
+
550
+ > **inline vs skill-scope (read this).** "Inline" here means the OLD behavior:
551
+ > the router editing within its own `/apt` turn under the router's allowlist.
552
+ > That is gone — the router has no edit tool. "Skill-scope" is the NEW
553
+ > behavior: a genuine `apt:quick` / `apt:debug` invocation whose own
554
+ > `allowed-tools` re-grants `Write, Edit` for the edit work, after the worktree
555
+ > exists.
556
+ >
557
+ > **Residual (host-runtime, not CI-provable — founder smoke-test gate).**
558
+ > Whether Claude Code treats a nested skill's `allowed-tools` as a REPLACEMENT
559
+ > (re-grants edit — design holds) or as an INTERSECTION/ceiling (the parent
560
+ > router allowlist caps the child — Fast Path breaks) is a host-implementation
561
+ > property that cannot be unit-tested from the framework. CI proves the
562
+ > frontmatter/prose structure; a founder in-app smoke-test is the residual gate.
563
+ > **Fallback if the smoke-test shows breakage:** revert ONLY the
564
+ > router-frontmatter line (re-add `Write, Edit`). The host-agnostic
565
+ > `task ensure` boundary (ID-02) still fixes the on-`main`-edit bug; the
566
+ > allowed-tools removal is hardening, not the fix.
493
567
 
494
568
  ### Step 4: Chain Pipeline (based on selected option)
495
569