footprint-explainable-ui 0.22.0 → 0.24.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 CHANGED
@@ -362,6 +362,22 @@ Strip all built-in styles for full CSS control. Components render semantic `data
362
362
 
363
363
  ---
364
364
 
365
+ ## Golden-Trace Fixtures (contributors)
366
+
367
+ The pipeline (structure/runtime translators, dagre layout, snapshot adapter,
368
+ narrative sync) is pinned against **real footprintjs engine output**, not
369
+ hand-built mocks. `test/fixtures/golden/` holds recorded traces from 4
370
+ representative charts (linear+decider, subflow+loop, parallel fork,
371
+ pause/resume); `test/golden/goldenTraces.test.ts` replays them through the full
372
+ pipeline and snapshot-asserts the outputs in `test/golden/__snapshots__/`.
373
+
374
+ - **Engine shape changed** (new footprintjs): `npm i -D --save-exact footprintjs@<version> && npm run fixtures:regen`. The generator runs every chart twice and fails on any nondeterminism.
375
+ - **Pipeline output changed intentionally** (eui edit): `npx vitest run test/golden -u`, then review the snapshot diff.
376
+ - `test/fixtures/golden/manifest.json` records the footprintjs version the fixtures were recorded with.
377
+
378
+ `footprintjs` is a devDependency used ONLY by the generator — the published
379
+ library still has zero footprintjs dependency (it consumes plain JSON shapes).
380
+
365
381
  ## License
366
382
 
367
383
  MIT
@@ -3261,7 +3261,7 @@ function walkNode(node, subflowPath, sink, visited) {
3261
3261
  walkNode(node.subflowStructure, nestedPath, sink, visited);
3262
3262
  }
3263
3263
  const type = node.type ?? "stage";
3264
- const isDecider = type === "decider" || type === "selector";
3264
+ const isDecider = type === "decider" || type === "selector" || node.hasDecider === true || node.hasSelector === true;
3265
3265
  const isFork = type === "fork";
3266
3266
  const isStreaming = type === "streaming";
3267
3267
  const isSubflow = !!node.isSubflowRoot;
@@ -3395,7 +3395,7 @@ function createTraceStructureRecorder(options = {}) {
3395
3395
  onStageAdded(event) {
3396
3396
  const spec = event.spec;
3397
3397
  const type = event.type;
3398
- const isDecider = type === "decider" || type === "selector";
3398
+ const isDecider = type === "decider" || type === "selector" || spec.hasDecider === true || spec.hasSelector === true;
3399
3399
  const isFork = type === "fork";
3400
3400
  const isStreaming = type === "streaming";
3401
3401
  const isSubflow = !!spec.isSubflowRoot;
@@ -3464,7 +3464,10 @@ function createTraceStructureRecorder(options = {}) {
3464
3464
  const node = nodes[existing];
3465
3465
  const data = {
3466
3466
  ...node.data,
3467
- branchIds: event.branchIds
3467
+ branchIds: event.branchIds,
3468
+ // A sealed branch list IS decider-ness — engines that stamp neither
3469
+ // `type: 'decider'` nor `spec.hasDecider` still get a decision node.
3470
+ isDecider: true
3468
3471
  };
3469
3472
  if (event.defaultBranch !== void 0) data.defaultBranch = event.defaultBranch;
3470
3473
  nodes[existing] = { ...node, data };