okstra 0.202.0 → 0.205.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 (263) hide show
  1. package/README.md +7 -6
  2. package/dist/cli-registry.mjs +7 -7
  3. package/dist/cli-registry.mjs.map +1 -1
  4. package/dist/commands/lifecycle/install.mjs +50 -124
  5. package/dist/commands/lifecycle/install.mjs.map +1 -1
  6. package/dist/commands/memory/memory.mjs +41 -8
  7. package/dist/commands/memory/memory.mjs.map +1 -1
  8. package/dist/lib/install-assets.mjs +3 -0
  9. package/dist/lib/install-assets.mjs.map +1 -1
  10. package/dist/lib/runtime-manifest.mjs +2 -1
  11. package/dist/lib/runtime-manifest.mjs.map +1 -1
  12. package/dist/lib/types.d.mts +2 -1
  13. package/docs/architecture/storage-model.md +14 -11
  14. package/docs/architecture.md +26 -20
  15. package/docs/cli.md +15 -12
  16. package/docs/contributor-change-matrix.md +3 -2
  17. package/docs/performance-improvement-plan-v2.md +3 -9
  18. package/docs/project-structure-overview.md +39 -11
  19. package/docs/task-process/README.md +1 -1
  20. package/docs/task-process/common-flow.md +1 -1
  21. package/docs/task-process/final-verification.md +3 -1
  22. package/docs/task-process/implementation-option-selection.md +1 -1
  23. package/docs/task-process/implementation.md +1 -1
  24. package/docs/task-process/release-handoff.md +36 -39
  25. package/package.json +1 -2
  26. package/runtime/BUILD.json +2 -2
  27. package/runtime/agents/common.json +28 -0
  28. package/runtime/agents/operations/code-review.json +6 -0
  29. package/runtime/agents/operations/report-translation.json +6 -0
  30. package/runtime/agents/operations/schedule-verification.json +6 -0
  31. package/runtime/agents/roles/analyser.json +18 -0
  32. package/runtime/agents/roles/critic.json +18 -0
  33. package/runtime/agents/roles/designer.json +18 -0
  34. package/runtime/agents/roles/implementer.json +20 -0
  35. package/runtime/agents/roles/leader.json +20 -0
  36. package/runtime/agents/roles/planner.json +18 -0
  37. package/runtime/agents/roles/report-writer.json +19 -0
  38. package/runtime/agents/roles/translator.json +19 -0
  39. package/runtime/agents/roles/verifier.json +18 -0
  40. package/runtime/bin/lib/okstra/usage.sh +5 -5
  41. package/runtime/prompts/duties/acceptance-critic.json +32 -0
  42. package/runtime/prompts/duties/acceptance-verifier.json +32 -0
  43. package/runtime/prompts/duties/analysis-worker.json +32 -0
  44. package/runtime/prompts/duties/code-reviewer.json +32 -0
  45. package/runtime/prompts/duties/diagnosis-worker.json +32 -0
  46. package/runtime/prompts/duties/direction-selection-worker.json +32 -0
  47. package/runtime/prompts/duties/discovery-worker.json +32 -0
  48. package/runtime/prompts/duties/implementation-executor.json +32 -0
  49. package/runtime/prompts/duties/implementation-verifier.json +32 -0
  50. package/runtime/prompts/duties/lead.json +32 -0
  51. package/runtime/prompts/duties/planning-worker.json +36 -0
  52. package/runtime/prompts/duties/report-writer.json +32 -0
  53. package/runtime/prompts/duties/reverification-worker.json +32 -0
  54. package/runtime/prompts/duties/schedule-verifier.json +32 -0
  55. package/runtime/prompts/duties/scope-critic.json +32 -0
  56. package/runtime/prompts/duties/technical-verification-worker.json +32 -0
  57. package/runtime/prompts/duties/translator.json +32 -0
  58. package/runtime/prompts/launch.template.md +2 -1
  59. package/runtime/prompts/lead/adapters/cmux.md +1 -1
  60. package/runtime/prompts/lead/convergence.md +4 -4
  61. package/runtime/prompts/lead/okstra-lead-contract.md +115 -6
  62. package/runtime/prompts/lead/plan-body-verification.md +6 -6
  63. package/runtime/prompts/lead/report-writer.md +3 -3
  64. package/runtime/prompts/profiles/_common-contract.md +2 -2
  65. package/runtime/prompts/profiles/_implementation-diff-review.md +1 -1
  66. package/runtime/prompts/profiles/_implementation-executor.md +4 -1
  67. package/runtime/prompts/profiles/_implementation-self-check.md +1 -1
  68. package/runtime/prompts/profiles/_implementation-verifier.md +2 -2
  69. package/runtime/prompts/profiles/change-impact-analysis.json +31 -0
  70. package/runtime/prompts/profiles/change-impact-analysis.md +0 -20
  71. package/runtime/prompts/profiles/error-analysis.json +39 -0
  72. package/runtime/prompts/profiles/error-analysis.md +0 -25
  73. package/runtime/prompts/profiles/feature-analysis.json +31 -0
  74. package/runtime/prompts/profiles/feature-analysis.md +0 -20
  75. package/runtime/prompts/profiles/final-verification.json +30 -0
  76. package/runtime/prompts/profiles/final-verification.md +4 -23
  77. package/runtime/prompts/profiles/forbidden-actions.json +4 -3
  78. package/runtime/prompts/profiles/implementation-option-selection.json +31 -0
  79. package/runtime/prompts/profiles/implementation-option-selection.md +0 -20
  80. package/runtime/prompts/profiles/implementation-planning.json +40 -0
  81. package/runtime/prompts/profiles/implementation-planning.md +4 -29
  82. package/runtime/prompts/profiles/implementation.json +30 -0
  83. package/runtime/prompts/profiles/implementation.md +1 -20
  84. package/runtime/prompts/profiles/improvement-discovery.json +31 -0
  85. package/runtime/prompts/profiles/improvement-discovery.md +0 -20
  86. package/runtime/prompts/profiles/project-analysis.json +31 -0
  87. package/runtime/prompts/profiles/project-analysis.md +0 -20
  88. package/runtime/prompts/profiles/release-handoff.json +5 -0
  89. package/runtime/prompts/profiles/release-handoff.md +74 -74
  90. package/runtime/prompts/profiles/requirements-discovery.json +39 -0
  91. package/runtime/prompts/profiles/requirements-discovery.md +0 -25
  92. package/runtime/prompts/profiles/technical-verification.json +39 -0
  93. package/runtime/prompts/profiles/technical-verification.md +0 -25
  94. package/runtime/prompts/wizard/prompts.ko.json +14 -18
  95. package/runtime/python/okstra_ctl/adapters/hosts/antigravity/relay.md +1 -0
  96. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +3 -0
  97. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/manifest.json +1 -1
  98. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +4 -3
  99. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/worker-session.md +108 -0
  100. package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +1 -0
  101. package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +2 -0
  102. package/runtime/python/okstra_ctl/adapters/hosts/kimi/relay.md +2 -0
  103. package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +8 -1
  104. package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +8 -0
  105. package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +23 -6
  106. package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +6 -2
  107. package/runtime/python/okstra_ctl/agent/invocation.py +168 -113
  108. package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +120 -0
  109. package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +107 -2
  110. package/runtime/python/okstra_ctl/agent/prompt_cli/run_identity.py +0 -49
  111. package/runtime/python/okstra_ctl/analysis_packet.py +4 -1
  112. package/runtime/python/okstra_ctl/application/open_worker.py +6 -1
  113. package/runtime/python/okstra_ctl/assignment_resolver.py +16 -5
  114. package/runtime/python/okstra_ctl/cmux.py +69 -20
  115. package/runtime/python/okstra_ctl/code_review_target.py +16 -8
  116. package/runtime/python/okstra_ctl/conformance.py +43 -0
  117. package/runtime/python/okstra_ctl/consumers.py +23 -8
  118. package/runtime/python/okstra_ctl/container.py +31 -8
  119. package/runtime/python/okstra_ctl/context_cost.py +11 -15
  120. package/runtime/python/okstra_ctl/contract_refreeze.py +156 -0
  121. package/runtime/python/okstra_ctl/convergence_engine.py +38 -0
  122. package/runtime/python/okstra_ctl/convergence_provenance.py +7 -1
  123. package/runtime/python/okstra_ctl/design_prep.py +34 -1
  124. package/runtime/python/okstra_ctl/dispatch_core.py +53 -27
  125. package/runtime/python/okstra_ctl/domain/host.py +5 -0
  126. package/runtime/python/okstra_ctl/domain/worker_runtime.py +10 -0
  127. package/runtime/python/okstra_ctl/error_report.py +4 -3
  128. package/runtime/python/okstra_ctl/execution_manifest.py +71 -18
  129. package/runtime/python/okstra_ctl/handoff.py +384 -286
  130. package/runtime/python/okstra_ctl/handoff_verification.py +25 -6
  131. package/runtime/python/okstra_ctl/implementation_stage.py +9 -0
  132. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +113 -0
  133. package/runtime/python/okstra_ctl/lead_progress.py +1 -1
  134. package/runtime/python/okstra_ctl/legacy_model_selection.py +2 -2
  135. package/runtime/python/okstra_ctl/manager_cli.py +92 -4
  136. package/runtime/python/okstra_ctl/manager_launch.py +1 -1
  137. package/runtime/python/okstra_ctl/manager_paths.py +14 -3
  138. package/runtime/python/okstra_ctl/manager_store.py +210 -3
  139. package/runtime/python/okstra_ctl/manager_sync.py +4 -1
  140. package/runtime/python/okstra_ctl/manager_view.py +2 -1
  141. package/runtime/python/okstra_ctl/model_discovery.py +30 -0
  142. package/runtime/python/okstra_ctl/model_io/lines.py +14 -1
  143. package/runtime/python/okstra_ctl/model_io/renderers.py +4 -3
  144. package/runtime/python/okstra_ctl/models.py +1 -1
  145. package/runtime/python/okstra_ctl/next_phase.py +16 -6
  146. package/runtime/python/okstra_ctl/operation_invocation.py +86 -0
  147. package/runtime/python/okstra_ctl/option_comparison.py +168 -0
  148. package/runtime/python/okstra_ctl/path_hints.py +9 -0
  149. package/runtime/python/okstra_ctl/paths.py +3 -0
  150. package/runtime/python/okstra_ctl/profile_show.py +42 -1
  151. package/runtime/python/okstra_ctl/registry/host_discovery.py +20 -12
  152. package/runtime/python/okstra_ctl/registry/host_registry.py +11 -0
  153. package/runtime/python/okstra_ctl/render.py +79 -0
  154. package/runtime/python/okstra_ctl/report_contract.py +1 -1
  155. package/runtime/python/okstra_ctl/report_html/view_models/release_handoff.py +21 -3
  156. package/runtime/python/okstra_ctl/report_synthesis_packet.py +177 -17
  157. package/runtime/python/okstra_ctl/report_translation.py +2 -1
  158. package/runtime/python/okstra_ctl/report_translation_dispatch.py +69 -9
  159. package/runtime/python/okstra_ctl/role_requirements.py +142 -129
  160. package/runtime/python/okstra_ctl/rollup.py +3 -1
  161. package/runtime/python/okstra_ctl/run.py +76 -29
  162. package/runtime/python/okstra_ctl/schedule_semantics.py +17 -6
  163. package/runtime/python/okstra_ctl/stage_fix_carry.py +23 -4
  164. package/runtime/python/okstra_ctl/stage_integrate.py +178 -18
  165. package/runtime/python/okstra_ctl/stage_map.py +16 -2
  166. package/runtime/python/okstra_ctl/stage_targets.py +209 -43
  167. package/runtime/python/okstra_ctl/team.py +22 -13
  168. package/runtime/python/okstra_ctl/time_report.py +2 -1
  169. package/runtime/python/okstra_ctl/usage_report.py +3 -1
  170. package/runtime/python/okstra_ctl/wizard/confirmation.py +3 -9
  171. package/runtime/python/okstra_ctl/wizard/ids.py +1 -1
  172. package/runtime/python/okstra_ctl/wizard/registry.py +1 -1
  173. package/runtime/python/okstra_ctl/wizard/state.py +3 -5
  174. package/runtime/python/okstra_ctl/wizard/steps_plan.py +12 -21
  175. package/runtime/python/okstra_ctl/worker_prompt_contract.py +5 -1
  176. package/runtime/python/okstra_ctl/worker_prompt_headers.py +35 -7
  177. package/runtime/python/okstra_ctl/worker_prompt_policy.py +66 -48
  178. package/runtime/python/okstra_ctl/workflow.py +1 -1
  179. package/runtime/python/okstra_ctl/worktree/__init__.py +3 -1
  180. package/runtime/python/okstra_ctl/worktree/naming.py +9 -0
  181. package/runtime/python/okstra_ctl/worktree_registry.py +38 -9
  182. package/runtime/python/okstra_token_usage/pricing.py +6 -4
  183. package/runtime/schemas/agent-common-v1.schema.json +34 -0
  184. package/runtime/schemas/agent-duty-v1.schema.json +38 -0
  185. package/runtime/schemas/agent-operation-v1.schema.json +11 -0
  186. package/runtime/schemas/agent-profile-v1.schema.json +46 -0
  187. package/runtime/schemas/agent-role-v1.schema.json +29 -0
  188. package/runtime/schemas/final-report-v2.0.schema.json +118 -97
  189. package/runtime/schemas/final-report-v3.0.schema.json +118 -97
  190. package/runtime/skills/okstra-brief-gen/SKILL.md +84 -4
  191. package/runtime/skills/okstra-chat/SKILL.md +2 -2
  192. package/runtime/skills/okstra-code-review/SKILL.md +23 -9
  193. package/runtime/skills/okstra-container-build/SKILL.md +10 -10
  194. package/runtime/skills/okstra-inspect/SKILL.md +1 -1
  195. package/runtime/skills/okstra-inspect/facets/cost.md +1 -1
  196. package/runtime/skills/okstra-inspect/facets/error-zip.md +9 -9
  197. package/runtime/skills/okstra-inspect/facets/errors.md +16 -16
  198. package/runtime/skills/okstra-inspect/facets/logs.md +7 -7
  199. package/runtime/skills/okstra-inspect/facets/recap.md +2 -2
  200. package/runtime/skills/okstra-inspect/facets/report.md +1 -1
  201. package/runtime/skills/okstra-inspect/facets/status.md +4 -3
  202. package/runtime/skills/okstra-inspect/facets/time.md +11 -10
  203. package/runtime/skills/okstra-manager/SKILL.md +18 -2
  204. package/runtime/skills/okstra-pr-gen/SKILL.md +6 -5
  205. package/runtime/skills/okstra-rollup/SKILL.md +5 -5
  206. package/runtime/skills/okstra-run/SKILL.md +31 -12
  207. package/runtime/skills/okstra-schedule-gen/SKILL.md +19 -14
  208. package/runtime/skills/okstra-setup/SKILL.md +12 -10
  209. package/runtime/skills/okstra-setup/references/project-config.md +7 -6
  210. package/runtime/skills/okstra-usage/SKILL.md +1 -1
  211. package/runtime/skills/okstra-user-response/SKILL.md +1 -1
  212. package/runtime/templates/manager/view.template.html +1 -0
  213. package/runtime/templates/report-writer-prompt-preamble.md +8 -0
  214. package/runtime/templates/reports/brief.template.md +14 -4
  215. package/runtime/templates/reports/html/i18n/en.json +5 -4
  216. package/runtime/templates/reports/html/i18n/ko.json +5 -4
  217. package/runtime/templates/reports/html/tasks/release-handoff.template.html +8 -5
  218. package/runtime/templates/reports/i18n/en.json +1 -1
  219. package/runtime/templates/reports/md/tasks/release-handoff.template.md +1 -1
  220. package/runtime/templates/reports/release-handoff-input.template.md +6 -4
  221. package/runtime/templates/translator-prompt-preamble.md +36 -0
  222. package/runtime/validators/checks/validate-assets-01.py +7 -8
  223. package/runtime/validators/validate-brief.py +70 -0
  224. package/runtime/validators/validate-implementation-plan-stages.py +2 -1
  225. package/runtime/validators/validate-run.py +72 -15
  226. package/runtime/validators/validate-schedule.py +9 -0
  227. package/docs/for-ai/README.md +0 -68
  228. package/docs/for-ai/skills/okstra-brief-gen.md +0 -262
  229. package/docs/for-ai/skills/okstra-chat.md +0 -34
  230. package/docs/for-ai/skills/okstra-code-review.md +0 -57
  231. package/docs/for-ai/skills/okstra-container-build.md +0 -129
  232. package/docs/for-ai/skills/okstra-inspect.md +0 -262
  233. package/docs/for-ai/skills/okstra-manager.md +0 -86
  234. package/docs/for-ai/skills/okstra-memory.md +0 -126
  235. package/docs/for-ai/skills/okstra-pr-gen.md +0 -49
  236. package/docs/for-ai/skills/okstra-rollup.md +0 -114
  237. package/docs/for-ai/skills/okstra-run.md +0 -250
  238. package/docs/for-ai/skills/okstra-schedule-gen.md +0 -240
  239. package/docs/for-ai/skills/okstra-setup.md +0 -167
  240. package/docs/for-ai/skills/okstra-usage.md +0 -29
  241. package/docs/for-ai/skills/okstra-user-response.md +0 -72
  242. package/runtime/agents/workers/claude-worker.md +0 -128
  243. package/runtime/agents/workers/report-writer-worker.md +0 -37
  244. package/runtime/agents/workers/translator-worker.md +0 -63
  245. package/runtime/prompts/duties/acceptance-critic.md +0 -44
  246. package/runtime/prompts/duties/acceptance-verifier.md +0 -44
  247. package/runtime/prompts/duties/analysis-worker.md +0 -44
  248. package/runtime/prompts/duties/code-reviewer.md +0 -44
  249. package/runtime/prompts/duties/common.md +0 -39
  250. package/runtime/prompts/duties/diagnosis-worker.md +0 -44
  251. package/runtime/prompts/duties/direction-selection-worker.md +0 -44
  252. package/runtime/prompts/duties/discovery-worker.md +0 -44
  253. package/runtime/prompts/duties/implementation-executor.md +0 -44
  254. package/runtime/prompts/duties/implementation-verifier.md +0 -44
  255. package/runtime/prompts/duties/lead.md +0 -44
  256. package/runtime/prompts/duties/planning-worker.md +0 -52
  257. package/runtime/prompts/duties/report-writer.md +0 -44
  258. package/runtime/prompts/duties/reverification-worker.md +0 -44
  259. package/runtime/prompts/duties/schedule-verifier.md +0 -44
  260. package/runtime/prompts/duties/scope-critic.md +0 -44
  261. package/runtime/prompts/duties/technical-verification-worker.md +0 -44
  262. package/runtime/prompts/duties/translator.md +0 -44
  263. package/runtime/python/okstra_ctl/pane_title.py +0 -154
