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.
Files changed (137) hide show
  1. package/README.md +23 -9
  2. package/docs/architecture/storage-model.md +39 -65
  3. package/docs/architecture.md +68 -60
  4. package/docs/cli.md +40 -23
  5. package/docs/for-ai/skills/okstra-run.md +13 -34
  6. package/docs/performance-improvement-plan-v2.md +2 -2
  7. package/docs/pr-template-usage.md +1 -1
  8. package/docs/project-structure-overview.md +26 -22
  9. package/docs/task-process/README.md +4 -4
  10. package/docs/task-process/common-flow.md +12 -12
  11. package/docs/task-process/final-verification.md +2 -2
  12. package/docs/task-process/implementation.md +1 -1
  13. package/docs/task-process/release-handoff.md +1 -1
  14. package/package.json +2 -2
  15. package/runtime/BUILD.json +2 -2
  16. package/runtime/agents/workers/antigravity-worker.md +2 -2
  17. package/runtime/agents/workers/claude-worker.md +1 -1
  18. package/runtime/agents/workers/codex-worker.md +2 -2
  19. package/runtime/agents/workers/grok-worker.md +256 -0
  20. package/runtime/agents/workers/kimi-worker.md +256 -0
  21. package/runtime/agents/workers/report-writer-worker.md +12 -12
  22. package/runtime/bin/lib/okstra/cli.sh +13 -1
  23. package/runtime/bin/lib/okstra/globals.sh +3 -0
  24. package/runtime/bin/lib/okstra/usage.sh +17 -12
  25. package/runtime/bin/okstra-grok-exec.sh +5 -0
  26. package/runtime/bin/okstra-kimi-exec.sh +5 -0
  27. package/runtime/bin/okstra-provider-exec.py +235 -0
  28. package/runtime/bin/okstra-render-final-report.py +4 -4
  29. package/runtime/bin/okstra-render-report-views.py +100 -12
  30. package/runtime/bin/okstra.sh +3 -0
  31. package/runtime/prompts/lead/adapters/antigravity.md +48 -0
  32. package/runtime/prompts/lead/adapters/claude-code.md +13 -11
  33. package/runtime/prompts/lead/adapters/codex.md +7 -7
  34. package/runtime/prompts/lead/okstra-lead-contract.md +5 -5
  35. package/runtime/prompts/lead/report-writer.md +16 -12
  36. package/runtime/prompts/profiles/_coding-conventions-preflight.md +1 -1
  37. package/runtime/prompts/profiles/_common-contract.md +16 -10
  38. package/runtime/prompts/profiles/_implementation-deliverable.md +2 -2
  39. package/runtime/prompts/profiles/_implementation-diff-review.md +1 -1
  40. package/runtime/prompts/profiles/_implementation-executor.md +12 -12
  41. package/runtime/prompts/profiles/_implementation-self-check.md +4 -4
  42. package/runtime/prompts/profiles/_implementation-verifier.md +3 -3
  43. package/runtime/prompts/profiles/change-impact-analysis.md +2 -0
  44. package/runtime/prompts/profiles/error-analysis.md +2 -0
  45. package/runtime/prompts/profiles/feature-analysis.md +2 -0
  46. package/runtime/prompts/profiles/final-verification.md +3 -1
  47. package/runtime/prompts/profiles/forbidden-actions.json +4 -4
  48. package/runtime/prompts/profiles/implementation-planning.md +3 -1
  49. package/runtime/prompts/profiles/implementation.md +2 -2
  50. package/runtime/prompts/profiles/improvement-discovery.md +6 -2
  51. package/runtime/prompts/profiles/project-analysis.md +2 -0
  52. package/runtime/prompts/profiles/release-handoff.md +7 -7
  53. package/runtime/prompts/profiles/requirements-discovery.md +2 -0
  54. package/runtime/prompts/wizard/prompts.ko.json +9 -1
  55. package/runtime/python/okstra_ctl/codex_dispatch.py +68 -87
  56. package/runtime/python/okstra_ctl/dispatch_core.py +4 -22
  57. package/runtime/python/okstra_ctl/final_report_schema.py +37 -12
  58. package/runtime/python/okstra_ctl/lead_events.py +1 -1
  59. package/runtime/python/okstra_ctl/lead_runtime.py +13 -2
  60. package/runtime/python/okstra_ctl/models.py +156 -8
  61. package/runtime/python/okstra_ctl/path_hints.py +9 -25
  62. package/runtime/python/okstra_ctl/paths.py +1 -1
  63. package/runtime/python/okstra_ctl/render.py +172 -74
  64. package/runtime/python/okstra_ctl/render_final_report.py +136 -28
  65. package/runtime/python/okstra_ctl/report_contract.py +124 -0
  66. package/runtime/python/okstra_ctl/report_finalize.py +1 -1
  67. package/runtime/python/okstra_ctl/report_html/__init__.py +10 -0
  68. package/runtime/python/okstra_ctl/report_html/common.py +86 -0
  69. package/runtime/python/okstra_ctl/report_html/filters.py +104 -0
  70. package/runtime/python/okstra_ctl/report_html/models.py +59 -0
  71. package/runtime/python/okstra_ctl/report_html/render.py +76 -0
  72. package/runtime/python/okstra_ctl/report_html/router.py +40 -0
  73. package/runtime/python/okstra_ctl/report_html/view_models/__init__.py +1 -0
  74. package/runtime/python/okstra_ctl/report_html/view_models/change_impact_analysis.py +39 -0
  75. package/runtime/python/okstra_ctl/report_html/view_models/error_analysis.py +49 -0
  76. package/runtime/python/okstra_ctl/report_html/view_models/feature_analysis.py +39 -0
  77. package/runtime/python/okstra_ctl/report_html/view_models/final_verification.py +47 -0
  78. package/runtime/python/okstra_ctl/report_html/view_models/implementation.py +47 -0
  79. package/runtime/python/okstra_ctl/report_html/view_models/implementation_planning.py +103 -0
  80. package/runtime/python/okstra_ctl/report_html/view_models/improvement_discovery.py +43 -0
  81. package/runtime/python/okstra_ctl/report_html/view_models/project_analysis.py +54 -0
  82. package/runtime/python/okstra_ctl/report_html/view_models/release_handoff.py +54 -0
  83. package/runtime/python/okstra_ctl/report_html/view_models/requirements_discovery.py +55 -0
  84. package/runtime/python/okstra_ctl/report_html/visualizations.py +139 -0
  85. package/runtime/python/okstra_ctl/report_view_artifacts.py +4 -1
  86. package/runtime/python/okstra_ctl/report_views.py +15 -43
  87. package/runtime/python/okstra_ctl/run.py +276 -51
  88. package/runtime/python/okstra_ctl/runner_resolution.py +103 -0
  89. package/runtime/python/okstra_ctl/schema_excerpt.py +7 -17
  90. package/runtime/python/okstra_ctl/team.py +2 -7
  91. package/runtime/python/okstra_ctl/wizard.py +194 -21
  92. package/runtime/python/okstra_ctl/worker_artifacts.py +46 -0
  93. package/runtime/python/okstra_ctl/workers.py +3 -1
  94. package/runtime/python/okstra_ctl/workflow.py +4 -2
  95. package/runtime/python/okstra_token_usage/__init__.py +1 -0
  96. package/runtime/python/okstra_token_usage/collect.py +32 -23
  97. package/runtime/python/okstra_token_usage/pricing.py +35 -3
  98. package/runtime/schemas/final-report-v2.0.schema.json +3923 -0
  99. package/runtime/skills/okstra-run/SKILL.md +31 -42
  100. package/runtime/templates/prd/pr-body.template.md +1 -1
  101. package/runtime/templates/reports/final-report-v2.template.md +66 -0
  102. package/runtime/templates/reports/html/assets/base.css +41 -0
  103. package/runtime/templates/reports/html/assets/base.js +5 -0
  104. package/runtime/templates/reports/html/base.template.html +79 -0
  105. package/runtime/templates/reports/html/macros/forms.html +47 -0
  106. package/runtime/templates/reports/html/macros/layout.html +19 -0
  107. package/runtime/templates/reports/html/macros/visualizations.html +27 -0
  108. package/runtime/templates/reports/html/tasks/change-impact-analysis.template.html +40 -0
  109. package/runtime/templates/reports/html/tasks/error-analysis.template.html +40 -0
  110. package/runtime/templates/reports/html/tasks/feature-analysis.template.html +40 -0
  111. package/runtime/templates/reports/html/tasks/final-verification.template.html +39 -0
  112. package/runtime/templates/reports/html/tasks/implementation-planning.template.html +47 -0
  113. package/runtime/templates/reports/html/tasks/implementation.template.html +40 -0
  114. package/runtime/templates/reports/html/tasks/improvement-discovery.template.html +29 -0
  115. package/runtime/templates/reports/html/tasks/project-analysis.template.html +57 -0
  116. package/runtime/templates/reports/html/tasks/release-handoff.template.html +36 -0
  117. package/runtime/templates/reports/html/tasks/requirements-discovery.template.html +37 -0
  118. package/runtime/templates/reports/report.js +21 -4
  119. package/runtime/templates/reports/settings.template.json +4 -0
  120. package/runtime/templates/reports/task-brief.template.md +7 -7
  121. package/runtime/validators/validate-report-views.py +86 -4
  122. package/runtime/validators/validate-run.py +73 -15
  123. package/runtime/validators/validate_improvement_report.py +55 -0
  124. package/runtime/validators/validate_session_conformance.py +2 -1
  125. package/src/cli-registry.mjs +4 -4
  126. package/src/commands/execute/codex-dispatch.mjs +7 -10
  127. package/src/commands/execute/render-bundle.mjs +3 -3
  128. package/src/commands/execute/run.mjs +17 -52
  129. package/src/commands/execute/wizard.mjs +4 -1
  130. package/src/commands/lifecycle/doctor.mjs +6 -3
  131. package/src/commands/lifecycle/install.mjs +49 -21
  132. package/src/commands/report/finalize.mjs +2 -3
  133. package/src/commands/report/render-final-report.mjs +4 -2
  134. package/src/commands/report/render-views.mjs +8 -8
  135. package/src/lib/runtime-manifest.mjs +1 -1
  136. package/src/lib/runtime-resolver.mjs +2 -2
  137. 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 (report.css / report.js / *.template.md)
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(["auto", "claude-code", "codex", "external", "all"]);
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) => e.isFile() && e.name.endsWith(".md"))
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 names = await listWorkerFiles(srcRoot);
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 names) {
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 / report.js / *.template.md are consumed at
779
- // runtime by okstra-render-report-views.py and final-report assembly. They
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-v1.0.schema.json is loaded at runtime by
790
- // okstra_ctl.final_report_schema.load_schema() (parent-walk from the
791
- // installed okstra_ctl package finds ~/.okstra/schemas/). It is needed by
792
- // (a) prepare_task_bundle to write the per-task-type schema excerpt into
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.css / report.js will be missing — re-run the build step.\n",
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
- if (!(await fileExists(join(paths.home, "schemas", "final-report-v1.0.schema.json")))) {
998
- reasons.push(`missing ${join(paths.home, "schemas", "final-report-v1.0.schema.json")}`);
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 self-contained *.html sibling (skipped when the
14
- report has no C-* clarification rows and is not a plan
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 markdown sibling of a final-report data.json
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 python helper.
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\`). Reads the final-
7
- report MD and writes a single sibling:
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 with form
10
- controls on §5 clarification rows (skipped when the
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
- When the optional flags are omitted the script infers from the report
19
- path and its '- Task Type:' / '- Task Key:' lines.
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
+ }