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
|
@@ -8,6 +8,7 @@ import { fileExists } from "../../lib/proc.mjs";
|
|
|
8
8
|
import { buildRuntimeManifest, RUNTIMES_MANIFEST_REL } from "../../lib/runtime-manifest.mjs";
|
|
9
9
|
import { normalizeRuntimeRequest, resolveRuntime } from "../../lib/runtime-resolver.mjs";
|
|
10
10
|
import { OBSOLETE_SKILL_NAMES, USER_SKILL_NAMES } from "../../lib/skill-catalog.mjs";
|
|
11
|
+
import { renderWorkerAgentDefinitions } from "../../lib/worker-agent-render.mjs";
|
|
11
12
|
|
|
12
13
|
const SKILLS_MANIFEST_REL = "installed-skills.json";
|
|
13
14
|
const AGENTS_MANIFEST_REL = "installed-agents.json";
|
|
@@ -29,6 +30,9 @@ const BIN_ENTRYPOINTS = [
|
|
|
29
30
|
"okstra-codex-exec.sh",
|
|
30
31
|
"okstra-claude-exec.sh",
|
|
31
32
|
"okstra-antigravity-exec.sh",
|
|
33
|
+
"okstra-grok-exec.sh",
|
|
34
|
+
"okstra-kimi-exec.sh",
|
|
35
|
+
"okstra-provider-exec.py",
|
|
32
36
|
"okstra-trace-cleanup.sh",
|
|
33
37
|
"okstra-subagent-reclaim.sh",
|
|
34
38
|
"okstra-team-reconcile.sh",
|
|
@@ -47,6 +51,7 @@ const REQUIRED_PROMPT_RESOURCE_FILES = Object.freeze([
|
|
|
47
51
|
["prompts", "lead", "okstra-lead-contract.md"],
|
|
48
52
|
["prompts", "lead", "adapters", "claude-code.md"],
|
|
49
53
|
["prompts", "lead", "adapters", "codex.md"],
|
|
54
|
+
["prompts", "lead", "adapters", "antigravity.md"],
|
|
50
55
|
["prompts", "lead", "adapters", "external.md"],
|
|
51
56
|
["prompts", "lead", "context-loader.md"],
|
|
52
57
|
["prompts", "lead", "team-contract.md"],
|
|
@@ -69,7 +74,7 @@ const INSTALL_USAGE = `okstra install — install runtime into ~/.okstra
|
|
|
69
74
|
|
|
70
75
|
Usage:
|
|
71
76
|
okstra install Install/update runtime (copy mode)
|
|
72
|
-
okstra install --runtime <claude-code|codex|external|all>
|
|
77
|
+
okstra install --runtime <claude-code|codex|antigravity|external|all>
|
|
73
78
|
okstra install --link <p> Dev only: symlink ~/.okstra/{lib/python,bin}
|
|
74
79
|
to the source repo at <p>. agents/ resolves
|
|
75
80
|
to <p>/agents. Not advertised to end users.
|
|
@@ -80,7 +85,8 @@ Effect (copy mode):
|
|
|
80
85
|
${"$HOME"}/.okstra/lib/python <- runtime/python
|
|
81
86
|
${"$HOME"}/.okstra/lib/validators <- runtime/validators (stage/report structure validators)
|
|
82
87
|
${"$HOME"}/.okstra/bin <- runtime/bin
|
|
83
|
-
${"$HOME"}/.okstra/templates <- runtime/templates (
|
|
88
|
+
${"$HOME"}/.okstra/templates <- runtime/templates (v1 assets + v2 AI/HTML template trees)
|
|
89
|
+
${"$HOME"}/.okstra/schemas <- runtime/schemas (final-report schema v1 + v2)
|
|
84
90
|
${"$HOME"}/.okstra/prompts <- runtime/prompts (lead contracts + coding-preflight pack)
|
|
85
91
|
${"$HOME"}/.okstra/templates/settings.local.json <- runtime/templates/reports/settings.template.json
|
|
86
92
|
${"$HOME"}/.claude/skills/<name> <- skills when ${"$HOME"}/.claude exists
|
|
@@ -119,13 +125,15 @@ const ENSURE_USAGE = `okstra ensure-installed — idempotent install check
|
|
|
119
125
|
|
|
120
126
|
Usage:
|
|
121
127
|
okstra ensure-installed Verify install; reinstall if version/files drift
|
|
122
|
-
okstra ensure-installed --runtime <claude-code|codex|external|all>
|
|
128
|
+
okstra ensure-installed --runtime <claude-code|codex|antigravity|external|all>
|
|
123
129
|
okstra ensure-installed -q Same, but suppress success output
|
|
124
130
|
|
|
125
131
|
Skills call this on every run. Returns 0 quickly when the install is fresh.
|
|
126
132
|
`;
|
|
127
133
|
|
|
128
|
-
const INSTALL_RUNTIMES = new Set([
|
|
134
|
+
const INSTALL_RUNTIMES = new Set([
|
|
135
|
+
"auto", "claude-code", "codex", "antigravity", "external", "all",
|
|
136
|
+
]);
|
|
129
137
|
|
|
130
138
|
export function runtimeIncludesClaudeAssets(runtime, resolution = null) {
|
|
131
139
|
if (runtime === "claude-code" || runtime === "all") return true;
|
|
@@ -139,7 +147,7 @@ function readRuntimeFlag(args, index) {
|
|
|
139
147
|
}
|
|
140
148
|
const next = args[index + 1];
|
|
141
149
|
if (!next || next.startsWith("--")) {
|
|
142
|
-
throw new Error("--runtime requires one of: claude-code, codex, external, all");
|
|
150
|
+
throw new Error("--runtime requires one of: claude-code, codex, antigravity, external, all");
|
|
143
151
|
}
|
|
144
152
|
return { value: next, nextIndex: index + 1 };
|
|
145
153
|
}
|
|
@@ -147,7 +155,7 @@ function readRuntimeFlag(args, index) {
|
|
|
147
155
|
export function validateInstallRuntime(value) {
|
|
148
156
|
const runtime = normalizeRuntimeRequest(value);
|
|
149
157
|
if (!INSTALL_RUNTIMES.has(runtime)) {
|
|
150
|
-
throw new Error(`unknown runtime '${runtime}' (expected: auto, claude-code, codex, external, all)`);
|
|
158
|
+
throw new Error(`unknown runtime '${runtime}' (expected: auto, claude-code, codex, antigravity, external, all)`);
|
|
151
159
|
}
|
|
152
160
|
return runtime;
|
|
153
161
|
}
|
|
@@ -495,7 +503,9 @@ async function listWorkerFiles(workersRoot) {
|
|
|
495
503
|
try {
|
|
496
504
|
const entries = await fs.readdir(workersRoot, { withFileTypes: true });
|
|
497
505
|
return entries
|
|
498
|
-
.filter((e) =>
|
|
506
|
+
.filter((e) => (
|
|
507
|
+
e.isFile() && e.name.endsWith(".md") && !e.name.startsWith("_")
|
|
508
|
+
))
|
|
499
509
|
.map((e) => e.name);
|
|
500
510
|
} catch (err) {
|
|
501
511
|
if (err.code === "ENOENT") return [];
|
|
@@ -550,18 +560,32 @@ async function installAgentsCopy(runtimeRoot, opts) {
|
|
|
550
560
|
async function installAgentsLink(repoAbs, opts) {
|
|
551
561
|
const { dryRun, quiet } = opts;
|
|
552
562
|
const srcRoot = join(repoAbs, "agents", "workers");
|
|
553
|
-
const
|
|
563
|
+
const sourceNames = await listWorkerFiles(srcRoot);
|
|
564
|
+
const renderedDefinitions = await renderWorkerAgentDefinitions(srcRoot);
|
|
565
|
+
const names = [
|
|
566
|
+
...sourceNames,
|
|
567
|
+
...renderedDefinitions.map(({ name }) => name),
|
|
568
|
+
].sort();
|
|
554
569
|
if (names.length === 0) {
|
|
555
570
|
if (!quiet) process.stdout.write(" agents: <repo>/agents/workers missing — skipped\n");
|
|
556
571
|
return { installed: [] };
|
|
557
572
|
}
|
|
558
573
|
if (!dryRun) await fs.mkdir(CLAUDE_AGENTS_DIR, { recursive: true });
|
|
559
|
-
for (const name of
|
|
574
|
+
for (const name of sourceNames) {
|
|
560
575
|
const src = join(srcRoot, name);
|
|
561
576
|
const dst = join(CLAUDE_AGENTS_DIR, name);
|
|
562
577
|
const action = await ensureSymlink(src, dst, { dryRun });
|
|
563
578
|
if (!quiet) process.stdout.write(` agents/${name}: ${action}\n`);
|
|
564
579
|
}
|
|
580
|
+
for (const { name, content } of renderedDefinitions) {
|
|
581
|
+
const dst = join(CLAUDE_AGENTS_DIR, name);
|
|
582
|
+
if (dryRun) {
|
|
583
|
+
process.stdout.write(`[dry-run] render ${name} -> ${dst}\n`);
|
|
584
|
+
} else {
|
|
585
|
+
await writeFileAtomic(dst, content, 0o644);
|
|
586
|
+
}
|
|
587
|
+
if (!quiet) process.stdout.write(` agents/${name}: rendered\n`);
|
|
588
|
+
}
|
|
565
589
|
return { installed: names };
|
|
566
590
|
}
|
|
567
591
|
|
|
@@ -775,8 +799,9 @@ export async function runInstall(args) {
|
|
|
775
799
|
paths.bin,
|
|
776
800
|
{ refresh: opts.refresh, dryRun: opts.dryRun, mode: 0o755 },
|
|
777
801
|
);
|
|
778
|
-
// templates/ tree — report.css
|
|
779
|
-
//
|
|
802
|
+
// templates/ tree — the v1 report.css/report.js compatibility assets, the
|
|
803
|
+
// v2 AI handoff template, and the task-specific html/** tree are consumed by
|
|
804
|
+
// okstra-render-report-views.py and final-report assembly. They
|
|
780
805
|
// are NOT covered by installNamedTemplate (which only handles the renamed
|
|
781
806
|
// settings.local.json sidecar), so without this step copy-mode installs
|
|
782
807
|
// miss every asset other than that single file. See
|
|
@@ -786,13 +811,10 @@ export async function runInstall(args) {
|
|
|
786
811
|
join(paths.home, "templates"),
|
|
787
812
|
{ refresh: opts.refresh, dryRun: opts.dryRun, mode: 0o644 },
|
|
788
813
|
);
|
|
789
|
-
// schemas/ tree — final-report
|
|
790
|
-
// okstra_ctl.final_report_schema.
|
|
791
|
-
//
|
|
792
|
-
//
|
|
793
|
-
// each run's instruction-set, and (b) validate-run's data.json schema
|
|
794
|
-
// check. Without this step copy-mode installs leave load_schema() unable
|
|
795
|
-
// to locate the schema. Link mode resolves it through the repo symlink.
|
|
814
|
+
// schemas/ tree — version-selected final-report v1/v2 schemas are loaded by
|
|
815
|
+
// okstra_ctl.final_report_schema. They support bundle excerpts, legacy
|
|
816
|
+
// re-renders, new task HTML, and validate-run. Link mode resolves the same
|
|
817
|
+
// files through the repo symlink.
|
|
796
818
|
const schemasResult = await copyTreeIfChanged(
|
|
797
819
|
join(runtimeRoot, "schemas"),
|
|
798
820
|
join(paths.home, "schemas"),
|
|
@@ -840,7 +862,7 @@ export async function runInstall(args) {
|
|
|
840
862
|
}
|
|
841
863
|
if (templatesResult.missingSource) {
|
|
842
864
|
process.stderr.write(
|
|
843
|
-
"warning: runtime/templates is empty. report
|
|
865
|
+
"warning: runtime/templates is empty. final-report Markdown and HTML templates will be missing — re-run the build step.\n",
|
|
844
866
|
);
|
|
845
867
|
}
|
|
846
868
|
if (schemasResult.missingSource) {
|
|
@@ -994,8 +1016,14 @@ export async function runEnsureInstalled(args) {
|
|
|
994
1016
|
}
|
|
995
1017
|
if (!(await dirExists(paths.pythonpath))) reasons.push(`missing ${paths.pythonpath}`);
|
|
996
1018
|
if (!(await dirExists(paths.agents))) reasons.push(`missing agents dir ${paths.agents}`);
|
|
997
|
-
|
|
998
|
-
|
|
1019
|
+
for (const relative of [
|
|
1020
|
+
["schemas", "final-report-v1.0.schema.json"],
|
|
1021
|
+
["schemas", "final-report-v2.0.schema.json"],
|
|
1022
|
+
["templates", "reports", "final-report-v2.template.md"],
|
|
1023
|
+
["templates", "reports", "html", "base.template.html"],
|
|
1024
|
+
]) {
|
|
1025
|
+
const installedPath = join(paths.home, ...relative);
|
|
1026
|
+
if (!(await fileExists(installedPath))) reasons.push(`missing ${installedPath}`);
|
|
999
1027
|
}
|
|
1000
1028
|
for (const reason of await promptResourceDriftReasons(paths)) {
|
|
1001
1029
|
reasons.push(reason);
|
|
@@ -10,9 +10,8 @@ Usage:
|
|
|
10
10
|
Runs the four Phase 7 steps in their contractual order against one final-report:
|
|
11
11
|
|
|
12
12
|
1. token-usage substitute real token/cost numbers into the data.json
|
|
13
|
-
2. render-views write the
|
|
14
|
-
|
|
15
|
-
approval target)
|
|
13
|
+
2. render-views write the schema-v2 task-specific *.html sibling; v1
|
|
14
|
+
keeps the legacy conditional interactive view
|
|
16
15
|
3. spawn-followups turn section 4 rows into task stubs
|
|
17
16
|
4. validate-run validate the finished run artifacts
|
|
18
17
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { runInstalledScript } from "../../lib/python-helper.mjs";
|
|
2
2
|
|
|
3
|
-
const USAGE = `okstra render-final-report — render the
|
|
3
|
+
const USAGE = `okstra render-final-report — render the AI handoff Markdown sibling of final-report data.json
|
|
4
4
|
|
|
5
5
|
Wraps the python helper (\`okstra-render-final-report.py\`) installed under
|
|
6
6
|
\`~/.okstra/bin/\` so skills call \`okstra render-final-report\` instead of
|
|
@@ -10,7 +10,9 @@ permission matching and prompts on every call).
|
|
|
10
10
|
Usage:
|
|
11
11
|
okstra render-final-report <path-to-final-report.data.json>
|
|
12
12
|
|
|
13
|
-
The argument is forwarded verbatim to the
|
|
13
|
+
The argument is forwarded verbatim to the Python helper. schemaVersion 1.0
|
|
14
|
+
keeps the legacy Markdown template; schemaVersion 2.0 selects the AI handoff
|
|
15
|
+
template. Human HTML is rendered separately from the same data.json.
|
|
14
16
|
`;
|
|
15
17
|
|
|
16
18
|
export async function run(args) {
|
|
@@ -3,20 +3,20 @@ import { runInstalledScript } from "../../lib/python-helper.mjs";
|
|
|
3
3
|
const USAGE = `okstra render-views — render the self-contained HTML view of a final-report
|
|
4
4
|
|
|
5
5
|
A thin spawn shim over \`scripts/okstra-render-report-views.py\` (installed
|
|
6
|
-
at \`$HOME/.okstra/bin/okstra-render-report-views.py\`).
|
|
7
|
-
report
|
|
6
|
+
at \`$HOME/.okstra/bin/okstra-render-report-views.py\`). Resolves the final-
|
|
7
|
+
report data and Markdown pair, then writes a single sibling:
|
|
8
8
|
|
|
9
|
-
<stem>.html — single-file self-contained human view
|
|
10
|
-
|
|
11
|
-
report has no §5 C-* clarification rows)
|
|
9
|
+
<stem>.html — single-file self-contained human view; schema v2 is
|
|
10
|
+
always generated, while v1/quick remains conditional
|
|
12
11
|
|
|
13
12
|
Usage:
|
|
14
|
-
okstra render-views <path-to-final-report.md>
|
|
13
|
+
okstra render-views <path-to-final-report.data.json|path-to-final-report.md>
|
|
15
14
|
[--task-key <key>] [--task-type <type>] [--seq <NNN>]
|
|
16
15
|
[--source-report <project-relative-path>]
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
Schema v2 data is rendered directly into its task-specific HTML view and is
|
|
18
|
+
always generated. Schema v1 and quick reports keep the legacy conditional
|
|
19
|
+
Markdown view. Optional flags override inferred report metadata.
|
|
20
20
|
`;
|
|
21
21
|
|
|
22
22
|
export async function run(args) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const RUNTIMES_MANIFEST_REL = "installed-runtimes.json";
|
|
2
2
|
export const RUNTIME_MANIFEST_SCHEMA_VERSION = 2;
|
|
3
|
-
export const EXPLICIT_RUNTIME_VALUES = ["claude-code", "codex", "external"];
|
|
3
|
+
export const EXPLICIT_RUNTIME_VALUES = ["claude-code", "codex", "antigravity", "external"];
|
|
4
4
|
|
|
5
5
|
export function runtimeListForSelection(runtime, resolution = null) {
|
|
6
6
|
if (runtime === "all") return [...EXPLICIT_RUNTIME_VALUES];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const RUNTIME_AUTO = "auto";
|
|
2
|
-
export const EXPLICIT_RUNTIMES = ["claude-code", "codex", "external"];
|
|
2
|
+
export const EXPLICIT_RUNTIMES = ["claude-code", "codex", "antigravity", "external"];
|
|
3
3
|
export const VALID_RUNTIME_REQUESTS = [RUNTIME_AUTO, ...EXPLICIT_RUNTIMES, "all"];
|
|
4
4
|
|
|
5
5
|
const VALID_HOSTS = new Set(EXPLICIT_RUNTIMES);
|
|
@@ -118,6 +118,6 @@ export function resolveRuntime({
|
|
|
118
118
|
|
|
119
119
|
return failResult(
|
|
120
120
|
request,
|
|
121
|
-
`host unknown: set OKSTRA_RUNTIME_HOST=claude-code|codex|external or pass ${explicitRuntimeFlag(command)} explicitly.`,
|
|
121
|
+
`host unknown: set OKSTRA_RUNTIME_HOST=claude-code|codex|antigravity|external or pass ${explicitRuntimeFlag(command)} explicitly.`,
|
|
122
122
|
);
|
|
123
123
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
const TEMPLATE_NAME = "_cli-wrapper-template.md";
|
|
5
|
+
const PARAM_SUFFIX = ".params.json";
|
|
6
|
+
|
|
7
|
+
async function pathExists(path) {
|
|
8
|
+
try {
|
|
9
|
+
await fs.access(path);
|
|
10
|
+
return true;
|
|
11
|
+
} catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function renderWorkerAgentDefinitions(workersRoot) {
|
|
17
|
+
const templatePath = join(workersRoot, TEMPLATE_NAME);
|
|
18
|
+
if (!(await pathExists(templatePath))) return [];
|
|
19
|
+
|
|
20
|
+
const template = await fs.readFile(templatePath, "utf8");
|
|
21
|
+
const entries = await fs.readdir(workersRoot);
|
|
22
|
+
const paramFiles = entries.filter((name) => name.endsWith(PARAM_SUFFIX)).sort();
|
|
23
|
+
|
|
24
|
+
return Promise.all(paramFiles.map(async (paramFile) => {
|
|
25
|
+
const params = JSON.parse(
|
|
26
|
+
await fs.readFile(join(workersRoot, paramFile), "utf8"),
|
|
27
|
+
);
|
|
28
|
+
const content = template.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
|
|
29
|
+
if (!(key in params)) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
`cli-wrapper template: unresolved token {{${key}}} in ${paramFile}`,
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
return params[key];
|
|
35
|
+
});
|
|
36
|
+
return {
|
|
37
|
+
name: paramFile.replace(/\.params\.json$/, ".md"),
|
|
38
|
+
content,
|
|
39
|
+
};
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function writeWorkerAgentDefinitions(workersRoot, destinationRoot) {
|
|
44
|
+
const definitions = await renderWorkerAgentDefinitions(workersRoot);
|
|
45
|
+
await fs.mkdir(destinationRoot, { recursive: true });
|
|
46
|
+
await Promise.all(definitions.map(({ name, content }) => (
|
|
47
|
+
fs.writeFile(join(destinationRoot, name), content, "utf8")
|
|
48
|
+
)));
|
|
49
|
+
return definitions;
|
|
50
|
+
}
|