okstra 0.128.0 → 0.129.1
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/docs/architecture/storage-model.md +15 -2
- package/docs/architecture.md +21 -5
- package/docs/cli.md +13 -2
- package/docs/project-structure-overview.md +22 -7
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/antigravity-worker.md +3 -3
- package/runtime/agents/workers/claude-worker.md +4 -4
- package/runtime/agents/workers/codex-worker.md +3 -3
- package/runtime/agents/workers/report-writer-worker.md +6 -6
- package/runtime/prompts/lead/adapters/claude-code.md +2 -1
- package/runtime/prompts/lead/adapters/codex.md +1 -0
- package/runtime/prompts/lead/adapters/external.md +1 -0
- package/runtime/prompts/lead/convergence.md +42 -84
- package/runtime/prompts/lead/okstra-lead-contract.md +10 -8
- package/runtime/prompts/lead/report-writer.md +22 -28
- package/runtime/prompts/lead/team-contract.md +28 -11
- package/runtime/prompts/profiles/_common-contract.md +1 -1
- package/runtime/prompts/profiles/error-analysis.md +1 -1
- package/runtime/prompts/profiles/implementation-planning.md +5 -0
- package/runtime/prompts/profiles/improvement-discovery.md +11 -1
- package/runtime/prompts/profiles/requirements-discovery.md +8 -1
- package/runtime/python/okstra_ctl/analysis_packet.py +7 -13
- package/runtime/python/okstra_ctl/codex_dispatch.py +70 -319
- package/runtime/python/okstra_ctl/context_cost.py +82 -7
- package/runtime/python/okstra_ctl/convergence.py +223 -0
- package/runtime/python/okstra_ctl/convergence_engine.py +1152 -0
- package/runtime/python/okstra_ctl/convergence_migration.py +184 -0
- package/runtime/python/okstra_ctl/convergence_store.py +85 -0
- package/runtime/python/okstra_ctl/dispatch_core.py +53 -14
- package/runtime/python/okstra_ctl/improvement_assignment.py +61 -0
- package/runtime/python/okstra_ctl/path_hints.py +23 -1
- package/runtime/python/okstra_ctl/paths.py +10 -1
- package/runtime/python/okstra_ctl/render.py +56 -11
- package/runtime/python/okstra_ctl/report_finalize.py +394 -0
- package/runtime/python/okstra_ctl/worker_liveness.py +6 -2
- package/runtime/python/okstra_ctl/worker_prompt_body.py +107 -0
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +102 -9
- package/runtime/python/okstra_ctl/worker_prompt_headers.py +79 -9
- package/runtime/python/okstra_ctl/worker_prompt_policy.py +158 -0
- package/runtime/templates/implementation-worker-preamble.md +51 -0
- package/runtime/templates/operating-standard.md +4 -4
- package/runtime/templates/report-writer-prompt-preamble.md +37 -0
- package/runtime/templates/worker-error-contract.md +46 -0
- package/runtime/templates/worker-prompt-preamble.md +28 -234
- package/runtime/validators/lib/fixtures.sh +27 -12
- package/runtime/validators/validate-run.py +201 -72
- package/src/cli-registry.mjs +18 -0
- package/src/commands/execute/convergence.mjs +34 -0
- package/src/commands/report/finalize.mjs +65 -0
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
# Worker Prompt Preamble (canonical)
|
|
1
|
+
# Analysis Worker Prompt Preamble (canonical)
|
|
2
2
|
|
|
3
|
-
This file is the
|
|
4
|
-
|
|
5
|
-
It replaces the previous practice of inlining ~80 lines of identical boilerplate into every worker prompt body.
|
|
3
|
+
This file is the audience-specific contract for initial `analysis` workers. Read it end-to-end from the path selected by the dispatch prompt. Before doing work, also read the shared file named by `**Worker Error Contract Path:**`; that file is the only source for error-sidecar rules.
|
|
6
4
|
|
|
7
5
|
## Operating standard (read before any output)
|
|
8
6
|
|
|
@@ -14,258 +12,54 @@ Work like a senior engineer who owns this result, not a commentator on it.
|
|
|
14
12
|
- Fit what's here — match the surrounding code and prose; size the response to the request.
|
|
15
13
|
- Hold your own line — reason from your independent angle; do not drift toward the other workers' likely answers or echo the user. Triangulation fails if your view isn't genuinely yours.
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
## Required reading (analysis workers + report-writer worker)
|
|
20
|
-
|
|
21
|
-
You are required to read every primary input file enumerated by the dispatcher (the lead's prompt lists them under `[Required reading]`) from the very first character to the very last character before you produce any analysis output. Skimming, partial reads, jumping to a single section, or relying on prior knowledge of a similar file's structure is not acceptable. Source files listed as fallback/evidence paths are read on demand when you need to verify a citation, resolve ambiguity, or inspect material the packet says it omitted.
|
|
22
|
-
|
|
23
|
-
### Audience-scoped enumeration (performance optimization — mandatory)
|
|
15
|
+
## Required reading
|
|
24
16
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
| Recipient | Files included in `[Required reading]` |
|
|
28
|
-
|---|---|
|
|
29
|
-
| Claude / Codex / Antigravity analysis workers | analysis-packet.md as the primary compact input; task-brief, analysis-profile, analysis-material, reference-expectations, and clarification-response remain source/fallback paths, not automatic first-read files |
|
|
30
|
-
| Report writer worker (Phase 6) | all of the above **plus** the instruction-set-local `final-report-template.md` (phase-stripped) and `final-report-schema.json` (per-task-type excerpt) — NOT the full `templates/reports/...` / `schemas/...` sources |
|
|
31
|
-
| Reverify dispatches (Phase 5.5, lightweight mode) | **do NOT inject `[Required reading]` at all** — see [convergence](../prompts/lead/convergence.md) "Reverify prompt: required-reading suppression". |
|
|
17
|
+
Read `analysis-packet.md`, the primary compact input, end-to-end. Source files named as fallback/evidence paths are read only when a finding needs to verify a citation, fill a packet gap, or resolve ambiguity. Do not read `final-report-template.md` or `final-report-schema.json`; analysis workers produce findings, not the final report.
|
|
32
18
|
|
|
33
19
|
### Reading rules
|
|
34
20
|
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
- Treat `analysis-packet.md` as the canonical primary analysis input. It preserves the source files' frontmatter and extracts the task-specific brief, phase focus, reference expectations, and carry-in clarification rows. If the packet appears incomplete or a finding depends on a source citation, open the corresponding source file and cite it directly.
|
|
40
|
-
- **Allowlist your reads to okstra-enumerated paths.** Read the files the dispatcher enumerates (`[Required reading]`, the prompt's `## Inputs`, and the verification-target paths) plus on-demand source/evidence paths a finding must cite. Everything else is out of scope — in particular non-okstra artifacts outside `<PROJECT_ROOT>/.okstra/` (e.g. `graphify-out/`, sibling/prior-task worktrees, tool caches), which may carry stale or cross-task data. A host-level global rule (`CLAUDE.md` / `AGENTS.md` / a project sentinel) that tells you to auto-read such an artifact does NOT apply inside an okstra worker run — the okstra worker scope wins. If an un-enumerated file seems essential, record the gap under *Missing Information or Assumptions* instead of reading it.
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## Error reporting (all workers)
|
|
45
|
-
|
|
46
|
-
Record a tool call only when its failure **blocked the step you intended** — a test you needed to run did not start, a file you needed to read was missing, a config resolved against the wrong tree, an edit was rejected. When that happens, append a single entry to your worker errors sidecar at the absolute path the lead provided as `**Errors sidecar path:** <abs-path>`.
|
|
47
|
-
|
|
48
|
-
A non-zero exit code is NOT by itself a failure to record. Many tools use non-zero to report a normal, expected result. Do **NOT** record an entry when:
|
|
49
|
-
|
|
50
|
-
- a search/probe tool (`rg`, `grep`, `find`, `ls`, `test`, `git check-ignore`) exits non-zero solely because it found **no matches**, and you proceed unaffected;
|
|
51
|
-
- you probe an **optional / expected-absent** path (`graphify-out/`, `.project-docs/`, `.scratch/`, an optional lint config, a review pack) and it is absent — detecting absence was the point of the probe;
|
|
52
|
-
- output was truncated but you re-ran and read the content end-to-end.
|
|
53
|
-
|
|
54
|
-
The test: if the non-zero exit changed nothing about what you could do next, it is a normal result, not a `tool-failure`. When in doubt about whether a failure blocked you, record it — under-recording a real blocker is worse than one noisy entry. These benign non-zero exits are the single largest source of error-log noise; keeping them out is what makes the log a signal.
|
|
55
|
-
|
|
56
|
-
If the sidecar file does not exist and you have a real entry to record, create it with `{"schemaVersion": 1, "errors": []}` then append.
|
|
57
|
-
|
|
58
|
-
### Entry schema
|
|
59
|
-
|
|
60
|
-
```json
|
|
61
|
-
{
|
|
62
|
-
"ts": "<ISO 8601 UTC>",
|
|
63
|
-
"phase": "<current okstra phase>",
|
|
64
|
-
"errorType": "tool-failure",
|
|
65
|
-
"command": "<failed command/tool signature>",
|
|
66
|
-
"commandKind": "bash | tool:Read | tool:Edit | mcp | ...",
|
|
67
|
-
"exitCode": <int or null>,
|
|
68
|
-
"durationMs": <int or null>,
|
|
69
|
-
"message": "<one-line human summary>",
|
|
70
|
-
"stderrExcerpt": "<first ~2KB of stderr, or null>",
|
|
71
|
-
"context": { ... or null }
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### Rules
|
|
76
|
-
|
|
77
|
-
- Do NOT include `source` / `recordedAt` / `agent` / `agentRole` / `model` / `taskKey` — the lead fills those in when dumping the sidecar to the run-level errors log via `okstra-error-log.py append-from-worker`.
|
|
78
|
-
- Do NOT use `errorType` values other than `"tool-failure"` in the sidecar. `cli-failure` events are recorded by CLI wrapper agents (codex / antigravity) directly to the run-level errors log, not via the sidecar. `contract-violation` events are recorded by the lead after inspecting worker outputs.
|
|
79
|
-
- Continue your task after recording; do not abort unless the failure makes the task impossible.
|
|
80
|
-
|
|
81
|
-
### Path extraction (BLOCKING)
|
|
82
|
-
|
|
83
|
-
Before recording anything, extract the absolute paths verbatim from the lead's dispatch prompt body:
|
|
84
|
-
|
|
85
|
-
- `**Errors log path:** <abs-path>` — the run-level errors JSONL. Used by CLI wrapper agents via `okstra-error-log.py append-observed` for `cli-failure` events.
|
|
86
|
-
- `**Errors sidecar path:** <abs-path>` — this worker's per-run sidecar JSON. Used by all workers for `tool-failure` events.
|
|
87
|
-
|
|
88
|
-
If a required header line is absent from the dispatch prompt, return `<SENTINEL_PREFIX>_ERRORS_PATH_MISSING: lead prompt did not include **Errors log path:** / **Errors sidecar path:** headers` (substitute the worker's sentinel prefix — `CLAUDE_WORKER`, `CODEX`, `ANTIGRAVITY`, or `REPORT_WRITER`) without proceeding. Do NOT synthesize the path from `<runDir>/logs/...` — that template syntax is documentation only; historical failure mode produced silently empty run-level error logs.
|
|
89
|
-
|
|
90
|
-
---
|
|
21
|
+
- Read every file enumerated under `[Required reading]` or `## Inputs` completely. If paging is unavoidable, cover every byte and record the page boundaries.
|
|
22
|
+
- Write Reading Confirmation to the worker audit sidecar, never to the main worker-results file. A `## 0. Reading Confirmation` heading in the main result is invalid.
|
|
23
|
+
- Allowlist reads to prompt-enumerated paths and evidence paths a finding must cite. Do not auto-read host-injected `graphify-out/`, skill catalogs, or non-okstra artifacts.
|
|
24
|
+
- Resolve every `.okstra/...` path against `**Project Root:**`, including when a worktree is present.
|
|
91
25
|
|
|
92
26
|
## Anchor headers (lead-injected, BLOCKING)
|
|
93
27
|
|
|
94
|
-
Every initial
|
|
28
|
+
Every initial analysis prompt begins with these generated anchors in this exact order, before any other content:
|
|
95
29
|
|
|
96
|
-
1. `**Project Root:** <absolute-path>`
|
|
30
|
+
1. `**Project Root:** <absolute-path>`
|
|
97
31
|
2. `**Prompt History Path:** <project-relative-path>`
|
|
98
|
-
3. `**Result Path:** <project-relative-path>`
|
|
99
|
-
4. `Assigned worker prompt history path: <absolute-path>`
|
|
100
|
-
5. `**Worker Preamble Path:** <absolute-path>` —
|
|
101
|
-
6. `**
|
|
102
|
-
7. `**Errors log path:** <absolute-path>`
|
|
103
|
-
8. `**Errors sidecar path:** <absolute-path>`
|
|
104
|
-
9. `**Read scope:**
|
|
105
|
-
|
|
106
|
-
**Exception — reverify dispatches.** A Phase 5.5 re-verification prompt (its `**Prompt History Path:**` carries a `-reverify-r<N>-` segment) deliberately omits anchor 5 and adds a `**Model:**` line — lightweight mode reads neither this file nor the implementation-only preflight pack. The two errors-path anchors are NOT omitted; that gate applies to reverify prompts unchanged. The reverify anchor set is owned by `prompts/lead/convergence.md` "Required reverify-prompt anchor headers".
|
|
107
|
-
|
|
108
|
-
For the **implementation phase** specifically, the dispatched prompt MUST also include:
|
|
109
|
-
|
|
110
|
-
- `**Worktree:** <absolute-path>` — the task worktree path.
|
|
111
|
-
- `cwd for every mutating command: <absolute-path>` — same as Worktree path; used by codex / antigravity wrappers as `--add-dir` / `--include-directories`.
|
|
112
|
-
|
|
113
|
-
For the **final-verification phase** specifically, the dispatched prompt MUST include the compact identity of the canonical verification-target sidecar so every analyser verifies the SAME target the lead captured at the entry gate:
|
|
114
|
-
|
|
115
|
-
- `**Worktree:** <absolute-path>` — the checkout under verification (read-only).
|
|
116
|
-
- `**Verification scope:** <whole-task|single-stage>` — the selected verification mode.
|
|
117
|
-
- `**Verification base ref:** <base-ref>` — the implementation base for the diff.
|
|
118
|
-
- `**Verification head ref:** <head-ref>` — the exact delivered revision under verification.
|
|
119
|
-
- `**Verification target path:** <project-relative-path>` — the canonical `instruction-set/verification-target.md` sidecar containing stages, source reports, and the complete captured diff stat.
|
|
120
|
-
- `**Verification target digest:** sha256:<digest>` — the digest over the normalized snapshot body.
|
|
121
|
-
|
|
122
|
-
Read the sidecar on demand when the full stage/report mapping or diff stat is needed. Do not copy its `Verification diff stat` block into the dispatch prompt.
|
|
123
|
-
|
|
124
|
-
The initial analysis prompt may contain exactly one `## Run-specific directive` section only when the run has a shared delta not already captured by the packet. The section applies unchanged to every selected analysis worker and is limited to 40 nonblank lines. If it would be longer, the lead writes the shared material into the instruction set and adds its common reference to `analysis-packet.md`; workers must not accept provider-, model-, or worker-specific verification scopes.
|
|
125
|
-
|
|
126
|
-
For the **improvement-discovery phase** specifically, the dispatched prompt MUST also include the resolved-scope log the lead wrote during Phase 1.5, so workers key off an explicit absolute path instead of re-deriving the run directory:
|
|
127
|
-
|
|
128
|
-
- `**Phase 1.5 Grilling Log:** <absolute-path>` — the lead's Phase 1.5 reflect-back log (`<RUN_DIR>/state/phase-1.5-grilling.md`, written before dispatch). Its `Resolved scope` / `Resolved lenses` blocks are the authoritative scope and lens definition for this run. Read the file at this absolute path; do NOT re-derive it from `<RUN_DIR>`, and do NOT re-interpret the brief's raw `scan-scope` / `priority-lenses`. The presence of this anchor is itself the signal that this is an improvement-discovery run — no separate task-type detection is required.
|
|
129
|
-
|
|
130
|
-
### Path anchoring (BLOCKING — the single largest source of worker tool-failures)
|
|
131
|
-
|
|
132
|
-
Every `.okstra/...` path is anchored at `**Project Root:**`, **never** at your cwd. When your run has a worktree (`**Worktree:**` is present), your cwd is that worktree — and the stage/task worktree does **not** contain the project's `.okstra/` directory. So a bare `Read`/`cat .okstra/tasks/...` from cwd resolves inside the worktree and fails "no such file". This is the same trap whether the path came from the prompt, a manifest field, a prior report's citation, or your own reasoning.
|
|
32
|
+
3. `**Result Path:** <project-relative-path>`
|
|
33
|
+
4. `Assigned worker prompt history path: <absolute-path>`
|
|
34
|
+
5. `**Worker Preamble Path:** <absolute-path>` — selects this analysis preamble.
|
|
35
|
+
6. `**Worker Error Contract Path:** <absolute-path>` — shared by every initial audience.
|
|
36
|
+
7. `**Errors log path:** <absolute-path>`
|
|
37
|
+
8. `**Errors sidecar path:** <absolute-path>`
|
|
38
|
+
9. `**Read scope:** <allowlist>`
|
|
133
39
|
|
|
134
|
-
-
|
|
135
|
-
- Mutating build/test commands still run from the worktree cwd (`cd <Worktree> && ...`) — but reads of okstra artifacts (`.okstra/**`) always go through `<Project Root>`, even while cwd is the worktree.
|
|
136
|
-
- If a `.okstra/...` read fails "no such file / does not exist in the worktree", do not retry the same relative path — re-anchor it to `<Project Root>` and read the absolute path.
|
|
40
|
+
`final-verification` additionally carries its six verification-target anchors. `improvement-discovery` carries `**Phase 1.5 Grilling Log:**`. Reverify prompts are lightweight and do not use this preamble.
|
|
137
41
|
|
|
138
|
-
|
|
42
|
+
## Worker output sections
|
|
139
43
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
**Authoritative source.** This preamble section is the canonical worker output contract. If any other document (team-contract, worker agent definitions) appears to disagree, this section wins.
|
|
143
|
-
|
|
144
|
-
### Result Frontmatter (mandatory, precedes Section 1)
|
|
145
|
-
|
|
146
|
-
Every worker result file MUST begin with a YAML frontmatter block. For analysis workers, values are sourced from `analysis-packet.md` frontmatter; fall back to `analysis-material.md` or `task-brief.md` only if the packet is missing a field. Report-writer can use `analysis-material.md` / `task-brief.md` as before. Copy values verbatim; do NOT regenerate them. Only `workerId` and `title` are worker-specific.
|
|
147
|
-
|
|
148
|
-
```yaml
|
|
149
|
-
---
|
|
150
|
-
title: OKSTRA <Worker Role> Result - <task-key>
|
|
151
|
-
id: "<task-key with ':' replaced by '-'>"
|
|
152
|
-
aliases: ["<id>-<task-type>"]
|
|
153
|
-
tags: ["worker-result", "<task-type>"]
|
|
154
|
-
taskType: "<task-type>"
|
|
155
|
-
workerId: "<claude|codex|antigravity|report-writer>"
|
|
156
|
-
task-id: "<task-id>"
|
|
157
|
-
task-group: "<task-group>"
|
|
158
|
-
project-id: "<project-id>"
|
|
159
|
-
date: <YYYY-MM-DD>
|
|
160
|
-
---
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
Concrete example for a `claude-worker` result on task-key `fontsninja-classifier-v2:DEV-9388:DEV-9429` and task-type `implementation`:
|
|
164
|
-
|
|
165
|
-
```yaml
|
|
166
|
-
---
|
|
167
|
-
title: OKSTRA Claude Worker Result - fontsninja-classifier-v2:DEV-9388:DEV-9429
|
|
168
|
-
id: "fontsninja-classifier-v2-DEV-9388-DEV-9429"
|
|
169
|
-
aliases: ["fontsninja-classifier-v2-DEV-9388-DEV-9429-implementation"]
|
|
170
|
-
tags: ["worker-result", "implementation"]
|
|
171
|
-
taskType: "implementation"
|
|
172
|
-
workerId: "claude"
|
|
173
|
-
task-id: "DEV-9429"
|
|
174
|
-
task-group: "DEV-9388"
|
|
175
|
-
project-id: "fontsninja-classifier-v2"
|
|
176
|
-
date: 2026-05-15
|
|
177
|
-
---
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
Rules:
|
|
181
|
-
- `id` is the run's `task-key` with `:` replaced by `-`. It is a scalar string, NOT an array.
|
|
182
|
-
- `aliases` is a YAML array containing a single value `"<id>-<task-type>"`.
|
|
183
|
-
- `taskType` mirrors the run's task type (`requirements-discovery`, `error-analysis`, `implementation-planning`, `implementation`, `final-verification`, `release-handoff`).
|
|
184
|
-
- `workerId` identifies which worker produced the file. Required values: `claude` / `codex` / `antigravity` / `report-writer`.
|
|
185
|
-
- Other fields (`task-id`, `task-group`, `project-id`, `date`) MUST match the input files' frontmatter exactly. If the input frontmatter is missing or unreadable, the worker MUST record a `tool-failure` and stop instead of guessing.
|
|
186
|
-
|
|
187
|
-
The same frontmatter contract applies to the `Report writer worker`'s final-report file — the report-writer copies these values from its inputs and only swaps `workerId` to `report-writer`.
|
|
188
|
-
|
|
189
|
-
### Worker Result Header Standard
|
|
190
|
-
|
|
191
|
-
Every worker result file under `worker-results/` must begin with a standardized header:
|
|
192
|
-
|
|
193
|
-
```markdown
|
|
194
|
-
# <Role> Analysis — <task-key>
|
|
195
|
-
|
|
196
|
-
**Target:** <path or scope> <!-- OPTIONAL: include when the run is scoped to a specific file/module -->
|
|
197
|
-
**Model:** <Role>, <AI model>
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
Task-type and date are **not** repeated in this human header — the YAML frontmatter (`taskType`, `date`) is the single source for both (and the copy Obsidian indexes). The `Target:` line is optional — include it when the run is scoped to a specific path or module, omit it for whole-project runs; when present, place it between the title and the `Model:` line.
|
|
201
|
-
|
|
202
|
-
Example (Codex / Report-writer headers are identical modulo the role name and model id):
|
|
203
|
-
|
|
204
|
-
```markdown
|
|
205
|
-
# Claude Worker Analysis — jobs:tasks:8852
|
|
206
|
-
|
|
207
|
-
**Target:** server/auth.ts
|
|
208
|
-
**Model:** Claude worker, opus
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
Use the actual model identifier recorded in team-state (never invent a model ID — read it from `resultContract.requiredWorkerRoles[*].modelExecutionValue` or the tool response metadata).
|
|
212
|
-
|
|
213
|
-
The header is followed by the standard worker output contract sections (Findings, Missing Information, etc.).
|
|
214
|
-
|
|
215
|
-
### Section ordering
|
|
216
|
-
|
|
217
|
-
A successful worker result must include the following sections in this exact order, beneath the frontmatter block:
|
|
44
|
+
Every analysis result starts with YAML frontmatter containing the task identity and `workerId`, followed by a header with the actual `**Model:**` value. Then emit these sections in exact order:
|
|
218
45
|
|
|
219
46
|
1. Findings
|
|
220
47
|
2. Missing Information or Assumptions
|
|
221
48
|
3. Safe or Reasonable Areas
|
|
222
49
|
4. Uncertain Points
|
|
223
50
|
5. Recommended Next Actions
|
|
224
|
-
6.
|
|
225
|
-
|
|
226
|
-
Every item in sections 1–5 (and any section 6) MUST carry a worker-internal item ID unique within the file. Lead synthesis preserves these as `<worker>:<item-id>` in `Source items (worker:item)` columns.
|
|
227
|
-
|
|
228
|
-
**Sections 1–5 are the common core.** Every analysis worker (Claude / Codex / Antigravity) MUST cover the same set of dimensions in sections 1–5 — feasibility, requirement interpretation, hidden assumptions, alternatives, and execution risk — regardless of which model is producing the result. The point of running three models is to triangulate the same answer space, not to partition it. A worker that produces "Findings" populated only with items from its own lens (e.g. Codex only listing implementation-feasibility findings) is in breach of contract; convergence will treat coverage gaps as `verification-error`.
|
|
229
|
-
|
|
230
|
-
**Section 6 is the only legal home for specialization.** When the worker has a depth-of-perspective contribution that genuinely sits outside the common core (e.g. a Codex-specific stack-trace decomposition, a Claude-specific assumption-chain teardown, a Antigravity-specific alternative-architecture sketch), put it there. Lead and convergence treat Section 6 as additive context, not as input to consensus measurement.
|
|
231
|
-
|
|
232
|
-
Code evidence must include file paths and line numbers.
|
|
233
|
-
|
|
234
|
-
### Ticket Tagging (mandatory for sections 1–5)
|
|
235
|
-
|
|
236
|
-
Every item in sections 1–5 MUST be tagged with the ticket(s) it relates to. This applies whenever the run's task type is `requirements-discovery`, `error-analysis`, `implementation-planning`, or `implementation`.
|
|
237
|
-
|
|
238
|
-
- **Table-form items**: include a `Ticket ID` column. The column is placed immediately after the row-ID column (e.g. after `F-001`, `M-001`).
|
|
239
|
-
- **Bullet / numbered-list items**: prepend `[TICKETID: <id>]` to the item title, immediately after the row ID and before the body text. Example: `- F-001 [TICKETID: TICKET-123] — <summary> (path:line)`.
|
|
240
|
-
- **Section headers in the final report** (e.g. `### 5.5.3 Recommended Option`): append `[TICKETID: <id>]` to the header when the section is scoped to a specific ticket. Headers that span all tickets in the run omit the tag.
|
|
241
|
-
|
|
242
|
-
Ticket ID fill rule (in order):
|
|
243
|
-
|
|
244
|
-
1. Use the `Issue / Ticket` value from the run's input template.
|
|
245
|
-
2. If empty, fall back to the `Task ID` value (no prefix; write `8852` not `task:8852`).
|
|
246
|
-
3. If both are absent, write `unknown`. This is allowed but signals an input-template defect — the worker SHOULD also record a `Missing Information` item noting the absent identifier.
|
|
247
|
-
4. When a single item maps to multiple tickets, separate them with commas: `TICKET-123, TICKET-456`. Ticket IDs containing commas are not supported.
|
|
248
|
-
|
|
249
|
-
Workers MUST apply these rules to every item in sections 1–5. Lead and report-writer MUST preserve the tagging when carrying worker findings into the final report.
|
|
250
|
-
|
|
251
|
-
For phases other than the four listed above (e.g. `release-handoff`, `final-verification`), ticket tagging is optional.
|
|
51
|
+
6. Specialization Lens (optional, additive only)
|
|
252
52
|
|
|
253
|
-
|
|
53
|
+
Every item has a worker-local ID and file:line evidence where code evidence exists. Sections 1–5 are the common core: feasibility, requirement interpretation, hidden assumptions, alternatives, and execution risk. Section 6 is the only legal home for specialization and is not consensus input.
|
|
254
54
|
|
|
255
|
-
|
|
55
|
+
### Ticket Tagging
|
|
256
56
|
|
|
257
|
-
|
|
258
|
-
**Model:** <Role>, <modelExecutionValue>
|
|
259
|
-
```
|
|
57
|
+
For `requirements-discovery`, `error-analysis`, and `implementation-planning`, tag every section 1–5 item with its related ticket. Use `Issue / Ticket`, fall back to Task ID, then `unknown`; comma-separate multiple tickets.
|
|
260
58
|
|
|
261
|
-
|
|
59
|
+
## Return message to the lead
|
|
262
60
|
|
|
263
|
-
|
|
61
|
+
Begin the inline return with the model identity copied verbatim from the `**Model:** <Role>, <modelExecutionValue>` line in the prompt, followed by the status summary. Never invent or abbreviate the model.
|
|
264
62
|
|
|
265
|
-
|
|
63
|
+
## Writing style
|
|
266
64
|
|
|
267
|
-
|
|
268
|
-
- Do NOT render a technical term as its literal dictionary noun. Use the term a developer actually says:
|
|
269
|
-
- `authoritative` → render it by its domain sense — "the value that takes precedence" / "the canonical value" — never by the bare dictionary noun for "authority".
|
|
270
|
-
- e.g. "overlays this row as authoritative" → phrase it as "overwrites this row as the definitive value", never as a word-for-word "authority" calque.
|
|
271
|
-
- Self-check before emitting any Korean sentence: if it reads like an awkward word-for-word translation, rewrite it by meaning. Confident-but-unreadable direct translation is a defect.
|
|
65
|
+
Translate meaning rather than dictionary words. Keep identifiers, paths, symbols, model names, CLI flags, and status tokens in English. Rewrite awkward word-for-word Korean before returning.
|
|
@@ -123,12 +123,20 @@ if not prompt_relative:
|
|
|
123
123
|
|
|
124
124
|
prompt_path = project_root / prompt_relative
|
|
125
125
|
prompt_path.parent.mkdir(parents=True, exist_ok=True)
|
|
126
|
+
artifacts = task_manifest.get("artifacts", {})
|
|
127
|
+
analysis_packet_path = (
|
|
128
|
+
str(artifacts.get("analysisPacketPath", "")).strip()
|
|
129
|
+
if isinstance(artifacts, dict)
|
|
130
|
+
else ""
|
|
131
|
+
)
|
|
126
132
|
prompt_path.write_text(
|
|
127
133
|
"\n".join(
|
|
128
134
|
[
|
|
129
|
-
|
|
130
|
-
"",
|
|
135
|
+
"**Worker Error Contract Path:** /okstra/templates/worker-error-contract.md",
|
|
131
136
|
f"Assigned worker prompt history path: {prompt_relative}",
|
|
137
|
+
f"- Primary analysis packet: `{analysis_packet_path}`",
|
|
138
|
+
"",
|
|
139
|
+
"# Initial Analysis Prompt",
|
|
132
140
|
f"Task Key: {task_manifest.get('taskKey', '')}",
|
|
133
141
|
"Validation fixture prompt body.",
|
|
134
142
|
]
|
|
@@ -213,17 +221,24 @@ for worker in team_state.get("workers", []):
|
|
|
213
221
|
if prompt_relative and worker_id != omitted_worker_id:
|
|
214
222
|
prompt_path = project_root / prompt_relative
|
|
215
223
|
prompt_path.parent.mkdir(parents=True, exist_ok=True)
|
|
216
|
-
|
|
217
|
-
"
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
"Validation fixture prompt body.",
|
|
224
|
-
]
|
|
224
|
+
prompt_lines = [
|
|
225
|
+
"**Worker Error Contract Path:** /okstra/templates/worker-error-contract.md",
|
|
226
|
+
f"Assigned worker prompt history path: {prompt_relative}",
|
|
227
|
+
]
|
|
228
|
+
if worker_id != "report-writer":
|
|
229
|
+
prompt_lines.append(
|
|
230
|
+
f"- Primary analysis packet: `{run_manifest.get('analysisPacketPath', '')}`"
|
|
225
231
|
)
|
|
226
|
-
|
|
232
|
+
prompt_lines.extend([
|
|
233
|
+
"",
|
|
234
|
+
"# Initial Analysis Prompt",
|
|
235
|
+
f"Task Key: {task_manifest.get('taskKey', '')}",
|
|
236
|
+
"Validation fixture prompt body.",
|
|
237
|
+
])
|
|
238
|
+
else:
|
|
239
|
+
prompt_lines.extend(["", "# Report Writer Prompt"])
|
|
240
|
+
prompt_path.write_text(
|
|
241
|
+
"\n".join(prompt_lines) + "\n"
|
|
227
242
|
)
|
|
228
243
|
|
|
229
244
|
result_relative = str(worker.get("resultPath", "")).strip()
|