okstra 0.102.2 → 0.102.4

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 (167) hide show
  1. package/README.kr.md +5 -5
  2. package/README.md +5 -5
  3. package/docs/kr/architecture/storage-model.md +8 -3
  4. package/docs/kr/architecture.md +12 -13
  5. package/docs/kr/cli.md +4 -4
  6. package/docs/kr/container.md +1 -1
  7. package/docs/kr/performance-improvement-plan-v2.md +2 -2
  8. package/docs/project-structure-overview.md +2 -2
  9. package/package.json +7 -2
  10. package/runtime/BUILD.json +2 -2
  11. package/runtime/bin/lib/okstra/interactive.sh +12 -0
  12. package/runtime/bin/okstra-antigravity-exec.sh +1 -2
  13. package/runtime/bin/okstra-codex-exec.sh +1 -2
  14. package/runtime/bin/okstra-render-final-report.py +2 -9
  15. package/runtime/bin/okstra-spawn-followups.py +4 -6
  16. package/runtime/bin/okstra-trace-cleanup.sh +24 -4
  17. package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
  18. package/runtime/prompts/lead/report-writer.md +1 -1
  19. package/runtime/prompts/profiles/_common-contract.md +9 -11
  20. package/runtime/python/okstra_ctl/codex_dispatch.py +6 -13
  21. package/runtime/python/okstra_ctl/consumers.py +35 -0
  22. package/runtime/python/okstra_ctl/container.py +4 -6
  23. package/runtime/python/okstra_ctl/dispatch_core.py +8 -13
  24. package/runtime/python/okstra_ctl/final_report_paths.py +24 -0
  25. package/runtime/python/okstra_ctl/handoff.py +2 -1
  26. package/runtime/python/okstra_ctl/implementation_outcome.py +271 -0
  27. package/runtime/python/okstra_ctl/implementation_stage.py +7 -11
  28. package/runtime/python/okstra_ctl/path_hints.py +665 -0
  29. package/runtime/python/okstra_ctl/render.py +4 -3
  30. package/runtime/python/okstra_ctl/report_view_artifacts.py +14 -0
  31. package/runtime/python/okstra_ctl/report_views.py +7 -4
  32. package/runtime/python/okstra_ctl/run.py +3 -10
  33. package/runtime/python/okstra_ctl/run_context.py +4 -2
  34. package/runtime/python/okstra_ctl/stage_targets.py +18 -0
  35. package/runtime/python/okstra_ctl/wizard.py +37 -26
  36. package/runtime/python/okstra_ctl/wizard_stage_intent.py +54 -0
  37. package/runtime/python/okstra_project/state.py +40 -2
  38. package/runtime/python/okstra_token_usage/report.py +2 -5
  39. package/runtime/validators/validate-report-views.py +2 -1
  40. package/runtime/validators/validate-run.py +1 -11
  41. package/src/commands/lifecycle/install.mjs +5 -5
  42. package/src/commands/lifecycle/uninstall.mjs +4 -4
  43. package/docs/superpowers/plans/2026-05-12-ticket-id-in-reports.md +0 -638
  44. package/docs/superpowers/plans/2026-05-14-convergence-queue-pruning.md +0 -1568
  45. package/docs/superpowers/plans/2026-05-17-dual-format-final-report.md +0 -167
  46. package/docs/superpowers/plans/2026-05-20-final-report-language.md +0 -1501
  47. package/docs/superpowers/plans/2026-05-20-implementation-planning-multi-stage.md +0 -1267
  48. package/docs/superpowers/plans/2026-05-20-okstra-run-prompt-sot-b1.md +0 -1007
  49. package/docs/superpowers/plans/2026-05-20-wizard-messages-json-sot.md +0 -720
  50. package/docs/superpowers/plans/2026-05-20-wizard-prompt-json-sot-a1.md +0 -681
  51. package/docs/superpowers/plans/2026-05-21-improvement-discovery-task-type.md +0 -1691
  52. package/docs/superpowers/plans/2026-05-24-implementation-lead-context-slimming.md +0 -1700
  53. package/docs/superpowers/plans/2026-05-25-okstra-project-root-rename.md +0 -158
  54. package/docs/superpowers/plans/2026-05-26-wizard-3-option-picker.md +0 -860
  55. package/docs/superpowers/plans/2026-06-02-final-verification-protocol-hardening.md +0 -326
  56. package/docs/superpowers/plans/2026-06-02-okstra-run-branch-confirm-step.md +0 -337
  57. package/docs/superpowers/plans/2026-06-02-okstra-run-phase-pane-cleanup.md +0 -410
  58. package/docs/superpowers/plans/2026-06-02-requirements-discovery-fanout.md +0 -728
  59. package/docs/superpowers/plans/2026-06-04-adversarial-implementation-planning.md +0 -294
  60. package/docs/superpowers/plans/2026-06-04-adversarial-verification.md +0 -570
  61. package/docs/superpowers/plans/2026-06-04-coverage-critic.md +0 -516
  62. package/docs/superpowers/plans/2026-06-04-stage-cohesion-planner.md +0 -351
  63. package/docs/superpowers/plans/2026-06-04-stage-run-batching.md +0 -457
  64. package/docs/superpowers/plans/2026-06-05-acceptance-critic.md +0 -251
  65. package/docs/superpowers/plans/2026-06-05-compact-markdown-report-tables.md +0 -323
  66. package/docs/superpowers/plans/2026-06-05-wizard-batch-prompts.md +0 -559
  67. package/docs/superpowers/plans/2026-06-06-final-verification-whole-task-gate.md +0 -993
  68. package/docs/superpowers/plans/2026-06-06-stage-parallel-and-pending-fixes.md +0 -93
  69. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p1.md +0 -447
  70. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p2.md +0 -289
  71. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p3.md +0 -774
  72. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p4.md +0 -303
  73. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p5-multidep-base.md +0 -387
  74. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase2.md +0 -275
  75. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase3.md +0 -282
  76. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4a.md +0 -147
  77. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4b.md +0 -262
  78. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4c.md +0 -184
  79. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4d.md +0 -88
  80. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4e.md +0 -250
  81. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa.md +0 -409
  82. package/docs/superpowers/plans/2026-06-09-implementation-run-artifact-stage-isolation.md +0 -320
  83. package/docs/superpowers/plans/2026-06-10-concurrent-run-team-guard.md +0 -456
  84. package/docs/superpowers/plans/2026-06-10-git-reconcile-stale-sha-recovery.md +0 -1408
  85. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling-PROBE.md +0 -42
  86. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling.md +0 -337
  87. package/docs/superpowers/plans/2026-06-10-p6-token-usage-incremental.md +0 -1029
  88. package/docs/superpowers/plans/2026-06-10-stage-group-handoff.md +0 -1572
  89. package/docs/superpowers/plans/2026-06-11-fix-cycle.md +0 -1290
  90. package/docs/superpowers/plans/2026-06-11-wizard-whole-task-final-verification.md +0 -526
  91. package/docs/superpowers/plans/2026-06-12-html-plan-approval.md +0 -1000
  92. package/docs/superpowers/plans/2026-06-13-repo-risk-hardening.md +0 -493
  93. package/docs/superpowers/plans/2026-06-14-host-runtime-auto-execution.md +0 -1775
  94. package/docs/superpowers/plans/2026-06-15-coding-preflight-pack-dispatch-path.md +0 -504
  95. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-final-fixups.md +0 -342
  96. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-fixups.md +0 -258
  97. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-remaining-fixups.md +0 -387
  98. package/docs/superpowers/plans/2026-06-15-internal-skill-resource-migration.md +0 -749
  99. package/docs/superpowers/plans/2026-06-15-worker-prompt-anchor-final-fixups.md +0 -828
  100. package/docs/superpowers/plans/2026-06-15-worker-prompt-header-error-contract.md +0 -490
  101. package/docs/superpowers/plans/2026-06-17-okstra-error-report.md +0 -724
  102. package/docs/superpowers/plans/2026-06-18-subagent-pane-reclaim.md +0 -483
  103. package/docs/superpowers/plans/2026-06-19-agent-operating-standard.md +0 -476
  104. package/docs/superpowers/plans/2026-06-19-okstra-inspect-recap-facet.md +0 -647
  105. package/docs/superpowers/plans/2026-06-20-error-feedback-loop.md +0 -1019
  106. package/docs/superpowers/plans/2026-06-20-run-index-row-normalization.md +0 -583
  107. package/docs/superpowers/plans/2026-06-20-stage-auto-integrate-teardown.md +0 -819
  108. package/docs/superpowers/plans/2026-06-21-okstra-container-local-user-test.md +0 -714
  109. package/docs/superpowers/plans/2026-06-21-release-handoff-local-checkout.md +0 -348
  110. package/docs/superpowers/plans/2026-06-23-implementation-stage-multiselect-chain.md +0 -630
  111. package/docs/superpowers/plans/2026-06-23-implementation-step-commit-granularity.md +0 -274
  112. package/docs/superpowers/plans/2026-06-23-phase-batch-cleanup-enforcement.md +0 -409
  113. package/docs/superpowers/plans/2026-06-24-cross-project-precondition.md +0 -542
  114. package/docs/superpowers/plans/2026-06-24-decision-drafts-render-gap.md +0 -568
  115. package/docs/superpowers/plans/2026-06-24-manual-user-test-section.md +0 -203
  116. package/docs/superpowers/plans/2026-06-24-okstra-container-build-rename.md +0 -525
  117. package/docs/superpowers/specs/2026-05-12-ticket-id-in-reports-design.md +0 -131
  118. package/docs/superpowers/specs/2026-05-15-implementation-plan-verification-design.md +0 -254
  119. package/docs/superpowers/specs/2026-05-20-final-report-language-design.md +0 -383
  120. package/docs/superpowers/specs/2026-05-20-implementation-planning-multi-stage-design.md +0 -322
  121. package/docs/superpowers/specs/2026-05-20-okstra-run-prompt-sot-design.md +0 -299
  122. package/docs/superpowers/specs/2026-05-21-improvement-discovery-task-type-design.md +0 -335
  123. package/docs/superpowers/specs/2026-06-02-okstra-run-branch-confirm-step-design.md +0 -113
  124. package/docs/superpowers/specs/2026-06-02-okstra-run-phase-pane-cleanup-design.md +0 -173
  125. package/docs/superpowers/specs/2026-06-02-requirements-discovery-fanout-design.md +0 -154
  126. package/docs/superpowers/specs/2026-06-04-adversarial-implementation-planning-design.md +0 -90
  127. package/docs/superpowers/specs/2026-06-04-adversarial-verification-design.md +0 -176
  128. package/docs/superpowers/specs/2026-06-04-coverage-critic-design.md +0 -99
  129. package/docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md +0 -98
  130. package/docs/superpowers/specs/2026-06-05-acceptance-critic-design.md +0 -90
  131. package/docs/superpowers/specs/2026-06-05-compact-markdown-report-tables-design.md +0 -87
  132. package/docs/superpowers/specs/2026-06-05-wizard-batch-prompts-design.md +0 -121
  133. package/docs/superpowers/specs/2026-06-06-final-verification-whole-task-gate-design.md +0 -126
  134. package/docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md +0 -180
  135. package/docs/superpowers/specs/2026-06-06-vertical-slice-tdd-planning-design.md +0 -179
  136. package/docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md +0 -169
  137. package/docs/superpowers/specs/2026-06-09-executor-model-custom-id-cascade-design.md +0 -66
  138. package/docs/superpowers/specs/2026-06-09-implementation-run-artifact-stage-isolation-design.md +0 -87
  139. package/docs/superpowers/specs/2026-06-10-blocking-contract-posthoc-conformance-design.md +0 -168
  140. package/docs/superpowers/specs/2026-06-10-concurrent-run-team-guard-design.md +0 -107
  141. package/docs/superpowers/specs/2026-06-10-git-reconcile-stale-sha-recovery-design.md +0 -105
  142. package/docs/superpowers/specs/2026-06-10-lead-worker-completion-polling-design.md +0 -113
  143. package/docs/superpowers/specs/2026-06-10-stage-group-handoff-design.md +0 -156
  144. package/docs/superpowers/specs/2026-06-11-brief-entry-only-handoff-stage-entry-design.md +0 -158
  145. package/docs/superpowers/specs/2026-06-11-fix-cycle-design.md +0 -94
  146. package/docs/superpowers/specs/2026-06-11-wizard-whole-task-final-verification-design.md +0 -89
  147. package/docs/superpowers/specs/2026-06-12-codex-lead-adapter-design.md +0 -358
  148. package/docs/superpowers/specs/2026-06-12-html-plan-approval-design.md +0 -85
  149. package/docs/superpowers/specs/2026-06-12-stage-discipline-rule-design.md +0 -108
  150. package/docs/superpowers/specs/2026-06-13-forbidden-actions-ssot-design.md +0 -134
  151. package/docs/superpowers/specs/2026-06-13-neutral-tmux-lead-adapter-design.md +0 -284
  152. package/docs/superpowers/specs/2026-06-14-host-runtime-auto-execution-design.md +0 -404
  153. package/docs/superpowers/specs/2026-06-17-okstra-error-report-design.md +0 -123
  154. package/docs/superpowers/specs/2026-06-18-subagent-pane-reclaim-design.md +0 -150
  155. package/docs/superpowers/specs/2026-06-19-agent-operating-standard-design.md +0 -120
  156. package/docs/superpowers/specs/2026-06-19-okstra-inspect-recap-facet-design.md +0 -96
  157. package/docs/superpowers/specs/2026-06-20-error-feedback-loop-design.md +0 -171
  158. package/docs/superpowers/specs/2026-06-20-run-index-row-normalization-design.md +0 -112
  159. package/docs/superpowers/specs/2026-06-20-stage-auto-integrate-teardown-design.md +0 -145
  160. package/docs/superpowers/specs/2026-06-21-okstra-container-local-user-test-design.md +0 -125
  161. package/docs/superpowers/specs/2026-06-21-release-handoff-local-checkout-design.md +0 -113
  162. package/docs/superpowers/specs/2026-06-23-implementation-stage-multiselect-chain-design.md +0 -138
  163. package/docs/superpowers/specs/2026-06-23-implementation-step-commit-granularity-design.md +0 -120
  164. package/docs/superpowers/specs/2026-06-24-cross-project-precondition-design.md +0 -129
  165. package/docs/superpowers/specs/2026-06-24-decision-drafts-render-gap-design.md +0 -185
  166. package/docs/superpowers/specs/2026-06-24-manual-user-test-section-design.md +0 -121
  167. package/docs/superpowers/specs/2026-06-24-okstra-container-build-rename-design.md +0 -110
@@ -1,490 +0,0 @@
1
- # Worker Prompt Header Error Contract Implementation Plan
2
-
3
- > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
-
5
- **Goal:** Make worker prompt header rendering failures surface through dispatcher-native `DispatchError` boundaries instead of leaking helper-local exception types or tracebacks.
6
-
7
- **Architecture:** Keep `worker_prompt_headers.py` as the single renderer for the eight team-contract anchor headers, but give it a domain-specific exception type. Each dispatcher boundary (`codex_dispatch.py`, `dispatch_core.py`) converts that shared exception into its own public `DispatchError`, preserving existing CLI/error contracts. No graphify/plugin refresh work is included; the user explicitly excluded that external-plugin failure.
8
-
9
- **Tech Stack:** Python 3.11+, `pytest`, existing Okstra dispatcher modules under `scripts/okstra_ctl/`, npm build/check wrappers.
10
-
11
- ---
12
-
13
- ## Current Evidence
14
-
15
- - `scripts/okstra_ctl/worker_prompt_headers.py` renders the worker anchor headers in one shared helper.
16
- - The helper currently raises raw `ValueError` from `_run_seq()` and `_require_string()` when required manifest fields are missing.
17
- - `scripts/okstra_ctl/codex_dispatch.py` catches only its local `DispatchError` in `main()`, so a malformed manifest can bypass the clean CLI error path.
18
- - `scripts/okstra_ctl/dispatch_core.py` already uses local `DispatchError` for malformed dispatch inputs, but `_materialize_prompt_if_missing()` delegates directly to `worker_prompt_headers()` without wrapping helper failures.
19
- - The only remaining issue in scope is this exception-boundary gap. The graphify update failure is intentionally out of scope.
20
-
21
- ## File Structure
22
-
23
- - Modify: `scripts/okstra_ctl/worker_prompt_headers.py`
24
- - Responsibility: render deterministic worker prompt anchor headers.
25
- - Add: `WorkerPromptHeaderError` for malformed manifest/context input.
26
- - Change: `_run_seq()` and `_require_string()` raise `WorkerPromptHeaderError`.
27
-
28
- - Modify: `scripts/okstra_ctl/codex_dispatch.py`
29
- - Responsibility: Codex CLI-wrapper dispatch boundary.
30
- - Change: import `WorkerPromptHeaderError` and convert it to Codex-local `DispatchError` in `_base_prompt_headers()`.
31
-
32
- - Modify: `scripts/okstra_ctl/dispatch_core.py`
33
- - Responsibility: backend-neutral deterministic worker dispatch.
34
- - Change: import `WorkerPromptHeaderError` and convert it to dispatch-core-local `DispatchError` in `_materialize_prompt_if_missing()`.
35
-
36
- - Modify: `tests/test_worker_prompt_headers.py`
37
- - Responsibility: shared header renderer regression tests.
38
- - Add: helper raises `WorkerPromptHeaderError` for malformed fallback manifest input.
39
-
40
- - Modify: `tests/test_codex_dispatch.py`
41
- - Responsibility: Codex dispatcher regression tests.
42
- - Add: `_base_prompt_headers()` wraps shared header errors as Codex `DispatchError`.
43
-
44
- - Modify: `tests/test_dispatch_core.py`
45
- - Responsibility: backend-neutral dispatcher regression tests.
46
- - Add: `_materialize_prompt_if_missing()` wraps shared header errors as dispatch-core `DispatchError` and does not create a prompt file on failure.
47
-
48
- - Modify: `CHANGES.md`
49
- - Responsibility: user-visible behavior log.
50
- - Add: clean dispatcher error behavior entry under `2026-06-15` after the current dispatch entry.
51
-
52
- ---
53
-
54
- ### Task 1: Add Shared Header Error Type
55
-
56
- **Files:**
57
- - Modify: `scripts/okstra_ctl/worker_prompt_headers.py`
58
- - Test: `tests/test_worker_prompt_headers.py`
59
-
60
- - [ ] **Step 1: Write the failing helper regression test**
61
-
62
- Add `pytest` to the test imports and import the new exception type:
63
-
64
- ```python
65
- import pytest
66
-
67
- from okstra_ctl.worker_prompt_headers import ( # noqa: E402
68
- WorkerPromptHeaderError,
69
- worker_prompt_headers,
70
- )
71
- ```
72
-
73
- Append this test to `tests/test_worker_prompt_headers.py`:
74
-
75
- ```python
76
- def test_worker_prompt_headers_raise_contract_error_for_missing_manifest_fields(
77
- tmp_path: Path,
78
- ) -> None:
79
- with pytest.raises(WorkerPromptHeaderError, match="teamStatePath"):
80
- worker_prompt_headers(
81
- project_root=tmp_path / "project",
82
- prompt_rel=".okstra/run/prompts/codex.md",
83
- result_rel=".okstra/run/worker-results/codex.md",
84
- worker_id="codex",
85
- manifest={},
86
- active_context={},
87
- )
88
- ```
89
-
90
- - [ ] **Step 2: Run the helper test and verify it fails for the intended reason**
91
-
92
- Run:
93
-
94
- ```bash
95
- python3 -m pytest tests/test_worker_prompt_headers.py::test_worker_prompt_headers_raise_contract_error_for_missing_manifest_fields -q
96
- ```
97
-
98
- Expected: FAIL because `WorkerPromptHeaderError` is not importable yet, or because the helper still raises `ValueError`.
99
-
100
- - [ ] **Step 3: Implement `WorkerPromptHeaderError` in the shared helper**
101
-
102
- In `scripts/okstra_ctl/worker_prompt_headers.py`, add this class after the imports:
103
-
104
- ```python
105
- class WorkerPromptHeaderError(Exception):
106
- """Raised when worker prompt anchor headers cannot be rendered."""
107
- ```
108
-
109
- Replace `_run_seq()` with:
110
-
111
- ```python
112
- def _run_seq(manifest: Mapping[str, Any]) -> str:
113
- seqs = manifest.get("runSequencesByCategory")
114
- if not isinstance(seqs, Mapping):
115
- raise WorkerPromptHeaderError("run manifest has no runSequencesByCategory object")
116
- return _require_string(seqs, "manifests")
117
- ```
118
-
119
- Replace `_require_string()` with:
120
-
121
- ```python
122
- def _require_string(payload: Mapping[str, Any], key: str) -> str:
123
- value = payload.get(key)
124
- if not isinstance(value, str) or not value.strip():
125
- raise WorkerPromptHeaderError(f"missing required string field: {key}")
126
- return value
127
- ```
128
-
129
- - [ ] **Step 4: Run the helper regression test and verify it passes**
130
-
131
- Run:
132
-
133
- ```bash
134
- python3 -m pytest tests/test_worker_prompt_headers.py::test_worker_prompt_headers_raise_contract_error_for_missing_manifest_fields -q
135
- ```
136
-
137
- Expected: PASS.
138
-
139
- - [ ] **Step 5: Run all shared helper tests**
140
-
141
- Run:
142
-
143
- ```bash
144
- python3 -m pytest tests/test_worker_prompt_headers.py -q
145
- ```
146
-
147
- Expected: PASS for all tests in `tests/test_worker_prompt_headers.py`.
148
-
149
- ---
150
-
151
- ### Task 2: Wrap Codex Dispatcher Header Errors
152
-
153
- **Files:**
154
- - Modify: `scripts/okstra_ctl/codex_dispatch.py`
155
- - Test: `tests/test_codex_dispatch.py`
156
-
157
- - [ ] **Step 1: Write the failing Codex boundary regression test**
158
-
159
- Extend the `tests/test_codex_dispatch.py` import from `okstra_ctl.codex_dispatch` to include `_base_prompt_headers`:
160
-
161
- ```python
162
- from okstra_ctl.codex_dispatch import ( # noqa: E402
163
- DispatchError,
164
- _base_prompt_headers,
165
- build_dispatch_plan,
166
- dispatch_plan,
167
- )
168
- ```
169
-
170
- Append this test near the other prompt-generation tests:
171
-
172
- ```python
173
- def test_base_prompt_headers_wraps_worker_header_errors() -> None:
174
- with pytest.raises(DispatchError, match="teamStatePath"):
175
- _base_prompt_headers(
176
- project_root=Path("/project"),
177
- manifest={},
178
- active_context={},
179
- worker_id="codex",
180
- prompt_rel=".okstra/run/prompts/codex.md",
181
- result_rel=".okstra/run/worker-results/codex.md",
182
- )
183
- ```
184
-
185
- - [ ] **Step 2: Run the Codex regression test and verify it fails for the intended reason**
186
-
187
- Run:
188
-
189
- ```bash
190
- python3 -m pytest tests/test_codex_dispatch.py::test_base_prompt_headers_wraps_worker_header_errors -q
191
- ```
192
-
193
- Expected: FAIL because `_base_prompt_headers()` raises `WorkerPromptHeaderError` instead of Codex `DispatchError`.
194
-
195
- - [ ] **Step 3: Convert shared header errors to Codex `DispatchError`**
196
-
197
- In `scripts/okstra_ctl/codex_dispatch.py`, replace the worker header import with:
198
-
199
- ```python
200
- from .worker_prompt_headers import WorkerPromptHeaderError, worker_prompt_headers
201
- ```
202
-
203
- Replace `_base_prompt_headers()` with:
204
-
205
- ```python
206
- def _base_prompt_headers(
207
- *,
208
- project_root: Path,
209
- manifest: Mapping[str, Any],
210
- active_context: Mapping[str, Any],
211
- worker_id: str,
212
- prompt_rel: str,
213
- result_rel: str,
214
- ) -> list[str]:
215
- try:
216
- return worker_prompt_headers(
217
- project_root=project_root,
218
- prompt_rel=prompt_rel,
219
- result_rel=result_rel,
220
- worker_id=worker_id,
221
- manifest=manifest,
222
- active_context=active_context,
223
- )
224
- except WorkerPromptHeaderError as exc:
225
- raise DispatchError(str(exc)) from exc
226
- ```
227
-
228
- - [ ] **Step 4: Run the Codex regression test and verify it passes**
229
-
230
- Run:
231
-
232
- ```bash
233
- python3 -m pytest tests/test_codex_dispatch.py::test_base_prompt_headers_wraps_worker_header_errors -q
234
- ```
235
-
236
- Expected: PASS.
237
-
238
- - [ ] **Step 5: Smoke-test the Codex boundary exception type**
239
-
240
- Run:
241
-
242
- ```bash
243
- python3 - <<'PY'
244
- from pathlib import Path
245
- import sys
246
-
247
- sys.path.insert(0, "scripts")
248
-
249
- from okstra_ctl.codex_dispatch import DispatchError, _base_prompt_headers
250
-
251
- try:
252
- _base_prompt_headers(
253
- project_root=Path("/project"),
254
- manifest={},
255
- active_context={},
256
- worker_id="codex",
257
- prompt_rel=".okstra/run/prompts/codex.md",
258
- result_rel=".okstra/run/worker-results/codex.md",
259
- )
260
- except DispatchError as exc:
261
- print(type(exc).__name__, str(exc))
262
- else:
263
- raise SystemExit("expected DispatchError")
264
- PY
265
- ```
266
-
267
- Expected output:
268
-
269
- ```text
270
- DispatchError missing required string field: teamStatePath
271
- ```
272
-
273
- ---
274
-
275
- ### Task 3: Wrap Backend-Neutral Dispatcher Header Errors
276
-
277
- **Files:**
278
- - Modify: `scripts/okstra_ctl/dispatch_core.py`
279
- - Test: `tests/test_dispatch_core.py`
280
-
281
- - [ ] **Step 1: Write the failing dispatch-core regression test**
282
-
283
- Add `pytest` to `tests/test_dispatch_core.py` imports:
284
-
285
- ```python
286
- import pytest
287
- ```
288
-
289
- Append this test to `tests/test_dispatch_core.py`:
290
-
291
- ```python
292
- def test_materialize_prompt_wraps_worker_header_errors(tmp_path: Path) -> None:
293
- prompt_path = tmp_path / "project" / "prompts" / "claude-worker-prompt.md"
294
-
295
- with pytest.raises(dispatch_core.DispatchError, match="teamStatePath"):
296
- dispatch_core._materialize_prompt_if_missing(
297
- prompt_path=prompt_path,
298
- prompt_rel="prompts/claude-worker-prompt.md",
299
- worker_id="claude",
300
- result_rel="worker-results/claude.md",
301
- project_root=tmp_path / "project",
302
- manifest={},
303
- active_context={},
304
- )
305
-
306
- assert not prompt_path.exists()
307
- ```
308
-
309
- - [ ] **Step 2: Run the dispatch-core regression test and verify it fails for the intended reason**
310
-
311
- Run:
312
-
313
- ```bash
314
- python3 -m pytest tests/test_dispatch_core.py::test_materialize_prompt_wraps_worker_header_errors -q
315
- ```
316
-
317
- Expected: FAIL because `_materialize_prompt_if_missing()` raises `WorkerPromptHeaderError` instead of dispatch-core `DispatchError`.
318
-
319
- - [ ] **Step 3: Convert shared header errors to dispatch-core `DispatchError`**
320
-
321
- In `scripts/okstra_ctl/dispatch_core.py`, replace the worker header import with:
322
-
323
- ```python
324
- from .worker_prompt_headers import WorkerPromptHeaderError, worker_prompt_headers
325
- ```
326
-
327
- Replace `_materialize_prompt_if_missing()` with:
328
-
329
- ```python
330
- def _materialize_prompt_if_missing(
331
- *,
332
- prompt_path: Path,
333
- prompt_rel: str,
334
- worker_id: str,
335
- result_rel: str,
336
- project_root: Path,
337
- manifest: Mapping[str, Any],
338
- active_context: Mapping[str, Any],
339
- ) -> None:
340
- if prompt_path.is_file():
341
- return
342
- prompt_path.parent.mkdir(parents=True, exist_ok=True)
343
- try:
344
- headers = worker_prompt_headers(
345
- project_root=project_root,
346
- prompt_rel=prompt_rel,
347
- result_rel=result_rel,
348
- worker_id=worker_id,
349
- manifest=manifest,
350
- active_context=active_context,
351
- )
352
- except WorkerPromptHeaderError as exc:
353
- raise DispatchError(str(exc)) from exc
354
- prompt_path.write_text("\n".join([*headers, ""]), encoding="utf-8")
355
- ```
356
-
357
- - [ ] **Step 4: Run the dispatch-core regression test and verify it passes**
358
-
359
- Run:
360
-
361
- ```bash
362
- python3 -m pytest tests/test_dispatch_core.py::test_materialize_prompt_wraps_worker_header_errors -q
363
- ```
364
-
365
- Expected: PASS.
366
-
367
- - [ ] **Step 5: Run all backend-neutral dispatch prompt tests**
368
-
369
- Run:
370
-
371
- ```bash
372
- python3 -m pytest tests/test_dispatch_core.py -q
373
- ```
374
-
375
- Expected: PASS for all tests in `tests/test_dispatch_core.py`.
376
-
377
- ---
378
-
379
- ### Task 4: Verify Integration and Update User-Facing Log
380
-
381
- **Files:**
382
- - Modify: `CHANGES.md`
383
- - Verify: `tests/test_worker_prompt_headers.py`, `tests/test_codex_dispatch.py`, `tests/test_dispatch_core.py`, `tests/test_docs_runtime_contract.py`, generated `runtime/`
384
-
385
- - [ ] **Step 1: Run the focused regression suite**
386
-
387
- Run:
388
-
389
- ```bash
390
- python3 -m pytest tests/test_worker_prompt_headers.py tests/test_codex_dispatch.py::test_base_prompt_headers_wraps_worker_header_errors tests/test_dispatch_core.py::test_materialize_prompt_wraps_worker_header_errors -q
391
- ```
392
-
393
- Expected: PASS for the shared helper test file and both new dispatcher boundary tests.
394
-
395
- - [ ] **Step 2: Run the prompt/dispatch contract suite**
396
-
397
- Run:
398
-
399
- ```bash
400
- python3 -m pytest tests/test_worker_prompt_headers.py tests/test_codex_dispatch.py tests/test_dispatch_core.py tests/test_docs_runtime_contract.py -q
401
- ```
402
-
403
- Expected: PASS for all prompt, dispatch, and runtime-contract tests.
404
-
405
- - [ ] **Step 3: Update `CHANGES.md` under `## 2026-06-15`**
406
-
407
- Insert this entry after the current `fix(dispatch): worker 프롬프트가 coding-preflight 팩 경로를 앵커 헤더로 직접 수신` section:
408
-
409
- ```markdown
410
- ### fix(dispatch): worker prompt header 오류를 dispatcher 경계에서 정규화
411
-
412
- - **배경**: worker prompt anchor header 렌더러를 공유 모듈로 추출한 뒤 malformed fallback manifest 가 renderer 내부 예외를 그대로 노출할 수 있었다. Codex CLI dispatcher 는 `DispatchError` 만 clean error 로 처리하므로 helper 예외가 그대로 올라오면 traceback 형태로 보일 위험이 있었다.
413
- - **해결**: shared renderer 는 `WorkerPromptHeaderError` 를 던지고, Codex dispatcher 와 backend-neutral dispatch core 는 이를 각자의 `DispatchError` 로 변환한다. 정상 header 렌더링 경로와 기존 deterministic prompt materialization 은 그대로 유지한다.
414
- - 사용자 영향: 잘못된 run manifest/context 로 fallback worker prompt 를 만들 수 없는 경우에도 내부 helper 예외나 traceback 대신 dispatcher 의 일관된 오류 메시지로 실패한다.
415
- ```
416
-
417
- - [ ] **Step 4: Refresh runtime build output**
418
-
419
- Run:
420
-
421
- ```bash
422
- npm run build
423
- ```
424
-
425
- Expected: exit code 0 and build sync completion, including `scripts/`, `prompts/`, `skills/`, `agents/`, `templates/`, and `validators/` sources.
426
-
427
- - [ ] **Step 5: Run the full project check**
428
-
429
- Run:
430
-
431
- ```bash
432
- npm run check
433
- ```
434
-
435
- Expected: exit code 0. JavaScript tests, Python tests, and `validators/validate-workflow.sh` all pass.
436
-
437
- - [ ] **Step 6: Smoke-test runtime import after build**
438
-
439
- Run:
440
-
441
- ```bash
442
- python3 - <<'PY'
443
- from pathlib import Path
444
- import sys
445
-
446
- sys.path.insert(0, "runtime/scripts")
447
-
448
- from okstra_ctl.codex_dispatch import DispatchError, _base_prompt_headers
449
-
450
- try:
451
- _base_prompt_headers(
452
- project_root=Path("/project"),
453
- manifest={},
454
- active_context={},
455
- worker_id="codex",
456
- prompt_rel=".okstra/run/prompts/codex.md",
457
- result_rel=".okstra/run/worker-results/codex.md",
458
- )
459
- except DispatchError as exc:
460
- print(type(exc).__name__, str(exc))
461
- else:
462
- raise SystemExit("expected DispatchError")
463
- PY
464
- ```
465
-
466
- Expected output:
467
-
468
- ```text
469
- DispatchError missing required string field: teamStatePath
470
- ```
471
-
472
- - [ ] **Step 7: Commit the finished fix**
473
-
474
- Run:
475
-
476
- ```bash
477
- git add scripts/okstra_ctl/worker_prompt_headers.py scripts/okstra_ctl/codex_dispatch.py scripts/okstra_ctl/dispatch_core.py tests/test_worker_prompt_headers.py tests/test_codex_dispatch.py tests/test_dispatch_core.py CHANGES.md
478
- git commit -m "fix(dispatch): normalize worker prompt header errors"
479
- ```
480
-
481
- Expected: one conventional commit containing source changes, regression tests, and the user-facing behavior log. `runtime/` stays generated and is not hand-edited.
482
- ---
483
-
484
- ## Self-Review Checklist
485
-
486
- - [ ] The plan covers the only remaining in-scope issue: shared header renderer exceptions leaking past dispatcher error boundaries.
487
- - [ ] The graphify update failure is excluded because the user classified it as an external plugin issue.
488
- - [ ] No compatibility shim or duplicate renderer is introduced; `worker_prompt_headers.py` remains the single header-rendering implementation.
489
- - [ ] Tests assert observable behavior: public exception type at the dispatcher boundary and absence of a partial prompt file on dispatch-core failure.
490
- - [ ] `CHANGES.md` states the user impact and the mechanism that enforces the cleaner failure mode.