okstra 0.202.0 → 0.204.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 (258) hide show
  1. package/README.md +3 -3
  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 +25 -19
  15. package/docs/cli.md +15 -12
  16. package/docs/contributor-change-matrix.md +3 -2
  17. package/docs/performance-improvement-plan-v2.md +2 -3
  18. package/docs/project-structure-overview.md +35 -9
  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.md +1 -1
  23. package/docs/task-process/release-handoff.md +36 -39
  24. package/package.json +1 -2
  25. package/runtime/BUILD.json +2 -2
  26. package/runtime/agents/common.json +28 -0
  27. package/runtime/agents/operations/code-review.json +6 -0
  28. package/runtime/agents/operations/report-translation.json +6 -0
  29. package/runtime/agents/operations/schedule-verification.json +6 -0
  30. package/runtime/agents/roles/analyser.json +18 -0
  31. package/runtime/agents/roles/critic.json +18 -0
  32. package/runtime/agents/roles/designer.json +18 -0
  33. package/runtime/agents/roles/implementer.json +20 -0
  34. package/runtime/agents/roles/leader.json +20 -0
  35. package/runtime/agents/roles/planner.json +18 -0
  36. package/runtime/agents/roles/report-writer.json +19 -0
  37. package/runtime/agents/roles/translator.json +19 -0
  38. package/runtime/agents/roles/verifier.json +18 -0
  39. package/runtime/bin/lib/okstra/usage.sh +5 -5
  40. package/runtime/prompts/duties/acceptance-critic.json +32 -0
  41. package/runtime/prompts/duties/acceptance-verifier.json +32 -0
  42. package/runtime/prompts/duties/analysis-worker.json +32 -0
  43. package/runtime/prompts/duties/code-reviewer.json +32 -0
  44. package/runtime/prompts/duties/diagnosis-worker.json +32 -0
  45. package/runtime/prompts/duties/direction-selection-worker.json +32 -0
  46. package/runtime/prompts/duties/discovery-worker.json +32 -0
  47. package/runtime/prompts/duties/implementation-executor.json +32 -0
  48. package/runtime/prompts/duties/implementation-verifier.json +32 -0
  49. package/runtime/prompts/duties/lead.json +32 -0
  50. package/runtime/prompts/duties/planning-worker.json +36 -0
  51. package/runtime/prompts/duties/report-writer.json +32 -0
  52. package/runtime/prompts/duties/reverification-worker.json +32 -0
  53. package/runtime/prompts/duties/schedule-verifier.json +32 -0
  54. package/runtime/prompts/duties/scope-critic.json +32 -0
  55. package/runtime/prompts/duties/technical-verification-worker.json +32 -0
  56. package/runtime/prompts/duties/translator.json +32 -0
  57. package/runtime/prompts/launch.template.md +2 -1
  58. package/runtime/prompts/lead/adapters/cmux.md +1 -1
  59. package/runtime/prompts/lead/convergence.md +4 -4
  60. package/runtime/prompts/lead/okstra-lead-contract.md +113 -4
  61. package/runtime/prompts/lead/plan-body-verification.md +6 -6
  62. package/runtime/prompts/lead/report-writer.md +3 -3
  63. package/runtime/prompts/profiles/_common-contract.md +2 -2
  64. package/runtime/prompts/profiles/_implementation-executor.md +4 -1
  65. package/runtime/prompts/profiles/_implementation-verifier.md +2 -2
  66. package/runtime/prompts/profiles/change-impact-analysis.json +31 -0
  67. package/runtime/prompts/profiles/change-impact-analysis.md +0 -20
  68. package/runtime/prompts/profiles/error-analysis.json +39 -0
  69. package/runtime/prompts/profiles/error-analysis.md +0 -25
  70. package/runtime/prompts/profiles/feature-analysis.json +31 -0
  71. package/runtime/prompts/profiles/feature-analysis.md +0 -20
  72. package/runtime/prompts/profiles/final-verification.json +30 -0
  73. package/runtime/prompts/profiles/final-verification.md +3 -22
  74. package/runtime/prompts/profiles/forbidden-actions.json +4 -3
  75. package/runtime/prompts/profiles/implementation-option-selection.json +31 -0
  76. package/runtime/prompts/profiles/implementation-option-selection.md +0 -20
  77. package/runtime/prompts/profiles/implementation-planning.json +40 -0
  78. package/runtime/prompts/profiles/implementation-planning.md +4 -29
  79. package/runtime/prompts/profiles/implementation.json +30 -0
  80. package/runtime/prompts/profiles/implementation.md +1 -20
  81. package/runtime/prompts/profiles/improvement-discovery.json +31 -0
  82. package/runtime/prompts/profiles/improvement-discovery.md +0 -20
  83. package/runtime/prompts/profiles/project-analysis.json +31 -0
  84. package/runtime/prompts/profiles/project-analysis.md +0 -20
  85. package/runtime/prompts/profiles/release-handoff.json +5 -0
  86. package/runtime/prompts/profiles/release-handoff.md +71 -73
  87. package/runtime/prompts/profiles/requirements-discovery.json +39 -0
  88. package/runtime/prompts/profiles/requirements-discovery.md +0 -25
  89. package/runtime/prompts/profiles/technical-verification.json +39 -0
  90. package/runtime/prompts/profiles/technical-verification.md +0 -25
  91. package/runtime/prompts/wizard/prompts.ko.json +12 -17
  92. package/runtime/python/okstra_ctl/adapters/hosts/antigravity/relay.md +1 -0
  93. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +3 -0
  94. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/manifest.json +1 -1
  95. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +4 -3
  96. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/worker-session.md +108 -0
  97. package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +1 -0
  98. package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +2 -0
  99. package/runtime/python/okstra_ctl/adapters/hosts/kimi/relay.md +2 -0
  100. package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +8 -1
  101. package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +8 -0
  102. package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +23 -6
  103. package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +6 -2
  104. package/runtime/python/okstra_ctl/agent/invocation.py +168 -113
  105. package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +120 -0
  106. package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +107 -2
  107. package/runtime/python/okstra_ctl/agent/prompt_cli/run_identity.py +0 -49
  108. package/runtime/python/okstra_ctl/analysis_packet.py +4 -1
  109. package/runtime/python/okstra_ctl/application/open_worker.py +6 -1
  110. package/runtime/python/okstra_ctl/assignment_resolver.py +16 -5
  111. package/runtime/python/okstra_ctl/cmux.py +69 -20
  112. package/runtime/python/okstra_ctl/code_review_target.py +16 -8
  113. package/runtime/python/okstra_ctl/conformance.py +43 -0
  114. package/runtime/python/okstra_ctl/consumers.py +6 -3
  115. package/runtime/python/okstra_ctl/container.py +31 -8
  116. package/runtime/python/okstra_ctl/context_cost.py +11 -15
  117. package/runtime/python/okstra_ctl/contract_refreeze.py +156 -0
  118. package/runtime/python/okstra_ctl/convergence_provenance.py +7 -1
  119. package/runtime/python/okstra_ctl/design_prep.py +34 -1
  120. package/runtime/python/okstra_ctl/dispatch_core.py +53 -27
  121. package/runtime/python/okstra_ctl/domain/host.py +5 -0
  122. package/runtime/python/okstra_ctl/domain/worker_runtime.py +10 -0
  123. package/runtime/python/okstra_ctl/error_report.py +4 -3
  124. package/runtime/python/okstra_ctl/execution_manifest.py +71 -18
  125. package/runtime/python/okstra_ctl/handoff.py +167 -277
  126. package/runtime/python/okstra_ctl/implementation_stage.py +9 -0
  127. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +113 -0
  128. package/runtime/python/okstra_ctl/lead_progress.py +1 -1
  129. package/runtime/python/okstra_ctl/legacy_model_selection.py +2 -2
  130. package/runtime/python/okstra_ctl/manager_cli.py +92 -4
  131. package/runtime/python/okstra_ctl/manager_launch.py +1 -1
  132. package/runtime/python/okstra_ctl/manager_paths.py +14 -3
  133. package/runtime/python/okstra_ctl/manager_store.py +210 -3
  134. package/runtime/python/okstra_ctl/manager_sync.py +4 -1
  135. package/runtime/python/okstra_ctl/manager_view.py +2 -1
  136. package/runtime/python/okstra_ctl/model_discovery.py +30 -0
  137. package/runtime/python/okstra_ctl/model_io/lines.py +14 -1
  138. package/runtime/python/okstra_ctl/model_io/renderers.py +4 -3
  139. package/runtime/python/okstra_ctl/models.py +1 -1
  140. package/runtime/python/okstra_ctl/next_phase.py +16 -6
  141. package/runtime/python/okstra_ctl/operation_invocation.py +86 -0
  142. package/runtime/python/okstra_ctl/option_comparison.py +168 -0
  143. package/runtime/python/okstra_ctl/path_hints.py +9 -0
  144. package/runtime/python/okstra_ctl/paths.py +3 -0
  145. package/runtime/python/okstra_ctl/profile_show.py +42 -1
  146. package/runtime/python/okstra_ctl/registry/host_discovery.py +20 -12
  147. package/runtime/python/okstra_ctl/registry/host_registry.py +11 -0
  148. package/runtime/python/okstra_ctl/render.py +50 -0
  149. package/runtime/python/okstra_ctl/report_contract.py +1 -1
  150. package/runtime/python/okstra_ctl/report_html/view_models/release_handoff.py +21 -3
  151. package/runtime/python/okstra_ctl/report_synthesis_packet.py +177 -17
  152. package/runtime/python/okstra_ctl/report_translation.py +2 -1
  153. package/runtime/python/okstra_ctl/report_translation_dispatch.py +69 -9
  154. package/runtime/python/okstra_ctl/role_requirements.py +142 -129
  155. package/runtime/python/okstra_ctl/rollup.py +3 -1
  156. package/runtime/python/okstra_ctl/run.py +76 -29
  157. package/runtime/python/okstra_ctl/schedule_semantics.py +17 -6
  158. package/runtime/python/okstra_ctl/stage_fix_carry.py +23 -4
  159. package/runtime/python/okstra_ctl/stage_integrate.py +178 -18
  160. package/runtime/python/okstra_ctl/stage_map.py +16 -2
  161. package/runtime/python/okstra_ctl/stage_targets.py +209 -43
  162. package/runtime/python/okstra_ctl/team.py +22 -13
  163. package/runtime/python/okstra_ctl/time_report.py +2 -1
  164. package/runtime/python/okstra_ctl/usage_report.py +3 -1
  165. package/runtime/python/okstra_ctl/wizard/confirmation.py +3 -9
  166. package/runtime/python/okstra_ctl/wizard/ids.py +1 -1
  167. package/runtime/python/okstra_ctl/wizard/registry.py +1 -1
  168. package/runtime/python/okstra_ctl/wizard/state.py +3 -5
  169. package/runtime/python/okstra_ctl/wizard/steps_plan.py +3 -23
  170. package/runtime/python/okstra_ctl/worker_prompt_contract.py +5 -1
  171. package/runtime/python/okstra_ctl/worker_prompt_headers.py +35 -7
  172. package/runtime/python/okstra_ctl/worker_prompt_policy.py +66 -48
  173. package/runtime/python/okstra_ctl/workflow.py +1 -1
  174. package/runtime/python/okstra_ctl/worktree/__init__.py +3 -1
  175. package/runtime/python/okstra_ctl/worktree/naming.py +9 -0
  176. package/runtime/python/okstra_ctl/worktree_registry.py +38 -9
  177. package/runtime/python/okstra_token_usage/pricing.py +6 -4
  178. package/runtime/schemas/agent-common-v1.schema.json +34 -0
  179. package/runtime/schemas/agent-duty-v1.schema.json +38 -0
  180. package/runtime/schemas/agent-operation-v1.schema.json +11 -0
  181. package/runtime/schemas/agent-profile-v1.schema.json +46 -0
  182. package/runtime/schemas/agent-role-v1.schema.json +29 -0
  183. package/runtime/schemas/final-report-v2.0.schema.json +118 -97
  184. package/runtime/schemas/final-report-v3.0.schema.json +118 -97
  185. package/runtime/skills/okstra-brief-gen/SKILL.md +84 -4
  186. package/runtime/skills/okstra-chat/SKILL.md +2 -2
  187. package/runtime/skills/okstra-code-review/SKILL.md +23 -9
  188. package/runtime/skills/okstra-container-build/SKILL.md +10 -10
  189. package/runtime/skills/okstra-inspect/SKILL.md +1 -1
  190. package/runtime/skills/okstra-inspect/facets/cost.md +1 -1
  191. package/runtime/skills/okstra-inspect/facets/error-zip.md +9 -9
  192. package/runtime/skills/okstra-inspect/facets/errors.md +16 -16
  193. package/runtime/skills/okstra-inspect/facets/logs.md +7 -7
  194. package/runtime/skills/okstra-inspect/facets/recap.md +2 -2
  195. package/runtime/skills/okstra-inspect/facets/report.md +1 -1
  196. package/runtime/skills/okstra-inspect/facets/status.md +4 -3
  197. package/runtime/skills/okstra-inspect/facets/time.md +11 -10
  198. package/runtime/skills/okstra-manager/SKILL.md +18 -2
  199. package/runtime/skills/okstra-pr-gen/SKILL.md +6 -5
  200. package/runtime/skills/okstra-rollup/SKILL.md +5 -5
  201. package/runtime/skills/okstra-run/SKILL.md +31 -12
  202. package/runtime/skills/okstra-schedule-gen/SKILL.md +19 -14
  203. package/runtime/skills/okstra-setup/SKILL.md +12 -10
  204. package/runtime/skills/okstra-setup/references/project-config.md +7 -6
  205. package/runtime/skills/okstra-usage/SKILL.md +1 -1
  206. package/runtime/skills/okstra-user-response/SKILL.md +1 -1
  207. package/runtime/templates/manager/view.template.html +1 -0
  208. package/runtime/templates/report-writer-prompt-preamble.md +8 -0
  209. package/runtime/templates/reports/brief.template.md +14 -4
  210. package/runtime/templates/reports/html/i18n/en.json +5 -4
  211. package/runtime/templates/reports/html/i18n/ko.json +5 -4
  212. package/runtime/templates/reports/html/tasks/release-handoff.template.html +8 -5
  213. package/runtime/templates/reports/i18n/en.json +1 -1
  214. package/runtime/templates/reports/md/tasks/release-handoff.template.md +1 -1
  215. package/runtime/templates/reports/release-handoff-input.template.md +6 -4
  216. package/runtime/templates/translator-prompt-preamble.md +36 -0
  217. package/runtime/validators/checks/validate-assets-01.py +7 -8
  218. package/runtime/validators/validate-brief.py +70 -0
  219. package/runtime/validators/validate-implementation-plan-stages.py +2 -1
  220. package/runtime/validators/validate-run.py +59 -9
  221. package/runtime/validators/validate-schedule.py +9 -0
  222. package/docs/for-ai/README.md +0 -68
  223. package/docs/for-ai/skills/okstra-brief-gen.md +0 -262
  224. package/docs/for-ai/skills/okstra-chat.md +0 -34
  225. package/docs/for-ai/skills/okstra-code-review.md +0 -57
  226. package/docs/for-ai/skills/okstra-container-build.md +0 -129
  227. package/docs/for-ai/skills/okstra-inspect.md +0 -262
  228. package/docs/for-ai/skills/okstra-manager.md +0 -86
  229. package/docs/for-ai/skills/okstra-memory.md +0 -126
  230. package/docs/for-ai/skills/okstra-pr-gen.md +0 -49
  231. package/docs/for-ai/skills/okstra-rollup.md +0 -114
  232. package/docs/for-ai/skills/okstra-run.md +0 -250
  233. package/docs/for-ai/skills/okstra-schedule-gen.md +0 -240
  234. package/docs/for-ai/skills/okstra-setup.md +0 -167
  235. package/docs/for-ai/skills/okstra-usage.md +0 -29
  236. package/docs/for-ai/skills/okstra-user-response.md +0 -72
  237. package/runtime/agents/workers/claude-worker.md +0 -128
  238. package/runtime/agents/workers/report-writer-worker.md +0 -37
  239. package/runtime/agents/workers/translator-worker.md +0 -63
  240. package/runtime/prompts/duties/acceptance-critic.md +0 -44
  241. package/runtime/prompts/duties/acceptance-verifier.md +0 -44
  242. package/runtime/prompts/duties/analysis-worker.md +0 -44
  243. package/runtime/prompts/duties/code-reviewer.md +0 -44
  244. package/runtime/prompts/duties/common.md +0 -39
  245. package/runtime/prompts/duties/diagnosis-worker.md +0 -44
  246. package/runtime/prompts/duties/direction-selection-worker.md +0 -44
  247. package/runtime/prompts/duties/discovery-worker.md +0 -44
  248. package/runtime/prompts/duties/implementation-executor.md +0 -44
  249. package/runtime/prompts/duties/implementation-verifier.md +0 -44
  250. package/runtime/prompts/duties/lead.md +0 -44
  251. package/runtime/prompts/duties/planning-worker.md +0 -52
  252. package/runtime/prompts/duties/report-writer.md +0 -44
  253. package/runtime/prompts/duties/reverification-worker.md +0 -44
  254. package/runtime/prompts/duties/schedule-verifier.md +0 -44
  255. package/runtime/prompts/duties/scope-critic.md +0 -44
  256. package/runtime/prompts/duties/technical-verification-worker.md +0 -44
  257. package/runtime/prompts/duties/translator.md +0 -44
  258. package/runtime/python/okstra_ctl/pane_title.py +0 -154
@@ -0,0 +1,46 @@
1
+ {
2
+ "type": "object",
3
+ "required": ["schemaVersion", "id", "roles"],
4
+ "properties": {
5
+ "schemaVersion": { "const": "1.0" },
6
+ "id": { "type": "string", "minLength": 1 },
7
+ "roles": {
8
+ "type": "array",
9
+ "items": {
10
+ "oneOf": [
11
+ {
12
+ "type": "object",
13
+ "required": ["mode", "roleId", "dutyId", "min", "recommended", "max"],
14
+ "properties": {
15
+ "mode": { "const": "static" },
16
+ "roleId": { "type": "string", "minLength": 1 },
17
+ "dutyId": { "type": "string", "minLength": 1 },
18
+ "min": { "type": "integer", "minimum": 0 },
19
+ "recommended": { "type": "integer", "minimum": 0 },
20
+ "max": { "type": "integer", "minimum": 0 }
21
+ },
22
+ "additionalProperties": false
23
+ },
24
+ {
25
+ "type": "object",
26
+ "required": ["mode", "roleId", "dutyId", "sourceRoleIds", "activation"],
27
+ "properties": {
28
+ "mode": { "const": "dynamic" },
29
+ "roleId": { "type": "string", "minLength": 1 },
30
+ "dutyId": { "type": "string", "minLength": 1 },
31
+ "sourceRoleIds": {
32
+ "type": "array",
33
+ "minItems": 1,
34
+ "uniqueItems": true,
35
+ "items": { "type": "string", "minLength": 1 }
36
+ },
37
+ "activation": { "const": "per-selected-source" }
38
+ },
39
+ "additionalProperties": false
40
+ }
41
+ ]
42
+ }
43
+ }
44
+ },
45
+ "additionalProperties": false
46
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "type": "object",
3
+ "required": [
4
+ "schemaVersion",
5
+ "id",
6
+ "legacyAliases",
7
+ "identity",
8
+ "responsibilities",
9
+ "requiredCapabilities",
10
+ "prohibitions"
11
+ ],
12
+ "properties": {
13
+ "schemaVersion": { "const": "1.0" },
14
+ "id": { "type": "string", "minLength": 1 },
15
+ "legacyAliases": { "$ref": "#/$defs/stringList" },
16
+ "identity": { "type": "string", "minLength": 1 },
17
+ "responsibilities": { "$ref": "#/$defs/stringList" },
18
+ "requiredCapabilities": { "$ref": "#/$defs/stringList" },
19
+ "prohibitions": { "$ref": "#/$defs/stringList" }
20
+ },
21
+ "additionalProperties": false,
22
+ "$defs": {
23
+ "stringList": {
24
+ "type": "array",
25
+ "items": { "type": "string", "minLength": 1 },
26
+ "uniqueItems": true
27
+ }
28
+ }
29
+ }
@@ -905,110 +905,103 @@
905
905
  "description": "RENDER_IF taskType == release-handoff. §5.6 deliverables.",
906
906
  "required": [
907
907
  "handoffScope",
908
+ "sourceVerificationReports",
908
909
  "featureBranchState",
909
910
  "userSelections",
910
911
  "localCheckoutOutcome",
911
912
  "executedCommands",
912
913
  "commitList",
913
914
  "mergeConflictProbe",
914
- "pullRequestOutcome",
915
+ "pullRequestOutcomes",
915
916
  "routingRecommendation",
916
917
  "userNarrative"
917
918
  ],
918
919
  "additionalProperties": false,
919
- "allOf": [
920
- {
921
- "if": {
922
- "properties": {
923
- "handoffScope": {
924
- "properties": {
925
- "mode": {
926
- "const": "stage-group"
927
- }
928
- },
929
- "required": [
930
- "mode"
931
- ]
932
- }
933
- },
934
- "required": [
935
- "handoffScope"
936
- ]
937
- },
938
- "then": {
939
- "required": [
940
- "sourceVerificationReports"
941
- ]
942
- },
943
- "else": {
944
- "required": [
945
- "sourceVerificationReport"
946
- ]
947
- }
948
- }
949
- ],
950
920
  "properties": {
951
921
  "handoffScope": {
952
922
  "type": "object",
953
923
  "required": [
954
- "mode"
924
+ "stages",
925
+ "releaseBase"
955
926
  ],
956
927
  "additionalProperties": false,
957
- "description": "Which shape of handoff this was. 'whole-task' turns the verified task branch into one PR; 'stage-group' merges a user-selected subset of verified stages into a collector branch and opens the PR from that. Without it a reader cannot tell one report from the other, and in stage-group mode cannot tell which stages shipped — the branch name alone does not say.",
928
+ "description": "What this handoff delivered. One stage is one PR, so the stage list is the PR list, and `stagePlan` is the only place a reader learns which branch each PR sat on — and therefore in what order the stack must be merged.",
958
929
  "properties": {
959
- "mode": {
960
- "enum": [
961
- "whole-task",
962
- "stage-group"
963
- ]
964
- },
965
930
  "stages": {
966
931
  "type": "array",
932
+ "minItems": 1,
967
933
  "items": {
968
934
  "type": "integer",
969
935
  "minimum": 1
970
936
  }
971
937
  },
972
- "collectorBranch": {
973
- "type": "string"
938
+ "releaseBase": {
939
+ "type": "string",
940
+ "minLength": 1,
941
+ "description": "The base branch the user picked for the run. A stage that sits on another stage does NOT target it — see stagePlan[].baseBranch."
974
942
  },
975
- "mergeCommits": {
943
+ "stagePlan": {
976
944
  "type": "array",
977
- "description": "Assemble's merge commit SHAs, in the order the stages were merged into the collector branch. Without them the collector branch's contents cannot be traced back to the stages that produced them once the branch moves on.",
945
+ "description": "`okstra handoff pr-plan` output, one row per stage. Without it the merge order of a stacked PR set cannot be reconstructed once the branches move.",
978
946
  "items": {
979
- "type": "string",
980
- "minLength": 7
947
+ "type": "object",
948
+ "required": [
949
+ "stage",
950
+ "headBranch",
951
+ "baseKind",
952
+ "baseBranch"
953
+ ],
954
+ "additionalProperties": false,
955
+ "properties": {
956
+ "stage": {
957
+ "type": "integer",
958
+ "minimum": 1
959
+ },
960
+ "headBranch": {
961
+ "type": "string",
962
+ "minLength": 1
963
+ },
964
+ "headCommit": {
965
+ "type": "string"
966
+ },
967
+ "baseKind": {
968
+ "enum": [
969
+ "release-base",
970
+ "stage",
971
+ "merge-base"
972
+ ]
973
+ },
974
+ "baseBranch": {
975
+ "type": "string",
976
+ "minLength": 1
977
+ },
978
+ "baseCommit": {
979
+ "type": "string"
980
+ },
981
+ "baseStages": {
982
+ "type": "array",
983
+ "description": "The predecessor stages this row's base carries. Empty for a release-base row.",
984
+ "items": {
985
+ "type": "integer",
986
+ "minimum": 1
987
+ }
988
+ },
989
+ "baseMergeCommits": {
990
+ "type": "array",
991
+ "description": "Merge commits pr-plan created on a merge-base branch. The only commits release-handoff is allowed to produce.",
992
+ "items": {
993
+ "type": "string",
994
+ "minLength": 7
995
+ }
996
+ }
997
+ }
981
998
  }
982
- },
983
- "dependencyClosureVerdict": {
984
- "type": "string",
985
- "minLength": 1,
986
- "description": "Whether the selected stages are closed under their dependencies, and on what basis. A stage-group PR that ships a stage without its predecessor is the failure this records."
987
- }
988
- }
989
- },
990
- "sourceVerificationReport": {
991
- "type": "object",
992
- "description": "whole-task mode: the one final-verification report this handoff ships. Required unless handoffScope.mode is stage-group.",
993
- "required": [
994
- "path",
995
- "verdictTokenQuote"
996
- ],
997
- "additionalProperties": false,
998
- "properties": {
999
- "path": {
1000
- "type": "string",
1001
- "minLength": 1
1002
- },
1003
- "verdictTokenQuote": {
1004
- "type": "string",
1005
- "minLength": 1
1006
999
  }
1007
1000
  }
1008
1001
  },
1009
1002
  "sourceVerificationReports": {
1010
1003
  "type": "array",
1011
- "description": "stage-group mode: one row per selected stage, because that handoff ships several verified stages and a single report path cannot say which stage each verdict belongs to.",
1004
+ "description": "One row per selected stage. Each stage ships its own PR under its own verdict, so a single report path cannot say which stage a verdict belongs to.",
1012
1005
  "minItems": 1,
1013
1006
  "items": {
1014
1007
  "type": "object",
@@ -1048,6 +1041,11 @@
1048
1041
  "checked-out"
1049
1042
  ]
1050
1043
  },
1044
+ "stage": {
1045
+ "type": "integer",
1046
+ "minimum": 1,
1047
+ "description": "The stage whose branch was checked out. Checkout is per stage, so a branch name without it leaves the reader matching branch suffixes by hand."
1048
+ },
1051
1049
  "branch": {
1052
1050
  "type": "string"
1053
1051
  },
@@ -1173,6 +1171,14 @@
1173
1171
  "userChoice": {
1174
1172
  "type": "string"
1175
1173
  },
1174
+ "conflictingStages": {
1175
+ "type": "array",
1176
+ "description": "The stages whose head did not merge cleanly into their own PR base. The probe runs per stage, so a bare path list cannot say which PR is affected.",
1177
+ "items": {
1178
+ "type": "integer",
1179
+ "minimum": 1
1180
+ }
1181
+ },
1176
1182
  "conflictingPaths": {
1177
1183
  "type": "array",
1178
1184
  "items": {
@@ -1181,32 +1187,41 @@
1181
1187
  }
1182
1188
  }
1183
1189
  },
1184
- "pullRequestOutcome": {
1185
- "type": "object",
1186
- "required": [
1187
- "kind"
1188
- ],
1189
- "additionalProperties": false,
1190
- "properties": {
1191
- "kind": {
1192
- "enum": [
1193
- "no-action",
1194
- "created",
1195
- "reused",
1196
- "skipped"
1197
- ]
1198
- },
1199
- "url": {
1200
- "type": "string"
1201
- },
1202
- "title": {
1203
- "type": "string"
1204
- },
1205
- "baseBranch": {
1206
- "type": "string"
1207
- },
1208
- "reason": {
1209
- "type": "string"
1190
+ "pullRequestOutcomes": {
1191
+ "type": "array",
1192
+ "description": "One row per selected stage — one stage is one PR. A single outcome object cannot say which stage was created, reused or skipped.",
1193
+ "items": {
1194
+ "type": "object",
1195
+ "additionalProperties": false,
1196
+ "required": [
1197
+ "stage",
1198
+ "kind"
1199
+ ],
1200
+ "properties": {
1201
+ "stage": {
1202
+ "type": "integer",
1203
+ "minimum": 1
1204
+ },
1205
+ "kind": {
1206
+ "enum": [
1207
+ "no-action",
1208
+ "created",
1209
+ "reused",
1210
+ "skipped"
1211
+ ]
1212
+ },
1213
+ "url": {
1214
+ "type": "string"
1215
+ },
1216
+ "title": {
1217
+ "type": "string"
1218
+ },
1219
+ "baseBranch": {
1220
+ "type": "string"
1221
+ },
1222
+ "reason": {
1223
+ "type": "string"
1224
+ }
1210
1225
  }
1211
1226
  }
1212
1227
  },
@@ -1582,6 +1597,7 @@
1582
1597
  "enum": [
1583
1598
  "release-handoff",
1584
1599
  "release-handoff(stage-group)",
1600
+ "final-verification",
1585
1601
  "error-analysis",
1586
1602
  "implementation-option-selection",
1587
1603
  "implementation-planning",
@@ -9687,6 +9703,11 @@
9687
9703
  ],
9688
9704
  "additionalProperties": false,
9689
9705
  "properties": {
9706
+ "stage": {
9707
+ "type": "integer",
9708
+ "minimum": 1,
9709
+ "description": "Which stage's PR carries this commit. One stage is one PR, so a flat commit list across several stages cannot be attributed without it."
9710
+ },
9690
9711
  "shortSha": {
9691
9712
  "type": "string",
9692
9713
  "minLength": 7
@@ -905,110 +905,103 @@
905
905
  "description": "RENDER_IF taskType == release-handoff. §5.6 deliverables.",
906
906
  "required": [
907
907
  "handoffScope",
908
+ "sourceVerificationReports",
908
909
  "featureBranchState",
909
910
  "userSelections",
910
911
  "localCheckoutOutcome",
911
912
  "executedCommands",
912
913
  "commitList",
913
914
  "mergeConflictProbe",
914
- "pullRequestOutcome",
915
+ "pullRequestOutcomes",
915
916
  "routingRecommendation",
916
917
  "userNarrative"
917
918
  ],
918
919
  "additionalProperties": false,
919
- "allOf": [
920
- {
921
- "if": {
922
- "properties": {
923
- "handoffScope": {
924
- "properties": {
925
- "mode": {
926
- "const": "stage-group"
927
- }
928
- },
929
- "required": [
930
- "mode"
931
- ]
932
- }
933
- },
934
- "required": [
935
- "handoffScope"
936
- ]
937
- },
938
- "then": {
939
- "required": [
940
- "sourceVerificationReports"
941
- ]
942
- },
943
- "else": {
944
- "required": [
945
- "sourceVerificationReport"
946
- ]
947
- }
948
- }
949
- ],
950
920
  "properties": {
951
921
  "handoffScope": {
952
922
  "type": "object",
953
923
  "required": [
954
- "mode"
924
+ "stages",
925
+ "releaseBase"
955
926
  ],
956
927
  "additionalProperties": false,
957
- "description": "Which shape of handoff this was. 'whole-task' turns the verified task branch into one PR; 'stage-group' merges a user-selected subset of verified stages into a collector branch and opens the PR from that. Without it a reader cannot tell one report from the other, and in stage-group mode cannot tell which stages shipped — the branch name alone does not say.",
928
+ "description": "What this handoff delivered. One stage is one PR, so the stage list is the PR list, and `stagePlan` is the only place a reader learns which branch each PR sat on — and therefore in what order the stack must be merged.",
958
929
  "properties": {
959
- "mode": {
960
- "enum": [
961
- "whole-task",
962
- "stage-group"
963
- ]
964
- },
965
930
  "stages": {
966
931
  "type": "array",
932
+ "minItems": 1,
967
933
  "items": {
968
934
  "type": "integer",
969
935
  "minimum": 1
970
936
  }
971
937
  },
972
- "collectorBranch": {
973
- "type": "string"
938
+ "releaseBase": {
939
+ "type": "string",
940
+ "minLength": 1,
941
+ "description": "The base branch the user picked for the run. A stage that sits on another stage does NOT target it — see stagePlan[].baseBranch."
974
942
  },
975
- "mergeCommits": {
943
+ "stagePlan": {
976
944
  "type": "array",
977
- "description": "Assemble's merge commit SHAs, in the order the stages were merged into the collector branch. Without them the collector branch's contents cannot be traced back to the stages that produced them once the branch moves on.",
945
+ "description": "`okstra handoff pr-plan` output, one row per stage. Without it the merge order of a stacked PR set cannot be reconstructed once the branches move.",
978
946
  "items": {
979
- "type": "string",
980
- "minLength": 7
947
+ "type": "object",
948
+ "required": [
949
+ "stage",
950
+ "headBranch",
951
+ "baseKind",
952
+ "baseBranch"
953
+ ],
954
+ "additionalProperties": false,
955
+ "properties": {
956
+ "stage": {
957
+ "type": "integer",
958
+ "minimum": 1
959
+ },
960
+ "headBranch": {
961
+ "type": "string",
962
+ "minLength": 1
963
+ },
964
+ "headCommit": {
965
+ "type": "string"
966
+ },
967
+ "baseKind": {
968
+ "enum": [
969
+ "release-base",
970
+ "stage",
971
+ "merge-base"
972
+ ]
973
+ },
974
+ "baseBranch": {
975
+ "type": "string",
976
+ "minLength": 1
977
+ },
978
+ "baseCommit": {
979
+ "type": "string"
980
+ },
981
+ "baseStages": {
982
+ "type": "array",
983
+ "description": "The predecessor stages this row's base carries. Empty for a release-base row.",
984
+ "items": {
985
+ "type": "integer",
986
+ "minimum": 1
987
+ }
988
+ },
989
+ "baseMergeCommits": {
990
+ "type": "array",
991
+ "description": "Merge commits pr-plan created on a merge-base branch. The only commits release-handoff is allowed to produce.",
992
+ "items": {
993
+ "type": "string",
994
+ "minLength": 7
995
+ }
996
+ }
997
+ }
981
998
  }
982
- },
983
- "dependencyClosureVerdict": {
984
- "type": "string",
985
- "minLength": 1,
986
- "description": "Whether the selected stages are closed under their dependencies, and on what basis. A stage-group PR that ships a stage without its predecessor is the failure this records."
987
- }
988
- }
989
- },
990
- "sourceVerificationReport": {
991
- "type": "object",
992
- "description": "whole-task mode: the one final-verification report this handoff ships. Required unless handoffScope.mode is stage-group.",
993
- "required": [
994
- "path",
995
- "verdictTokenQuote"
996
- ],
997
- "additionalProperties": false,
998
- "properties": {
999
- "path": {
1000
- "type": "string",
1001
- "minLength": 1
1002
- },
1003
- "verdictTokenQuote": {
1004
- "type": "string",
1005
- "minLength": 1
1006
999
  }
1007
1000
  }
1008
1001
  },
1009
1002
  "sourceVerificationReports": {
1010
1003
  "type": "array",
1011
- "description": "stage-group mode: one row per selected stage, because that handoff ships several verified stages and a single report path cannot say which stage each verdict belongs to.",
1004
+ "description": "One row per selected stage. Each stage ships its own PR under its own verdict, so a single report path cannot say which stage a verdict belongs to.",
1012
1005
  "minItems": 1,
1013
1006
  "items": {
1014
1007
  "type": "object",
@@ -1048,6 +1041,11 @@
1048
1041
  "checked-out"
1049
1042
  ]
1050
1043
  },
1044
+ "stage": {
1045
+ "type": "integer",
1046
+ "minimum": 1,
1047
+ "description": "The stage whose branch was checked out. Checkout is per stage, so a branch name without it leaves the reader matching branch suffixes by hand."
1048
+ },
1051
1049
  "branch": {
1052
1050
  "type": "string"
1053
1051
  },
@@ -1173,6 +1171,14 @@
1173
1171
  "userChoice": {
1174
1172
  "type": "string"
1175
1173
  },
1174
+ "conflictingStages": {
1175
+ "type": "array",
1176
+ "description": "The stages whose head did not merge cleanly into their own PR base. The probe runs per stage, so a bare path list cannot say which PR is affected.",
1177
+ "items": {
1178
+ "type": "integer",
1179
+ "minimum": 1
1180
+ }
1181
+ },
1176
1182
  "conflictingPaths": {
1177
1183
  "type": "array",
1178
1184
  "items": {
@@ -1181,32 +1187,41 @@
1181
1187
  }
1182
1188
  }
1183
1189
  },
1184
- "pullRequestOutcome": {
1185
- "type": "object",
1186
- "required": [
1187
- "kind"
1188
- ],
1189
- "additionalProperties": false,
1190
- "properties": {
1191
- "kind": {
1192
- "enum": [
1193
- "no-action",
1194
- "created",
1195
- "reused",
1196
- "skipped"
1197
- ]
1198
- },
1199
- "url": {
1200
- "type": "string"
1201
- },
1202
- "title": {
1203
- "type": "string"
1204
- },
1205
- "baseBranch": {
1206
- "type": "string"
1207
- },
1208
- "reason": {
1209
- "type": "string"
1190
+ "pullRequestOutcomes": {
1191
+ "type": "array",
1192
+ "description": "One row per selected stage — one stage is one PR. A single outcome object cannot say which stage was created, reused or skipped.",
1193
+ "items": {
1194
+ "type": "object",
1195
+ "additionalProperties": false,
1196
+ "required": [
1197
+ "stage",
1198
+ "kind"
1199
+ ],
1200
+ "properties": {
1201
+ "stage": {
1202
+ "type": "integer",
1203
+ "minimum": 1
1204
+ },
1205
+ "kind": {
1206
+ "enum": [
1207
+ "no-action",
1208
+ "created",
1209
+ "reused",
1210
+ "skipped"
1211
+ ]
1212
+ },
1213
+ "url": {
1214
+ "type": "string"
1215
+ },
1216
+ "title": {
1217
+ "type": "string"
1218
+ },
1219
+ "baseBranch": {
1220
+ "type": "string"
1221
+ },
1222
+ "reason": {
1223
+ "type": "string"
1224
+ }
1210
1225
  }
1211
1226
  }
1212
1227
  },
@@ -1582,6 +1597,7 @@
1582
1597
  "enum": [
1583
1598
  "release-handoff",
1584
1599
  "release-handoff(stage-group)",
1600
+ "final-verification",
1585
1601
  "error-analysis",
1586
1602
  "implementation-option-selection",
1587
1603
  "implementation-planning",
@@ -9839,6 +9855,11 @@
9839
9855
  ],
9840
9856
  "additionalProperties": false,
9841
9857
  "properties": {
9858
+ "stage": {
9859
+ "type": "integer",
9860
+ "minimum": 1,
9861
+ "description": "Which stage's PR carries this commit. One stage is one PR, so a flat commit list across several stages cannot be attributed without it."
9862
+ },
9842
9863
  "shortSha": {
9843
9864
  "type": "string",
9844
9865
  "minLength": 7