Skip to content

feat(menu): Phase E - wire menu content via windowTypes manifest (legacy parity)#688

Merged
jsavin merged 2 commits into
developfrom
worktree-menu-port-phase-e-content
Jun 1, 2026
Merged

feat(menu): Phase E - wire menu content via windowTypes manifest (legacy parity)#688
jsavin merged 2 commits into
developfrom
worktree-menu-port-phase-e-content

Conversation

@jsavin

@jsavin jsavin commented Jun 1, 2026

Copy link
Copy Markdown
Owner

Summary

Final phase of the menu-port plan. Achieves functional parity with the legacy Frontier GUI menu system in the headless REPL.

Predecessors merged: #678 (Phase A multi-bar enumeration), #680 (Phase B1 getsystemtablescript), #683 (Phase C bridge), #687 (Phase D primitives). This PR ships the actual menu content that makes the REPL look + behave like legacy.

What ships

  • New frontier menubar installed at REPL boot with File / Edit / View menus
  • File: New, Open, Close, Save, Save As, Quit
  • Edit: Find, Find Next, Replace, Replace and Find Next, Insert Date/Time
  • View: Huge, Medium, Tiny, Readable
  • Two new UserTalk adapter scripts under system.menus.handlers.repl that bridge the Phase C kernel-fired system.callbacks.openWindow("path") to the windowTypes framework's address-expecting openWindow(adr) handler
  • installReplMenubar.ut extended to register the adapters in user.callbacks.openWindow/closeWindow (the missing wire from Phase C)
  • File > Quit and REPL > Exit are dispatch-target-identical (both call repl.exit); resolves task docs: capture headless daemon vision #21

Palette strip at boot: Edit File View REPL (alphabetical union of two installed bars per Phase A enumeration contract).

Test plan

  • Unit: 492/492 pass
  • Integration: 6 new behavioral tests in replwindow_openwindow_menus_phase_e.yaml all pass
  • Phase D regression suite (9 tests) continues to pass
  • Startup tests verified pass in isolation (the runner's sequential: true state pollution can show transient failures in a fully-parallel suite run; reproduced clean on develop's baseline)
  • Live-tested by JES before commit per task feat: hydrate headless system root and modernize db format #15 standing gate
  • Virgin.root: regenerated, compacted to 10.5 MB (net +9.5 KB for 3 new scripts + 1 modified)

Design decisions

  • Bar named frontier — sorts before repl so File/Edit/View leads the strip per legacy convention
  • File>Quit -> repl.exit (not commands.quit which walks GUI windows that don't exist in headless)
  • Edit Cut/Copy/Paste deferred — no terminal analog in classic Frontier; needs linenoise.* bridge
  • Adapter scripts, not inline lambdas — UserTalk does not support taking the address of a script inside a bundle block; named-script-and-reference is the canonical pattern
  • Adapter strips @ prefix from kernel-supplied pathWINDOW_BRIDGE_REPL_PATH carries @ but address() rejects strings with a leading @

Issues filed during development (deferred)

🤖 Generated with Claude Code

jsavin and others added 2 commits May 31, 2026 19:25
…acy parity)

Final phase of the menu-port plan. Achieves functional parity with the
legacy Frontier GUI menu system in the headless REPL.

What ships:
- New "frontier" menubar with File / Edit / View menus, installed at
  REPL boot via the Phase C bridge -> windowTypes framework -> new
  ReplWindow.openWindow handler
- File menu: New, Open, Close, Save, Save As, Quit
- Edit menu: Find, Find Next, Replace, Replace and Find Next,
  Insert Date/Time
- View menu: Huge, Medium, Tiny, Readable
- Adapters under system.menus.handlers.repl that bridge the kernel-fired
  system.callbacks.openWindow("<path>") to the windowTypes framework
  (strips @ prefix that address() rejects)
- File>Quit and REPL>Exit dispatch-target-identical (both call
  repl.exit) - resolves task #21

Palette strip at boot: "Edit  File  View  REPL" (alphabetical union of
the two installed bars, matching Phase A's enumeration contract).

Design decisions:
- Bar named "frontier" sorts before "repl" so File/Edit/View lead the
  strip per legacy convention
- File>Quit wired directly to repl.exit (not commands.quit which walks
  GUI windows that don't exist in headless)
- Edit Cut/Copy/Paste deferred - no terminal analog in classic Frontier
- Adapter scripts (not inline lambdas) because UserTalk does not support
  taking the address of a script inside a bundle block
- Adapter strips leading @ from WINDOW_BRIDGE_REPL_PATH because address()
  rejects strings with a leading @

Tests:
- 6 new behavioral integration tests in replwindow_openwindow_menus_phase_e.yaml
- All 9 Phase D regression tests continue to pass
- Unit: 492/492; Integration: +6 new tests, all green; pre-existing
  html/tcp baseline unchanged

Virgin.root: regenerated + compacted (10.5 MB, +9.5 KB net for 3 new
scripts + 1 modified). Live-tested by JES before commit per task #15.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Three items from /gate round-1:

bar-raiser P1-1: Tighten File>Quit script-payload assertion (test #6)
  Was `contains "repl.exit"` -- matches repl.exitNow, repl.exit2, etc.
  Now `contains "repl.exit ("` to lock down the exact dispatch contract.

bar-raiser P1-2: Adapter parameter mutation -> local copy
  windowTypesOpenAdapter and windowTypesCloseAdapter were mutating the
  formal parameter `name` in place. UserTalk parameter-passing semantics
  for shared buffers are not formally guaranteed; defensive idiom is to
  copy to a local. Matches the convention used elsewhere in
  Frontier.tools.windowTypes.*

security P1: closeWindow adapter discards framework veto
  Was unconditional `return (true)`. Framework's closeWindow returns
  false when a save-confirmation dialog is cancelled -- the kernel-level
  close chain interprets that as "abort the close". Phase E (REPL only)
  has no save dialog so it's moot today, but Phase F editor windows
  with unsaved-change prompts would silently close + lose user edits
  with the old code. One-line correctness fix:
    return (Frontier.tools.windowTypes.callbacks.closeWindow (adr))

Virgin.root regenerated to pick up the new adapter bodies, then
re-compacted: 10.5 MB -> 13.4 MB (install churn) -> 11.0 MB (compact).

Tests: 492/492 unit, 15/15 Phase D+E. P2 items deferred to issue #686
(Phase F hardening).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@jsavin

jsavin commented Jun 1, 2026

Copy link
Copy Markdown
Owner Author

/gate — PR #688 (Phase E — final)

Round 1

  • bar-raiser: PASS WITH NOTES — 2 P1, 4 P2, 6 praise
  • security: PASS WITH NOTES — 1 P1, 3 P2, 5 positive
  • concurrency: skipped (no frontier-cli/** path, no concurrency patterns)

Round 2 (after fix commit 2c44794ca)

ID Item Status
bar-raiser P1-1 Tighten test #6 repl.exit assertion FIXED (contains "repl.exit (")
bar-raiser P1-2 Adapter mutates parameter in place FIXED (local copy in both adapters)
security P1 closeWindow adapter discards framework veto (Phase F data-loss risk) FIXED (return Frontier.tools.windowTypes.callbacks.closeWindow(adr))

P2s deferred to issue #686 (Phase F hardening)

  • View menu items have no failure path on click (silent thread.callScript drops)
  • File>Quit silently skips guest-DB save flow (Phase F+ guest DBs)
  • Trust contract for adapter input (Phase F editor windows)
  • Slot name windowTypesAdapter collision risk
  • Doc drift in MENU_PORT_PLAN.md line-count claims (cosmetic)

Tests

  • Unit: 492/492 (cached at 2c44794)
  • Phase E behavioral: 6/6
  • Phase D regression: 9/9
  • Integration full suite: pre-existing html/tcp/startup-pollution baseline maintained

Virgin.root

  • Pre-fix: 10.5 MB
  • After adapter reinstall: 13.4 MB (install churn)
  • After re-compact: 11.0 MB

Convergence: PASS — ready to merge

🤖 Generated with Claude Code

@jsavin jsavin merged commit beb1666 into develop Jun 1, 2026
@jsavin jsavin deleted the worktree-menu-port-phase-e-content branch June 1, 2026 02:39
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