Skip to content

spec(field): refuse a homeAmount rateField whose declared scale is below 12, and document CURRENCY_FRACTION_DIGITS as CLDR fraction digits, not ISO 4217 minor units (multi-currency, epic #8345) #30103

Closed

Description

@objectstack-fleet

epic:#8345#1 · os-bill · session_01Utp6CZWjnSeed8H4dMjt9d

Part of #8345. Filed by the epic PM into the domain:spec seat's queue (spec children of the epic go to the spec seat; seat-lifecycle 〈Epic 子树车道〉). Owed by the predecessor's sign-off ledger (brief 6540325320). ⛔ Not a claim.

Ruling-ref: 6469382727

维护者速读

Task

  • In the object-level judge of homeAmount pointers (packages/spec/src/data/object.zod.ts#refuseDishonestHomeAmount), refuse a rateField whose declared scale is below 12; the message names the field and the floor. Decide and state what an undeclared scale means.
  • TSDoc on CURRENCY_FRACTION_DIGITS and content/docs/data-modeling/currency.mdx: CLDR fraction digits; list each code where CLDR differs from ISO 4217 minor units, measured from the table, not recalled.
  • Tests: scale 4 refused, 12 and 14 accepted, undeclared per the decision.

Lane: spec · Size: S · Review: CONTRACT_REVIEW_TIER (narrowing a published accept set). Clause-②: no (narrowing) · Metadata-protocol: none.

Evidence: PR #28302 pins 0.138912345678 stored in full under a declared scale: 4 (home 71987.84); the engine never rounds the rate.

Dedupe: #8345 body ledger; open domain:spec cards searched, none carries this.

Activity

  1. added
    enhancementNew feature or request
    pm:queueReady for the PM dispatch loop
    domain:specDomain lane — seat card indexed by label:pm:seat
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    on Nov 4, 2026
  2. objectstack-fleet commented on Nov 4, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: first-touch audit · p3 kept · domain:spec kept · 2026-11-04T13:57Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 5, 2026
  4. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-sales · session_01L6bhgVugtCCwBs98FeR27P

    Claim: PM loop round 1 · 2026-11-05T18:10Z
    Session: session_01L6bhgVugtCCwBs98FeR27P (seat; mode:subagent, so the dev shares this session id and is identified by the branch)
    Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-30103-rate-field-scale-floor
    Worktree: objectstack-issue-30103
    Domain: domain:spec
    Seat: domain:spec#2
    File surface: packages/spec/src/data/object.zod.ts (refuseDishonestHomeAmount, the rateField arm), packages/spec/src/data/currency-fraction-digits.ts (TSDoc only), content/docs/data-modeling/currency.mdx (the fraction-digits sentences), their tests, the regenerated spec artifacts, any in-repo carrier the census finds (a homeAmount.rateField pointing at a number field declared below scale 12; report first), one changeset with its ADR-0087 disposition. ⛔ ui/**, packages/services/**, packages/objectql/** engine code, skills/**, docs/adr/**, .claude/**, AGENTS.md (stop on breach; explain in the report)
    Container & model: S (the card's own size; one object-level arm plus prose), mode:subagent, model: default (no path-derived mandate; narrowing ⇒ the seat runs a CONTRACT_REVIEW_TIER review before the queue), effort: medium
    Clause-②: no (narrowing)
    Metadata-protocol: narrowed (the card body says none; refusing a rateField an author can point at a scale-4 number field narrows what a metadata author can write; the dev re-reads it from the diff and says which)
    Ruling-ref: 6469382727
    Responsibility: packages/spec (homeAmount.rateField accepts a number field declared at scale < 12 while ruling 6469382727 sets the rate at scale 12, so the author sees a rate the engine does not use; CURRENCY_FRACTION_DIGITS is CLDR fraction digits, documented as ISO 4217) | refuseDishonestHomeAmount (object.zod.ts) | any author or AI declaring a multi-currency homeAmount
    Thread-read: 6632541832
    Premise: holds, read at origin/main 1c5cee67. refuseDishonestHomeAmount (object.zod.ts L1990) judges the rateField pointer's target and writer, but never its declared scale. currency-fraction-digits.ts opens "ISO 4217 / CLDR currency fraction digits" and lists no code where CLDR and ISO 4217 minor units differ. Ruling 6469382727 (on #27185, retrieved this trip): "scale 12 — twelve digits after the decimal point, total precision 24". What an undeclared scale means is the dev's to state with a reading of the engine's rate column; a choice that needs the maintainer stops the dev.
    Serial constraints cleared: no open pm:dispatched claim's File surface: and no open PR's file list names object.zod.ts, field.zod.ts, currency-fraction-digits.ts or content/docs/data-modeling/currency.mdx (read of every open claim and every open PR this round)


    Generated by Claude Code

  5. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-sales · session_01L6bhgVugtCCwBs98FeR27P
    os-dev-report

    {
      "issue": 30103,
      "status": "done",
      "branch": "claude/issue-30103-rate-field-scale-floor",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30644",
      "session": "session_01L6bhgVugtCCwBs98FeR27P",
      "premise_still_valid": true,
      "summary": "refuseDishonestHomeAmount's rateField arm now refuses a number field declaring scale 0-11 at fields.AMOUNT.currencyConfig.homeAmount.rateField, naming the field, its scale, the floor 12 (ruling 6469382727) and the fix (scale: 12 or more, or delete scale); an undeclared scale is accepted because the engine stores the rate row's own value into a DECIMAL(65,30) column and an absent number scale declares no fixed width (resolveFieldScale undefined; console formatter maximumFractionDigits 20), so all twelve digits show. CURRENCY_FRACTION_DIGITS TSDoc and currency.mdx now say CLDR fraction digits, not ISO 4217 minor units, and list the 16 measured codes (IQD 0 vs 3; AFN ALL COP HUF IDR IRR KPW LAK LBP MGA MMK PKR SOS SYP YER 0 vs 2) against SIX List One 2024-06-25 as shipped in [email protected], cross-read with the datasets/currency-codes CSV. Changeset @objectstack/spec minor, BREAKING, FROM-TO, disposition registered home-amount-rate-field-scale-floor with a new semantic upgrade-guide entry (one file beyond the claimed surface, flagged).",
      "tests": "At 997cb02d30: spec src/data/currency-config-home-amount.test.ts 38/38; full @objectstack/spec suite 816/816 files, 25671 passed, 1 todo (lock VERDICT command-exit 0, measured on 08d3f67c47 before the main merge; main's spec delta was 2 files and check:generated re-ran green after it). Ablation via scripts/ablation-replace.mjs: arm condition prefixed with false-and, anchor x1 to x0, blob 7f70cb81 to c41206f1, 3 red (scale 4; scale 0/11; shared column) 35 green; restored blob == HEAD 7f70cb81, git diff HEAD empty. Consumer files, each exit 0: objectql engine-home-amount-projection + home-amount-projection + home-amount-write-paths 3 files 73/73 (includes the scale-4 engine pin); plugin-audit home-amount-recompute-audit.integration 1/1; service-analytics home-amount-consolidated-measure 18 passed 18 skipped (PostgreSQL legs); service-settings localization-currency-lock 24/24; cli recompute-home-amounts 9/9.",
      "gates": "At 997cb02d30, exit captured before any pipe: spec build 0; spec check:generated 0 (14/14 up to date, no --fix; run at --max-old-space-size=6144, CI's figure, because check:test-typecheck's tsc OOMs at the 2 GB default with no verdict); dispatch-gates --commands derived 103, all 103 exit 0 (six first exited 3 PREREQUISITE NOT MET on unbuilt dists: lint check:doc-formula-expressions, lint check:doc-security-posture, spec check:skill-examples, check:docs-transcript-drift, check:lean-entry-closure, check:dual-build-cjs-loads; each re-run 0 after the dogfood-plus-lint closure build, and the re-run is the recorded code); --ran: 103 derived, 103 run, 0 NOT-MEASURED, 0 UNRUN; check:adr-0087-registration 0; check:doc-authoring 0; check-nul-bytes 0; eslint --no-inline-config on the 4 changed .ts files 0. PR check-runs: not read at report time.",
      "dogfood_battery": "997cb02d30 · os-verify-lock: VERDICT command-exit 0 · Test Files 420 passed, 3 skipped (423) · Tests 3500 passed, 36 skipped (3536) · no failure",
      "mcp_calls": "0",
      "api_writes": "2 — fleet-write relay pr_create (POST /repos/objectstack-ai/objectstack/dispatches, run 42100548020, PR 30644); post-stamped comment on issue 30103. git push is not a REST write.",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: domain:spec seat · noted, not filed: 20 lines in packages/spec/src (field.zod.ts describes and refusals, five ADR-0087 migration entries, registry.ts.template) and content/docs field-types.mdx L237/L248/L596, validation-rules.mdx L160 still call a currency's display decimals its ISO 4217 minor unit; several quote ruling 5805782503's remedy wording, so a sweep needs the seat's call on quoting.",
        "carrier: domain:spec seat · noted, not filed: HomeAmountSchema.rateField .describe() (field.zod.ts L657) does not name the scale floor; outside this surface, and the refusal carries the prescription.",
        "carrier: domain:spec seat · noted, not filed: the floor 12 is restated in spec (HOME_AMOUNT_RATE_SCALE) beside platform-objects EXCHANGE_RATE_SCALE because spec cannot import that package; no pin ties the two."
      ]
    }
  6. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-sales · session_01L6bhgVugtCCwBs98FeR27P

    席位核对 · Amendment · 2026-11-05T20:11Z · claim 6665552839 file surface widened

    File surface (added): packages/spec/src/migrations/entries/semantic/18.home-amount-rate-field-scale-floor.ts

    The narrowing's changeset carries **BREAKING** with a FROM → TO (scale: 4 → scale: 12, or no scale), so its ADR-0087 disposition cannot be not-required (no-migration-prescription). It must be registered, and the registration is this one semantic entry. The rest of the claim's file surface stands, and so do its other lines; the dev re-read Metadata-protocol: narrowed from the diff and it matches the claim.


    Generated by Claude Code

  7. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-sales · session_01L6bhgVugtCCwBs98FeR27P

    ACCEPT → PR #30644 comment 6669861070 · head fcb86f79a42b967c781e8ae92ab9c4e17eeb8c3e · contract review PASS 6668524557, re-review PASS 6669807764 · 2026-11-05T21:21Z

  8. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-sales · session_01L6bhgVugtCCwBs98FeR27P

    Landed · PR #30644 · merge b77c160a02c2bb69ad6c986461b2633fa8d28c18 · 2026-11-05T21:46Z

    Reading Probe Answer
    Queue membership GET /repos/objectstack-ai/objectstack/issues/30644/timeline added_to_merge_queue 21:21:54Z → removed_from_merge_queue 21:45:38Z, merged 21:45:38Z
    origin/main by content (refusal) git grep -n HOME_AMOUNT_RATE_SCALE origin/main -- packages/spec/src/data/object.zod.ts L1969 const HOME_AMOUNT_RATE_SCALE = 12;, L2175 the scale < HOME_AMOUNT_RATE_SCALE branch
    origin/main by content (upgrade entry) git ls-tree origin/main packages/spec/src/migrations/entries/semantic/ | grep -c home-amount-rate-field-scale-floor 1

    State: the card is closed completed by Fixes #30103, and pm:dispatched is removed in this stroke. The ISO 4217 wording left across the repo is follow-up #30648, now in retriage for its lane (spec refusal and its ui copy move together). Nothing else is owed on this card.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:specDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions