okstra 0.102.2 → 0.102.3

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 (161) hide show
  1. package/README.kr.md +5 -5
  2. package/README.md +5 -5
  3. package/docs/kr/architecture/storage-model.md +1 -1
  4. package/docs/kr/architecture.md +7 -11
  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/okstra-antigravity-exec.sh +1 -2
  12. package/runtime/bin/okstra-codex-exec.sh +1 -2
  13. package/runtime/bin/okstra-render-final-report.py +2 -9
  14. package/runtime/bin/okstra-spawn-followups.py +4 -6
  15. package/runtime/bin/okstra-trace-cleanup.sh +24 -4
  16. package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
  17. package/runtime/prompts/lead/report-writer.md +1 -1
  18. package/runtime/prompts/profiles/_common-contract.md +9 -11
  19. package/runtime/python/okstra_ctl/codex_dispatch.py +4 -12
  20. package/runtime/python/okstra_ctl/consumers.py +35 -0
  21. package/runtime/python/okstra_ctl/container.py +4 -6
  22. package/runtime/python/okstra_ctl/dispatch_core.py +4 -12
  23. package/runtime/python/okstra_ctl/final_report_paths.py +24 -0
  24. package/runtime/python/okstra_ctl/handoff.py +2 -1
  25. package/runtime/python/okstra_ctl/implementation_stage.py +7 -11
  26. package/runtime/python/okstra_ctl/report_view_artifacts.py +14 -0
  27. package/runtime/python/okstra_ctl/report_views.py +7 -4
  28. package/runtime/python/okstra_ctl/run.py +3 -10
  29. package/runtime/python/okstra_ctl/stage_targets.py +18 -0
  30. package/runtime/python/okstra_ctl/wizard.py +24 -25
  31. package/runtime/python/okstra_ctl/wizard_stage_intent.py +54 -0
  32. package/runtime/python/okstra_token_usage/report.py +2 -5
  33. package/runtime/validators/validate-report-views.py +2 -1
  34. package/runtime/validators/validate-run.py +1 -11
  35. package/src/commands/lifecycle/install.mjs +5 -5
  36. package/src/commands/lifecycle/uninstall.mjs +4 -4
  37. package/docs/superpowers/plans/2026-05-12-ticket-id-in-reports.md +0 -638
  38. package/docs/superpowers/plans/2026-05-14-convergence-queue-pruning.md +0 -1568
  39. package/docs/superpowers/plans/2026-05-17-dual-format-final-report.md +0 -167
  40. package/docs/superpowers/plans/2026-05-20-final-report-language.md +0 -1501
  41. package/docs/superpowers/plans/2026-05-20-implementation-planning-multi-stage.md +0 -1267
  42. package/docs/superpowers/plans/2026-05-20-okstra-run-prompt-sot-b1.md +0 -1007
  43. package/docs/superpowers/plans/2026-05-20-wizard-messages-json-sot.md +0 -720
  44. package/docs/superpowers/plans/2026-05-20-wizard-prompt-json-sot-a1.md +0 -681
  45. package/docs/superpowers/plans/2026-05-21-improvement-discovery-task-type.md +0 -1691
  46. package/docs/superpowers/plans/2026-05-24-implementation-lead-context-slimming.md +0 -1700
  47. package/docs/superpowers/plans/2026-05-25-okstra-project-root-rename.md +0 -158
  48. package/docs/superpowers/plans/2026-05-26-wizard-3-option-picker.md +0 -860
  49. package/docs/superpowers/plans/2026-06-02-final-verification-protocol-hardening.md +0 -326
  50. package/docs/superpowers/plans/2026-06-02-okstra-run-branch-confirm-step.md +0 -337
  51. package/docs/superpowers/plans/2026-06-02-okstra-run-phase-pane-cleanup.md +0 -410
  52. package/docs/superpowers/plans/2026-06-02-requirements-discovery-fanout.md +0 -728
  53. package/docs/superpowers/plans/2026-06-04-adversarial-implementation-planning.md +0 -294
  54. package/docs/superpowers/plans/2026-06-04-adversarial-verification.md +0 -570
  55. package/docs/superpowers/plans/2026-06-04-coverage-critic.md +0 -516
  56. package/docs/superpowers/plans/2026-06-04-stage-cohesion-planner.md +0 -351
  57. package/docs/superpowers/plans/2026-06-04-stage-run-batching.md +0 -457
  58. package/docs/superpowers/plans/2026-06-05-acceptance-critic.md +0 -251
  59. package/docs/superpowers/plans/2026-06-05-compact-markdown-report-tables.md +0 -323
  60. package/docs/superpowers/plans/2026-06-05-wizard-batch-prompts.md +0 -559
  61. package/docs/superpowers/plans/2026-06-06-final-verification-whole-task-gate.md +0 -993
  62. package/docs/superpowers/plans/2026-06-06-stage-parallel-and-pending-fixes.md +0 -93
  63. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p1.md +0 -447
  64. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p2.md +0 -289
  65. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p3.md +0 -774
  66. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p4.md +0 -303
  67. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p5-multidep-base.md +0 -387
  68. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase2.md +0 -275
  69. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase3.md +0 -282
  70. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4a.md +0 -147
  71. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4b.md +0 -262
  72. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4c.md +0 -184
  73. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4d.md +0 -88
  74. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4e.md +0 -250
  75. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa.md +0 -409
  76. package/docs/superpowers/plans/2026-06-09-implementation-run-artifact-stage-isolation.md +0 -320
  77. package/docs/superpowers/plans/2026-06-10-concurrent-run-team-guard.md +0 -456
  78. package/docs/superpowers/plans/2026-06-10-git-reconcile-stale-sha-recovery.md +0 -1408
  79. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling-PROBE.md +0 -42
  80. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling.md +0 -337
  81. package/docs/superpowers/plans/2026-06-10-p6-token-usage-incremental.md +0 -1029
  82. package/docs/superpowers/plans/2026-06-10-stage-group-handoff.md +0 -1572
  83. package/docs/superpowers/plans/2026-06-11-fix-cycle.md +0 -1290
  84. package/docs/superpowers/plans/2026-06-11-wizard-whole-task-final-verification.md +0 -526
  85. package/docs/superpowers/plans/2026-06-12-html-plan-approval.md +0 -1000
  86. package/docs/superpowers/plans/2026-06-13-repo-risk-hardening.md +0 -493
  87. package/docs/superpowers/plans/2026-06-14-host-runtime-auto-execution.md +0 -1775
  88. package/docs/superpowers/plans/2026-06-15-coding-preflight-pack-dispatch-path.md +0 -504
  89. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-final-fixups.md +0 -342
  90. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-fixups.md +0 -258
  91. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-remaining-fixups.md +0 -387
  92. package/docs/superpowers/plans/2026-06-15-internal-skill-resource-migration.md +0 -749
  93. package/docs/superpowers/plans/2026-06-15-worker-prompt-anchor-final-fixups.md +0 -828
  94. package/docs/superpowers/plans/2026-06-15-worker-prompt-header-error-contract.md +0 -490
  95. package/docs/superpowers/plans/2026-06-17-okstra-error-report.md +0 -724
  96. package/docs/superpowers/plans/2026-06-18-subagent-pane-reclaim.md +0 -483
  97. package/docs/superpowers/plans/2026-06-19-agent-operating-standard.md +0 -476
  98. package/docs/superpowers/plans/2026-06-19-okstra-inspect-recap-facet.md +0 -647
  99. package/docs/superpowers/plans/2026-06-20-error-feedback-loop.md +0 -1019
  100. package/docs/superpowers/plans/2026-06-20-run-index-row-normalization.md +0 -583
  101. package/docs/superpowers/plans/2026-06-20-stage-auto-integrate-teardown.md +0 -819
  102. package/docs/superpowers/plans/2026-06-21-okstra-container-local-user-test.md +0 -714
  103. package/docs/superpowers/plans/2026-06-21-release-handoff-local-checkout.md +0 -348
  104. package/docs/superpowers/plans/2026-06-23-implementation-stage-multiselect-chain.md +0 -630
  105. package/docs/superpowers/plans/2026-06-23-implementation-step-commit-granularity.md +0 -274
  106. package/docs/superpowers/plans/2026-06-23-phase-batch-cleanup-enforcement.md +0 -409
  107. package/docs/superpowers/plans/2026-06-24-cross-project-precondition.md +0 -542
  108. package/docs/superpowers/plans/2026-06-24-decision-drafts-render-gap.md +0 -568
  109. package/docs/superpowers/plans/2026-06-24-manual-user-test-section.md +0 -203
  110. package/docs/superpowers/plans/2026-06-24-okstra-container-build-rename.md +0 -525
  111. package/docs/superpowers/specs/2026-05-12-ticket-id-in-reports-design.md +0 -131
  112. package/docs/superpowers/specs/2026-05-15-implementation-plan-verification-design.md +0 -254
  113. package/docs/superpowers/specs/2026-05-20-final-report-language-design.md +0 -383
  114. package/docs/superpowers/specs/2026-05-20-implementation-planning-multi-stage-design.md +0 -322
  115. package/docs/superpowers/specs/2026-05-20-okstra-run-prompt-sot-design.md +0 -299
  116. package/docs/superpowers/specs/2026-05-21-improvement-discovery-task-type-design.md +0 -335
  117. package/docs/superpowers/specs/2026-06-02-okstra-run-branch-confirm-step-design.md +0 -113
  118. package/docs/superpowers/specs/2026-06-02-okstra-run-phase-pane-cleanup-design.md +0 -173
  119. package/docs/superpowers/specs/2026-06-02-requirements-discovery-fanout-design.md +0 -154
  120. package/docs/superpowers/specs/2026-06-04-adversarial-implementation-planning-design.md +0 -90
  121. package/docs/superpowers/specs/2026-06-04-adversarial-verification-design.md +0 -176
  122. package/docs/superpowers/specs/2026-06-04-coverage-critic-design.md +0 -99
  123. package/docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md +0 -98
  124. package/docs/superpowers/specs/2026-06-05-acceptance-critic-design.md +0 -90
  125. package/docs/superpowers/specs/2026-06-05-compact-markdown-report-tables-design.md +0 -87
  126. package/docs/superpowers/specs/2026-06-05-wizard-batch-prompts-design.md +0 -121
  127. package/docs/superpowers/specs/2026-06-06-final-verification-whole-task-gate-design.md +0 -126
  128. package/docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md +0 -180
  129. package/docs/superpowers/specs/2026-06-06-vertical-slice-tdd-planning-design.md +0 -179
  130. package/docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md +0 -169
  131. package/docs/superpowers/specs/2026-06-09-executor-model-custom-id-cascade-design.md +0 -66
  132. package/docs/superpowers/specs/2026-06-09-implementation-run-artifact-stage-isolation-design.md +0 -87
  133. package/docs/superpowers/specs/2026-06-10-blocking-contract-posthoc-conformance-design.md +0 -168
  134. package/docs/superpowers/specs/2026-06-10-concurrent-run-team-guard-design.md +0 -107
  135. package/docs/superpowers/specs/2026-06-10-git-reconcile-stale-sha-recovery-design.md +0 -105
  136. package/docs/superpowers/specs/2026-06-10-lead-worker-completion-polling-design.md +0 -113
  137. package/docs/superpowers/specs/2026-06-10-stage-group-handoff-design.md +0 -156
  138. package/docs/superpowers/specs/2026-06-11-brief-entry-only-handoff-stage-entry-design.md +0 -158
  139. package/docs/superpowers/specs/2026-06-11-fix-cycle-design.md +0 -94
  140. package/docs/superpowers/specs/2026-06-11-wizard-whole-task-final-verification-design.md +0 -89
  141. package/docs/superpowers/specs/2026-06-12-codex-lead-adapter-design.md +0 -358
  142. package/docs/superpowers/specs/2026-06-12-html-plan-approval-design.md +0 -85
  143. package/docs/superpowers/specs/2026-06-12-stage-discipline-rule-design.md +0 -108
  144. package/docs/superpowers/specs/2026-06-13-forbidden-actions-ssot-design.md +0 -134
  145. package/docs/superpowers/specs/2026-06-13-neutral-tmux-lead-adapter-design.md +0 -284
  146. package/docs/superpowers/specs/2026-06-14-host-runtime-auto-execution-design.md +0 -404
  147. package/docs/superpowers/specs/2026-06-17-okstra-error-report-design.md +0 -123
  148. package/docs/superpowers/specs/2026-06-18-subagent-pane-reclaim-design.md +0 -150
  149. package/docs/superpowers/specs/2026-06-19-agent-operating-standard-design.md +0 -120
  150. package/docs/superpowers/specs/2026-06-19-okstra-inspect-recap-facet-design.md +0 -96
  151. package/docs/superpowers/specs/2026-06-20-error-feedback-loop-design.md +0 -171
  152. package/docs/superpowers/specs/2026-06-20-run-index-row-normalization-design.md +0 -112
  153. package/docs/superpowers/specs/2026-06-20-stage-auto-integrate-teardown-design.md +0 -145
  154. package/docs/superpowers/specs/2026-06-21-okstra-container-local-user-test-design.md +0 -125
  155. package/docs/superpowers/specs/2026-06-21-release-handoff-local-checkout-design.md +0 -113
  156. package/docs/superpowers/specs/2026-06-23-implementation-stage-multiselect-chain-design.md +0 -138
  157. package/docs/superpowers/specs/2026-06-23-implementation-step-commit-granularity-design.md +0 -120
  158. package/docs/superpowers/specs/2026-06-24-cross-project-precondition-design.md +0 -129
  159. package/docs/superpowers/specs/2026-06-24-decision-drafts-render-gap-design.md +0 -185
  160. package/docs/superpowers/specs/2026-06-24-manual-user-test-section-design.md +0 -121
  161. 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.