@x12i/graphenix-trace-format
v2.17.0
Published
GraphExecutionTrace format: append-only events, validation, and trace helpers.
Readme
@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 PACKAGEReference 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-formatTrace 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 stateNormative 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 v2Dependencies
@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 |
