okstra 0.180.0 → 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 (223) hide show
  1. package/dist/cli-registry.mjs +16 -2
  2. package/dist/cli-registry.mjs.map +1 -1
  3. package/dist/commands/execute/render-bundle.d.mts +4 -2
  4. package/dist/commands/execute/render-bundle.mjs +46 -5
  5. package/dist/commands/execute/render-bundle.mjs.map +1 -1
  6. package/dist/commands/execute/run.mjs +11 -3
  7. package/dist/commands/execute/run.mjs.map +1 -1
  8. package/dist/commands/inspect/model-io.d.mts +1 -0
  9. package/dist/commands/inspect/model-io.mjs +25 -0
  10. package/dist/commands/inspect/model-io.mjs.map +1 -0
  11. package/dist/commands/inspect/stage-map.mjs +29 -8
  12. package/dist/commands/inspect/stage-map.mjs.map +1 -1
  13. package/dist/commands/inspect/task-list.mjs +52 -6
  14. package/dist/commands/inspect/task-list.mjs.map +1 -1
  15. package/dist/commands/inspect/user-response.mjs +14 -4
  16. package/dist/commands/inspect/user-response.mjs.map +1 -1
  17. package/dist/commands/lifecycle/check-project.d.mts +1 -0
  18. package/dist/commands/lifecycle/check-project.mjs +69 -50
  19. package/dist/commands/lifecycle/check-project.mjs.map +1 -1
  20. package/dist/commands/lifecycle/contract-check.d.mts +1 -0
  21. package/dist/commands/lifecycle/contract-check.mjs +18 -0
  22. package/dist/commands/lifecycle/contract-check.mjs.map +1 -0
  23. package/dist/commands/lifecycle/preflight.mjs +154 -51
  24. package/dist/commands/lifecycle/preflight.mjs.map +1 -1
  25. package/dist/commands/pr/pr.d.mts +1 -0
  26. package/dist/commands/pr/pr.mjs +19 -1
  27. package/dist/commands/pr/pr.mjs.map +1 -1
  28. package/dist/commands/report/agent-activity.mjs +2 -2
  29. package/dist/commands/report/translate.mjs +3 -0
  30. package/dist/commands/report/translate.mjs.map +1 -1
  31. package/dist/lib/host-registry-client.mjs +13 -9
  32. package/dist/lib/host-registry-client.mjs.map +1 -1
  33. package/docs/architecture.md +11 -0
  34. package/docs/cli.md +26 -13
  35. package/docs/container.md +6 -4
  36. package/docs/contributor-change-matrix.md +1 -1
  37. package/docs/for-ai/README.md +2 -2
  38. package/docs/for-ai/skills/okstra-brief-gen.md +5 -3
  39. package/docs/for-ai/skills/okstra-code-review.md +4 -4
  40. package/docs/for-ai/skills/okstra-container-build.md +20 -17
  41. package/docs/for-ai/skills/okstra-inspect.md +20 -23
  42. package/docs/for-ai/skills/okstra-manager.md +19 -18
  43. package/docs/for-ai/skills/okstra-memory.md +2 -2
  44. package/docs/for-ai/skills/okstra-pr-gen.md +3 -3
  45. package/docs/for-ai/skills/okstra-rollup.md +14 -13
  46. package/docs/for-ai/skills/okstra-run.md +7 -3
  47. package/docs/for-ai/skills/okstra-schedule-gen.md +15 -18
  48. package/docs/for-ai/skills/okstra-setup.md +7 -7
  49. package/docs/for-ai/skills/okstra-usage.md +5 -4
  50. package/docs/for-ai/skills/okstra-user-response.md +50 -32
  51. package/docs/project-structure-overview.md +29 -26
  52. package/docs/task-process/implementation.md +7 -4
  53. package/package.json +1 -1
  54. package/runtime/BUILD.json +2 -2
  55. package/runtime/agents/workers/claude-worker.md +4 -4
  56. package/runtime/agents/workers/report-writer-worker.md +3 -3
  57. package/runtime/agents/workers/translator-worker.md +5 -13
  58. package/runtime/bin/okstra-error-log.py +51 -11
  59. package/runtime/bin/okstra-report-translate.py +210 -23
  60. package/runtime/prompts/host-orchestration/implementation.md +1 -1
  61. package/runtime/prompts/launch.template.md +3 -7
  62. package/runtime/prompts/lead/context-loader.md +41 -141
  63. package/runtime/prompts/lead/convergence.md +8 -6
  64. package/runtime/prompts/lead/okstra-lead-contract.md +25 -35
  65. package/runtime/prompts/lead/plan-body-verification.md +187 -14
  66. package/runtime/prompts/lead/report-writer.md +20 -1
  67. package/runtime/prompts/lead/team-contract.md +8 -53
  68. package/runtime/prompts/profiles/_coding-conventions-preflight.md +3 -2
  69. package/runtime/prompts/profiles/_common-contract.md +1 -1
  70. package/runtime/prompts/profiles/_implementation-diff-review.md +1 -1
  71. package/runtime/prompts/profiles/_implementation-verifier.md +3 -3
  72. package/runtime/prompts/profiles/final-verification.md +1 -1
  73. package/runtime/prompts/profiles/implementation-planning.md +8 -2
  74. package/runtime/prompts/profiles/release-handoff.md +0 -1
  75. package/runtime/prompts/wizard/prompts.ko.json +0 -1
  76. package/runtime/python/okstra_ctl/adapters/hosts/capability_adapter.py +69 -17
  77. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +13 -4
  78. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +6 -1
  79. package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +2 -2
  80. package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +50 -5
  81. package/runtime/python/okstra_ctl/adapters/hosts/grok/adapter.py +2 -2
  82. package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +66 -5
  83. package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +70 -2
  84. package/runtime/python/okstra_ctl/agent_activity.py +118 -35
  85. package/runtime/python/okstra_ctl/agent_invocation.py +19 -6
  86. package/runtime/python/okstra_ctl/agent_prompt_cli.py +65 -18
  87. package/runtime/python/okstra_ctl/analysis_inputs.py +5 -4
  88. package/runtime/python/okstra_ctl/analysis_packet.py +81 -1
  89. package/runtime/python/okstra_ctl/approval_decisions.py +3 -2
  90. package/runtime/python/okstra_ctl/attempt_evidence.py +2 -2
  91. package/runtime/python/okstra_ctl/backfill.py +13 -10
  92. package/runtime/python/okstra_ctl/batch.py +2 -4
  93. package/runtime/python/okstra_ctl/build_tools.py +6 -3
  94. package/runtime/python/okstra_ctl/claim_reproduction.py +101 -0
  95. package/runtime/python/okstra_ctl/clarification_items.py +27 -13
  96. package/runtime/python/okstra_ctl/cmux.py +130 -52
  97. package/runtime/python/okstra_ctl/code_review_target.py +34 -8
  98. package/runtime/python/okstra_ctl/consumers.py +5 -4
  99. package/runtime/python/okstra_ctl/container.py +103 -8
  100. package/runtime/python/okstra_ctl/context_cost.py +2 -1
  101. package/runtime/python/okstra_ctl/contract_graph.py +497 -0
  102. package/runtime/python/okstra_ctl/contract_graph_cli.py +62 -0
  103. package/runtime/python/okstra_ctl/convergence.py +338 -17
  104. package/runtime/python/okstra_ctl/convergence_engine.py +10 -18
  105. package/runtime/python/okstra_ctl/convergence_provenance.py +58 -8
  106. package/runtime/python/okstra_ctl/convergence_store.py +55 -34
  107. package/runtime/python/okstra_ctl/design_prep.py +7 -4
  108. package/runtime/python/okstra_ctl/dispatch_core.py +35 -65
  109. package/runtime/python/okstra_ctl/dispatch_state.py +134 -59
  110. package/runtime/python/okstra_ctl/doctor.py +6 -3
  111. package/runtime/python/okstra_ctl/domain/worker_presentation.py +70 -9
  112. package/runtime/python/okstra_ctl/entrypoints/hosts.py +16 -30
  113. package/runtime/python/okstra_ctl/error_log_write.py +35 -30
  114. package/runtime/python/okstra_ctl/error_report.py +26 -1
  115. package/runtime/python/okstra_ctl/error_zip.py +27 -5
  116. package/runtime/python/okstra_ctl/execution_identity.py +3 -2
  117. package/runtime/python/okstra_ctl/execution_manifest.py +7 -4
  118. package/runtime/python/okstra_ctl/final_report_schema.py +2 -2
  119. package/runtime/python/okstra_ctl/fix_cycles.py +2 -2
  120. package/runtime/python/okstra_ctl/fixed_text.py +39 -0
  121. package/runtime/python/okstra_ctl/git_reconcile.py +41 -9
  122. package/runtime/python/okstra_ctl/handoff.py +5 -4
  123. package/runtime/python/okstra_ctl/i18n.py +4 -2
  124. package/runtime/python/okstra_ctl/implementation_direction.py +22 -14
  125. package/runtime/python/okstra_ctl/implementation_outcome.py +4 -7
  126. package/runtime/python/okstra_ctl/incremental_carry.py +2 -1
  127. package/runtime/python/okstra_ctl/incremental_scope.py +8 -3
  128. package/runtime/python/okstra_ctl/index.py +8 -11
  129. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +79 -7
  130. package/runtime/python/okstra_ctl/invocation.py +3 -6
  131. package/runtime/python/okstra_ctl/json_boundary.py +366 -0
  132. package/runtime/python/okstra_ctl/json_registry.py +10 -12
  133. package/runtime/python/okstra_ctl/jsonl.py +19 -2
  134. package/runtime/python/okstra_ctl/lead_events.py +33 -1
  135. package/runtime/python/okstra_ctl/listing.py +3 -3
  136. package/runtime/python/okstra_ctl/log_report.py +24 -2
  137. package/runtime/python/okstra_ctl/manager_cli.py +92 -7
  138. package/runtime/python/okstra_ctl/manager_store.py +12 -10
  139. package/runtime/python/okstra_ctl/material.py +5 -1
  140. package/runtime/python/okstra_ctl/migrate.py +29 -25
  141. package/runtime/python/okstra_ctl/model_cli.py +3 -15
  142. package/runtime/python/okstra_ctl/model_io_cli.py +1051 -0
  143. package/runtime/python/okstra_ctl/mutation_probe.py +13 -4
  144. package/runtime/python/okstra_ctl/pane_reclaim.py +3 -2
  145. package/runtime/python/okstra_ctl/paths.py +9 -0
  146. package/runtime/python/okstra_ctl/plan_items.py +115 -4
  147. package/runtime/python/okstra_ctl/plan_items_cli.py +513 -18
  148. package/runtime/python/okstra_ctl/pr_template.py +3 -2
  149. package/runtime/python/okstra_ctl/project_meta.py +5 -7
  150. package/runtime/python/okstra_ctl/recap.py +5 -4
  151. package/runtime/python/okstra_ctl/reconcile.py +21 -27
  152. package/runtime/python/okstra_ctl/registry/host_discovery.py +3 -2
  153. package/runtime/python/okstra_ctl/registry/provider_registry.py +3 -2
  154. package/runtime/python/okstra_ctl/render.py +26 -15
  155. package/runtime/python/okstra_ctl/render_final_report.py +3 -2
  156. package/runtime/python/okstra_ctl/report_assembly.py +172 -17
  157. package/runtime/python/okstra_ctl/report_finalize.py +7 -10
  158. package/runtime/python/okstra_ctl/report_html/render.py +3 -2
  159. package/runtime/python/okstra_ctl/report_language.py +3 -2
  160. package/runtime/python/okstra_ctl/report_markdown.py +13 -1
  161. package/runtime/python/okstra_ctl/report_narrative.py +40 -8
  162. package/runtime/python/okstra_ctl/report_synthesis_packet.py +518 -0
  163. package/runtime/python/okstra_ctl/report_views.py +3 -2
  164. package/runtime/python/okstra_ctl/rollup.py +65 -4
  165. package/runtime/python/okstra_ctl/run.py +159 -56
  166. package/runtime/python/okstra_ctl/run_audit.py +3 -2
  167. package/runtime/python/okstra_ctl/run_context.py +6 -9
  168. package/runtime/python/okstra_ctl/run_index_row.py +2 -8
  169. package/runtime/python/okstra_ctl/schedule_semantics.py +5 -2
  170. package/runtime/python/okstra_ctl/schema_excerpt.py +4 -2
  171. package/runtime/python/okstra_ctl/session_transcript.py +27 -1
  172. package/runtime/python/okstra_ctl/set_work_status.py +64 -38
  173. package/runtime/python/okstra_ctl/stage_fix_carry.py +4 -2
  174. package/runtime/python/okstra_ctl/stage_map.py +26 -6
  175. package/runtime/python/okstra_ctl/stage_targets.py +3 -4
  176. package/runtime/python/okstra_ctl/team.py +2 -1
  177. package/runtime/python/okstra_ctl/team_reconcile.py +11 -2
  178. package/runtime/python/okstra_ctl/time_report.py +51 -4
  179. package/runtime/python/okstra_ctl/usage_identity.py +2 -1
  180. package/runtime/python/okstra_ctl/usage_report.py +58 -4
  181. package/runtime/python/okstra_ctl/user_response.py +1431 -66
  182. package/runtime/python/okstra_ctl/wizard.py +11 -44
  183. package/runtime/python/okstra_ctl/work_categories.py +3 -2
  184. package/runtime/python/okstra_ctl/worker_prompt_body.py +18 -7
  185. package/runtime/python/okstra_ctl/worker_prompt_contract.py +3 -2
  186. package/runtime/python/okstra_ctl/worker_runner.py +14 -12
  187. package/runtime/python/okstra_ctl/workflow.py +2 -1
  188. package/runtime/python/okstra_ctl/worktree.py +3 -2
  189. package/runtime/python/okstra_ctl/wrapper_status.py +4 -2
  190. package/runtime/python/okstra_ctl/write_policy.py +4 -2
  191. package/runtime/python/okstra_token_usage/antigravity.py +39 -12
  192. package/runtime/python/okstra_token_usage/collect.py +90 -38
  193. package/runtime/python/okstra_token_usage/grok.py +127 -0
  194. package/runtime/schemas/final-report-v2.0.schema.json +9 -0
  195. package/runtime/schemas/final-report-v3.0.schema.json +9 -0
  196. package/runtime/schemas/report-synthesis-packet-v1.0.schema.json +140 -0
  197. package/runtime/skills/okstra-brief-gen/SKILL.md +9 -7
  198. package/runtime/skills/okstra-code-review/SKILL.md +21 -11
  199. package/runtime/skills/okstra-container-build/SKILL.md +18 -18
  200. package/runtime/skills/okstra-inspect/SKILL.md +12 -11
  201. package/runtime/skills/okstra-inspect/facets/error-zip.md +8 -8
  202. package/runtime/skills/okstra-inspect/facets/errors.md +2 -2
  203. package/runtime/skills/okstra-inspect/facets/history.md +9 -14
  204. package/runtime/skills/okstra-inspect/facets/logs.md +2 -2
  205. package/runtime/skills/okstra-inspect/facets/recap.md +5 -5
  206. package/runtime/skills/okstra-inspect/facets/report.md +6 -10
  207. package/runtime/skills/okstra-inspect/facets/status.md +9 -8
  208. package/runtime/skills/okstra-inspect/facets/time.md +3 -3
  209. package/runtime/skills/okstra-manager/SKILL.md +16 -14
  210. package/runtime/skills/okstra-memory/SKILL.md +3 -3
  211. package/runtime/skills/okstra-pr-gen/SKILL.md +5 -4
  212. package/runtime/skills/okstra-rollup/SKILL.md +6 -16
  213. package/runtime/skills/okstra-run/SKILL.md +7 -7
  214. package/runtime/skills/okstra-schedule-gen/SKILL.md +21 -17
  215. package/runtime/skills/okstra-setup/SKILL.md +21 -13
  216. package/runtime/skills/okstra-setup/references/project-config.md +2 -2
  217. package/runtime/skills/okstra-usage/SKILL.md +10 -10
  218. package/runtime/skills/okstra-user-response/SKILL.md +78 -107
  219. package/runtime/templates/report-writer-prompt-preamble.md +17 -1
  220. package/runtime/templates/reports/schedule.template.md +4 -4
  221. package/runtime/templates/worker-error-contract.md +17 -29
  222. package/runtime/validators/validate-run.py +379 -63
  223. package/runtime/validators/validate_session_conformance.py +43 -7
