Move the lane from active-work.md into its Closed section, retire the
protocol v20 / main-hash references to LANDED form in agent-handoff.md, and
record both review-round lessons (failure-socket containment, upgrade-gated
replica publication) in the ops-lessons ledger.
Integrate folding Stage 2 and its landed-state documentation with the
protocol-v20 GPU initial-target branch. Preserve per-session fold projection
selection in the target bootstrap transaction and retain v19 compatibility
coverage after the later protocol bump.
Shut down bootstrap sockets on every dispatcher-side failure and reject
frontend events whose session state was never installed. This prevents a
lingering failed client from reaching absent render/size state.
Track target-side CRDT upgrades independently from load/create status so a
deduplicated hidden buffer is published to every existing grid replica. Add
real-daemon regressions for both failure containment and replica publication.
Post-merge housekeeping owed from #149, kept as its own docs-only PR per
the #138-#140 / #147 convention. No runtime code.
- active-work.md: base snapshot and the recovery check bump 47581f4 ->
6ed4fe9. The Stage 2 lane is retired and replaced by a folding lane that
records both stages as merged with nothing in flight, and states Stage 3
(GPU) has no branch and no framing yet — carrying its named obligations
(GPU collapse at TUI parity, caret/hit-test fold-awareness, the
BufferSnapshot fold-mirror clear, CRDT-origin unfold, and flipping
FrontendView.fold_projection true for semantic frontends) as that
framing's starting point. "Closed since the last snapshot" gains #149
and #147.
- agent-handoff.md §1: main @ 6ed4fe9, the "Last updated" line and section
date, the Stage 2 bullet flipped from IMPLEMENTED/PR-OPEN to LANDED with
the Stage 3 obligations attached, and the roadmap entry (remaining arcs
now read "6 folding Stage 3").
Both stages' design points are recorded as traps Stage 3 inherits rather
than as history: the merged-hidden-component unit, per-window/per-target
map instances, per-frontend projection, position-not-row normalization,
and the post-intercept edit site.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
PR #149 review round 5 flagged this PR as stale: it still claimed `main`
@ `c49a8c7`, Stage 2 framing "rev 2, under review; no implementation, no
PR", while `main` is `47581f4` and Stage 2 is implemented and open.
- Base snapshot and the recovery check bump `c49a8c7` -> `47581f4`.
- The folding Stage 2 lane becomes IMPLEMENTED / PR #149 OPEN: framing
rev 4 approved, the `VisibleLineMap` spine, the base-moved merge (and
why it was merged rather than rebased), and the five review rounds'
design-changing findings — each of which is a trap Stage 3 inherits.
- `main`'s ledger had gone unrefreshed through four merges, not one, so
"Closed since the last snapshot" now also records web grammars HTML +
CSS (#146) and LaTeX Stage 1 (#144) with its inline-math framing
(#145), including their durable lessons.
- agent-handoff §1: `main` @ `47581f4`, the "Last updated" line, the
Stage 2 substrate bullet, and the roadmap entry.
Rebased onto `47581f4` so it stays one documentation-only commit
directly off canonical main.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
Post-merge housekeeping owed from #142, kept as its own docs PR (no
runtime code).
- agent-handoff.md §1: bump main to c49a8c7, add the folding Stage 1
substrate bullet (store/View, structural source, C-c @ surface,
command-path unfold, FoldState production; no protocol bump), refresh
the "Last updated" line and the roadmap Arc 6 entry, and note Stage 2
is in framing on folding-tui (the visible-line-map reframe).
- active-work.md: retire the Stage 1 folding lane (PR #142 was OPEN),
add a "Closed since the last snapshot" entry for #142, open the
Stage 2 (grid/daemon collapse) framing lane on folding-tui, and
refresh the canonical base snapshot to c49a8c7.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
Keep foreign BufferSnapshot publications out of existing semantic GPU
sessions while retaining grid-replica coherence. Treat dead peer writes as
peer-local failures, restore active-frontend cleanup, deterministic probe
readiness, GPU logging, shared tilde expansion, and accurate docs.
Add focused publication and cleanup coverage and record the two-window
Wayland/Vulkan smoke plus the complete post-review gate results.
`main` moved from c49a8c7 (folding Stage 1, #142) to 47581f4 (web
grammars, #146) while Stage 2 was in framing and implementation. The
text merge is clean, but it is NOT semantically clean: #146 added three
new `Viewport { .. }` literals to `src/highlight.rs`'s unit tests, and
Stage 2 gives `Viewport` a `folds` field. Merged alone, `cargo test
--lib` fails to compile — so the carry-over is resolved here rather
than left for CI to discover.
Merged (not rebased) so the four framing revisions the review rounds
cite by SHA (59410c0, e221f13, 8160d66, 4222ffa) stay reachable.
Full gate suite re-run on the merged tree.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
Update the framing, durable handoff, and active-work ledger after integrating
current canonical main and completing the required gates and real GPU smoke.
Add protocol-v20 semantic bootstrap and readiness result framing so
`pmacs --gpu FILE` opens the requested path before the GPU window becomes
ready. Keep target identity scoped to the authenticated frontend, preserve
legacy/no-target attach behavior, and publish fresh buffers coherently to
existing replicas.
Carry Unix path bytes and launcher cwd through the root broker, resolve paths
lexically in the daemon, reuse or create buffers without ambient-view state,
and preserve the managed daemon lifecycle from #141. Add focused parser,
wire, lifecycle, hook, isolation, and real-connector acceptance coverage.
Route command-time visible-line maps through each operation's target
window, while retaining the acting frontend as the projection-policy
owner. Model nested and crossing folds as merged hidden components so
row and byte clamps always resolve to one actually visible head.
Also key projection on the negotiated render selection and correct the
unmerged status of the separate Stage 1 housekeeping PR.
Round 2's three findings + two nits, all verified against c49a8c7:
- F1 (major): fold-aware motion must be frontend-projection scoped. Shared
EditorCore::move_up/down/page_* would make a simultaneous unfolded GPU
session skip source lines it still displays (a grid + a semantic session
can attach to one buffer, daemon.rs:876). Add a per-FrontendView
`fold_projection_active` flag (editor_core.rs:240, set at attach / cleared
at detach); gate ALL command-time visible-line reckoning (motion, paging,
wheel, click, auto-scroll) on it. Render-time clamps are already
grid-path-only. New Q#FD21 + simultaneous TUI+semantic acceptance.
- F2 (major): render maps must be per WINDOW, not per frame — paint_frame
and the presence pass iterate windows with distinct buffer_ids
(editor.rs:2922, overlay_paint.rs:124). Specify one map per rendered
nonterminal window (keyed on window buffer_id + TextView); peer presence
uses the recipient window's map. New split-of-different-buffers acceptance.
- F3 (moderate): hidden positions need COLUMN projection, not only row
clamping. Add `visible_position_of(pos)` -> outermost fold's range.start
(end of visible head line, Stage 1's point-move target) for local/peer
carets and selection endpoints; hidden interiors still drop. New
hidden-cursor-column-differs acceptance.
- Nits: fix the Viewport<'a> typo; state build cost honestly as O(folds)
with a byte->line lookup per fold (B4).
PR #147 (the #142 housekeeping) confirmed clean by the reviewer, no findings.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
Review found that adding ("attribute", fg(3)) for HTML/CSS also colours the
@attribute capture three already-bundled grammars emit — rust (attribute_item),
lua (<const>), yaml (directives) — which were previously unpainted. Verified on
a Rust buffer: #[derive(Debug)] now paints uniformly yellow (fg 3), an
improvement over unpainted and the distinct-attribute convention most editors
follow.
Name this retro-paint as intended in the framing (Q#WEB4, rev 4) and pin it with
rust_attribute_repaints_via_shared_attribute_capture so it is a chosen effect,
not incidental. @tag is unaffected (HTML/CSS only).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Round 1's five findings + two rulings, all verified against c49a8c7:
- F1 (major): nested folds. `head_of`(innermost) could clamp onto a
still-hidden inner head. Replace with `visible_head_of` (outermost
visible head); `view_top` clamps BACKWARD to the head, not forward
past the fold; relative numbers anchor on the clamped visible cursor.
- F2 (major): the consumer census was incomplete. Add the full §2.2
table — local selection (editor.rs:3241), peer presence
(overlay_paint.rs:159, after paint_frame), mode-line indicator
(editor.rs:3803), style/search/completion overlays — and make TUI
peer-presence fold behavior explicit scope.
- F3 (major): line numbers default Off => gutter_w==0 => no sign cell.
Make the fold glyph conditional: off => ellipsis only; on => sign
cell with diagnostic priority. Dedicated column (unconditional) named
as a deferred layout change.
- F4 (major): a frame-pinned map can't serve command-time motion, and
Viewport is Copy. Reframe as one derivation primitive with per-phase
short-lived instances (render via Option<&VisibleLineMap> on a
lifetime-bearing Viewport, preserving Copy; after-frame direct;
command-time fresh); home usable from EditorCore.
- F5 (moderate): key the Lua-path widening on InteractiveCommandOrigin
(editor.rs:53), hook the common run_buffer_edit (not only
run_managed_edit) so bypass_intercept edits don't escape, require the
target to be the invoking frontend's active-window buffer, and
explicitly DEFER undo/redo unfold.
Rulings: Q#FD17 include (normalize a hidden cursor to the visible head
before stepping); #142 housekeeping stays a separate docs PR.
Acceptance expanded to pin nested-fold/shared-cursor, local selection,
peer presence, an ordinary overlay across a fold, completion anchoring,
the scroll indicator, and both gutter-off/gutter-on fold-marker cases.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
Reframe Arc 6 folding Stage 2 in detail off canonical main @ c49a8c7
(Stage 1 / #142 merged), per the parent framing's §8/§14. Continues the
Q#FD scheme from Q#FD12.
Stage 2 makes the daemon grid renderer fold-aware: collapse hidden lines,
head-line ellipsis + gutter fold glyph, fold-aware line numbers
(visible-line relative distance), diagnostic-sign clamp-to-head, caret
clamp, visible-line viewport/scroll accounting, and the interactive-Lua
unfold widening (yank/query-replace/comment). No wire schema or protocol
change — FoldState production (Stage 1) is untouched; the GPU path is
Stage 3.
Scout findings that shaped the framing:
- The TUI has NO non-identity source-line->display-row map today; the
identity `view_top + row` is baked into ~7 sites. Folding is the first
such map, so Stage 2's spine is one shared per-frame visible-line map
(Q#FD12) that the render loop and every view_top-arithmetic site
consult; collapse lives in TextView::render, not the diff shell.
- Correcting the parent's premise: yank + query-replace are
apply_active_edit callers (local), not Lua-mutator callers; only
comment-toggle/yank-pop take the Lua path (shared with the
remote/optimistic-CRDT apply that stays deferred to Stage 3). The
widening hooks the local funnels only (Q#FD19).
One open scope fork flagged for the user: Q#FD17 (fold-aware vertical
line-motion vs render-time caret clamp only).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
Advance the active lane to Revision 2 and record closure of all four
non-structural framing findings. Keep implementation gated on explicit user
approval.
Pin launcher-owned tilde expansion, require same-buffer dedup hooks, fail
closed when hooks kill the target, and document stderr feedback during the
pre-window bootstrap wait. Record the observed protocol-version echo and
non-Unicode argv panic.
Add tree-sitter HTML and CSS grammars for .html/.htm/.xhtml and .css
highlighting, and light up HTML's <script>->javascript / <style>->css
injections (the north-star injection consumer). Both crates export their query
constants over the tree-sitter-language shim (no overlay, ABI-fine). The only
reconciliation is two new capture entries (tag, attribute) in highlight.rs.
Framing approved through three review rounds.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Advance the volatile ledger to the current canonical base and record the
portable Revision 1 framing checkpoint, scope, recovery command, and approval
boundary.
Round 2 correctly found the Finding-2/3 fixes were unpinned (reverting
them left the suite green). Both are now bite-verified:
- **Kill-path purge (Finding 2).** Replaced the direct
`forget_buffer(id)` unit test with
`killing_a_buffer_through_the_real_path_purges_its_fold_store`, which
drives `pmacs.buffer.remove` — the production route through
`after_buffer_removed` — and asserts the store is gone via the dead id
(BufferIds never recycle). Mirrors config_registry's real-kill-path
test. Bite-verified: reverting the `after_buffer_removed` fold branch
turns it red.
- **close-all point move (Finding 3).** Added
`close_all_command_moves_point_to_enclosing_head`, which invokes the
`fold.close-all` command with the point inside the second of two
top-level fns and asserts the cursor landed on that fn's head-line
content end (and both folds exist). Bite-verified: reverting close_all's
`maybe_move_point` loop turns it red.
- Ledger: `docs/active-work.md` folding lane now records PR #142 OPEN +
the two landed review rounds (was "opens once the gate suite is green").
Correction to the round-1 gate report: the acceptance suite is **21**
tests (round 1 was 20, not 24 — a tally slip), green under default and
`--features crdt`. Full gate suite otherwise green (fmt, clippy
--workspace --all-targets, git diff --check).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
The parent-arc framing was authored on the desktop but never tracked, so
references to it — from the merged latex-grammar lane framing and its Cargo.toml
comment (#144) — dangled on a fresh clone. Commit it as its own docs change and
drop the now-stale "untracked, desktop-only" caveat from the lane framing.
Frames the full four-tier inline-math renderer (detection -> parse -> layout ->
GPU render). Stage 1 (LaTeX grammar) shipped as #144; the math parser (Tier 2),
layout (Tier 3), GPU render (Tier 4), and (math_environment) @math injection are
deferred, tracked in docs/latex-grammar-math-substrate-framing.md.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Advance the durable snapshot to merge 63fbc66, record the green CI rerun, and
remove the completed GPU invocation lane from the volatile active-work ledger.
The Cargo.toml comment and the lane framing both cited docs/inline-math-framing.md,
which is an untracked, desktop-only doc — the path dangles on a fresh clone.
Point the Cargo.toml comment at the committed lane framing instead, and note the
parent's untracked status in the framing header (committing it as its own docs
PR, or listing it in the handoff's machine-local inventory, remains a tracked
follow-up).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Advance the framing to Revision 6 and record the strengthened non-CRDT,
Ctrl-C, strict-operand, probe-throttling, and PID-cleanup contracts. Update the
durable and volatile checkpoints to implementation commit 154cb9f.
Advance the active and durable checkpoints to 69825d0 and clarify that every
spawned managed daemon enters the named reaper before connection or handshake
work can fail.
Advance the framing to Revision 5 and record the reviewed lifecycle, CLI, and
acceptance contracts. Update the durable and volatile handoffs with checkpoint
82355ca and the completed verification matrix.
Carve the frontend-agnostic, conflict-free substrate out of the parent
inline-math arc: Stage 1 bundles a LaTeX/TeX grammar for .tex/.latex/.sty/.cls
highlighting; the math parser (Tier 2) and GPU render (Tier 4) are deferred to
the inline-math arc. Framing approved through three review rounds; provenance
diff of the chosen grammar crate against upstream latex-lsp is discharged
(grammar.js/scanner.c byte-identical).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Update the durable handoff and volatile active-work ledger for open PR #141, including the implementation checkpoint, accepted architecture, verification record, visible Wayland/Vulkan smoke, and cross-machine recovery commands.
Add the root --gpu broker, strict GPU entry points, daemon connect-or-start orchestration, process-group isolation, bounded retry, named child reaping, and a deterministic headless lifecycle probe. Cover the complete launch matrix with real subprocess acceptance, make root Cargo runs unambiguous, and document the coherent build and one-command workflow.
Q#FD4 settled: the user chose Emacs hideshow parity, so Stage 1 ships the
`C-c @` prefix set (`C-c <letter>` is fully taken by the LSP surface; the
hs-minor-mode prefix collides with nothing). §6/§9 now list the five
bindings; §0 records the rev 4 -> rev 5 approval note; §14 records the
rebase onto canonical `main` @ 96d0bae at implementation start. Bet B1
accepted as framed. active-work.md folding lane flipped to APPROVED /
Stage 1 implementing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
One major, three minors, and a nit from the third review, all fixed:
R3-1 (major, derived head line): rev 3's head-selection ascend was not a
no-op for brace languages — rustfmt wraps long signatures
(fn foo( / a: u32, / ) -> bool {) and puts { on its own line under where
clauses, so block.start_line > parent.start_line, the ascend fired, and
the fold hid the wrapped signature: the R2-5 defect class one level up.
Replaced by a derived head line — the interior comes from the body node
alone (closer-aware tail unchanged) and the head is the line immediately
above the first hidden line (B.start_line - 1 for an introduced
delimiter-less body, B.start_line otherwise). Emacs hideshow / LSP
foldingRange parity: the fold hides the body, nothing else. The
introducer<->body association survives for matching and close-all only.
Acceptance 1 gains wrapped-signature cases in both grammar shapes.
R3-2: "innermost-first" on a shared head line made the outer fold
unreachable via fold.toggle (close inner, reopen inner, forever) and
allowed zero-visible-change presses. Replaced by state-aware ordering:
close acts on the innermost open fold, open on the outermost closed
fold, toggle cycles org-TAB-style (close inward-out, then open all).
Acceptance 9 updated.
R3-3: Stage 1's "command path" is dispatch_key self-insert/delete only;
interactive Lua commands (yank, query-replace, comment-toggle) mutate
through the Lua mutator path and classify programmatic, so their edits
land inside a fold without unfolding. Stated as the intended Stage 1
line; widening the classifier to interactive Lua command contexts is a
named Stage 2 obligation beside Stage 3's CRDT-origin unfold.
R3-4: the data API's normalization of an arbitrary range is now defined
(head = line containing start; hidden = full lines strictly after it
through the line containing end, exclusive of an end at a line start).
Nit: stored-range containment pinned start-exclusive/end-inclusive with
the matching View boundary bias, so typing at the end of a head line
neither unfolds nor lands hidden; acceptance 6 asserts it.
Also: Sec 14 records that canonical main has advanced past the cac4961
base (docs + tab-width #137, no Stage 1 overlap; rebase at
implementation start), and the active-work folding lane is brought
current (head was stale at rev 1).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Five majors + four minors from the second review, all fixed:
R2-1 (head line on indentation grammars): tree-sitter-python's block
starts on the first statement line, so the old heuristic made a body line
the fold head and left def foo(): headless. Added a head-selection ascend
rule (block-like node -> ascend to the introducer parent while
parent.start_line < block.start_line), a no-op for brace languages.
Acceptance 1 now tests both Rust and Python.
R2-2 (Q#FD5 cannot live in the View): View::on_edit(&Buffer,&Edit) and
Edit carry no source frontend and no point-inside signal (only crdt_op),
verified at overlay.rs:248 / rope.rs. The store View now does translate +
drop only; the interactive unfold is a pre-edit step at the dispatch layer
that holds the authenticated frontend and its point.
R2-3 (CRDT typing misclassified): the classifier is the authenticated
source frontend's point, not the transport — a GPU user's CRDT-op insert
inside a fold is interactive. Stage 1 implements the command path;
CRDT-origin unfold is a named Stage 3 obligation.
R2-4 (#120 stale-mirror trap): revert drops the store + emits
BufferSnapshot + resets the baseline, so the empty store is suppressed as
'initial empty' and the GPU keeps stale folds unless its snapshot arm
clears the fold mirror. Pinned as a Stage 3 obligation and in acceptance 7.
R2-5 (line-aligned tail hid non-member text): } else { / }, [deps]) —
now the closing-delimiter line stays visible (closer-aware tail);
delimiter-less nodes still hide through the last body line. Decided, not
bet.
Minors: unfold is plural (nested); shared head lines toggle
innermost-first; Q#FD9's reason corrected to the >=1-hidden-line rule (not
bounds); and the Stage 2/3 sketch now names fold-aware LineNumbers,
visible-line viewport/scroll accounting, and hidden-line sign/presence
clamp-or-drop.
Seven findings from the first review, all fixed:
F1 (architectural): the grid TUI is daemon-rendered and never receives
FoldState (advertises semantic_render:false), so its fold collapse is
instance-side work in the daemon grid renderer reading the store directly
— the vterm Stage 2 shape. FoldState on the wire serves only semantic
(GPU) sessions. Staging reworked: Stage 2 = grid/daemon rendering, Stage
3 = wire-fed GPU.
F2: stored range pinned to the line-aligned hidden interior (head line
visible, closing-delimiter line hidden); one normalized form everywhere,
resolving the R1 5/7 contradiction.
F3: the store's edit-translation is the instance-side buffer-attached View
(BufferStyleSpanTranslator pattern, overlay.rs:235), which sees every real
edit — not the frontend-side translate_byte_range. Split the two resets:
per-session producer baseline vs per-buffer store lifecycle on content
replacement.
F4: stale-tree fold creation refuses with a message when
ParseViewHandle::current() is None or pending_edit_count() > 0.
F5: multi-frontend point + edit-vs-fold pinned — invoking point moves to
the head; interactive-point-inside edits unfold, programmatic/remote edits
translate; the no-cursor-inside invariant is creation-time-only in Stage 1.
F6: Lua data API takes an explicit buffer (no ambient resolution, per
#127) with full range validation, which is also what makes terminals
never fold.
F7: FoldState follows the authoritative-empty discipline; open-all emits
exactly one empty frame; the flipped pin test keeps asserting
BlockAdornments is never emitted.
Minors: source lines not display rows; close-all folds top-level only
(hs-hide-all parity); an injected-layer (markdown fence) acceptance added;
and an explicit note that FoldState needs no protocol bump.
The ledger inherited from #135's merge still listed Vterm Stage 3 as an
open 'never merge without authorization' implementation lane; it is merged
(main @ cac4961), so per the update protocol it moves to Closed and Arc 5's
terminal stage is marked complete. Adds the folding framing lane (branch
folding, off cac4961, framing-only) and points the canonical base at
cac4961 / protocol v19.
Draft framing for the folding arc, committed to the `folding` branch for
review before any implementation. Branch is cut from canonical main @
cac4961 (post Vterm Stage 3 #135).
The load-bearing finding: the bundled tree-sitter grammars ship no fold
query and no folds.scm — they export HIGHLIGHTS/INJECTIONS/LOCALS/TAGS
only. The roadmap's "tree-sitter fold ranges" premise is therefore not
free, so the fold source is a real decision (Q#FD1). The draft recommends
structural node folding (fold the nearest enclosing block-like node
spanning >= 2 rows), which reuses the existing parse trees for every
grammar and injection layer with zero per-language authoring; indentation
folding (grammarless fallback) and curated per-language queries (quality
pass) are deferred.
FoldState already exists in the protocol, declared but unproduced, with a
test pinning that it is never emitted; no frontend consumes it; gutter
markers are frontend-derived like the diagnostic sign bars, so no new wire
type is needed. Staged like vterm: Stage 1 engine (instance-side fold
model + structural source + Lua commands + FoldState production, headless),
Stage 2 TUI collapse+gutter, Stage 3 GPU at parity.
Numbered decisions Q#FD1-9, three falsifiable bets, named deferrals, and a
Stage 1 acceptance list. Awaiting review rounds; bindings (Q#FD4) and the
block-kind heuristic (Bet B1) are the two calls flagged for the user.
Record the approved managed-launch contract, daemon lifecycle and process-group rules, strict GPU CLI behavior, headless acceptance seam, and the complete acceptance matrix before implementation.