okstra 0.180.0 → 0.184.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- 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 +13 -2
- package/docs/cli.md +31 -15
- 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 +30 -27
- package/docs/task-process/README.md +1 -1
- package/docs/task-process/common-flow.md +2 -3
- package/docs/task-process/error-analysis.md +3 -4
- package/docs/task-process/final-verification.md +2 -3
- package/docs/task-process/implementation-planning.md +2 -3
- package/docs/task-process/implementation.md +9 -7
- package/docs/task-process/release-handoff.md +3 -4
- package/docs/task-process/requirements-discovery.md +3 -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 +11 -14
- 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 +26 -36
- package/runtime/prompts/lead/plan-body-verification.md +211 -30
- package/runtime/prompts/lead/report-writer.md +23 -4
- 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-executor.md +1 -0
- package/runtime/prompts/profiles/_implementation-verifier.md +4 -4
- package/runtime/prompts/profiles/final-verification.md +1 -1
- package/runtime/prompts/profiles/implementation-planning.md +17 -13
- package/runtime/prompts/profiles/release-handoff.md +0 -1
- package/runtime/prompts/wizard/prompts.ko.json +7 -11
- 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/conformance.py +37 -1
- 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 +89 -39
- 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 +525 -5
- package/runtime/python/okstra_ctl/plan_items_cli.py +842 -32
- 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 +30 -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 +50 -117
- 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 +21 -0
- package/runtime/schemas/final-report-v3.0.schema.json +21 -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 +9 -9
- 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 +527 -113
- package/runtime/validators/validate_session_conformance.py +65 -10
|
@@ -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
|
|
|
@@ -102,19 +98,19 @@ For a new `implementation-planning` run, the plan-body sequence is initial verif
|
|
|
102
98
|
|
|
103
99
|
### Incremental re-verification (implementation-planning clarification re-runs only)
|
|
104
100
|
|
|
105
|
-
The **default is full re-verification**.
|
|
101
|
+
The **default is full re-verification**. Narrow this re-run to the impacted stages only when the deterministic `okstra incremental-scope` CLI returns `mode == "incremental"`. When the wizard pin is `auto` and the CLI returns `mode == "incremental"`, do not upgrade to full — the CLI already applied the base-ref check, the dependency closure, and the cutoff. This procedure fires ONLY when this run's task-type is `implementation-planning` AND a prior final report exists for this task-key (its data.json at `runs/implementation-planning/reports/final-report-implementation-planning-<prev-seq>.data.json`, where `<prev-seq>` is the most recent prior implementation-planning run's seq). For every other task-type, ignore this block and re-verify normally. This branches on the CLI's `mode` output only — it does NOT re-implement the safety logic in the prompt.
|
|
106
102
|
|
|
107
|
-
0. **Honour the scope the user already pinned (not a judgement — an instruction).** The wizard asks for a re-verification scope whenever this re-run is narrowable, and the answer arrives as two tokens: mode `{{REVERIFY_SCOPE_MODE}}`, stages `{{REVERIFY_SCOPE_STAGES}}`. Apply it before you form your own view:
|
|
108
|
-
- `auto` — the user left the decision to this procedure. Run steps 1–
|
|
103
|
+
0. **Honour the scope the user already pinned (not a judgement — an instruction).** The wizard asks for a re-verification scope whenever this re-run is narrowable or an answered id traces to no stage, and the answer arrives as two tokens: mode `{{REVERIFY_SCOPE_MODE}}`, stages `{{REVERIFY_SCOPE_STAGES}}`. Apply it before you form your own view:
|
|
104
|
+
- `auto` — the user left the decision to this procedure. Run steps 1–7 exactly as written; nothing is pinned. If the CLI returns `mode == "incremental"`, keep it; do not upgrade to full.
|
|
109
105
|
- `full` — the user asked for full re-verification. Still call the CLI once (the record is the audit trail), passing `--full-reason "user requested full re-verification"` and every other CSV empty. Do not argue the user out of it with a narrower `--impacted`: the answer already weighed the cost.
|
|
110
106
|
- `stages` — the user named the stages that must be re-verified. Put **every** number in `{{REVERIFY_SCOPE_STAGES}}` into `--impacted`, unioned with any stage you resolve yourself. Never drop one because your own back-trace did not reach it — the user is telling you about a blast radius the prior report failed to record, which is exactly what the back-trace cannot see. The CLI still applies the dependency closure and the cutoff on top, so a wide enough pin correctly ends in `mode == "full"`.
|
|
111
107
|
1. **List the answered clarifications (a fact, not a judgement).** Collect the `C-NNN` ids you reconciled as answered in §1, and the IDs of any PREP items changed by the carried response. Pass the ids through `--answered-clarifications`; the CLI resolves which Stage Map stages each one touches by reading the prior run's own links — the `P-*` plan item that carried that `clarificationId`, and the requirement-coverage row blocked on `C-NNN` in either its `status` or its `approvalDisposition` (a `documented-deviation` row records the block in the latter). Do NOT map answers to stage numbers yourself.
|
|
112
|
-
- An id that traces to no stage in the prior report
|
|
113
|
-
- **Structural change is your call, and you declare it.** When an answer overturns the selected Option, restructures the stages, or changes the recommended approach, pass `--full-reason "<what changes and how>"`. It forces `mode == "full"` regardless of every other input — the back-trace resolves stages, it cannot judge whether the plan's shape survived. Do NOT express this by leaving the CSVs empty
|
|
108
|
+
- An id that traces to no stage in the prior report does **not** force `mode == "full"` for the whole re-run. The CLI returns `mode == "unresolved"` and names the ids. Ask the user for the stage numbers those answers affect, then call the CLI again with those numbers in `--impacted`. Do not drop the unlinked id from `--answered-clarifications`. Do not treat `unresolved` as full, and do not silently narrow to the ids that did trace. An approval blocker in this shape should have failed the prior report's back-trace; naming stages is the remaining outlet.
|
|
109
|
+
- **Structural change is your call, and you declare it.** When an answer overturns the selected Option, restructures the stages, or changes the recommended approach, pass `--full-reason "<what changes and how>"`. It forces `mode == "full"` regardless of every other input — the back-trace resolves stages, it cannot judge whether the plan's shape survived. Do NOT express this by leaving the CSVs empty. `--impacted` remains available for stage numbers you resolved yourself. `--full-reason` is the only structural path that still forces full.
|
|
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 \
|
|
@@ -128,8 +124,9 @@ The **default is full re-verification**. Only narrow this re-run to the impacted
|
|
|
128
124
|
```
|
|
129
125
|
The CLI reads the plan's dependency graph from the prior `implementationPlanning.stageMap`, which is authoritative for the impacted stage numbers. The CLI prints JSON `{mode, reverify_stages, carry_stages, reason}`. Instruct the report writer to record this decision in its narrative as `implementationPlanning.incrementalDecision`, using camel-case array keys `reverifyStages` and `carryStages`. Final report assembly preserves that writer-owned decision.
|
|
130
126
|
4. **`mode == "full"`** → run the existing full re-verification path unchanged; ignore `reverify_stages` / `carry_stages`.
|
|
131
|
-
5. **`mode == "incremental"`** → scope every worker dispatch prompt to `reverify_stages` only (the downstream closure of the impacted stages). Do NOT re-analyze `carry_stages` — their prior plan-item verdicts are carried forward verbatim (see `prompts/profiles/implementation-planning.md` "Cross-verification mode" and `prompts/lead/convergence.md` "Convergence scope").
|
|
132
|
-
6.
|
|
127
|
+
5. **`mode == "incremental"`** → scope every worker dispatch prompt to `reverify_stages` only (the downstream closure of the impacted stages). Do NOT re-analyze `carry_stages` — their prior plan-item verdicts are carried forward verbatim (see `prompts/profiles/implementation-planning.md` "Cross-verification mode" and `prompts/lead/convergence.md` "Convergence scope"). When the pin in step 0 was `auto`, this is the decision — do not upgrade it to full.
|
|
128
|
+
6. **`mode == "unresolved"`** → ask the user for stage numbers; re-enter step 3 with those numbers in `--impacted`. Do not fall back to full. Do not record `unresolved` as `incrementalDecision`. Then continue from the new `mode`.
|
|
129
|
+
7. **Merge carried-forward verdicts.** In `incremental` mode, the report writer includes every `carry_stages` stage row unchanged in its narrative. After `okstra plan-items seed --narrative ... --state ...`, the lead runs:
|
|
133
130
|
```
|
|
134
131
|
okstra incremental-carry \
|
|
135
132
|
--prev-data runs/implementation-planning/reports/final-report-implementation-planning-<prev-seq>.data.json \
|
|
@@ -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.
|