docs: capture headless daemon vision#21
Merged
Merged
Conversation
jsavin
added a commit
that referenced
this pull request
Jan 11, 2026
… cursor invariants This commit addresses outline operation test failures by properly documenting and implementing the empty summit behavior, fixing op.firstSummit(), and correcting test expectations to match UserTalk conventions and headless mode. ## Changes ### Documentation - **docs/OUTLINE_STRUCTURE.md**: Added critical section documenting cursor and collapsed nodes invariant - the cursor can NEVER be on a child of a collapsed node. When expansion state is restored, cursor auto-moves to first visible ancestor if needed. - **planning/phase3/OUTLINE_EMPTY_SUMMIT_FIX.md**: Documented the empty summit issue and historical context (file was created in previous work but uncommitted). ### Implementation Fixes - **tests/headless_op_verbs.c**: Fixed op.firstSummit() to explicitly move to hsummit using opmoveto() instead of opmotionkey(flatup, infinity), and always return true (opmoveto returns false when already at target, causing test failures). ### Test Fixes - **tests/integration/test_cases/op_verbs.yaml**: - Fixed test #11 (cursor independence): Rewrote to properly test that expansion state captures entire outline, accounting for cursor auto-move when parent is collapsed - Fixed type safety tests based on UserTalk conventions: - Test #19 (setCursor): Expects false when invalid cursor passed - Test #20 (setDisplay): UserTalk type coercion (1 → true) is correct behavior - Test #21 (setExpansionState): Expects json_parse_error for non-list - Test #22 (setScrollState): Noop in headless, returns true - Test #23 (setRefcon): Split into 4 tests proving round-trip for boolean, string, long, and double (refcons can store any type) ## Context Following Phase 4 state management implementation, tests revealed misunderstandings about: 1. Empty summit behavior (all outlines start with 1 empty headline) 2. Cursor visibility invariant (cursor must always be on accessible/visible node) 3. UserTalk type coercion vs strict type checking expectations This commit documents these behaviors and aligns tests with reality. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
jsavin
added a commit
that referenced
this pull request
Jan 11, 2026
When passing a non-list type to op.setExpansionState(), it attempts type coercion and fails with a script error: 'Can't coerce the string "foo" into a number because it contains non-numeric characters.' Verified in Windows Frontier by user testing. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
jsavin
added a commit
that referenced
this pull request
Jan 11, 2026
… cursor invariants This commit addresses outline operation test failures by properly documenting and implementing the empty summit behavior, fixing op.firstSummit(), and correcting test expectations to match UserTalk conventions and headless mode. - **docs/OUTLINE_STRUCTURE.md**: Added critical section documenting cursor and collapsed nodes invariant - the cursor can NEVER be on a child of a collapsed node. When expansion state is restored, cursor auto-moves to first visible ancestor if needed. - **planning/phase3/OUTLINE_EMPTY_SUMMIT_FIX.md**: Documented the empty summit issue and historical context (file was created in previous work but uncommitted). - **tests/headless_op_verbs.c**: Fixed op.firstSummit() to explicitly move to hsummit using opmoveto() instead of opmotionkey(flatup, infinity), and always return true (opmoveto returns false when already at target, causing test failures). - **tests/integration/test_cases/op_verbs.yaml**: - Fixed test #11 (cursor independence): Rewrote to properly test that expansion state captures entire outline, accounting for cursor auto-move when parent is collapsed - Fixed type safety tests based on UserTalk conventions: - Test #19 (setCursor): Expects false when invalid cursor passed - Test #20 (setDisplay): UserTalk type coercion (1 → true) is correct behavior - Test #21 (setExpansionState): Expects json_parse_error for non-list - Test #22 (setScrollState): Noop in headless, returns true - Test #23 (setRefcon): Split into 4 tests proving round-trip for boolean, string, long, and double (refcons can store any type) Following Phase 4 state management implementation, tests revealed misunderstandings about: 1. Empty summit behavior (all outlines start with 1 empty headline) 2. Cursor visibility invariant (cursor must always be on accessible/visible node) 3. UserTalk type coercion vs strict type checking expectations This commit documents these behaviors and aligns tests with reality. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
jsavin
added a commit
that referenced
this pull request
Jan 11, 2026
When passing a non-list type to op.setExpansionState(), it attempts type coercion and fails with a script error: 'Can't coerce the string "foo" into a number because it contains non-numeric characters.' Verified in Windows Frontier by user testing. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
jsavin
added a commit
that referenced
this pull request
Jan 11, 2026
* fix: Phase 4 state management verbs - expansion state, refcon, and documentation Fixed P0 expansion state save/restore issues and improved state management verbs: - Fixed op.setExpansionState to restore state after collapse (tests 3, 7, 17) - Root cause: Checked (**nomad).flexpanded flag which gets cleared by opcollapse() - Solution: Only check !opsubheadsexpanded() to allow re-expansion - Tests now passing: Basic restore, workflow restore, deep nesting stress test - Fixed op.promote/demote to use oppromote()/opdemote() instead of opreorgcursor() - Properly handles multiple nodes and preserves refcon data (test 14) - Fixed op.setCursor to use opmoveto() for proper state updates (test 15) - Made scroll state operations noops in headless mode (tests 5, 13) - Created docs/OUTLINE_STRUCTURE.md documenting critical architectural fact: All new outlines start with 1 empty summit headline - Updated CLAUDE.md with outline structure quick reference - Documented memory logging false alarms (format detection, not corruption) - Created planning/phase3/phase4_test_failures.md analyzing all test failures - Updated scroll state test expectations for headless mode behavior - Fixed workflow test ordering issues Test results: 537/600 passing (89.5%), P0 expansion state issues resolved Related: Issues #272, #273 filed for future expansion state design improvements Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix: Align outline operation tests with empty summit behavior and fix cursor invariants This commit addresses outline operation test failures by properly documenting and implementing the empty summit behavior, fixing op.firstSummit(), and correcting test expectations to match UserTalk conventions and headless mode. - **docs/OUTLINE_STRUCTURE.md**: Added critical section documenting cursor and collapsed nodes invariant - the cursor can NEVER be on a child of a collapsed node. When expansion state is restored, cursor auto-moves to first visible ancestor if needed. - **planning/phase3/OUTLINE_EMPTY_SUMMIT_FIX.md**: Documented the empty summit issue and historical context (file was created in previous work but uncommitted). - **tests/headless_op_verbs.c**: Fixed op.firstSummit() to explicitly move to hsummit using opmoveto() instead of opmotionkey(flatup, infinity), and always return true (opmoveto returns false when already at target, causing test failures). - **tests/integration/test_cases/op_verbs.yaml**: - Fixed test #11 (cursor independence): Rewrote to properly test that expansion state captures entire outline, accounting for cursor auto-move when parent is collapsed - Fixed type safety tests based on UserTalk conventions: - Test #19 (setCursor): Expects false when invalid cursor passed - Test #20 (setDisplay): UserTalk type coercion (1 → true) is correct behavior - Test #21 (setExpansionState): Expects json_parse_error for non-list - Test #22 (setScrollState): Noop in headless, returns true - Test #23 (setRefcon): Split into 4 tests proving round-trip for boolean, string, long, and double (refcons can store any type) Following Phase 4 state management implementation, tests revealed misunderstandings about: 1. Empty summit behavior (all outlines start with 1 empty headline) 2. Cursor visibility invariant (cursor must always be on accessible/visible node) 3. UserTalk type coercion vs strict type checking expectations This commit documents these behaviors and aligns tests with reality. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix: Correct test #21 expectation - script_error not json_parse_error When passing a non-list type to op.setExpansionState(), it attempts type coercion and fails with a script error: 'Can't coerce the string "foo" into a number because it contains non-numeric characters.' Verified in Windows Frontier by user testing. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix: Address Codex feedback issues #1, #3, #4 Issue #1 (Safety): Add pointer validation in op.setCursor() - Validate nodeid is non-zero before casting to pointer - Prevents potential null pointer dereference Issue #2 (Default refcon): Already correctly returns 0 - op.getRefcon() returns 0 when hrefcon is nil (verified) - No changes needed Issue #3 (Documentation): Clarify Parent is sibling of empty summit - Added explanatory comments in OUTLINE_STRUCTURE.md - Explains op.insert("Parent", down) creates sibling, not child - Both empty summit and Parent are at summit level Issue #4 (Loop safety): Add explicit summit check - Added summit termination check in expansion state restoration - Checks both self-reference and hsummit comparison - Prevents potential infinite loop Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
jsavin
added a commit
that referenced
this pull request
May 31, 2026
Investigation produced from reading /Users/jake/dev/tedchoward/Frontier/
Common/source/ (~9k lines across menu*.c, meprograms.c, langipcmenus.c,
tablestructure.{c,h}, cancoon.c). Triggered by JES guidance: editor
windows are coming, and the legacy menu system's windowTypes framework
(JES-authored UserTalk on top of kernel hooks) is the substrate they'll
plug into. We need to understand it before planning Phase 6 in detail.
Part 1 covers the C kernel side end-to-end:
- 3-layer architecture (kernel, UserTalk verb surface, UserTalk windowTypes framework)
- Data structures (menubarlist, menubarstack, menurecord)
- Database storage at system.menus.sharedmenus.<appid>
- Dispatch path from OS menu hit to script execution (memenu -> memenuhit -> meuserselected)
- Per-database menubar swap via setcancoonglobals
- Kernel->UserTalk callback registry (40+ idXxxScript hooks)
- The 13 menu.* UserTalk verbs
- Worked example: File > New Script click traced through to async script dispatch
Part 2 maps the legacy model to the headless port:
- What survives intact (data model, verb surface, dispatch mechanism)
- What needs adaptation (per-database scope, OS menu manager handoff)
- New substrate needed for editor windows (window-type registry, frontmost
tracking, callback bridge for window events, multi-menubar enumeration)
- Proposed port sequencing in 5 steps
- Disposition of task #21 (File > Exit vs REPL > Exit) — answers itself once
windowTypes drives composition (they appear at different times)
Gaps:
- The actual UserTalk windowTypes framework implementation lives in a
Frontier.root not present in either tedchoward or jsavin/Frontier;
framework contract here is inferred from kernel evidence + JES guidance
- idmenubarscript declared in tablestructure.h but unreferenced in source
(vestigial or called from Mac-specific code outside Common/source)
- Async (legacy) vs sync (headless) script dispatch semantics differ
Becomes the foundation for issue #677 (multi-menubar enumeration), the
detailed Phase 6 plan (task #20, blocked on this), and editor-window
work whenever that arrives.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
jsavin
added a commit
that referenced
this pull request
Jun 1, 2026
…acy parity) (#688) * feat(menu): Phase E - wire menu content via windowTypes manifest (legacy 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> * fix(menu): address PR #688 round-1 review feedback 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> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.