@x12i/graphenix-trace-format
GraphExecutionTrace format — append-only run evidence for a single graph execution.
Covers node traces, execution unit traces, model invocation attempts, fallback events, and final output. Does not depend on authoring graphs.
Canonical vocabulary: GLOSSARY.md — task run phases map to trace unit.* events in plan order.
Finalization brief: EXECUTE-TRACE-FORMAT-FINALIZATION.md.
Do not use “Synthesis PRE” in trace docs — use PRE-phase utility / externalPreUtility with strategyKey.
Who should use this
| Role | Use this package? |
|---|---|
| Execution engine | Yes — create and append events during a run |
| Run history / observability / analytics | Yes — validate and read traces |
| Graph designer / Studio | No (unless displaying run history) |
Lifecycle position
ExecutableGraphPlan + GraphRuntimeObject
│ engine executes executionUnits[] (prePhase → mainPhase → postPhase)
▼
GraphExecutionTrace ← THIS PACKAGE
Reference domain: content pipeline plan (graph:content-pipeline) — three parallel tasks with PRE synthesis + MAIN skill, no POST on reference tasks.
Install
npm install @x12i/graphenix-trace-format
Trace document shape
GraphExecutionTrace
├─ traceId, jobId, status, createdAt, completedAt
├─ source — graphId, graphHash (from plan)
├─ plan — planId, planHash (bind trace to frozen plan)
├─ runtime — mode, environment, inputHash (no credentials)
├─ events[] — append-only audit log
├─ unitExecutions{} — indexed unit lifecycle records
├─ modelInvocations{} — indexed model invocation records
└─ nodeExecutions{} — per-node rollups derived from unit terminal state
Normative dual-write: When appending unit.* or model.invocation.* events, also update unitExecutions / modelInvocations through the lifecycle API. Events alone do not satisfy analytics or plan validation consumers.
Examples (JSON)
Trace header (bound to content pipeline plan)
{
"format": "graphenix.execution-trace/v1",
"traceId": "trace:job-001",
"jobId": "job-001",
"createdAt": "2026-06-06T12:00:00.000Z",
"status": "running",
"source": {
"graphId": "graph:content-pipeline",
"graphRevision": "1.0.0",
"graphHash": "sha256:…"
},
"plan": {
"planId": "plan:abc123",
"planHash": "sha256:…"
},
"runtime": {
"mode": "live",
"environment": "prod",
"inputHash": "sha256:…"
},
"events": [],
"nodeExecutions": {}
}
Unit events for one content-pipeline task (PRE + MAIN)
After node:audience-insights runs PRE-phase utility synthesis then MAIN skill:
"events": [
{
"id": "evt:1",
"ts": "2026-06-06T12:00:01.000Z",
"level": "info",
"type": "node.started",
"nodeId": "node:audience-insights"
},
{
"id": "evt:2",
"ts": "2026-06-06T12:00:01.100Z",
"level": "info",
"type": "unit.started",
"nodeId": "node:audience-insights",
"unitId": "unit:node:audience-insights:pre:0",
"unitKind": "externalPreUtility"
},
{
"id": "evt:3",
"ts": "2026-06-06T12:00:02.500Z",
"level": "info",
"type": "model.invocation.completed",
"nodeId": "node:audience-insights",
"unitId": "unit:node:audience-insights:pre:0",
"modelSlot": "preActionModel"
},
{
"id": "evt:4",
"ts": "2026-06-06T12:00:02.600Z",
"level": "info",
"type": "unit.started",
"nodeId": "node:audience-insights",
"unitId": "unit:node:audience-insights:main:1",
"unitKind": "mainSkill"
},
{
"id": "evt:5",
"ts": "2026-06-06T12:00:05.000Z",
"level": "info",
"type": "node.completed",
"nodeId": "node:audience-insights"
}
]
Model profiles were resolved at compile time — trace records which modelSlot was invoked, not a re-selected case.
Example (API)
import {
createEmptyExecutionTrace,
appendTraceEvent,
appendUnitLifecycleEvent,
markUnitCompleted,
recordModelInvocationStarted,
recordModelInvocationCompleted,
validateTraceAgainstPlan,
deriveGraphStatus,
summarizeExecutionTrace
} from "@x12i/graphenix-trace-format";
const trace = createEmptyExecutionTrace({ traceId, plan, runtime });
appendTraceEvent(trace, {
id: "evt:1",
ts: new Date().toISOString(),
sequence: 1,
level: "info",
type: "graph.started"
}, { mutate: true });
const unit = plan.nodePlans["node:audience-insights"].executionUnits[0];
appendUnitLifecycleEvent(trace, "unit.started", unit);
recordModelInvocationStarted(trace, {
invocationId: "inv:pre:1",
unitId: unit.unitId,
nodeId: unit.nodeId,
modelSlot: unit.modelSlot,
plannedModelSelection: unit.modelSelection
});
recordModelInvocationCompleted(trace, "inv:pre:1", { durationMs: 1200 });
appendUnitLifecycleEvent(trace, "unit.completed", unit, { durationMs: 1500 });
const result = validateTraceAgainstPlan(trace, plan);
const status = deriveGraphStatus(trace);
const summary = summarizeExecutionTrace(trace);
Key exports
| API | Purpose |
|---|---|
createEmptyExecutionTrace |
Initialize v2 trace with seeded unit/node indexes |
appendTraceEvent |
Append-only event mutation |
markUnitStarted / markUnitCompleted / markUnitFailed |
Update unitExecutions + graphExecution indexes |
recordModelInvocationStarted / Completed / Failed |
Update modelInvocations + link to units |
appendUnitLifecycleEvent |
Append unit.* event and update indexes in one call |
rollupNodeExecution |
Roll up unit terminal state to node indexes and append node.completed / node.failed |
appendFallbackAppliedEvent |
Append fallback.applied and update unit fallback index |
reconcileTraceIndexesFromEvents |
Best-effort rebuild of indexes from legacy event-only traces |
validateTraceAgainstPlan |
Validate trace against frozen v2 plan |
deriveGraphStatus |
Overall run status from indexes |
deriveNodeStatusFromUnits |
Per-node status from unit indexes |
summarizeExecutionTrace |
Compact summary for dashboards |
createContentPipelineReferenceTrace(plan, options?) |
Build completed CP trace for tests and golden fixtures |
Trace event types include graph/node lifecycle, execution unit lifecycle (unit.started / unit.completed), model invocation, fallback applied, validation failures, and warnings.
Event catalog (required fields per type): execution-logs.md · golden trace: fixtures/content-pipeline.trace.json
Validation tier
| When | API |
|---|---|
| Run end (engine) | validateExecutionTrace(trace, plan.nodePlans) |
| Index / analytics | validateExecutionTrace before storing |
| Dashboards | deriveGraphStatus, summarizeExecutionTrace |
Store planHash (or full plan snapshot) with each trace for strict replay validation.
Format identifiers
EXECUTION_TRACE_FORMAT // v1 — @x12i/graphenix-executable-contracts
EXECUTION_TRACE_FORMAT_V2 // v2 — when plan is v2
Dependencies
@x12i/graphenix-executable-contracts^1.1.0
Related packages
| Package | Role |
|---|---|
| GLOSSARY.md | Phase vocabulary for unit events |
@x12i/graphenix-plan-format |
Plan shape traces reference |
@x12i/graphenix-plan-compiler |
Produces the plan a trace is bound to |
| EXECUTE-TRACE-FORMAT-FINALIZATION.md | Execute + trace phase brief |
| observability role guide | Run history client guide |
README sync policy
When documenting task run phases at execution/trace layer, update together:
| Layer | README / doc |
|---|---|
| Compiled plan units | plan-format/README.md |
| Trace events | this file |
| Execute + trace brief | EXECUTE-TRACE-FORMAT-FINALIZATION.md |
| Terms of record | GLOSSARY.md |