@interf/compiler 0.4.0 → 0.5.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 (160) hide show
  1. package/README.md +71 -69
  2. package/builtin-workflows/interf/README.md +6 -6
  3. package/builtin-workflows/interf/compile/stages/shape/SKILL.md +7 -7
  4. package/builtin-workflows/interf/compile/stages/structure/SKILL.md +2 -2
  5. package/builtin-workflows/interf/compile/stages/summarize/SKILL.md +1 -1
  6. package/builtin-workflows/interf/{workspace.schema.json → compiled.schema.json} +5 -5
  7. package/builtin-workflows/interf/improve/SKILL.md +3 -3
  8. package/builtin-workflows/interf/use/query/SKILL.md +2 -2
  9. package/builtin-workflows/interf/workflow.json +42 -31
  10. package/dist/commands/check-draft.d.ts +19 -0
  11. package/dist/commands/check-draft.js +110 -0
  12. package/dist/commands/compile-controller.d.ts +4 -4
  13. package/dist/commands/compile-controller.js +117 -81
  14. package/dist/commands/compile.d.ts +5 -5
  15. package/dist/commands/compile.js +61 -62
  16. package/dist/commands/compiled-flow.d.ts +23 -0
  17. package/dist/commands/compiled-flow.js +112 -0
  18. package/dist/commands/create-workflow-wizard.d.ts +3 -3
  19. package/dist/commands/create-workflow-wizard.js +11 -11
  20. package/dist/commands/create.d.ts +2 -2
  21. package/dist/commands/create.js +50 -57
  22. package/dist/commands/default.js +2 -2
  23. package/dist/commands/executor-flow.d.ts +20 -1
  24. package/dist/commands/executor-flow.js +67 -7
  25. package/dist/commands/init.js +242 -289
  26. package/dist/commands/list.js +14 -10
  27. package/dist/commands/reset.js +6 -6
  28. package/dist/commands/source-config-wizard.d.ts +12 -8
  29. package/dist/commands/source-config-wizard.js +356 -119
  30. package/dist/commands/status.js +49 -26
  31. package/dist/commands/test-flow.d.ts +23 -10
  32. package/dist/commands/test-flow.js +278 -58
  33. package/dist/commands/test.d.ts +7 -1
  34. package/dist/commands/test.js +264 -65
  35. package/dist/commands/verify.js +23 -14
  36. package/dist/index.d.ts +7 -7
  37. package/dist/index.js +4 -4
  38. package/dist/lib/agent-args.js +2 -1
  39. package/dist/lib/agent-constants.js +1 -1
  40. package/dist/lib/agent-render.js +4 -4
  41. package/dist/lib/agent-shells.d.ts +8 -8
  42. package/dist/lib/agent-shells.js +231 -142
  43. package/dist/lib/compiled-compile.d.ts +52 -0
  44. package/dist/lib/compiled-compile.js +274 -0
  45. package/dist/lib/compiled-home.d.ts +5 -0
  46. package/dist/lib/compiled-home.js +32 -0
  47. package/dist/lib/compiled-layout.d.ts +2 -0
  48. package/dist/lib/compiled-layout.js +60 -0
  49. package/dist/lib/compiled-paths.d.ts +41 -0
  50. package/dist/lib/compiled-paths.js +111 -0
  51. package/dist/lib/{workspace-raw.d.ts → compiled-raw.d.ts} +8 -7
  52. package/dist/lib/{workspace-raw.js → compiled-raw.js} +16 -14
  53. package/dist/lib/compiled-reset.d.ts +1 -0
  54. package/dist/lib/compiled-reset.js +44 -0
  55. package/dist/lib/compiled-schema.d.ts +27 -0
  56. package/dist/lib/compiled-schema.js +110 -0
  57. package/dist/lib/config.d.ts +0 -1
  58. package/dist/lib/config.js +0 -1
  59. package/dist/lib/discovery.d.ts +1 -1
  60. package/dist/lib/discovery.js +3 -3
  61. package/dist/lib/interf-bootstrap.d.ts +1 -1
  62. package/dist/lib/interf-bootstrap.js +4 -4
  63. package/dist/lib/interf-detect.d.ts +10 -10
  64. package/dist/lib/interf-detect.js +78 -56
  65. package/dist/lib/interf-scaffold.d.ts +2 -2
  66. package/dist/lib/interf-scaffold.js +90 -57
  67. package/dist/lib/interf-workflow-package.d.ts +3 -3
  68. package/dist/lib/interf-workflow-package.js +30 -30
  69. package/dist/lib/interf.d.ts +5 -5
  70. package/dist/lib/interf.js +4 -4
  71. package/dist/lib/local-workflows.d.ts +4 -4
  72. package/dist/lib/local-workflows.js +35 -70
  73. package/dist/lib/obsidian.d.ts +1 -1
  74. package/dist/lib/parse.js +92 -1
  75. package/dist/lib/project-paths.d.ts +13 -0
  76. package/dist/lib/project-paths.js +29 -0
  77. package/dist/lib/runtime-acceptance.d.ts +7 -1
  78. package/dist/lib/runtime-acceptance.js +194 -59
  79. package/dist/lib/runtime-contracts.d.ts +2 -4
  80. package/dist/lib/runtime-contracts.js +17 -161
  81. package/dist/lib/runtime-inventory.d.ts +7 -0
  82. package/dist/lib/runtime-inventory.js +29 -0
  83. package/dist/lib/runtime-paths.js +5 -5
  84. package/dist/lib/runtime-prompt.js +9 -6
  85. package/dist/lib/runtime-reconcile.d.ts +2 -3
  86. package/dist/lib/runtime-reconcile.js +92 -171
  87. package/dist/lib/runtime-runs.js +30 -39
  88. package/dist/lib/runtime-types.d.ts +10 -19
  89. package/dist/lib/runtime.d.ts +2 -2
  90. package/dist/lib/runtime.js +1 -1
  91. package/dist/lib/schema.d.ts +163 -140
  92. package/dist/lib/schema.js +163 -124
  93. package/dist/lib/source-config.d.ts +24 -20
  94. package/dist/lib/source-config.js +154 -116
  95. package/dist/lib/state-artifacts.d.ts +5 -5
  96. package/dist/lib/state-artifacts.js +8 -8
  97. package/dist/lib/state-health.d.ts +4 -4
  98. package/dist/lib/state-health.js +108 -126
  99. package/dist/lib/state-io.d.ts +8 -8
  100. package/dist/lib/state-io.js +77 -50
  101. package/dist/lib/state-paths.js +5 -5
  102. package/dist/lib/state-view.d.ts +4 -4
  103. package/dist/lib/state-view.js +52 -55
  104. package/dist/lib/state.d.ts +5 -5
  105. package/dist/lib/state.js +4 -4
  106. package/dist/lib/summarize-plan.d.ts +3 -2
  107. package/dist/lib/summarize-plan.js +18 -16
  108. package/dist/lib/test-execution.js +9 -9
  109. package/dist/lib/test-matrices.d.ts +3 -3
  110. package/dist/lib/test-matrices.js +6 -6
  111. package/dist/lib/test-paths.d.ts +4 -4
  112. package/dist/lib/test-paths.js +16 -10
  113. package/dist/lib/test-sandbox.d.ts +1 -1
  114. package/dist/lib/test-sandbox.js +38 -31
  115. package/dist/lib/test-targets.d.ts +2 -2
  116. package/dist/lib/test-targets.js +11 -11
  117. package/dist/lib/test-types.d.ts +1 -1
  118. package/dist/lib/test.d.ts +1 -1
  119. package/dist/lib/test.js +1 -1
  120. package/dist/lib/util.d.ts +2 -0
  121. package/dist/lib/util.js +14 -1
  122. package/dist/lib/validate-compiled.d.ts +27 -0
  123. package/dist/lib/validate-compiled.js +236 -0
  124. package/dist/lib/validate-helpers.d.ts +0 -8
  125. package/dist/lib/validate-helpers.js +0 -30
  126. package/dist/lib/validate.d.ts +4 -4
  127. package/dist/lib/validate.js +49 -15
  128. package/dist/lib/workflow-abi.d.ts +37 -46
  129. package/dist/lib/workflow-abi.js +51 -76
  130. package/dist/lib/workflow-definitions.d.ts +11 -11
  131. package/dist/lib/workflow-definitions.js +36 -53
  132. package/dist/lib/workflow-helpers.d.ts +2 -3
  133. package/dist/lib/workflow-helpers.js +9 -13
  134. package/dist/lib/workflow-improvement.d.ts +3 -3
  135. package/dist/lib/workflow-improvement.js +48 -48
  136. package/dist/lib/workflow-review-paths.d.ts +3 -3
  137. package/dist/lib/workflow-review-paths.js +11 -11
  138. package/dist/lib/workflow-stage-runner.d.ts +1 -1
  139. package/dist/lib/workflow-stage-runner.js +8 -8
  140. package/dist/lib/workflows.d.ts +9 -9
  141. package/dist/lib/workflows.js +15 -17
  142. package/package.json +10 -9
  143. package/dist/commands/workspace-flow.d.ts +0 -23
  144. package/dist/commands/workspace-flow.js +0 -109
  145. package/dist/lib/registry.d.ts +0 -16
  146. package/dist/lib/registry.js +0 -65
  147. package/dist/lib/validate-workspace.d.ts +0 -121
  148. package/dist/lib/validate-workspace.js +0 -407
  149. package/dist/lib/workspace-compile.d.ts +0 -54
  150. package/dist/lib/workspace-compile.js +0 -476
  151. package/dist/lib/workspace-home.d.ts +0 -5
  152. package/dist/lib/workspace-home.js +0 -32
  153. package/dist/lib/workspace-layout.d.ts +0 -2
  154. package/dist/lib/workspace-layout.js +0 -60
  155. package/dist/lib/workspace-paths.d.ts +0 -41
  156. package/dist/lib/workspace-paths.js +0 -107
  157. package/dist/lib/workspace-reset.d.ts +0 -1
  158. package/dist/lib/workspace-reset.js +0 -43
  159. package/dist/lib/workspace-schema.d.ts +0 -17
  160. package/dist/lib/workspace-schema.js +0 -74
@@ -1,22 +1,22 @@
1
1
  import chalk from "chalk";
2
2
  import { basename } from "node:path";
3
3
  import * as p from "@clack/prompts";
4
- import { detectInterf, defaultWorkspaceNameForSource, listWorkspacesForSourceFolder, } from "../lib/interf.js";
4
+ import { detectInterf, defaultCompiledNameForSource, listCompiledDatasetsForSourceFolder, } from "../lib/interf.js";
5
5
  import { slugify } from "../lib/util.js";
6
6
  import { addExecutionProfileOptions, executionProfileFromArgv, } from "../lib/execution-profile.js";
7
- import { loadSourceFolderConfig, upsertSourceWorkspaceConfig } from "../lib/source-config.js";
8
- import { buildWorkspaceWorkflowOptions, chooseWorkspaceWorkflow, createWorkflowWizard, } from "./create-workflow-wizard.js";
9
- import { ensureWorkspaceFromConfig, } from "./workspace-flow.js";
10
- import { DEFAULT_WORKSPACE_NAME, promptSingleWorkspaceConfig, } from "./source-config-wizard.js";
7
+ import { listSourceDatasetConfigs, loadSourceFolderConfig, upsertSourceDatasetConfig, } from "../lib/source-config.js";
8
+ import { createWorkflowWizard, } from "./create-workflow-wizard.js";
9
+ import { ensureCompiledFromConfig, } from "./compiled-flow.js";
10
+ import { DEFAULT_COMPILED_NAME, promptSingleCompiledConfig, } from "./source-config-wizard.js";
11
11
  import { resolveOrConfigureLocalExecutor } from "./executor-flow.js";
12
- import { runConfiguredWorkspaceCompile } from "./compile.js";
12
+ import { runConfiguredCompiledCompile } from "./compile.js";
13
13
  function normalizeCreateTarget(value) {
14
14
  if (!value)
15
15
  return null;
16
16
  switch (value) {
17
- case "workspace":
18
- case "ws":
19
- return "workspace";
17
+ case "dataset":
18
+ case "ds":
19
+ return "dataset";
20
20
  case "workflow":
21
21
  case "wf":
22
22
  return "workflow";
@@ -29,9 +29,9 @@ async function selectCreateTarget() {
29
29
  message: "Create what?",
30
30
  options: [
31
31
  {
32
- value: "workspace",
33
- label: "Workspace (Recommended)",
34
- hint: "Create a compiled workspace for this dataset",
32
+ value: "dataset",
33
+ label: "Dataset (Recommended)",
34
+ hint: "Add one dataset entry to this project",
35
35
  },
36
36
  {
37
37
  value: "workflow",
@@ -43,10 +43,10 @@ async function selectCreateTarget() {
43
43
  }
44
44
  export const createCommand = {
45
45
  command: "create [type]",
46
- describe: "Create a compiled workspace or reusable workflow",
46
+ describe: "Create a dataset entry or reusable workflow",
47
47
  builder: (yargs) => addExecutionProfileOptions(yargs.positional("type", {
48
48
  type: "string",
49
- describe: "Type to create (`workspace` or `workflow`)",
49
+ describe: "Type to create (`dataset` or `workflow`)",
50
50
  default: undefined,
51
51
  })),
52
52
  handler: async (argv) => {
@@ -68,39 +68,32 @@ export const createCommand = {
68
68
  await createWorkflowWizard({ sourcePath: process.cwd() });
69
69
  return;
70
70
  }
71
- await createWorkspaceWizard({ executionProfile });
71
+ await createCompiledWizard({ executionProfile });
72
72
  },
73
73
  };
74
- export async function createWorkspaceWizard(options = {}) {
74
+ export async function createCompiledWizard(options = {}) {
75
75
  if (options.intro !== false) {
76
- p.intro(chalk.bold("Create a workspace"));
76
+ p.intro(chalk.bold("Add a dataset"));
77
77
  }
78
78
  const cwd = process.cwd();
79
79
  const detected = detectInterf(cwd);
80
80
  if (detected) {
81
81
  process.exitCode = 1;
82
- p.log.error("You are already inside a compiled workspace.");
82
+ p.log.error("You are already inside a compiled dataset.");
83
83
  return;
84
84
  }
85
- const existing = listWorkspacesForSourceFolder(cwd);
85
+ const existing = listCompiledDatasetsForSourceFolder(cwd);
86
86
  if (existing.length > 0) {
87
- p.log.info(`This dataset already has ${existing.length} workspace${existing.length === 1 ? "" : "s"}. Add another only when you need a separate set of truth checks or a different focus.`);
87
+ p.log.info(`This project already has ${existing.length} compiled dataset${existing.length === 1 ? "" : "s"}. Add another only when you need a separate folder, truth checks, or focus.`);
88
88
  }
89
- p.log.info("Interf Compiler builds a compiled workspace on top of the dataset. The source files stay where they are and stay the source of truth.");
89
+ p.log.info("Interf Compiler measures one dataset at a time. Start with truth checks and a baseline, then build a compiled dataset only when you need it.");
90
90
  const existingConfig = loadSourceFolderConfig(cwd);
91
- const suggestedName = slugify(defaultWorkspaceNameForSource(cwd) || basename(cwd)) || DEFAULT_WORKSPACE_NAME;
92
- const workflowChoice = await chooseWorkspaceWorkflow(cwd, {
93
- message: "Which workflow should this workspace start from?",
94
- });
95
- if (p.isCancel(workflowChoice))
96
- return;
97
- const workflowId = workflowChoice;
98
- const workflowLabel = buildWorkspaceWorkflowOptions(cwd)
99
- .find((option) => option.value === workflowId)?.label ?? workflowId;
100
- const draft = await promptSingleWorkspaceConfig({
91
+ const suggestedName = slugify(defaultCompiledNameForSource(cwd) || basename(cwd)) || DEFAULT_COMPILED_NAME;
92
+ const workflowId = "interf";
93
+ const draft = await promptSingleCompiledConfig({
94
+ projectPath: cwd,
101
95
  initial: { name: suggestedName },
102
96
  introStyle: existingConfig ? "additional" : "first",
103
- selectedWorkflowLabel: workflowLabel,
104
97
  });
105
98
  if (!draft)
106
99
  return;
@@ -108,34 +101,21 @@ export async function createWorkspaceWizard(options = {}) {
108
101
  ...draft,
109
102
  workflow: workflowId,
110
103
  };
111
- const existingNames = new Set((existingConfig?.workspaces ?? []).map((workspace) => workspace.name));
104
+ const existingNames = new Set(listSourceDatasetConfigs(existingConfig).map((dataset) => dataset.name));
112
105
  if (existingNames.has(configToSave.name)) {
113
106
  process.exitCode = 1;
114
- p.log.error(`Workspace "${configToSave.name}" already exists. Use \`interf\` or \`interf init\` to edit it.`);
115
- return;
116
- }
117
- upsertSourceWorkspaceConfig(cwd, configToSave);
118
- const spinner = p.spinner();
119
- spinner.start("Creating workspace...");
120
- let workspacePath = "";
121
- try {
122
- workspacePath = ensureWorkspaceFromConfig(cwd, configToSave);
123
- spinner.stop("Workspace created.");
124
- }
125
- catch (error) {
126
- spinner.stop("Workspace creation failed.");
127
- process.exitCode = 1;
128
- p.log.error(error instanceof Error ? error.message : String(error));
107
+ p.log.error(`Dataset "${configToSave.name}" already exists. Use \`interf\` or \`interf init\` to edit it.`);
129
108
  return;
130
109
  }
110
+ upsertSourceDatasetConfig(cwd, configToSave);
131
111
  const compileNow = await p.confirm({
132
- message: "Build it now with this workflow and compile mode? (Recommended)",
112
+ message: "Build the compiled dataset now? (Recommended)",
133
113
  initialValue: true,
134
114
  });
135
115
  if (p.isCancel(compileNow) || !compileNow) {
136
116
  p.outro(configToSave.checks.length > 0
137
- ? "Next:\n interf compile\n interf test"
138
- : "Next:\n interf compile\n interf or interf init");
117
+ ? "Next:\n interf test\n interf compile"
118
+ : "Next:\n interf or interf init");
139
119
  return;
140
120
  }
141
121
  const { executor, error } = await resolveOrConfigureLocalExecutor({
@@ -150,14 +130,27 @@ export async function createWorkspaceWizard(options = {}) {
150
130
  p.log.error(error ?? "No coding agent detected.");
151
131
  return;
152
132
  }
153
- await compileWorkspaceAfterCreate(executor, cwd, configToSave, workspacePath, options.executionProfile);
133
+ const spinner = p.spinner();
134
+ spinner.start("Preparing compiled dataset...");
135
+ let compiledPath = "";
136
+ try {
137
+ compiledPath = ensureCompiledFromConfig(cwd, configToSave);
138
+ spinner.stop("Compiled dataset target ready.");
139
+ }
140
+ catch (error) {
141
+ spinner.stop("Compiled dataset target preparation failed.");
142
+ process.exitCode = 1;
143
+ p.log.error(error instanceof Error ? error.message : String(error));
144
+ return;
145
+ }
146
+ await compileCompiledAfterCreate(executor, cwd, configToSave, compiledPath, options.executionProfile);
154
147
  }
155
- async function compileWorkspaceAfterCreate(executor, sourcePath, workspaceConfig, workspacePath, executionProfile) {
156
- const compiled = await runConfiguredWorkspaceCompile({
148
+ async function compileCompiledAfterCreate(executor, sourcePath, datasetConfig, compiledPath, executionProfile) {
149
+ const compiled = await runConfiguredCompiledCompile({
157
150
  executor,
158
- workspacePath,
151
+ compiledPath,
159
152
  sourcePath,
160
- workspaceConfig,
153
+ compiledConfig: datasetConfig,
161
154
  executionProfile,
162
155
  maxAttemptsOverride: null,
163
156
  maxLoopsOverride: null,
@@ -166,4 +159,4 @@ async function compileWorkspaceAfterCreate(executor, sourcePath, workspaceConfig
166
159
  process.exitCode = 1;
167
160
  return compiled;
168
161
  }
169
- export { formatWorkflowLabel, chooseWorkspaceWorkflow, createWorkflowWizard, createWorkspaceWorkflowWizard, } from "./create-workflow-wizard.js";
162
+ export { formatWorkflowLabel, chooseCompiledWorkflow, createWorkflowWizard, createCompiledWorkflowWizard, } from "./create-workflow-wizard.js";
@@ -5,7 +5,7 @@ function printStaticLanding() {
5
5
  const config = loadUserConfig();
6
6
  console.log();
7
7
  console.log(chalk.bold(" Interf Compiler"));
8
- console.log(chalk.dim(" Set truth checks on a dataset, compile a workspace, and test whether it passes."));
8
+ console.log(chalk.dim(" Define truth checks, measure files-as-is, then compile only if it improves accuracy."));
9
9
  console.log();
10
10
  if (config) {
11
11
  console.log(chalk.dim(` Agent: ${config.agent}`));
@@ -13,12 +13,12 @@ function printStaticLanding() {
13
13
  }
14
14
  console.log(chalk.dim(" Suggested flow:"));
15
15
  console.log(chalk.dim(" interf"));
16
+ console.log(chalk.dim(" interf test"));
16
17
  console.log(chalk.dim(" interf compile"));
17
18
  console.log(chalk.dim(" interf test"));
18
19
  console.log();
19
20
  console.log(chalk.dim(" More:"));
20
21
  console.log(chalk.dim(" interf init"));
21
- console.log(chalk.dim(" interf create workspace"));
22
22
  console.log(chalk.dim(" interf create workflow"));
23
23
  console.log(chalk.dim(" interf doctor"));
24
24
  console.log(chalk.dim(" interf --help"));
@@ -1,8 +1,27 @@
1
1
  import { type WorkflowExecutionProfile, type WorkflowExecutor } from "../lib/executors.js";
2
+ export interface RunAgentOption {
3
+ name: string;
4
+ displayName: string;
5
+ command: string;
6
+ current: boolean;
7
+ }
8
+ export declare function resolvedConfiguredAgentName(): string | null;
9
+ export declare function listRunAgentOptions(): RunAgentOption[];
10
+ export declare function resolveNamedLocalExecutor(agentName: string, options?: {
11
+ preflight?: boolean;
12
+ executionProfile?: WorkflowExecutionProfile;
13
+ }): {
14
+ executor: WorkflowExecutor | null;
15
+ error?: string;
16
+ };
17
+ export declare function promptForTestAgents(): Promise<{
18
+ agents: RunAgentOption[];
19
+ cancelled: boolean;
20
+ }>;
2
21
  export declare function resolveOrConfigureLocalExecutor(options?: {
3
22
  preflight?: boolean;
4
23
  executionProfile?: WorkflowExecutionProfile;
5
- purpose?: "compile" | "test";
24
+ purpose?: "compile" | "test" | "draft";
6
25
  }): Promise<{
7
26
  executor: WorkflowExecutor | null;
8
27
  error?: string;
@@ -1,13 +1,13 @@
1
1
  import * as p from "@clack/prompts";
2
2
  import { AGENTS } from "../lib/agent-constants.js";
3
- import { detectAgents, supportsAutomatedRuns } from "../lib/agents.js";
4
- import { resolveLocalExecutor, } from "../lib/executors.js";
3
+ import { detectAgents, ensureAgentAutomatedRunReady, supportsAutomatedRuns } from "../lib/agents.js";
4
+ import { createLocalAgentExecutor, resolveLocalExecutor, } from "../lib/executors.js";
5
5
  import { loadUserConfig, saveUserConfig } from "../lib/user-config.js";
6
6
  const promptedPurposes = new Set();
7
7
  function supportedDetectedAgents() {
8
8
  return detectAgents().filter((agent) => AGENTS.some((candidate) => candidate.name === agent.name) && supportsAutomatedRuns(agent));
9
9
  }
10
- function resolvedConfiguredAgentName() {
10
+ export function resolvedConfiguredAgentName() {
11
11
  const current = loadUserConfig();
12
12
  if (!current)
13
13
  return null;
@@ -29,7 +29,67 @@ function persistSelectedAgent(selectedName) {
29
29
  initialized: current?.initialized ?? new Date().toISOString(),
30
30
  });
31
31
  }
32
+ export function listRunAgentOptions() {
33
+ const configuredName = resolvedConfiguredAgentName();
34
+ return supportedDetectedAgents().map((agent) => ({
35
+ name: agent.name,
36
+ displayName: agent.displayName,
37
+ command: agent.command,
38
+ current: agent.name === configuredName,
39
+ }));
40
+ }
41
+ export function resolveNamedLocalExecutor(agentName, options = {}) {
42
+ const agent = supportedDetectedAgents().find((entry) => entry.name === agentName);
43
+ if (!agent) {
44
+ return { executor: null, error: `Local agent \"${agentName}\" is not detected.` };
45
+ }
46
+ if (options.preflight !== false) {
47
+ const readiness = ensureAgentAutomatedRunReady(agent);
48
+ if (!readiness.ok) {
49
+ return { executor: null, error: readiness.error };
50
+ }
51
+ }
52
+ return {
53
+ executor: createLocalAgentExecutor(agent, options.executionProfile),
54
+ };
55
+ }
56
+ export async function promptForTestAgents() {
57
+ const detected = listRunAgentOptions();
58
+ if (detected.length === 0)
59
+ return { agents: [], cancelled: false };
60
+ if (detected.length === 1) {
61
+ const only = detected[0];
62
+ if (only) {
63
+ persistSelectedAgent(only.name);
64
+ p.log.info(`Local agent for this test: ${only.displayName}`);
65
+ return { agents: [only], cancelled: false };
66
+ }
67
+ }
68
+ const current = detected.find((agent) => agent.current) ?? detected[0] ?? null;
69
+ const selected = await p.multiselect({
70
+ message: current
71
+ ? `Which local agents should run this test? Current: ${current.displayName}`
72
+ : "Which local agents should run this test?",
73
+ options: detected.map((agent) => ({
74
+ value: agent.name,
75
+ label: agent.current ? `${agent.displayName} (Current)` : agent.displayName,
76
+ hint: agent.command,
77
+ })),
78
+ required: false,
79
+ initialValues: current ? [current.name] : [],
80
+ });
81
+ if (p.isCancel(selected)) {
82
+ return { agents: [], cancelled: true };
83
+ }
84
+ const selectedNames = Array.isArray(selected) ? selected.map(String) : [];
85
+ const agents = detected.filter((agent) => selectedNames.includes(agent.name));
86
+ if (agents.length === 1 && agents[0]) {
87
+ persistSelectedAgent(agents[0].name);
88
+ }
89
+ return { agents, cancelled: false };
90
+ }
32
91
  async function promptForRunAgent(purpose) {
92
+ const purposeLabel = purpose === "draft" ? "truth-check draft" : purpose;
33
93
  const detected = supportedDetectedAgents();
34
94
  if (detected.length === 0)
35
95
  return { selected: false, cancelled: false };
@@ -38,9 +98,9 @@ async function promptForRunAgent(purpose) {
38
98
  (detected.length === 1 ? detected[0] ?? null : null);
39
99
  let selectedName = null;
40
100
  if (detected.length === 1) {
41
- p.log.info(`Local agent for this ${purpose}: ${detected[0]?.displayName ?? "unknown"}`);
101
+ p.log.info(`Local agent for this ${purposeLabel}: ${detected[0]?.displayName ?? "unknown"}`);
42
102
  const confirmed = await p.confirm({
43
- message: `Run this ${purpose} with ${detected[0]?.displayName ?? "the detected agent"}?`,
103
+ message: `Run this ${purposeLabel} with ${detected[0]?.displayName ?? "the detected agent"}?`,
44
104
  initialValue: true,
45
105
  });
46
106
  if (p.isCancel(confirmed) || !confirmed) {
@@ -51,8 +111,8 @@ async function promptForRunAgent(purpose) {
51
111
  else {
52
112
  selectedName = await p.select({
53
113
  message: currentAgent
54
- ? `Local agent for this ${purpose}? Current: ${currentAgent.displayName}`
55
- : `Which local agent should run this ${purpose}?`,
114
+ ? `Local agent for this ${purposeLabel}? Current: ${currentAgent.displayName}`
115
+ : `Which local agent should run this ${purposeLabel}?`,
56
116
  options: detected.map((agent) => ({
57
117
  value: agent.name,
58
118
  label: agent.name === currentAgent?.name ? `${agent.displayName} (Current)` : agent.displayName,