Skip to content

feat(truapi-debugger): wire trace, decode, and render engine - #536

Draft
decrypto21 wants to merge 2 commits into
nidish/debug-host-portfrom
nidish/debugger-2-engine
Draft

feat(truapi-debugger): wire trace, decode, and render engine#536
decrypto21 wants to merge 2 commits into
nidish/debug-host-portfrom
nidish/debugger-2-engine

Conversation

@decrypto21

Copy link
Copy Markdown
Contributor

Stacked on #295. Design doc: #315.

The debugger package's engine: raw frames in, per-operation traces out. No I/O and no mount — it renders HTML and ships the stylesheets, but nothing attaches it to a DOM or a socket. Both mounts (the standalone inspector, the in-app panel) are PRs above this one and both drive this single engine, so no surface can show a grouping, badge or latency the other would not.

What

  • Ingest (ingest.ts) — one envelope to one ObservedFrame. Resolves the lifecycle role as a pure function of the frame id against the wire table, at ingest, so it is true for every consumer rather than for one view adapter. Length-clamps retained ids.
  • Correlation (wire-debugger.ts) — traces keyed on (channelId, requestId), never requestId alone: each host mints its own p:1, so two hosts would collide. Generation rotation for recycled ids. Bounded on three axes (traces, frames per trace, bytes per trace), and every bound surfaces rather than misreports.
  • Decode (decode.ts) — gated on the frame's own producer having attested a matching wire schema, and on the channel's standing verdict. Both gates apply; neither replaces the other.
  • View + render (trace-view.ts, trace-render.ts) — one projection and one renderer, shared by both mounts.
  • Cross-op signals (retry-storm.ts) — a burst of like operations is invisible to a single-trace view, so the engine groups by (channelId, opener frameId).

Two invariants worth reviewing closely

  • The opener is located by role, not position. frames[0] is only the opener if the opener was the first frame observed, and every tap attaches mid-session — so the first frame seen for an id is often a closer for an operation that predates the tap. Retention spares the opener by role; keying on index 0 evicts the frame pairing and storm detection depend on.
  • Pairing verdicts are not conflated. "An opener with no close" is a claim about the host. "A close with no opener" is usually a claim about the debugger — the op began before the tap attached, or retention dropped the opener. They get different badges, because sharing one made the tool report its own retention as a protocol defect.

Verification

tsc -b clean, typecheck:tests clean (this PR adds that script and its CI step — tsconfig.json excludes test files and bun test does not typecheck, so nothing checked them), 115 tests.

@socket-security

socket-security Bot commented Aug 28, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​happy-dom@​20.11.2661008896100

View full report

@decrypto21
decrypto21 force-pushed the nidish/debugger-2-engine branch from eebee61 to e8d9625 Compare August 28, 2026 06:53
@decrypto21
decrypto21 force-pushed the nidish/debug-host-port branch 3 times, most recently from 715bfec to af7b25a Compare August 31, 2026 10:25
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.

1 participant