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.
- package/README.kr.md +5 -5
- package/README.md +5 -5
- package/docs/kr/architecture/storage-model.md +8 -3
- package/docs/kr/architecture.md +12 -13
- package/docs/kr/cli.md +4 -4
- package/docs/kr/container.md +1 -1
- package/docs/kr/performance-improvement-plan-v2.md +2 -2
- package/docs/project-structure-overview.md +2 -2
- package/package.json +7 -2
- package/runtime/BUILD.json +2 -2
- package/runtime/bin/lib/okstra/interactive.sh +12 -0
- package/runtime/bin/okstra-antigravity-exec.sh +1 -2
- package/runtime/bin/okstra-codex-exec.sh +1 -2
- package/runtime/bin/okstra-render-final-report.py +2 -9
- package/runtime/bin/okstra-spawn-followups.py +4 -6
- package/runtime/bin/okstra-trace-cleanup.sh +24 -4
- package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
- package/runtime/prompts/lead/report-writer.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +9 -11
- package/runtime/python/okstra_ctl/codex_dispatch.py +6 -13
- package/runtime/python/okstra_ctl/consumers.py +35 -0
- package/runtime/python/okstra_ctl/container.py +4 -6
- package/runtime/python/okstra_ctl/dispatch_core.py +8 -13
- package/runtime/python/okstra_ctl/final_report_paths.py +24 -0
- package/runtime/python/okstra_ctl/handoff.py +2 -1
- package/runtime/python/okstra_ctl/implementation_outcome.py +271 -0
- package/runtime/python/okstra_ctl/implementation_stage.py +7 -11
- package/runtime/python/okstra_ctl/path_hints.py +665 -0
- package/runtime/python/okstra_ctl/render.py +4 -3
- package/runtime/python/okstra_ctl/report_view_artifacts.py +14 -0
- package/runtime/python/okstra_ctl/report_views.py +7 -4
- package/runtime/python/okstra_ctl/run.py +3 -10
- package/runtime/python/okstra_ctl/run_context.py +4 -2
- package/runtime/python/okstra_ctl/stage_targets.py +18 -0
- package/runtime/python/okstra_ctl/wizard.py +37 -26
- package/runtime/python/okstra_ctl/wizard_stage_intent.py +54 -0
- package/runtime/python/okstra_project/state.py +40 -2
- package/runtime/python/okstra_token_usage/report.py +2 -5
- package/runtime/validators/validate-report-views.py +2 -1
- package/runtime/validators/validate-run.py +1 -11
- package/src/commands/lifecycle/install.mjs +5 -5
- package/src/commands/lifecycle/uninstall.mjs +4 -4
- package/docs/superpowers/plans/2026-05-12-ticket-id-in-reports.md +0 -638
- package/docs/superpowers/plans/2026-05-14-convergence-queue-pruning.md +0 -1568
- package/docs/superpowers/plans/2026-05-17-dual-format-final-report.md +0 -167
- package/docs/superpowers/plans/2026-05-20-final-report-language.md +0 -1501
- package/docs/superpowers/plans/2026-05-20-implementation-planning-multi-stage.md +0 -1267
- package/docs/superpowers/plans/2026-05-20-okstra-run-prompt-sot-b1.md +0 -1007
- package/docs/superpowers/plans/2026-05-20-wizard-messages-json-sot.md +0 -720
- package/docs/superpowers/plans/2026-05-20-wizard-prompt-json-sot-a1.md +0 -681
- package/docs/superpowers/plans/2026-05-21-improvement-discovery-task-type.md +0 -1691
- package/docs/superpowers/plans/2026-05-24-implementation-lead-context-slimming.md +0 -1700
- package/docs/superpowers/plans/2026-05-25-okstra-project-root-rename.md +0 -158
- package/docs/superpowers/plans/2026-05-26-wizard-3-option-picker.md +0 -860
- package/docs/superpowers/plans/2026-06-02-final-verification-protocol-hardening.md +0 -326
- package/docs/superpowers/plans/2026-06-02-okstra-run-branch-confirm-step.md +0 -337
- package/docs/superpowers/plans/2026-06-02-okstra-run-phase-pane-cleanup.md +0 -410
- package/docs/superpowers/plans/2026-06-02-requirements-discovery-fanout.md +0 -728
- package/docs/superpowers/plans/2026-06-04-adversarial-implementation-planning.md +0 -294
- package/docs/superpowers/plans/2026-06-04-adversarial-verification.md +0 -570
- package/docs/superpowers/plans/2026-06-04-coverage-critic.md +0 -516
- package/docs/superpowers/plans/2026-06-04-stage-cohesion-planner.md +0 -351
- package/docs/superpowers/plans/2026-06-04-stage-run-batching.md +0 -457
- package/docs/superpowers/plans/2026-06-05-acceptance-critic.md +0 -251
- package/docs/superpowers/plans/2026-06-05-compact-markdown-report-tables.md +0 -323
- package/docs/superpowers/plans/2026-06-05-wizard-batch-prompts.md +0 -559
- package/docs/superpowers/plans/2026-06-06-final-verification-whole-task-gate.md +0 -993
- package/docs/superpowers/plans/2026-06-06-stage-parallel-and-pending-fixes.md +0 -93
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p1.md +0 -447
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p2.md +0 -289
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p3.md +0 -774
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p4.md +0 -303
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p5-multidep-base.md +0 -387
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase2.md +0 -275
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase3.md +0 -282
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4a.md +0 -147
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4b.md +0 -262
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4c.md +0 -184
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4d.md +0 -88
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4e.md +0 -250
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa.md +0 -409
- package/docs/superpowers/plans/2026-06-09-implementation-run-artifact-stage-isolation.md +0 -320
- package/docs/superpowers/plans/2026-06-10-concurrent-run-team-guard.md +0 -456
- package/docs/superpowers/plans/2026-06-10-git-reconcile-stale-sha-recovery.md +0 -1408
- package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling-PROBE.md +0 -42
- package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling.md +0 -337
- package/docs/superpowers/plans/2026-06-10-p6-token-usage-incremental.md +0 -1029
- package/docs/superpowers/plans/2026-06-10-stage-group-handoff.md +0 -1572
- package/docs/superpowers/plans/2026-06-11-fix-cycle.md +0 -1290
- package/docs/superpowers/plans/2026-06-11-wizard-whole-task-final-verification.md +0 -526
- package/docs/superpowers/plans/2026-06-12-html-plan-approval.md +0 -1000
- package/docs/superpowers/plans/2026-06-13-repo-risk-hardening.md +0 -493
- package/docs/superpowers/plans/2026-06-14-host-runtime-auto-execution.md +0 -1775
- package/docs/superpowers/plans/2026-06-15-coding-preflight-pack-dispatch-path.md +0 -504
- package/docs/superpowers/plans/2026-06-15-internal-skill-migration-final-fixups.md +0 -342
- package/docs/superpowers/plans/2026-06-15-internal-skill-migration-fixups.md +0 -258
- package/docs/superpowers/plans/2026-06-15-internal-skill-migration-remaining-fixups.md +0 -387
- package/docs/superpowers/plans/2026-06-15-internal-skill-resource-migration.md +0 -749
- package/docs/superpowers/plans/2026-06-15-worker-prompt-anchor-final-fixups.md +0 -828
- package/docs/superpowers/plans/2026-06-15-worker-prompt-header-error-contract.md +0 -490
- package/docs/superpowers/plans/2026-06-17-okstra-error-report.md +0 -724
- package/docs/superpowers/plans/2026-06-18-subagent-pane-reclaim.md +0 -483
- package/docs/superpowers/plans/2026-06-19-agent-operating-standard.md +0 -476
- package/docs/superpowers/plans/2026-06-19-okstra-inspect-recap-facet.md +0 -647
- package/docs/superpowers/plans/2026-06-20-error-feedback-loop.md +0 -1019
- package/docs/superpowers/plans/2026-06-20-run-index-row-normalization.md +0 -583
- package/docs/superpowers/plans/2026-06-20-stage-auto-integrate-teardown.md +0 -819
- package/docs/superpowers/plans/2026-06-21-okstra-container-local-user-test.md +0 -714
- package/docs/superpowers/plans/2026-06-21-release-handoff-local-checkout.md +0 -348
- package/docs/superpowers/plans/2026-06-23-implementation-stage-multiselect-chain.md +0 -630
- package/docs/superpowers/plans/2026-06-23-implementation-step-commit-granularity.md +0 -274
- package/docs/superpowers/plans/2026-06-23-phase-batch-cleanup-enforcement.md +0 -409
- package/docs/superpowers/plans/2026-06-24-cross-project-precondition.md +0 -542
- package/docs/superpowers/plans/2026-06-24-decision-drafts-render-gap.md +0 -568
- package/docs/superpowers/plans/2026-06-24-manual-user-test-section.md +0 -203
- package/docs/superpowers/plans/2026-06-24-okstra-container-build-rename.md +0 -525
- package/docs/superpowers/specs/2026-05-12-ticket-id-in-reports-design.md +0 -131
- package/docs/superpowers/specs/2026-05-15-implementation-plan-verification-design.md +0 -254
- package/docs/superpowers/specs/2026-05-20-final-report-language-design.md +0 -383
- package/docs/superpowers/specs/2026-05-20-implementation-planning-multi-stage-design.md +0 -322
- package/docs/superpowers/specs/2026-05-20-okstra-run-prompt-sot-design.md +0 -299
- package/docs/superpowers/specs/2026-05-21-improvement-discovery-task-type-design.md +0 -335
- package/docs/superpowers/specs/2026-06-02-okstra-run-branch-confirm-step-design.md +0 -113
- package/docs/superpowers/specs/2026-06-02-okstra-run-phase-pane-cleanup-design.md +0 -173
- package/docs/superpowers/specs/2026-06-02-requirements-discovery-fanout-design.md +0 -154
- package/docs/superpowers/specs/2026-06-04-adversarial-implementation-planning-design.md +0 -90
- package/docs/superpowers/specs/2026-06-04-adversarial-verification-design.md +0 -176
- package/docs/superpowers/specs/2026-06-04-coverage-critic-design.md +0 -99
- package/docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md +0 -98
- package/docs/superpowers/specs/2026-06-05-acceptance-critic-design.md +0 -90
- package/docs/superpowers/specs/2026-06-05-compact-markdown-report-tables-design.md +0 -87
- package/docs/superpowers/specs/2026-06-05-wizard-batch-prompts-design.md +0 -121
- package/docs/superpowers/specs/2026-06-06-final-verification-whole-task-gate-design.md +0 -126
- package/docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md +0 -180
- package/docs/superpowers/specs/2026-06-06-vertical-slice-tdd-planning-design.md +0 -179
- package/docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md +0 -169
- package/docs/superpowers/specs/2026-06-09-executor-model-custom-id-cascade-design.md +0 -66
- package/docs/superpowers/specs/2026-06-09-implementation-run-artifact-stage-isolation-design.md +0 -87
- package/docs/superpowers/specs/2026-06-10-blocking-contract-posthoc-conformance-design.md +0 -168
- package/docs/superpowers/specs/2026-06-10-concurrent-run-team-guard-design.md +0 -107
- package/docs/superpowers/specs/2026-06-10-git-reconcile-stale-sha-recovery-design.md +0 -105
- package/docs/superpowers/specs/2026-06-10-lead-worker-completion-polling-design.md +0 -113
- package/docs/superpowers/specs/2026-06-10-stage-group-handoff-design.md +0 -156
- package/docs/superpowers/specs/2026-06-11-brief-entry-only-handoff-stage-entry-design.md +0 -158
- package/docs/superpowers/specs/2026-06-11-fix-cycle-design.md +0 -94
- package/docs/superpowers/specs/2026-06-11-wizard-whole-task-final-verification-design.md +0 -89
- package/docs/superpowers/specs/2026-06-12-codex-lead-adapter-design.md +0 -358
- package/docs/superpowers/specs/2026-06-12-html-plan-approval-design.md +0 -85
- package/docs/superpowers/specs/2026-06-12-stage-discipline-rule-design.md +0 -108
- package/docs/superpowers/specs/2026-06-13-forbidden-actions-ssot-design.md +0 -134
- package/docs/superpowers/specs/2026-06-13-neutral-tmux-lead-adapter-design.md +0 -284
- package/docs/superpowers/specs/2026-06-14-host-runtime-auto-execution-design.md +0 -404
- package/docs/superpowers/specs/2026-06-17-okstra-error-report-design.md +0 -123
- package/docs/superpowers/specs/2026-06-18-subagent-pane-reclaim-design.md +0 -150
- package/docs/superpowers/specs/2026-06-19-agent-operating-standard-design.md +0 -120
- package/docs/superpowers/specs/2026-06-19-okstra-inspect-recap-facet-design.md +0 -96
- package/docs/superpowers/specs/2026-06-20-error-feedback-loop-design.md +0 -171
- package/docs/superpowers/specs/2026-06-20-run-index-row-normalization-design.md +0 -112
- package/docs/superpowers/specs/2026-06-20-stage-auto-integrate-teardown-design.md +0 -145
- package/docs/superpowers/specs/2026-06-21-okstra-container-local-user-test-design.md +0 -125
- package/docs/superpowers/specs/2026-06-21-release-handoff-local-checkout-design.md +0 -113
- package/docs/superpowers/specs/2026-06-23-implementation-stage-multiselect-chain-design.md +0 -138
- package/docs/superpowers/specs/2026-06-23-implementation-step-commit-granularity-design.md +0 -120
- package/docs/superpowers/specs/2026-06-24-cross-project-precondition-design.md +0 -129
- package/docs/superpowers/specs/2026-06-24-decision-drafts-render-gap-design.md +0 -185
- package/docs/superpowers/specs/2026-06-24-manual-user-test-section-design.md +0 -121
- 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.
|