voratiq 0.1.0-beta.21 → 0.1.0-beta.22

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 (149) hide show
  1. package/README.md +18 -22
  2. package/dist/agents/launch/chat.d.ts +3 -1
  3. package/dist/agents/launch/chat.js +2 -0
  4. package/dist/bin.js +28 -7
  5. package/dist/cli/auto.js +1 -0
  6. package/dist/cli/contract.d.ts +26 -17
  7. package/dist/cli/contract.js +3 -1
  8. package/dist/cli/doctor.d.ts +12 -0
  9. package/dist/cli/doctor.js +115 -0
  10. package/dist/cli/list.js +4 -1
  11. package/dist/cli/operator-envelope.d.ts +19 -6
  12. package/dist/cli/operator-envelope.js +61 -1
  13. package/dist/cli/run.js +2 -0
  14. package/dist/cli/verify.d.ts +1 -1
  15. package/dist/cli/verify.js +48 -9
  16. package/dist/commands/auto/command.d.ts +1 -0
  17. package/dist/commands/auto/command.js +22 -12
  18. package/dist/commands/auto/errors.js +1 -1
  19. package/dist/commands/doctor/agents.d.ts +5 -0
  20. package/dist/commands/{init → doctor}/agents.js +37 -19
  21. package/dist/commands/doctor/command.d.ts +22 -0
  22. package/dist/commands/doctor/command.js +99 -0
  23. package/dist/commands/doctor/environment.d.ts +2 -0
  24. package/dist/commands/{init → doctor}/environment.js +38 -6
  25. package/dist/commands/{init/types.d.ts → doctor/fix-types.d.ts} +30 -9
  26. package/dist/commands/doctor/fix.d.ts +2 -0
  27. package/dist/commands/{init/command.js → doctor/fix.js} +106 -10
  28. package/dist/commands/doctor/reconcile.d.ts +2 -0
  29. package/dist/commands/doctor/reconcile.js +101 -0
  30. package/dist/commands/interactive/lifecycle.d.ts +2 -0
  31. package/dist/commands/interactive/lifecycle.js +8 -0
  32. package/dist/commands/list/command.d.ts +1 -0
  33. package/dist/commands/list/command.js +211 -352
  34. package/dist/commands/list/normalization.d.ts +56 -0
  35. package/dist/commands/list/normalization.js +317 -0
  36. package/dist/commands/message/command.d.ts +2 -1
  37. package/dist/commands/message/command.js +35 -14
  38. package/dist/commands/message/errors.d.ts +12 -3
  39. package/dist/commands/message/errors.js +19 -3
  40. package/dist/commands/reduce/command.js +16 -17
  41. package/dist/commands/reduce/errors.d.ts +2 -2
  42. package/dist/commands/reduce/errors.js +3 -3
  43. package/dist/commands/reduce/targets.js +11 -2
  44. package/dist/commands/root-launcher/command.js +12 -6
  45. package/dist/commands/run/command.d.ts +1 -0
  46. package/dist/commands/run/command.js +4 -1
  47. package/dist/commands/run/record-init.d.ts +2 -0
  48. package/dist/commands/run/record-init.js +2 -1
  49. package/dist/commands/run/spec-provenance.d.ts +37 -0
  50. package/dist/commands/run/spec-provenance.js +384 -0
  51. package/dist/commands/run/validation.d.ts +4 -0
  52. package/dist/commands/run/validation.js +25 -62
  53. package/dist/commands/spec/command.js +19 -6
  54. package/dist/commands/spec/errors.d.ts +5 -0
  55. package/dist/commands/spec/errors.js +9 -0
  56. package/dist/commands/verify/agents.d.ts +4 -2
  57. package/dist/commands/verify/agents.js +4 -11
  58. package/dist/commands/verify/command.js +15 -5
  59. package/dist/commands/verify/errors.d.ts +12 -0
  60. package/dist/commands/verify/errors.js +22 -0
  61. package/dist/commands/verify/targets.js +108 -12
  62. package/dist/competition/shared/preflight.d.ts +1 -1
  63. package/dist/competition/shared/preflight.js +15 -2
  64. package/dist/contracts/list.d.ts +129 -149
  65. package/dist/contracts/list.js +47 -99
  66. package/dist/domain/interactive/persistence/adapter.d.ts +23 -0
  67. package/dist/domain/interactive/persistence/adapter.js +42 -0
  68. package/dist/domain/message/model/types.d.ts +32 -0
  69. package/dist/domain/message/model/types.js +25 -0
  70. package/dist/domain/reduce/competition/adapter.js +21 -7
  71. package/dist/domain/reduce/competition/finalize.d.ts +7 -0
  72. package/dist/domain/reduce/competition/finalize.js +19 -0
  73. package/dist/domain/reduce/model/types.d.ts +3 -3
  74. package/dist/domain/run/competition/agents/artifacts.js +4 -2
  75. package/dist/domain/run/competition/errors.d.ts +1 -1
  76. package/dist/domain/run/competition/errors.js +4 -7
  77. package/dist/domain/run/model/types.d.ts +384 -0
  78. package/dist/domain/run/model/types.js +87 -0
  79. package/dist/domain/spec/competition/adapter.d.ts +1 -0
  80. package/dist/domain/spec/competition/adapter.js +6 -1
  81. package/dist/domain/spec/model/types.d.ts +3 -0
  82. package/dist/domain/spec/model/types.js +5 -0
  83. package/dist/domain/verify/competition/finalize.d.ts +9 -0
  84. package/dist/domain/verify/competition/finalize.js +22 -3
  85. package/dist/domain/verify/model/types.d.ts +2 -2
  86. package/dist/interactive/providers/mcp.d.ts +1 -0
  87. package/dist/interactive/providers/mcp.js +45 -7
  88. package/dist/interactive/substrate.js +20 -3
  89. package/dist/mcp/server.js +26 -9
  90. package/dist/policy/verification.js +18 -1
  91. package/dist/preflight/agents.d.ts +24 -0
  92. package/dist/preflight/agents.js +71 -0
  93. package/dist/preflight/environment.d.ts +6 -0
  94. package/dist/preflight/environment.js +17 -0
  95. package/dist/preflight/formatting.d.ts +5 -0
  96. package/dist/preflight/formatting.js +20 -0
  97. package/dist/preflight/index.d.ts +2 -0
  98. package/dist/preflight/index.js +5 -9
  99. package/dist/preflight/operator.d.ts +32 -0
  100. package/dist/preflight/operator.js +40 -0
  101. package/dist/preflight/settings.d.ts +2 -0
  102. package/dist/preflight/settings.js +17 -0
  103. package/dist/render/transcripts/interactive.d.ts +16 -0
  104. package/dist/render/transcripts/interactive.js +42 -0
  105. package/dist/render/transcripts/list.d.ts +41 -0
  106. package/dist/render/transcripts/list.js +152 -3
  107. package/dist/render/transcripts/message.d.ts +2 -1
  108. package/dist/render/transcripts/message.js +19 -20
  109. package/dist/render/transcripts/reduce.d.ts +1 -0
  110. package/dist/render/transcripts/reduce.js +21 -21
  111. package/dist/render/transcripts/root-launcher.js +2 -12
  112. package/dist/render/transcripts/run.d.ts +3 -0
  113. package/dist/render/transcripts/run.js +30 -4
  114. package/dist/render/transcripts/spec.js +5 -8
  115. package/dist/render/transcripts/verify.d.ts +5 -3
  116. package/dist/render/transcripts/verify.js +44 -31
  117. package/dist/render/utils/duration.d.ts +5 -0
  118. package/dist/render/utils/duration.js +6 -0
  119. package/dist/render/utils/runs.d.ts +1 -0
  120. package/dist/render/utils/runs.js +1 -0
  121. package/dist/render/utils/transcript-shell.d.ts +2 -1
  122. package/dist/render/utils/transcript-shell.js +19 -6
  123. package/dist/utils/errors.d.ts +2 -1
  124. package/dist/utils/errors.js +3 -1
  125. package/dist/utils/git.d.ts +1 -1
  126. package/dist/utils/git.js +25 -2
  127. package/dist/utils/list-target.d.ts +4 -0
  128. package/dist/utils/list-target.js +35 -0
  129. package/dist/utils/terminal.d.ts +1 -0
  130. package/dist/utils/terminal.js +11 -0
  131. package/dist/workspace/chat/artifacts.d.ts +7 -0
  132. package/dist/workspace/chat/artifacts.js +94 -3
  133. package/dist/workspace/errors.js +2 -2
  134. package/dist/workspace/managed-state.d.ts +32 -0
  135. package/dist/workspace/managed-state.js +103 -0
  136. package/dist/workspace/setup.js +66 -2
  137. package/dist/workspace/shim.d.ts +1 -0
  138. package/dist/workspace/shim.js +3 -3
  139. package/dist/workspace/structure.d.ts +1 -0
  140. package/dist/workspace/structure.js +1 -0
  141. package/package.json +2 -2
  142. package/dist/cli/init.d.ts +0 -15
  143. package/dist/cli/init.js +0 -70
  144. package/dist/commands/init/agents.d.ts +0 -4
  145. package/dist/commands/init/command.d.ts +0 -2
  146. package/dist/commands/init/environment.d.ts +0 -2
  147. package/dist/render/transcripts/init.d.ts +0 -7
  148. package/dist/render/transcripts/init.js +0 -83
  149. /package/dist/commands/{init/types.js → doctor/fix-types.js} +0 -0
@@ -2,17 +2,18 @@ import type { EnvironmentConfig } from "../../configs/environment/types.js";
2
2
  import type { ConfirmationOptions, PromptOptions } from "../../render/interactions/confirmation.js";
3
3
  import type { AgentPreset } from "../../workspace/templates.js";
4
4
  import type { CreateWorkspaceResult } from "../../workspace/types.js";
5
- export interface InitCommandInput {
5
+ export interface DoctorBootstrapInput {
6
6
  root: string;
7
7
  preset: AgentPreset;
8
8
  presetProvided?: boolean;
9
9
  onPresetResolved?: (preset: AgentPreset) => void;
10
10
  assumeYes?: boolean;
11
11
  interactive: boolean;
12
- confirm?: InitConfirmationHandler;
13
- prompt?: InitPromptHandler;
12
+ confirm?: DoctorConfirmationHandler;
13
+ prompt?: DoctorPromptHandler;
14
14
  }
15
- export interface InitCommandResult {
15
+ export interface DoctorBootstrapResult {
16
+ mode: "bootstrap" | "repair";
16
17
  preset: AgentPreset;
17
18
  workspaceResult: CreateWorkspaceResult;
18
19
  agentSummary: AgentInitSummary;
@@ -29,6 +30,7 @@ export interface AgentInitSummary {
29
30
  providerEnablementPrompted: boolean;
30
31
  configCreated: boolean;
31
32
  configUpdated: boolean;
33
+ managed: boolean;
32
34
  }
33
35
  export interface DetectedProviderSummary {
34
36
  provider: string;
@@ -48,12 +50,31 @@ export interface SandboxInitSummary {
48
50
  export interface OrchestrationInitSummary {
49
51
  configPath: string;
50
52
  configCreated: boolean;
53
+ configUpdated?: boolean;
51
54
  }
52
- export type InitConfirmationHandler = (options: ConfirmationOptions) => Promise<boolean>;
53
- export type InitPromptHandler = (options: PromptOptions) => Promise<string>;
54
- export interface InitConfigureOptions {
55
+ export type DoctorConfirmationHandler = (options: ConfirmationOptions) => Promise<boolean>;
56
+ export type DoctorPromptHandler = (options: PromptOptions) => Promise<string>;
57
+ export interface DoctorBootstrapConfigureOptions {
55
58
  interactive: boolean;
56
59
  assumeYes?: boolean;
57
- confirm?: InitConfirmationHandler;
58
- prompt?: InitPromptHandler;
60
+ confirm?: DoctorConfirmationHandler;
61
+ prompt?: DoctorPromptHandler;
62
+ }
63
+ export interface DoctorReconcileInput {
64
+ root: string;
65
+ }
66
+ export interface DoctorReconcileOrchestrationSummary {
67
+ configPath: string;
68
+ configCreated: boolean;
69
+ configUpdated: boolean;
70
+ skippedCustomized: boolean;
71
+ managed: boolean;
72
+ preset: AgentPreset;
73
+ }
74
+ export interface DoctorReconcileResult {
75
+ workspaceBootstrapped: boolean;
76
+ workspaceResult?: CreateWorkspaceResult;
77
+ agentSummary: AgentInitSummary;
78
+ environmentSummary: EnvironmentInitSummary;
79
+ orchestrationSummary: DoctorReconcileOrchestrationSummary;
59
80
  }
@@ -0,0 +1,2 @@
1
+ import type { DoctorBootstrapInput, DoctorBootstrapResult } from "./fix-types.js";
2
+ export declare function executeDoctorBootstrap(input: DoctorBootstrapInput): Promise<DoctorBootstrapResult>;
@@ -1,21 +1,40 @@
1
+ import { readFile } from "node:fs/promises";
1
2
  import { getAgentDefaultId, getAgentDefaultsForPreset, getSupportedAgentDefaults, } from "../../configs/agents/defaults.js";
2
3
  import { readAgentsConfig } from "../../configs/agents/loader.js";
4
+ import { loadEnvironmentConfig } from "../../configs/environment/loader.js";
3
5
  import { buildDefaultOrchestrationTemplate } from "../../configs/orchestration/bootstrap.js";
4
- import { renderPresetPromptPreface } from "../../render/transcripts/init.js";
6
+ import { pathExists } from "../../utils/fs.js";
5
7
  import { normalizeConfigText, readConfigSnapshot, writeConfigIfChanged, } from "../../utils/yaml.js";
8
+ import { updateManagedState } from "../../workspace/managed-state.js";
6
9
  import { createWorkspace } from "../../workspace/setup.js";
7
10
  import { formatWorkspacePath, resolveWorkspacePath, VORATIQ_AGENTS_FILE, VORATIQ_ORCHESTRATION_FILE, VORATIQ_SANDBOX_FILE, } from "../../workspace/structure.js";
8
11
  import { listAgentPresetTemplates, serializeAgentsConfigEntries, } from "../../workspace/templates.js";
9
- import { configureAgents } from "./agents.js";
10
- import { configureEnvironment } from "./environment.js";
11
- export async function executeInitCommand(input) {
12
+ import { bootstrapDoctorAgents } from "./agents.js";
13
+ import { reconcileDoctorEnvironment } from "./environment.js";
14
+ export async function executeDoctorBootstrap(input) {
12
15
  const { root, preset, presetProvided, onPresetResolved, assumeYes, interactive, confirm, prompt, } = input;
16
+ const workspaceExistsBeforeInit = await pathExists(resolveWorkspacePath(root));
13
17
  const agentsConfigPath = resolveWorkspacePath(root, VORATIQ_AGENTS_FILE);
14
18
  const agentsSnapshotBeforeInit = await readConfigSnapshot(agentsConfigPath);
15
19
  const agentsConfigMissing = !agentsSnapshotBeforeInit.exists;
16
20
  const orchestrationConfigPath = resolveWorkspacePath(root, VORATIQ_ORCHESTRATION_FILE);
17
21
  const orchestrationSnapshotBeforeInit = await readConfigSnapshot(orchestrationConfigPath);
18
22
  const orchestrationConfigMissing = !orchestrationSnapshotBeforeInit.exists;
23
+ const workspaceResult = await createWorkspace(root);
24
+ if (workspaceExistsBeforeInit) {
25
+ const repairedOrchestrationSummary = await repairExistingWorkspaceOrchestration(root, {
26
+ orchestrationConfigMissing,
27
+ preset,
28
+ });
29
+ const repairOnly = await buildRepairOnlySummaries(root, workspaceResult);
30
+ return {
31
+ mode: "repair",
32
+ preset,
33
+ workspaceResult,
34
+ ...repairOnly,
35
+ orchestrationSummary: repairedOrchestrationSummary ?? repairOnly.orchestrationSummary,
36
+ };
37
+ }
19
38
  const resolvedPreset = await resolveAgentPreset({
20
39
  preset,
21
40
  presetProvided,
@@ -24,12 +43,11 @@ export async function executeInitCommand(input) {
24
43
  agentsConfigMissing,
25
44
  });
26
45
  onPresetResolved?.(resolvedPreset);
27
- const workspaceResult = await createWorkspace(root);
28
46
  await applyAgentPresetTemplate(root, resolvedPreset, {
29
47
  presetProvided: Boolean(presetProvided),
30
48
  agentsConfigMissing,
31
49
  });
32
- const agentSummary = await configureAgents(root, resolvedPreset, {
50
+ const agentSummary = await bootstrapDoctorAgents(root, resolvedPreset, {
33
51
  interactive,
34
52
  assumeYes,
35
53
  confirm,
@@ -38,11 +56,13 @@ export async function executeInitCommand(input) {
38
56
  orchestrationConfigMissing,
39
57
  preset: resolvedPreset,
40
58
  });
41
- const environmentSummary = await configureEnvironment(root, {
59
+ const environmentSummary = await reconcileDoctorEnvironment(root, {
42
60
  interactive: false,
43
61
  });
44
62
  const sandboxSummary = buildSandboxSummary(workspaceResult);
63
+ await refreshManagedState(root, resolvedPreset);
45
64
  return {
65
+ mode: "bootstrap",
46
66
  preset: resolvedPreset,
47
67
  workspaceResult,
48
68
  agentSummary,
@@ -51,6 +71,56 @@ export async function executeInitCommand(input) {
51
71
  sandboxSummary,
52
72
  };
53
73
  }
74
+ async function buildRepairOnlySummaries(root, workspaceResult) {
75
+ const createdFiles = new Set(workspaceResult.createdFiles.map((value) => value.replace(/\\/g, "/")));
76
+ const agentsConfig = readAgentsConfig(await readFile(resolveWorkspacePath(root, VORATIQ_AGENTS_FILE), "utf8"));
77
+ const environmentConfig = loadEnvironmentConfig({ root, optional: true });
78
+ return {
79
+ agentSummary: {
80
+ configPath: formatWorkspacePath(VORATIQ_AGENTS_FILE),
81
+ enabledAgents: agentsConfig.agents
82
+ .filter((entry) => entry.enabled !== false)
83
+ .map((entry) => entry.id),
84
+ agentCount: agentsConfig.agents.length,
85
+ zeroDetections: agentsConfig.agents.every((entry) => (entry.binary ?? "").trim().length === 0),
86
+ detectedProviders: collectDetectedProvidersFromConfig(agentsConfig),
87
+ providerEnablementPrompted: false,
88
+ configCreated: createdFiles.has(formatWorkspacePath(VORATIQ_AGENTS_FILE)),
89
+ configUpdated: false,
90
+ managed: false,
91
+ },
92
+ orchestrationSummary: {
93
+ configPath: formatWorkspacePath(VORATIQ_ORCHESTRATION_FILE),
94
+ configCreated: createdFiles.has(formatWorkspacePath(VORATIQ_ORCHESTRATION_FILE)),
95
+ configUpdated: false,
96
+ },
97
+ environmentSummary: {
98
+ configPath: formatWorkspacePath("environment.yaml"),
99
+ detectedEntries: Object.keys(environmentConfig),
100
+ configCreated: createdFiles.has(formatWorkspacePath("environment.yaml")),
101
+ configUpdated: false,
102
+ config: environmentConfig,
103
+ },
104
+ sandboxSummary: buildSandboxSummary(workspaceResult),
105
+ };
106
+ }
107
+ async function repairExistingWorkspaceOrchestration(root, options) {
108
+ if (!options.orchestrationConfigMissing) {
109
+ return undefined;
110
+ }
111
+ return reconcileOrchestrationConfig(root, options);
112
+ }
113
+ async function refreshManagedState(root, preset) {
114
+ const [agentsContent, orchestrationContent] = await Promise.all([
115
+ readFile(resolveWorkspacePath(root, VORATIQ_AGENTS_FILE), "utf8"),
116
+ readFile(resolveWorkspacePath(root, VORATIQ_ORCHESTRATION_FILE), "utf8"),
117
+ ]);
118
+ await updateManagedState(root, {
119
+ agentsContent,
120
+ orchestrationContent,
121
+ orchestrationPreset: preset,
122
+ });
123
+ }
54
124
  function buildSandboxSummary(workspaceResult) {
55
125
  const configPath = formatWorkspacePath(VORATIQ_SANDBOX_FILE);
56
126
  const normalizedCreated = workspaceResult.createdFiles.map((file) => file.replace(/\\/g, "/"));
@@ -72,8 +142,12 @@ async function reconcileOrchestrationConfig(root, options) {
72
142
  const baseline = orchestrationSnapshot.exists
73
143
  ? orchestrationSnapshot.normalized
74
144
  : "__missing__";
75
- await writeConfigIfChanged(orchestrationConfigPath, nextContent, baseline);
76
- return { configPath, configCreated: true };
145
+ const updated = await writeConfigIfChanged(orchestrationConfigPath, nextContent, baseline);
146
+ await updateManagedState(root, {
147
+ orchestrationContent: nextContent,
148
+ orchestrationPreset: preset,
149
+ });
150
+ return { configPath, configCreated: true, configUpdated: updated };
77
151
  }
78
152
  async function applyAgentPresetTemplate(root, preset, options) {
79
153
  const { presetProvided, agentsConfigMissing } = options;
@@ -149,7 +223,7 @@ async function promptForPresetSelection(prompt) {
149
223
  for (;;) {
150
224
  const response = await prompt({
151
225
  message: "[1]",
152
- prefaceLines: renderPresetPromptPreface(firstPrompt),
226
+ prefaceLines: buildPresetPromptPreface(firstPrompt),
153
227
  });
154
228
  const trimmed = response.trim();
155
229
  const normalized = trimmed.length === 0 ? "1" : trimmed;
@@ -161,6 +235,19 @@ async function promptForPresetSelection(prompt) {
161
235
  firstPrompt = false;
162
236
  }
163
237
  }
238
+ function collectDetectedProvidersFromConfig(config) {
239
+ const detected = [];
240
+ const seenProviders = new Set();
241
+ for (const entry of config.agents) {
242
+ const binary = entry.binary?.trim();
243
+ if (!binary || seenProviders.has(entry.provider)) {
244
+ continue;
245
+ }
246
+ seenProviders.add(entry.provider);
247
+ detected.push({ provider: entry.provider, binary });
248
+ }
249
+ return detected;
250
+ }
164
251
  function tryReadAgentsConfig(content) {
165
252
  try {
166
253
  return readAgentsConfig(content);
@@ -242,6 +329,15 @@ function detectManagedAgentsPreset(config) {
242
329
  }
243
330
  return undefined;
244
331
  }
332
+ function buildPresetPromptPreface(firstPrompt) {
333
+ const lines = [
334
+ "Which workspace preset would you like?",
335
+ " [1] Pro (flagship)",
336
+ " [2] Lite (faster/cheaper)",
337
+ " [3] Manual (configure yourself)",
338
+ ];
339
+ return firstPrompt ? ["", ...lines] : lines;
340
+ }
245
341
  function retargetManagedAgentEntries(config, fromPreset) {
246
342
  const fromRoster = buildPresetRoster(fromPreset);
247
343
  const fromIds = new Set(fromRoster.map((entry) => entry.id));
@@ -0,0 +1,2 @@
1
+ import type { DoctorReconcileInput, DoctorReconcileResult } from "./fix-types.js";
2
+ export declare function executeDoctorReconcile(input: DoctorReconcileInput): Promise<DoctorReconcileResult>;
@@ -0,0 +1,101 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { readAgentsConfig } from "../../configs/agents/loader.js";
3
+ import { buildDefaultOrchestrationTemplate } from "../../configs/orchestration/bootstrap.js";
4
+ import { pathExists } from "../../utils/fs.js";
5
+ import { readConfigSnapshot, writeConfigIfChanged } from "../../utils/yaml.js";
6
+ import { computeManagedFingerprint, isManagedFingerprintMatch, readManagedState, updateManagedState, } from "../../workspace/managed-state.js";
7
+ import { createWorkspace } from "../../workspace/setup.js";
8
+ import { formatWorkspacePath, resolveWorkspacePath, VORATIQ_ORCHESTRATION_FILE, } from "../../workspace/structure.js";
9
+ import { reconcileManagedDoctorAgents } from "./agents.js";
10
+ import { reconcileDoctorEnvironment } from "./environment.js";
11
+ export async function executeDoctorReconcile(input) {
12
+ const { root } = input;
13
+ const workspaceDirExists = await pathExists(resolveWorkspacePath(root));
14
+ const workspaceResult = workspaceDirExists
15
+ ? undefined
16
+ : await createWorkspace(root);
17
+ const agentSummary = await reconcileManagedDoctorAgents(root);
18
+ const environmentSummary = await reconcileDoctorEnvironment(root, {
19
+ interactive: false,
20
+ });
21
+ const orchestrationSummary = await reconcileManagedOrchestration(root);
22
+ const [agentsContent, orchestrationContent] = await Promise.all([
23
+ readFile(resolveWorkspacePath(root, "agents.yaml"), "utf8"),
24
+ readFile(resolveWorkspacePath(root, "orchestration.yaml"), "utf8"),
25
+ ]);
26
+ await updateManagedState(root, {
27
+ ...(agentSummary.managed ? { agentsContent } : {}),
28
+ ...(orchestrationSummary.managed
29
+ ? {
30
+ orchestrationContent,
31
+ orchestrationPreset: orchestrationSummary.preset,
32
+ }
33
+ : {}),
34
+ });
35
+ return {
36
+ workspaceBootstrapped: !workspaceDirExists,
37
+ workspaceResult,
38
+ agentSummary,
39
+ environmentSummary,
40
+ orchestrationSummary,
41
+ };
42
+ }
43
+ async function reconcileManagedOrchestration(root) {
44
+ const configPath = formatWorkspacePath(VORATIQ_ORCHESTRATION_FILE);
45
+ const filePath = resolveWorkspacePath(root, VORATIQ_ORCHESTRATION_FILE);
46
+ const agentsPath = resolveWorkspacePath(root, "agents.yaml");
47
+ const [snapshot, agentsContent, managedState] = await Promise.all([
48
+ readConfigSnapshot(filePath),
49
+ readFile(agentsPath, "utf8"),
50
+ readManagedState(root),
51
+ ]);
52
+ const agentsConfig = readAgentsConfig(agentsContent);
53
+ const preset = managedState?.configs.orchestration?.preset ??
54
+ inferManagedPreset(snapshot.content, agentsConfig) ??
55
+ "pro";
56
+ const desired = buildDefaultOrchestrationTemplate(agentsConfig, preset);
57
+ const managed = !snapshot.exists ||
58
+ isManagedFingerprintMatch(managedState?.configs.orchestration, snapshot.content) ||
59
+ computeManagedFingerprint(snapshot.content) ===
60
+ computeManagedFingerprint(desired);
61
+ if (!snapshot.exists) {
62
+ await writeConfigIfChanged(filePath, desired, "__missing__");
63
+ return {
64
+ configPath,
65
+ configCreated: true,
66
+ configUpdated: true,
67
+ skippedCustomized: false,
68
+ managed: true,
69
+ preset,
70
+ };
71
+ }
72
+ if (!managed) {
73
+ return {
74
+ configPath,
75
+ configCreated: false,
76
+ configUpdated: false,
77
+ skippedCustomized: true,
78
+ managed: false,
79
+ preset,
80
+ };
81
+ }
82
+ const updated = await writeConfigIfChanged(filePath, desired, snapshot.normalized);
83
+ return {
84
+ configPath,
85
+ configCreated: false,
86
+ configUpdated: updated,
87
+ skippedCustomized: false,
88
+ managed: true,
89
+ preset,
90
+ };
91
+ }
92
+ function inferManagedPreset(content, agentsConfig) {
93
+ const normalized = computeManagedFingerprint(content);
94
+ for (const preset of ["pro", "lite", "manual"]) {
95
+ const candidate = buildDefaultOrchestrationTemplate(agentsConfig, preset);
96
+ if (computeManagedFingerprint(candidate) === normalized) {
97
+ return preset;
98
+ }
99
+ }
100
+ return undefined;
101
+ }
@@ -7,9 +7,11 @@ interface ActiveInteractiveContext {
7
7
  process?: ChildProcess;
8
8
  completion?: Promise<InteractiveSessionRecord>;
9
9
  teardown?: TeardownController;
10
+ terminationStatus?: "failed" | "aborted";
10
11
  }
11
12
  export declare function registerActiveInteractive(context: ActiveInteractiveContext): void;
12
13
  export declare function clearActiveInteractive(sessionId: string): void;
14
+ export declare function getActiveInteractiveTerminationStatus(sessionId: string): "failed" | "aborted" | undefined;
13
15
  export declare function terminateActiveInteractive(status: "failed" | "aborted", reason?: string): Promise<void>;
14
16
  export declare function finalizeActiveInteractive(sessionId: string): Promise<void>;
15
17
  export {};
@@ -15,12 +15,19 @@ export function clearActiveInteractive(sessionId) {
15
15
  activeInteractive = undefined;
16
16
  }
17
17
  }
18
+ export function getActiveInteractiveTerminationStatus(sessionId) {
19
+ if (activeInteractive?.sessionId !== sessionId) {
20
+ return undefined;
21
+ }
22
+ return activeInteractive.terminationStatus;
23
+ }
18
24
  export async function terminateActiveInteractive(status, reason) {
19
25
  if (!activeInteractive || terminationInFlight) {
20
26
  return;
21
27
  }
22
28
  terminationInFlight = true;
23
29
  const context = activeInteractive;
30
+ context.terminationStatus = status;
24
31
  let persistenceError;
25
32
  try {
26
33
  terminateInteractiveProcess(context.process);
@@ -57,6 +64,7 @@ export async function terminateActiveInteractive(status, reason) {
57
64
  await runTeardown(context.teardown);
58
65
  }
59
66
  finally {
67
+ context.terminationStatus = undefined;
60
68
  terminationInFlight = false;
61
69
  activeInteractive = undefined;
62
70
  }
@@ -6,6 +6,7 @@ export interface ListCommandInput {
6
6
  reductionsFilePath: string;
7
7
  messagesFilePath: string;
8
8
  verificationsFilePath: string;
9
+ interactiveFilePath: string;
9
10
  operator: ListOperator;
10
11
  sessionId?: string;
11
12
  limit?: number;