okstra 0.180.0 → 0.183.2
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/dist/cli-registry.mjs +16 -2
- package/dist/cli-registry.mjs.map +1 -1
- package/dist/commands/execute/render-bundle.d.mts +4 -2
- package/dist/commands/execute/render-bundle.mjs +46 -5
- package/dist/commands/execute/render-bundle.mjs.map +1 -1
- package/dist/commands/execute/run.mjs +11 -3
- package/dist/commands/execute/run.mjs.map +1 -1
- package/dist/commands/inspect/model-io.d.mts +1 -0
- package/dist/commands/inspect/model-io.mjs +25 -0
- package/dist/commands/inspect/model-io.mjs.map +1 -0
- package/dist/commands/inspect/stage-map.mjs +29 -8
- package/dist/commands/inspect/stage-map.mjs.map +1 -1
- package/dist/commands/inspect/task-list.mjs +52 -6
- package/dist/commands/inspect/task-list.mjs.map +1 -1
- package/dist/commands/inspect/user-response.mjs +14 -4
- package/dist/commands/inspect/user-response.mjs.map +1 -1
- package/dist/commands/lifecycle/check-project.d.mts +1 -0
- package/dist/commands/lifecycle/check-project.mjs +69 -50
- package/dist/commands/lifecycle/check-project.mjs.map +1 -1
- package/dist/commands/lifecycle/contract-check.d.mts +1 -0
- package/dist/commands/lifecycle/contract-check.mjs +18 -0
- package/dist/commands/lifecycle/contract-check.mjs.map +1 -0
- package/dist/commands/lifecycle/preflight.mjs +154 -51
- package/dist/commands/lifecycle/preflight.mjs.map +1 -1
- package/dist/commands/pr/pr.d.mts +1 -0
- package/dist/commands/pr/pr.mjs +19 -1
- package/dist/commands/pr/pr.mjs.map +1 -1
- package/dist/commands/report/agent-activity.mjs +2 -2
- package/dist/commands/report/translate.mjs +3 -0
- package/dist/commands/report/translate.mjs.map +1 -1
- package/dist/lib/host-registry-client.mjs +13 -9
- package/dist/lib/host-registry-client.mjs.map +1 -1
- package/docs/architecture.md +11 -0
- package/docs/cli.md +26 -13
- package/docs/container.md +6 -4
- package/docs/contributor-change-matrix.md +1 -1
- package/docs/for-ai/README.md +2 -2
- package/docs/for-ai/skills/okstra-brief-gen.md +5 -3
- package/docs/for-ai/skills/okstra-code-review.md +4 -4
- package/docs/for-ai/skills/okstra-container-build.md +20 -17
- package/docs/for-ai/skills/okstra-inspect.md +20 -23
- package/docs/for-ai/skills/okstra-manager.md +19 -18
- package/docs/for-ai/skills/okstra-memory.md +2 -2
- package/docs/for-ai/skills/okstra-pr-gen.md +3 -3
- package/docs/for-ai/skills/okstra-rollup.md +14 -13
- package/docs/for-ai/skills/okstra-run.md +7 -3
- package/docs/for-ai/skills/okstra-schedule-gen.md +15 -18
- package/docs/for-ai/skills/okstra-setup.md +7 -7
- package/docs/for-ai/skills/okstra-usage.md +5 -4
- package/docs/for-ai/skills/okstra-user-response.md +50 -32
- package/docs/project-structure-overview.md +29 -26
- package/docs/task-process/implementation.md +7 -4
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/claude-worker.md +4 -4
- package/runtime/agents/workers/report-writer-worker.md +3 -3
- package/runtime/agents/workers/translator-worker.md +5 -13
- package/runtime/bin/okstra-error-log.py +51 -11
- package/runtime/bin/okstra-report-translate.py +210 -23
- package/runtime/prompts/host-orchestration/implementation.md +1 -1
- package/runtime/prompts/launch.template.md +3 -7
- package/runtime/prompts/lead/context-loader.md +41 -141
- package/runtime/prompts/lead/convergence.md +8 -6
- package/runtime/prompts/lead/okstra-lead-contract.md +25 -35
- package/runtime/prompts/lead/plan-body-verification.md +187 -14
- package/runtime/prompts/lead/report-writer.md +20 -1
- package/runtime/prompts/lead/team-contract.md +8 -53
- package/runtime/prompts/profiles/_coding-conventions-preflight.md +3 -2
- package/runtime/prompts/profiles/_common-contract.md +1 -1
- package/runtime/prompts/profiles/_implementation-diff-review.md +1 -1
- package/runtime/prompts/profiles/_implementation-verifier.md +3 -3
- package/runtime/prompts/profiles/final-verification.md +1 -1
- package/runtime/prompts/profiles/implementation-planning.md +8 -2
- package/runtime/prompts/profiles/release-handoff.md +0 -1
- package/runtime/prompts/wizard/prompts.ko.json +0 -1
- package/runtime/python/okstra_ctl/adapters/hosts/capability_adapter.py +69 -17
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +13 -4
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +6 -1
- package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +2 -2
- package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +50 -5
- package/runtime/python/okstra_ctl/adapters/hosts/grok/adapter.py +2 -2
- package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +66 -5
- package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +70 -2
- package/runtime/python/okstra_ctl/agent_activity.py +118 -35
- package/runtime/python/okstra_ctl/agent_invocation.py +19 -6
- package/runtime/python/okstra_ctl/agent_prompt_cli.py +65 -18
- package/runtime/python/okstra_ctl/analysis_inputs.py +5 -4
- package/runtime/python/okstra_ctl/analysis_packet.py +81 -1
- package/runtime/python/okstra_ctl/approval_decisions.py +3 -2
- package/runtime/python/okstra_ctl/attempt_evidence.py +2 -2
- package/runtime/python/okstra_ctl/backfill.py +13 -10
- package/runtime/python/okstra_ctl/batch.py +2 -4
- package/runtime/python/okstra_ctl/build_tools.py +6 -3
- package/runtime/python/okstra_ctl/claim_reproduction.py +101 -0
- package/runtime/python/okstra_ctl/clarification_items.py +27 -13
- package/runtime/python/okstra_ctl/cmux.py +130 -52
- package/runtime/python/okstra_ctl/code_review_target.py +34 -8
- package/runtime/python/okstra_ctl/consumers.py +5 -4
- package/runtime/python/okstra_ctl/container.py +103 -8
- package/runtime/python/okstra_ctl/context_cost.py +2 -1
- package/runtime/python/okstra_ctl/contract_graph.py +497 -0
- package/runtime/python/okstra_ctl/contract_graph_cli.py +62 -0
- package/runtime/python/okstra_ctl/convergence.py +338 -17
- package/runtime/python/okstra_ctl/convergence_engine.py +10 -18
- package/runtime/python/okstra_ctl/convergence_provenance.py +58 -8
- package/runtime/python/okstra_ctl/convergence_store.py +55 -34
- package/runtime/python/okstra_ctl/design_prep.py +7 -4
- package/runtime/python/okstra_ctl/dispatch_core.py +35 -65
- package/runtime/python/okstra_ctl/dispatch_state.py +134 -59
- package/runtime/python/okstra_ctl/doctor.py +6 -3
- package/runtime/python/okstra_ctl/domain/worker_presentation.py +70 -9
- package/runtime/python/okstra_ctl/entrypoints/hosts.py +16 -30
- package/runtime/python/okstra_ctl/error_log_write.py +35 -30
- package/runtime/python/okstra_ctl/error_report.py +26 -1
- package/runtime/python/okstra_ctl/error_zip.py +27 -5
- package/runtime/python/okstra_ctl/execution_identity.py +3 -2
- package/runtime/python/okstra_ctl/execution_manifest.py +7 -4
- package/runtime/python/okstra_ctl/final_report_schema.py +2 -2
- package/runtime/python/okstra_ctl/fix_cycles.py +2 -2
- package/runtime/python/okstra_ctl/fixed_text.py +39 -0
- package/runtime/python/okstra_ctl/git_reconcile.py +41 -9
- package/runtime/python/okstra_ctl/handoff.py +5 -4
- package/runtime/python/okstra_ctl/i18n.py +4 -2
- package/runtime/python/okstra_ctl/implementation_direction.py +22 -14
- package/runtime/python/okstra_ctl/implementation_outcome.py +4 -7
- package/runtime/python/okstra_ctl/incremental_carry.py +2 -1
- package/runtime/python/okstra_ctl/incremental_scope.py +8 -3
- package/runtime/python/okstra_ctl/index.py +8 -11
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +79 -7
- package/runtime/python/okstra_ctl/invocation.py +3 -6
- package/runtime/python/okstra_ctl/json_boundary.py +366 -0
- package/runtime/python/okstra_ctl/json_registry.py +10 -12
- package/runtime/python/okstra_ctl/jsonl.py +19 -2
- package/runtime/python/okstra_ctl/lead_events.py +33 -1
- package/runtime/python/okstra_ctl/listing.py +3 -3
- package/runtime/python/okstra_ctl/log_report.py +24 -2
- package/runtime/python/okstra_ctl/manager_cli.py +92 -7
- package/runtime/python/okstra_ctl/manager_store.py +12 -10
- package/runtime/python/okstra_ctl/material.py +5 -1
- package/runtime/python/okstra_ctl/migrate.py +29 -25
- package/runtime/python/okstra_ctl/model_cli.py +3 -15
- package/runtime/python/okstra_ctl/model_io_cli.py +1051 -0
- package/runtime/python/okstra_ctl/mutation_probe.py +13 -4
- package/runtime/python/okstra_ctl/pane_reclaim.py +3 -2
- package/runtime/python/okstra_ctl/paths.py +9 -0
- package/runtime/python/okstra_ctl/plan_items.py +115 -4
- package/runtime/python/okstra_ctl/plan_items_cli.py +513 -18
- package/runtime/python/okstra_ctl/pr_template.py +3 -2
- package/runtime/python/okstra_ctl/project_meta.py +5 -7
- package/runtime/python/okstra_ctl/recap.py +5 -4
- package/runtime/python/okstra_ctl/reconcile.py +21 -27
- package/runtime/python/okstra_ctl/registry/host_discovery.py +3 -2
- package/runtime/python/okstra_ctl/registry/provider_registry.py +3 -2
- package/runtime/python/okstra_ctl/render.py +26 -15
- package/runtime/python/okstra_ctl/render_final_report.py +3 -2
- package/runtime/python/okstra_ctl/report_assembly.py +172 -17
- package/runtime/python/okstra_ctl/report_finalize.py +7 -10
- package/runtime/python/okstra_ctl/report_html/render.py +3 -2
- package/runtime/python/okstra_ctl/report_language.py +3 -2
- package/runtime/python/okstra_ctl/report_markdown.py +13 -1
- package/runtime/python/okstra_ctl/report_narrative.py +40 -8
- package/runtime/python/okstra_ctl/report_synthesis_packet.py +518 -0
- package/runtime/python/okstra_ctl/report_views.py +3 -2
- package/runtime/python/okstra_ctl/rollup.py +65 -4
- package/runtime/python/okstra_ctl/run.py +159 -56
- package/runtime/python/okstra_ctl/run_audit.py +3 -2
- package/runtime/python/okstra_ctl/run_context.py +6 -9
- package/runtime/python/okstra_ctl/run_index_row.py +2 -8
- package/runtime/python/okstra_ctl/schedule_semantics.py +5 -2
- package/runtime/python/okstra_ctl/schema_excerpt.py +4 -2
- package/runtime/python/okstra_ctl/session_transcript.py +27 -1
- package/runtime/python/okstra_ctl/set_work_status.py +64 -38
- package/runtime/python/okstra_ctl/stage_fix_carry.py +4 -2
- package/runtime/python/okstra_ctl/stage_map.py +26 -6
- package/runtime/python/okstra_ctl/stage_targets.py +3 -4
- package/runtime/python/okstra_ctl/team.py +2 -1
- package/runtime/python/okstra_ctl/team_reconcile.py +11 -2
- package/runtime/python/okstra_ctl/time_report.py +51 -4
- package/runtime/python/okstra_ctl/usage_identity.py +2 -1
- package/runtime/python/okstra_ctl/usage_report.py +58 -4
- package/runtime/python/okstra_ctl/user_response.py +1431 -66
- package/runtime/python/okstra_ctl/wizard.py +11 -44
- package/runtime/python/okstra_ctl/work_categories.py +3 -2
- package/runtime/python/okstra_ctl/worker_prompt_body.py +18 -7
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +3 -2
- package/runtime/python/okstra_ctl/worker_runner.py +14 -12
- package/runtime/python/okstra_ctl/workflow.py +2 -1
- package/runtime/python/okstra_ctl/worktree.py +3 -2
- package/runtime/python/okstra_ctl/wrapper_status.py +4 -2
- package/runtime/python/okstra_ctl/write_policy.py +4 -2
- package/runtime/python/okstra_token_usage/antigravity.py +39 -12
- package/runtime/python/okstra_token_usage/collect.py +90 -38
- package/runtime/python/okstra_token_usage/grok.py +127 -0
- package/runtime/schemas/final-report-v2.0.schema.json +9 -0
- package/runtime/schemas/final-report-v3.0.schema.json +9 -0
- package/runtime/schemas/report-synthesis-packet-v1.0.schema.json +140 -0
- package/runtime/skills/okstra-brief-gen/SKILL.md +9 -7
- package/runtime/skills/okstra-code-review/SKILL.md +21 -11
- package/runtime/skills/okstra-container-build/SKILL.md +18 -18
- package/runtime/skills/okstra-inspect/SKILL.md +12 -11
- package/runtime/skills/okstra-inspect/facets/error-zip.md +8 -8
- package/runtime/skills/okstra-inspect/facets/errors.md +2 -2
- package/runtime/skills/okstra-inspect/facets/history.md +9 -14
- package/runtime/skills/okstra-inspect/facets/logs.md +2 -2
- package/runtime/skills/okstra-inspect/facets/recap.md +5 -5
- package/runtime/skills/okstra-inspect/facets/report.md +6 -10
- package/runtime/skills/okstra-inspect/facets/status.md +9 -8
- package/runtime/skills/okstra-inspect/facets/time.md +3 -3
- package/runtime/skills/okstra-manager/SKILL.md +16 -14
- package/runtime/skills/okstra-memory/SKILL.md +3 -3
- package/runtime/skills/okstra-pr-gen/SKILL.md +5 -4
- package/runtime/skills/okstra-rollup/SKILL.md +6 -16
- package/runtime/skills/okstra-run/SKILL.md +7 -7
- package/runtime/skills/okstra-schedule-gen/SKILL.md +21 -17
- package/runtime/skills/okstra-setup/SKILL.md +21 -13
- package/runtime/skills/okstra-setup/references/project-config.md +2 -2
- package/runtime/skills/okstra-usage/SKILL.md +10 -10
- package/runtime/skills/okstra-user-response/SKILL.md +78 -107
- package/runtime/templates/report-writer-prompt-preamble.md +17 -1
- package/runtime/templates/reports/schedule.template.md +4 -4
- package/runtime/templates/worker-error-contract.md +17 -29
- package/runtime/validators/validate-run.py +379 -63
- package/runtime/validators/validate_session_conformance.py +43 -7
|
@@ -23,6 +23,7 @@ This script is the canonical single-reference-point. The Node CLI
|
|
|
23
23
|
from __future__ import annotations
|
|
24
24
|
|
|
25
25
|
import argparse
|
|
26
|
+
import hashlib
|
|
26
27
|
import json
|
|
27
28
|
import os
|
|
28
29
|
import sys
|
|
@@ -57,18 +58,77 @@ from okstra_ctl.final_report_paths import ( # noqa: E402
|
|
|
57
58
|
translation_sidecar_path,
|
|
58
59
|
translation_source_path,
|
|
59
60
|
)
|
|
61
|
+
from okstra_ctl.json_boundary import ( # noqa: E402
|
|
62
|
+
JsonBoundaryError,
|
|
63
|
+
load_owned_object,
|
|
64
|
+
load_owned_object_snapshot,
|
|
65
|
+
write_owned_object_atomic,
|
|
66
|
+
)
|
|
67
|
+
from okstra_ctl.fixed_text import line, scalar # noqa: E402
|
|
68
|
+
from okstra_ctl.convergence import ( # noqa: E402
|
|
69
|
+
ConvergenceContractError,
|
|
70
|
+
RunArtifactAuthority,
|
|
71
|
+
canonical_run_report_artifact,
|
|
72
|
+
validated_run_authority,
|
|
73
|
+
)
|
|
60
74
|
|
|
61
75
|
|
|
62
76
|
def _load(path: Path) -> dict:
|
|
63
77
|
try:
|
|
64
|
-
|
|
65
|
-
except
|
|
66
|
-
raise SystemExit(f"error:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
return load_owned_object(path, artifact="report translation artifact")
|
|
79
|
+
except JsonBoundaryError as exc:
|
|
80
|
+
raise SystemExit(f"error: {exc}") from exc
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _translation_authority(
|
|
84
|
+
manifest_path: Path,
|
|
85
|
+
) -> tuple[RunArtifactAuthority, Path]:
|
|
86
|
+
try:
|
|
87
|
+
authority = validated_run_authority(manifest_path)
|
|
88
|
+
report = canonical_run_report_artifact(authority)
|
|
89
|
+
except (ConvergenceContractError, JsonBoundaryError) as exc:
|
|
90
|
+
raise SystemExit(f"error: {exc}") from exc
|
|
91
|
+
return authority, report
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _report_snapshot(path: Path):
|
|
95
|
+
try:
|
|
96
|
+
return load_owned_object_snapshot(
|
|
97
|
+
path, artifact="report translation source"
|
|
98
|
+
)
|
|
99
|
+
except JsonBoundaryError as exc:
|
|
100
|
+
raise SystemExit(f"error: {exc}") from exc
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _source_payload(
|
|
104
|
+
authority: RunArtifactAuthority, data_path: Path, raw_bytes: bytes, data: dict
|
|
105
|
+
) -> dict:
|
|
106
|
+
return {
|
|
107
|
+
"taskKey": authority.task_key,
|
|
108
|
+
"runManifestPath": authority.manifest_ref,
|
|
109
|
+
"sourceData": data_path.name,
|
|
110
|
+
"sourceDataPath": data_path.relative_to(authority.project_root).as_posix(),
|
|
111
|
+
"sourceDataSha256": hashlib.sha256(raw_bytes).hexdigest(),
|
|
112
|
+
"lang": str((data.get("meta") or {}).get("reportLanguage") or ""),
|
|
113
|
+
"strings": extract(data),
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _validate_source_payload(
|
|
118
|
+
source: dict, expected: dict, supplied_digest: str
|
|
119
|
+
) -> None:
|
|
120
|
+
for key in (
|
|
121
|
+
"taskKey", "runManifestPath", "sourceData", "sourceDataPath",
|
|
122
|
+
"sourceDataSha256", "lang", "strings",
|
|
123
|
+
):
|
|
124
|
+
if source.get(key) != expected.get(key):
|
|
125
|
+
raise SystemExit(
|
|
126
|
+
"error: report changed after translation source publication"
|
|
127
|
+
)
|
|
128
|
+
if supplied_digest != expected["sourceDataSha256"]:
|
|
129
|
+
raise SystemExit(
|
|
130
|
+
"error: report changed after translation source publication"
|
|
131
|
+
)
|
|
72
132
|
|
|
73
133
|
|
|
74
134
|
def _english_source_failure(data_path: Path, data: dict) -> str | None:
|
|
@@ -99,18 +159,10 @@ def cmd_extract(args: argparse.Namespace) -> int:
|
|
|
99
159
|
strings = extract(data)
|
|
100
160
|
out_path = translation_source_path(data_path)
|
|
101
161
|
lang = str((data.get("meta") or {}).get("reportLanguage") or "")
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
"sourceData": data_path.name,
|
|
107
|
-
"strings": strings,
|
|
108
|
-
},
|
|
109
|
-
ensure_ascii=False,
|
|
110
|
-
indent=2,
|
|
111
|
-
)
|
|
112
|
-
+ "\n",
|
|
113
|
-
encoding="utf-8",
|
|
162
|
+
write_owned_object_atomic(
|
|
163
|
+
out_path,
|
|
164
|
+
{"lang": lang, "sourceData": data_path.name, "strings": strings},
|
|
165
|
+
artifact="translation source",
|
|
114
166
|
)
|
|
115
167
|
print(
|
|
116
168
|
json.dumps(
|
|
@@ -128,8 +180,130 @@ def cmd_extract(args: argparse.Namespace) -> int:
|
|
|
128
180
|
return 0
|
|
129
181
|
|
|
130
182
|
|
|
183
|
+
def cmd_source(args: argparse.Namespace) -> int:
|
|
184
|
+
authority, data_path = _translation_authority(Path(args.run_manifest))
|
|
185
|
+
snapshot = _report_snapshot(data_path)
|
|
186
|
+
data = snapshot.value
|
|
187
|
+
failure = _english_source_failure(data_path, data)
|
|
188
|
+
if failure is not None:
|
|
189
|
+
sys.stderr.write(failure)
|
|
190
|
+
return 1
|
|
191
|
+
payload = _source_payload(authority, data_path, snapshot.raw_bytes, data)
|
|
192
|
+
out_path = translation_source_path(data_path)
|
|
193
|
+
if out_path.is_symlink():
|
|
194
|
+
raise SystemExit("error: translation source path is a symlink")
|
|
195
|
+
write_owned_object_atomic(
|
|
196
|
+
out_path, payload, artifact="translation source"
|
|
197
|
+
)
|
|
198
|
+
strings = payload["strings"]
|
|
199
|
+
print("# Translation work list")
|
|
200
|
+
print(line("Task key", authority.task_key), end="")
|
|
201
|
+
print(line("Report", payload["sourceDataPath"]), end="")
|
|
202
|
+
print(line("Run manifest", authority.manifest_ref), end="")
|
|
203
|
+
print(line("Source digest", payload["sourceDataSha256"]), end="")
|
|
204
|
+
print(line("String count", len(strings)), end="")
|
|
205
|
+
for index, source in enumerate(strings.values(), 1):
|
|
206
|
+
print(f"\n## T-{index:03d}\n{scalar(source)}")
|
|
207
|
+
return 0
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _translation_blocks(path: Path) -> list[str]:
|
|
211
|
+
text = path.read_text(encoding="utf-8")
|
|
212
|
+
blocks: list[str] = []
|
|
213
|
+
current: list[str] | None = None
|
|
214
|
+
for row in text.splitlines():
|
|
215
|
+
if row.startswith("## T-"):
|
|
216
|
+
if current is not None:
|
|
217
|
+
blocks.append("\n".join(current).strip())
|
|
218
|
+
expected = f"## T-{len(blocks) + 1:03d}"
|
|
219
|
+
if row != expected:
|
|
220
|
+
raise SystemExit(f"error: expected translation heading {expected}")
|
|
221
|
+
current = []
|
|
222
|
+
elif current is not None:
|
|
223
|
+
current.append(row)
|
|
224
|
+
if current is not None:
|
|
225
|
+
blocks.append("\n".join(current).strip())
|
|
226
|
+
return blocks
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def cmd_write(args: argparse.Namespace) -> int:
|
|
230
|
+
authority, data_path = _translation_authority(Path(args.run_manifest))
|
|
231
|
+
snapshot = _report_snapshot(data_path)
|
|
232
|
+
data = snapshot.value
|
|
233
|
+
expected = _source_payload(
|
|
234
|
+
authority, data_path, snapshot.raw_bytes, data
|
|
235
|
+
)
|
|
236
|
+
source_path = translation_source_path(data_path)
|
|
237
|
+
if source_path.is_symlink():
|
|
238
|
+
raise SystemExit("error: translation source path is a symlink")
|
|
239
|
+
source = _load(source_path)
|
|
240
|
+
_validate_source_payload(source, expected, args.source_digest)
|
|
241
|
+
sources = expected["strings"]
|
|
242
|
+
translated = _translation_blocks(Path(args.translations))
|
|
243
|
+
if len(translated) != len(sources) or any(not value for value in translated):
|
|
244
|
+
raise SystemExit("error: translation blocks must match every T-NNN item")
|
|
245
|
+
lang = expected["lang"]
|
|
246
|
+
sidecar = translation_sidecar_path(data_path, lang)
|
|
247
|
+
if sidecar.is_symlink():
|
|
248
|
+
raise SystemExit("error: translation sidecar path is a symlink")
|
|
249
|
+
strings = dict(zip(sources, translated))
|
|
250
|
+
_, report = overlay(data, strings)
|
|
251
|
+
if report.unresolved or report.applied != len(strings):
|
|
252
|
+
raise SystemExit("error: translations do not validate against report source")
|
|
253
|
+
write_owned_object_atomic(
|
|
254
|
+
sidecar,
|
|
255
|
+
{
|
|
256
|
+
"taskKey": authority.task_key,
|
|
257
|
+
"runManifestPath": authority.manifest_ref,
|
|
258
|
+
"lang": lang,
|
|
259
|
+
"sourceData": data_path.name,
|
|
260
|
+
"sourceDataPath": expected["sourceDataPath"],
|
|
261
|
+
"sourceDataSha256": expected["sourceDataSha256"],
|
|
262
|
+
"strings": strings,
|
|
263
|
+
},
|
|
264
|
+
artifact="report translation sidecar",
|
|
265
|
+
)
|
|
266
|
+
print("Translation sidecar\n" + line("Status", "ready"), end="")
|
|
267
|
+
return 0
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def cmd_check_data(args: argparse.Namespace) -> int:
|
|
271
|
+
authority, data_path = _translation_authority(Path(args.run_manifest))
|
|
272
|
+
snapshot = _report_snapshot(data_path)
|
|
273
|
+
expected = _source_payload(
|
|
274
|
+
authority, data_path, snapshot.raw_bytes, snapshot.value
|
|
275
|
+
)
|
|
276
|
+
sidecar_path = translation_sidecar_path(data_path, expected["lang"])
|
|
277
|
+
if sidecar_path.is_symlink():
|
|
278
|
+
raise SystemExit("error: translation sidecar path is a symlink")
|
|
279
|
+
sidecar = _load(sidecar_path)
|
|
280
|
+
_validate_authority_sidecar(sidecar, expected)
|
|
281
|
+
payload, code = _check_sidecar(sidecar_path)
|
|
282
|
+
print("Translation check\n" + line("Status", "ready" if payload["ok"] else "error")
|
|
283
|
+
+ line("Applied strings", payload["applied"])
|
|
284
|
+
+ line("Unresolved strings", len(payload["unresolved"])), end="")
|
|
285
|
+
return code
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def _validate_authority_sidecar(sidecar: dict, expected: dict) -> None:
|
|
289
|
+
for key in (
|
|
290
|
+
"taskKey", "runManifestPath", "lang", "sourceData", "sourceDataPath",
|
|
291
|
+
"sourceDataSha256",
|
|
292
|
+
):
|
|
293
|
+
if sidecar.get(key) != expected.get(key):
|
|
294
|
+
raise SystemExit(
|
|
295
|
+
"error: translation sidecar does not match run authority"
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
|
|
131
299
|
def cmd_check(args: argparse.Namespace) -> int:
|
|
132
300
|
sidecar_file = Path(args.sidecar).resolve()
|
|
301
|
+
payload, code = _check_sidecar(sidecar_file)
|
|
302
|
+
print(json.dumps(payload, ensure_ascii=False))
|
|
303
|
+
return code
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def _check_sidecar(sidecar_file: Path) -> tuple[dict, int]:
|
|
133
307
|
sidecar = _load(sidecar_file)
|
|
134
308
|
strings = sidecar.get("strings")
|
|
135
309
|
if not isinstance(strings, dict):
|
|
@@ -150,7 +324,6 @@ def cmd_check(args: argparse.Namespace) -> int:
|
|
|
150
324
|
"untranslated": list(report.untranslated),
|
|
151
325
|
"unresolved": list(report.unresolved),
|
|
152
326
|
}
|
|
153
|
-
print(json.dumps(payload, ensure_ascii=False))
|
|
154
327
|
if report.unresolved:
|
|
155
328
|
# A pointer that resolves nowhere means the sidecar was written against
|
|
156
329
|
# a different report. Rendering it would silently drop those strings.
|
|
@@ -158,8 +331,8 @@ def cmd_check(args: argparse.Namespace) -> int:
|
|
|
158
331
|
f"error: {len(report.unresolved)} pointer(s) do not resolve in "
|
|
159
332
|
f"{data_path.name}\n"
|
|
160
333
|
)
|
|
161
|
-
return 1
|
|
162
|
-
return 0
|
|
334
|
+
return payload, 1
|
|
335
|
+
return payload, 0
|
|
163
336
|
|
|
164
337
|
|
|
165
338
|
def cmd_check_source(args: argparse.Namespace) -> int:
|
|
@@ -191,6 +364,20 @@ def _parser() -> argparse.ArgumentParser:
|
|
|
191
364
|
extract_cmd.add_argument("data", help="path to final-report-<type>-<seq>.data.json")
|
|
192
365
|
extract_cmd.set_defaults(func=cmd_extract)
|
|
193
366
|
|
|
367
|
+
source_view = sub.add_parser("source", help="render a fixed translation work list")
|
|
368
|
+
source_view.add_argument("--run-manifest", required=True)
|
|
369
|
+
source_view.set_defaults(func=cmd_source)
|
|
370
|
+
|
|
371
|
+
write_cmd = sub.add_parser("write", help="publish translations from T-NNN blocks")
|
|
372
|
+
write_cmd.add_argument("--run-manifest", required=True)
|
|
373
|
+
write_cmd.add_argument("--source-digest", required=True)
|
|
374
|
+
write_cmd.add_argument("--translations", required=True)
|
|
375
|
+
write_cmd.set_defaults(func=cmd_write)
|
|
376
|
+
|
|
377
|
+
check_data = sub.add_parser("check-data", help="verify the derived sidecar")
|
|
378
|
+
check_data.add_argument("--run-manifest", required=True)
|
|
379
|
+
check_data.set_defaults(func=cmd_check_data)
|
|
380
|
+
|
|
194
381
|
check_cmd = sub.add_parser("check", help="verify a filled sidecar against its report")
|
|
195
382
|
check_cmd.add_argument("sidecar", help="path to final-report-<type>-<seq>.i18n.<lang>.json")
|
|
196
383
|
check_cmd.set_defaults(func=cmd_check)
|
|
@@ -41,7 +41,7 @@ If `render-bundle` stdout carries an `okstra concurrent-run stages: <stages>` la
|
|
|
41
41
|
|
|
42
42
|
If `render-bundle` fails with a `PrepareError` containing `Recorded stage SHAs no longer match the git history`, the git history changed outside okstra (rebase / squash / review-feedback amend / branch deletion). Never fix the registry/consumers by hand; recover in this order:
|
|
43
43
|
|
|
44
|
-
1. Run the `okstra git-reconcile … --check --
|
|
44
|
+
1. Run the `okstra git-reconcile … --check --text` command printed in the error message verbatim to get the stale report. (Items whose content-identity is proven by patch-id were already auto-reconciled by prepare, so only confirm items remain here.)
|
|
45
45
|
2. For each confirm item, present a 3-option picker to the user:
|
|
46
46
|
- **Re-record to the `stage-<N>` branch's current tip (recommended)** — when an intended change such as review feedback lives on that branch.
|
|
47
47
|
- **Enter a different ref directly** — the user names a commit/branch/tag.
|
|
@@ -49,6 +49,7 @@ For a new `implementation-planning` run, the plan-body sequence is initial verif
|
|
|
49
49
|
## Run Paths
|
|
50
50
|
|
|
51
51
|
- Team state: `{{TEAM_STATE_RELATIVE_PATH}}`
|
|
52
|
+
- Plan-body verification state: `{{PLAN_BODY_VERIFICATION_STATE_RELATIVE_PATH}}`
|
|
52
53
|
- Final report: `{{FINAL_REPORT_RECORD_RELATIVE_PATH}}`
|
|
53
54
|
- Final status: `{{FINAL_STATUS_RELATIVE_PATH}}`
|
|
54
55
|
- Validator: `{{RUN_VALIDATOR_RELATIVE_PATH}}`
|
|
@@ -57,12 +58,7 @@ For a new `implementation-planning` run, the plan-body sequence is initial verif
|
|
|
57
58
|
|
|
58
59
|
- Run-level errors log (absolute): `{{RUN_ERRORS_LOG_PATH}}`
|
|
59
60
|
- Run-level errors log (relative): `{{RUN_ERRORS_LOG_RELATIVE_PATH}}`
|
|
60
|
-
-
|
|
61
|
-
- Claude worker: `{{CLAUDE_WORKER_ERRORS_SIDECAR_PATH}}`
|
|
62
|
-
- Codex worker: `{{CODEX_WORKER_ERRORS_SIDECAR_PATH}}`
|
|
63
|
-
- Antigravity worker: `{{ANTIGRAVITY_WORKER_ERRORS_SIDECAR_PATH}}`
|
|
64
|
-
- Report writer worker: `{{REPORT_WRITER_WORKER_ERRORS_SIDECAR_PATH}}`
|
|
65
|
-
- The paths above are the values; the wiring duties — injecting the `**Errors log path:**` / `**Errors sidecar path:**` header pair into every dispatch prompt, and dumping each terminated worker's sidecar via `okstra error-log append-from-worker` — are defined once in the lifecycle core contract (`{{OKSTRA_LEAD_CONTRACT_PATH}}` "Errors log path wiring (BLOCKING)"). Follow that section; do not re-derive the rules from this block.
|
|
61
|
+
- The lead injects `**Errors log path:**` into every dispatch prompt. Workers use the typed `okstra error-log append-observed` command in the shared worker error contract; runtime-owned sidecar compatibility is not a worker instruction.
|
|
66
62
|
|
|
67
63
|
## Executor Worktree
|
|
68
64
|
|
|
@@ -114,7 +110,7 @@ The **default is full re-verification**. Only narrow this re-run to the impacted
|
|
|
114
110
|
- Pass ONLY stage numbers that appear in that Stage Map when you do use `--impacted`. Never invent or guess a stage number — a number absent from the graph must never enter `--impacted` (it would leak into `reverify_stages`).
|
|
115
111
|
2. **Resolve the two base SHAs (safety condition C1 — code-unchanged, decided by the CLI, not by you).**
|
|
116
112
|
- Current base SHA: `{{EXECUTOR_WORKTREE_BASE_REF}}` (this run's resolved worktree base commit).
|
|
117
|
-
- Prior base SHA:
|
|
113
|
+
- Prior base SHA: run `okstra model-io active-context-input --project-root <project-root> --run-manifest <run-manifest>` and use its fixed `Executor base ref` field. Python resolves the prior active context only when it belongs to this project and run. If the command fails or the field is empty, treat the run as **full** and skip the rest of this procedure.
|
|
118
114
|
3. **Call the CLI** (it is pure — same inputs always yield the same decision):
|
|
119
115
|
```
|
|
120
116
|
okstra incremental-scope \
|
|
@@ -2,154 +2,54 @@
|
|
|
2
2
|
|
|
3
3
|
## When to Use
|
|
4
4
|
|
|
5
|
-
- When starting okstra lead Phase 1
|
|
6
|
-
- When the user needs
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- okstra task root
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
`task-
|
|
33
|
-
|
|
34
|
-
| Field | Description |
|
|
35
|
-
|------|------|
|
|
36
|
-
| `taskKey` | `<project-id>:<task-group>:<task-id>` |
|
|
37
|
-
| `projectId` | Project ID |
|
|
38
|
-
| `taskGroup` | Task group |
|
|
39
|
-
| `taskId` | Task ID |
|
|
40
|
-
| `taskType` | Analysis type (requirements-discovery, error-analysis, implementation-option-selection, implementation-planning, implementation, final-verification, release-handoff, plus the sidetrack improvement-discovery) |
|
|
41
|
-
| `workCategory` | bugfix / feature / improvement / refactor / ops / unknown |
|
|
42
|
-
| `recommendedWorkers` | List of selected workers |
|
|
43
|
-
| `currentStatus` | Current task status |
|
|
44
|
-
| `workflow.phaseSequence` | Ordered lifecycle phases for the task |
|
|
45
|
-
| `workflow.currentPhase` | Current lifecycle phase |
|
|
46
|
-
| `workflow.currentPhaseState` | Current lifecycle phase state |
|
|
47
|
-
| `workflow.phaseStates` | Phase-by-phase lifecycle state map |
|
|
48
|
-
| `workflow.lastCompletedPhase` | Last completed lifecycle phase |
|
|
49
|
-
| `workflow.nextRecommendedPhase` | Next-Phase Pointer — an object carrying the target phase, whether it can be started, and why. A projection of this report's Phase Routing; not authored here. Written per the Artifact Persistence Checklist in [report-writer](./report-writer.md); do not re-derive its rules here. |
|
|
50
|
-
| `workflow.awaitingApproval` | Approval wait marker |
|
|
51
|
-
| `workflow.lastSafeCheckpoint` | Safe resume checkpoint metadata |
|
|
52
|
-
| `instructionSetPath` | Path to the `instruction-set/` **directory** containing `analysis-packet.md`, `analysis-profile.md`, `analysis-material.md`, `reference-expectations.md`, `task-brief.md`, `final-report-template.md`, and — only for task types whose host orchestration carries gates — `host-orchestration-rules.md` (see Step 4). Not a single-file path. |
|
|
53
|
-
| `referenceExpectationsPath` | config/deployment expectation artifact path |
|
|
54
|
-
| `latestRunPath` | latest run path |
|
|
55
|
-
| `latestRunStatus` | latest run status |
|
|
56
|
-
| `latestRunPromptsPath` | latest run prompt directory path |
|
|
57
|
-
| `latestReportRecordPath` | latest report path |
|
|
58
|
-
| `latestResumeCommandPath` | resume helper path |
|
|
59
|
-
| `historyTimelinePath` | timeline path |
|
|
60
|
-
| `resultContract` | team contract and expected artifact metadata |
|
|
61
|
-
| `resultContract.requiredWorkerRoles[*].promptPath` | worker prompt history path by role |
|
|
62
|
-
| `convergence` | convergence loop settings (`enabled`, `maxRounds`, `verificationMode`). See [convergence](./convergence.md) for the authoritative defaults — do not re-document the `maxRounds` value here. |
|
|
63
|
-
|
|
64
|
-
## Step 3: Directory Structure Rules
|
|
65
|
-
|
|
66
|
-
After identifying the task root in `task-manifest.json`, derive all paths according to the following rules:
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
<task-root>/
|
|
70
|
-
├── task-manifest.json (canonical metadata)
|
|
71
|
-
├── task-index.md (human-readable summary, non-canonical)
|
|
72
|
-
├── instruction-set/
|
|
73
|
-
│ ├── analysis-profile.md (analysis guide by task type)
|
|
74
|
-
│ ├── analysis-packet.md (primary compact input for analysis workers)
|
|
75
|
-
│ ├── analysis-material.md (analysis materials)
|
|
76
|
-
│ ├── reference-expectations.md (config/deployment expected values)
|
|
77
|
-
│ ├── task-brief.md (task brief)
|
|
78
|
-
│ ├── final-report-template.md (Final Report Template)
|
|
79
|
-
│ └── host-orchestration-rules.md (host gate rules; present only for task types whose host orchestration carries gates)
|
|
80
|
-
├── runs/
|
|
81
|
-
│ └── <task-type>/ (Run scope isolated per task-type, e.g. error-analysis)
|
|
82
|
-
│ ├── manifests/ (run-manifest-<task-type>-<seq>.json)
|
|
83
|
-
│ ├── state/ (team-state-<task-type>-<seq>.json, convergence-<task-type>-<seq>.json)
|
|
84
|
-
│ ├── prompts/ (run prompt path and worker prompt history paths recorded in the manifest)
|
|
85
|
-
│ ├── reports/ (final-report-<task-type>-<seq>.data.json + .html;
|
|
86
|
-
│ the .md reading copy is rendered on demand)
|
|
87
|
-
│ ├── status/ (final-<task-type>-<seq>.status)
|
|
88
|
-
│ ├── sessions/ (runtime-specific resume artifacts when the selected adapter supports them)
|
|
89
|
-
│ ├── logs/ (errors-<task-type>-<seq>.jsonl, optional)
|
|
90
|
-
│ └── worker-results/
|
|
91
|
-
│ ├── claude-worker-<task-type>-<seq>.md
|
|
92
|
-
│ ├── codex-worker-<task-type>-<seq>.md
|
|
93
|
-
│ ├── antigravity-worker-<task-type>-<seq>.md
|
|
94
|
-
│ └── report-writer-worker-<task-type>-<seq>.md
|
|
95
|
-
└── history/
|
|
96
|
-
└── timeline.json
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### File Naming Conventions
|
|
100
|
-
|
|
101
|
-
- Run-level artifact files use the `-<task-type>-<seq>` suffix, where `<seq>` is a 3-digit zero-padded sequence number (`001`, `002`, …) scanned **per-category directory** (`manifests/`, `prompts/`, `reports/`, `status/`, `state/`, `sessions/`, `worker-results/`). Re-runs of the same task-type never overwrite each other's artifacts.
|
|
102
|
-
- Because each category directory has its own counter, the `<seq>` for `manifests/` may differ from the `<seq>` for `reports/` if a previous run only wrote some categories. The shared run identifier across categories is the manifest `runDateTimeSegment` field (still ISO timestamp), not a filename infix.
|
|
103
|
-
- Worker result files use the same `-<task-type>-<seq>` filename suffix as other run-level artifacts (counter scoped to `worker-results/`).
|
|
104
|
-
- Worker prompt history files use role + suffix names such as `claude-worker-prompt-<task-type>-<seq>.md`.
|
|
105
|
-
- A single `runs/<task-type>/` directory is reused for every run of that task type; the per-run separation comes entirely from the per-category sequence-number infix inside each typed subdirectory.
|
|
106
|
-
|
|
107
|
-
### Finding the Latest Run
|
|
108
|
-
|
|
109
|
-
1. If a `latest-task` pointer exists, prioritize the path to the latest run, latest run manifest, or latest team-state recorded there.
|
|
110
|
-
2. If entering via an explicit task key/path, locate the current run based on the latest run metadata in `task-manifest.json`.
|
|
111
|
-
3. Only if necessary, directly check `manifests/`, `state/`, `prompts/`, `reports/`, and `sessions/` within the relevant run directory.
|
|
112
|
-
|
|
113
|
-
## Step 4: Instruction Set Reading Order
|
|
114
|
-
|
|
115
|
-
After verifying `task-manifest.json`, read only the compact intake files needed for the current action. Do not bulk-read the whole instruction-set directory.
|
|
116
|
-
|
|
117
|
-
1. `instruction-set/analysis-profile.md` (analysis guide by task type)
|
|
118
|
-
2. `instruction-set/analysis-packet.md` (primary compact input for analysis workers)
|
|
119
|
-
3. `runs/<task-type>/state/active-run-context-<task-type>-<seq>.json` if present (compact current-run path/worker snapshot)
|
|
120
|
-
4. `instruction-set/host-orchestration-rules.md` when the launch prompt's Host Orchestration Rules path is set. Read it here even though no gate has fired yet — the gates it governs fire around `render-bundle`, so waiting for one means reading it too late, and this is the copy that survives compaction. **Enforced:** Phase 7 conformance fails an `implementation` run whose evidence source records no read of it.
|
|
121
|
-
|
|
122
|
-
Read source files lazily:
|
|
123
|
-
|
|
124
|
-
- `instruction-set/task-brief.md` only for reporter-confirmation checks, source verification, or report-writer synthesis.
|
|
125
|
-
- `instruction-set/analysis-material.md` only when packet content is insufficient or a source citation needs verification.
|
|
126
|
-
- `instruction-set/reference-expectations.md` for report-writer synthesis or when packet expectation extract is insufficient.
|
|
127
|
-
- `instruction-set/final-report-template.md` only for report-writer authoring.
|
|
128
|
-
- `instruction-set/host-orchestration-rules.md` — already read at Step 4; re-read it whenever you are about to act on a host gate — the conformance waiver offer, the concurrent-run branch, stale-SHA recovery, the chaining queue — and again after any compaction. Absent file means this task type carries no host gates.
|
|
5
|
+
- When starting okstra lead Phase 1 task-bundle intake.
|
|
6
|
+
- When the user needs the task bundle or current run paths.
|
|
7
|
+
|
|
8
|
+
## JSON Boundary
|
|
9
|
+
|
|
10
|
+
Do not open, parse, or infer Okstra-owned task, run, discovery, or active-context JSON. This contract uses the fixed text views below before the lead contract is loaded, so it cannot bypass that boundary.
|
|
11
|
+
|
|
12
|
+
- `okstra model-io project-context --project-root <project-root> --task-ref <task-ref>` provides project identity and the pointer for one explicit task reference. `task-ref` accepts a bare task ID, full task key, or that task's manifest path.
|
|
13
|
+
- `okstra model-io run-input --run-manifest <run-manifest-path>` provides the current run identity, worker roster, model assignments, and permitted artifact paths.
|
|
14
|
+
|
|
15
|
+
## Step 1: Resolve the Task and Run Paths
|
|
16
|
+
|
|
17
|
+
1. Determine `<project-root>` from the user request or the current project.
|
|
18
|
+
2. If the user supplies a task ID, full task key, or task-manifest path, run `okstra model-io project-context --project-root <project-root> --task-ref <task-ref>`. Otherwise run `okstra model-io project-context --project-root <project-root>`.
|
|
19
|
+
3. If the supplied bare task ID is ambiguous, require the full task key or task-manifest path.
|
|
20
|
+
4. Use the `Task key`, `Task manifest`, and `Latest run manifest` labels from the same Project Context result.
|
|
21
|
+
5. Use `Latest run manifest` as `<run-manifest-path>`. If it is `-`, request an explicit run-manifest path from the launch context or stop with `OKSTRA_CONTEXT_NOT_INITIALIZED`. Do not scan task directories or reconstruct a run path.
|
|
22
|
+
6. Run `okstra model-io run-input --run-manifest <run-manifest-path>`.
|
|
23
|
+
|
|
24
|
+
## Step 2: Read the Compact Intake Files
|
|
25
|
+
|
|
26
|
+
Use the `Instruction set` and `Reference expectations` labels in Run Input as paths for Markdown resources. Read only the resources needed for the current action.
|
|
27
|
+
|
|
28
|
+
1. `<instruction-set>/analysis-profile.md` for the task-type rules and required worker block.
|
|
29
|
+
2. `<instruction-set>/analysis-packet.md` for the Phase 1 compact input.
|
|
30
|
+
3. `<instruction-set>/host-orchestration-rules.md` when the launch prompt supplies that path.
|
|
31
|
+
|
|
32
|
+
Read `task-brief.md`, `analysis-material.md`, `reference-expectations.md`, and `final-report-template.md` only at their phase-specific need. The report writer owns the final-report template.
|
|
129
33
|
|
|
130
34
|
### Brief Reporter-Confirmation Precondition (BLOCKING)
|
|
131
35
|
|
|
132
|
-
After reading `task-brief.md`, extract the frontmatter `reporter-confirmations` field
|
|
36
|
+
After reading `task-brief.md`, extract the frontmatter `reporter-confirmations` field when present and apply the shared handling matrix in `prompts/profiles/_common-contract.md` "Brief handoff contract" → "Reporter confirmation precondition". That block is the authority for the value semantics.
|
|
133
37
|
|
|
134
|
-
|
|
38
|
+
On `pending`, emit `REPORTER_CONFIRMATION_PENDING` and stop. Do not invoke `team-contract` or an analyser, and do not write a final report. Regenerate the brief with `okstra-brief-gen` Step 6.5 and prepare a fresh run. A missing field is a legacy brief and proceeds with the matrix's carried flags. Current-format invalid values are rejected during preparation.
|
|
135
39
|
|
|
136
|
-
## Step
|
|
40
|
+
## Step 3: Use Run Input as the Run-State View
|
|
137
41
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
42
|
+
Run Input is the only Phase 1 source for task identity, work category, workflow state, selected workers, model assignments, worker prompt paths, result paths, validator path, resume command, and configuration references.
|
|
43
|
+
|
|
44
|
+
Use the `Worker Roster` section for dispatch and model assignment. Use `Artifact Paths` for prompt, result, report, status, validator, and resume locations. Use `Configuration References` for the task-level Markdown resources. Do not derive sibling paths from file names or sequence counters.
|
|
45
|
+
|
|
46
|
+
Use the `Current phase` labels as the workflow view. Rules for `nextRecommendedPhase` are maintained by [report-writer](./report-writer.md); do not re-derive phase routing here.
|
|
143
47
|
|
|
144
48
|
## Output
|
|
145
49
|
|
|
146
50
|
Information produced after completing this contract:
|
|
147
|
-
|
|
148
|
-
-
|
|
149
|
-
-
|
|
150
|
-
-
|
|
151
|
-
-
|
|
152
|
-
- Current run prompt history contract for attempted workers
|
|
153
|
-
- Candidate `teamName` for the manifest/team-state audit identity: `okstra-<task-key>` (with task-key slugified per Step 1's slug rule); implementation stage runs append `-s<N>`. The selected runtime adapter owns whether an adapter-specific audit label is exposed in the launch prompt's "Runtime Adapter Dispatch Gate (BLOCKING)" setup facts; this common contract does not guarantee that label for every runtime.
|
|
154
|
-
- Current lead session/checkpoint identity, when supplied by the selected adapter
|
|
155
|
-
- Resume artifact path from `task-manifest.json.artifacts.resumeCommandPath`; never reconstruct a runtime-specific filename
|
|
51
|
+
|
|
52
|
+
- Project ID, task key, task type, work category, and workflow snapshot.
|
|
53
|
+
- Selected workers and assigned models.
|
|
54
|
+
- Prompt, result, report, status, validator, resume, and configuration-reference paths.
|
|
55
|
+
- The compact Markdown intake paths required for Phase 1.
|
|
@@ -84,7 +84,9 @@ Read the worker result files generated in Phase 4/5 and extract individual findi
|
|
|
84
84
|
- Same semantics but disjoint ticket sets → separate groups (do NOT over-merge across tickets).
|
|
85
85
|
- Only one worker confirms a finding → one single-source group.
|
|
86
86
|
4. When grouping is ambiguous, prefer splitting over merging (avoid over-merging). Semantic matching, ticket-set equality, and evidence interpretation remain lead judgments; the engine does not perform fuzzy matching or decide whether evidence is credible.
|
|
87
|
-
5.
|
|
87
|
+
5. Author the fixed grouping Markdown accepted by `okstra convergence prepare-groups --run-manifest <run-manifest> --input <grouping.md>`, then run that command. Python owns the artifact identifier, target path, schema version, task identity, run-manifest reference, and every participant reference. Each Markdown group records ticket IDs, origin worker and evidence, discovering workers, source worker item IDs, and optional captured evidence. An analysis sidetrack with no ticket uses an empty `Tickets:` value, never a placeholder. Use the ordered functional roster: finding workers have the `analysis` audience, the report author has `report-writer`, and the lead uses `lead`. A lead source never votes. Never infer live evidence or functional scope from wording, provider, model, or execution label.
|
|
88
|
+
|
|
89
|
+
The command sets each worker's paired `participantRef` and `sourceRoleExecutionRef` from the run manifest's canonical role state. It sets `sourceRoleExecutionRef` to the selected source `RoleExecution` row's `roleExecutionRef`, not that row's `sourceRoleExecutionRef` field.
|
|
88
90
|
6. Do not write a queue or classification in this grouped-input artifact. `okstra convergence seed` classifies Round 0 by mode:
|
|
89
91
|
- Collaborative mode: multi-source groups become `full-consensus` immediately; only single-source groups enter the working queue.
|
|
90
92
|
- Adversarial mode: every finding enters the working queue regardless of source count. Semantic grouping merges provenance only; it does not decide a finding is reliable.
|
|
@@ -254,7 +256,7 @@ row names the invocation, replacement is rejected even for v1 and the prompt is
|
|
|
254
256
|
history. Do not delete prompt, metadata, or reservation files by hand.
|
|
255
257
|
|
|
256
258
|
Run `okstra agent-prompt verify --run-manifest <path> --metadata
|
|
257
|
-
<metadataPath> --
|
|
259
|
+
<metadataPath> --text` immediately before dispatch. A failed verification is a
|
|
258
260
|
pre-dispatch contract failure. For `runner=native-session`, pass only the
|
|
259
261
|
returned `hostModelValue` to the host model argument. For
|
|
260
262
|
`runner=cli-wrapper`, follow the planned execution surface after
|
|
@@ -298,9 +300,9 @@ Assigned worker prompt history path: <Project Root>/<Prompt History Path>
|
|
|
298
300
|
|
|
299
301
|
Before dispatch, materialize `**Audit sidecar path:**` by passing the exact reverify `**Result Path:**` through `okstra_ctl.worker_artifact_paths.audit_sidecar_rel()` and resolving that project-relative result against `**Project Root:**`. Write the resulting absolute path into the header. The lead MUST NOT construct the audit filename from a role, task type, round, or sequence independently.
|
|
300
302
|
|
|
301
|
-
The two
|
|
303
|
+
The two error-path anchors carry the same absolute values the lead forwarded in the initial Phase 4 dispatch for that role (source: the launch prompt's `## Run Logs (error-log wiring)` section). Workers use the errors log path with the typed error-log command from [team-contract](./team-contract.md) "Error reporting". The errors sidecar path only reserves the runtime-owned write-artifact path used by dispatch validation; no model-authored error JSON file is part of reverify.
|
|
302
304
|
|
|
303
|
-
Relative to the Phase 4 anchor set rendered by `okstra_ctl.worker_prompt_headers.worker_prompt_headers()`, a reverify prompt drops two anchors whose targets lightweight mode never reads: `**Worker Preamble Path:**` and `**
|
|
305
|
+
Relative to the Phase 4 anchor set rendered by `okstra_ctl.worker_prompt_headers.worker_prompt_headers()`, a reverify prompt drops two anchors whose targets lightweight mode never reads: `**Worker Preamble Path:**` and `**Worker Error Contract Path:**`.
|
|
304
306
|
|
|
305
307
|
**Where the composer's sections go.** `okstra agent-prompt materialize` (§"Invocation materialization gate") writes the dispatched body itself, as: these anchors, then the model-assignment block it appends (`**Provider:**`, `**Model:**`, `**Model execution value:**`, `**Runner:**`, `**Host runtime:**`, and `**Host model value:**` for a native host), then `## Duty Contract`, then `## Task Instructions` followed verbatim by the task-instructions file the lead wrote. So the lead authors only the last part, and every rule below about ordering — the phase boundary before the instruction headings, the `**Model:** <role>, <modelExecutionValue>` line — is about the lead's own file, not about the composed document. The composer's `**Model:** <modelExecutionValue>` anchor is a different line with a different shape; do not try to reshape it, and do not count it among the 8.
|
|
306
308
|
|
|
@@ -687,7 +689,7 @@ say so explicitly for that half; silence on one half is an incomplete result.
|
|
|
687
689
|
```
|
|
688
690
|
|
|
689
691
|
### Gap verification (1 adversarial reverify round)
|
|
690
|
-
Each critic gap enters the verification queue as a finding with `originWorker = "<provider>-critic"` and `source = "critic"`. The lead runs ONE adversarial reverify round (§"Adversarial Verification Mode" classifier) with
|
|
692
|
+
Each critic gap enters the verification queue as a finding with `originWorker = "<provider>-critic"` and `source = "critic"`. The lead runs ONE adversarial reverify round (§"Adversarial Verification Mode" classifier) with **every Phase 4 analyser as a voter**. Choosing a critic provider that is already in the analyser roster costs nothing: the critic is a different role contract, a different duty and a different session, so an analyser is not disqualified by sharing its provider name (ADR-0017 — provider and model are not role identity, and the same model assigned to two roles gets two independent workers). The critic cannot judge its own gaps because it is not an analyser: the voter roster is `workers[]` filtered to `audience == "analysis"`, and a critic is not even representable there (the allowed values are `analysis` / `lead` / `report-writer`). `okstra apply-critic-gaps` refuses a vote from anyone outside that roster (`critic voter must be a non-critic analyser`). Only gaps classified `full-consensus` / `partial-consensus` merge into the final report findings; `contested` / `worker-unique` gaps are treated as hallucinations and dropped (recorded in the convergence state, not promoted).
|
|
691
693
|
|
|
692
694
|
**A gap that received no verdict is NOT a rejected gap (BLOCKING).** Dropping applies only to gaps the voters actually judged. A gap can also end the round *unjudged* — the verification dispatch returned a terminal non-result (`timeout`, `error`, no result file), the returned result covered only some of the gaps, or no non-critic analyser was available to vote at all. Nobody inspected those, so classifying them as hallucinations is a fabricated verdict. Each one MUST be recorded as a `## 5. Missing Information and Risks` row (`missingInformation`, `source: "critic-unverified"`) whose `risk` names the gap and the reason verification did not complete, and counted in `config.critic.gapsUnverified`. They are **not** promoted to findings (unverified) and **not** raised as `clarification` items — an unverified gap needs an analyser to verify it on the next run, not a decision from the user. Silently losing them is a contract violation: the batch that times out is exactly the batch of gaps too expensive to check, so the highest-risk items are the ones that vanish.
|
|
693
695
|
|
|
@@ -738,7 +740,7 @@ so explicitly.
|
|
|
738
740
|
|
|
739
741
|
### Verification — confirm-or-downgrade (BLOCKING)
|
|
740
742
|
|
|
741
|
-
Each candidate blocker is verified by the Phase 4 analysers
|
|
743
|
+
Each candidate blocker is verified by the Phase 4 analysers — all of them, on the same roster rule as §"critic gaps" above; sharing the critic's provider name does not disqualify an analyser. Do NOT use the adversarial finding classifier's "uncertain → reject" rule here.
|
|
742
744
|
- Do NOT run `apply-critic-gaps` for this mode. That reducer implements coverage merge/drop semantics and rejects `acceptance-devils-advocate` input.
|
|
743
745
|
- **Confirmed** (an analyser reproduces it or cites supporting evidence) → promote to a `## 5.8 Acceptance Blockers` row (keep severity + recommended follow-up phase).
|
|
744
746
|
- **Not confirmed** (cannot reproduce, or evidence is weak) → **downgrade to a Residual Risk row — never drop it.** Record the escalation trigger so the user can re-judge a high-severity-but-unconfirmed candidate.
|