okstra 0.62.0 → 0.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/claude-worker.md +6 -2
- package/runtime/agents/workers/codex-worker.md +6 -2
- package/runtime/agents/workers/gemini-worker.md +6 -2
- package/runtime/agents/workers/report-writer-worker.md +6 -1
- package/runtime/templates/reports/final-report.template.md +5 -8
- package/runtime/templates/reports/i18n/en.json +1 -1
- package/runtime/templates/reports/i18n/ko.json +1 -1
- package/runtime/templates/worker-prompt-preamble.md +10 -0
- package/runtime/validators/validate-implementation-plan-stages.py +10 -5
package/package.json
CHANGED
package/runtime/BUILD.json
CHANGED
|
@@ -90,8 +90,12 @@ You are an in-process Claude subagent — Lead's `Agent()` call blocks until you
|
|
|
90
90
|
|
|
91
91
|
After your `Write` to the assigned worker-results file (path provided by Lead as `**Result Path:**` — the canonical anchor header defined in `okstra-team-contract` "Worker Prompt Composition" — or derived under `runs/<task-type>/worker-results/claude-worker-<task-type>-<seq>.md`) succeeds:
|
|
92
92
|
|
|
93
|
-
1. Return your final assistant message **immediately
|
|
94
|
-
|
|
93
|
+
1. Return your final assistant message **immediately**. Begin every return with your model identity, copied verbatim from the `**Model:** Claude worker, <modelExecutionValue>` line in your dispatch prompt (per Worker Preamble → "Return message to the lead"), then the status line — for an analysis dispatch:
|
|
94
|
+
```
|
|
95
|
+
**Model:** Claude worker, <modelExecutionValue>
|
|
96
|
+
Worker results written to <abs path>. Sections 1–5 complete. Findings: <n>.
|
|
97
|
+
```
|
|
98
|
+
The `**Model:**` line precedes whatever you return — analysis status above, or a convergence reverify verdict summary.
|
|
95
99
|
2. Do NOT perform additional `Read`, `Grep`, `Glob`, MCP, or self-review tool calls after the file is written.
|
|
96
100
|
3. Do NOT rewrite the worker-results file with `Write` more than once. If a correction is genuinely required, perform a single `Edit` and then return immediately.
|
|
97
101
|
4. The only exception is recording a `tool-failure` in the errors sidecar when a post-Write failure is itself the failure being reported — return immediately after that single sidecar append.
|
|
@@ -106,7 +106,11 @@ The wrapper exists because Claude Code's Bash permission matcher rejects simple-
|
|
|
106
106
|
2. Record a `cli-failure` event directly to the run-level error log via the exact `okstra-error-log.py append-observed` template in §"Error reporting" — substitute `--exit-code 0`, `--duration-ms <observed-ms>`, `--message "okstra-codex-exec.sh exited 0 but no result file at <abs-path>"`, and `--stderr-excerpt-file <temp-tail-path>`.
|
|
107
107
|
3. Return `CODEX_RESULT_MISSING: codex exited 0 but result file absent at <abs-path>` instead of the raw stdout. The lead is responsible for deciding redispatch per `okstra-team-contract` "Lead Redispatch Policy on Result-Missing".
|
|
108
108
|
|
|
109
|
-
d. **Normal return.** Otherwise (`exit_code == 0` AND result file exists),
|
|
109
|
+
d. **Normal return.** Otherwise (`exit_code == 0` AND result file exists), return the wrapper's accumulated stdout from `BashOutput`, prefixed by exactly one model-identity line copied verbatim from the `**Model:** Codex worker, <execution-value>` line in the lead prompt (per Worker Preamble → "Return message to the lead"):
|
|
110
|
+
```
|
|
111
|
+
**Model:** Codex worker, <assigned-model-execution-value>
|
|
112
|
+
```
|
|
113
|
+
Emit that line first, then the stdout unmodified. The model line is the ONLY addition permitted — do not otherwise summarize or alter the CLI output. This applies to convergence reverify dispatches too.
|
|
110
114
|
|
|
111
115
|
9. When `Task Type` is `improvement-discovery`, the lead's Phase 1.5 reflect-back log at `<RUN_DIR>/state/phase-1.5-grilling.md` is the authoritative scope and lens definition. Read its `Resolved scope` and `Resolved lenses` blocks and do NOT re-interpret the brief's raw `scan-scope` / `priority-lenses` fields. Findings that violate the resolved lens whitelist or scope are rejected by `validators/validate-improvement-report.py`.
|
|
112
116
|
|
|
@@ -228,7 +232,7 @@ pre-flight terminal status, not a runtime CLI error.
|
|
|
228
232
|
|
|
229
233
|
- Ignore stderr warnings from MCP integration.
|
|
230
234
|
- Return error messages as-is on failure.
|
|
231
|
-
- Do not summarize or modify Codex results.
|
|
235
|
+
- Do not summarize or modify Codex results beyond prepending the single `**Model:**` line on a normal return (step 8d).
|
|
232
236
|
- Sections 1–5 of the worker output are the common core shared with the Claude and Gemini workers — the dispatched prompt asks identical questions for all three roles, and the Codex CLI must answer all of them, not only implementation-feasibility findings. Your specialization (implementation realism, code-path implications, edge cases, technical trade-offs) belongs only in optional Section 6 as additive depth. A Codex result whose Findings section is populated solely with implementation-feasibility items is in breach of contract; see `skills/okstra-team-contract/SKILL.md` "Worker Output Contract".
|
|
233
237
|
|
|
234
238
|
## Stage evidence emission (BLOCKING, implementation task only)
|
|
@@ -106,7 +106,11 @@ The wrapper exists because Claude Code's Bash permission matcher rejects simple-
|
|
|
106
106
|
2. Record a `cli-failure` event directly to the run-level error log via the exact `okstra-error-log.py append-observed` template in §"Error reporting" — substitute `--exit-code 0`, `--duration-ms <observed-ms>`, `--message "okstra-gemini-exec.sh exited 0 but no result file at <abs-path>"`, and `--stderr-excerpt-file <temp-tail-path>`.
|
|
107
107
|
3. Return `GEMINI_RESULT_MISSING: gemini exited 0 but result file absent at <abs-path>` instead of the raw stdout. The lead is responsible for deciding redispatch per `okstra-team-contract` "Lead Redispatch Policy on Result-Missing".
|
|
108
108
|
|
|
109
|
-
d. **Normal return.** Otherwise (`exit_code == 0` AND result file exists),
|
|
109
|
+
d. **Normal return.** Otherwise (`exit_code == 0` AND result file exists), return the wrapper's accumulated stdout from `BashOutput`, prefixed by exactly one model-identity line copied verbatim from the `**Model:** Gemini worker, <execution-value>` line in the lead prompt (per Worker Preamble → "Return message to the lead"):
|
|
110
|
+
```
|
|
111
|
+
**Model:** Gemini worker, <assigned-model-execution-value>
|
|
112
|
+
```
|
|
113
|
+
Emit that line first, then the stdout unmodified. The model line is the ONLY addition permitted — do not otherwise summarize or alter the CLI output. This applies to convergence reverify dispatches too.
|
|
110
114
|
|
|
111
115
|
9. When `Task Type` is `improvement-discovery`, the lead's Phase 1.5 reflect-back log at `<RUN_DIR>/state/phase-1.5-grilling.md` is the authoritative scope and lens definition. Read its `Resolved scope` and `Resolved lenses` blocks and do NOT re-interpret the brief's raw `scan-scope` / `priority-lenses` fields. Findings that violate the resolved lens whitelist or scope are rejected by `validators/validate-improvement-report.py`.
|
|
112
116
|
|
|
@@ -228,7 +232,7 @@ pre-flight terminal status, not a runtime CLI error.
|
|
|
228
232
|
|
|
229
233
|
- Always specify the assigned `-m` value for the current run.
|
|
230
234
|
- Return error messages as-is on failure.
|
|
231
|
-
- Do not summarize or modify Gemini results.
|
|
235
|
+
- Do not summarize or modify Gemini results beyond prepending the single `**Model:**` line on a normal return (step 8d).
|
|
232
236
|
- Sections 1–5 of the worker output are the common core shared with the Claude and Codex workers — the dispatched prompt asks identical questions for all three roles, and the Gemini CLI must answer all of them, not only requirement-interpretation findings. Your specialization (requirement interpretation, consistency, safety, documentation quality, alternative viewpoints) belongs only in optional Section 6 as additive depth. A Gemini result whose Findings section is populated solely with requirement-interpretation items is in breach of contract; see `skills/okstra-team-contract/SKILL.md` "Worker Output Contract".
|
|
233
237
|
|
|
234
238
|
## Stage evidence emission (BLOCKING, implementation task only)
|
|
@@ -103,7 +103,12 @@ Rules (the schema enforces most of these — they are listed here so you know *w
|
|
|
103
103
|
- For `implementation-planning`, populate `implementationPlanning.requirementCoverage` with one row per concrete requirement from the brief / packet, using IDs `R-001`, `R-002`, ... in source order. `coveredBy` MUST name the specific Option Candidate plus Stage/Step that satisfies the requirement. Use `status: "covered"` only when the report's plan actually covers it; otherwise use `gap` or `blocked C-NNN` and ensure the corresponding `Clarification Items` row blocks approval. Do not collapse this into `ticketCoverage`; ticket coverage is not requirement coverage.
|
|
104
104
|
- When the `Task Type` is `improvement-discovery`, populate `## 5.9 Improvement Candidates` with the 10-column schema enforced by `validators/validate-improvement-report.py`. Source the row IDs (`I-NNN`), lens whitelist, and Source workers patterns from `scripts/okstra_ctl/improvement_lenses.py` — do NOT introduce new lens names or worker prefixes. `improvement-discovery` is NOT in the data.json schema enum, so author its markdown directly (not via `okstra-render-final-report.py`). Immediately after writing the markdown, run (`Bash`): `python3 scripts/okstra-inject-report-index.py <markdown path> --report-language <en|ko>`. That adds the top-of-report Index plus `I-NNN` / `C-NNN` scroll anchors; the run validator fails the report when the Index anchor is absent.
|
|
105
105
|
|
|
106
|
-
Write the data.json with your `Write` tool against the absolute `Result Path`. Then invoke the renderer (`Bash`): `python3 scripts/okstra-render-final-report.py <data.json path>`. Confirm both files exist and respond with a short status line
|
|
106
|
+
Write the data.json with your `Write` tool against the absolute `Result Path`. Then invoke the renderer (`Bash`): `python3 scripts/okstra-render-final-report.py <data.json path>`. Confirm both files exist and respond with a short status line prefixed by your model identity, copied verbatim from the `**Model:** Report writer worker, <modelExecutionValue>` line in your dispatch prompt (per Worker Preamble → "Return message to the lead"):
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
**Model:** Report writer worker, <modelExecutionValue>
|
|
110
|
+
data.json written to <abs path>; markdown rendered to <abs path>. Sections populated: <count>.
|
|
111
|
+
```
|
|
107
112
|
|
|
108
113
|
<!-- Worker Result File contract lives above, right after the Authority
|
|
109
114
|
section. The legacy "after Authoring Contract" placement was kept
|
|
@@ -235,18 +235,15 @@ implementation-option: {{ frontmatter.implementationOption | yaml_scalar }}
|
|
|
235
235
|
{% for stage in implementationPlanning.stages %}
|
|
236
236
|
## 5.5.{{ stage.stage }} Stage {{ stage.stage }}: {{ stage.title }}
|
|
237
237
|
|
|
238
|
-
Slice value
|
|
239
|
-
|
|
240
|
-
Acceptance: {{ stage.acceptance }}
|
|
241
|
-
|
|
238
|
+
- **Slice value:** {{ stage.sliceValue }}
|
|
239
|
+
- **Acceptance:** {{ stage.acceptance }}
|
|
242
240
|
{% if stage.conformanceTests %}
|
|
243
|
-
Conformance tests
|
|
241
|
+
- **Conformance tests:** stage-{{ stage.stage }} — {{ stage.conformanceTests }}
|
|
244
242
|
{% else %}
|
|
245
|
-
Conformance exemption
|
|
243
|
+
- **Conformance exemption:** {{ stage.conformanceExemption }}
|
|
246
244
|
{% endif %}
|
|
247
245
|
{% if stage.tddExemption %}
|
|
248
|
-
|
|
249
|
-
TDD exemption: {{ stage.tddExemption }}
|
|
246
|
+
- **TDD exemption:** {{ stage.tddExemption }}
|
|
250
247
|
{% endif %}
|
|
251
248
|
|
|
252
249
|
### Carry-In
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"columnRelatedIds": "Related item IDs"
|
|
69
69
|
},
|
|
70
70
|
"finalVerdict": {
|
|
71
|
-
"intro": "
|
|
71
|
+
"intro": "This run's final conclusion and next action. **`Direction`** is the recommended next action — one of `continue-investigation`, `begin-implementation`, `approve`, `reject`, or `hold` — and is present for every task-type. **`Verdict Token`** is meaningful only for the `final-verification` task-type, where it is one of `accepted`, `conditional-accept`, or `blocked` and serves as the `release-handoff` entry gate. For every other task-type, `Verdict Token` is always `not-applicable`."
|
|
72
72
|
},
|
|
73
73
|
"evidence": {
|
|
74
74
|
"sourceItemsColumnNote": "The `Source items` column is described in §6.1."
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"columnRelatedIds": "관련 항목 IDs"
|
|
69
69
|
},
|
|
70
70
|
"finalVerdict": {
|
|
71
|
-
"intro": "최종 결론과
|
|
71
|
+
"intro": "이 run 의 최종 결론과 다음 행동입니다. **`Direction`** 은 권장 다음 행동으로 `continue-investigation`(조사 계속) · `begin-implementation`(구현 시작) · `approve`(승인) · `reject`(반려) · `hold`(보류) 중 하나이며, 모든 task-type 에 존재합니다. **`Verdict Token`** 은 `final-verification` task-type 에서만 의미를 가집니다 — `accepted` · `conditional-accept` · `blocked` 중 하나로 `release-handoff` 진입 게이트로 쓰입니다. 그 외 task-type 에서 `Verdict Token` 은 항상 `not-applicable`(해당 없음) 입니다."
|
|
72
72
|
},
|
|
73
73
|
"evidence": {
|
|
74
74
|
"sourceItemsColumnNote": "`Source items` 열 설명은 §6.1 과 동일합니다."
|
|
@@ -114,6 +114,16 @@ For task types `requirements-discovery`, `error-analysis`, `implementation-plann
|
|
|
114
114
|
|
|
115
115
|
See `skills/okstra-team-contract/SKILL.md` "Worker Output Contract" for the full frontmatter schema and section ordering rules. This preamble is consistent with that contract; the team-contract document is authoritative if the two ever diverge.
|
|
116
116
|
|
|
117
|
+
## Return message to the lead (all workers)
|
|
118
|
+
|
|
119
|
+
The short message you return inline to the lead — the text shown to the user as your agent box — MUST begin with one line identifying the model you ran under, copied verbatim from the `**Model:** <Role>, <modelExecutionValue>` line in your dispatch prompt:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
**Model:** <Role>, <modelExecutionValue>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Emit that line first, then your normal status / summary text on the following lines. This keeps the acting model visible in every worker box — across every provider (Claude / Codex / Gemini / report-writer) and every dispatch type (initial analysis, convergence reverify, report authoring). Copy the value exactly; never guess, abbreviate, or substitute a provider default. If your prompt carries no `**Model:**` line, say so in the return message rather than inventing one. Each worker spec applies this rule at its own concrete return point — see `agents/workers/claude-worker.md` "Stop Condition", `agents/workers/_cli-wrapper-template.md` step 8d, and `agents/workers/report-writer-worker.md` "Authoring Contract".
|
|
126
|
+
|
|
117
127
|
## Writing style (all prose output — analysis workers + report-writer)
|
|
118
128
|
|
|
119
129
|
When you write in Korean (`Report Language: ko` / `meta.reportLanguage = "ko"`), write so a Korean developer understands it on first read. Translate the **meaning**, never the dictionary word.
|
|
@@ -162,11 +162,16 @@ def _check_each_stage_section(text: str, stages: List[StageMeta]) -> List[Valida
|
|
|
162
162
|
return errs
|
|
163
163
|
|
|
164
164
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
165
|
+
# Each label line may be plain (`Slice value: …`) or rendered as a bold-label
|
|
166
|
+
# bullet (`- **Slice value:** …`). The optional `(?:[-*]\s+)?` bullet marker and
|
|
167
|
+
# the two optional `\*\*` groups accept both forms; the bold wraps the colon, so
|
|
168
|
+
# the closing `**` sits AFTER the colon.
|
|
169
|
+
_LABEL_PREFIX = r"^\s*(?:[-*]\s+)?(?:\*\*)?"
|
|
170
|
+
SLICE_VALUE = re.compile(_LABEL_PREFIX + r"Slice value\s*:\s*(?:\*\*)?\s*(.+?)\s*$", re.M)
|
|
171
|
+
ACCEPTANCE = re.compile(_LABEL_PREFIX + r"Acceptance\s*:\s*(?:\*\*)?\s*(.+?)\s*$", re.M)
|
|
172
|
+
TDD_EXEMPTION = re.compile(_LABEL_PREFIX + r"TDD exemption\s*:\s*(?:\*\*)?\s*\S", re.M)
|
|
173
|
+
CONFORMANCE_TESTS = re.compile(_LABEL_PREFIX + r"Conformance tests\s*:\s*(?:\*\*)?\s*\S", re.M)
|
|
174
|
+
CONFORMANCE_EXEMPTION = re.compile(_LABEL_PREFIX + r"Conformance exemption\s*:\s*(?:\*\*)?\s*\S", re.M)
|
|
170
175
|
|
|
171
176
|
|
|
172
177
|
def _check_slice_tdd(text: str, stages: List[StageMeta]) -> List[ValidationError]:
|