Skip to content

Phase 1 / Forge / Tier 0 pre-freeze and C1.1 cost - #73

Open
guysenpai wants to merge 31 commits into
mainfrom
phase-1/forge/tier0-pregate-and-c11-cost
Open

Phase 1 / Forge / Tier 0 pre-freeze and C1.1 cost#73
guysenpai wants to merge 31 commits into
mainfrom
phase-1/forge/tier0-pregate-and-c11-cost

Conversation

@guysenpai

@guysenpai guysenpai commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Brief: briefs/m1.1.15.1-tier0-pregate-and-c11-cost.md — Status CLOSED, 2026-08-27, reopened twice on external review before closing (RD-7, RD-9, RD-11).

M1.1.15.1 is the milestone that makes the freeze possible rather than the one that takes it. Six gates, A to F, each stopped for an explicit GO — then two reopenings and a third pass, and what they found is worth more than what the gates delivered.


What it delivers

(a) core.ModuleContext, minted with FOUR fields. Each of engine-tier-interfaces.md §0's four removals is absent for a named reason and none by minimalism: registrar and event_bus would be second declarants of acts World already owns (pattern D11); asset_loader would be a tier inversion whose absurdity needs no invariant to see, that module's own init taking a *ModuleContext and so receiving a pointer to itself; frame_allocator has no Tier 0 producer and no consumer. The *World is outside ARCH-030 rather than an exception to it. Pinned by a negative twin with a two-mechanism predicate whose counter-factual changes the object — a refused six-field shape — never its own expected constant.

(b) The Tier 1 allocator and fallibility contract. ARCH-013 forbids an allocator on a Tier 1 interface entry while six PhysicsWorld entries need one, so src/modules/forge/module.zig fronts it. Measured: Forge3DModule holds the one allocator on the physics path, PhysicsWorld holds zero of its nineteen fields as one, and 0 of the adapter's 28 entries take one. Broadphase.update became infallible on an invariant — at most one unconsumed log entry per slot — not on a reservation promise, which is what let the three pose setters collapse to void. step became anyerror!void over eight measured allocation sites with a written failure contract.

(c) M1.D.13 closed, and the C1.1 instrument written. proxyOf went from a linear search to a dense BodyId-keyed index, with an authority statement rather than a second source: bodies[i].proxy is the fact, the index is derived, rebindProxy is the single derivation point. bench/physics_forge_3d_integration.zig is the instrument C1.1 named and that did not exist.

(d)–(e) The M1.1.26 → M1.1.15.2 / M1.1.25 → M1.1.21.1 renames propagated (24 code sites, 17 CLAUDE.md sites), the 27 → 30 count correction, the CLAUDE.md §3.4 patch.


C1.1, measured for the first time

1 000 dynamic + 10 000 static at 60 Hz, on 1 000 awake dynamic bodies of 11 000, P = 8 809 retained pairs, 240 frames from frame 31.

Mode median p99 (gated) max budget margin on worst p99
ReleaseFast 2.028–2.144 ms 2.113–3.576 ms 2.235–4.589 ms 16.6 ms 4.6×
ReleaseSafe 2.152–2.436 ms 2.253–5.467 ms 2.275–7.873 ms 16.6 ms 3.0×

Zero allocation attempts in steady state in both, where steady state is defined on the scene (pairs and constraints unchanged for thirty frames) and never on the allocator — otherwise the result would be true by choice of window and unable to fail.

Gated on the p99, not the median. A 60 Hz budget is a real-time constraint and a hitch is invisible to a centre. Reported in the other direction too: across five runs per mode on identical code with a bit-identical checksum, the median moves 6 %, the p99 up to 2.4× and the max up to 3.5× — the tail is machine noise, so this gate buys sensitivity and costs stability, and the margin is claimed on the worst p99 observed.

Retention shape (reported). N ×3.72 at a measured-constant P = 2 209 gives frame ×1.14. A Θ(P·N) step 2 would demand 33.1 million extra endpoint resolutions per frame for a measured delta of 70 µs — 2.1 picoseconds each. Refuted by ~470×.


The two reopenings, and the finding that outranks the gates

