@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,4 +1,4 @@
|
|
|
1
|
-
import { appendFileSync,
|
|
1
|
+
import { appendFileSync, existsSync, mkdirSync, writeFileSync, } from "node:fs";
|
|
2
2
|
import { join, relative } from "node:path";
|
|
3
3
|
import { createWorkflowImprovementShell, freezeWorkflowImprovementShell, } from "./agent-shells.js";
|
|
4
4
|
import { readInterfConfig } from "./interf.js";
|
|
@@ -7,44 +7,9 @@ import { readJsonFileWithSchema } from "./parse.js";
|
|
|
7
7
|
import { saveCompiledInterfConfig } from "./source-config.js";
|
|
8
8
|
import { WorkflowImprovementRunLedgerSchema, } from "./schema.js";
|
|
9
9
|
import { resolveWorkflowImprovementReviewPaths } from "./workflow-review-paths.js";
|
|
10
|
+
import { runWorkflowEditSession } from "./workflow-edit-session.js";
|
|
10
11
|
import { targetTestRunsRootForCompiled, targetTestSandboxesRootForCompiled, workflowImprovementRunRoot, workflowPackagePathForCompiled, } from "./compiled-paths.js";
|
|
11
|
-
|
|
12
|
-
rmSync(targetPath, { recursive: true, force: true });
|
|
13
|
-
mkdirSync(targetPath, { recursive: true });
|
|
14
|
-
cpSync(sourcePath, targetPath, { recursive: true });
|
|
15
|
-
}
|
|
16
|
-
function listFileSnapshot(dirPath) {
|
|
17
|
-
const snapshot = new Map();
|
|
18
|
-
if (!existsSync(dirPath))
|
|
19
|
-
return snapshot;
|
|
20
|
-
const collect = (currentPath) => {
|
|
21
|
-
for (const entry of readdirSync(currentPath)) {
|
|
22
|
-
const fullPath = join(currentPath, entry);
|
|
23
|
-
const stat = statSync(fullPath);
|
|
24
|
-
if (stat.isDirectory()) {
|
|
25
|
-
collect(fullPath);
|
|
26
|
-
continue;
|
|
27
|
-
}
|
|
28
|
-
if (!stat.isFile())
|
|
29
|
-
continue;
|
|
30
|
-
snapshot.set(relative(dirPath, fullPath), readFileSync(fullPath, "utf8"));
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
collect(dirPath);
|
|
34
|
-
return snapshot;
|
|
35
|
-
}
|
|
36
|
-
function directoriesMatch(leftPath, rightPath) {
|
|
37
|
-
const left = listFileSnapshot(leftPath);
|
|
38
|
-
const right = listFileSnapshot(rightPath);
|
|
39
|
-
if (left.size !== right.size)
|
|
40
|
-
return false;
|
|
41
|
-
for (const [relativePath, content] of left.entries()) {
|
|
42
|
-
if (right.get(relativePath) !== content) {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
12
|
+
import { WORKFLOW_SCHEMA_FILE } from "./compiled-schema.js";
|
|
48
13
|
function toShellArtifactPath(absolutePath, sourceRoot, shellRoot) {
|
|
49
14
|
if (!absolutePath)
|
|
50
15
|
return null;
|
|
@@ -90,16 +55,18 @@ function buildLoopContext(options) {
|
|
|
90
55
|
}
|
|
91
56
|
function buildWorkflowImprovementPrompt() {
|
|
92
57
|
return [
|
|
93
|
-
"This is an automated Interf
|
|
58
|
+
"This is an automated Interf workflow-improvement run, not an open-ended chat session.",
|
|
94
59
|
"The user already invoked this through `interf compile` with self-improving loops enabled. Execute it now.",
|
|
95
60
|
"Read `runtime/loop-context.json` first.",
|
|
96
|
-
|
|
61
|
+
`Then read \`workflow/README.md\`, \`workflow/workflow.json\`, \`workflow/${WORKFLOW_SCHEMA_FILE}\`, and \`workflow/improve/SKILL.md\` if it exists.`,
|
|
97
62
|
"Review preserved evidence from earlier failures under `artifacts/` before you edit the workflow.",
|
|
98
63
|
"Treat `workflow/improve/SKILL.md` as guidance for how to improve the workflow, not as the default file to edit.",
|
|
99
64
|
"Prefer editing the stage docs, workflow contract, or schema ownership that actually change compiled outputs.",
|
|
100
65
|
"Edit only files under `workflow/`.",
|
|
101
66
|
"Do not edit truth checks, test specs, raw dataset files, or generated compiled outputs.",
|
|
102
|
-
"Keep the workflow valid for the current compiler API and
|
|
67
|
+
"Keep the workflow valid for the current compiler API and workflow schema.",
|
|
68
|
+
"Respect stage boundaries: a stage may only introduce links that resolve within that stage's declared writes or already-existing read zones.",
|
|
69
|
+
"Do not make one stage point at files or notes that are only created later by another stage.",
|
|
103
70
|
"Prefer small, defensible changes to workflow docs, stage docs, stage policies, or schema ownership over random churn.",
|
|
104
71
|
"Do not narrate plans or ask follow-up questions.",
|
|
105
72
|
"Only emit user-visible updates that begin with STATUS:, DONE:, BLOCKED:, or ERROR:.",
|
|
@@ -193,170 +160,14 @@ export async function runWorkflowImprovementLoop(options) {
|
|
|
193
160
|
context,
|
|
194
161
|
});
|
|
195
162
|
const workflowRoot = workflowPackagePathForCompiled(options.compiledPath);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
eventLogPath: shell.eventLogPath,
|
|
204
|
-
statusLogPath: shell.statusLogPath,
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
catch (error) {
|
|
208
|
-
executeError = error instanceof Error ? error.message : String(error);
|
|
209
|
-
}
|
|
210
|
-
copyDirectory(workflowRoot, shell.workflowAfterPath);
|
|
163
|
+
const session = await runWorkflowEditSession({
|
|
164
|
+
executor: options.executor,
|
|
165
|
+
workflowPath: workflowRoot,
|
|
166
|
+
shell,
|
|
167
|
+
prompt: buildWorkflowImprovementPrompt(),
|
|
168
|
+
validate: validateWorkflowPackage,
|
|
169
|
+
});
|
|
211
170
|
const preservedShellManifestPath = freezeWorkflowImprovementShell(shell.rootPath);
|
|
212
|
-
const changed = !directoriesMatch(shell.workflowBeforePath, shell.workflowAfterPath);
|
|
213
|
-
if (executeError) {
|
|
214
|
-
copyDirectory(shell.workflowBeforePath, workflowRoot);
|
|
215
|
-
const summary = `Workflow improver failed before completing: ${executeError}`;
|
|
216
|
-
writeWorkflowImprovementRunLedger(options.compiledPath, options.runId, buildWorkflowImprovementLoopRecord({
|
|
217
|
-
targetName: compiledName,
|
|
218
|
-
workflowId: options.workflowId,
|
|
219
|
-
runId: options.runId,
|
|
220
|
-
loopIndex: options.loopIndex,
|
|
221
|
-
shellPath: shell.rootPath,
|
|
222
|
-
loopRootPath: shell.loopRootPath,
|
|
223
|
-
workflowBeforePath: shell.workflowBeforePath,
|
|
224
|
-
workflowAfterPath: shell.workflowAfterPath,
|
|
225
|
-
promptLogPath: shell.promptLogPath,
|
|
226
|
-
eventLogPath: shell.eventLogPath,
|
|
227
|
-
statusLogPath: shell.statusLogPath,
|
|
228
|
-
preservedShellManifestPath,
|
|
229
|
-
changed,
|
|
230
|
-
validation: null,
|
|
231
|
-
result: "executor-failed",
|
|
232
|
-
summary,
|
|
233
|
-
}), {
|
|
234
|
-
targetName: compiledName,
|
|
235
|
-
workflowId: options.workflowId,
|
|
236
|
-
maxLoops: options.maxLoops,
|
|
237
|
-
maxAttempts: options.maxAttempts,
|
|
238
|
-
});
|
|
239
|
-
return {
|
|
240
|
-
status: "executor-failed",
|
|
241
|
-
changed,
|
|
242
|
-
validation: null,
|
|
243
|
-
summary,
|
|
244
|
-
shellPath: shell.rootPath,
|
|
245
|
-
loopRootPath: shell.loopRootPath,
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
if (code !== 0) {
|
|
249
|
-
copyDirectory(shell.workflowBeforePath, workflowRoot);
|
|
250
|
-
const summary = `Workflow improver exited with code ${code}.`;
|
|
251
|
-
writeWorkflowImprovementRunLedger(options.compiledPath, options.runId, buildWorkflowImprovementLoopRecord({
|
|
252
|
-
targetName: compiledName,
|
|
253
|
-
workflowId: options.workflowId,
|
|
254
|
-
runId: options.runId,
|
|
255
|
-
loopIndex: options.loopIndex,
|
|
256
|
-
shellPath: shell.rootPath,
|
|
257
|
-
loopRootPath: shell.loopRootPath,
|
|
258
|
-
workflowBeforePath: shell.workflowBeforePath,
|
|
259
|
-
workflowAfterPath: shell.workflowAfterPath,
|
|
260
|
-
promptLogPath: shell.promptLogPath,
|
|
261
|
-
eventLogPath: shell.eventLogPath,
|
|
262
|
-
statusLogPath: shell.statusLogPath,
|
|
263
|
-
preservedShellManifestPath,
|
|
264
|
-
changed,
|
|
265
|
-
validation: null,
|
|
266
|
-
result: "executor-failed",
|
|
267
|
-
summary,
|
|
268
|
-
}), {
|
|
269
|
-
targetName: compiledName,
|
|
270
|
-
workflowId: options.workflowId,
|
|
271
|
-
maxLoops: options.maxLoops,
|
|
272
|
-
maxAttempts: options.maxAttempts,
|
|
273
|
-
});
|
|
274
|
-
return {
|
|
275
|
-
status: "executor-failed",
|
|
276
|
-
changed,
|
|
277
|
-
validation: null,
|
|
278
|
-
summary,
|
|
279
|
-
shellPath: shell.rootPath,
|
|
280
|
-
loopRootPath: shell.loopRootPath,
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
if (!changed) {
|
|
284
|
-
const validation = validateWorkflowPackage(workflowRoot);
|
|
285
|
-
const result = validation.ok ? "no-change" : "invalid";
|
|
286
|
-
if (!validation.ok) {
|
|
287
|
-
copyDirectory(shell.workflowBeforePath, workflowRoot);
|
|
288
|
-
}
|
|
289
|
-
const summary = validation.ok
|
|
290
|
-
? "Workflow improver made no workflow edits."
|
|
291
|
-
: `Workflow variation is invalid without any workflow edits: ${validation.summary}`;
|
|
292
|
-
writeWorkflowImprovementRunLedger(options.compiledPath, options.runId, buildWorkflowImprovementLoopRecord({
|
|
293
|
-
targetName: compiledName,
|
|
294
|
-
workflowId: options.workflowId,
|
|
295
|
-
runId: options.runId,
|
|
296
|
-
loopIndex: options.loopIndex,
|
|
297
|
-
shellPath: shell.rootPath,
|
|
298
|
-
loopRootPath: shell.loopRootPath,
|
|
299
|
-
workflowBeforePath: shell.workflowBeforePath,
|
|
300
|
-
workflowAfterPath: shell.workflowAfterPath,
|
|
301
|
-
promptLogPath: shell.promptLogPath,
|
|
302
|
-
eventLogPath: shell.eventLogPath,
|
|
303
|
-
statusLogPath: shell.statusLogPath,
|
|
304
|
-
preservedShellManifestPath,
|
|
305
|
-
changed: false,
|
|
306
|
-
validation,
|
|
307
|
-
result,
|
|
308
|
-
summary,
|
|
309
|
-
}), {
|
|
310
|
-
targetName: compiledName,
|
|
311
|
-
workflowId: options.workflowId,
|
|
312
|
-
maxLoops: options.maxLoops,
|
|
313
|
-
maxAttempts: options.maxAttempts,
|
|
314
|
-
});
|
|
315
|
-
return {
|
|
316
|
-
status: result,
|
|
317
|
-
changed: false,
|
|
318
|
-
validation,
|
|
319
|
-
summary,
|
|
320
|
-
shellPath: shell.rootPath,
|
|
321
|
-
loopRootPath: shell.loopRootPath,
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
const validation = validateWorkflowPackage(workflowRoot);
|
|
325
|
-
if (!validation.ok) {
|
|
326
|
-
copyDirectory(shell.workflowBeforePath, workflowRoot);
|
|
327
|
-
const summary = `Workflow variation failed validation: ${validation.summary}`;
|
|
328
|
-
writeWorkflowImprovementRunLedger(options.compiledPath, options.runId, buildWorkflowImprovementLoopRecord({
|
|
329
|
-
targetName: compiledName,
|
|
330
|
-
workflowId: options.workflowId,
|
|
331
|
-
runId: options.runId,
|
|
332
|
-
loopIndex: options.loopIndex,
|
|
333
|
-
shellPath: shell.rootPath,
|
|
334
|
-
loopRootPath: shell.loopRootPath,
|
|
335
|
-
workflowBeforePath: shell.workflowBeforePath,
|
|
336
|
-
workflowAfterPath: shell.workflowAfterPath,
|
|
337
|
-
promptLogPath: shell.promptLogPath,
|
|
338
|
-
eventLogPath: shell.eventLogPath,
|
|
339
|
-
statusLogPath: shell.statusLogPath,
|
|
340
|
-
preservedShellManifestPath,
|
|
341
|
-
changed: true,
|
|
342
|
-
validation,
|
|
343
|
-
result: "invalid",
|
|
344
|
-
summary,
|
|
345
|
-
}), {
|
|
346
|
-
targetName: compiledName,
|
|
347
|
-
workflowId: options.workflowId,
|
|
348
|
-
maxLoops: options.maxLoops,
|
|
349
|
-
maxAttempts: options.maxAttempts,
|
|
350
|
-
});
|
|
351
|
-
return {
|
|
352
|
-
status: "invalid",
|
|
353
|
-
changed: true,
|
|
354
|
-
validation,
|
|
355
|
-
summary,
|
|
356
|
-
shellPath: shell.rootPath,
|
|
357
|
-
loopRootPath: shell.loopRootPath,
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
171
|
writeWorkflowImprovementRunLedger(options.compiledPath, options.runId, buildWorkflowImprovementLoopRecord({
|
|
361
172
|
targetName: compiledName,
|
|
362
173
|
workflowId: options.workflowId,
|
|
@@ -370,26 +181,28 @@ export async function runWorkflowImprovementLoop(options) {
|
|
|
370
181
|
eventLogPath: shell.eventLogPath,
|
|
371
182
|
statusLogPath: shell.statusLogPath,
|
|
372
183
|
preservedShellManifestPath,
|
|
373
|
-
changed:
|
|
374
|
-
validation,
|
|
375
|
-
result:
|
|
376
|
-
summary:
|
|
184
|
+
changed: session.changed,
|
|
185
|
+
validation: session.validation,
|
|
186
|
+
result: session.status,
|
|
187
|
+
summary: session.summary,
|
|
377
188
|
}), {
|
|
378
189
|
targetName: compiledName,
|
|
379
190
|
workflowId: options.workflowId,
|
|
380
191
|
maxLoops: options.maxLoops,
|
|
381
192
|
maxAttempts: options.maxAttempts,
|
|
382
193
|
});
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
194
|
+
if (session.status === "updated") {
|
|
195
|
+
updateCompiledWorkflowOrigin({
|
|
196
|
+
compiledPath: options.compiledPath,
|
|
197
|
+
selectedWorkflowId: options.workflowId,
|
|
198
|
+
localDraft: true,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
388
201
|
return {
|
|
389
|
-
status:
|
|
390
|
-
changed:
|
|
391
|
-
validation,
|
|
392
|
-
summary:
|
|
202
|
+
status: session.status,
|
|
203
|
+
changed: session.changed,
|
|
204
|
+
validation: session.validation,
|
|
205
|
+
summary: session.summary,
|
|
393
206
|
shellPath: shell.rootPath,
|
|
394
207
|
loopRootPath: shell.loopRootPath,
|
|
395
208
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export interface StagePolicyStageLike {
|
|
2
|
+
id: string;
|
|
3
|
+
}
|
|
4
|
+
export declare function normalizeStagePolicyNotes(value: unknown): Record<string, string[]> | undefined;
|
|
5
|
+
export declare function mergeStagePolicyNotesForStages(stages: readonly StagePolicyStageLike[], baseNotes: unknown, overrideNotes: Record<string, string[]> | undefined): Record<string, string[]> | undefined;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function normalizeStagePolicyNotes(value) {
|
|
2
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
3
|
+
return undefined;
|
|
4
|
+
const normalized = {};
|
|
5
|
+
for (const [stageId, notes] of Object.entries(value)) {
|
|
6
|
+
if (!Array.isArray(notes))
|
|
7
|
+
continue;
|
|
8
|
+
const cleaned = Array.from(new Set(notes
|
|
9
|
+
.filter((note) => typeof note === "string")
|
|
10
|
+
.map((note) => note.trim())
|
|
11
|
+
.filter((note) => note.length > 0)));
|
|
12
|
+
if (cleaned.length > 0) {
|
|
13
|
+
normalized[stageId] = cleaned;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return Object.keys(normalized).length > 0 ? normalized : undefined;
|
|
17
|
+
}
|
|
18
|
+
export function mergeStagePolicyNotesForStages(stages, baseNotes, overrideNotes) {
|
|
19
|
+
const normalizedBase = normalizeStagePolicyNotes(baseNotes);
|
|
20
|
+
const merged = {};
|
|
21
|
+
for (const stage of stages) {
|
|
22
|
+
const combined = Array.from(new Set([
|
|
23
|
+
...(normalizedBase?.[stage.id] ?? []),
|
|
24
|
+
...((overrideNotes?.[stage.id] ?? []).map((note) => note.trim()).filter((note) => note.length > 0)),
|
|
25
|
+
]));
|
|
26
|
+
if (combined.length > 0) {
|
|
27
|
+
merged[stage.id] = combined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
31
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interf/compiler",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Interf
|
|
3
|
+
"version": "0.6.1",
|
|
4
|
+
"description": "Interf helps make data ready for agent work. Measure raw files first, then prepare a compiled dataset when you need it.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"interf": "dist/bin.js"
|
|
@@ -37,13 +37,14 @@
|
|
|
37
37
|
"test:internal:cbre:max:keep": "npm run test:matrix -- --matrix internal/test-matrices/cbre-chart-tier1-max.json --keep-project-clones",
|
|
38
38
|
"test:full": "npm test && npm run test:e2e:quick:matrix",
|
|
39
39
|
"test:release:matrix": "npm run test:internal:cbre:max",
|
|
40
|
-
"test:release": "npm test && npm run test:acceptance-live -- --agent claude-code --with-test && npm run test:acceptance-live -- --agent codex --with-test",
|
|
40
|
+
"test:release": "npm test && npm run test:acceptance-quick:workflow-authoring -- --agent claude-code && npm run test:acceptance-live -- --agent claude-code --with-test && npm run test:acceptance-quick:workflow-authoring -- --agent codex && npm run test:acceptance-live -- --agent codex --with-test",
|
|
41
41
|
"test:acceptance-live": "npm run build && node scripts/acceptance-live.mjs",
|
|
42
42
|
"test:acceptance-cache:refresh": "npm run test:acceptance-cache:refresh:claude && npm run test:acceptance-cache:refresh:codex",
|
|
43
43
|
"test:acceptance-cache:refresh:claude": "node scripts/acceptance-cache-refresh.mjs --agent claude-code",
|
|
44
44
|
"test:acceptance-cache:refresh:codex": "node scripts/acceptance-cache-refresh.mjs --agent codex",
|
|
45
45
|
"test:acceptance-quick:create-compiled": "npm run build && node scripts/acceptance-targeted.mjs create-compiled",
|
|
46
46
|
"test:acceptance-quick:compiled-query": "npm run build && node scripts/acceptance-targeted.mjs compiled-query",
|
|
47
|
+
"test:acceptance-quick:workflow-authoring": "npm run build && node scripts/acceptance-targeted.mjs workflow-authoring",
|
|
47
48
|
"test:acceptance-quick:self-improving": "npm run build && node scripts/acceptance-targeted.mjs self-improving-compile",
|
|
48
49
|
"prepublishOnly": "node scripts/prepublish-gate.mjs"
|
|
49
50
|
},
|
|
@@ -59,8 +60,6 @@
|
|
|
59
60
|
"interf",
|
|
60
61
|
"ai",
|
|
61
62
|
"agent",
|
|
62
|
-
"knowledge",
|
|
63
|
-
"obsidian",
|
|
64
63
|
"coding-agent",
|
|
65
64
|
"claude",
|
|
66
65
|
"codex"
|
package/dist/lib/obsidian.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function writeObsidianDefaults(dirPath: string, type: "compiled"): void;
|
package/dist/lib/obsidian.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { mkdirSync, writeFileSync, } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
export function writeObsidianDefaults(dirPath, type) {
|
|
4
|
-
const obsidianDir = join(dirPath, ".obsidian");
|
|
5
|
-
mkdirSync(obsidianDir, { recursive: true });
|
|
6
|
-
const graphSettings = {
|
|
7
|
-
"collapse-filter": true,
|
|
8
|
-
search: 'path:"summaries" OR path:"knowledge" OR path:"home"',
|
|
9
|
-
showTags: false,
|
|
10
|
-
showAttachments: false,
|
|
11
|
-
hideUnresolved: true,
|
|
12
|
-
showOrphans: false,
|
|
13
|
-
};
|
|
14
|
-
writeFileSync(join(obsidianDir, "graph.json"), JSON.stringify(graphSettings, null, 2) + "\n");
|
|
15
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export interface SummarizeTarget {
|
|
2
|
-
source: string;
|
|
3
|
-
summary: string | null;
|
|
4
|
-
output: string;
|
|
5
|
-
reason: "pending" | "missing_synth" | "changed" | "full_pass";
|
|
6
|
-
}
|
|
7
|
-
export interface SummarizePlan {
|
|
8
|
-
generatedAt: string;
|
|
9
|
-
sourceCount: number;
|
|
10
|
-
summaryCount: number;
|
|
11
|
-
pendingCount: number;
|
|
12
|
-
targetCount: number;
|
|
13
|
-
targets: SummarizeTarget[];
|
|
14
|
-
}
|
|
15
|
-
export declare const SUMMARIZE_PLAN_RELATIVE_PATH: string;
|
|
16
|
-
export declare function buildSummarizePlan(sourcePath: string, compiledPath: string, mode?: "pending" | "all"): SummarizePlan;
|
|
17
|
-
export declare function writeSummarizePlan(compiledPath: string, plan: SummarizePlan): string;
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join, relative } from "node:path";
|
|
3
|
-
import { listFilesRecursive } from "./filesystem.js";
|
|
4
|
-
import { builtinCompiledZoneRelativePath, compiledSummariesPath, BUILTIN_COMPILED_ZONE_IDS, } from "./compiled-schema.js";
|
|
5
|
-
import { discoverSourceFiles } from "./discovery.js";
|
|
6
|
-
import { loadState } from "./state.js";
|
|
7
|
-
import { parseJsonFrontmatter } from "./parse.js";
|
|
8
|
-
import { compiledRuntimeRoot } from "./compiled-paths.js";
|
|
9
|
-
export const SUMMARIZE_PLAN_RELATIVE_PATH = join(".interf", "runtime", "summarize-targets.json");
|
|
10
|
-
export function buildSummarizePlan(sourcePath, compiledPath, mode = "pending") {
|
|
11
|
-
const discovery = discoverSourceFiles(sourcePath, compiledPath);
|
|
12
|
-
const sourceFiles = discovery.sourceFiles;
|
|
13
|
-
const summariesDir = compiledSummariesPath(compiledPath);
|
|
14
|
-
const summaryFiles = listSummaryFiles(summariesDir, compiledPath);
|
|
15
|
-
const state = loadState(compiledPath);
|
|
16
|
-
const pending = new Set((state?.pending ?? []).filter((value) => typeof value === "string" && sourceFiles.includes(value)));
|
|
17
|
-
const summaryIndex = new Map();
|
|
18
|
-
for (const summary of summaryFiles) {
|
|
19
|
-
const source = readSourceReference(join(compiledPath, summary));
|
|
20
|
-
if (source)
|
|
21
|
-
summaryIndex.set(source, summary);
|
|
22
|
-
}
|
|
23
|
-
const targets = new Map();
|
|
24
|
-
if (mode === "all") {
|
|
25
|
-
for (const src of sourceFiles) {
|
|
26
|
-
targets.set(src, {
|
|
27
|
-
source: src,
|
|
28
|
-
summary: summaryIndex.get(src) ?? null,
|
|
29
|
-
output: defaultSummaryPath(src),
|
|
30
|
-
reason: "full_pass",
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
return {
|
|
34
|
-
generatedAt: new Date().toISOString(),
|
|
35
|
-
sourceCount: sourceFiles.length,
|
|
36
|
-
summaryCount: summaryFiles.length,
|
|
37
|
-
pendingCount: pending.size,
|
|
38
|
-
targetCount: targets.size,
|
|
39
|
-
targets: Array.from(targets.values()).sort((a, b) => a.source.localeCompare(b.source)),
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
for (const src of pending) {
|
|
43
|
-
targets.set(src, {
|
|
44
|
-
source: src,
|
|
45
|
-
summary: summaryIndex.get(src) ?? null,
|
|
46
|
-
output: defaultSummaryPath(src),
|
|
47
|
-
reason: "pending",
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
for (const src of sourceFiles) {
|
|
51
|
-
if (summaryIndex.has(src))
|
|
52
|
-
continue;
|
|
53
|
-
if (targets.has(src))
|
|
54
|
-
continue;
|
|
55
|
-
targets.set(src, {
|
|
56
|
-
source: src,
|
|
57
|
-
summary: null,
|
|
58
|
-
output: defaultSummaryPath(src),
|
|
59
|
-
reason: "missing_synth",
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
// Detect changed source files (source newer than its summary)
|
|
63
|
-
for (const [src, summary] of summaryIndex) {
|
|
64
|
-
if (targets.has(src))
|
|
65
|
-
continue;
|
|
66
|
-
const sourceFile = join(sourcePath, src);
|
|
67
|
-
const synthFile = join(compiledPath, summary);
|
|
68
|
-
if (!existsSync(sourceFile) || !existsSync(synthFile))
|
|
69
|
-
continue;
|
|
70
|
-
try {
|
|
71
|
-
const sourceMtime = statSync(sourceFile).mtimeMs;
|
|
72
|
-
const synthMtime = statSync(synthFile).mtimeMs;
|
|
73
|
-
if (sourceMtime > synthMtime) {
|
|
74
|
-
targets.set(src, {
|
|
75
|
-
source: src,
|
|
76
|
-
summary,
|
|
77
|
-
output: defaultSummaryPath(src),
|
|
78
|
-
reason: "changed",
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return {
|
|
87
|
-
generatedAt: new Date().toISOString(),
|
|
88
|
-
sourceCount: sourceFiles.length,
|
|
89
|
-
summaryCount: summaryFiles.length,
|
|
90
|
-
pendingCount: pending.size,
|
|
91
|
-
targetCount: targets.size,
|
|
92
|
-
targets: Array.from(targets.values()).sort((a, b) => a.source.localeCompare(b.source)),
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
export function writeSummarizePlan(compiledPath, plan) {
|
|
96
|
-
const planPath = join(compiledPath, SUMMARIZE_PLAN_RELATIVE_PATH);
|
|
97
|
-
mkdirSync(compiledRuntimeRoot(compiledPath), { recursive: true });
|
|
98
|
-
writeFileSync(planPath, JSON.stringify(plan, null, 2) + "\n");
|
|
99
|
-
return planPath;
|
|
100
|
-
}
|
|
101
|
-
function listSummaryFiles(summariesDir, compiledPath) {
|
|
102
|
-
return listFilesRecursive(summariesDir, (filePath) => filePath.endsWith(".md")).map((filePath) => relative(compiledPath, filePath));
|
|
103
|
-
}
|
|
104
|
-
function readSourceReference(synthPath) {
|
|
105
|
-
if (!existsSync(synthPath))
|
|
106
|
-
return null;
|
|
107
|
-
const content = readFileSync(synthPath, "utf-8");
|
|
108
|
-
const parsed = parseJsonFrontmatter(content);
|
|
109
|
-
const source = typeof parsed?.frontmatter.source === "string"
|
|
110
|
-
? parsed.frontmatter.source
|
|
111
|
-
: null;
|
|
112
|
-
return source?.trim() ?? null;
|
|
113
|
-
}
|
|
114
|
-
function defaultSummaryPath(sourcePath) {
|
|
115
|
-
const summariesRoot = builtinCompiledZoneRelativePath(BUILTIN_COMPILED_ZONE_IDS.SUMMARIES);
|
|
116
|
-
if (sourcePath.endsWith(".md"))
|
|
117
|
-
return `${summariesRoot}/${sourcePath}`;
|
|
118
|
-
const replaced = sourcePath.replace(/\.[^.]+$/, ".md");
|
|
119
|
-
return `${summariesRoot}/${replaced === sourcePath ? `${sourcePath}.md` : replaced}`;
|
|
120
|
-
}
|