Skip to content

fix: architecture review quick wins (settle-once, hub, config lookup, turn-idle grace) - #66

Merged
william0wang merged 3 commits into
mainfrom
fix/arch-review-quick-wins
Aug 20, 2026
Merged

fix: architecture review quick wins (settle-once, hub, config lookup, turn-idle grace)#66
william0wang merged 3 commits into
mainfrom
fix/arch-review-quick-wins

Conversation

@william0wang

Copy link
Copy Markdown
Owner

Quick-fix batch from the full-codebase architecture review (plus one pending CORS fix). The bigger candidates (SessionRegistry, turn-loop decomposition) are left for separate design passes.

MED+ — interaction settle-once (server-requests.ts, session.ts)

The interaction forward path (pending.set → popup → reply) had no try/finally: any throw left the zcode request unanswered forever, leaked the reannounce-dedup entry (its 30s cleanup only arms inside sendInteractionReply), and every ~1s reannounce refreshed the turn loop's no-progress timer — the 120s timeout never fired and the turn could hang indefinitely. Now the forward degrades to a decline reply (zcode always gets exactly one answer, the entry always resolves), and the turn loop wraps handleServerRequests in best-effort containment instead of dying on a throw. Tests: tests/settle-once.test.ts.

Hub fixes (hub-server.ts)

  • Expose X-Zcode-First-Line via Access-Control-Expose-Headers — without it the web file viewer cannot read the line-window header cross-origin at all.
  • Guard the WS upgrade dial window: a client socket that dies while the hub dials the bridge no longer reaches handleUpgrade against a dead socket.

Config option lookup by id (dispatch.ts)

dispatchConfigChanged wrote options[0]/[1]/[2] relying on buildConfigOptions' push order as a hidden contract; a reorder would silently write the wrong option. Now finds by id (matching emitModeViaConfigOption's existing pattern).

Turn-idle lock grace (extensions.ts)

waitForTurnIdle(expectLock=true) could spin the full 300s and report a false __lockTimeout when the lock was never observed — a turn finishing between probes, or backend error-message drift away from "prompt is running". A 30s grace (injectable) bounds the lock-watching phase; past it, a successful probe counts as released. Tests: tests/wait-turn-idle.test.ts.

Minor

  • pendingTurns keyed number | string (JSON-RPC ids); prompt/preempt signatures widened.
  • Corrected two stopSent comments in session.ts that claimed cross-turn dedup (backend stop is idempotent; each turn guards its own).

Verification

typecheck / lint / full suite: 44 files, 665 tests pass (+2 files, +7 tests).

@william0wang
william0wang merged commit 6a3e81f into main Aug 20, 2026
@william0wang
william0wang deleted the fix/arch-review-quick-wins branch August 20, 2026 13:56
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