Skip to content

feat: runtime execution trace bitmask tracking with manifest view#119

Merged
aarne merged 11 commits intotraversal_id_doingfrom
copilot/add-traversal-id-tracking
Mar 9, 2026
Merged

feat: runtime execution trace bitmask tracking with manifest view#119
aarne merged 11 commits intotraversal_id_doingfrom
copilot/add-traversal-id-tracking

Conversation

Copy link
Contributor

Copilot AI commented Mar 9, 2026

Track which traversal paths a request takes through a bridge at runtime, encoding decisions as a compact bitmask. Adds static manifest building, runtime collection, decode API, and playground visualization.

Core API

  • buildTraversalManifest(bridge) — returns TraversalEntry[] with bitIndex and description on each entry
  • decodeExecutionTrace(manifest, trace) — decodes bitmask back to active entries
  • executionTrace added to ExecuteBridgeResult — always populated by executeBridge()
const { data, executionTrace } = await executeBridge({
  document, operation: "Query.getWeather", input: { cityName: "Berlin" },
  tools: { std }
});
// executionTrace = 31n (0x1f)

const manifest = buildTraversalManifest(bridge);
const activePaths = decodeExecutionTrace(manifest, executionTrace);
// [{ target: ["lat"], kind: "primary", bitIndex: 1, description: "api.lat" }, ...]

TraversalEntry descriptions

Each TraversalEntry includes a human-readable description field showing the source reference, value, or control keyword:

  • primary: api.username, departure.delay
  • fallback: || "Anonymous", ?? api.username, || journey.category
  • catch: catch "UNKNOWN", catch continue 3
  • const: = "SBB"
  • ternary: ? api.yes, : api.no
  • empty-array: c[] empty, s[] empty

Handle alias resolution covers tool, input, context, pipe, and alias (__local) refs.

Runtime collection

  • traceBits / traceMask on TreeContextMap<Wire, TraceWireBits> + boxed [bigint]
  • Uses bigint for unlimited scaling — no bit-count limit per bridge
  • Bit flips injected at decision points in resolveWires: primary, fallback, catch, then/else
  • Overhead when enabled: one Map.get + one bitwise OR per wire decision
  • Shared across shadow trees via reference

Playground

  • Execution trace hex badge in result panel
  • Manifest tab in Bridge DSL panel with:
    • Entries grouped by wire target — each group shows target path as header with source descriptions below
    • Alias wires properly labeled by alias name (not *)
    • Each array scope gets its own group with iterator label (e.g., c[] empty, s[] empty)
    • "Show alternatives only" toggle (always visible) to hide always-on paths and focus on decision points
    • Scrollable view for complex bridges
    • Active paths highlighted after execution

Alias example — proper labels with source descriptions:

SBB Train Search — separate empty-array groups, source descriptions:

SBB filtered to alternatives only (4/23 groups):

String Transform — trace badge:

Limitations

  • AOT compiler path returns executionTrace: 0n (not instrumented)

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@changeset-bot
Copy link

changeset-bot bot commented Mar 9, 2026

🦋 Changeset detected

Latest commit: 0ad7859

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@stackables/bridge Patch
@stackables/bridge-core Patch
@stackables/bridge-compiler Patch
@stackables/bridge-graphql Patch
@stackables/bridge-parser Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

- Add bitIndex to TraversalEntry for bitmask encoding
- Add buildTraversalManifest (alias for enumerateTraversalIds)
- Add decodeExecutionTrace to decode bitmask back to entries
- Add buildTraceBitsMap for runtime wire→bit lookup
- Add traceBits/traceMask to TreeContext interface
- Inject trace recording in resolveWires (primary/fallback/catch/then/else)
- Add executionTrace to ExecuteBridgeResult
- Propagate trace mask through shadow trees
- All existing tests pass (133 execute-bridge + 64 resilience + 14 traversal)

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 9, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
bridge 0ad7859 Commit Preview URL

Branch Preview URL
Mar 09 2026, 11:35 AM

Copilot AI and others added 3 commits March 9, 2026 07:55
- Test buildTraversalManifest alias and bitIndex assignment
- Test decodeExecutionTrace with empty/single/multiple/round-trip
- Test end-to-end trace collection: primary, fallback, catch, then/else, const
- All 27 tests pass

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>
- Add executionTrace to RunResult type in engine
- Pipe executionTrace through runBridgeStandalone
- Add getTraversalManifest and decodeExecutionTrace helpers to engine
- Show execution trace badge (hex) in ResultView
- Add Manifest tab to Bridge DSL panel header
- ManifestView shows all traversal entries with kind badges
- Active paths highlighted with ring + dot based on execution trace
- Works across mobile and desktop layouts

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>
- Rename dslTab → activeDslTab for clarity
- Rename fi → fallbackIndex in applyFallbackGates loop
- Add comment explaining bitmask check in decodeExecutionTrace
- Add INVARIANT comment for traceMask/traceBits coupling
- Document bitIndex assignment lifecycle in enumerateTraversalIds

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>
Copilot AI changed the title [WIP] Add tracking for execution path with traversal ID feat: runtime execution trace bitmask tracking with manifest view Mar 9, 2026
Copilot finished work on behalf of aarne March 9, 2026 08:12
@aarne
Copy link
Contributor

aarne commented Mar 9, 2026

@copilot

Good work ... small additions

look at http://localhost:4321/playground#sbb-train-search which is a bit more complicated bridge

  1. the manifest view is not scrollable so the end is cut off

  2. most the the paths are always "on" as they dont have alternatives (const direct wires etc)

  • have the ability to filter off (in ui only) paths that don't have alternatives.

  • group the alternatives into visual groups
    result.legs.origin.delayMinutes <- this is the important part
    primary [fallback1] fallback2. <- this is the options space and what was triggered

  1. i think we only support up to 31 traces?
    ctx.traceMask![0] |= 1 << bits.primary;

use BigInt or a Bit Vector Array to enable scaling

Copilot AI and others added 2 commits March 9, 2026 08:45
- Switch traceMask from number to bigint for unlimited entry support
- Update all recording helpers to use BigInt bitwise ops
- Update decodeExecutionTrace, ExecuteBridgeResult, TreeContext
- Update playground engine, ResultView, Playground types
- ManifestView: group entries by wire, show group headers for alternatives
- ManifestView: add "Show alternatives only" toggle filter
- ManifestView: fix scrolling with h-full / max-h-[60vh]
- Update tests to use bigint assertions
- All 1143 tests pass

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>
Co-authored-by: aarne <82001+aarne@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 9, 2026

@copilot

Good work ... small additions
...

All three items addressed in 6f7c37e:

1. Manifest scrolling — Fixed with h-full (desktop) / max-h-[60vh] (mobile autoHeight). All entries now scrollable.

2. Filter & group alternatives — Entries are grouped by wire target. Groups with alternatives (fallback/catch/ternary) show a bordered container with the target path as header and the options space below. "Show alternatives only" toggle hides always-on single-path groups. For SBB Train Search this reduces from 22 → 5 groups.

Filtered

3. BigInt trace mask — Replaced number with bigint across the entire pipeline: traceMask: [bigint], recording helpers use 1n << BigInt(bits.primary), decodeExecutionTrace accepts bigint, ExecuteBridgeResult.executionTrace is bigint. No bit-count limit — scales to any manifest size.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • workers.cloudflare.com
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/bridge/bridge/packages/playground/node_modules/.bin/../vite/bin/vite.js preview --port 8080 --host 0.0.0.0 tools/pnpm/10.30.3/bin/node credential.helpesh (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/bridge/bridge/packages/playground/node_modules/.bin/../vite/bin/vite.js preview --port 9090 --local credential.username packages/bridge/node_modules/.bin/node (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot finished work on behalf of aarne March 9, 2026 08:48
@aarne
Copy link
Contributor

aarne commented Mar 9, 2026

@copilot

http://localhost:4321/playground#alias

the manifest show duplicate * paths? i think this is related to alias that is not properly labeled

=====

actually for all labels we should be able to show the the ref or const value or even the continue/break/throw/... keyword instead of the plain fallback ... this would make the paths much simpler to read

primary = api.username
fallback = "?? "Anonymous""
catch = "continue 3"

=====

we have 2 ways to show the paths in ui ... always use the same element with ID as group header and variants below variant

always allow to switch on and off the filter for alternatives ... the ui is too smart right now ... lets users switch even if it means the next view will be empty

=====

http://localhost:4321/playground#sbb-train-search

*
empty-array
empty-array

o <- api.connections[] as c {
.legs <- c.sections[] as s {
}
}

grouping them under the same * does not make much sense

…-on toggle

- Add `description` field to TraversalEntry with human-readable source info
  (e.g., "api.username", "|| \"Anonymous\"", "catch continue", "= \"SBB\"")
- Fix alias wires showing as `*` — use `to.field` for `__local` module targets
- Fix empty-array entries grouped under same `*` — assign unique wireIndex per scope
- Handle map resolves tool, input, context, pipe, and alias refs to handle aliases
- Filter toggle always visible regardless of whether alternatives exist
- Consistent group headers shown for all entries (not just alternatives)
- Empty-array entries show iterator variable in description (e.g., "c[] empty")
- All 1143 tests pass

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 9, 2026

@copilot

http://localhost:4321/playground#alias
...

All items addressed in e0cc512:

Alias * labels — Fixed. Alias wires (__local module) now use to.field (the alias name) as target instead of empty to.path. Each alias shows its proper name.

Source descriptions — Added description field to TraversalEntry. Each entry now shows the source ref, value, or control keyword:

  • primary: api.username, departure.delay
  • fallback: || "Anonymous", ?? api.username, || journey.category
  • catch: catch "UNKNOWN", catch continue 3
  • const: = SBB
  • ternary: ? api.yes, : api.no
  • empty-array: c[] empty, s[] empty

Empty-array grouping — Each array scope gets a unique negative wireIndex (-1, -2, ...) so they appear as separate groups instead of all under *.

Filter toggle — Always visible. Shows "No entries match" message if filtered view is empty.

Alias example:
Alias

SBB (alternatives only — 4/23 groups):
SBB

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • workers.cloudflare.com
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/bridge/bridge/packages/playground/node_modules/.bin/../vite/bin/vite.js preview --port 9090 --noprofile (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot finished work on behalf of aarne March 9, 2026 09:28
@aarne aarne marked this pull request as ready for review March 9, 2026 11:34
@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

🐰 Bencher Report

Branchcopilot/add-traversal-id-tracking
Testbedubuntu-latest

⚠️ WARNING: No Threshold found!

Without a Threshold, no Alerts will ever be generated.

Click here to create a new Threshold
For more information, see the Threshold documentation.
To only post results if a Threshold exists, set the --ci-only-thresholds flag.

Click to view all benchmark results
BenchmarkLatencynanoseconds (ns)
compiled: absolute baseline (passthrough, no tools)📈 view plot
⚠️ NO THRESHOLD
0.00 ns
compiled: array + SYNC tool-per-element 10📈 view plot
⚠️ NO THRESHOLD
0.01 ns
compiled: array + SYNC tool-per-element 100📈 view plot
⚠️ NO THRESHOLD
0.02 ns
compiled: array + tool-per-element 10📈 view plot
⚠️ NO THRESHOLD
0.01 ns
compiled: array + tool-per-element 100📈 view plot
⚠️ NO THRESHOLD
0.04 ns
compiled: chained 3-tool fan-out📈 view plot
⚠️ NO THRESHOLD
0.00 ns
compiled: flat array 10 items📈 view plot
⚠️ NO THRESHOLD
0.01 ns
compiled: flat array 100 items📈 view plot
⚠️ NO THRESHOLD
0.02 ns
compiled: flat array 1000 items📈 view plot
⚠️ NO THRESHOLD
0.12 ns
compiled: nested array 10x10📈 view plot
⚠️ NO THRESHOLD
0.03 ns
compiled: nested array 20x10📈 view plot
⚠️ NO THRESHOLD
0.05 ns
compiled: nested array 5x5📈 view plot
⚠️ NO THRESHOLD
0.01 ns
compiled: short-circuit (overdefinition bypass)📈 view plot
⚠️ NO THRESHOLD
0.00 ns
compiled: simple chain (1 tool)📈 view plot
⚠️ NO THRESHOLD
0.00 ns
exec: absolute baseline (passthrough, no tools)📈 view plot
⚠️ NO THRESHOLD
0.00 ns
exec: array + SYNC tool-per-element 10📈 view plot
⚠️ NO THRESHOLD
0.11 ns
exec: array + SYNC tool-per-element 100📈 view plot
⚠️ NO THRESHOLD
0.93 ns
exec: array + tool-per-element 10📈 view plot
⚠️ NO THRESHOLD
0.12 ns
exec: array + tool-per-element 100📈 view plot
⚠️ NO THRESHOLD
1.06 ns
exec: chained 3-tool fan-out📈 view plot
⚠️ NO THRESHOLD
0.05 ns
exec: flat array 10 items📈 view plot
⚠️ NO THRESHOLD
0.02 ns
exec: flat array 100 items📈 view plot
⚠️ NO THRESHOLD
0.10 ns
exec: flat array 1000 items📈 view plot
⚠️ NO THRESHOLD
0.87 ns
exec: nested array 10x10📈 view plot
⚠️ NO THRESHOLD
0.15 ns
exec: nested array 20x10📈 view plot
⚠️ NO THRESHOLD
0.30 ns
exec: nested array 5x5📈 view plot
⚠️ NO THRESHOLD
0.06 ns
exec: short-circuit (overdefinition bypass)📈 view plot
⚠️ NO THRESHOLD
0.01 ns
exec: simple chain (1 tool)📈 view plot
⚠️ NO THRESHOLD
0.01 ns
parse: large bridge (20 handles x 5 wires)📈 view plot
⚠️ NO THRESHOLD
1.34 ns
parse: simple bridge📈 view plot
⚠️ NO THRESHOLD
0.04 ns
🐰 View full continuous benchmarking report in Bencher

@aarne aarne merged commit dc670b2 into traversal_id_doing Mar 9, 2026
4 checks passed
@aarne aarne deleted the copilot/add-traversal-id-tracking branch March 9, 2026 11:36
aarne added a commit that referenced this pull request Mar 9, 2026
* feat(bridge-core): add enumerateTraversalIds for bridge traversal path enumeration (#117)

* Initial plan

* feat(bridge-core): add enumerateTraversalIds function

Enumerates all possible traversal paths through a Bridge.
Each entry represents a unique code path determined by the wire
structure (fallback chains, catch gates, array scopes, ternary
branches). Useful for complexity assessment and future integration
into the execution engine for monitoring.

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aarne <82001+aarne@users.noreply.github.com>

* feat: runtime execution trace bitmask tracking with manifest view (#119)

* Initial plan

* feat: add execution trace bitmask to core engine

- Add bitIndex to TraversalEntry for bitmask encoding
- Add buildTraversalManifest (alias for enumerateTraversalIds)
- Add decodeExecutionTrace to decode bitmask back to entries
- Add buildTraceBitsMap for runtime wire→bit lookup
- Add traceBits/traceMask to TreeContext interface
- Inject trace recording in resolveWires (primary/fallback/catch/then/else)
- Add executionTrace to ExecuteBridgeResult
- Propagate trace mask through shadow trees
- All existing tests pass (133 execute-bridge + 64 resilience + 14 traversal)

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>

* test: add comprehensive tests for execution trace feature

- Test buildTraversalManifest alias and bitIndex assignment
- Test decodeExecutionTrace with empty/single/multiple/round-trip
- Test end-to-end trace collection: primary, fallback, catch, then/else, const
- All 27 tests pass

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>

* feat: add execution trace and manifest view to playground

- Add executionTrace to RunResult type in engine
- Pipe executionTrace through runBridgeStandalone
- Add getTraversalManifest and decodeExecutionTrace helpers to engine
- Show execution trace badge (hex) in ResultView
- Add Manifest tab to Bridge DSL panel header
- ManifestView shows all traversal entries with kind badges
- Active paths highlighted with ring + dot based on execution trace
- Works across mobile and desktop layouts

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>

* refactor: address code review feedback

- Rename dslTab → activeDslTab for clarity
- Rename fi → fallbackIndex in applyFallbackGates loop
- Add comment explaining bitmask check in decodeExecutionTrace
- Add INVARIANT comment for traceMask/traceBits coupling
- Document bitIndex assignment lifecycle in enumerateTraversalIds

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>

* feat: BigInt trace mask, manifest grouping/filtering, scroll fix

- Switch traceMask from number to bigint for unlimited entry support
- Update all recording helpers to use BigInt bitwise ops
- Update decodeExecutionTrace, ExecuteBridgeResult, TreeContext
- Update playground engine, ResultView, Playground types
- ManifestView: group entries by wire, show group headers for alternatives
- ManifestView: add "Show alternatives only" toggle filter
- ManifestView: fix scrolling with h-full / max-h-[60vh]
- Update tests to use bigint assertions
- All 1143 tests pass

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>

* fix: add aria-label to manifest group count for accessibility

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>

* feat: source descriptions, alias labels, empty-array grouping, always-on toggle

- Add `description` field to TraversalEntry with human-readable source info
  (e.g., "api.username", "|| \"Anonymous\"", "catch continue", "= \"SBB\"")
- Fix alias wires showing as `*` — use `to.field` for `__local` module targets
- Fix empty-array entries grouped under same `*` — assign unique wireIndex per scope
- Handle map resolves tool, input, context, pipe, and alias refs to handle aliases
- Filter toggle always visible regardless of whether alternatives exist
- Consistent group headers shown for all entries (not just alternatives)
- Empty-array entries show iterator variable in description (e.g., "c[] empty")
- All 1143 tests pass

Co-authored-by: aarne <82001+aarne@users.noreply.github.com>

* UI tweaks

* LSP for dead code in playground

* Docs

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aarne <82001+aarne@users.noreply.github.com>
Co-authored-by: Aarne Laur <aarne.laur@gmail.com>

* Rename

* feat: add SocialIcons component and update social links in config

---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aarne <82001+aarne@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants