@interf/compiler 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +126 -188
- package/builtin-workflows/interf/README.md +22 -10
- package/builtin-workflows/interf/compile/stages/shape/SKILL.md +6 -3
- package/builtin-workflows/interf/compile/stages/structure/SKILL.md +3 -0
- package/builtin-workflows/interf/compile/stages/summarize/SKILL.md +18 -2
- package/builtin-workflows/interf/improve/SKILL.md +2 -2
- package/builtin-workflows/interf/workflow.json +18 -4
- package/builtin-workflows/interf/{compiled.schema.json → workflow.schema.json} +9 -2
- package/dist/commands/check-draft.js +3 -3
- package/dist/commands/compile-controller.js +9 -16
- package/dist/commands/compile.d.ts +19 -1
- package/dist/commands/compile.js +98 -28
- package/dist/commands/create-workflow-wizard.d.ts +20 -2
- package/dist/commands/create-workflow-wizard.js +163 -27
- package/dist/commands/create.d.ts +1 -1
- package/dist/commands/create.js +67 -60
- package/dist/commands/dataset-selection.d.ts +6 -0
- package/dist/commands/dataset-selection.js +11 -0
- package/dist/commands/default.js +3 -3
- package/dist/commands/doctor.js +8 -8
- package/dist/commands/executor-flow.d.ts +1 -1
- package/dist/commands/executor-flow.js +5 -2
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.js +56 -48
- package/dist/commands/list.js +6 -3
- package/dist/commands/reset.js +1 -1
- package/dist/commands/source-config-wizard.d.ts +2 -2
- package/dist/commands/source-config-wizard.js +50 -17
- package/dist/commands/test-flow.js +5 -16
- package/dist/commands/test.d.ts +0 -6
- package/dist/commands/test.js +9 -17
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/agent-args.d.ts +1 -0
- package/dist/lib/agent-args.js +10 -0
- package/dist/lib/agent-execution.js +2 -1
- package/dist/lib/agent-preflight.js +2 -1
- package/dist/lib/agent-shells.d.ts +26 -1
- package/dist/lib/agent-shells.js +214 -40
- package/dist/lib/agents.d.ts +1 -1
- package/dist/lib/agents.js +1 -1
- package/dist/lib/builtin-compiled-workflow.d.ts +38 -0
- package/dist/lib/builtin-compiled-workflow.js +94 -0
- package/dist/lib/compiled-compile.d.ts +0 -4
- package/dist/lib/compiled-compile.js +11 -30
- package/dist/lib/compiled-paths.d.ts +1 -2
- package/dist/lib/compiled-paths.js +8 -13
- package/dist/lib/compiled-raw.d.ts +2 -2
- package/dist/lib/compiled-reset.d.ts +1 -0
- package/dist/lib/compiled-reset.js +42 -14
- package/dist/lib/compiled-schema.d.ts +11 -7
- package/dist/lib/compiled-schema.js +47 -16
- package/dist/lib/discovery.d.ts +1 -1
- package/dist/lib/discovery.js +2 -2
- package/dist/lib/executors.d.ts +1 -1
- package/dist/lib/executors.js +2 -2
- package/dist/lib/interf-detect.d.ts +0 -1
- package/dist/lib/interf-detect.js +7 -18
- package/dist/lib/interf-scaffold.js +4 -11
- package/dist/lib/interf-workflow-package.d.ts +8 -3
- package/dist/lib/interf-workflow-package.js +128 -62
- package/dist/lib/interf.d.ts +1 -1
- package/dist/lib/interf.js +1 -1
- package/dist/lib/local-workflows.d.ts +4 -3
- package/dist/lib/local-workflows.js +127 -104
- package/dist/lib/project-paths.d.ts +2 -4
- package/dist/lib/project-paths.js +13 -10
- package/dist/lib/runtime-acceptance.js +15 -3
- package/dist/lib/runtime-contracts.js +3 -2
- package/dist/lib/runtime-paths.d.ts +1 -0
- package/dist/lib/runtime-paths.js +4 -1
- package/dist/lib/runtime-prompt.js +4 -4
- package/dist/lib/runtime-reconcile.js +90 -64
- package/dist/lib/runtime-runs.js +29 -102
- package/dist/lib/runtime.d.ts +1 -1
- package/dist/lib/runtime.js +1 -1
- package/dist/lib/schema.d.ts +104 -54
- package/dist/lib/schema.js +32 -116
- package/dist/lib/source-config.js +21 -22
- package/dist/lib/state-health.js +4 -2
- package/dist/lib/state-io.js +2 -110
- package/dist/lib/state-view.js +8 -8
- package/dist/lib/state.d.ts +1 -0
- package/dist/lib/state.js +7 -0
- package/dist/lib/test-execution.js +2 -2
- package/dist/lib/test-paths.js +12 -3
- package/dist/lib/test-sandbox.js +4 -17
- package/dist/lib/test-specs.js +1 -1
- package/dist/lib/validate-compiled.js +13 -8
- package/dist/lib/validate.d.ts +5 -1
- package/dist/lib/validate.js +30 -22
- package/dist/lib/workflow-authoring.d.ts +26 -0
- package/dist/lib/workflow-authoring.js +119 -0
- package/dist/lib/workflow-definitions.d.ts +14 -3
- package/dist/lib/workflow-definitions.js +21 -17
- package/dist/lib/workflow-edit-session.d.ts +16 -0
- package/dist/lib/workflow-edit-session.js +57 -0
- package/dist/lib/workflow-edit-utils.d.ts +10 -0
- package/dist/lib/workflow-edit-utils.js +39 -0
- package/dist/lib/workflow-improvement.js +30 -217
- package/dist/lib/workflow-primitives.d.ts +2 -0
- package/dist/lib/workflow-primitives.js +5 -0
- package/dist/lib/workflow-stage-policy.d.ts +5 -0
- package/dist/lib/workflow-stage-policy.js +31 -0
- package/package.json +7 -8
- package/dist/lib/compiled-layout.d.ts +0 -2
- package/dist/lib/compiled-layout.js +0 -60
- package/dist/lib/obsidian.d.ts +0 -1
- package/dist/lib/obsidian.js +0 -15
- package/dist/lib/summarize-plan.d.ts +0 -17
- package/dist/lib/summarize-plan.js +0 -124
- package/dist/lib/workflow-abi.d.ts +0 -129
- package/dist/lib/workflow-abi.js +0 -156
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import * as p from "@clack/prompts";
|
|
3
|
-
import {
|
|
3
|
+
import { statSync } from "node:fs";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import { listCompiledWorkflowChoices, getCompiledWorkflow, } from "../lib/workflow-definitions.js";
|
|
4
6
|
import { createLocalWorkflowPackageFromTemplate } from "../lib/interf-workflow-package.js";
|
|
5
7
|
import { isWorkflowId, } from "../lib/local-workflows.js";
|
|
8
|
+
import { resolveOrConfigureLocalExecutor } from "./executor-flow.js";
|
|
9
|
+
import { runWorkflowAuthoringDraft } from "../lib/workflow-authoring.js";
|
|
10
|
+
import { listSourceDatasetConfigs, loadSourceFolderConfig, resolveSourceDatasetPath, } from "../lib/source-config.js";
|
|
6
11
|
import { slugify } from "../lib/util.js";
|
|
7
12
|
export const clackWorkflowPrompts = {
|
|
8
13
|
intro: p.intro,
|
|
@@ -11,8 +16,22 @@ export const clackWorkflowPrompts = {
|
|
|
11
16
|
isCancel: p.isCancel,
|
|
12
17
|
log: {
|
|
13
18
|
info: p.log.info,
|
|
19
|
+
error: p.log.error,
|
|
14
20
|
},
|
|
15
21
|
};
|
|
22
|
+
function findMatchingDatasetConfig(sourcePath, datasetPath) {
|
|
23
|
+
const config = loadSourceFolderConfig(sourcePath);
|
|
24
|
+
for (const dataset of listSourceDatasetConfigs(config)) {
|
|
25
|
+
if (resolveSourceDatasetPath(sourcePath, dataset) === datasetPath) {
|
|
26
|
+
return dataset;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
function describeSavedDataset(dataset) {
|
|
32
|
+
return dataset.about
|
|
33
|
+
?? `${dataset.checks.length} saved truth check${dataset.checks.length === 1 ? "" : "s"} · path ${dataset.path}`;
|
|
34
|
+
}
|
|
16
35
|
export function formatWorkflowLabel(workflow) {
|
|
17
36
|
return {
|
|
18
37
|
value: workflow.id,
|
|
@@ -54,15 +73,38 @@ export async function createWorkflowWizard(options = {}, prompts = clackWorkflow
|
|
|
54
73
|
prompts.intro(chalk.bold("Create a workflow"));
|
|
55
74
|
}
|
|
56
75
|
const sourcePath = options.sourcePath ?? process.cwd();
|
|
57
|
-
return createCompiledWorkflowWizard(sourcePath, prompts
|
|
76
|
+
return createCompiledWorkflowWizard(sourcePath, prompts, {
|
|
77
|
+
executionProfile: options.executionProfile,
|
|
78
|
+
datasetContext: options.datasetContext,
|
|
79
|
+
resolveExecutor: options.resolveExecutor,
|
|
80
|
+
runDraft: options.runDraft,
|
|
81
|
+
});
|
|
58
82
|
}
|
|
59
|
-
export async function createCompiledWorkflowWizard(sourcePath, prompts = clackWorkflowPrompts) {
|
|
83
|
+
export async function createCompiledWorkflowWizard(sourcePath, prompts = clackWorkflowPrompts, options = {}) {
|
|
60
84
|
const baseWorkflow = await prompts.select({
|
|
61
85
|
message: "Start from which existing workflow?",
|
|
62
86
|
options: listCompiledWorkflowChoices(sourcePath).map(formatWorkflowLabel),
|
|
63
87
|
});
|
|
64
88
|
if (prompts.isCancel(baseWorkflow))
|
|
65
89
|
return baseWorkflow;
|
|
90
|
+
const resolvedBaseWorkflow = getCompiledWorkflow(String(baseWorkflow), { sourcePath });
|
|
91
|
+
const creationMode = await prompts.select({
|
|
92
|
+
message: "How do you want to create it?",
|
|
93
|
+
options: [
|
|
94
|
+
{
|
|
95
|
+
value: "draft",
|
|
96
|
+
label: "Draft a workflow from this dataset (Recommended)",
|
|
97
|
+
hint: "Seed a workflow, prepare a preview, then let a local agent draft a reusable method for this task",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
value: "manual",
|
|
101
|
+
label: "Copy an existing workflow",
|
|
102
|
+
hint: "Start from an existing workflow and edit stage guidance directly",
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
});
|
|
106
|
+
if (prompts.isCancel(creationMode))
|
|
107
|
+
return creationMode;
|
|
66
108
|
const rawName = await prompts.text({
|
|
67
109
|
message: "New workflow name?",
|
|
68
110
|
placeholder: "founder-research",
|
|
@@ -89,36 +131,130 @@ export async function createCompiledWorkflowWizard(sourcePath, prompts = clackWo
|
|
|
89
131
|
});
|
|
90
132
|
if (prompts.isCancel(hint))
|
|
91
133
|
return hint;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
134
|
+
if (creationMode === "draft") {
|
|
135
|
+
let datasetPath = options.datasetContext?.datasetPath ?? null;
|
|
136
|
+
let matchedDataset = options.datasetContext?.config ?? null;
|
|
137
|
+
if (!datasetPath) {
|
|
138
|
+
const savedDatasets = listSourceDatasetConfigs(loadSourceFolderConfig(sourcePath));
|
|
139
|
+
if (savedDatasets.length > 0) {
|
|
140
|
+
const datasetChoice = await prompts.select({
|
|
141
|
+
message: "Which dataset should shape this workflow?",
|
|
142
|
+
options: [
|
|
143
|
+
...savedDatasets.map((dataset) => ({
|
|
144
|
+
value: dataset.name,
|
|
145
|
+
label: dataset.name,
|
|
146
|
+
hint: describeSavedDataset(dataset),
|
|
147
|
+
})),
|
|
148
|
+
{
|
|
149
|
+
value: "__manual__",
|
|
150
|
+
label: "Enter folder path manually",
|
|
151
|
+
hint: "Use a folder that is not saved as a dataset yet",
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
});
|
|
155
|
+
if (prompts.isCancel(datasetChoice))
|
|
156
|
+
return datasetChoice;
|
|
157
|
+
if (datasetChoice !== "__manual__") {
|
|
158
|
+
matchedDataset = savedDatasets.find((dataset) => dataset.name === datasetChoice) ?? null;
|
|
159
|
+
datasetPath = matchedDataset
|
|
160
|
+
? resolveSourceDatasetPath(sourcePath, matchedDataset)
|
|
161
|
+
: null;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (!datasetPath) {
|
|
166
|
+
const datasetFolder = await prompts.text({
|
|
167
|
+
message: "Which dataset folder should shape this workflow?",
|
|
168
|
+
placeholder: ".",
|
|
169
|
+
initialValue: ".",
|
|
170
|
+
validate: (value) => {
|
|
171
|
+
const trimmed = value.trim();
|
|
172
|
+
if (trimmed.length === 0)
|
|
173
|
+
return "Dataset folder is required";
|
|
174
|
+
const absolutePath = resolve(sourcePath, trimmed);
|
|
175
|
+
try {
|
|
176
|
+
const stat = statSync(absolutePath);
|
|
177
|
+
return stat.isDirectory() ? undefined : "Dataset folder must be a directory";
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return "Dataset folder was not found";
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
if (prompts.isCancel(datasetFolder))
|
|
185
|
+
return datasetFolder;
|
|
186
|
+
datasetPath = resolve(sourcePath, String(datasetFolder).trim());
|
|
187
|
+
matchedDataset = matchedDataset ?? findMatchingDatasetConfig(sourcePath, datasetPath);
|
|
188
|
+
}
|
|
189
|
+
const taskPrompt = await prompts.text({
|
|
190
|
+
message: "What task should this workflow prepare the dataset for?",
|
|
191
|
+
placeholder: "Example: chart reads, board-prep questions, or latest planned launch status",
|
|
192
|
+
validate: (value) => (value.trim().length === 0 ? "Task focus is required" : undefined),
|
|
193
|
+
});
|
|
194
|
+
if (prompts.isCancel(taskPrompt))
|
|
195
|
+
return taskPrompt;
|
|
196
|
+
if (matchedDataset) {
|
|
197
|
+
prompts.log.info(`Shaping this workflow from dataset "${matchedDataset.name}".`);
|
|
198
|
+
}
|
|
199
|
+
if (matchedDataset?.checks.length) {
|
|
200
|
+
prompts.log.info(`Using ${matchedDataset.checks.length} saved truth check${matchedDataset.checks.length === 1 ? "" : "s"} from dataset "${matchedDataset.name}" as authoring context.`);
|
|
201
|
+
}
|
|
202
|
+
const resolveExecutor = options.resolveExecutor ?? resolveOrConfigureLocalExecutor;
|
|
203
|
+
const runDraft = options.runDraft ?? runWorkflowAuthoringDraft;
|
|
204
|
+
const { executor, error } = await resolveExecutor({
|
|
205
|
+
executionProfile: options.executionProfile,
|
|
206
|
+
purpose: "workflow",
|
|
207
|
+
});
|
|
208
|
+
if (!executor && !error) {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
if (!executor) {
|
|
212
|
+
process.exitCode = 1;
|
|
213
|
+
(prompts.log.error ?? prompts.log.info)(error ?? "No coding agent detected.");
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
prompts.log.info("Preparing a workflow-authoring preview from the dataset, then drafting the package.");
|
|
217
|
+
const result = await runDraft({
|
|
218
|
+
sourcePath,
|
|
219
|
+
datasetPath,
|
|
220
|
+
baseWorkflowId: baseWorkflow,
|
|
221
|
+
workflowId,
|
|
222
|
+
label,
|
|
223
|
+
hint: hint.trim(),
|
|
224
|
+
taskPrompt: taskPrompt.trim(),
|
|
225
|
+
checks: matchedDataset?.checks ?? [],
|
|
226
|
+
executor,
|
|
227
|
+
preparePreview: true,
|
|
228
|
+
});
|
|
229
|
+
if (result.status === "updated") {
|
|
230
|
+
prompts.log.info(`Saved local workflow: ${result.workflowPath}`);
|
|
231
|
+
return workflowId;
|
|
232
|
+
}
|
|
233
|
+
process.exitCode = 1;
|
|
234
|
+
(prompts.log.error ?? prompts.log.info)(result.status === "no-change"
|
|
235
|
+
? `${result.summary} Draft mode only succeeds when it produces a task-specific package change.`
|
|
236
|
+
: result.summary);
|
|
237
|
+
prompts.log.info(`Workflow shell kept at: ${result.shellPath}`);
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
const stagePolicyNotes = {};
|
|
241
|
+
for (const stage of resolvedBaseWorkflow.stages) {
|
|
242
|
+
const stagePrompt = await prompts.text({
|
|
243
|
+
message: `What should ${stage.id} (${stage.label}) emphasize?`,
|
|
244
|
+
placeholder: stage.description,
|
|
245
|
+
validate: (value) => (value.trim().length === 0 ? `${stage.label} guidance is required` : undefined),
|
|
246
|
+
});
|
|
247
|
+
if (prompts.isCancel(stagePrompt))
|
|
248
|
+
return stagePrompt;
|
|
249
|
+
stagePolicyNotes[stage.id] = [String(stagePrompt).trim()];
|
|
250
|
+
}
|
|
113
251
|
const workflowPath = createLocalWorkflowPackageFromTemplate({
|
|
114
252
|
sourcePath,
|
|
115
253
|
baseWorkflowId: baseWorkflow,
|
|
116
254
|
workflowId,
|
|
117
255
|
label,
|
|
118
256
|
hint: hint.trim(),
|
|
119
|
-
|
|
120
|
-
structureBias: structureBias.trim(),
|
|
121
|
-
shapeBias: shapeBias.trim(),
|
|
257
|
+
stagePolicyNotes,
|
|
122
258
|
});
|
|
123
259
|
prompts.log.info(`Saved local workflow: ${workflowPath}`);
|
|
124
260
|
return workflowId;
|
|
@@ -5,4 +5,4 @@ export declare function createCompiledWizard(options?: {
|
|
|
5
5
|
intro?: boolean;
|
|
6
6
|
executionProfile?: WorkflowExecutionProfile;
|
|
7
7
|
}): Promise<void>;
|
|
8
|
-
export { type WorkflowWizardPrompts, formatWorkflowLabel,
|
|
8
|
+
export { type WorkflowWizardPrompts, formatWorkflowLabel, createWorkflowWizard, createCompiledWorkflowWizard, } from "./create-workflow-wizard.js";
|
package/dist/commands/create.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { basename } from "node:path";
|
|
3
3
|
import * as p from "@clack/prompts";
|
|
4
|
-
import { detectInterf, defaultCompiledNameForSource, listCompiledDatasetsForSourceFolder, } from "../lib/interf.js";
|
|
4
|
+
import { detectInterf, defaultCompiledNameForSource, listCompiledDatasetsForSourceFolder, resolveSourceControlPath, } from "../lib/interf.js";
|
|
5
5
|
import { slugify } from "../lib/util.js";
|
|
6
6
|
import { addExecutionProfileOptions, executionProfileFromArgv, } from "../lib/execution-profile.js";
|
|
7
|
-
import { listSourceDatasetConfigs, loadSourceFolderConfig, upsertSourceDatasetConfig, } from "../lib/source-config.js";
|
|
7
|
+
import { listSourceDatasetConfigs, loadSourceFolderConfig, syncCompiledInterfConfigFromSourceDatasetConfig, upsertSourceDatasetConfig, } from "../lib/source-config.js";
|
|
8
8
|
import { createWorkflowWizard, } from "./create-workflow-wizard.js";
|
|
9
|
-
import {
|
|
9
|
+
import { findBuiltCompiledPath, } from "./compiled-flow.js";
|
|
10
10
|
import { DEFAULT_COMPILED_NAME, promptSingleCompiledConfig, } from "./source-config-wizard.js";
|
|
11
|
-
import { resolveOrConfigureLocalExecutor } from "./executor-flow.js";
|
|
12
|
-
import { runConfiguredCompiledCompile } from "./compile.js";
|
|
13
11
|
function normalizeCreateTarget(value) {
|
|
14
12
|
if (!value)
|
|
15
13
|
return null;
|
|
@@ -41,6 +39,56 @@ async function selectCreateTarget() {
|
|
|
41
39
|
],
|
|
42
40
|
});
|
|
43
41
|
}
|
|
42
|
+
async function maybeAssignWorkflowToDataset(sourcePath, workflowId) {
|
|
43
|
+
const config = loadSourceFolderConfig(sourcePath);
|
|
44
|
+
const datasets = listSourceDatasetConfigs(config);
|
|
45
|
+
if (datasets.length === 0) {
|
|
46
|
+
p.log.info(`Created workflow "${workflowId}".`);
|
|
47
|
+
p.log.info(`Next: run \`interf\`, add a dataset, then assign workflow "${workflowId}" from that dataset menu.`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const assignNow = await p.confirm({
|
|
51
|
+
message: "Assign this workflow to a dataset now? (Recommended)",
|
|
52
|
+
initialValue: true,
|
|
53
|
+
});
|
|
54
|
+
if (p.isCancel(assignNow) || !assignNow) {
|
|
55
|
+
p.log.info(`Created workflow "${workflowId}".`);
|
|
56
|
+
p.log.info(`Next: run \`interf\`, open a dataset, and assign workflow "${workflowId}" from that dataset menu.`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
let targetDataset = datasets[0] ?? null;
|
|
60
|
+
if (datasets.length > 1) {
|
|
61
|
+
const selected = await p.select({
|
|
62
|
+
message: "Which dataset should use this workflow?",
|
|
63
|
+
options: datasets.map((dataset) => ({
|
|
64
|
+
value: dataset.name,
|
|
65
|
+
label: dataset.name,
|
|
66
|
+
hint: `${dataset.path} · ${dataset.about ?? `${dataset.checks.length} saved truth check${dataset.checks.length === 1 ? "" : "s"}`}`,
|
|
67
|
+
})),
|
|
68
|
+
});
|
|
69
|
+
if (p.isCancel(selected))
|
|
70
|
+
return;
|
|
71
|
+
targetDataset = datasets.find((dataset) => dataset.name === selected) ?? null;
|
|
72
|
+
}
|
|
73
|
+
if (!targetDataset)
|
|
74
|
+
return;
|
|
75
|
+
const nextConfig = {
|
|
76
|
+
...targetDataset,
|
|
77
|
+
workflow: workflowId,
|
|
78
|
+
};
|
|
79
|
+
upsertSourceDatasetConfig(sourcePath, nextConfig, {
|
|
80
|
+
matchName: targetDataset.name,
|
|
81
|
+
});
|
|
82
|
+
const builtCompiledPath = findBuiltCompiledPath(sourcePath, targetDataset.name);
|
|
83
|
+
if (builtCompiledPath) {
|
|
84
|
+
syncCompiledInterfConfigFromSourceDatasetConfig(builtCompiledPath, nextConfig);
|
|
85
|
+
}
|
|
86
|
+
p.log.info(`Assigned workflow "${workflowId}" to dataset "${targetDataset.name}".`);
|
|
87
|
+
if (builtCompiledPath) {
|
|
88
|
+
p.log.info("The active local copy for that built dataset lives under `.interf/workflow/`.");
|
|
89
|
+
}
|
|
90
|
+
p.log.info("Next: run `interf compile`, then `interf test`.");
|
|
91
|
+
}
|
|
44
92
|
export const createCommand = {
|
|
45
93
|
command: "create [type]",
|
|
46
94
|
describe: "Create a dataset entry or reusable workflow",
|
|
@@ -65,7 +113,14 @@ export const createCommand = {
|
|
|
65
113
|
type = selected;
|
|
66
114
|
}
|
|
67
115
|
if (type === "workflow") {
|
|
68
|
-
|
|
116
|
+
const detected = detectInterf(process.cwd());
|
|
117
|
+
const workflowId = await createWorkflowWizard({
|
|
118
|
+
sourcePath: detected ? resolveSourceControlPath(detected.path) : process.cwd(),
|
|
119
|
+
executionProfile,
|
|
120
|
+
});
|
|
121
|
+
if (typeof workflowId === "string") {
|
|
122
|
+
await maybeAssignWorkflowToDataset(detected ? resolveSourceControlPath(detected.path) : process.cwd(), workflowId);
|
|
123
|
+
}
|
|
69
124
|
return;
|
|
70
125
|
}
|
|
71
126
|
await createCompiledWizard({ executionProfile });
|
|
@@ -86,10 +141,9 @@ export async function createCompiledWizard(options = {}) {
|
|
|
86
141
|
if (existing.length > 0) {
|
|
87
142
|
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
143
|
}
|
|
89
|
-
p.log.info("Interf
|
|
144
|
+
p.log.info("Interf works one dataset at a time. Start with the task, truth checks, and a baseline, then build a compiled dataset only when you need it.");
|
|
90
145
|
const existingConfig = loadSourceFolderConfig(cwd);
|
|
91
146
|
const suggestedName = slugify(defaultCompiledNameForSource(cwd) || basename(cwd)) || DEFAULT_COMPILED_NAME;
|
|
92
|
-
const workflowId = "interf";
|
|
93
147
|
const draft = await promptSingleCompiledConfig({
|
|
94
148
|
projectPath: cwd,
|
|
95
149
|
initial: { name: suggestedName },
|
|
@@ -99,7 +153,7 @@ export async function createCompiledWizard(options = {}) {
|
|
|
99
153
|
return;
|
|
100
154
|
const configToSave = {
|
|
101
155
|
...draft,
|
|
102
|
-
workflow:
|
|
156
|
+
workflow: "interf",
|
|
103
157
|
};
|
|
104
158
|
const existingNames = new Set(listSourceDatasetConfigs(existingConfig).map((dataset) => dataset.name));
|
|
105
159
|
if (existingNames.has(configToSave.name)) {
|
|
@@ -108,55 +162,8 @@ export async function createCompiledWizard(options = {}) {
|
|
|
108
162
|
return;
|
|
109
163
|
}
|
|
110
164
|
upsertSourceDatasetConfig(cwd, configToSave);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
});
|
|
115
|
-
if (p.isCancel(compileNow) || !compileNow) {
|
|
116
|
-
p.outro(configToSave.checks.length > 0
|
|
117
|
-
? "Next:\n interf test\n interf compile"
|
|
118
|
-
: "Next:\n interf or interf init");
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
const { executor, error } = await resolveOrConfigureLocalExecutor({
|
|
122
|
-
executionProfile: options.executionProfile,
|
|
123
|
-
purpose: "compile",
|
|
124
|
-
});
|
|
125
|
-
if (!executor && !error) {
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
if (!executor) {
|
|
129
|
-
process.exitCode = 1;
|
|
130
|
-
p.log.error(error ?? "No coding agent detected.");
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
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);
|
|
147
|
-
}
|
|
148
|
-
async function compileCompiledAfterCreate(executor, sourcePath, datasetConfig, compiledPath, executionProfile) {
|
|
149
|
-
const compiled = await runConfiguredCompiledCompile({
|
|
150
|
-
executor,
|
|
151
|
-
compiledPath,
|
|
152
|
-
sourcePath,
|
|
153
|
-
compiledConfig: datasetConfig,
|
|
154
|
-
executionProfile,
|
|
155
|
-
maxAttemptsOverride: null,
|
|
156
|
-
maxLoopsOverride: null,
|
|
157
|
-
});
|
|
158
|
-
if (!compiled)
|
|
159
|
-
process.exitCode = 1;
|
|
160
|
-
return compiled;
|
|
165
|
+
p.outro(configToSave.checks.length > 0
|
|
166
|
+
? "Saved dataset.\nNext:\n interf test\n interf compile"
|
|
167
|
+
: "Saved dataset.\nNext:\n interf or interf init");
|
|
161
168
|
}
|
|
162
|
-
export { formatWorkflowLabel,
|
|
169
|
+
export { formatWorkflowLabel, createWorkflowWizard, createCompiledWorkflowWizard, } from "./create-workflow-wizard.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SourceDatasetConfig } from "../lib/schema.js";
|
|
2
|
+
export declare function resolveConfiguredDatasetSelection(options: {
|
|
3
|
+
sourcePath: string;
|
|
4
|
+
requestedDatasetName?: string | null;
|
|
5
|
+
hintedDatasetConfig?: SourceDatasetConfig | null;
|
|
6
|
+
}): SourceDatasetConfig | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { findSavedCompiledConfig } from "./compiled-flow.js";
|
|
2
|
+
export function resolveConfiguredDatasetSelection(options) {
|
|
3
|
+
if (options.hintedDatasetConfig &&
|
|
4
|
+
(!options.requestedDatasetName || options.hintedDatasetConfig.name === options.requestedDatasetName)) {
|
|
5
|
+
return options.hintedDatasetConfig;
|
|
6
|
+
}
|
|
7
|
+
if (!options.requestedDatasetName) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return findSavedCompiledConfig(options.sourcePath, options.requestedDatasetName);
|
|
11
|
+
}
|
package/dist/commands/default.js
CHANGED
|
@@ -4,8 +4,8 @@ import { runInitCommand } from "./init.js";
|
|
|
4
4
|
function printStaticLanding() {
|
|
5
5
|
const config = loadUserConfig();
|
|
6
6
|
console.log();
|
|
7
|
-
console.log(chalk.bold(" Interf
|
|
8
|
-
console.log(chalk.dim(" Define truth checks, measure files
|
|
7
|
+
console.log(chalk.bold(" Interf"));
|
|
8
|
+
console.log(chalk.dim(" Define the task, save truth checks, measure raw files first, then compile only if they are not good enough."));
|
|
9
9
|
console.log();
|
|
10
10
|
if (config) {
|
|
11
11
|
console.log(chalk.dim(` Agent: ${config.agent}`));
|
|
@@ -20,7 +20,7 @@ function printStaticLanding() {
|
|
|
20
20
|
console.log(chalk.dim(" More:"));
|
|
21
21
|
console.log(chalk.dim(" interf init"));
|
|
22
22
|
console.log(chalk.dim(" interf create workflow"));
|
|
23
|
-
console.log(chalk.dim(" interf doctor"));
|
|
23
|
+
console.log(chalk.dim(" interf doctor --live"));
|
|
24
24
|
console.log(chalk.dim(" interf --help"));
|
|
25
25
|
console.log();
|
|
26
26
|
}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -12,7 +12,7 @@ function iconFor(status) {
|
|
|
12
12
|
}
|
|
13
13
|
export const doctorCommand = {
|
|
14
14
|
command: "doctor",
|
|
15
|
-
describe: "Check local executor setup before a real
|
|
15
|
+
describe: "Check local executor setup before a real local run",
|
|
16
16
|
builder: (yargs) => yargs
|
|
17
17
|
.option("live", {
|
|
18
18
|
type: "boolean",
|
|
@@ -31,7 +31,7 @@ export const doctorCommand = {
|
|
|
31
31
|
if (config) {
|
|
32
32
|
checks.push({
|
|
33
33
|
id: "config",
|
|
34
|
-
label: "Interf
|
|
34
|
+
label: "Interf setup",
|
|
35
35
|
status: "pass",
|
|
36
36
|
message: `Configured default agent: ${config.agent}`,
|
|
37
37
|
});
|
|
@@ -39,9 +39,9 @@ export const doctorCommand = {
|
|
|
39
39
|
else {
|
|
40
40
|
checks.push({
|
|
41
41
|
id: "config",
|
|
42
|
-
label: "Interf
|
|
42
|
+
label: "Interf setup",
|
|
43
43
|
status: "warn",
|
|
44
|
-
message: "No saved Interf
|
|
44
|
+
message: "No saved Interf setup found. `interf` or `interf init` is recommended for deterministic local runs.",
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
if (!agent) {
|
|
@@ -56,7 +56,7 @@ export const doctorCommand = {
|
|
|
56
56
|
}
|
|
57
57
|
else {
|
|
58
58
|
console.log();
|
|
59
|
-
console.log(chalk.bold(" Interf
|
|
59
|
+
console.log(chalk.bold(" Interf doctor"));
|
|
60
60
|
console.log();
|
|
61
61
|
for (const check of checks) {
|
|
62
62
|
console.log(` ${iconFor(check.status)} ${check.label}: ${check.message}`);
|
|
@@ -79,7 +79,7 @@ export const doctorCommand = {
|
|
|
79
79
|
label: "Live executor preflight",
|
|
80
80
|
status: preflight.ok ? "pass" : "fail",
|
|
81
81
|
message: preflight.ok
|
|
82
|
-
? `${agent.displayName} accepted Interf
|
|
82
|
+
? `${agent.displayName} accepted Interf's automated run invocation`
|
|
83
83
|
: preflight.timedOut
|
|
84
84
|
? `${agent.displayName} timed out during preflight`
|
|
85
85
|
: preflight.error ?? `${agent.displayName} could not complete the preflight run`,
|
|
@@ -98,7 +98,7 @@ export const doctorCommand = {
|
|
|
98
98
|
id: "live",
|
|
99
99
|
label: "Live executor preflight",
|
|
100
100
|
status: "skipped",
|
|
101
|
-
message: "Skipped. Run `interf doctor --live` to exercise the real local agent before a compile.",
|
|
101
|
+
message: "Skipped. Run `interf doctor --live` to exercise the real local agent before a truth-check draft, workflow authoring run, test, or compile.",
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
const ok = checks.every((check) => check.status !== "fail");
|
|
@@ -115,7 +115,7 @@ export const doctorCommand = {
|
|
|
115
115
|
}
|
|
116
116
|
else {
|
|
117
117
|
console.log();
|
|
118
|
-
console.log(chalk.bold(" Interf
|
|
118
|
+
console.log(chalk.bold(" Interf doctor"));
|
|
119
119
|
console.log();
|
|
120
120
|
for (const check of checks) {
|
|
121
121
|
console.log(` ${iconFor(check.status)} ${check.label}: ${check.message}`);
|
|
@@ -21,7 +21,7 @@ export declare function promptForTestAgents(): Promise<{
|
|
|
21
21
|
export declare function resolveOrConfigureLocalExecutor(options?: {
|
|
22
22
|
preflight?: boolean;
|
|
23
23
|
executionProfile?: WorkflowExecutionProfile;
|
|
24
|
-
purpose?: "compile" | "test" | "draft";
|
|
24
|
+
purpose?: "compile" | "test" | "draft" | "workflow";
|
|
25
25
|
}): Promise<{
|
|
26
26
|
executor: WorkflowExecutor | null;
|
|
27
27
|
error?: string;
|
|
@@ -25,7 +25,6 @@ function persistSelectedAgent(selectedName) {
|
|
|
25
25
|
agent: selected.name,
|
|
26
26
|
agentCommand: selected.command,
|
|
27
27
|
skillsInstalled: current?.skillsInstalled ?? false,
|
|
28
|
-
...(current?.viewer ? { viewer: current.viewer } : {}),
|
|
29
28
|
initialized: current?.initialized ?? new Date().toISOString(),
|
|
30
29
|
});
|
|
31
30
|
}
|
|
@@ -89,7 +88,11 @@ export async function promptForTestAgents() {
|
|
|
89
88
|
return { agents, cancelled: false };
|
|
90
89
|
}
|
|
91
90
|
async function promptForRunAgent(purpose) {
|
|
92
|
-
const purposeLabel = purpose === "draft"
|
|
91
|
+
const purposeLabel = purpose === "draft"
|
|
92
|
+
? "truth-check draft"
|
|
93
|
+
: purpose === "workflow"
|
|
94
|
+
? "workflow authoring"
|
|
95
|
+
: purpose;
|
|
93
96
|
const detected = supportedDetectedAgents();
|
|
94
97
|
if (detected.length === 0)
|
|
95
98
|
return { selected: false, cancelled: false };
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
import type { CommandModule } from "yargs";
|
|
2
|
+
import type { SourceDatasetConfig } from "../lib/schema.js";
|
|
3
|
+
import { runCompileCommand } from "./compile.js";
|
|
4
|
+
export declare function compileSelectedCompiled(sourcePath: string, compiledConfig: SourceDatasetConfig, deps?: {
|
|
5
|
+
runCompileCommand?: typeof runCompileCommand;
|
|
6
|
+
}): Promise<import("./compile.js").CompileCommandResult | null>;
|
|
2
7
|
export declare const initCommand: CommandModule;
|
|
3
8
|
export declare function runInitCommand(): Promise<void>;
|