pmacs/builtin/runtime
Levi Neuwirth 723afa717f
fix(git): give diff requests a ticket, and share one channel mechanism
`git.diff-file` started a plan with no request generation while every
plan writes the SINGLETON `*git-diff*` buffer through
`show_diff_buffer`. Press `d` on A, then `d` on B before A finishes: if
A completes last, A's diff replaces B's. The newest invocation loses to
the slowest subprocess --- the same defect the status channel had before
`ffe5ae2`, on the one surface that had never been given the fix.

Every finding on this lane has now been one shape: module-level mutable
state read or written at CONTINUATION time without an invocation-time
ticket. So the rule gets ONE implementation rather than a fourth
hand-rolled counter. `new_channel()` hands out a ticket at the command
and answers "is this still the request in force?" at the completion;
`state.generation` and `reserve_generation` are gone.

TWO channels, and that is a design decision rather than an oversight: a
single module-wide counter would make `d` cancel an in-flight `g` and
vice versa. The status panel and the diff view are independent things a
user asks for, so each gets its own "newest wins" ordering. What is
shared is the MECHANISM, not the counter. A channel spans a whole
request rather than one process --- a status open is `rev-parse` then
`status`, and a diff is one or two `git diff` runs --- so `_deliver_root`
and `_deliver_status` correctly share one ticket while the diff plan
gets its own. `g6_23` asserts the separation directly: two `d` presses
leave `_generation()` untouched.

The plan is restructured into the request shape the other two
continuations already use. `step_done`'s closure becomes
`pmacs.git._deliver_diff(request, step, res)`, exposed for exactly the
reason `_deliver_status` and `_deliver_root` are: no arrangement of real
subprocess timing can make two `git diff` runs finish in a chosen order,
and the contract is about the order the caller did NOT choose. The
ticket check sits at the single point a plan re-enters from a
continuation, so one check covers everything downstream --- no further
spawn, no buffer write, and no status message, since a status line from
a replaced invocation is as wrong as a buffer from one.

Witnessed by `g6_23` in two halves. The real half presses `d` twice with
nothing pumped between, so two plans are genuinely in flight and each
really reserved its own ticket. The driven half then completes the OLDER
request after the newer one has rendered --- the ordering that is the
whole contract, and the one real timing will not produce on demand,
since the first plan spawned normally finishes first and that order
passes on the broken code. A superseded FAILURE is asserted too, since a
buffer-only check would miss the status-message half. The positive
control at the current ticket makes the discards attributable to the
ticket rather than the payload.

Mutation-verified: removing the ticket check fails `g6_23` --- and in
that run it failed at the REAL half, the older plan having overwritten
the newer one's patch before the fabricated delivery was ever reached.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai
2026-08-09 16:48:54 +02:00
..
async.lua feat(journey): open a directory, on one path 2026-07-26 16:39:59 -04:00
autosave.lua feat(config): typed configuration registry with buffer-local scope 2026-07-21 18:29:18 -04:00
comment.lua feat(lean4): editing surface + Stage 1 acceptance (Q#LN5, LN6, LN17) 2026-07-25 09:59:48 -04:00
compile.lua review round 1: the crdt suite Stage 3 missed, and two stale explanations 2026-08-04 12:08:28 +02:00
completion.lua fix(completion): address TUI-validation findings (LSP query gaps, scoping, prefix keys, window scope) 2026-07-07 16:54:14 -04:00
desktop.lua fix(persistence): reliable daemon gate, unarm, per-pane after-load 2026-07-08 22:27:24 -04:00
dired.lua refactor(panel): one shared rule for the adopter `display` vocabulary 2026-08-01 20:25:27 -04:00
editops.lua fix(config): reject wrongly-typed spec fields; make trim-on-save buffer-aware 2026-07-21 18:29:18 -04:00
fold.lua feat(fold): Arc 6 Stage 1 — instance fold engine (headless) 2026-07-23 12:14:00 -04:00
fs.lua wip(stage2a): the Lua half — hooks, LSP subscribers, applier origin 2026-07-29 18:09:03 -04:00
git.lua fix(git): give diff requests a ticket, and share one channel mechanism 2026-08-09 16:48:54 +02:00
help.lua fix(help): forwarders must work programmatically, not only from M-x 2026-07-31 20:31:00 -04:00
indent.lua fix(edit): PR #109 round 1 — shared search invalidation, daemon anchor clear, bounded indent scan 2026-07-10 15:46:36 -04:00
killring.lua feat(edit): editing-conveniences pack (editops) 2026-07-12 15:33:17 +01:00
lean.lua fix(lsp): close round-six Lean fallback gaps 2026-07-25 22:32:48 -04:00
lean_abbrev.lua feat(lean4): the Unicode input method (Arc 8 Stage 4b) 2026-07-26 16:24:06 -04:00
lean_input.lua fix(lean4): count fan-outs where a claim cannot skip the count 2026-07-26 17:15:24 -04:00
linewrap.lua feat(view): horizontal scroll, text and decorations together 2026-08-07 22:43:17 +02:00
listview.lua fix(listview): tear the panel down when a `keys` bind is refused 2026-08-09 15:52:17 +02:00
lsp.lua feat(listview): the tree primitive — depth, collapse, and identity 2026-08-05 14:31:31 +02:00
mcp.lua M9 ship gate 2026-05-09 15:04:23 -04:00
pair.lua feat(typed-edit): the typed-edit consumer chain (Arc 8 Stage 4a) 2026-07-26 13:00:03 -04:00
recentf.lua fix(persistence): symlink confinement, real test-inertness, view_top restore 2026-07-08 18:21:46 -04:00
saveplace.lua fix(persistence): symlink confinement, real test-inertness, view_top restore 2026-07-08 18:21:46 -04:00
syntax.lua feat(lean4): editing surface + Stage 1 acceptance (Q#LN5, LN6, LN17) 2026-07-25 09:59:48 -04:00
terminal.lua fix(buffer): fan out generated writes, and clear the history that exists 2026-07-26 13:43:22 -04:00
typed_edit.lua fix(typed-edit): close round-8 review on the consumer chain 2026-07-26 13:39:33 -04:00
welcome.lua feat(help): the discovery command family — P4 Stage 1 2026-07-31 19:04:48 -04:00
window.lua feat(window): adopter placement opt-in and the Stage 1 acceptance suite 2026-07-24 14:10:45 -04:00
zoom.lua docs(zoom): the ties both round up, they do not oppose 2026-08-06 17:50:03 +02:00