Status: complete
Started: 2026-08-28
Owner: repository maintainers and Codex implementation session
This document is the authoritative implementation and completion plan for the v2 architecture. A phase is complete only when its code, tests, documentation, and acceptance evidence are all present in the current worktree. A passing subset of tests is not sufficient to mark the overall plan complete.
- Make
NodeNativeAdaptera first-class backend from the first implementation phase. - Replace mocked "CDP correctness" tests with real protocol end-to-end tests.
- Separate network capture, CDP target creation, and frontend launching.
- Stop coupling the debug server lifecycle to a Chrome process.
- Preserve a Legacy backend for capabilities missing from Node's native network inspector.
- Improve zero-code setup, diagnostics, configuration, watch-mode behavior, and package-consumer verification.
- Add session recording, HAR export, replay, Legacy-only mocking, and trace correlation after the runtime and connection layers are stable.
- Security hardening as a dedicated workstream.
- Incoming HTTP/server request inspection.
- A custom DevTools frontend.
- Bun or Deno support.
- Native/Legacy hybrid capture for a single session.
- Pretending that Node Native capabilities exist when the selected Node release does not provide them.
NodeNativeAdapter and LegacyAdapter are mutually exclusive complete
backends. Native uses Node's own capture, CDP implementation, and Inspector
target. Legacy uses the existing monkey-patch capture and a project-owned CDP
bridge. They must never emit the same request in one session.
register / preload / CLI
|
v
RuntimeController
|- ConfigResolver
|- AdapterSelector
`- RegistrationHandle
|
+-----+-----------+
| |
v v
NodeNativeAdapter LegacyAdapter
| |
Node Inspector Legacy capture + bridge
| |
+--------+--------+
v
DevtoolsTarget
| |
v v
optional frontend optional ProtocolTap/session pipeline
The backend owns a debuggable target, not a browser. Core runtime code must not
start a Chrome remote-debugging server, send Page.navigate, retain a browser
process handle, or kill a browser during disposal.
Selection is based on an explicit, versioned capability matrix verified by E2E tests. Forced Native fails if requirements are not met. Only Auto may fall back to Legacy, and it must expose a structured fallback reason.
const registration = register({
mode: 'auto',
requiredCapabilities: ['responseBody'],
inspector: { host: '127.0.0.1', port: 0 },
devtools: { open: false }
})
const ready = await registration.ready
console.log(ready.mode, ready.target, ready.capabilities)
await registration.openDevtools()
await registration.dispose()During the compatibility period the returned handle remains callable, so the
existing const unregister = register(); unregister() form still works.
Mode semantics:
native: require the experimental flag and required runtime capabilities; never silently fall back.legacy: always use project-owned capture and CDP bridge.auto: prefer a proven Native baseline, otherwise use Legacy with a visible fallback diagnostic.
- Define runtime, adapter, target, session, diagnostic, and capability types.
- Implement
AdapterSelector. - Implement
NodeNativeAdapterusingnode:inspector. - Reuse an existing Inspector endpoint without taking ownership of it.
- Open an Inspector on an OS-assigned port when the adapter owns the target.
- Read the canonical target descriptor from Node's
/json/listendpoint. - Return a backward-compatible observable registration handle.
- Ensure Native never patches
fetch,http.request, orhttps.request. - Ensure Native never forks or starts the Legacy 5270/5271 services.
- Add real Native protocol E2E tests against the built package.
- Add a CI quality workflow that runs the first Native E2E gate.
-
Network.enablereturns a response with the same command id. - A real HTTP request emits a valid lifecycle.
- A real Fetch request emits a valid lifecycle.
- A failed request emits
Network.loadingFailedonly. -
Network.getResponseBodyreturns the actual fixture body where supported. -
Runtime.evaluate('process.pid')proves the client is attached to the target process. - Initiator data points to a real fixture source location where supported.
- Explicit Native without the required flag fails with an actionable error.
- Auto fallback returns a structured reason.
- Disposal closes only an Inspector created by the adapter.
- Add the
nndCLI. - Add a side-effect preload export.
- Add
nnd dev,nnd doctor, andnnd doctor --json. - Launch Native targets with the experimental network-inspection flag.
- Support wait-for-first-frontend and no-wait startup modes.
- Add explicit frontend launching through a separate
FrontendLauncher. - Remove the Chrome port 9333 polling and
Page.navigateimplementation. - Stop retaining or killing a Chrome process.
- Add hosted official DevTools frontend smoke tests.
- Add CJS, ESM, tsx, Nest compiled, and Node watch fixtures.
-
nnd dev app.jsstarts a Native-capable target with no source edit. -
nnd dev --open app.jsexplicitly opens the returned target URL. - Library usage does not open a browser by default.
- Ready output contains mode, target, capabilities, and fallback reason.
- Diagnostics use stable codes and provide actionable hints.
- Repeated registration is idempotent for equal configuration and rejects conflicting configuration.
- Move current capture behavior behind
LegacyAdapter. - Complete Auto/Native/Legacy selection and old-option migration.
- Mark current request hooks as Legacy-only.
- Add real Legacy protocol E2E with no mocked server or manufactured CDP events.
- Respond to all command ids with a result or a standard CDP error.
- Implement correct
Network.loadingFailedbehavior. - Preserve HTTP, Fetch, binary, SSE, WebSocket, and initiator behavior.
- HTTP GET and Fetch POST.
- Text, gzip, and binary response bodies.
- Redirect, abort, reset, and timeout behavior.
- SSE event name, id, data, and ordering.
- WebSocket handshake, text frame, binary frame, and close.
- Concurrent requests use stable, distinct request ids.
- CJS and ESM package consumers.
- Replace the application-to-fork 5270 WebSocket with child-process IPC.
- Remove the lock-file and WebSocket health-ping mechanisms.
- Use a single HTTP server for Legacy target discovery and CDP WebSocket upgrade.
- Implement
/json/list,/json/version, and/json/protocol. - Default to port
0; never probe a free port before binding. - Support multiple clients and DevTools refresh/reconnect.
- Ensure abnormal bridge exits produce bounded recovery and visible status.
- Ensure disposal leaves no port, timer, child, or pending promise behind.
- Maintain a capability matrix backed by tests rather than runtime skipping.
- Add Node 18/20/22/24/26 runtime coverage as appropriate per adapter.
- Run mandatory Ubuntu protocol E2E on pull requests.
- Run Windows and macOS adapter smoke tests.
- Run a complete OS/runtime matrix nightly.
- Build and
npm packonce, then test the published artifact as CJS and ESM consumers. - Make npm publishing depend on the same reusable quality workflow.
- Document Native/Legacy differences and migration from old options.
- Add a common protocol event journal/tap for both backends.
- Store sessions as
manifest.json,events.ndjson, and external body files. - Export valid HAR with matching text and binary bodies.
- Replay requests from a session or HAR, including dry-run mode.
- Implement request/response mocking for Legacy only.
- Reject Native plus Mock as an explicit capability conflict.
- Correlate existing
traceparentvalues without injecting tracing by default. - Add real-network E2E for Session, HAR, Replay, Mock, and Trace.
Protocol E2E uses a thin raw WebSocket CDP client for both backends. It must spawn a real packaged consumer, connect to the real endpoint, trigger a real loopback request, and assert observed protocol invariants. It must not import a backend plugin directly.
The fixture controller communicates with target applications over process IPC so test-control traffic does not pollute Network events. Each scenario uses a unique URL/query token and waits on explicit events instead of fixed sleeps.
Frontend smoke tests use the official DevTools frontend bundled with the exact
Playwright Chromium revision pinned in the lockfile. Chromium's loopback
remote-debugging HTTP server serves those generated assets locally. The tests
verify frontend connection, Network model population, response body retrieval,
reconnect, console errors, page errors, and the absence of non-loopback
frontend traffic. The source-only chrome-devtools-frontend npm tarball is not
treated as a runnable frontend build.
Required failure artifacts:
- Complete CDP inbound/outbound NDJSON journal.
- Target stdout and stderr.
- Session descriptor and capability selection.
- Playwright trace, screenshot, console, and page errors for frontend tests.
Pull-request minimum:
| Job | Runtime and platform |
|---|---|
| Unit | Node 20/22/24/26 on Ubuntu |
| Legacy runtime | Node 18/20/22/24/26 on Ubuntu |
| Native runtime | supported Node 22/24/26 releases on Ubuntu |
| Adapter OS smoke | Node 24 on Windows and macOS |
| Frontend smoke | Node 24 on Ubuntu, Native and Legacy |
| Pack consumer | CJS and ESM from the generated tarball |
The runtime E2E controller should use node:test so evidence for Node 18 does not
depend on the Vitest controller's own minimum runtime.
packages/network-debugger/
src/
runtime/
adapters/
node-native/
legacy/
target/
diagnostics/
config/
session/
preload/
cli/
legacy-bridge/
test/e2e/
fixtures/
harness/
contracts/
protocol/
frontend/
Before declaring the overall plan complete, inspect current evidence for every checkbox above and additionally prove:
- Native requests appear exactly once and never pass through Legacy code.
- Native does not change the references of supported network APIs.
- Legacy retains every previously documented capability.
- Both backends connect through actual standard targets.
- The project no longer owns a Chrome process.
- Protocol E2E contains no
vi.mock, fake WebSocket server, or hand-writtenNetwork.*event used as product evidence. - Both protocol suites pass 50 consecutive runs without a failure or leaked process.
- Windows and macOS smoke suites pass 20 consecutive runs.
- Frontend smoke passes 10 consecutive runs.
- Pull requests and publishing are blocked by the verified quality workflow.
- Documentation describes actual current capabilities, not intended ones.
- Every planned artifact exists in the packed npm output when required.
- 2026-08-28: Plan established from repository inspection, Node official network-inspection capabilities, and a successful local Node 24.16 Native CDP probe. Phase 1 started.
- 2026-08-28: Phase 1 requirement audit passed. Evidence: 886 unit tests; clean
Vite build plus declaration emit; four real built-package Native CDP E2E
scenarios; ten consecutive E2E repetitions; owned/reused Inspector lifecycle
tests; public forced-Native and Auto-fallback tests; and a pull-request quality
workflow running unit, build, and Native E2E. Node 24.16 emits Native
wallTimein epoch milliseconds, so the Native-only E2E records and validates that upstream deviation without transforming the direct Inspector protocol. - 2026-08-28: Phase 2 requirement audit passed. Evidence: 910 unit tests; clean
declaration and dual-runtime builds including ESM-only preload; four real
Native protocol scenarios; eight built-package CLI E2E scenarios covering
doctor, real
--open/Inspector-wait resume, Auto-to-Legacy fallback, CJS, ESM, tsx, watch, compiled Nest-style startup, signals, and orphan cleanup; and an official pinned Chromium DevTools frontend smoke that populated its real Network model, retrieved two response bodies across a reload/reconnect, rejected non-loopback frontend traffic, and passed ten consecutive runs. The CI quality job installs that pinned browser and runs all Phase 1/2 gates. - 2026-08-28: Phase 3 requirement audit passed. Legacy capture is isolated behind its adapter and uses a real built-package CDP target. Evidence: eight protocol scenarios pass for both CJS and ESM consumers and ten consecutive repetitions completed 80/80; coverage includes HTTP, Fetch POST (including multi-chunk request bodies), text/gzip/binary bodies, redirect/reset/timeout/abort, SSE, WebSocket text/binary/close, 20 concurrent command ids, response-body retrieval, standard CDP errors, and initiators. The official frontend also passed ten consecutive Legacy runs and a combined Native/Legacy reconnect run.
- 2026-08-28: Phase 4 requirement audit passed. The Legacy application bridge now uses advanced-serialization child IPC and a single loopback HTTP/WebSocket target on an OS-assigned port; the old 5270 transport, lock file, and health endpoint are gone. Fifty-five target/discovery tests and 25 IPC lifecycle tests cover bounded queues/history, multi-client isolation, stable target recovery, child flag sanitization, and terminal diagnostics. A CLI shutdown race found by full E2E was fixed by making the dedicated bridge close and exit on parent IPC disconnect; the focused regression and the complete 8/8 CLI suite leave no matching child.
- 2026-08-28: Phase 6 requirement audit passed. A backend-neutral real CDP
ProtocolTaprecords atomic manifests, NDJSON events, integrity-indexed external bodies, and existing trace context; HAR 1.2 export preserves text/binary bodies, while library andnnd replayAPIs support Session/HAR dry-run and real replay. Legacy-only HTTP/Fetch/Undici mocks traverse normal capture, Auto exposes a structured reason, and forced Native fails withNND_NATIVE_MOCK_CONFLICT. Twenty-two Session unit/integration tests and the full unit suite passed. The built-package enhancement E2E passed 2/2 and then 20/20 across ten repetitions, covering six real business requests/bodies, HAR, Replay, HTTP+Fetch Mock, traceparent/tracestate, and zero origin leakage. That gate exposed and verified the fix for an internal ProtocolTap self-observation recursion: the final manifest contains exactly six requests, six bodies, zero failures, and no child process leak. - 2026-08-28: Phase 5 requirement audit passed. The reusable quality workflow
builds and packs exactly once, then gates isolated CJS/ESM consumers, Ubuntu
Native/Legacy/CLI/enhancement protocol suites, the official frontend, Node
20/22/24/26 unit lanes, Legacy Node 18/20/22/24/26, Native Node 22/24/26, and
Windows/macOS Node 24 20-round adapter smoke. Nightly adds Legacy on both OSes
for all five runtimes and Native for 22/24/26. Local exact-tarball evidence was
green across those available runtimes and macOS smoke; Node 22's incomplete
Native Fetch body caused the public cross-transport
responseBodycapability to be conservatively disabled there. Publishing consumes the same SHA-256 verified artifact through the reusable gate with OIDC/provenance and checks its release tag. That phase-5 candidatenode-network-devtools-2.0.0.tgzinstalled in CJS and ESM consumers, exposed all five exports/two bins, contained 187 files, and passednpm publish --dry-runwithout performing a real publish. - 2026-08-28: Final local audit passed on the post-review tree. Three independent
reviews found and drove fixes for the Node
--importminimum (>=18.18), side-effect preload declarations, stale published-site instructions, missing packed LICENSE, finite Legacy/-e/-pprocess lifetime, and negotiatedpermessage-deflatecapture. The final local gate passed 60 files/833 unit tests, declaration plus CJS/ESM builds with no TypeScript diagnostic, all Native/Legacy/enhancement/CLI/official-frontend E2E, and the nine-page VuePress build. Native and Legacy protocol suites each passed 50 consecutive final-tree runs; frontend, enhancement, and CLI suites each passed 10 consecutive runs; the watcher-specific regression passed 50; macOS packed Native and Legacy adapters each passed 20 rounds; and no matching process remained. The current exactnode-network-devtools-2.0.0.tgzinstalls in CJS and ESM consumers, passes packed Native/Legacy runtime tests plus publish dry-run, contains 190 files including LICENSE, and has SHA-256dbd24df4d1ff4dda6ac545df0ef95c1287f0cace81d1e26fca08caa5667fce84. - 2026-08-28: Final remote audit passed at commit
231bcae02a9f05763a24c01d064127a71301895a. GitHub Actions run 33147572570 completed all 18 reusable-workflow jobs plus the top-levelQuality Gatesuccessfully. The exact uploaded artifactnode-network-devtools-tgz-33147572570-1contains 190 files and has the same SHA-256 recorded above. Its isolated packed-package controller passed 20 Native and 20 Legacy rounds on bothwindows-latestandmacos-latest, with discovery, target, disposal, and closed-endpoint assertions preserved. Active repository ruleset 21711512 targetsrefs/heads/main, strictly requiresQuality Gatefrom GitHub Actions integration15368, and has no bypass actors (current_user_can_bypassisnever). The release workflow cannot reachpublishuntil the same reusable quality workflow succeeds; it then downloads that workflow's sole artifact and verifies its SHA-256 and release tag before publishing. No real npm publish was performed as part of this implementation. - 2026-08-28: PR #64 manual acceptance audit passed 14/14 cases against exact
packed product commit
449d47db89109e826eb0e7e0584777365eac3f9band tarball SHA-256e97dc360d2fcd5d141b13bca490f603b802dc7fe94f3b6a06a690c7a7f48e2ac. Computer Use and Playwright exercised six public CLI cases, Native and Legacy runtime selection, full standard discovery, official Chromium DevTools request details, reload/reconnect, HTTPS, failed requests, Legacy mocks, SSE, WebSocket lifecycle/frames, Session/HAR/Replay/Trace, capability boundaries, and closed-endpoint disposal. The audit discovered that a non-empty HTTP/2 response crashes Node 24.16 and 26.8 insidenode:internal/inspector/network_http2; commit449d47dtherefore replaced the open-ended Native capability claim with the verified Node 22.20+ 22.x range. The exact-package probe proves a complete lifecycle and body on Node 22.22.3 while the affected/future majors correctly withhold the capability. The reviewable matrix, 26 privacy-reviewed screenshots, 17 structured artifacts, five reproduction harnesses, test TLS inputs, and SHA-256 manifest are retained in the PR #64 manual evidence report.