Skip to content

spec(field): homeAmount: { field, rateDate, rateField? } on a record-mode amount — the stored home-currency projection declared by pointer (multi-currency M2-1, epic #8345; released with M2-2) #27191

Closed

Description

@objectstack-fleet

Blocked-by: #27184

Filing gate ③ (maintainer-directed). Ruling 6465431966 on #27119 (batch #421 item 2, Q1 = 乙-现在, maintainer 「同意立专题卡」 2026-10-28): the multi-currency epic resumes on #8345 in shape C′. Part of #8345. Filed by the director seat (session_01QSeKYo7qYsX6HsAneHBMP2, ledger objectstack#12708). ⛔ Not a claim. Workload row and precedents: 6464936321; design: 6464438764.

Ruling-ref: 6465431966

维护者速读

  • 改了什么: record 模式金额字段可声明 homeAmount:field 指向同对象上一个 dynamic 模式(组织本位币)的存储型币种字段(平台写、只读),rateDate 指向日期字段(无默认),rateField 必填,指向 number 字段(ADR-0144 D5:裁决 6465431966 D1「STORED with the rate used」+ D8 规则 2;PR docs(adr): ADR-0144 multi-currency — record currency, dated rates, write-time home projection; dated note on ADR-0104 #27239 契约复审 6468858562 M2)。
  • 为什么改: 合并报表要一个存下来的本位币金额。
  • 风险与回滚: 新增可选键;⛔ 不单独发版,与 M2-2 同一次发布,否则是声明而未兑现。
  • 先看: field.zod.ts CurrencyConfigSchema;object.zod.ts superRefine 臂。
  • 两分钟验证: 指错类型 / 漏 rateDate / 影子列是 fixed ⇒ 各自拒收带处方。
  • 需要您做的: 无。

Task

Lane: spec · Size: M · Review: CONTRACT_REVIEW_TIER. Clause-②: yes (widening) · Metadata-protocol: added · Skills-docs: updated here.

Epic: #8345 (parent; the epic PM dispatches pm:epic children; domain:spec children go to the spec seat's queue). Dedupe: #8345 thread, #27119 (ruled), the workload list 6464936321; no open card carries this slice.

Activity

  1. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

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

    Epic PM, executing maintainer ruling 6522614678 on #8345 (letter A: R2 development starts now, and only the R2 release waits for the customer's consolidation terms). This card goes first in the spec seat's queue: pm:epic is released (it never sits beside pm:queue), pm:queue + domain:spec stand, and priority is raised to p1, because #27198 and #27192 build on this card's branch once its PR is up. The pointer's shape does not depend on the customer's terms, since rateDate is author-declared.

    Ruling-ref: 6522614678

  2. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V

    Claim: PM loop round 3 · 2026-10-30T12:24Z
    Session: session_017ihL2fi9zfJhUTubyJYb6V
    Account: marchtian
    Branch: claude/issue-27191-home-amount-pointer
    Worktree: objectstack-issue-27191
    Domain: domain:spec
    Seat: domain:spec#4
    Ruling-ref: epic PM 6522692087 executing maintainer ruling 6522614678 on #8345 (letter A: "R2 development starts now, and only the R2 release waits for the customer's consolidation terms"; this card first in the spec queue, p1); ruling 6465431966 on #27119 (D1 "STORED with the rate used", D8 rule 2); ADR-0144 D5 (rateField required, correcting the card's rateField?; contract review 6468858562 M2 on PR #27239; "the homeAmount key never ships ahead of the engine")
    File surface: packages/spec/src/data/field.zod.ts (CurrencyConfigSchema gains homeAmount: { field, rateDate, rateField } on a record-mode amount, refused on fixed / dynamic), packages/spec/src/data/object.zod.ts (the superRefine arm that resolves the three pointers on the same object: field a stored currency field in dynamic mode, rateDate a date / datetime field, rateField a number field, each refused with a remedy; the home and rate fields marked platform-computed, read-only at the door), describe / guidance / baselines, skills/** currency guidance (Skills-docs: updated here), pin tests, regenerated spec artefacts, changeset (@objectstack/spec minor, held to ship with M2-2 by the release pairing the R1 key used). ⛔ No engine write path here (that is #27192); ⛔ the key must not reach a Version Packages release ahead of the engine (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: TIER_DEFAULT (opus) — the quota-exhaustion exemption (claude-fable-5-1 answered HTTP 429; maintainer 「你没有fable了,使用 opus开发完之后等契约复审」), effort: high. Governed skills/** ⇒ Tier H, the maintainer approves in the PR
    Clause-②: yes (widening)
    Metadata-protocol: added
    Responsibility: a record-mode amount (multi-currency M0-1, #27184) has no way to declare the stored home-currency amount that consolidated reports read | ADR-0144 D5: the amount field declares homeAmount by pointer and the engine (M2-2, #27192) writes it at the document date's rate, stored with the rate | every multi-currency deployment that builds a consolidated report (epic #8345, R2); #27198 and #27192 build on this branch once its PR is up
    Thread-read: 6522692087
    Premise: holds — on 549203d040 CurrencyConfigSchema carries currencyMode: 'record' + currencyField (field.zod.ts:538–575, #27184 closed, PR #27268 merged) and no homeAmount; the object-level currencyField resolver arm is at object.zod.ts:1857–1904; ADR-0144 D5 is on main (docs/adr/0144-*.md:188–203)
    Serial constraints cleared: no open PR touches field.zod.ts, object.zod.ts, ADR-0144 or the currency skills text (open PR file lists read just before this claim). #27198 and #27192 branch from this PR's head once it is up

  3. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V
    os-dev-report

    Reported at 2026-10-30T15:24Z on head 361f8f25cc.

    {
     "issue": 27191,
     "status": "done",
     "branch": "claude/issue-27191-home-amount-pointer",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/28096",
     "head": "361f8f25cc",
     "session": "session_017ihL2fi9zfJhUTubyJYb6V",
     "premise_still_valid": true,
     "summary": "CurrencyConfigSchema gains homeAmount {field, rateDate, rateField}: a closed shape, all three pointers required and non-empty, refused outside record mode. ObjectSchema superRefine gains refuseDishonestHomeAmount: the amount must be a stored currency field; field must name another dynamic-mode currency field that no other amount already claims; rateDate a date/datetime field; rateField a number field, shared only by amounts with the same currencyField and rateDate; the home and rate fields must declare readonly: true (the existing platform-written mark) and no expression. Skills text, changeset (spec + skills minor, R2 pairing line), ADR-0144 D5 anchors, regenerated artifacts, and a form-reconciliation omit for homeAmount.",
     "tests": "packages/spec currency-config-home-amount.test.ts: 30 tests (every refusal pinned with code + path + first message clause, plus the accepted shapes and idempotence). @objectstack/spec full suite at 361f8f25cc: Test Files 757 passed (757), Tests 22540 passed, 1 todo (VERDICT command-exit 0). An earlier run at 6db7ac8584 had 1 failure, metadata-form-zod-reconciliation: field.currencyConfig homeAmount accepted by Zod but not offered in the form; fixed in 361f8f25cc with a planned-key ledger omit. @objectstack/spec typecheck exit 0 (includes check:test-typecheck OK). Ablation on committed head 6db7ac8584 via scripts/ablation-replace.mjs: the readonly arm in refuseUnlessPlatformWritten was mutated to accept any non-expression field (anchor 1->0, blob bb901f14->56e3f35b). Exactly the 2 readonly pins went red (2 failed / 28 passed), and the file was restored to the HEAD blob with git diff HEAD empty. The test imports src by relative path, so no dist was involved.",
     "gates": "dispatch-gates --commands at 361f8f25cc derived 118 families (identical to the list at 6db7ac8584). Each was run with its exit code recorded before any pipe: 117 exit 0, and 1 exit 3, pnpm check:dual-build-cjs-loads, PREREQUISITE NOT MET because it needs every workspace package built. --ran reconciliation exit 0: 118 accounted, 117 run, 1 NOT-MEASURED, 0 UNRUN. On the first pass, 5 more families exited 3 (lint doc-formula-expressions and doc-security-posture, spec check:skill-examples, check:docs-transcript-drift, check:lean-entry-closure); they went green after the lint, client-react and objectql closures were built. Local-only families: check:skill-frame-freshness exit 0; check:dev-prereqs exit 1 (the local workspace is not wholly built, which is machine state, not a finding); check-nul-bytes exit 0. check-skills-token-ratchet: field-types.md 3207 -> 3181 tokens, within its ceiling. spec check:generated: all 14 artifacts current. CI at 361f8f25cc: 50 check runs, 41 success, 9 skipped, 0 failed. Success includes Lint & Repo Gates, TypeScript Type Check, Test Core 1-8/8, Test UI, Type Check UI, Build Core, Build & E2E UI, Live E2E UI, Check Changeset, Governed Surface Queue Guard, PR-body guards and Dogfood Regression Gate. Skipped: Lint UI and Test UI shards (no ui change), plus the opt-in and schedule-gated jobs.",
     "dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm",
     "line_budget": "PR own diff vs merged main 8cb8c7f461: 13 files, +607 -42 (generated: 5 files, +22 -11). skills: field-types.md 323 -> 304 lines, 3207 -> 3181 tokens. Bundle: all skills .md 17864 -> 17845 lines, 219711 -> 219685 tokens; SKILL.md sum 4609 -> 4609 lines.",
     "files_changed": [
      ".changeset/27191-home-amount-pointer.md",
      "content/docs/references/data/field.mdx",
      "content/docs/references/data/object.mdx",
      "content/docs/references/system/migration.mdx",
      "docs/audits/2026-07-unknown-key-strictness-ledger.counts/data.md",
      "packages/spec/authorable-surface/data.json",
      "packages/spec/src/data/currency-config-home-amount.test.ts",
      "packages/spec/src/data/field.zod.ts",
      "packages/spec/src/data/object.zod.ts",
      "packages/spec/src/system/metadata-form-zod-reconciliation.test.ts",
      "scripts/adr-anchors/packages__spec__src__data__field.zod.ts.json",
      "scripts/adr-anchors/packages__spec__src__data__object.zod.ts.json",
      "skills/objectstack-data/rules/field-types.md"
     ],
     "deviations": [
      "Studio field form: not mirrored from R1. The R1 template offered currencyField as a field.form.ts row. homeAmount is instead a planned omit in the metadata-form-zod-reconciliation ledger, because nothing writes it until the engine lands (the precedent is the print / record / conditionalFormatting spec-first keys). The PR body's Not-touched note is true, but its Tests and Generated bullets do not list this ledger file or the regenerated docs/audits strictness-ledger counts. Body correction for the seat to make: add both files.",
      "Refusals beyond the card's list (contract-review items): homeAmount on a formula or other non-currency amount; a home field claimed by two amounts; a rate field shared by amounts with a different currencyField or rateDate; an expression on the home or rate field. Missing and empty pointers each carry their own remedy message.",
      "PR body attribution: the two session lines are at the top, per the order, not at the end as the harness reminder suggests. No extra footer was added.",
      "Lock narrowing: spec check:generated --fix waited 2 x 540s without the lock (holder issue-27864). Ran instead, unlocked: gen:schema, gen:docs and gen:strictness-ledger against the dist built earlier under the lock. check:generated was then green.",
      "Merged origin/main once before opening the PR (49b193446a, clean). HEAD is now about 34 commits behind origin/main. Not re-merged: no conflict, no main-caused red.",
      "Fable review not run (order override); the PR stays draft."
     ],
     "release_hold": "Nothing mechanical holds the key. The R1 template (#27268) was held only by a PR-body pairing line, a changeset sentence and the maintainer's hand on Version Packages (PD #15; epic #8345: the maintainer merges VP only when a pair is complete). This PR carries the same two markers. No gate, ledger, release-pending-publish mode or changeset pre mode reads them. Once merged, the changeset joins the standing Version Packages PR #26517 with everything else pending. The R2 sibling .changeset/27185-exchange-rate-table.md is already on main in that state.",
     "mcp_calls": "0",
     "api_writes": "2: POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create, run 41056893317, read back identical 9141/9141 bytes) and this os-dev-report comment through post-stamped. Plus 5 git pushes, which are not REST writes.",
     "open_questions": [
      {
       "question": "Land order versus release: should #28096 merge only once #27192 is ready, or merge now and rely on the maintainer holding Version Packages until R2 is complete?",
       "options": [
        "A merge now; the maintainer holds VP until #27192 lands",
        "B keep #28096 unmerged until #27192 is ready to land in the same window"
       ],
       "recommendation": "A, because siblings #27198 and #27192 build on this branch, and the #27185 changeset already sits in VP the same way. The seat should tell the maintainer that the hold is manual."
      },
      {
       "question": "Who offers homeAmount in the Studio field form (the planned omit added here)?",
       "options": [
        "A #27192 removes the omit and adds the row when the engine writes",
        "B #27196 (M3-2, home field UI)"
       ],
       "recommendation": "B, because it is the ui card that already owns the home-field presentation."
      }
     ],
     "out_of_scope_findings": [
      "class: none (note) · reach: consumer none until #27192 · evidence: FieldSchema.readonly strips every non-system write of the field on insert and update. The write-time projection must store the home amount and the rate through a system-context write or after the strip, or the engine's own write is dropped · carrier: #27192",
      "class: none (note) · reach: none · evidence: content/docs/data-modeling/currency.mdx (hand-written) does not mention homeAmount · carrier: #27189 family or the R2 docs card; noted, not filed",
      "class: none (note) · reach: none · evidence: a rateField declaring scale below 12 makes every converting write refuse with max_scale (the rate has scale 12 per ADR-0144 D7). The refusal is loud, not silent, so no spec refusal was added · carrier: #27192"
     ]
    }
  4. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V

    Landed · 2026-10-31T03:21Z · PR #28096 merged by the queue at 2026-10-31T03:21Z as 73b7270960; the card closed by Fixes. This seat strips pm:dispatched in the same act. os-zhuang approved it (Tier H, skills/**). Contract review: PASS 6526217217 on the reviewed head, and delta PASS 6538122473 on the merge-forward head that landed. Should-fixes are filed: #28205 (one message for both faults), #28203 (the skills date/datetime wording, the currencyConfig row, the ADR-0144 Open item 1 amendment); the defaultValue and preserveAudit import-door note sits on #27192. Release note: currencyConfig.homeAmount declares the pointer only; the write-time conversion is #27192, so a release cut before #27192 lands ships a declared-but-unconverted home amount.

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:specenhancementNew feature or requestpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions