Skip to content

[drill] contrib sim (sanitize + ledger anchoring) - #3

Closed
pelmentor wants to merge 3 commits into
mainfrom
drill/contrib-sim
Closed

[drill] contrib sim (sanitize + ledger anchoring)#3
pelmentor wants to merge 3 commits into
mainfrom
drill/contrib-sim

Conversation

@pelmentor

Copy link
Copy Markdown
Contributor

Gate-campaign drill branch: benign on:push workflow + corrupted ledger. Closed after the drill.

@pelmentor

Copy link
Copy Markdown
Contributor Author

Drill campaign complete: sanitize zero-runs + ledger-anchoring both proven. Closing; branch deleted.

@pelmentor pelmentor closed this Jul 25, 2026
@pelmentor
pelmentor deleted the drill/contrib-sim branch July 25, 2026 11:40
pelmentor pushed a commit that referenced this pull request Jul 27, 2026
Two things the 4-peer smoke caught that the build could not.

1. HotPathGuard ERROR: "g_rows (roster_ledger::Reset) accessed OFF the game
   thread". Reset is called from event_feed::OnSessionStart, which runs on the
   BRINGUP thread at harness/session_runtime.cpp:386 -- before g_session.Start()
   at :430 spawns the net thread and before the pump can tick a running session.
   So the ACCESS is safe by construction (no concurrent reader; Start()'s thread
   creation is the happens-before edge) and the ASSERT was mis-scoped. Reset is
   now the one accessor deliberately without it, with the contract written down.
   Also recorded there: Reset notifies subscribers per slot, but every outgoing
   row is empty at bringup and every subscriber early-returns on an unoccupied
   outgoing row -- so no subscriber body, none of which is bringup-thread-safe,
   actually runs. That invariant is load-bearing and now says so.

2. The client-side "installed cross-peer identity" log line vanished when I
   rewrote the handler, taking mp.py's xpeer_identity counter with it (the smoke
   reported []). That is lost observability, not a stale matcher, so the line is
   restored -- gated on the ACTUAL mirror install rather than on every pulse
   re-assert, or a per-second repeat would make it useless as a signal.

mp.py's two matchers repointed at the renamed lines (held-WIP, not committed).

RE-SMOKE ON THE FIXED BYTES -- 4 peers, PASS:
  host accepted [1,2,3], relayed roster 3x, epoch latched [1,2,3]
  CLIENT1 slot=1 sees [0,2,3], xpeer=[2,3]; CLIENT2 slot=2 sees [0,1,3],
  xpeer=[1,3]; CLIENT3 slot=3 sees [0,1,2], xpeer=[1,2]
  ledger: slot 0 -> #1 (host role constant), slots 1..3 -> #2,#3,#4 (monotonic,
  host never draws #1)
  0 HotPathGuard violations, 0 puppet spawn failures, 0 malformed drops,
  0 stale-gen drops, no roster/ledger WARN or ERROR
  IDEMPOTENCY PROVEN: exactly 4 ledger transitions and exactly 2 identity
  installs per client across the whole run, while the repair pulse re-asserted
  every 1-5 s throughout -- the receiver treats rows as STATE, not events.

Still NOT hands-on, and the replacement/successor drills still owed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
pelmentor pushed a commit that referenced this pull request Jul 27, 2026
Records the autonomous evidence for arc A in the design doc.

4-PEER SMOKE, PASS. Idempotency is the part worth naming: exactly 4 ledger
transitions and 2 identity installs per client across the whole run, while the
repair pulse re-asserted every 1-5 s throughout. The receiver genuinely treats
roster rows as STATE.

DEPARTURE DRILL, PASS -- the case the smoke does not cover and the arc's central
claim. Killing one client mid-session produced, on the HOST and on BOTH SURVIVING
CLIENTS within the same second: the "left the game" line, "peer slot 2 (#3) left
-- puppet destroyed", and "ledger: slot 2 emptied (was #3 'Client2')". Exactly
once per peer, no double-fire under the pulse.

The two CLIENT lines are the whole point. Before this arc a client could not
learn of a third peer's departure at all: IsSlotReady(2) is permanently false
there, so no edge ever fired -- the frozen puppet stayed in the world for the
rest of the session and no roster row ever existed. CLIENT1's pose-diag for
slot 2 sitting at fresh=0/s from 22:31:42 until the destroy at 22:31:48 is that
body, now actually collected.

Getting the drill honest took three instrument fixes, each measured rather than
guessed: multivoid.log is ROTATED per boot (so a line-count baseline can never be
exceeded and the wait hangs); the process name is VotV-Win64-Shipping while
"VotV" is only the window title; and smoke4's default monitor window expired and
killed the peers during the settle, leaving nothing to test. Instrument lives at
<scratchpad>/arcA_departure_drill.ps1 (it drives mp.py, which is never-commit).

Still owed: the REPLACEMENT drill (a peer taking the departed slot with the
departure row injected-lost), the successor-ban drill, an audit, and hands-on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
pelmentor pushed a commit that referenced this pull request Jul 30, 2026
…is not CORRECT

The chat-history feature shipped yesterday as BUILT, with two purpose-written
drills PASSing 4/4 and both shown RED under injection. A /qf phase IMPLEMENTATION
pass over the REAL DIFF found twelve defects in four rounds, and not one of them
would turn either drill red.

Design doc gains the whole pass:
  SS19  the twelve, ranked by what a human hits, each citing a line. #5 is the
        ESC close path -- the user's own spec ("close like minecraft") -- broken
        three ways because imgui_overlay.cpp:359 gates hud::Render() on
        !PauseMenuOpen() and chat_view::Draw() therefore stops running entirely.
  SS20  the USER'S REFRAME: every peer gets ALL history, event-feed lines
        included. This makes the architecture SMALLER -- the host's record owns
        every retained row, so Keep is deleted (RULE 2) and defects #3 and #8
        DISSOLVE rather than being patched. proto 133 -> 134.
  SS21  NEXT, gated on the 7-site peer_action_feed::Announce census.

Status corrections, both directions, against the code this run:
  COOP_SYNC_PROFILES.md chat HISTORY  BUILT -> BUILT AND DEFECTIVE, with the
        drill verdict re-scoped to the two axes it actually covers
  COOP_SYNC_PROFILES.md "NOT SYNCED: nothing outstanding" -> nothing on the WIRE;
        the 12 + the reframe are open
  COOP_EVENT_JOIN.md 3.4  the late-join ANSWER is correct and unchanged; the CODE
        implementing it is not finished

Four lessons, paired 1:1 into docs/LESSONS.md:
  built+drilled+green is a statement about the DRILLS, not the code -- an
    --inject control proves ONE BIT, never coverage
  a harness WORKAROUND deletes the path it works around (mp.py closes with Enter
    "NOT Escape" -- which removed the user's own close path from all coverage)
  a keep-alive predicate is worthless if a gate ONE LEVEL UP can veto the draw
  ONE capacity expressed in THREE places will disagree (200 / 100 / 106)

Plus a third instance of census-the-DIRECTION: chat_input.cpp:62 censused what
Open/Close tell the STORE and never what else those functions WRITE.

No code changed this session. HEAD DLL and proto are untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
pelmentor pushed a commit that referenced this pull request Jul 30, 2026
Two /qf passes this session (8 rounds on the glyph thread, 6 on the upgrade
plan) and one real measurement. No code: the spike was reverted, the submodule
is still pinned v1.91.5, the tree is clean.

THE GLYPH QUESTION IS ANSWERED. CJK is unaffordable in ImGui 1.91.5 whatever
the glyph SOURCE and whatever the bake TRIGGER, because 1.91.5 has no dynamic
atlas. The five objections this tree recorded against on-demand OS fonts
collapse to that one root: count 4 was FALSE against the prior art it cited
(MTA hands a FILE to the OS via AddFontResourceEx + D3DXCreateFont;
MapCharacters is a discovery API MTA never touches), count 2 was a product
question, count 1 a survivable cost, count 6 an invariant to preserve -- and
count 3, the only real kill, is a CONSEQUENCE of the missing dynamic atlas.
MTA absorbs arbitrary remote text because CEGUI rasterises per PAGE and evicts:
one remote codepoint costs it a page, ours costs a whole atlas.

MEASURED, not estimated: the 1.92.9 port is 3 files, +18/-14, and it LINKS.
400 TUs compiled, DLL +71 KB (+0.41 %). Three findings a changelog could not
have given: GlyphRanges is DEAD INPUT once RendererHasTextures is on -- read
only under `if (RendererHasTextures == false)` -- which DISSOLVES arc D2's
one-generator fold==bake construction rather than violating it;
FindGlyphNoFallback moved to ImFontBaked and now BAKES on miss, so the font
selftest can no longer ask "is it in the atlas"; and three call sites compile
only via obsolete shims, which is RULE-2 baggage rather than a finished port.

FIVE STATUS FLIPS, each checked against code this run:
  - RF3's "structural DX12 precondition" is largely ALREADY BUILT -- we have
    owned a 256-slot SRV heap, per-slot handle math and fence-gated slot
    recycling since the July UI-texture work. Framing superseded.
  - M2's diff row #7 ("zero sites -- free") was wrong by 10 references to
    REMOVED FIELDS; rows #1/#3/#4 are not breaks at all; row #2's sites had
    rotted onto a file that did not exist when it was written.
  - The bake doc's own status box, written last sweep, said the OS-font /qf was
    still owed. It had already run, 200 lines down in the same document. That
    is the false-status failure the sweep exists to prevent, committed inside
    the sweep.
  - Greek / Latin-Extended "render as the sentinel" is STALE in two places
    (shipped 9b4286f); CJK / Hangul / Thai unchanged.
  - Two price fusions un-fused: +FULL CJK is LEGAL at every config and only
    EVERYTHING@worst@x2.0 is illegal, so a purchasable YES branch exists.

THREE LIVE DEFECTS recorded, none caused by the upgrade: a straight port ships
two drawable repertoires in ONE build (DX11 sets the flag, DX12's legacy init
strips it); 33 shipped invisible uniqueness-bearing codepoints (U+0080-U+009F
and U+00A0 are IN the repertoire -- twenty NBSPs is a "unique" nickname that
shows nothing); and g_pending[64] is a live latent use-after-free whose
unbounded producer is staging buffers, not the slot table.

The fold now has a DATED EXPIRY in the arc-D2 design doc rather than a commit
note: the sentinel mapping is a function of coverage, and coverage stops being
a build constant under OS fonts -- at which point two visibly different CJK
names would fold to one sentinel and one would take a suffix. With the machine
trip-wire that must fail the build the day an OsSupplied font source appears.

Six lessons, paired 1:1 into LESSONS.md: an upgrade can demote your INPUT to a
hint; querying a lazy cache POPULATES it; a clean upgrade build may be riding
obsolete shims; five objections with one root are one objection and a list;
decompose a rejected mechanism into AXES before telling the user their choice
is dead (SOURCING was never in question -- only TRIGGERING); and a cost number
must carry its REGIME.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
pelmentor added a commit that referenced this pull request Aug 25, 2026
…ot deployable

SYNC_MAP: the coingun row was written when A50/A51 were open and the module
was two files. It is now three (client half / host arbiter / collect), both
security rows are built at proto 140, and field defect #3's call site is
fixed -- but the two facts that actually gate a re-test are unchanged and now
say so plainly: nothing is smoked, nothing is deployed, the install still
holds the failing b137 payload, and deploy-mod.ps1 picks its payload by MTIME
so a casual deploy would ship an unaudited build.

Still open and named: B3 (Points on the spawn payload + the mirror-park
owner), B4, and the pre-existing Install coupling found during the extraction.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D9S4dw1Fg8UNsT7SHiWJ3W
pelmentor added a commit that referenced this pull request Aug 26, 2026
… build already parses

Round 13, three hits, all against artefacts from this same turn.

THE DOCSTRING CLAIMED "mutate instantly" WHILE THE CODE ASSIGNED THE ROW LIST
EXACTLY ONCE. Section 8c.2's phases C (grow), D (shrink) and E (shuffle at
constant count) all need the set to change while the game is looking at it -- and
E is the phase I have repeatedly called the one that would have caught the
HashMap-order defect. The shipped fixture could drive none of them. There is now
a control channel: /control/count?n= grows by appending and shrinks by keeping a
prefix (so surviving ids are stable), /control/shuffle reorders with the SET HELD
CONSTANT, /control/state reports an ORDER-SENSITIVE fingerprint -- a count or a
set hash cannot see a reorder, which is the whole point of E.

Driven end to end before claiming it: 100 -> 200 -> 50 -> shuffle, fingerprints
changing at each step. And I checked the shuffle rather than trusting its own
report, because the first run served fake-0000 first after shuffling and a
fingerprint that says "changed" while the body is unchanged is precisely the
selftest-that-lies shape this project keeps learning about. It was the 2%
coincidence: the served body really is reordered, same 50 ids.

PROTO AND GAME TARGET ARE NOW PARSED, not hand-copied, from the same protocol.h
and CMakeLists.txt the build itself reads -- and the parse EXITS if the pattern
moves. A drifted proto is a silent failure of the worst kind: every row renders
amber, the perf numbers stay clean because the cost is identical, and the
tester's feel verdict is quietly delivered about the wrong screen.

Also: round 12 moved the cadence to T2b and orphaned two references. 8c.2 phase B
still told the tester to watch a "1 Hz refresh" that T2b deletes, and 8c.3 #3
still pointed at T4a. My own contradiction sweep missed both because I grepped
for the phrases I remembered instead of the concept -- the alias-vocabulary
census failure, again.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WpYi5yy8yPvP1sv8mfiz59
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.

2 participants