okstra 0.147.0 → 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 (116) hide show
  1. package/README.md +21 -7
  2. package/docs/architecture/storage-model.md +34 -61
  3. package/docs/architecture.md +51 -49
  4. package/docs/cli.md +38 -21
  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 +10 -8
  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 +2 -2
  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.sh +3 -0
  29. package/runtime/prompts/lead/adapters/antigravity.md +48 -0
  30. package/runtime/prompts/lead/adapters/claude-code.md +13 -11
  31. package/runtime/prompts/lead/adapters/codex.md +7 -7
  32. package/runtime/prompts/lead/okstra-lead-contract.md +1 -1
  33. package/runtime/prompts/lead/report-writer.md +1 -1
  34. package/runtime/prompts/profiles/_coding-conventions-preflight.md +1 -1
  35. package/runtime/prompts/profiles/_common-contract.md +4 -4
  36. package/runtime/prompts/profiles/_implementation-deliverable.md +2 -2
  37. package/runtime/prompts/profiles/_implementation-diff-review.md +1 -1
  38. package/runtime/prompts/profiles/_implementation-executor.md +12 -12
  39. package/runtime/prompts/profiles/_implementation-self-check.md +4 -4
  40. package/runtime/prompts/profiles/_implementation-verifier.md +3 -3
  41. package/runtime/prompts/profiles/change-impact-analysis.md +2 -0
  42. package/runtime/prompts/profiles/error-analysis.md +2 -0
  43. package/runtime/prompts/profiles/feature-analysis.md +2 -0
  44. package/runtime/prompts/profiles/final-verification.md +3 -1
  45. package/runtime/prompts/profiles/forbidden-actions.json +4 -4
  46. package/runtime/prompts/profiles/implementation-planning.md +3 -1
  47. package/runtime/prompts/profiles/implementation.md +2 -2
  48. package/runtime/prompts/profiles/improvement-discovery.md +3 -1
  49. package/runtime/prompts/profiles/project-analysis.md +2 -0
  50. package/runtime/prompts/profiles/release-handoff.md +7 -7
  51. package/runtime/prompts/profiles/requirements-discovery.md +2 -0
  52. package/runtime/prompts/wizard/prompts.ko.json +9 -1
  53. package/runtime/python/okstra_ctl/codex_dispatch.py +68 -87
  54. package/runtime/python/okstra_ctl/dispatch_core.py +4 -22
  55. package/runtime/python/okstra_ctl/lead_events.py +1 -1
  56. package/runtime/python/okstra_ctl/lead_runtime.py +13 -2
  57. package/runtime/python/okstra_ctl/models.py +156 -8
  58. package/runtime/python/okstra_ctl/path_hints.py +9 -25
  59. package/runtime/python/okstra_ctl/paths.py +1 -1
  60. package/runtime/python/okstra_ctl/render.py +172 -74
  61. package/runtime/python/okstra_ctl/report_html/common.py +38 -2
  62. package/runtime/python/okstra_ctl/report_html/filters.py +104 -0
  63. package/runtime/python/okstra_ctl/report_html/render.py +7 -0
  64. package/runtime/python/okstra_ctl/report_html/view_models/change_impact_analysis.py +2 -1
  65. package/runtime/python/okstra_ctl/report_html/view_models/error_analysis.py +2 -1
  66. package/runtime/python/okstra_ctl/report_html/view_models/feature_analysis.py +2 -1
  67. package/runtime/python/okstra_ctl/report_html/view_models/final_verification.py +2 -1
  68. package/runtime/python/okstra_ctl/report_html/view_models/implementation.py +2 -1
  69. package/runtime/python/okstra_ctl/report_html/view_models/implementation_planning.py +2 -1
  70. package/runtime/python/okstra_ctl/report_html/view_models/improvement_discovery.py +2 -1
  71. package/runtime/python/okstra_ctl/report_html/view_models/release_handoff.py +2 -1
  72. package/runtime/python/okstra_ctl/report_html/view_models/requirements_discovery.py +2 -1
  73. package/runtime/python/okstra_ctl/report_html/visualizations.py +32 -6
  74. package/runtime/python/okstra_ctl/run.py +264 -45
  75. package/runtime/python/okstra_ctl/runner_resolution.py +103 -0
  76. package/runtime/python/okstra_ctl/team.py +2 -7
  77. package/runtime/python/okstra_ctl/wizard.py +194 -21
  78. package/runtime/python/okstra_ctl/worker_artifacts.py +46 -0
  79. package/runtime/python/okstra_ctl/workers.py +3 -1
  80. package/runtime/python/okstra_ctl/workflow.py +4 -2
  81. package/runtime/python/okstra_token_usage/__init__.py +1 -0
  82. package/runtime/python/okstra_token_usage/collect.py +32 -23
  83. package/runtime/python/okstra_token_usage/pricing.py +35 -3
  84. package/runtime/schemas/final-report-v2.0.schema.json +2 -2
  85. package/runtime/skills/okstra-run/SKILL.md +31 -42
  86. package/runtime/templates/prd/pr-body.template.md +1 -1
  87. package/runtime/templates/reports/html/assets/base.css +6 -3
  88. package/runtime/templates/reports/html/base.template.html +22 -8
  89. package/runtime/templates/reports/html/macros/forms.html +2 -2
  90. package/runtime/templates/reports/html/macros/layout.html +5 -5
  91. package/runtime/templates/reports/html/macros/visualizations.html +11 -1
  92. package/runtime/templates/reports/html/tasks/change-impact-analysis.template.html +11 -11
  93. package/runtime/templates/reports/html/tasks/error-analysis.template.html +12 -12
  94. package/runtime/templates/reports/html/tasks/feature-analysis.template.html +9 -9
  95. package/runtime/templates/reports/html/tasks/final-verification.template.html +7 -7
  96. package/runtime/templates/reports/html/tasks/implementation-planning.template.html +12 -12
  97. package/runtime/templates/reports/html/tasks/implementation.template.html +7 -7
  98. package/runtime/templates/reports/html/tasks/improvement-discovery.template.html +6 -6
  99. package/runtime/templates/reports/html/tasks/project-analysis.template.html +11 -11
  100. package/runtime/templates/reports/html/tasks/release-handoff.template.html +5 -5
  101. package/runtime/templates/reports/html/tasks/requirements-discovery.template.html +8 -8
  102. package/runtime/templates/reports/report.js +21 -4
  103. package/runtime/templates/reports/settings.template.json +4 -0
  104. package/runtime/templates/reports/task-brief.template.md +7 -7
  105. package/runtime/validators/validate-run.py +11 -6
  106. package/runtime/validators/validate_session_conformance.py +2 -1
  107. package/src/cli-registry.mjs +4 -4
  108. package/src/commands/execute/codex-dispatch.mjs +7 -10
  109. package/src/commands/execute/render-bundle.mjs +3 -3
  110. package/src/commands/execute/run.mjs +17 -52
  111. package/src/commands/execute/wizard.mjs +4 -1
  112. package/src/commands/lifecycle/doctor.mjs +6 -3
  113. package/src/commands/lifecycle/install.mjs +31 -8
  114. package/src/lib/runtime-manifest.mjs +1 -1
  115. package/src/lib/runtime-resolver.mjs +2 -2
  116. package/src/lib/worker-agent-render.mjs +50 -0
@@ -7,10 +7,10 @@ const USAGE = `okstra run — host-aware okstra execution front door
7
7
 
8
8
  Usage:
9
9
  okstra run --project-root <dir> --project-id <id> --task-group <tg> \\
10
- --task-id <tid> --task-type <type> [--lead-runtime auto|claude-code|codex|external]
10
+ --task-id <tid> --task-type <type> [--lead-runtime auto|claude-code|codex|antigravity|external]
11
11
 
12
- Claude Code native execution remains the /okstra-run skill front door. Bare
13
- 'okstra run' orchestrates Codex and external/tmux CLI execution.
12
+ Host-native Claude Code, Codex, and Antigravity execution use the okstra-run
13
+ skill front door. Bare 'okstra run' orchestrates only external/tmux all-CLI execution.
14
14
  `;
15
15
 
16
16
  function flagValue(args, flag) {
@@ -48,55 +48,22 @@ function projectRootFromArgs(args) {
48
48
  return flagValue(args, "--project-root");
49
49
  }
50
50
 
51
- function withoutDispatchOnlyFlags(args) {
52
- const out = [];
53
- for (let i = 0; i < args.length; i += 1) {
54
- const arg = args[i];
55
- if (arg === "--enable-codex-report-writer") continue;
56
- if (arg === "--report-writer-codex-model") {
57
- i += 1;
58
- continue;
59
- }
60
- if (arg.startsWith("--report-writer-codex-model=")) continue;
61
- out.push(arg);
62
- }
63
- return out;
64
- }
65
-
66
51
  function renderArgs(args, resolution) {
67
52
  return [
68
53
  "--lead-runtime", resolution.resolvedRuntime,
69
54
  "--lead-runtime-request", resolution.requestedRuntime,
70
55
  "--runtime-resolution-json", JSON.stringify(resolution),
71
- ...withoutDispatchOnlyFlags(withoutLeadRuntimeFlags(args)),
56
+ ...withoutLeadRuntimeFlags(args),
72
57
  ];
73
58
  }
74
59
 
75
- function codexDispatchArgs(args, projectRoot, runManifestPath) {
76
- const out = ["--project-root", projectRoot, "--run-manifest", runManifestPath];
77
- for (let i = 0; i < args.length; i += 1) {
78
- const arg = args[i];
79
- if (arg === "--enable-codex-report-writer") {
80
- out.push(arg);
81
- continue;
82
- }
83
- if (arg === "--report-writer-codex-model") {
84
- out.push(arg, args[i + 1] ?? "");
85
- i += 1;
86
- continue;
87
- }
88
- if (arg.startsWith("--report-writer-codex-model=")) out.push(arg);
89
- }
90
- return out;
91
- }
92
-
93
60
  export function buildRunPlan({ args, paths, resolution, runManifestPath = "" }) {
94
61
  void paths;
95
62
  const projectRoot = projectRootFromArgs(args);
96
63
  if (resolution.resolvedRuntime === "claude-code") {
97
64
  return {
98
65
  ok: false,
99
- reason: "Bare okstra run cannot invoke Claude Code TeamCreate / Agent(...). Use /okstra-run in Claude Code or pass --lead-runtime external|codex.",
66
+ reason: "Bare okstra run cannot invoke host-native Claude workers. Use the okstra-run skill in Claude Code or pass --lead-runtime external.",
100
67
  commands: [],
101
68
  };
102
69
  }
@@ -115,12 +82,17 @@ export function buildRunPlan({ args, paths, resolution, runManifestPath = "" })
115
82
 
116
83
  if (resolution.resolvedRuntime === "codex") {
117
84
  return {
118
- ok: true,
119
- reason: resolution.reason,
120
- commands: [
121
- { name: "codex-run", args: renderArgs(args, resolution), capture: true },
122
- { name: "codex-dispatch", args: codexDispatchArgs(args, projectRoot, runManifestPath), capture: false },
123
- ],
85
+ ok: false,
86
+ reason: "Bare okstra run cannot invoke host-native Codex workers. Use the okstra-run skill in Codex or pass --lead-runtime external for an all-CLI run.",
87
+ commands: [],
88
+ };
89
+ }
90
+
91
+ if (resolution.resolvedRuntime === "antigravity") {
92
+ return {
93
+ ok: false,
94
+ reason: "Bare okstra run cannot invoke host-native Antigravity workers. Use the okstra-run skill in Antigravity or pass --lead-runtime external for an all-CLI run.",
95
+ commands: [],
124
96
  };
125
97
  }
126
98
 
@@ -147,11 +119,6 @@ async function runTeam(args) {
147
119
  return await runTeamCommand(args);
148
120
  }
149
121
 
150
- async function runCodexDispatch(args) {
151
- const { run: runCodexDispatchCommand } = await import("./codex-dispatch.mjs");
152
- return await runCodexDispatchCommand(args);
153
- }
154
-
155
122
  export async function run(args) {
156
123
  if (args.includes("--help") || args.includes("-h")) {
157
124
  process.stdout.write(USAGE);
@@ -192,9 +159,7 @@ export async function run(args) {
192
159
 
193
160
  const plan = buildRunPlan({ args, paths, resolution, runManifestPath });
194
161
  for (const command of plan.commands.slice(1)) {
195
- const code = command.name.startsWith("team ")
196
- ? await runTeam(command.args)
197
- : await runCodexDispatch(command.args);
162
+ const code = await runTeam(command.args);
198
163
  if (code !== 0) return code;
199
164
  }
200
165
  return 0;
@@ -20,7 +20,7 @@ Subcommands:
20
20
 
21
21
  Usage:
22
22
  okstra wizard new-state-file
23
- okstra wizard init --state-file <path> --project-root <p> --project-id <id>
23
+ okstra wizard init --state-file <path> --project-root <p> --project-id <id> --host-runtime <runtime>
24
24
  okstra wizard step --state-file <path> [--answer <value>]
25
25
  okstra wizard render-args --state-file <path>
26
26
  okstra wizard confirmation --state-file <path>
@@ -106,6 +106,9 @@ export async function run(args) {
106
106
  pyArgs.push("--workspace-root", paths.workspace);
107
107
  pyArgs.push("--project-root", flags["project-root"]);
108
108
  pyArgs.push("--project-id", flags["project-id"]);
109
+ if (flags["host-runtime"]) {
110
+ pyArgs.push("--host-runtime", flags["host-runtime"]);
111
+ }
109
112
  } else if (sub === "step" && flags.answer !== undefined) {
110
113
  pyArgs.push("--answer", flags.answer);
111
114
  }
@@ -14,7 +14,7 @@ const USAGE = `okstra doctor — diagnose the installed runtime
14
14
 
15
15
  Usage:
16
16
  okstra doctor Run all checks and print a summary
17
- okstra doctor --runtime <claude-code|codex|external|all>
17
+ okstra doctor --runtime <claude-code|codex|antigravity|external|all>
18
18
  okstra doctor --phase <phase>
19
19
  okstra doctor --json Machine-readable result
20
20
  Checks:
@@ -48,7 +48,7 @@ export function parseDoctorArgs(args) {
48
48
  } else if (arg === "--runtime" || arg.startsWith("--runtime=")) {
49
49
  const value = arg.startsWith("--runtime=") ? arg.slice("--runtime=".length) : args[i + 1];
50
50
  if (!value || value.startsWith("--")) {
51
- throw new Error("--runtime requires one of: claude-code, codex, external, all");
51
+ throw new Error("--runtime requires one of: claude-code, codex, antigravity, external, all");
52
52
  }
53
53
  result.runtime = validateInstallRuntime(value);
54
54
  if (arg === "--runtime") i++;
@@ -226,6 +226,9 @@ export async function run(args) {
226
226
  await check("bin: okstra.sh", () => checkBashEntry(paths.bin, "okstra.sh")),
227
227
  await check("bin: okstra-codex-exec.sh", () => checkBashEntry(paths.bin, "okstra-codex-exec.sh")),
228
228
  await check("bin: okstra-antigravity-exec.sh", () => checkBashEntry(paths.bin, "okstra-antigravity-exec.sh")),
229
+ await check("bin: okstra-grok-exec.sh", () => checkBashEntry(paths.bin, "okstra-grok-exec.sh")),
230
+ await check("bin: okstra-kimi-exec.sh", () => checkBashEntry(paths.bin, "okstra-kimi-exec.sh")),
231
+ await check("bin: okstra-provider-exec.py", () => checkBashEntry(paths.bin, "okstra-provider-exec.py")),
229
232
  await check("bin: okstra-central.sh", () => checkBashEntry(paths.bin, "okstra-central.sh")),
230
233
  ...(await Promise.all(
231
234
  requiredSkillNamesForRuntime(resolvedRuntime).map((name) =>
@@ -275,7 +278,7 @@ export async function run(args) {
275
278
 
276
279
  if (!runtimeResolution.ok) {
277
280
  process.stdout.write(
278
- ` [WARN] runtime host: ${runtimeResolution.reason} skill checks skipped — pass --runtime <claude-code|codex|external> to include them.\n`,
281
+ ` [WARN] runtime host: ${runtimeResolution.reason} skill checks skipped — pass --runtime <claude-code|codex|antigravity|external> to include them.\n`,
279
282
  );
280
283
  }
281
284
  if (dockerWarning) {
@@ -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.
@@ -120,13 +125,15 @@ const ENSURE_USAGE = `okstra ensure-installed — idempotent install check
120
125
 
121
126
  Usage:
122
127
  okstra ensure-installed Verify install; reinstall if version/files drift
123
- okstra ensure-installed --runtime <claude-code|codex|external|all>
128
+ okstra ensure-installed --runtime <claude-code|codex|antigravity|external|all>
124
129
  okstra ensure-installed -q Same, but suppress success output
125
130
 
126
131
  Skills call this on every run. Returns 0 quickly when the install is fresh.
127
132
  `;
128
133
 
129
- 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
+ ]);
130
137
 
131
138
  export function runtimeIncludesClaudeAssets(runtime, resolution = null) {
132
139
  if (runtime === "claude-code" || runtime === "all") return true;
@@ -140,7 +147,7 @@ function readRuntimeFlag(args, index) {
140
147
  }
141
148
  const next = args[index + 1];
142
149
  if (!next || next.startsWith("--")) {
143
- 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");
144
151
  }
145
152
  return { value: next, nextIndex: index + 1 };
146
153
  }
@@ -148,7 +155,7 @@ function readRuntimeFlag(args, index) {
148
155
  export function validateInstallRuntime(value) {
149
156
  const runtime = normalizeRuntimeRequest(value);
150
157
  if (!INSTALL_RUNTIMES.has(runtime)) {
151
- 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)`);
152
159
  }
153
160
  return runtime;
154
161
  }
@@ -496,7 +503,9 @@ async function listWorkerFiles(workersRoot) {
496
503
  try {
497
504
  const entries = await fs.readdir(workersRoot, { withFileTypes: true });
498
505
  return entries
499
- .filter((e) => e.isFile() && e.name.endsWith(".md"))
506
+ .filter((e) => (
507
+ e.isFile() && e.name.endsWith(".md") && !e.name.startsWith("_")
508
+ ))
500
509
  .map((e) => e.name);
501
510
  } catch (err) {
502
511
  if (err.code === "ENOENT") return [];
@@ -551,18 +560,32 @@ async function installAgentsCopy(runtimeRoot, opts) {
551
560
  async function installAgentsLink(repoAbs, opts) {
552
561
  const { dryRun, quiet } = opts;
553
562
  const srcRoot = join(repoAbs, "agents", "workers");
554
- 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();
555
569
  if (names.length === 0) {
556
570
  if (!quiet) process.stdout.write(" agents: <repo>/agents/workers missing — skipped\n");
557
571
  return { installed: [] };
558
572
  }
559
573
  if (!dryRun) await fs.mkdir(CLAUDE_AGENTS_DIR, { recursive: true });
560
- for (const name of names) {
574
+ for (const name of sourceNames) {
561
575
  const src = join(srcRoot, name);
562
576
  const dst = join(CLAUDE_AGENTS_DIR, name);
563
577
  const action = await ensureSymlink(src, dst, { dryRun });
564
578
  if (!quiet) process.stdout.write(` agents/${name}: ${action}\n`);
565
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
+ }
566
589
  return { installed: names };
567
590
  }
568
591
 
@@ -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
+ }