First — F1/F2/F3. entitiesOf returned one entry per body where engine-physics-queries.md §1.11.14 makes deduplication MANDATORY at the tier projecting bodies onto entities, and its comment deferred that obligation to a tier above the interface which receives entities already projected — nothing would ever have deduplicated. A private staging depth of 256 capped four public entries below the caller's own slice. The cause was that no multi-result entry was exercised through the adapter at all, and the sweep produced the number:

count
behaviour-asserted 9 deinit, step (failure path), addBody, setBodyTransform, getBodyTransform, createShape, createCharacter, resizeCharacter, getCharacterInnerBody
signature / smoke only 8 init, removeBody, setLinearVelocity, addForce, addImpulse, destroyShape, destroyCharacter, setCharacterPosition
never called at all 11 moveKinematic, setAngularVelocity, raycast, raycastAny, raycastAll, shapeCast, overlapShape, overlapAabb, pointQuery, closestPoint, moveCharacter

F1 and F2 were the first two of nineteen. And the classification is what makes that number usable in one direction rather than the other: the four single-result query entries and the mutators passed on their first run, so seventeen entries were correct and unguarded while two were wrong — a family of missing guards, not of missing correctness.

Second — G1/G2. stageBodies said "two of the three callers are frozen as bare u32"; measured, four callers and three bare, the fourth being overlapShape, frozen anyerror!u32, which the code silently made swallow an OutOfMemory its own signature declares transmissible. And the sweep declared closed had been closed on call sites, where the predicate that matters is whether an oracle tells an entry apart from a plausible neighbour: moveKinematic asserted only the pose reached, which setBodyTransform also reaches. Re-counted with the right predicate, three more fell — init, setLinearVelocity, resizeCharacter — plus pointQuery. 28 of 28 now carry a discriminating oracle, with one reservation named and not closed: setAngularVelocity asserts that the orientation changed, not which axis.

Third — H1, and the defect was inside F1's own fix. dedupEntities deduplicates by adjacency, correct only under the entity-major order of query/overlap.zig's collector, and the whole premise was held by a std.debug.assert — which ReleaseFast compiles to nothing. The guard was live in the two matrix cells where a breach costs nothing and absent in the mode the bench runs and a game ships. Fixed on the repository's own precedent (query/root.zig:380 already replaces a release-stripped class assert with an active check, for this reason and in these words): the comparison is active in every mode, and on detection the function stops trusting adjacency and scans what it has written — exact, because everything written before the break was deduplicated over an ordered run. The answer is never wrong even under a violated premise, and the violation is counted because two of three callers have no channel. Counter-factual decisive both ways: the old form gives expected 2, found 3 in ReleaseFast and panics in Debug.

Class swept, with the criterion stated — read literally, "an assert guarding another module's contract" sweeps in almost every precondition. 132 production asserts: 15 comptime (every mode), 117 runtime — 43 caller-parameter domain preconditions, 65 local or owned-structure invariants, 9 asserting a shape's class (not in the class: the category is chosen upstream by an exhaustive switch whose net M1.1.11.1 audited, and the caller-supplied-handle path already carries an active probeAdmissible check). One neighbour ruled out with its reason rather than by silence. The H1 class had exactly one member.

And the gap H1 came out of is closed here. One CI cell added, ubuntu-24.04 / ReleaseFast / f32, 12 → 13 — deliberately not an axis: a release-stripped assert is mode-dependent and neither platform- nor precision-dependent, so one cell detects the whole class where completing the axis would cost 50 % of the matrix. The reason is written in ci.yml at the cell, with an explicit instruction not to complete it by symmetry.


Findings reported, not worked around

  • api.JointDescriptor and api.JointId are declared nowhere (measured), so the adapter presents 28 of 30 frozen entries and the plan line assigning joints to M1.1.15.2 is unrealisable as written.
  • An asleep scene allocates where an awake one does not: 11 000 bodies with sleeping enabled allocate 5 280 times over 240 steady-state frames (rigid/contact_constraint.zig:578) against zero awake. C1.1's zero-allocation property is gated in a configuration a shipped game does not run. Mechanism already owned; this is its first measurement.
  • Three frozen entries cannot report an allocation failure (raycastAll, overlapAabb, pointQuery, bare u32). Under exhaustion they answer a correct prefix — a degradation, not a designed cap. Whether that should be so is a contract decision for M1.1.15.2 (RD-10).
  • Two count discrepancies in the frozen brief, reported with their units rather than reconciled away.

Method — the milestone's real subject

Three times, on three different objects, a green count was produced by a predicate weaker than the claim it supported: 28 entries counted as existing when the question was what they answer; four staging callers counted as three, which made an arbitration follow from a false enumeration; 28 entries counted as called when the question was whether their oracles discriminate. Each count was correct for what it measured and useless for what it was used to conclude.

Eight instrument defects, and not one was found by a red check pointing at it. Three arrived at Gate E in a bench just written, under a green PASS. A fourth was a cap probe whose 500:1 box hit a documented GJK limit. A fifth was echo "push exit=$?" returning the exit code of the echo. A sixth was an until status == completed loop reading a stale finished run as a re-run's result. A seventh was a mutation string naming a parameter the source does not have. An eighth did not compile, so it measured nothing while reporting exit=1 — which reads exactly like a counter-factual that fired.

Two rules the milestone leaves behind: a guard must be shown able to fail on the property it claims, not merely to fail — hence the p99 counter-factual injects hitches at the unchanged budget rather than lowering it; and a counter-factual must be shown to have RUN, not merely to have been applied.


Validation

  • zig fmt --check — 0 files unformatted
  • zig build lint — exit 0, dead-tests conservation OK at 1962
  • Suite — 1943 passed + 19 skipped = 1962 collected (macOS, windows-2025 1960); test-forge-3d 580
  • Four corners {Debug, ReleaseSafe} × {f32, f64} — exit 0, 0, 0, 0 — plus ReleaseFast/f32, the mode H1 concerns, now a standing CI cell
  • zig build forge-determinism at f32 and f64 — exit 0, 0 witnesses regenerated
  • Bench gates — both PASS in ReleaseFast and ReleaseSafe
  • 28 of 28 adapter entries carry a discriminating oracle; every fix pinned by a counter-factual that fires
  • Language audit (Python, never a grep bracket class) — zero French prose
  • Rename residue — zero in src/, tests/, tools/, bench/, build.zig, .github/

Out of scope, not debt: the freeze itself (WELD_PHYSICS_PROTOCOL_VERSION, the thirty surface guards), syncIn and the authority model, the Tier 1 physics service and the Etch wrappers, getTriggerOverlaps, the Forge → Tier 0 bus → EventStore bridge — all M1.1.15.2; ModuleContext.frame_allocator; M1.D.12; wiring the adapter into a running engine.

Planned tag: v0.11.16-tier0-pregate. Merge and tag are Guy's.

C1.1 names `bench/physics_forge_3d_integration.zig` as where the frame column
is measured and it did not exist; two files cited it in the present tense. The
raycast and shapecast benches reach 10 000 bodies but interrogate a static
scene — they never tick — so C1.1's figures were neither met nor refuted.

Two targets gated. 1 000 dynamic + 10 000 static at 60 Hz, on 1 000 awake
dynamic bodies of 11 000, P = 8 809, 240 frames from frame 31: ReleaseFast
median 2.001 ms, ReleaseSafe median 2.436 ms against 16.6 ms, and zero
allocation attempts in steady state in both.

Steady state is defined on the scene, not on the allocator: the first frame
after which pairs and constraints hold for thirty frames. Defining it as "after
allocation stops" would make the zero-alloc result unable to fail.

Two defects in the instrument, found by reading its numbers after it answered
PASS. The awake count included statics, so its guard could not fall below
10 000 and could never fire. The retention experiment grew N and P together, so
it discriminated nothing; a far static field now holds P fixed at a measured
2 209 while N moves x3.72, and Theta(P*N) is refuted by ~470x.

Ungated finding: an asleep scene allocates 5 280 times in steady state where an
awake one allocates zero. Mechanism named at contact_constraint.zig:578 and
already owned; this is its first measurement.
The brief says "frame time <= 16.6 ms" and names no statistic. Gate E
settled that on the median — the permissive reading — and then attributed
the choice to Guy, who had framed nothing. A 60 Hz budget is a real-time
constraint: one frame in a hundred at 20 ms is a visible hitch, and a
median never sees it.

Nearest rank, stated in the code rather than left to a library convention:
ceil(0.99 * 240) - 1 = 237, the third-worst frame of the window. Median and
max stay in the report so the tail stays readable.

Still passes: worst p99 observed over five runs per mode is 3.576 ms
(ReleaseFast) and 5.467 ms (ReleaseSafe) against 16.6 ms.

The counter-factual is the one that discriminates. Lowering the budget only
proves a comparison works, and twice it did not even fail because the p99
landed under the threshold by machine noise. Three 20 ms hitches injected
into 240 frames at the UNCHANGED budget give p99 20000000 ns against a
median of 2050000 that clears it by 8x — a median gate would have passed a
run containing three visible hitches.

Reported because it argues both ways: over five runs on identical code the
median moves 6%, the p99 up to 2.4x, the max up to 3.5x, with a
bit-identical checksum throughout. The tail is machine noise, so this gate
buys sensitivity and costs stability; the margin is claimed on the worst
observation.
The corpus renamed M1.1.26 -> M1.1.15.2 (the freeze) and M1.1.25 ->
M1.1.21.1 (per-island parallel resolution); the repository had not
followed.

Re-swept on the current tree with grep -o — occurrences, never lines: 92,
of which 14 are in this milestone's own brief, which describes the rename
and did not exist at the frozen sweep. 92 - 14 = 78, the frozen figure.

24 code, test, tooling, build and CI sites patched here, per-file counts
reproducing the frozen table row for row. Zero survive in code. 37 stay
untouched by design: 29 + 7 in two closed briefs and the v0.11.15
orchestration tag row. A journal is not retro-patched.

Matched on CONTENT, not on line number, and that mattered: the brief
located a test name at transform_sync_test.zig:775 and the lines had
shifted with the tests gates C, D and F-D1 added — it is at 844.

The .why string of no_precision_crossing.zig is diagnostic output, so the
brief asked whether a test asserts its literal. Measured: none does. The
phrase occurs twice, both inside the rule file. No companion patch was due.

PhysicsModule.zig also gains the 27 -> 30 count correction: the assert
block guards thirty entries, of which twenty-seven exclude init, deinit and
step, and a guard built on twenty-seven would pass an implementation
missing any of the three. And the paragraph claiming ModuleContext "does
not exist in this repository" is deleted rather than softened — exact when
written, obsoleted by this milestone's own gate A.
Gate F execution log with the interaction pass reported by what it crossed:
the moved log walked against a concrete slot-recycling sequence rather than
against its doc comment; the proxy's three holders measured at 3
authoritative writes against 3 derivations and 2 removals against 2
unbindings; the allocator found in exactly one field, PhysicsWorld holding
zero of its nineteen and the adapter's 28 entries taking none.

RD-5 records the p99 ruling and its STOP condition, not met. RD-6 records
that C1.1's zero-allocation property is gated in a configuration a shipped
game does not run, with the number that makes the criterion patch writable.

CLAUDE.md §3.4: current state, one Tags row, and the open-decision delta —
M1.D.13 CLOSED by measurement, the two freeze preconditions DECIDED and
reduced from narrative to pointers, M1.D.12 untouched, and the three
M1.1.8 leftovers re-pointed because their named owner closed without doing
the work.

The propagation's CLAUDE.md half does not reconcile with the frozen figure:
the five rows carry 13 token occurrences, not 17, the remaining four being
statements false without either token. Reported rather than reconciled
away.

Method lesson recorded: nine findings were defects in an instrument or a
contract rather than in the engine, and the three sharpest arrived under a
green PASS in a bench just written. A guard must be shown able to fail ON
THE PROPERTY IT CLAIMS, not merely to fail.
@guysenpai
guysenpai marked this pull request as ready for review August 27, 2026 09:35
@guysenpai
guysenpai marked this pull request as draft August 27, 2026 11:34
THIS COMMIT IS RED ON PURPOSE and the next one turns it green. A test
written after a fix does not prove it would have caught the defect, so the
three pinning tests land first with their redness on the record: expected 1
found 2 (one entity, two bodies, two answers), expected 2 found 1, expected
400 found 256.

The middle one earns its own line. Under the deduplication defect the COUNT
is right — four slots, four entries — and the SET is wrong, so a test
asserting only the count passes. It asserts the set.

Cause, measured by reading the file rather than grepping it: the adapter's
tests attested that its 28 entries EXIST and never what they ANSWER. Nine
were behaviour-asserted, eight were called with their answer never
asserted, and eleven were never called at all. So the two review findings
are the first two of nineteen unguarded entries, and the class is swept
rather than the instances patched.

Four further tests take the rest of the surface to behaviour: the read-back
mutators, the four single-result query entries (raycast at 9.5 m against
shapeCast at 9.0 m on the same geometry, which is what distinguishes a real
cast from a raycast wearing its name), and the character entries. All four
pass on their first run, so the family is one of missing guards and not of
missing correctness.

Floor re-derived FROM THE SUITE: 1949 -> 1956 (1937 passed + 19 skipped).
F1. engine-physics-queries.md §1.11.14 puts deduplication at the tier that
PROJECTS BODIES ONTO ENTITIES and makes it mandatory there. The frozen
signatures of overlapShape, overlapAabb and pointQuery return []EntityId,
so this IS that tier; the old comment deferred the obligation to the Tier 1
service, which sits ABOVE the interface and receives entities already
projected, so nothing would ever have deduplicated.

raycastAll is deliberately NOT in that class, and the distinction is the
body identity: a RaycastHit carries body alongside entity plus its own
position, normal and distance, so nothing is projected away and collapsing
two hits would destroy information the caller was handed.

Adjacent deduplication is exact rather than approximate, and that is a
property of the solver's key: OverlapCollector.finish sorts on keyLess,
entity-major with BodyId only as the final tie-break, so every body of one
entity forms one contiguous run. Stated as a debug assertion at the site
that relies on it.

The second-order half is the real defect. Deduplicating AFTER the
truncation under-fills the slice and evicts unique entities entitled to it:
one entity holding three bodies eats three of four slots and the answer
names two entities where four exist. Retention therefore runs on the
deduplicated ENTITY set, through a loop that doubles the staging and
re-queries, exiting the moment the slice is full or the solver returns
fewer than it was offered.

F2. The staging constant survives as stack_hits, a FLOOR below which no
query allocates, never a ceiling: above it the adapter grows a reusable
buffer from the allocator it already holds. No frozen signature moved --
the declared-cap-with-a-channel alternative does, and belongs to M1.1.15.2.

One residual, written on the function: two entries are frozen as bare u32,
so an allocation failure degrades to a correct prefix instead of reporting.
That cannot fire on a healthy allocator, where the 256 fired on every call.
Status back to ACTIVE, PR back to draft, both reverted from a closure that
should not have been taken. RD-7 records the reopening with its cause: two
wrong behaviours reached a CLOSED brief because the adapter's tests
attested that its entries exist and never what they answer.

The class sweep is the reportable result and it is in the execution log: 9
behaviour-asserted entries against 19 that were not, so the two findings
are the first two of nineteen and the class was swept rather than the
instances patched. All four sweep tests passed on their first run, which
makes the family one of missing guards and not of missing correctness.

RD-8 records that two of the review's own figures were unit errors -- "17
CLAUDE.md sites" is 13 token occurrences plus four statements false without
a token, and "37 sites" mixes occurrences with rows. Reported, not
reconciled away.

A fifth instrument defect is logged with the rest: a cap probe with a 500:1
box answered 265 of 400, diagnosed by changing only the probe's aspect
ratio -- 500:1 gives 265, 1:1 gives 400 -- the documented GJK limit for
radius-0 box cores and not the staging under test.

Floor 1949 -> 1956. Closing notes and the tag row updated to match.
Status CLOSED, and the reopening stays visible in the header rather than
being smoothed out: it happened, and a brief that hid it would be the same
class of defect the milestone spent itself on.

Closing notes gain the finding the reopening actually produced, which is
neither F1 nor F2 but the nineteen. The review named two instances; the
sweep produced the number -- 9 behaviour-asserted, 8 called with their
answer never asserted, 11 never called at all.