@@ -1,115 +1,115 @@
1
1
  # Release Handoff Profile
2
2
 
3
- ```yaml
4
- roles: []
5
- ```
6
-
7
- - Record the handoff shape in `releaseHandoff.handoffScope`: `mode` always, plus `stages`
8
- and `collectorBranch` in stage-group mode. The report is the only place a reader learns
9
- which stages shipped — the collector branch name does not say.
10
- - Purpose: take an `accepted` final-verification verdict for an already-committed implementation branch and turn it into a delivered push and/or pull request, with explicit user selection at every mutating step. Two modes: **whole-task** (default — the verified task branch becomes one PR) and **stage-group** (a user-selected subset of verified stages is merged into a collector branch and becomes one PR).
3
+ - Record the handoff shape in `releaseHandoff.handoffScope`: the `stages` this run delivered and
4
+ the `releaseBase` the user picked. The report is the only place a reader learns which stages
5
+ shipped and in what order their PRs must be merged — the branch names do not say.
6
+ - Purpose: take a release-ready single-stage final-verification verdict for each already-committed implementation stage and turn it into a delivered push and/or pull request, with explicit user selection at every mutating step. **One stage is one PR.** The PR head is that stage's stack branch (`<prefix>-<task-id>-s<N>`); nothing is squashed, rebased, or collected into a bundle branch.
11
7
  - **Execution model: single-lead, no worker dispatch.** This phase is a thin orchestrator over `git` / `gh`; it does NOT dispatch teammates, does NOT dispatch analysis or drafter sub-agents, and does NOT run convergence. The host-native Okstra lead performs every step inline (drafting PR text, asking the user, running git / gh, writing the final report) — see "Lead-only contract" below.
12
8
  - Worker roster: none — this profile intentionally has no `- Required workers:` block; the run is executed entirely by the Okstra lead.
13
9
  - Lead-only contract (replaces the shared team contract for this phase):
14
- - The host-native Okstra lead is the sole agent for this run. No worker dispatch, no teammates, no parallel sub-agents, no convergence loop.
15
- - The lead drafts the PR title and PR body **inline** by reading the run brief, the cited final-verification report, `git log --oneline <base>..HEAD`, and `git diff <base>..HEAD --stat`. No drafter worker is dispatched.
10
+ - The host-native Okstra lead is the sole agent for this run. No worker dispatch, no teammates, no parallel sub-agents, no convergence loop. Do NOT run `okstra convergence` in any form: prepare already wrote this run's convergence state as "not run — fewer than two analysers", which is the record report assembly reads. **Enforced:** `okstra_ctl.render._initialize_lead_only_convergence` writes it when the run has no analysers, and leaves an existing state alone.
11
+ - The lead drafts each stage's PR title and PR body **inline** by reading the run brief, that stage's cited final-verification report, `git log --oneline <stage base>..<stage head>`, and `git diff <stage base>..<stage head> --stat`. No drafter worker is dispatched.
16
12
  - The lead authors the final-report file directly (no `Report writer worker` dispatch). The report still conforms to the standard `templates/reports/final-report-v2.template.md` structure, including the `## 5.6 Release Handoff Deliverables` section.
17
13
  - The shared anti-escalation rule from the common contract still applies: do not start any other lifecycle phase from inside this run.
18
14
  - The shared "authority & permissions assumption" rule from the common contract still applies: assume the user holds every permission needed; do not block on hypothetical approvals.
19
15
  - Pre-handoff entry gate (mandatory — refuse to start if any item fails):
20
- - the run's input document (`release-handoff-input.md`, generated by prepare in place of a task brief — briefs belong to entry phases only) carries a `## Source Verification Report` section with `Mode`, `Stages`, and one table row per cited `final-verification` final-report. The run context exposes the same selection as `HANDOFF_MODE` (`whole-task` | `stage-group`) and `HANDOFF_STAGES` (csv, empty for whole-task).
21
- - **whole-task mode** (`HANDOFF_MODE=whole-task`): the lead opens the cited report and confirms its `verificationScope` is `whole-task` and its verdict is release-ready — `Verdict Token` exactly `accepted`, or exactly `conditional-accept` with every **Conditional Acceptance Condition** row declaring `blocksReleaseHandoff: false`. The rule lives in `okstra_ctl.release_gate.release_handoff_allowed`; the lead reads the report against it and does not invent a third case.
22
- - **stage-group mode** (`HANDOFF_MODE=stage-group`): the lead opens each cited single-stage report and confirms every verdict is release-ready by the same rule as whole-task mode. Eligibility was already enforced at prepare time (`okstra_ctl.handoff.compute_eligibility`) and is re-enforced by `okstra handoff assemble` — the lead never hand-computes it.
23
- - if the verdict is `blocked`, a `conditional-accept` carrying any condition that blocks release, or any other token (including ambiguous phrasing like "looks good"), the run MUST end immediately with status `blocked` and a routing recommendation back to `error-analysis` or `implementation-planning`. Do NOT prompt the user; Do NOT run any git command.
24
- - when the cited verdict is `conditional-accept`, the lead MUST carry every **Conditional Acceptance Condition** row into the PR body under a heading naming them as unresolved — id, condition, and the evidence the reviewer would need. These conditions are the whole reason a non-`accepted` verdict was allowed through; a PR body that drops them turns a recorded condition into a silent one.
16
+ - the run's input document (`release-handoff-input.md`, generated by prepare in place of a task brief — briefs belong to entry phases only) carries a `## Source Verification Report` section with `Stages` and one table row per cited `final-verification` final-report. The run context exposes the same selection as `HANDOFF_STAGES` (csv, never empty — prepare defaults it to every eligible stage).
17
+ - the lead opens each cited single-stage report and confirms its `verificationScope` is `single-stage` and its verdict is release-ready — `Verdict Token` exactly `accepted`, or exactly `conditional-accept` with every **Conditional Acceptance Condition** row declaring `blocksReleaseHandoff: false`. The rule lives in `okstra_ctl.release_gate.release_handoff_allowed`; the lead reads the reports against it and does not invent a third case. Eligibility was already enforced at prepare time (`okstra_ctl.handoff.compute_eligibility`) and is re-enforced by `okstra handoff pr-plan` — the lead never hand-computes it.
18
+ - if any cited verdict is `blocked`, a `conditional-accept` carrying a condition that blocks release, or any other token (including ambiguous phrasing like "looks good"), the run MUST end immediately with status `blocked` and a routing recommendation back to `error-analysis` or `implementation-planning`. Do NOT prompt the user; Do NOT run any git command.
19
+ - when a cited verdict is `conditional-accept`, the lead MUST carry that stage's **Conditional Acceptance Condition** rows into **that stage's** PR body under a heading naming them as unresolved — id, condition, and the evidence the reviewer would need. These conditions are the whole reason a non-`accepted` verdict was allowed through; a PR body that drops them turns a recorded condition into a silent one.
25
20
  - the lead MUST capture `git status --short` and confirm the working tree is clean. Dirty state aborts the run; release-handoff packages the commits produced by `implementation`, it does not stage or commit changes.
26
- - the lead MUST capture `git rev-parse --abbrev-ref HEAD` and record it as the **feature branch**. If the current branch is itself `main`, `master`, `prod`, `preprod`, `staging`, or `dev`, the run MUST end immediately — release-handoff never operates on a base branch.
27
- - the lead MUST confirm `git log --oneline <base>..HEAD` contains at least one implementation commit. If it is empty, the run MUST end with status `blocked` and route back to `implementation`.
28
- - In whole-task mode, compare `git rev-parse <handoff-branch>` with `finalVerification.sourceImplementationReport.capturedHeadSha` in the cited latest verification report, both at entry and immediately before pushing. Any mismatch stops delivery and requires final-verification again. In stage-group mode, run `okstra handoff eligible` again before pushing and confirm each selected stage is still eligible; assemble already checks the recorded verified commits. Record the compared commits and eligibility output in Executed Commands. These pre-push comparisons are lead instructions; the automated entry and assembly checks are enforced by `okstra_ctl.handoff_verification` and the handoff tests.
21
+ - the lead MUST capture `git rev-parse --abbrev-ref HEAD` and record it as the run's current branch. It is evidence, not a PR head: every PR head comes from `okstra handoff pr-plan`. If the current branch is `main`, `master`, `prod`, `preprod`, `staging`, or `dev`, record it and do not push it — release-handoff never pushes a base branch.
22
+ - before pushing, run `okstra handoff pr-plan` again if anything mutated since entry, and confirm each selected stage is still present in its output. `pr-plan` re-checks eligibility and each stage's recorded verified commit. Record the pr-plan output in Executed Commands. These pre-push comparisons are lead instructions; the automated entry checks are enforced by `okstra_ctl.handoff_verification` and the handoff tests.
23
+ - **Commit history is preserved — structurally, not as a preference.** These PRs are a stack: stage N's PR base is stage N-1's branch. Squash-merging a PR in the stack replaces its commits with a new one, so the next PR's base points at commits that no longer exist on the target branch and its diff re-shows the predecessor's changes. Therefore: okstra never rebases, squashes, amends, or cherry-picks a stage branch, and the merge policy — **merge commit or rebase-merge, never squash, and merge in ascending stage order** — is stated to the operator in the final report's `Stage PR Plan` and next-action narrative. It does NOT go into the PR body: the reviewer of one stage's PR is not the person merging the stack, and the block was noise they deleted by hand (2026-09-24, dev-10860 PRs #1487-#1490).
29
24
  - User interaction protocol (Okstra lead — performed in order, using the selected runtime adapter's interactive prompt):
30
25
  1. **Action selection** — present three choices and capture exactly one:
31
- - `local checkout` — bring a verified branch into the MAIN worktree for local testing (no push, no PR). Two targets: the whole-task branch (whole-task mode only), or a single stage's stack branch (`--stage N`, available in both modes since stage branches survive verification). See step 1c. When `HANDOFF_MODE` is `stage-group`, offer only the per-stage target.
32
- - `push + PR` — push the feature branch, then open or reuse a pull request.
26
+ - `local checkout` — bring one stage's branch into the MAIN worktree for local testing (no push, no PR). See step 1c.
27
+ - `push + PR` — push the selected stage branches and open or reuse one pull request per stage.
33
28
  - `skip` — cancel delivery actions for now: record that release-handoff was intentionally skipped and end the run without any git command.
34
29
  If the user picks `skip`, route directly to the final-report self-review pass.
35
- 1c. **Local checkout execution** (only when the user picked `local checkout`) — first ask which target — when `HANDOFF_MODE` is `whole-task`, offer both the whole-task branch and one stage's stack branch; when it is `stage-group`, offer only the per-stage target — listing the selectable stage numbers (from the approved plan's Stage Map, since the run input document carries no Stage Map). Then confirm with the user that okstra will remove the corresponding okstra worktree (when it still exists) and `git checkout <branch>` in the MAIN worktree, and that the base branch is never modified. On confirmation run:
36
- `okstra handoff local-checkout --project-root <project root> --project-id <id> --task-group <g> --task-id <t>` — append `--stage <N>` for the per-stage target.
37
- Exit 1 means a precondition failed (MAIN worktree dirty, registry entry missing, another run of this task still `in-progress`, the target branch already deleted, or checkout failed): show the error verbatim and re-ask the action selection. On success the okstra worktree for that target no longer exists — if the lead's cwd was inside it, EVERY subsequent step (final-report authoring included) MUST use absolute paths or run from the MAIN worktree. Then route to the final-report self-review pass.
38
- - **stage-group mode step order** (overrides the default Q1→Q3 sequence): after Q1 picks `push + PR`, run (1) base-branch selection first — identical to Q2 below, because the dependency-closure check needs `origin/<base>`; (2) G2 stage confirmation (step 1g); (3) assemble (step 2g); then Q2b and Q3 as usual, with the collector branch as the PR head.
39
- 1g. **G2 — stage confirmation**: the stage selection already happened before the run (wizard `handoff_stage_pick`, or the CLI `--stages` flag) and is fixed in `HANDOFF_STAGES`. Display it as a one-line confirmation (`PR target stage: <csv> — proceeding`) and proceed; do NOT re-ask the multi-select. Only if `HANDOFF_MODE` is `stage-group` but `HANDOFF_STAGES` is empty (defensive, should not happen) run `okstra handoff eligible --plan-run-root <plan-run-root> --approved-plan <approved plan path>` and ask the user to pick from the eligible stages.
40
- 2g. **assemble**: run `okstra handoff assemble --plan-run-root <...> --approved-plan <...> --project-root <project root> --project-id <id> --task-group <g> --task-id <t> --work-category <c> --stages <csv> --base <chosen-base>`. Exit 2 means a stage-vs-stage merge conflict: show the `conflicts` paths and stop (route: reshape the group or resolve manually). Exit 1 means an eligibility/closure violation: show the error verbatim and re-ask G2. On success the returned `branch` is the PR head branch for every subsequent step.
41
- 2. **PR base branch** (only when the user picked `push + PR`) — present four options and capture exactly one:
30
+ 1c. **Local checkout execution** (only when the user picked `local checkout`) — first ask which stage, listing the stage numbers from `HANDOFF_STAGES` (a stage outside that list is still checkoutable; offer the approved plan's Stage Map numbers when the user asks for one, since the run input document carries no Stage Map). Then confirm with the user that okstra will remove that stage's okstra worktree (when it still exists) and `git checkout <branch>` in the MAIN worktree, and that no base branch is modified. On confirmation run:
31
+ `okstra handoff local-checkout --project-root <project root> --project-id <id> --task-group <g> --task-id <t> --stage <N>`
32
+ Exit 1 means a precondition failed (MAIN worktree dirty, registry entry missing, a run still holds the stage, the target branch already deleted, or checkout failed): show the error verbatim and re-ask the action selection. On success the okstra worktree for that stage no longer exists — if the lead's cwd was inside it, EVERY subsequent step (final-report authoring included) MUST use absolute paths or run from the MAIN worktree. Then route to the final-report self-review pass.
33
+ 2. **Release base branch** (only when the user picked `push + PR`) — present these options and capture exactly one:
42
34
  - `preprod`
43
35
  - `main`
44
36
  - `direct input` (free-form branch name; lead validates the name exists on origin via `git ls-remote --heads origin <name>` and re-asks on failure)
45
- The chosen base MUST NOT equal the feature branch. If it does, re-ask.
46
- 2b. **Pre-merge conflict probe** (only when the user picked `push + PR`) — before the push/PR step, the lead MUST refresh the base ref and probe for merge conflicts against it:
47
- - run `git fetch origin <chosen-base>` (read-only on the local working tree).
48
- - run `git merge-tree --write-tree <handoff-branch> origin/<chosen-base>`. Use the verified task branch in whole-task mode or the branch returned by assemble in stage-group mode, regardless of the current directory's HEAD. Exit 0 means clean. Exit 1 with a result-tree object ID on the first stdout line means a merge conflict. A missing result tree, or any other exit code, is an execution error: stop and report it, without offering permission to proceed as if it were a content conflict. An invalid ref can also return exit 1, so the exit code alone is insufficient.
49
- - If no conflict is detected, proceed silently to Q3 (do NOT add a confirmation prompt — keep the happy path frictionless).
50
- - If a conflict IS detected, present the conflicting paths (parsed from the `merge-tree` output) and capture exactly one:
51
- - `proceed anyway` — continue to Q3; the PR will be opened with conflicts and the final report MUST flag this in `Merge Conflict Probe`.
52
- - `change base branch` — return to Q2 and re-ask the base selection.
37
+ This is the release base for the run, not necessarily each PR's base: a stage that sits on another stage targets that stage's branch. The chosen base MUST NOT be one of the stage branches. If it is, re-ask.
38
+ 2p. **PR plan** (only when the user picked `push + PR`) — run
39
+ `okstra handoff pr-plan --plan-run-root <...> --approved-plan <...> --project-root <project root> --project-id <id> --task-group <g> --task-id <t> --work-category <c> --stages <HANDOFF_STAGES> --base <chosen-base>`.
40
+ It returns one row per stage with `head_branch`, `head_commit`, `base_kind` (`release-base` | `stage` | `merge-base`), `base_branch` and `base_commit`. Exit 2 means the predecessors of a multi-dependency stage conflict with each other: show the `conflicts` paths and stop (route: resolve manually, then retry). Exit 1 means an eligibility or dependency violation — most often a stage whose predecessor is neither in this run nor already PR'd nor merged into the release base: show the error verbatim and re-ask the action selection. On success these rows are authoritative for every subsequent step; the lead does not recompute a base by hand.
41
+ A `merge-base` row means `pr-plan` created a branch merging that stage's predecessors. That branch is a PR base only — it is never a PR head — and it MUST be pushed before the PR that targets it.
42
+ The output also carries `push_plan` and `warnings`. `push_plan` is every branch the PRs sit on, already in push order (each `merge-base` first, then the stage heads in ascending order), with the `commit` it must reach and an `action` of `create` (origin does not have it), `fast-forward` (origin is behind) or `up-to-date` (origin already has that commit — do not push it). GitHub resolves a PR's head and base by name on origin, so this list, not the local branch set, is what makes the stack real. A `warnings` row means `pr-plan` fast-forwarded a local branch to origin because origin was ahead: the commits origin adds are outside what this run verified. Quote every `warnings` row verbatim in Executed Commands and say so in the branch/PR explanation — the user is deciding whether to release commits this run did not verify. `pr-plan` refuses outright when a branch moved outside okstra or diverged from origin, since only a force push could deliver it.
43
+ 2b. **Pre-merge conflict probe** (only when the user picked `push + PR`) — before pushing, for each planned stage in ascending order:
44
+ - run `git fetch origin <chosen-base>` once (read-only on the local working tree).
45
+ - run `git merge-tree --write-tree <head_branch> <base_branch>` for that stage, using the `base_branch` from the pr-plan row (`origin/<chosen-base>` for a `release-base` row). Exit 0 means clean. Exit 1 with a result-tree object ID on the first stdout line means a merge conflict. A missing result tree, or any other exit code, is an execution error: stop and report it, without offering permission to proceed as if it were a content conflict. An invalid ref can also return exit 1, so the exit code alone is insufficient.
46
+ - If no stage conflicts, proceed silently to Q3 (do NOT add a confirmation prompt — keep the happy path frictionless).
47
+ - If any stage conflicts, present the conflicting stage(s) and their paths (parsed from the `merge-tree` output) and capture exactly one:
48
+ - `proceed anyway` — continue to Q3; the affected PRs will be opened with conflicts and the final report MUST flag this in `Merge Conflict Probe`.
49
+ - `change base branch` — return to Q2 and re-ask the base selection (and re-run pr-plan).
53
50
  - `cancel` — end the run without push or PR; record the cancellation in the final report.
54
51
  - The probe is read-only. It MUST NOT run `git merge`, `git rebase`, `git pull`, or any command that mutates the working tree or local refs.
55
- 3. **PR title + PR body confirmation** — show the lead's inline draft verbatim, together with the filled-body self-check result (either `body self-check: clean` or the list of hits with their lines, per the drafting rules below), and capture one of:
56
- - `use as-is` — proceed with the drafted text.
57
- - `edit then proceed` — accept inline edits from the user, then proceed with the edited text.
52
+ 3. **PR title + PR body confirmation** — draft every selected stage's title and body first, then show all of them verbatim in ONE question, each with the filled-body self-check result (either `body self-check: clean` or the list of hits with their lines, per the drafting rules below), and capture one of:
53
+ - `use as-is` — proceed with the drafted text for every stage.
54
+ - `edit then proceed` — accept inline edits from the user (the user may edit any subset), then proceed with the edited text.
58
55
  - `cancel` — end the run without executing push or PR commands; record the cancellation in the final report.
59
- - Inline drafting rules (Okstra lead):
60
- - read the run brief, the cited final-verification report, `git log --oneline <base>..HEAD`, and `git diff <base>..HEAD --stat` to ground the drafted text in actual committed changes. In stage-group mode the draft is grounded on `git log <implementation_base_commit>..<collector HEAD>` / `git diff <implementation_base_commit>..<collector HEAD> --stat`, with source material = each selected stage's implementation report + its single-stage verification report.
56
+ - Inline drafting rules (Okstra lead) — applied once per stage:
57
+ - read the run brief, that stage's cited final-verification report and its implementation report, `git log --oneline <base_commit>..<head_commit>`, and `git diff <base_commit>..<head_commit> --stat` (both from the stage's pr-plan row) to ground the drafted text in the commits that PR actually carries. A stacked PR's diff is that stage alone — do not describe a predecessor's work in it.
61
58
  - **PR body template** — the run context exposes `PR_TEMPLATE_PATH` and `PR_TEMPLATE_SOURCE`. The path MUST be an okstra-owned project artifact under `<PROJECT_ROOT>/.okstra/**`, or a file the prepare step already materialised into this run's artifact directory. If the resolved file is missing or outside that boundary at draft time, abort with a clear error — do NOT invent a structure. Otherwise the lead MUST `Read` it verbatim, strip HTML comments, and fill in the placeholders, treating the template (never a hard-coded section list) as the source of truth for the structure.
62
- - produce **two artifacts** before showing them to the user:
63
- 1. **PR title** — by default the subject of the most recent implementation commit, or a concise Conventional Commits-style summary of the committed range.
64
- 2. **PR body** — markdown filled from `PR_TEMPLATE_PATH`. The user-confirmation step's diff (Q3 `edit then proceed`) is computed against the filled template, not against the raw template file.
65
- - **Filled-body self-check (runs on the drafted body, before Q3 shows it).** "Fill in the placeholders" is only observable if someone checks that they were filled, so scan the drafted body for these and carry the result into Q3: a residual HTML comment or template marker (`<!-- … -->`, `_Describe your changes…_`, a bare `TODO` / `FIXME` the diff did not introduce), an unchecked `- [ ]` box with no inline N/A justification, a section heading whose body is empty, and a whole body short enough to carry no substance. Each hit is reported to the user with its line — never silently left in, and never auto-filled with invented content. The user remains free to accept it; the point is that they see it before choosing `use as-is`.
59
+ - produce **two artifacts per stage** before showing them to the user:
60
+ 1. **PR title** — by default the subject of that stage's most recent implementation commit, or a concise Conventional Commits-style summary of the stage's committed range.
61
+ 2. **PR body** — markdown filled from `PR_TEMPLATE_PATH`, and nothing else. Do NOT append a stack plan, a stage checklist, a sentence about where this PR stops in the stack, or a merge-policy line: the stack's shape and merge rule belong to the final report and the closeout, not to a reviewer's PR. The user-confirmation step's diff (Q3 `edit then proceed`) is computed against the filled template, not against the raw template file.
62
+ - **Filled-body self-check (runs on each drafted body, before Q3 shows it).** "Fill in the placeholders" is only observable if someone checks that they were filled, so scan the drafted body for these and carry the result into Q3: a residual HTML comment or template marker (`<!-- … -->`, `_Describe your changes…_`, a bare `TODO` / `FIXME` the diff did not introduce), an unchecked `- [ ]` box with no inline N/A justification, a section heading whose body is empty, and a whole body short enough to carry no substance. Each hit is reported to the user with its line — never silently left in, and never auto-filled with invented content. The user remains free to accept it; the point is that they see it before choosing `use as-is`.
66
63
  - Allowed actions during the run (Okstra lead only):
67
64
  - read-only inspection: `git status`, `git status --short`, `git diff`, `git log`, `git rev-parse`, `git ls-remote --heads origin <name>`, `gh pr list --head <branch>`, `gh pr view <url>`.
68
- - merge-conflict probe (only when the user picked `push + PR`): `git fetch origin <chosen-base>` and the exact `git merge-tree` command from step 2b. Both preserve the working tree and branch tips.
69
- - feature-branch push (only when the user picked `push + PR`): `git push -u origin <current-branch>`. The pushed ref MUST be the feature branch — never the chosen base branch. (stage-group mode: the collector branch returned by assemble)
70
- - PR creation (only when the user picked `push + PR` AND no PR with the same head already exists on origin): `gh pr create --base <chosen-base> --head <current-branch> --title "<title>" --body "<body>"`. The title and body are the user-confirmed PR draft.
71
- - PR reuse: if `gh pr list --head <branch> --state open --json url --jq '.[0].url'` returns a URL, treat that PR as already existing — record the URL in the final report and SKIP `gh pr create`.
72
- - after `gh pr create` succeeds (or an existing PR is reused), the lead MUST run `okstra handoff record-pr --plan-run-root <...> --stages <csv> --branch <head branch> --url <pr url>` and quote the command + exit code in the final report. This applies to BOTH modes — whole-task runs record `--stages` as the full Stage Map list — so duplicate-PR prevention for both modes converges on a single consumers ledger.
73
- - stage-group helpers: `okstra handoff eligible`, `okstra handoff assemble`, `okstra handoff record-pr`. The assemble step is the ONLY path that may create commits (merge commits on the collector branch) in this phase.
65
+ - merge-conflict probe (only when the user picked `push + PR`): `git fetch origin <chosen-base>` and the exact `git merge-tree` commands from step 2b. Both preserve the working tree and branch tips.
66
+ - branch push (only when the user picked `push + PR`): `git push -u origin <branch>` for each `push_plan` row whose `action` is `create` or `fast-forward`, in the order `push_plan` lists them (each `merge-base` branch before the PR that targets it, then the stage heads in ascending order). Skip an `up-to-date` row — origin already holds that commit. The pushed ref MUST come from a `push_plan` row — never the release base branch, and never a ref that list does not name.
67
+ - PR creation, one per stage (only when the user picked `push + PR` AND no PR with the same head already exists on origin): `gh pr create --base <row base_branch> --head <row head_branch> --title "<title>" --body "<body>"`. The title and body are the user-confirmed PR draft for that stage. Open them in ascending stage order so each base branch already exists on origin.
68
+ - PR reuse: if `gh pr list --head <branch> --state open --json url --jq '.[0].url'` returns a URL, treat that PR as already existing — record the URL in the final report and SKIP `gh pr create` for that stage.
69
+ - after each `gh pr create` succeeds (or an existing PR is reused), the lead MUST run `okstra handoff record-pr --plan-run-root <...> --stage <N> --branch <head branch> --base <base branch> --url <pr url>` and quote the command + exit code in the final report. One record-pr call per stage — the consumers ledger is what stops the same stage being PR'd twice.
70
+ - stage helpers: `okstra handoff eligible`, `okstra handoff pr-plan`, `okstra handoff record-pr`, `okstra handoff local-checkout`. `pr-plan` is the ONLY path that may create commits in this phase (merge commits on a `merge-base` branch, and only for a multi-dependency stage).
74
71
  - Forbidden actions (any occurrence → terminal status `contract-violated`):
75
72
  {{PHASE_FORBIDDEN_ACTIONS}}
76
73
  - Required deliverable shape (final report, in addition to the standard sections):
77
- - **Source Verification Report**: relative path of the originating `final-verification` final-report file plus the literal quoted `Verdict Token` row, and — when that token is `conditional-accept` — every Conditional Acceptance Condition row quoted with its `blocksReleaseHandoff` value.
78
- - **Feature Branch & Working-Tree State**: branch name from `git rev-parse --abbrev-ref HEAD`, output of `git status --short` at run start.
74
+ - **Source Verification Reports**: one row per selected stage — relative path of that stage's originating `final-verification` final-report plus the literal quoted `Verdict Token` row, and — when that token is `conditional-accept` — every Conditional Acceptance Condition row quoted with its `blocksReleaseHandoff` value.
75
+ - **Feature Branch & Working-Tree State**: the branch from `git rev-parse --abbrev-ref HEAD` at run start and the output of `git status --short` at run start.
76
+ - **Stage PR Plan**: the pr-plan rows — stage, head branch, head commit, base kind, base branch, base commit — plus, for every `merge-base` row, which predecessor stages it merges and the merge commits it created. This is the table a reader uses to merge the stack in the right order, so it carries the merge rule with it: merge in ascending stage order, with a merge commit or rebase-merge, never a squash.
77
+ - **User narrative `nextAction`**: when this run opened or reused any PR, it names the merge order (ascending stage number) and the merge rule (merge commit or rebase-merge, never squash), and says why — squashing one PR in the stack invalidates the next PR's base. This is where the operator reads the rule; the PR bodies do not carry it.
79
78
  - **User Selections**: a block recording each prompt and the user's verbatim answer.
80
79
  - Q1 action: `local checkout` | `push + PR` | `skip`.
81
- - Q1c checkout target (only when Q1 is `local checkout`): `whole-task branch` | `stage <N> stack branch`, plus the `--stage <N>` value this answer produced (or `no --stage` for the whole-task branch). Record it in the `User Selections` row `H1c` (`userSelections.h1c`); omit the row entirely when Q1 was not `local checkout`.
82
- - Q2 PR base (if applicable): the chosen branch and how it was selected (menu pick vs free-form input).
83
- - Q2b merge-conflict probe (if applicable): `not-run` | `clean` (no conflict, no prompt shown) | `proceed anyway` | `change base branch` | `cancel`. Record it in both the `User Selections` row `H2b` and the `Merge Conflict Probe` deliverable. When a conflict was detected, list the conflicting paths.
80
+ - Q1c checkout stage (only when Q1 is `local checkout`): the `--stage <N>` value this answer produced. Record it in the `User Selections` row `H1c` (`userSelections.h1c`); omit the row entirely when Q1 was not `local checkout`.
81
+ - Q2 release base (if applicable): the chosen branch and how it was selected (menu pick vs free-form input).
82
+ - Q2b merge-conflict probe (if applicable): `not-run` | `clean` (no conflict, no prompt shown) | `proceed anyway` | `change base branch` | `cancel`. Record it in both the `User Selections` row `H2b` and the `Merge Conflict Probe` deliverable. When a conflict was detected, list the conflicting stages and paths.
84
83
  - Q3 title/body: `use as-is` | `edit then proceed` (with a diff between the lead's draft and the final text) | `cancel`.
85
84
  - **Executed Commands**: every git / gh command the lead actually ran, with its exit code and a one-line stdout/stderr summary. Read-only inspection commands MAY be summarised; mutating commands MUST be listed verbatim.
86
- - **Commit List**: each existing implementation commit in `git log <base>..HEAD`, with short/full SHA, subject line, and touched files. Release-handoff MUST NOT create new commits.
85
+ - **Commit List**: per stage, each implementation commit in `git log <base_commit>..<head_commit>`, with short/full SHA, subject line, and touched files. Release-handoff MUST NOT create new commits other than a `merge-base` branch's merge commits.
87
86
  - **Merge Conflict Probe**: one of
88
87
  - `- Not run (user picked local checkout or skip).`
89
- - `- Clean — no conflicts against <base> at <origin/base SHA>.`
90
- - `- Conflicts detected against <base> at <origin/base SHA>; user chose <proceed anyway | change base branch | cancel>. Conflicting paths: <list>.`
91
- - **Pull Request Outcome**: one of
88
+ - `- Clean — every stage merges cleanly into its PR base at <origin/base SHA>.`
89
+ - `- Conflicts detected for stage(s) <list> against <base> at <origin/base SHA>; user chose <proceed anyway | change base branch | cancel>. Conflicting paths: <list>.`
90
+ - **Pull Request Outcomes**: one row per selected stage, each one of
92
91
  - `- No PR action requested.` (user picked `local checkout` or `skip`)
93
- - `- PR created: <url>` with title and base branch
94
- - `- PR reused: <url>` when an existing PR was found via `gh pr list`
95
- - `- PR creation skipped: <reason>` for any user-driven cancellation
92
+ - `- Stage <N> PR created: <url>` with title and base branch
93
+ - `- Stage <N> PR reused: <url>` when an existing PR was found via `gh pr list`
94
+ - `- Stage <N> PR creation skipped: <reason>` for any user-driven cancellation
96
95
  - **Local Checkout Outcome**: one of
97
96
  - `- Not run (user picked push + PR or skip).`
98
- - `- Checked out <branch> into <main worktree path>; okstra worktree <path> removed. Next: to run a local test and then open a PR, re-enter release-handoff via okstra-run → push + PR.`
99
- - `- Checked out <branch> into <main worktree path>; no okstra worktree removed (already torn down — the branch survived). Next: to run a local test and then open a PR, re-enter release-handoff via okstra-run → push + PR.`
97
+ - `- Checked out <branch> (stage <N>) into <main worktree path>; okstra worktree <path> removed. Next: to run a local test and then open a PR, re-enter release-handoff via okstra-run → push + PR.`
98
+ - `- Checked out <branch> (stage <N>) into <main worktree path>; no okstra worktree removed (already torn down — the branch survived). Next: to run a local test and then open a PR, re-enter release-handoff via okstra-run → push + PR.`
100
99
  - Pick between the two `Checked out` variants by the command's `removedWorktree` field: a non-empty path takes the first, an empty string takes the second. Never write a removal that did not happen.
101
- - **Stage Group** (stage-group mode only): selected stages, each stage's single-stage verification report path + quoted `Verdict Token` row, collector branch name, merge commit SHAs from assemble, and the dependency-closure verdict (from the assemble output / error).
102
- - **Routing recommendation**: explicit `done` token, since release-handoff is the terminal lifecycle phase. If the run ended in `skip` or `cancel`, the recommendation MUST also state whether re-entry into release-handoff is appropriate.
100
+ - **Routing recommendation**: explicit `done` token, since release-handoff is the terminal lifecycle phase. If the run ended in `skip` or `cancel`, or delivered only some of the selected stages, the recommendation MUST state which stages still need a PR and that re-entry into release-handoff is appropriate.
103
101
  - Self-review pass before finalising the report (the Okstra lead runs this):
104
- 1. **Entry-gate audit** — section 2 cites the originating final-verification report path and the literal `Verdict Token` row with a release-ready value. If either is missing, or a `conditional-accept` run's PR body omits the conditions, the run is invalid and MUST be re-routed to `final-verification`.
102
+ 1. **Entry-gate audit** — the report cites, for every stage it delivered, that stage's final-verification report path and the literal `Verdict Token` row with a release-ready value. If any is missing, or a `conditional-accept` stage's PR body omits its conditions, the run is invalid and MUST be re-routed to `final-verification`.
105
103
  2. **User-selection traceability** — every executed mutating command maps to a user selection captured in the report. Any mutating command without a corresponding user answer is a contract violation.
106
104
  3. **Forbidden-action audit** — scan the run's session transcripts (`git`, `gh` invocations) for every entry in the Forbidden actions list above. Any occurrence means the run has crossed into unsafe territory and MUST be flagged as `contract-violated`.
107
- 4. **Push-target audit** — for every `git push` recorded, confirm the refspec resolves to the feature branch, not the base branch.
108
- 5. **Idempotency check** — if a PR with the same head already existed at run start, confirm the report records `PR reused` rather than a fresh `gh pr create` invocation.
109
- 6. **Merge-conflict probe audit** — for any `push + PR` run, confirm the report's `Merge Conflict Probe` section is present and either records `Clean` or records `Conflicts detected` with the user's verbatim choice. A missing or unparseable probe entry on a `push + PR` run is a contract violation.
105
+ 4. **Push-target audit** — for every `git push` recorded, confirm the refspec resolves to a branch that appears in the pr-plan output, not to the release base branch.
106
+ 5. **Stack-integrity audit** — for every PR opened, confirm its base is the `base_branch` of that stage's pr-plan row and that the base branch was pushed first. A stacked PR opened against the release base instead of its predecessor ships the predecessor's diff twice. Confirm too that no PR body carries a stack plan or merge-policy block — that text belongs to the report and the closeout.
107
+ 6. **Idempotency check** — for every stage whose PR already existed at run start, confirm the report records `PR reused` rather than a fresh `gh pr create` invocation.
108
+ 7. **Merge-conflict probe audit** — for any `push + PR` run, confirm the report's `Merge Conflict Probe` section is present and either records `Clean` or records `Conflicts detected` with the user's verbatim choice. A missing or unparseable probe entry on a `push + PR` run is a contract violation.
110
109
  - Non-goals:
111
- - re-litigating the final-verification verdict — release-handoff trusts the cited release-ready verdict and does not reopen acceptance checks. Carrying a conditional-accept's conditions into the PR body is transcription, not verification: the lead does not check whether a condition has been satisfied.
112
- - creating, amending, squashing, or rewriting commits. Commit production belongs to `implementation`.
113
- - opening additional PRs, releases, or deployments beyond the single PR the user chose to create.
114
- - merging the PR. Merging is a separate, manual step performed by the user (or by repo automation) after release-handoff ends; the lead MUST NOT call `gh pr merge`.
110
+ - re-litigating a final-verification verdict — release-handoff trusts the cited release-ready verdicts and does not reopen acceptance checks. Carrying a conditional-accept's conditions into the PR body is transcription, not verification: the lead does not check whether a condition has been satisfied.
111
+ - creating, amending, squashing, rebasing, or rewriting commits. Commit production belongs to `implementation`; the only commits this phase may create are the merge commits `okstra handoff pr-plan` makes on a `merge-base` branch.
112
+ - bundling several stages into one PR, or building a branch that collects every stage. One stage is one PR.
113
+ - opening releases or deployments beyond the per-stage PRs the user chose to create.
114
+ - merging the PRs. Merging is a separate, manual step performed by the user (or by repo automation) after release-handoff ends; the lead MUST NOT call `gh pr merge`.
115
115
  - escalating beyond the menu choices on user phrasing — every mutating action requires an explicit menu selection.
@@ -0,0 +1,39 @@
1
+ {
2
+ "schemaVersion": "1.0",
3
+ "id": "requirements-discovery",
4
+ "roles": [
5
+ {
6
+ "mode": "static",
7
+ "roleId": "analyser",
8
+ "dutyId": "discovery-worker",
9
+ "min": 2,
10
+ "recommended": 3,
11
+ "max": 5
12
+ },
13
+ {
14
+ "mode": "static",
15
+ "roleId": "critic",
16
+ "dutyId": "scope-critic",
17
+ "min": 0,
18
+ "recommended": 1,
19
+ "max": 1
20
+ },
21
+ {
22
+ "mode": "static",
23
+ "roleId": "report-writer",
24
+ "dutyId": "report-writer",
25
+ "min": 1,
26
+ "recommended": 1,
27
+ "max": 1
28
+ },
29
+ {
30
+ "mode": "dynamic",
31
+ "roleId": "verifier",
32
+ "dutyId": "reverification-worker",
33
+ "sourceRoleIds": [
34
+ "analyser"
35
+ ],
36
+ "activation": "per-selected-source"
37
+ }
38
+ ]
39
+ }
@@ -1,30 +1,5 @@
1
1
  # Requirements Discovery Profile
2
2
 
3
- ```yaml
4
- roles:
5
- - role: analyser
6
- min: 2
7
- recommended: 3
8
- max: 5
9
- duty: discovery-worker
10
- - role: critic
11
- min: 0
12
- recommended: 1
13
- max: 1
14
- duty: scope-critic
15
- - role: report-writer
16
- min: 1
17
- recommended: 1
18
- max: 1
19
- duty: report-writer
20
- - role: verifier
21
- min: 0
22
- recommended: 0
23
- max: 0
24
- duty: reverification-worker
25
- dynamic: true
26
- ```
27
-
28
3
  - Purpose: classify the work request, identify missing requirement evidence, and route the task to the safest next lifecycle phase before implementation starts
29
4
  - Required workers:
30
5
  - claude
@@ -0,0 +1,39 @@
1
+ {
2
+ "schemaVersion": "1.0",
3
+ "id": "technical-verification",
4
+ "roles": [
5
+ {
6
+ "mode": "static",
7
+ "roleId": "analyser",
8
+ "dutyId": "technical-verification-worker",
9
+ "min": 2,
10
+ "recommended": 2,
11
+ "max": 5
12
+ },
13
+ {
14
+ "mode": "static",
15
+ "roleId": "critic",
16
+ "dutyId": "scope-critic",
17
+ "min": 0,
18
+ "recommended": 1,
19
+ "max": 1
20
+ },
21
+ {
22
+ "mode": "static",
23
+ "roleId": "report-writer",
24
+ "dutyId": "report-writer",
25
+ "min": 1,
26
+ "recommended": 1,
27
+ "max": 1
28
+ },
29
+ {
30
+ "mode": "dynamic",
31
+ "roleId": "verifier",
32
+ "dutyId": "reverification-worker",
33
+ "sourceRoleIds": [
34
+ "analyser"
35
+ ],
36
+ "activation": "per-selected-source"
37
+ }
38
+ ]
39
+ }
@@ -1,30 +1,5 @@
1
1
  # Technical Verification Profile
2
2
 
3
- ```yaml
4
- roles:
5
- - role: analyser
6
- min: 2
7
- recommended: 2
8
- max: 5
9
- duty: technical-verification-worker
10
- - role: critic
11
- min: 0
12
- recommended: 1
13
- max: 1
14
- duty: scope-critic
15
- - role: report-writer
16
- min: 1
17
- recommended: 1
18
- max: 1
19
- duty: report-writer
20
- - role: verifier
21
- min: 0
22
- recommended: 0
23
- max: 0
24
- duty: reverification-worker
25
- dynamic: true
26
- ```
27
-
28
3
  - Purpose: collect experimental evidence for unresolved technical facts before a new implementation comparison.
29
4
  - Required workers:
30
5
  - claude
@@ -101,7 +101,7 @@
101
101
  "echo_template": "task-type: {value}"
102
102
  },
103
103
  "selected_direction_pick": {
104
- "label": "상세 계획의 입력으로 사용할 확정 구현 방향 보고서를 선택하세요 (같은 task의 최신 3개). 고른 보고서의 user-responses/ 답변(방향 선택·C-NNN 답)이 함께 전달됩니다 — clarification-response 단계는 필요 없습니다",
104
+ "label": "상세 계획의 입력으로 쓸 확정 구현 방향 보고서를 고르세요 (같은 task 의 최신 3개). 고른 보고서에 딸린 답변 — 어느 방향을 골랐는지와 확인 질문(C-NNN) 답 — 이 함께 전달되므로 뒤의 clarification 단계는 건너뜁니다",
105
105
  "echo_template": "selected-direction: {value}",
106
106
  "errors": {
107
107
  "none": "같은 task에서 선택할 implementation-option-selection 최종 보고서를 찾을 수 없습니다.",
@@ -189,37 +189,34 @@
189
189
  "echo_template": "analysis-target: {value}"
190
190
  },
191
191
  "handoff_stage_pick": {
192
- "label": "PR 로 내보낼 범위를 선택하세요 (복수 선택 가능 — 검증 accepted + 미-PR stage 만 표시). 제외된 stage: {blocked}",
193
- "echo_template": "handoff-scope: {value}",
192
+ "label": "PR 을 열 stage 를 선택하세요 (복수 선택 가능, stage 하나가 PR 하나 — 검증 accepted + 미-PR stage 만 표시). 제외된 stage: {blocked}",
193
+ "echo_template": "handoff-stages: {value}",
194
194
  "labels": {
195
- "whole_task": "전체 task — whole-task 검증 기반 단일 PR (단독 선택)",
196
195
  "stage": "stage {stage} (depends-on: {deps})",
197
- "blocked_none": "없음"
196
+ "blocked_none": "없음",
197
+ "all_stages": "전체 stage ({stages}) — 자격 있는 stage 마다 PR 하나"
198
198
  },
199
199
  "echo_variants": {
200
- "whole_task": "handoff scope: 전체 task (whole-task 검증 기반)",
201
- "stage_group": "handoff scope: stage-group ({stages})"
200
+ "stages": "handoff stages: {stages}"
202
201
  },
203
202
  "errors": {
204
203
  "no_plan": "release-handoff 는 이 task 의 implementation-planning final-report 가 필요합니다 — implementation-planning → implementation → final-verification 을 먼저 진행하세요.",
205
204
  "plan_not_approved": "최신 plan 이 approved 상태가 아닙니다: {plan} — implementation 이 완료된 task 에서만 release-handoff 를 시작할 수 있습니다.",
206
- "nothing_eligible": "PR 로 내보낼 수 있는 범위가 없습니다 — 제외 사유: {blocked}. 단독-stage final-verification 의 accepted 기록(okstra handoff record-verified) 또는 whole-task 검증을 먼저 완료하세요.",
207
- "none_selected": "최소 1개의 범위를 선택하세요",
208
- "whole_task_exclusive": "'전체 task' 는 단독 선택만 가능합니다 — stage 묶음을 원하면 stage 번호들만 선택하세요",
209
- "whole_task_missing": "accepted whole-task final-verification 보고서가 없습니다",
205
+ "nothing_eligible": "PR 로 내보낼 수 있는 stage 가 없습니다 — 제외 사유: {blocked}. final-verification 의 accepted 판정을 `okstra handoff record-verified` 로 먼저 기록하세요 — 단독-stage 판정과 전체 task 판정 모두 근거가 됩니다.",
206
+ "none_selected": "최소 1개의 stage 를 선택하세요",
210
207
  "not_eligible": "eligible 하지 않은 stage: {bad} (선택 가능: {eligible})"
211
208
  }
212
209
  },
213
210
  "brief_carry": {
214
- "label": "이 task 에 carry-in 할 brief 가 없습니다. {task_type} 는 entry phase 의 brief 를 이어받는 단계입니다 — 어떻게 진행할까요?",
211
+ "label": "이 task 에는 이어받을 brief 가 없습니다. {task_type} 는 앞 단계가 쓴 brief 를 물려받아 도는 단계라 그 brief 없이는 시작할 수 없습니다 — 어떻게 할까요?",
215
212
  "echo_template": "brief-carry: {value}",
216
213
  "options": {
217
- "__switch_entry__": "entry phase 로 전환 (추천) — requirements-discovery / error-analysis / improvement-discovery 부터 시작",
214
+ "__switch_entry__": "brief 를 처음 쓰는 단계부터 시작 (추천) — requirements-discovery / error-analysis / improvement-discovery",
218
215
  "__free_input__": "brief 경로 직접 입력",
219
216
  "__abort__": "중단"
220
217
  },
221
218
  "echo_variants": {
222
- "switch_entry": "brief-carry: entry phase 로 전환 — task-type 을 다시 선택합니다",
219
+ "switch_entry": "brief-carry: brief 를 처음 쓰는 단계로 전환 — task-type 을 다시 선택합니다",
223
220
  "abort": "brief-carry: 중단"
224
221
  }
225
222
  },
@@ -402,7 +399,7 @@
402
399
  }
403
400
  },
404
401
  "clarification_pick": {
405
- "label": "clarification-response 를 넘길까요? (follow-up 시에만 — final-report 선택 시 user-responses/ 폴더의 답변도 함께 첨부됩니다)",
402
+ "label": "지난 run 이 남긴 확인 질문(C-NNN)에 답한 파일을 이번 입력으로 넘길까요? 이어서 도는 run 에서만 해당합니다 — 최근 final-report 를 고르면 그 리포트에 딸린 답변도 함께 전달됩니다",
406
403
  "echo_template": "clarification(pick): {value}",
407
404
  "options": {
408
405
  "__skip__": "없음 (건너뛰기)",
@@ -590,7 +587,7 @@
590
587
  "echo_template": "related-tasks: {value}"
591
588
  },
592
589
  "clarification": {
593
- "label": "clarification-response 파일 경로 (follow-up 시에만, 없으면 빈 줄)",
590
+ "label": "지난 run 의 확인 질문에 답한 파일 경로 (이어서 도는 run 에서만, 없으면 빈 줄)",
594
591
  "echo_template": "clarification: {value}"
595
592
  },
596
593
  "pr_template": {
@@ -670,7 +667,6 @@
670
667
  "reverify_scope_user_carry_all": " reverify-scope: carry-all (사용자 지정 — 재검증 없이 직전 판정 전부 이월, 새 stage 만 검증; 브랜치가 움직였으면 full 로 내려감)",
671
668
  "reverify_scope_user_stages": " reverify-scope: stage {stages} 재검증 지정 (사용자 지정 — 하위 stage 포함, 나머지는 직전 판정 이월)",
672
669
  "stage_whole_task": "전체 task",
673
- "handoff_scope_whole_task": "전체 task (whole-task 검증 기반)",
674
- "handoff_scope_stage_group": "stage-group ({stages})"
670
+ "handoff_scope_stages": "stage {stages} (stage 당 PR 1건)"
675
671
  }
676
672
  }
@@ -89,6 +89,7 @@ Render every numbered item as its option label followed by its description verba
89
89
  - For convergence reverify, consume the persisted round plan exactly. This adapter may map and transport each returned batch, but it cannot change batch membership and does not classify findings or branch on task type, provider, or model identity.
90
90
  - The current Antigravity session is the lead. Never launch another provider as a replacement lead.
91
91
  - The prepared run manifest and team-state are the assignment authority. Keep `runner=native-session` assignments in the current host and route `runner=cli-wrapper` assignments through the registered wrapper.
92
+ - This host declares no worker session contract. A `runner=native-session` worker therefore receives no host session rules beyond its duty contract, the selected preamble, and the task instructions; the dispatch prompt carries no `**Host Session Contract Path:**` header. Declaring one means adding `workerSessionContract` to this adapter's `manifest.json` and descriptor — it is never installed into a host-global discovery path.
92
93
  - Do not infer the current host from an installed `agy` binary. The `antigravity` runtime must come from the active host skill or an explicit runtime flag.
93
94
  - Unsupported workers or unavailable models fail before dispatch; do not change the provider, model, or runner silently.
94
95
  - Reverify and critic retries use fresh attempts and persist the core-supplied `dispatchKind`.
@@ -42,6 +42,9 @@ DESCRIPTOR = HostDescriptor(
42
42
  session_accounting="claude-jsonl",
43
43
  has_claude_session=True,
44
44
  relay_contract=str(Path(__file__).with_name("relay.md").resolve()),
45
+ worker_session_contract=str(
46
+ Path(__file__).with_name("worker-session.md").resolve()
47
+ ),
45
48
  initial_prompt_delivery_mode="eager-include",
46
49
  )
47
50
 
@@ -1 +1 @@
1
- {"schemaVersion": 1, "id": "claude-code", "factory": "adapter.py:create_adapter", "nativeProviderId": "claude", "requiredExecutables": ["claude"], "relayContract": "relay.md"}
1
+ {"schemaVersion": 1, "id": "claude-code", "factory": "adapter.py:create_adapter", "nativeProviderId": "claude", "requiredExecutables": ["claude"], "relayContract": "relay.md", "workerSessionContract": "worker-session.md"}
@@ -158,7 +158,7 @@ The `confirm` prompt's `label` is the selection summary (one line per resolved i
158
158
  | `read_artifacts` | Use the host file-read primitive and preserve the core contract's read order. |
159
159
  | `write_artifact` | Use the host file-write primitive only for paths authorized by the active lifecycle phase. |
160
160
  | `prompt_user` | Use `AskUserQuestion` for approvals and clarifications that fit `nativeLimits`. Do not print a numbered list in chat while that tool is available. Emit the question as the last thing in that turn: assistant text emitted after the call renders below the question and separates it from the user's answer. Do not infer an answer from silence. |
161
- | `dispatch_worker` | First verify the materialized invocation metadata. Dispatch `runner=native-session` through `Agent(name: "<role>", run_in_background: true)` without `team_name`, with `hostModelValue` and a summon message only — never the prompt body. The summon is exactly: `Your complete dispatch instructions are the document at <absolute promptPath>. Read that document in full before doing anything else — every line, continuing with offset until end of file — then execute it exactly. Do not act on this message alone.` The verified `promptPath` is already persisted and metadata-verified; inlining its body into the `Agent` call duplicates it in the lead context and lets the two copies drift. Dispatch `runner=cli-wrapper` with the deterministic shell command `okstra worker-dispatch --project-root <root> --run-manifest <path> --workers <ids>`; never wrap that process in another `Agent(...)` call. **Not in a cmux run:** when the run manifest's `terminalBackend` is `cmux-pane`, `prompts/lead/adapters/cmux.md` overrides this row. |
161
+ | `dispatch_worker` | First verify the materialized invocation metadata. Dispatch `runner=native-session` through `Agent(name: "<role>", run_in_background: true)` without `team_name`, with `hostModelValue` and a summon message only — never the prompt body. The summon is exactly: `Your complete dispatch instructions are the document at <absolute promptPath>. Read that document in full before doing anything else — every line, continuing with offset until end of file — then execute it exactly. Do not act on this message alone. If this message carries no such path, return `CLAUDE_PROMPT_PATH_MISSING: dispatch prompt document path was not provided` and do nothing else.` The verified `promptPath` is already persisted and metadata-verified; inlining its body into the `Agent` call duplicates it in the lead context and lets the two copies drift. The summon carries the read requirement because nothing else can: every other rule the worker follows lives inside the document it is being told to open. This host declares a worker session contract (`worker-session.md`), which the materialized prompt delivers to `runner=native-session` workers as `**Host Session Contract Path:**`. Dispatch `runner=cli-wrapper` with the deterministic shell command `okstra worker-dispatch --project-root <root> --run-manifest <path> --workers <ids>`; never wrap that process in another `Agent(...)` call. **Not in a cmux run:** when the run manifest's `terminalBackend` is `cmux-pane`, `prompts/lead/adapters/cmux.md` overrides this row. |
162
162
  | `await_workers` | Arm one background shell poll for the pending Result Paths; the spawn acknowledgement is not completion. |
163
163
  | `redispatch_worker` | Materialize and verify a fresh invocation, then use a fresh native `Agent(...)` session or `okstra worker-dispatch` attempt according to the persisted runner. |
164
164
  | `shutdown_workers` | For each confirmed-complete worker selected for cleanup, send `SendMessage(to: <name>, message: { type: "shutdown_request" })` to idle the roster member **and** call `TaskStop(task_id: "<name>")` to stop its background task. Both are required; neither subsumes the other. |
@@ -169,14 +169,15 @@ The `confirm` prompt's `label` is the selection summary (one line per resolved i
169
169
 
170
170
  - The session owns one implicit team. `TeamCreate` and `TeamDelete` are absent on current Claude Code builds; never probe for them and never pass `team_name`.
171
171
  - Set `name` to the core-assigned functional role label so token attribution can match `agentName`.
172
- - Map a `runner=native-session` Claude assignment to the real host execution definition for its function (`claude-worker`, `report-writer-worker`, or `translator-worker`). A CLI-wrapper assignment has no Claude agent definition; `worker-dispatch` starts its registered provider process directly.
172
+ - A `runner=native-session` Claude assignment opens a general-purpose session: pass no `subagent_type`. okstra registers no agent definitions in this host's discovery path, so there is none to name (ADR-0017). Everything the worker must do reaches it through the summon message and the document that message points at. A CLI-wrapper assignment does not enter this layer at all; `worker-dispatch` starts its registered provider process directly.
173
+ - The native worker primitive for this host is the `Agent` tool. Host session rules — working directory, shell invocation, MCP call shape, and when to return — are owned by this host's worker session contract, not by an execution definition, so they reach a native worker through `**Host Session Contract Path:**` and never reach a CLI-wrapper worker.
173
174
  - For `runner=native-session`, pass the persisted `hostModelValue` as the `model` argument. For `runner=cli-wrapper`, `worker-dispatch` passes the persisted `modelExecutionValue` to the provider process. Never interchange the two fields.
174
175
  - Immediately before every native host primitive, run `okstra agent-prompt record-dispatch` with the project root, run manifest, verified metadata path, and `--enforcement-mode host-native-spec-link-gate`. After the Result Path exists, run `okstra agent-prompt link-result` with `--dispatch-id <invocationId>:attempt-1` and that path before accepting or parsing it. CLI-wrapper calls are recorded by `worker-dispatch` itself.
175
176
  - A resumed lead can dispatch a fresh worker; resume is not a valid reason to omit a rostered role.
176
177
 
177
178
  ### Dispatch-time model enforcement
178
179
 
179
- - A native Claude execution definition declares `model: inherit`; the lead MUST override it with the verified assignment's `hostModelValue`.
180
+ - A native call inherits nothing: pass the verified assignment's `hostModelValue` as the `model` argument on every dispatch.
180
181
  - CLI-wrapper assignments never enter the Agent layer. `okstra worker-dispatch` validates the metadata and passes `modelExecutionValue` to the registered provider script.
181
182
  - Missing or unsupported family-token mapping is a pre-dispatch contract failure. Never inherit the lead model, choose a nearby alias, or switch provider silently.
182
183
  - Every analysis dispatch sets `name: "<workerId>-worker"`; convergence retries append `-reverify-r<N>`, implementation uses the functional `-executor` / `-verifier` suffix, and report writing uses `report-writer`. These values are retained as `agentName` in session JSONL for usage attribution.