@@ -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.
@@ -1,193 +1,164 @@
1
1
  ---
2
2
  name: okstra-user-response
3
3
  description: >-
4
- Use this to answer an okstra task's open clarification questions in-session, without hand-editing any file. The tell is a request to respond to an okstra run's clarification items or its approval gate — "answer okstra", "I'll answer the questions", "clarification response", "user response", "approve and move on". This skill lists tasks whose latest report still has open clarification blockers, then walks the open C-ids one at a time — each rewritten as a self-contained question with background, its options with their impact plus "Enter directly" — echoes the collected answers back for an explicit "confirmed" acknowledgement, optionally records approval, and writes the `user-responses/` sidecar via `okstra user-response write`. NOT for starting a run (okstra-run), inspecting a finished task (okstra-inspect), or generating a brief (okstra-brief-gen). The skill never picks an answer — it builds the option board and transcribes what the user decides.
4
+ Use this to answer an okstra task's open clarification questions in-session without hand-editing a report or sidecar. It projects the available tasks and one report as fixed text, asks one question at a time, confirms the user's exact answers, and publishes only the user-owned user-responses sidecar through a typed transaction. NOT for starting a run, inspecting a finished task, or generating a brief.
5
5
  ---
6
6
 
7
7
  # OKSTRA User Response
8
8
 
9
- Single entry point for answering the clarification questions an okstra run left behind (the open `C-*` rows under the final report's `## 1. Clarification Items`) **in-session**, and recording those answers as a `runs/<type>/user-responses/` sidecar. The next `/okstra-run` auto-attaches this sidecar via `--clarification-response`.
9
+ Use this skill for open `C-*` clarification items and explicit plan decisions. The user alone selects or writes every answer. Never infer an answer or approval.
10
10
 
11
- **Core principle — the skill never picks an answer for the user.** It builds the option board — background, a self-contained question, the report's options with their impact, `Enter directly` — and the user alone picks from it; every `value` is what the user chose or typed. It never calls `write` until the user has explicitly confirmed.
11
+ The model-facing commands are fixed text reads and typed transaction writes:
12
12
 
13
- **Second principle — one question at a time.** Never batch two clarification items into one question, and never dump the whole open list at the user. Ask item 1, transcribe the answer, then ask item 2.
14
-
15
- | Sub-command | What it does |
13
+ | Command | Purpose |
16
14
  |---|---|
17
- | `list` | List tasks that still have approval-open clarification, newest report first. |
18
- | `show` | Expand one report's open `C-*` rows (statement + options + contextRefs). |
19
- | `write` | Record the collected answers (+ optional approval) as a `user-responses/` sidecar. |
15
+ | `user-response list-view` | Show tasks that still await user input. |
16
+ | `user-response show-view` | Show questions, choices, resolved context, and current response state. |
17
+ | `user-response begin` | Open a sidecar transaction for one report identity. |
18
+ | `user-response answer` | Add or replace one validated clarification answer. |
19
+ | `user-response plan-decision` | Record an explicit plan decision in the transaction. |
20
+ | `user-response legacy-report-authoring` | Record legacy report-authoring permission for report contract 2.0 only. |
21
+ | `user-response finalize` | Atomically merge and publish the user-owned sidecar. |
20
22
 
21
- ## Step 0: Preflight (shared)
23
+ Do not use the automation-oriented `list` or `show` commands. Do not open a report record to select fields. The fixed views provide every value this skill may use.
22
24
 
23
- Before anything:
25
+ ## Step 0: Preflight
24
26
 
25
27
  <!-- BEGIN FRAGMENT: bash-invocation-rule -->
26
28
  Run one Bash tool call, starting with the literal token `okstra` (never wrapped in `if`/`eval`/`export`/`$(...)`/`VAR=...`/`||`/`&&`/`npx` — a non-literal leading token defeats the `Bash(okstra:*)` permission match):
27
29
  <!-- END FRAGMENT: bash-invocation-rule -->
28
30
 
29
31
  ```bash
30
- okstra preflight --runtime claude-code --json
32
+ okstra preflight --runtime claude-code
31
33
  ```
32
34
 
33
- Branch on the stdout JSON:
34
- - `ok: true` → carry `projectRoot` and `projectId` as literal strings; they are the base for every step below.
35
- - `ok: false` → this project has no okstra setup. Tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop. If the user pointed at a specific project directory, 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 that **also** returns `ok:false` do you stop.
35
+ On `Okstra preflight: failed`, show `Reason` and `Recovery`, then stop. On `Okstra preflight: ready`, carry the fixed `Project root` and `Project ID` lines as literal values.
36
36
 
37
37
  <!-- BEGIN FRAGMENT: preflight-outdated-cli -->
38
38
  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).
39
39
  <!-- END FRAGMENT: preflight-outdated-cli -->
40
40
 
41
- Then resolve the okstra home once (the `list` sub-command needs it):
41
+ Resolve the installed home:
42
42
 
43
43
  ```bash
44
44
  okstra paths --field home
45
45
  ```
46
46
 
47
- Paste the printed path literally into `--home` below.
48
-
49
47
  <!-- BEGIN FRAGMENT: python-bootstrap-note -->
50
48
  Every subsequent `okstra <subcmd>` call self-bootstraps its Python path, so this skill never needs `okstra paths --shell` / `export PYTHONPATH=...`.
51
49
  <!-- END FRAGMENT: python-bootstrap-note -->
52
50
 
53
- ## Step 1: List awaiting tasks → picker
51
+ ## Step 1: Select a task from the fixed list view
54
52
 
55
53
  ```bash
56
- okstra user-response list --home <resolved-home> --project <projectId> --limit 3
54
+ okstra user-response list-view --home <resolved-home> --project <projectId> --limit 3
57
55
  ```
58
56
 
59
- Returns a JSON array (latest report mtime first); each entry:
60
- `{taskKey, taskType, seq, reportPath, reportMtime, openBlockerCount, openApprovalCount, unreadable}`. `openBlockerCount` counts every open row that still owes the user an answer (`Blocks` = `approval` or `next-phase`); `openApprovalCount` is the `approval`-only subset that gates the frontmatter `approved` flip.
57
+ The view gives `Task key`, `Task type`, `Report`, open-item counts, and readability status. If the count is zero, answer `No task has open clarification items.` and stop. Do not continue with an unreadable entry.
61
58
 
62
- - Empty array → answer `No task has open clarification items.` and stop.
63
- - Otherwise present a **3-option picker**: the top recommendations from the list (each shown as `taskKey (taskType, <openBlockerCount> open items)`), and the **final option is always "Enter directly"** — where the user pastes a `reportPath` or a `task-key` directly (for a task not in the top-3 window).
64
- - An entry with `unreadable: true` means its `## 1. Clarification Items` heading exists but drifted from the expected format. Flag it as `⚠ §1 format drift — the CLI could not parse its items` and do not proceed on it until the report is regenerated; do not fabricate rows for it.
59
+ Present up to three task choices. The final picker option is `Enter directly`, where the user may provide a report path or task key.
65
60
 
66
- Carry the chosen entry's `reportPath` and `taskKey` forward.
67
-
68
- ## Step 2: Fetch the open rows (data only — ask nothing yet)
61
+ ## Step 2: Read the fixed report view
69
62
 
70
63
  ```bash
71
- okstra user-response show --report <reportPath>
64
+ okstra user-response show-view --report <reportPath> --project-root <projectRoot>
72
65
  ```
73
66
 
74
- Returns `{reportPath, rows: [{id, kind, blocks, status, statement, expectedForm, options, contextRefs, resolvedRefs}]}`.
75
-
76
- Each entry of `options[]` is `{role, answer, rationale, scopeImpact, addedWork, directionChange, disposition}`. `role` is `recommended` for exactly one entry and `alternative` for the rest; `scopeImpact` is a token list drawn from `in-repo` / `cross-repo` / `new-schema` / `deferrable`; `addedWork` and `directionChange` are one sentence each. Activity-contract v1 approval options also carry the gate action in `disposition`. A legacy schema-v1 report has nowhere to record impact or a gate action, so those fields arrive empty — the CLI reconstructs only the answers from the report's `Expected form` cell.
77
-
78
- `resolvedRefs` is `[{ref, definition}]` — the CLI has already looked up what each record coordinate (`RB-002`, `FU-001`) means in the report record; `definition` is `null` when the record has no such row, when the citation is a section number (`§4.7`, leftover from an older report), or when the citation is a `path:line` pointer.
79
-
80
- This call is a **data fetch, not a presentation step**. Do not print `rows` at the user, and do not paste a raw `statement` as a question — a `statement` like `Rewrite RB-002 rollback (see §4.7)` is meaningless on its own, which is the whole reason this skill exists. Announce only the count and the plan:
81
-
82
- > `<N>` open items — I'll go through them one at a time.
67
+ The view contains the report identity, contract version, every open clarification question, its expected form, its current response and disposition, its options, approval context, plan option candidates, current plan decision, and resolved context. It is the only report-information source for this skill.
83
68
 
84
- Step 3 then turns exactly one row at a time into a question.
69
+ Each entry in `options[]` corresponds to `{role, answer, rationale, scopeImpact, addedWork, directionChange, disposition}`. Put the `recommended` option first and suffix its label with `(Recommended)`. Then put the alternatives in view order and finish with `Enter directly`.
85
70
 
86
- ## Step 3: Ask one item at a time (loop)
71
+ Contract 3.0 options also expose `reach` and `scopeEffects`. Contract 3.0 approval-blocking rows expose `approvalContext`. Present those values exactly as the view prints them.
87
72
 
88
- Walk the open rows in report order. **One item per `AskUserQuestion` call** — never batch two items into one call, and never pre-announce the items still to come. Ask, transcribe, move on. Head each item with its position and what it is holding up:
73
+ Each option description uses all three impact axes in this order:
89
74
 
90
- > **[2/5] C-014** — blocks: approval gate
75
+ > `<rationale>` — Scope: `<scopeImpact>` · Added work: `<addedWork>` · Direction: `<directionChange>`
91
76
 
92
- ### 3a. Background first (plain text, above the picker)
77
+ When an axis says `not stated in the report`, repeat that text. Do not infer missing impact. The skill must **never invent it**.
93
78
 
94
- `AskUserQuestion` carries one sentence of question, so the background goes in the message text right before the call. Write these three blocks, **3–6 lines total** — enough that someone who never read the report can answer:
79
+ ## Step 3: Ask one clarification at a time
95
80
 
96
- 1. **Situation** — what the run was doing when it stopped at this item, in the user's own domain terms.
97
- 2. **What is undecided** — the actual fork, with every internal token expanded inline from `resolvedRefs[].definition`; the user must never need to know what `RB-002` is to answer. Say what is stuck right now in plain words: `blocks: approval` → the approval gate stays shut and `implementation` cannot start; `blocks: next-phase` → the next phase cannot begin.
98
- 3. **What changes with your answer** — what each direction actually causes downstream.
81
+ For each item that still needs an answer, show its position, ID, blocking effect, question, expected form, and resolved context. Use one single-select question per clarification.
99
82
 
100
- Where the background comes from — in this order:
83
+ Use the displayed values to confirm the user's choice. Do not copy a predefined option's answer, disposition, reach, or scope effects into command arguments. The typed command resolves those report-owned fields from its option number.
101
84
 
102
- - `resolvedRefs[].definition`, which is already resolved and needs no file read;
103
- - when a `definition` is `null`, or the three blocks would otherwise be empty, **Read** the report record (the `.data.json` at `reportPath`) and take the cited row's `statement` / `summary` / `item` from there. Do not open the full reading copy to chase a `§` number — that number is not a record coordinate;
104
- - **never invent it.** If the report genuinely does not say why, write `The report states nothing beyond the statement itself.` and go straight to the question. Fabricated background corrupts the answer it collects.
105
-
106
- Close the background with the raw source on one line, so the mapping back to the report stays visible:
107
-
108
- > Source: `C-014` — "<raw statement>"
109
-
110
- ### 3b. The picker — the report's options plus `Enter directly`
111
-
112
- One `AskUserQuestion` (single-select). Fill the slots from `options[]` in array order — the `role: recommended` entry first with its label suffixed `(Recommended)`, then the `alternative` entries — and always close with `Enter directly` as the last option. Never mark anything but the `recommended` entry as recommended.
113
-
114
- Each `label` is that option's `answer`, kept to the answer itself (1–5 words). Each `description` carries the rationale followed by the three impact axes, in this fixed order:
85
+ | User action | Value | Disposition |
86
+ |---|---|---|
87
+ | Selects an option | that option's `answer` | that option's `disposition` |
88
+ | Enters an answer | the user's text verbatim | `answer` |
89
+ | Asks for the item to be presented again | the user's request verbatim | `reframe` |
115
90
 
116
- > `<rationale>` — Scope: `<scopeImpact, comma-joined>` · Added work: `<addedWork>` · Direction: `<directionChange>`
91
+ Copy `kind` from the view. A `reframe` does not satisfy the gate. If the user asks what an item means, explain only from the view and ask the same item again.
117
92
 
118
- The three axes answer three different questions: how far the choice reaches, what new work it creates, and what it overturns. Never fold them into one phrase — whichever is easiest to write ends up standing in for the other two, and the user weighs a scope change as though it were free. That is the failure this board exists to prevent.
93
+ ## Step 4: Confirm the complete response
119
94
 
120
- When an axis is empty — a schema-v1 report has nowhere to record impact — write `not stated in the report` for that axis. Do not infer it, and do not read the code to reconstruct it. A guessed side effect is worse than a stated gap, because the user cannot tell the two apart.
95
+ Echo each clarification ID, kind, disposition, value, and rationale. Include any explicit plan decision or legacy report-authoring decision. Ask:
121
96
 
122
- When `options[]` carries more than three entries, keep the recommended one plus the two alternatives whose `scopeImpact` differs most from it, and say in the background text how many you left out. When it carries exactly two, the picker has three options in total — do not pad it with an invented third.
97
+ > Record it as shown above? Reply `confirmed` to publish the sidecar.
123
98
 
124
- ### 3c. Transcribe the decision, then move on
99
+ Do not start a transaction until the user clearly confirms. If the user changes an item, show the complete response again and reconfirm.
125
100
 
126
- Record one entry — `{id, kind, value, rationale?, disposition}`, `kind` copied from the row `show` returned:
101
+ ## Step 5: Begin the typed transaction
127
102
 
128
- | The user picks | `value` | `disposition` |
129
- |---|---|---|
130
- | One of the `options[]` entries | that option's `answer` text, not its short label | that option's `disposition` (`answer` only when absent on a legacy option) |
131
- | `Enter directly` → their own answer | the user's utterance verbatim (rationale into `rationale`) | `answer` |
132
- | Free text asking for the item to be re-asked | what the user wants re-asked, verbatim (empty → the raw statement) | `reframe` |
103
+ ```bash
104
+ okstra user-response begin --report <reportPath> --task-key <taskKey>
105
+ ```
133
106
 
134
- A reframe is not an answer, so it does not satisfy the approval gate.
107
+ Carry the returned opaque `transaction` value exactly. Do not decode it or inspect its state file.
135
108
 
136
- If the user replies with a question instead of an answer ("what does this mean?"), record nothing: **Read** the report record for the cited row id from `contextRefs[]`, explain it in plain language, and re-ask the same item with the same options. Explain only — **do not resolve it for them**; the decision goes back to the user.
109
+ For a predefined option, pass only its one-based number from the fixed view:
137
110
 
138
- Echo one line per finished item (`[2/5] C-014 → answer: 60s`), then ask the next one. Do not summarize the whole set until Step 4.
111
+ ```bash
112
+ okstra user-response answer --transaction <transaction> --clarification-id <C-NNN> --kind <kind> --option-number <N>
113
+ ```
139
114
 
140
- ## Step 4: Echo the full sidecar back → explicit "confirmed" gate
115
+ Every value, rationale, and reason body file must be a regular file under `<projectRoot>/.okstra/tmp/user-response/`; do not use an external file or a symbolic link. For a direct user answer, write the exact value there. Write the rationale to a separate Markdown file only when present. Then run:
141
116
 
142
- Once the loop has covered every open item, **before** calling `write`, **echo back** everything collected (each `id`, `disposition`, `value`, `rationale` if present, and the approval decision from Step 5 below) to the user as-is. Then ask for explicit confirmation:
117
+ ```bash
118
+ okstra user-response answer --transaction <transaction> --clarification-id <C-NNN> --kind <kind> --disposition <disposition> --value-file <value.md> [--rationale-file <rationale.md>]
119
+ ```
143
120
 
144
- > Record it as shown above? (Reply `confirmed` to write the sidecar.)
121
+ The two answer forms are mutually exclusive. The command validates that the clarification ID and kind exist and remain open in the selected report. Repeating the same answer command is safe.
145
122
 
146
- - **Never call `write`** until the user says `confirmed` (or gives clear approval).
147
- - If the user changes any item, show the echo-back again with the changed value and re-confirm.
148
- - Every `value` must be what the user picked or typed, never a wording you settled on for them — this gate guarantees that.
123
+ ## Step 6: Record an explicit decision when present
149
124
 
150
- ## Step 5: (Optional) Record the plan decision
125
+ When the user explicitly approved a plan:
151
126
 
152
- Record a decision alongside the answers only when the user stated one outright. Never infer it from the tone of the conversation.
127
+ ```bash
128
+ okstra user-response plan-decision --transaction <transaction> --status approved [--implementation-option <name>]
129
+ ```
153
130
 
154
- Approval also requires that the report's approval-blocking clarification items are **all filled with an answer**:
131
+ For `revision-requested` or `rejected`, write the user's reason verbatim to a Markdown file in that same temporary directory and pass it:
155
132
 
156
- ```
157
- --plan-decision '{"status":"approved","implementationOption":"<the option the user chose>"}'
133
+ ```bash
134
+ okstra user-response plan-decision --transaction <transaction> --status <revision-requested|rejected> --reason-file <reason.md>
158
135
  ```
159
136
 
160
- If any approval-target item is not filled with an answer, or is a reframe/hold, do not approve — tell the user the gate is still open.
137
+ Never infer a plan decision from the user's tone.
161
138
 
162
- A user who turns the plan down gets the same treatment, and the reason is mandatory — the next planning run reads it to know what to change:
139
+ Only for a report whose fixed view says `Report contract: 2.0`, an explicit legacy report-authoring decision may be recorded. A reason file in that same temporary directory is always required:
163
140
 
141
+ ```bash
142
+ okstra user-response legacy-report-authoring --transaction <transaction> --status <approved|denied> --reason-file <reason.md>
164
143
  ```
165
- --plan-decision '{"status":"rejected","reason":"<the user's own words>"}'
166
- ```
167
-
168
- Use `revision-requested` instead of `rejected` when the user wants the same plan reworked rather than dropped. Either way, quote the user's reason; do not summarise it into your own.
169
144
 
170
- ## Step 6: Write the sidecar
145
+ Report contract 3.0 rejects this command because report inputs have separate owners.
171
146
 
172
- Run only after the user has confirmed the echo-back with "confirmed":
147
+ ## Step 7: Finalize once
173
148
 
174
149
  ```bash
175
- okstra user-response write --report <reportPath> --answers '<answers-json>' --plan-decision '<plan-decision-json>' --task-key <taskKey>
150
+ okstra user-response finalize --transaction <transaction>
176
151
  ```
177
152
 
178
- - `--answers` = the JSON array of `{id, kind, value, rationale?, disposition}` objects collected in Step 3.
179
- - `--plan-decision` is attached only when recording a decision in Step 5 (otherwise omit it).
180
- - `--task-key` is the value carried forward from Step 1/2.
181
- - Report the path from the returned JSON `{sidecar: <path>}` to the user. (`write` merges items when a sidecar already exists — the same `id` is overwritten with the new value.)
182
-
183
- ## Step 7: Self-describing next-step guidance
153
+ Only `finalize` publishes the sidecar. Report the returned `sidecar` path. A retry with the same transaction returns the same published result.
184
154
 
185
- Leave the following in the final output as-is:
155
+ Leave this guidance in the final answer:
186
156
 
187
- > This answer was recorded in the `user-responses/` sidecar (`<sidecar path>`). Re-running this task's `<task-type>` with `/okstra-run` auto-attaches this answer (if you approved all approval-blocking items, the next phase is `implementation`).
157
+ > This answer was recorded in the `user-responses/` sidecar (`<sidecar path>`). Re-running this task with `/okstra-run` attaches the answer to the next eligible phase.
188
158
 
189
- ## Output Rules (shared)
159
+ ## Output rules
190
160
 
191
- - Keep responses concise and in the language the user is using, unless they ask otherwise.
192
- - Give path guidance host-relative (`~/.okstra/...` or relative to the `projectRoot` preflight returned). Use repo paths only when pointing at a code source.
193
- - This skill never hand-edits a rendered report (`runs/*/reports/*.md` / `*.data.json`). Writing the `user-responses/` sidecar goes only through the `okstra user-response write` CLI.
161
+ - Keep responses in the user's language.
162
+ - Never edit a rendered report, report record, approval ledger, lead events, team state, convergence state, or report-writer narrative.
163
+ - Never edit a `user-responses/` sidecar directly. Publish it only with `user-response finalize`.
164
+ - Never create or parse structured state for these commands. Pass scalar arguments and Markdown body files only.
@@ -20,7 +20,23 @@ Write the audit sidecar before synthesis with one `- PROGRESS: <stage> <ISO-8601
20
20
 
21
21
  ## Narrative format
22
22
 
23
- Start with `# OKSTRA Report Narrative`. Encode fields as nested Markdown list entries using `- **Humanised Field Name**`; use `- Item N` for array entries and `> value` for scalar or multiline values. Follow the task-specific schema order and write the prose in English. JSON, YAML, JSON Pointer, and fenced JSON are not narrative syntax.
23
+ The narrative is not free-form Markdown. A narrative file is the line `# OKSTRA Report Narrative`, then lines of exactly three shapes and nothing else:
24
+
25
+ - `- **Humanised Field Name**` — one field. Nest a child field by indenting two more spaces.
26
+ - `- Item <N>` — one array entry, numbered `1..N` with no gaps.
27
+ - `> value` — one scalar. Repeat the line for a multi-line value. Write `> _none_` for null, an empty object, or an empty array.
28
+
29
+ Blank lines are ignored. **Every other line is rejected**, including Markdown headings (`#`, `##`, `###`), a pipe table written at column 0, code fences, bare paragraphs, JSON, YAML, and JSON Pointer. A heading or table that belongs in the reader's report is written as the text of a `> ` value, never as a narrative line of its own.
30
+
31
+ Follow the task-specific schema order and write the prose in English.
32
+
33
+ ### Top-level fields you may author
34
+
35
+ These are the only names allowed at the top level:
36
+
37
+ `Analysis Common`, `Change Impact Analysis`, `Error Analysis`, `Feature Analysis`, `Final Verdict`, `Final Verification`, `Follow Up Tasks`, `Human Summary`, `Implementation`, `Implementation Option Selection`, `Implementation Planning`, `Improvement Discovery`, `Project Analysis`, `Rationale`, `Recommended Next Steps`, `Release Handoff`, `Requirements Discovery`, `Summary`, `Ticket Coverage`, `Verdict Card`
38
+
39
+ Any other top-level name is rejected however reasonable it reads — a section title copied out of a lead procedure document (`Clarification Response Carried In`, `Stage Map`, `Rollback Strategy`) is a heading in that document, not a top-level field here. Nested names come from the task's block in `schemas/final-report-v3.0.schema.json`; when a name is refused, the parser's message lists the names allowed at that exact position, so correct against that list rather than guessing a second time.
24
40
 
25
41
  ## Pointer record
26
42
 
@@ -200,10 +200,10 @@ Stage 3 ██████░░░░
200
200
  **Solution**: <…>
201
201
 
202
202
  <!-- Everything below this line is transcribed from the planning report the CLI
203
- resolved — `okstra stage-map <task-key> --json` carries each stage's
204
- `acceptance` / `exitContract` / `sliceValue` and the task-level
205
- `rollbackStrategy` / `validationChecklist` / `dependencyMigrationRisk`
206
- rows. Transcribe those rows; do not re-summarise the report body. -->
203
+ resolved — `okstra stage-map <task-key> --text` carries fixed `Stages` and
204
+ `Planning` count/name/value rows for each stage's acceptance, exit contract,
205
+ slice value, and the task-level rollback, validation, and migration-risk
206
+ fields. Transcribe those rows; do not re-summarise the report body. -->
207
207
 
208
208
  **Work Breakdown**:
209
209
 
@@ -1,6 +1,6 @@
1
1
  # Worker Error Contract (canonical)
2
2
 
3
- This audience-neutral file is the single source of truth for every initial worker's error path, sidecar schema, and write protocol. Read it end-to-end from `**Worker Error Contract Path:**` before work.
3
+ This audience-neutral file is the single source of truth for every initial worker's error path and typed write command. Read it end-to-end from `**Worker Error Contract Path:**` before work.
4
4
 
5
5
  ## Error reporting
6
6
 
@@ -12,44 +12,32 @@ Record a tool call only when its failure blocked the step you intended. A non-ze
12
12
 
13
13
  If the non-zero exit changed nothing about what you could do next, it is normal. When in doubt, record the real blocker: under-recording a real blocker is worse than one noisy entry.
14
14
 
15
- If the sidecar does not exist when a real failure occurs, create `{"schemaVersion": 1, "errors": []}` and append one entry.
16
-
17
- ### Entry schema
18
-
19
- ```json
20
- {
21
- "ts": "<ISO 8601 UTC>",
22
- "phase": "<current okstra phase>",
23
- "errorType": "tool-failure",
24
- "command": "<failed command/tool signature>",
25
- "commandKind": "bash | tool:Read | tool:Edit | mcp | ...",
26
- "exitCode": null,
27
- "durationMs": null,
28
- "message": "<one-line human summary>",
29
- "stderrExcerpt": null,
30
- "context": {
31
- "cause": "sandbox-denied | service-unavailable | auth-failed | unknown",
32
- "causeEvidence": {
33
- "targetProbe": "<command + raw output proving the target's state>",
34
- "controlProbe": "<command + raw output proving another target is reachable>"
35
- }
36
- }
37
- }
15
+ For each real failure, invoke this typed command. Replace only the angle-bracket values supplied by the dispatch prompt or observed from the failed call. Do not create a JSON file or pass JSON text.
16
+
17
+ ```bash
18
+ okstra error-log append-observed \
19
+ --out <absolute-errors-log-path> \
20
+ --task-key <task-key> --phase <phase> \
21
+ --agent <assigned-agent> --agent-role worker --model <assigned-model> \
22
+ --error-type tool-failure --command-file <failed-command-file> \
23
+ --command-kind <command-kind> --message-file <message-markdown-file> \
24
+ --cause sandbox-denied \
25
+ --evidence-file targetProbe=<target-probe-file> \
26
+ --evidence-file controlProbe=<control-probe-file>
38
27
  ```
39
28
 
40
- `context` and both `cause` fields are optional; omit `context` entirely (`null`) when there is nothing to add.
29
+ For a cause other than `sandbox-denied`, replace the cause value and omit both `--evidence-file` arguments unless you observed the required probes. Put any free-form message or probe output in the supplied Markdown file rather than relying on shell quoting.
41
30
 
42
31
  ### Rules
43
32
 
44
- - Do not add `source`, `recordedAt`, `agent`, `agentRole`, `model`, or `taskKey`; the lead supplies them when merging the sidecar.
45
- - The sidecar accepts only `errorType: "tool-failure"`. CLI wrappers write `cli-failure` directly to the run log; the lead records `contract-violation`.
46
- - To record a block (sandbox/permission) as the cause, submit `context.cause = "sandbox-denied"` together with both probes in `context.causeEvidence`. Without the probes, leave `cause` as `unknown` — and then keep `message` to what you observed (`connection refused`, `1045 access denied`), not what you infer. A block asserted in `message` prose is rejected exactly like one asserted in `cause`, so "sandbox blocked it" with `cause: unknown` fails the write too. Failing to reach a target and the target being down are not the same fact — never assert the former without checking. Only `sandbox-denied` requires evidence; `service-unavailable` and `auth-failed` do not. Each probe is stored truncated to 256 bytes, so lead with the decisive command and its output.
33
+ - Use only `--error-type tool-failure`. CLI wrappers write `cli-failure` directly to the run log; the lead records `contract-violation`.
34
+ - To record a block (sandbox/permission) as the cause, pass `--cause sandbox-denied` together with both `--evidence-file targetProbe=<target-probe-file>` and `--evidence-file controlProbe=<control-probe-file>`. Without the probes, pass `--cause unknown` — and then keep the `--message-file` content to what you observed (`connection refused`, `1045 access denied`), not what you infer. A block asserted in message prose is rejected exactly like one asserted in the cause. Failing to reach a target and the target being down are not the same fact. Only `sandbox-denied` requires evidence; `service-unavailable` and `auth-failed` do not. Each probe is stored truncated to 256 bytes, so lead with the decisive command and its output.
47
35
  - [Guideline] Put raw output in `stderrExcerpt` verbatim. Never merge several commands' output into one line, summarize it, or elide it with `...`. Once the host, port, and errno are gone, the cause cannot be recovered later.
48
36
  - Continue after recording unless the failure makes the task impossible.
49
37
 
50
38
  ### Path extraction (BLOCKING)
51
39
 
52
- Extract `**Errors log path:**` and `**Errors sidecar path:**` verbatim from the dispatch prompt. If either is absent, return the worker-specific `<SENTINEL_PREFIX>_ERRORS_PATH_MISSING` sentinel and stop. Never synthesize a path from a run-directory pattern.
40
+ Extract `**Errors log path:**` verbatim from the dispatch prompt. If it is absent, return the worker-specific `<SENTINEL_PREFIX>_ERRORS_PATH_MISSING` sentinel and stop. Never synthesize a path from a run-directory pattern.
53
41
 
54
42
  ## Path anchoring
55
43