Skip to content

test(helpers): refuse unwitnessed doc-changing dispatches in withUnstarvedFrontier - #483

Merged
mtskf merged 4 commits into
mainfrom
chore/arch-07-structural-range-model
Nov 8, 2026
Merged

mtskf merged 4 commits into
mainfrom
chore/arch-07-structural-range-model

Conversation

@mtskf

@mtskf mtskf commented Nov 8, 2026

Copy link
Copy Markdown
Owner

Summary

withUnstarvedFrontier (the view form of the bounded ≡ full oracle helper) let two doc-changing dispatches through between two gates. The second one was never checked, so the oracle could go vacuous without anyone noticing. The helper now refuses that case. It also refuses a state that reached the view without going through view.update(). This is ARCH-07 PR1. PR2 and PR3 are separate.

Changes

  • test/webview/helpers/unstarved-frontier.ts
    • runUnstarvedAttempts gains a required admitGate(context) hook. It runs at every gate entry, after assertHasLanguage and before the starvation check.
    • The view form wraps the instance's view.update once per attempt.
      • It counts doc-changing transactions, committing each count only after update succeeds.
      • It records the expected post-update state, so a later bypass can be detected.
    • Its admitGate refuses a bypassed state, and refuses more than one doc change since the last gate (or since mount).
    • Refusals are plain Errors, so a refusal that observe() swallows is still convicted by the gate-entry conservation law.
    • If installing the wrapper fails, the helper tears the view down and rethrows.
    • The state form passes a no-op admitGate.
  • test/webview/helpers/unstarved-frontier.test.ts: 80 tests now. The new ones cover count and bypass refusals, listener re-entry, a rejected or throwing update, setup failure, and conviction of a swallowed refusal.
  • test/webview/cm-block-widget-bounded.test.ts: comment only. It notes that the helper now enforces one item of its operating rule.

The commit body has a mutation table, (a)–(i). The implementation lives under test/, so revert-check would report a vacuous ALL_PINNED.

Known residue, documented in the helper and not fixed here: reconfiguring a Compartment with effects only moves the frontier without being counted.

Related TODO

ARCH-07 PR1: bounded≡full oracle の空虚化を塞ぐ — withUnstarvedFrontier が未検証の doc-changing dispatch を 2 つ通すのを拒否する

Test plan

  • pnpm compile
  • pnpm exec biome check on changed files
  • pnpm test:unit: 287 files / 6131 tests passed
  • Call-site suites: 9 files / 227 tests passed
  • pnpm package (audit OK) and install
  • Mutation table (a)–(i): each mutation went red as expected, and the files were restored byte-identical

mtskf added 4 commits November 8, 2026 22:26
…arvedFrontier

The view form now wraps view.update for each attempt and judges at every gate
entry (a new admitGate hook in runUnstarvedAttempts). It refuses more than one
doc-changing transaction between two gates (or between mount and the first
gate), and refuses a state that reached the view without passing through, or
completing, view.update(). Both are plain Errors, so a refusal that observe()
swallows is still convicted by the gate-entry conservation law. The state form
has no view-owned seam, so its admitGate is a no-op.

Mutation results (observed red sets, each reverted afterwards; the helper files
were byte-identical to the snapshot and 80/80 passed again). They are recorded
here because the implementation lives under test/, so revert-check classifies
this commit as test-only and returns a vacuous ALL_PINNED (precedent: PR #392,
same file):
- (a) delete both admission throws -> 17 red (8 count + 9 bypass refusal tests)
- (b) count every transaction, not only doc-changing ones -> 4 red: the
  selection-only, phrases-reconfiguration and listener-selection accept tests,
  plus the swallowed-refusal + throwing-destroy conviction test
- (c) commit the count before original() -> red: does not count a transaction
  the view rejected
- (d) drop the entry latch -> red: the 3 table rows plus the failed-update
  preservation test
- (e) drop `bypassed` -> red: all 9 bypass tests
- (f) record the expectation after original() -> 3 red: the listener-selection
  accept test, the listener doc-changing count test, the listener setState
  bypass test
- (g) catch arm sets view.state instead of restoring -> red: both
  throw-after-advance tests
- (h) eager read of the last transaction's .state -> red: rejected-transaction
  test
- (i1) bypass throw as HelperRefusal -> red: only the bypass
  swallowed-sentinel test
- (i2) count throw as HelperRefusal -> red: only the count swallowed-sentinel
  test

No call site batches two doc changes per gate, so no call-site test changed;
cm-block-widget-bounded.test.ts only notes that the helper now enforces that
one item of its operating rule.
@mtskf
mtskf merged commit dd93485 into main Nov 8, 2026
2 checks passed
@mtskf
mtskf deleted the chore/arch-07-structural-range-model branch November 8, 2026 14:18
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