@interf/compiler 0.7.1 → 0.7.3
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 +77 -72
- package/builtin-workflows/interf/README.md +4 -4
- package/builtin-workflows/interf/compile/stages/shape/SKILL.md +4 -4
- package/builtin-workflows/interf/improve/SKILL.md +1 -1
- package/builtin-workflows/interf/use/query/SKILL.md +1 -1
- package/builtin-workflows/interf/workflow.json +4 -4
- package/builtin-workflows/interf/workflow.schema.json +1 -1
- package/dist/cli/commands/compile-controller.js +5 -5
- package/dist/cli/commands/compile.js +1 -1
- package/dist/cli/commands/create-workflow-wizard.d.ts +6 -0
- package/dist/cli/commands/create-workflow-wizard.js +57 -5
- package/dist/cli/commands/create.js +21 -11
- package/dist/cli/commands/default.js +2 -1
- package/dist/cli/commands/init.js +65 -54
- package/dist/cli/commands/source-config-wizard.d.ts +0 -1
- package/dist/cli/commands/source-config-wizard.js +1 -4
- package/dist/cli/commands/status.js +3 -3
- package/dist/cli/commands/test-flow.js +9 -7
- package/dist/cli/commands/test.js +7 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/packages/agents/lib/shells.js +22 -19
- package/dist/packages/compiler/compiled-paths.js +1 -1
- package/dist/packages/compiler/runtime-prompt.js +1 -1
- package/dist/packages/project-model/interf-detect.js +24 -10
- package/dist/packages/project-model/interf-scaffold.d.ts +1 -0
- package/dist/packages/project-model/interf-scaffold.js +30 -11
- package/dist/packages/project-model/interf.d.ts +1 -1
- package/dist/packages/project-model/interf.js +1 -1
- package/dist/packages/project-model/project-paths.d.ts +3 -1
- package/dist/packages/project-model/project-paths.js +6 -2
- package/dist/packages/project-model/source-config.d.ts +5 -0
- package/dist/packages/project-model/source-config.js +60 -7
- package/dist/packages/testing/test-paths.js +6 -3
- package/dist/packages/workflow-authoring/workflow-authoring.js +4 -2
- package/dist/packages/workflow-authoring/workflow-edit-session.js +5 -2
- package/dist/packages/workflow-package/context-interface.js +1 -1
- package/dist/packages/workflow-package/workflow-review-paths.js +5 -1
- package/package.json +2 -4
|
@@ -65,7 +65,7 @@ export function resolveSourceInputPath(compiledPath) {
|
|
|
65
65
|
const projectPath = resolveSourceControlPathForCompiled(compiledPath);
|
|
66
66
|
return assertPathWithinRoot(projectPath, resolve(compiledPath, config.source.dataset_path), "Dataset source path");
|
|
67
67
|
}
|
|
68
|
-
throw new Error(`
|
|
68
|
+
throw new Error(`Compiled context is missing source.dataset_path in ${compiledInterfConfigPath(compiledPath)}.`);
|
|
69
69
|
}
|
|
70
70
|
export function listCompiledDatasetsForSourceFolder(sourcePath) {
|
|
71
71
|
const interfRoot = projectInterfRoot(sourcePath);
|
|
@@ -82,7 +82,8 @@ export function listCompiledDatasetsForSourceFolder(sourcePath) {
|
|
|
82
82
|
return readdirSync(interfRoot)
|
|
83
83
|
.filter((entry) => !entry.startsWith(".") &&
|
|
84
84
|
entry !== WORKFLOW_CONTAINER_NAME &&
|
|
85
|
-
entry !== TEST_CONTAINER_NAME
|
|
85
|
+
entry !== TEST_CONTAINER_NAME &&
|
|
86
|
+
entry !== INTERF_CONFIG_FILE)
|
|
86
87
|
.map((entry) => compiledCompiledPathForDataset(sourcePath, entry))
|
|
87
88
|
.filter((compiledPath) => existsSync(compiledPath))
|
|
88
89
|
.map((compiledPath) => {
|
|
@@ -102,6 +103,15 @@ export function assertCompiledContainer(sourcePath) {
|
|
|
102
103
|
if (entry.startsWith("."))
|
|
103
104
|
return false;
|
|
104
105
|
const entryPath = join(interfRoot, entry);
|
|
106
|
+
if (entry === INTERF_CONFIG_FILE) {
|
|
107
|
+
try {
|
|
108
|
+
return !statSync(entryPath).isFile();
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
warnInterf(`Warning: failed to inspect Interf config path at ${entryPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
105
115
|
if (entry === WORKFLOW_CONTAINER_NAME || entry === TEST_CONTAINER_NAME) {
|
|
106
116
|
try {
|
|
107
117
|
return !statSync(entryPath).isDirectory();
|
|
@@ -112,14 +122,12 @@ export function assertCompiledContainer(sourcePath) {
|
|
|
112
122
|
}
|
|
113
123
|
}
|
|
114
124
|
try {
|
|
115
|
-
|
|
116
|
-
return true;
|
|
125
|
+
return !statSync(entryPath).isDirectory();
|
|
117
126
|
}
|
|
118
127
|
catch (error) {
|
|
119
128
|
warnInterf(`Warning: failed to inspect Interf entry at ${entryPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
120
129
|
return true;
|
|
121
130
|
}
|
|
122
|
-
return false;
|
|
123
131
|
});
|
|
124
132
|
if (unexpectedRootEntries.length > 0) {
|
|
125
133
|
throw new Error(`Interf container contains unexpected entries: ${interfRoot}`);
|
|
@@ -136,6 +144,16 @@ export function assertCompiledContainer(sourcePath) {
|
|
|
136
144
|
const unexpectedEntries = readdirSync(containerPath).filter((entry) => {
|
|
137
145
|
if (entry.startsWith("."))
|
|
138
146
|
return false;
|
|
147
|
+
if (entry === INTERF_CONFIG_FILE) {
|
|
148
|
+
const entryPath = join(containerPath, entry);
|
|
149
|
+
try {
|
|
150
|
+
return !statSync(entryPath).isFile();
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
warnInterf(`Warning: failed to inspect Interf config path at ${entryPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
139
157
|
if (entry === WORKFLOW_CONTAINER_NAME || entry === TEST_CONTAINER_NAME)
|
|
140
158
|
return false;
|
|
141
159
|
const entryPath = join(containerPath, entry);
|
|
@@ -147,11 +165,7 @@ export function assertCompiledContainer(sourcePath) {
|
|
|
147
165
|
warnInterf(`Warning: failed to inspect Interf entry at ${entryPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
148
166
|
return true;
|
|
149
167
|
}
|
|
150
|
-
|
|
151
|
-
if (!existsSync(compiledPath)) {
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
return !readInterfConfig(compiledPath);
|
|
168
|
+
return false;
|
|
155
169
|
});
|
|
156
170
|
if (unexpectedEntries.length > 0) {
|
|
157
171
|
throw new Error(`Interf container contains invalid dataset entries: ${containerPath}`);
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
export declare function ensurePortableContextScaffold(sourcePath: string, datasetName: string, workflowId?: string): string;
|
|
1
2
|
export declare function createCompiled(name: string, sourcePath: string, workflowId?: string, about?: string, datasetPath?: string): string;
|
|
2
3
|
export declare function defaultCompiledNameForSource(sourcePath: string): string;
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { mkdirSync, existsSync, writeFileSync, } from "node:fs";
|
|
2
2
|
import { basename, join, relative, sep } from "node:path";
|
|
3
3
|
import { getCompiledWorkflow } from "../workflow-package/workflow-definitions.js";
|
|
4
|
+
import { loadWorkflowDefinitionFromDir, seedLocalDefaultWorkflow } from "../workflow-package/local-workflows.js";
|
|
4
5
|
import { initializeCompiledRuntimeState, } from "../compiler/state.js";
|
|
5
6
|
import { refreshCompiledBootstrapGuidance } from "../agents/lib/compiled-bootstrap.js";
|
|
6
7
|
import { syncCompiledRawSnapshot } from "../compiler/raw-snapshot.js";
|
|
7
|
-
import { assertCompiledContainer,
|
|
8
|
+
import { assertCompiledContainer, assertCompiledName, } from "./interf-detect.js";
|
|
8
9
|
import { seedCompiledWorkflowPackage } from "../workflow-package/interf-workflow-package.js";
|
|
9
10
|
import { compiledCompiledPathForDataset } from "./project-paths.js";
|
|
10
11
|
import { ensureCompiledZoneTargets, readCompiledSchemaFile } from "../compiler/compiled-schema.js";
|
|
11
12
|
import { findSourceDatasetConfig, listSourceDatasetConfigs, loadSourceFolderConfig, resolveSourceDatasetPath, saveCompiledInterfConfig, } from "./source-config.js";
|
|
12
|
-
import { defaultControlPathForCompiled, workflowPackagePathForCompiled } from "../compiler/compiled-paths.js";
|
|
13
|
+
import { defaultControlPathForCompiled, testRootForCompiled, workflowPackagePathForCompiled } from "../compiler/compiled-paths.js";
|
|
13
14
|
const DEFAULT_INTERFIGNORE = [
|
|
14
15
|
".claude/",
|
|
15
16
|
".codex/",
|
|
@@ -61,14 +62,37 @@ function scaffoldCompiledOutputs(compiledPath, compiledName, about) {
|
|
|
61
62
|
writeFileSync(targetPath, renderUncompiledCompiledFile(compiledName, zone.path, about));
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
function localWorkflowMatches(compiledPath, workflowId) {
|
|
66
|
+
const localWorkflow = loadWorkflowDefinitionFromDir(workflowPackagePathForCompiled(compiledPath));
|
|
67
|
+
return localWorkflow?.id === workflowId;
|
|
68
|
+
}
|
|
69
|
+
export function ensurePortableContextScaffold(sourcePath, datasetName, workflowId = "interf") {
|
|
70
|
+
assertCompiledName(datasetName, "Portable context");
|
|
66
71
|
assertCompiledContainer(sourcePath);
|
|
67
|
-
const compiledPath = compiledCompiledPathForDataset(sourcePath,
|
|
68
|
-
assertWritableTargetDir(compiledPath, "Portable context");
|
|
72
|
+
const compiledPath = compiledCompiledPathForDataset(sourcePath, datasetName);
|
|
69
73
|
mkdirSync(compiledPath, { recursive: true });
|
|
74
|
+
mkdirSync(testRootForCompiled(compiledPath), { recursive: true });
|
|
75
|
+
if (workflowId === "interf-default") {
|
|
76
|
+
seedLocalDefaultWorkflow({ sourcePath });
|
|
77
|
+
}
|
|
78
|
+
const selectedWorkflow = getCompiledWorkflow(workflowId, { sourcePath });
|
|
79
|
+
if (!localWorkflowMatches(compiledPath, selectedWorkflow.id)) {
|
|
80
|
+
seedCompiledWorkflowPackage({
|
|
81
|
+
compiledPath,
|
|
82
|
+
sourcePath,
|
|
83
|
+
workflowId: selectedWorkflow.id,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (!existsSync(join(compiledPath, ".gitignore"))) {
|
|
87
|
+
writeFileSync(join(compiledPath, ".gitignore"), [...compiledGitignoreEntries(compiledPath), ""].join("\n"));
|
|
88
|
+
}
|
|
89
|
+
return compiledPath;
|
|
90
|
+
}
|
|
91
|
+
export function createCompiled(name, sourcePath, workflowId = "interf", about, datasetPath) {
|
|
92
|
+
assertCompiledName(name, "Portable context");
|
|
70
93
|
const savedCompiled = findSourceDatasetConfig(loadSourceFolderConfig(sourcePath), name);
|
|
71
94
|
const selectedWorkflow = getCompiledWorkflow(workflowId, { sourcePath });
|
|
95
|
+
const compiledPath = ensurePortableContextScaffold(sourcePath, name, selectedWorkflow.id);
|
|
72
96
|
const resolvedAbout = about ?? savedCompiled?.about;
|
|
73
97
|
const resolvedDatasetPath = (() => {
|
|
74
98
|
if (savedCompiled) {
|
|
@@ -108,11 +132,6 @@ export function createCompiled(name, sourcePath, workflowId = "interf", about, d
|
|
|
108
132
|
mkdirSync(join(compiledPath, "raw"), { recursive: true });
|
|
109
133
|
syncCompiledRawSnapshot(compiledPath, resolvedDatasetPath);
|
|
110
134
|
writeFileSync(join(compiledPath, ".interfignore"), DEFAULT_INTERFIGNORE);
|
|
111
|
-
seedCompiledWorkflowPackage({
|
|
112
|
-
compiledPath,
|
|
113
|
-
sourcePath,
|
|
114
|
-
workflowId: selectedWorkflow.id,
|
|
115
|
-
});
|
|
116
135
|
scaffoldCompiledOutputs(compiledPath, name, about);
|
|
117
136
|
refreshCompiledBootstrapGuidance(compiledPath);
|
|
118
137
|
writeFileSync(join(compiledPath, ".gitignore"), [...compiledGitignoreEntries(compiledPath), ""].join("\n"));
|
|
@@ -2,4 +2,4 @@ export { INTERF_CONTAINER_NAME, WORKFLOW_CONTAINER_NAME, TEST_CONTAINER_NAME, IN
|
|
|
2
2
|
export type { InterfConfig, ResolvedCompiled } from "./interf-detect.js";
|
|
3
3
|
export { ensureCompiledRawBinding, resolveCompiledRawPath, syncCompiledRawSnapshot, } from "./compiled-raw.js";
|
|
4
4
|
export { refreshCompiledBootstrapGuidance, renderClaudeBootstrap, } from "./interf-bootstrap.js";
|
|
5
|
-
export { createCompiled, defaultCompiledNameForSource, } from "./interf-scaffold.js";
|
|
5
|
+
export { createCompiled, defaultCompiledNameForSource, ensurePortableContextScaffold, } from "./interf-scaffold.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { INTERF_CONTAINER_NAME, WORKFLOW_CONTAINER_NAME, TEST_CONTAINER_NAME, INTERF_CONFIG_FILE, WORKFLOW_PACKAGE_DIR, readInterfConfig, detectInterf, resolveCompiled, resolveSourceFolderPath, resolveSourceControlPath, resolveSourceInputPath, listCompiledDatasetsForSourceFolder, hasSourceFolderInput, assertCompiledContainer, assertWritableTargetDir, assertCompiledName, } from "./interf-detect.js";
|
|
2
2
|
export { ensureCompiledRawBinding, resolveCompiledRawPath, syncCompiledRawSnapshot, } from "./compiled-raw.js";
|
|
3
3
|
export { refreshCompiledBootstrapGuidance, renderClaudeBootstrap, } from "./interf-bootstrap.js";
|
|
4
|
-
export { createCompiled, defaultCompiledNameForSource, } from "./interf-scaffold.js";
|
|
4
|
+
export { createCompiled, defaultCompiledNameForSource, ensurePortableContextScaffold, } from "./interf-scaffold.js";
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export declare const PROJECT_INTERF_DIR = "interf";
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const DATASET_INTERF_DIR = ".interf";
|
|
3
|
+
export declare const PORTABLE_CONTEXT_TESTS_DIR = "tests";
|
|
3
4
|
export declare function projectInterfRoot(projectPath: string): string;
|
|
4
5
|
export declare function compiledCompiledPathForDataset(projectPath: string, datasetName: string): string;
|
|
6
|
+
export declare function portableContextPath(projectPath: string, datasetName: string): string;
|
|
5
7
|
export declare function datasetTestsRoot(projectPath: string, datasetName: string): string;
|
|
6
8
|
export type DatasetTestTargetLabel = "file-as-is" | "compiled";
|
|
7
9
|
export declare function datasetTestRunsRoot(projectPath: string, datasetName: string, target: DatasetTestTargetLabel): string;
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
export const PROJECT_INTERF_DIR = "interf";
|
|
3
|
-
export const
|
|
3
|
+
export const DATASET_INTERF_DIR = ".interf";
|
|
4
|
+
export const PORTABLE_CONTEXT_TESTS_DIR = "tests";
|
|
4
5
|
export function projectInterfRoot(projectPath) {
|
|
5
6
|
return join(projectPath, PROJECT_INTERF_DIR);
|
|
6
7
|
}
|
|
7
8
|
export function compiledCompiledPathForDataset(projectPath, datasetName) {
|
|
8
9
|
return join(projectInterfRoot(projectPath), datasetName);
|
|
9
10
|
}
|
|
11
|
+
export function portableContextPath(projectPath, datasetName) {
|
|
12
|
+
return compiledCompiledPathForDataset(projectPath, datasetName);
|
|
13
|
+
}
|
|
10
14
|
export function datasetTestsRoot(projectPath, datasetName) {
|
|
11
|
-
return join(
|
|
15
|
+
return join(portableContextPath(projectPath, datasetName), DATASET_INTERF_DIR, PORTABLE_CONTEXT_TESTS_DIR);
|
|
12
16
|
}
|
|
13
17
|
export function datasetTestRunsRoot(projectPath, datasetName, target) {
|
|
14
18
|
return join(datasetTestsRoot(projectPath, datasetName), target, "runs");
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { type InterfConfig, type SourceTruthCheck, type SourceDatasetConfig, type SourceFolderConfig } from "./lib/schema.js";
|
|
2
2
|
import type { TestSpec, TestTargetType } from "../testing/lib/schema.js";
|
|
3
3
|
export declare const SOURCE_FOLDER_CONFIG_FILE = "interf.json";
|
|
4
|
+
export declare const SOURCE_FOLDER_CONFIG_PATH = "interf/interf.json";
|
|
4
5
|
export interface LoadedSourceTestSpec extends TestSpec {
|
|
5
6
|
id: string;
|
|
6
7
|
filePath: string;
|
|
7
8
|
}
|
|
9
|
+
export declare function sourceFolderConfigPath(sourcePath: string): string;
|
|
10
|
+
export declare function legacySourceFolderConfigPath(sourcePath: string): string;
|
|
11
|
+
export declare function resolveSourceFolderConfigPath(sourcePath: string): string;
|
|
12
|
+
export declare function migrateLegacySourceFolderConfig(sourcePath: string): boolean;
|
|
8
13
|
export declare function fingerprintTruthChecks(checks: SourceTruthCheck[]): string;
|
|
9
14
|
export declare function loadSourceFolderConfig(sourcePath: string): SourceFolderConfig | null;
|
|
10
15
|
export interface WritableSourceProjectConfig {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { join, relative, resolve, sep } from "node:path";
|
|
4
4
|
import { refreshCompiledBootstrapGuidance } from "../agents/lib/compiled-bootstrap.js";
|
|
5
5
|
import { readInterfConfig, } from "./interf.js";
|
|
@@ -10,10 +10,61 @@ import { SourceFolderConfigSchema, } from "./lib/schema.js";
|
|
|
10
10
|
import { slugify } from "../shared/naming.js";
|
|
11
11
|
import { assertPathWithinRoot } from "../shared/path-guards.js";
|
|
12
12
|
import { defaultControlPathForCompiled, resolveSourceControlPathForCompiled, compiledInterfConfigPath, compiledInterfRoot, } from "../compiler/compiled-paths.js";
|
|
13
|
+
import { projectInterfRoot, PROJECT_INTERF_DIR } from "./project-paths.js";
|
|
13
14
|
export const SOURCE_FOLDER_CONFIG_FILE = "interf.json";
|
|
14
|
-
|
|
15
|
+
export const SOURCE_FOLDER_CONFIG_PATH = `${PROJECT_INTERF_DIR}/${SOURCE_FOLDER_CONFIG_FILE}`;
|
|
16
|
+
export function sourceFolderConfigPath(sourcePath) {
|
|
17
|
+
return join(projectInterfRoot(sourcePath), SOURCE_FOLDER_CONFIG_FILE);
|
|
18
|
+
}
|
|
19
|
+
export function legacySourceFolderConfigPath(sourcePath) {
|
|
15
20
|
return join(sourcePath, SOURCE_FOLDER_CONFIG_FILE);
|
|
16
21
|
}
|
|
22
|
+
export function resolveSourceFolderConfigPath(sourcePath) {
|
|
23
|
+
const primaryPath = sourceFolderConfigPath(sourcePath);
|
|
24
|
+
if (existsSync(primaryPath))
|
|
25
|
+
return primaryPath;
|
|
26
|
+
const legacyPath = legacySourceFolderConfigPath(sourcePath);
|
|
27
|
+
if (existsSync(legacyPath))
|
|
28
|
+
return legacyPath;
|
|
29
|
+
return primaryPath;
|
|
30
|
+
}
|
|
31
|
+
function readSourceFolderConfigFile(filePath) {
|
|
32
|
+
return readJsonFileWithSchema(filePath, "Interf project config", SourceFolderConfigSchema);
|
|
33
|
+
}
|
|
34
|
+
function readJsonFileUncheckedQuiet(filePath) {
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(readFileSync(filePath, "utf-8"));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function isValidLegacySourceFolderConfig(sourcePath) {
|
|
43
|
+
const legacyPath = legacySourceFolderConfigPath(sourcePath);
|
|
44
|
+
if (!existsSync(legacyPath))
|
|
45
|
+
return false;
|
|
46
|
+
const raw = readJsonFileUncheckedQuiet(legacyPath);
|
|
47
|
+
return SourceFolderConfigSchema.safeParse(raw).success;
|
|
48
|
+
}
|
|
49
|
+
export function migrateLegacySourceFolderConfig(sourcePath) {
|
|
50
|
+
const primaryPath = sourceFolderConfigPath(sourcePath);
|
|
51
|
+
const legacyPath = legacySourceFolderConfigPath(sourcePath);
|
|
52
|
+
if (existsSync(primaryPath) || !existsSync(legacyPath))
|
|
53
|
+
return false;
|
|
54
|
+
if (!isValidLegacySourceFolderConfig(sourcePath))
|
|
55
|
+
return false;
|
|
56
|
+
mkdirSync(projectInterfRoot(sourcePath), { recursive: true });
|
|
57
|
+
renameSync(legacyPath, primaryPath);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
function removeLegacySourceFolderConfig(sourcePath) {
|
|
61
|
+
const legacyPath = legacySourceFolderConfigPath(sourcePath);
|
|
62
|
+
if (!existsSync(legacyPath))
|
|
63
|
+
return;
|
|
64
|
+
if (!isValidLegacySourceFolderConfig(sourcePath))
|
|
65
|
+
return;
|
|
66
|
+
rmSync(legacyPath, { force: true });
|
|
67
|
+
}
|
|
17
68
|
function normalizeTruthChecks(cases) {
|
|
18
69
|
const seen = new Set();
|
|
19
70
|
return cases.map((caseSpec, index) => {
|
|
@@ -47,10 +98,10 @@ export function fingerprintTruthChecks(checks) {
|
|
|
47
98
|
.slice(0, 16);
|
|
48
99
|
}
|
|
49
100
|
export function loadSourceFolderConfig(sourcePath) {
|
|
50
|
-
const filePath =
|
|
101
|
+
const filePath = resolveSourceFolderConfigPath(sourcePath);
|
|
51
102
|
if (!existsSync(filePath))
|
|
52
103
|
return null;
|
|
53
|
-
return
|
|
104
|
+
return readSourceFolderConfigFile(filePath);
|
|
54
105
|
}
|
|
55
106
|
export function listSourceDatasetConfigs(config) {
|
|
56
107
|
return config?.datasets ?? [];
|
|
@@ -101,7 +152,9 @@ function toWritableSourceDatasetConfig(dataset) {
|
|
|
101
152
|
};
|
|
102
153
|
}
|
|
103
154
|
export function saveSourceFolderConfig(sourcePath, config) {
|
|
104
|
-
|
|
155
|
+
mkdirSync(projectInterfRoot(sourcePath), { recursive: true });
|
|
156
|
+
writeFileSync(sourceFolderConfigPath(sourcePath), JSON.stringify(toWritableSourceProjectConfig(config), null, 2) + "\n");
|
|
157
|
+
removeLegacySourceFolderConfig(sourcePath);
|
|
105
158
|
}
|
|
106
159
|
export function appendSourceDatasetChecks(sourcePath, datasetName, checks) {
|
|
107
160
|
const existing = loadSourceFolderConfig(sourcePath);
|
|
@@ -263,7 +316,7 @@ export function buildTestSpecFromSourceFolderConfig(options) {
|
|
|
263
316
|
: getDefaultSourceDatasetConfig(config);
|
|
264
317
|
if (!match)
|
|
265
318
|
return null;
|
|
266
|
-
const configPath =
|
|
319
|
+
const configPath = resolveSourceFolderConfigPath(sourcePath);
|
|
267
320
|
return buildLoadedTestSpec({
|
|
268
321
|
id: match.id,
|
|
269
322
|
name: match.name,
|
|
@@ -273,7 +326,7 @@ export function buildTestSpecFromSourceFolderConfig(options) {
|
|
|
273
326
|
filePath: targetType === "raw"
|
|
274
327
|
? `${configPath}#datasets/${match.name}:file-as-is`
|
|
275
328
|
: `${configPath}#datasets/${match.name}:compiled`,
|
|
276
|
-
fallbackDescription: `Derived from saved dataset checks in ${
|
|
329
|
+
fallbackDescription: `Derived from saved dataset checks in ${SOURCE_FOLDER_CONFIG_PATH}`,
|
|
277
330
|
});
|
|
278
331
|
}
|
|
279
332
|
export function buildTestSpecFromCompiledDatasetConfig(options) {
|
|
@@ -10,7 +10,10 @@ export function testSpecTypePath(sourcePath, type) {
|
|
|
10
10
|
return join(testSpecRootPath(sourcePath), type);
|
|
11
11
|
}
|
|
12
12
|
function isDatasetTestsRootPath(artifactRootPath) {
|
|
13
|
-
|
|
13
|
+
const portableContextTestsRoot = basename(artifactRootPath) === "tests" &&
|
|
14
|
+
basename(dirname(artifactRootPath)) === ".interf";
|
|
15
|
+
const legacyProjectTestsRoot = basename(dirname(artifactRootPath)) === "tests";
|
|
16
|
+
return portableContextTestsRoot || legacyProjectTestsRoot;
|
|
14
17
|
}
|
|
15
18
|
export function targetTestRunsPath(compiledPath, type) {
|
|
16
19
|
if (existsSync(compiledInterfConfigPath(compiledPath))) {
|
|
@@ -19,7 +22,7 @@ export function targetTestRunsPath(compiledPath, type) {
|
|
|
19
22
|
if (isDatasetTestsRootPath(compiledPath)) {
|
|
20
23
|
return join(compiledPath, type === "raw" ? "file-as-is" : "compiled", "runs");
|
|
21
24
|
}
|
|
22
|
-
throw new Error(`Unsupported test artifact root: ${compiledPath}. Expected a compiled context or interf/tests
|
|
25
|
+
throw new Error(`Unsupported test artifact root: ${compiledPath}. Expected a compiled context or interf/<dataset>/.interf/tests root.`);
|
|
23
26
|
}
|
|
24
27
|
export function targetTestRunGitignorePath(compiledPath, type) {
|
|
25
28
|
return join(targetTestRunsPath(compiledPath, type), ".gitignore");
|
|
@@ -31,7 +34,7 @@ export function targetTestSandboxesPath(compiledPath, type) {
|
|
|
31
34
|
if (isDatasetTestsRootPath(compiledPath)) {
|
|
32
35
|
return join(compiledPath, type === "raw" ? "file-as-is" : "compiled", "sandboxes");
|
|
33
36
|
}
|
|
34
|
-
throw new Error(`Unsupported test artifact root: ${compiledPath}. Expected a compiled context or interf/tests
|
|
37
|
+
throw new Error(`Unsupported test artifact root: ${compiledPath}. Expected a compiled context or interf/<dataset>/.interf/tests root.`);
|
|
35
38
|
}
|
|
36
39
|
export function targetTestSandboxGitignorePath(compiledPath, type) {
|
|
37
40
|
return join(targetTestSandboxesPath(compiledPath, type), ".gitignore");
|
|
@@ -13,15 +13,17 @@ function buildWorkflowAuthoringPrompt() {
|
|
|
13
13
|
return [
|
|
14
14
|
"This is an automated Interf workflow-authoring run, not an open-ended chat session.",
|
|
15
15
|
"Execute it now.",
|
|
16
|
-
"Create one standalone workflow for the
|
|
16
|
+
"Create one standalone workflow for the source data, desired portable-context outputs, and proof requirements in this source folder.",
|
|
17
17
|
"Read `runtime/authoring-context.json` first.",
|
|
18
|
+
"Treat `task_prompt` as the user's produce-and-prove brief: source data, output shape, and evidence that should show the data is ready.",
|
|
18
19
|
`Then read \`workflow/README.md\`, \`workflow/workflow.json\`, and \`workflow/${CONTEXT_INTERFACE_FILE}\`.`,
|
|
19
20
|
"Review `artifacts/source-dataset/raw/` and any `artifacts/preview-compiled/` notes before editing the package.",
|
|
20
21
|
"Prefer direct file-reading and search tools over shell commands for routine file inspection.",
|
|
21
22
|
"Do not use shell helpers like `cat`, `sed`, `ls`, or `find` when a native read/search tool can inspect the same files.",
|
|
22
23
|
"Edit only files under `workflow/`.",
|
|
23
24
|
"Keep the workflow valid for the current compiler API and workflow schema.",
|
|
24
|
-
"
|
|
25
|
+
"When editing acceptance rules: `zone_counts_at_least` takes numeric fixed minimums; `zone_counts_at_least_counts` takes runtime count-key strings such as `source_total`, never numbers.",
|
|
26
|
+
"Make the package materially more specific to this dataset task, output shape, and proof requirement than the seeded base workflow. A no-op copy is not acceptable.",
|
|
25
27
|
"Treat the workflow package as four aligned layers: purpose, inputs, context interface, and stages.",
|
|
26
28
|
"Prefer explicit stage-doc, stage-policy, purpose, input-contract, and context-interface edits over vague rewrites.",
|
|
27
29
|
"Do not introduce wikilinks unless the workflow also creates the target note by exact basename or explicit relative path.",
|
|
@@ -37,13 +37,16 @@ export async function runWorkflowEditSession(options) {
|
|
|
37
37
|
const validation = options.validate(options.workflowPath);
|
|
38
38
|
if (!validation.ok) {
|
|
39
39
|
copyDirectory(options.shell.workflowBeforePath, options.workflowPath);
|
|
40
|
+
const details = validation.errors.length > 0
|
|
41
|
+
? `: ${validation.errors.slice(0, 6).join("; ")}`
|
|
42
|
+
: "";
|
|
40
43
|
return {
|
|
41
44
|
status: "invalid",
|
|
42
45
|
changed,
|
|
43
46
|
validation,
|
|
44
47
|
summary: changed
|
|
45
|
-
? `Workflow package failed validation: ${validation.summary}`
|
|
46
|
-
: `Workflow package is invalid without any workflow edits: ${validation.summary}`,
|
|
48
|
+
? `Workflow package failed validation: ${validation.summary}${details}`
|
|
49
|
+
: `Workflow package is invalid without any workflow edits: ${validation.summary}${details}`,
|
|
47
50
|
};
|
|
48
51
|
}
|
|
49
52
|
return {
|
|
@@ -13,7 +13,7 @@ export const ContextInterfaceSchema = WorkflowCompiledSchemaSchema;
|
|
|
13
13
|
export const ContextInterfaceZoneSchema = WorkflowCompiledZoneSchema;
|
|
14
14
|
export const ContextInterfaceZoneIdSchema = WorkflowZoneIdSchema;
|
|
15
15
|
export const ContextInterfaceZoneRoleSchema = WorkflowZoneRoleSchema;
|
|
16
|
-
// Package-owned input contract for authoring, review, and future
|
|
16
|
+
// Package-owned input contract for authoring, review, and future authoring flows.
|
|
17
17
|
// This does not change compiler execution semantics; it describes what data a
|
|
18
18
|
// workflow expects to organize before the compiler materializes the context
|
|
19
19
|
// interface on disk.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
2
3
|
import { testRootForCompiled, targetTestRunsRootForCompiled, targetTestSandboxesRootForCompiled, stageExecutionShellsRoot, compiledRuntimeRoot, } from "../compiler/compiled-paths.js";
|
|
3
4
|
export function resolveWorkflowImprovementReviewSourcePaths(compiledPath) {
|
|
4
5
|
const compiledRuntime = compiledRuntimeRoot(compiledPath);
|
|
@@ -8,7 +9,10 @@ export function resolveWorkflowImprovementReviewSourcePaths(compiledPath) {
|
|
|
8
9
|
const targetTestSandboxes = targetTestSandboxesRootForCompiled(compiledPath);
|
|
9
10
|
return {
|
|
10
11
|
compiledRuntime: existsSync(compiledRuntime) ? compiledRuntime : null,
|
|
11
|
-
testComparisons: existsSync(testComparisons)
|
|
12
|
+
testComparisons: existsSync(join(testComparisons, "latest.json")) ||
|
|
13
|
+
existsSync(join(testComparisons, "latest.md"))
|
|
14
|
+
? testComparisons
|
|
15
|
+
: null,
|
|
12
16
|
executionShells: existsSync(executionShells) ? executionShells : null,
|
|
13
17
|
targetTestRuns: existsSync(targetTestRuns) ? targetTestRuns : null,
|
|
14
18
|
targetTestSandboxes: existsSync(targetTestSandboxes) ? targetTestSandboxes : null,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interf/compiler",
|
|
3
|
-
"version": "0.7.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.7.3",
|
|
4
|
+
"description": "Interf prepares data for agent work. It runs locally, processes your files, shows evidence that your data is ready, and writes portable context: a local folder with verifiable outputs agents can use.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"interf": "dist/bin.js"
|
|
@@ -43,8 +43,6 @@
|
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc && chmod 755 dist/bin.js",
|
|
45
45
|
"dev": "tsc --watch",
|
|
46
|
-
"setup:local-skills": "bash scripts/setup-local-skills.sh",
|
|
47
|
-
"refresh:bootstrap-mirror": "node scripts/docs/sync-bootstrap-mirror.mjs",
|
|
48
46
|
"docs:sync-public-test-example": "npm run build && node scripts/docs/sync-public-test-example.mjs",
|
|
49
47
|
"test:matrix": "npm run build && node scripts/matrix/run.mjs",
|
|
50
48
|
"test:smoke": "npm run build && node --test test/**/*.test.mjs",
|