okstra 0.146.1 → 0.148.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 +23 -9
- package/docs/architecture/storage-model.md +39 -65
- package/docs/architecture.md +68 -60
- package/docs/cli.md +40 -23
- package/docs/for-ai/skills/okstra-run.md +13 -34
- package/docs/performance-improvement-plan-v2.md +2 -2
- package/docs/pr-template-usage.md +1 -1
- package/docs/project-structure-overview.md +26 -22
- package/docs/task-process/README.md +4 -4
- package/docs/task-process/common-flow.md +12 -12
- package/docs/task-process/final-verification.md +2 -2
- package/docs/task-process/implementation.md +1 -1
- package/docs/task-process/release-handoff.md +1 -1
- package/package.json +2 -2
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/antigravity-worker.md +2 -2
- package/runtime/agents/workers/claude-worker.md +1 -1
- package/runtime/agents/workers/codex-worker.md +2 -2
- package/runtime/agents/workers/grok-worker.md +256 -0
- package/runtime/agents/workers/kimi-worker.md +256 -0
- package/runtime/agents/workers/report-writer-worker.md +12 -12
- package/runtime/bin/lib/okstra/cli.sh +13 -1
- package/runtime/bin/lib/okstra/globals.sh +3 -0
- package/runtime/bin/lib/okstra/usage.sh +17 -12
- package/runtime/bin/okstra-grok-exec.sh +5 -0
- package/runtime/bin/okstra-kimi-exec.sh +5 -0
- package/runtime/bin/okstra-provider-exec.py +235 -0
- package/runtime/bin/okstra-render-final-report.py +4 -4
- package/runtime/bin/okstra-render-report-views.py +100 -12
- package/runtime/bin/okstra.sh +3 -0
- package/runtime/prompts/lead/adapters/antigravity.md +48 -0
- package/runtime/prompts/lead/adapters/claude-code.md +13 -11
- package/runtime/prompts/lead/adapters/codex.md +7 -7
- package/runtime/prompts/lead/okstra-lead-contract.md +5 -5
- package/runtime/prompts/lead/report-writer.md +16 -12
- package/runtime/prompts/profiles/_coding-conventions-preflight.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +16 -10
- package/runtime/prompts/profiles/_implementation-deliverable.md +2 -2
- package/runtime/prompts/profiles/_implementation-diff-review.md +1 -1
- package/runtime/prompts/profiles/_implementation-executor.md +12 -12
- package/runtime/prompts/profiles/_implementation-self-check.md +4 -4
- package/runtime/prompts/profiles/_implementation-verifier.md +3 -3
- package/runtime/prompts/profiles/change-impact-analysis.md +2 -0
- package/runtime/prompts/profiles/error-analysis.md +2 -0
- package/runtime/prompts/profiles/feature-analysis.md +2 -0
- package/runtime/prompts/profiles/final-verification.md +3 -1
- package/runtime/prompts/profiles/forbidden-actions.json +4 -4
- package/runtime/prompts/profiles/implementation-planning.md +3 -1
- package/runtime/prompts/profiles/implementation.md +2 -2
- package/runtime/prompts/profiles/improvement-discovery.md +6 -2
- package/runtime/prompts/profiles/project-analysis.md +2 -0
- package/runtime/prompts/profiles/release-handoff.md +7 -7
- package/runtime/prompts/profiles/requirements-discovery.md +2 -0
- package/runtime/prompts/wizard/prompts.ko.json +9 -1
- package/runtime/python/okstra_ctl/codex_dispatch.py +68 -87
- package/runtime/python/okstra_ctl/dispatch_core.py +4 -22
- package/runtime/python/okstra_ctl/final_report_schema.py +37 -12
- package/runtime/python/okstra_ctl/lead_events.py +1 -1
- package/runtime/python/okstra_ctl/lead_runtime.py +13 -2
- package/runtime/python/okstra_ctl/models.py +156 -8
- package/runtime/python/okstra_ctl/path_hints.py +9 -25
- package/runtime/python/okstra_ctl/paths.py +1 -1
- package/runtime/python/okstra_ctl/render.py +172 -74
- package/runtime/python/okstra_ctl/render_final_report.py +136 -28
- package/runtime/python/okstra_ctl/report_contract.py +124 -0
- package/runtime/python/okstra_ctl/report_finalize.py +1 -1
- package/runtime/python/okstra_ctl/report_html/__init__.py +10 -0
- package/runtime/python/okstra_ctl/report_html/common.py +86 -0
- package/runtime/python/okstra_ctl/report_html/filters.py +104 -0
- package/runtime/python/okstra_ctl/report_html/models.py +59 -0
- package/runtime/python/okstra_ctl/report_html/render.py +76 -0
- package/runtime/python/okstra_ctl/report_html/router.py +40 -0
- package/runtime/python/okstra_ctl/report_html/view_models/__init__.py +1 -0
- package/runtime/python/okstra_ctl/report_html/view_models/change_impact_analysis.py +39 -0
- package/runtime/python/okstra_ctl/report_html/view_models/error_analysis.py +49 -0
- package/runtime/python/okstra_ctl/report_html/view_models/feature_analysis.py +39 -0
- package/runtime/python/okstra_ctl/report_html/view_models/final_verification.py +47 -0
- package/runtime/python/okstra_ctl/report_html/view_models/implementation.py +47 -0
- package/runtime/python/okstra_ctl/report_html/view_models/implementation_planning.py +103 -0
- package/runtime/python/okstra_ctl/report_html/view_models/improvement_discovery.py +43 -0
- package/runtime/python/okstra_ctl/report_html/view_models/project_analysis.py +54 -0
- package/runtime/python/okstra_ctl/report_html/view_models/release_handoff.py +54 -0
- package/runtime/python/okstra_ctl/report_html/view_models/requirements_discovery.py +55 -0
- package/runtime/python/okstra_ctl/report_html/visualizations.py +139 -0
- package/runtime/python/okstra_ctl/report_view_artifacts.py +4 -1
- package/runtime/python/okstra_ctl/report_views.py +15 -43
- package/runtime/python/okstra_ctl/run.py +276 -51
- package/runtime/python/okstra_ctl/runner_resolution.py +103 -0
- package/runtime/python/okstra_ctl/schema_excerpt.py +7 -17
- package/runtime/python/okstra_ctl/team.py +2 -7
- package/runtime/python/okstra_ctl/wizard.py +194 -21
- package/runtime/python/okstra_ctl/worker_artifacts.py +46 -0
- package/runtime/python/okstra_ctl/workers.py +3 -1
- package/runtime/python/okstra_ctl/workflow.py +4 -2
- package/runtime/python/okstra_token_usage/__init__.py +1 -0
- package/runtime/python/okstra_token_usage/collect.py +32 -23
- package/runtime/python/okstra_token_usage/pricing.py +35 -3
- package/runtime/schemas/final-report-v2.0.schema.json +3923 -0
- package/runtime/skills/okstra-run/SKILL.md +31 -42
- package/runtime/templates/prd/pr-body.template.md +1 -1
- package/runtime/templates/reports/final-report-v2.template.md +66 -0
- package/runtime/templates/reports/html/assets/base.css +41 -0
- package/runtime/templates/reports/html/assets/base.js +5 -0
- package/runtime/templates/reports/html/base.template.html +79 -0
- package/runtime/templates/reports/html/macros/forms.html +47 -0
- package/runtime/templates/reports/html/macros/layout.html +19 -0
- package/runtime/templates/reports/html/macros/visualizations.html +27 -0
- package/runtime/templates/reports/html/tasks/change-impact-analysis.template.html +40 -0
- package/runtime/templates/reports/html/tasks/error-analysis.template.html +40 -0
- package/runtime/templates/reports/html/tasks/feature-analysis.template.html +40 -0
- package/runtime/templates/reports/html/tasks/final-verification.template.html +39 -0
- package/runtime/templates/reports/html/tasks/implementation-planning.template.html +47 -0
- package/runtime/templates/reports/html/tasks/implementation.template.html +40 -0
- package/runtime/templates/reports/html/tasks/improvement-discovery.template.html +29 -0
- package/runtime/templates/reports/html/tasks/project-analysis.template.html +57 -0
- package/runtime/templates/reports/html/tasks/release-handoff.template.html +36 -0
- package/runtime/templates/reports/html/tasks/requirements-discovery.template.html +37 -0
- package/runtime/templates/reports/report.js +21 -4
- package/runtime/templates/reports/settings.template.json +4 -0
- package/runtime/templates/reports/task-brief.template.md +7 -7
- package/runtime/validators/validate-report-views.py +86 -4
- package/runtime/validators/validate-run.py +73 -15
- package/runtime/validators/validate_improvement_report.py +55 -0
- package/runtime/validators/validate_session_conformance.py +2 -1
- package/src/cli-registry.mjs +4 -4
- package/src/commands/execute/codex-dispatch.mjs +7 -10
- package/src/commands/execute/render-bundle.mjs +3 -3
- package/src/commands/execute/run.mjs +17 -52
- package/src/commands/execute/wizard.mjs +4 -1
- package/src/commands/lifecycle/doctor.mjs +6 -3
- package/src/commands/lifecycle/install.mjs +49 -21
- package/src/commands/report/finalize.mjs +2 -3
- package/src/commands/report/render-final-report.mjs +4 -2
- package/src/commands/report/render-views.mjs +8 -8
- package/src/lib/runtime-manifest.mjs +1 -1
- package/src/lib/runtime-resolver.mjs +2 -2
- package/src/lib/worker-agent-render.mjs +50 -0
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""CLI entrypoint for Phase 7 step 1.5 — render
|
|
3
|
-
view of an okstra final-report markdown.
|
|
2
|
+
"""CLI entrypoint for Phase 7 step 1.5 — render a final-report HTML view.
|
|
4
3
|
|
|
5
4
|
Usage:
|
|
6
|
-
okstra-render-report-views.py <path-to-final-report.md>
|
|
5
|
+
okstra-render-report-views.py <path-to-final-report.data.json|final-report.md>
|
|
7
6
|
[--task-key <task-group/task-id>]
|
|
8
7
|
[--task-type <profile>]
|
|
9
8
|
[--seq <NNN>]
|
|
10
9
|
[--source-report <relative-path>]
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
Schema-v2 ``.data.json`` input is rendered directly into the dedicated task
|
|
12
|
+
HTML template and always produces an HTML sibling. Markdown input resolves its
|
|
13
|
+
data sibling first; schema-v1 and quick reports keep the legacy conditional
|
|
14
|
+
Markdown renderer.
|
|
15
15
|
|
|
16
16
|
Output (idempotent — overwrites):
|
|
17
17
|
- <stem>.html — single-file self-contained HTML view
|
|
@@ -22,13 +22,19 @@ This script is the canonical single-reference-point. The Node CLI
|
|
|
22
22
|
from __future__ import annotations
|
|
23
23
|
|
|
24
24
|
import argparse
|
|
25
|
+
import json
|
|
25
26
|
import os
|
|
27
|
+
import re
|
|
26
28
|
import sys
|
|
27
29
|
from pathlib import Path
|
|
28
30
|
|
|
29
31
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
30
32
|
SCRIPTS_DIR = REPO_ROOT / "scripts"
|
|
31
|
-
HOME_LIB =
|
|
33
|
+
HOME_LIB = (
|
|
34
|
+
Path(os.environ.get("OKSTRA_HOME", str(Path.home() / ".okstra")))
|
|
35
|
+
/ "lib"
|
|
36
|
+
/ "python"
|
|
37
|
+
)
|
|
32
38
|
|
|
33
39
|
# Prefer dev sources when present, fall back to install. Without this
|
|
34
40
|
# order, a stale install (~/.okstra/lib/python/okstra_ctl) without the
|
|
@@ -43,6 +49,10 @@ elif HOME_LIB.is_dir() and str(HOME_LIB) not in sys.path:
|
|
|
43
49
|
sys.path.insert(0, str(HOME_LIB))
|
|
44
50
|
|
|
45
51
|
from okstra_ctl.report_views import infer_run_meta, render_html_view # noqa: E402
|
|
52
|
+
from okstra_ctl.final_report_paths import ( # noqa: E402
|
|
53
|
+
final_report_data_path,
|
|
54
|
+
final_report_markdown_path,
|
|
55
|
+
)
|
|
46
56
|
|
|
47
57
|
|
|
48
58
|
_OKSTRA_HOME = Path(os.environ.get("OKSTRA_HOME", str(Path.home() / ".okstra")))
|
|
@@ -77,6 +87,60 @@ def _load_assets() -> tuple[str, str]:
|
|
|
77
87
|
return css_text, js_text
|
|
78
88
|
|
|
79
89
|
|
|
90
|
+
def _templates_root() -> Path:
|
|
91
|
+
for directory in _TEMPLATES_DIRS:
|
|
92
|
+
if (directory / "html" / "base.template.html").is_file():
|
|
93
|
+
return directory
|
|
94
|
+
raise SystemExit(
|
|
95
|
+
"schema-v2 HTML templates not found. Looked under: "
|
|
96
|
+
+ ", ".join(str(directory) for directory in _TEMPLATES_DIRS)
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _report_pair(report_path: Path) -> tuple[Path, Path]:
|
|
101
|
+
if report_path.name.endswith(".data.json"):
|
|
102
|
+
return report_path, final_report_markdown_path(report_path)
|
|
103
|
+
return final_report_data_path(report_path), report_path
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _load_data_if_present(data_path: Path) -> dict | None:
|
|
107
|
+
if not data_path.is_file():
|
|
108
|
+
return None
|
|
109
|
+
try:
|
|
110
|
+
data = json.loads(data_path.read_text(encoding="utf-8"))
|
|
111
|
+
except json.JSONDecodeError as exc:
|
|
112
|
+
raise SystemExit(
|
|
113
|
+
f"final-report data is not valid JSON: {data_path} ({exc})"
|
|
114
|
+
) from exc
|
|
115
|
+
if not isinstance(data, dict):
|
|
116
|
+
raise SystemExit(f"final-report data must be a JSON object: {data_path}")
|
|
117
|
+
return data
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _v2_run_meta(data: dict, markdown_path: Path, args: argparse.Namespace):
|
|
121
|
+
from okstra_ctl.report_html.models import HtmlRunMeta
|
|
122
|
+
|
|
123
|
+
header = data.get("header", {})
|
|
124
|
+
task_key = args.task_key or header.get("taskKey")
|
|
125
|
+
task_type = args.task_type or header.get("taskType")
|
|
126
|
+
match = re.search(r"-(\d+)\.md$", markdown_path.name)
|
|
127
|
+
seq = (
|
|
128
|
+
args.seq
|
|
129
|
+
or data.get("analysisCommon", {}).get("runSeq")
|
|
130
|
+
or (match.group(1) if match else None)
|
|
131
|
+
)
|
|
132
|
+
if not all(
|
|
133
|
+
isinstance(value, str) and value for value in (task_key, task_type, seq)
|
|
134
|
+
):
|
|
135
|
+
raise SystemExit("schema-v2 report metadata requires task-key, task-type, and seq")
|
|
136
|
+
return HtmlRunMeta(
|
|
137
|
+
task_key,
|
|
138
|
+
task_type,
|
|
139
|
+
seq,
|
|
140
|
+
args.source_report or markdown_path.name,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
80
144
|
def main(argv: list[str] | None = None) -> int:
|
|
81
145
|
parser = argparse.ArgumentParser(
|
|
82
146
|
description="Render the self-contained HTML view of an okstra final-report."
|
|
@@ -88,18 +152,42 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
88
152
|
parser.add_argument("--source-report", default=None)
|
|
89
153
|
args = parser.parse_args(argv)
|
|
90
154
|
|
|
91
|
-
report_path
|
|
155
|
+
report_path = args.report_path.resolve()
|
|
92
156
|
if not report_path.is_file():
|
|
93
157
|
parser.error(f"final-report not found: {report_path}")
|
|
158
|
+
data_path, markdown_path = _report_pair(report_path)
|
|
159
|
+
data = _load_data_if_present(data_path)
|
|
160
|
+
|
|
161
|
+
if data is not None and data.get("schemaVersion") == "2.0":
|
|
162
|
+
if not markdown_path.is_file():
|
|
163
|
+
parser.error(f"schema-v2 markdown sibling not found: {markdown_path}")
|
|
164
|
+
from okstra_ctl.report_html.render import render_v2_html_view
|
|
165
|
+
|
|
166
|
+
html_path = render_v2_html_view(
|
|
167
|
+
data_path,
|
|
168
|
+
markdown_path,
|
|
169
|
+
run_meta=_v2_run_meta(data, markdown_path, args),
|
|
170
|
+
templates_root=_templates_root(),
|
|
171
|
+
)
|
|
172
|
+
print(f"html: {html_path}")
|
|
173
|
+
return 0
|
|
94
174
|
|
|
175
|
+
if not markdown_path.is_file():
|
|
176
|
+
parser.error(f"legacy markdown sibling not found: {markdown_path}")
|
|
95
177
|
meta = infer_run_meta(
|
|
96
|
-
|
|
97
|
-
|
|
178
|
+
markdown_path,
|
|
179
|
+
task_key=args.task_key,
|
|
180
|
+
task_type=args.task_type,
|
|
181
|
+
seq=args.seq,
|
|
182
|
+
source_report=args.source_report,
|
|
98
183
|
)
|
|
99
184
|
css, js = _load_assets()
|
|
100
|
-
html_path = render_html_view(
|
|
185
|
+
html_path = render_html_view(markdown_path, run_meta=meta, css=css, js=js)
|
|
101
186
|
if html_path is None:
|
|
102
|
-
print(
|
|
187
|
+
print(
|
|
188
|
+
"html: skipped (no §1 clarification rows — html view carries no "
|
|
189
|
+
"interactive forms for this report)"
|
|
190
|
+
)
|
|
103
191
|
else:
|
|
104
192
|
print(f"html: {html_path}")
|
|
105
193
|
return 0
|
package/runtime/bin/okstra.sh
CHANGED
|
@@ -110,10 +110,13 @@ PY_ARGS=(
|
|
|
110
110
|
[[ -n "${DIRECTIVE-}" ]] && PY_ARGS+=(--directive "$DIRECTIVE")
|
|
111
111
|
[[ -n "${FIX_CYCLE-}" ]] && PY_ARGS+=(--fix-cycle "$FIX_CYCLE")
|
|
112
112
|
[[ -n "${WORKERS_OVERRIDE-}" ]] && PY_ARGS+=(--workers "$WORKERS_OVERRIDE")
|
|
113
|
+
[[ -n "${LEAD_PROVIDER_OVERRIDE-}" ]] && PY_ARGS+=(--lead-provider "$LEAD_PROVIDER_OVERRIDE")
|
|
113
114
|
[[ -n "${LEAD_MODEL_OVERRIDE-}" ]] && PY_ARGS+=(--lead-model "$LEAD_MODEL_OVERRIDE")
|
|
114
115
|
[[ -n "${CLAUDE_MODEL_OVERRIDE-}" ]] && PY_ARGS+=(--claude-model "$CLAUDE_MODEL_OVERRIDE")
|
|
115
116
|
[[ -n "${CODEX_MODEL_OVERRIDE-}" ]] && PY_ARGS+=(--codex-model "$CODEX_MODEL_OVERRIDE")
|
|
116
117
|
[[ -n "${ANTIGRAVITY_MODEL_OVERRIDE-}" ]] && PY_ARGS+=(--antigravity-model "$ANTIGRAVITY_MODEL_OVERRIDE")
|
|
118
|
+
[[ -n "${WORKER_MODELS_OVERRIDE-}" ]] && PY_ARGS+=(--worker-model "$WORKER_MODELS_OVERRIDE")
|
|
119
|
+
[[ -n "${REPORT_WRITER_PROVIDER_OVERRIDE-}" ]] && PY_ARGS+=(--report-writer-provider "$REPORT_WRITER_PROVIDER_OVERRIDE")
|
|
117
120
|
[[ -n "${REPORT_WRITER_MODEL_OVERRIDE-}" ]] && PY_ARGS+=(--report-writer-model "$REPORT_WRITER_MODEL_OVERRIDE")
|
|
118
121
|
[[ -n "${LEAD_RUNTIME-}" ]] && PY_ARGS+=(--lead-runtime "$LEAD_RUNTIME")
|
|
119
122
|
[[ -n "${EXECUTOR_OVERRIDE-}" ]] && PY_ARGS+=(--executor "$EXECUTOR_OVERRIDE")
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Antigravity Lead Runtime Adapter
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
This adapter maps the neutral Okstra lead operations to the current Antigravity CLI host. Read it only when the rendered launch prompt selects `leadRuntime=antigravity`.
|
|
6
|
+
|
|
7
|
+
## Capability declaration
|
|
8
|
+
|
|
9
|
+
| Field | Value |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `runtime` | `antigravity` |
|
|
12
|
+
| `leadRoleLabel` | `Antigravity lead` |
|
|
13
|
+
| `userPromptMode` | `host-text` |
|
|
14
|
+
| `workerDispatchBackend` | `mixed` |
|
|
15
|
+
| `initialPromptDeliveryMode` | `eager-include` |
|
|
16
|
+
| `sessionAccounting` | `artifact-only` |
|
|
17
|
+
| `resumeMode` | `artifact-checkpoint` |
|
|
18
|
+
| `teardownMode` | `process-cleanup` |
|
|
19
|
+
| `leadEventSource` | `lead-events-jsonl` |
|
|
20
|
+
|
|
21
|
+
## Semantic operation mapping
|
|
22
|
+
|
|
23
|
+
| Operation | Mapping |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `read_artifacts` | Read the manifest-provided paths through the current Antigravity host file interface. |
|
|
26
|
+
| `write_artifact` | Write only core-authorized `.okstra/` artifacts and preserve their schemas. |
|
|
27
|
+
| `prompt_user` | Ask through the current host text/question interface and stop at approval gates until an explicit answer arrives. |
|
|
28
|
+
| `dispatch_worker` | Dispatch every `runner=native-session` Antigravity assignment through the current host. Dispatch every `runner=cli-wrapper` assignment through its registered provider wrapper. |
|
|
29
|
+
| `await_workers` | Await native host workers through the host primitive and CLI workers through their status sidecars, then verify terminal state and Result Paths. |
|
|
30
|
+
| `redispatch_worker` | Start a fresh native worker or CLI wrapper attempt according to the persisted assignment and record the supplied dispatch kind. |
|
|
31
|
+
| `shutdown_workers` | Perform host or process cleanup only for resources owned by this run. |
|
|
32
|
+
| `record_lead_event` | Append the required structured event to the manifest-provided `leadEventsPath`; emit the matching user-facing `PROGRESS:` line. |
|
|
33
|
+
| `collect_usage` | Collect host- or artifact-backed usage through the existing Okstra token-usage path; do not substitute another runtime's session log. |
|
|
34
|
+
|
|
35
|
+
## Antigravity dispatch details
|
|
36
|
+
|
|
37
|
+
- For convergence reverify, consume the persisted round plan exactly. This adapter may map and transport each returned batch, but it cannot change batch membership and does not classify findings or branch on task type, provider, or model identity.
|
|
38
|
+
- The current Antigravity session is the lead. Never launch another provider as a replacement lead.
|
|
39
|
+
- The prepared run manifest and team-state are the assignment authority. Keep `runner=native-session` assignments in the current host and route `runner=cli-wrapper` assignments through the registered wrapper.
|
|
40
|
+
- Do not infer the current host from an installed `agy` binary. The `antigravity` runtime must come from the active host skill or an explicit runtime flag.
|
|
41
|
+
- Unsupported workers or unavailable models fail before dispatch; do not change the provider, model, or runner silently.
|
|
42
|
+
- Reverify and critic retries use fresh attempts and persist the core-supplied `dispatchKind`.
|
|
43
|
+
- Report-writer completion requires both the data Result Path and the worker-results audit path.
|
|
44
|
+
|
|
45
|
+
## Completion, cleanup, and resume
|
|
46
|
+
|
|
47
|
+
- A native host completion or successful wrapper return alone is insufficient. Verify terminal state, every required completion path, and the corresponding dispatch audit record.
|
|
48
|
+
- Resume from run artifacts and lead-event checkpoints. Do not invent Claude or Codex session identifiers.
|
|
@@ -11,7 +11,7 @@ This adapter maps the neutral Okstra lead operations to Claude Code host primiti
|
|
|
11
11
|
| `runtime` | `claude-code` |
|
|
12
12
|
| `leadRoleLabel` | `Claude lead` |
|
|
13
13
|
| `userPromptMode` | `native-question` |
|
|
14
|
-
| `workerDispatchBackend` | `
|
|
14
|
+
| `workerDispatchBackend` | `mixed` |
|
|
15
15
|
| `initialPromptDeliveryMode` | `lazy-path-reference` |
|
|
16
16
|
| `sessionAccounting` | `claude-jsonl` |
|
|
17
17
|
| `resumeMode` | `session-id` |
|
|
@@ -25,10 +25,10 @@ This adapter maps the neutral Okstra lead operations to Claude Code host primiti
|
|
|
25
25
|
| `read_artifacts` | Use the host file-read primitive and preserve the core contract's read order. |
|
|
26
26
|
| `write_artifact` | Use the host file-write primitive only for paths authorized by the active lifecycle phase. |
|
|
27
27
|
| `prompt_user` | Use the native question tool for approvals and clarifications; do not infer an answer from silence. |
|
|
28
|
-
| `dispatch_worker` | Dispatch `Agent(name: "<role>", run_in_background: true)` without `team_name`;
|
|
28
|
+
| `dispatch_worker` | Dispatch each assignment through `Agent(name: "<role>", run_in_background: true)` without `team_name`; use an in-process worker for `runner=native-session` and the assigned provider's wrapper worker for `runner=cli-wrapper`. |
|
|
29
29
|
| `await_workers` | Arm one background shell poll for the pending Result Paths; the spawn acknowledgement is not completion. |
|
|
30
30
|
| `redispatch_worker` | Dispatch a fresh `Agent(...)` session with the same prompt plus the core reverify/retry reason. |
|
|
31
|
-
| `shutdown_workers` |
|
|
31
|
+
| `shutdown_workers` | For each confirmed-complete worker selected for cleanup, send `SendMessage(to: <name>, message: { type: "shutdown_request" })` to idle the roster member **and** call `TaskStop(task_id: "<name>")` to stop its background task. Both are required; neither subsumes the other. |
|
|
32
32
|
| `record_lead_event` | Emit the required `PROGRESS:` line as assistant text and persist core-required state/artifact updates. |
|
|
33
33
|
| `collect_usage` | Run `okstra token-usage` against the team-state; it reads the run-scoped `~/.claude/projects` session JSONL evidence. |
|
|
34
34
|
|
|
@@ -36,14 +36,14 @@ This adapter maps the neutral Okstra lead operations to Claude Code host primiti
|
|
|
36
36
|
|
|
37
37
|
- The session owns one implicit team. `TeamCreate` and `TeamDelete` are absent on current Claude Code builds; never probe for them and never pass `team_name`.
|
|
38
38
|
- Set `name` to the core-assigned functional role label so token attribution can match `agentName`.
|
|
39
|
-
- Map
|
|
40
|
-
- For
|
|
39
|
+
- Map a `runner=native-session` Claude assignment to `claude-worker`. Map a `runner=cli-wrapper` assignment to `<provider>-worker`; the registered providers currently resolve to `claude-worker`, `codex-worker`, `antigravity-worker`, `grok-worker`, or `kimi-worker`. The functional `report-writer` worker ID does not override its provider assignment. Never substitute `general-purpose` for a rostered worker.
|
|
40
|
+
- For `runner=native-session`, map `modelExecutionValue` to the supported Claude family token and pass it as the `model` argument. CLI-wrapper roles apply their exact model in the provider wrapper and remain `inherit` at the Agent layer.
|
|
41
41
|
- A resumed lead can dispatch a fresh worker; resume is not a valid reason to omit a rostered role.
|
|
42
42
|
|
|
43
43
|
### Dispatch-time model enforcement
|
|
44
44
|
|
|
45
|
-
-
|
|
46
|
-
-
|
|
45
|
+
- A native Claude worker definition declares `model: inherit`; the lead MUST override that default by passing the assigned family token (`fable`, `opus`, `sonnet`, or `haiku`) as the `Agent(...)` `model` argument.
|
|
46
|
+
- Every CLI-wrapper agent remains `inherit` at the Agent layer because its exact `modelExecutionValue` is applied by `okstra-claude-exec.sh`, `okstra-codex-exec.sh`, `okstra-antigravity-exec.sh`, `okstra-grok-exec.sh`, or `okstra-kimi-exec.sh` according to the assignment provider.
|
|
47
47
|
- Missing or unsupported family-token mapping is a pre-dispatch contract failure. Never inherit the lead model, choose a nearby alias, or switch provider silently.
|
|
48
48
|
- Every analysis dispatch sets `name: "<workerId>-worker"`; convergence retries append `-reverify-r<N>`, implementation uses the functional `-executor` / `-verifier` suffix, and report writing uses `report-writer`. These values are retained as `agentName` in session JSONL for usage attribution.
|
|
49
49
|
- Every Codex / Antigravity prompt includes `**Pane role:** <functional-role>` so the wrapper's optional fifth argument names both its caller pane and trace pane.
|
|
@@ -56,7 +56,7 @@ This adapter maps the neutral Okstra lead operations to Claude Code host primiti
|
|
|
56
56
|
- For convergence reverify, consume the persisted round plan exactly. This adapter may map and transport each returned batch, but it cannot change batch membership and does not classify findings or branch on task type, provider, or model identity.
|
|
57
57
|
- Reverify dispatch uses a fresh one-shot `Agent(...)` call named `<workerId>-worker-reverify-r<N>`. Preserve the initial worker's definition and map an in-process Claude assignment's `modelExecutionValue` to its exact family token; CLI-wrapper assignments remain `inherit` at the Agent layer and apply the exact model in their wrapper.
|
|
58
58
|
- Critic dispatch uses `name: "<provider>-worker-critic"`, `dispatchKind: "critic"`, and the exact mapped model from `config.critic.modelExecutionValue`. If that value cannot be mapped, record `critic-skipped: model-unresolved` and do not dispatch.
|
|
59
|
-
- Report-writer dispatch uses `name: "report-writer"
|
|
59
|
+
- Report-writer dispatch uses `name: "report-writer"`. A native Claude assignment maps `modelExecutionValue` to the supported family token; a CLI-wrapper assignment remains `inherit` at the Agent layer and applies the exact value in its provider wrapper. The prompt's `**Model:**` header must carry the same execution value.
|
|
60
60
|
- Each variant persists its prompt path, Result Path, worker-results path, error paths, and `dispatchKind` before dispatch. Completion uses the shared background Result Path poll; an Agent acknowledgement never completes the variant.
|
|
61
61
|
|
|
62
62
|
## Completion, cleanup, and resume
|
|
@@ -71,7 +71,7 @@ This adapter maps the neutral Okstra lead operations to Claude Code host primiti
|
|
|
71
71
|
|
|
72
72
|
### CLI-wrapper polling
|
|
73
73
|
|
|
74
|
-
- Start `okstra-codex-exec.sh`
|
|
74
|
+
- Start the assignment's registered wrapper (`okstra-claude-exec.sh`, `okstra-codex-exec.sh`, `okstra-antigravity-exec.sh`, `okstra-grok-exec.sh`, or `okstra-kimi-exec.sh`) with `Bash(run_in_background: true)` and poll `BashOutput(bash_id)` back-to-back until terminal completion. Never add a foreground sleep.
|
|
75
75
|
- Return accumulated stdout on success. On a non-zero `exit_code`, record the real code and observed duration.
|
|
76
76
|
- At the 1800-second cap, inspect the live log mtime once. Recent output grants one extension to 2100 seconds; otherwise call `KillShell(shell_id)`, record exit code 124, and return the wrapper timeout sentinel.
|
|
77
77
|
- Keep the wrapper subagent alive throughout polling so its JSONL timestamp window covers the underlying CLI rollout.
|
|
@@ -81,7 +81,7 @@ This adapter maps the neutral Okstra lead operations to Claude Code host primiti
|
|
|
81
81
|
- At the start of Phase 7, run `okstra token-usage /abs/path/to/run/state/team-state-<task-type>-<seq>.json --write --summary` with the literal team-state path.
|
|
82
82
|
- Read the lead and Claude-side wrapper evidence from `~/.claude/projects/<encoded-cwd>/<sessionId>.jsonl`; attribute workers by the dispatch `agentName` recorded above.
|
|
83
83
|
- Resolve `teamName` from `state.teamName` or `state.team.teamName` and use the full manifest-provided value as the team needle. If it is missing, the collector's short-form fallback cannot match worker JSONLs and records those workers as `source: "unavailable"`.
|
|
84
|
-
- Keep underlying
|
|
84
|
+
- Keep every underlying provider CLI's usage separate from the Claude wrapper-session usage. Persist `leadUsage`, per-worker usage, and `usageSummary` before report substitution and cleanup.
|
|
85
85
|
|
|
86
86
|
## Run-scoped resource lifecycle
|
|
87
87
|
|
|
@@ -89,6 +89,7 @@ This adapter maps the neutral Okstra lead operations to Claude Code host primiti
|
|
|
89
89
|
- Record the lead pane once with `mkdir -p "<RUN_DIR>/state" && { . "$HOME/.okstra/bin/lib/okstra/tmux-pane.sh" 2>/dev/null && okstra_resolve_caller_pane; } > "<RUN_DIR>/state/lead-pane.id" 2>/dev/null || true`. This is silent setup and must not gate cleanup; the cleanup script protects the lead pane itself.
|
|
90
90
|
- Collect and persist token usage before any live-roster cleanup, including cleanup between batches and the run-end shutdown sequence.
|
|
91
91
|
- Before each new worker batch (and before the next phase's render-bundle), reclaim the prior round's completed teammate panes in two passes, adding `--keep report-writer-worker` to **both** passes while the report writer is in flight. First source the count: `$HOME/.okstra/bin/okstra-trace-cleanup.sh --list --run-dir "<RUN_DIR>" [--keep report-writer-worker]` never kills and prints one `<pane_id>\t<pane_title>` line per pane it would reclaim — count those lines as `<n>`. Then perform the reclaim by running the same command **without** `--list`, and emit the neutral contract's `PROGRESS: phase-batch-cleanup panes=<n>` checkpoint with that count. Call both passes after collecting that round's results and token usage and before the next dispatch, so no in-flight worker pane is caught. This `tmux kill-pane`s the harness teammate panes; `shutdown_request` only idles the agent and never frees the pane, so it stays part of the run-end sequence for roster/token hygiene. In a non-tmux session there are no panes, both passes no-op, and `<n>` is `0` — still emit the checkpoint. The lead pane (read from `<RUN_DIR>/state/lead-pane.id`) is always preserved.
|
|
92
|
+
- Reclaiming a pane does not stop the worker's background task. Every `dispatch_worker` Agent runs with `run_in_background: true`, so a worker whose result is already collected stays a live background task for the rest of the session — that residue is what fills the harness's exit-time `Background work is running` list. At the same batch boundary, right after the pane reclaim, call `TaskStop(task_id: "<name>")` once per worker of the completed batch, passing the exact `name` used at dispatch (`<workerId>-worker`, `<workerId>-worker-reverify-r<N>`, `<provider>-worker-critic`, `report-writer`). Stop only workers whose results were already collected — never an in-flight worker, never the lead, and keep `report-writer` while it is in flight, matching the pane pass's `--keep report-writer-worker`. `TaskStop` on an already-finished task is a no-op; treat a failure as benign, record nothing, and continue the boundary. This runs in a non-tmux session too, where the pane passes no-op but the background tasks still exist.
|
|
92
93
|
- After batch cleanup, record the current live session generation with `okstra token-usage "<TEAM_STATE_PATH>" --record-observed-session --project-root "<PROJECT_ROOT>"`. This protects usage accounting when Claude Code re-issues the session id after resume or compaction.
|
|
93
94
|
- Claude Code cannot delete the implicit team or surgically remove an idle roster entry. Explain that teammates may remain visible until session end and, when needed, give the manual action `Delete team <teamName> in Teams/FleetView`.
|
|
94
95
|
- The `SessionEnd` hook runs `$HOME/.okstra/bin/okstra-team-reconcile.sh --session-end` as the safety net for the current live session.
|
|
@@ -104,4 +105,5 @@ This adapter maps the neutral Okstra lead operations to Claude Code host primiti
|
|
|
104
105
|
> (Yes) Close everything and clean up teammates / (No) Keep everything
|
|
105
106
|
5. On `keep`, preserve every residual resource and show `$HOME/.okstra/bin/okstra-trace-cleanup.sh --run-dir "<RUN_DIR>"` plus the manual Teams/FleetView action. Tell the user that `keep` holds only until the next boundary: if this session goes on to another phase/batch, that transition's round-boundary cleanup reclaims the kept **completed** panes unattended (in-flight resources and the lead pane are never touched).
|
|
106
107
|
6. On approved `clean`, emit the teardown checkpoint, run `$HOME/.okstra/bin/okstra-trace-cleanup.sh --run-dir "<RUN_DIR>"`, then run `$HOME/.okstra/bin/okstra-team-reconcile.sh --project-root "<PROJECT_ROOT>" --fallback-team "session-<lead.sessionId-prefix>"` exactly once. The resolver reads the current live session's `~/.claude/teams/session-<live>/config.json`, falling back to the snapshot directory only when the live directory is absent, and prints `dismissible-member: <name>` records.
|
|
107
|
-
7. Send `SendMessage(to: <name>, message: { type: "shutdown_request" })` to each printed, confirmed-complete non-lead member. The `message` MUST be the object literal shown, NEVER a JSON string in a text field. Never target the lead
|
|
108
|
+
7. Send `SendMessage(to: <name>, message: { type: "shutdown_request" })` to each printed, confirmed-complete non-lead member. The `message` MUST be the object literal shown, NEVER a JSON string in a text field. Never target the lead.
|
|
109
|
+
8. Call `TaskStop(task_id: "<name>")` for every worker this run dispatched, reusing the step-7 names plus any batch worker already reclaimed earlier. `shutdown_request` only idles the roster member and the step-6 pane reclaim only closes the pane — neither ends the background task, so this step is the one that empties the harness's exit-time `Background work is running` list. Never target the lead; a `TaskStop` on an already-finished task is a benign no-op.
|
|
@@ -11,7 +11,7 @@ This adapter maps the neutral Okstra lead operations to the Codex artifact-first
|
|
|
11
11
|
| `runtime` | `codex` |
|
|
12
12
|
| `leadRoleLabel` | `Codex lead` |
|
|
13
13
|
| `userPromptMode` | `host-text` |
|
|
14
|
-
| `workerDispatchBackend` | `
|
|
14
|
+
| `workerDispatchBackend` | `mixed` |
|
|
15
15
|
| `initialPromptDeliveryMode` | `eager-include` |
|
|
16
16
|
| `sessionAccounting` | `artifact-only` |
|
|
17
17
|
| `resumeMode` | `artifact-checkpoint` |
|
|
@@ -25,9 +25,9 @@ This adapter maps the neutral Okstra lead operations to the Codex artifact-first
|
|
|
25
25
|
| `read_artifacts` | Read the manifest-provided paths through the current host's file interface. |
|
|
26
26
|
| `write_artifact` | Write only core-authorized `.okstra/` artifacts and preserve their schemas. |
|
|
27
27
|
| `prompt_user` | Ask through the host text/question interface and stop at approval gates until an explicit answer arrives. |
|
|
28
|
-
| `dispatch_worker` |
|
|
29
|
-
| `await_workers` |
|
|
30
|
-
| `redispatch_worker` |
|
|
28
|
+
| `dispatch_worker` | Dispatch every `runner=native-session` assignment with the current Codex host's native worker/session primitive. Pass only `runner=cli-wrapper` assignments to `okstra codex-dispatch --project-root <root> --run-manifest <path> --workers <ids>`; use `--dry-run` first when the core requires a dispatch preview. |
|
|
29
|
+
| `await_workers` | Await native host workers through the host primitive and CLI workers through synchronous dispatch, then verify team-state terminal records and Result Paths for both. |
|
|
30
|
+
| `redispatch_worker` | Start a fresh native worker or `okstra codex-dispatch` attempt according to the persisted assignment's `runner`, and record the retry/reverify dispatch kind. |
|
|
31
31
|
| `shutdown_workers` | Perform process cleanup when a wrapper remains live; otherwise this operation is a no-op recorded in state. |
|
|
32
32
|
| `record_lead_event` | Append the required structured event to the manifest-provided `leadEventsPath`; emit the matching user-facing `PROGRESS:` line. |
|
|
33
33
|
| `collect_usage` | Collect artifact/rollout-backed usage through the existing Okstra token-usage path; never read Claude session JSONL as a substitute. |
|
|
@@ -36,12 +36,12 @@ This adapter maps the neutral Okstra lead operations to the Codex artifact-first
|
|
|
36
36
|
|
|
37
37
|
- For convergence reverify, consume the persisted round plan exactly. This adapter may map and transport each returned batch, but it cannot change batch membership and does not classify findings or branch on task type, provider, or model identity.
|
|
38
38
|
- Do not invoke Claude Code team or subagent tools.
|
|
39
|
-
- The prepared run manifest and team-state are the dispatch authority. Unsupported explicitly requested workers fail; an adapter must not silently change the roster.
|
|
40
|
-
-
|
|
39
|
+
- The prepared run manifest and team-state are the dispatch authority. A `runner=native-session` assignment stays in the current Codex host; a `runner=cli-wrapper` assignment uses the registered provider wrapper. Unsupported explicitly requested workers fail; an adapter must not silently change the roster.
|
|
40
|
+
- The report-writer follows its persisted provider, model, and runner assignment exactly. It has no Codex-only provider override or separate opt-in gate.
|
|
41
41
|
- Reverify and critic retries invoke a fresh worker attempt and persist the core-supplied `dispatchKind` (`reverify-r<N>` or `critic`) in the dispatch record; never reuse a prior rollout as a new vote.
|
|
42
42
|
- Report-writer completion requires both the data.json Result Path and the worker-results audit path, even when the synchronous dispatch command exits successfully.
|
|
43
43
|
|
|
44
44
|
## Completion, cleanup, and resume
|
|
45
45
|
|
|
46
|
-
- A successful synchronous
|
|
46
|
+
- A native host completion or successful synchronous CLI return alone is insufficient; verify terminal state, every required completion path, and the corresponding worker-dispatch audit record before counting the worker as complete.
|
|
47
47
|
- Resume from run artifacts and lead-events checkpoints. Do not invent a Claude session id.
|
|
@@ -202,7 +202,7 @@ If previous run reports exist, use as historical context only. If discovery meta
|
|
|
202
202
|
|
|
203
203
|
For `project-analysis`, `feature-analysis`, and `change-impact-analysis`, Lead MUST use the run manifest's immutable pre-dispatch `analysisScopeConfirmation` snapshot as the structured reporter-confirmation evidence before Phase 4 worker dispatch. Its `status` MUST be `complete`; its `taskBriefPath` and `briefSha256` bind that status to the exact brief bytes captured when the run manifest was created. A later edit to the live brief, clarification prose, or inferred consent cannot substitute for this snapshot. `project-analysis` confirms which areas remain shallow; `feature-analysis` confirms the exact feature target and covered flows; `change-impact-analysis` confirms the proposed change, preserved behavior, and dependency boundary.
|
|
204
204
|
|
|
205
|
-
If that snapshot is incomplete, missing, or malformed, Lead MUST follow the shared Reporter Confirmation Required / Clarification Items contract
|
|
205
|
+
If that snapshot is incomplete, missing, or malformed, Lead MUST follow the shared Reporter Confirmation Required / Clarification Items contract and stop before dispatch. A scope reduction must be explicitly confirmed in the brief's `## Reporter Confirmations` before a fresh bundle records `analysisScopeConfirmation.status=complete`. Do not dispatch workers and then defer a foreseeable scope conflict to a final HTML question. **Enforcement:** `scripts/okstra_ctl/render.py` records the brief path, reporter-confirmation status, and brief byte digest in the run manifest before the lead can dispatch workers; `validators/validate_analysis_report.py` validates only that immutable snapshot, rejects required-worker execution before a complete snapshot, and recomputes the analysis verdict; `validators/validate-run.py` runs that check only after schema validation succeeds.
|
|
206
206
|
|
|
207
207
|
## Phase 2 — Phase 5: Prompt preparation, teammate setup, execution, completion poll
|
|
208
208
|
|
|
@@ -308,7 +308,7 @@ If convergence is disabled, `seed`/`finalize` produce the auto-disabled final st
|
|
|
308
308
|
|
|
309
309
|
### Authoring ownership (BLOCKING)
|
|
310
310
|
|
|
311
|
-
If `Report writer worker` is in the selected roster (`recommendedWorkers` / `resultContract.requiredWorkerRoles`), **Lead MUST dispatch it to author the final report**. The worker writes the JSON SSOT at `runs/<task-type>/reports/final-report-<task-type>-<seq>.data.json` and invokes `scripts/okstra-render-final-report.py` to produce the sibling
|
|
311
|
+
If `Report writer worker` is in the selected roster (`recommendedWorkers` / `resultContract.requiredWorkerRoles`), **Lead MUST dispatch it to author the final report data.json**. The worker writes the JSON SSOT at `runs/<task-type>/reports/final-report-<task-type>-<seq>.data.json` and invokes `scripts/okstra-render-final-report.py` to produce the sibling AI handoff Markdown. Phase 7 renders human HTML directly from the same data.json. Lead writes none of these files; it prepares the prompt, dispatches, and reviews both audience artifacts. See [report-writer](./report-writer.md) "File-author ownership".
|
|
312
312
|
|
|
313
313
|
Before constructing the dispatch prompt, the lead MUST:
|
|
314
314
|
|
|
@@ -358,8 +358,8 @@ Lead's responsibilities in this sub-step (in order):
|
|
|
358
358
|
2. Dispatch a single plan-body reverify round to every analyser worker in the roster (`claude`, `codex`, and `antigravity` when opted in). `Report writer worker` is NOT a participant in this round.
|
|
359
359
|
3. Aggregate verdicts and resolve the gate result to one of `passed` / `passed-with-dissent` / `blocked-by-disagreement` / `aborted-non-result`.
|
|
360
360
|
4. Write `runs/<task-type>/state/plan-body-verification.json` (schema in the plan-body-verification contract), appending one `roundHistory[]` entry per round — including every self-fix re-verification round, since data.json keeps only the final verdicts.
|
|
361
|
-
5. Populate
|
|
362
|
-
6. For every `majority-disagree` plan item, append
|
|
361
|
+
5. Populate `implementationPlanning.planBodyVerification` in data.json with round count, gate result, per-item verdicts, and dissent log. The AI handoff task-deliverable block carries this structure without a second prose rendering.
|
|
362
|
+
6. For every `majority-disagree` plan item, append one `clarificationItems[]` row with `blocks=approval` and the 1:1 ID match in the verdict classification (`majority-disagree → C-<N>`). Do not create a parallel open-questions structure.
|
|
363
363
|
7. Publish the YAML frontmatter `approved:` field as `false`. There is no in-body `- [ ] Approved` marker line — approval lives only in the frontmatter (see [plan-body-verification](./plan-body-verification.md) §"Round protocol" step 9). The user may flip it to `true` only when the gate is `passed` or `passed-with-dissent`. **Enforced:** `validators/validate-run.py` `validate_phase_boundary` fails a report shipping `approved: true` under `blocked-by-disagreement` / `aborted-non-result`, and run-prep (`scripts/okstra_ctl/run.py` `_validate_approved_plan`) fail-closes the same case. Manually flipping a blocked gate to passing is a contract violation.
|
|
364
364
|
|
|
365
365
|
If `convergence.planBodyVerification.enabled == false` (set by `--no-plan-verification` or by `okstra config set plan-verification off`), the entire sub-step is skipped and the top-of-report Approval marker is rendered unconditionally (legacy behaviour). This opt-out is intended for fast iteration only and is not recommended for handoff-ready plans.
|
|
@@ -397,7 +397,7 @@ After persistence, reply briefly in the resolved Report Language with: completio
|
|
|
397
397
|
## Run-scoped worker-resource lifecycle
|
|
398
398
|
|
|
399
399
|
- At run start, call the selected adapter's setup required to distinguish lead-owned resources from worker-owned resources.
|
|
400
|
-
- Before every new worker batch, and between worker rounds within a phase, close the prior round's completed
|
|
400
|
+
- Before every new worker batch, and between worker rounds within a phase, close **every** resource the prior round's completed workers still hold — display surfaces, roster entries, and live execution handles alike — before the next dispatch; never the lead and never an in-flight worker. Call `record_lead_event` for the batch-cleanup checkpoint. Which resources exist and how each one is released is the selected adapter's mapping.
|
|
401
401
|
- After Phase 7 persistence and `collect_usage`, enumerate residual adapter-owned resources. If none remain, skip the question.
|
|
402
402
|
- If resources remain, call `prompt_user` once with a binary keep-or-clean choice. The answer controls the entire residual set; do not ask a second backend-specific cleanup question.
|
|
403
403
|
- On keep, preserve all resources and provide the selected adapter's manual-cleanup instruction.
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
The final-report data.json is authored by `Report writer worker` when that role is in the roster. The lead reviews both rendered artifacts but does not write them. Lead-authored fallback is legal only after a real `dispatch_worker` attempt records `error`, `timeout`, or `not-run` with a concrete reason. `release-handoff` remains the intentional single-lead exception.
|
|
6
6
|
|
|
7
|
-
The JSON SSOT path is `runs/<task-type>/reports/final-report-<task-type>-<seq>.data.json`.
|
|
7
|
+
The JSON SSOT path is `runs/<task-type>/reports/final-report-<task-type>-<seq>.data.json`. Two audience artifacts are independently derived from the data.json: `scripts/okstra-render-final-report.py` produces the AI handoff Markdown sibling, and Phase 7 produces the task-specific human HTML sibling directly from data.json. The worker-result pointer at `**Worker Result Path:**` records the data and Markdown paths plus reconciled convergence input. These three completion artifacts land on disk before the worker returns; HTML follows during finalization and the heartbeat sidecar remains a separate audit artifact.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
New bundles use `schemas/final-report-v2.0.schema.json`. The Markdown keeps verdict, routing, evidence, one structured task deliverable, and audit data for the next agent. The HTML uses `humanSummary`, task `userNarrative`, and structured facts for the user. Raw worker discussion, convergence mechanics, and usage belong to audit structures and never to the HTML human main body.
|
|
10
10
|
|
|
11
11
|
Two `frontmatter` approval fields are always emitted with their unset default — never pre-fill them: `frontmatter.approved` is emitted as `false`, and `frontmatter.implementationOption` is emitted as an empty string `""`. The user later flips `approved` to `true` (via `--approve` or manual edit) and fills `implementationOption` with the chosen Option Candidate name (via `--implementation-option <name>` or manual edit) to authorise and scope the next `implementation` run.
|
|
12
12
|
|
|
@@ -46,8 +46,8 @@ The prompt MUST include, in this order at the top:
|
|
|
46
46
|
8. `**Prompt Delivery Mode:** <mode>` — the selected adapter's declared `initialPromptDeliveryMode`.
|
|
47
47
|
9. `**Model:** Report writer worker, <modelExecutionValue>` (resolved per Phase 5.5 anchor-header rules)
|
|
48
48
|
10. The full `[Required reading]` clause (see [team-contract](./team-contract.md)) — for Phase 6 it adds two **per-task-type, instruction-set-local** read-only files, both scoped to this run's task-type by `okstra-ctl` at prep time:
|
|
49
|
-
- `<instruction-set>/final-report-schema.json` — a task-type excerpt of
|
|
50
|
-
- `<instruction-set>/final-report-template.md` — the
|
|
49
|
+
- `<instruction-set>/final-report-schema.json` — a task-type excerpt of schema v2. This is the binding authoring shape; the installed full schema is what the run is judged against. Do **NOT** pull the full repository schema because it is outside the task bundle.
|
|
50
|
+
- `<instruction-set>/final-report-template.md` — the AI handoff Markdown template. It shows the agent-facing ledger shape, not the human presentation. The task-specific HTML renderer reads data.json separately.
|
|
51
51
|
11. A one-line MCP pointer instead of the verbatim block (redundant — the brief is already in the report-writer's Required reading, item 10): `**MCP servers:** follow the task brief's "## Available MCP Servers" section (already in your Required reading).`
|
|
52
52
|
12. `Convergence state: runs/<task-type>/state/convergence-<task-type>-<seq>.json`, followed by pointers to all analysis-worker result files under `worker-results/`. The convergence path is deterministic and is listed even before Phase 5.5 creates the file. Read its classifications (Full/Partial/Contested/Worker-Unique), `roundHistory[]`, `round2SkippedReason`, and `finalClassificationCounts`; populate `crossVerification.roundHistory` in data.json so Section 6 can show which rounds executed, queue sizes, and why Round 2 was (or was not) skipped. The renderer prints the full per-round table only when more than one round ran; single-round or zero-round histories are auto-collapsed to a one-line summary.
|
|
53
53
|
13. `**Report Language:** <en|ko>` — must be either `en` or `ko`; `auto`
|
|
@@ -56,7 +56,7 @@ The prompt MUST include, in this order at the top:
|
|
|
56
56
|
into `data.json.meta.reportLanguage`.
|
|
57
57
|
14. For implementation-planning runs: a literal block listing the 12 required English section headings — `Option Candidates`, `Trade-off`, `Recommended Option`, `Stage Map`, `Stepwise Execution Order`, `Dependency`, `Validation Checklist`, `Rollback`, `Requirement Coverage`, `Plan Body Verification`, `Cross-Project Dependencies`, `Decision Drafts`. This list is `PLANNING_REQUIRED_SECTIONS` in `validators/validate-run.py`; that tuple is the SSOT and this block must match it exactly. The writer uses these exact substrings as section headings (Korean translation in parentheses is allowed), and the `Plan Body Verification` section carries its required `Gate result:` line.
|
|
58
58
|
15. An explicit instruction: `You are the author of THREE files: (a) the final-report data.json at <Result Path>, (b) its rendered Markdown sibling produced through "okstra render-final-report <Result Path>", and (c) the worker-result pointer at <Worker Result Path>. Maintain the separate heartbeat audit sidecar at <Audit sidecar path>. Do not return the report inline. The dispatch fails when any of the three completion artifacts is missing, and session conformance fails when the audit sidecar is missing or invalid.`
|
|
59
|
-
16. The prose budget (dedup contract): `verdictCard.finalConclusion` is the conclusion SSOT — at most 3 sentences. `rationale.*` fields stay within 2 sentences each
|
|
59
|
+
16. The prose budget (dedup contract): `verdictCard.finalConclusion` is the conclusion SSOT — at most 3 sentences. `rationale.*` fields stay within 2 sentences each; `humanSummary` entries stay concise; task `userNarrative` explains each user-facing section once with evidence references. Do not copy these narratives into the AI Markdown. `summary` stays at 3-5 rows unless the run covers multiple tickets. Generation time scales with output volume, so exceeding the budget is a cost bug, not extra diligence.
|
|
60
60
|
|
|
61
61
|
**Fix-run incremental authoring (applies when the run's profile carries a "Fix-Run Carry" block).** Do not author the data.json from scratch. Start by copying the previous run's data.json (the `Previous report` path in the Fix-Run Carry block) to this run's Result Path, then update ONLY the blocks the fix run changed: `meta`/`header` (run seq, dates), `executionStatus`, `implementation.verifierResults`, `implementation.validationEvidence`, `implementation.commitList` / `diffSummary`, `crossVerification`, `verdictCard`, `finalVerdict`, and any `evidence` rows the fix touched. Deliverable prose for unchanged sections is carried forward verbatim — do not re-generate it. Then invoke the renderer exactly as in a full run. The schema validation and renderer contract are unchanged, so an incrementally-authored data.json passes the same post-hoc gates. The lead's dispatch prompt MUST include the previous data.json path when the carry block is present.
|
|
62
62
|
|
|
@@ -81,7 +81,7 @@ Speculative reasons such as "session resume constraint", "runtime state is unava
|
|
|
81
81
|
|
|
82
82
|
Phase 6 first produces the final-report data.json at `runs/<task-type>/reports/final-report-<task-type>-<seq>.data.json` and its rendered markdown sibling. Token Usage cells are `null` at this point, and Section 3 does not yet include auto-spawned follow-ups.
|
|
83
83
|
|
|
84
|
-
For an implementation-planning run, the Report writer worker owns the Phase 6 design assessment snapshot: it writes `designPreparation` and every stage's `designSurfaceCoverage` into data.json from the detector output and consolidated plan. It does not create user inputs, consume a user answer as if it were part of that snapshot, or materialize `design-prep-requests/`; `schemas/final-report-
|
|
84
|
+
For an implementation-planning run, the Report writer worker owns the Phase 6 design assessment snapshot: it writes `designPreparation` and every stage's `designSurfaceCoverage` into data.json from the detector output and consolidated plan. It does not create user inputs, consume a user answer as if it were part of that snapshot, or materialize `design-prep-requests/`; `schemas/final-report-v2.0.schema.json` and `validators/validate-run.py` `_validate_design_prep_contract` enforce the snapshot shape, detector coverage, and references.
|
|
85
85
|
|
|
86
86
|
Phase 7 post-processing is **one command**. `okstra report-finalize` owns the ordered sequence — it is the same code path the Codex lead adapter runs automatically, so a Claude-led run and a Codex-led run finalize identically:
|
|
87
87
|
|
|
@@ -101,12 +101,12 @@ The steps it executes, in this contractual order, and the contract each one carr
|
|
|
101
101
|
The data.json paths populated: `tokenUsage.lead.{totalTokens,billableTokens,costUsd}`, the `worker` / `grand` rows, `tokenUsage.cli.costUsd`, and each `executionStatus[].{totalTokens,billableTokens,costUsd,durationMs,cliTotalTokens,cliCostUsd}` for rows whose role matches a team-state worker. The data.json MUST already exist (Phase 6 output).
|
|
102
102
|
|
|
103
103
|
For implementation-planning, this Phase 7 canonical render calls `materialize_design_prep_requests()` after token substitution and creates deterministic request files only for `provisional` / `blocked` items. Later answers are append-only user-input sidecars; request generation and user input never rewrite the assessment fields, so the source report remains immutable as the design-input snapshot after this render. `validators/validate-run.py` `_validate_design_prep_requests` enforces request existence, canonical path, content, and assessment fingerprint.
|
|
104
|
-
2. **`render-views` — render the human report artifact.** Runs against the substituted
|
|
104
|
+
2. **`render-views` — render the human report artifact.** Runs against the substituted v2 data.json and its Markdown sibling.
|
|
105
105
|
|
|
106
106
|
Output (idempotent — re-running overwrites):
|
|
107
|
-
- `runs/<task-type>/reports/final-report-<task-type>-<seq>.html` — single-file self-contained human view,
|
|
107
|
+
- `runs/<task-type>/reports/final-report-<task-type>-<seq>.html` — single-file self-contained human view, always generated for schema v2 from the dedicated template registered for that task type. Clarification rows with `Status` ∈ {`open`, `answered`} embed response controls and export a `user-response-<task-type>-<seq>.md` sidecar. The original data and Markdown artifacts are never mutated by user input.
|
|
108
108
|
- the implementation-planning report renders a **Plan Approval** section at the end of the body (implementation-option `<select>` + an approval checkbox) — disabled while any §1 `Blocks: approval` row is unresolved. Checking approval and exporting embeds a `## APPROVAL` block in the sidecar body, and the implementation-start wizard's approve-confirm step detects it and, after user confirmation, applies it through the existing `--approve` / `--implementation-option` path.
|
|
109
|
-
-
|
|
109
|
+
- Schema-v1 and quick compatibility reports retain the legacy conditional HTML path; this does not change the schema-v2 always-generated contract.
|
|
110
110
|
|
|
111
111
|
It runs after usage collection so token placeholders are substituted in any rendered html, and before routing persistence so the html artifact, when generated, exists for the validator step that checks it.
|
|
112
112
|
3. **`spawn-followups` — routing and follow-up persistence.** Turns the report's `## 4. Follow-up Tasks` rows into `tasks/<task-group>/<new-task-id>/` stubs.
|
|
@@ -128,13 +128,17 @@ The steps it executes, in this contractual order, and the contract each one carr
|
|
|
128
128
|
|
|
129
129
|
After `okstra report-finalize` reports `"ok": true`, **execute the run-scoped cleanup gate.** Call `shutdown_workers` only after that success, all persistence work, and explicit user approval under [okstra-lead-contract](./okstra-lead-contract.md) "Run-scoped worker-resource lifecycle". If the user keeps resources, leave the selected adapter's resources intact and surface its manual cleanup guidance.
|
|
130
130
|
|
|
131
|
-
##
|
|
131
|
+
## Schema-v2 report data responsibilities
|
|
132
132
|
|
|
133
|
-
The
|
|
133
|
+
The binding authoring shape is the task bundle's `instruction-set/final-report-schema.json`. Populate both audiences in data.json: agent-facing verdict, routing, evidence, task facts, and audits; user-facing `humanSummary` and task `userNarrative`. The AI handoff template deliberately omits the full user narrative, while the task-specific HTML deliberately moves `crossVerification`, `executionStatus`, and `tokenUsage` into collapsed audit details.
|
|
134
|
+
|
|
135
|
+
## Legacy schema-v1 Markdown structure reference
|
|
136
|
+
|
|
137
|
+
The remaining numbered-section guide exists only for rendering or diagnosing historical schema-v1 data. New report-writer runs do not author against it; their instruction-set schema and AI handoff template are authoritative.
|
|
134
138
|
|
|
135
139
|
### Report Header
|
|
136
140
|
|
|
137
|
-
|
|
141
|
+
Read the exact permitted values for `header.reportOwner` and `header.reportAuthor` from the task bundle's `instruction-set/final-report-schema.json` excerpt, then write those values according to the actual authorship path. The current v2 contract uses the provider-neutral `Okstra lead`; a legacy v1 excerpt may retain historical compatibility values. Do not derive either header field from the selected runtime's provider-specific lead label. Runtime identity remains visible in the execution-status row and team-state audit fields.
|
|
138
142
|
|
|
139
143
|
```markdown
|
|
140
144
|
# <task-key> - Multi-Agent Cross Verification Final Report
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Single source for the executor's Coding-conventions preflight gate. Two delivery
|
|
3
3
|
paths converge here (see _implementation-executor.md "Pre-implementation context
|
|
4
4
|
exploration"):
|
|
5
|
-
-
|
|
5
|
+
- The native-session executor reads this file directly before its first edit.
|
|
6
6
|
- codex / antigravity executor cannot read this path (it sits outside the CLI
|
|
7
7
|
sandbox and the CLI only sees its stdin prompt), so the lead appends this
|
|
8
8
|
file's body into the persisted executor prompt at dispatch time.
|