fix: address the Copilot review of the Ace editor

- `isProgressToken` used `Number.isInteger`, but zod 4's `.int()` rejects
  anything past `MAX_SAFE_INTEGER` — verified against the pinned zod — so an
  unsafe integer passed the guard and was left for the server to reject. Now
  `isSafeInteger`, with the boundary covered in both directions.

- `echoed` held only what this component last emitted, so it went stale the
  moment an external value was applied: A → B → A stranded the editor on B,
  because the second A matched the entry left from before B arrived and was
  dismissed as our own echo. It now advances to whatever is on screen.

- `Input.Wrapper` associates a *Mantine* input through context, and Ace is not
  one — it renders its own DOM. The wrapper's label and error node therefore
  pointed at nothing: the editor was never marked `aria-invalid`, never
  described by the error text, and its visible label did not focus it. Wired
  explicitly through the wrapper's id in an effect.

- Removed two leftover `[dbg]` logs an earlier regex cleanup missed.

- Documented the editor integration and the shared `cssVariablesResolver` in
  the web README, per the rule about new dependencies and patterns. Both
  footguns are recorded: the `?url` worker import, and the gutter override
  keying off Ace's cssClass rather than the theme module name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177mPHAdECD18nLLCTwR5rh
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-23 17:36:43 -04:00
commit 7f10fa971c

View file

@ -1419,6 +1419,10 @@ describe("InspectorClient", () => {
["an array", [1]],
["null", null],
["a boolean", true],
// Past `Number.MAX_SAFE_INTEGER` the float64 value is no longer the
// integer it was written as, and zod 4's `.int()` rejects it — so
// `Number.isInteger` is too loose a check here.
["an unsafe integer", Number.MAX_SAFE_INTEGER + 1],
])(
"drops a reserved progressToken that is %s rather than sending it",
async (_label, badToken) => {
@ -1511,6 +1515,8 @@ describe("InspectorClient", () => {
it.each([
["a string", "tok-1"],
["an integer", 7],
// The boundary itself is still valid.
["the largest safe integer", Number.MAX_SAFE_INTEGER],
])("keeps a valid progressToken that is %s", async (_label, token) => {
client = new InspectorClient(
{