@interf/compiler 0.6.3 → 0.6.4

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 (115) hide show
  1. package/README.md +70 -64
  2. package/dist/cli/commands/check-draft.js +4 -4
  3. package/dist/cli/commands/compile-controller.js +23 -23
  4. package/dist/cli/commands/compile.js +2 -2
  5. package/dist/cli/commands/compiled-flow.js +4 -4
  6. package/dist/cli/commands/create-workflow-wizard.js +8 -8
  7. package/dist/cli/commands/create.js +5 -5
  8. package/dist/cli/commands/default.js +1 -1
  9. package/dist/cli/commands/init.js +43 -43
  10. package/dist/cli/commands/list.js +2 -2
  11. package/dist/cli/commands/reset.js +1 -1
  12. package/dist/cli/commands/source-config-wizard.d.ts +1 -1
  13. package/dist/cli/commands/source-config-wizard.js +40 -40
  14. package/dist/cli/commands/status.js +5 -5
  15. package/dist/cli/commands/test-flow.js +26 -26
  16. package/dist/cli/commands/test.js +12 -12
  17. package/dist/lib/chart-guidance.d.ts +1 -1
  18. package/dist/lib/chart-guidance.js +1 -8
  19. package/dist/lib/discovery.d.ts +1 -7
  20. package/dist/lib/discovery.js +1 -84
  21. package/dist/lib/filesystem.d.ts +1 -2
  22. package/dist/lib/filesystem.js +1 -55
  23. package/dist/lib/logger.d.ts +1 -3
  24. package/dist/lib/logger.js +1 -10
  25. package/dist/lib/parse.d.ts +1 -8
  26. package/dist/lib/parse.js +1 -145
  27. package/dist/lib/util.d.ts +1 -4
  28. package/dist/lib/util.js +1 -25
  29. package/dist/packages/agents/index.d.ts +1 -0
  30. package/dist/packages/agents/index.js +1 -0
  31. package/dist/packages/agents/lib/chart-guidance.d.ts +1 -0
  32. package/dist/packages/agents/lib/chart-guidance.js +8 -0
  33. package/dist/packages/agents/lib/compiled-bootstrap.d.ts +3 -0
  34. package/dist/packages/agents/lib/compiled-bootstrap.js +18 -0
  35. package/dist/packages/agents/lib/executors.d.ts +2 -2
  36. package/dist/packages/agents/lib/shells.d.ts +3 -1
  37. package/dist/packages/agents/lib/shells.js +22 -20
  38. package/dist/packages/agents/lib/user-config.js +1 -1
  39. package/dist/packages/compiler/compiled-compile.d.ts +4 -48
  40. package/dist/packages/compiler/compiled-compile.js +4 -256
  41. package/dist/packages/compiler/compiled-paths.d.ts +40 -0
  42. package/dist/packages/compiler/compiled-paths.js +106 -0
  43. package/dist/packages/compiler/compiled-pipeline.d.ts +39 -0
  44. package/dist/packages/compiler/compiled-pipeline.js +134 -0
  45. package/dist/packages/compiler/compiled-schema.js +2 -2
  46. package/dist/packages/compiler/compiled-stage-plan.d.ts +15 -0
  47. package/dist/packages/compiler/compiled-stage-plan.js +79 -0
  48. package/dist/packages/compiler/compiled-stage-runner.d.ts +10 -0
  49. package/dist/packages/compiler/compiled-stage-runner.js +46 -0
  50. package/dist/packages/compiler/compiled-target.d.ts +11 -0
  51. package/dist/packages/compiler/compiled-target.js +16 -0
  52. package/dist/packages/compiler/discovery.d.ts +7 -0
  53. package/dist/packages/compiler/discovery.js +80 -0
  54. package/dist/packages/compiler/lib/schema.js +2 -0
  55. package/dist/packages/compiler/raw-snapshot.d.ts +49 -0
  56. package/dist/packages/compiler/raw-snapshot.js +102 -0
  57. package/dist/packages/compiler/reset.d.ts +2 -0
  58. package/dist/packages/compiler/reset.js +72 -0
  59. package/dist/packages/compiler/runtime-acceptance.js +3 -3
  60. package/dist/packages/compiler/runtime-contracts.js +1 -1
  61. package/dist/packages/compiler/runtime-paths.js +1 -1
  62. package/dist/packages/compiler/runtime-reconcile.js +3 -3
  63. package/dist/packages/compiler/runtime-runs.js +2 -2
  64. package/dist/packages/compiler/state-health.js +3 -3
  65. package/dist/packages/compiler/state-io.js +3 -3
  66. package/dist/packages/compiler/state-paths.js +1 -1
  67. package/dist/packages/compiler/state-view.js +2 -2
  68. package/dist/packages/compiler/validate-compiled.js +3 -3
  69. package/dist/packages/compiler/validate.js +4 -4
  70. package/dist/packages/project-model/compiled-paths.d.ts +1 -40
  71. package/dist/packages/project-model/compiled-paths.js +1 -106
  72. package/dist/packages/project-model/compiled-raw.d.ts +1 -49
  73. package/dist/packages/project-model/compiled-raw.js +1 -102
  74. package/dist/packages/project-model/compiled-reset.d.ts +1 -2
  75. package/dist/packages/project-model/compiled-reset.js +1 -72
  76. package/dist/packages/project-model/interf-bootstrap.d.ts +1 -3
  77. package/dist/packages/project-model/interf-bootstrap.js +1 -18
  78. package/dist/packages/project-model/interf-detect.js +4 -4
  79. package/dist/packages/project-model/interf-scaffold.js +7 -7
  80. package/dist/packages/project-model/source-config.js +6 -5
  81. package/dist/packages/shared/file-types.d.ts +1 -0
  82. package/dist/packages/shared/file-types.js +4 -0
  83. package/dist/packages/shared/filesystem.d.ts +2 -0
  84. package/dist/packages/shared/filesystem.js +55 -0
  85. package/dist/packages/shared/index.d.ts +7 -0
  86. package/dist/packages/shared/index.js +7 -0
  87. package/dist/packages/shared/logger.d.ts +3 -0
  88. package/dist/packages/shared/logger.js +10 -0
  89. package/dist/packages/shared/naming.d.ts +1 -0
  90. package/dist/packages/shared/naming.js +8 -0
  91. package/dist/packages/shared/parse.d.ts +8 -0
  92. package/dist/packages/shared/parse.js +145 -0
  93. package/dist/packages/shared/path-guards.d.ts +2 -0
  94. package/dist/packages/shared/path-guards.js +14 -0
  95. package/dist/packages/shared/util.d.ts +3 -0
  96. package/dist/packages/shared/util.js +3 -0
  97. package/dist/packages/testing/test-execution.js +3 -3
  98. package/dist/packages/testing/test-paths.js +1 -1
  99. package/dist/packages/testing/test-sandbox.js +3 -3
  100. package/dist/packages/testing/test-specs.js +1 -1
  101. package/dist/packages/workflow-authoring/workflow-authoring.js +5 -4
  102. package/dist/packages/workflow-authoring/workflow-improvement.js +6 -5
  103. package/dist/packages/workflow-package/builtin-compiled-workflow.js +1 -1
  104. package/dist/packages/workflow-package/context-interface.d.ts +96 -0
  105. package/dist/packages/workflow-package/context-interface.js +146 -0
  106. package/dist/packages/workflow-package/index.d.ts +2 -0
  107. package/dist/packages/workflow-package/index.js +2 -0
  108. package/dist/packages/workflow-package/interf-workflow-package.js +75 -28
  109. package/dist/packages/workflow-package/local-workflows.d.ts +5 -2
  110. package/dist/packages/workflow-package/local-workflows.js +15 -13
  111. package/dist/packages/workflow-package/workflow-definitions.d.ts +11 -7
  112. package/dist/packages/workflow-package/workflow-definitions.js +10 -3
  113. package/dist/packages/workflow-package/workflow-helpers.js +4 -4
  114. package/dist/packages/workflow-package/workflow-review-paths.js +1 -1
  115. package/package.json +2 -2
@@ -0,0 +1,146 @@
1
+ import { existsSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { z } from "zod";
4
+ import { warnInterf } from "../shared/logger.js";
5
+ import { readJsonFileUnchecked } from "../shared/parse.js";
6
+ import { WorkflowCompiledSchemaSchema, WorkflowCompiledZoneSchema, WorkflowZoneIdSchema, WorkflowZoneRoleSchema, } from "../compiler/lib/schema.js";
7
+ import { listBuiltinCompiledZoneSpecs, requiredCompiledZoneOwners, } from "./builtin-compiled-workflow.js";
8
+ // Workflow packages define the context interface. The compiler persists the
9
+ // same schema on disk, but higher layers should prefer this boundary when they
10
+ // mean "the workflow-declared shape a compiled context must implement."
11
+ export const CONTEXT_INTERFACE_FILE = "workflow.schema.json";
12
+ export const ContextInterfaceSchema = WorkflowCompiledSchemaSchema;
13
+ export const ContextInterfaceZoneSchema = WorkflowCompiledZoneSchema;
14
+ export const ContextInterfaceZoneIdSchema = WorkflowZoneIdSchema;
15
+ export const ContextInterfaceZoneRoleSchema = WorkflowZoneRoleSchema;
16
+ // Package-owned input contract for authoring, review, and future Studio flows.
17
+ // This does not change compiler execution semantics; it describes what data a
18
+ // workflow expects to organize before the compiler materializes the context
19
+ // interface on disk.
20
+ export const WorkflowInputSpecSchema = z.object({
21
+ id: WorkflowZoneIdSchema,
22
+ label: z.string().min(1),
23
+ description: z.string().min(1),
24
+ required: z.boolean().default(false),
25
+ examples: z.array(z.string().min(1)).optional(),
26
+ }).strict();
27
+ export const WorkflowInputContractSchema = z.array(WorkflowInputSpecSchema);
28
+ function normalizeContextInterface(contextInterface) {
29
+ return {
30
+ ...contextInterface,
31
+ kind: "workflow-schema",
32
+ };
33
+ }
34
+ function pushContextInterfaceZone(zones, zone) {
35
+ if (zones.some((existing) => existing.path === zone.path))
36
+ return;
37
+ zones.push(zone);
38
+ }
39
+ function titleCaseZoneId(zoneId) {
40
+ return zoneId
41
+ .split("-")
42
+ .filter(Boolean)
43
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
44
+ .join(" ");
45
+ }
46
+ export function contextInterfaceFilePath(rootPath) {
47
+ return join(rootPath, CONTEXT_INTERFACE_FILE);
48
+ }
49
+ export function resolveContextInterfacePath(rootPath) {
50
+ const path = contextInterfaceFilePath(rootPath);
51
+ return existsSync(path) ? path : null;
52
+ }
53
+ export function contextInterfaceExists(rootPath) {
54
+ return existsSync(contextInterfaceFilePath(rootPath));
55
+ }
56
+ export function contextInterfaceRelativePath() {
57
+ return `workflow/${CONTEXT_INTERFACE_FILE}`;
58
+ }
59
+ export function listContextInterfaceZones(contextInterface) {
60
+ return [...contextInterface.zones];
61
+ }
62
+ export function findContextInterfaceZone(contextInterface, zoneId) {
63
+ return contextInterface.zones.find((zone) => zone.id === zoneId) ?? null;
64
+ }
65
+ export function contextInterfaceZoneAbsolutePath(compiledPath, zone) {
66
+ return join(compiledPath, zone.path);
67
+ }
68
+ export function contextInterfaceArtifactPath(zone) {
69
+ if (zone.kind === "file")
70
+ return zone.path;
71
+ return zone.path.endsWith("/") ? zone.path : `${zone.path}/`;
72
+ }
73
+ export function contextInterfaceArtifactPathsForZoneIds(contextInterface, zoneIds) {
74
+ return zoneIds.map((zoneId) => {
75
+ const zone = findContextInterfaceZone(contextInterface, zoneId);
76
+ if (!zone) {
77
+ throw new Error(`Context interface is missing declared zone "${zoneId}".`);
78
+ }
79
+ return contextInterfaceArtifactPath(zone);
80
+ });
81
+ }
82
+ export function summarizeContextInterface(contextInterface) {
83
+ return {
84
+ inputZones: contextInterface.zones.filter((zone) => zone.role === "input"),
85
+ workingZones: contextInterface.zones.filter((zone) => zone.role === "working"),
86
+ outputZones: contextInterface.zones.filter((zone) => zone.role === "output"),
87
+ runtimeZones: contextInterface.zones.filter((zone) => zone.role === "runtime"),
88
+ };
89
+ }
90
+ export function deriveWorkflowInputsFromContextInterface(contextInterface) {
91
+ if (!contextInterface)
92
+ return [];
93
+ return contextInterface.zones
94
+ .filter((zone) => zone.role === "input")
95
+ .map((zone) => ({
96
+ id: zone.id,
97
+ label: titleCaseZoneId(zone.id),
98
+ description: zone.description,
99
+ required: zone.required,
100
+ }));
101
+ }
102
+ export function buildContextInterface(stages, label = "Workflow context interface") {
103
+ const zones = [];
104
+ for (const zone of listBuiltinCompiledZoneSpecs()) {
105
+ pushContextInterfaceZone(zones, {
106
+ id: zone.id,
107
+ role: zone.role,
108
+ path: zone.path,
109
+ kind: zone.kind,
110
+ required: zone.required,
111
+ owned_by: requiredCompiledZoneOwners(stages, zone.id),
112
+ description: zone.description,
113
+ });
114
+ }
115
+ return {
116
+ kind: "workflow-schema",
117
+ version: 1,
118
+ target_type: "compiled",
119
+ label,
120
+ zones,
121
+ };
122
+ }
123
+ export function writeContextInterfaceFile(rootPath, stages, label) {
124
+ const contextInterface = buildContextInterface(stages, label);
125
+ writeContextInterface(rootPath, contextInterface);
126
+ return contextInterface;
127
+ }
128
+ export function writeContextInterface(rootPath, contextInterface) {
129
+ const normalized = normalizeContextInterface(contextInterface);
130
+ writeFileSync(contextInterfaceFilePath(rootPath), `${JSON.stringify(normalized, null, 2)}\n`);
131
+ return normalized;
132
+ }
133
+ export function readContextInterface(rootPath) {
134
+ const path = contextInterfaceFilePath(rootPath);
135
+ if (!existsSync(path))
136
+ return null;
137
+ const raw = readJsonFileUnchecked(path, "workflow context interface");
138
+ if (raw === null)
139
+ return null;
140
+ const parsed = ContextInterfaceSchema.safeParse(raw);
141
+ if (!parsed.success) {
142
+ warnInterf(`Warning: failed to validate workflow context interface at ${path}: ${parsed.error.issues.map((issue) => issue.message).join("; ")}`);
143
+ return null;
144
+ }
145
+ return normalizeContextInterface(parsed.data);
146
+ }
@@ -1,4 +1,5 @@
1
1
  export * as builtinWorkflow from "./builtin-compiled-workflow.js";
2
+ export * as contextInterface from "./context-interface.js";
2
3
  export * as localWorkflows from "./local-workflows.js";
3
4
  export * as packageWriters from "./interf-workflow-package.js";
4
5
  export * as workflowDefinitions from "./workflow-definitions.js";
@@ -7,3 +8,4 @@ export * as workflowStagePolicy from "./workflow-stage-policy.js";
7
8
  export * as workflowStageRunner from "./workflow-stage-runner.js";
8
9
  export * as workflowReviewPaths from "./workflow-review-paths.js";
9
10
  export * as packageRoot from "./lib/package-root.js";
11
+ export { CONTEXT_INTERFACE_FILE, ContextInterfaceSchema, ContextInterfaceZoneSchema, ContextInterfaceZoneIdSchema, ContextInterfaceZoneRoleSchema, WorkflowInputSpecSchema, WorkflowInputContractSchema, contextInterfaceFilePath, resolveContextInterfacePath, contextInterfaceExists, contextInterfaceRelativePath, listContextInterfaceZones, findContextInterfaceZone, contextInterfaceZoneAbsolutePath, contextInterfaceArtifactPath, contextInterfaceArtifactPathsForZoneIds, buildContextInterface, writeContextInterfaceFile, writeContextInterface, readContextInterface, type ContextInterface, type ContextInterfaceZone, type ContextInterfaceZoneId, type ContextInterfaceZoneRole, type ContextInterfaceStageLike, type WorkflowInputSpec, type ContextInterfaceSummary, summarizeContextInterface, deriveWorkflowInputsFromContextInterface, } from "./context-interface.js";
@@ -1,4 +1,5 @@
1
1
  export * as builtinWorkflow from "./builtin-compiled-workflow.js";
2
+ export * as contextInterface from "./context-interface.js";
2
3
  export * as localWorkflows from "./local-workflows.js";
3
4
  export * as packageWriters from "./interf-workflow-package.js";
4
5
  export * as workflowDefinitions from "./workflow-definitions.js";
@@ -7,3 +8,4 @@ export * as workflowStagePolicy from "./workflow-stage-policy.js";
7
8
  export * as workflowStageRunner from "./workflow-stage-runner.js";
8
9
  export * as workflowReviewPaths from "./workflow-review-paths.js";
9
10
  export * as packageRoot from "./lib/package-root.js";
11
+ export { CONTEXT_INTERFACE_FILE, ContextInterfaceSchema, ContextInterfaceZoneSchema, ContextInterfaceZoneIdSchema, ContextInterfaceZoneRoleSchema, WorkflowInputSpecSchema, WorkflowInputContractSchema, contextInterfaceFilePath, resolveContextInterfacePath, contextInterfaceExists, contextInterfaceRelativePath, listContextInterfaceZones, findContextInterfaceZone, contextInterfaceZoneAbsolutePath, contextInterfaceArtifactPath, contextInterfaceArtifactPathsForZoneIds, buildContextInterface, writeContextInterfaceFile, writeContextInterface, readContextInterface, summarizeContextInterface, deriveWorkflowInputsFromContextInterface, } from "./context-interface.js";
@@ -1,10 +1,10 @@
1
1
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
2
  import { dirname, join } from "node:path";
3
3
  import { renderCompiledQuerySkill } from "../agents/lib/shells.js";
4
- import { WORKFLOW_SCHEMA_FILE, writeWorkflowSchemaDocument, writeWorkflowSchemaFile, } from "../compiler/compiled-schema.js";
5
4
  import { copyWorkflowPackageDirectory, isPortableWorkflowPackage, patchWorkflowPackageMetadata, resolveWorkflowPackageSourcePath, workflowDefinitionPath, } from "./local-workflows.js";
6
5
  import { getCompiledWorkflow, } from "./workflow-definitions.js";
7
- import { workflowPackagePathForCompiled } from "../project-model/compiled-paths.js";
6
+ import { CONTEXT_INTERFACE_FILE, deriveWorkflowInputsFromContextInterface, summarizeContextInterface, writeContextInterface, writeContextInterfaceFile, } from "./context-interface.js";
7
+ import { workflowPackagePathForCompiled } from "../compiler/compiled-paths.js";
8
8
  import { mergeStagePolicyNotesForStages } from "./workflow-stage-policy.js";
9
9
  function workflowPackagePath(dirPath) {
10
10
  return workflowPackagePathForCompiled(dirPath);
@@ -22,6 +22,9 @@ function writeWorkflowPackageJson(rootPath, workflow, options) {
22
22
  const targetPath = join(rootPath, "workflow.json");
23
23
  if (!options.overwrite && existsSync(targetPath))
24
24
  return;
25
+ const inputs = workflow.inputs?.length
26
+ ? workflow.inputs
27
+ : deriveWorkflowInputsFromContextInterface(workflow.contextInterface ?? workflow.schema);
25
28
  writeFileSync(targetPath, `${JSON.stringify({
26
29
  id: workflow.id,
27
30
  type: "compiled",
@@ -37,6 +40,7 @@ function writeWorkflowPackageJson(rootPath, workflow, options) {
37
40
  },
38
41
  }
39
42
  : {}),
43
+ ...(inputs.length > 0 ? { inputs } : {}),
40
44
  label: workflow.label,
41
45
  hint: workflow.hint,
42
46
  stages: workflow.stages.map((stage) => ({
@@ -53,14 +57,34 @@ function writeWorkflowPackageJson(rootPath, workflow, options) {
53
57
  }, null, 2)}\n`);
54
58
  }
55
59
  function renderWorkflowReadme(workflow) {
60
+ const contextInterface = workflow.contextInterface ?? workflow.schema ?? null;
56
61
  const stageLines = workflow.stages
57
62
  .map((stage) => `- \`${stage.id}\` — ${stage.description} (${stage.contractType}; reads: ${stage.reads.join(", ")}; writes: ${stage.writes.join(", ")})`)
58
63
  .join("\n");
59
- const zoneLines = workflow.schema?.zones
60
- ? workflow.schema.zones
61
- .map((zone) => `- \`${zone.id}\` — ${zone.role} ${zone.kind} at \`${zone.path}\``)
64
+ const interfaceSummary = contextInterface
65
+ ? summarizeContextInterface(contextInterface)
66
+ : null;
67
+ const contextInterfaceLines = contextInterface?.zones
68
+ ? contextInterface.zones
69
+ .map((zone) => `- \`${zone.id}\` — ${zone.role} ${zone.kind} at \`${zone.path}\`: ${zone.description}`)
70
+ .join("\n")
71
+ : null;
72
+ const inputs = workflow.inputs?.length
73
+ ? workflow.inputs
74
+ : deriveWorkflowInputsFromContextInterface(contextInterface);
75
+ const inputLines = inputs.length > 0
76
+ ? inputs
77
+ .map((input) => `- \`${input.id}\` — ${input.label}: ${input.description}${input.required ? " (required)" : ""}${input.examples?.length ? ` Example inputs: ${input.examples.join("; ")}` : ""}`)
62
78
  .join("\n")
63
79
  : null;
80
+ const contextInterfaceSummaryLines = interfaceSummary
81
+ ? [
82
+ `- Input zones: ${interfaceSummary.inputZones.length > 0 ? interfaceSummary.inputZones.map((zone) => `\`${zone.id}\``).join(", ") : "none"}`,
83
+ `- Working zones: ${interfaceSummary.workingZones.length > 0 ? interfaceSummary.workingZones.map((zone) => `\`${zone.id}\``).join(", ") : "none"}`,
84
+ `- Output zones: ${interfaceSummary.outputZones.length > 0 ? interfaceSummary.outputZones.map((zone) => `\`${zone.id}\``).join(", ") : "none"}`,
85
+ `- Runtime zones: ${interfaceSummary.runtimeZones.length > 0 ? interfaceSummary.runtimeZones.map((zone) => `\`${zone.id}\``).join(", ") : "none"}`,
86
+ ].join("\n")
87
+ : null;
64
88
  return [
65
89
  `# ${workflow.label}`,
66
90
  "",
@@ -74,22 +98,38 @@ function renderWorkflowReadme(workflow) {
74
98
  `- ${workflow.purpose.taskHint}`,
75
99
  ]
76
100
  : []),
101
+ ...(inputLines
102
+ ? [
103
+ "",
104
+ "## Inputs",
105
+ "",
106
+ inputLines,
107
+ ]
108
+ : []),
109
+ ...(contextInterfaceLines
110
+ ? [
111
+ "",
112
+ "## Context Interface",
113
+ "",
114
+ ...(contextInterfaceSummaryLines
115
+ ? [
116
+ contextInterfaceSummaryLines,
117
+ "",
118
+ ]
119
+ : []),
120
+ "Zone map:",
121
+ "",
122
+ contextInterfaceLines,
123
+ ]
124
+ : []),
77
125
  "",
78
126
  "## Package",
79
127
  "",
80
128
  "- `workflow.json` = stage graph, compiler API target, and compile contract mapping",
81
- "- `workflow.schema.json` = deterministic zone contract for the workflow package",
129
+ "- `workflow.schema.json` = deterministic context interface for the workflow package",
82
130
  "- `improve/`, `compile/stages/`, and `use/query/` = human-readable authoring docs",
83
131
  "- Portable workflow packages are standalone: explicit stages, schema, and docs live together in this folder",
84
132
  "- Interf projects native agent shells from these docs for query use, stage execution, and workflow-improvement loops",
85
- ...(zoneLines
86
- ? [
87
- "",
88
- "## Zones",
89
- "",
90
- zoneLines,
91
- ]
92
- : []),
93
133
  "",
94
134
  "## Stages",
95
135
  "",
@@ -105,9 +145,9 @@ function renderDerivedWorkflowReadme(options) {
105
145
  "",
106
146
  options.hint,
107
147
  "",
108
- `This workflow package was copied from \`${options.baseWorkflowId}\` and materialized as a standalone package for this task.`,
148
+ `This workflow package was copied from \`${options.baseWorkflowId}\` and materialized as a standalone package for this kind of work.`,
109
149
  "",
110
- "Interf runs the local copy of this package directly. Keep changes in this folder self-contained instead of relying on runtime inheritance or fallback.",
150
+ "Interf runs the local copy of this package directly. Keep purpose, inputs, context interface, and stage docs self-contained in this folder instead of relying on runtime inheritance or fallback.",
111
151
  "",
112
152
  "## Emphasis",
113
153
  "",
@@ -125,7 +165,7 @@ function renderSeedWorkflowReadme(options) {
125
165
  "",
126
166
  `This workflow package was seeded from \`${options.baseWorkflowId}\` as a standalone local draft.`,
127
167
  "",
128
- "Interf runs the local copy of this package directly. Refine the workflow docs, stage instructions, and zone contract in this folder instead of relying on inheritance or runtime fallback.",
168
+ "Interf runs the local copy of this package directly. Refine purpose, inputs, context interface, and stage instructions in this folder instead of relying on inheritance or runtime fallback.",
129
169
  "",
130
170
  ].join("\n");
131
171
  }
@@ -141,13 +181,14 @@ function renderImproveSkill(workflow) {
141
181
  "Default loop:",
142
182
  "1. Read the loop context first.",
143
183
  "2. Review preserved stage shells, runtime logs, and saved test runs from failed attempts.",
144
- "3. Edit only the local workflow package for this compiled context to create a better workflow variation for this task.",
145
- `4. Keep \`workflow.json\`, \`${WORKFLOW_SCHEMA_FILE}\`, and any changed stage docs aligned.`,
184
+ "3. Edit only the local workflow package for this compiled context to create a better workflow variation for this kind of work.",
185
+ `4. Keep purpose, inputs, \`workflow.json\`, \`${CONTEXT_INTERFACE_FILE}\`, and any changed stage docs aligned.`,
146
186
  "",
147
187
  "Guardrails:",
148
188
  "- do not edit checks, test specs, or raw files",
149
189
  "- do not hardcode expected answers into workflow docs",
150
190
  "- keep this package standalone; do not add or rely on runtime `extends` or fallback behavior",
191
+ "- keep the workflow stack coherent: purpose, inputs, context interface, and stages should describe the same job",
151
192
  "- prefer small, defensible workflow changes over random churn",
152
193
  "",
153
194
  ].join("\n");
@@ -214,15 +255,16 @@ export function writeWorkflowPackageToDir(workflowDir, workflow, options = {}) {
214
255
  mkdirSync(join(workflowDir, "compile", "stages", stage.skillDir), { recursive: true });
215
256
  }
216
257
  writeWorkflowPackageJson(workflowDir, workflow, { overwrite });
217
- if (overwrite || !existsSync(join(workflowDir, WORKFLOW_SCHEMA_FILE))) {
218
- if (workflow.schema) {
219
- writeWorkflowSchemaDocument(workflowDir, {
220
- ...workflow.schema,
221
- label: workflow.schema.label || `${workflow.label} workflow schema`,
258
+ if (overwrite || !existsSync(join(workflowDir, CONTEXT_INTERFACE_FILE))) {
259
+ const contextInterface = workflow.contextInterface ?? workflow.schema;
260
+ if (contextInterface) {
261
+ writeContextInterface(workflowDir, {
262
+ ...contextInterface,
263
+ label: contextInterface.label || `${workflow.label} workflow schema`,
222
264
  });
223
265
  }
224
266
  else {
225
- writeWorkflowSchemaFile(workflowDir, workflow.stages, `${workflow.label} workflow schema`);
267
+ writeContextInterfaceFile(workflowDir, workflow.stages, `${workflow.label} workflow schema`);
226
268
  }
227
269
  }
228
270
  if (overwrite || !existsSync(join(workflowDir, "README.md"))) {
@@ -253,10 +295,14 @@ export function seedCompiledWorkflowPackage(options) {
253
295
  copyWorkflowPackageDirectory(sourceWorkflowPath, workflowPackagePath(options.compiledPath));
254
296
  patchWorkflowPackageMetadata(workflowPackagePath(options.compiledPath), {
255
297
  id: resolvedWorkflow.id,
298
+ inputs: resolvedWorkflow.inputs,
256
299
  label: resolvedWorkflow.label,
257
300
  hint: resolvedWorkflow.hint,
258
301
  stagePolicyNotes: resolvedWorkflow.stagePolicyNotes,
259
302
  });
303
+ if (resolvedWorkflow.scope === "builtin") {
304
+ writeFileSync(join(workflowPackagePath(options.compiledPath), "README.md"), renderWorkflowReadme(resolvedWorkflow));
305
+ }
260
306
  return;
261
307
  }
262
308
  // Legacy or partially-defined seed packages are resolved once and
@@ -296,6 +342,9 @@ export function createLocalWorkflowPackageFromTemplate(options) {
296
342
  return targetPath;
297
343
  }
298
344
  export function seedLocalWorkflowPackageFromBase(options) {
345
+ const baseWorkflow = getCompiledWorkflow(options.baseWorkflowId, {
346
+ sourcePath: options.sourcePath,
347
+ });
299
348
  const sourceWorkflowPath = resolveWorkflowPackageSourcePath(options.sourcePath, options.baseWorkflowId);
300
349
  const targetPath = workflowDefinitionPath(options.sourcePath, options.workflowId);
301
350
  if (sourceWorkflowPath && isPortableWorkflowPackage(sourceWorkflowPath)) {
@@ -303,6 +352,7 @@ export function seedLocalWorkflowPackageFromBase(options) {
303
352
  copyWorkflowPackageDirectory(sourceWorkflowPath, targetPath);
304
353
  patchWorkflowPackageMetadata(targetPath, {
305
354
  id: options.workflowId,
355
+ inputs: baseWorkflow.inputs,
306
356
  label: options.label,
307
357
  hint: options.hint,
308
358
  });
@@ -315,9 +365,6 @@ export function seedLocalWorkflowPackageFromBase(options) {
315
365
  }
316
366
  // Legacy or inherited base packages are materialized immediately so the new
317
367
  // local workflow package is standalone from its first write.
318
- const baseWorkflow = getCompiledWorkflow(options.baseWorkflowId, {
319
- sourcePath: options.sourcePath,
320
- });
321
368
  const localWorkflow = {
322
369
  ...baseWorkflow,
323
370
  id: options.workflowId,
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
- import { WorkflowCompilerApiSchema, RuntimeContractTypeSchema, RuntimeStageAcceptanceSchema, WorkflowPurposeSchema, WorkflowStageZoneAccessSchema, type WorkflowCompiledSchema } from "../compiler/lib/schema.js";
2
+ import { WorkflowCompilerApiSchema, RuntimeContractTypeSchema, RuntimeStageAcceptanceSchema, WorkflowPurposeSchema, WorkflowStageZoneAccessSchema } from "../compiler/lib/schema.js";
3
+ import { WorkflowInputSpecSchema, type ContextInterface, type WorkflowInputSpec } from "./context-interface.js";
3
4
  export interface LocalWorkflowStarterDoc {
4
5
  relativePath: string;
5
6
  content: string;
@@ -19,12 +20,13 @@ export interface LocalWorkflowDefinition {
19
20
  type: "compiled";
20
21
  compiler_api?: z.infer<typeof WorkflowCompilerApiSchema>;
21
22
  purpose?: z.infer<typeof WorkflowPurposeSchema>;
23
+ inputs?: Array<z.infer<typeof WorkflowInputSpecSchema>>;
22
24
  label: string;
23
25
  hint: string;
24
26
  extends?: string;
25
27
  stages?: LocalWorkflowStageDefinition[];
26
28
  stage_policy_notes?: Record<string, string[]>;
27
- workflow_schema: WorkflowCompiledSchema;
29
+ workflow_schema: ContextInterface;
28
30
  starter_docs: LocalWorkflowStarterDoc[];
29
31
  directoryPath: string;
30
32
  workflowPath: string;
@@ -38,6 +40,7 @@ export declare function resolveWorkflowPackageSourcePath(sourcePath: string, wor
38
40
  export declare function isWorkflowId(value: string): boolean;
39
41
  export declare function patchWorkflowPackageMetadata(dirPath: string, options?: {
40
42
  id?: string;
43
+ inputs?: WorkflowInputSpec[];
41
44
  label?: string;
42
45
  hint?: string;
43
46
  stagePolicyNotes?: Record<string, string[]>;
@@ -1,13 +1,13 @@
1
1
  import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, } from "node:fs";
2
2
  import { dirname, join, relative } from "node:path";
3
3
  import { z } from "zod";
4
- import { listFilesRecursive } from "../../lib/filesystem.js";
5
- import { warnInterf } from "../../lib/logger.js";
6
- import { readJsonFileUnchecked, readJsonFileWithSchema } from "../../lib/parse.js";
7
- import { isMarkdownFile } from "../../lib/util.js";
8
- import { WORKFLOW_SCHEMA_FILE as WORKFLOW_SCHEMA_FILENAME, workflowSchemaExists, writeWorkflowSchemaDocument, workflowSchemaFilePath, readWorkflowSchemaFile, } from "../compiler/compiled-schema.js";
4
+ import { listFilesRecursive } from "../shared/filesystem.js";
5
+ import { warnInterf } from "../shared/logger.js";
6
+ import { readJsonFileUnchecked, readJsonFileWithSchema } from "../shared/parse.js";
7
+ import { isMarkdownFile } from "../shared/file-types.js";
9
8
  import { WorkflowCompilerApiSchema, RuntimeContractTypeSchema, RuntimeStageAcceptanceSchema, WorkflowPurposeSchema, WorkflowStageZoneAccessSchema, WorkflowIdPattern, } from "../compiler/lib/schema.js";
10
9
  import { listBuiltinCompiledZoneSpecs, } from "./builtin-compiled-workflow.js";
10
+ import { CONTEXT_INTERFACE_FILE, contextInterfaceExists, contextInterfaceFilePath, readContextInterface, WorkflowInputSpecSchema, writeContextInterface, } from "./context-interface.js";
11
11
  import { PACKAGE_ROOT } from "./lib/package-root.js";
12
12
  import { mergeStagePolicyNotesForStages } from "./workflow-stage-policy.js";
13
13
  const LocalWorkflowStageDefinitionSchema = z.object({
@@ -25,6 +25,7 @@ const LocalWorkflowDefinitionSchema = z.object({
25
25
  type: z.literal("compiled"),
26
26
  compiler_api: WorkflowCompilerApiSchema.optional(),
27
27
  purpose: WorkflowPurposeSchema.optional(),
28
+ inputs: z.array(WorkflowInputSpecSchema).min(1).optional(),
28
29
  label: z.string().min(1),
29
30
  hint: z.string().min(1),
30
31
  extends: z.string().regex(WorkflowIdPattern).optional(),
@@ -64,7 +65,7 @@ function collectStarterDocs(dirPath) {
64
65
  function workflowPackageCopyPaths(dirPath) {
65
66
  return [
66
67
  "workflow.json",
67
- WORKFLOW_SCHEMA_FILENAME,
68
+ CONTEXT_INTERFACE_FILE,
68
69
  ...collectStarterDocs(dirPath).map((doc) => doc.relativePath),
69
70
  ];
70
71
  }
@@ -92,7 +93,7 @@ export function loadWorkflowDefinitionFromDir(dirPath) {
92
93
  const definition = readJsonFileWithSchema(workflowPath, "local workflow definition", LocalWorkflowDefinitionSchema);
93
94
  if (!definition)
94
95
  return null;
95
- const workflowSchema = readWorkflowSchemaFile(dirPath);
96
+ const workflowSchema = readContextInterface(dirPath);
96
97
  if (!workflowSchema)
97
98
  return null;
98
99
  if (definition.type !== "compiled") {
@@ -105,7 +106,7 @@ export function loadWorkflowDefinitionFromDir(dirPath) {
105
106
  starter_docs: collectStarterDocs(dirPath),
106
107
  directoryPath: dirPath,
107
108
  workflowPath,
108
- workflowSchemaPath: workflowSchemaFilePath(dirPath),
109
+ workflowSchemaPath: contextInterfaceFilePath(dirPath),
109
110
  };
110
111
  }
111
112
  export function listLocalWorkflowDefinitions(sourcePath) {
@@ -169,6 +170,7 @@ export function patchWorkflowPackageMetadata(dirPath, options = {}) {
169
170
  },
170
171
  stages: normalizedStages,
171
172
  ...(options.id ? { id: options.id } : {}),
173
+ ...(options.inputs && options.inputs.length > 0 ? { inputs: options.inputs } : {}),
172
174
  ...(options.label ? { label: options.label } : {}),
173
175
  ...(options.hint ? { hint: options.hint } : {}),
174
176
  };
@@ -182,11 +184,11 @@ export function patchWorkflowPackageMetadata(dirPath, options = {}) {
182
184
  }
183
185
  writeFileSync(workflowPath, JSON.stringify(nextWorkflowJson, null, 2) + "\n");
184
186
  const schemaLabel = `${String(nextWorkflowJson.label ?? workflowJson.label ?? options.id ?? "Workflow")} workflow schema`;
185
- const existingSchema = readWorkflowSchemaFile(dirPath);
187
+ const existingSchema = readContextInterface(dirPath);
186
188
  if (!existingSchema) {
187
- throw new Error(`Cannot patch workflow package at ${dirPath}: missing ${WORKFLOW_SCHEMA_FILENAME}. Restore or reseed the package instead of regenerating a schema from workflow.json.`);
189
+ throw new Error(`Cannot patch workflow package at ${dirPath}: missing ${CONTEXT_INTERFACE_FILE}. Restore or reseed the package instead of regenerating a schema from workflow.json.`);
188
190
  }
189
- writeWorkflowSchemaDocument(dirPath, {
191
+ writeContextInterface(dirPath, {
190
192
  ...existingSchema,
191
193
  label: schemaLabel,
192
194
  });
@@ -196,7 +198,7 @@ function collectWorkflowPackageStructureIssues(dirPath, stages) {
196
198
  const workflowPath = join(dirPath, "workflow.json");
197
199
  if (!existsSync(workflowPath))
198
200
  issues.push("missing workflow.json");
199
- if (!workflowSchemaExists(dirPath))
201
+ if (!contextInterfaceExists(dirPath))
200
202
  issues.push("missing workflow.schema.json");
201
203
  if (!existsSync(join(dirPath, "README.md")))
202
204
  issues.push("missing README.md");
@@ -323,7 +325,7 @@ export function validateWorkflowPackage(dirPath) {
323
325
  : issue;
324
326
  errors.push(formatted);
325
327
  }
326
- const workflowSchema = readWorkflowSchemaFile(dirPath);
328
+ const workflowSchema = readContextInterface(dirPath);
327
329
  if (!workflowSchema) {
328
330
  errors.push("workflow.schema.json is missing or invalid.");
329
331
  }
@@ -1,4 +1,5 @@
1
- import type { RuntimeContractType, RuntimeStageAcceptance, WorkflowCompilerApi, WorkflowCompiledSchema, WorkflowId, WorkflowZoneId } from "../compiler/lib/schema.js";
1
+ import type { RuntimeContractType, RuntimeStageAcceptance, WorkflowCompilerApi, WorkflowId } from "../compiler/lib/schema.js";
2
+ import { type ContextInterface, type ContextInterfaceZoneId, type WorkflowInputSpec } from "./context-interface.js";
2
3
  export interface WorkflowStarterDoc {
3
4
  relativePath: string;
4
5
  content: string;
@@ -9,8 +10,8 @@ export interface WorkflowStageDefinition {
9
10
  description: string;
10
11
  contractType: RuntimeContractType;
11
12
  skillDir: string;
12
- reads: WorkflowZoneId[];
13
- writes: WorkflowZoneId[];
13
+ reads: ContextInterfaceZoneId[];
14
+ writes: ContextInterfaceZoneId[];
14
15
  acceptance?: RuntimeStageAcceptance;
15
16
  }
16
17
  export interface WorkflowDefinition<TId extends string> {
@@ -20,10 +21,12 @@ export interface WorkflowDefinition<TId extends string> {
20
21
  label: string;
21
22
  taskHint: string;
22
23
  };
24
+ inputs?: WorkflowInputSpec[];
23
25
  label: string;
24
26
  hint: string;
25
27
  recommended?: boolean;
26
- schema?: WorkflowCompiledSchema;
28
+ contextInterface?: ContextInterface;
29
+ schema?: ContextInterface;
27
30
  stages: WorkflowStageDefinition[];
28
31
  stagePolicyNotes?: Record<string, string[]>;
29
32
  starterDocs?: WorkflowStarterDoc[];
@@ -37,6 +40,7 @@ export declare function standaloneWorkflowDefinitionFromLocalPackage(local: {
37
40
  label: string;
38
41
  task_hint: string;
39
42
  };
43
+ inputs?: WorkflowInputSpec[];
40
44
  label: string;
41
45
  hint: string;
42
46
  stages?: Array<{
@@ -45,12 +49,12 @@ export declare function standaloneWorkflowDefinitionFromLocalPackage(local: {
45
49
  description?: string;
46
50
  contract_type: RuntimeContractType;
47
51
  skill_dir?: string;
48
- reads: WorkflowZoneId[];
49
- writes: WorkflowZoneId[];
52
+ reads: ContextInterfaceZoneId[];
53
+ writes: ContextInterfaceZoneId[];
50
54
  acceptance?: RuntimeStageAcceptance;
51
55
  }>;
52
56
  stage_policy_notes?: Record<string, string[]>;
53
- workflow_schema?: WorkflowCompiledSchema;
57
+ workflow_schema?: ContextInterface;
54
58
  starter_docs: WorkflowStarterDoc[];
55
59
  }): WorkflowDefinition<string>;
56
60
  export declare function listCompiledWorkflowChoices(sourcePath?: string): WorkflowDefinition<string>[];
@@ -1,10 +1,11 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { isWorkflowId, listLocalWorkflowDefinitions, loadLocalWorkflowDefinition, loadWorkflowDefinitionFromDir, } from "./local-workflows.js";
4
- import { warnInterf } from "../../lib/logger.js";
5
- import { workflowPackagePathForCompiled } from "../project-model/compiled-paths.js";
4
+ import { warnInterf } from "../shared/logger.js";
5
+ import { workflowPackagePathForCompiled } from "../compiler/compiled-paths.js";
6
6
  import { resolveSourceControlPath } from "../project-model/interf.js";
7
7
  import { PACKAGE_ROOT } from "./lib/package-root.js";
8
+ import { deriveWorkflowInputsFromContextInterface, } from "./context-interface.js";
8
9
  import { mergeStagePolicyNotesForStages } from "./workflow-stage-policy.js";
9
10
  let builtinInterfWorkflowCache = null;
10
11
  function toWorkflowStages(stages, fallbackStages) {
@@ -26,6 +27,10 @@ export function standaloneWorkflowDefinitionFromLocalPackage(local) {
26
27
  throw new Error(`Workflow package "${local.id}" is missing explicit stages. Compiled-local and portable workflow packages must be standalone.`);
27
28
  }
28
29
  const stages = toWorkflowStages(local.stages, []);
30
+ const contextInterface = local.workflow_schema;
31
+ const inputs = local.inputs?.length
32
+ ? [...local.inputs]
33
+ : deriveWorkflowInputsFromContextInterface(contextInterface);
29
34
  return {
30
35
  id: local.id,
31
36
  compilerApi: local.compiler_api ?? {
@@ -40,10 +45,12 @@ export function standaloneWorkflowDefinitionFromLocalPackage(local) {
40
45
  },
41
46
  }
42
47
  : {}),
48
+ inputs,
43
49
  label: local.label,
44
50
  hint: local.hint,
45
51
  recommended: false,
46
- ...(local.workflow_schema ? { schema: local.workflow_schema } : {}),
52
+ contextInterface,
53
+ ...(contextInterface ? { schema: contextInterface } : {}),
47
54
  stages,
48
55
  stagePolicyNotes: mergeStagePolicyNotesForStages(stages, undefined, local.stage_policy_notes),
49
56
  starterDocs: [...local.starter_docs],
@@ -1,10 +1,10 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { join, relative, sep } from "node:path";
3
- import { listFilesRecursive } from "../../lib/filesystem.js";
4
- import { parseJsonFrontmatter } from "../../lib/parse.js";
5
- import { isMarkdownFile } from "../../lib/util.js";
3
+ import { listFilesRecursive } from "../shared/filesystem.js";
4
+ import { parseJsonFrontmatter } from "../shared/parse.js";
5
+ import { isMarkdownFile } from "../shared/file-types.js";
6
6
  import { getCompiledWorkflow, } from "./workflow-definitions.js";
7
- import { workflowPackagePathForCompiled } from "../project-model/compiled-paths.js";
7
+ import { workflowPackagePathForCompiled } from "../compiler/compiled-paths.js";
8
8
  const LOCAL_SKILL_READ_LIMIT = 50;
9
9
  export function workflowQueryDirectory() {
10
10
  return "workflow/use/query";
@@ -1,5 +1,5 @@
1
1
  import { existsSync } from "node:fs";
2
- import { testRootForCompiled, targetTestRunsRootForCompiled, targetTestSandboxesRootForCompiled, stageExecutionShellsRoot, compiledRuntimeRoot, } from "../project-model/compiled-paths.js";
2
+ import { testRootForCompiled, targetTestRunsRootForCompiled, targetTestSandboxesRootForCompiled, stageExecutionShellsRoot, compiledRuntimeRoot, } from "../compiler/compiled-paths.js";
3
3
  export function resolveWorkflowImprovementReviewSourcePaths(compiledPath) {
4
4
  const compiledRuntime = compiledRuntimeRoot(compiledPath);
5
5
  const testComparisons = testRootForCompiled(compiledPath);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@interf/compiler",
3
- "version": "0.6.3",
4
- "description": "Interf prepares task context for your agents by testing the files behind a task, building a local context folder, and using self-improving loops until checks pass.",
3
+ "version": "0.6.4",
4
+ "description": "Interf prepares context for your agents by checking your files first, building a local folder when needed, and using self-improving loops until more questions pass.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "interf": "dist/bin.js"