@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.
Files changed (93) hide show
  1. package/README.md +126 -187
  2. package/builtin-workflows/interf/README.md +22 -10
  3. package/builtin-workflows/interf/compile/stages/shape/SKILL.md +6 -3
  4. package/builtin-workflows/interf/compile/stages/structure/SKILL.md +3 -0
  5. package/builtin-workflows/interf/compile/stages/summarize/SKILL.md +18 -2
  6. package/builtin-workflows/interf/improve/SKILL.md +2 -2
  7. package/builtin-workflows/interf/workflow.json +18 -4
  8. package/builtin-workflows/interf/{compiled.schema.json → workflow.schema.json} +9 -2
  9. package/dist/commands/check-draft.js +3 -3
  10. package/dist/commands/compile-controller.js +6 -13
  11. package/dist/commands/compile.d.ts +19 -1
  12. package/dist/commands/compile.js +98 -28
  13. package/dist/commands/create-workflow-wizard.d.ts +20 -2
  14. package/dist/commands/create-workflow-wizard.js +163 -27
  15. package/dist/commands/create.d.ts +1 -1
  16. package/dist/commands/create.js +67 -60
  17. package/dist/commands/dataset-selection.d.ts +6 -0
  18. package/dist/commands/dataset-selection.js +11 -0
  19. package/dist/commands/default.js +3 -3
  20. package/dist/commands/doctor.js +8 -8
  21. package/dist/commands/executor-flow.d.ts +1 -1
  22. package/dist/commands/executor-flow.js +5 -2
  23. package/dist/commands/init.d.ts +5 -0
  24. package/dist/commands/init.js +56 -48
  25. package/dist/commands/list.js +6 -3
  26. package/dist/commands/reset.js +1 -1
  27. package/dist/commands/source-config-wizard.d.ts +2 -2
  28. package/dist/commands/source-config-wizard.js +50 -17
  29. package/dist/commands/test.d.ts +0 -6
  30. package/dist/commands/test.js +9 -17
  31. package/dist/index.d.ts +1 -1
  32. package/dist/index.js +1 -1
  33. package/dist/lib/agent-args.d.ts +1 -0
  34. package/dist/lib/agent-args.js +10 -0
  35. package/dist/lib/agent-execution.js +2 -1
  36. package/dist/lib/agent-preflight.js +2 -1
  37. package/dist/lib/agent-shells.d.ts +26 -1
  38. package/dist/lib/agent-shells.js +213 -39
  39. package/dist/lib/agents.d.ts +1 -1
  40. package/dist/lib/agents.js +1 -1
  41. package/dist/lib/builtin-compiled-workflow.d.ts +6 -97
  42. package/dist/lib/builtin-compiled-workflow.js +66 -125
  43. package/dist/lib/compiled-compile.d.ts +0 -4
  44. package/dist/lib/compiled-compile.js +9 -28
  45. package/dist/lib/compiled-paths.d.ts +1 -0
  46. package/dist/lib/compiled-paths.js +3 -0
  47. package/dist/lib/compiled-reset.d.ts +1 -0
  48. package/dist/lib/compiled-reset.js +42 -14
  49. package/dist/lib/compiled-schema.d.ts +9 -5
  50. package/dist/lib/compiled-schema.js +45 -14
  51. package/dist/lib/discovery.d.ts +1 -1
  52. package/dist/lib/discovery.js +2 -2
  53. package/dist/lib/executors.d.ts +1 -1
  54. package/dist/lib/executors.js +2 -2
  55. package/dist/lib/interf-scaffold.js +4 -11
  56. package/dist/lib/interf-workflow-package.d.ts +8 -3
  57. package/dist/lib/interf-workflow-package.js +128 -62
  58. package/dist/lib/local-workflows.d.ts +4 -3
  59. package/dist/lib/local-workflows.js +126 -103
  60. package/dist/lib/runtime-acceptance.js +15 -3
  61. package/dist/lib/runtime-contracts.js +3 -2
  62. package/dist/lib/runtime-paths.d.ts +1 -0
  63. package/dist/lib/runtime-paths.js +4 -1
  64. package/dist/lib/runtime-prompt.js +3 -1
  65. package/dist/lib/runtime-reconcile.js +88 -51
  66. package/dist/lib/runtime-runs.js +27 -15
  67. package/dist/lib/runtime.d.ts +1 -1
  68. package/dist/lib/runtime.js +1 -1
  69. package/dist/lib/schema.d.ts +71 -14
  70. package/dist/lib/schema.js +15 -12
  71. package/dist/lib/state-view.js +6 -6
  72. package/dist/lib/state.d.ts +1 -0
  73. package/dist/lib/state.js +7 -0
  74. package/dist/lib/test-execution.js +2 -2
  75. package/dist/lib/validate-compiled.js +9 -6
  76. package/dist/lib/validate.d.ts +3 -1
  77. package/dist/lib/validate.js +4 -11
  78. package/dist/lib/workflow-authoring.d.ts +26 -0
  79. package/dist/lib/workflow-authoring.js +119 -0
  80. package/dist/lib/workflow-definitions.d.ts +11 -1
  81. package/dist/lib/workflow-definitions.js +12 -15
  82. package/dist/lib/workflow-edit-session.d.ts +16 -0
  83. package/dist/lib/workflow-edit-session.js +57 -0
  84. package/dist/lib/workflow-edit-utils.d.ts +10 -0
  85. package/dist/lib/workflow-edit-utils.js +39 -0
  86. package/dist/lib/workflow-improvement.js +30 -217
  87. package/dist/lib/workflow-stage-policy.d.ts +5 -0
  88. package/dist/lib/workflow-stage-policy.js +31 -0
  89. package/package.json +4 -5
  90. package/dist/lib/obsidian.d.ts +0 -1
  91. package/dist/lib/obsidian.js +0 -15
  92. package/dist/lib/summarize-plan.d.ts +0 -17
  93. package/dist/lib/summarize-plan.js +0 -120
@@ -1,5 +1,5 @@
1
1
  import { existsSync, readFileSync, statSync, writeFileSync, } from "node:fs";
2
- import { join, relative } from "node:path";
2
+ import { extname, join, relative } from "node:path";
3
3
  import { listFilesRecursive } from "./filesystem.js";
4
4
  import { compiledZoneAbsolutePath, findCompiledSchemaZone, readCompiledSchemaFile, } from "./compiled-schema.js";
5
5
  import { parseJsonFrontmatter } from "./parse.js";
@@ -51,59 +51,99 @@ function summaryAbstract(content) {
51
51
  return null;
52
52
  return extractSynthAbstract(parsed.frontmatter, parsed.body);
53
53
  }
54
+ function listZoneArtifacts(dirPath, zone) {
55
+ const absolutePath = compiledZoneAbsolutePath(dirPath, zone);
56
+ if (!existsSync(absolutePath) || zone.kind === "runtime")
57
+ return [];
58
+ if (zone.kind === "file") {
59
+ try {
60
+ return statSync(absolutePath).isFile() ? [absolutePath] : [];
61
+ }
62
+ catch {
63
+ return [];
64
+ }
65
+ }
66
+ return listFilesRecursive(absolutePath);
67
+ }
68
+ function buildInventoryMetadata(options) {
69
+ const metadata = {
70
+ zone_id: options.zoneId,
71
+ zone_kind: options.zoneKind,
72
+ file_extension: extname(options.filePath).toLowerCase() || null,
73
+ };
74
+ if (!options.parsedFrontmatter) {
75
+ return metadata;
76
+ }
77
+ metadata.frontmatter_scanned = true;
78
+ const abstract = summaryAbstract(readFileSync(options.filePath, "utf8"));
79
+ if (abstract) {
80
+ metadata.abstract = abstract;
81
+ metadata.abstract_read = true;
82
+ }
83
+ const frontmatter = options.parsedFrontmatter.frontmatter;
84
+ if (typeof frontmatter.source_kind === "string") {
85
+ metadata.source_kind = frontmatter.source_kind;
86
+ }
87
+ if (typeof frontmatter.evidence_tier === "string") {
88
+ metadata.evidence_tier = frontmatter.evidence_tier;
89
+ }
90
+ if (typeof frontmatter.truth_mode === "string") {
91
+ metadata.truth_mode = frontmatter.truth_mode;
92
+ }
93
+ return metadata;
94
+ }
54
95
  function buildStageInventoryEntries(dirPath, stage) {
55
96
  const schema = readCompiledSchemaFile(join(dirPath, ".interf", "workflow"));
56
97
  if (!schema)
57
98
  return [];
58
- const inputZone = stage.reads
99
+ const readableInputZones = stage.reads
59
100
  .map((zoneId) => findCompiledSchemaZone(schema, zoneId))
60
- .find((zone) => zone && zone.kind !== "runtime");
61
- const outputZone = stage.writes
101
+ .filter((zone) => zone !== null && zone.kind !== "runtime");
102
+ const outputZones = stage.writes
62
103
  .map((zoneId) => findCompiledSchemaZone(schema, zoneId))
63
- .find((zone) => zone && zone.kind !== "runtime");
64
- if (!inputZone || !outputZone)
104
+ .filter((zone) => zone !== null && zone.kind !== "runtime");
105
+ if (outputZones.length === 0)
65
106
  return [];
66
- const outputRoot = compiledZoneAbsolutePath(dirPath, outputZone);
67
- if (!existsSync(outputRoot))
68
- return [];
69
- return listFilesRecursive(outputRoot, isOutputMarkdownFile)
70
- .map((filePath) => {
71
- const content = readFileSync(filePath, "utf8");
72
- const parsed = parseJsonFrontmatter(content);
73
- if (!parsed)
74
- return null;
75
- const inputPath = typeof parsed.frontmatter.source === "string"
76
- ? parsed.frontmatter.source.trim()
77
- : "";
78
- if (inputPath.length === 0)
79
- return null;
80
- const abstract = summaryAbstract(content);
81
- return {
82
- input_zone: inputZone.id,
83
- input_path: inputPath,
84
- output_zone: outputZone.id,
85
- output_path: relative(dirPath, filePath).replaceAll("\\", "/"),
86
- state: typeof parsed.frontmatter.state === "string"
87
- ? parsed.frontmatter.state
88
- : "complete",
89
- metadata: {
90
- source_kind: typeof parsed.frontmatter.source_kind === "string"
91
- ? parsed.frontmatter.source_kind
92
- : "unknown",
93
- evidence_tier: typeof parsed.frontmatter.evidence_tier === "string"
94
- ? parsed.frontmatter.evidence_tier
95
- : "primary",
96
- truth_mode: typeof parsed.frontmatter.truth_mode === "string"
97
- ? parsed.frontmatter.truth_mode
98
- : "reported-data",
99
- abstract,
100
- frontmatter_scanned: true,
101
- abstract_read: Boolean(abstract),
102
- },
103
- };
104
- })
105
- .filter((entry) => entry !== null)
106
- .sort((left, right) => left.input_path.localeCompare(right.input_path));
107
+ const entries = [];
108
+ for (const outputZone of outputZones) {
109
+ for (const filePath of listZoneArtifacts(dirPath, outputZone)) {
110
+ const relativeOutputPath = relative(dirPath, filePath).replaceAll("\\", "/");
111
+ const parsed = isOutputMarkdownFile(filePath)
112
+ ? parseJsonFrontmatter(readFileSync(filePath, "utf8"))
113
+ : null;
114
+ const sourcePath = typeof parsed?.frontmatter.source === "string"
115
+ ? parsed.frontmatter.source.trim()
116
+ : "";
117
+ const sourceZoneId = typeof parsed?.frontmatter.source_zone === "string"
118
+ ? parsed.frontmatter.source_zone.trim()
119
+ : "";
120
+ const inputZone = sourceZoneId.length > 0
121
+ ? readableInputZones.find((zone) => zone.id === sourceZoneId) ?? null
122
+ : readableInputZones.length === 1
123
+ ? readableInputZones[0]
124
+ : null;
125
+ entries.push({
126
+ ...(inputZone && sourcePath.length > 0
127
+ ? {
128
+ input_zone: inputZone.id,
129
+ input_path: sourcePath,
130
+ }
131
+ : {}),
132
+ output_zone: outputZone.id,
133
+ output_path: relativeOutputPath,
134
+ ...(typeof parsed?.frontmatter.state === "string"
135
+ ? { state: parsed.frontmatter.state }
136
+ : {}),
137
+ metadata: buildInventoryMetadata({
138
+ zoneId: outputZone.id,
139
+ zoneKind: outputZone.kind,
140
+ filePath,
141
+ parsedFrontmatter: parsed,
142
+ }),
143
+ });
144
+ }
145
+ }
146
+ return entries.sort((left, right) => `${left.output_zone}:${left.output_path}`.localeCompare(`${right.output_zone}:${right.output_path}`));
107
147
  }
108
148
  function writeStageInventory(dirPath, stageId, entries) {
109
149
  writeFileSync(join(compiledRuntimeRoot(dirPath), "inventory.json"), JSON.stringify(compiledInventoryFromEntries(entries, stageId), null, 2) + "\n");
@@ -126,10 +166,7 @@ export function reconcileCompiledStageRun(dirPath, stage) {
126
166
  if (!writeZones.some((zone) => anyPathUpdatedSince(compiledZoneAbsolutePath(dirPath, zone), startedAtMs))) {
127
167
  return false;
128
168
  }
129
- const inventoryEntries = buildStageInventoryEntries(dirPath, stage);
130
- if (inventoryEntries.length > 0) {
131
- writeStageInventory(dirPath, stage.id, inventoryEntries);
132
- }
169
+ writeStageInventory(dirPath, stage.id, buildStageInventoryEntries(dirPath, stage));
133
170
  const currentState = {
134
171
  ...initCompiledState(),
135
172
  ...(loadState(dirPath) ?? {}),
@@ -5,7 +5,7 @@ import { countFilesRecursive } from "./filesystem.js";
5
5
  import { buildRuntimeExecutorInfo } from "./executors.js";
6
6
  import { RuntimeRunSchema, } from "./schema.js";
7
7
  import { getWorkflowStageDefinition, getWorkflowStagePosition, getWorkflowStages, } from "./workflow-definitions.js";
8
- import { eventLogPath, logsDirPath, promptLogPath, runHistoryPath, runPath, stageContractPath, statusLogPath, } from "./runtime-paths.js";
8
+ import { archivedStageContractPath, eventLogPath, logsDirPath, promptLogPath, runHistoryPath, runPath, stageContractPath, statusLogPath, } from "./runtime-paths.js";
9
9
  import { warnInterf } from "./logger.js";
10
10
  export function loadRuntimeRun(dirPath) {
11
11
  const path = runPath(dirPath);
@@ -34,28 +34,34 @@ export function writeStageContract(dirPath, contract) {
34
34
  writeFileSync(path, JSON.stringify(contract, null, 2) + "\n");
35
35
  return path;
36
36
  }
37
+ function writeArchivedStageContract(dirPath, runId, contract) {
38
+ const path = archivedStageContractPath(dirPath, runId);
39
+ mkdirSync(dirname(path), { recursive: true });
40
+ writeFileSync(path, JSON.stringify(contract, null, 2) + "\n");
41
+ return path;
42
+ }
37
43
  export async function runExecutorStage(options) {
38
- const run = startRuntimeRun(options);
39
- const prompt = options.buildPrompt(run.contract_path);
40
- writeRuntimeRunPrompt(options.compiledPath, run.run_id, prompt);
44
+ const startedRun = startRuntimeRun(options);
45
+ const prompt = options.buildPrompt(startedRun.activeContractPath);
46
+ writeRuntimeRunPrompt(options.compiledPath, startedRun.run.run_id, prompt);
41
47
  const executionPath = options.executionPath ?? options.compiledPath;
42
48
  const code = await options.executor.execute(executionPath, prompt, {
43
- eventLogPath: eventLogPath(options.compiledPath, run.run_id),
44
- statusLogPath: statusLogPath(options.compiledPath, run.run_id),
49
+ eventLogPath: eventLogPath(options.compiledPath, startedRun.run.run_id),
50
+ statusLogPath: statusLogPath(options.compiledPath, startedRun.run.run_id),
45
51
  completionCheck: options.completionCheck,
46
52
  });
47
53
  finalizeRuntimeRun(options.compiledPath, code);
48
54
  return code;
49
55
  }
50
56
  export async function runExecutorSummarizeStage(options) {
51
- const run = startRuntimeRun(options);
52
- const prompt = options.buildPrompt(run.contract_path);
57
+ const startedRun = startRuntimeRun(options);
58
+ const prompt = options.buildPrompt(startedRun.activeContractPath);
53
59
  let lastReported = 0;
54
- writeRuntimeRunPrompt(options.compiledPath, run.run_id, prompt);
60
+ writeRuntimeRunPrompt(options.compiledPath, startedRun.run.run_id, prompt);
55
61
  const executionPath = options.executionPath ?? options.compiledPath;
56
62
  const progressPromise = options.executor.execute(executionPath, prompt, {
57
- eventLogPath: eventLogPath(options.compiledPath, run.run_id),
58
- statusLogPath: statusLogPath(options.compiledPath, run.run_id),
63
+ eventLogPath: eventLogPath(options.compiledPath, startedRun.run.run_id),
64
+ statusLogPath: statusLogPath(options.compiledPath, startedRun.run.run_id),
59
65
  completionCheck: options.completionCheck,
60
66
  });
61
67
  const timer = setInterval(() => {
@@ -66,7 +72,7 @@ export async function runExecutorSummarizeStage(options) {
66
72
  lastReported = completed;
67
73
  updateRuntimeRun(options.compiledPath, {
68
74
  counts: {
69
- ...run.counts,
75
+ ...startedRun.run.counts,
70
76
  completed_summaries: completed,
71
77
  target_summaries: options.targetCount,
72
78
  },
@@ -164,7 +170,8 @@ function startRuntimeRun(options) {
164
170
  artifacts: options.contract.artifacts,
165
171
  policies: options.contract.policies,
166
172
  };
167
- const contractPath = writeStageContract(options.compiledPath, contract);
173
+ const activeContractPath = writeStageContract(options.compiledPath, contract);
174
+ const archivedContractPath = writeArchivedStageContract(options.compiledPath, runId, contract);
168
175
  const run = {
169
176
  kind: "interf-run",
170
177
  version: 1,
@@ -180,7 +187,7 @@ function startRuntimeRun(options) {
180
187
  started_at: generatedAt,
181
188
  updated_at: generatedAt,
182
189
  finished_at: null,
183
- contract_path: relative(options.compiledPath, contractPath),
190
+ contract_path: relative(options.compiledPath, archivedContractPath),
184
191
  ...(options.executionPath ? { execution_path: relative(options.compiledPath, options.executionPath) } : {}),
185
192
  counts: { ...contract.counts },
186
193
  output_artifacts: [...contract.artifacts.writes],
@@ -193,7 +200,12 @@ function startRuntimeRun(options) {
193
200
  exit_code: null,
194
201
  error: null,
195
202
  };
196
- return beginRuntimeRun(options.compiledPath, run);
203
+ return {
204
+ run: beginRuntimeRun(options.compiledPath, run),
205
+ activeContractPath: options.executionPath
206
+ ? "runtime/stage-contract.json"
207
+ : relative(options.compiledPath, activeContractPath),
208
+ };
197
209
  }
198
210
  function finalizeRuntimeRun(dirPath, code) {
199
211
  const current = loadRuntimeRun(dirPath);
@@ -1,5 +1,5 @@
1
1
  export type { RuntimeRunPatch, RuntimeRunStatus, RuntimeStageAcceptanceValidation, RuntimeStageContractDraft, RuntimeStageExecutionOptions, RuntimeSummarizeExecutionOptions, RuntimeStageContractOptions, } from "./runtime-types.js";
2
- export { eventLogPath, logsDirPath, promptLogPath, runHistoryPath, runPath, stageContractPath, statusLogPath, } from "./runtime-paths.js";
2
+ export { archivedStageContractPath, eventLogPath, logsDirPath, promptLogPath, runHistoryPath, runPath, stageContractPath, statusLogPath, } from "./runtime-paths.js";
3
3
  export { validateStageContractAcceptance } from "./runtime-acceptance.js";
4
4
  export { buildStagePrompt } from "./runtime-prompt.js";
5
5
  export { buildRuntimeStageContract, } from "./runtime-contracts.js";
@@ -1,4 +1,4 @@
1
- export { eventLogPath, logsDirPath, promptLogPath, runHistoryPath, runPath, stageContractPath, statusLogPath, } from "./runtime-paths.js";
1
+ export { archivedStageContractPath, eventLogPath, logsDirPath, promptLogPath, runHistoryPath, runPath, stageContractPath, statusLogPath, } from "./runtime-paths.js";
2
2
  export { validateStageContractAcceptance } from "./runtime-acceptance.js";
3
3
  export { buildStagePrompt } from "./runtime-prompt.js";
4
4
  export { buildRuntimeStageContract, } from "./runtime-contracts.js";
@@ -18,6 +18,12 @@ export declare const WorkflowCompiledZoneKindSchema: z.ZodEnum<{
18
18
  directory: "directory";
19
19
  file: "file";
20
20
  }>;
21
+ export declare const WorkflowZoneRoleSchema: z.ZodEnum<{
22
+ output: "output";
23
+ runtime: "runtime";
24
+ input: "input";
25
+ working: "working";
26
+ }>;
21
27
  export declare const CompiledStageStatusSchema: z.ZodEnum<{
22
28
  idle: "idle";
23
29
  running: "running";
@@ -61,11 +67,6 @@ export declare const CompiledStateSchema: z.ZodObject<{
61
67
  }, z.core.$strip>>>;
62
68
  last_add: z.ZodOptional<z.ZodNullable<z.ZodString>>;
63
69
  last_compile: z.ZodOptional<z.ZodNullable<z.ZodString>>;
64
- inventory_complete: z.ZodOptional<z.ZodBoolean>;
65
- abstracts_read: z.ZodOptional<z.ZodNumber>;
66
- full_reads: z.ZodOptional<z.ZodNumber>;
67
- entity_count: z.ZodOptional<z.ZodNumber>;
68
- claim_count: z.ZodOptional<z.ZodNumber>;
69
70
  warning_count: z.ZodOptional<z.ZodNumber>;
70
71
  error_count: z.ZodOptional<z.ZodNumber>;
71
72
  }, z.core.$strict>;
@@ -158,8 +159,36 @@ export declare const CompiledRawSnapshotSchema: z.ZodObject<{
158
159
  source_total: z.ZodNumber;
159
160
  sample_files: z.ZodArray<z.ZodString>;
160
161
  }, z.core.$strip>;
162
+ export declare const WorkflowPurposeSchema: z.ZodObject<{
163
+ label: z.ZodString;
164
+ task_hint: z.ZodString;
165
+ }, z.core.$strict>;
166
+ export declare const WorkflowZoneSchema: z.ZodObject<{
167
+ id: z.ZodString;
168
+ role: z.ZodEnum<{
169
+ output: "output";
170
+ runtime: "runtime";
171
+ input: "input";
172
+ working: "working";
173
+ }>;
174
+ path: z.ZodString;
175
+ kind: z.ZodEnum<{
176
+ runtime: "runtime";
177
+ directory: "directory";
178
+ file: "file";
179
+ }>;
180
+ required: z.ZodBoolean;
181
+ owned_by: z.ZodArray<z.ZodString>;
182
+ description: z.ZodString;
183
+ }, z.core.$strip>;
161
184
  export declare const WorkflowCompiledZoneSchema: z.ZodObject<{
162
185
  id: z.ZodString;
186
+ role: z.ZodEnum<{
187
+ output: "output";
188
+ runtime: "runtime";
189
+ input: "input";
190
+ working: "working";
191
+ }>;
163
192
  path: z.ZodString;
164
193
  kind: z.ZodEnum<{
165
194
  runtime: "runtime";
@@ -170,13 +199,43 @@ export declare const WorkflowCompiledZoneSchema: z.ZodObject<{
170
199
  owned_by: z.ZodArray<z.ZodString>;
171
200
  description: z.ZodString;
172
201
  }, z.core.$strip>;
202
+ export declare const WorkflowSchemaSchema: z.ZodObject<{
203
+ kind: z.ZodLiteral<"workflow-schema">;
204
+ version: z.ZodLiteral<1>;
205
+ target_type: z.ZodLiteral<"compiled">;
206
+ label: z.ZodString;
207
+ zones: z.ZodArray<z.ZodObject<{
208
+ id: z.ZodString;
209
+ role: z.ZodEnum<{
210
+ output: "output";
211
+ runtime: "runtime";
212
+ input: "input";
213
+ working: "working";
214
+ }>;
215
+ path: z.ZodString;
216
+ kind: z.ZodEnum<{
217
+ runtime: "runtime";
218
+ directory: "directory";
219
+ file: "file";
220
+ }>;
221
+ required: z.ZodBoolean;
222
+ owned_by: z.ZodArray<z.ZodString>;
223
+ description: z.ZodString;
224
+ }, z.core.$strip>>;
225
+ }, z.core.$strip>;
173
226
  export declare const WorkflowCompiledSchemaSchema: z.ZodObject<{
174
- kind: z.ZodLiteral<"compiled-schema">;
227
+ kind: z.ZodLiteral<"workflow-schema">;
175
228
  version: z.ZodLiteral<1>;
176
229
  target_type: z.ZodLiteral<"compiled">;
177
230
  label: z.ZodString;
178
231
  zones: z.ZodArray<z.ZodObject<{
179
232
  id: z.ZodString;
233
+ role: z.ZodEnum<{
234
+ output: "output";
235
+ runtime: "runtime";
236
+ input: "input";
237
+ working: "working";
238
+ }>;
180
239
  path: z.ZodString;
181
240
  kind: z.ZodEnum<{
182
241
  runtime: "runtime";
@@ -258,6 +317,7 @@ export declare const RuntimeStageAcceptanceSchema: z.ZodObject<{
258
317
  zone_counts_at_least: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
259
318
  zone_counts_at_least_counts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
260
319
  markdown_frontmatter_valid_zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
320
+ frontmatter_required_keys_in_zones: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
261
321
  markdown_abstract_valid_zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
262
322
  wikilinks_valid_in_zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
263
323
  artifacts_must_not_contain: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
@@ -318,6 +378,7 @@ export declare const RuntimeStageContractSchema: z.ZodObject<{
318
378
  zone_counts_at_least: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
319
379
  zone_counts_at_least_counts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
320
380
  markdown_frontmatter_valid_zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
381
+ frontmatter_required_keys_in_zones: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
321
382
  markdown_abstract_valid_zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
322
383
  wikilinks_valid_in_zones: z.ZodOptional<z.ZodArray<z.ZodString>>;
323
384
  artifacts_must_not_contain: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
@@ -389,8 +450,8 @@ export declare const RuntimeRunSchema: z.ZodObject<{
389
450
  error: z.ZodNullable<z.ZodString>;
390
451
  }, z.core.$strip>;
391
452
  export declare const CompiledInventoryEntrySchema: z.ZodObject<{
392
- input_zone: z.ZodString;
393
- input_path: z.ZodString;
453
+ input_zone: z.ZodOptional<z.ZodString>;
454
+ input_path: z.ZodOptional<z.ZodString>;
394
455
  output_zone: z.ZodString;
395
456
  output_path: z.ZodString;
396
457
  state: z.ZodOptional<z.ZodString>;
@@ -401,8 +462,8 @@ export declare const CompiledInventorySchema: z.ZodObject<{
401
462
  version: z.ZodOptional<z.ZodNumber>;
402
463
  stage: z.ZodOptional<z.ZodString>;
403
464
  entries: z.ZodArray<z.ZodObject<{
404
- input_zone: z.ZodString;
405
- input_path: z.ZodString;
465
+ input_zone: z.ZodOptional<z.ZodString>;
466
+ input_path: z.ZodOptional<z.ZodString>;
406
467
  output_zone: z.ZodString;
407
468
  output_path: z.ZodString;
408
469
  state: z.ZodOptional<z.ZodString>;
@@ -967,10 +1028,6 @@ export declare const InterfUserConfigSchema: z.ZodObject<{
967
1028
  agent: z.ZodString;
968
1029
  agentCommand: z.ZodString;
969
1030
  skillsInstalled: z.ZodBoolean;
970
- viewer: z.ZodOptional<z.ZodEnum<{
971
- plain: "plain";
972
- obsidian: "obsidian";
973
- }>>;
974
1031
  initialized: z.ZodString;
975
1032
  }, z.core.$strip>;
976
1033
  export type InterfConfig = z.infer<typeof InterfConfigSchema>;
@@ -19,6 +19,7 @@ export const RuntimeContractTypeSchema = z.string().regex(WorkflowIdPattern);
19
19
  export const WorkflowIdSchema = z.string().regex(WorkflowIdPattern);
20
20
  export const WorkflowZoneIdSchema = z.string().regex(WorkflowIdPattern);
21
21
  export const WorkflowCompiledZoneKindSchema = z.enum(COMPILED_ZONE_KINDS);
22
+ export const WorkflowZoneRoleSchema = z.enum(["input", "working", "output", "runtime"]);
22
23
  export const CompiledStageStatusSchema = z.enum(["idle", "running", "succeeded", "failed"]);
23
24
  export const CompiledStageStateSchema = z.object({
24
25
  contract_type: RuntimeContractTypeSchema.optional(),
@@ -37,11 +38,6 @@ export const CompiledStateSchema = z.object({
37
38
  stages: z.record(z.string().regex(WorkflowIdPattern), CompiledStageStateSchema).optional(),
38
39
  last_add: z.string().nullable().optional(),
39
40
  last_compile: z.string().nullable().optional(),
40
- inventory_complete: z.boolean().optional(),
41
- abstracts_read: z.number().optional(),
42
- full_reads: z.number().optional(),
43
- entity_count: z.number().optional(),
44
- claim_count: z.number().optional(),
45
41
  warning_count: z.number().optional(),
46
42
  error_count: z.number().optional(),
47
43
  }).strict();
@@ -95,8 +91,13 @@ export const CompiledRawSnapshotSchema = z.object({
95
91
  source_total: z.number(),
96
92
  sample_files: z.array(z.string()),
97
93
  });
98
- export const WorkflowCompiledZoneSchema = z.object({
94
+ export const WorkflowPurposeSchema = z.object({
95
+ label: z.string().min(1),
96
+ task_hint: z.string().min(1),
97
+ }).strict();
98
+ export const WorkflowZoneSchema = z.object({
99
99
  id: WorkflowZoneIdSchema,
100
+ role: WorkflowZoneRoleSchema,
100
101
  path: z.string().min(1).refine(isCompiledRelativePath, {
101
102
  message: "Zone paths must stay inside the compiled root",
102
103
  }),
@@ -105,13 +106,15 @@ export const WorkflowCompiledZoneSchema = z.object({
105
106
  owned_by: z.array(z.string().regex(WorkflowIdPattern)),
106
107
  description: z.string().min(1),
107
108
  });
108
- export const WorkflowCompiledSchemaSchema = z.object({
109
- kind: z.literal("compiled-schema"),
109
+ export const WorkflowCompiledZoneSchema = WorkflowZoneSchema;
110
+ export const WorkflowSchemaSchema = z.object({
111
+ kind: z.literal("workflow-schema"),
110
112
  version: z.literal(1),
111
113
  target_type: z.literal("compiled"),
112
114
  label: z.string().min(1),
113
- zones: z.array(WorkflowCompiledZoneSchema).min(1),
115
+ zones: z.array(WorkflowZoneSchema).min(1),
114
116
  });
117
+ export const WorkflowCompiledSchemaSchema = WorkflowSchemaSchema;
115
118
  export const WorkflowCompilerApiSchema = z.object({
116
119
  kind: z.literal("compiled"),
117
120
  version: z.literal(1),
@@ -158,6 +161,7 @@ export const RuntimeStageAcceptanceSchema = z.object({
158
161
  zone_counts_at_least: z.record(z.string().regex(WorkflowIdPattern), z.number()).optional(),
159
162
  zone_counts_at_least_counts: z.record(z.string().regex(WorkflowIdPattern), z.string()).optional(),
160
163
  markdown_frontmatter_valid_zones: z.array(WorkflowZoneIdSchema).optional(),
164
+ frontmatter_required_keys_in_zones: z.record(WorkflowZoneIdSchema, z.array(z.string().min(1)).min(1)).optional(),
161
165
  markdown_abstract_valid_zones: z.array(WorkflowZoneIdSchema).optional(),
162
166
  wikilinks_valid_in_zones: z.array(WorkflowZoneIdSchema).optional(),
163
167
  artifacts_must_not_contain: z.record(z.string(), z.array(z.string().min(1))).optional(),
@@ -230,8 +234,8 @@ export const RuntimeRunSchema = z.object({
230
234
  error: z.string().nullable(),
231
235
  });
232
236
  export const CompiledInventoryEntrySchema = z.object({
233
- input_zone: WorkflowZoneIdSchema,
234
- input_path: z.string().min(1),
237
+ input_zone: WorkflowZoneIdSchema.optional(),
238
+ input_path: z.string().min(1).optional(),
235
239
  output_zone: WorkflowZoneIdSchema,
236
240
  output_path: z.string().min(1),
237
241
  state: z.string().min(1).optional(),
@@ -534,6 +538,5 @@ export const InterfUserConfigSchema = z.object({
534
538
  agent: z.string(),
535
539
  agentCommand: z.string(),
536
540
  skillsInstalled: z.boolean(),
537
- viewer: z.enum(["plain", "obsidian"]).optional(),
538
541
  initialized: z.string(),
539
542
  });
@@ -73,10 +73,10 @@ function buildDefaultCompiledViewSpec(dirPath, compiledName, generatedAt) {
73
73
  const workflowId = resolveRequiredCompiledWorkflowFromConfig(config, `.interf/interf.json for ${dirPath}`);
74
74
  const workflow = getActiveCompiledWorkflow(dirPath, workflowId);
75
75
  const schema = readCompiledSchemaFile(workflowPackagePathForCompiled(dirPath));
76
- const zoneDocumentPaths = (schema?.zones ?? [])
77
- .filter((zone) => zone.kind !== "runtime")
76
+ const outputDocumentPaths = (schema?.zones ?? [])
77
+ .filter((zone) => zone.role === "output" && zone.kind !== "runtime")
78
78
  .map((zone) => zone.path);
79
- const defaultNote = (schema?.zones ?? []).find((zone) => zone.kind === "file")?.path ?? null;
79
+ const defaultNote = (schema?.zones ?? []).find((zone) => zone.role === "output" && zone.kind === "file")?.path ?? null;
80
80
  return {
81
81
  kind: "compiled-view-spec",
82
82
  version: 2,
@@ -85,7 +85,7 @@ function buildDefaultCompiledViewSpec(dirPath, compiledName, generatedAt) {
85
85
  health_source: ".interf/runtime/health.json",
86
86
  state_source: ".interf/runtime/state.json",
87
87
  default_note: defaultNote,
88
- graph_scope: zoneDocumentPaths,
88
+ graph_scope: outputDocumentPaths,
89
89
  cards: [
90
90
  { id: "source-total", label: "Source Files", metric: "source_total", format: "number" },
91
91
  { id: "stage-total", label: "Stages", metric: "stage_total", format: "number" },
@@ -94,8 +94,8 @@ function buildDefaultCompiledViewSpec(dirPath, compiledName, generatedAt) {
94
94
  sections: [
95
95
  { id: "status", type: "status", title: "Compile Status", path: ".interf/runtime/health.json" },
96
96
  { id: "cards", type: "cards", title: "Key Metrics", path: ".interf/runtime/health.json" },
97
- ...(zoneDocumentPaths.length > 0
98
- ? [{ id: "outputs", type: "documents", title: "Compiled Outputs", paths: zoneDocumentPaths }]
97
+ ...(outputDocumentPaths.length > 0
98
+ ? [{ id: "outputs", type: "documents", title: "Output Zones", paths: outputDocumentPaths }]
99
99
  : []),
100
100
  { id: "workflow", type: "documents", title: "Workflow Docs", paths: ["workflow/README.md", ...workflow.stages.map((stage) => `workflow/compile/stages/${stage.skillDir}`)] },
101
101
  ],
@@ -4,3 +4,4 @@ export { loadState, saveState, loadCompiledHealth, saveCompiledHealth, loadCompi
4
4
  export { refreshCompiledArtifacts, } from "./state-artifacts.js";
5
5
  export { computeCompiledHealth, resolveCompiledStatus, resolveCompiledStage, } from "./state-health.js";
6
6
  export { ensureCompiledViewSpec, ensureCompiledRawSnapshot, normalizeCompiledViewSpec, } from "./state-view.js";
7
+ export declare function initializeCompiledRuntimeState(dirPath: string): void;
package/dist/lib/state.js CHANGED
@@ -3,3 +3,10 @@ export { loadState, saveState, loadCompiledHealth, saveCompiledHealth, loadCompi
3
3
  export { refreshCompiledArtifacts, } from "./state-artifacts.js";
4
4
  export { computeCompiledHealth, resolveCompiledStatus, resolveCompiledStage, } from "./state-health.js";
5
5
  export { ensureCompiledViewSpec, ensureCompiledRawSnapshot, normalizeCompiledViewSpec, } from "./state-view.js";
6
+ import { saveEmptyCompiledInventory, initCompiledState, saveState } from "./state-io.js";
7
+ import { refreshCompiledArtifacts } from "./state-artifacts.js";
8
+ export function initializeCompiledRuntimeState(dirPath) {
9
+ saveState(dirPath, initCompiledState());
10
+ saveEmptyCompiledInventory(dirPath);
11
+ refreshCompiledArtifacts(dirPath, { ensureViewSpec: true });
12
+ }
@@ -203,7 +203,7 @@ function buildTestQueryPrompt(target, testCase, answerPath, tracePath) {
203
203
  "Answer the truth-check question the same way you would answer a real user inside this compiled dataset.",
204
204
  "Prefer the workflow-declared compiled outputs before raw fallback.",
205
205
  "This sandbox is self-contained: the copied compiled dataset has its own sanitized `raw/` fallback via `.interf/interf.json` `source.path`.",
206
- "The project control plane is intentionally absent from this sandbox. Work only from this sandboxed compiled dataset and its embedded raw files.",
206
+ "The original project root is intentionally absent from this sandbox. Work only from this sandboxed compiled dataset and its embedded raw files.",
207
207
  ]
208
208
  : [
209
209
  "You are running an Interf baseline test inside an isolated raw test shell.",
@@ -211,7 +211,7 @@ function buildTestQueryPrompt(target, testCase, answerPath, tracePath) {
211
211
  "Use the local native `interf-query` skill available in this shell.",
212
212
  "There is no compiled dataset in this sandbox.",
213
213
  "Answer only from `raw/` inside this shell.",
214
- "The project control plane is intentionally absent from this sandbox.",
214
+ "The original project root is intentionally absent from this sandbox.",
215
215
  ];
216
216
  return [
217
217
  ...header,
@@ -1,7 +1,7 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { discoverSourceFiles } from "./discovery.js";
4
- import { compiledZoneAbsolutePath, findCompiledSchemaZone, readCompiledSchemaFile, } from "./compiled-schema.js";
4
+ import { WORKFLOW_SCHEMA_FILE, compiledZoneAbsolutePath, findCompiledSchemaZone, readCompiledSchemaFile, workflowSchemaExists, } from "./compiled-schema.js";
5
5
  import { resolveSourceFolderPath } from "./interf.js";
6
6
  import { compiledInterfConfigPath, workflowPackagePathForCompiled } from "./compiled-paths.js";
7
7
  import { readCompiledConfig } from "./validate.js";
@@ -9,6 +9,9 @@ import { loadState } from "./state.js";
9
9
  import { validateResolvedStageAcceptance, stageRecordFromState } from "./runtime-acceptance.js";
10
10
  import { getActiveCompiledWorkflow, resolveRequiredCompiledWorkflowFromConfig, } from "./workflow-definitions.js";
11
11
  import { listFilesRecursive } from "./filesystem.js";
12
+ function workflowSchemaPresent(dirPath) {
13
+ return workflowSchemaExists(join(dirPath, ".interf", "workflow"));
14
+ }
12
15
  function countZoneArtifacts(compiledPath, zonePath, kind) {
13
16
  const absolutePath = compiledZoneAbsolutePath(compiledPath, { path: zonePath });
14
17
  if (!existsSync(absolutePath))
@@ -84,7 +87,7 @@ export function validateCompiled(dirPath) {
84
87
  config_type_match: context.config.typeMatch(),
85
88
  workflow_present: existsSync(join(dirPath, ".interf", "workflow", "workflow.json")),
86
89
  workflow_valid: context.workflow !== null,
87
- schema_present: existsSync(join(dirPath, ".interf", "workflow", "compiled.schema.json")),
90
+ schema_present: workflowSchemaPresent(dirPath),
88
91
  schema_valid: context.schema !== null,
89
92
  };
90
93
  }
@@ -96,7 +99,7 @@ export function validateCompiledStage(dirPath, stageId) {
96
99
  config_type_match: context.config.typeMatch(),
97
100
  workflow_present: existsSync(join(dirPath, ".interf", "workflow", "workflow.json")),
98
101
  workflow_valid: context.workflow !== null,
99
- schema_present: existsSync(join(dirPath, ".interf", "workflow", "compiled.schema.json")),
102
+ schema_present: workflowSchemaPresent(dirPath),
100
103
  schema_valid: context.schema !== null,
101
104
  };
102
105
  const errors = [];
@@ -111,9 +114,9 @@ export function validateCompiledStage(dirPath, stageId) {
111
114
  else if (!checks.workflow_valid)
112
115
  errors.push("Could not load the active workflow package.");
113
116
  if (!checks.schema_present)
114
- errors.push("Missing .interf/workflow/compiled.schema.json.");
117
+ errors.push(`Missing .interf/workflow/${WORKFLOW_SCHEMA_FILE}.`);
115
118
  else if (!checks.schema_valid)
116
- errors.push("Could not parse .interf/workflow/compiled.schema.json.");
119
+ errors.push(`Could not parse .interf/workflow/${WORKFLOW_SCHEMA_FILE}.`);
117
120
  const workflowStage = context.workflow?.stages.find((stage) => stage.id === stageId) ?? null;
118
121
  checks.stage_present = workflowStage !== null;
119
122
  if (!checks.stage_present) {
@@ -178,7 +181,7 @@ export function validateCompiledWorkflow(dirPath) {
178
181
  config_type_match: context.config.typeMatch(),
179
182
  workflow_present: existsSync(join(dirPath, ".interf", "workflow", "workflow.json")),
180
183
  workflow_valid: context.workflow !== null,
181
- schema_present: existsSync(join(dirPath, ".interf", "workflow", "compiled.schema.json")),
184
+ schema_present: workflowSchemaPresent(dirPath),
182
185
  schema_valid: context.schema !== null,
183
186
  };
184
187
  if (!context.workflow) {
@@ -5,7 +5,9 @@ export declare function readCompiledConfig(dirPath: string): {
5
5
  value: ReturnType<typeof readInterfConfig>;
6
6
  typeMatch(): boolean;
7
7
  };
8
- export declare function validateSynthFiles(files: string[]): {
8
+ export declare function validateSynthFiles(files: string[], options?: {
9
+ requiredFrontmatterKeys?: string[];
10
+ }): {
9
11
  invalid_frontmatter: number;
10
12
  short_abstracts: number;
11
13
  };