okstra 0.202.0 → 0.205.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/README.md +7 -6
  2. package/dist/cli-registry.mjs +7 -7
  3. package/dist/cli-registry.mjs.map +1 -1
  4. package/dist/commands/lifecycle/install.mjs +50 -124
  5. package/dist/commands/lifecycle/install.mjs.map +1 -1
  6. package/dist/commands/memory/memory.mjs +41 -8
  7. package/dist/commands/memory/memory.mjs.map +1 -1
  8. package/dist/lib/install-assets.mjs +3 -0
  9. package/dist/lib/install-assets.mjs.map +1 -1
  10. package/dist/lib/runtime-manifest.mjs +2 -1
  11. package/dist/lib/runtime-manifest.mjs.map +1 -1
  12. package/dist/lib/types.d.mts +2 -1
  13. package/docs/architecture/storage-model.md +14 -11
  14. package/docs/architecture.md +26 -20
  15. package/docs/cli.md +15 -12
  16. package/docs/contributor-change-matrix.md +3 -2
  17. package/docs/performance-improvement-plan-v2.md +3 -9
  18. package/docs/project-structure-overview.md +39 -11
  19. package/docs/task-process/README.md +1 -1
  20. package/docs/task-process/common-flow.md +1 -1
  21. package/docs/task-process/final-verification.md +3 -1
  22. package/docs/task-process/implementation-option-selection.md +1 -1
  23. package/docs/task-process/implementation.md +1 -1
  24. package/docs/task-process/release-handoff.md +36 -39
  25. package/package.json +1 -2
  26. package/runtime/BUILD.json +2 -2
  27. package/runtime/agents/common.json +28 -0
  28. package/runtime/agents/operations/code-review.json +6 -0
  29. package/runtime/agents/operations/report-translation.json +6 -0
  30. package/runtime/agents/operations/schedule-verification.json +6 -0
  31. package/runtime/agents/roles/analyser.json +18 -0
  32. package/runtime/agents/roles/critic.json +18 -0
  33. package/runtime/agents/roles/designer.json +18 -0
  34. package/runtime/agents/roles/implementer.json +20 -0
  35. package/runtime/agents/roles/leader.json +20 -0
  36. package/runtime/agents/roles/planner.json +18 -0
  37. package/runtime/agents/roles/report-writer.json +19 -0
  38. package/runtime/agents/roles/translator.json +19 -0
  39. package/runtime/agents/roles/verifier.json +18 -0
  40. package/runtime/bin/lib/okstra/usage.sh +5 -5
  41. package/runtime/prompts/duties/acceptance-critic.json +32 -0
  42. package/runtime/prompts/duties/acceptance-verifier.json +32 -0
  43. package/runtime/prompts/duties/analysis-worker.json +32 -0
  44. package/runtime/prompts/duties/code-reviewer.json +32 -0
  45. package/runtime/prompts/duties/diagnosis-worker.json +32 -0
  46. package/runtime/prompts/duties/direction-selection-worker.json +32 -0
  47. package/runtime/prompts/duties/discovery-worker.json +32 -0
  48. package/runtime/prompts/duties/implementation-executor.json +32 -0
  49. package/runtime/prompts/duties/implementation-verifier.json +32 -0
  50. package/runtime/prompts/duties/lead.json +32 -0
  51. package/runtime/prompts/duties/planning-worker.json +36 -0
  52. package/runtime/prompts/duties/report-writer.json +32 -0
  53. package/runtime/prompts/duties/reverification-worker.json +32 -0
  54. package/runtime/prompts/duties/schedule-verifier.json +32 -0
  55. package/runtime/prompts/duties/scope-critic.json +32 -0
  56. package/runtime/prompts/duties/technical-verification-worker.json +32 -0
  57. package/runtime/prompts/duties/translator.json +32 -0
  58. package/runtime/prompts/launch.template.md +2 -1
  59. package/runtime/prompts/lead/adapters/cmux.md +1 -1
  60. package/runtime/prompts/lead/convergence.md +4 -4
  61. package/runtime/prompts/lead/okstra-lead-contract.md +115 -6
  62. package/runtime/prompts/lead/plan-body-verification.md +6 -6
  63. package/runtime/prompts/lead/report-writer.md +3 -3
  64. package/runtime/prompts/profiles/_common-contract.md +2 -2
  65. package/runtime/prompts/profiles/_implementation-diff-review.md +1 -1
  66. package/runtime/prompts/profiles/_implementation-executor.md +4 -1
  67. package/runtime/prompts/profiles/_implementation-self-check.md +1 -1
  68. package/runtime/prompts/profiles/_implementation-verifier.md +2 -2
  69. package/runtime/prompts/profiles/change-impact-analysis.json +31 -0
  70. package/runtime/prompts/profiles/change-impact-analysis.md +0 -20
  71. package/runtime/prompts/profiles/error-analysis.json +39 -0
  72. package/runtime/prompts/profiles/error-analysis.md +0 -25
  73. package/runtime/prompts/profiles/feature-analysis.json +31 -0
  74. package/runtime/prompts/profiles/feature-analysis.md +0 -20
  75. package/runtime/prompts/profiles/final-verification.json +30 -0
  76. package/runtime/prompts/profiles/final-verification.md +4 -23
  77. package/runtime/prompts/profiles/forbidden-actions.json +4 -3
  78. package/runtime/prompts/profiles/implementation-option-selection.json +31 -0
  79. package/runtime/prompts/profiles/implementation-option-selection.md +0 -20
  80. package/runtime/prompts/profiles/implementation-planning.json +40 -0
  81. package/runtime/prompts/profiles/implementation-planning.md +4 -29
  82. package/runtime/prompts/profiles/implementation.json +30 -0
  83. package/runtime/prompts/profiles/implementation.md +1 -20
  84. package/runtime/prompts/profiles/improvement-discovery.json +31 -0
  85. package/runtime/prompts/profiles/improvement-discovery.md +0 -20
  86. package/runtime/prompts/profiles/project-analysis.json +31 -0
  87. package/runtime/prompts/profiles/project-analysis.md +0 -20
  88. package/runtime/prompts/profiles/release-handoff.json +5 -0
  89. package/runtime/prompts/profiles/release-handoff.md +74 -74
  90. package/runtime/prompts/profiles/requirements-discovery.json +39 -0
  91. package/runtime/prompts/profiles/requirements-discovery.md +0 -25
  92. package/runtime/prompts/profiles/technical-verification.json +39 -0
  93. package/runtime/prompts/profiles/technical-verification.md +0 -25
  94. package/runtime/prompts/wizard/prompts.ko.json +14 -18
  95. package/runtime/python/okstra_ctl/adapters/hosts/antigravity/relay.md +1 -0
  96. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +3 -0
  97. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/manifest.json +1 -1
  98. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +4 -3
  99. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/worker-session.md +108 -0
  100. package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +1 -0
  101. package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +2 -0
  102. package/runtime/python/okstra_ctl/adapters/hosts/kimi/relay.md +2 -0
  103. package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +8 -1
  104. package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +8 -0
  105. package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +23 -6
  106. package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +6 -2
  107. package/runtime/python/okstra_ctl/agent/invocation.py +168 -113
  108. package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +120 -0
  109. package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +107 -2
  110. package/runtime/python/okstra_ctl/agent/prompt_cli/run_identity.py +0 -49
  111. package/runtime/python/okstra_ctl/analysis_packet.py +4 -1
  112. package/runtime/python/okstra_ctl/application/open_worker.py +6 -1
  113. package/runtime/python/okstra_ctl/assignment_resolver.py +16 -5
  114. package/runtime/python/okstra_ctl/cmux.py +69 -20
  115. package/runtime/python/okstra_ctl/code_review_target.py +16 -8
  116. package/runtime/python/okstra_ctl/conformance.py +43 -0
  117. package/runtime/python/okstra_ctl/consumers.py +23 -8
  118. package/runtime/python/okstra_ctl/container.py +31 -8
  119. package/runtime/python/okstra_ctl/context_cost.py +11 -15
  120. package/runtime/python/okstra_ctl/contract_refreeze.py +156 -0
  121. package/runtime/python/okstra_ctl/convergence_engine.py +38 -0
  122. package/runtime/python/okstra_ctl/convergence_provenance.py +7 -1
  123. package/runtime/python/okstra_ctl/design_prep.py +34 -1
  124. package/runtime/python/okstra_ctl/dispatch_core.py +53 -27
  125. package/runtime/python/okstra_ctl/domain/host.py +5 -0
  126. package/runtime/python/okstra_ctl/domain/worker_runtime.py +10 -0
  127. package/runtime/python/okstra_ctl/error_report.py +4 -3
  128. package/runtime/python/okstra_ctl/execution_manifest.py +71 -18
  129. package/runtime/python/okstra_ctl/handoff.py +384 -286
  130. package/runtime/python/okstra_ctl/handoff_verification.py +25 -6
  131. package/runtime/python/okstra_ctl/implementation_stage.py +9 -0
  132. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +113 -0
  133. package/runtime/python/okstra_ctl/lead_progress.py +1 -1
  134. package/runtime/python/okstra_ctl/legacy_model_selection.py +2 -2
  135. package/runtime/python/okstra_ctl/manager_cli.py +92 -4
  136. package/runtime/python/okstra_ctl/manager_launch.py +1 -1
  137. package/runtime/python/okstra_ctl/manager_paths.py +14 -3
  138. package/runtime/python/okstra_ctl/manager_store.py +210 -3
  139. package/runtime/python/okstra_ctl/manager_sync.py +4 -1
  140. package/runtime/python/okstra_ctl/manager_view.py +2 -1
  141. package/runtime/python/okstra_ctl/model_discovery.py +30 -0
  142. package/runtime/python/okstra_ctl/model_io/lines.py +14 -1
  143. package/runtime/python/okstra_ctl/model_io/renderers.py +4 -3
  144. package/runtime/python/okstra_ctl/models.py +1 -1
  145. package/runtime/python/okstra_ctl/next_phase.py +16 -6
  146. package/runtime/python/okstra_ctl/operation_invocation.py +86 -0
  147. package/runtime/python/okstra_ctl/option_comparison.py +168 -0
  148. package/runtime/python/okstra_ctl/path_hints.py +9 -0
  149. package/runtime/python/okstra_ctl/paths.py +3 -0
  150. package/runtime/python/okstra_ctl/profile_show.py +42 -1
  151. package/runtime/python/okstra_ctl/registry/host_discovery.py +20 -12
  152. package/runtime/python/okstra_ctl/registry/host_registry.py +11 -0
  153. package/runtime/python/okstra_ctl/render.py +79 -0
  154. package/runtime/python/okstra_ctl/report_contract.py +1 -1
  155. package/runtime/python/okstra_ctl/report_html/view_models/release_handoff.py +21 -3
  156. package/runtime/python/okstra_ctl/report_synthesis_packet.py +177 -17
  157. package/runtime/python/okstra_ctl/report_translation.py +2 -1
  158. package/runtime/python/okstra_ctl/report_translation_dispatch.py +69 -9
  159. package/runtime/python/okstra_ctl/role_requirements.py +142 -129
  160. package/runtime/python/okstra_ctl/rollup.py +3 -1
  161. package/runtime/python/okstra_ctl/run.py +76 -29
  162. package/runtime/python/okstra_ctl/schedule_semantics.py +17 -6
  163. package/runtime/python/okstra_ctl/stage_fix_carry.py +23 -4
  164. package/runtime/python/okstra_ctl/stage_integrate.py +178 -18
  165. package/runtime/python/okstra_ctl/stage_map.py +16 -2
  166. package/runtime/python/okstra_ctl/stage_targets.py +209 -43
  167. package/runtime/python/okstra_ctl/team.py +22 -13
  168. package/runtime/python/okstra_ctl/time_report.py +2 -1
  169. package/runtime/python/okstra_ctl/usage_report.py +3 -1
  170. package/runtime/python/okstra_ctl/wizard/confirmation.py +3 -9
  171. package/runtime/python/okstra_ctl/wizard/ids.py +1 -1
  172. package/runtime/python/okstra_ctl/wizard/registry.py +1 -1
  173. package/runtime/python/okstra_ctl/wizard/state.py +3 -5
  174. package/runtime/python/okstra_ctl/wizard/steps_plan.py +12 -21
  175. package/runtime/python/okstra_ctl/worker_prompt_contract.py +5 -1
  176. package/runtime/python/okstra_ctl/worker_prompt_headers.py +35 -7
  177. package/runtime/python/okstra_ctl/worker_prompt_policy.py +66 -48
  178. package/runtime/python/okstra_ctl/workflow.py +1 -1
  179. package/runtime/python/okstra_ctl/worktree/__init__.py +3 -1
  180. package/runtime/python/okstra_ctl/worktree/naming.py +9 -0
  181. package/runtime/python/okstra_ctl/worktree_registry.py +38 -9
  182. package/runtime/python/okstra_token_usage/pricing.py +6 -4
  183. package/runtime/schemas/agent-common-v1.schema.json +34 -0
  184. package/runtime/schemas/agent-duty-v1.schema.json +38 -0
  185. package/runtime/schemas/agent-operation-v1.schema.json +11 -0
  186. package/runtime/schemas/agent-profile-v1.schema.json +46 -0
  187. package/runtime/schemas/agent-role-v1.schema.json +29 -0
  188. package/runtime/schemas/final-report-v2.0.schema.json +118 -97
  189. package/runtime/schemas/final-report-v3.0.schema.json +118 -97
  190. package/runtime/skills/okstra-brief-gen/SKILL.md +84 -4
  191. package/runtime/skills/okstra-chat/SKILL.md +2 -2
  192. package/runtime/skills/okstra-code-review/SKILL.md +23 -9
  193. package/runtime/skills/okstra-container-build/SKILL.md +10 -10
  194. package/runtime/skills/okstra-inspect/SKILL.md +1 -1
  195. package/runtime/skills/okstra-inspect/facets/cost.md +1 -1
  196. package/runtime/skills/okstra-inspect/facets/error-zip.md +9 -9
  197. package/runtime/skills/okstra-inspect/facets/errors.md +16 -16
  198. package/runtime/skills/okstra-inspect/facets/logs.md +7 -7
  199. package/runtime/skills/okstra-inspect/facets/recap.md +2 -2
  200. package/runtime/skills/okstra-inspect/facets/report.md +1 -1
  201. package/runtime/skills/okstra-inspect/facets/status.md +4 -3
  202. package/runtime/skills/okstra-inspect/facets/time.md +11 -10
  203. package/runtime/skills/okstra-manager/SKILL.md +18 -2
  204. package/runtime/skills/okstra-pr-gen/SKILL.md +6 -5
  205. package/runtime/skills/okstra-rollup/SKILL.md +5 -5
  206. package/runtime/skills/okstra-run/SKILL.md +31 -12
  207. package/runtime/skills/okstra-schedule-gen/SKILL.md +19 -14
  208. package/runtime/skills/okstra-setup/SKILL.md +12 -10
  209. package/runtime/skills/okstra-setup/references/project-config.md +7 -6
  210. package/runtime/skills/okstra-usage/SKILL.md +1 -1
  211. package/runtime/skills/okstra-user-response/SKILL.md +1 -1
  212. package/runtime/templates/manager/view.template.html +1 -0
  213. package/runtime/templates/report-writer-prompt-preamble.md +8 -0
  214. package/runtime/templates/reports/brief.template.md +14 -4
  215. package/runtime/templates/reports/html/i18n/en.json +5 -4
  216. package/runtime/templates/reports/html/i18n/ko.json +5 -4
  217. package/runtime/templates/reports/html/tasks/release-handoff.template.html +8 -5
  218. package/runtime/templates/reports/i18n/en.json +1 -1
  219. package/runtime/templates/reports/md/tasks/release-handoff.template.md +1 -1
  220. package/runtime/templates/reports/release-handoff-input.template.md +6 -4
  221. package/runtime/templates/translator-prompt-preamble.md +36 -0
  222. package/runtime/validators/checks/validate-assets-01.py +7 -8
  223. package/runtime/validators/validate-brief.py +70 -0
  224. package/runtime/validators/validate-implementation-plan-stages.py +2 -1
  225. package/runtime/validators/validate-run.py +72 -15
  226. package/runtime/validators/validate-schedule.py +9 -0
  227. package/docs/for-ai/README.md +0 -68
  228. package/docs/for-ai/skills/okstra-brief-gen.md +0 -262
  229. package/docs/for-ai/skills/okstra-chat.md +0 -34
  230. package/docs/for-ai/skills/okstra-code-review.md +0 -57
  231. package/docs/for-ai/skills/okstra-container-build.md +0 -129
  232. package/docs/for-ai/skills/okstra-inspect.md +0 -262
  233. package/docs/for-ai/skills/okstra-manager.md +0 -86
  234. package/docs/for-ai/skills/okstra-memory.md +0 -126
  235. package/docs/for-ai/skills/okstra-pr-gen.md +0 -49
  236. package/docs/for-ai/skills/okstra-rollup.md +0 -114
  237. package/docs/for-ai/skills/okstra-run.md +0 -250
  238. package/docs/for-ai/skills/okstra-schedule-gen.md +0 -240
  239. package/docs/for-ai/skills/okstra-setup.md +0 -167
  240. package/docs/for-ai/skills/okstra-usage.md +0 -29
  241. package/docs/for-ai/skills/okstra-user-response.md +0 -72
  242. package/runtime/agents/workers/claude-worker.md +0 -128
  243. package/runtime/agents/workers/report-writer-worker.md +0 -37
  244. package/runtime/agents/workers/translator-worker.md +0 -63
  245. package/runtime/prompts/duties/acceptance-critic.md +0 -44
  246. package/runtime/prompts/duties/acceptance-verifier.md +0 -44
  247. package/runtime/prompts/duties/analysis-worker.md +0 -44
  248. package/runtime/prompts/duties/code-reviewer.md +0 -44
  249. package/runtime/prompts/duties/common.md +0 -39
  250. package/runtime/prompts/duties/diagnosis-worker.md +0 -44
  251. package/runtime/prompts/duties/direction-selection-worker.md +0 -44
  252. package/runtime/prompts/duties/discovery-worker.md +0 -44
  253. package/runtime/prompts/duties/implementation-executor.md +0 -44
  254. package/runtime/prompts/duties/implementation-verifier.md +0 -44
  255. package/runtime/prompts/duties/lead.md +0 -44
  256. package/runtime/prompts/duties/planning-worker.md +0 -52
  257. package/runtime/prompts/duties/report-writer.md +0 -44
  258. package/runtime/prompts/duties/reverification-worker.md +0 -44
  259. package/runtime/prompts/duties/schedule-verifier.md +0 -44
  260. package/runtime/prompts/duties/scope-critic.md +0 -44
  261. package/runtime/prompts/duties/technical-verification-worker.md +0 -44
  262. package/runtime/prompts/duties/translator.md +0 -44
  263. package/runtime/python/okstra_ctl/pane_title.py +0 -154
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: okstra-brief-gen
3
3
  description: Use when the user wants to generate a task brief file for okstra from a requirements document, an existing markdown file, an issue-tracker ticket (Linear / Jira / GitHub / Notion), a link URL, conversation context, or short user input. Produces the markdown brief consumed by `okstra-run` Step 5 (task-brief). Trigger words include "okstra brief", "make a brief", "generate a brief", "make a brief from requirements", "make an okstra input", "write a task brief", "brief from this ticket", "brief from this link".
4
+ disable-model-invocation: true
4
5
  ---
5
6
 
6
7
  # okstra-brief-gen
@@ -153,6 +154,40 @@ and retain the explicit free-text follow-up where this skill specifies one.
153
154
 
154
155
  ## Step 1: Choose input source
155
156
 
157
+ ### Capture contract (binds every sub-flow below)
158
+
159
+ `Source Material` is the one section a later phase can fall back to when a
160
+ derived section reads wrong, so it carries the source whole. Three rules hold
161
+ for every variant and every source type below.
162
+
163
+ 1. **Capture in full.** Length is never a reason to excerpt, summarize, or
164
+ restructure. A source too long to be comfortable in the conversation is
165
+ still written into the brief in full. "In full" is measured against the
166
+ source the reporter named, not against the file that happens to contain
167
+ it: when they point at one section of a larger document — a backlog item,
168
+ one `## Cross-Repo Carry — <repo>` appendix — that section is what must
169
+ arrive whole, and `ref` names the containing file and the heading. Taking
170
+ a section the reporter did not name is the same failure as dropping half
171
+ of one they did.
172
+ 2. **Capture the record, not only the body.** What the record is, per source
173
+ type:
174
+
175
+ | Source type | Captured into `## Source Material` |
176
+ |---|---|
177
+ | `File` | the entire file, or the named section whole when the reporter pointed at one |
178
+ | `Issue tracker ticket` | title, description body, every comment, status, labels, assignee, and linked / child issue references — plus the remaining response metadata |
179
+ | `Link URL` | title and full body text, quotes and examples included |
180
+ | `User input` | the utterance as typed, or the conversation's key utterances quoted |
181
+ | `Error feedback` | the chosen cluster's anonymized error records |
182
+
183
+ 3. **What the tool could not deliver is recorded, never silently dropped.** A
184
+ truncated fetch, an attachment the API hands back as a signed link, an
185
+ embed the response carries as an opaque node, a body behind auth — each one
186
+ gets a `conversion-block:` row in `## Open Questions` naming what is
187
+ missing and where it lives. A bracketed note inside the captured block
188
+ helps the reader, but it does not replace that row: the row is what a later
189
+ phase sees when it asks whether the source arrived complete.
190
+
156
191
  ### 1.0. brief variant
157
192
 
158
193
  `AskUserQuestion` (single-select):
@@ -456,7 +491,7 @@ to Source Material body, not to the filename):
456
491
  Validate the full `<ticket-id>-<file-title>` slug: must have at least one
457
492
  alphanumeric character after slugification. Apply Step 2c on collision.
458
493
 
459
- **Enforced:** `validators/validate-brief.py` checks the brief's filename and its task-group directory segment against the slugified frontmatter `task-group`, and rejects a Source Material section whose entry does not match the source it names.
494
+ **Enforced:** `validators/validate-brief.py` checks the brief's filename and its task-group directory segment against the slugified frontmatter `task-group`.
460
495
 
461
496
  ### 2c. Collision handling
462
497
 
@@ -553,7 +588,7 @@ empty or trivially thin **after** reading Source Material verbatim, ask **at
553
588
  most one** `AskUserQuestion` to fill it. Never ask about sections already
554
589
  covered by the source material.
555
590
 
556
- **Enforced:** `validators/validate-brief.py` fails a brief whose required section is missing, is left as a template placeholder (`is_placeholder`), or carries only the template's own example lines (`is_template_example`) — so a section skipped here does not pass as filled.
591
+ **Enforced:** `validators/validate-brief.py` fails a brief whose required section is missing, has a blank body (`check_variant_required_sections`), or still carries the template's `<...>` text (`check_template_scaffold`). `## Source Material` is exempt from the template-text check because it holds the reporter's words verbatim.
557
592
 
558
593
  ### Sharpening pass (bounded grill)
559
594
 
@@ -854,11 +889,56 @@ The required-key set (`type`, `brief-id`, `parent-id`, `ticket-id`,
854
889
  Step 6.6. The byte-for-byte field shape remains the job of
855
890
  `~/.okstra/templates/reports/brief.template.md`.
856
891
 
892
+ ### Source requirement sweep (run before asking for approval)
893
+
894
+ Source Material holds the reporter's words, but every later phase reads the
895
+ derived sections. A requirement that is captured and then never carried into a
896
+ derived section is invisible from that point on, and no downstream phase can
897
+ recover it — it has no id to map and no heading to cite. Close that gap here,
898
+ while the source is still in front of you.
899
+
900
+ Read `## Source Material` from its first line to its last and list every
901
+ **requirement unit** it holds:
902
+
903
+ - an imperative or a request ("switch to S3", "il faudrait les extraire")
904
+ - a checklist row, whatever its box state
905
+ - a condition or a threshold ("only under 50 MB", "daily, not continuous")
906
+ - a prohibition ("never overwrite a non-empty value")
907
+ - a decision the reporter states as still open ("to be decided: who is alerted")
908
+ - a number the reporter gives as a target or a bound
909
+
910
+ Give every unit exactly one destination, and write it there before you ask for
911
+ approval:
912
+
913
+ | Unit | Destination |
914
+ |---|---|
915
+ | Runtime behaviour an okstra phase can reach by changing repository files | `## Expected Behavior` |
916
+ | Behaviour that must survive the change unchanged | `## Preserved Behavior` |
917
+ | Artifact state the finished work must leave behind | `## Expected Outcome` |
918
+ | A must-pass point a person or live infrastructure owns | `## External Gates` |
919
+ | A limit, a deadline, or an untouchable area | `## Constraints` |
920
+ | A decision the reporter left open | `## Open Questions` |
921
+ | Deliberately not part of this task | `## Constraints`, as `out of scope: <unit> — <why>` |
922
+
923
+ No unit may end the sweep without a destination. `out of scope:` is the only
924
+ way to drop one, and it costs a line that names the reason — an omission
925
+ nobody wrote down cannot be told apart from an oversight when the run later
926
+ misses it. A unit whose destination is genuinely unclear is an
927
+ `## Open Questions` `general:` row, not a silent drop.
928
+
929
+ The sweep reads the source; it does not interview the user. It runs after
930
+ Step 4's question budget is spent and adds no questions of its own — a gap it
931
+ surfaces is filled from Source Material, or parked in `## Open Questions`.
932
+
857
933
  Echo the file path back on one line. Show the rendered brief to the user
858
- inline and ask:
934
+ inline, and directly above the approval question show the sweep as a table —
935
+ one row per requirement unit, its destination section, and for an end-state
936
+ unit the `EB-` / `PB-` / `EO-` id it became. That table is what lets the
937
+ reporter check their own list in one pass. Then ask:
859
938
 
860
939
  `AskUserQuestion`: `"Proceed with this brief?"` — options `Save` / `Edit`.
861
- On `Edit`, return to Step 4 for the section to revise.
940
+ On `Edit`, return to Step 4 for the section to revise; a unit the user reports
941
+ missing returns to this sweep instead.
862
942
 
863
943
  ## Step 6: Recommend next okstra phase
864
944
 
@@ -8,7 +8,7 @@ description: Use when the user wants to create or join a global okstra chat room
8
8
  Cross-session rooms in the global okstra home. Not a project task artifact.
9
9
  Do not write JSON. Call `okstra chat` and read its fixed text.
10
10
 
11
- Rooms are independent of tasks and runs. A participant is this host session.
11
+ Rooms are independent of tasks and runs. A participant is a display name that this host session joins with; the CLI does not tie the name to a session, so every command acts as whichever member `--as` names.
12
12
  The display name is typed at join. Do not invent a default name.
13
13
 
14
14
  ## When to use
@@ -114,5 +114,5 @@ The whole room, including messages not addressed to you. Log does not move the c
114
114
 
115
115
  - Call only `okstra chat`. Do not open files under the chat store.
116
116
  - Do not treat chat rows as evidence for a finding, verdict, or assignment.
117
- - Workers may run the same commands with `--name` and `--as`. Joining is optional.
117
+ - Workers may run the same commands: `join` with `--name`, then the rest with `--as`. Taking part is optional, but `send`, `unread`, `inbox`, `log`, and `ack` fail with `not a member` until that name has joined.
118
118
  - Do not generate a display name from the provider, model, or execution label.
@@ -109,7 +109,7 @@ pass task manifests, target-CLI JSON, or arbitrary JSON fields to a reviewer.
109
109
  2. Collect the diff from the work directory chosen in Step 1 — `git -C <workdir> diff --name-status <baseCommit>..<headCommit>` for the file list, and `git -C <workdir> diff <baseCommit>..<headCommit>` for the hunks. Before trusting that range, run `git -C <workdir> rev-list --count <headCommit>..<baseCommit>`: anything but `0` is the rewritten-history case in the Exceptions table. An empty diff skips Steps 3–3.5 (also in Exceptions).
110
110
  3. **Route the packs once, here — and fix both absolute paths the briefs carry.** `okstra paths --field home` prints the okstra home; read `<okstraHome>/prompts/coding-preflight/overview.md` and walk all three stages of its routed resource selection over the changed-file list. The result is the applied pack list — the absolute paths reviewers will read. This routing happens exactly once per run; no reviewer repeats it.
111
111
 
112
- The second path is this skill's own calibration file. A subagent has no "next to this file" coordinate, so the brief must spell it out: the installed skill home is `~/.claude/skills/okstra-code-review/`, making the literal path `~/.claude/skills/okstra-code-review/references/review-calibration.md` — the same string whether the skill was copied in or dev-linked. Carry it, together with the pack list, into every Step 3 brief.
112
+ The second path is this skill's own calibration file. A subagent has no "next to this file" coordinate, so the brief must spell it out: `okstra install` writes this skill to `~/.agents/skills/okstra-code-review/` on every machine (and to `~/.claude/skills/` only when `~/.claude` exists), making the literal path `~/.agents/skills/okstra-code-review/references/review-calibration.md` — the same string whether the skill was copied in or dev-linked. Carry it, together with the pack list, into every Step 3 brief.
113
113
  4. Build the cells per `references/census-rules.md` and print, in this response: one cell table per axis, the exclusion list with a reason on every entry, and the applied pack list.
114
114
  5. Restate both completion criteria and show they hold: censused files + exclusions = files in the diff, and every hunk maps to a censused function or to file-level code.
115
115
 
@@ -119,23 +119,37 @@ A large census is never truncated. Report the cell count and confirm before disp
119
119
 
120
120
  ## Step 3 — Materialize and dispatch four reviewers in parallel
121
121
 
122
- Every reviewer and later gap-fill is a separate auditable standalone invocation. Before dispatch, create
122
+ Ask the runtime what this operation runs — do not choose the role, the providers, or the reviewer count
123
+ here:
124
+
125
+ ```
126
+ okstra agent-prompt resolve-operation --operation code-review
127
+ ```
128
+
129
+ It prints the duty, the role, the reviewer count, and one `slot` line per reviewer carrying that slot's
130
+ provider and model. The contract owns those values (`agents/operations/code-review.json`), so a machine
131
+ with too few distinct models fails here rather than quietly running fewer reviewers. Dispatch exactly the
132
+ slots it prints.
133
+
134
+ Every reviewer and later gap-fill is a separate auditable standalone invocation. For each slot, create
123
135
  `.okstra/agent-invocations/code-review/<invocation-id>.instructions.md` from that reviewer's brief, then run
124
- `okstra agent-prompt materialize` with `--purpose code-review`, `--audience code-reviewer`, and the canonical
125
- `.prompt.md` path beside it. Pass the current host runtime, selected provider, and `--model-role analyser`;
126
- the returned assignment is authoritative. Run `okstra agent-prompt verify` against the returned
127
- `metadataPath` before invoking any model.
136
+ `okstra agent-prompt materialize` with `--purpose code-review`, `--audience <dutyId>`, that slot's
137
+ `--provider` and `--model <modelRef>`, and the canonical `.prompt.md` path beside it; the returned
138
+ assignment is authoritative. Run `okstra agent-prompt verify` against the returned `metadataPath` before
139
+ invoking any model.
128
140
 
129
141
  For a native host call, pass the verified prompt body and `hostModelValue`. For a deterministic provider
130
- process, run `okstra worker-dispatch` with the verified prompt path and `modelExecutionValue`; never
131
- substitute one model value for the other. Dispatch the four verified calls in parallel when the host supports
142
+ process, run the provider wrapper `~/.okstra/bin/okstra-<provider>-exec.sh <projectRoot> <modelExecutionValue> <prompt-path>`
143
+ with the verified prompt path (`okstra worker-dispatch` dispatches only a run manifest's assignments, not a
144
+ standalone prompt). The wrapper records the provider's output in the prompt path with `.md` replaced by
145
+ `.log`. Never substitute one model value for the other. Dispatch the four verified calls in parallel when the host supports
132
146
  it. Every brief carries:
133
147
 
134
148
  - the diff, plus the work directory path so the reviewer can read whole files for context
135
149
  - the project layout in one or two lines (where source, tests, and — if the routing found one — domain / ports / adapters live)
136
150
  - **its own axis's cell list**, verbatim from the census
137
151
  - the absolute paths of the packs its axis reads (from step 2's routing)
138
- - the calibration path, written out in full as Step 2 fixed it — `~/.claude/skills/okstra-code-review/references/review-calibration.md`. The verdict format, the severity points, and the rules for a legitimate `clean` are defined there, not in the brief; a reviewer that cannot open this file cannot return a usable verdict, so never hand it a relative path or a "next to the skill" hint
152
+ - the calibration path, written out in full as Step 2 fixed it — `~/.agents/skills/okstra-code-review/references/review-calibration.md`. The verdict format, the severity points, and the rules for a legitimate `clean` are defined there, not in the brief; a reviewer that cannot open this file cannot return a usable verdict, so never hand it a relative path or a "next to the skill" hint
139
153
 
140
154
  Each axis is **one rule group**, so a cell is `target × <axis>` — never `target × <individual rule>`. The reviewer names the specific rule it found violated inside the verdict's `rule` field, and one cell may carry findings from several rules of its group.
141
155
 
@@ -6,13 +6,13 @@ description: |
6
6
 
7
7
  # OKSTRA Container Build
8
8
 
9
- Single entry point for the okstra user-test container runtime. okstra provisions a docker-compose group from an `implementation` task's worktree (the `docker-compose.yml` at the worktree root), and labels it with the task's run-trace so later sub-commands can find the group. This skill drives that lifecycle. Sub-commands:
9
+ Single entry point for the okstra user-test container runtime. okstra provisions a docker-compose group from an `implementation` task's worktree (the `docker-compose.yml` at the worktree root), and labels every service with `okstra.task-key`, `okstra.project-name`, and `okstra.run-trace`; `status` finds the group by its `okstra.project-name` label. This skill drives that lifecycle. Sub-commands:
10
10
 
11
11
  | Sub-command | What it does |
12
12
  |---|---|
13
13
  | `up` | Integrate the task's stages into the worktree, run `docker compose up -d`, and poll healthchecks. |
14
- | `status` | Query the running containers for a task-key (by run-trace label). |
15
- | `down` | Tear down the containers (label query); `--all` covers every container group in the project. |
14
+ | `status` | List the task's containers in any state (by `okstra.project-name` label). |
15
+ | `down` | Tear down the task's compose project by name; `--all` covers every task in the project that has a container deploy state. |
16
16
 
17
17
  ## Step 0: Preflight (shared)
18
18
 
@@ -69,8 +69,8 @@ Every sub-command needs a **task-key** (`<project-id>:<task-group>:<task-id>`)
69
69
  Brings up the task's container group: integrates the implementation stages into the task worktree, synthesizes the compose env override, runs `docker compose up -d`, and polls healthchecks.
70
70
 
71
71
  **Preconditions** (state them if unmet, do not guess):
72
- - The task must be an `implementation` task whose worktree is registered in `~/.okstra/worktrees/registry.json`. If `up` fails with "task worktree is not in the registry" → the task has no implementation worktree yet; tell the user to run the `implementation` phase first.
73
- - The worktree root must contain a `docker-compose.yml`. If `up` fails with "there is no ... at the worktree root" → no compose file shipped with this task; surface the message verbatim.
72
+ - The task's worktree must be registered in `~/.okstra/worktrees/registry.json`, and the task must have a done `implementation-planning` run. `up` does not check the task type. If `up` refuses because the task-key's worktree is not in the registry → surface the message verbatim; the task has no worktree yet, so the user runs a phase of the task (normally `implementation`) first.
73
+ - The worktree root must contain a `docker-compose.yml`. If `up` refuses because the worktree root has no `docker-compose.yml` → no compose file shipped with this task; surface the message verbatim.
74
74
  - Every stage declared in the approved plan's Stage Map must be `done`. `up` integrates the whole task, so a partially-finished task (e.g. only stage 1 of 3 done) is refused rather than deployed as if complete (gate in `stage_targets.py`, shared with whole-task `final-verification`). If `up` fails with `final-verification(whole-task): stage N not done — run implementation --stage N first`, surface that message verbatim and tell the user to finish the named stage via the `implementation` phase with `--stage N`.
75
75
 
76
76
  Run:
@@ -81,13 +81,13 @@ okstra container up --project-root <projectRoot> --task-key <task-key> --text
81
81
 
82
82
  Read the fixed output fields and report the provisioned services. 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.
83
83
 
84
- 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.
84
+ 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 --project-root <projectRoot> --task-key <task-key>` / `okstra container down --project-root <projectRoot> --task-key <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.
85
85
 
86
86
  ---
87
87
 
88
88
  ## status
89
89
 
90
- Reports the running containers, queried by the run-trace label — the source of truth for "is it up".
90
+ Reports the task's containers, queried by the `okstra.project-name` label with `docker ps -a` — so stopped and exited containers are listed too. The label query is the source of truth for "is it up".
91
91
 
92
92
  ```bash
93
93
  okstra container status --project-root <projectRoot> --task-key <task-key> --text
@@ -98,9 +98,9 @@ Read the fixed `Project name` and numbered `Container` fields and report:
98
98
  | Field | Meaning |
99
99
  |---|---|
100
100
  | `projectName` | the compose project name (label group) |
101
- | `containers` | running containers found by label — empty array means nothing is up |
101
+ | `containers` | containers found by label, in any state — empty array means no container exists; a non-empty list is up only where `state` is `running` |
102
102
 
103
- If `containers` is empty, say the group is not running and offer `up`.
103
+ If `containers` is empty, or no container's `state` is `running`, say the group is not running and offer `up`.
104
104
 
105
105
  To follow a service's live logs, the user runs `docker compose -p <projectName> logs -f <service>` (get `<projectName>` from `status`).
106
106
 
@@ -108,7 +108,7 @@ To follow a service's live logs, the user runs `docker compose -p <projectName>
108
108
 
109
109
  ## down
110
110
 
111
- Tears down the container group — removes the containers found by the run-trace label.
111
+ Tears down the container group by compose project name — no label query. `--all` finds its targets from the tasks that have a `container/deploy-state.json`.
112
112
 
113
113
  Single task:
114
114
 
@@ -11,7 +11,7 @@ and direct completion records are available to status, recap, group context, and
11
11
  For an explicit status change, dispatch to status.4 before catalog-only task selection.
12
12
  An unregistered brief will not appear in that selection yet.
13
13
 
14
- Single read-side entry point for okstra runtime inspection plus the one status mutation that belongs here (`workStatus`) and read-derived artifact rendering (`errors` report). Each sub-command's full procedure lives in a lazily loaded facet file — after dispatch, Read exactly the one facet you need.
14
+ Single read-side entry point for okstra runtime inspection plus the one status mutation that belongs here (`workStatus`) and read-derived artifact rendering (`errors` report). One more write sits underneath: the task-key lookup used by `time-report`, `context-cost`, `error-report`, `recap record`, `recap note`, and `model-io recap-input --task-group` self-heals a finished implementation phase — when a task's current phase is `implementation`, it appends a `done` row to `runs/implementation-planning/consumers.jsonl` for each stage whose carry file is complete but has no settled row, and when every stage of the latest plan has a `done` row and a pass-grade carry it marks the phase completed in `task-manifest.json` (`workflow`, `phaseOutcome.implementation`) and refreshes the catalog entry. `status-input`, `history-input`, `report-input`, and task-scope `recap-input` do not take that path. Each sub-command's full procedure lives in a lazily loaded facet file — after dispatch, Read exactly the one facet you need.
15
15
 
16
16
  | Sub-command | Facet file | What it does |
17
17
  |---|---|---|
@@ -6,7 +6,7 @@ Loaded lazily by the dispatch table in `SKILL.md` (core). Shared rules — Step
6
6
 
7
7
  Trigger phrases: "okstra context-cost", "context cost", "context-cost", "read cost", "artifact cost", "task bundle cost", "agent read cost".
8
8
 
9
- Read-only estimate of how much file/context surface a prepared task bundle asks the lead, analysis workers, and report-writer to absorb. This sub-command does **not** mutate task artifacts.
9
+ Estimate of how much file/context surface a prepared task bundle asks the lead, analysis workers, and report-writer to absorb. This sub-command does **not** mutate task artifacts itself; a task-key target goes through the lookup that may self-heal a finished implementation phase (see `SKILL.md`).
10
10
 
11
11
  ### cost.1 — Resolve target
12
12
 
@@ -28,14 +28,14 @@ okstra error-zip --out <resolved-path> --text
28
28
 
29
29
  Use the fixed text labels and report:
30
30
 
31
- | Field | Source |
31
+ | Field | Label |
32
32
  |---|---|
33
- | Output zip | `outPath` |
34
- | Total errors | `errorCount` |
35
- | Logs (runs) | `runCount` |
36
- | Unreachable runs | `unreachableRuns` |
37
- | Cluster count | `clusterCount` |
38
- | Project count | `projectCount` |
39
-
40
- - If `unreachableRuns > 0`, surface it (no silent omission).
33
+ | Output zip | `Output zip` |
34
+ | Total errors | `Total errors` |
35
+ | Logs (runs) | `Run count` |
36
+ | Unreachable runs | `Unreachable runs` |
37
+ | Cluster count | `Cluster count` |
38
+ | Project count | `Project count` |
39
+
40
+ - If `Unreachable runs` > 0, surface it (no silent omission).
41
41
  - End with the next step: "To fix okstra itself with this zip, build a brief with the error-feedback variant of `/okstra-brief-gen`, then run `okstra-run --task-type error-analysis` in the okstra repo."
@@ -6,7 +6,7 @@ Loaded lazily by the dispatch table in `SKILL.md` (core). Shared rules — Step
6
6
 
7
7
  Trigger phrases: "okstra errors", "error report", "error summary", "gather the errors", "clean up failure logs".
8
8
 
9
- Aggregate a task's okstra-run error logs (`runs/*/logs/errors-*.jsonl`, lead-observed + worker-reported) into a timestamped markdown report and summarize it. This sub-command renders a **read-derived artifact** (a `.md` file) but never mutates task state (`task-manifest.json`, catalog, timeline).
9
+ Aggregate a task's okstra-run error logs (`runs/*/logs/errors-*.jsonl`, lead-observed + worker-reported) into a timestamped markdown report and summarize it. This sub-command renders a **read-derived artifact** (a `.md` file) and never edits task state itself (`task-manifest.json`, catalog, timeline); a task-key target goes through the lookup that may self-heal a finished implementation phase (see `SKILL.md`).
10
10
 
11
11
  ### errors.1 — Resolve target
12
12
 
@@ -32,28 +32,28 @@ For a task-root path, run `okstra error-report <path>` directly. Do not parse th
32
32
 
33
33
  Use the fixed text labels and report:
34
34
 
35
- | Field | Source |
35
+ | Field | Label |
36
36
  |---|---|
37
- | Report file | `reportPath` (project-root-relative `.md`) |
38
- | Total errors | `totals.errorCount` |
39
- | Logs (runs) | `totals.runCount` |
40
- | By errorType | `totals.byErrorType` (tool-failure / cli-failure / contract-violation) |
41
- | By source | `totals.bySource` (lead-observed / worker-reported) |
42
- | By phase | `byPhase[]` |
43
- | By agent | `byAgent[]` |
44
- | Parse-skipped lines | `parseSkipped` |
45
-
46
- - If `reportPath` is empty AND `totals.errorCount == 0`: report `This task has no recorded error logs.` and do not claim a file was written.
37
+ | Report file | `Report path` (project-root-relative `.md`) |
38
+ | Total errors | `Total errors` |
39
+ | Logs (runs) | `Run count` |
40
+ | By errorType | `Error type <name>` lines (tool-failure / cli-failure / contract-violation) |
41
+ | By source | `Source <name>` lines (lead-observed / worker-reported) |
42
+ | By phase | `Phase <name>` lines |
43
+ | By agent | `Agent <name>` lines |
44
+ | Parse-skipped lines | `Parse skipped` |
45
+
46
+ - If `Report path` is `-` AND `Total errors` is 0: report `This task has no recorded error logs.` and do not claim a file was written.
47
47
  - Otherwise show the `.md` path and offer to read it.
48
- - If `parseSkipped > 0`, surface it (do not silently hide malformed lines).
48
+ - If `Parse skipped` > 0, surface it (do not silently hide malformed lines).
49
49
 
50
50
  ### errors — Output template
51
51
 
52
52
  ```markdown
53
53
  ## okstra Error Report — <task-key>
54
54
 
55
- - Report: `<reportPath-or-->`
56
- - Total errors: <N> across <runCount> log(s)
55
+ - Report: `<Report path-or-->`
56
+ - Total errors: <N> across <Run count> log(s)
57
57
  - By type: <tool-failure: a, cli-failure: b, ...>
58
58
  - By source: <lead-observed: x, worker-reported: y>
59
59
 
@@ -65,5 +65,5 @@ Use the fixed text labels and report:
65
65
  |---|---:|
66
66
  | codex-worker | 2 |
67
67
 
68
- <If parseSkipped > 0: "⚠ Parse-skipped lines: <N>">
68
+ <If Parse skipped > 0: "⚠ Parse-skipped lines: <N>">
69
69
  ```
@@ -25,21 +25,21 @@ okstra log-report --project-root <projectRoot> --text
25
25
  ```
26
26
 
27
27
  Scans `<projectRoot>/.okstra/tasks/**/runs/*/prompts/*.log` and returns fixed labeled text (sizes are **raw bytes**, mtimes **epoch seconds**):
28
- - `topLargest[]` — `{path, sizeBytes, mtimeEpoch, taskKey, taskGroup, taskId, phase, worker, seq}`, size desc (widen with `--top <N>`)
29
- - `perTask[]` — `{taskKey, fileCount, totalBytes, oldestEpoch, newestEpoch}`, total-size desc
30
- - `totals` — `{fileCount, totalBytes, taskCount}`
28
+ - Top-level total labels — `File count`, `Total bytes`, `Task count` (plus `Prompt bytes`, `Transcript bytes`, `Paired file count`)
29
+ - Repeated `## Log` blocks, size desc (widen with `--top <N>`) — `Task key`, `Phase`, `Worker`, `Sequence`, `Size bytes`, `Modified epoch`, `Path`
30
+ - Repeated `## Task total` blocks, total-size desc — `Task key`, `File count`, `Total bytes`, `Oldest epoch`, `Newest epoch`
31
31
 
32
- If `totals.fileCount` is 0, report `No worker log files found under <projectRoot>` and stop.
32
+ If the top-level `File count` is 0, report `No worker log files found under <projectRoot>` and stop.
33
33
 
34
34
  ### logs.2 — Summary tables
35
35
 
36
36
  Render from the CLI output (format bytes → KB/MB; epoch → `Nd`/`Nh` relative to now):
37
37
 
38
- **Table A — Top largest logs** (from `topLargest`): `| # | Task | Phase | Worker | Seq | Size | Age | Path |`.
38
+ **Table A — Top largest logs** (from the `## Log` blocks): `| # | Task | Phase | Worker | Seq | Size | Age | Path |`.
39
39
 
40
- **Table B — Per-task totals** (from `perTask`): `| Task Key | Files | Total Size | Oldest | Newest |`.
40
+ **Table B — Per-task totals** (from the `## Task total` blocks): `| Task Key | Files | Total Size | Oldest | Newest |`.
41
41
 
42
- **Footer:** `Total: <fileCount> files, <totalBytes→MB> across <taskCount> tasks under <PROJECT_ROOT>`.
42
+ **Footer:** `Total: <File count> files, <Total bytes→MB> across <Task count> tasks under <PROJECT_ROOT>`.
43
43
 
44
44
  ### logs.3 — Suggested cleanup commands
45
45
 
@@ -6,7 +6,7 @@ Loaded lazily by the dispatch table in `SKILL.md` (core). Shared rules — Step
6
6
 
7
7
  Trigger phrases: "okstra recap", "recap", "work summary", "summarize this task", "before/after summary", "explain this work", "task question".
8
8
 
9
- On top of the `.okstra` artifacts accumulated for a single task-id — or for every task of one task-group — (a) produce a before/after summary and (b) answer free-form questions about that work. By default it reads only the `.okstra/` subtree (artifact mode). It expands to code mode only when the user explicitly asks to look at the code changes too. This sub-command performs the `recap-log.jsonl` append, the `notes/` note authoring (recap.5), and the group-context reconciliation that note triggers (recap.6); it never mutates `task-manifest.json` / catalog / timeline, and it touches `group-context.md` only in the authored sections above the `<!-- okstra:task-memory:begin -->` marker.
9
+ On top of the `.okstra` artifacts accumulated for a single task-id — or for every task of one task-group — (a) produce a before/after summary and (b) answer free-form questions about that work. By default it reads only the `.okstra/` subtree (artifact mode). It expands to code mode only when the user explicitly asks to look at the code changes too. This sub-command performs the `recap-log.jsonl` append, the `notes/` note authoring (recap.5), and the group-context reconciliation that note triggers (recap.6); it never edits `task-manifest.json` / catalog / timeline itself (`recap record` / `recap note` with a task-key target, and `recap-input --task-group`, go through the lookup that may self-heal a finished implementation phase — see `SKILL.md`), and it touches `group-context.md` only in the authored sections above the `<!-- okstra:task-memory:begin -->` marker.
10
10
 
11
11
  ### recap.1 — Resolve target
12
12
 
@@ -144,7 +144,7 @@ Write the body to the scratchpad as markdown first, then pass it with `--body-fi
144
144
  **self-check rules (there is no validator, so you keep them yourself):**
145
145
 
146
146
  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.
147
- 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.
147
+ 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 publishing the `created-by: user` sidecar through that skill's `begin` → `answer` → `finalize` transaction is legitimate (`okstra user-response` has no `write` command). This exception holds only after the user has explicitly confirmed "correct", and only for verbatim input.
148
148
  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.
149
149
  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.
150
150
 
@@ -10,7 +10,7 @@ Trigger phrases: "find report", "show report for", "read the okstra report", "co
10
10
 
11
11
  task-key format: `<project-id>:<task-group>:<task-id>`.
12
12
 
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.
13
+ **Normalization:** task-key matching is lowercase. Disk segments are slugified (lowercase + non-alphanumeric runs → `-`) per `slugify_task_segment` (`scripts/okstra_ctl/ids.py:78`); the `model-io` projections build task paths with `okstra_project.slugify` (`scripts/okstra_project/slug.py:16`), which applies the same rule. Catalog lookup is case-insensitive; file path assembly uses slugified segments.
14
14
 
15
15
  Run `okstra model-io report-input --project-root <projectRoot> --task-ref
16
16
  <task-key>` and use `Latest report`. For a specific date, run `okstra model-io
@@ -100,7 +100,7 @@ The status response always includes one of:
100
100
  4. **Restart current phase** — only when there is nothing to answer: `latestReportRecordPath` is empty, or the open-item count is zero and `latestRunStatus` is `contract-violated`. Only an allowlisted blocking-class failure produces that status; findings demoted to `validation.advisories` leave the run passed and are not a reason to re-run. The task can be re-run with the same `task-key` and current `taskType`.
101
101
  Branches 5–7 are decided by `workflow.nextRecommendedPhase.status` when `awaitingApproval` is false — one status, one branch:
102
102
 
103
- 5. **Start next phase** — `status` is `ready` and `awaitingApproval` is false. Propose `nextRecommendedPhase.phase` as the next run's `--task-type` and quote its `rationale` as the reason. This is the only status under which a named phase may be launched without a prior approval ask, so it is the only branch that proposes a run. A `ready` pointer to `release-handoff` already implies an `accepted` final-verification verdict (the report validator refuses that routing target otherwise), so do not re-gate it here.
103
+ 5. **Start next phase** — `status` is `ready` and `awaitingApproval` is false. Propose `nextRecommendedPhase.phase` as the next run's `--task-type` and quote its `rationale` as the reason. This is the only status under which a named phase may be launched without a prior approval ask, so it is the only branch that proposes a run. A `ready` pointer to `release-handoff` already implies a final-verification verdict of `accepted`, or `conditional-accept` with every condition declaring `blocksReleaseHandoff: false` (the report validator refuses that routing target otherwise), so do not re-gate it here.
104
104
  6. **Need more information** — `status` is `pending` (the last run did not settle where this task goes next) or `blocked` (it did settle, and the answer is that something outside the run has to change first). Neither proposes a run, and a leftover `phase` name does not change that — `prepare` keeps the name when it lowers a pointer to `pending`, so read `status`, not the emptiness of `phase`. Show the `rationale`, and for `blocked` state what it names as the obstacle. After `implementation-planning`, branch 3 already owns the routing: the `C-NNN` answers come first, and planning is not re-run until they exist.
105
105
  7. **Task complete (terminal)** — `status` is `terminal`: the task lifecycle ends here. This is **not** a "next phase" — do not propose a new okstra run. Surface the latest report and ask the user whether any follow-up task should be opened separately.
106
106
 
@@ -112,8 +112,9 @@ This includes briefs whose tasks have never run. Call this command directly with
112
112
  token; do not require a catalog match or a prior `okstra-run`. The command resolves the brief
113
113
  and registers it when needed. For "do this small task directly and record completion", perform
114
114
  the authorized work, then record `done` with `--note` or `--note-file` containing the changes,
115
- verification results or reasons checks were not run, and remaining limitations. These inputs
116
- are checked by `set-work-status` and covered by `test_okstra_set_work_status.py`.
115
+ verification results or reasons checks were not run, and remaining limitations. `set-work-status`
116
+ refuses a direct completion whose note is empty (`test_okstra_set_work_status.py`); it does not
117
+ check the note's content, so including those three parts is on you.
117
118
 
118
119
  Read `Direct work record` alongside `Work status`. A direct result is user-recorded work,
119
120
  not a passed cross-verification run. The command shares the result in group context and
@@ -19,20 +19,21 @@ okstra time-report <task-key> --project-root <projectRoot> --text
19
19
  ```
20
20
 
21
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
- - `perWorker` — `{<taskType>: [{workerId, agents[], runs, totalMs, avgMs}]}`; only workers with a nonzero run appear, and `agents[]` lists agent labels that differ from `workerId`
24
- - `perRunWallClock[]` — `{runTimestamp, taskType, wallClockMs}` (max `endedAt` − min `startedAt` per run)
25
- - `phaseTimelines[]` — `{runTimestamp, taskType, phases:[{phase, firstAt, wallMsToNext}]}`
26
- - `unavailable[]` — `{runTimestamp, taskType, reason}` for runs with no Phase-7 durations (never summed into totals)
22
+ - Top-level total labels — `Total runs`, `Total lead ms`, `Total workers ms`, `Total CPU sum ms`
23
+ - Repeated `## Task type` blocks — `Task type`, `Runs`, `Lead ms`, `Workers ms`, `CPU sum ms`
24
+ - Repeated `## Worker` blocks — `Task type`, `Worker ID`, `Agents` (comma-separated agent labels that differ from the worker ID), `Runs`, `Total ms`, `Average ms`; only workers with a nonzero run appear
25
+ - Repeated `## Run wall clock` blocks — `Run timestamp`, `Task type`, `Wall clock ms` (max `endedAt` − min `startedAt` per run)
26
+ - Repeated `## Phase` blocks, one per phase marker — `Run timestamp`, `Task type`, `Phase`, `First at`, `Wall ms to next`
27
+ - Repeated `## Unavailable run` blocks — `Run timestamp`, `Task type`, `Reason` for runs with no Phase-7 durations (never summed into totals)
27
28
 
28
29
  ### time.3 — Render
29
30
 
30
- Convert every `*Ms` to `HH:MM:SS` (zero-pad; never show raw ms). Task types in `byTaskType` are already in chronological (first-appearance) order.
31
+ Convert every `ms` label to `HH:MM:SS` (zero-pad; never show raw ms). `## Task type` blocks are already in chronological (first-appearance) order.
31
32
 
32
- - **By task type** — `| Task type | Runs | CPU sum | Lead | Workers |` from `byTaskType`, plus a `grandTotal` row. `CPU sum` (= Lead + Workers) overlaps because workers run inside the lead's window — it is *not* wall-clock. Surface wall-clock only when the user explicitly asks, from `perRunWallClock`.
33
- - **Per worker** (per task type) — `| Worker | Runs | Total | Avg/run |` from `perWorker`. Render the worker as bare `workerId` when `agents` is empty, else `workerId (agent1, agent2)`.
34
- - **Phase breakdown** — "by stage"/"per stage"/"which stage took longest" in okstra most often means the **lifecycle stage (task-type)** view, which the *By task type* table above already answers — lead with that table, do not treat the request as unanswerable. Render the intra-run phase timeline only when the user clearly means within-a-run phases ("which phase", "Phase 1~7", "phase timeline"): one table per run from `phaseTimelines`: `| Phase | Start | Wall to next |` using `firstAt`/`wallMsToNext` (`null` → `--`). When `phaseTimelines` is empty, do **not** headline "not measurable" — the By-task-type table is the stage answer; mention the missing intra-run markers only as a trailing footnote.
35
- - If `unavailable[]` is non-empty, append a trailing note listing each run with its reason. Never fold them into totals.
33
+ - **By task type** — `| Task type | Runs | CPU sum | Lead | Workers |` from the `## Task type` blocks, plus a total row from the `Total …` labels. `CPU sum` (= Lead + Workers) overlaps because workers run inside the lead's window — it is *not* wall-clock. Surface wall-clock only when the user explicitly asks, from the `## Run wall clock` blocks.
34
+ - **Per worker** (per task type) — `| Worker | Runs | Total | Avg/run |` from the `## Worker` blocks. Render the worker as bare `Worker ID` when `Agents` is `-`, else `<Worker ID> (agent1, agent2)`.
35
+ - **Phase breakdown** — "by stage"/"per stage"/"which stage took longest" in okstra most often means the **lifecycle stage (task-type)** view, which the *By task type* table above already answers — lead with that table, do not treat the request as unanswerable. Render the intra-run phase timeline only when the user clearly means within-a-run phases ("which phase", "Phase 1~7", "phase timeline"): one table per run from the `## Phase` blocks grouped by `Run timestamp`: `| Phase | Start | Wall to next |` using `First at`/`Wall ms to next` (`-` → `--`). When there is no `## Phase` block, do **not** headline "not measurable" — the By-task-type table is the stage answer; mention the missing intra-run markers only as a trailing footnote.
36
+ - If any `## Unavailable run` block exists, append a trailing note listing each run with its reason. Never fold them into totals.
36
37
  - Show the resolved `<task-key>` in the heading.
37
38
 
38
39
  ```markdown
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: okstra-manager
3
3
  description: Use when the user wants to manage okstra work across multiple project roots, register or discover projects under a manager, create or update a shared manager task, sync project child-task status into manager state, split a Linear project or issue into per-project scoped briefs, or launch a child task from manager context. Trigger words include "okstra manager", "okstra-manager", "multiple projects", "cross-project", "group projects together", "manager task", "split this Linear project", "brief per project".
4
+ user-invocable: true
5
+ disable-model-invocation: true
4
6
  ---
5
7
 
6
8
  # OKSTRA Manager
@@ -22,7 +24,7 @@ okstra manager init --manager-id <manager-id>
22
24
  okstra manager discover-projects
23
25
  okstra manager new project --manager-id <manager-id> --project-id <project-id> --project-root <abs-path> [--role <role>] [--tag <tag>]
24
26
  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>
27
+ okstra manager new task --manager-id <manager-id> --task-group <task-group> --task-id <task-id> [--task <project-id:task-group:task-id>]
26
28
  okstra manager task status --manager-id <manager-id> --task-group <task-group> --task-id <task-id>
27
29
  okstra manager task sync --manager-id <manager-id> --task-group <task-group> --task-id <task-id>
28
30
  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>]
@@ -31,14 +33,28 @@ okstra manager task run --manager-id <manager-id> --project-id <project-id> --ta
31
33
  okstra manager task split --manager-id <manager-id> --task-group <task-group> --task-id <task-id> --plan <split-plan.json> [--overwrite]
32
34
  okstra manager list managers
33
35
  okstra manager list projects --manager-id <manager-id>
36
+ okstra manager list task-groups --manager-id <manager-id>
34
37
  okstra manager list tasks --manager-id <manager-id>
38
+ okstra manager task update --manager-id <manager-id> --task-group <task-group> --task-id <task-id> [--objective <text>] [--common-brief <path>] [--progress-mode <manual|auto>]
39
+ okstra manager task remove-child --manager-id <manager-id> --task-group <task-group> --task-id <task-id> --project-id <project-id> [--child-task-id <child-task-id>] [--confirm]
40
+ okstra manager remove project --manager-id <manager-id> --project-id <project-id> [--confirm]
41
+ okstra manager remove task --manager-id <manager-id> --task-group <task-group> --task-id <task-id> [--confirm]
42
+ okstra manager remove task-group --manager-id <manager-id> --task-group <task-group> [--confirm]
35
43
  okstra manager view --manager-id <manager-id>
36
44
  ```
37
45
 
38
46
  - Public child task identity is `project-id:task-group:task-id`.
47
+ - `--task` on `new task` is optional and repeatable; without it the task is created with no children.
39
48
  - `okstra manager new task --task ...` should prefer the full child key form above. The CLI also accepts shorthand under the command's `--task-group`, but the full key is the public form to show users.
40
49
  - When a manager task id differs from the actual child task id for a specific project, pass `--child-task-id <child-task-id>` to `task assign` and `task run`.
41
50
 
51
+ ## Removal Rule
52
+
53
+ `remove project`, `remove task`, `remove task-group` and `task remove-child` change nothing without `--confirm`; they print what would be removed (`Removed: no — dry run`). Run the command without `--confirm` first, show the user the listed project, path, tasks or kept children, and rerun with `--confirm` only after the user approves that exact target. These commands touch manager files only; project `.okstra/` state and briefs written by `task split` stay.
54
+
55
+ - `remove project` unregisters the project and keeps its child tasks. `task status` shows them with `project linked: no`, the view marks them `unlinked`, and `task run` refuses them until the project is registered again with `new project`.
56
+ - `task update` changes only the fields given and needs no confirmation. `new task` still refuses to change an existing task's objective, common brief or progress mode.
57
+
42
58
  ## Tracker Split
43
59
 
44
60
  Use this when one Linear project, or one parent issue, covers work in several registered projects and each project needs its own brief. A Linear project can point at several projects, and one issue can too; every (issue, project) pair gets its own brief and child task.
@@ -77,7 +93,7 @@ Plan JSON (`schemaVersion` 1). `source.kind` is `project` or `issue`; `recommend
77
93
  }
78
94
  ```
79
95
 
80
- The CLI writes each brief to `<projectRoot>/.okstra/briefs/<task-group>/<ticketId>-<file-title>.md` with a `## Project Scope` section: this project's scope, `outOfScope`, and the scope of every other project the same issue went to. It validates every brief with the brief validator before writing any file, registers the child tasks, and keeps the plan at `split-plan.json` in the manager task directory.
96
+ The CLI writes each brief to `<projectRoot>/.okstra/briefs/<group-slug>/<ticketId>-<file-title>.md` (`<group-slug>` is the task group lowercased, with each run of characters other than `a-z` and `0-9` replaced by `-`, so `Upload V2` becomes `upload-v2`) with a `## Project Scope` section: this project's scope, `outOfScope`, and the scope of every other project the same issue went to. It validates every brief with the brief validator before writing any file, registers the child tasks, and keeps the plan at `split-plan.json` in the manager task directory.
81
97
 
82
98
  ## Overview Page
83
99
 
@@ -61,10 +61,10 @@ the user states explicitly wins verbatim; never rewrite it.
61
61
  okstra pr template list
62
62
  ```
63
63
 
64
- - If `templates` is non-empty, present a picker: 1–2 recommended templates from
64
+ - If it prints template names (one per line), present a picker: 1–2 recommended templates from
65
65
  the list, plus `Default template` (the bundled default), plus `Enter directly`
66
66
  last.
67
- - If empty, tell the user the bundled default template will be used.
67
+ - If it prints `(no templates)`, tell the user the bundled default template will be used.
68
68
 
69
69
  Carry the chosen template name as `<template>` (`default` for the bundled one).
70
70
 
@@ -74,8 +74,9 @@ Carry the chosen template name as `<template>` (`default` for the bundled one).
74
74
  okstra pr branches
75
75
  ```
76
76
 
77
- Present a 3-option base picker from `recommended` (top entries) plus `Enter directly`
78
- last. Carry the choice as `<base>`.
77
+ It prints the recommended base branches one per line, current branch excluded, or `(no branches)`.
78
+ Present a 3-option base picker from the first two printed branches plus `Enter directly` last; with
79
+ `(no branches)`, ask for the base directly. Carry the choice as `<base>`.
79
80
 
80
81
  ### A3. Build the generation bundle and fill the template
81
82
 
@@ -94,7 +95,7 @@ git diff <base>...HEAD
94
95
  For a large diff, read it in sections. Fill the `template` placeholders from the
95
96
  diff and commits: describe only what actually changed. Mark checklist boxes
96
97
  `[x]` only when the diff supports them (tests touched → tests box, docs touched →
97
- docs box). If `commits`/`diffStat` are empty, tell the user there is nothing to
98
+ docs box). If the `Commits`/`Diff stat` sections print `-` (empty), tell the user there is nothing to
98
99
  describe and stop. **Never** append AI trailers/footers.
99
100
 
100
101
  ### A3b. Identifier allowlist for the body