@x12i/graphenix-plan-format 1.0.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/README.md +417 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/validators/validate-executable-plan-v1.d.ts +3 -0
- package/dist/validators/validate-executable-plan-v1.d.ts.map +1 -0
- package/dist/validators/validate-executable-plan-v1.js +207 -0
- package/dist/validators/validate-executable-plan-v1.js.map +1 -0
- package/dist/validators/validate-executable-plan-v2.d.ts +3 -0
- package/dist/validators/validate-executable-plan-v2.d.ts.map +1 -0
- package/dist/validators/validate-executable-plan-v2.js +534 -0
- package/dist/validators/validate-executable-plan-v2.js.map +1 -0
- package/dist/validators/validate-executable-plan.d.ts +5 -0
- package/dist/validators/validate-executable-plan.d.ts.map +1 -0
- package/dist/validators/validate-executable-plan.js +17 -0
- package/dist/validators/validate-executable-plan.js.map +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
# @x12i/graphenix-plan-format
|
|
2
|
+
|
|
3
|
+
**ExecutableGraphPlan** format — validates the engine-facing artifact produced by `@x12i/graphenix-plan-compiler`.
|
|
4
|
+
|
|
5
|
+
Defines and checks what a correct compiled plan looks like: resolved **phase model profiles**, ordered **execution units** per run phase, finalizer plans, embedded normalized graph snapshot, and forbidden runtime fields.
|
|
6
|
+
|
|
7
|
+
This package **does not compile** from authoring graphs — it only validates plan documents. Use `@x12i/graphenix-plan-compiler` to produce plans.
|
|
8
|
+
|
|
9
|
+
**Canonical vocabulary:** [GLOSSARY.md](../../GLOSSARY.md) at monorepo root.
|
|
10
|
+
**Finalization brief:** [COMPILE-FORMAT-FINALIZATION.md](../../docs/COMPILE-FORMAT-FINALIZATION.md) · execute/trace: [EXECUTE-TRACE-FORMAT-FINALIZATION.md](../../docs/EXECUTE-TRACE-FORMAT-FINALIZATION.md).
|
|
11
|
+
When task **run phases** or plan-phase terms change, update this README and [GLOSSARY.md §5](../../GLOSSARY.md#5-plan-phase-action-lists-design-vs-plan--do-not-confuse) together.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Who should use this
|
|
16
|
+
|
|
17
|
+
| Role | Use this package? |
|
|
18
|
+
| ---- | ----------------- |
|
|
19
|
+
| Execution engine | **Yes** — validate plan before run |
|
|
20
|
+
| Compiler / execution prep | **Yes** — validate output before handoff |
|
|
21
|
+
| Run history / observability | **Yes** — bind traces to validated plan shape |
|
|
22
|
+
| Graph designer / Studio | Only if showing compile preview |
|
|
23
|
+
| Authoring-only services | **No** — use `@x12i/graphenix-authoring-format` |
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @x12i/graphenix-plan-format
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Types (`ExecutableGraphPlan`, `ExecutableGraphPlanV2`, `ExecutionUnitPlanV2`, …) live in `@x12i/graphenix-executable-contracts`.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Lifecycle position
|
|
38
|
+
|
|
39
|
+
```txt
|
|
40
|
+
AuthoringGraphDocument + GraphRuntimeObject
|
|
41
|
+
│ compileExecutablePlan() (@x12i/graphenix-plan-compiler)
|
|
42
|
+
▼
|
|
43
|
+
ExecutableGraphPlan ← THIS PACKAGE validates
|
|
44
|
+
│ executeGraph()
|
|
45
|
+
▼
|
|
46
|
+
GraphExecutionTrace (@x12i/graphenix-trace-format)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The engine consumes **only** the plan (+ runtime binding). It never reads authoring graphs or Studio shadow documents directly.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Task run phases (runtime topology)
|
|
54
|
+
|
|
55
|
+
One task node invocation is three **run phases** ([GLOSSARY §1](../../GLOSSARY.md#1-task-run-phases-runtime-shape-of-one-runtask-wave)):
|
|
56
|
+
|
|
57
|
+
| Run phase | Meaning | Typical plan units |
|
|
58
|
+
| --------- | ------- | ------------------ |
|
|
59
|
+
| **prePhase** | Optional utility work before the skill | `externalPreUtility` (v2) / `preAction` (v1) |
|
|
60
|
+
| **mainPhase** | Skill / MAIN execution | `mainSkill`, `pipelinePhase`, `localSkill` (v2) / `skill` (v1) |
|
|
61
|
+
| **postPhase** | Optional utility work after the skill | `externalPostUtility` (v2) / `postAction` (v1) |
|
|
62
|
+
|
|
63
|
+
This is **phase topology** — not model choice and not catalog action ids.
|
|
64
|
+
|
|
65
|
+
### Design → plan mapping (do not conflate)
|
|
66
|
+
|
|
67
|
+
Authoring declares **phase utility strategies** on the task node. The compiler expands them into **plan execution units**:
|
|
68
|
+
|
|
69
|
+
```txt
|
|
70
|
+
prePhase.strategyKey (design: aiTaskStrategies.pre)
|
|
71
|
+
│ compile
|
|
72
|
+
▼
|
|
73
|
+
PRE-phase execution units (plan: externalPreUtility / preAction)
|
|
74
|
+
|
|
75
|
+
mainPhase.executionStrategies + skill input synthesis profile (design)
|
|
76
|
+
│ compile
|
|
77
|
+
▼
|
|
78
|
+
MAIN-phase execution units (plan: mainSkill, pipelinePhase, …)
|
|
79
|
+
|
|
80
|
+
postPhase.strategyKey (design: aiTaskStrategies.post)
|
|
81
|
+
│ compile
|
|
82
|
+
▼
|
|
83
|
+
POST-phase execution units (plan: externalPostUtility / postAction)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
| Design (authoring) | Plan (this package) | Glossary |
|
|
87
|
+
| ------------------ | ------------------- | -------- |
|
|
88
|
+
| `aiTaskStrategies.pre` | PRE-phase units with `strategyKey` / `actionKey` | PRE-phase utility strategy → plan PRE-phase action list |
|
|
89
|
+
| `executionStrategies`, `aiTaskProfile.inputSynthesis` | `mainSkill`, `pipelinePhase`, … | MAIN-phase wrappers / skill input synthesis profile |
|
|
90
|
+
| `aiTaskStrategies.post` | POST-phase units | POST-phase utility strategy → plan POST-phase action list |
|
|
91
|
+
| `preActions[]` / `postActions[]` (optional on design) | Same shape at plan layer | Plan-phase action lists — **not** synonyms for `aiTaskStrategies.pre` |
|
|
92
|
+
|
|
93
|
+
**Explicit rule:** `strategyKey: "synthesis"` (PRE-phase utility) ≠ `inputSynthesis.enabled` (MAIN skill input synthesis profile). The plan may contain `pipelinePhase` units from the latter without any PRE-phase utility unit.
|
|
94
|
+
|
|
95
|
+
Each execution unit carries a **phase model profile** binding ([GLOSSARY §4](../../GLOSSARY.md#4-phase-model-profiles-executable-extension--separate-layer)):
|
|
96
|
+
|
|
97
|
+
| `modelSlot` | Run phase |
|
|
98
|
+
| ----------- | --------- |
|
|
99
|
+
| `preActionModel` | PRE-phase model profile |
|
|
100
|
+
| `skillModel` | MAIN-phase model profile |
|
|
101
|
+
| `postActionModel` | POST-phase model profile |
|
|
102
|
+
| `finalizerModel` | Finalizer (graph output) |
|
|
103
|
+
|
|
104
|
+
Utility strategy = **what** runs. Model profile = **which AI profile** runs it.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Plan document shape
|
|
109
|
+
|
|
110
|
+
### v1 — `graphenix.executable-plan/v1`
|
|
111
|
+
|
|
112
|
+
```txt
|
|
113
|
+
ExecutableGraphPlan
|
|
114
|
+
├─ format, planId, createdAt
|
|
115
|
+
├─ source (graphId, graphHash, …)
|
|
116
|
+
├─ profileRegistry (@x12i/ai-profiles version)
|
|
117
|
+
├─ runtimeBinding (jobId, mode, environment, hashes)
|
|
118
|
+
├─ graph — embedded NormalizedExecutableGraphDocument
|
|
119
|
+
├─ caseSelection — graph + per-node selected cases
|
|
120
|
+
├─ nodePlans[nodeId]
|
|
121
|
+
│ ├─ selectedCases, modelSlots (preActionModel / skillModel / postActionModel)
|
|
122
|
+
│ └─ executionUnits[] — ordered preAction → skill → postAction
|
|
123
|
+
└─ finalizerPlans (if applicable)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
v1 unit kinds: `preAction` | `skill` | `postAction` | `finalizer`.
|
|
127
|
+
|
|
128
|
+
### v2 — `graphenix.executable-plan/v2` (preferred for new engines)
|
|
129
|
+
|
|
130
|
+
```txt
|
|
131
|
+
ExecutableGraphPlanV2
|
|
132
|
+
├─ format, planId, createdAt, planHash
|
|
133
|
+
├─ source, profileRegistry, runtimeBinding, runtimeExpectations
|
|
134
|
+
├─ normalizedGraph — embedded or ref
|
|
135
|
+
├─ policies (directModelPolicy, fallback, trace, …)
|
|
136
|
+
├─ nodeIndex[], deferredGates[]
|
|
137
|
+
├─ nodePlans[nodeId] — NodeExecutionPlan
|
|
138
|
+
│ ├─ invokeContract (pipeline snapshot from authoring)
|
|
139
|
+
│ ├─ modelSlots, selectedCases
|
|
140
|
+
│ └─ executionUnits[] — ordered by run phase
|
|
141
|
+
└─ finalizerPlans[nodeId] — FinalizerExecutionPlan
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
v2 unit kinds include:
|
|
145
|
+
|
|
146
|
+
| `unitKind` | Typical run phase | `invokeMode` |
|
|
147
|
+
| ---------- | ----------------- | ------------ |
|
|
148
|
+
| `externalPreUtility` | prePhase | `externalRunTask` |
|
|
149
|
+
| `mainSkill` | mainPhase | `mainRunTask` |
|
|
150
|
+
| `pipelinePhase` | mainPhase (wrapper / synthesis inside MAIN) | `pipelinePhase` |
|
|
151
|
+
| `localSkill` | mainPhase | `local` |
|
|
152
|
+
| `externalPostUtility` | postPhase | `externalRunTask` |
|
|
153
|
+
| `finalizer` | graph output | `finalizer` |
|
|
154
|
+
| `validation`, `mapping`, `callGraph` | special | `none` / … |
|
|
155
|
+
|
|
156
|
+
Each `ExecutionUnitPlanV2` exposes: `unitId`, `nodeId`, `unitKind`, `invokeMode`, `order`, `actionKey`, `strategyKey`, `skillKey`, `modelSlot`, `modelSelection`, `modelSource`, `invokeContract`, retry/fallback/trace policies, and `sourcePath` (JSON pointer into embedded graph).
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Per-task node plan (diagram)
|
|
161
|
+
|
|
162
|
+
```txt
|
|
163
|
+
NodeExecutionPlan (one task node, one runTask wave)
|
|
164
|
+
│
|
|
165
|
+
├─ prePhase units[] externalPreUtility / preAction
|
|
166
|
+
│ modelSlot: preActionModel
|
|
167
|
+
│
|
|
168
|
+
├─ mainPhase units[] mainSkill | pipelinePhase | localSkill
|
|
169
|
+
│ modelSlot: skillModel (pipelinePhase may share MAIN profile)
|
|
170
|
+
│
|
|
171
|
+
└─ postPhase units[] externalPostUtility / postAction
|
|
172
|
+
modelSlot: postActionModel
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Order is strict: PRE units → MAIN units → POST units. Validators reject missing MAIN skill, duplicate orders, and slot/kind mismatches.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Examples (JSON)
|
|
180
|
+
|
|
181
|
+
### v2 plan header (minimal)
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
{
|
|
185
|
+
"format": "graphenix.executable-plan/v2",
|
|
186
|
+
"planId": "plan:abc123",
|
|
187
|
+
"createdAt": "2026-06-06T12:00:00.000Z",
|
|
188
|
+
"planHash": "sha256:…",
|
|
189
|
+
"source": {
|
|
190
|
+
"graphId": "graph:content-pipeline",
|
|
191
|
+
"graphRevision": "1.0.0",
|
|
192
|
+
"graphHash": "sha256:…",
|
|
193
|
+
"formatVersion": "2.0.0"
|
|
194
|
+
},
|
|
195
|
+
"profileRegistry": {
|
|
196
|
+
"package": "@x12i/ai-profiles",
|
|
197
|
+
"version": "3.2.0",
|
|
198
|
+
"registryHash": "sha256:…"
|
|
199
|
+
},
|
|
200
|
+
"runtimeBinding": {
|
|
201
|
+
"jobId": "job-001",
|
|
202
|
+
"mode": "live",
|
|
203
|
+
"environment": "prod",
|
|
204
|
+
"sourceGraphHash": "sha256:…",
|
|
205
|
+
"profileRegistryHash": "sha256:…"
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### v2 `nodePlans` — PRE + MAIN execution units (content pipeline)
|
|
211
|
+
|
|
212
|
+
Compiled from authoring `aiTaskStrategies.pre: "synthesis"` + `executionStrategies: []` on `node:audience-insights`. No POST units unless design declares `aiTaskStrategies.post`:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
"nodePlans": {
|
|
216
|
+
"node:audience-insights": {
|
|
217
|
+
"nodeId": "node:audience-insights",
|
|
218
|
+
"nodeType": "task",
|
|
219
|
+
"executionClass": "aiTask",
|
|
220
|
+
"skillKey": "professional-answer",
|
|
221
|
+
"selectedCases": {
|
|
222
|
+
"graphModelCaseId": "default"
|
|
223
|
+
},
|
|
224
|
+
"modelSlots": {
|
|
225
|
+
"preActionModel": {
|
|
226
|
+
"selection": { "kind": "profileChoice", "key": "cheap/default" },
|
|
227
|
+
"source": "graphCase"
|
|
228
|
+
},
|
|
229
|
+
"skillModel": {
|
|
230
|
+
"selection": { "kind": "profileChoice", "key": "vol/default" },
|
|
231
|
+
"source": "graphCase"
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
"executionUnits": [
|
|
235
|
+
{
|
|
236
|
+
"unitId": "unit:node:audience-insights:pre:0",
|
|
237
|
+
"nodeId": "node:audience-insights",
|
|
238
|
+
"unitKind": "externalPreUtility",
|
|
239
|
+
"invokeMode": "externalRunTask",
|
|
240
|
+
"order": 0,
|
|
241
|
+
"strategyKey": "synthesis",
|
|
242
|
+
"actionKey": "synthesis",
|
|
243
|
+
"modelSlot": "preActionModel",
|
|
244
|
+
"modelSelection": { "kind": "profileChoice", "key": "cheap/default" },
|
|
245
|
+
"sourcePath": "/graph/nodes/node:audience-insights/parameters/taskConfiguration/aiTaskStrategies/pre"
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"unitId": "unit:node:audience-insights:main:1",
|
|
249
|
+
"nodeId": "node:audience-insights",
|
|
250
|
+
"unitKind": "mainSkill",
|
|
251
|
+
"invokeMode": "mainRunTask",
|
|
252
|
+
"order": 1,
|
|
253
|
+
"skillKey": "professional-answer",
|
|
254
|
+
"modelSlot": "skillModel",
|
|
255
|
+
"modelSelection": { "kind": "profileChoice", "key": "vol/default" },
|
|
256
|
+
"sourcePath": "/graph/nodes/node:audience-insights/parameters/skillKey"
|
|
257
|
+
}
|
|
258
|
+
],
|
|
259
|
+
"sourcePath": "/graph/nodes/node:audience-insights"
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### v2 `nodePlans` — PRE / MAIN / POST
|
|
265
|
+
|
|
266
|
+
When authoring declares `aiTaskStrategies.post`, the compiler appends POST-phase units (same mapping as PRE via `externalPostUtility`).
|
|
267
|
+
|
|
268
|
+
### v2 MAIN `pipelinePhase` from skill input synthesis profile (not PRE utility)
|
|
269
|
+
|
|
270
|
+
When authoring uses `aiTaskProfile.inputSynthesis.enabled` (not `aiTaskStrategies.pre`):
|
|
271
|
+
|
|
272
|
+
```json
|
|
273
|
+
{
|
|
274
|
+
"unitId": "unit:node:task:pipeline:0",
|
|
275
|
+
"unitKind": "pipelinePhase",
|
|
276
|
+
"invokeMode": "pipelinePhase",
|
|
277
|
+
"order": 0,
|
|
278
|
+
"modelSlot": "skillModel",
|
|
279
|
+
"sourcePath": "/graph/nodes/node:task/parameters/taskConfiguration/aiTaskProfile/inputSynthesis"
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### v1 plan unit shape (legacy engines)
|
|
284
|
+
|
|
285
|
+
```json
|
|
286
|
+
"executionUnits": [
|
|
287
|
+
{
|
|
288
|
+
"unitId": "unit:1:pre",
|
|
289
|
+
"unitKind": "preAction",
|
|
290
|
+
"order": 0,
|
|
291
|
+
"actionKey": "synthesis",
|
|
292
|
+
"modelSlot": "preActionModel",
|
|
293
|
+
"modelSelection": { "kind": "profileChoice", "key": "cheap/default" }
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"unitId": "unit:1:skill",
|
|
297
|
+
"unitKind": "skill",
|
|
298
|
+
"order": 1,
|
|
299
|
+
"skillKey": "professional-answer",
|
|
300
|
+
"modelSlot": "skillModel",
|
|
301
|
+
"modelSelection": { "kind": "profileChoice", "key": "vol/default" }
|
|
302
|
+
}
|
|
303
|
+
]
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Example (API)
|
|
309
|
+
|
|
310
|
+
```ts
|
|
311
|
+
import {
|
|
312
|
+
validateExecutablePlan,
|
|
313
|
+
validateExecutablePlanV1,
|
|
314
|
+
validateExecutablePlanV2
|
|
315
|
+
} from "@x12i/graphenix-plan-format";
|
|
316
|
+
import type { ExecutableGraphPlan } from "@x12i/graphenix-executable-contracts";
|
|
317
|
+
|
|
318
|
+
const result = validateExecutablePlan(plan);
|
|
319
|
+
if (!result.valid) {
|
|
320
|
+
console.error(result.errors.map((e) => `${e.path}: ${e.message}`));
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Or target a specific format version:
|
|
324
|
+
validateExecutablePlanV2(planV2);
|
|
325
|
+
validateExecutablePlanV1(planV1);
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
`validateExecutablePlan()` auto-selects v1 vs v2 from `plan.format`.
|
|
329
|
+
|
|
330
|
+
Typical compile + validate flow:
|
|
331
|
+
|
|
332
|
+
```ts
|
|
333
|
+
import { compileExecutablePlan } from "@x12i/graphenix-plan-compiler";
|
|
334
|
+
import { validateExecutablePlan } from "@x12i/graphenix-plan-format";
|
|
335
|
+
|
|
336
|
+
const plan = compileExecutablePlan(authoringGraph, runtime, {
|
|
337
|
+
profileRegistry: { package: "@x12i/ai-profiles", version: "3.2.0" }
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
const validation = validateExecutablePlan(plan);
|
|
341
|
+
if (!validation.valid) throw new Error("Invalid plan");
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Key exports
|
|
347
|
+
|
|
348
|
+
| API | Purpose |
|
|
349
|
+
| --- | ------- |
|
|
350
|
+
| `validateExecutablePlan(plan)` | Validate v1 or v2 (detects `plan.format`) |
|
|
351
|
+
| `validateExecutablePlanV1(plan)` | Validate `graphenix.executable-plan/v1` only |
|
|
352
|
+
| `validateExecutablePlanV2(plan)` | Validate `graphenix.executable-plan/v2` only |
|
|
353
|
+
|
|
354
|
+
Types and constants are imported from `@x12i/graphenix-executable-contracts`:
|
|
355
|
+
|
|
356
|
+
| Symbol | Value / role |
|
|
357
|
+
| ------ | ------------ |
|
|
358
|
+
| `EXECUTABLE_PLAN_FORMAT` | `"graphenix.executable-plan/v1"` |
|
|
359
|
+
| `EXECUTABLE_PLAN_FORMAT_V2` | `"graphenix.executable-plan/v2"` |
|
|
360
|
+
| `ExecutableGraphPlan` | v1 plan document |
|
|
361
|
+
| `ExecutableGraphPlanV2` | v2 plan document |
|
|
362
|
+
| `NodeExecutionPlan` | Per-node v2 plan with `executionUnits` |
|
|
363
|
+
| `ExecutionUnitPlanV2` | Single v2 execution unit |
|
|
364
|
+
| `ExecutionUnitPlan` | v1 unit (deprecated for new work) |
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## What validation enforces
|
|
369
|
+
|
|
370
|
+
- Plan metadata: `format`, `planId`, `createdAt`, source graph refs, profile registry ref
|
|
371
|
+
- Embedded graph is **normalized** (`validateNormalizedExecutableGraph` via authoring-format)
|
|
372
|
+
- **Case selection** frozen on plan — graph + node cases with explanations
|
|
373
|
+
- **Model slots** resolved per node; `profileChoice` keys well-formed; direct model policy (v2)
|
|
374
|
+
- **Execution units**: ordering, unique ids, kind ↔ `modelSlot` alignment, required MAIN skill
|
|
375
|
+
- **Forbidden fields** never on plan: credentials, trace events, provider responses, execution logs, …
|
|
376
|
+
- v2: `invokeMode` matches `unitKind`, invoke contracts, deferred gates, finalizer plans
|
|
377
|
+
|
|
378
|
+
Validation errors use glossary-friendly paths (e.g. PRE/MAIN/POST phase model slots). Do not label plan units as “Synthesis PRE” — use PRE-phase utility strategy vs skill input synthesis profile per [GLOSSARY.md](../../GLOSSARY.md).
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## Dependencies
|
|
383
|
+
|
|
384
|
+
| Package | Why |
|
|
385
|
+
| ------- | --- |
|
|
386
|
+
| `@x12i/graphenix-executable-contracts` | Plan and unit types, error codes |
|
|
387
|
+
| `@x12i/graphenix-authoring-format` | Validates embedded normalized authoring graph |
|
|
388
|
+
|
|
389
|
+
Peer (via compiler, not required at runtime for validation alone): `@x12i/graphenix-core`.
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## Related packages
|
|
394
|
+
|
|
395
|
+
| Package | Role |
|
|
396
|
+
| ------- | ---- |
|
|
397
|
+
| [GLOSSARY.md](../../GLOSSARY.md) | Canonical phase + strategy + model vocabulary |
|
|
398
|
+
| [`@x12i/graphenix-plan-compiler`](../plan-compiler) | Produces plans from authoring + runtime |
|
|
399
|
+
| [`@x12i/graphenix-authoring-format`](../authoring-format) | Design authoring; phase utility strategies |
|
|
400
|
+
| [`@x12i/graphenix-task-node-format`](../task-node-format) | Task-node body validation (design layer) |
|
|
401
|
+
| [`@x12i/graphenix-executable-profile-format`](../executable-profile-format) | Phase model profiles on authoring graph |
|
|
402
|
+
| [`@x12i/graphenix-trace-format`](../trace-format) | Run evidence bound to a validated plan |
|
|
403
|
+
| [Compiler role guide](../../docs/roles/compiler-service.md) | End-to-end compile client guide |
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## README sync policy
|
|
408
|
+
|
|
409
|
+
When documenting or changing **task run phases**, update these together:
|
|
410
|
+
|
|
411
|
+
| Layer | Package README |
|
|
412
|
+
| ----- | -------------- |
|
|
413
|
+
| Design task body + utility strategies | [task-node-format/README.md](../task-node-format/README.md) |
|
|
414
|
+
| Phase model profiles (authoring) | [executable-profile-format/README.md](../executable-profile-format/README.md) |
|
|
415
|
+
| Compiled plan + execution units | **this file** — include example JSON |
|
|
416
|
+
| Compile pipeline | [plan-compiler/README.md](../plan-compiler/README.md) |
|
|
417
|
+
| Terms of record | [GLOSSARY.md](../../GLOSSARY.md) |
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,0CAA0C,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,0CAA0C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-executable-plan-v1.d.ts","sourceRoot":"","sources":["../../src/validators/validate-executable-plan-v1.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,sCAAsC,CAAC;AAyO5F,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,OAAO,GACZ,+BAA+B,CAyMjC"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { EXECUTABLE_PLAN_FORMAT } from "@x12i/graphenix-executable-contracts";
|
|
2
|
+
import { execError, getExecutableProfile, isExecutableTaskNode, isRecord } from "@x12i/graphenix-executable-contracts";
|
|
3
|
+
import { EXECUTABLE_PROFILE_PATH } from "@x12i/graphenix-executable-contracts";
|
|
4
|
+
import { validateNormalizedExecutableGraph } from "@x12i/graphenix-authoring-format";
|
|
5
|
+
const AI_MODEL_SLOTS = [
|
|
6
|
+
"preActionModel",
|
|
7
|
+
"skillModel",
|
|
8
|
+
"postActionModel"
|
|
9
|
+
];
|
|
10
|
+
const FORBIDDEN_PLAN_FIELDS = [
|
|
11
|
+
"credentials",
|
|
12
|
+
"openrouterApiKey",
|
|
13
|
+
"providerResponse",
|
|
14
|
+
"tokenUsage",
|
|
15
|
+
"executionLog"
|
|
16
|
+
];
|
|
17
|
+
const UNIT_KIND_SLOT = {
|
|
18
|
+
preAction: "preActionModel",
|
|
19
|
+
skill: "skillModel",
|
|
20
|
+
postAction: "postActionModel"
|
|
21
|
+
};
|
|
22
|
+
function validateNodeExecutionUnits(nodeId, executionUnits, errors) {
|
|
23
|
+
if (executionUnits.length === 0) {
|
|
24
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNIT_INVALID", `nodePlans.${nodeId}.executionUnits must contain at least one unit.`, `/nodePlans/${nodeId}/executionUnits`));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
let skillCount = 0;
|
|
28
|
+
let skillIndex = -1;
|
|
29
|
+
const seenUnitIds = new Set();
|
|
30
|
+
const seenOrders = new Set();
|
|
31
|
+
for (const [index, unit] of executionUnits.entries()) {
|
|
32
|
+
const path = `/nodePlans/${nodeId}/executionUnits/${index}`;
|
|
33
|
+
if (!isRecord(unit)) {
|
|
34
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNIT_INVALID", `Execution unit ${index} on node ${nodeId} must be an object.`, path));
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (typeof unit.unitId !== "string" || unit.unitId.length === 0) {
|
|
38
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNIT_INVALID", `Execution unit ${index} on node ${nodeId} must define unitId.`, `${path}/unitId`));
|
|
39
|
+
}
|
|
40
|
+
else if (seenUnitIds.has(unit.unitId)) {
|
|
41
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNIT_INVALID", `Duplicate execution unit id "${unit.unitId}" on node ${nodeId}.`, `${path}/unitId`));
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
seenUnitIds.add(unit.unitId);
|
|
45
|
+
}
|
|
46
|
+
if (unit.nodeId !== nodeId) {
|
|
47
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNIT_INVALID", `Execution unit ${index} on node ${nodeId} must reference nodeId ${nodeId}.`, `${path}/nodeId`));
|
|
48
|
+
}
|
|
49
|
+
if (typeof unit.order !== "number" || !Number.isInteger(unit.order)) {
|
|
50
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNIT_INVALID", `Execution unit ${index} on node ${nodeId} must define integer order.`, `${path}/order`));
|
|
51
|
+
}
|
|
52
|
+
else if (seenOrders.has(unit.order)) {
|
|
53
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNIT_INVALID", `Duplicate execution unit order ${unit.order} on node ${nodeId}.`, `${path}/order`));
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
seenOrders.add(unit.order);
|
|
57
|
+
}
|
|
58
|
+
const unitKind = unit.unitKind;
|
|
59
|
+
if (unitKind === "skill") {
|
|
60
|
+
skillCount += 1;
|
|
61
|
+
skillIndex = index;
|
|
62
|
+
}
|
|
63
|
+
const expectedSlot = UNIT_KIND_SLOT[String(unitKind)];
|
|
64
|
+
if (expectedSlot && unit.modelSlot !== expectedSlot) {
|
|
65
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNIT_INVALID", `Execution unit ${unit.unitId ?? index} on node ${nodeId} must use modelSlot ${expectedSlot}.`, `${path}/modelSlot`));
|
|
66
|
+
}
|
|
67
|
+
if (unitKind === "preAction" ||
|
|
68
|
+
unitKind === "skill" ||
|
|
69
|
+
unitKind === "postAction") {
|
|
70
|
+
if (!isRecord(unit.modelSelection)) {
|
|
71
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNIT_INVALID", `Execution unit ${unit.unitId ?? index} on node ${nodeId} must define modelSelection.`, `${path}/modelSelection`));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (skillCount !== 1) {
|
|
76
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNIT_INVALID", `nodePlans.${nodeId}.executionUnits must contain exactly one skill unit.`, `/nodePlans/${nodeId}/executionUnits`));
|
|
77
|
+
}
|
|
78
|
+
if (skillIndex >= 0) {
|
|
79
|
+
for (let index = 0; index < skillIndex; index += 1) {
|
|
80
|
+
const unit = executionUnits[index];
|
|
81
|
+
if (isRecord(unit) && unit.unitKind !== "preAction") {
|
|
82
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNIT_INVALID", `Pre-action units on node ${nodeId} must appear before the skill unit.`, `/nodePlans/${nodeId}/executionUnits/${index}`));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
for (let index = skillIndex + 1; index < executionUnits.length; index += 1) {
|
|
86
|
+
const unit = executionUnits[index];
|
|
87
|
+
if (isRecord(unit) && unit.unitKind !== "postAction") {
|
|
88
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNIT_INVALID", `Post-action units on node ${nodeId} must appear after the skill unit.`, `/nodePlans/${nodeId}/executionUnits/${index}`));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const orders = [...seenOrders].sort((a, b) => a - b);
|
|
93
|
+
for (let index = 0; index < orders.length; index += 1) {
|
|
94
|
+
if (orders[index] !== index) {
|
|
95
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNIT_INVALID", `Execution unit orders on node ${nodeId} must be contiguous starting at 0.`, `/nodePlans/${nodeId}/executionUnits`));
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function containsForbiddenFields(value, path, errors) {
|
|
101
|
+
if (!isRecord(value)) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
for (const field of FORBIDDEN_PLAN_FIELDS) {
|
|
105
|
+
if (field in value) {
|
|
106
|
+
errors.push(execError("EXECUTABLE_PLAN_FORBIDDEN_FIELD", `Executable plan must not contain ${field}.`, `${path}/${field}`));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
for (const [key, child] of Object.entries(value)) {
|
|
110
|
+
if (isRecord(child) || Array.isArray(child)) {
|
|
111
|
+
containsForbiddenFields(child, `${path}/${key}`, errors);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
export function validateExecutablePlanV1(plan) {
|
|
116
|
+
const errors = [];
|
|
117
|
+
if (!isRecord(plan)) {
|
|
118
|
+
return {
|
|
119
|
+
valid: false,
|
|
120
|
+
errors: [
|
|
121
|
+
execError("EXECUTABLE_PLAN_INVALID", "Executable plan must be an object.", "")
|
|
122
|
+
]
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (plan.format !== EXECUTABLE_PLAN_FORMAT) {
|
|
126
|
+
errors.push(execError("EXECUTABLE_PLAN_FORMAT_INVALID", `format must be ${EXECUTABLE_PLAN_FORMAT}.`, "/format"));
|
|
127
|
+
}
|
|
128
|
+
if (typeof plan.planId !== "string" || plan.planId.length === 0) {
|
|
129
|
+
errors.push(execError("EXECUTABLE_PLAN_ID_MISSING", "planId is required.", "/planId"));
|
|
130
|
+
}
|
|
131
|
+
if (typeof plan.createdAt !== "string") {
|
|
132
|
+
errors.push(execError("EXECUTABLE_PLAN_CREATED_AT_MISSING", "createdAt is required.", "/createdAt"));
|
|
133
|
+
}
|
|
134
|
+
const source = plan.source;
|
|
135
|
+
if (!isRecord(source)) {
|
|
136
|
+
errors.push(execError("EXECUTABLE_PLAN_SOURCE_MISSING", "source is required.", "/source"));
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
if (typeof source.graphId !== "string") {
|
|
140
|
+
errors.push(execError("EXECUTABLE_PLAN_SOURCE_GRAPH_ID_MISSING", "source.graphId is required.", "/source/graphId"));
|
|
141
|
+
}
|
|
142
|
+
if (typeof source.graphHash !== "string") {
|
|
143
|
+
errors.push(execError("EXECUTABLE_PLAN_SOURCE_GRAPH_HASH_MISSING", "source.graphHash is required.", "/source/graphHash"));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const runtimeBinding = plan.runtimeBinding;
|
|
147
|
+
if (!isRecord(runtimeBinding) || typeof runtimeBinding.jobId !== "string") {
|
|
148
|
+
errors.push(execError("EXECUTABLE_PLAN_RUNTIME_BINDING_MISSING", "runtimeBinding.jobId is required.", "/runtimeBinding"));
|
|
149
|
+
}
|
|
150
|
+
if (!isRecord(plan.graph)) {
|
|
151
|
+
errors.push(execError("EXECUTABLE_PLAN_GRAPH_MISSING", "graph is required.", "/graph"));
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
const graphValidation = validateNormalizedExecutableGraph(plan.graph);
|
|
155
|
+
if (!graphValidation.valid) {
|
|
156
|
+
errors.push(...graphValidation.errors);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
const profile = getExecutableProfile(plan.graph);
|
|
160
|
+
const modelConfig = profile?.modelConfig;
|
|
161
|
+
if (modelConfig?.default !== undefined) {
|
|
162
|
+
errors.push(execError("EXECUTABLE_PLAN_GRAPH_NOT_NORMALIZED", "Executable plan graph must not use modelConfig.default shorthand.", `${EXECUTABLE_PROFILE_PATH}/modelConfig/default`));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const caseSelection = plan.caseSelection;
|
|
167
|
+
if (!isRecord(caseSelection) || !isRecord(caseSelection.graph)) {
|
|
168
|
+
errors.push(execError("EXECUTABLE_PLAN_CASE_SELECTION_MISSING", "caseSelection.graph is required.", "/caseSelection/graph"));
|
|
169
|
+
}
|
|
170
|
+
else if (typeof caseSelection.graph.caseId !== "string") {
|
|
171
|
+
errors.push(execError("EXECUTABLE_PLAN_GRAPH_CASE_MISSING", "caseSelection.graph.caseId is required.", "/caseSelection/graph/caseId"));
|
|
172
|
+
}
|
|
173
|
+
const nodePlans = plan.nodePlans;
|
|
174
|
+
if (!isRecord(nodePlans)) {
|
|
175
|
+
errors.push(execError("EXECUTABLE_PLAN_NODE_PLANS_MISSING", "nodePlans is required.", "/nodePlans"));
|
|
176
|
+
}
|
|
177
|
+
else if (isRecord(plan.graph)) {
|
|
178
|
+
const graphDoc = plan.graph;
|
|
179
|
+
const taskNodeIds = graphDoc.graph.nodes
|
|
180
|
+
.filter(isExecutableTaskNode)
|
|
181
|
+
.map((node) => node.id);
|
|
182
|
+
for (const nodeId of taskNodeIds) {
|
|
183
|
+
const nodePlan = nodePlans[nodeId];
|
|
184
|
+
if (!isRecord(nodePlan)) {
|
|
185
|
+
errors.push(execError("EXECUTABLE_PLAN_NODE_PLAN_MISSING", `nodePlans must contain resolved plan for task node ${nodeId}.`, `/nodePlans/${nodeId}`));
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const modelSlots = nodePlan
|
|
189
|
+
.modelSlots;
|
|
190
|
+
for (const slot of AI_MODEL_SLOTS) {
|
|
191
|
+
const slotPlan = modelSlots?.[slot];
|
|
192
|
+
if (!isRecord(slotPlan) || !isRecord(slotPlan.selection)) {
|
|
193
|
+
errors.push(execError("EXECUTABLE_PLAN_NODE_SLOT_MISSING", `nodePlans.${nodeId}.modelSlots.${slot} must be resolved.`, `/nodePlans/${nodeId}/modelSlots/${slot}`));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const executionUnits = nodePlan.executionUnits;
|
|
197
|
+
if (!Array.isArray(executionUnits)) {
|
|
198
|
+
errors.push(execError("EXECUTABLE_PLAN_EXECUTION_UNITS_MISSING", `nodePlans.${nodeId}.executionUnits is required.`, `/nodePlans/${nodeId}/executionUnits`));
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
validateNodeExecutionUnits(nodeId, executionUnits, errors);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
containsForbiddenFields(plan, "", errors);
|
|
205
|
+
return { valid: errors.length === 0, errors };
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=validate-executable-plan-v1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-executable-plan-v1.js","sourceRoot":"","sources":["../../src/validators/validate-executable-plan-v1.ts"],"names":[],"mappings":"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"}
|