Skip to content

feat(local-edge): let the host own the debug-seed URL rewrite - #25

Merged
zgq354-code merged 4 commits into
mainfrom
feat/local-edge-debug-url-writer
Sep 27, 2026
Merged

zgq354-code merged 4 commits into
mainfrom
feat/local-edge-debug-url-writer

Conversation

@zgq354-code

@zgq354-code zgq354-code commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Outcome

Applications whose navigation runtime is the only history writer can now own the URL rewrite that Local Edge diagnostics perform. The first consumer is ds-playground, where the FWA navigation backend replaces history.pushState / replaceState and admits only its own writes.

Problem

When diagnostics change through debug.setEnabled or the panel, the loader removes __fwa_debug with a direct history.replaceState. In ds-playground that write is rejected silently by the navigation backend's write admission, and the loader's try/catch then swallows the error. The seed therefore stays in the URL: ?__fwa_debug=0 remains after turning Developer mode on, and a reload turns diagnostics back off.

Changes

  • debug.setUrlWriter(writer | null) on the public FwaDebugApi, plus the queued command ['debug.setUrlWriter', writer | null] for hosts that register before the loader runs. The loader applies queued writers before debug startup. Only null clears a writer; other non-function values are ignored.
  • When a writer is registered, the loader passes it the cleaned pathname + search + hash and does not write history itself. null restores the direct write.
  • The writer is synchronous by contract. If it throws or returns a rejected promise, the diagnostics state and stored preference still update.
  • Unchanged: __fwa_debug=1 and 0 are never rewritten at startup; see the demo case "shows opt-in diagnostics without changing app routing". __fwa_debug=reset is still consumed at startup, through a queued writer if one exists. Consumers that register no writer behave exactly as before.
  • Queued-command dispatch moves verbatim into command-dispatch.ts, which is added to the published file list, so it can be tested.
  • docs/loader-contract.md gains a "URL ownership" section, an API table row, and the full debug.* command list.

Verification

  • pnpm run ci passes at ccf3652: 211 package tests, 39 demo e2e, and the document-shell packed consumer smoke test. The packed-consumer check caught a missing files entry during review, and it was fixed in cd4ee4d.

  • debug-runtime.test.ts and command-dispatch.test.ts cover:

    • the default direct write, the host writer, and a throwing writer;
    • an async writer that rejects (removing the absorption surfaces an unhandled rejection);
    • no seed present, and clearing the writer;
    • invalid inputs;
    • the reset-seed startup path and seeds 1/0 left in place;
    • queued registration, including writers applied before startup.

    Removing the writer branch fails the host-writer test.

  • Read-only review in a local session (gpt-5.6-terra / high), three rounds:

    • round 1 HOLD: the reset-seed startup rewrite contradicted the new doc, plus two P2s;
    • rounds 2 and 3 GO, including the GitHub Codex P2 about queued writers at startup, fixed in ccf3652 and resolved.

Limits

  • The end-to-end fix in ds-playground (local-edge.spec.ts:673) needs a published 0.1.0-beta.8 and a consumer-side writer. That follow-up lives in ds-playground and is not verified here.
  • The diagnostics panel overflowing short viewports is a separate, untouched issue.

Release: after merge, prepare local-edge@0.1.0-beta.8 through the Prepare release workflow (owner approved republishing).

When diagnostics change, the loader removes `__fwa_debug` from the current
URL with a direct `history.replaceState`. An application whose navigation
runtime is the only history writer rejects that write silently, so the
seed stays in the URL and a reload flips diagnostics back.

- Add `debug.setUrlWriter(writer | null)` and the matching queued command.
  With a writer registered, the loader hands it the cleaned
  path + search + hash instead of writing history; `null` restores the
  direct write, so existing consumers are unchanged.
- The loader still never rewrites the URL at startup.
- Document the URL ownership rule in the loader contract and cover the
  writer, the default path, a throwing writer and clearing it in tests.
@zgq354-code
zgq354-code requested a review from a team as a code owner September 27, 2026 07:09
@zgq354

zgq354 commented Sep 27, 2026

Copy link
Copy Markdown
Contributor

@codex review this

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-27T07:17:38.353720Z 1379874 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 137987470d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- Document the startup exception: `__fwa_debug=reset` is consumed during
  startup with a direct write, before any writer can be registered; 1 and 0
  stay in the URL until diagnostics change.
- Only `null` clears the writer; other non-function values are ignored,
  matching the queued command.
- The writer is synchronous by contract; a returned rejected promise is
  absorbed instead of surfacing as an unhandled rejection.
- Move queued-command dispatch into command-dispatch.ts (no behavior change)
  so it can be tested, and cover queued registration, invalid inputs, the
  reset-seed startup path and the async writer.
The loader sources are published as an explicit file list; the new module
was missing, so a packed consumer failed to resolve it.
A host that queues debug.setUrlWriter before the loader runs expects the
startup __fwa_debug=reset removal to go through it too. The loader now
applies queued writers before debug.start(); the commands stay queued and
replaying them is idempotent.

@zgq354 zgq354 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved by the owner at exact head ccf3652: local Terra / high review GO (three rounds), GitHub Codex P2 fixed and resolved, pnpm run ci green.

@zgq354-code
zgq354-code merged commit 9ae9329 into main Sep 27, 2026
2 checks passed
@zgq354-code
zgq354-code deleted the feat/local-edge-debug-url-writer branch September 27, 2026 08:22
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