okstra 0.179.2 → 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/README.md +1 -1
- package/dist/cli-registry.mjs +30 -2
- package/dist/cli-registry.mjs.map +1 -1
- package/dist/commands/execute/incremental-carry.mjs +9 -8
- package/dist/commands/execute/incremental-carry.mjs.map +1 -1
- package/dist/commands/execute/plan-verify.mjs +3 -1
- package/dist/commands/execute/plan-verify.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/approval-decision.d.mts +1 -0
- package/dist/commands/report/approval-decision.mjs +21 -0
- package/dist/commands/report/approval-decision.mjs.map +1 -0
- package/dist/commands/report/design-snapshot.d.mts +1 -0
- package/dist/commands/report/design-snapshot.mjs +19 -0
- package/dist/commands/report/design-snapshot.mjs.map +1 -0
- 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/storage-model.md +1 -1
- package/docs/architecture.md +21 -10
- package/docs/cli.md +36 -20
- 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 +43 -31
- package/docs/task-process/implementation-planning.md +2 -2
- 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 +15 -164
- 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 +9 -12
- package/runtime/prompts/lead/adapters/cmux.md +1 -1
- package/runtime/prompts/lead/context-loader.md +41 -141
- package/runtime/prompts/lead/convergence.md +10 -8
- package/runtime/prompts/lead/okstra-lead-contract.md +40 -49
- package/runtime/prompts/lead/plan-body-verification.md +217 -23
- package/runtime/prompts/lead/report-writer.md +81 -421
- package/runtime/prompts/lead/team-contract.md +9 -54
- package/runtime/prompts/profiles/_clarification-recommendation.md +5 -4
- package/runtime/prompts/profiles/_coding-conventions-preflight.md +3 -2
- package/runtime/prompts/profiles/_common-contract.md +4 -4
- package/runtime/prompts/profiles/_implementation-deliverable.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/change-impact-analysis.md +1 -1
- package/runtime/prompts/profiles/error-analysis.md +1 -1
- package/runtime/prompts/profiles/feature-analysis.md +1 -1
- package/runtime/prompts/profiles/final-verification.md +1 -1
- package/runtime/prompts/profiles/implementation-planning.md +20 -12
- package/runtime/prompts/profiles/improvement-discovery.md +1 -1
- package/runtime/prompts/profiles/project-analysis.md +1 -1
- package/runtime/prompts/profiles/release-handoff.md +0 -1
- package/runtime/prompts/profiles/requirements-discovery.md +1 -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 +8 -2
- 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/external/relay.md +1 -1
- 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 +141 -38
- package/runtime/python/okstra_ctl/agent_invocation.py +19 -6
- package/runtime/python/okstra_ctl/agent_prompt_cli.py +70 -23
- package/runtime/python/okstra_ctl/analysis_inputs.py +5 -4
- package/runtime/python/okstra_ctl/analysis_packet.py +124 -3
- package/runtime/python/okstra_ctl/approval_decisions.py +328 -0
- 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/design_snapshot.py +134 -0
- package/runtime/python/okstra_ctl/dispatch_core.py +97 -69
- package/runtime/python/okstra_ctl/dispatch_state.py +163 -63
- 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/execution_mutation_audit.py +6 -2
- package/runtime/python/okstra_ctl/final_report_schema.py +26 -17
- 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 +130 -17
- package/runtime/python/okstra_ctl/incremental_scope.py +12 -4
- 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/path_hints.py +12 -0
- package/runtime/python/okstra_ctl/paths.py +21 -0
- package/runtime/python/okstra_ctl/plan_items.py +115 -4
- package/runtime/python/okstra_ctl/plan_items_cli.py +626 -34
- package/runtime/python/okstra_ctl/ports/worker_dispatch.py +2 -1
- 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 +74 -16
- package/runtime/python/okstra_ctl/render_final_report.py +10 -8
- package/runtime/python/okstra_ctl/report_assembly.py +509 -0
- package/runtime/python/okstra_ctl/report_contract.py +2 -1
- package/runtime/python/okstra_ctl/report_finalize.py +67 -32
- package/runtime/python/okstra_ctl/report_html/render.py +3 -2
- package/runtime/python/okstra_ctl/report_inputs.py +72 -0
- package/runtime/python/okstra_ctl/report_language.py +3 -2
- package/runtime/python/okstra_ctl/report_markdown.py +81 -8
- package/runtime/python/okstra_ctl/report_narrative.py +351 -0
- package/runtime/python/okstra_ctl/report_projections.py +265 -0
- 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 +184 -65
- 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 +15 -8
- 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 +8 -6
- package/runtime/python/okstra_ctl/stage_ledger.py +132 -18
- package/runtime/python/okstra_ctl/stage_map.py +96 -28
- package/runtime/python/okstra_ctl/stage_targets.py +3 -4
- package/runtime/python/okstra_ctl/team.py +3 -2
- 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_dispatch.py +5 -2
- package/runtime/python/okstra_ctl/worker_prompt_body.py +49 -3
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +3 -2
- package/runtime/python/okstra_ctl/worker_prompt_policy.py +31 -3
- 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 +10219 -0
- package/runtime/schemas/report-narrative-v3.0.schema.json +30 -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 +29 -19
- package/runtime/templates/reports/html/macros/forms.html +6 -4
- package/runtime/templates/reports/schedule.template.md +4 -4
- package/runtime/templates/worker-error-contract.md +17 -29
- package/runtime/validators/validate-run.py +636 -72
- 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 \
|
|
@@ -126,19 +122,20 @@ The **default is full re-verification**. Only narrow this re-run to the impacted
|
|
|
126
122
|
--answered-clarifications <csv of answered C-NNN ids, empty when none> \
|
|
127
123
|
--full-reason "<empty, or what structural change forces full>"
|
|
128
124
|
```
|
|
129
|
-
The CLI reads the plan's dependency graph from the
|
|
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
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").
|
|
132
|
-
6. **Merge carried-forward verdicts.** In `incremental` mode,
|
|
128
|
+
6. **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
129
|
```
|
|
134
130
|
okstra incremental-carry \
|
|
135
131
|
--prev-data runs/implementation-planning/reports/final-report-implementation-planning-<prev-seq>.data.json \
|
|
136
|
-
--cur-
|
|
132
|
+
--cur-narrative <this run's report-writer narrative> \
|
|
133
|
+
--state <this run's plan-body-verification state> \
|
|
137
134
|
--prev-seq <prev-seq> \
|
|
138
135
|
--carry-stages <csv from incrementalDecision.carry_stages> \
|
|
139
136
|
--reverify-stages <csv from incrementalDecision.reverify_stages> \
|
|
140
|
-
--out <this run's
|
|
137
|
+
--out-state <this run's plan-body-verification state>
|
|
141
138
|
```
|
|
142
|
-
A non-zero exit
|
|
139
|
+
A non-zero exit means the writer changed or omitted a carried stage, the item set drifted, or the stage scopes conflict. Fall back to **full** and re-verify every stage. The command writes only the convergence-owned plan state. It never patches the writer narrative or final `data.json`. `verdictCard` / `finalVerdict` are never carried.
|
|
143
140
|
|
|
144
141
|
**Carry completeness (BLOCKING).** In incremental mode, this run's `planItems` MUST contain every plan-item id from the re-verified stages, each carried forward with its updated verdict. If re-verification concludes a plan item should be REMOVED, that is a signal the answer's blast radius is NOT local — abandon incremental and re-route to a FULL re-verification. The carry merge only ever ADDS prior items whose id is absent from this run; it cannot distinguish a legitimate deletion from an untouched carry, so it would resurrect a stale verdict.
|
|
@@ -64,7 +64,7 @@ Use the screen to tell "still working" from "stuck", and to see at a glance whic
|
|
|
64
64
|
- **v1 entry**: carries `workerId`, `provider`, `promptPath`, and `workerResultPath`, and must carry none of the v2 identity fields.
|
|
65
65
|
- `resultPath` and `completionPaths` are advisory in both: dispatch derives them from the same rules the roster path uses, so a jobs file cannot disagree with a roster dispatch about which artifact is the result.
|
|
66
66
|
- `workerResultPath` must carry the canonical `-worker-` token (`<role>-worker-<task-type>-<seq>.md`); the audit sidecar name is derived from it by inserting `-audit-` after that token, so a reverify name like `<role>-reverify-r1-<task-type>-<seq>.md` is refused with `worker result path has no canonical -worker- token`. The round belongs in `dispatchKind` and `invocationRef`, not in the artifact name.
|
|
67
|
-
- `role` names the role execution's own role — `verifier` for reverify, `report-writer` for the report writer. It is not a per-round label: `dispatch_state.py` requires the entry's `role` to equal both the role execution's `role` and the duty's role, so a value like `worker-reverify-r<N>` is refused as `jobs file v2 identity does not match role execution authority`. The round lives in `dispatchKind` and in `invocationRef`. The report-writer completion paths include
|
|
67
|
+
- `role` names the role execution's own role — `verifier` for reverify, `report-writer` for the report writer. It is not a per-round label: `dispatch_state.py` requires the entry's `role` to equal both the role execution's `role` and the duty's role, so a value like `worker-reverify-r<N>` is refused as `jobs file v2 identity does not match role execution authority`. The round lives in `dispatchKind` and in `invocationRef`. The report-writer completion paths include its narrative Markdown, worker-result pointer, and audit sidecar; they do not include the Phase 7 report record.
|
|
68
68
|
- After either dispatch, run `okstra team await --project-root <root> --run-manifest <path>` before evaluating terminal status or completion paths.
|
|
69
69
|
|
|
70
70
|
## Completion, cleanup, and resume
|
|
@@ -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.
|