Skip to content

fix(gateway): close four matchableTerms gaps from astra's #439 review (#439 follow-up) - #549

Merged
LamaSu merged 2 commits into
masterfrom
followup/439-nits
Oct 3, 2026
Merged

LamaSu merged 2 commits into
masterfrom
followup/439-nits

Conversation

@LamaSu

@LamaSu LamaSu commented Oct 3, 2026

Copy link
Copy Markdown
Owner

What

This follow-up to #439 (merged 9/30) closes four matchableTerms gaps from astra's #439 review. #439 merged before this commit, so the follow-up needs its own PR.

Review

The review pack is 130-composition-439-followup-3a7721e8.md: a narrow confirmation at 3a7721e, 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 2 commits September 29, 2026 19:46
AGENT_NAME: implementer-alpha

Board N23 follow-up. astra (SHIP-WITH-NITS on PR #439) found four ways
matchableTerms() could still match a capability on invented or corrupted
terms instead of failing closed:

- 439-A: sub-cent headlines ("0.001", "0.004") both digested as "0.00"
  in the v1 preimage (toFixed(2)) while capPrice still returned a
  nonzero estimate -- two different declared prices could share one
  commitment. Now rejected (not rounded); restricted to this legacy
  2-decimal representation only.
- 439-B: headlines above Number.MAX_SAFE_INTEGER silently changed value
  through parseFloat ("9007199254740993" -> ...992; 30 nines -> 1e+30,
  which toFixed(2) renders in exponential notation). Now rejected.
- 439-C: a currency of " " or " USDC " passed the nonempty-string check.
  Now requires a non-empty string equal to its own trim().
- 439-D: a sparse tiers array ([0,,1]) passed because Array#every skips
  holes, and new Set() then materialized the hole as `undefined`. Now
  validated by bounded-index hasOwnProperty scan, which cannot skip a
  hole.

Also added 439-E (preserves_declared_non_default_currency, "EUR") since
the prior currency-preservation test only ever declared "USDC" and could
not catch unconditional replacement with it.

Not reproduced: an explicit object-shape check on `pricing`. Non-object
pricing (array/string/number/boolean) is already rejected by the
existing currency-type guard, since none of those JS-boxed primitives
expose a `currency` string property -- added a regression test proving
this rather than new validation code.

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

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ites exactly its value (#439 follow-up, astra 130)

Astra 130 left 439-B open (MEDIUM) and found a regression in its guard.
- 439-B: isSafeTwoDecimalHeadline checked only the integer part, so
  "9007199254740991.01" and "…​.02" both passed, both parsed to
  9007199254740991, and both entered the digest as "9007199254740991.00".
- The regression: leading zeros counted toward the digit limit, so
  "00000000000000001" (the value 1) was refused.

The guard now states the property directly: the v1 digest writes
Number(headline).toFixed(2), and a headline is accepted only when that is
exactly the two-decimal value it spells (leading zeros stripped). This also
refuses any other value a double cannot hold, such as "99999999999999.99",
which the new property test found, and anything toFixed writes in
exponential notation.

Reproduced first: the 3 new tests fail at 3a7721e. Decomposer and digest
suites: 64/64. Full gateway suite: 3022 passed, 6 skipped. tsc is clean.
Mutants 3/3 killed: the equality dropped, zeros counted, and the
integer-only check restored.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSBxBEX3sn9DPSqihyjuZE
@LamaSu
LamaSu marked this pull request as ready for review October 3, 2026 22:41
@LamaSu
LamaSu merged commit 49a6c5f 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