@interf/compiler 0.5.1 → 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 -187
- 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 +6 -13
- 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.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 +213 -39
- package/dist/lib/agents.d.ts +1 -1
- package/dist/lib/agents.js +1 -1
- package/dist/lib/builtin-compiled-workflow.d.ts +6 -97
- package/dist/lib/builtin-compiled-workflow.js +66 -125
- package/dist/lib/compiled-compile.d.ts +0 -4
- package/dist/lib/compiled-compile.js +9 -28
- package/dist/lib/compiled-paths.d.ts +1 -0
- package/dist/lib/compiled-paths.js +3 -0
- package/dist/lib/compiled-reset.d.ts +1 -0
- package/dist/lib/compiled-reset.js +42 -14
- package/dist/lib/compiled-schema.d.ts +9 -5
- package/dist/lib/compiled-schema.js +45 -14
- 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-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/local-workflows.d.ts +4 -3
- package/dist/lib/local-workflows.js +126 -103
- 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 +3 -1
- package/dist/lib/runtime-reconcile.js +88 -51
- package/dist/lib/runtime-runs.js +27 -15
- package/dist/lib/runtime.d.ts +1 -1
- package/dist/lib/runtime.js +1 -1
- package/dist/lib/schema.d.ts +71 -14
- package/dist/lib/schema.js +15 -12
- package/dist/lib/state-view.js +6 -6
- 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/validate-compiled.js +9 -6
- package/dist/lib/validate.d.ts +3 -1
- package/dist/lib/validate.js +4 -11
- package/dist/lib/workflow-authoring.d.ts +26 -0
- package/dist/lib/workflow-authoring.js +119 -0
- package/dist/lib/workflow-definitions.d.ts +11 -1
- package/dist/lib/workflow-definitions.js +12 -15
- 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-stage-policy.d.ts +5 -0
- package/dist/lib/workflow-stage-policy.js +31 -0
- package/package.json +4 -5
- 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 -120
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"kind": "
|
|
2
|
+
"kind": "workflow-schema",
|
|
3
3
|
"version": 1,
|
|
4
4
|
"target_type": "compiled",
|
|
5
|
-
"label": "Interf
|
|
5
|
+
"label": "Interf built-in workflow schema",
|
|
6
6
|
"zones": [
|
|
7
7
|
{
|
|
8
8
|
"id": "raw",
|
|
9
|
+
"role": "input",
|
|
9
10
|
"path": "raw",
|
|
10
11
|
"kind": "directory",
|
|
11
12
|
"required": true,
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
},
|
|
15
16
|
{
|
|
16
17
|
"id": "summaries",
|
|
18
|
+
"role": "working",
|
|
17
19
|
"path": "summaries",
|
|
18
20
|
"kind": "directory",
|
|
19
21
|
"required": true,
|
|
@@ -24,6 +26,7 @@
|
|
|
24
26
|
},
|
|
25
27
|
{
|
|
26
28
|
"id": "knowledge-entities",
|
|
29
|
+
"role": "output",
|
|
27
30
|
"path": "knowledge/entities",
|
|
28
31
|
"kind": "directory",
|
|
29
32
|
"required": true,
|
|
@@ -34,6 +37,7 @@
|
|
|
34
37
|
},
|
|
35
38
|
{
|
|
36
39
|
"id": "knowledge-claims",
|
|
40
|
+
"role": "output",
|
|
37
41
|
"path": "knowledge/claims",
|
|
38
42
|
"kind": "directory",
|
|
39
43
|
"required": true,
|
|
@@ -44,6 +48,7 @@
|
|
|
44
48
|
},
|
|
45
49
|
{
|
|
46
50
|
"id": "knowledge-indexes",
|
|
51
|
+
"role": "output",
|
|
47
52
|
"path": "knowledge/indexes",
|
|
48
53
|
"kind": "directory",
|
|
49
54
|
"required": true,
|
|
@@ -55,6 +60,7 @@
|
|
|
55
60
|
},
|
|
56
61
|
{
|
|
57
62
|
"id": "home",
|
|
63
|
+
"role": "output",
|
|
58
64
|
"path": "home.md",
|
|
59
65
|
"kind": "file",
|
|
60
66
|
"required": true,
|
|
@@ -65,6 +71,7 @@
|
|
|
65
71
|
},
|
|
66
72
|
{
|
|
67
73
|
"id": "runtime",
|
|
74
|
+
"role": "runtime",
|
|
68
75
|
"path": ".interf/runtime",
|
|
69
76
|
"kind": "runtime",
|
|
70
77
|
"required": true,
|
|
@@ -12,18 +12,18 @@ export function buildTruthCheckDraftPrompt(options) {
|
|
|
12
12
|
const taskLines = normalizedAbout
|
|
13
13
|
? [
|
|
14
14
|
`Primary task: ${normalizedAbout}`,
|
|
15
|
-
"Draft checks that directly measure whether a local agent
|
|
15
|
+
"Draft checks that directly measure whether a local agent can answer the key questions from the data behind that task.",
|
|
16
16
|
"Prefer checks that would make a human confident the dataset is useful for that exact job.",
|
|
17
17
|
]
|
|
18
18
|
: [
|
|
19
19
|
"No primary task was provided.",
|
|
20
|
-
"Prefer broad, representative checks that reflect the most useful questions this dataset
|
|
20
|
+
"Prefer broad, representative checks that reflect the most useful questions a human would verify from this dataset.",
|
|
21
21
|
];
|
|
22
22
|
return [
|
|
23
23
|
"You are drafting Interf truth checks for a local dataset.",
|
|
24
24
|
"Read the files in this folder and draft a small set of checks that a human can verify from the source material.",
|
|
25
25
|
"Do not ask follow-up questions.",
|
|
26
|
-
"Keep the checks concrete, explicit, and useful for measuring agent
|
|
26
|
+
"Keep the checks concrete, explicit, and useful for measuring whether an agent can reason correctly over the data in this dataset.",
|
|
27
27
|
"",
|
|
28
28
|
`Dataset id: ${options.datasetName}`,
|
|
29
29
|
`Dataset folder: ${options.datasetPath}`,
|
|
@@ -3,12 +3,13 @@ import { tmpdir } from "node:os";
|
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import { readInterfConfig } from "../lib/interf.js";
|
|
6
|
-
import { resetCompiledGeneratedState } from "../lib/compiled-reset.js";
|
|
6
|
+
import { clearCompiledRuntimeDerivedArtifacts, resetCompiledGeneratedState, } from "../lib/compiled-reset.js";
|
|
7
7
|
import { formatActiveCompiledWorkflowStageStep, resolveRequiredCompiledWorkflowFromConfig, } from "../lib/workflow-definitions.js";
|
|
8
8
|
import { resolveDatasetCompileMaxAttempts, resolveDatasetCompileMaxLoops, } from "../lib/source-config.js";
|
|
9
9
|
import { runWorkflowImprovementLoop } from "../lib/workflow-improvement.js";
|
|
10
10
|
import { stageExecutionShellsRoot, workflowPackagePathForCompiled, } from "../lib/compiled-paths.js";
|
|
11
11
|
import { readCompiledSchemaFile } from "../lib/compiled-schema.js";
|
|
12
|
+
import { initializeCompiledRuntimeState } from "../lib/state.js";
|
|
12
13
|
import { compileCompiledWithReporter } from "./compiled-flow.js";
|
|
13
14
|
import { printSavedTestOutcome, questionPassRate, runSavedCompiledTest, } from "./test-flow.js";
|
|
14
15
|
function printCompileFailure(compiledPath, failedStage) {
|
|
@@ -19,14 +20,6 @@ function printCompileFailure(compiledPath, failedStage) {
|
|
|
19
20
|
function testScore(outcome) {
|
|
20
21
|
return (outcome.result.passedCases * 1000) + outcome.result.passedChecks;
|
|
21
22
|
}
|
|
22
|
-
const BEST_VARIATION_RUNTIME_RESTORE_PATHS = [
|
|
23
|
-
".interf/runtime/state.json",
|
|
24
|
-
".interf/runtime/health.json",
|
|
25
|
-
".interf/runtime/view-spec.json",
|
|
26
|
-
".interf/runtime/inventory.json",
|
|
27
|
-
".interf/runtime/run.json",
|
|
28
|
-
".interf/runtime/raw-snapshot.json",
|
|
29
|
-
];
|
|
30
23
|
function bestVariationRestorePaths(compiledPath) {
|
|
31
24
|
const schema = readCompiledSchemaFile(workflowPackagePathForCompiled(compiledPath));
|
|
32
25
|
const zonePaths = (schema?.zones ?? [])
|
|
@@ -39,10 +32,8 @@ function bestVariationRestorePaths(compiledPath) {
|
|
|
39
32
|
".codex",
|
|
40
33
|
".agents",
|
|
41
34
|
".cursor",
|
|
42
|
-
".obsidian",
|
|
43
35
|
".interf/interf.json",
|
|
44
36
|
".interf/workflow",
|
|
45
|
-
...BEST_VARIATION_RUNTIME_RESTORE_PATHS,
|
|
46
37
|
...zonePaths,
|
|
47
38
|
];
|
|
48
39
|
}
|
|
@@ -71,6 +62,8 @@ function restoreCompiledBestState(snapshotPath, compiledPath) {
|
|
|
71
62
|
rmSync(join(compiledPath, relativePath), { recursive: true, force: true });
|
|
72
63
|
copyRelativePathIfPresent(snapshotPath, compiledPath, relativePath);
|
|
73
64
|
}
|
|
65
|
+
clearCompiledRuntimeDerivedArtifacts(compiledPath);
|
|
66
|
+
initializeCompiledRuntimeState(compiledPath);
|
|
74
67
|
}
|
|
75
68
|
async function runWorkflowVariation(options) {
|
|
76
69
|
let bestOutcome = null;
|
|
@@ -267,14 +260,14 @@ export async function runConfiguredCompiledCompile(options) {
|
|
|
267
260
|
else if (loopEnabled) {
|
|
268
261
|
if (maxAttempts > 1) {
|
|
269
262
|
console.log(chalk.dim(` Retry mode: up to ${maxAttempts} compile attempts.`));
|
|
270
|
-
console.log(chalk.dim(" Interf
|
|
263
|
+
console.log(chalk.dim(" Interf will rerun the same workflow variation, test the compiled dataset, and stop early if it passes."));
|
|
271
264
|
}
|
|
272
265
|
else {
|
|
273
266
|
console.log(chalk.dim(" Compile mode: 1 attempt per workflow variation."));
|
|
274
267
|
}
|
|
275
268
|
if (maxLoops != null) {
|
|
276
269
|
console.log(chalk.dim(` Self-improving loops: up to ${maxLoops} workflow edits after retries fail.`));
|
|
277
|
-
console.log(chalk.dim(" Interf
|
|
270
|
+
console.log(chalk.dim(" Interf will review failed runs, edit the workflow, and test new workflow variations."));
|
|
278
271
|
}
|
|
279
272
|
}
|
|
280
273
|
if (!loopEnabled || checks.length === 0) {
|
|
@@ -1,8 +1,26 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import { detectInterf } from "../lib/interf.js";
|
|
1
3
|
import type { SourceDatasetConfig } from "../lib/schema.js";
|
|
2
4
|
import type { CommandModule } from "yargs";
|
|
5
|
+
import { chooseCompiledConfigToBuild, ensureCompiledFromConfig } from "./compiled-flow.js";
|
|
6
|
+
import { resolveOrConfigureLocalExecutor } from "./executor-flow.js";
|
|
7
|
+
import { runConfiguredCompiledCompile } from "./compile-controller.js";
|
|
3
8
|
export { runConfiguredCompiledCompile } from "./compile-controller.js";
|
|
4
9
|
export declare const compileCommand: CommandModule;
|
|
5
|
-
|
|
10
|
+
interface CompileCommandDeps {
|
|
11
|
+
chooseCompiledConfigToBuild: typeof chooseCompiledConfigToBuild;
|
|
12
|
+
confirm: typeof p.confirm;
|
|
13
|
+
detectInterf: typeof detectInterf;
|
|
14
|
+
ensureCompiledFromConfig: typeof ensureCompiledFromConfig;
|
|
15
|
+
resolveInteractiveCompileLoopOverrides: typeof resolveInteractiveCompileLoopOverrides;
|
|
16
|
+
resolveOrConfigureLocalExecutor: typeof resolveOrConfigureLocalExecutor;
|
|
17
|
+
runConfiguredCompiledCompile: typeof runConfiguredCompiledCompile;
|
|
18
|
+
}
|
|
19
|
+
export interface CompileCommandResult {
|
|
20
|
+
compiledPath: string;
|
|
21
|
+
testedDuringCompile: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function runCompileCommand(argv?: Record<string, unknown>, deps?: Partial<CompileCommandDeps>): Promise<CompileCommandResult | null>;
|
|
6
24
|
export declare function resolveInteractiveCompileLoopOverrides(options: {
|
|
7
25
|
compiledPath: string;
|
|
8
26
|
compiledConfig: SourceDatasetConfig | null;
|
package/dist/commands/compile.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import * as p from "@clack/prompts";
|
|
3
3
|
import { detectInterf, readInterfConfig, resolveSourceControlPath, } from "../lib/interf.js";
|
|
4
|
-
import { sourceDatasetConfigFromInterfConfig, } from "../lib/source-config.js";
|
|
4
|
+
import { sourceDatasetConfigFromInterfConfig, resolveDatasetCompileMaxAttempts, resolveDatasetCompileMaxLoops, } from "../lib/source-config.js";
|
|
5
5
|
import { addExecutionProfileOptions, executionProfileFromArgv, } from "../lib/execution-profile.js";
|
|
6
6
|
import { chooseCompiledConfigToBuild, ensureCompiledFromConfig, } from "./compiled-flow.js";
|
|
7
|
+
import { resolveConfiguredDatasetSelection } from "./dataset-selection.js";
|
|
7
8
|
import { promptCompileLoopSelection, } from "./source-config-wizard.js";
|
|
8
9
|
import { resolveOrConfigureLocalExecutor } from "./executor-flow.js";
|
|
9
10
|
import { runConfiguredCompiledCompile } from "./compile-controller.js";
|
|
10
11
|
export { runConfiguredCompiledCompile } from "./compile-controller.js";
|
|
11
12
|
export const compileCommand = {
|
|
12
13
|
command: "compile",
|
|
13
|
-
describe: "Build
|
|
14
|
+
describe: "Build a compiled dataset and optionally run retry or self-improving compile loops",
|
|
14
15
|
builder: (yargs) => addExecutionProfileOptions(yargs).option("max-attempts", {
|
|
15
16
|
type: "number",
|
|
16
17
|
describe: "Retry compile + test for the same workflow until the dataset passes or reaches this total attempt limit",
|
|
@@ -26,48 +27,105 @@ export const compileCommand = {
|
|
|
26
27
|
await runCompileCommand(argv);
|
|
27
28
|
},
|
|
28
29
|
};
|
|
29
|
-
|
|
30
|
+
const defaultCompileCommandDeps = {
|
|
31
|
+
chooseCompiledConfigToBuild,
|
|
32
|
+
confirm: p.confirm,
|
|
33
|
+
detectInterf,
|
|
34
|
+
ensureCompiledFromConfig,
|
|
35
|
+
resolveInteractiveCompileLoopOverrides,
|
|
36
|
+
resolveOrConfigureLocalExecutor,
|
|
37
|
+
runConfiguredCompiledCompile,
|
|
38
|
+
};
|
|
39
|
+
function readHintedSourcePath(argv) {
|
|
40
|
+
return typeof argv.sourcePath === "string" && argv.sourcePath.trim().length > 0
|
|
41
|
+
? argv.sourcePath.trim()
|
|
42
|
+
: null;
|
|
43
|
+
}
|
|
44
|
+
function readRequestedDatasetName(argv) {
|
|
45
|
+
return typeof argv.dataset === "string" && argv.dataset.trim().length > 0
|
|
46
|
+
? argv.dataset.trim()
|
|
47
|
+
: null;
|
|
48
|
+
}
|
|
49
|
+
function shouldSkipCompileConfirm(argv) {
|
|
50
|
+
return argv.skipConfirm === true;
|
|
51
|
+
}
|
|
52
|
+
function shouldSkipDatasetBanner(argv) {
|
|
53
|
+
return argv.skipDatasetBanner === true;
|
|
54
|
+
}
|
|
55
|
+
function compileRunTests(options) {
|
|
56
|
+
const checks = options.compiledConfig?.checks ?? [];
|
|
57
|
+
if (checks.length === 0)
|
|
58
|
+
return false;
|
|
59
|
+
const configuredMaxAttempts = resolveDatasetCompileMaxAttempts(options.compiledConfig ?? { max_attempts: undefined }, options.maxAttemptsOverride);
|
|
60
|
+
const maxLoops = resolveDatasetCompileMaxLoops(options.compiledConfig ?? { max_loops: undefined }, options.maxLoopsOverride);
|
|
61
|
+
const maxAttempts = configuredMaxAttempts ?? (maxLoops != null ? 1 : null);
|
|
62
|
+
return maxAttempts != null;
|
|
63
|
+
}
|
|
64
|
+
export async function runCompileCommand(argv = {}, deps = {}) {
|
|
65
|
+
const helpers = {
|
|
66
|
+
...defaultCompileCommandDeps,
|
|
67
|
+
...deps,
|
|
68
|
+
};
|
|
30
69
|
let compiledPath = null;
|
|
31
|
-
|
|
70
|
+
const hintedSourcePath = readHintedSourcePath(argv);
|
|
71
|
+
const detected = hintedSourcePath ? null : helpers.detectInterf(process.cwd());
|
|
72
|
+
let sourcePath = hintedSourcePath ?? process.cwd();
|
|
32
73
|
let compiledConfig = null;
|
|
33
|
-
const
|
|
74
|
+
const requestedDatasetName = readRequestedDatasetName(argv);
|
|
75
|
+
const hintedDatasetConfig = (argv.datasetConfig ?? null);
|
|
76
|
+
const skipConfirm = shouldSkipCompileConfirm(argv);
|
|
77
|
+
const skipDatasetBanner = shouldSkipDatasetBanner(argv);
|
|
34
78
|
if (detected) {
|
|
35
79
|
compiledPath = detected.path;
|
|
36
80
|
sourcePath = resolveSourceControlPath(detected.path);
|
|
37
81
|
compiledConfig = sourceDatasetConfigFromInterfConfig(detected.config);
|
|
38
|
-
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
39
|
-
const confirmed = await
|
|
82
|
+
if (!skipConfirm && process.stdin.isTTY && process.stdout.isTTY) {
|
|
83
|
+
const confirmed = await helpers.confirm({
|
|
40
84
|
message: `Compile dataset "${detected.config.name}" now?`,
|
|
41
85
|
initialValue: true,
|
|
42
86
|
});
|
|
43
87
|
if (p.isCancel(confirmed) || !confirmed)
|
|
44
|
-
return;
|
|
88
|
+
return null;
|
|
45
89
|
}
|
|
46
90
|
}
|
|
47
91
|
else {
|
|
48
|
-
const selectedCompiled =
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
92
|
+
const selectedCompiled = requestedDatasetName || hintedDatasetConfig
|
|
93
|
+
? resolveConfiguredDatasetSelection({
|
|
94
|
+
sourcePath,
|
|
95
|
+
requestedDatasetName,
|
|
96
|
+
hintedDatasetConfig,
|
|
97
|
+
})
|
|
98
|
+
: await helpers.chooseCompiledConfigToBuild({
|
|
99
|
+
sourcePath,
|
|
100
|
+
selectMessage: "Which dataset do you want to compile?",
|
|
101
|
+
});
|
|
52
102
|
if (selectedCompiled === undefined)
|
|
53
|
-
return;
|
|
103
|
+
return null;
|
|
54
104
|
if (!selectedCompiled) {
|
|
55
105
|
process.exitCode = 1;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
106
|
+
if (requestedDatasetName) {
|
|
107
|
+
console.log(chalk.red(` Dataset "${requestedDatasetName}" is not set up in this project.`));
|
|
108
|
+
console.log(chalk.dim(" Run `interf list` to see the saved datasets."));
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
console.log(chalk.red(" No datasets are set up for this folder yet."));
|
|
112
|
+
console.log(chalk.dim(" Start with `interf` or `interf init` to set up this folder."));
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
59
115
|
}
|
|
60
|
-
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
61
|
-
const confirmed = await
|
|
116
|
+
if (!skipConfirm && process.stdin.isTTY && process.stdout.isTTY) {
|
|
117
|
+
const confirmed = await helpers.confirm({
|
|
62
118
|
message: `Compile dataset "${selectedCompiled.name}" now?`,
|
|
63
119
|
initialValue: true,
|
|
64
120
|
});
|
|
65
121
|
if (p.isCancel(confirmed) || !confirmed)
|
|
66
|
-
return;
|
|
122
|
+
return null;
|
|
67
123
|
}
|
|
68
124
|
compiledConfig = selectedCompiled;
|
|
69
|
-
compiledPath = ensureCompiledFromConfig(
|
|
70
|
-
|
|
125
|
+
compiledPath = helpers.ensureCompiledFromConfig(sourcePath, selectedCompiled);
|
|
126
|
+
if (!skipDatasetBanner) {
|
|
127
|
+
console.log(chalk.dim(` Dataset: ${selectedCompiled.name}`));
|
|
128
|
+
}
|
|
71
129
|
}
|
|
72
130
|
let maxAttemptsOverride = null;
|
|
73
131
|
let maxLoopsOverride = null;
|
|
@@ -78,32 +136,37 @@ export async function runCompileCommand(argv = {}) {
|
|
|
78
136
|
catch (error) {
|
|
79
137
|
process.exitCode = 1;
|
|
80
138
|
console.log(chalk.red(error instanceof Error ? error.message : String(error)));
|
|
81
|
-
return;
|
|
139
|
+
return null;
|
|
82
140
|
}
|
|
83
|
-
const interactiveOverrides = await resolveInteractiveCompileLoopOverrides({
|
|
141
|
+
const interactiveOverrides = await helpers.resolveInteractiveCompileLoopOverrides({
|
|
84
142
|
compiledPath,
|
|
85
143
|
compiledConfig,
|
|
86
144
|
maxAttemptsOverride,
|
|
87
145
|
maxLoopsOverride,
|
|
88
146
|
});
|
|
89
147
|
if (!interactiveOverrides)
|
|
90
|
-
return;
|
|
148
|
+
return null;
|
|
91
149
|
compiledConfig = interactiveOverrides.compiledConfig;
|
|
92
150
|
maxAttemptsOverride = interactiveOverrides.maxAttemptsOverride;
|
|
93
151
|
maxLoopsOverride = interactiveOverrides.maxLoopsOverride;
|
|
152
|
+
const testedDuringCompile = compileRunTests({
|
|
153
|
+
compiledConfig,
|
|
154
|
+
maxAttemptsOverride,
|
|
155
|
+
maxLoopsOverride,
|
|
156
|
+
});
|
|
94
157
|
const executionProfile = executionProfileFromArgv(argv);
|
|
95
|
-
const { executor, error } = await resolveOrConfigureLocalExecutor({
|
|
158
|
+
const { executor, error } = await helpers.resolveOrConfigureLocalExecutor({
|
|
96
159
|
executionProfile,
|
|
97
160
|
purpose: "compile",
|
|
98
161
|
});
|
|
99
162
|
if (!executor && !error)
|
|
100
|
-
return;
|
|
163
|
+
return null;
|
|
101
164
|
if (!executor) {
|
|
102
165
|
process.exitCode = 1;
|
|
103
166
|
console.log(chalk.red(error ?? "No coding agent detected."));
|
|
104
|
-
return;
|
|
167
|
+
return null;
|
|
105
168
|
}
|
|
106
|
-
await runConfiguredCompiledCompile({
|
|
169
|
+
const compiled = await helpers.runConfiguredCompiledCompile({
|
|
107
170
|
executor,
|
|
108
171
|
compiledPath,
|
|
109
172
|
sourcePath,
|
|
@@ -113,6 +176,13 @@ export async function runCompileCommand(argv = {}) {
|
|
|
113
176
|
maxLoopsOverride,
|
|
114
177
|
preserveStageShells: readStageShellRetentionMode(argv),
|
|
115
178
|
});
|
|
179
|
+
if (!compiled) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
compiledPath,
|
|
184
|
+
testedDuringCompile,
|
|
185
|
+
};
|
|
116
186
|
}
|
|
117
187
|
export async function resolveInteractiveCompileLoopOverrides(options) {
|
|
118
188
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { resolveOrConfigureLocalExecutor } from "./executor-flow.js";
|
|
2
|
+
import { runWorkflowAuthoringDraft } from "../lib/workflow-authoring.js";
|
|
3
|
+
import type { SourceDatasetConfig } from "../lib/schema.js";
|
|
4
|
+
import type { WorkflowExecutionProfile } from "../lib/executors.js";
|
|
1
5
|
export interface WorkflowWizardPrompts {
|
|
2
6
|
intro(message: string): void;
|
|
3
7
|
select(options: {
|
|
@@ -17,8 +21,13 @@ export interface WorkflowWizardPrompts {
|
|
|
17
21
|
isCancel(value: unknown): value is symbol;
|
|
18
22
|
log: {
|
|
19
23
|
info(message: string): void;
|
|
24
|
+
error?(message: string): void;
|
|
20
25
|
};
|
|
21
26
|
}
|
|
27
|
+
export interface WorkflowWizardDatasetContext {
|
|
28
|
+
config: SourceDatasetConfig;
|
|
29
|
+
datasetPath: string;
|
|
30
|
+
}
|
|
22
31
|
export declare const clackWorkflowPrompts: WorkflowWizardPrompts;
|
|
23
32
|
export declare function formatWorkflowLabel(workflow: {
|
|
24
33
|
id: string;
|
|
@@ -42,5 +51,14 @@ export declare function chooseCompiledWorkflow(sourcePath: string, options?: {
|
|
|
42
51
|
export declare function createWorkflowWizard(options?: {
|
|
43
52
|
intro?: boolean;
|
|
44
53
|
sourcePath?: string;
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
executionProfile?: WorkflowExecutionProfile;
|
|
55
|
+
datasetContext?: WorkflowWizardDatasetContext;
|
|
56
|
+
resolveExecutor?: typeof resolveOrConfigureLocalExecutor;
|
|
57
|
+
runDraft?: typeof runWorkflowAuthoringDraft;
|
|
58
|
+
}, prompts?: WorkflowWizardPrompts): Promise<string | symbol | null>;
|
|
59
|
+
export declare function createCompiledWorkflowWizard(sourcePath: string, prompts?: WorkflowWizardPrompts, options?: {
|
|
60
|
+
executionProfile?: WorkflowExecutionProfile;
|
|
61
|
+
datasetContext?: WorkflowWizardDatasetContext;
|
|
62
|
+
resolveExecutor?: typeof resolveOrConfigureLocalExecutor;
|
|
63
|
+
runDraft?: typeof runWorkflowAuthoringDraft;
|
|
64
|
+
}): Promise<string | symbol | null>;
|
|
@@ -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";
|