okstra 0.180.0 → 0.184.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 (233) hide show
  1. package/README.md +1 -1
  2. package/dist/cli-registry.mjs +16 -2
  3. package/dist/cli-registry.mjs.map +1 -1
  4. package/dist/commands/execute/render-bundle.d.mts +4 -2
  5. package/dist/commands/execute/render-bundle.mjs +46 -5
  6. package/dist/commands/execute/render-bundle.mjs.map +1 -1
  7. package/dist/commands/execute/run.mjs +11 -3
  8. package/dist/commands/execute/run.mjs.map +1 -1
  9. package/dist/commands/inspect/model-io.d.mts +1 -0
  10. package/dist/commands/inspect/model-io.mjs +25 -0
  11. package/dist/commands/inspect/model-io.mjs.map +1 -0
  12. package/dist/commands/inspect/stage-map.mjs +29 -8
  13. package/dist/commands/inspect/stage-map.mjs.map +1 -1
  14. package/dist/commands/inspect/task-list.mjs +52 -6
  15. package/dist/commands/inspect/task-list.mjs.map +1 -1
  16. package/dist/commands/inspect/user-response.mjs +14 -4
  17. package/dist/commands/inspect/user-response.mjs.map +1 -1
  18. package/dist/commands/lifecycle/check-project.d.mts +1 -0
  19. package/dist/commands/lifecycle/check-project.mjs +69 -50
  20. package/dist/commands/lifecycle/check-project.mjs.map +1 -1
  21. package/dist/commands/lifecycle/contract-check.d.mts +1 -0
  22. package/dist/commands/lifecycle/contract-check.mjs +18 -0
  23. package/dist/commands/lifecycle/contract-check.mjs.map +1 -0
  24. package/dist/commands/lifecycle/preflight.mjs +154 -51
  25. package/dist/commands/lifecycle/preflight.mjs.map +1 -1
  26. package/dist/commands/pr/pr.d.mts +1 -0
  27. package/dist/commands/pr/pr.mjs +19 -1
  28. package/dist/commands/pr/pr.mjs.map +1 -1
  29. package/dist/commands/report/agent-activity.mjs +2 -2
  30. package/dist/commands/report/translate.mjs +3 -0
  31. package/dist/commands/report/translate.mjs.map +1 -1
  32. package/dist/lib/host-registry-client.mjs +13 -9
  33. package/dist/lib/host-registry-client.mjs.map +1 -1
  34. package/docs/architecture.md +13 -2
  35. package/docs/cli.md +31 -15
  36. package/docs/container.md +6 -4
  37. package/docs/contributor-change-matrix.md +1 -1
  38. package/docs/for-ai/README.md +2 -2
  39. package/docs/for-ai/skills/okstra-brief-gen.md +5 -3
  40. package/docs/for-ai/skills/okstra-code-review.md +4 -4
  41. package/docs/for-ai/skills/okstra-container-build.md +20 -17
  42. package/docs/for-ai/skills/okstra-inspect.md +20 -23
  43. package/docs/for-ai/skills/okstra-manager.md +19 -18
  44. package/docs/for-ai/skills/okstra-memory.md +2 -2
  45. package/docs/for-ai/skills/okstra-pr-gen.md +3 -3
  46. package/docs/for-ai/skills/okstra-rollup.md +14 -13
  47. package/docs/for-ai/skills/okstra-run.md +7 -3
  48. package/docs/for-ai/skills/okstra-schedule-gen.md +15 -18
  49. package/docs/for-ai/skills/okstra-setup.md +7 -7
  50. package/docs/for-ai/skills/okstra-usage.md +5 -4
  51. package/docs/for-ai/skills/okstra-user-response.md +50 -32
  52. package/docs/project-structure-overview.md +30 -27
  53. package/docs/task-process/README.md +1 -1
  54. package/docs/task-process/common-flow.md +2 -3
  55. package/docs/task-process/error-analysis.md +3 -4
  56. package/docs/task-process/final-verification.md +2 -3
  57. package/docs/task-process/implementation-planning.md +2 -3
  58. package/docs/task-process/implementation.md +9 -7
  59. package/docs/task-process/release-handoff.md +3 -4
  60. package/docs/task-process/requirements-discovery.md +3 -4
  61. package/package.json +1 -1
  62. package/runtime/BUILD.json +2 -2
  63. package/runtime/agents/workers/claude-worker.md +4 -4
  64. package/runtime/agents/workers/report-writer-worker.md +3 -3
  65. package/runtime/agents/workers/translator-worker.md +5 -13
  66. package/runtime/bin/okstra-error-log.py +51 -11
  67. package/runtime/bin/okstra-report-translate.py +210 -23
  68. package/runtime/prompts/host-orchestration/implementation.md +1 -1
  69. package/runtime/prompts/launch.template.md +11 -14
  70. package/runtime/prompts/lead/context-loader.md +41 -141
  71. package/runtime/prompts/lead/convergence.md +8 -6
  72. package/runtime/prompts/lead/okstra-lead-contract.md +26 -36
  73. package/runtime/prompts/lead/plan-body-verification.md +211 -30
  74. package/runtime/prompts/lead/report-writer.md +23 -4
  75. package/runtime/prompts/lead/team-contract.md +8 -53
  76. package/runtime/prompts/profiles/_coding-conventions-preflight.md +3 -2
  77. package/runtime/prompts/profiles/_common-contract.md +1 -1
  78. package/runtime/prompts/profiles/_implementation-diff-review.md +1 -1
  79. package/runtime/prompts/profiles/_implementation-executor.md +1 -0
  80. package/runtime/prompts/profiles/_implementation-verifier.md +4 -4
  81. package/runtime/prompts/profiles/final-verification.md +1 -1
  82. package/runtime/prompts/profiles/implementation-planning.md +17 -13
  83. package/runtime/prompts/profiles/release-handoff.md +0 -1
  84. package/runtime/prompts/wizard/prompts.ko.json +7 -11
  85. package/runtime/python/okstra_ctl/adapters/hosts/capability_adapter.py +69 -17
  86. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +13 -4
  87. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +6 -1
  88. package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +2 -2
  89. package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +50 -5
  90. package/runtime/python/okstra_ctl/adapters/hosts/grok/adapter.py +2 -2
  91. package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +66 -5
  92. package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +70 -2
  93. package/runtime/python/okstra_ctl/agent_activity.py +118 -35
  94. package/runtime/python/okstra_ctl/agent_invocation.py +19 -6
  95. package/runtime/python/okstra_ctl/agent_prompt_cli.py +65 -18
  96. package/runtime/python/okstra_ctl/analysis_inputs.py +5 -4
  97. package/runtime/python/okstra_ctl/analysis_packet.py +81 -1
  98. package/runtime/python/okstra_ctl/approval_decisions.py +3 -2
  99. package/runtime/python/okstra_ctl/attempt_evidence.py +2 -2
  100. package/runtime/python/okstra_ctl/backfill.py +13 -10
  101. package/runtime/python/okstra_ctl/batch.py +2 -4
  102. package/runtime/python/okstra_ctl/build_tools.py +6 -3
  103. package/runtime/python/okstra_ctl/claim_reproduction.py +101 -0
  104. package/runtime/python/okstra_ctl/clarification_items.py +27 -13
  105. package/runtime/python/okstra_ctl/cmux.py +130 -52
  106. package/runtime/python/okstra_ctl/code_review_target.py +34 -8
  107. package/runtime/python/okstra_ctl/conformance.py +37 -1
  108. package/runtime/python/okstra_ctl/consumers.py +5 -4
  109. package/runtime/python/okstra_ctl/container.py +103 -8
  110. package/runtime/python/okstra_ctl/context_cost.py +2 -1
  111. package/runtime/python/okstra_ctl/contract_graph.py +497 -0
  112. package/runtime/python/okstra_ctl/contract_graph_cli.py +62 -0
  113. package/runtime/python/okstra_ctl/convergence.py +338 -17
  114. package/runtime/python/okstra_ctl/convergence_engine.py +10 -18
  115. package/runtime/python/okstra_ctl/convergence_provenance.py +58 -8
  116. package/runtime/python/okstra_ctl/convergence_store.py +55 -34
  117. package/runtime/python/okstra_ctl/design_prep.py +7 -4
  118. package/runtime/python/okstra_ctl/dispatch_core.py +35 -65
  119. package/runtime/python/okstra_ctl/dispatch_state.py +134 -59
  120. package/runtime/python/okstra_ctl/doctor.py +6 -3
  121. package/runtime/python/okstra_ctl/domain/worker_presentation.py +70 -9
  122. package/runtime/python/okstra_ctl/entrypoints/hosts.py +16 -30
  123. package/runtime/python/okstra_ctl/error_log_write.py +35 -30
  124. package/runtime/python/okstra_ctl/error_report.py +26 -1
  125. package/runtime/python/okstra_ctl/error_zip.py +27 -5
  126. package/runtime/python/okstra_ctl/execution_identity.py +3 -2
  127. package/runtime/python/okstra_ctl/execution_manifest.py +7 -4
  128. package/runtime/python/okstra_ctl/final_report_schema.py +2 -2
  129. package/runtime/python/okstra_ctl/fix_cycles.py +2 -2
  130. package/runtime/python/okstra_ctl/fixed_text.py +39 -0
  131. package/runtime/python/okstra_ctl/git_reconcile.py +41 -9
  132. package/runtime/python/okstra_ctl/handoff.py +5 -4
  133. package/runtime/python/okstra_ctl/i18n.py +4 -2
  134. package/runtime/python/okstra_ctl/implementation_direction.py +22 -14
  135. package/runtime/python/okstra_ctl/implementation_outcome.py +4 -7
  136. package/runtime/python/okstra_ctl/incremental_carry.py +2 -1
  137. package/runtime/python/okstra_ctl/incremental_scope.py +89 -39
  138. package/runtime/python/okstra_ctl/index.py +8 -11
  139. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +79 -7
  140. package/runtime/python/okstra_ctl/invocation.py +3 -6
  141. package/runtime/python/okstra_ctl/json_boundary.py +366 -0
  142. package/runtime/python/okstra_ctl/json_registry.py +10 -12
  143. package/runtime/python/okstra_ctl/jsonl.py +19 -2
  144. package/runtime/python/okstra_ctl/lead_events.py +33 -1
  145. package/runtime/python/okstra_ctl/listing.py +3 -3
  146. package/runtime/python/okstra_ctl/log_report.py +24 -2
  147. package/runtime/python/okstra_ctl/manager_cli.py +92 -7
  148. package/runtime/python/okstra_ctl/manager_store.py +12 -10
  149. package/runtime/python/okstra_ctl/material.py +5 -1
  150. package/runtime/python/okstra_ctl/migrate.py +29 -25
  151. package/runtime/python/okstra_ctl/model_cli.py +3 -15
  152. package/runtime/python/okstra_ctl/model_io_cli.py +1051 -0
  153. package/runtime/python/okstra_ctl/mutation_probe.py +13 -4
  154. package/runtime/python/okstra_ctl/pane_reclaim.py +3 -2
  155. package/runtime/python/okstra_ctl/paths.py +9 -0
  156. package/runtime/python/okstra_ctl/plan_items.py +525 -5
  157. package/runtime/python/okstra_ctl/plan_items_cli.py +842 -32
  158. package/runtime/python/okstra_ctl/pr_template.py +3 -2
  159. package/runtime/python/okstra_ctl/project_meta.py +5 -7
  160. package/runtime/python/okstra_ctl/recap.py +5 -4
  161. package/runtime/python/okstra_ctl/reconcile.py +21 -27
  162. package/runtime/python/okstra_ctl/registry/host_discovery.py +3 -2
  163. package/runtime/python/okstra_ctl/registry/provider_registry.py +3 -2
  164. package/runtime/python/okstra_ctl/render.py +30 -15
  165. package/runtime/python/okstra_ctl/render_final_report.py +3 -2
  166. package/runtime/python/okstra_ctl/report_assembly.py +172 -17
  167. package/runtime/python/okstra_ctl/report_finalize.py +7 -10
  168. package/runtime/python/okstra_ctl/report_html/render.py +3 -2
  169. package/runtime/python/okstra_ctl/report_language.py +3 -2
  170. package/runtime/python/okstra_ctl/report_markdown.py +13 -1
  171. package/runtime/python/okstra_ctl/report_narrative.py +40 -8
  172. package/runtime/python/okstra_ctl/report_synthesis_packet.py +518 -0
  173. package/runtime/python/okstra_ctl/report_views.py +3 -2
  174. package/runtime/python/okstra_ctl/rollup.py +65 -4
  175. package/runtime/python/okstra_ctl/run.py +159 -56
  176. package/runtime/python/okstra_ctl/run_audit.py +3 -2
  177. package/runtime/python/okstra_ctl/run_context.py +6 -9
  178. package/runtime/python/okstra_ctl/run_index_row.py +2 -8
  179. package/runtime/python/okstra_ctl/schedule_semantics.py +5 -2
  180. package/runtime/python/okstra_ctl/schema_excerpt.py +4 -2
  181. package/runtime/python/okstra_ctl/session_transcript.py +27 -1
  182. package/runtime/python/okstra_ctl/set_work_status.py +64 -38
  183. package/runtime/python/okstra_ctl/stage_fix_carry.py +4 -2
  184. package/runtime/python/okstra_ctl/stage_map.py +26 -6
  185. package/runtime/python/okstra_ctl/stage_targets.py +3 -4
  186. package/runtime/python/okstra_ctl/team.py +2 -1
  187. package/runtime/python/okstra_ctl/team_reconcile.py +11 -2
  188. package/runtime/python/okstra_ctl/time_report.py +51 -4
  189. package/runtime/python/okstra_ctl/usage_identity.py +2 -1
  190. package/runtime/python/okstra_ctl/usage_report.py +58 -4
  191. package/runtime/python/okstra_ctl/user_response.py +1431 -66
  192. package/runtime/python/okstra_ctl/wizard.py +50 -117
  193. package/runtime/python/okstra_ctl/work_categories.py +3 -2
  194. package/runtime/python/okstra_ctl/worker_prompt_body.py +18 -7
  195. package/runtime/python/okstra_ctl/worker_prompt_contract.py +3 -2
  196. package/runtime/python/okstra_ctl/worker_runner.py +14 -12
  197. package/runtime/python/okstra_ctl/workflow.py +2 -1
  198. package/runtime/python/okstra_ctl/worktree.py +3 -2
  199. package/runtime/python/okstra_ctl/wrapper_status.py +4 -2
  200. package/runtime/python/okstra_ctl/write_policy.py +4 -2
  201. package/runtime/python/okstra_token_usage/antigravity.py +39 -12
  202. package/runtime/python/okstra_token_usage/collect.py +90 -38
  203. package/runtime/python/okstra_token_usage/grok.py +127 -0
  204. package/runtime/schemas/final-report-v2.0.schema.json +21 -0
  205. package/runtime/schemas/final-report-v3.0.schema.json +21 -0
  206. package/runtime/schemas/report-synthesis-packet-v1.0.schema.json +140 -0
  207. package/runtime/skills/okstra-brief-gen/SKILL.md +9 -7
  208. package/runtime/skills/okstra-code-review/SKILL.md +21 -11
  209. package/runtime/skills/okstra-container-build/SKILL.md +18 -18
  210. package/runtime/skills/okstra-inspect/SKILL.md +12 -11
  211. package/runtime/skills/okstra-inspect/facets/error-zip.md +8 -8
  212. package/runtime/skills/okstra-inspect/facets/errors.md +2 -2
  213. package/runtime/skills/okstra-inspect/facets/history.md +9 -14
  214. package/runtime/skills/okstra-inspect/facets/logs.md +2 -2
  215. package/runtime/skills/okstra-inspect/facets/recap.md +5 -5
  216. package/runtime/skills/okstra-inspect/facets/report.md +6 -10
  217. package/runtime/skills/okstra-inspect/facets/status.md +9 -8
  218. package/runtime/skills/okstra-inspect/facets/time.md +3 -3
  219. package/runtime/skills/okstra-manager/SKILL.md +16 -14
  220. package/runtime/skills/okstra-memory/SKILL.md +3 -3
  221. package/runtime/skills/okstra-pr-gen/SKILL.md +5 -4
  222. package/runtime/skills/okstra-rollup/SKILL.md +6 -16
  223. package/runtime/skills/okstra-run/SKILL.md +9 -9
  224. package/runtime/skills/okstra-schedule-gen/SKILL.md +21 -17
  225. package/runtime/skills/okstra-setup/SKILL.md +21 -13
  226. package/runtime/skills/okstra-setup/references/project-config.md +2 -2
  227. package/runtime/skills/okstra-usage/SKILL.md +10 -10
  228. package/runtime/skills/okstra-user-response/SKILL.md +78 -107
  229. package/runtime/templates/report-writer-prompt-preamble.md +17 -1
  230. package/runtime/templates/reports/schedule.template.md +4 -4
  231. package/runtime/templates/worker-error-contract.md +17 -29
  232. package/runtime/validators/validate-run.py +527 -113
  233. package/runtime/validators/validate_session_conformance.py +65 -10
@@ -38,12 +38,12 @@ Run one Bash tool call, starting with the literal token `okstra` (never wrapped
38
38
  <!-- END FRAGMENT: bash-invocation-rule -->
39
39
 
40
40
  ```bash
41
- okstra preflight --runtime claude-code --json
41
+ okstra preflight --runtime claude-code
42
42
  ```
43
43
 
44
- Branch on the stdout JSON:
45
- - `ok: true` → carry `projectRoot` as a literal string; every later step is anchored on it.
46
- - `ok: false` → the check only sees the cwd of the Bash call, so a project that is not the cwd reads as missing setup. Ask whether the user pointed at a specific project directory; if they did, re-run targeting it: `okstra preflight --runtime claude-code --cwd <that-dir> --json` (`--cwd` is the sanctioned way to target a project — a leading `cd` would break the permission match). Only if this **also** returns `ok:false` do you tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop.
44
+ Branch on the fixed first line:
45
+ - `Okstra preflight: ready` → carry `Project root` as a literal string; every later step is anchored on it.
46
+ - `Okstra preflight: failed` → the check only sees the cwd of the Bash call, so a project that is not the cwd can read as missing setup. Ask whether the user pointed at a specific project directory; if they did, re-run targeting it: `okstra preflight --runtime claude-code --cwd <that-dir>` (`--cwd` is the sanctioned way to target a project — a leading `cd` would break the permission match). Only if this also fails do you show `Reason` and `Recovery`, then stop.
47
47
 
48
48
  <!-- BEGIN FRAGMENT: preflight-outdated-cli -->
49
49
  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).
@@ -63,8 +63,8 @@ Pick the mode from what the user actually gave you:
63
63
 
64
64
  **Stage mode.**
65
65
 
66
- 1. `okstra resolve-task-key <token> --project-root <projectRoot> --json` → branch on `matches[]`: **0** → report the task cannot be found and stop; **1** → take that entry's `taskKey`; **N** → list the candidates (with `updatedAt`) and ask via a 3-option picker (1–2 recommendations + `Enter directly`).
67
- 2. `okstra stage-map <taskKey> --project <projectRoot> --json` → `stages[]` (`stage_number`, `title`, `depends_on`) and `doneStages[]`.
66
+ 1. A full `project-id:task-group:task-id` token is already the task key. For a bare token, run `okstra model-io task-selection-input --project-root <projectRoot> --task-ref <token>` and branch on the fixed `Match count`, `Task`, and `Updated at` rows: **0** → report the task cannot be found and stop; **1** → take `Task`; **N** → list the candidates and ask via a 3-option picker (1–2 recommendations + `Enter directly`).
67
+ 2. `okstra stage-map <taskKey> --project <projectRoot> --text` → use the fixed `Stages` and `Done stages` count/name/value rows.
68
68
  3. Choose the stage with a 3-option picker — recommend the highest done stage (the work that just finished) first, a second plausible stage if there is one, and `Enter directly` last. Pick silently only when exactly one stage exists.
69
69
 
70
70
  **Branch mode.**
@@ -75,13 +75,23 @@ Pick the mode from what the user actually gave you:
75
75
  **Then call the target CLI.** One call resolves everything the rest of this skill needs; the only reason to call it again is a base the user overrides in the confirmation step below.
76
76
 
77
77
  ```bash
78
- okstra code-review target --task-key <taskKey> --stage <N> --project-root <projectRoot> --json
79
- okstra code-review target --branch <name> [--base <ref>] --project-root <projectRoot> --json
78
+ okstra code-review target --task-key <taskKey> --stage <N> --project-root <projectRoot> --text
79
+ okstra code-review target --branch <name> [--base <ref>] --project-root <projectRoot> --text
80
80
  ```
81
81
 
82
- `ok: true` carries `projectRoot`, `mode`, `worktreePath`, `branch`, `baseCommit`, `headCommit`, `reviewPath`, `round`; stage mode adds `taskKey`, `taskRoot`, `stage`. Carry every field verbatim into the later steps — none of them is recomputed anywhere below.
82
+ `Status: ready` carries `Project root`, `Mode`, `Worktree path`, `Branch`, `Base commit`, `Head commit`, `Review path`, and `Round`; stage mode adds `Task key`, `Task root`, and `Stage`. Carry every field verbatim into the later steps — none of them is recomputed anywhere below.
83
83
 
84
- `ok: false` carries `stage` (a failure code) and `reason`. Report both and stop, unless the Exceptions table names that case.
84
+ `Status: error` carries `Failure stage` and `Failure reason`. Report both and stop, unless the Exceptions table names that case.
85
+
86
+ After the range is resolved, render the only project identity and range values
87
+ that later model prompts may consume:
88
+
89
+ ```bash
90
+ okstra model-io code-review-input --project-root <projectRoot> --base <baseCommit> --head <headCommit>
91
+ ```
92
+
93
+ Carry this fixed Markdown view into the census and reviewer prompts. Do not
94
+ pass task manifests, target-CLI JSON, or arbitrary JSON fields to a reviewer.
85
95
 
86
96
  **You never derive the base.** Pass `--base <ref>` only when the user named one; otherwise the CLI resolves it. `baseCommit` is a **ref, not necessarily a commit id** — a caller-supplied `--base` passes through verbatim — so use it as given in `git diff <baseCommit>..<headCommit>` and never present it as "commit `<sha>`".
87
97
 
@@ -181,7 +191,7 @@ generatedAt: <YYYY-MM-DD HH:MM>
181
191
 
182
192
  | Situation | Handling |
183
193
  |---|---|
184
- | `preflight` returns `ok:false` | retry with `--cwd <dir>`; if that also fails, tell the user to run `/okstra-setup` first and stop |
194
+ | `preflight` reports `Okstra preflight: failed` | retry with `--cwd <dir>`; if that also fails, tell the user to run `/okstra-setup` first and stop |
185
195
  | `unknown command: code-review` | the `okstra` binary predates this skill — tell the user to update it (`npm i -g okstra@latest`) and stop |
186
196
  | `worktreePath` is empty | not a hard stop and not a missing stage: run git in `projectRoot` against the stage's `branch` ref and continue |
187
197
  | `baseCommit` is not an ancestor of `headCommit` — `git -C <workdir> rev-list --count <headCommit>..<baseCommit>` returns a **non-zero** count, meaning a rebase or squash rewrote the history the stage was recorded against, and `<baseCommit>..<headCommit>` would drag predecessor work in backwards | code-review is read-only, so do not force a reconcile. Offer two options: review against the branch's current tip, or run `okstra git-reconcile` first and retry |
@@ -25,10 +25,10 @@ Run one Bash tool call, starting with the literal token `okstra` (never wrapped
25
25
  <!-- END FRAGMENT: bash-invocation-rule -->
26
26
 
27
27
  ```bash
28
- okstra preflight --runtime claude-code --json
28
+ okstra preflight --runtime claude-code
29
29
  ```
30
30
 
31
- Parse the stdout JSON. `ok: true` → carry `projectRoot` as a literal string and pass it as `--project-root <projectRoot>` to every `okstra container` call below. `ok: false` → tell the user to run `/okstra-setup` first, then stop.
31
+ On `Okstra preflight: ready`, carry the fixed `Project root` line and pass it as `--project-root <projectRoot>` to every `okstra container` call below. On `Okstra preflight: failed`, show `Reason` and `Recovery`, then stop.
32
32
 
33
33
  <!-- BEGIN FRAGMENT: preflight-outdated-cli -->
34
34
  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).
@@ -61,7 +61,7 @@ When the user chains multiple facets in one message (e.g. "bring it up, then sho
61
61
  Every sub-command needs a **task-key** (`<project-id>:<task-group>:<task-id>`) — the container group is bound to one implementation task's worktree. Resolve it the same way across sub-commands:
62
62
 
63
63
  1. If the user gave a full task-key, use it.
64
- 2. If the user gave only a task-id, resolve it via `okstra resolve-task-key <task-id> --project-root <projectRoot> --json` and branch on the stdout `matches[]`: single → use its `taskKey`; multiple → list candidates and ask (3-option picker); none → report not found.
64
+ 2. If the user gave only a task-id, run `okstra model-io task-selection-input --project-root <projectRoot> --task-ref <task-id>`. Use the fixed `Selection status`, `Task key`, and numbered `Candidate` lines: one match → use its task key; multiple → list candidates and ask (3-option picker); none → report not found.
65
65
  3. `down --all` is the only call that does not need a task-key (see `down`).
66
66
 
67
67
  ---
@@ -78,12 +78,12 @@ Brings up the task's container group: integrates the implementation stages into
78
78
  Run:
79
79
 
80
80
  ```bash
81
- okstra container up --project-root <projectRoot> --task-key <task-key>
81
+ okstra container up --project-root <projectRoot> --task-key <task-key> --text
82
82
  ```
83
83
 
84
- Parse the stdout JSON and report the provisioned services and the watcher pane. If a service failed its healthcheck, the call surfaces the failing services and the `docker compose ... logs` line to inspect — relay that line; do not invent your own.
84
+ Read the fixed output fields and report the provisioned services and watcher pane. If a service failed its healthcheck, the call surfaces the failing services and the `docker compose ... logs` line to inspect — relay that line; do not invent your own.
85
85
 
86
- After a successful `up`, tell the user how to reach the running build (the compose file's published ports) and that `okstra container status <task-key>` / `okstra container down <task-key>` manage it from here. For *what to verify* once it is up, point the user to the implementation report's §5.7.9 Manual User Test (Draft) — its steps and expected results are the manual test script for this build.
86
+ After a successful `up`, run the `status --text` command below and read its numbered container `ports` fields to tell the user how to reach the running build. Also explain that `okstra container status <task-key>` / `okstra container down <task-key>` manage it from here. For *what to verify* once it is up, point the user to the implementation report's §5.7.9 Manual User Test (Draft) — its steps and expected results are the manual test script for this build.
87
87
 
88
88
  ---
89
89
 
@@ -92,10 +92,10 @@ After a successful `up`, tell the user how to reach the running build (the compo
92
92
  Reports the running containers (queried by run-trace label — the source of truth for "is it up") plus the watcher metadata recorded in the registry.
93
93
 
94
94
  ```bash
95
- okstra container status --project-root <projectRoot> --task-key <task-key>
95
+ okstra container status --project-root <projectRoot> --task-key <task-key> --text
96
96
  ```
97
97
 
98
- Parse the stdout JSON (`{projectName, containers, watchers}`) and report:
98
+ Read the fixed `Project name`, `Containers`, and `Watchers` fields and report:
99
99
 
100
100
  | Field | Meaning |
101
101
  |---|---|
@@ -112,16 +112,16 @@ If `containers` is empty, say the group is not running and offer `up`. Treat the
112
112
  The live log stream lives in the tmux watcher pane, not in a file. This sub-command points at the watcher findings directory and the per-service watcher state.
113
113
 
114
114
  ```bash
115
- okstra container logs --project-root <projectRoot> --task-key <task-key>
115
+ okstra container logs --project-root <projectRoot> --task-key <task-key> --text
116
116
  ```
117
117
 
118
118
  Add `--service <name>` to scope to one service:
119
119
 
120
120
  ```bash
121
- okstra container logs --project-root <projectRoot> --task-key <task-key> --service <service>
121
+ okstra container logs --project-root <projectRoot> --task-key <task-key> --service <service> --text
122
122
  ```
123
123
 
124
- Parse the stdout JSON (`{watchersDir, watchers}`). Report the `watchersDir` host path (under `~/.okstra/...`-style project artifacts — display the absolute path the CLI returns) and the watcher entries. Explain that the live stream is in the attached tmux pane; to see raw container logs the user runs `docker compose -p <projectName> logs -f <service>` (get `<projectName>` from `status`).
124
+ Read the fixed `Watchers dir` and numbered `Watchers` fields. Report the host path and watcher entries. Explain that the live stream is in the attached tmux pane; to see raw container logs the user runs `docker compose -p <projectName> logs -f <service>` (get `<projectName>` from `status`).
125
125
 
126
126
  ---
127
127
 
@@ -130,10 +130,10 @@ Parse the stdout JSON (`{watchersDir, watchers}`). Report the `watchersDir` host
130
130
  Reaps the watcher/tail tmux panes for the task **without stopping the containers**. Use when the user wants to silence the monitor but keep the build running.
131
131
 
132
132
  ```bash
133
- okstra container stop-watcher --project-root <projectRoot> --task-key <task-key>
133
+ okstra container stop-watcher --project-root <projectRoot> --task-key <task-key> --text
134
134
  ```
135
135
 
136
- Parse the stdout JSON (`{reapedPanes, note}`). Confirm which panes were reaped and that the containers are still running (the `note` says so). If the user actually wants the containers gone, route to `down`.
136
+ Read the fixed `Reaped panes` and `Note` fields. Confirm which panes were reaped and that the containers are still running. If the user actually wants the containers gone, route to `down`.
137
137
 
138
138
  ---
139
139
 
@@ -144,23 +144,23 @@ Tears down the container group (removes containers found by the run-trace label)
144
144
  Single task:
145
145
 
146
146
  ```bash
147
- okstra container down --project-root <projectRoot> --task-key <task-key>
147
+ okstra container down --project-root <projectRoot> --task-key <task-key> --text
148
148
  ```
149
149
 
150
150
  Every container group in the project (no task-key needed):
151
151
 
152
152
  ```bash
153
- okstra container down --project-root <projectRoot> --all
153
+ okstra container down --project-root <projectRoot> --all --text
154
154
  ```
155
155
 
156
- Parse the stdout JSON (`{downed, orphanPanesReaped}`). Report each torn-down `projectName` and the orphan panes reaped. `down` runs `docker compose -p <name> down --remove-orphans` — a compose-native teardown that removes the project's containers and the compose network, but deliberately keeps named volumes (e.g. DB data) by NOT passing `-v`. Confirm with the user before running `--all`, since it takes down every okstra container group in the project at once. A single-task `down` is safe to run directly once the task-key is resolved.
156
+ Read the fixed `Downed` and `Orphan panes reaped` fields. Report each torn-down project name and the orphan panes reaped. `down` runs `docker compose -p <name> down --remove-orphans` — a compose-native teardown that removes the project's containers and the compose network, but deliberately keeps named volumes (e.g. DB data) by NOT passing `-v`. Confirm with the user before running `--all`, since it takes down every okstra container group in the project at once. A single-task `down` is safe to run directly once the task-key is resolved.
157
157
 
158
158
  ---
159
159
 
160
160
  ## Output Rules (shared)
161
161
 
162
162
  - Responses should be concise and written in Korean unless the user requests otherwise.
163
- - The stdout JSON from each `okstra container` call is the source of truth — do not run raw `docker` commands to second-guess it unless the CLI fails and the user explicitly asks for a manual fallback.
163
+ - The fixed text fields from each `okstra container` call are the source of truth — do not run raw `docker` commands to second-guess them unless the CLI fails and the user explicitly asks for a manual fallback.
164
164
  - Show the resolved `<task-key>` in the heading so the user can confirm disambiguation.
165
165
  - Surface failure messages from the CLI verbatim (compose-up failures, missing worktree/compose file) — do not paraphrase the remediation line.
166
- - Display container/service states as-is from the JSON; do not normalize or remap.
166
+ - Display container/service states as-is from the fixed fields; do not normalize or remap.
@@ -28,14 +28,14 @@ Run one Bash tool call, starting with the literal token `okstra` (never wrapped
28
28
  <!-- END FRAGMENT: bash-invocation-rule -->
29
29
 
30
30
  ```bash
31
- okstra preflight --runtime claude-code --json
31
+ okstra preflight --runtime claude-code
32
32
  ```
33
33
 
34
- The project check only sees the cwd of the Bash call. When the user is asking about a project that is **not** the cwd (a sibling repo, a monorepo subdir, or a project named explicitly in the request), the bare form resolves to the wrong project or none and returns `ok:false` — a false negative, not a missing setup; do not hard-stop on it.
34
+ The project check only sees the cwd of the Bash call. When the user is asking about a project that is **not** the cwd (a sibling repo, a monorepo subdir, or a project named explicitly in the request), the bare form can report `Okstra preflight: failed` — a false negative, not a missing setup; do not hard-stop on it.
35
35
 
36
- Branch on the stdout JSON:
37
- - `ok: true` → carry `projectRoot` as a literal string; it is the base for every sub-command step below.
38
- - `ok: false` → before concluding "no setup", ask whether the user pointed at a specific project directory. If they did, re-run targeting it: `okstra preflight --runtime claude-code --cwd <that-dir> --json` (`--cwd` is the sanctioned way to target a project — a leading `cd` would break the permission match). Only if this **also** returns `ok:false` do you tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop.
36
+ Branch on the fixed first line:
37
+ - `Okstra preflight: ready` → carry `Project root` as a literal string; it is the base for every sub-command step below.
38
+ - `Okstra preflight: failed` → before concluding "no setup", ask whether the user pointed at a specific project directory. If they did, re-run targeting it: `okstra preflight --runtime claude-code --cwd <that-dir>` (`--cwd` is the sanctioned way to target a project — a leading `cd` would break the permission match). Only if this also fails do you show `Reason` and `Recovery`, then stop.
39
39
 
40
40
  <!-- BEGIN FRAGMENT: preflight-outdated-cli -->
41
41
  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).
@@ -59,13 +59,14 @@ When the user chains multiple facets in one message (e.g. "status, and then time
59
59
 
60
60
  ### Standard task-key resolution (0/1/N)
61
61
 
62
- Facets that accept a bare token (a task-id like `DEV-9184` **or** a task-group like `PROD`) resolve it with the shared resolver (SSOT — `scripts/okstra_ctl/resolve_task_key.py` / `okstra_project.resolve_task_reference`). The resolver matches the token as a task-id **and** as a task-group, unioning both (a group expands to its member tasks); each entry carries `_matchedVia` (`"taskId"` | `"taskGroup"`):
62
+ Facets that accept a bare token (a task-id like `DEV-9184` **or** a task-group like `PROD`) resolve it through the fixed text projection:
63
63
 
64
64
  ```bash
65
- okstra resolve-task-key <token> --project-root <projectRoot> --json
65
+ okstra model-io task-selection-input --project-root <projectRoot> --task-ref <token>
66
66
  ```
67
67
 
68
- Branch on the stdout JSON `matches[]`:
68
+ Branch on `Match count` in the projection and use only its repeated `Task`,
69
+ `Updated at`, and `Matched via` lines:
69
70
  - **0** → report the task cannot be found. Do not guess.
70
71
  - **1** → use that entry's `taskKey`.
71
72
  - **N** → list the candidate `taskKey`s (with `updatedAt`, and `_matchedVia` so the user sees which came from a task-id vs a task-group) and ask via a 3-option picker (1–2 recommendations + `Enter directly`), then use the chosen `taskKey`.
@@ -74,8 +75,8 @@ Branch on the stdout JSON `matches[]`:
74
75
 
75
76
  When a facet needs a task but the user did not name one:
76
77
 
77
- 1. Read `.okstra/discovery/task-catalog.json`.
78
- 2. If exactly one task exists, use it.
78
+ 1. Run `okstra model-io task-selection-input --project-root <projectRoot>`.
79
+ 2. Branch on `Match count`; if exactly one task exists, use it.
79
80
  3. If multiple tasks exist, show the latest 10 by `updatedAt` as real task-keys and ask which one. Do not guess, and do not answer with placeholder forms only.
80
81
 
81
82
  ## Output Rules (shared)
@@ -84,7 +85,7 @@ When a facet needs a task but the user did not name one:
84
85
  status values the first time each appears — the reader has not seen the report you are summarizing.
85
86
  - Use project-relative paths whenever possible.
86
87
  - If there is no recent report, display `--`.
87
- - If a specific task does not exist, explicitly state that it cannot be found based on `task-catalog.json`.
88
+ - If a specific task does not exist, explicitly state that the task resolver returned no match.
88
89
  - If `awaitingApproval` is true, clearly indicate that the task is awaiting user approval.
89
90
  - Display status fields as-is from disk (`completed`, `contract-violated`, `todo`, `error`, empty, ...). Do not normalize or remap.
90
91
  - Dates in `YYYY-MM-DD HH:MM` format.
@@ -10,23 +10,23 @@ Collect and anonymize the okstra run errors (`runs/*/logs/errors-*.jsonl`) of ev
10
10
 
11
11
  ### error-zip.1 — Decide the output path (picker)
12
12
 
13
- Read the previous output path from `lastOutputPath` in `~/.okstra/error-zip.json`. If that value exists, present it in a 3-option picker:
13
+ First run the fixed text projection below. If `Previous output path` is not `-`,
14
+ offer it as the recommended first option. Otherwise recommend
15
+ `~/okstra-error-feedback-<YYYY-MM-DD>.zip`. Keep `Enter directly` last.
14
16
 
15
- 1. (previous path exists) reuse `<lastOutputPath>` — recommended, first option.
16
- (no previous path) propose the default path `~/okstra-error-feedback-<YYYY-MM-DD>.zip` — recommended.
17
- 2. Enter directly (always the last option).
18
-
19
- Read `~/.okstra/error-zip.json` directly with Read (if absent, treat it as no previous path).
17
+ ```bash
18
+ okstra model-io error-zip-input
19
+ ```
20
20
 
21
21
  ### error-zip.2 — Run the renderer
22
22
 
23
23
  ```bash
24
- okstra error-zip --out <resolved-path>
24
+ okstra error-zip --out <resolved-path> --text
25
25
  ```
26
26
 
27
27
  ### error-zip.3 — Report the summary
28
28
 
29
- Parse the stdout JSON and report:
29
+ Use the fixed text labels and report:
30
30
 
31
31
  | Field | Source |
32
32
  |---|---|
@@ -23,14 +23,14 @@ If the user asks for an error report without naming a task, apply the core no-ta
23
23
  Use the CLI output as the source of truth:
24
24
 
25
25
  ```bash
26
- okstra error-report <resolved-target> --project-root <projectRoot>
26
+ okstra error-report <resolved-target> --project-root <projectRoot> --text
27
27
  ```
28
28
 
29
29
  For a task-root path, run `okstra error-report <path>` directly. Do not parse the jsonl files by hand unless the CLI fails and the user explicitly asks for a manual fallback.
30
30
 
31
31
  ### errors.3 — Summarize output
32
32
 
33
- Parse the stdout JSON and report:
33
+ Use the fixed text labels and report:
34
34
 
35
35
  | Field | Source |
36
36
  |---|---|
@@ -8,16 +8,16 @@ Trigger phrases: "okstra history", "past runs", "run history", "re-run", "list t
8
8
 
9
9
  **Re-run vs Resume — decide upfront.** Re-run = start a fresh run (new run-seq, new manifest, new report) reusing an old run's parameters → `history.3`. Resume = continue an interrupted Claude session for an existing run, no new run-seq → `history.4`. If the user is ambiguous, ask — defaulting to the wrong one either wastes a fresh run-seq or silently abandons a recoverable session.
10
10
 
11
- ### history.1 — Read the task catalog
11
+ ### history.1 — Project task history
12
12
 
13
- 1. Read `.okstra/discovery/task-catalog.json`.
13
+ 1. Run `okstra model-io history-input --project-root <projectRoot>`.
14
14
  2. Apply filters from user input (all optional, AND-combined):
15
15
  - `--task-type <type>` → keep entries whose `taskType` matches.
16
16
  - `--latest-run-status <status>` → keep entries whose `latestRunStatus` matches (`completed`, `contract-violated`, `error`).
17
17
  - `--task-group <group>` → keep entries whose `taskGroup` matches.
18
18
  3. Sort by `updatedAt` desc.
19
19
  4. Page: default `--limit 20`. If truncated, add `... <N> more (pass --limit <N> to see all)`.
20
- 5. Extract: `taskKey`, `taskType`, `currentStatus`, `latestRunStatus`, `latestRunManifestPath`, `updatedAt`, `latestReportRecordPath`, `latestResumeCommandPath`, `historyTimelinePath`.
20
+ 5. Use the task/status/time/report lines emitted by the fixed text projection.
21
21
 
22
22
  ```markdown
23
23
  ## okstra Task History — <project-id>
@@ -28,19 +28,14 @@ Trigger phrases: "okstra history", "past runs", "run history", "re-run", "list t
28
28
  | 2 | proj:group:id2 | final-verification | todo | error | 2026-04-04 15:30 | -- |
29
29
  ```
30
30
 
31
- **Catalog absent — fallback.** Do NOT bail out. Manifests on disk are the source of truth.
32
-
33
- 1. Glob `<projectRoot>/.okstra/tasks/*/*/task-manifest.json`.
34
- 2. For each manifest, read the same fields as above.
35
- 3. Apply the same filters/sort/limit and print the same table, prefixed with: `note: task-catalog.json missing; reconstructed from task manifests on disk.`
36
- 4. Only if the glob yields zero manifests: `There is no okstra execution history yet.`
31
+ If stdout `taskCount` is zero, answer `There is no okstra execution history yet.`
37
32
 
38
33
  ### history.2 — Run history by task
39
34
 
40
35
  When a user selects a specific task:
41
36
 
42
- 1. Retrieve `historyTimelinePath`, read `runs` array.
43
- 2. Extract: `runTimestamp`, `runDateTimeSegment`, `taskType`, `status`, `runManifestPath`, `reportPath`, `resumeCommandPath`, `relatedTasks`.
37
+ 1. Run `okstra model-io history-input --project-root <projectRoot> --task-ref <task-key>`.
38
+ 2. Use each numbered run block for chronological status, report, run-manifest, and resume paths.
44
39
 
45
40
  ```markdown
46
41
  ## Runs for <task-key>
@@ -56,7 +51,7 @@ When a user selects a specific task:
56
51
  Builds a fresh run — new run-seq, new manifest, new report — using parameters from a previous `run-manifest-*.json`. Does NOT touch old artifacts; use `history.4` to continue an interrupted session.
57
52
 
58
53
  1. Pick the source run-manifest: `runManifestPath` from `history.2`, or task's `latestRunManifestPath` from `history.1`. Note: `latestRunManifestPath` is projected from the timeline's latest run, so it is empty when the task has no recorded run yet (timeline absent) — in that case fall back to a `history.2` per-run `runManifestPath`, or ask the user.
59
- 2. Read the manifest and extract required arguments:
54
+ 2. Run `okstra model-io rerun-input --run-manifest <runManifestPath>` and use its required argument lines:
60
55
  - `projectId` → `--project-id`
61
56
  - `taskGroup` → `--task-group`
62
57
  - `taskId` → `--task-id`
@@ -67,7 +62,7 @@ Builds a fresh run — new run-seq, new manifest, new report — using parameter
67
62
  - `relatedTasks` → `--related-tasks`
68
63
  - model overrides → `--claude-model`, `--codex-model`, `--antigravity-model`
69
64
  - for `taskType: implementation`: `teamContract.executor.provider` → `--executor <claude|codex|antigravity>` when different from `claude`.
70
- 4. **`taskType: implementation` only — resolve `--base-ref`:** base ref is NOT in the run-manifest; it lives in the worktree registry at `~/.okstra/worktrees/registry.json`. If a worktree is already registered, existing branch & base are reused — omit `--base-ref` unless the user explicitly wants a different starting point. If no worktree is registered (cleaned up), `--base-ref` is mandatory — ask the user before running.
65
+ 4. **`taskType: implementation` only — resolve `--base-ref`:** do not inspect the worktree registry. Omit `--base-ref` to reuse an existing registration. If the launch reports that no worktree is registered and a base is required, ask the user before retrying.
71
66
  5. Display the assembled command:
72
67
  ```bash
73
68
  ~/.okstra/bin/okstra.sh \
@@ -84,7 +79,7 @@ Builds a fresh run — new run-seq, new manifest, new report — using parameter
84
79
 
85
80
  Continues an existing Claude session for an unfinished run. Does NOT create a new run-seq — for a fresh dispatch use `history.3`.
86
81
 
87
- 1. Read `latestResumeCommandPath` from `history.1` (or `resumeCommandPath` from a `history.2` timeline entry).
82
+ 1. Use `Latest resume command` from status input or `Resume command` from a history run block.
88
83
  2. Verify the file exists on disk.
89
84
  3. If it exists: `bash <resume-command-path>`.
90
85
  4. If the path is empty or the file is missing: `No resume script available for this run. Use 'history.3' to start a fresh run instead.`
@@ -21,10 +21,10 @@ The log is rewritten from scratch at each dispatch — only the latest run for a
21
21
  ### logs.1 — Inventory
22
22
 
23
23
  ```bash
24
- okstra log-report --project-root <projectRoot> --json
24
+ okstra log-report --project-root <projectRoot> --text
25
25
  ```
26
26
 
27
- Scans `<projectRoot>/.okstra/tasks/**/runs/*/prompts/*.log` and parses task/phase/worker/seq from each path. Returns (sizes are **raw bytes**, mtimes **epoch seconds**):
27
+ Scans `<projectRoot>/.okstra/tasks/**/runs/*/prompts/*.log` and returns fixed labeled text (sizes are **raw bytes**, mtimes **epoch seconds**):
28
28
  - `topLargest[]` — `{path, sizeBytes, mtimeEpoch, taskKey, taskGroup, taskId, phase, worker, seq}`, size desc (widen with `--top <N>`)
29
29
  - `perTask[]` — `{taskKey, fileCount, totalBytes, oldestEpoch, newestEpoch}`, total-size desc
30
30
  - `totals` — `{fileCount, totalBytes, taskCount}`
@@ -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 phase → To 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.