test(window): pin the cross-frontend exception, and fix two ledger counts
panel_commit_dedication_refusal matches on `fid` as well as on the profile: a nested commit for a DIFFERENT frontend may dedicate that frontend's own side slot, because resolve_placement consults only the requesting frontend's panel_capable and its own one side window, so nothing done to B can change where A's side request lands. That promise was documented and unpinned. Both revision 9 nesting tests drive a single frontend, so the comparison is trivially true throughout them: deleting it, and making any outer "panel" contract globally restrictive, passed the whole file. a_nested_commit_for_another_frontend_may_dedicate_its_own_slot runs two frontends. While an outer "panel" commit for A is in force, a nested commit for B dedicates B's slot and is ALLOWED --- and B's slot is asserted really dedicated afterwards, not merely unrefused. The far side runs in the same test: A's slot stays undedicated and A's result still lands in A's panel, so the row cannot pass by having weakened the restriction generally. This is the suite's only POSITIVE row; every other asserts a refusal, which is the shape it was thinnest on. An exception only the doc comment knows about is one review round from being simplified out. Mutation-checked: deleting `&& contract.destination.frontend == fid` fails ONLY this test. Both single-frontend nesting tests pass under it, which is the evidence they are independent of the frontend match rather than merely looking so. journey_acceptance (47), dired_acceptance (31) and cargo test --lib (1920) stay green. Two ledger corrections, both section-local: * "Eight writes exist; five are reachable" then listed four. The fifth is quit_window's QuitAction::Restore --- the site proved unreachable and guarded anyway. It now appears in the list that justifies it, and the bullet counts what actually matters: all five are guarded. * The revision 9 mutation paragraph had the preservation counts REVERSED (journey 31 / dired 47). It is journey 47 / dired 31, matching the bullet further up and measured per target. The same reversal is in 394fa43's commit message; that is left as written rather than rewriting a pushed commit, and the ledger now says so where the numbers are, so a reader following the SHA takes the corrected pair. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai
This commit is contained in:
parent
5f3f38dfd7
commit
3b8e426f90
|
|
@ -335,10 +335,15 @@ form:
|
||||||
`register_frontend_view` has callers only in `daemon.rs` and core
|
`register_frontend_view` has callers only in `daemon.rs` and core
|
||||||
unit tests.
|
unit tests.
|
||||||
- **Eight writes to `dedicated` exist** (`rg 'params\.dedicated\s*='
|
- **Eight writes to `dedicated` exist** (`rg 'params\.dedicated\s*='
|
||||||
src/`); **five are reachable**: `apply_placement`'s `Side` created /
|
src/`); **four are reachable and a fifth is guarded defensively** —
|
||||||
replacing / non-replacing arms, and `set_params`. Two `Ordinary` arms
|
`apply_placement`'s `Side` created / replacing / non-replacing arms
|
||||||
are harmless (their target is never a side window; one only ever
|
and `set_params` are the reachable four, and `quit_window`'s
|
||||||
clears the flag) and one is a unit test.
|
`QuitAction::Restore` is the fifth, proved unreachable below and
|
||||||
|
guarded anyway. **All five are guarded**, which is the count that
|
||||||
|
matters; listing four under the word "five" is what an earlier version
|
||||||
|
of this bullet did. Two `Ordinary` arms are harmless (their target is
|
||||||
|
never a side window; one only ever clears the flag) and one is a unit
|
||||||
|
test.
|
||||||
- **The guards are sited where the property converges, not per caller.**
|
- **The guards are sited where the property converges, not per caller.**
|
||||||
All three `Side` arms are reached through `apply_placement`, which has
|
All three `Side` arms are reached through `apply_placement`, which has
|
||||||
**exactly one caller** — so one guard in `display_buffer` covers every
|
**exactly one caller** — so one guard in `display_buffer` covers every
|
||||||
|
|
@ -383,10 +388,11 @@ authoritative tip** — the ref, not a SHA. Recover with
|
||||||
(`pmacs.window.capture_destination()`, the `ViewDestination` rename,
|
(`pmacs.window.capture_destination()`, the `ViewDestination` rename,
|
||||||
the profile argument); `d5a6170` is
|
the profile argument); `d5a6170` is
|
||||||
`tests/destination_capture_acceptance.rs`; `469d5c8` is the
|
`tests/destination_capture_acceptance.rs`; `469d5c8` is the
|
||||||
revision-8 panel-profile correction plus the invalid-UTF-8 hole; the
|
revision-8 panel-profile correction plus the invalid-UTF-8 hole;
|
||||||
commit below is revision 9's contract stack. **14 pins**, and both
|
`394fa43` is revision 9's contract stack and the commit below adds its
|
||||||
preservation suites pass **unchanged** (journey 47, dired 31) — §7's
|
cross-frontend pin. **15 pins**, and both preservation suites pass
|
||||||
stop signal not firing rather than being suppressed.
|
**unchanged** (journey 47, dired 31) — §7's stop signal not firing
|
||||||
|
rather than being suppressed.
|
||||||
- **HOW THE PANEL PROFILE IS ENFORCED, in one sentence so no earlier
|
- **HOW THE PANEL PROFILE IS ENFORCED, in one sentence so no earlier
|
||||||
revision gets reinstated by someone reading only that document:** the
|
revision gets reinstated by someone reading only that document:** the
|
||||||
preflight stays exactly where it was, and the mutations that would
|
preflight stays exactly where it was, and the mutations that would
|
||||||
|
|
@ -413,10 +419,17 @@ authoritative tip** — the ref, not a SHA. Recover with
|
||||||
so a nested scope rightly replaces them; a contract is a
|
so a nested scope rightly replaces them; a contract is a
|
||||||
*restriction*, and replacing one suspends it. The guard stores a
|
*restriction*, and replacing one suspends it. The guard stores a
|
||||||
depth and truncates back to it, so an inner exit removes exactly the
|
depth and truncates back to it, so an inner exit removes exactly the
|
||||||
contract it added and leaves every enclosing one in force. Matching
|
contract it added and leaves every enclosing one in force.
|
||||||
is per **frontend**: a nested commit for a different frontend may
|
- **Matching is per FRONTEND as well as per profile, and that is a
|
||||||
dedicate *its* side slot, which cannot change where this frontend's
|
deliberate exception with its own positive pin.** A nested commit for
|
||||||
side request lands.
|
a different frontend may dedicate *its* side slot: `resolve_placement`
|
||||||
|
consults only the requesting frontend's `panel_capable` and its own
|
||||||
|
one side window, so nothing done to B can change where A's side
|
||||||
|
request lands. Pinned by
|
||||||
|
`a_nested_commit_for_another_frontend_may_dedicate_its_own_slot`,
|
||||||
|
which is the file's only row asserting that something is **allowed**
|
||||||
|
— every other asserts a refusal, and an exception only the doc
|
||||||
|
comment knows about is one review round from being simplified out.
|
||||||
- **Prohibiting nested `commit_to` was the other candidate and was
|
- **Prohibiting nested `commit_to` was the other candidate and was
|
||||||
rejected.** It closes the hole by forbidding a construction no rule
|
rejected.** It closes the hole by forbidding a construction no rule
|
||||||
objects to — `commit_to` is public Lua API for saying where a
|
objects to — `commit_to` is public Lua API for saying where a
|
||||||
|
|
@ -516,17 +529,35 @@ authoritative tip** — the ref, not a SHA. Recover with
|
||||||
And reverting the byte comparison to `to_str()?` fails the
|
And reverting the byte comparison to `to_str()?` fails the
|
||||||
`invalid utf-8` row with mlua's conversion error, on content.
|
`invalid utf-8` row with mlua's conversion error, on content.
|
||||||
|
|
||||||
**Revision 9's, run across all three suites and the lib:** restore
|
**Revision 9's two, each isolating a different half of the rule:**
|
||||||
`panel_commit_dedication_refusal` to reading only the innermost
|
1. restore `panel_commit_dedication_refusal` to reading only the
|
||||||
contract (`.last()`, which is exactly revision 8's swapped slot) →
|
innermost contract (`.last()`, which is exactly revision 8's
|
||||||
**only** `a_nested_commit_cannot_mask_an_outer_panel_restriction`
|
swapped slot) → **only**
|
||||||
fails. The other 13 pins, `journey_acceptance` (31),
|
`a_nested_commit_cannot_mask_an_outer_panel_restriction` fails.
|
||||||
`dired_acceptance` (47) and `cargo test --lib` (1920) all stay green,
|
Note the ordinary-nesting pin deliberately survives this — it
|
||||||
which is what makes the new test the pin for this defect and not a
|
exists to fail the *other* candidate fix (prohibit nesting), so the
|
||||||
restatement of the depth-1 one. Note the ordinary-nesting pin
|
two are a pair rather than one test written twice.
|
||||||
deliberately survives that mutation — it exists to fail the *other*
|
2. delete `&& contract.destination.frontend == fid` from the same
|
||||||
candidate fix (prohibit nesting), so the two are a pair rather than
|
scan, making any outer `"panel"` contract **globally** restrictive
|
||||||
one test written twice.
|
→ **only**
|
||||||
|
`a_nested_commit_for_another_frontend_may_dedicate_its_own_slot`
|
||||||
|
fails. Both single-frontend nesting tests pass under it, which is
|
||||||
|
the evidence they are independent of the frontend match rather than
|
||||||
|
merely looking so; the cross-frontend exception had no pin at all
|
||||||
|
before this row, since every other test in the file drives one
|
||||||
|
frontend.
|
||||||
|
|
||||||
|
Both were run across all three acceptance suites and the lib: in each
|
||||||
|
case `journey_acceptance` (47), `dired_acceptance` (31) and
|
||||||
|
`cargo test --lib` (1920) stay green, along with every other pin in
|
||||||
|
this file.
|
||||||
|
|
||||||
|
**The counts above are journey 47 / dired 31**, matching the bullet
|
||||||
|
further up. The mutation paragraph committed at `394fa43` had them
|
||||||
|
**reversed** in both the ledger and that commit's message; the ledger
|
||||||
|
is corrected here and the message is left as written, since rewriting
|
||||||
|
a pushed commit is worse than a footnote. A reader following that SHA
|
||||||
|
should take these numbers, not those.
|
||||||
- **The public API #227 adopts against (Q#DC-5), pinned so it is a
|
- **The public API #227 adopts against (Q#DC-5), pinned so it is a
|
||||||
contract rather than an intention:**
|
contract rather than an intention:**
|
||||||
`pmacs.window.commit_to(dest, body [, profile])`. Profile is an
|
`pmacs.window.commit_to(dest, body [, profile])`. Profile is an
|
||||||
|
|
|
||||||
|
|
@ -719,6 +719,21 @@ incidental: no arguments is what keeps capture profile-blind.
|
||||||
force after the nested commit returns** (popped, not cleared), and
|
force after the nested commit returns** (popped, not cleared), and
|
||||||
**outside every commit dedication is ordinary again**, so the fix
|
**outside every commit dedication is ordinary again**, so the fix
|
||||||
leaked no permanent restriction onto the editor.
|
leaked no permanent restriction onto the editor.
|
||||||
|
- **THE CROSS-FRONTEND EXCEPTION IS PINNED POSITIVELY**, over **two**
|
||||||
|
frontends: while an outer `"panel"` commit for A is in force, a nested
|
||||||
|
commit for **B** dedicates **B's** side slot and is **allowed** — and
|
||||||
|
B's slot is asserted really dedicated afterwards, not merely
|
||||||
|
unrefused. The far side runs in the same test: A's slot is still
|
||||||
|
undedicated and A's result still lands in A's panel, so this cannot
|
||||||
|
pass by having weakened the restriction generally. **This is the one
|
||||||
|
row asserting that something is permitted**; every other in the suite
|
||||||
|
asserts a refusal, and without it, deleting the `fid` comparison —
|
||||||
|
making any outer panel contract *globally* restrictive — passes the
|
||||||
|
whole file, because both nesting rows above drive a single frontend.
|
||||||
|
The exception is real and not a convenience: `resolve_placement`
|
||||||
|
consults only the requesting frontend's `panel_capable` and its own
|
||||||
|
one side window, so nothing done to B can change where A's side
|
||||||
|
request lands.
|
||||||
- **A `"panel"` commit that really lands in the panel still skips
|
- **A `"panel"` commit that really lands in the panel still skips
|
||||||
checks 2–4** — otherwise the fix has quietly collapsed the two
|
checks 2–4** — otherwise the fix has quietly collapsed the two
|
||||||
profiles into one and the parameterization buys nothing.
|
profiles into one and the parameterization buys nothing.
|
||||||
|
|
|
||||||
|
|
@ -1062,6 +1062,121 @@ fn an_ordinary_nested_commit_still_runs_and_restores_the_outer_restriction() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// **P** — the restriction is scoped to its **frontend**: a nested commit
|
||||||
|
/// for a *different* frontend may still dedicate that frontend's own side
|
||||||
|
/// slot (revision 9).
|
||||||
|
///
|
||||||
|
/// `panel_commit_dedication_refusal` scans every contract in force, but it
|
||||||
|
/// matches on `fid` as well as on the profile, and that comparison is a
|
||||||
|
/// deliberate exception rather than an oversight: frontend B's side slot
|
||||||
|
/// has no bearing on where **A's** side request lands. `resolve_placement`
|
||||||
|
/// consults only the requesting frontend's `panel_capable` and its own one
|
||||||
|
/// side window, so a contract for A cannot be invalidated by anything done
|
||||||
|
/// to B.
|
||||||
|
///
|
||||||
|
/// **This is a POSITIVE pin, which is the shape this suite is thinnest
|
||||||
|
/// on** — every other row asserts a refusal. Without it, deleting the
|
||||||
|
/// `fid` comparison and making any outer `"panel"` contract *globally*
|
||||||
|
/// restrictive passes the whole file: the two nesting tests above use one
|
||||||
|
/// frontend, so the comparison is trivially true throughout them. An
|
||||||
|
/// exception that only the doc comment knows about is one review round
|
||||||
|
/// away from being "simplified" out.
|
||||||
|
///
|
||||||
|
/// The far side is still asserted in the same run: A's slot stays
|
||||||
|
/// undedicated and A's commit still lands in A's panel, so this cannot
|
||||||
|
/// pass by having weakened the restriction generally.
|
||||||
|
///
|
||||||
|
/// *Mutation:* delete `&& contract.destination.frontend == fid` from
|
||||||
|
/// `panel_commit_dedication_refusal` and only this test fails.
|
||||||
|
#[test]
|
||||||
|
fn a_nested_commit_for_another_frontend_may_dedicate_its_own_slot() {
|
||||||
|
let s = editor();
|
||||||
|
|
||||||
|
// Frontend B: its own layout, its own undedicated panel, and a
|
||||||
|
// destination captured while it is the acting frontend.
|
||||||
|
attach_frontend(&s, COMPETITOR);
|
||||||
|
s.core.borrow_mut().active_frontend = COMPETITOR;
|
||||||
|
exec(
|
||||||
|
&s,
|
||||||
|
"pmacs.window.display(pmacs.buffer.create('*b-panel*'),
|
||||||
|
{ side = 'bottom', select = false })
|
||||||
|
dest_b = pmacs.window.capture_destination()",
|
||||||
|
);
|
||||||
|
let b_panel = s
|
||||||
|
.core
|
||||||
|
.borrow()
|
||||||
|
.side_window_for(COMPETITOR)
|
||||||
|
.expect("the competitor gets its own side slot");
|
||||||
|
assert!(
|
||||||
|
!dedicated(&s, b_panel),
|
||||||
|
"B's slot must start undedicated, or the row would prove nothing"
|
||||||
|
);
|
||||||
|
s.core.borrow_mut().active_frontend = FrontendId::LOCAL;
|
||||||
|
|
||||||
|
// Frontend A: an undedicated panel, so its `"panel"` commit takes the
|
||||||
|
// relaxed preflight and the restriction is really in force.
|
||||||
|
exec(&s, PANEL_ARRANGED);
|
||||||
|
let a_panel = s
|
||||||
|
.core
|
||||||
|
.borrow()
|
||||||
|
.side_window_for(FrontendId::LOCAL)
|
||||||
|
.expect("the arrangement creates A's side slot");
|
||||||
|
capture(&s);
|
||||||
|
let doc = local_window(&s);
|
||||||
|
exec(
|
||||||
|
&s,
|
||||||
|
"pmacs.window.switch_buffer(pmacs.buffer.create('*newer*'))",
|
||||||
|
);
|
||||||
|
|
||||||
|
commit_body(
|
||||||
|
&s,
|
||||||
|
Some("'panel'"),
|
||||||
|
&format!(
|
||||||
|
"b_ok, b_reason = pmacs.window.commit_to(dest_b, function()
|
||||||
|
pmacs.window.set_params(pmacs.window.panel(), {{ dedicated = true }})
|
||||||
|
end)
|
||||||
|
{PANEL_BODY}"
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 1. THE CROSS-FRONTEND DEDICATION IS ALLOWED.
|
||||||
|
assert_eq!(
|
||||||
|
raised(&s),
|
||||||
|
None,
|
||||||
|
"dedicating ANOTHER frontend's side slot must not be refused -- it cannot change \
|
||||||
|
where this frontend's side request lands"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
eval::<bool>(&s, "return b_ok == true"),
|
||||||
|
"the nested commit for B must be accepted: {}",
|
||||||
|
eval::<String>(&s, "return tostring(b_reason)")
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
dedicated(&s, b_panel),
|
||||||
|
"B's slot must really be dedicated -- asserting only that nothing was refused \
|
||||||
|
would pass on a call that was silently dropped"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 2. AND A'S RESTRICTION IS UNWEAKENED: its slot is untouched and its
|
||||||
|
// commit still lands in its own panel rather than falling back.
|
||||||
|
assert!(ok(&s), "A's commit must be accepted: {}", reason(&s));
|
||||||
|
assert!(
|
||||||
|
!dedicated(&s, a_panel),
|
||||||
|
"A's own slot must be untouched -- this row must not pass by having relaxed the \
|
||||||
|
restriction for everyone"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
name_in(&s, a_panel),
|
||||||
|
"*result*",
|
||||||
|
"A's \"panel\" commit still belongs in A's panel"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
name_in(&s, doc),
|
||||||
|
"*newer*",
|
||||||
|
"and A's newer document buffer must survive"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// **P** — a `"panel"` commit that falls back with a **still-valid**
|
/// **P** — a `"panel"` commit that falls back with a **still-valid**
|
||||||
/// destination lands in the document window, exactly as it does today.
|
/// destination lands in the document window, exactly as it does today.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue