6 Commits

Author SHA1 Message Date
28f20eb146 Merge: the ownership repeal 2026-09-18 08:11:19 +07:00
534907d204 Merge: the registry answers honestly under churn 2026-09-18 07:50:48 +07:00
2b9f271cc3 The repeal is written down where the rules were: spec, BUILT, NEXT, the ledger, FIX 2026-09-18 07:46:37 +07:00
5caf455e66 A compaction that can reclaim nothing does not run, and a listing nobody could read says so
The registry compacted whenever the table was three quarters full, and a
compaction reclaims dead entries and nothing else. A program holding more than
three quarters of the table in live blocks therefore compacted on every
allocation for the rest of its life, reclaiming nothing each time and holding
the table-wide epoch odd while it did. A listing racing that loop lost all
eight of its attempts and answered with zero rows -- "nothing is held", about a
program holding three thousand blocks, from the verb that exists to find a
leak. Measured at 199 wrong answers in 200.

The trigger now also asks whether there is an eighth of a table's worth of dead
to reclaim, which is a count four places maintain: a death, an arena's
free-all, a note written over a dead slot, and the sweep itself. That bounds
the cost from the other side too, since a sweep that runs reclaims at least 512
slots and so cannot run twice in 512 allocations.

Separately, flan_dev_reg_by_type answered a walk it could not take with zero
rows, which is the same number a program that had freed everything gets, and
stepped past slots flan_reg_snap could not copy while still calling the walk
whole. It now counts those slots and returns -1 with the count, the agent
refuses in a sentence the daemon already renders, and the snap contract says
which caller keeps it and why reg_at is allowed not to.

A note that finds no slot is still dropped -- dying because a diagnostic ran out
of room would be the diagnostic shooting the patient -- and now says so on
stderr once, quoting how many entries were dead rather than claiming the table
is all live.

test/dev_limits.c gains three modes, driven from test_reload: 3100 live blocks
read under a writer thread (1 right in 200 before, 200 after), 3000 live with
600 churned on top of them to prove the sweep still runs, and a genuinely full
table that must say so exactly once.
2026-09-18 07:36:45 +07:00
9585d8c2fe An enum member is checked against the i32 it will be, before anything reasons about it
The members of a defenum are i32 at run time, but the reader hands the parser
an int64, so a value too large for the type arrived looking ordinary: truncated
by the x86 backend, malformed in the LLVM IR, and -- the reason this is a
correctness hole and not a nicety -- invisible to the duplicate-value rule
sitting right below it. That rule compares int64s, so (defenum E [A 0
B 4294967296]) passed it: the two differ as int64 and are both 0 as i32, and
the one check written to catch two names for one number waved through exactly
the case it exists for.

Each value is now checked where it is resolved, which is before the collision
scan runs, so the scan compares the numbers the program will actually have. A
value that does not fit is refused rather than quietly made to fit, naming the
member, its enum, and the value, with a different sentence for a value that was
written and one autoincrement walked into -- nothing in the source wrote
2147483648, so the refusal has to say where it came from before it can say it
is wrong.

The check is bound with a let rather than inlined into the cons, and that is
load-bearing: OCaml leaves :: operand order unspecified and takes the tail
first, so an inlined check would run after the recursive Int64.add and let
(defenum E [A 9223372036854775807 B]) wrap to min_int and refuse B for a number
in no one's source. Bound first, A is refused and the wrap is unreachable.

The parser is the only place this needs to happen: Parse.decl is the sole
constructor of Ast.Defenum's member values, and Load only re-qualifies the
enum's name.

Explicit-duplicate aliasing is untouched; that rule is deliberate.
2026-09-18 07:31:00 +07:00
ce3e879e83 The hunt's ledger: five dispatched, the rest recorded 2026-09-18 07:08:49 +07:00