Skip to content

docs: W1 done, D3 resolved, and D4's constant-pool recommendation REVERSED - #238

Merged
AdaWorldAPI merged 4 commits into
mainfrom
claude/rust-scratch-abi-soa-gsamge
Aug 4, 2026
Merged

docs: W1 done, D3 resolved, and D4's constant-pool recommendation REVERSED#238
AdaWorldAPI merged 4 commits into
mainfrom
claude/rust-scratch-abi-soa-gsamge

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

Records what landed in blockly-rs for W1 and reverses D4's recommendation in the plan doc. Docs only — no code in this repo changes.

W1 is done, and the gate is green

The falsifier — a drag produces zero SoA writes, an operand change produces exactly one — passes in blockly-rs (4d39590). Both halves route through Workspace::apply, so a handler that let a drag reach the record fails the test. Verified by injecting exactly that leak and confirming two tests fail; without the apply step the first half would have been f(x) == f(x), which is how the first version was written and why it was rewritten.

D4 — the recommendation is REVERSED

The plan recommended the Inventory SoA as the constant pool's home. That is withdrawn, in place rather than rewritten.

It conflates two codebooks. Inventory indexes functions, which are shared by definition; constants are per-function data, which are owned by definition. A per-function pool in the one table every function shares is a shared-mutable sink with N writers.

Shipped instead: a sibling pool node — same 30 content slots, same 16-byte stride, identity inherited from the owning function, and a per-facet classid naming each constant's type. An f64 and a UTF-8 string are different readings of 12 bytes, so a discriminant byte inside the payload would be a second schema under one classid.

Two further options are recorded as killed by named constraints, so they are not re-proposed:

option what kills it
literal as a run of calls the W1 one-write gate — call count would track literal width, so editing 2551000000 rewrites the tail of the body
steal content slots from the body the call budget becomes per-function, so "add one string" can make a program that fit stop fitting, with the overflow blaming the calls

Capacity is explicit: 255 usable indices, 30 per node, 9 nodes; the 256th is PoolFull and the remedy is a function split, never a wider index. Reachable only under Quads (270 addressable value bytes > 255).

Still gated on an operator mint. The pool is opt-in in code — lower_script still refuses a wide literal, and only lower_script_with_pool interns, under caller-supplied classids with deliberately invalid placeholders in the interim. The proposed ids (0x1703..0x1705) are labelled a proposal, not an assumption, and the cheap alternative (one concept plus a type-tag byte) is refused on the record.

D3 — resolved, with two anchors because one was insufficient

The pre-existing census compared against FnIndex::LT — the symbol. A renumber upstream would have left every symbolic assertion passing while every stored program changed meaning. So the bytes are now pinned too, and asserted mutually distinct, so a collapsed palette cannot be matched by a collapsed expectation table.

ValueParam encoding

A code encodes as its ordinal in the codebook's own pinned table, keyed on (block type, field name) — deliberately not Blockly's live array order, since reordering an options array is cosmetic upstream and would silently reinterpret stored programs here. Keyed on the field because text_getSubstring's WHERE1/WHERE2 differ only in their third entry.

W2's producer half

Recorded with the reasoning for the ordinal choice: the ordinal is the call index, so raise_calls(body)[ordinal] IS the clicked block's call by construction, which makes an address checkable against the ABI rather than merely self-consistent. Proven non-vacuous by injection — a pre-order walk yields unique, dense, plausible ordinals and fails two tests.

Companion

AdaWorldAPI/blockly-rs @ e4b5e7e — 47 tests, fmt / clippy -D warnings / rustdoc broken-link gates clean.


Generated by Claude Code

W1's gate is green in blockly-rs (4d39590) and the three follow-ups the
plan listed as prerequisites have landed (31e18fb, e4b5e7e). Recorded
here rather than left to the commit log, per the append-only rule.

D4's recommendation is REVERSED, in place rather than rewritten. The
Inventory host conflates two codebooks: Inventory indexes functions,
which are shared by definition; constants are per-function data, which
are owned by definition, so a pool there is a shared-mutable sink with
N writers. Shipped instead is a sibling pool node with per-facet
classids naming each constant's type — an f64 and a UTF-8 string are
different readings of 12 bytes, and a discriminant byte inside the
payload would be a second schema under one classid.

Two further options are recorded as killed by named constraints so they
are not re-proposed: literal-as-call-run breaks the W1 one-write gate
(call count would track literal width), and stealing content slots
makes the call budget per-function so a new string can overflow the
calls.

The pool remains gated on an operator mint and is opt-in in code:
lower_script still refuses a wide literal, so a placeholder classid
cannot reach stored data before the concepts exist. The proposed ids
are labelled a proposal, and the cheap alternative (one concept plus a
type-tag byte) is refused on the record.

D3 resolved with two anchors, because the obvious one was insufficient:
the census compared against SYMBOLS, so a renumber upstream would have
left it passing while every stored program changed meaning.

W2's producer half is recorded with the reasoning for the ordinal
choice and the injection that proved its falsifier non-vacuous.
@cursor

cursor Bot commented Aug 4, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_6f80a617-a032-4c20-81fc-2b95a10139f1)

…W4 gap

Marks every wave DONE and records what the work found, including two
places the plan's own audit was wrong and one place it missed a defect.

W2's audit was corrected on two points by reading the source: Form and
Flow do not map the position address at all (they place by iteration
order), so Grid is the FIRST address-driven skin rather than a
symmetric addition; and FACET_LEN=12 is a byte WIDTH, not a facet
count — the framing that a prior session's withdrawn truncation claim
died on. It also missed the real defect: an out-of-range mask position
was silently dropped while apply returned Ok.

W4 is marked done with an explicit gap rather than a claim: the
lowering is proven end-to-end, but the gate as written names a .sb3
round-trip and no .sb3 is imported yet. Saying so is cheaper than
letting a future session discover it.

D1/D2/D5 resolved as recommended; D3 and D4 already recorded above,
D4 reversed.
@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review August 4, 2026 19:08
The previous entry marked W4 done with an explicit gap: the gate names a
.sb3 round-trip and none was imported. That gap is now closed, and the
entry records how rather than merely that.

The arms meet at execution rather than at the IR — not a compromise. An
IR diff is not available (load_block takes a CompileContext with private
fields and no public constructor), but it would also be the weaker
check: a structural diff is satisfied by two trees that are equal and
both wrong.

Records both injections, because 'identical output' is the easiest
assertion in the world to satisfy with an inert harness.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 99d25ee504

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/BLOCK-EDITOR-PLAN.md Outdated
operator ruling and a ledger correction.

### W1 — the POC cast (`blockly-rs`) — **NEXT**
### W1 — the POC cast (`blockly-rs`) — **DONE**

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep W1 open until the Blockly prefix is minted

Marking W1 as DONE makes the W1 checklist read as complete, but the same section still names an OGAR-side app-prefix mint for blockly-rs in ogar-vocab::ports; at this commit the ports implementation and allocation table still only reserve the existing app prefixes and have no blockly-rs entry. Anyone starting the W2 address work from this plan will assume the low-u16 render prefix exists and may hardcode or collide on an unallocated value, so either keep W1 partially open or move the mint into explicit remaining work.

Useful? React with 👍 / 👎.

Comment thread docs/BLOCK-EDITOR-PLAN.md
while "one surface, many skins" quietly collapsed to "one skin". Verified by
injection.

### W4 — execution (`scratch-rs`, GPL leaf) — **DONE**

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep W4 open until the .sb3 gate passes

This heading declares W4 DONE, but the newly added falsifier status below says the required .sb3 parity gate is not met and that rash_loader_sb3::ProjectLoader plus a fixture project are still remaining W4 work. That contradiction makes the wave tracker claim execution is complete while the plan's own release gate is still open, so downstream scheduling can skip the actual import/parity work.

Useful? React with 👍 / 👎.

…med was real

Codex flagged W1 as marked DONE while its own section still named an
unfinished app-prefix mint, warning that someone could hardcode a
colliding value. Correct, and the hypothetical was already instantiated:
blockly-abi's Klickwege tests used 0x1000, which ogar-vocab::ports
reserves for the V3-adoption monitor marker with a test asserting it
must never be a port APP_PREFIX. Fixed in blockly-rs e53aefe.

W1 is now 'DONE (one mint outstanding)' and the mint moved into a new
Remaining section that collects all three open operator decisions in one
place, with the allocation state and the reserved value recorded so the
next reader does not re-derive them. No value is proposed for any of the
three — a mint is an operator decision by standing rule.

Codex's other P2 (W4 marked DONE while its gate was open) was already
resolved in 7077e3a, one commit after the 99d25ee it reviewed: the .sb3
gate is green.
@AdaWorldAPI

Copy link
Copy Markdown
Owner Author

Both P2s addressed.

W1 (line 81) — correct, and the risk it names was already instantiated. Fixed in cd21d85 here plus blockly-rs e53aefe.

W1 is now DONE (one mint outstanding) and the app-prefix mint is moved into a new § Remaining — operator mints, which collects all three open decisions in one place.

The concrete part: blockly-abi's Klickwege tests used 0x1000 as their app prefix — and ogar-vocab::ports reserves 0x1000 for the V3-adoption monitor marker, with a test asserting it "must never be allocatable as a port's APP_PREFIX". So the hypothetical about hardcoding a colliding value was not hypothetical. The test constant is now an obviously-unreal 0xFF00 so it cannot be mistaken for the answer when the mint lands.

Worth noting what limited the blast radius: app_prefix is a parameter on every public function in klickweg, and nothing in the crate names a prefix. That parameterisation is what kept a documentation contradiction from becoming a stored collision. No value is proposed for the mint — a mint is an operator decision by standing rule.

W4 (line 258) — already resolved. This reviewed 99d25ee; 7077e3a (the next commit) closed it. The .sb3 gate is green: a real .sb3 — genuine zip, project.json plus a costume asset, since rash resolves currentCostume and reads the asset's bytes — computing (3 + 4) * 2, run through ProjectLoader::new().build() on one side and to_scratch_block into the same Script/SpriteBuilder/ProjectBuilder entry points on the other.

The arms meet at execution rather than at the IR. That is not a compromise: an IR diff isn't available (load_block takes a CompileContext with private fields and no public constructor), but it would also be the weaker check, since a structural diff is satisfied by two trees that are equal and both wrong.

Both injections were run, because "identical output" is the easiest assertion in the world to satisfy with an inert harness: changing the fixture to (3 + 4) * 9 makes the native arm read 63 (proving rash parses and runs our fixture rather than returning a cached value), and lowering MUL to OpAdd gives native 14 vs SoA 9 (proving the SoA arm feeds the comparison).


Generated by Claude Code

@AdaWorldAPI
AdaWorldAPI merged commit f35cd6b into main Aug 4, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants