# @x12i/graphenix-plan-format

> ExecutableGraphPlan format: plan schema validation and canonicalization.

Latest version **2.17.0** (published 2026-07-10) · MIT license · 0 weekly downloads

## Install

```sh
npm install @x12i/graphenix-plan-format
pnpm add @x12i/graphenix-plan-format
yarn add @x12i/graphenix-plan-format
bun add @x12i/graphenix-plan-format
```

## Health

**Score 60/100 (C)** — status: active.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 2.17.0 |
| Published | 2026-07-10 |
| First published | 2026-06-06 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 2 |
| Unpacked size | 262.2 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Maintainers | x12i |
| Keywords | graph, graphenix, plan, executable |

## Links

- npm: https://www.npmjs.com/package/@x12i/graphenix-plan-format
- Repository: https://github.com/x12i/graphenix-format
- Homepage: https://github.com/x12i/graphenix-format/tree/master/packages/plan-format#readme
- Issues: https://github.com/x12i/graphenix-format/issues
- npm.io page: https://npm.io/package/@x12i/graphenix-plan-format

## Dependencies (2)

- [@x12i/graphenix-authoring-format](https://npm.io/package/@x12i/graphenix-authoring-format.md) ^2.17.0
- [@x12i/graphenix-executable-contracts](https://npm.io/package/@x12i/graphenix-executable-contracts.md) ^2.17.0

## Alternatives

- [apollo-link-http-common](https://npm.io/package/apollo-link-http-common.md) — 879.0K weekly downloads
- [react-relay](https://npm.io/package/react-relay.md) — 336.8K weekly downloads
- [relay-test-utils](https://npm.io/package/relay-test-utils.md) — 181.6K weekly downloads
- [@vendure/core](https://npm.io/package/@vendure/core.md) — 14.8K weekly downloads
- [@pnpm/deps.graph-sequencer](https://npm.io/package/@pnpm/deps.graph-sequencer.md) — 13.4K weekly downloads

## Recent versions

- 2.17.0 (latest) — 2026-07-10
- 2.16.0 — 2026-06-29
- 2.15.0 — 2026-06-29
- 2.14.0 — 2026-06-28
- 2.12.5 — 2026-06-28
- 2.12.4 — 2026-06-28
- 2.12.3 — 2026-06-27
- 2.12.2 — 2026-06-27
- 2.11.0 — 2026-06-24
- 2.10.0 — 2026-06-24
- 2.9.0 — 2026-06-23
- 2.8.1 — 2026-06-21
- 2.8.0 — 2026-06-21
- 2.7.3 — 2026-06-20
- 2.7.2 — 2026-06-20
- … 16 more at https://npm.io/package/@x12i/graphenix-plan-format/versions

## README

# @x12i/graphenix-plan-format

**ExecutableGraphPlan** format — validates the engine-facing artifact produced by `@x12i/graphenix-plan-compiler`.

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.

This package **does not compile** from authoring graphs — it only validates plan documents. Use `@x12i/graphenix-plan-compiler` to produce plans.

**Canonical vocabulary:** [GLOSSARY.md](../../GLOSSARY.md) at monorepo root.  
**Finalization brief:** [COMPILE-FORMAT-FINALIZATION.md](../../docs/COMPILE-FORMAT-FINALIZATION.md) · execute/trace: [EXECUTE-TRACE-FORMAT-FINALIZATION.md](../../docs/EXECUTE-TRACE-FORMAT-FINALIZATION.md).  
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.

---

## Who should use this

| Role | Use this package? |
| ---- | ----------------- |
| Execution engine | **Yes** — validate plan before run |
| Compiler / execution prep | **Yes** — validate output before handoff |
| Run history / observability | **Yes** — bind traces to validated plan shape |
| Graph designer / Studio | Only if showing compile preview |
| Authoring-only services | **No** — use `@x12i/graphenix-authoring-format` |

---

## Install

```bash
npm install @x12i/graphenix-plan-format
```

Types (`ExecutableGraphPlan`, `ExecutableGraphPlanV2`, `ExecutionUnitPlanV2`, …) live in `@x12i/graphenix-executable-contracts`.

---

## Lifecycle position

```txt
AuthoringGraphDocument
        │  compileAuthoringGraphToExecutablePlan()  (static — no runtime)
        │  compileExecutablePlanV2(authoring, runtime)  (execute path only)
        ▼
ExecutableGraphPlan              ← THIS PACKAGE validates
```

**Execute contract:** `validateExecutablePlanV2` requires **complete** `nodePlans[].modelSlots` for AI tasks (job ⊕ node merge happens at compile — execute must not re-read partial node `taskConfiguration.modelConfig`).

---

## Task run phases (runtime topology)

One task node invocation is three **run phases** ([GLOSSARY §1](../../GLOSSARY.md#1-task-run-phases-runtime-shape-of-one-runtask-wave)):

| Run phase | Meaning | Typical plan units |
| --------- | ------- | ------------------ |
| **prePhase** | Optional utility work before the skill | `externalPreUtility` (v2) / `preAction` (v1) |
| **mainPhase** | Skill / MAIN execution | `mainSkill`, `pipelinePhase`, `localSkill` (v2) / `skill` (v1) |
| **postPhase** | Optional utility work after the skill | `externalPostUtility` (v2) / `postAction` (v1) |

This is **phase topology** — not model choice and not catalog action ids.

### Design → plan mapping (do not conflate)

Authoring declares **phase utility strategies** on the task node. The compiler expands them into **plan execution units**:

```txt
prePhase.strategyKey (design: aiTaskStrategies.pre)
        │  compile
        ▼
PRE-phase execution units (plan: externalPreUtility / preAction)

mainPhase.executionStrategies + skill input synthesis profile (design)
        │  compile
        ▼
MAIN-phase execution units (plan: mainSkill, pipelinePhase, …)

postPhase.strategyKey (design: aiTaskStrategies.post)
        │  compile
        ▼
POST-phase execution units (plan: externalPostUtility / postAction)
```

| Design (authoring) | Plan (this package) | Glossary |
| ------------------ | ------------------- | -------- |
| `aiTaskStrategies.pre` | PRE-phase units with `strategyKey` / `actionKey` | PRE-phase utility strategy → plan PRE-phase action list |
| `executionStrategies`, `aiTaskProfile.inputSynthesis` | `mainSkill`, `pipelinePhase`, … | MAIN-phase wrappers / skill input synthesis profile |
| `aiTaskStrategies.post` | POST-phase units | POST-phase utility strategy → plan POST-phase action list |
| `preActions[]` / `postActions[]` (optional on design) | Same shape at plan layer | Plan-phase action lists — **not** synonyms for `aiTaskStrategies.pre` |

**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.

**PRE synthesis (2.4.0):** `inputsConfig` and `smartInput.paths` are MAIN only. PRE `invokeContract.reads` / `unitParams.memoryPaths` come from `aiTaskProfile.inputSynthesis.sources` or are empty (`[]`) for runtime default trio. When `sources` is authored, `reads` and `memoryPaths` must be identical.

Each execution unit carries a **phase model profile** binding ([GLOSSARY §4](../../GLOSSARY.md#4-phase-model-profiles-executable-extension--separate-layer)):

| `modelSlot` | Run phase |
| ----------- | --------- |
| `preActionModel` | PRE-phase model profile |
| `skillModel` | MAIN-phase model profile |
| `postActionModel` | POST-phase model profile |
| `finalizerModel` | Finalizer (graph output) |

Utility strategy = **what** runs. Model profile = **which AI profile** runs it.

---

## Plan document shape

### v1 — `graphenix.executable-plan/v1`

```txt
ExecutableGraphPlan
  ├─ format, planId, createdAt
  ├─ source (graphId, graphHash, …)
  ├─ profileRegistry (@x12i/ai-profiles version)
  ├─ runtimeBinding (jobId, mode, environment, hashes)
  ├─ graph — embedded NormalizedExecutableGraphDocument
  ├─ caseSelection — graph + per-node selected cases
  ├─ nodePlans[nodeId]
  │     ├─ selectedCases, modelSlots (preActionModel / skillModel / postActionModel)
  │     └─ executionUnits[] — ordered preAction → skill → postAction
  └─ finalizerPlans (if applicable)
```

v1 unit kinds: `preAction` | `skill` | `postAction` | `finalizer`.

### v2 — `graphenix.executable-plan/v2` (preferred for new engines)

```txt
ExecutableGraphPlanV2
  ├─ format, planId, createdAt, planHash
  ├─ source, profileRegistry, runtimeBinding, runtimeExpectations
  ├─ normalizedGraph — embedded or ref
  ├─ policies (directModelPolicy, fallback, trace, …)
  ├─ nodeIndex[], deferredGates[]
  ├─ nodePlans[nodeId] — NodeExecutionPlan
  │     ├─ invokeContract (pipeline snapshot from authoring)
  │     ├─ modelSlots, selectedCases
  │     └─ executionUnits[] — ordered by run phase
  └─ finalizerPlans[nodeId] — FinalizerExecutionPlan
```

v2 unit kinds include:

| `unitKind` | Typical run phase | `invokeMode` |
| ---------- | ----------------- | ------------ |
| `externalPreUtility` | prePhase | `externalRunTask` |
| `mainSkill` | mainPhase | `mainRunTask` |
| `pipelinePhase` | mainPhase (wrapper / synthesis inside MAIN) | `pipelinePhase` |
| `localSkill` | mainPhase | `local` |
| `externalPostUtility` | postPhase | `externalRunTask` |
| `finalizer` | graph output | `finalizer` |
| `validation`, `mapping`, `callGraph` | special | `none` / … |

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).

---

## Per-task node plan (diagram)

```txt
NodeExecutionPlan (one task node, one runTask wave)
│
├─ prePhase units[]     externalPreUtility / preAction
│       modelSlot: preActionModel
│
├─ mainPhase units[]    mainSkill | pipelinePhase | localSkill
│       modelSlot: skillModel (pipelinePhase may share MAIN profile)
│
└─ postPhase units[]    externalPostUtility / postAction
        modelSlot: postActionModel
```

Order is strict: PRE units → MAIN units → POST units. Validators reject missing MAIN skill, duplicate orders, and slot/kind mismatches.

---

## Examples (JSON)

### v2 plan header (minimal)

```json
{
  "format": "graphenix.executable-plan/v2",
  "planId": "plan:abc123",
  "createdAt": "2026-06-06T12:00:00.000Z",
  "planHash": "sha256:…",
  "source": {
    "graphId": "graph:content-pipeline",
    "graphRevision": "1.0.0",
    "graphHash": "sha256:…",
    "formatVersion": "2.0.0"
  },
  "profileRegistry": {
    "package": "@x12i/ai-profiles",
    "version": "3.2.0",
    "registryHash": "sha256:…"
  },
  "runtimeBinding": {
    "jobId": "job-001",
    "mode": "live",
    "environment": "prod",
    "sourceGraphHash": "sha256:…",
    "profileRegistryHash": "sha256:…"
  }
}
```

### v2 `nodePlans` — PRE + MAIN execution units (content pipeline)

Compiled from authoring `aiTaskStrategies.pre: "synthesis"` + `executionStrategies: []` on `node:audience-insights`. No POST units unless design declares `aiTaskStrategies.post`:

```json
"nodePlans": {
  "node:audience-insights": {
    "nodeId": "node:audience-insights",
    "nodeType": "task",
    "executionClass": "aiTask",
    "skillKey": "professional-answer",
    "selectedCases": {
      "graphModelCaseId": "default"
    },
    "modelSlots": {
      "preActionModel": {
        "selection": { "kind": "profileChoice", "key": "cheap/default" },
        "source": "graphCase"
      },
      "skillModel": {
        "selection": { "kind": "profileChoice", "key": "vol/default" },
        "source": "graphCase"
      }
    },
    "executionUnits": [
      {
        "unitId": "unit:node:audience-insights:pre:0",
        "nodeId": "node:audience-insights",
        "unitKind": "externalPreUtility",
        "invokeMode": "externalRunTask",
        "order": 0,
        "strategyKey": "synthesis",
        "actionKey": "synthesis",
        "modelSlot": "preActionModel",
        "modelSelection": { "kind": "profileChoice", "key": "cheap/default" },
        "sourcePath": "/graph/nodes/node:audience-insights/parameters/taskConfiguration/aiTaskStrategies/pre"
      },
      {
        "unitId": "unit:node:audience-insights:main:1",
        "nodeId": "node:audience-insights",
        "unitKind": "mainSkill",
        "invokeMode": "mainRunTask",
        "order": 1,
        "skillKey": "professional-answer",
        "modelSlot": "skillModel",
        "modelSelection": { "kind": "profileChoice", "key": "vol/default" },
        "sourcePath": "/graph/nodes/node:audience-insights/parameters/skillKey"
      }
    ],
    "sourcePath": "/graph/nodes/node:audience-insights"
  }
}
```

### v2 `nodePlans` — PRE / MAIN / POST

When authoring declares `aiTaskStrategies.post`, the compiler appends POST-phase units (same mapping as PRE via `externalPostUtility`).

### v2 MAIN `pipelinePhase` from skill input synthesis profile (not PRE utility)

When authoring uses `aiTaskProfile.inputSynthesis.enabled` (not `aiTaskStrategies.pre`):

```json
{
  "unitId": "unit:node:task:pipeline:0",
  "unitKind": "pipelinePhase",
  "invokeMode": "pipelinePhase",
  "order": 0,
  "modelSlot": "skillModel",
  "sourcePath": "/graph/nodes/node:task/parameters/taskConfiguration/aiTaskProfile/inputSynthesis"
}
```

### v1 plan unit shape (legacy engines)

```json
"executionUnits": [
  {
    "unitId": "unit:1:pre",
    "unitKind": "preAction",
    "order": 0,
    "actionKey": "synthesis",
    "modelSlot": "preActionModel",
    "modelSelection": { "kind": "profileChoice", "key": "cheap/default" }
  },
  {
    "unitId": "unit:1:skill",
    "unitKind": "skill",
    "order": 1,
    "skillKey": "professional-answer",
    "modelSlot": "skillModel",
    "modelSelection": { "kind": "profileChoice", "key": "vol/default" }
  }
]
```

---

## Example (API)

```ts
import {
  validateExecutablePlan,
  validateExecutablePlanV1,
  validateExecutablePlanV2
} from "@x12i/graphenix-plan-format";
import type { ExecutableGraphPlan } from "@x12i/graphenix-executable-contracts";

const result = validateExecutablePlan(plan);
if (!result.valid) {
  console.error(result.errors.map((e) => `${e.path}: ${e.message}`));
}

// Or target a specific format version:
validateExecutablePlanV2(planV2);
validateExecutablePlanV1(planV1);
```

`validateExecutablePlan()` auto-selects v1 vs v2 from `plan.format`.

Typical compile + validate flow:

```ts
import { compileExecutablePlan } from "@x12i/graphenix-plan-compiler";
import { validateExecutablePlan } from "@x12i/graphenix-plan-format";

const plan = compileExecutablePlan(authoringGraph, runtime, {
  profileRegistry: { package: "@x12i/ai-profiles", version: "3.2.0" }
});

const validation = validateExecutablePlan(plan);
if (!validation.valid) throw new Error("Invalid plan");
```

---

## Key exports

| API | Purpose |
| --- | ------- |
| `validateExecutablePlan(plan)` | Validate v1 or v2 (detects `plan.format`) |
| `validateExecutablePlanV1(plan)` | Validate `graphenix.executable-plan/v1` only |
| `validateExecutablePlanV2(plan)` | Validate `graphenix.executable-plan/v2` only |

Types and constants are imported from `@x12i/graphenix-executable-contracts`:

| Symbol | Value / role |
| ------ | ------------ |
| `EXECUTABLE_PLAN_FORMAT` | `"graphenix.executable-plan/v1"` |
| `EXECUTABLE_PLAN_FORMAT_V2` | `"graphenix.executable-plan/v2"` |
| `ExecutableGraphPlan` | v1 plan document |
| `ExecutableGraphPlanV2` | v2 plan document |
| `NodeExecutionPlan` | Per-node v2 plan with `executionUnits` |
| `ExecutionUnitPlanV2` | Single v2 execution unit |
| `ExecutionUnitPlan` | v1 unit (deprecated for new work) |

---

## What validation enforces

- Plan metadata: `format`, `planId`, `createdAt`, source graph refs, profile registry ref
- Embedded graph is **normalized** (`validateNormalizedExecutableGraph` via authoring-format)
- **Case selection** frozen on plan — graph + node cases with explanations
- **Model slots** resolved per node; `profileChoice` keys well-formed; direct model policy (v2)
- **Execution units**: ordering, unique ids, kind ↔ `modelSlot` alignment, required MAIN skill
- **Optional fact-guard** on sub-action `unitParams` (`synthesis`, `polish`, `audit`); `enabled: true` requires `policyId`; `mainSkill` forbidden — see [GLOSSARY §6](../../GLOSSARY.md#6-fact-guard-optional-sub-action-integrity)
- **Forbidden fields** never on plan: credentials, trace events, provider responses, execution logs, …
- v2: `invokeMode` matches `unitKind`, invoke contracts, deferred gates, finalizer plans

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).

---

## Dependencies

| Package | Why |
| ------- | --- |
| `@x12i/graphenix-executable-contracts` | Plan and unit types, error codes |
| `@x12i/graphenix-authoring-format` | Validates embedded normalized authoring graph |

Peer (via compiler, not required at runtime for validation alone): `@x12i/graphenix-core`.

---

## Related packages

| Package | Role |
| ------- | ---- |
| [GLOSSARY.md](../../GLOSSARY.md) | Canonical phase + strategy + model vocabulary |
| [`@x12i/graphenix-plan-compiler`](../plan-compiler) | Produces plans from authoring + runtime |
| [`@x12i/graphenix-authoring-format`](../authoring-format) | Design authoring; phase utility strategies |
| [`@x12i/graphenix-task-node-format`](../task-node-format) | Task-node body validation (design layer) |
| [`@x12i/graphenix-executable-profile-format`](../executable-profile-format) | Phase model profiles on authoring graph |
| [`@x12i/graphenix-trace-format`](../trace-format) | Run evidence bound to a validated plan |
| [Compiler role guide](../../docs/roles/compiler-service.md) | End-to-end compile client guide |

---

## README sync policy

When documenting or changing **task run phases**, update these together:

| Layer | Package README |
| ----- | -------------- |
| Design task body + utility strategies | [task-node-format/README.md](../task-node-format/README.md) |
| Phase model profiles (authoring) | [executable-profile-format/README.md](../executable-profile-format/README.md) |
| Compiled plan + execution units | **this file** — include example JSON |
| Compile pipeline | [plan-compiler/README.md](../plan-compiler/README.md) |
| Terms of record | [GLOSSARY.md](../../GLOSSARY.md) |

---
_Source: https://npm.io/package/@x12i/graphenix-plan-format · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
