@yycholla/pi-dynamic-workflows 3.3.0
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/LICENSE +22 -0
- package/README.md +325 -0
- package/assets/readme/hero.png +0 -0
- package/assets/readme/hero.svg +70 -0
- package/assets/readme/package-cover.png +0 -0
- package/assets/readme/package-cover.svg +66 -0
- package/assets/readme/workflow.png +0 -0
- package/assets/readme/workflow.svg +77 -0
- package/dist/accept-workflow-guidance.d.ts +14 -0
- package/dist/accept-workflow-guidance.js +53 -0
- package/dist/adversarial-review.d.ts +30 -0
- package/dist/adversarial-review.js +107 -0
- package/dist/agent-history.d.ts +20 -0
- package/dist/agent-history.js +122 -0
- package/dist/agent-registry.d.ts +83 -0
- package/dist/agent-registry.js +190 -0
- package/dist/agent.d.ts +364 -0
- package/dist/agent.js +714 -0
- package/dist/builtin-commands.d.ts +19 -0
- package/dist/builtin-commands.js +251 -0
- package/dist/builtin-workflows.d.ts +45 -0
- package/dist/builtin-workflows.js +121 -0
- package/dist/code-review.d.ts +26 -0
- package/dist/code-review.js +181 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.js +44 -0
- package/dist/deep-research.d.ts +30 -0
- package/dist/deep-research.js +124 -0
- package/dist/display.d.ts +134 -0
- package/dist/display.js +248 -0
- package/dist/effort-command.d.ts +28 -0
- package/dist/effort-command.js +68 -0
- package/dist/enums.d.ts +69 -0
- package/dist/enums.js +78 -0
- package/dist/errors.d.ts +113 -0
- package/dist/errors.js +140 -0
- package/dist/extension-reload.d.ts +37 -0
- package/dist/extension-reload.js +78 -0
- package/dist/fs-persistence.d.ts +63 -0
- package/dist/fs-persistence.js +102 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.js +35 -0
- package/dist/logger.d.ts +21 -0
- package/dist/logger.js +66 -0
- package/dist/model-routing.d.ts +30 -0
- package/dist/model-routing.js +50 -0
- package/dist/model-spec.d.ts +29 -0
- package/dist/model-spec.js +252 -0
- package/dist/model-tier-config.d.ts +133 -0
- package/dist/model-tier-config.js +249 -0
- package/dist/run-persistence.d.ts +180 -0
- package/dist/run-persistence.js +294 -0
- package/dist/saved-commands.d.ts +28 -0
- package/dist/saved-commands.js +100 -0
- package/dist/shared-store.d.ts +98 -0
- package/dist/shared-store.js +212 -0
- package/dist/structured-output.d.ts +19 -0
- package/dist/structured-output.js +30 -0
- package/dist/task-panel.d.ts +61 -0
- package/dist/task-panel.js +422 -0
- package/dist/usage-limit-scheduler.d.ts +145 -0
- package/dist/usage-limit-scheduler.js +368 -0
- package/dist/web-tools.d.ts +20 -0
- package/dist/web-tools.js +120 -0
- package/dist/workflow-authoring-coverage.d.ts +70 -0
- package/dist/workflow-authoring-coverage.js +421 -0
- package/dist/workflow-authoring-reference.d.ts +20 -0
- package/dist/workflow-authoring-reference.js +156 -0
- package/dist/workflow-capability-contract.d.ts +131 -0
- package/dist/workflow-capability-contract.js +604 -0
- package/dist/workflow-commands.d.ts +18 -0
- package/dist/workflow-commands.js +260 -0
- package/dist/workflow-comprehension.d.ts +133 -0
- package/dist/workflow-comprehension.js +1321 -0
- package/dist/workflow-context-measurement.d.ts +72 -0
- package/dist/workflow-context-measurement.js +213 -0
- package/dist/workflow-control-tool.d.ts +30 -0
- package/dist/workflow-control-tool.js +176 -0
- package/dist/workflow-delivery-choice.d.ts +20 -0
- package/dist/workflow-delivery-choice.js +48 -0
- package/dist/workflow-editor.d.ts +93 -0
- package/dist/workflow-editor.js +363 -0
- package/dist/workflow-manager.d.ts +492 -0
- package/dist/workflow-manager.js +1124 -0
- package/dist/workflow-paths.d.ts +22 -0
- package/dist/workflow-paths.js +46 -0
- package/dist/workflow-release-gate.d.ts +39 -0
- package/dist/workflow-release-gate.js +309 -0
- package/dist/workflow-saved.d.ts +38 -0
- package/dist/workflow-saved.js +126 -0
- package/dist/workflow-settings.d.ts +70 -0
- package/dist/workflow-settings.js +131 -0
- package/dist/workflow-tool.d.ts +71 -0
- package/dist/workflow-tool.js +367 -0
- package/dist/workflow-ui.d.ts +182 -0
- package/dist/workflow-ui.js +1587 -0
- package/dist/workflow.d.ts +333 -0
- package/dist/workflow.js +1151 -0
- package/dist/workflows-models-command.d.ts +31 -0
- package/dist/workflows-models-command.js +156 -0
- package/dist/worktree.d.ts +25 -0
- package/dist/worktree.js +61 -0
- package/extensions/workflow.ts +151 -0
- package/package.json +104 -0
- package/skills/workflow-authoring/SKILL.md +30 -0
- package/skills/workflow-authoring/examples/adversarial-verification.js +63 -0
- package/skills/workflow-authoring/examples/bounded-semantic-retry.js +56 -0
- package/skills/workflow-authoring/examples/classify-and-act.js +67 -0
- package/skills/workflow-authoring/examples/fan-out-and-synthesize.js +47 -0
- package/skills/workflow-authoring/examples/generate-and-filter.js +68 -0
- package/skills/workflow-authoring/examples/loop-until-done.js +68 -0
- package/skills/workflow-authoring/examples/phased-budgets.js +75 -0
- package/skills/workflow-authoring/examples/saved-nested-workflows.js +44 -0
- package/skills/workflow-authoring/examples/structured-output.js +37 -0
- package/skills/workflow-authoring/examples/tournament.js +81 -0
- package/skills/workflow-authoring/examples/validated-gate.js +63 -0
- package/skills/workflow-authoring/references/capabilities.md +41 -0
- package/skills/workflow-authoring/references/capability-details.md +357 -0
- package/skills/workflow-authoring/references/common-helpers.md +4 -0
- package/skills/workflow-authoring/references/debugging.md +27 -0
- package/skills/workflow-authoring/references/focused-recipes.md +11 -0
- package/skills/workflow-authoring/references/helpers.md +9 -0
- package/skills/workflow-authoring/references/lifecycle.md +33 -0
- package/skills/workflow-authoring/references/pattern-selection.md +15 -0
- package/skills/workflow-authoring/references/quality-helpers.md +8 -0
- package/skills/workflow-authoring/references/registry-ownership.md +15 -0
- package/skills/workflow-authoring/references/retry-helper.md +5 -0
- package/skills/workflow-authoring/references/review.md +43 -0
- package/skills/workflow-authoring/references/runtime.md +27 -0
- package/skills/workflow-authoring/references/specialized-helpers.md +19 -0
- package/skills/workflow-authoring/references/versions.md +13 -0
- package/skills/workflow-patterns/SKILL.md +51 -0
- package/src/accept-workflow-guidance.ts +71 -0
- package/src/adversarial-review.ts +120 -0
- package/src/agent-history.ts +157 -0
- package/src/agent-registry.ts +221 -0
- package/src/agent.ts +929 -0
- package/src/builtin-commands.ts +286 -0
- package/src/builtin-workflows.ts +155 -0
- package/src/code-review.ts +183 -0
- package/src/config.ts +55 -0
- package/src/deep-research.ts +135 -0
- package/src/display.ts +367 -0
- package/src/effort-command.ts +87 -0
- package/src/enums.ts +77 -0
- package/src/errors.ts +199 -0
- package/src/extension-reload.ts +100 -0
- package/src/fs-persistence.ts +124 -0
- package/src/index.ts +176 -0
- package/src/logger.ts +88 -0
- package/src/model-routing.ts +73 -0
- package/src/model-spec.ts +309 -0
- package/src/model-tier-config.ts +296 -0
- package/src/run-persistence.ts +484 -0
- package/src/saved-commands.ts +115 -0
- package/src/shared-store.ts +228 -0
- package/src/structured-output.ts +47 -0
- package/src/task-panel.ts +490 -0
- package/src/usage-limit-scheduler.ts +432 -0
- package/src/web-tools.ts +124 -0
- package/src/workflow-authoring-coverage.ts +486 -0
- package/src/workflow-authoring-reference.ts +186 -0
- package/src/workflow-capability-contract.ts +806 -0
- package/src/workflow-commands.ts +287 -0
- package/src/workflow-comprehension.ts +1673 -0
- package/src/workflow-context-measurement.ts +262 -0
- package/src/workflow-control-tool.ts +238 -0
- package/src/workflow-delivery-choice.ts +69 -0
- package/src/workflow-editor.ts +444 -0
- package/src/workflow-manager.ts +1405 -0
- package/src/workflow-paths.ts +63 -0
- package/src/workflow-release-gate.ts +529 -0
- package/src/workflow-saved.ts +180 -0
- package/src/workflow-settings.ts +194 -0
- package/src/workflow-tool.ts +464 -0
- package/src/workflow-ui.ts +1789 -0
- package/src/workflow.ts +1615 -0
- package/src/workflows-models-command.ts +211 -0
- package/src/worktree.ts +76 -0
|
@@ -0,0 +1,806 @@
|
|
|
1
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
2
|
+
import {
|
|
3
|
+
CapabilityClassification,
|
|
4
|
+
CapabilityOrigin,
|
|
5
|
+
CapabilitySupport,
|
|
6
|
+
DiagnosticSeverity,
|
|
7
|
+
DiscoveryPlacement,
|
|
8
|
+
} from "./enums.js";
|
|
9
|
+
import { WorkflowCapabilityContractError } from "./errors.js";
|
|
10
|
+
|
|
11
|
+
/** Re-exported capability domains used by contract consumers. */
|
|
12
|
+
export {
|
|
13
|
+
CapabilityClassification,
|
|
14
|
+
CapabilityOrigin,
|
|
15
|
+
CapabilitySupport,
|
|
16
|
+
DiagnosticSeverity,
|
|
17
|
+
DiscoveryPlacement,
|
|
18
|
+
} from "./enums.js";
|
|
19
|
+
|
|
20
|
+
/** Version marker for behavior present at or after a release. */
|
|
21
|
+
export interface PresentAtVersion {
|
|
22
|
+
kind: "present-at";
|
|
23
|
+
version: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** One named option and the facts safe to publish about it. */
|
|
27
|
+
export interface OptionDescriptor {
|
|
28
|
+
name: string;
|
|
29
|
+
type: string;
|
|
30
|
+
optional: boolean;
|
|
31
|
+
default: string | null;
|
|
32
|
+
constraints: readonly string[];
|
|
33
|
+
dynamicReference: "model-routes" | "agent-types" | null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Reusable option group referenced by capability descriptors. */
|
|
37
|
+
export interface OptionShape {
|
|
38
|
+
id:
|
|
39
|
+
| "agent-options"
|
|
40
|
+
| "checkpoint-options"
|
|
41
|
+
| "phase-options"
|
|
42
|
+
| "verify-options"
|
|
43
|
+
| "judge-panel-options"
|
|
44
|
+
| "loop-until-dry-options"
|
|
45
|
+
| "retry-options"
|
|
46
|
+
| "gate-options";
|
|
47
|
+
options: readonly OptionDescriptor[];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Authoritative declaration of one workflow capability and its evidence. */
|
|
51
|
+
export interface CapabilityDescriptor {
|
|
52
|
+
id: `workflow.${string}`;
|
|
53
|
+
label: string;
|
|
54
|
+
classification: CapabilityClassification;
|
|
55
|
+
support: CapabilitySupport;
|
|
56
|
+
discovery: DiscoveryPlacement;
|
|
57
|
+
origin: CapabilityOrigin;
|
|
58
|
+
lifecycle: PresentAtVersion;
|
|
59
|
+
signature: string | null;
|
|
60
|
+
optionShape: OptionShape["id"] | null;
|
|
61
|
+
constraints: readonly string[];
|
|
62
|
+
enforcementOwner: string;
|
|
63
|
+
runtimeBinding: { global: string; implementation: string; allowsUndefined?: true } | null;
|
|
64
|
+
behaviorEvidence: readonly string[];
|
|
65
|
+
staticReference: { path: string; anchor: string } | null;
|
|
66
|
+
dynamicReference: "model-routes" | "agent-types" | null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Ownership and item shape for a live catalogue that static docs must not embed. */
|
|
70
|
+
export interface DynamicReferenceDescriptor {
|
|
71
|
+
id: "model-routes" | "agent-types";
|
|
72
|
+
owner: "model-tier-config" | "agent-registry";
|
|
73
|
+
itemShape: string;
|
|
74
|
+
connection: string;
|
|
75
|
+
items?: never;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Versioned plain-data source for runtime assembly and generated documentation. */
|
|
79
|
+
export interface WorkflowCapabilityDefinition {
|
|
80
|
+
versions: {
|
|
81
|
+
extension: string;
|
|
82
|
+
format: PresentAtVersion;
|
|
83
|
+
content: PresentAtVersion;
|
|
84
|
+
};
|
|
85
|
+
optionShapes: readonly OptionShape[];
|
|
86
|
+
capabilities: readonly CapabilityDescriptor[];
|
|
87
|
+
dynamicReferences: readonly DynamicReferenceDescriptor[];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Machine-readable disagreement between the contract and an observed surface. */
|
|
91
|
+
export interface CapabilityDiagnostic {
|
|
92
|
+
code:
|
|
93
|
+
| "MISSING_RUNTIME_IMPLEMENTATION"
|
|
94
|
+
| "UNDECLARED_RUNTIME_IMPLEMENTATION"
|
|
95
|
+
| "DECLARED_GLOBAL_UNOBSERVED"
|
|
96
|
+
| "OBSERVED_GLOBAL_UNDECLARED"
|
|
97
|
+
| "INVALID_CAPABILITY_DEFINITION";
|
|
98
|
+
severity: DiagnosticSeverity;
|
|
99
|
+
subject: string;
|
|
100
|
+
message: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Re-exported contract failure type retained for existing consumers. */
|
|
104
|
+
export { WorkflowCapabilityContractError } from "./errors.js";
|
|
105
|
+
|
|
106
|
+
/** Runtime globals assembled from declared implementations plus non-fatal diagnostics. */
|
|
107
|
+
export interface RuntimeBindingAssembly {
|
|
108
|
+
globals: Readonly<Record<string, unknown>>;
|
|
109
|
+
diagnostics: readonly CapabilityDiagnostic[];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Project-owned implementations required to assemble the workflow VM context. */
|
|
113
|
+
export interface WorkflowRuntimeImplementations {
|
|
114
|
+
agent: unknown;
|
|
115
|
+
parallel: unknown;
|
|
116
|
+
pipeline: unknown;
|
|
117
|
+
workflow: unknown;
|
|
118
|
+
verify: unknown;
|
|
119
|
+
judgePanel: unknown;
|
|
120
|
+
loopUntilDry: unknown;
|
|
121
|
+
completenessCheck: unknown;
|
|
122
|
+
retry: unknown;
|
|
123
|
+
gate: unknown;
|
|
124
|
+
checkpoint: unknown;
|
|
125
|
+
log: unknown;
|
|
126
|
+
phase: unknown;
|
|
127
|
+
args: unknown;
|
|
128
|
+
cwd: unknown;
|
|
129
|
+
process: unknown;
|
|
130
|
+
budget: unknown;
|
|
131
|
+
console: unknown;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Exact static projection of one capability for generated references. */
|
|
135
|
+
export interface StaticCapabilityFact {
|
|
136
|
+
id: string;
|
|
137
|
+
label: string;
|
|
138
|
+
classification: CapabilityClassification;
|
|
139
|
+
support: CapabilitySupport;
|
|
140
|
+
signature: string | null;
|
|
141
|
+
options: OptionShape | null;
|
|
142
|
+
constraints: readonly string[];
|
|
143
|
+
reference: string | null;
|
|
144
|
+
dynamicReference: DynamicReferenceDescriptor | null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Runtime implementations or observed globals used for drift diagnostics. */
|
|
148
|
+
export interface AlignmentEvidence {
|
|
149
|
+
suppliedImplementations?: Readonly<Record<string, unknown>>;
|
|
150
|
+
observedProjectGlobals?: readonly string[];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Validated capability contract with runtime, publication, and alignment projections. */
|
|
154
|
+
export interface WorkflowCapabilityContract {
|
|
155
|
+
readonly definition: WorkflowCapabilityDefinition;
|
|
156
|
+
assembleRuntimeBindings(implementations: Readonly<Record<string, unknown>>): RuntimeBindingAssembly;
|
|
157
|
+
projectStaticReferenceFacts(): readonly StaticCapabilityFact[];
|
|
158
|
+
diagnoseAlignment(evidence: AlignmentEvidence): readonly CapabilityDiagnostic[];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const REFERENCE_PATH = "skills/workflow-authoring/references/capability-details.md";
|
|
162
|
+
const PRESENT_AT: PresentAtVersion = { kind: "present-at", version: packageJson.version };
|
|
163
|
+
const noOptions = [] as const;
|
|
164
|
+
|
|
165
|
+
const option = (
|
|
166
|
+
name: string,
|
|
167
|
+
type: string,
|
|
168
|
+
optional: boolean,
|
|
169
|
+
defaultValue: string | null = null,
|
|
170
|
+
constraints: readonly string[] = noOptions,
|
|
171
|
+
dynamicReference: OptionDescriptor["dynamicReference"] = null,
|
|
172
|
+
): OptionDescriptor => ({ name, type, optional, default: defaultValue, constraints, dynamicReference });
|
|
173
|
+
|
|
174
|
+
const AGENT_OPTIONS: OptionShape = {
|
|
175
|
+
id: "agent-options",
|
|
176
|
+
options: [
|
|
177
|
+
option("label", "string", true, "derived from phase and call count"),
|
|
178
|
+
option("phase", "string", true, "current phase"),
|
|
179
|
+
option("schema", "plain JSON Schema", true),
|
|
180
|
+
option("model", "string", true, null, ["highest-priority exact model selector"]),
|
|
181
|
+
option("tier", "string", true, null, ["configured route name"], "model-routes"),
|
|
182
|
+
option("isolation", '"worktree"', true),
|
|
183
|
+
option("agentType", "string", true, null, ["must come from provided context"], "agent-types"),
|
|
184
|
+
option("timeoutMs", "number | null", true, "run timeout; null disables"),
|
|
185
|
+
option("retries", "number", true, "run retry count", ["finite values are floored and clamped to 0..3"]),
|
|
186
|
+
],
|
|
187
|
+
};
|
|
188
|
+
const CHECKPOINT_OPTIONS: OptionShape = {
|
|
189
|
+
id: "checkpoint-options",
|
|
190
|
+
options: [
|
|
191
|
+
option("default", "unknown", true, "true when no UI and omitted"),
|
|
192
|
+
option("headless", '"default" | "abort"', true, '"default"'),
|
|
193
|
+
option("kind", '"confirm" | "input" | "select"', true, '"confirm"'),
|
|
194
|
+
option("choices", "string[]", true),
|
|
195
|
+
option("timeoutMs", "number", true),
|
|
196
|
+
],
|
|
197
|
+
};
|
|
198
|
+
const PHASE_OPTIONS: OptionShape = {
|
|
199
|
+
id: "phase-options",
|
|
200
|
+
options: [option("budget", "number", true, null, ["positive soft pre-call token gate"])],
|
|
201
|
+
};
|
|
202
|
+
const VERIFY_OPTIONS: OptionShape = {
|
|
203
|
+
id: "verify-options",
|
|
204
|
+
options: [
|
|
205
|
+
option("reviewers", "number", true, "2", ["authors should provide a finite integer; runtime clamps below 1"]),
|
|
206
|
+
option("threshold", "number", true, "0.5"),
|
|
207
|
+
option("lens", "string | string[]", true),
|
|
208
|
+
],
|
|
209
|
+
};
|
|
210
|
+
const JUDGE_PANEL_OPTIONS: OptionShape = {
|
|
211
|
+
id: "judge-panel-options",
|
|
212
|
+
options: [
|
|
213
|
+
option("judges", "number", true, "3", ["authors should provide a finite integer; runtime clamps below 1"]),
|
|
214
|
+
option("rubric", "string", true, '"overall quality and correctness"'),
|
|
215
|
+
],
|
|
216
|
+
};
|
|
217
|
+
const LOOP_UNTIL_DRY_OPTIONS: OptionShape = {
|
|
218
|
+
id: "loop-until-dry-options",
|
|
219
|
+
options: [
|
|
220
|
+
option("round", "(roundIndex: number) => unknown[] | Promise<unknown[]>", false),
|
|
221
|
+
option("key", "(item: unknown) => string", true, "JSON.stringify"),
|
|
222
|
+
option("consecutiveEmpty", "number", true, "2", [
|
|
223
|
+
"authors should provide a finite integer; runtime clamps below 1",
|
|
224
|
+
]),
|
|
225
|
+
option("maxRounds", "number", true, "50", ["authors should provide a finite positive integer"]),
|
|
226
|
+
],
|
|
227
|
+
};
|
|
228
|
+
const RETRY_OPTIONS: OptionShape = {
|
|
229
|
+
id: "retry-options",
|
|
230
|
+
options: [
|
|
231
|
+
option("attempts", "number", true, "3", [
|
|
232
|
+
"authors must provide a finite integer; runtime clamps values below 1 to 1",
|
|
233
|
+
]),
|
|
234
|
+
option("until", "(result: unknown) => boolean", true, "accept first result when omitted", [
|
|
235
|
+
"must be synchronous; use gate for asynchronous validation",
|
|
236
|
+
]),
|
|
237
|
+
],
|
|
238
|
+
};
|
|
239
|
+
const GATE_OPTIONS: OptionShape = {
|
|
240
|
+
id: "gate-options",
|
|
241
|
+
options: [
|
|
242
|
+
option("attempts", "number", true, "3", [
|
|
243
|
+
"authors must provide a finite integer; runtime clamps values below 1 to 1",
|
|
244
|
+
]),
|
|
245
|
+
],
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
interface RuntimeDescriptorOptions {
|
|
249
|
+
signature?: string;
|
|
250
|
+
discovery?: DiscoveryPlacement;
|
|
251
|
+
support?: CapabilitySupport;
|
|
252
|
+
optionShape?: OptionShape["id"];
|
|
253
|
+
constraints?: readonly string[];
|
|
254
|
+
evidence?: readonly string[];
|
|
255
|
+
allowsUndefined?: true;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const runtimeGlobal = (name: string, options: RuntimeDescriptorOptions = {}): CapabilityDescriptor => ({
|
|
259
|
+
id: `workflow.runtime.${name}`,
|
|
260
|
+
label: name,
|
|
261
|
+
classification: CapabilityClassification.RUNTIME_GLOBAL,
|
|
262
|
+
support: options.support ?? CapabilitySupport.SUPPORTED,
|
|
263
|
+
discovery: options.discovery ?? DiscoveryPlacement.COMPACT_GUIDANCE,
|
|
264
|
+
origin: CapabilityOrigin.PROJECT,
|
|
265
|
+
lifecycle: PRESENT_AT,
|
|
266
|
+
signature: options.signature ?? name,
|
|
267
|
+
optionShape: options.optionShape ?? null,
|
|
268
|
+
constraints: options.constraints ?? noOptions,
|
|
269
|
+
enforcementOwner: "runWorkflow context assembly",
|
|
270
|
+
runtimeBinding: {
|
|
271
|
+
global: name,
|
|
272
|
+
implementation: name,
|
|
273
|
+
...(options.allowsUndefined ? { allowsUndefined: true as const } : {}),
|
|
274
|
+
},
|
|
275
|
+
behaviorEvidence: options.evidence ?? ["tests/workflow-runtime.test.ts"],
|
|
276
|
+
staticReference: { path: REFERENCE_PATH, anchor: name.toLowerCase() },
|
|
277
|
+
dynamicReference: null,
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
const toolInput = (
|
|
281
|
+
name: string,
|
|
282
|
+
signature: string,
|
|
283
|
+
constraints: readonly string[] = noOptions,
|
|
284
|
+
): CapabilityDescriptor => ({
|
|
285
|
+
id: `workflow.tool-input.${name}`,
|
|
286
|
+
label: name,
|
|
287
|
+
classification: CapabilityClassification.WORKFLOW_TOOL_INPUT,
|
|
288
|
+
support: CapabilitySupport.SUPPORTED,
|
|
289
|
+
discovery: DiscoveryPlacement.COMPACT_GUIDANCE,
|
|
290
|
+
origin: CapabilityOrigin.TOOL_ADAPTER,
|
|
291
|
+
lifecycle: PRESENT_AT,
|
|
292
|
+
signature,
|
|
293
|
+
optionShape: null,
|
|
294
|
+
constraints,
|
|
295
|
+
enforcementOwner: "workflowToolSchema and createWorkflowTool",
|
|
296
|
+
runtimeBinding: null,
|
|
297
|
+
behaviorEvidence: ["tests/workflow-tool.test.ts"],
|
|
298
|
+
staticReference: { path: REFERENCE_PATH, anchor: `tool-input-${name.toLowerCase()}` },
|
|
299
|
+
dynamicReference: null,
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
const capabilities: readonly CapabilityDescriptor[] = [
|
|
303
|
+
runtimeGlobal("agent", {
|
|
304
|
+
signature: "agent(prompt, options?) => Promise<string | structured value | null>",
|
|
305
|
+
optionShape: "agent-options",
|
|
306
|
+
constraints: [
|
|
307
|
+
"recoverable failures return null after retries; nonrecoverable failures throw",
|
|
308
|
+
"schema noncompliance after bounded structured-output repair is nonrecoverable and bypasses agent retries",
|
|
309
|
+
"per-agent retries override invocation retries; retries are floored and clamped to 0..3",
|
|
310
|
+
"resume replays only the longest unchanged prefix; the first miss and every later call execute live",
|
|
311
|
+
"selector priority is explicit model > agentType model > tier > phase model > metadata model > implicit medium > session default",
|
|
312
|
+
"if the selected model or route is unavailable, execution falls directly to the session default rather than trying lower-priority selectors",
|
|
313
|
+
"worktree isolation is best-effort; failure logs that isolation was ignored and continues without an isolated working directory",
|
|
314
|
+
],
|
|
315
|
+
evidence: ["tests/workflow-runtime.test.ts", "tests/agent-registry.test.ts", "tests/structured-output.test.ts"],
|
|
316
|
+
}),
|
|
317
|
+
runtimeGlobal("parallel", {
|
|
318
|
+
signature: "parallel(thunks) => Promise<Array<unknown | null>>",
|
|
319
|
+
constraints: [
|
|
320
|
+
"requires functions rather than promises",
|
|
321
|
+
"result order matches input order",
|
|
322
|
+
"recoverable thunk failures become null; nonrecoverable failures throw",
|
|
323
|
+
],
|
|
324
|
+
}),
|
|
325
|
+
runtimeGlobal("pipeline", {
|
|
326
|
+
signature: "pipeline(items, ...stages) => Promise<Array<unknown | null>>",
|
|
327
|
+
constraints: [
|
|
328
|
+
"items run concurrently while stages per item run sequentially",
|
|
329
|
+
"each stage receives previousValue, originalItem, and zero-based index",
|
|
330
|
+
"a null stage result is passed to the next stage; authors must guard missing coverage explicitly",
|
|
331
|
+
"recoverable stage failures become null; nonrecoverable failures throw",
|
|
332
|
+
],
|
|
333
|
+
}),
|
|
334
|
+
runtimeGlobal("workflow", {
|
|
335
|
+
signature: "workflow(savedName, childArgs?) => Promise<unknown>",
|
|
336
|
+
constraints: [
|
|
337
|
+
"one nested level",
|
|
338
|
+
"shares limiter, counters, token accounting, and store",
|
|
339
|
+
"nested workflows do not reuse the parent resume journal",
|
|
340
|
+
],
|
|
341
|
+
evidence: ["tests/workflow-saved.test.ts", "tests/shared-store.test.ts"],
|
|
342
|
+
}),
|
|
343
|
+
runtimeGlobal("verify", {
|
|
344
|
+
signature:
|
|
345
|
+
"verify(item: unknown, options?: { reviewers?: number; threshold?: number; lens?: string | string[] }) => Promise<{ real: boolean; realCount: number; total: number; votes: Array<{ real: boolean; reason?: string }> }>",
|
|
346
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
347
|
+
optionShape: "verify-options",
|
|
348
|
+
constraints: [
|
|
349
|
+
"reviewer failures are omitted; successful votes form the denominator in realCount / total",
|
|
350
|
+
"threshold comparison is inclusive and real is false when no reviewer succeeds",
|
|
351
|
+
"multiple lenses cycle across reviewers",
|
|
352
|
+
],
|
|
353
|
+
evidence: ["tests/quality-stdlib.test.ts"],
|
|
354
|
+
}),
|
|
355
|
+
runtimeGlobal("judgePanel", {
|
|
356
|
+
signature:
|
|
357
|
+
"judgePanel(attempts: unknown[], options?: { judges?: number; rubric?: string }) => Promise<{ index: number; attempt: unknown; score: number; judgments: Array<{ score: number; reason?: string }> } | undefined>",
|
|
358
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
359
|
+
optionShape: "judge-panel-options",
|
|
360
|
+
constraints: [
|
|
361
|
+
"failed judgments are omitted and each candidate score averages successful judgments only",
|
|
362
|
+
"a candidate with no successful judgments scores 0",
|
|
363
|
+
"highest mean score wins with stable input index as the tie-break; empty input returns undefined",
|
|
364
|
+
],
|
|
365
|
+
evidence: ["tests/quality-stdlib.test.ts"],
|
|
366
|
+
}),
|
|
367
|
+
runtimeGlobal("loopUntilDry", {
|
|
368
|
+
signature:
|
|
369
|
+
"loopUntilDry(options: { round: (roundIndex: number) => unknown[] | Promise<unknown[]>; key?: (item: unknown) => string; consecutiveEmpty?: number; maxRounds?: number }) => Promise<unknown[]>",
|
|
370
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
371
|
+
optionShape: "loop-until-dry-options",
|
|
372
|
+
constraints: [
|
|
373
|
+
"roundIndex is zero-based; null, non-array, or duplicate-only round results count as empty",
|
|
374
|
+
"token-budget or agent-limit capacity exhaustion returns the accumulated partial array instead of throwing",
|
|
375
|
+
"the returned array does not report whether termination came from dryness, maxRounds, or capacity exhaustion",
|
|
376
|
+
"authors must retain failed-round identity and truthful termination state outside the helper",
|
|
377
|
+
],
|
|
378
|
+
evidence: ["tests/quality-stdlib.test.ts"],
|
|
379
|
+
}),
|
|
380
|
+
runtimeGlobal("completenessCheck", {
|
|
381
|
+
signature:
|
|
382
|
+
"completenessCheck(taskArgs: unknown, results: unknown) => Promise<{ complete: boolean; missing?: string[] } | null>",
|
|
383
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
384
|
+
constraints: [
|
|
385
|
+
"only the first 4,000 characters of serialized result evidence are sent to the critic",
|
|
386
|
+
"missing is optional and recoverable critic failure returns null",
|
|
387
|
+
"large evidence sets must be chunked or summarized before relying on the advisory verdict",
|
|
388
|
+
],
|
|
389
|
+
evidence: ["tests/quality-stdlib.test.ts"],
|
|
390
|
+
}),
|
|
391
|
+
runtimeGlobal("retry", {
|
|
392
|
+
signature:
|
|
393
|
+
"retry(thunk: (attempt: number) => unknown | Promise<unknown>, options?: { attempts?: number; until?: (result: unknown) => boolean }) => Promise<unknown>",
|
|
394
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
395
|
+
optionShape: "retry-options",
|
|
396
|
+
constraints: [
|
|
397
|
+
"attempt is zero-based and attempts counts total thunk calls",
|
|
398
|
+
"until is synchronous; returning a Promise is truthy and accepts the first result",
|
|
399
|
+
"omitting until accepts the first result regardless of attempts",
|
|
400
|
+
"stops when until(result) is true; exhaustion returns only the last result without attempt metadata",
|
|
401
|
+
"authors must supply a finite attempts bound when overriding the default",
|
|
402
|
+
],
|
|
403
|
+
evidence: ["tests/quality-stdlib.test.ts"],
|
|
404
|
+
}),
|
|
405
|
+
runtimeGlobal("gate", {
|
|
406
|
+
signature:
|
|
407
|
+
"gate(thunk: (feedback: string | undefined, attempt: number) => unknown | Promise<unknown>, validator: (value: unknown) => { ok: boolean; feedback?: string } | Promise<{ ok: boolean; feedback?: string }>, options?: { attempts?: number }) => Promise<{ ok: boolean; value: unknown; attempts: number }>",
|
|
408
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
409
|
+
optionShape: "gate-options",
|
|
410
|
+
constraints: [
|
|
411
|
+
"feedback is undefined on the first thunk call and then receives the previous validator feedback string",
|
|
412
|
+
"attempt is zero-based for the thunk while the returned attempts count is one-based",
|
|
413
|
+
"a value is accepted when the validator returns an object with a truthy ok property; a bare boolean is not accepted",
|
|
414
|
+
"exhaustion returns ok false with the last value and the bounded attempts count",
|
|
415
|
+
"authors must supply a finite attempts bound when overriding the default",
|
|
416
|
+
],
|
|
417
|
+
evidence: ["tests/quality-stdlib.test.ts"],
|
|
418
|
+
}),
|
|
419
|
+
runtimeGlobal("checkpoint", {
|
|
420
|
+
signature: "checkpoint(prompt, options?) => Promise<unknown>",
|
|
421
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
422
|
+
optionShape: "checkpoint-options",
|
|
423
|
+
constraints: [
|
|
424
|
+
"foreground confirm and headless behavior are implemented; input/select/timeout are declared-only",
|
|
425
|
+
"consumes one agent slot and no tokens",
|
|
426
|
+
"journaled answers replay only within an unchanged resume prefix",
|
|
427
|
+
],
|
|
428
|
+
evidence: ["tests/checkpoint.test.ts"],
|
|
429
|
+
}),
|
|
430
|
+
runtimeGlobal("log", { signature: "log(message) => void" }),
|
|
431
|
+
runtimeGlobal("phase", {
|
|
432
|
+
signature: "phase(title, options?) => void",
|
|
433
|
+
optionShape: "phase-options",
|
|
434
|
+
constraints: ["phase budgets are soft pre-call gates"],
|
|
435
|
+
}),
|
|
436
|
+
runtimeGlobal("args", { signature: "args: unknown", allowsUndefined: true }),
|
|
437
|
+
runtimeGlobal("cwd", { signature: "cwd: string" }),
|
|
438
|
+
runtimeGlobal("process", { signature: "process: { cwd(): string }" }),
|
|
439
|
+
runtimeGlobal("budget", {
|
|
440
|
+
signature: "budget: { total, spent(), remaining() }",
|
|
441
|
+
constraints: [
|
|
442
|
+
"frozen view over shared soft token accounting",
|
|
443
|
+
"spend accrues after agents finish, so in-flight work can overshoot",
|
|
444
|
+
"nested workflows share the same accounting",
|
|
445
|
+
],
|
|
446
|
+
}),
|
|
447
|
+
runtimeGlobal("console", {
|
|
448
|
+
signature: "console: { log, info, warn, error }",
|
|
449
|
+
support: CapabilitySupport.COMPATIBILITY,
|
|
450
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
451
|
+
constraints: ["new workflows should use log()"],
|
|
452
|
+
}),
|
|
453
|
+
toolInput("script", "script?: string", ["required raw JavaScript workflow source unless `name` is given"]),
|
|
454
|
+
toolInput("name", "name?: string", [
|
|
455
|
+
"resolves a project/user saved workflow first, then one of the 5 built-in patterns",
|
|
456
|
+
"mutually exclusive with resumeFromRunId",
|
|
457
|
+
]),
|
|
458
|
+
toolInput("args", "args?: unknown"),
|
|
459
|
+
toolInput("background", "background?: boolean = true", [
|
|
460
|
+
"background workflows are headless; use background false when checkpoint must show foreground confirmation",
|
|
461
|
+
]),
|
|
462
|
+
toolInput("maxAgents", "maxAgents?: number = 1000", ["default, not a hard product maximum"]),
|
|
463
|
+
toolInput("concurrency", "concurrency?: number", ["runtime clamps to 1..16"]),
|
|
464
|
+
toolInput("agentRetries", "agentRetries?: number = configured value or 0", ["floored and clamped to 0..3"]),
|
|
465
|
+
toolInput("agentTimeoutMs", "agentTimeoutMs?: number = configured default or unbounded"),
|
|
466
|
+
toolInput("tokenBudget", "tokenBudget?: number = configured default or unlimited", [
|
|
467
|
+
"soft pre-call gate; in-flight work can overshoot",
|
|
468
|
+
]),
|
|
469
|
+
toolInput("resumeFromRunId", "resumeFromRunId?: string", [
|
|
470
|
+
"resumes a prior incomplete run with an edited script",
|
|
471
|
+
"unchanged positional agent calls replay from cache until the first changed or inserted call",
|
|
472
|
+
"always runs in the background",
|
|
473
|
+
]),
|
|
474
|
+
{
|
|
475
|
+
id: "workflow.script.metadata",
|
|
476
|
+
label: "export const meta",
|
|
477
|
+
classification: CapabilityClassification.SCRIPT_CONTRACT,
|
|
478
|
+
support: CapabilitySupport.SUPPORTED,
|
|
479
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
480
|
+
origin: CapabilityOrigin.PROJECT,
|
|
481
|
+
lifecycle: PRESENT_AT,
|
|
482
|
+
signature:
|
|
483
|
+
"export const meta = { name: string, description: string, phases?: Array<{ title: string; detail?: string; model?: string }>, model?: string }",
|
|
484
|
+
optionShape: null,
|
|
485
|
+
constraints: [
|
|
486
|
+
"must be the first statement",
|
|
487
|
+
"name and description must be nonblank strings",
|
|
488
|
+
"metadata must use literal values; expressions such as string concatenation and template interpolation are rejected",
|
|
489
|
+
"the meta declaration is the only legal export because the remaining body executes inside an async function",
|
|
490
|
+
],
|
|
491
|
+
enforcementOwner: "parseWorkflowScript",
|
|
492
|
+
runtimeBinding: null,
|
|
493
|
+
behaviorEvidence: ["tests/workflow-parser.test.ts"],
|
|
494
|
+
staticReference: { path: REFERENCE_PATH, anchor: "metadata" },
|
|
495
|
+
dynamicReference: null,
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
id: "workflow.script.return-value",
|
|
499
|
+
label: "workflow return value",
|
|
500
|
+
classification: CapabilityClassification.SCRIPT_CONTRACT,
|
|
501
|
+
support: CapabilitySupport.SUPPORTED,
|
|
502
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
503
|
+
origin: CapabilityOrigin.PROJECT,
|
|
504
|
+
lifecycle: PRESENT_AT,
|
|
505
|
+
signature: "return JSON-serializable data",
|
|
506
|
+
optionShape: null,
|
|
507
|
+
constraints: ["do not return functions, promises, cyclic objects, BigInt, or runtime handles"],
|
|
508
|
+
enforcementOwner: "workflow tool result boundary",
|
|
509
|
+
runtimeBinding: null,
|
|
510
|
+
behaviorEvidence: ["tests/workflow-authoring-skill.test.ts", "tests/workflow-tool.test.ts"],
|
|
511
|
+
staticReference: { path: REFERENCE_PATH, anchor: "return-value" },
|
|
512
|
+
dynamicReference: null,
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
id: "workflow.script.determinism",
|
|
516
|
+
label: "deterministic script execution",
|
|
517
|
+
classification: CapabilityClassification.SCRIPT_CONTRACT,
|
|
518
|
+
support: CapabilitySupport.SUPPORTED,
|
|
519
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
520
|
+
origin: CapabilityOrigin.PROJECT,
|
|
521
|
+
lifecycle: PRESENT_AT,
|
|
522
|
+
signature: null,
|
|
523
|
+
optionShape: null,
|
|
524
|
+
constraints: [
|
|
525
|
+
"Date.now(), Math.random(), and no-argument new Date() are unavailable",
|
|
526
|
+
"pass timestamps and randomness through args",
|
|
527
|
+
],
|
|
528
|
+
enforcementOwner: "parseWorkflowScript and VM determinism prelude",
|
|
529
|
+
runtimeBinding: null,
|
|
530
|
+
behaviorEvidence: ["tests/workflow-parser.test.ts", "tests/workflow-runtime.test.ts"],
|
|
531
|
+
staticReference: { path: REFERENCE_PATH, anchor: "determinism" },
|
|
532
|
+
dynamicReference: null,
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
id: "workflow.compat.markdown-fences",
|
|
536
|
+
label: "whole-script Markdown fence stripping",
|
|
537
|
+
classification: CapabilityClassification.COMPATIBILITY_BEHAVIOR,
|
|
538
|
+
support: CapabilitySupport.COMPATIBILITY,
|
|
539
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
540
|
+
origin: CapabilityOrigin.TOOL_ADAPTER,
|
|
541
|
+
lifecycle: PRESENT_AT,
|
|
542
|
+
signature: null,
|
|
543
|
+
optionShape: null,
|
|
544
|
+
constraints: ["accepted for compatibility but not recommended"],
|
|
545
|
+
enforcementOwner: "normalizeWorkflowScript",
|
|
546
|
+
runtimeBinding: null,
|
|
547
|
+
behaviorEvidence: ["tests/workflow-tool.test.ts"],
|
|
548
|
+
staticReference: { path: REFERENCE_PATH, anchor: "compatibility" },
|
|
549
|
+
dynamicReference: null,
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
id: "workflow.vm.realm-substrate",
|
|
553
|
+
label: "VM realm JavaScript substrate",
|
|
554
|
+
classification: CapabilityClassification.INTERNAL_SUBSTRATE,
|
|
555
|
+
support: CapabilitySupport.INTERNAL,
|
|
556
|
+
discovery: DiscoveryPlacement.NONE,
|
|
557
|
+
origin: CapabilityOrigin.VM_REALM,
|
|
558
|
+
lifecycle: PRESENT_AT,
|
|
559
|
+
signature: null,
|
|
560
|
+
optionShape: null,
|
|
561
|
+
constraints: ["Node-version-dependent globals are not project-owned workflow API", "VM is not a security sandbox"],
|
|
562
|
+
enforcementOwner: "node:vm",
|
|
563
|
+
runtimeBinding: null,
|
|
564
|
+
behaviorEvidence: ["tests/workflow-runtime.test.ts"],
|
|
565
|
+
staticReference: null,
|
|
566
|
+
dynamicReference: null,
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
id: "workflow.dynamic.model-routes",
|
|
570
|
+
label: "model routes",
|
|
571
|
+
classification: CapabilityClassification.DYNAMIC_REFERENCE,
|
|
572
|
+
support: CapabilitySupport.SUPPORTED,
|
|
573
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
574
|
+
origin: CapabilityOrigin.LIVE_CONFIGURATION,
|
|
575
|
+
lifecycle: PRESENT_AT,
|
|
576
|
+
signature: null,
|
|
577
|
+
optionShape: null,
|
|
578
|
+
constraints: ["live values must not be copied into static contract data"],
|
|
579
|
+
enforcementOwner: "model-tier-config",
|
|
580
|
+
runtimeBinding: null,
|
|
581
|
+
behaviorEvidence: ["tests/workflows-models-command.test.ts"],
|
|
582
|
+
staticReference: { path: REFERENCE_PATH, anchor: "model-routes" },
|
|
583
|
+
dynamicReference: "model-routes",
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
id: "workflow.dynamic.agent-types",
|
|
587
|
+
label: "agent types",
|
|
588
|
+
classification: CapabilityClassification.DYNAMIC_REFERENCE,
|
|
589
|
+
support: CapabilitySupport.SUPPORTED,
|
|
590
|
+
discovery: DiscoveryPlacement.WORKFLOW_AUTHORING_SKILL,
|
|
591
|
+
origin: CapabilityOrigin.LIVE_CONFIGURATION,
|
|
592
|
+
lifecycle: PRESENT_AT,
|
|
593
|
+
signature: null,
|
|
594
|
+
optionShape: null,
|
|
595
|
+
constraints: ["live values must not be copied into static contract data"],
|
|
596
|
+
enforcementOwner: "agent-registry",
|
|
597
|
+
runtimeBinding: null,
|
|
598
|
+
behaviorEvidence: ["tests/agent-registry.test.ts"],
|
|
599
|
+
staticReference: { path: REFERENCE_PATH, anchor: "agent-types" },
|
|
600
|
+
dynamicReference: "agent-types",
|
|
601
|
+
},
|
|
602
|
+
];
|
|
603
|
+
|
|
604
|
+
/** Authoritative versioned inventory used by runtime assembly and every static projection. */
|
|
605
|
+
export const WORKFLOW_CAPABILITY_DEFINITION: WorkflowCapabilityDefinition = {
|
|
606
|
+
versions: {
|
|
607
|
+
extension: packageJson.version,
|
|
608
|
+
format: { kind: "present-at", version: "1.0.0" },
|
|
609
|
+
content: PRESENT_AT,
|
|
610
|
+
},
|
|
611
|
+
optionShapes: [
|
|
612
|
+
AGENT_OPTIONS,
|
|
613
|
+
CHECKPOINT_OPTIONS,
|
|
614
|
+
PHASE_OPTIONS,
|
|
615
|
+
VERIFY_OPTIONS,
|
|
616
|
+
JUDGE_PANEL_OPTIONS,
|
|
617
|
+
LOOP_UNTIL_DRY_OPTIONS,
|
|
618
|
+
RETRY_OPTIONS,
|
|
619
|
+
GATE_OPTIONS,
|
|
620
|
+
],
|
|
621
|
+
capabilities,
|
|
622
|
+
dynamicReferences: [
|
|
623
|
+
{
|
|
624
|
+
id: "model-routes",
|
|
625
|
+
owner: "model-tier-config",
|
|
626
|
+
itemShape: "{ name: string; description?: string }",
|
|
627
|
+
connection: "loadModelTierConfig",
|
|
628
|
+
},
|
|
629
|
+
{
|
|
630
|
+
id: "agent-types",
|
|
631
|
+
owner: "agent-registry",
|
|
632
|
+
itemShape: "{ name: string; description?: string }",
|
|
633
|
+
connection: "loadAgentRegistry",
|
|
634
|
+
},
|
|
635
|
+
],
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
/** Validate and freeze a definition, throwing with diagnostics when its identities or references conflict. */
|
|
639
|
+
export function defineWorkflowCapabilityContract(definition: WorkflowCapabilityDefinition): WorkflowCapabilityContract {
|
|
640
|
+
deepFreeze(definition);
|
|
641
|
+
const definitionDiagnostics = validateDefinition(definition);
|
|
642
|
+
if (definitionDiagnostics.length > 0) {
|
|
643
|
+
throw new WorkflowCapabilityContractError("invalid workflow capability definition", definitionDiagnostics);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
const optionShapes = new Map(definition.optionShapes.map((shape) => [shape.id, shape]));
|
|
647
|
+
const dynamicReferences = new Map(definition.dynamicReferences.map((reference) => [reference.id, reference]));
|
|
648
|
+
const bindings = definition.capabilities.flatMap((capability) =>
|
|
649
|
+
capability.runtimeBinding ? [{ ...capability.runtimeBinding }] : [],
|
|
650
|
+
);
|
|
651
|
+
const implementations = new Set(bindings.map((binding) => binding.implementation));
|
|
652
|
+
const globals = new Set(bindings.map((binding) => binding.global));
|
|
653
|
+
|
|
654
|
+
const diagnoseAlignment = (evidence: AlignmentEvidence): readonly CapabilityDiagnostic[] => {
|
|
655
|
+
const diagnostics: CapabilityDiagnostic[] = [];
|
|
656
|
+
if (evidence.suppliedImplementations) {
|
|
657
|
+
for (const binding of bindings) {
|
|
658
|
+
if (
|
|
659
|
+
!Object.hasOwn(evidence.suppliedImplementations, binding.implementation) ||
|
|
660
|
+
(evidence.suppliedImplementations[binding.implementation] === undefined && !binding.allowsUndefined)
|
|
661
|
+
) {
|
|
662
|
+
diagnostics.push({
|
|
663
|
+
code: "MISSING_RUNTIME_IMPLEMENTATION",
|
|
664
|
+
severity: DiagnosticSeverity.ERROR,
|
|
665
|
+
subject: binding.implementation,
|
|
666
|
+
message: `Declared workflow global "${binding.global}" has no supplied implementation "${binding.implementation}".`,
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
for (const name of Object.keys(evidence.suppliedImplementations)) {
|
|
671
|
+
if (!implementations.has(name)) {
|
|
672
|
+
diagnostics.push({
|
|
673
|
+
code: "UNDECLARED_RUNTIME_IMPLEMENTATION",
|
|
674
|
+
severity: DiagnosticSeverity.WARNING,
|
|
675
|
+
subject: name,
|
|
676
|
+
message: `Supplied runtime implementation "${name}" is undeclared and was ignored.`,
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
if (evidence.observedProjectGlobals) {
|
|
682
|
+
const observed = new Set(evidence.observedProjectGlobals);
|
|
683
|
+
for (const name of globals) {
|
|
684
|
+
if (!observed.has(name)) {
|
|
685
|
+
diagnostics.push({
|
|
686
|
+
code: "DECLARED_GLOBAL_UNOBSERVED",
|
|
687
|
+
severity: DiagnosticSeverity.ERROR,
|
|
688
|
+
subject: name,
|
|
689
|
+
message: `Declared workflow global "${name}" was not observed in the assembled context.`,
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
for (const name of observed) {
|
|
694
|
+
if (!globals.has(name)) {
|
|
695
|
+
diagnostics.push({
|
|
696
|
+
code: "OBSERVED_GLOBAL_UNDECLARED",
|
|
697
|
+
severity: DiagnosticSeverity.ERROR,
|
|
698
|
+
subject: name,
|
|
699
|
+
message: `Observed project-owned workflow global "${name}" is undeclared.`,
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
return diagnostics;
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
return {
|
|
708
|
+
definition,
|
|
709
|
+
assembleRuntimeBindings(supplied) {
|
|
710
|
+
const diagnostics = diagnoseAlignment({ suppliedImplementations: supplied });
|
|
711
|
+
const missing = diagnostics.filter((diagnostic) => diagnostic.code === "MISSING_RUNTIME_IMPLEMENTATION");
|
|
712
|
+
if (missing.length > 0) {
|
|
713
|
+
throw new WorkflowCapabilityContractError(
|
|
714
|
+
`missing declared runtime implementation: ${missing.map((diagnostic) => diagnostic.subject).join(", ")}`,
|
|
715
|
+
diagnostics,
|
|
716
|
+
);
|
|
717
|
+
}
|
|
718
|
+
const assembled: Record<string, unknown> = {};
|
|
719
|
+
for (const binding of bindings) assembled[binding.global] = supplied[binding.implementation];
|
|
720
|
+
return { globals: assembled, diagnostics };
|
|
721
|
+
},
|
|
722
|
+
projectStaticReferenceFacts() {
|
|
723
|
+
return definition.capabilities
|
|
724
|
+
.filter((capability) => capability.staticReference !== null)
|
|
725
|
+
.map((capability) => ({
|
|
726
|
+
id: capability.id,
|
|
727
|
+
label: capability.label,
|
|
728
|
+
classification: capability.classification,
|
|
729
|
+
support: capability.support,
|
|
730
|
+
signature: capability.signature,
|
|
731
|
+
options: capability.optionShape ? (optionShapes.get(capability.optionShape) ?? null) : null,
|
|
732
|
+
constraints: capability.constraints,
|
|
733
|
+
reference: capability.staticReference
|
|
734
|
+
? `${capability.staticReference.path}#${capability.staticReference.anchor}`
|
|
735
|
+
: null,
|
|
736
|
+
dynamicReference: capability.dynamicReference
|
|
737
|
+
? (dynamicReferences.get(capability.dynamicReference) ?? null)
|
|
738
|
+
: null,
|
|
739
|
+
}));
|
|
740
|
+
},
|
|
741
|
+
diagnoseAlignment,
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
function validateDefinition(definition: WorkflowCapabilityDefinition): CapabilityDiagnostic[] {
|
|
746
|
+
const diagnostics: CapabilityDiagnostic[] = [];
|
|
747
|
+
const ids = new Set<string>();
|
|
748
|
+
const globals = new Set<string>();
|
|
749
|
+
const runtimeImplementations = new Set<string>();
|
|
750
|
+
const optionShapes = new Set<string>();
|
|
751
|
+
const dynamicReferences = new Set<string>();
|
|
752
|
+
const invalid = (subject: string, message: string) =>
|
|
753
|
+
diagnostics.push({ code: "INVALID_CAPABILITY_DEFINITION", severity: DiagnosticSeverity.ERROR, subject, message });
|
|
754
|
+
for (const shape of definition.optionShapes) {
|
|
755
|
+
if (optionShapes.has(shape.id)) invalid(shape.id, `Duplicate option shape "${shape.id}".`);
|
|
756
|
+
optionShapes.add(shape.id);
|
|
757
|
+
}
|
|
758
|
+
for (const reference of definition.dynamicReferences) {
|
|
759
|
+
if (dynamicReferences.has(reference.id)) invalid(reference.id, `Duplicate dynamic reference "${reference.id}".`);
|
|
760
|
+
dynamicReferences.add(reference.id);
|
|
761
|
+
}
|
|
762
|
+
for (const capability of definition.capabilities) {
|
|
763
|
+
if (ids.has(capability.id)) invalid(capability.id, `Duplicate capability id "${capability.id}".`);
|
|
764
|
+
ids.add(capability.id);
|
|
765
|
+
if (capability.classification === CapabilityClassification.RUNTIME_GLOBAL && !capability.runtimeBinding) {
|
|
766
|
+
invalid(capability.id, "Runtime-global capabilities require a runtime binding.");
|
|
767
|
+
}
|
|
768
|
+
if (capability.runtimeBinding) {
|
|
769
|
+
if (globals.has(capability.runtimeBinding.global)) {
|
|
770
|
+
invalid(capability.runtimeBinding.global, `Duplicate runtime global "${capability.runtimeBinding.global}".`);
|
|
771
|
+
}
|
|
772
|
+
globals.add(capability.runtimeBinding.global);
|
|
773
|
+
if (runtimeImplementations.has(capability.runtimeBinding.implementation)) {
|
|
774
|
+
invalid(
|
|
775
|
+
capability.runtimeBinding.implementation,
|
|
776
|
+
`Duplicate runtime implementation identity "${capability.runtimeBinding.implementation}".`,
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
runtimeImplementations.add(capability.runtimeBinding.implementation);
|
|
780
|
+
if (
|
|
781
|
+
capability.classification !== CapabilityClassification.RUNTIME_GLOBAL ||
|
|
782
|
+
capability.origin !== CapabilityOrigin.PROJECT
|
|
783
|
+
) {
|
|
784
|
+
invalid(capability.id, "Runtime bindings require runtime-global classification and project origin.");
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
if (capability.optionShape && !optionShapes.has(capability.optionShape)) {
|
|
788
|
+
invalid(capability.id, `Unknown option shape "${capability.optionShape}".`);
|
|
789
|
+
}
|
|
790
|
+
if (capability.dynamicReference && !dynamicReferences.has(capability.dynamicReference)) {
|
|
791
|
+
invalid(capability.id, `Unknown dynamic reference "${capability.dynamicReference}".`);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
return diagnostics;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
function deepFreeze<T>(value: T): T {
|
|
798
|
+
if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
|
|
799
|
+
for (const nested of Object.values(value)) deepFreeze(nested);
|
|
800
|
+
Object.freeze(value);
|
|
801
|
+
}
|
|
802
|
+
return value;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
/** Installed validated workflow capability contract. */
|
|
806
|
+
export const WORKFLOW_CAPABILITY_CONTRACT = defineWorkflowCapabilityContract(WORKFLOW_CAPABILITY_DEFINITION);
|