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
|
@@ -5,6 +5,12 @@ from pathlib import Path
|
|
|
5
5
|
from typing import Any, Mapping
|
|
6
6
|
|
|
7
7
|
from .paths import okstra_home
|
|
8
|
+
from .worker_prompt_policy import (
|
|
9
|
+
PromptPlan,
|
|
10
|
+
WORKER_ERROR_CONTRACT_FILENAME,
|
|
11
|
+
WORKER_PREAMBLE_FILENAME_BY_AUDIENCE,
|
|
12
|
+
resolve_prompt_plan_for_manifest,
|
|
13
|
+
)
|
|
8
14
|
|
|
9
15
|
|
|
10
16
|
class WorkerPromptHeaderError(Exception):
|
|
@@ -36,30 +42,42 @@ def worker_prompt_headers(
|
|
|
36
42
|
prompt_rel: str,
|
|
37
43
|
result_rel: str,
|
|
38
44
|
worker_id: str,
|
|
45
|
+
dispatch_kind: str,
|
|
39
46
|
manifest: Mapping[str, Any],
|
|
40
47
|
active_context: Mapping[str, Any],
|
|
41
48
|
) -> list[str]:
|
|
42
49
|
"""Render the team-contract worker prompt anchor headers."""
|
|
43
50
|
prompt_path = _resolve_project_path(project_root, prompt_rel)
|
|
51
|
+
errors_log_path = _errors_log_path(project_root, manifest, active_context)
|
|
52
|
+
errors_sidecar_path = _worker_errors_sidecar_path(
|
|
53
|
+
project_root,
|
|
54
|
+
manifest,
|
|
55
|
+
active_context,
|
|
56
|
+
worker_id,
|
|
57
|
+
)
|
|
58
|
+
plan = _prompt_plan(manifest, worker_id, dispatch_kind)
|
|
44
59
|
headers = [
|
|
45
60
|
f"**Project Root:** {project_root}",
|
|
46
61
|
f"**Prompt History Path:** {prompt_rel}",
|
|
47
62
|
f"**Result Path:** {result_rel}",
|
|
48
63
|
f"Assigned worker prompt history path: {prompt_path}",
|
|
49
|
-
f"**Worker Preamble Path:** {_worker_preamble_path()}",
|
|
64
|
+
f"**Worker Preamble Path:** {_worker_preamble_path(plan, active_context)}",
|
|
65
|
+
f"**Worker Error Contract Path:** {_worker_error_contract_path(active_context)}",
|
|
50
66
|
]
|
|
51
|
-
if
|
|
67
|
+
if plan.allow_coding_preflight:
|
|
52
68
|
headers.append(
|
|
53
69
|
f"**Coding preflight pack:** {_coding_preflight_pack_path(active_context)}"
|
|
54
70
|
)
|
|
55
71
|
headers.extend([
|
|
56
|
-
f"**Errors log path:** {
|
|
57
|
-
|
|
58
|
-
f"**Errors sidecar path:** "
|
|
59
|
-
f"{_worker_errors_sidecar_path(project_root, manifest, active_context, worker_id)}"
|
|
60
|
-
),
|
|
72
|
+
f"**Errors log path:** {errors_log_path}",
|
|
73
|
+
f"**Errors sidecar path:** {errors_sidecar_path}",
|
|
61
74
|
READ_SCOPE_HEADER,
|
|
62
75
|
])
|
|
76
|
+
if _string_value(manifest.get("taskType")) == "improvement-discovery":
|
|
77
|
+
headers.append(
|
|
78
|
+
f"**Phase 1.5 Grilling Log:** "
|
|
79
|
+
f"{_improvement_grilling_log_path(project_root, manifest)}"
|
|
80
|
+
)
|
|
63
81
|
if _string_value(manifest.get("taskType")) == "final-verification":
|
|
64
82
|
headers.extend(_final_verification_target_headers(active_context))
|
|
65
83
|
return headers
|
|
@@ -86,8 +104,31 @@ def _final_verification_target_headers(
|
|
|
86
104
|
]
|
|
87
105
|
|
|
88
106
|
|
|
89
|
-
def _worker_preamble_path(
|
|
90
|
-
|
|
107
|
+
def _worker_preamble_path(
|
|
108
|
+
plan: PromptPlan,
|
|
109
|
+
active_context: Mapping[str, Any],
|
|
110
|
+
) -> Path:
|
|
111
|
+
runtime_resources = active_context.get("runtimeResources")
|
|
112
|
+
if isinstance(runtime_resources, Mapping):
|
|
113
|
+
paths = runtime_resources.get("workerPreamblePathByAudience")
|
|
114
|
+
if isinstance(paths, Mapping):
|
|
115
|
+
value = _string_value(paths.get(plan.audience))
|
|
116
|
+
if value:
|
|
117
|
+
return Path(value)
|
|
118
|
+
filename = WORKER_PREAMBLE_FILENAME_BY_AUDIENCE.get(
|
|
119
|
+
plan.audience,
|
|
120
|
+
WORKER_PREAMBLE_FILENAME_BY_AUDIENCE["analysis"],
|
|
121
|
+
)
|
|
122
|
+
return okstra_home() / "templates" / filename
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _worker_error_contract_path(active_context: Mapping[str, Any]) -> Path:
|
|
126
|
+
runtime_resources = active_context.get("runtimeResources")
|
|
127
|
+
if isinstance(runtime_resources, Mapping):
|
|
128
|
+
value = _string_value(runtime_resources.get("workerErrorContractPath"))
|
|
129
|
+
if value:
|
|
130
|
+
return Path(value)
|
|
131
|
+
return okstra_home() / "templates" / WORKER_ERROR_CONTRACT_FILENAME
|
|
91
132
|
|
|
92
133
|
|
|
93
134
|
def _coding_preflight_pack_path(active_context: Mapping[str, Any]) -> Path:
|
|
@@ -99,6 +140,35 @@ def _coding_preflight_pack_path(active_context: Mapping[str, Any]) -> Path:
|
|
|
99
140
|
return okstra_home() / "prompts" / "coding-preflight"
|
|
100
141
|
|
|
101
142
|
|
|
143
|
+
def _prompt_plan(
|
|
144
|
+
manifest: Mapping[str, Any],
|
|
145
|
+
worker_id: str,
|
|
146
|
+
dispatch_kind: str,
|
|
147
|
+
) -> PromptPlan:
|
|
148
|
+
try:
|
|
149
|
+
return resolve_prompt_plan_for_manifest(
|
|
150
|
+
manifest=manifest,
|
|
151
|
+
worker_id=worker_id,
|
|
152
|
+
dispatch_kind=dispatch_kind,
|
|
153
|
+
)
|
|
154
|
+
except ValueError as exc:
|
|
155
|
+
raise WorkerPromptHeaderError(str(exc)) from exc
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _improvement_grilling_log_path(
|
|
159
|
+
project_root: Path,
|
|
160
|
+
manifest: Mapping[str, Any],
|
|
161
|
+
) -> Path:
|
|
162
|
+
path = (
|
|
163
|
+
_run_directory_path(project_root, manifest)
|
|
164
|
+
/ "state"
|
|
165
|
+
/ "phase-1.5-grilling.md"
|
|
166
|
+
)
|
|
167
|
+
if not path.is_file():
|
|
168
|
+
raise WorkerPromptHeaderError(f"Phase 1.5 grilling log not found: {path}")
|
|
169
|
+
return path
|
|
170
|
+
|
|
171
|
+
|
|
102
172
|
def _errors_log_path(
|
|
103
173
|
project_root: Path,
|
|
104
174
|
manifest: Mapping[str, Any],
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""Resolve worker prompt requirements from functional audience."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Any, Literal, Mapping
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
PromptAudience = Literal[
|
|
9
|
+
"analysis",
|
|
10
|
+
"implementation-executor",
|
|
11
|
+
"implementation-verifier",
|
|
12
|
+
"report-writer",
|
|
13
|
+
"reverify",
|
|
14
|
+
"lead-only",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
FINAL_VERIFICATION_HEADERS = (
|
|
18
|
+
"**Worktree:**",
|
|
19
|
+
"**Verification scope:**",
|
|
20
|
+
"**Verification base ref:**",
|
|
21
|
+
"**Verification head ref:**",
|
|
22
|
+
"**Verification target path:**",
|
|
23
|
+
"**Verification target digest:**",
|
|
24
|
+
)
|
|
25
|
+
SUPPORTED_TASK_TYPES = frozenset({
|
|
26
|
+
"requirements-discovery",
|
|
27
|
+
"error-analysis",
|
|
28
|
+
"implementation-planning",
|
|
29
|
+
"improvement-discovery",
|
|
30
|
+
"implementation",
|
|
31
|
+
"final-verification",
|
|
32
|
+
"release-handoff",
|
|
33
|
+
})
|
|
34
|
+
WORKER_PREAMBLE_FILENAME_BY_AUDIENCE = {
|
|
35
|
+
"analysis": "worker-prompt-preamble.md",
|
|
36
|
+
"implementation-executor": "implementation-worker-preamble.md",
|
|
37
|
+
"implementation-verifier": "implementation-worker-preamble.md",
|
|
38
|
+
"report-writer": "report-writer-prompt-preamble.md",
|
|
39
|
+
}
|
|
40
|
+
WORKER_ERROR_CONTRACT_FILENAME = "worker-error-contract.md"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True)
|
|
44
|
+
class PromptPlan:
|
|
45
|
+
audience: PromptAudience
|
|
46
|
+
equality_group: str | None
|
|
47
|
+
packet_only: bool
|
|
48
|
+
allow_coding_preflight: bool
|
|
49
|
+
required_headers: tuple[str, ...]
|
|
50
|
+
max_body_lines: int | None
|
|
51
|
+
max_directive_lines: int | None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def resolve_prompt_plan(
|
|
55
|
+
*,
|
|
56
|
+
task_type: str,
|
|
57
|
+
worker_id: str,
|
|
58
|
+
executor_worker_id: str | None,
|
|
59
|
+
dispatch_kind: str,
|
|
60
|
+
) -> PromptPlan:
|
|
61
|
+
"""Resolve prompt policy without consulting provider or model identity."""
|
|
62
|
+
if task_type not in SUPPORTED_TASK_TYPES:
|
|
63
|
+
raise ValueError(f"unsupported task type: {task_type}")
|
|
64
|
+
if task_type == "release-handoff":
|
|
65
|
+
return _plan("lead-only")
|
|
66
|
+
if not worker_id.strip():
|
|
67
|
+
raise ValueError("worker ID is required")
|
|
68
|
+
if dispatch_kind.startswith("reverify-r"):
|
|
69
|
+
return _plan("reverify")
|
|
70
|
+
if task_type == "implementation" and not executor_worker_id:
|
|
71
|
+
raise ValueError("implementation executor worker ID is required")
|
|
72
|
+
if worker_id == "report-writer":
|
|
73
|
+
return _plan("report-writer")
|
|
74
|
+
if task_type == "implementation" and worker_id == executor_worker_id:
|
|
75
|
+
return _plan(
|
|
76
|
+
"implementation-executor",
|
|
77
|
+
allow_coding_preflight=True,
|
|
78
|
+
required_headers=("**Worktree:**",),
|
|
79
|
+
)
|
|
80
|
+
if task_type == "implementation":
|
|
81
|
+
return _plan(
|
|
82
|
+
"implementation-verifier",
|
|
83
|
+
equality_group="implementation-verifier-core",
|
|
84
|
+
allow_coding_preflight=True,
|
|
85
|
+
required_headers=("**Worktree:**",),
|
|
86
|
+
)
|
|
87
|
+
if task_type == "final-verification":
|
|
88
|
+
return _plan(
|
|
89
|
+
"analysis",
|
|
90
|
+
equality_group="analysis-core",
|
|
91
|
+
packet_only=True,
|
|
92
|
+
required_headers=FINAL_VERIFICATION_HEADERS,
|
|
93
|
+
max_body_lines=96,
|
|
94
|
+
max_directive_lines=40,
|
|
95
|
+
)
|
|
96
|
+
if task_type == "improvement-discovery":
|
|
97
|
+
return _plan(
|
|
98
|
+
"analysis",
|
|
99
|
+
equality_group="analysis-core",
|
|
100
|
+
packet_only=True,
|
|
101
|
+
required_headers=("**Phase 1.5 Grilling Log:**",),
|
|
102
|
+
)
|
|
103
|
+
return _plan("analysis", equality_group="analysis-core", packet_only=True)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def resolve_prompt_plan_for_manifest(
|
|
107
|
+
*,
|
|
108
|
+
manifest: Mapping[str, Any],
|
|
109
|
+
worker_id: str,
|
|
110
|
+
dispatch_kind: str,
|
|
111
|
+
) -> PromptPlan:
|
|
112
|
+
"""Resolve policy from canonical task and executor manifest fields."""
|
|
113
|
+
task_type = _required_string(manifest, "taskType")
|
|
114
|
+
return resolve_prompt_plan(
|
|
115
|
+
task_type=task_type,
|
|
116
|
+
worker_id=worker_id,
|
|
117
|
+
executor_worker_id=_executor_worker_id(manifest),
|
|
118
|
+
dispatch_kind=dispatch_kind,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _plan(
|
|
123
|
+
audience: PromptAudience,
|
|
124
|
+
*,
|
|
125
|
+
equality_group: str | None = None,
|
|
126
|
+
packet_only: bool = False,
|
|
127
|
+
allow_coding_preflight: bool = False,
|
|
128
|
+
required_headers: tuple[str, ...] = (),
|
|
129
|
+
max_body_lines: int | None = None,
|
|
130
|
+
max_directive_lines: int | None = None,
|
|
131
|
+
) -> PromptPlan:
|
|
132
|
+
return PromptPlan(
|
|
133
|
+
audience=audience,
|
|
134
|
+
equality_group=equality_group,
|
|
135
|
+
packet_only=packet_only,
|
|
136
|
+
allow_coding_preflight=allow_coding_preflight,
|
|
137
|
+
required_headers=required_headers,
|
|
138
|
+
max_body_lines=max_body_lines,
|
|
139
|
+
max_directive_lines=max_directive_lines,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _executor_worker_id(manifest: Mapping[str, Any]) -> str | None:
|
|
144
|
+
team_contract = manifest.get("teamContract")
|
|
145
|
+
if not isinstance(team_contract, Mapping):
|
|
146
|
+
return None
|
|
147
|
+
executor = team_contract.get("executor")
|
|
148
|
+
if not isinstance(executor, Mapping):
|
|
149
|
+
return None
|
|
150
|
+
provider = executor.get("provider")
|
|
151
|
+
return provider.strip() if isinstance(provider, str) and provider.strip() else None
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _required_string(payload: Mapping[str, Any], key: str) -> str:
|
|
155
|
+
value = payload.get(key)
|
|
156
|
+
if not isinstance(value, str) or not value.strip():
|
|
157
|
+
raise ValueError(f"missing required string field: {key}")
|
|
158
|
+
return value.strip()
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Implementation Worker Prompt Preamble (canonical)
|
|
2
|
+
|
|
3
|
+
This file is shared by the `implementation-executor` and `implementation-verifier` audiences. Read it end-to-end, then read the role sidecar enumerated by the prompt. Before work, also read the shared file named by `**Worker Error Contract Path:**`; error rules live only there.
|
|
4
|
+
|
|
5
|
+
## Operating standard (read before any output)
|
|
6
|
+
|
|
7
|
+
Work like a senior engineer who owns this result, not a commentator on it.
|
|
8
|
+
- Evidence over assertion — back every claim with a file:line, or mark it an explicit assumption. Never state the unverified as fact.
|
|
9
|
+
- Read before you reason — read each required input end to end; when you lack basis, write "insufficient evidence" instead of filling the gap plausibly.
|
|
10
|
+
- Shortest sound path — chase the most likely cause first; don't re-verify what is settled or pad with restatement.
|
|
11
|
+
- Decide, don't survey — when options exist, give the trade-off and one recommendation, not an exhaustive list.
|
|
12
|
+
- Fit what's here — match the surrounding code and prose; size the response to the request.
|
|
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.
|
|
14
|
+
|
|
15
|
+
## Required reading
|
|
16
|
+
|
|
17
|
+
- Read the implementation role sidecar named by the prompt end-to-end. The executor sidecar owns mutation behavior; the verifier sidecar owns read-only review behavior.
|
|
18
|
+
- Read `overview.md` and `clean-code.md` under `**Coding preflight pack:**`, then follow every matching language, framework, and architecture route before editing or verification.
|
|
19
|
+
- Read the approved implementation deliverable and any effective design-preparation block enumerated by the prompt.
|
|
20
|
+
|
|
21
|
+
## Worktree and command discipline
|
|
22
|
+
|
|
23
|
+
- `**Worktree:**` is the canonical checkout. Project commands run with that directory as cwd.
|
|
24
|
+
- `.okstra/**` artifacts remain anchored at `**Project Root:**`; the worktree may not contain them.
|
|
25
|
+
- Only the executor may mutate source files. Verifiers remain read-only except for okstra result/audit artifacts and project-declared QA commands.
|
|
26
|
+
- Execute the role sidecar's pre-write, post-write, QA, and return gates without substituting analysis Sections 1–6 or report-authoring instructions.
|
|
27
|
+
|
|
28
|
+
## Anchor headers
|
|
29
|
+
|
|
30
|
+
Every initial implementation prompt begins with these generated common anchors in this exact order, before its implementation-specific body:
|
|
31
|
+
|
|
32
|
+
1. `**Project Root:** <absolute-path>`
|
|
33
|
+
2. `**Prompt History Path:** <project-relative-path>`
|
|
34
|
+
3. `**Result Path:** <project-relative-path>`
|
|
35
|
+
4. `Assigned worker prompt history path: <absolute-path>`
|
|
36
|
+
5. `**Worker Preamble Path:** <absolute-path>`
|
|
37
|
+
6. `**Worker Error Contract Path:** <absolute-path>`
|
|
38
|
+
7. `**Coding preflight pack:** <absolute-path>`
|
|
39
|
+
8. `**Errors log path:** <absolute-path>`
|
|
40
|
+
9. `**Errors sidecar path:** <absolute-path>`
|
|
41
|
+
10. `**Read scope:** <allowlist>`
|
|
42
|
+
|
|
43
|
+
The implementation body additionally carries `**Worktree:**` and its role-sidecar inputs. Do not synthesize any missing path.
|
|
44
|
+
|
|
45
|
+
## Return message to the lead
|
|
46
|
+
|
|
47
|
+
Begin the inline return with the exact `**Model:** <Role>, <modelExecutionValue>` line from the prompt, followed by the role-sidecar status summary. Never invent or abbreviate the model.
|
|
48
|
+
|
|
49
|
+
## Writing style
|
|
50
|
+
|
|
51
|
+
Use concise evidence-backed prose. Keep identifiers, paths, symbols, model names, CLI flags, and status tokens in English. Translate meaning rather than dictionary words.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Operating Standard (canonical)
|
|
2
2
|
|
|
3
3
|
This file is the single source of truth for the operating standard injected into
|
|
4
|
-
every okstra agent. The "Common core" block below is inlined verbatim into
|
|
5
|
-
`templates
|
|
6
|
-
`prompts/lead/okstra-lead-contract.md` (lead). A unit test asserts
|
|
7
|
-
|
|
4
|
+
every okstra agent. The "Common core" block below is inlined verbatim into the
|
|
5
|
+
three audience preambles under `templates/` and
|
|
6
|
+
`prompts/lead/okstra-lead-contract.md` (lead). A unit test asserts every inlined
|
|
7
|
+
copy matches this core — update all copies together.
|
|
8
8
|
|
|
9
9
|
## Common core
|
|
10
10
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Report Writer Prompt Preamble (canonical)
|
|
2
|
+
|
|
3
|
+
This file is the audience-specific contract for `report-writer`. Read it end-to-end. Before work, also read the shared file named by `**Worker Error Contract Path:**`; error rules live only there.
|
|
4
|
+
|
|
5
|
+
## Operating standard (read before any output)
|
|
6
|
+
|
|
7
|
+
Work like a senior engineer who owns this result, not a commentator on it.
|
|
8
|
+
- Evidence over assertion — back every claim with a file:line, or mark it an explicit assumption. Never state the unverified as fact.
|
|
9
|
+
- Read before you reason — read each required input end to end; when you lack basis, write "insufficient evidence" instead of filling the gap plausibly.
|
|
10
|
+
- Shortest sound path — chase the most likely cause first; don't re-verify what is settled or pad with restatement.
|
|
11
|
+
- Decide, don't survey — when options exist, give the trade-off and one recommendation, not an exhaustive list.
|
|
12
|
+
- Fit what's here — match the surrounding code and prose; size the response to the request.
|
|
13
|
+
|
|
14
|
+
## Required reading
|
|
15
|
+
|
|
16
|
+
Read every input enumerated by the Phase 6 dispatch end-to-end: task/analysis inputs, worker results, convergence state, the instruction-set-local `final-report-template.md`, and the task-type excerpt `final-report-schema.json`. Do not pull the full repository template or schema when the scoped instruction-set copies are provided.
|
|
17
|
+
|
|
18
|
+
Write Reading Confirmation to the report-writer audit sidecar, not the rendered final report. Resolve `.okstra/**` paths against `**Project Root:**`.
|
|
19
|
+
|
|
20
|
+
## Report authoring handoff
|
|
21
|
+
|
|
22
|
+
- Author the data.json at `**Result Path:**` and the audit file at `**Worker Result Path:**`.
|
|
23
|
+
- Follow the task-type schema excerpt and Phase 6 report-writer contract. Do not perform independent analysis, edit source code, or load implementation coding-preflight resources.
|
|
24
|
+
- Invoke `okstra render-final-report <Result Path>` after writing data.json and verify the markdown sibling exists before returning.
|
|
25
|
+
- Preserve source item IDs, convergence classifications, round history, and unresolved dissent; do not recompute them from intuition.
|
|
26
|
+
|
|
27
|
+
## Anchor headers
|
|
28
|
+
|
|
29
|
+
The generated prompt selects this file through `**Worker Preamble Path:**` and includes `**Worker Error Contract Path:**`, error paths, and read scope. It never includes `**Coding preflight pack:**`.
|
|
30
|
+
|
|
31
|
+
## Return message to the lead
|
|
32
|
+
|
|
33
|
+
Begin the inline return with the exact `**Model:** Report writer worker, <modelExecutionValue>` line from the prompt, followed by the artifact status. Never invent or abbreviate the model.
|
|
34
|
+
|
|
35
|
+
## Writing style
|
|
36
|
+
|
|
37
|
+
Use concise reader-facing prose and honor the report language. Keep identifiers, paths, symbols, model names, CLI flags, and status tokens in English. Translate meaning rather than dictionary words.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Worker Error Contract (canonical)
|
|
2
|
+
|
|
3
|
+
This audience-neutral file is the single source of truth for every initial worker's error path, sidecar schema, and write protocol. Read it end-to-end from `**Worker Error Contract Path:**` before work.
|
|
4
|
+
|
|
5
|
+
## Error reporting
|
|
6
|
+
|
|
7
|
+
Record a tool call only when its failure blocked the step you intended. A non-zero exit code is NOT by itself a failure to record. Do not record an entry when:
|
|
8
|
+
|
|
9
|
+
- a search/probe exits non-zero solely because it found no matches and work proceeds unaffected;
|
|
10
|
+
- an optional / expected-absent path is absent and detecting absence was the purpose;
|
|
11
|
+
- output was truncated but a later read covered the content end-to-end.
|
|
12
|
+
|
|
13
|
+
If the non-zero exit changed nothing about what you could do next, it is normal. When in doubt, record the real blocker: under-recording a real blocker is worse than one noisy entry.
|
|
14
|
+
|
|
15
|
+
If the sidecar does not exist when a real failure occurs, create `{"schemaVersion": 1, "errors": []}` and append one entry.
|
|
16
|
+
|
|
17
|
+
### Entry schema
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"ts": "<ISO 8601 UTC>",
|
|
22
|
+
"phase": "<current okstra phase>",
|
|
23
|
+
"errorType": "tool-failure",
|
|
24
|
+
"command": "<failed command/tool signature>",
|
|
25
|
+
"commandKind": "bash | tool:Read | tool:Edit | mcp | ...",
|
|
26
|
+
"exitCode": null,
|
|
27
|
+
"durationMs": null,
|
|
28
|
+
"message": "<one-line human summary>",
|
|
29
|
+
"stderrExcerpt": null,
|
|
30
|
+
"context": null
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Rules
|
|
35
|
+
|
|
36
|
+
- Do not add `source`, `recordedAt`, `agent`, `agentRole`, `model`, or `taskKey`; the lead supplies them when merging the sidecar.
|
|
37
|
+
- The sidecar accepts only `errorType: "tool-failure"`. CLI wrappers write `cli-failure` directly to the run log; the lead records `contract-violation`.
|
|
38
|
+
- Continue after recording unless the failure makes the task impossible.
|
|
39
|
+
|
|
40
|
+
### Path extraction (BLOCKING)
|
|
41
|
+
|
|
42
|
+
Extract `**Errors log path:**` and `**Errors sidecar path:**` verbatim from the dispatch prompt. If either is absent, return the worker-specific `<SENTINEL_PREFIX>_ERRORS_PATH_MISSING` sentinel and stop. Never synthesize a path from a run-directory pattern.
|
|
43
|
+
|
|
44
|
+
## Path anchoring
|
|
45
|
+
|
|
46
|
+
Every `.okstra/...` path is anchored at `**Project Root:**`, never at cwd. A task or stage worktree does **not** contain the project's `.okstra/` directory. Mutating project commands may use `**Worktree:**`, but okstra artifact reads and error writes use absolute paths resolved from Project Root. If a relative read fails in a worktree, re-anchor it to `<Project Root>` instead of retrying the same path.
|