Skip to content

fix(gateway): #440 review follow-up: v2 digest tier and location handling (N20) - #550

Merged
LamaSu merged 4 commits into
masterfrom
followup/440-nits-r2
Oct 3, 2026
Merged

LamaSu merged 4 commits into
masterfrom
followup/440-nits-r2

Conversation

@LamaSu

@LamaSu LamaSu commented Oct 3, 2026

Copy link
Copy Markdown
Owner

What

This follow-up to #440 (N20, merged 9/30) carries astra's #440 review fixes. #440 merged before them, so they need their own PR.

  • 46f3d45: closes the v2 tier-iteration gap and pins v1.
  • 9d3913b: the v2 digest treats a {0,0} or null kernel location as no location.
  • bb742a2: drops a tier check (review 131 found it reachable; restored below).
  • 93cefa9: a tier list whose length reads below one is refused. This closes 131's finding, and it is the confirmation round.

Review

  • Pack 131 was SHIP-WITH-FIXES; its fixes are at 93cefa9.
  • The narrow confirmation is 134-composition-440-followup-r2-93cefa96.md, in the steward's PASTE ORDER.
  • It merges once that pack confirms the fixes (rule 8) and CI is green on this exact SHA.

🤖 Generated with Claude Code

LamaSu and others added 4 commits September 29, 2026 19:48
…review

AGENT_NAME: implementer-alpha

Board N20 follow-up. astra (SHIP-WITH-NITS on PR #440) found that
matchedCapabilityDigestV2's assuranceTiers validation checked the array's
length, then trusted the iterable protocol (`for...of`) to actually walk
it -- a caller-substituted Symbol.iterator can serve fewer, different, or
zero entries than the checked length, e.g. an empty generator turns a
real `[0]` into a hashed `[]`, or a generator yielding `3` launders a real
`[99]` (invalid) into a valid-looking committed tier.

440-A fix: read `.length` exactly once, reject outright if the array's
Symbol.iterator has been reassigned away from Array.prototype's built-in
one (rather than trying to "see through" a substituted iterator), then
walk indices 0..length-1 by `hasOwnProperty` (never the iterable
protocol) so a hole must throw instead of being skipped or smuggled.
Explicit non-empty check on the resulting set before hashing.

440-B: added pins_v1_preimage_and_digest_to_base_vector -- the existing
v1-regression test only checked shape/inequality with v2, so a mutation
to v1's price precision could still pass it. Computed the exact
preimage bytes and digest from the current (#440-unchanged) v1
implementation and pinned them literally.

440-C: MAX_TIER_ENTRIES (16) and the CSD class/version length caps
(64/32) are implementation-side restrictions not stated in N20's quoted
text. Per operator directive, kept (not removed) and documented
explicitly in a contract comment above the constants, flagged for the
spec owner to fold into N20's text. No behavior change.

Also added the regression tests astra listed for existing (correct)
behavior, pinning it against silent drift: ordinary sparse tier arrays
throw, a NaN tier throws, -0 normalizes to 0, an identifier containing
a quote/backslash cannot forge a second JSON key (verified via
JSON.parse, not just canonicalize's own escaping), and a trailing slash
in the CSD url throws while a bare query string is accepted literally.

Tests: packages/gateway/src/__tests__/matched-capability-digest-v2.test.ts
(15 tests, was 8). Also ran matched-capability-digest.test.ts (11) and
agentic-decomposer-digest.test.ts (4) -- all green, no regressions.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…tion

AGENT_NAME: implementer-alpha

Board N20 round 2, agreed with the gateway lane (#3603). Two conditions
on matchedCapabilityDigestV2's kernelLocation:

(a) an exact {lat:0,lng:0} counts as NO location -- it is not a real
    place any kernel is actually registered at, so it must not silently
    commit to the Gulf of Guinea geohash cell ("s00000") as if it were
    real.
(b) no location (null, absent, or {0,0}) all encode identically as
    `"kernelLocationGeohash6": null` -- never a geohash string, never an
    omitted key -- so "we don't know" can never be misread as a real
    cell by a consumer that just checks the key is present.

kernelLocation is now optional/nullable in MatchedCapabilitySnapshotV2
(verified no production consumer yet -- this encoder is still unused
per astra's #440 review). A real, non-origin location (including valid
edge cases like {lat:0,lng:45} on the equator) still geohashes normally.

Golden vector: computed the null-location preimage/digest from the
implementation and confirmed it matches the gateway lane's agreed
fixture exactly before pinning it -- 536 bytes,
0xfacd369395f056b2ca426c49fff8706146d0ff4bac212bd5c4990e5b72c71925.
{0,0} and an absent kernelLocation key both produce that identical
digest. The existing 540-byte real-location golden
(0x7558a7e581e369241ac072f29f0b60a4d6d6e1de757180f12fa7750e969d29bf) is
verified unchanged.

Tests: packages/gateway/src/__tests__/matched-capability-digest-v2.test.ts
(18 tests, was 15) -- new describe block covers null/{0,0}/absent parity,
the unchanged 540-byte golden, and the {0,0} vs on-equator boundary.
Also ran matched-capability-digest.test.ts (11) and
agentic-decomposer-digest.test.ts (4) -- all green.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… follow-up, confirmation round)

astra's confirmation review of bb742a2 reopened 440-A as a MEDIUM. The tier
count check refused only exactly 0, so a Proxy reporting a negative length
passed it. The index loop then ran zero times and an empty tier set was
committed. bb742a2 had removed the post-loop non-empty check on the
premise that the count was already above zero, but the code did not
guarantee that premise. Reproduced first: the reviewer's Proxy with length
-1 did not throw at bb742a2.

The count must now be at least one. That makes the premise hold by
construction, so the loop pushes or throws at least once. A test covers
lengths -1, -16 and 0.

Tests: matched-capability-digest v2 19/19, plus the v1 and decomposer
digest tests (34 in all). Mutations: reverting to === 0, and dropping the
lower bound, are both killed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0171FftEAfqjwbJHowVTqAbz
@LamaSu
LamaSu marked this pull request as ready for review October 3, 2026 22:38
@LamaSu
LamaSu merged commit 6ef4b34 into master Oct 3, 2026
9 checks 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.

1 participant