okstra 0.179.2 → 0.183.2

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 +1 -1
  2. package/dist/cli-registry.mjs +30 -2
  3. package/dist/cli-registry.mjs.map +1 -1
  4. package/dist/commands/execute/incremental-carry.mjs +9 -8
  5. package/dist/commands/execute/incremental-carry.mjs.map +1 -1
  6. package/dist/commands/execute/plan-verify.mjs +3 -1
  7. package/dist/commands/execute/plan-verify.mjs.map +1 -1
  8. package/dist/commands/execute/render-bundle.d.mts +4 -2
  9. package/dist/commands/execute/render-bundle.mjs +46 -5
  10. package/dist/commands/execute/render-bundle.mjs.map +1 -1
  11. package/dist/commands/execute/run.mjs +11 -3
  12. package/dist/commands/execute/run.mjs.map +1 -1
  13. package/dist/commands/inspect/model-io.d.mts +1 -0
  14. package/dist/commands/inspect/model-io.mjs +25 -0
  15. package/dist/commands/inspect/model-io.mjs.map +1 -0
  16. package/dist/commands/inspect/stage-map.mjs +29 -8
  17. package/dist/commands/inspect/stage-map.mjs.map +1 -1
  18. package/dist/commands/inspect/task-list.mjs +52 -6
  19. package/dist/commands/inspect/task-list.mjs.map +1 -1
  20. package/dist/commands/inspect/user-response.mjs +14 -4
  21. package/dist/commands/inspect/user-response.mjs.map +1 -1
  22. package/dist/commands/lifecycle/check-project.d.mts +1 -0
  23. package/dist/commands/lifecycle/check-project.mjs +69 -50
  24. package/dist/commands/lifecycle/check-project.mjs.map +1 -1
  25. package/dist/commands/lifecycle/contract-check.d.mts +1 -0
  26. package/dist/commands/lifecycle/contract-check.mjs +18 -0
  27. package/dist/commands/lifecycle/contract-check.mjs.map +1 -0
  28. package/dist/commands/lifecycle/preflight.mjs +154 -51
  29. package/dist/commands/lifecycle/preflight.mjs.map +1 -1
  30. package/dist/commands/pr/pr.d.mts +1 -0
  31. package/dist/commands/pr/pr.mjs +19 -1
  32. package/dist/commands/pr/pr.mjs.map +1 -1
  33. package/dist/commands/report/agent-activity.mjs +2 -2
  34. package/dist/commands/report/approval-decision.d.mts +1 -0
  35. package/dist/commands/report/approval-decision.mjs +21 -0
  36. package/dist/commands/report/approval-decision.mjs.map +1 -0
  37. package/dist/commands/report/design-snapshot.d.mts +1 -0
  38. package/dist/commands/report/design-snapshot.mjs +19 -0
  39. package/dist/commands/report/design-snapshot.mjs.map +1 -0
  40. package/dist/commands/report/translate.mjs +3 -0
  41. package/dist/commands/report/translate.mjs.map +1 -1
  42. package/dist/lib/host-registry-client.mjs +13 -9
  43. package/dist/lib/host-registry-client.mjs.map +1 -1
  44. package/docs/architecture/storage-model.md +1 -1
  45. package/docs/architecture.md +21 -10
  46. package/docs/cli.md +36 -20
  47. package/docs/container.md +6 -4
  48. package/docs/contributor-change-matrix.md +1 -1
  49. package/docs/for-ai/README.md +2 -2
  50. package/docs/for-ai/skills/okstra-brief-gen.md +5 -3
  51. package/docs/for-ai/skills/okstra-code-review.md +4 -4
  52. package/docs/for-ai/skills/okstra-container-build.md +20 -17
  53. package/docs/for-ai/skills/okstra-inspect.md +20 -23
  54. package/docs/for-ai/skills/okstra-manager.md +19 -18
  55. package/docs/for-ai/skills/okstra-memory.md +2 -2
  56. package/docs/for-ai/skills/okstra-pr-gen.md +3 -3
  57. package/docs/for-ai/skills/okstra-rollup.md +14 -13
  58. package/docs/for-ai/skills/okstra-run.md +7 -3
  59. package/docs/for-ai/skills/okstra-schedule-gen.md +15 -18
  60. package/docs/for-ai/skills/okstra-setup.md +7 -7
  61. package/docs/for-ai/skills/okstra-usage.md +5 -4
  62. package/docs/for-ai/skills/okstra-user-response.md +50 -32
  63. package/docs/project-structure-overview.md +43 -31
  64. package/docs/task-process/implementation-planning.md +2 -2
  65. package/docs/task-process/implementation.md +7 -4
  66. package/package.json +1 -1
  67. package/runtime/BUILD.json +2 -2
  68. package/runtime/agents/workers/claude-worker.md +4 -4
  69. package/runtime/agents/workers/report-writer-worker.md +15 -164
  70. package/runtime/agents/workers/translator-worker.md +5 -13
  71. package/runtime/bin/okstra-error-log.py +51 -11
  72. package/runtime/bin/okstra-report-translate.py +210 -23
  73. package/runtime/prompts/host-orchestration/implementation.md +1 -1
  74. package/runtime/prompts/launch.template.md +9 -12
  75. package/runtime/prompts/lead/adapters/cmux.md +1 -1
  76. package/runtime/prompts/lead/context-loader.md +41 -141
  77. package/runtime/prompts/lead/convergence.md +10 -8
  78. package/runtime/prompts/lead/okstra-lead-contract.md +40 -49
  79. package/runtime/prompts/lead/plan-body-verification.md +217 -23
  80. package/runtime/prompts/lead/report-writer.md +81 -421
  81. package/runtime/prompts/lead/team-contract.md +9 -54
  82. package/runtime/prompts/profiles/_clarification-recommendation.md +5 -4
  83. package/runtime/prompts/profiles/_coding-conventions-preflight.md +3 -2
  84. package/runtime/prompts/profiles/_common-contract.md +4 -4
  85. package/runtime/prompts/profiles/_implementation-deliverable.md +1 -1
  86. package/runtime/prompts/profiles/_implementation-diff-review.md +1 -1
  87. package/runtime/prompts/profiles/_implementation-verifier.md +3 -3
  88. package/runtime/prompts/profiles/change-impact-analysis.md +1 -1
  89. package/runtime/prompts/profiles/error-analysis.md +1 -1
  90. package/runtime/prompts/profiles/feature-analysis.md +1 -1
  91. package/runtime/prompts/profiles/final-verification.md +1 -1
  92. package/runtime/prompts/profiles/implementation-planning.md +20 -12
  93. package/runtime/prompts/profiles/improvement-discovery.md +1 -1
  94. package/runtime/prompts/profiles/project-analysis.md +1 -1
  95. package/runtime/prompts/profiles/release-handoff.md +0 -1
  96. package/runtime/prompts/profiles/requirements-discovery.md +1 -1
  97. package/runtime/prompts/wizard/prompts.ko.json +0 -1
  98. package/runtime/python/okstra_ctl/adapters/hosts/capability_adapter.py +69 -17
  99. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +13 -4
  100. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +8 -2
  101. package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +2 -2
  102. package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +50 -5
  103. package/runtime/python/okstra_ctl/adapters/hosts/external/relay.md +1 -1
  104. package/runtime/python/okstra_ctl/adapters/hosts/grok/adapter.py +2 -2
  105. package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +66 -5
  106. package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +70 -2
  107. package/runtime/python/okstra_ctl/agent_activity.py +141 -38
  108. package/runtime/python/okstra_ctl/agent_invocation.py +19 -6
  109. package/runtime/python/okstra_ctl/agent_prompt_cli.py +70 -23
  110. package/runtime/python/okstra_ctl/analysis_inputs.py +5 -4
  111. package/runtime/python/okstra_ctl/analysis_packet.py +124 -3
  112. package/runtime/python/okstra_ctl/approval_decisions.py +328 -0
  113. package/runtime/python/okstra_ctl/attempt_evidence.py +2 -2
  114. package/runtime/python/okstra_ctl/backfill.py +13 -10
  115. package/runtime/python/okstra_ctl/batch.py +2 -4
  116. package/runtime/python/okstra_ctl/build_tools.py +6 -3
  117. package/runtime/python/okstra_ctl/claim_reproduction.py +101 -0
  118. package/runtime/python/okstra_ctl/clarification_items.py +27 -13
  119. package/runtime/python/okstra_ctl/cmux.py +130 -52
  120. package/runtime/python/okstra_ctl/code_review_target.py +34 -8
  121. package/runtime/python/okstra_ctl/consumers.py +5 -4
  122. package/runtime/python/okstra_ctl/container.py +103 -8
  123. package/runtime/python/okstra_ctl/context_cost.py +2 -1
  124. package/runtime/python/okstra_ctl/contract_graph.py +497 -0
  125. package/runtime/python/okstra_ctl/contract_graph_cli.py +62 -0
  126. package/runtime/python/okstra_ctl/convergence.py +338 -17
  127. package/runtime/python/okstra_ctl/convergence_engine.py +10 -18
  128. package/runtime/python/okstra_ctl/convergence_provenance.py +58 -8
  129. package/runtime/python/okstra_ctl/convergence_store.py +55 -34
  130. package/runtime/python/okstra_ctl/design_prep.py +7 -4
  131. package/runtime/python/okstra_ctl/design_snapshot.py +134 -0
  132. package/runtime/python/okstra_ctl/dispatch_core.py +97 -69
  133. package/runtime/python/okstra_ctl/dispatch_state.py +163 -63
  134. package/runtime/python/okstra_ctl/doctor.py +6 -3
  135. package/runtime/python/okstra_ctl/domain/worker_presentation.py +70 -9
  136. package/runtime/python/okstra_ctl/entrypoints/hosts.py +16 -30
  137. package/runtime/python/okstra_ctl/error_log_write.py +35 -30
  138. package/runtime/python/okstra_ctl/error_report.py +26 -1
  139. package/runtime/python/okstra_ctl/error_zip.py +27 -5
  140. package/runtime/python/okstra_ctl/execution_identity.py +3 -2
  141. package/runtime/python/okstra_ctl/execution_manifest.py +7 -4
  142. package/runtime/python/okstra_ctl/execution_mutation_audit.py +6 -2
  143. package/runtime/python/okstra_ctl/final_report_schema.py +26 -17
  144. package/runtime/python/okstra_ctl/fix_cycles.py +2 -2
  145. package/runtime/python/okstra_ctl/fixed_text.py +39 -0
  146. package/runtime/python/okstra_ctl/git_reconcile.py +41 -9
  147. package/runtime/python/okstra_ctl/handoff.py +5 -4
  148. package/runtime/python/okstra_ctl/i18n.py +4 -2
  149. package/runtime/python/okstra_ctl/implementation_direction.py +22 -14
  150. package/runtime/python/okstra_ctl/implementation_outcome.py +4 -7
  151. package/runtime/python/okstra_ctl/incremental_carry.py +130 -17
  152. package/runtime/python/okstra_ctl/incremental_scope.py +12 -4
  153. package/runtime/python/okstra_ctl/index.py +8 -11
  154. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +79 -7
  155. package/runtime/python/okstra_ctl/invocation.py +3 -6
  156. package/runtime/python/okstra_ctl/json_boundary.py +366 -0
  157. package/runtime/python/okstra_ctl/json_registry.py +10 -12
  158. package/runtime/python/okstra_ctl/jsonl.py +19 -2
  159. package/runtime/python/okstra_ctl/lead_events.py +33 -1
  160. package/runtime/python/okstra_ctl/listing.py +3 -3
  161. package/runtime/python/okstra_ctl/log_report.py +24 -2
  162. package/runtime/python/okstra_ctl/manager_cli.py +92 -7
  163. package/runtime/python/okstra_ctl/manager_store.py +12 -10
  164. package/runtime/python/okstra_ctl/material.py +5 -1
  165. package/runtime/python/okstra_ctl/migrate.py +29 -25
  166. package/runtime/python/okstra_ctl/model_cli.py +3 -15
  167. package/runtime/python/okstra_ctl/model_io_cli.py +1051 -0
  168. package/runtime/python/okstra_ctl/mutation_probe.py +13 -4
  169. package/runtime/python/okstra_ctl/pane_reclaim.py +3 -2
  170. package/runtime/python/okstra_ctl/path_hints.py +12 -0
  171. package/runtime/python/okstra_ctl/paths.py +21 -0
  172. package/runtime/python/okstra_ctl/plan_items.py +115 -4
  173. package/runtime/python/okstra_ctl/plan_items_cli.py +626 -34
  174. package/runtime/python/okstra_ctl/ports/worker_dispatch.py +2 -1
  175. package/runtime/python/okstra_ctl/pr_template.py +3 -2
  176. package/runtime/python/okstra_ctl/project_meta.py +5 -7
  177. package/runtime/python/okstra_ctl/recap.py +5 -4
  178. package/runtime/python/okstra_ctl/reconcile.py +21 -27
  179. package/runtime/python/okstra_ctl/registry/host_discovery.py +3 -2
  180. package/runtime/python/okstra_ctl/registry/provider_registry.py +3 -2
  181. package/runtime/python/okstra_ctl/render.py +74 -16
  182. package/runtime/python/okstra_ctl/render_final_report.py +10 -8
  183. package/runtime/python/okstra_ctl/report_assembly.py +509 -0
  184. package/runtime/python/okstra_ctl/report_contract.py +2 -1
  185. package/runtime/python/okstra_ctl/report_finalize.py +67 -32
  186. package/runtime/python/okstra_ctl/report_html/render.py +3 -2
  187. package/runtime/python/okstra_ctl/report_inputs.py +72 -0
  188. package/runtime/python/okstra_ctl/report_language.py +3 -2
  189. package/runtime/python/okstra_ctl/report_markdown.py +81 -8
  190. package/runtime/python/okstra_ctl/report_narrative.py +351 -0
  191. package/runtime/python/okstra_ctl/report_projections.py +265 -0
  192. package/runtime/python/okstra_ctl/report_synthesis_packet.py +518 -0
  193. package/runtime/python/okstra_ctl/report_views.py +3 -2
  194. package/runtime/python/okstra_ctl/rollup.py +65 -4
  195. package/runtime/python/okstra_ctl/run.py +184 -65
  196. package/runtime/python/okstra_ctl/run_audit.py +3 -2
  197. package/runtime/python/okstra_ctl/run_context.py +6 -9
  198. package/runtime/python/okstra_ctl/run_index_row.py +2 -8
  199. package/runtime/python/okstra_ctl/schedule_semantics.py +5 -2
  200. package/runtime/python/okstra_ctl/schema_excerpt.py +15 -8
  201. package/runtime/python/okstra_ctl/session_transcript.py +27 -1
  202. package/runtime/python/okstra_ctl/set_work_status.py +64 -38
  203. package/runtime/python/okstra_ctl/stage_fix_carry.py +8 -6
  204. package/runtime/python/okstra_ctl/stage_ledger.py +132 -18
  205. package/runtime/python/okstra_ctl/stage_map.py +96 -28
  206. package/runtime/python/okstra_ctl/stage_targets.py +3 -4
  207. package/runtime/python/okstra_ctl/team.py +3 -2
  208. package/runtime/python/okstra_ctl/team_reconcile.py +11 -2
  209. package/runtime/python/okstra_ctl/time_report.py +51 -4
  210. package/runtime/python/okstra_ctl/usage_identity.py +2 -1
  211. package/runtime/python/okstra_ctl/usage_report.py +58 -4
  212. package/runtime/python/okstra_ctl/user_response.py +1431 -66
  213. package/runtime/python/okstra_ctl/wizard.py +11 -44
  214. package/runtime/python/okstra_ctl/work_categories.py +3 -2
  215. package/runtime/python/okstra_ctl/worker_dispatch.py +5 -2
  216. package/runtime/python/okstra_ctl/worker_prompt_body.py +49 -3
  217. package/runtime/python/okstra_ctl/worker_prompt_contract.py +3 -2
  218. package/runtime/python/okstra_ctl/worker_prompt_policy.py +31 -3
  219. package/runtime/python/okstra_ctl/worker_runner.py +14 -12
  220. package/runtime/python/okstra_ctl/workflow.py +2 -1
  221. package/runtime/python/okstra_ctl/worktree.py +3 -2
  222. package/runtime/python/okstra_ctl/wrapper_status.py +4 -2
  223. package/runtime/python/okstra_ctl/write_policy.py +4 -2
  224. package/runtime/python/okstra_token_usage/antigravity.py +39 -12
  225. package/runtime/python/okstra_token_usage/collect.py +90 -38
  226. package/runtime/python/okstra_token_usage/grok.py +127 -0
  227. package/runtime/schemas/final-report-v2.0.schema.json +9 -0
  228. package/runtime/schemas/final-report-v3.0.schema.json +10219 -0
  229. package/runtime/schemas/report-narrative-v3.0.schema.json +30 -0
  230. package/runtime/schemas/report-synthesis-packet-v1.0.schema.json +140 -0
  231. package/runtime/skills/okstra-brief-gen/SKILL.md +9 -7
  232. package/runtime/skills/okstra-code-review/SKILL.md +21 -11
  233. package/runtime/skills/okstra-container-build/SKILL.md +18 -18
  234. package/runtime/skills/okstra-inspect/SKILL.md +12 -11
  235. package/runtime/skills/okstra-inspect/facets/error-zip.md +8 -8
  236. package/runtime/skills/okstra-inspect/facets/errors.md +2 -2
  237. package/runtime/skills/okstra-inspect/facets/history.md +9 -14
  238. package/runtime/skills/okstra-inspect/facets/logs.md +2 -2
  239. package/runtime/skills/okstra-inspect/facets/recap.md +5 -5
  240. package/runtime/skills/okstra-inspect/facets/report.md +6 -10
  241. package/runtime/skills/okstra-inspect/facets/status.md +9 -8
  242. package/runtime/skills/okstra-inspect/facets/time.md +3 -3
  243. package/runtime/skills/okstra-manager/SKILL.md +16 -14
  244. package/runtime/skills/okstra-memory/SKILL.md +3 -3
  245. package/runtime/skills/okstra-pr-gen/SKILL.md +5 -4
  246. package/runtime/skills/okstra-rollup/SKILL.md +6 -16
  247. package/runtime/skills/okstra-run/SKILL.md +7 -7
  248. package/runtime/skills/okstra-schedule-gen/SKILL.md +21 -17
  249. package/runtime/skills/okstra-setup/SKILL.md +21 -13
  250. package/runtime/skills/okstra-setup/references/project-config.md +2 -2
  251. package/runtime/skills/okstra-usage/SKILL.md +10 -10
  252. package/runtime/skills/okstra-user-response/SKILL.md +78 -107
  253. package/runtime/templates/report-writer-prompt-preamble.md +29 -19
  254. package/runtime/templates/reports/html/macros/forms.html +6 -4
  255. package/runtime/templates/reports/schedule.template.md +4 -4
  256. package/runtime/templates/worker-error-contract.md +17 -29
  257. package/runtime/validators/validate-run.py +636 -72
  258. package/runtime/validators/validate_session_conformance.py +43 -7
@@ -19,14 +19,14 @@ If the user asks for a recap without naming a task (e.g. "summarize this work"),
19
19
  Use the CLI output as the source of truth:
20
20
 
21
21
  ```bash
22
- okstra recap assemble <resolved-target> --project-root <projectRoot>
22
+ okstra model-io recap-input --project-root <projectRoot> --task-ref <resolved-target>
23
23
  ```
24
24
 
25
- Parse the stdout JSON (`{taskKey, runCount, transitions[], latestPhaseStates}`) and narrate the per-run before/after transitions. For each `transitions[]` entry, show `fromPhase toPhase` (previous run currentPhase this run currentPhase), `status`, `lastCompletedPhase`, `nextRecommendedPhase`, and `reportPath` in chronological order. If `runCount == 0`, answer only "This task has no recorded runs." and do not claim to have read any file.
25
+ Read the fixed-text `Run count` and repeated `Transition` blocks. Narrate each block's `From phaseTo phase`, `Status`, `Last completed phase`, `Next phase`, and `Report` in the emitted chronological order. If `Run count: 0`, answer only "This task has no recorded runs." and do not claim to have read any file.
26
26
 
27
- `nextRecommendedPhase` in each entry is an **object** `{phase, status, rationale}`, not a phase-name string. Narrate it as `phase` when `phase` is non-empty, and as what `status` says otherwise `pending` (that run did not settle the route), `blocked` (it stopped on something outside the run), `terminal` (the lifecycle ended there). Printing the object itself puts a raw dict in front of the reader.
27
+ `Next phase` is already a fixed scalar projection. Narrate it when non-empty, and otherwise use `Next phase status`: `pending` means that run did not settle the route, `blocked` means it stopped on something outside the run, and `terminal` means the lifecycle ended there.
28
28
 
29
- For a run that has a `reportPath`, read that report record (`.data.json`) to enrich the summary only when the user wants a deeper one (do not read them all automatically).
29
+ For a transition that has a `Report`, run `okstra render-final-report <Report>` and read the rendered Markdown only when the user wants a deeper summary. Do not open the report data JSON directly and do not render every report automatically.
30
30
 
31
31
  ### recap.3 — Free-form Q&A loop
32
32
 
@@ -90,7 +90,7 @@ Write the body to the scratchpad as markdown first, then pass it with `--body-fi
90
90
 
91
91
  **self-check rules (there is no validator, so you keep them yourself):**
92
92
 
93
- 1. **Do not hand-edit a rendered report** (`*.md` / `*.data.json` / `*.html` under `runs/*/reports/`). Because it is regenerated from `data.json`, an edit is overwritten and diverges from the SSOT. Write findings to `notes/` instead.
93
+ 1. **Do not hand-edit a rendered report** (`*.md` / `*.data.json` / `*.html` under `runs/*/reports/`). Report assembly regenerates those artifacts, so write findings to `notes/` instead.
94
94
  2. **Do not author a `user-responses/` file or apply `created-by: user`.** That is the user's decision, and writing it for them forges a decision the user never made. If your evidence supports a particular answer, write that in `notes/` and leave the decision to the user. The one exception is the echo-back confirmation flow of the `okstra-user-response` skill — there the user makes the decision in-session and the CLI is merely a transcription channel, so recording a `created-by: user` sidecar with `write` is legitimate. This exception holds only after the user has explicitly confirmed "correct", and only for verbatim input.
95
95
  3. **Do not write to okstra-managed directories** (`runs/`, `instruction-set/`, `history/`, `recap/`, `.okstra/decisions/`). `notes/` is the only agent-owned lane. `recap/recap-log.jsonl` is the exception — write it, but not by hand; only via the `okstra recap record` CLI.
96
96
  4. **`notes/` is inert to okstra** — no run reads it automatically. After writing, relay the `clarificationResponseArg` the CLI printed (e.g. `--clarification-response <notePath>`) to the user verbatim, telling them it only takes effect when the next run is executed with that argument.
@@ -12,21 +12,17 @@ task-key format: `<project-id>:<task-group>:<task-id>`.
12
12
 
13
13
  **Normalization:** task-key matching is lowercase. Disk segments are slugified (lowercase + non-alphanumeric runs → `-`) per `scripts/okstra_ctl/ids.py:88` (`slugify_task_segment`, the SSOT; `interactive.sh` consumes it via import). Catalog lookup is case-insensitive; file path assembly uses slugified segments.
14
14
 
15
- Lookup methods (in priority order):
16
-
17
- A. **`task-catalog.json` (fast):** read `.okstra/discovery/task-catalog.json`, match `taskKey` lowercase. `latestReportRecordPath` is task-type-agnostic "most recent report".
18
-
19
- B. **`task-manifest.json` (direct):** if catalog missing, slugify task-group / task-id, read `.okstra/tasks/<group-segment>/<task-id-segment>/task-manifest.json`, use `latestReportRecordPath` (task-type-agnostic).
20
-
21
- C. **`timeline.json` (specific run):** for a specific date or run, read `.okstra/tasks/<group-segment>/<id-segment>/history/timeline.json`, filter `runs[]` by `runTimestamp` / `status` / `taskType`, use `runs[].reportPath`.
22
-
23
- D. **Specific task-type (fallback):** `latestReportRecordPath` is task-type-agnostic. For a specific task-type's latest report, look under `.okstra/tasks/<group-segment>/<id-segment>/runs/<task-type-segment>/reports/`, filename pattern `final-report-<task-type-segment>-<NNN>.data.json`. Highest seq is latest. Stage-isolated runs (`implementation`, single-stage `final-verification`) keep their reports one level deeper at `runs/<task-type-segment>/stage-<N>/reports/` — scan those subdirectories too; seq is independent per stage. Cross-verify with `timeline.json`'s `runs[].taskType` filter. If the user wants the full reading copy, render it with `okstra render-final-report <that data.json>`.
15
+ Run `okstra model-io report-input --project-root <projectRoot> --task-ref
16
+ <task-key>` and use `Latest report`. For a specific date, run `okstra model-io
17
+ history-input --project-root <projectRoot> --task-ref <task-key>` and select the
18
+ matching numbered run block's `Report` line. If the user wants the full reading copy,
19
+ render the selected record with `okstra render-final-report <report-path>`.
24
20
 
25
21
  ### report.2 — Confirm existence
26
22
 
27
23
  1. Verify `latestReportRecordPath` is non-empty AND the file exists on disk. Either signal indicates report presence (tolerant).
28
24
  2. If present, display the path and ask the user whether to read it.
29
- 3. If absent, check `task-manifest.json` signals:
25
+ 3. If absent, check the `Current status`, `Work status`, and `Next phase status` projection lines:
30
26
  - `latestReportRecordPath` empty/missing AND `currentStatus != completed` AND `workStatus != done` AND `workflow.nextRecommendedPhase.status != "terminal"` → `This task is not yet complete (currentStatus: <currentStatus>, workStatus: <workStatus>).`
31
27
  - Any signal indicates completion but the file is missing → `Report file does not exist: <path>`
32
28
 
@@ -8,7 +8,8 @@ Trigger phrases: "okstra status", "task status", "current phase", "next phase",
8
8
 
9
9
  ### status.1 — Overall project status
10
10
 
11
- Read `.okstra/discovery/task-catalog.json`. The catalog is the authoritative source — every field listed below (including `workStatus`, `workStatusUpdatedAt`, `workStatusNote`) is projected directly from each `task-manifest.json` by `scripts/okstra_ctl/render.py :: render_task_catalog_discovery`. Do NOT re-open individual manifests for the overview.
11
+ Run `okstra model-io status-input --project-root <projectRoot>`. Use the fixed
12
+ text task blocks as the overview source.
12
13
 
13
14
  | Field | Description |
14
15
  |------|------|
@@ -47,13 +48,13 @@ The `Next` cell is `nextRecommendedPhase.phase`, or `--` when that string is emp
47
48
 
48
49
  Given a specific `task-key` or `task-group + task-id`:
49
50
 
50
- 1. If possible, quickly look it up in `task-catalog.json`.
51
- 2. If necessary, read `.okstra/tasks/<task-group>/<task-id>/task-manifest.json` directly.
52
- 3. If you need the latest run information, read `history/timeline.json` along with the latest run manifest.
51
+ 1. Run `okstra model-io status-input --project-root <projectRoot> --task-ref <task-key>`.
52
+ 2. Use only the named lines in that fixed text projection.
53
53
 
54
54
  Required fields: `taskKey`, `taskType`, `workCategory`, `currentStatus`, `latestRunStatus`, `workflow.{currentPhase, currentPhaseState, phaseStates, lastCompletedPhase, nextRecommendedPhase, awaitingApproval, lastSafeCheckpoint}`, `workStatus`, `workStatusUpdatedAt`, `workStatusNote`, `latestReportRecordPath`, `latestResumeCommandPath`, `historyTimelinePath`.
55
55
 
56
- `workflow.nextRecommendedPhase` is the `{phase, status, rationale}` object described in `status.1` — read its three fields, do not print it whole. A `task-manifest.json` written before the object existed still holds a bare string there; `scripts/okstra_ctl/next_phase.py::promote` is what turns that string into the object, and every CLI-projected surface you can read instead (`task-catalog.json`, `okstra rollup`, `okstra recap`) has already applied it. Prefer those over a raw manifest rather than promoting a legacy string yourself.
56
+ The projection renders next phase, status, and rationale as separate lines.
57
+ It has already promoted legacy values.
57
58
 
58
59
  ```markdown
59
60
  ## okstra Task Status — <task-key>
@@ -120,11 +121,11 @@ Accepted `<status>` values: `todo`, `in-progress`, `blocked`, `done`.
120
121
  **Procedure:** run the update through the CLI (one Bash call, literal `okstra` token) — never edit `task-manifest.json` by hand:
121
122
 
122
123
  ```bash
123
- okstra set-work-status <token> <status> --project-root <projectRoot> --json
124
+ okstra set-work-status <token> <status> --project-root <projectRoot> --text
124
125
  ```
125
126
 
126
127
  - `<token>` is a full task-key or a bare task-id. Add `--task-group <group>` to scope a duplicated id, `--note "<note>"` to set `workStatusNote` (flag omitted → any existing note is left untouched).
127
- - Branch on the stdout JSON: `ok: true` → confirm below. `stage: "ambiguous"` → list `matches[]` (with `_matchedVia`) via a 3-option picker and retry with the chosen full task-key. `stage: "not-found"` → `<TASK-ID> cannot be found.` An invalid `<status>` makes the CLI exit 2 with the allowed-values list — surface it verbatim; nothing was modified.
128
+ - Branch on the fixed text labels: `OK: True` → confirm below. `Stage: ambiguous` → list each `Match` via a 3-option picker and retry with the chosen full task-key. `Stage: not-found` → `<TASK-ID> cannot be found.` An invalid `<status>` makes the CLI exit 2 with the allowed-values list — surface it verbatim; nothing was modified.
128
129
 
129
130
  Confirm in Korean (the block below shows the message shape only — render the actual confirmation text in Korean):
130
131
  ```
@@ -144,4 +145,4 @@ Confirm in Korean (the block below shows the message shape only — render the a
144
145
 
145
146
  Annotate inferred values with `(inferred)` or `(default)`. Do not back-fill on read; only write when the user explicitly issues an update.
146
147
 
147
- **Catalog sync note:** the CLI updates `task-manifest.json` only. `discovery/task-catalog.json` may be stale until the next run regenerates it; downstream consumers (e.g. `okstra-schedule-gen`) re-read each manifest directly.
148
+ The projection commands own catalog/manifest reconciliation; do not repair their storage while inspecting status.
@@ -15,11 +15,11 @@ Apply the standard task-key resolution rule from `SKILL.md` (core): full task-ke
15
15
  ### time.2 — Fetch aggregated data
16
16
 
17
17
  ```bash
18
- okstra time-report <task-key> --project-root <projectRoot> --json
18
+ okstra time-report <task-key> --project-root <projectRoot> --text
19
19
  ```
20
20
 
21
- Returns (all durations are **raw milliseconds**):
22
- - `byTaskType[]` — `{taskType, runs, leadMs, workersMs, cpuSumMs}`, plus `grandTotal`
21
+ Returns fixed labeled text (all durations are **raw milliseconds**):
22
+ - Repeated `Task type` blocks task type, runs, lead ms, workers ms, and CPU sum ms, plus total labels
23
23
  - `perWorker` — `{<taskType>: [{workerId, agents[], runs, totalMs, avgMs}]}`; only workers with a nonzero run appear, and `agents[]` lists agent labels that differ from `workerId`
24
24
  - `perRunWallClock[]` — `{runTimestamp, taskType, wallClockMs}` (max `endedAt` − min `startedAt` per run)
25
25
  - `phaseTimelines[]` — `{runTimestamp, taskType, phases:[{phase, firstAt, wallMsToNext}]}`
@@ -5,7 +5,7 @@ description: Use when the user wants to manage okstra work across multiple proje
5
5
 
6
6
  # OKSTRA Manager
7
7
 
8
- Thin conversational wrapper over `okstra manager`. Manager state and child launch decisions belong to the CLI JSON/output, not to this skill.
8
+ Thin conversational wrapper over `okstra manager`. Manager state and child launch decisions belong to the CLI fixed output, not to this skill.
9
9
 
10
10
  ## Bash Invocation Rule
11
11
 
@@ -14,18 +14,20 @@ Every command in this skill must begin with the literal token `okstra`. Do not i
14
14
  ## Command Surface
15
15
 
16
16
  Use the CLI output as the source of truth.
17
+ Nested project, manifest, child, snapshot, and directive values are carried by
18
+ the CLI's numbered count/name/value rows; do not omit or reconstruct them.
17
19
 
18
20
  ```bash
19
- okstra manager init --manager-id <manager-id> --json
20
- okstra manager discover-projects --json
21
- okstra manager new project --manager-id <manager-id> --project-id <project-id> --project-root <abs-path> [--role <role>] [--tag <tag>] --json
22
- okstra manager new task-group --manager-id <manager-id> --task-group <task-group> --json
23
- okstra manager new task --manager-id <manager-id> --task-group <task-group> --task-id <task-id> --task <project-id:task-group:task-id> --json
24
- okstra manager task status --manager-id <manager-id> --task-group <task-group> --task-id <task-id> --json
25
- okstra manager task sync --manager-id <manager-id> --task-group <task-group> --task-id <task-id> --json
26
- okstra manager task assign --manager-id <manager-id> --task-group <task-group> --task-id <task-id> --project-id <project-id> [--child-task-id <child-task-id>] [--role <role>] [--tag <tag>] [--assignment <text>] --json
27
- okstra manager task note --manager-id <manager-id> --task-group <task-group> --task-id <task-id> --scope <shared|project> [--project-id <project-id>] --body <text> --json
28
- okstra manager task run --manager-id <manager-id> --project-id <project-id> --task-group <task-group> --task-id <task-id> [--child-task-id <child-task-id>] --json
21
+ okstra manager init --manager-id <manager-id>
22
+ okstra manager discover-projects
23
+ okstra manager new project --manager-id <manager-id> --project-id <project-id> --project-root <abs-path> [--role <role>] [--tag <tag>]
24
+ okstra manager new task-group --manager-id <manager-id> --task-group <task-group>
25
+ okstra manager new task --manager-id <manager-id> --task-group <task-group> --task-id <task-id> --task <project-id:task-group:task-id>
26
+ okstra manager task status --manager-id <manager-id> --task-group <task-group> --task-id <task-id>
27
+ okstra manager task sync --manager-id <manager-id> --task-group <task-group> --task-id <task-id>
28
+ okstra manager task assign --manager-id <manager-id> --task-group <task-group> --task-id <task-id> --project-id <project-id> [--child-task-id <child-task-id>] [--role <role>] [--tag <tag>] [--assignment <text>]
29
+ okstra manager task note --manager-id <manager-id> --task-group <task-group> --task-id <task-id> --scope <shared|project> [--project-id <project-id>] --body <text>
30
+ okstra manager task run --manager-id <manager-id> --project-id <project-id> --task-group <task-group> --task-id <task-id> [--child-task-id <child-task-id>]
29
31
  ```
30
32
 
31
33
  - Public child task identity is `project-id:task-group:task-id`.
@@ -36,9 +38,9 @@ okstra manager task run --manager-id <manager-id> --project-id <project-id> --ta
36
38
 
37
39
  For launching child work:
38
40
 
39
- 1. Run `okstra manager task sync ... --json` if the manager snapshot must be refreshed first.
40
- 2. Run `okstra manager task run ... --json`.
41
- 3. Read the returned launch packet fields such as `backend`, `projectRoot`, `contextPath`, and `runArgs`.
41
+ 1. Run `okstra manager task sync ...` if the manager snapshot must be refreshed first.
42
+ 2. Run `okstra manager task run ...`.
43
+ 3. Read the returned fixed fields `Backend`, `Worker dispatch backend`, `Project root`, `Context path`, and every numbered `Run arg N`.
42
44
  4. Use that launch packet for the host-native child lead handoff.
43
45
 
44
46
  The launch packet remains the source of truth. Do not rebuild child args by hand.
@@ -54,7 +54,7 @@ searching so the rest of the skill can scope to it.
54
54
  1. Enumerate existing groups to build recommendations:
55
55
 
56
56
  ```bash
57
- okstra memory groups --json
57
+ okstra memory groups
58
58
  ```
59
59
 
60
60
  2. Present a 3-option picker (most-used existing group, next existing group,
@@ -107,5 +107,5 @@ okstra memory show "<memory-id>"
107
107
  okstra memory archive "<memory-id>"
108
108
  ```
109
109
 
110
- Prefer `--json` when you need to parse IDs, then present a short human summary
111
- to the user.
110
+ Use the fixed text rows emitted by these commands, then present a short human
111
+ summary to the user.
@@ -58,7 +58,7 @@ the user states explicitly wins verbatim; never rewrite it.
58
58
  ### A1. Pick a template
59
59
 
60
60
  ```bash
61
- okstra pr template list --json
61
+ okstra pr template list
62
62
  ```
63
63
 
64
64
  - If `templates` is non-empty, present a picker: 1–2 recommended templates from
@@ -71,7 +71,7 @@ Carry the chosen template name as `<template>` (`default` for the bundled one).
71
71
  ### A2. Pick the base branch
72
72
 
73
73
  ```bash
74
- okstra pr branches --json
74
+ okstra pr branches
75
75
  ```
76
76
 
77
77
  Present a 3-option base picker from `recommended` (top entries) plus `Enter directly`
@@ -80,10 +80,11 @@ last. Carry the choice as `<base>`.
80
80
  ### A3. Build the generation bundle and fill the template
81
81
 
82
82
  ```bash
83
- okstra pr gen --base <base> --template <template> --json
83
+ okstra pr gen --base <base> --template <template>
84
84
  ```
85
85
 
86
- Parse `{base, currentBranch, templateName, template, commits, diffStat}`. Then
86
+ Read the fixed `Base`, `Current branch`, `Template name`, `Commits`, `Diff stat`,
87
+ and `Template` sections. Then
87
88
  read the full diff honestly — it is the source of truth:
88
89
 
89
90
  ```bash
@@ -17,10 +17,10 @@ Run one Bash tool call, starting with the literal token `okstra` (never wrapped
17
17
  <!-- END FRAGMENT: bash-invocation-rule -->
18
18
 
19
19
  ```bash
20
- okstra preflight --runtime claude-code --json
20
+ okstra preflight --runtime claude-code
21
21
  ```
22
22
 
23
- Parse the stdout JSON. `ok: true` carry `projectRoot` as a literal string. `ok: false` tell the user to run `/okstra-setup` first, then stop.
23
+ On `Okstra preflight: ready`, carry the fixed `Project root` line. On `Okstra preflight: failed`, show `Reason` and `Recovery`, then stop.
24
24
 
25
25
  <!-- BEGIN FRAGMENT: preflight-outdated-cli -->
26
26
  If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary).
@@ -35,24 +35,14 @@ If the call fails with `unknown command: preflight`, the `okstra` binary on PATH
35
35
  ## Step 2: Fetch the roll-up
36
36
 
37
37
  ```bash
38
- okstra rollup --task-group <group> --project-root <projectRoot> --json
38
+ okstra rollup --task-group <group> --project-root <projectRoot> --text
39
39
  ```
40
40
 
41
- Omit `--task-group` for the whole project. The JSON shape (all durations are **raw milliseconds**):
42
-
43
- - `taskGroup` — the scope (`null` = whole project), `taskCount` — number of tasks.
44
- - `tasks[]` — per task: `taskKey, taskGroup, taskId, taskType, workCategory, workStatus, currentPhase, currentPhaseState, nextRecommendedPhase, latestRunStatus, updatedAt, reportPath, runCount, cpuSumMs, wallClockMs, errorCount`, plus `criticRuns, criticGapsProposed, criticGapsMerged, criticGapsRejected, criticGapsUnverified`.
45
- - `nextRecommendedPhase` is an **object** `{phase, status, rationale}`, not a phase-name string. Anywhere you surface it, print `nextRecommendedPhase.phase` — or `--` when that string is empty, which is what `status` `pending` / `blocked` / `terminal` all produce. Never interpolate the object into a table cell or a sentence: it renders as a raw dict.
46
- - `totals` — `runs, cpuSumMs, wallClockMs, errors`, plus `byWorkStatus`, `byWorkCategory`, `byCurrentPhase`, `byTaskType` (each a `{value: count}` map), plus `critic` (`runsWithCritic, gapsProposed, gapsMerged, gapsRejected, gapsUnverified`).
47
- - The coverage critic is opt-in, so `totals.critic.runsWithCritic == 0` means it was never used — report that as "not used", never as a zero-yield result. When it IS non-zero, the merge rate (`gapsMerged / gapsProposed`) is what tells the user whether the pass earns its tokens; state it only when at least one run used it.
48
-
49
- `runCount` counts every timeline run; `cpuSumMs`/`wallClockMs` only reflect runs that reached Phase 7 usage, so they can be `0` while `runCount > 0`. `reportPath` is project-relative and may be empty (task not yet reported).
50
-
51
- If `taskCount` is `0`, tell the user there are no okstra tasks in that scope and stop.
41
+ Omit `--task-group` for the whole project. The command returns fixed, ordered label/value lines. Read only those labels; do not request machine output or open an artifact to recover omitted fields. Durations are raw milliseconds. If `Task count` is `0`, tell the user there are no okstra tasks in that scope and stop.
52
42
 
53
43
  ## Step 3: Render the roll-up table
54
44
 
55
- Convert every `*Ms` to `HH:MM:SS` (zero-pad; never show raw ms). `cpuSumMs` is CPU-sum (lead + workers overlap), not wall-clock label it "CPU"; only surface `wallClockMs` when the user asks. Sort tasks by `updatedAt` desc.
45
+ Convert each returned `ms` label to `HH:MM:SS` (zero-pad; never show raw ms). CPU sum includes overlapping lead and worker time. Use the returned task order.
56
46
 
57
47
  ```markdown
58
48
  ## okstra Rollup — <task-group or "whole project"> (<taskCount> tasks)
@@ -66,7 +56,7 @@ Convert every `*Ms` to `HH:MM:SS` (zero-pad; never show raw ms). `cpuSumMs` is C
66
56
  **workStatus:** done 1 · in-progress 1 **category:** bugfix 1 · feature 1
67
57
  ```
68
58
 
69
- Render `Report` as `✓` when `reportPath` is non-empty, else `—`. Build the status/category lines from the `totals` tally maps verbatim do not count the `tasks[]` array yourself.
59
+ Render `Report` as `✓` when the corresponding `Task N report path` is non-empty, else `—`. Use the numbered fixed labels and total labels verbatim; do not re-count tasks.
70
60
 
71
61
  ## Step 4: Synthesize the digest (the summary)
72
62
 
@@ -70,16 +70,16 @@ The host-native provider runs as the current lead session when its role is suppo
70
70
  Run one Bash tool call (Bash invocation rule from the top of this file applies):
71
71
 
72
72
  ```bash
73
- okstra preflight --runtime <host-runtime> --json
73
+ okstra preflight --runtime <host-runtime>
74
74
  ```
75
75
 
76
- Parse the stdout JSON. If `ok: false` with `stage: runtime_readiness`, show `runtimeReadiness.status` and every readiness check, including each adapter-provided `action`, then stop before Step 2. Do not relabel a host login, license, daemon, trust, or other readiness failure as missing Okstra setup. Any other `ok: false` response (or `okstra` not on `PATH` at all) → tell the user: "okstra not set up — run `/okstra-setup` first." Then stop. If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary). Do **not** try to invoke `npx -y okstra@latest ...` as a fallback — `npx` is not on the literal-token allow-list and will force a confirmation prompt on every wizard call afterward. Every subsequent `okstra <subcmd>` call self-bootstraps its Python path, so never `export PYTHONPATH=...`.
76
+ Read the fixed text lines. If the first line is `Okstra preflight: failed`, show `Runtime readiness` and every repeated `Readiness check`, `Readiness check status`, and `Readiness check action`, then stop before Step 2. Show `Reason` and `Recovery` for every failure. Do not relabel a host login, license, daemon, trust, or other readiness failure as missing Okstra setup. If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary). Do **not** try to invoke `npx -y okstra@latest ...` as a fallback — `npx` is not on the literal-token allow-list and will force a confirmation prompt on every wizard call afterward. Every subsequent `okstra <subcmd>` call self-bootstraps its Python path, so never `export PYTHONPATH=...`.
77
77
 
78
- When `runtimeReadiness` is present on an `ok: true` response, require `runtimeReadiness.status: ready` before Step 2. These checks come from the selected host adapter and are independent of worker-provider choices. A `blocked` or `unknown` status is a host readiness failure regardless of check IDs: show the status and checks, then stop before Step 2. Any other readiness status is unrecognized runtime output: show it and stop before Step 2 instead of guessing that the host is ready.
78
+ On `Okstra preflight: ready`, require `Runtime readiness: ready` before Step 2. These checks come from the selected host adapter and are independent of worker-provider choices. Any other readiness value is unrecognized runtime output: show it and stop before Step 2 instead of guessing that the host is ready.
79
79
 
80
- For a ready response, read the absolute file path in `runtimeReadiness.relayContract` with the current host's file-read primitive. Do not derive the path from the host ID or search `PATH`. In that file, find the `Wizard interaction relay` JSON block, require `schemaVersion: 1` and `runtime` equal to `runtimeReadiness.runtime`, then take its `semanticFunctions` allowlist and intersect it with the functions the live harness exposes. Pass only that intersection to Step 2; `plain_text_input` must be present. Keep the parsed `interactions` object for Step 3's function/input/response conversion. An unreadable file, malformed block, runtime mismatch, absent `plain_text_input`, or later interaction kind missing from the object is a host relay contract failure: show the problem and stop rather than guessing.
80
+ For a ready response, read the absolute path in the fixed `Relay contract` line with the current host's file-read primitive. Do not derive the path from the host ID or search `PATH`. In that file, find the `Wizard interaction relay` JSON block, require `schemaVersion: 1` and `runtime` equal to the fixed `Runtime` line, then take its `semanticFunctions` allowlist and intersect it with the functions the live harness exposes. The live harness does not expose tools named `native_single_select`. Map each allowlist token to the matching `interactions` kind (`native_single_select` → `native-single`, `native_multi_select` → `native-multi`, `native_question_group` → `native-group`). Include the token in the intersection only when this session can call the string in that kind's `function` field. If the kind is absent from `interactions`, omit the token. Pass only that intersection to Step 2; `plain_text_input` must be present. Keep the parsed `interactions` object for Step 3's function/input/response conversion. An unreadable file, malformed block, runtime mismatch, absent `plain_text_input`, or later interaction kind missing from the object is a host relay contract failure: show the problem and stop rather than guessing.
81
81
 
82
- If `runtimeReadiness` is absent, preserve compatibility with an older preflight response: carry `projectRoot` and `projectId` into Step 2 and treat it as a response with no `relayContract`. If readiness exists but `relayContract` is absent, also enter the compatibility branch below. In that branch only, declare `plain_text_input` and keep its built-in `interactions` mapping for Step 3; do not assume a native tool from the host ID. The existing `unknown command: preflight` branch remains the authoritative stale-CLI failure.
82
+ If the successful fixed projection has `Relay contract: -`, enter the compatibility branch below. In that branch only, declare `plain_text_input` and keep its built-in `interactions` mapping for Step 3; do not assume a native tool from the host ID. The existing `unknown command: preflight` branch remains the authoritative stale-CLI failure.
83
83
 
84
84
  ### Legacy text relay compatibility
85
85
 
@@ -158,7 +158,7 @@ Output: the same `{ok, next}` JSON described above. The first `next` is always `
158
158
 
159
159
  Repeat until `next.kind == "done"` (or `"aborted"` — terminal cancel, see "How the wizard talks to you"):
160
160
 
161
- 1. **Render** the prompt according to `next.interaction.kind` using the relay rules above. **Always append the progress marker to the rendered question label**: suffix it with ` (<next.progress.label>)` — render `progress.label` exactly as the wizard sent it, never recompute it. Example: label `Step 8/11 · 3 steps remaining` → `Select a model (Step 8/11 · 3 steps remaining)`. Re-prompts after `ok: false` reuse `current.progress.label` the same way. The progress marker is presentation-only — never send it back to the wizard as part of an answer.
161
+ 1. **Render** the prompt according to `next.interaction.kind` using the relay rules above. For a native kind, invoke the `function` string from that same `interactions` entry — the Claude Code picker, the Grok picker, and the Codex picker are different names, and substituting one for another is a relay-contract failure. **Always append the progress marker to the rendered question label**: suffix it with ` (<next.progress.label>)` — render `progress.label` exactly as the wizard sent it, never recompute it. Example: label `Step 8/11 · 3 steps remaining` → `Select a model (Step 8/11 · 3 steps remaining)`. Re-prompts after `ok: false` reuse `current.progress.label` the same way. The progress marker is presentation-only — never send it back to the wizard as part of an answer.
162
162
  2. **Submit** the answer — call `okstra wizard step` with the literal state-file path from Step 2 and the literal user answer (no shell variables, no `$(...)`):
163
163
  ```bash
164
164
  okstra wizard step --state-file /var/folders/.../okstra-wizard.AbCd.json --answer preprod
@@ -323,7 +323,7 @@ If `render-bundle` stdout carries an `okstra concurrent-run stages: <stages>` la
323
323
 
324
324
  If `render-bundle` fails with a `PrepareError` containing `Recorded stage SHAs no longer match the git history`, the git history changed outside okstra (rebase / squash / review-feedback amend / branch deletion). Never fix the registry/consumers by hand; recover in this order:
325
325
 
326
- 1. Run the `okstra git-reconcile … --check --json` command printed in the error message verbatim to get the stale report. (Items whose content-identity is proven by patch-id were already auto-reconciled by prepare, so only confirm items remain here.)
326
+ 1. Run the `okstra git-reconcile … --check --text` command printed in the error message verbatim to get the stale report. (Items whose content-identity is proven by patch-id were already auto-reconciled by prepare, so only confirm items remain here.)
327
327
  2. For each confirm item, present a 3-option picker to the user:
328
328
  - **Re-record to the `stage-<N>` branch's current tip (recommended)** — when an intended change such as review feedback lives on that branch.
329
329
  - **Enter a different ref directly** — the user names a commit/branch/tag.
@@ -24,10 +24,10 @@ Run one Bash tool call, starting with the literal token `okstra` (never wrapped
24
24
  <!-- END FRAGMENT: bash-invocation-rule -->
25
25
 
26
26
  ```bash
27
- okstra preflight --runtime claude-code --json
27
+ okstra preflight --runtime claude-code
28
28
  ```
29
29
 
30
- Parse the stdout JSON. `ok: true` carry `projectRoot` as a literal string and use it to locate `.okstra/discovery/task-catalog.json` and the task-group directory. `ok: false` tell the user to run `/okstra-setup` first, then stop.
30
+ On `Okstra preflight: ready`, carry the fixed `Project root` line for the later `model-io` calls. On `Okstra preflight: failed`, show `Reason` and `Recovery`, then stop.
31
31
 
32
32
  <!-- BEGIN FRAGMENT: preflight-outdated-cli -->
33
33
  If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary).
@@ -78,15 +78,19 @@ One computation rule the template scaffold cannot carry inline:
78
78
 
79
79
  ### Step 1: Resolve task-group and collect tasks
80
80
 
81
- 1. Read `.okstra/discovery/task-catalog.json`.
82
- 2. **Resolve which task-group to schedule never silently guess.**
83
- - The user **explicitly named a task-group** (as the `/okstra-schedule-gen [task-group]` argument or unambiguously in the request) → use that token; skip the picker and go to sub-step 3.
84
- - The user **named no task-group, or the named token matches 0 or ≥2 groups** → present a 3-option picker via `AskUserQuestion` and do NOT proceed until the user chooses. Build the options from the catalog: walk `tasks[]` in catalog order (already `updatedAt` desc — see `scripts/okstra_ctl/render.py:654`), collect distinct `taskGroupPathSegment` values that have ≥1 entry whose resolved `workStatus` is **non-done** (defer to Step 2's inference table), and offer the newest **1–2** such groups as recommendations. The **last option is always `Enter directly`** (free-text group token, fed into sub-step 3). Label each recommendation with its non-done task count (e.g. `uploadFont (non-done 3)`).
85
- - If **zero groups have a non-done task** (or the catalog is empty), do NOT open a picker — emit `All tasks in this task-group are done. There is no schedule to generate.` (or `That task-group could not be found.` when the catalog has no tasks at all) and stop **without creating a file**.
86
- 3. **Normalise the resolved `<task-group>`:** lowercase it, then strip every character that is not `[a-z0-9]`. Apply the same transform to each entry's `taskGroupPathSegment`. Match on equality — this is the single comparison rule; do NOT also fall back to the raw `taskGroup` field.
87
- 4. If no tasks found, output `That task-group could not be found.` and stop.
88
- 5. For each matched task, read `.okstra/tasks/<task-group-segment>/<task-id-segment>/task-manifest.json` directly. Catalog data may be stale; the manifest is authoritative.
89
- 6. **Derive `<project-id>`** for the header: prefer `task-catalog.json`'s top-level `projectId`, otherwise the first matched manifest's `projectId`. Do not invent a value.
81
+ 1. **Resolve which task-group to schedule — never silently guess.** The user may name it in the `/okstra-schedule-gen [task-group]` argument. If the user did not name one, ask one free-text question for its task-group token before continuing.
82
+ 2. Render the group's authoritative task metadata with the fixed view:
83
+
84
+ ```bash
85
+ okstra model-io schedule-input --project-root <projectRoot> --task-group <task-group>
86
+ ```
87
+
88
+ The `## Tasks` section is authoritative for each task's key, status,
89
+ category, type, and current phase. If it is `- None`, output `That
90
+ task-group could not be found.` and stop without creating a file. Do not
91
+ read task catalogs or task manifests directly.
92
+ 3. **Derive `<project-id>`** for the header from the fixed view's `Project ID`.
93
+ Do not invent a value.
90
94
 
91
95
  ### Step 2: Filter by workStatus
92
96
 
@@ -99,18 +103,18 @@ If 0 tasks remain, output `All tasks in this task-group are done. There is no sc
99
103
  For each in-scope task, the **authoritative source is its `implementation-planning` Stage Map resolved by the CLI**. Do not hand-parse it or use `latestReportRecordPath` to choose its source. Call:
100
104
 
101
105
  ```bash
102
- okstra stage-map <task-key> --json
106
+ okstra stage-map <task-key> --text
103
107
  ```
104
108
 
105
- The response is source-aware: `{ok, taskKey, taskRoot, state, sourcePlanPath, stages:[…], doneStages:[int], planning:{…}}`. Each stage row carries `stage_number`, `title`, `depends_on`, `step_count`, `exit_contract_summary` and — from a schema-v2 report — that stage's `stepwiseExecution` (the numbered steps, each with `action`, `files`, `command`, `expected`), `sliceValue`, `acceptance` and `exitContract`. `planning` carries the report's task-level rows: `rollbackStrategy`, `validationChecklist`, `crossProjectDependencies`, `dependencyMigrationRisk`, `recommendedOption`. Branch on it explicitly:
109
+ The fixed response is source-aware. It carries `Status`, `Task key`, `Task root`, `State`, `Source plan path`, plus lossless numbered `Stages`, `Done stages`, and `Planning` count/name/value rows. Stage fields include `stage_number`, `title`, `depends_on`, `step_count`, `exit_contract_summary` and — from a schema-v2 report — that stage's `stepwiseExecution` (`action`, `files`, `command`, `expected`), `sliceValue`, `acceptance` and `exitContract`. Planning fields include `rollbackStrategy`, `validationChecklist`, `crossProjectDependencies`, `dependencyMigrationRisk`, and `recommendedOption`. Branch on those fixed fields explicitly:
106
110
 
107
111
  The resolved source, when ready, is a report under `runs/implementation-planning`; the CLI owns choosing exactly one report from that domain.
108
112
 
109
- - `ok: true, state: "ready"` — preserve `sourcePlanPath`, stage rows, and `doneStages`. Compute unfinished stages as `stages doneStages`. Only unfinished stages can be selected. Every selected stage's transitive prerequisites must be either selected or present in `doneStages`; the completed prerequisite closure is retained as evidence, never rendered as forward work.
110
- - `ok: true, state: "missing"` — record an empty source and empty stage sets. Tag the task `[NEEDS-PLANNING]`, skip the stage picker, and render task-level metadata only, with no forward Work Breakdown row, Gantt row, or day total.
111
- - `ok: false` or any state other than `ready` and `missing` — this is a structured Stage Map error, such as a corrupt or conflicting plan source. Stop before drafting, preserve the CLI `stage` and `reason` in the user-facing error, and do not guess from another report.
113
+ - `Status: ready`, `State: ready` — preserve `Source plan path`, stage rows, and done stages. Compute unfinished stages as stages minus done stages. Only unfinished stages can be selected. Every selected stage's transitive prerequisites must be either selected or done; the completed prerequisite closure is retained as evidence, never rendered as forward work.
114
+ - `Status: ready`, `State: missing` — record an empty source and empty stage sets. Tag the task `[NEEDS-PLANNING]`, skip the stage picker, and render task-level metadata only, with no forward Work Breakdown row, Gantt row, or day total.
115
+ - `Status: error` or any state other than `ready` and `missing` — stop before drafting, preserve `Failure stage` and `Failure reason` in the user-facing error, and do not guess from another report.
112
116
 
113
- For `ready`, the CLI response is the source for everything the schedule renders — stage rows and `planning` together. Read `sourcePlanPath` only for the task-level Priority / Risk / Scope / Repos that the payload does not carry, and read no further into it: transcribing the payload is the whole point of Step 4. Read header metadata from `task-manifest.json`: `taskId`, `taskGroup`, `taskKey`, `workCategory`, `workStatus`, `taskType`, and `workflow.currentPhase`. Blocking and approval items are not extracted (see Audience & authority).
117
+ For `ready`, the CLI response is the source for everything the schedule renders — stage rows and `planning` together. Read `sourcePlanPath` only for the task-level Priority / Risk / Scope / Repos that the payload does not carry, and read no further into it: transcribing the payload is the whole point of Step 4. Take task key, category, status, type, and current phase from the fixed `model-io schedule-input` view. Blocking and approval items are not extracted (see Audience & authority).
114
118
 
115
119
  If unfinished stages are empty while `workStatus` is not `done`, render `_Complete — no remaining stage_` under the task's phase section and contribute no forward day total.
116
120
 
@@ -58,29 +58,37 @@ running the legacy `okstra-install.sh` — that path is dev-only.
58
58
  ## Step 2: Resolve PROJECT_ROOT
59
59
 
60
60
  ```bash
61
- okstra check-project --json
61
+ okstra preflight
62
62
  ```
63
63
 
64
- Parse the JSON from stdout. The shape is `{ok, projectRoot, projectJsonPath, projectId, stage?}`.
64
+ Read the fixed `Okstra preflight`, `Project root`, `Project JSON`, `Project ID`,
65
+ `Reason`, and `Recovery` lines.
65
66
 
66
- - `ok: true` → carry `projectRoot` as a literal absolute string and paste it into every subsequent command in this skill.
67
- - `ok: false`, `stage: "resolve"` → ask the user (`AskUserQuestion`, free text) for an absolute project root and rerun as a separate Bash tool call with the literal absolute path:
67
+ - `Ok: true` → carry `Project root` as a literal absolute string and paste it into every subsequent command in this skill.
68
+ - `Ok: false`, `Stage: resolve` → ask the user (`AskUserQuestion`, free text) for an absolute project root and rerun as a separate Bash tool call with the literal absolute path:
68
69
 
69
70
  ```bash
70
- okstra check-project --cwd /abs/path/from/user --json
71
+ okstra preflight --cwd /abs/path/from/user
71
72
  ```
72
73
 
73
- - `ok: false`, `stage: "project_json_missing"` → proceed to Step 3 (this is the normal create path).
74
- - `ok: false`, any other `stage` (`python`, `parse`, `project_json_invalid`) → show the JSON `reason` field to the user verbatim and follow the recovery it names (typically `okstra doctor` to diagnose, then `okstra ensure-installed` or re-running the Step 1 install). `reason` is the SSOT — do not hand-enumerate stage causes.
74
+ - `Ok: false`, `Stage: project_json_missing` → proceed to Step 3 (this is the normal create path).
75
+ - `Ok: false`, any other `Stage` (`python`, `parse`, `project_json_invalid`) → show the fixed `Reason` line to the user verbatim and follow the `Recovery` line (typically `okstra doctor` to diagnose, then `okstra ensure-installed` or re-running the Step 1 install). `Reason` is the SSOT — do not hand-enumerate stage causes.
75
76
 
76
- ## Step 3: Inspect or create `project.json`
77
+ ## Step 3: Project metadata setup
77
78
 
78
- Use the `Read` tool on the literal absolute path `<projectRoot>/.okstra/project.json` (substitute the literal `projectRoot` value parsed in Step 2). If `Read` errors with "file does not exist", treat that as the "create" branch below; otherwise the file exists and you can inspect its contents inline.
79
+ Render the existing project metadata with the purpose-specific view. Paste the
80
+ literal `projectRoot` value parsed in Step 2:
79
81
 
80
- If the file exists, surface its `projectId`/`projectRoot` and ask whether to
81
- keep or overwrite. Default is to keep — okstra refuses to change `projectId`
82
- on an existing project (see `okstra_project.resolver.upsert_project_json`),
83
- so overwriting requires manually deleting the file first.
82
+ ```bash
83
+ okstra model-io project-context --project-root /abs/path/to/projectRoot
84
+ ```
85
+
86
+ If the command reports that project metadata is missing, treat that as the
87
+ "create" branch below. Otherwise, surface the rendered `Project ID` and
88
+ `Project root`, then ask whether to keep or overwrite. Default is to keep —
89
+ okstra refuses to change `projectId` on an existing project (see
90
+ `okstra_project.resolver.upsert_project_json`), so overwriting requires
91
+ manually deleting the file first.
84
92
 
85
93
  If the file does NOT exist, ask via `AskUserQuestion`:
86
94
 
@@ -1,6 +1,6 @@
1
1
  # Optional project configuration (okstra-setup)
2
2
 
3
- Read this only when the user asks to customise one of the areas below after
3
+ Use this reference only when the user asks to customise one of the areas below after
4
4
  `project.json` exists. The built-in defaults work for most projects — none of
5
5
  these sections is required for a working setup.
6
6
 
@@ -189,7 +189,7 @@ okstra config set pr-template-path "<typed-path>" --scope <project|global>
189
189
  ```
190
190
 
191
191
  The command validates the value (global rejects relative paths) and writes
192
- atomically. Surface its stdout JSON. If the user chose `Later`, tell them
192
+ atomically. Surface its fixed text result. If the user chose `Later`, tell them
193
193
  they can register later via the same `okstra config set` command or the
194
194
  per-run override prompt during the next release-handoff run.
195
195
 
@@ -17,11 +17,11 @@ Read-only project usage snapshot. The CLI owns every sum; never re-add rows.
17
17
  Run one literal Bash call:
18
18
 
19
19
  ```bash
20
- okstra preflight --runtime claude-code --json
20
+ okstra preflight --runtime claude-code
21
21
  ```
22
22
 
23
- On `ok:true`, carry `projectRoot`. On `ok:false`, tell the user to run `/okstra-setup` first
24
- and stop.
23
+ On `Okstra preflight: ready`, carry the fixed `Project root` line. On
24
+ `Okstra preflight: failed`, show `Reason` and `Recovery`, then stop.
25
25
 
26
26
  <!-- BEGIN FRAGMENT: preflight-outdated-cli -->
27
27
  If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary).
@@ -37,7 +37,7 @@ If the call fails with `unknown command: preflight`, the `okstra` binary on PATH
37
37
  ## Step 2: Fetch once
38
38
 
39
39
  ```bash
40
- okstra usage-report --days 30 --project-root <projectRoot> --json
40
+ okstra usage-report --days 30 --project-root <projectRoot> --text
41
41
  ```
42
42
 
43
43
  Replace `30` only with the resolved positive integer. Do not wrap the command in
@@ -45,23 +45,23 @@ Replace `30` only with the resolved positive integer. Do not wrap the command in
45
45
 
46
46
  ## Step 3: Render
47
47
 
48
- If `ok:false`, report `stage` and `reason`, then stop. If `runs.total == 0`, say
48
+ If `Status` is `error`, report `Failure stage` and `Failure reason`, then stop. If `Runs total` is `0`, say
49
49
  `No okstra usage found in the last N days.`, omit the table, and continue to Step 4.
50
50
 
51
- Otherwise, render `byTaskType` in returned order:
51
+ Otherwise, render the numbered `Task type N ...` fixed fields in returned order:
52
52
 
53
53
  | Task type | Runs | Coverage | Raw tokens | Billable | Cost | CPU | Wall |
54
54
  |---|---:|---:|---:|---:|---:|---:|---:|
55
55
 
56
- - `Coverage` = returned `collectedRuns/runs`; never calculate a new aggregate.
56
+ - `Coverage` = returned `Task type N collection rate`; never divide or calculate a new aggregate.
57
57
  - Format tokens with K/M suffixes, milliseconds as zero-padded `HH:MM:SS`, and
58
58
  USD to two decimals. For tokens, use one decimal at `>= 1,000` (`K`) and
59
59
  `>= 1,000,000` (`M`), trimming a trailing `.0`; below 1,000 render the integer.
60
- - Render the `totals` object as the final bold row.
60
+ - Render the fixed total labels as the final bold row.
61
61
  - Never treat unavailable usage as collected zero usage.
62
62
 
63
63
  ## Step 4: Diagnostics
64
64
 
65
- - Render non-zero `unavailable` and `warnings` counts after the Step 3 output.
66
- - If `unmatchedModels` is non-empty, mark Cost with `*` when the table exists and
65
+ - Render non-zero numbered `Unavailable N` and `Warning N` fields after the Step 3 output.
66
+ - If numbered `Unmatched model N name` fields exist, mark Cost with `*` when the table exists and
67
67
  always say known-price cost excludes those exact model names.