24061586683b5c33347fee06973635ab3ab7c888
42
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
89d886b7f7 |
CLAUDE.md: correct four stale claims, add reshuffle pointer; record as FABRIC-3.5 §XLIV
Authorized by Captain Bob. Each claim re-verified against source immediately before editing rather than from this session's notes. Theory files: 23 becomes 52, all listed in proof/ROOT, with a pointer to COVERAGE.md's own statement that the deliverable is the verified boundary rather than a green build. LITHOS_VERSION: 2.0.1 becomes 2.0.0, noting §I.2 rolled it back because 2.0.1 names the SER5 hardware-track line and claims progress not yet verified, and that the policy is semantic rather than sequential. ACL pinning carried two mutually inconsistent rules, neither matching the code: policy never in C with no vm_find_word plus field assignment, and separately that kernel-only words should be pinned in a kernel-specific capsule. kernel_main.c:771-782 pins BIRTH and CAPSULE-BIRTH exactly the forbidden way, deliberately, and ACL.4th's block-4005 comment explains why -- so ACL.4th stays host-portable. Now stated as the rule plus its one sanctioned exception. The mkcapsule block rule was described as a 1024-byte budget verified with wc -c. Reading tools/mkcapsule.c shows validate_forth_blocks enforces 64 chars by 16 lines and a block number in [2048,5120). 64 times 16 is 1024, which is where the figure came from, but the enforcement is per-line: eight lines of 128 chars is 1024 bytes and still fails. Note that FABRIC-3 §XXXII.2's own correction of this claim was itself incomplete, fixing the number while missing the line-length rule. Adds a WORK IN PROGRESS pointer directing a fresh session to FABRIC-3.6.md's START HERE, since CLAUDE.md is what auto-loads. It states no reshuffle code exists and that the file's current Tripod descriptions stay correct until the reshuffle lands, deliberately not pre-writing the post-reshuffle state. FABRIC-3.6.md: trap 5 rewritten, since it told a fresh session to distrust four claims that are now fixed; it now names MANIFEST.md and FABRIC-0 §25.7 as the documents that still drift. Also removes a quoted commit id from the handoff that will always be stale. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
6233dcaef5 |
FABRIC-3.6.md: correct the handoff for execution on a real toolchain
Captain Bob confirmed execution happens on his PC with the toolchain installed, not in a container. Two lines of the handoff would have misdirected the session they exist for. Task 0.0 said it must be run by Captain Bob on a machine with the real toolchain. On the intended machine the session can run it itself, and the old wording would have had it wait for a human who was expecting it to proceed. Now it says to run it, after verifying the toolchain is actually present, and to stop and say so rather than improvise a partial test if anything is missing. Adds a note that the unchecked state is not-yet-attempted rather than a prior failure, since a fresh reader could reasonably assume the latter. The working-directory warning was written around this container's own layout and named a path that will not exist on the target machine. Replaced with the check that actually matters -- git remote -v must show the Gitea repo -- keeping the container case as a parenthetical rather than the headline. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
ca5443cb1a |
FABRIC-3.6.md: correct the handoff -- GitHub is not part of this project
The GitHub reference came from this session's own harness, not from LithosAnanke: the session was started in /home/user/StarForth, a separate empty repo wired to github.com/rajames440/StarForth, and the task instructions named that as the build target. The mirror claim came from another GitHub repo's own description, which is itself stale -- per Captain Bob, GitHub has been removed from everything and is not a mirror. Both statements are wrong and were about to mislead exactly the audience the handoff exists for, so they are replaced rather than softened. The underlying hazard is real and kept in accurate form: a session launched the same way will land in a directory that is not this project and be told to build there. The note now says that plainly -- nothing outside Gitea is this project, and a directory that is not a clone of admin/LithosAnanake is the wrong place. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
eb6cad2330 |
FABRIC-3.6.md: add START HERE session handoff
Written so a cold session told "go build it" can begin without re-deriving anything. Records where the code actually is -- the Gitea instance, not the empty GitHub StarForth repo that cost this session time at the outset, and not the read-only mirror -- plus the branch, its head, and that no code has been written yet. States the two-document split and the rule that 3.5 is authoritative and a task proving a ruling wrong is a finding to record rather than a divergence to make quietly. Carries the five traps this project's own history proves are real, since a fresh session would otherwise walk into each: silent failure is the dominant mode and a green boot is weak evidence; grep cannot establish capsule reachability, having put six live capsules at zero references; fleet_conserved cannot see Stadium heat, so a leaking allocator leaves it reporting fine; dict_hash changing is expected while diverging is the stop condition; and CLAUDE.md carries four known-stale claims to trust the code over. Names the three blocked decisions and the standing prohibitions -- no branches, no stashing, no fixing in passing, no bundling, nothing without authorization. No credentials committed; the handoff names the host and repo only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
2032974f3a |
FABRIC-3.6.md: add pre-flight -- three-ISA baseline as task 0.0, and why it gates
Records the branch state execution starts from: head
|
||
|
|
3a4e5cff07 |
FABRIC-3.5.md §XLIII: B3 settled -- the target drains its own queue at its own checkpoint
The last genuine design question in the reshuffle, and once again the mechanism already exists, built for the structurally identical problem and corrected twice in the field. Delivery must execute the payload inside the target, but §XXXII retired the pump so kernel-Hermes may not VM-EXEC into anyone. The payload must wait somewhere the target consumes under its own power, at a moment when doing so is safe -- and safe is the hard part, since interpreting mid-word, mid-unwind or nested inside someone else's dispatch is the reentrancy class this codebase has been bitten by repeatedly. vm_core.c already has all of it: sk_vm_at_outermost_interpret() as the predicate, a per-word checkpoint in execute_colon_word() gated on it, a defer-don't-lose discipline for the nested case whose own comment explains that a nested word does not own the stack it is running on, and placement before the error and unwind checks so it only acts when the VM is in a clean resumable state. That is the exact predicate, placement and deferral semantics delivery needs, because the switcher had to answer the same question. Ruling: kernel-Hermes enqueues and publishes the fact, dispatching nothing; the target drains its own queue in its own context at its own outermost checkpoint. One published fact, two independent consumers -- the switcher for eligibility, the VM itself for drain -- and neither dispatches into anyone. Notes this is §XX's proven pattern generalized: the pump's defect was never draining but draining from outside, and Hera was special-cased into safety. Retire the pump and every VM does what she already does, so the special case disappears by becoming universal. Also notes recursive drain is prevented for free, since interpreting increments the same depth counter that defines the boundary. Names three constraints rather than leaving them to be discovered: INPUT_BUFFER_SIZE is 1025 so a payload above 1024 bytes cannot be interpreted in one drain, starvation is real but is the switcher's existing risk rather than a new one, and draining one message per checkpoint rather than the whole queue keeps the work bounded. FABRIC-3.6.md: B3 cleared, B4 added for the payload bound. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
dd255eac58 |
FABRIC-3.6.md: open the execution log; FABRIC-3.5.md §XLII records the split
Agreed to move the punchlist to its own document, on the series' own rule rather than preference. FABRIC-1 closed at 4,420 lines because "the still-open work [was] hard to find" among hundreds of resolved ones; FABRIC-3.5 stands at 4,452 with 40+ open items in the same shape. Annotating 25 tasks there, commit by commit, would bury the design record it exists to be. The split is strict and stated firmly, because §XXXI found this series' documents losing track of each other. 3.5 holds the design record and stays authoritative on conflict; 3.6 holds the work. Rulings are cited in 3.6, never restated, since duplication is how two documents begin to disagree -- and a task that proves a ruling wrong is recorded as a finding there and amended here, never silently diverged. 3.6 restores the checkbox convention. §XXXI.2 found the carry-forward discipline was mechanically auditable through FABRIC-2 and broke at FABRIC-3, which has no checkboxes, after which "is anything still open" stopped being a grep and became a reading exercise -- which is how six design items went quiet without anyone deciding to drop them. The next document in the series does not repeat the defect the gap analysis found in it. §XLI stays in 3.5 as the source 3.6 instantiates: the phase structure, why Phase 2 sits early, and the three Phase 3 blockers with their justification. What moved is the checklist, not the argument. 3.6 also carries an explicit out-of-scope section so deliberately excluded work is not absorbed by an executing session. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
91108c23c9 |
FABRIC-3.5.md §XLI: the build punchlist -- phases 0-2 buildable, phase 3 blocked
Answers the question asked: yes for the first three phases, no for the fourth, and the reason is three named things rather than general caution. Phase 0 is preparation with no behaviour change -- Category A reachability established per §XXII.2's three routes rather than by grep, the strips themselves, MANIFEST corrected as its files go, freed blocks returned, stadium_conserved() added, and the framebuffer registration audited. Phase 1 is Hestia with messaging untouched, sequenced per §XXXIV.4 so Hermes is retained and is_fleet_foundation holds four names. Phase 2 is the allocator and its audit, inert, ending in the Stage B proof that §XXXIX.4 corrected: the ledger plus stadium_conserved(), with fleet_conserved explicitly not evidence. Twenty-five tasks across those three phases, each with its own check, which also discharges item 34. Phase 2 is deliberately reachable early, since §XXXIII named it the only genuinely hard part and it should fail cheaply with nothing built on top. Phase 3 is not buildable pending item 27 (channels: negotiation or one membership), item 32 (SK_SWITCH_MAX_SLOTS is 16 and §XXXII made the switcher the sole mover, so whether this is a constant bump or a table redesign changes the phase's shape), and §XXXII.5.1, the delivery hand-off, which is the last genuine design question in the reshuffle and sits on the critical path. Records a caution: phases 0-2 can run without answering those, which is a feature, but it means arriving at a working audited allocator with the cutover still undesigned. Better to settle the hand-off before phase 2 finishes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
91173854cb |
FABRIC-3.5.md §XL: item 40 settled -- preserve the consumption model, ledger the sink
New evidence found while settling this reverses §XXXVIII's framing. messaging.4th block 5025, immediately above MSG-REAP, states outright that K reap only fires at heat=0 so the freed contribution is 0, and anticipates that a force-reap would require explicit K redistribution. The zero-return at natural reap is a documented design note, not an oversight: heat is modelled as consumed over a message's life rather than held as a refundable deposit. So §XXXVIII's trace stands exactly -- decay drains the field, reap returns nothing, the eviction guard is bypassed -- but its interpretation does not. The word leak is withdrawn, along with its recommendation to change the economics as part of this reshuffle. Two further roles for message heat turned up and both corroborate the model: MSG-NACK-LAST halves it, so a rejected message ages twice as fast, a penalty in the same currency; and delivery order does not consult it at all, so changing it cannot perturb sequencing. Ruling: kernel-Hermes preserves the economy exactly and additionally records what it consumes, making the Stadium invariant read patron heat plus reservoir plus consumed equals Q48_ONE. That is what makes item 41's stadium_conserved() possible at all -- without a consumed term a checker over a designed sink reports non-conservation as normal operation, which forces a tolerance that hides real bugs. §XXXVII.3's counter is therefore vindicated rather than deleted, and for a better reason than it was introduced for. Declines to separate reservation from age now, despite it being the better architecture, on scope, measurement comparability, and the fact that this subsystem yielded two new surprises while a third was being settled. Names but does not answer the real question: nothing replenishes a reservoir, so a long-lived VM's send capacity declines monotonically, and batched pumping accelerates it with fleet size. Fourth instance of latent at Tripod scale, visible at fleet scale. Filed as outside this reshuffle. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
3843e1d685 |
FABRIC-3.5.md §XXXIX: item 39 settled -- the accountings are not coupled, and §XXXIV.6 watched the wrong one
Traced both directions. capsule_vm_physics.c has zero references to stadium and does not include its header; it has zero references to reservoir. stadium.c's single vm_physics mention is a comment. vm_physics_fleet_heat_sum() sums execution_heat_q48, whose only writers are initialise, transfer between two VMs, and redistribute on death. Message allocation cannot move it. They are not even the same shape of invariant. StadiumVMQuota.reservoir's own comment states Stadium conservation is per-VM -- resident patron heat plus that VM's reservoir equals Q48_ONE each -- while vm-physics K is fleet-wide across all VMs. Two scopes, two disjoint data sets, sharing only the Q48.16 format, the constant, and the word heat. That shared vocabulary is what made them look like one system. Only one has a checker. vm_physics_conserved() is the sole *_conserved() function in the kernel; the Stadium side has a documented invariant, a human-readable diagnostic print, and MSG-K covering just the messaging slice. So §XXXVIII's leak is invisible to every automated check -- not because checks disagree, but because nothing is looking. Corrects §XXXIV.6 in the dangerous direction: it made fleet_conserved the tripwire for Stage B, but a kernel-Hermes allocator leaking every reservation would leave it reporting a serene 1. That is §XXXV.0's signature exactly, built into the plan, and item 39 existed to catch it before it mattered. Stage B instead verifies kernel-Hermes's own ledger and the Stadium per-VM invariant, and should add the missing stadium_conserved() as its first act. Two earlier rulings need consequent care. §XV.4's K must be qualified, since the heat a dying arbiter holds is Stadium heat rather than the verified fleet K -- substance stands, citation was wrong. And the self-audit is promoted from safety net to sole instrument, which argues for an independent Stadium checker rather than the arbiter policing itself alone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
b4bd2413d5 |
FABRIC-3.5.md §XXXVIII: item 38 settled -- decayed heat does not return, and a reaped message returns nothing
Read the path end to end. Message heat is Stadium cell heat, since MSG-HEAT@/! route through MSG-STADIUM-CELL@ STADIUM-HEAT@/!, so MSG-COOL-ONE decays header->heat in the cell itself. stadium_evict returns whatever remains to the owner's reservoir, and its own comment says why: otherwise every reap leaks heat and the sum drifts below Q48_ONE. But MSG-REAP fires exactly when heat reaches zero, so at eviction time the field is already zero. So the eviction guard that exists to stop reaps leaking is bypassed completely for every aged-out message, and the whole Q.SLOT pulled to send it is destroyed. That is worse than §XXXVII.6 anticipated, which expected partial loss. The root cause is one field carrying two incompatible meanings: an activity metric, which should decay, and a reservation currency, which must not. Decaying a budget token destroys budget. Whether that is intentional is arguable -- pay to send, forfeit if uncollected is a coherent backpressure economy -- but nothing replenishes reservoirs, so the forfeit is permanent against a finite pool. States a precision boundary rather than overclaiming: there are two heat accountings, Stadium and VM-physics, and this leak is in the Stadium one. Whether it is visible to VM-CONSERVED? was not established, so that is filed as its own item to settle before §XXXIV.6's tripwire is relied on. Recommends separating reservation from age as two fields, which costs nothing in greenfield C, removes the leak, keeps reaping working and preserves backpressure in an honest form. Notes the consequence for §XXXVII: separating the fields restores §XXXVI.3's original invariant and deletes the decayed counter §XXXVII.3 had to invent. Both earlier sections were right about the destination and wrong about the obstacle -- it was never decay, it was decay applied to the wrong field. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
cbed0c5f02 |
FABRIC-3.5.md §XXXVII: item 36 settled -- audit epsilon is zero, after correcting §XXXVI's invariant
Checking the numbers first showed §XXXVI.3's proposed invariant cannot hold. MSG-COOL-ONE multiplies a message's heat by Q-DECAY and writes it back, returning the difference to nothing, so heat held diverges from heat pulled with no bug involved -- that is Loop #3's decay working. §XXXVI's ruling that the sinking condition is a failed self-audit stands; its arithmetic is corrected in place. The numbers settle the epsilon on their own. Q48_ONE is 65536, VM_PHYSICS_EPSILON_Q48 is 3277, and Q.SLOT is about 929 today or 1365 once channels are retired. So the existing epsilon is three and a half messages' worth of heat -- loose enough to hide the exact failure the audit exists to catch. It is not wrong, it was sized for fleet heat, which is genuinely noisy; it must not be reused here. Corrected invariant: held equals pulled minus returned minus decayed. All four terms are exact integers, Q.SLOT is a compile-time constant, and decay's delta is computable at the moment it is applied. Nothing is a measurement, so there is no noise to tolerate and epsilon is zero -- any divergence is a bug and the audit fires on the first unit. The one change required is the whole trick: today decay is an invisible overwrite, so kernel-Hermes must record what it destroys. One counter converts an unauditable quantity into an exact one, which is why the epsilon can be zero rather than guessed. Cadence is running counters rather than recomputation, since MSG-TOTAL-HEAT scans the whole arena and as a fleet-wide kernel structure that is §XXII's O(N) wall a third time, after the pump and the switch slot table. The check becomes one comparison of four integers, O(1), on every mutation. A scan stays useful for verifying the counters themselves, in Stage B and diagnostics rather than the hot path. Flags without resolving that if decayed heat is destroyed and eviction returns only what remains, fleet heat drifts downward over a long run -- the same shape F0 §25.7 warned of for a different, since-fixed cause. States the limit of the trace honestly: STADIUM-EVICT's return semantics were not read, so this is reported, not established. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
3a593055de |
FABRIC-3.5.md §XXXVI: item 31 settled -- kernel-Hermes sinks when its own heat accounting fails
§XXXV.1 found §VIII's latch had no trigger, since kernel-Hermes is not a Stadium patron and §VII's ladder cannot reach it. §VIII survives with a trigger that is concrete, cheap and already precedented twice here. Enumerates what can actually go wrong and finds only one state between healthy and gone: corrupted internal state, still executing but unable to route correctly and possibly unaware. kmalloc failure and budget exhaustion are refusals, which is the economy working; a panic is not sinking because it is already gone. Keeps §VIII rather than retiring it, for a concrete reason: the window buys a flush. block_subsystem.c carries dirty RAM blocks a hard halt loses, and §XV.4 already ruled payloads may vanish, so the window's value is that dirty blocks reach the disk. The sinking condition is a failed self-audit: the sum of heat held in live messages must equal total pulled minus total returned. An arbiter that has lost track of the heat it holds is exactly one that will break K for everyone else, and this is the earliest honest moment it can know. Not a new mechanism -- MSG-K already audits the FORTH messaging layer's own heat, and vm_physics_conserved() is the C shape verbatim. Notes the honest adaptation, that MSG-K is per-VM and sums a reservoir kernel-Hermes does not have, so the idea ports rather than the code. Records the resulting property: K is both the thing §XV.4 says must survive a death and the quantity whose violation announces it. States the accepted loss rather than engineering around it. Panics raise nothing and flush nothing, because the corruption that caused the panic may be in the block layer and flushing corrupt data over good data is worse than losing it. The audit narrows the window of silent loss without closing it. Bounds §VII explicitly, since §XXI.3's table reads as universal: rung 2 is a from-scratch BIRTH and BIRTH births VMs, so kernel-Hermes has a two-state life, correct or stopped. The bound was always implicit in authority flowing down the birth graph -- a thing never born has no place on it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
cdf9cb24aa |
FABRIC-3.5.md §XXXV: pre-mortem -- two new design gaps, one hypothesis weakened
Assume failure six months on and work backwards, grounded in this project's own failure record rather than generic risk. Puts the dominant failure mode first, with four independent instances: things here fail without saying anything -- an identical serial log for a switch storm and a healthy idle REPL, a console-name mismatch that quietly never relays, 6 of 9 identities silently not attaching, and FORTH silently dropping a definition that references an undefined word. The principal finding is a design gap rather than a risk. §VIII's sinking latch was conceived when Hermes was a Stadium patron that could degrade. Kernel-Hermes is not admitted -- stadium_admit() runs only on birth -- so it has no heat, no TTL, no eviction and no compudynamic death. Its real failure modes are a panic, which halts instantly and gives the fleet no window at all, or allocation refusal, which is degraded but not dying and would be wrong to latch irreversibly. §VII's ladder does not apply either, since rung 2 is a from-scratch BIRTH and BIRTH births VMs. So the failure story for the one component that cannot emit SOS is undesigned, and retiring §VIII is a legitimate option rather than a tidiness problem. Second finding: SK_SWITCH_MAX_SLOTS is 16, which was reasonable when the switcher was one of two ways a VM got control. §XXXII made it the only one, so 16 becomes a hard ceiling on the fleet the moment that ruling lands, against §XXII's own note that the fleet is headed toward hundreds of VMs. This is the pump story repeating one layer up, findable on paper this time. Records a hypothesis that weakened on inspection rather than pushing it: K verification is vm_physics_conserved() in capsule_vm_physics.c, exposed as VM-CONSERVED?, independent of the DoE, which only reports it. The capability survives a DoE rewrite; only the continuous per-tick record does not, so Stage B needs its own deterministic check loop. Also flags that Hestia's ownership is conventional and therefore checkable -- the framebuffer primitives must be registered to her alone -- and that the Category A strip should precede the DoE rewrite while the campaign that would catch a bad strip still runs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
e67eb207f0 |
FABRIC-3.5.md §XXXIV: the transition state -- two messaging layers without corrupting K
§XXII.1 says Category B is load-bearing until the replacement boots, which implies a window where both messaging layers are live, and nothing said how they behave in it. The hazard is not control but heat. Two allocators draw on the same per-VM Stadium reservoir, and the budget is explicit: Q.SLOT is the reservoir less COMMON-CH's third, split across 32 messages plus 15 channel slots. Conservation itself is not at risk, since K holds as long as each layer honestly pulls and returns; the budget is, because a pool sized for one layer is oversubscribed by two. The failure mode is allocation refusal rather than silent drift, and fleet_conserved makes it visible. Notes that §XXXIII's channel retirement removes 15 of those 47 slots, recovering roughly a third of the per-VM budget precisely when two layers share it. Rules the coexistence: every message type is owned by exactly one layer, and no message crosses. Double-accounting becomes structurally impossible rather than carefully avoided, which is the heat-side analogue of §XXXII's control-side ruling. Reuses §XXVIII's staging discipline rather than inventing one, since it solved the structurally identical problem of standing up a second control-transfer mechanism beside a live one. Five stages: inert structures, prove the allocator against fleet_conserved, cut over one narrow type, cut over the rest, then strip. Stage A feels like wasted work and is what makes every later stage a one-commit revert. Surfaces a coupling nobody had noticed. §XIX.6's obvious reading, swap Hermes for Hestia, would break the middle stages on first boot, because FORTH Hermes must keep routing every type not yet cut over. So is_fleet_foundation temporarily holds four names and both births run, with Hermes removed only at the strip. This sequences §XIX rather than contradicting it. Names the acceptance cost honestly -- at least eight full three-arch cycles -- and states three tripwires that would stop the plan rather than be pushed through. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
71ef7914dd |
FABRIC-3.5.md §XXXIII: size kernel-Hermes -- the rewrite is smaller than advertised
§XIV.1 made kernel-Hermes greenfield, which quietly exited this document's own reorganize-don't-rewrite scope discipline, and nobody counted the result. messaging.4th is 504 lines and 85 words; that number turns out to be misleading in the reassuring direction. Roughly 34 of the 85 are field accessors that vanish as C struct members. 28 are channel machinery -- and the entire CH-NEGOTIATING to CH-OPEN to CH-CLOSING handshake has no caller anywhere in capsules, src or experiments. CH-REQUEST, CH-ACCEPT, CH-CONFIRM, CH-CLOSE and CH-MINT-ID are referenced only by MANIFEST.md, which is documentation. The live channel lifecycle is one static channel created at boot with three members added via CH-ADD-MBR and never negotiated, closed or reaped, with console proxies opting out of channels entirely. Kernel-Hermes needs one broadcast membership list, not a channel subsystem. The three event words die with process.4th, which is EXEC'd nowhere, and take SPAWN-EVENT's unwired placeholder with them. What must survive is narrow: the heat-coupled allocator, about nine protocol words, one membership list, the live elevation path through zuse-eligibility.4th, and the status words that make the subsystem debuggable at all. States the caveat plainly: unexercised is not unwanted, and deleting the channel abstraction is Captain Bob's decision rather than an observation. Notes the evidence here is stronger than §XXII.2's capsule search, since FORTH words are invoked by literal text rather than runtime-assembled names, but that a human can still type CH-REQUEST at a REPL. Also flags MANIFEST.md describing the negotiation as live, another entry for the documentation sweep. Names the one genuinely hard piece and recommends building it first: the heat-coupled allocator, because K is continuously verified and any drift is visible. If K holds across alloc, free and evict under the new arbiter, the rest is protocol plumbing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
7aa9bad243 |
FABRIC-3.5.md §XXXII: item 22 settled -- retire the pump, the switcher is the sole mover of control
§XXXI.5 found FABRIC-3 carrying an open defect where both the MSG-TICK pump and the Stage-3/4 switcher can independently move control between the same VMs, a live instance of what §XV.3 forbids as a principle. Settled, and the reshuffle turns out to close it rather than inherit it. Kernel-Hermes publishes eligibility and does not dispatch. The switcher, which moves control by saving and restoring a per-VM native stack, becomes the sole path; the pump, which moves control by nested vm_interpret on the shared kernel C stack, retires. Three reasons. The pump is already legacy by §XIV.1, existing only to drain per-VM FORTH queues that kernel-Hermes will hold instead, so retiring it is a consequence of a ruling already made rather than a new decision. It is also a known scaling wall: §XXII records it as O(N) per idle beat with no cap, caught live at just 9 VMs on riscv64 where a campaign that finished in 200-340s elsewhere never finished at all, then band-aided with batching that trades per-VM latency for bounded cost, with its own comment naming hundreds of VMs as the endgame. And "not observed failing" carries little weight here by FABRIC-3's own finding -- §XXVIII.1 records that Stage 3 emits nothing per switch by default, so a switch storm and a healthy idle REPL produce an identical serial log, and the corruption it fixed was live in every previously clean boot. Reconciles with §XV.3 rather than amending it: moving control is a mechanism, deciding whose turn it is is a policy. The switcher is the mechanism; the compudynamics remains the policy and is still owned by nobody. The defect was never about deciding but about two physical paths for the same transfer. Also notes this makes §XXIII.4 implementable, since checking the sinking latch "on giving a VM its turn" silently assumed a single place where turns are given. Verifies the dependency: the ruling would strand identity VMs unless the switcher covers them, and §XXX records Stage 4's WIREBIND-scope extension as built and verified live. It holds only because Stage 4 landed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
afcaeebbc7 |
FABRIC-3.5.md §XXXI: gap-analysis sweep of the FABRIC set; document reopened
Reopened by instruction to add the sweep. The design phase stays closed and the prior close header is kept rather than overwritten, per the series' own rule against silently rewriting a prior state. A gap analysis of a series whose central rule is never silently drop a stale claim is an audit of whether it kept that rule. Mostly it did. The carry-forward chain held twice and then terminated. F0 to F1 held; F1 to F2 is independently verifiable, since F2 claims a non-sampled carry-forward of 51 items and grep returns exactly 51 today; F2 to F3 broke, with every long-lived F0 item id returning zero references in FABRIC-3. FABRIC-3 carries no checkboxes at all, which is a legitimate style choice but ends the mechanical audit trail -- after FABRIC-2, "is anything still open" stops being a grep and becomes a reading exercise, which is how the orphaned items went quiet without anyone deciding to drop them. FABRIC-2's close header claims every item was closed or left open pending a physical machine. Eight of its fourteen opens are the hardware boot checklist and the claim holds for those; six are design items with no hardware dependency and appear nowhere since. FABRIC-0's seven opens all remain, and three were re-derived by this document without either side knowing: 4.3's deferred tail is verbatim "Console as a fleet VM under Hera's birth protocol," which is §XVII and §XVIII; 5.2 already specifies the Isabelle target as one conservation theorem, almost certainly the K that §XV.4 rediscovered independently; and 5.3 already asked for §XXVI.1's subsystem-doc work. The urgent finding is that FABRIC-3 holds an open item contradicting §XV.3. The MSG-TICK/Stage-3 dual-ownership rough edge -- both mechanisms can independently move control between the same VMs -- is still open and not observed failing, which is a live instance of exactly the dual ownership §XV.3 forbids as a principle. §XIV.5's scheduler concern was a rediscovery of it, and kernel-Hermes lands directly on that seam by becoming the caller of sk_vm_switch_signal_mark_work(). Filed ahead of the kernel-Hermes work rather than alongside it. Also re-homes §17.4's undesigned framebuffer heat/decay as Hestia's, and records that three reported-not-scheduled registries exist with inconsistent hygiene -- §25.7 leaves two resolved entries unstruck, including a fleet heat leak closed in FABRIC-1 that still reads as live. No ruling in §I-§XXX is invalidated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
3e6b3275ac |
FABRIC-3.5.md: close the design phase (provisional, not archival)
Closed by direct instruction. Every design question this document opened is ruled; no code has been written and none is authorized. Deliberately a narrower close than §XXVI.5 specified, and the difference is stated rather than glossed. §XXVI.5 ruled that this document closes when the tag exists, in FABRIC-2's CLOSED/ARCHIVAL form, naming the tag it closed at. The tag does not exist, so claiming that close would be a label running ahead of the real state -- the exact error §I.2 corrected when it rolled LITHOS_VERSION back, and the same standard §XXIX applied to the LTS question. The archival close still stands and still happens at v2.1.0; this header is the provisional one the instruction's own "for now" asks for. Restates that nothing is carried forward and no successor is created, since this document is not in the FABRIC-0 through -3 chain, and that FABRIC-3 remains open and authoritative for bare metal boot. Names the punch list as the live artifact the build works from, and records the three items that are explicitly outside this reshuffle and still need their own authorization: the CLAUDE.md and MANIFEST documentation reconciliation, the src/*.c.bak hygiene question, and the stray v2.0.1 branch and PR #1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
6751b2629f |
FABRIC-3.5.md §XXX: versioning policy CLOSED
§XXIX's recommendations ratified, written as the text to carry into Makefile.starkernel and ROADMAP.md. Resolves the two places §XXIX left as alternatives rather than leaving them hanging. Conflict 1: X.5.0 semantics retired. The minor field stops carrying a milestone meaning and means only "release within the line." The milestones survive as roadmap entries rather than arithmetic, which has a pleasing consequence that was not contrived -- the hardware bare-metal release that was going to be v2.5.0 is exactly where the first LTS criterion is satisfied, so the milestone formerly encoded in the minor field becomes the natural candidate for the first LTS major. Scheme and roadmap agree without being forced. Conflict 2: resolved in favour of keeping the major for LTS parity, since that is the scheme's point, and relocating the compatibility signal instead of abandoning it. Breaking changes land on the even working line; an odd LTS line takes non-breaking fixes only. The line tells you whether breakage is possible, not the major. Corollary recorded: an LTS line that needs a breaking fix has failed as an LTS, and the fix goes to the working line -- no exceptions, since the exception is the failure mode the rule exists to prevent. Conflict 3: the two version strings are independent and may coincide. CLAUDE.md already says they do not auto-sync and they describe different artifacts, so LITHOS_VERSION reaching 3.0.0 beside an engine already at 3.1.0 is documentation, not renumbering. Engine VERSION closed as a rule rather than a number, because the correct bump is a function of the realised diff and the code is not written -- picking now would be guessing, which is what §I.2's rollback was about. Major for FORTH-79-visible semantics change, minor for words added, removed or relocated, patch for build-only. On the current plan this is a minor bump, to be confirmed against the real diff. Every decision this document required is now made. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
8bba715bf6 |
FABRIC-3.5.md §XXIX: versioning policy closed; LTS deferred with written criteria
Captain Bob proposed odd-major LTS / even-major working, minor for release, patch for working builds, CI build number appended later, and asked directly whether this release is the first fully production-ready one, inviting disagreement. Policy closed here; LTS designation deferred, with criteria written down rather than left to judgement. The disagreement is recorded plainly because it was asked for, and rests on five findings rather than taste. §XIV is open and was reproduced live by §XXXI's rerun -- near-simultaneous thumbdrive attach silently dropped 6 of 9 identities with every device confirmed present at the host level, which is the identity-attach path failing silently. It has never booted on real hardware, which is FABRIC-3's whole topic and what v2.2.0 and v2.5.0 are reserved for. ACL Phase 8 is the open item. At tag time the reshuffle is brand-new code, and LTS normally means soaked rather than freshly rewritten. And §XXV.4 expects formal coverage to contract at this tag, which is the wrong moment to claim maximum stability to a licensee or patent audience. The precedent is the project's own: §I.2 rolled the version back for claiming ahead of the real state, and "first fully production ready" is a much larger claim than 2.0.1 was. Offers the constructive form instead of a refusal -- make LTS a test, the same move §XV.2 and §XXVII already used to better effect than judgement. Five criteria proposed; the first tag meeting them takes the odd major. Flags three conflicts in the new scheme while closing it: the minor position already carries QEMU-versus-hardware semantics with v2.5.0 already planned, odd/even major collides with major-means-breaking, and an odd major lands LITHOS_VERSION on 3.0.0 where the engine string already lives. Recommends SemVer build metadata for CI numbers rather than a fourth dotted field, since the SBOM is syft-generated SPDX and X.Y.Z.N is not valid SemVer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
e0ebd4cb5f |
FABRIC-3.5.md §XXVIII: this release is 2.1.0
LITHOS_VERSION becomes 2.1.0 and the tag cut at close is v2.1.0. Checked against the authoritative policy rather than §I.2's paraphrase of it. Makefile.starkernel carries the roadmap table itself, and it is more specific: X.0.0 is a QEMU release, X.5.0 a hardware bare-metal release, with 2.0.0 QEMU, 2.0.1 the SER5 hardware-track line, 2.2.0 amd64 bare-metal and 2.5.0 the hardware release. 2.1.0 is unallocated, so the ruling takes a real gap rather than overloading a rung, and it lands below both bare-metal milestones -- correct, since this is QEMU-only work and must claim no hardware progress, which was §I.2's whole concern when it rolled the version back. Notes the table must gain a 2.1.0 line or the ladder will step 2.0.1 to 2.2.0 with a released tag sitting in a gap it does not mention. Two live places to edit; FABRIC-2 §G is the origin but is closed/archival, so it is cited rather than amended -- amending a closed document to match a later decision is what this series' discipline forbids. Flags a trap for the documentation sweep with precedent. Makefile.starkernel is not a .md file, and §I.2 records a FABRIC rename that looked complete but silently skipped it along with Kconfig.kernel, a shell script, four proof/*.thy files and an .S source, because the sweep matched four extensions by inclusion. The sweep must grep by exclusion instead, reuse §I.2's ordered placeholder technique, and keep §I.2's own deliberate exclusions -- settings.local.json's command log and ClaudeEXPORT are frozen audit records, and rewriting them would falsify an audit trail rather than fix a citation. Leaves the engine VERSION string explicitly unruled. It is independently tracked, plausibly moves given the registration and messaging changes, but is a separate decision at tag time. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
3013071855 |
FABRIC-3.5.md §XXVII: item 18 settled -- the empty floor is unreachable, build nothing
Tested §XVI.7's premise against the code rather than designing to it, and
the premise is false. An empty Stadium floor requires Hera to be gone,
and every path by which she can cease already terminates the machine.
She cannot starve: she is pinned via session_set_pinned(), and stadium.c
refuses pinned patrons at :453 and skips them at :559. She cannot be
killed: mama_word_kill()'s own doc says Hera cannot be killed, and
capsule_vm_kill_all_nonmama() spares her by construction. BYE reboots.
Scuttle and panic both halt. There is no route to a live kernel over an
empty floor.
So the ruling is to build nothing, and §XVI.7's proposed shape is
withdrawn. An empty-floor halt would be defensive code for a state that
cannot occur, which CLAUDE.md names directly as a thing not to add.
Notes that the pinning result generalises -- no Tripod leg can die a
compudynamic death, since all three are pinned by the same
is_fleet_foundation line, which puts §XV.2's compudynamic death exactly
where it was always aimed: the unpinned population.
Records that sk_hal_panic() already executes while(1){arch_halt();},
character for character the idiom §XXIV.2 specified for the suicide word.
The two converge on one terminal state by different triggers: a scuttle
is a panic Hera chose.
Closes by stating the three invariants the ruling depends on, since a
future change could break them silently -- Hera stays pinned, KILL keeps
refusing her, and involuntary death always ends at a permanent halt. The
first is edited by this very reshuffle when Hermes leaves the
is_fleet_foundation triple and Hestia enters it.
Design phase complete. Every question this document opened is ruled.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP
|
||
|
|
ea1c630eca |
FABRIC-3.5.md §XXVI: the close protocol, and this document's close condition
Captain Bob, 2026-09-19: documentation sweep and SBOM/SPDX before making it master's head and tagging, and that is when FABRIC-3.5.md closes. The tail of the sequence is now fixed and the document has a defined end. Consolidates item 20 into a real checklist rather than a hunt. CLAUDE.md alone accumulated four traced errors during this design pass: 23 theory files against an actual 52, LITHOS_VERSION 2.0.1 against an actual 2.0.0 that FABRIC-3 §I.2 corrected down and CLAUDE.md never followed, the three-way ACL-pinning contradiction, and the stale 1024-byte mkcapsule framing. Plus the Tripod membership itself. MANIFEST corrections ride the strip so the manifest never describes a file that no longer exists, and the superseded subsystem docs need a deliberate update-or-archive call rather than a silent edit. SBOM is a real syft target in the hosted Makefile, so the step is run and commit -- but the committed output is dated 2026-07-24 and its DocumentName says StarForth rather than LithosAnanke, plausibly a monorepo-split artifact. A bill of materials naming the wrong product is read literally by exactly the audiences it exists for. Flags that the version for this work is a real decision and that 2.0.1 is not available for it. Per §I.2 the policy is semantic: 2.0.0 is the QEMU line, 2.0.1 is the SER5 hardware track, and §I.2 rolled the version back precisely because claiming 2.0.1 implies hardware verification that is still FABRIC-3's open topic. This reshuffle is QEMU-only work. Reports two pieces of unexpected remote state without acting on either. refs/heads/v2.0.1 still exists although §I.2 records deleting it and concludes master is the only branch; and refs/pull/1/head exists against this branch although this session opened no pull request and the repo's workflow forbids them unless asked. Records how the close is written: FABRIC-2's dated CLOSED/ARCHIVAL form, naming the tag, creating no successor since this document is not in the carry-forward chain, and leaving FABRIC-3 open and authoritative for its own topic. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
ae18f773ce |
FABRIC-3.5.md §XXV: DoE constraint relaxed; Isabelle/HOL pass closes the sequence
Captain Bob, 2026-09-19. The DoE's invocative paths are slated for rewrite, so doe_log.c's six Tripod-hardcoded columns stop being the expensive consequence §XIII.3 named -- the schema change is absorbed rather than paid, and doe-campaign.4th's five by-name Hermes sites fold into the same rewrite. Notes what this does not relax: §XXII.3's strip-safety rule stands on its own footing, since rewriting how the apparatus is invoked is not discarding the apparatus, and the audit and patent-support roles are unchanged. Experiment capsules stay live-by-default during the strip. A formal re-verification pass runs at the end, giving the sequence a symmetry -- the surgical strip opens it, Isabelle/HOL closes it. Corrects CLAUDE.md while scoping it: it claims proof/ holds 23 theory files, 18 core plus 5 ACL. There are 52, all listed in proof/ROOT, and COVERAGE.md already says 52. Stale by more than a factor of two; added to item 20's documentation reconciliation. Records the standard the pass must meet, which COVERAGE.md already states in Bob's own framing: a clean pass/fail is not the deliverable, the boundary between formally verified and not-for-this-reason is. A suite that still compiles while quietly covering less would satisfy the build and fail the standard. States a cost of this reshuffle not previously named anywhere. COVERAGE.md scopes the suite to words over modelled per-VM state and explicitly flags implementations that reach outside it via file-scope statics. Messaging today is FORTH over per-VM dictionary state, inside the model; kernel-Hermes makes it C with file-scope statics, outside it. So the reshuffle is likely a net reduction in formal coverage of the messaging area -- plausibly the right trade given §III.2's circular-dependency argument, but a real one the pass must name rather than let the boundary move quietly. Partially offset by the one-way latch being close to the easiest thing here to prove. Maps the affected theories, and carries forward the observation that ACL_No_Escalation.thy already proves no-escalation at word level, making §VI.1's central safety claim the same theorem one level up. The reshuffle's most important safety property is already half-proven at a different granularity. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
e0152381ea |
FABRIC-3.5.md §XXIV: item 17 settled -- separate word for Hera's suicide, BYE untouched
Captain Bob, 2026-09-19. mama_word_bye() keeps its current behaviour exactly -- reap children, cold-restart -- which is the right thing for an operator typing BYE at Hera's REPL, the argument §XVI.2 flagged for two words. The larger consequence is that this reshuffle now modifies the behaviour of zero live registered words. §XVI.2 had flagged Hera's BYE as the one place the design proposed changing one; it is now not changed at all. The two words share their first half and differ only in the terminal action: cold reset versus a permanent arch_halt() loop behind disabled interrupts. That idiom is not new either -- it is what amd64's own arch_cold_reset() already uses as its unreachable fallback and what the panic path uses, and arch_halt() exists on all three architectures, so parity holds with no per-arch work. Hera-only registration, since §IX.1's no-handoff rule means no other VM may stop the machine on her behalf. All seven candidate names are unregistered. Recommends SCUTTLE without deciding it -- to scuttle is to deliberately sink the vessel you command, and it separates cleanly from Hermes sinking. Cautions against HALT, since vm->halted already means something different and reusing the stem invites the ambiguity §XIX renamed a Tripod leg to avoid. Records a three-way contradiction found while placing the new word's ACL pin. CLAUDE.md's hard rule forbids policy in C and specifically forbids vm_find_word plus field assignment for pinning in kernel_main.c; CLAUDE.md later says to pin kernel-only words in a kernel-specific capsule; and ACL.4th's own block-4005 comment says they are pinned in kernel_main.c so that file stays host-portable. The live code does the third: kernel_main.c:771-782 is exactly the forbidden construct, deliberate and working. Recommends matching the working code rather than the rule the working code already breaks, and files the reconciliation as item 20 -- reported, not fixed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
d0c4f60194 |
FABRIC-3.5.md §XXIII: the sinking latch settled -- design phase complete
The last open design question. The signal is a plain scalar in kernel-Hermes's own translation unit, written only by Hermes, read by every VM through a registered primitive. That invents nothing: it is the same registration path §XX already established when register_child_vm_ words() hands the eight STADIUM-* primitives to every VM and Hera's two sites mirror them. Reading a scalar needs no queue, channel, routing table or working arbiter, which is precisely the requirement -- the transport is the thing that failed. Names it accurately. "Semaphore" was the original framing but the mechanism is a one-way latch, and the distinction carries correctness. Per §VII.1 a VM attempts its own recovery before announcing anything, so raising the latch means recovery already failed and there is no path back to not-sinking. Single writer, many readers, one irreversible transition, both observable values valid -- which is the discipline heartbeat.c:33-34 already states verbatim and §XXVIII Stage 3 already reused once rather than inventing new locking. This is the third such variable and takes the same route for the same reason. Calling it a semaphore in code would imply counting and blocking semantics it must not acquire. Settles who reads it, which is the part §XXVIII's shared C stack constrains: a VM has no thread and cannot poll. So the check happens at the dispatch point, and the split is the design -- the kernel delivers the fact, the VM runs its own flush-and-BYE in its own context. The kernel publishes, never decides, so §XV.3 and §XIV.5 hold, and each VM running its own shutdown is what §IX.1 already ruled. The window needs no deadline because Hera's halt is physically terminal. Completes §VIII.2's two-mechanism rule with no exceptions list: floor VMs send SOS through routing, the arbiter beneath raises the latch, and which one applies is decided entirely by which side of the routing layer the sender sits on. Every design question this document opened is now ruled. What remains is build sequencing plus two small local decisions, items 17 and 18. No code is authorized. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
3f65a86993 |
FABRIC-3.5.md §XXII: the surgical strip is punch item 1, and it is iterative
Captain Bob, 2026-09-19: strip the anticipated-dead FORTH before coding; the real gaps reveal themselves as we code/test iterate, and further dead FORTH falls out in the same loop. Re-orders the punch list to put the strip first. Draws the ordering distinction that protects it. Category A is dead today independent of this reshuffle and can be stripped immediately. Category B -- hermes/init.4th, most of messaging.4th, the routing table, the slot-3 pairing -- is dead only on arrival of kernel-Hermes and is load-bearing until the replacement boots. "Strip before we code" must not be read as deleting the working messaging layer with nothing behind it. Records the trap this document nearly walked into while building the inventory. A reference count over capsules/ and src/ put the six init-l8-* personality capsules and sdk.4th at zero references. They are not dead -- including experiments/, tools/ and docs/ finds 18-19 hits each. Reachability cannot be established by grep in either direction: it under-reports because capsules are birthed by name from runtime strings, and over-reports because a capsule named for a common word returns prose noise. So no strip list is authoritative, including any this document produces; reachability is per capsule via boot path, tooling invocation, or the baked capsule directory. Names the asymmetry that makes "surgical" the right word. The three-arch boot is the only acceptance test and it exercises the boot path, so a bad Category A strip fails loudly. It does not exercise DoE capsules, so deleting one passes all three architectures cleanly and surfaces months later during a campaign -- and that infrastructure has an evidentiary role, since CLAUDE.md records the logs as committed audit artifacts and the campaign report as patent support material. Proposes treating every experiments-reachable capsule as live by default. Sets the loop: strip Category A in isolated commits, boot three arches before writing anything new, then code, then strip each Category B item in its own commit as it is proven dead. Notes dict_hash moves every time and cross-arch identity is the property that must hold. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
8bdbfd1aad |
FABRIC-3.5.md §XXI: item 9 settled -- SOS travels up the birth graph
Actionability is a property of the relationship, not of the message. To the sender's birther an SOS is actionable: the parent may re-birth, exercising its own birth authority rather than inheriting the child's, so §IX.2 is untouched. To every other VM it is advisory -- a peer may shed its own dependence on the sender but may not act on its behalf. One rule, no exceptions list: an SOS is actionable exactly where the birth graph already grants authority. Pressure-tested against the supervisor risk §XIV.5 warned about, and it survives: message-driven rather than polling (the doctrine's own sanctioned form), optional rather than obligatory, no declarer since the sender reports its own trouble, and no authority transfer. What this actually closes is larger than a message type. §VII.1's ladder had no actor for rung 2, and now each rung has exactly one: the VM itself warm-restarts while alive, the birther re-births on SOS, and nobody acts on compudynamic death. That also shows §IX.1's fleet-shutdown rule is not a special case bolted on for Hera -- she has no birther, so rung 2 has no actor and the ladder falls through to rung 3. The ladder and §IX are the same rule from two ends: rung 2 exists iff you have a birther. Flags a hazard specific to this system. Payloads here are FORTH text executed by the receiver, per messaging.4th block 5041's own comment. An SOS carrying an executable payload would let a failing VM drive its parent, inverting the authority direction at the moment the sender is least trustworthy. SOS payloads are descriptive only -- a deliberate departure from the convention, and the reason the message exists. Number: 10, the next in sequence. Verified 5 and 6 are genuinely unallocated, but monotonic allocation means a number in any log means one thing forever, which matters while legacy constants and the new kernel enum coexist during cleanup. Names the consumer explicitly so this does not become another SPAWN-EVENT, which §I.4 recorded as having none. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
d984b16102 |
FABRIC-3.5.md §XX: item 3 settled -- delete the suffix from the mechanism
§XVIII.5 posed agent binding as widen-the-convention vs. add-a-word. Both accept a premise the code does not support: the pairing is already recorded explicitly at bind time, and the ~user reconstruction is a redundant second derivation of information the mechanism already holds. sk_repl_dispatch_line() does two separable things. The guard builds console_get_vm_name() + "~user" and checks it is live. The actual relay then sends to index 3 -- and repl.c's own comment says that slot is "set once at pairing time," which PAIR-TEST's header confirms from the other side. Routing never uses the derived string; only the liveness guard does, and the stored pairing can answer that question without deriving anything. This is also the documented cause of a known silent failure. CONSOLE-ATTACH's own comment records that a console named anything other than the identity's base name reconstructs the wrong target and quietly falls back to direct interpretation with no error. Its "takes exactly one name" constraint is a workaround for that derivation, not a requirement of the problem. Ruling: the guard reads the recorded pairing, CONSOLE-ATTACH resolves the target as given, and ~user survives as a naming convention rather than a mechanism. Agent binding then stops being a special case -- a GPIO VM binds by the same unchanged path, because nothing appends anything to its name. Punch item 19 is retired rather than fixed: with no string to mismatch there is nothing to make loud. The six memcpy sites split cleanly -- three name a VM at birth and stay, two re-derive a partner for lookup and go. Only the derivation sites change, which is why the convention can survive without the mechanism. Also separates what §V.1 conflated: reachability is kernel-Hermes's, fabric access is vocabulary and ACL, and binding proper is the console path. An agent VM does not routinely bind at all. Scoped per §XIV.1: this states the principle kernel-Hermes must carry forward, not a proposal to patch the legacy FORTH path in place. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
7a9a8ed698 |
FABRIC-3.5.md §XIX: the third Tripod leg is named Hestia
The Tripod is Hera, Artemis, Hestia. 99 occurrences renamed; three verbatim quotations deliberately left saying Console. Records the naming convention, which had never been written down and was being re-litigated for want of it: a Greek deity name, evocative rather than literal. Captain Bob's reasoning, and it generalizes -- Hera and Hermes are close fits, Artemis for block storage and freemap arbitration is a loose one that has never caused anyone a problem. Fidelity was never the standard. antiprosopos was considered first and rejected for being the wrong kind of word: a common noun straining for literal accuracy, which is the opposite of how the other three work. Hestia is a deity, is evocative -- the hearth is the fixed centre where everyone gathers, which is what a bind point is -- and carries an incidental that was not the reason for choosing it: Hestia is the one who never leaves, which is the pinned session model FABRIC-2 §H.1 already describes. It also retires both costs the longer name carried, restoring the pattern fully and cutting twelve characters of unusual spelling to six in a path where a name mismatch fails silently. The rename itself is structural rather than cosmetic. §XVII.1 found three distinct things all called console, and that collision is what led §XIII.5 to the wrong conclusion about whether a singular Console existed. "Hestia owns console.c" is unambiguous in a way "Console owns console.c" cannot be. Deliberately narrow: the HAL stays console.c, the proxies stay console proxies, and CONSOLE-ATTACH keeps its name since CLAUDE.md's rule against modifying a registered tested word applies with more force to renaming one. Keeps the ~user suffix question separate and still open as item 3, with the buffer analysis recorded so the two are not conflated later. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
38735e52c2 |
FABRIC-3.5.md §XVIII: the Console component designed in full
Console is three layers and only the middle one is new: the HAL fabric (~98 KB of C) is unchanged, the per-attach proxies are unchanged, and Console the VM is a capsule rather than a mechanism. The finding that shapes the design is that 1,051 lines of Console vocabulary already exist in the wrong dictionary. fabric.4th's own header calls it "Console drawing-fabric coordinate machinery" and says outright that it is the FORTH-side policy over the C pixel primitives -- and it loads into Hera, along with font.4th, from init.4th block 2049. Moving both to capsules/console/init.4th is a pure relocation and the clearest evidence that the fabric wants an owner: it already has the vocabulary, just attached to the wrong VM. PLOT/FB-WIDTH/FB-HEIGHT registration moves with it; the implementations do not change. Records the invariant that constrains everything else. console.h:220-224 states that console.c must have no dependency on capsule or WIREBIND logic, calling it a real layering violation rather than a style preference. So Console the VM cannot be built by making console.c VM-aware: ownership flows one way, and where the HAL genuinely needs something VM-shaped it takes the shape already established by console_set_user_prefix_provider() -- a registered callback, never an include. Console's ownership is therefore by vocabulary and registration, not enforcement, which is weaker than it sounds and exactly right. Carries the headless-until-login invariant onto this second path: Console is born at boot, a console session is not, and Console's birth must not touch g_wirebind_attached_username or mint a proxy. Same rule §XXXII.2 imposed on unattended birth, cheap to hold and easy to violate with a well-meaning startup line. Notes what Console does not own, since a component owning "the bind point" attracts responsibilities belonging elsewhere, and records that the three Tripod legs have three different failure characters -- Console degrades gracefully because the fabric is HAL C and survives its owner, which is why only Hermes needed the semaphore. One genuinely open design question remains: whether agent-VM binding widens the ~user convention or takes a sibling word. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
887b34d0a7 |
FABRIC-3.5.md §XVII: item 12 CLOSED -- Console already exists as a singleton, it just has no VM face
Closes the largest remaining design item, the one gating §IV. §XIII.5 got this wrong by comparing the wrong object. It measured the Tripod legs against capsule_console_birth()'s per-attach proxies, found Console "plural, ephemeral and capsule-less," and concluded a singular Console did not exist -- so §IV.1 would be inventing one. Traced: there are three distinct things called console here, not two. The HAL drawing fabric (hal/console.c, framebuffer.c, vt100.c, font_8x16.c, ~98 KB of kernel C) is already singular, already permanent, already kernel-resident. It is not a VM and has no owner. So the Console leg is that fabric given a VM face, not a promoted proxy. The proxies stay plural and ephemeral, which is correct -- they are what binding produces, not what Console is. §V.1's bind point then falls out rather than being asserted: the VM owning the fabric is necessarily what you bind to. §XIII.5's proposed shape was right; its justification was wrong, and is corrected in place. Records the evidence that the fabric actually wants an owner, which is an argument for the reshuffle this document had not previously identified. The ownerless console_set_vm_name() global has already caused a live bug, documented in console.h:193-203 -- get_vm_name() is unsafe for save-then-restore because an intervening set overwrites the saved pointer's own bytes before the restore runs; found live 2026-08-28, silently no-opping, with console_save_vm_name() existing solely to work around it. That is the signature of shared mutable state with no owner. Notes what the ruling commits to: a new capsules/console/init.4th (the one genuinely new artifact, and it is a capsule rather than a mechanism), the is_fleet_foundation triple changing membership, kernel_main.c's Hermes birth becoming Console's, the DoE CSV schema change, and Console needing BIRTH registered. §IV is unblocked. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
bd0c23286c |
FABRIC-3.5.md §XVI: item 10 settled -- clean shutdown is forced flush + BYE, Hera's is suicide
Captain Bob, 2026-09-18. A clean shutdown is a VM termination where flush is forced and the VM says BYE; Hera is the special case that halts the processor instead. Traced, and the ruling is almost entirely existing mechanism. blk_flush(0) is already the documented flush-all sentinel (block_subsystem.c:988-990) and already the Stadium's own write-back action. A child's BYE already terminates it -- system_word_bye sets vm->halted, which mama_forth_words.c's own doc comment describes as the child path. arch_halt() exists on all three architectures (amd64:207, aarch64:126, riscv64:170), so three-arch parity holds without new per-arch work. The one real finding is a behavioural change rather than a gap: Hera's BYE does not halt today, it cold-restarts. mama_word_bye() reaps children then calls arch_cold_reset(). The reaping half already matches the ruling; the terminal action is the opposite of it. Flagged so the change is made knowingly -- CLAUDE.md forbids modifying a registered tested word to "fix" it, and this is a ruled change rather than a fix, but it should not surface first in a diff. Whether suicide replaces BYE or becomes a separate word is left open as item 17, noting cold-restart-on-BYE is plausibly wanted for an operator typing BYE at Hera's REPL. Records a constraint on where the flush goes: system_word_bye lives in shared vendored source that must keep working in the hosted build, so the forced flush belongs in the kernel-side shutdown path, not inside BYE. §VIII.3's bounded-window question answers itself -- the window ends when Hera halts, a bound by construction with no timeout to tune, which is consistent with §XV.3's no-owner invariant. Item 9 is now half-answered. Raises one residual edge as analysis only: if Hera is already dead, nobody performs the halt, leaving a live kernel over an empty floor. An empty floor is arguably a kernel-observable condition rather than a VM's decision, which would terminate without any VM inheriting her authority. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
a842789ae6 |
FABRIC-3.5.md §XV: the authority questions answered, three by rejecting the premise
Captain Bob, 2026-09-18. Any VM may birth a near-clone of itself carrying its own ACL DNA; nobody declares a VM dead, it dies a compudynamic death; nobody owns turn order, turn order is compudynamic. These close six punch items. Birth-by-near-clone settles what "ACL/DNA" refers to -- inheritance by copy, using the existing ACL-INHERIT semantics, needing no fifth DictEntry field -- and settles "standing" as decorative, confirming the minimal reading. The authority bound holds literally rather than aspirationally: a child cannot exceed its parent because it is built from it, so there is no gate to bypass. Compudynamic death retires the largest scheduler-shaped risk in the design. §VII's ladder appeared to need a supervisor watching liveness, and a supervisor with a timer is a scheduler's twin; with death as a physical outcome rather than a judgment, that component is not needed and does not exist. §VII.3 and §IX.3 both asked the wrong question and are marked withdrawn and premise-rejected in place. Turn order gets a stronger invariant than the firewall previously proposed: that one named an owner, and naming an owner is what a conventional scheduler is. Nothing owns turn order. Flags one honest seam for later, predating this work and belonging to §XXVIII: SK_SWITCH_READINESS_THRESHOLD is a hardcoded 50, the same category of fixed policy §XIX rejected. Reframes the message-durability question that was posed badly enough to be unintelligible. It is not persistence but conservation: a message holds Q.SLOT of heat (MSG-ALLOC pulls, MSG-FREE-NODE evicts), so a dying arbiter holds N x Q.SLOT of fleet heat. Payloads may vanish; the heat may not, or K breaks. Nothing survives except K. This dissolves the Artemis-at-death-time hazard entirely rather than trading against it -- there is nothing to persist, and since death is already a Stadium eviction, returning heat is what dying consists of. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
9b69c1f447 |
FABRIC-3.5.md §XIV: two rulings collapse the root dependency
Captain Bob, 2026-09-18. The existing FORTH messaging layer is legacy -- kernel Hermes is greenfield C, not a migration of messaging.4th, and the dead FORTH gets retired by a separate cleanup pass. Persistence goes through Artemis wherever possible; that part is ratified. Together these dissolve rather than answer four open questions. §III.4, named the root dependency throughout §X, is resolved in the "full centralization" direction but without the migration cost that made it frightening: with the FORTH legacy there is no live state to port. §III.3 loses its subject, and §XIII.1's 14-site inventory changes purpose rather than content -- it now feeds the cleanup. §IV.2 dissolves via its own option 3, exactly as that section predicted. The MANIFEST corrections are absorbed into the cleanup pass. All four marked superseded in place with pointers rather than rewritten. Traced the layering question the persistence ruling raises, and it answers cleanly: storage is already two layers, so no inversion is needed. The block subsystem is kernel C below the floor (block_subsystem.c, blkio_*.c, virtio_blk.c; capsule_loader.c:98-100 calls it with no Artemis involved), while Artemis is the storage policy arbiter on the floor. Fleet persistence goes through Artemis; anything kernel Hermes needs uses the same block layer Artemis sits on. Flags the one hazard that ruling carries: Hermes must not depend on Artemis for persistence at its own death, since reaching Artemis requires the mechanism that is broken -- the same trap §VIII solved for signalling with a semaphore. Recommends a stateless arbiter holding only registry-reconstructible state, offered as analysis, not a ruling. Also records the scheduler firewall as raised-but-unruled, and why the legacy ruling makes it more urgent: eligibility marking moves inside the arbiter by default once kernel Hermes replaces FORTH MSG-SEND as the caller of sk_vm_switch_signal_mark_work(). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
bcf41e5618 |
FABRIC-3.5.md §XIII: work punch items 1 and 2, CLOSED with evidence
Items 1 and 2 were the two pure-investigation entries, carrying no design
commitment, so they were executable without a ruling. Traced against the
tree at
|
||
|
|
0e4e6673a9 |
FABRIC-3.5.md: open the Tripod/kernel reshuffle as its own document
Opened by direct instruction as a standalone document rather than a FABRIC-4 scratchpad entry: the reshuffle is a ratified architectural direction needing full FABRIC discipline, but it is not bare-metal boot, so it does not belong in FABRIC-3 and does not close it. FABRIC-3 stays open, living and authoritative for its own topic. Records what was decided 2026-09-18 (Hermes into the kernel as arbiter rather than client; Tripod reconstituted as Hera/Artemis/Console; Console as the fleet bind point; BIRTH general with authority bounded by inheritance; one gentle -> from-scratch -> brutal recovery ladder; SOS as a standard message type with Hermes excepted via a sinking semaphore; no provisional handoff of a failed birther's authority), and separates it from what is still open. Grounded against the tree rather than recalled, with provenance marked per claim. Notes the concrete consequences the move runs into: Artemis's two by-name S" Hermes" VM-EXEC call sites, the routing table's written "never renumbered" commitment on slots 0/1/2, and the per-VM CREATE/ALLOT message arenas that decide whether this stays a reshuffle or becomes a rewrite. Design only. No code authorized, nothing else in the tree touched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP |
||
|
|
04cc17920e |
3-arch QEMU acceptance logs for the FINDINGS.md defect-repair commits
Per .claude/CLAUDE.md's non-negotiable acceptance criteria, ran `make -f Makefile.starkernel ARCH=<amd64|aarch64|riscv64> clean qemu` sequentially (one instance at a time, TCG) against the two preceding commits. All three booted cleanly to `(zuse) ok>` with the full Tripod fleet (Hera/Hermes/Artemis) alive, Stadium conservation holding (resident_sum=43691 reservoir=21845 sum=65536), and identical dictionary hashes across all three ISAs: Mama: dict_hash=0x8d712e07c690d713 Hermes: dict_hash=0xa07a57d794c1665d Artemis: dict_hash=0x9cc9a7e72b590250 Confirms cross-arch determinism holds with the EXECUTE/format/TYPE/ vocabulary/control-flow fixes applied. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Qf6YcnHgaEtEygq3knx19 |
||
|
|
7191ce5a56 |
Refresh lfs/amd64/starforth binary artifact
Rebuilt after the EXECUTE/format/TYPE/vocabulary/control-flow fixes in the two preceding commits, per lfs/README.md's convention (this binary is synced whenever the hosted amd64 build runs). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Qf6YcnHgaEtEygq3knx19 |
||
|
|
d6895bdd15 |
Move vocabulary and control-flow state off file-scope statics onto VM
proof/FINDINGS.md's Isabelle/HOL word-source sweep (§1) found the two defects severe enough to actively corrupt the live Tripod multi-VM fleet: file-scope C statics standing in for state that belongs on struct VM. - vocabulary_words.c (highest severity in the sweep): forth_vocab/ context_vocab/current_vocab, context_var_addr/current_var_addr, the ctx_fc/forth_fc first-char search index, and the `initialized` guard were all process-wide statics. Only the first VM to touch any vocabulary word ever ran setup; every VM after that silently shared VM #1's dictionary-chain pointers and reused VM #1's byte-offset addresses as if valid in its own vm->memory. One VM's VOCABULARY/ DEFINITIONS/FORTH silently changed where every other VM looked up and defined words. - control_words.c: cf_stack/cf_sp/cf_last_mode (IF/THEN/BEGIN/DO/CASE compile-time nesting) and the LEAVE/ENDOF patch-site bookkeeping (leave_addrs/leave_sp/leave_mark_*, endof_addrs/endof_sp/endof_mark_*) were also process-wide statics. Two VMs compiling colon definitions at overlapping times would corrupt each other's nesting state. Both moved onto struct VM, following the existing hold_addr/hold_pos precedent in include/vm.h ("lives in each VM's own memory... so child VMs never alias Hera's buffer"): - New VocabularyState struct (vm->vocab): chain heads, VM-cell addresses, first-char index, initialized flag. - New ControlFlowState struct (vm->cf): cf_stack/cf_sp/cf_last_mode plus the LEAVE/ENDOF patch-site stacks. cf_tag_t/cf_item_t/CF_STACK_MAX moved from control_words.c into include/vm.h since they're now part of the struct VM field's type. - Sentinel fields (-1/-999, meaning "empty") explicitly initialized in both vm_init_with_host() implementations (hosted src/vm_bootstrap.c and kernel src/starkernel/vm/vm_bootstrap.c) alongside the existing dsp/rsp = -1 initialization, since the preceding zero-init leaves them at 0 rather than their empty sentinel. Every word function in both files already took VM *vm, so no call sites outside these two files needed to change; cf_push_item/cf_pop_item/ cf_peek_item gained a VM* parameter to reach vm->cf. Verified: hosted (amd64) and kernel (amd64, __STARKERNEL__) both build clean with -Wall -Werror after a full clean rebuild (struct VM's layout changed size, and this Makefile has no header-dependency tracking, so a stale incremental build would have linked mismatched object layouts). Hosted POST suite 1012/1012 passing (0 regressions). Manually exercised VOCABULARY/DEFINITIONS/FORTH/ORDER, and IF/ELSE, DO/LOOP/LEAVE, BEGIN/WHILE/REPEAT, and CASE/OF/ENDOF/ENDCASE (including nested DO with I/J) in the REPL -- all correct and unchanged from pre-refactor behavior. Note: a pre-existing CASE/ENDCASE default-clause bug (the code after the last OF...ENDOF pair does not correctly become the "default" value once DROP runs) was found while testing this refactor and confirmed present on unmodified master too -- not touched here, out of scope for this pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Qf6YcnHgaEtEygq3knx19 |
||
|
|
c36bd99e1e |
Fix EXECUTE/?/DUMP/TYPE/DECIMAL-HEX-OCTAL/ALIGN defects from proof sweep
proof/FINDINGS.md's Isabelle/HOL word-source sweep (§4) flagged five real defects; this fixes all five and records resolution in that doc: - EXECUTE (system_words.c): cast a popped cell straight to a DictEntry* and called through it with only a null check. Now validates via a new shared vm_dict_entry_ok(), promoted out of starforth_words.c's ENTROPY@/ENTROPY! guard (dictionary_management.c) so EXECUTE gets the same live-entry check. - ? and DUMP (format_words.c): dereferenced the popped cell as a raw host pointer, bypassing vm_addr_ok entirely (out-of-VM-bounds read). Both now go through VM_ADDR/vm_addr_ok/vm_load_cell/vm_ptr like every other memory word (@, `,`, editor_words.c). - TYPE (io_words.c): bounds check computed addr+count in signed 64-bit arithmetic, which can overflow and bypass the check on large operands. Replaced with vm_addr_ok(), which is written to avoid that overflow. - DECIMAL/HEX/OCTAL (format_words.c): wrote only the BASE memory cell, never vm->base, the host-mirror field number-output words actually read via current_base() -- so these words silently affected number parsing but never printing. Now call the existing vm_set_base() (previously only used at boot init), which updates both. vm_get_base/vm_set_base promoted to public declarations in include/vm.h. - ALIGN vs ALLOT/,/C,/2, (dictionary_words.c): disagreed on dictionary growth ceiling (2MB vs 5MB). Investigated which was correct rather than blindly widening: vm_get_block_addr() maps block N to vm->memory + N*BLOCK_SIZE across the full 5MB arena, and USER_BLOCKS_START (block 2048) lines up exactly with DICTIONARY_MEMORY_SIZE -- so ALLOT/,/C,/2, letting `here` grow past 2MB could silently corrupt live block/user data sharing that memory. Tightened ALLOT/,/C,/2, to DICTIONARY_MEMORY_SIZE to match ALIGN. Verified: hosted (amd64) and kernel (amd64, __STARKERNEL__) both build clean with -Wall -Werror; hosted POST suite 1012/1012 passing (0 regressions); manually exercised EXECUTE, ?/DUMP, TYPE, HEX/DECIMAL/OCTAL, and large-ALLOT rejection in the REPL. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Qf6YcnHgaEtEygq3knx19 |