And the classification is what makes that number usable in one direction
rather than the other: the four single-result query entries and the
mutators passed on their first run, so seventeen entries were correct and
unguarded while two were wrong. A family of missing guards, not of missing
correctness. Without the sweep neither reading could be told from the
other, and two instances would have been fixed in the belief that something
had been closed.
@guysenpai
guysenpai marked this pull request as ready for review August 27, 2026 14:58
@guysenpai
guysenpai marked this pull request as draft August 27, 2026 16:08
G2. "28 entries, 28 called, zero remaining" counted CALL SITES. The
predicate that matters is whether an entry's oracle tells it apart from a
plausible NEIGHBOURING entry, and three entries passed the weak one while
failing the real one.

moveKinematic asserted only the pose reached -- and setBodyTransform
reaches the same pose, so a teleport passed a test listed as covering the
entry whose whole contract is that it DERIVES velocities. The overshoot
oracle drafted to replace it discriminated nothing either: measured, both
forms sit at 4.0000 after one step and are still at 4.0000 after two. The
frozen surface has no velocity getter but has exactly one place where a
kinematic body's velocity surfaces -- moveCharacter's ground_velocity. The
oracle reads 3 m/s against 0 for a teleported twin driven in the same test.

addForce is discriminated from addImpulse by the travel ratio. The first
version predicted 1/dt = 60 and measured 95.99, which is exactly 1.6/dt
under four TGS Soft substeps; asserted as a BAND, because pinning 96 would
pin the solver's cadence in an adapter test.

destroyShape is discriminated from a no-op by error.InvalidShape.

Re-counting the class with the right predicate found three more: init (a
zero-gravity world passed everything, all static or gravity_factor = 0),
setLinearVelocity (indistinguishable from addImpulse at unit mass until
made to follow one), resizeCharacter (its true asserted, its effect never).
And pointQuery answered like a degenerate overlapAabb until a sphere
separated them.

28 of 28 now discriminate, with one reservation named not closed:
setAngularVelocity asserts the orientation changed, not which axis.

Six counter-factuals fire. A seventh reported exit=0 and was refused: its
mutation string named a parameter `v` where the source says `velocity`, so
nothing was mutated. The guard is now in the probe -- assert the mutation is
present before trusting its verdict.

Floor re-derived FROM THE SUITE: 1956 -> 1961 (1942 passed + 19 skipped).
G1. The staging's doc comment said "two of the three callers are frozen as
bare u32". Measured: FOUR callers, THREE bare. raycastAll, overlapAabb and
pointQuery have nowhere to put an allocation failure; overlapShape is
frozen anyerror!u32 and CAN report.

So the arbitration -- panic or degrade, no third way -- was true of three
entries and FALSE of the fourth, and `resize(...) catch return stack`
silently swallowed an OutOfMemory on the one entry whose frozen signature
declares it transmissible. An arbitration is worth what the enumeration of
its scope is worth, and this one's was wrong on both numbers.

stageBodiesFallible propagates, stageBodies absorbs, and collectEntities
routes between them on a reports_allocation_failure declared ON EACH FILLER,
at the call site, beside the signature it mirrors. Per site on purpose: a
single enumeration written in one place is exactly what was wrong, and a
const next to its own entry cannot drift from it.

No frozen signature moved. Whether three signatures on the frozen surface
SHOULD be unable to report an allocation failure is a contract decision for
M1.1.15.2, recorded rather than settled here.
RD-9 records it, and states the cause the two reopenings share rather than
treating them as two events: a conclusion is worth what the enumeration of
its scope is worth. Three times, on three different objects, a green count
was produced by a predicate weaker than the claim it supported -- 28
entries counted as EXISTING when the question was what they answer, four
staging callers counted as three, and 28 entries counted as CALLED when the
question was whether their oracles discriminate.

RD-10 records the decision this surfaces and does not take: three frozen
entries cannot report an allocation failure. That is a contract decision for
M1.1.15.2, before its assert block rather than during it.

Closing notes and the tag row updated. Floor 1956 -> 1961. Status stays
ACTIVE; the brief closes on a verdict, not on my own say-so.
H1, and the defect was inside F1's own fix. dedupEntities deduplicates by
ADJACENCY, correct only under an entity-major order, and the whole premise
was held by std.debug.assert -- which ReleaseFast compiles to nothing. Live
in the two matrix cells where a breach costs nothing, ABSENT in the mode the
C1.1 bench runs and a game ships, where it silently reproduces the defect F1
had just closed: an entity returned twice, damage applied twice.

And the premise is not this file's to keep. Entity-major order belongs to
query/overlap.zig's collector and can stop being true through a change in
its owner with nothing here moving.

Fixed on the repository's own precedent: query/root.zig:380 already replaces
a release-stripped class assert with an active probeAdmissible check, for
this reason and in these words. The comparison is active in every mode, and
on detection the function stops trusting adjacency and scans what it has
written -- exact, because everything written before the break was
deduplicated over an ordered run. The answer is never wrong even under a
violated premise: no truncation, no panic, no error channel. The violation
is COUNTED, because two of three callers are frozen bare u32 and a counter
is what makes "detected" true rather than a word.

Cost stated structurally: one integer comparison per projected body inside a
loop that already performs one. The C1.1 bench cannot establish it -- it
drives PhysicsWorld and never touches the adapter -- and saying so beats
replaying it and presenting an unmoved number as evidence.

Counter-factual decisive both ways: the old form gives expected 2, found 3
in ReleaseFast and PANICS in Debug. Loud where it costs nothing, silent
where it costs everything. The pinning test is green in Debug, ReleaseSafe
and ReleaseFast, and an ordered run must leave the counter at zero.

Floor re-derived FROM THE SUITE: 1961 -> 1962.
RD-11 records H1 and why it was handled in the same push as G1/G2: the
correction touches dedupEntities, which they touch already, and three passes
over one file cost three matrices where one costs one.

The sweep states its criterion, because the boundary depends on it. Read
literally, "an assert guarding another module's contract" sweeps in almost
every precondition, since callers usually live elsewhere. The discriminating
question is whether a breach yields a SILENTLY WRONG ANSWER rather than a
caller-auditable violation or a loud failure in the modes that run.

132 production asserts in src/modules/forge/. 15 sit in a comptime block and
fire in every mode. Of the 117 runtime ones: 43 are domain preconditions on
a caller-supplied parameter, 65 are local bounds or invariants of a
structure the file owns, and 9 assert the class of a shape fetched from the
store. The 9 are not in the class -- the category is chosen upstream by an
exhaustive switch whose net M1.1.11.1 audited, and the one caller-supplied
handle path already carries an active probeAdmissible check.

One neighbour ruled out with its reason rather than by silence:
determinism.zig:56 is stripped identically, but its arbitration is written
on the function and its instrument runs on exactly the two modes where the
assert is live.

The H1 class had exactly one member.

An eighth instrument defect is logged with the rest: the first H1
counter-factual did not compile, so it measured nothing while reporting
exit=1 -- which reads exactly like one that fired. The guard grew: a
counter-factual must be shown to have RUN, not merely to have been applied.

Floor 1961 -> 1962. Status stays ACTIVE.
H1's gap, closed in the milestone that found it. std.debug.assert is
compiled to nothing in ReleaseFast, and the matrix carried {Debug,
ReleaseSafe} only -- so every assert in the tree was verified in exactly the
two modes where its breach costs nothing and in neither mode a game ships.
That gap is where H1 was born and it cost two review rounds.

ONE cell, ubuntu-24.04 / ReleaseFast / f32, 12 -> 13. Deliberately not an
axis: a release-stripped assert is MODE-dependent and neither platform- nor
precision-dependent, so -Doptimize alone decides whether the assert exists.
One cell detects the whole class; completing the axis would cost 50% of the
matrix for the same detection. The reason is written in ci.yml AT the cell,
with an explicit instruction not to complete it by symmetry -- a future
platform- or precision-dependent finding is a different class and owes its
own reason.

ReleaseFast joins ReleaseSafe on the 55-minute budget, both being optimising
builds. Sizing the new cell to Debug's 20 would make it fail on compile time
rather than on the class it exists to detect, which is the worst kind of red.

The cell was measured GREEN locally before being added, so its addition
carries no discovery risk -- only the standing detection it did not have.

Brief CLOSED. The two reopenings stay visible in the header: they happened,
and a brief that hid them would be the same class of defect the milestone
spent itself on.
@guysenpai
guysenpai marked this pull request as ready for review August 27, 2026 17:51
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