fix(cluster-tool): decode each outbound-gate code by its own carrier - #103
Merged
Merged
Conversation
runOutboundEnvelopesQueued read chains.code with String(code.value) and
compared spellings. Once the depot registers the slug_name ABI builtin the
cell is "ETH", .value is undefined, every expected code becomes
"undefined", and the gate can never match — external bootstrap times out.
The fixture pinned {code:{value}}, so no test saw it.
Both sides now decode by declared type and compare packed values:
chains.code is a slug_name field (slugValue handles the wrapper and the
spelling), outenvelopes.chain_code is uint64 (packedSlugValue). The
failure message keeps the spelling via SlugName.toString. Fixture covers
both carriers.
Change-Id: I481aa204ba3368b6d269488e36cab8637170fe9a
jglanz
approved these changes
Sep 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The remaining chain-table reader flagged as [P1] on wire-sysio#619: "one live consumer bypasses it:
ExternalOutpostSteps.tsstill maps eachgetChains()row withString(code.value)."Confirmed exactly as described.
runOutboundEnvelopesQueuedbuilt its expected set withString(code.value)and compared spellings againstString(row.chain_code). That worked only because both sides happened to land on the same decimal. Once the depot registers theslug_nameABI builtin,chains.codeis"ETH",.valueisundefined, every expected code becomes the literal"undefined", and the gate can never match — external-outpost bootstrap polls its fullSingleHopBudgetMsand times out.#101did not expose it for two reasons: the reader bypassesslugValueentirely, so classifyingslugValuecall sites could not find it — and its fixture pinned{ code: { value } }, so no test ever supplied the string carrier.The fix
Both sides decode by declared type and compare packed values:
chains.codeis aslug_nameABI field →slugValue, which handles the{value}wrapper before the builtin and the canonical spelling after.outenvelopes.chain_codeis declareduint64→packedSlugValue, the decoder added in fix(cluster-tool): parse a bare slug cell as a slug, not a decimal #101 for precisely this carrier. It renders as a number, or a quoted decimal past0xffffffff, which every real chain code exceeds.The failure message keeps the human-readable form via
SlugName.toString, so the enrichment context still namesETH/SOLrather than packed integers.Fixture
chainRowis now parameterized over aSlugCarrieridentity enum, and the gate's positive case runs under both carriers viait.each— the string spelling and the legacy{value}wrapper — so the rollout window is covered from both sides. Codes are real (ETH/SOL/WIRE) rather than small integers, so the spelling carrier is genuinely exercised.I deliberately did not add a negative carrier case: the gate polls
SingleHopBudgetMs(7 min) before failing, so a no-envelope test would stall the unit suite. The failure path is already covered by the existing enrichment test, which rejects through the fastgetOutboundEnvelopesthrow.Verification
ExternalOutpostSteps+slugUtils: 30/30, 4.6s. Filtering to-t carriergives 2 passed / 11 skipped, confirming both parameterized variants execute rather than silently collapsing to one.eslintclean on both files.Order-independent, like #101: correct before and after #619.