Skip to content

objectql: record-mode guards — blank code refuses the write; ungrouped sum/avg/min/max over a record-mode field refused; summary roll-up over one refused at registration (multi-currency M0-2, epic #8345) #27186

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 模式金额的币种码为空 ⇒ 拒写;sum/avg/min/max 跨 record 字段未按币种分组 ⇒ 拒收;summary 汇总 record 子字段 ⇒ 注册时拒收。
  • 为什么改: 今天 USD 100 + JPY 15000 = 15100(测量轮探针);这些门把静默错数变成响亮拒收。
  • 风险与回滚: 只对 record 字段生效;其它字段零查找。
  • 先看: record-validator.ts;engine-aggregate-field-type-door;summary 注册。
  • 两分钟验证: 测量轮的 fx_invoice 探针变成固定测试:混币 sum 被拒,分组 sum 通过。
  • 需要您做的: 无。

Task

  • Validator: ERR_CURRENCY_CODE_REQUIRED with the field named.
  • Aggregate door: refuse unless grouped by the code field; message carries the prescription (group, or use the home field).
  • Summary registration: refuse a roll-up over a record-mode child field.
  • Fixtures from 6041378776 (PROBE-A / PROBE-R) as tests on memory and SQLite.

Lane: server · Size: M · Review: default. Clause-②: no · Metadata-protocol: none.

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. added
    enhancementNew feature or request
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    domain:serverDomain lane — seat card indexed by label:pm:seat
    and removed on Oct 28, 2026
  2. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-28T13:58Z
    Session: session_01Utp6CbTZrFqRYNgjSaSbN5 (epic PM, epic:#8345)
    Account: os-bill
    Branch: claude/project-thread-1v9hrc (card thread session_01Utp6CboxRwQPbQZnhxyuzt; the platform assigns the thread's one push branch — the recorded platform exception)
    Worktree: objectstack-issue-27186
    Domain: domain:server
    Seat: epic:#8345
    File surface: packages/objectql/src (validator, aggregate door, summary registration, tests), rider packages/formula/src/formula-return.ts, the ADR-0112 extension ledger, .changeset/ (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: opus (TIER_DEFAULT; dispatch-gates --tier: no path-derived mandate), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: none
    Premise: holds
    Serial constraints cleared: no — builds on #27184's draft PR #27268 (branch claude/project-thread-0wmk7j) by maintainer-authorised acceleration; pm:blocked → pm:dispatched in this stroke, Blocked-by: lines stay as merge order; the PR stays draft and merges after #27268.
    Release pairing: R1 — ⛔ not released alone, pairs with #27184, #27187, #27188.
    Maintainer authority: Bill, project thread, 2026-10-28 「epic的卡你统一派」, 「并发可以5」, 「你自主完成后续阶段」, 「后续开发如何加速」 (audit 6467659191 on #8345).

  3. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#8345#1 · os-bill · session_01Utp6CboxRwQPbQZnhxyuzt
    os-dev-report

    {
      "issue": 27186,
      "status": "done",
      "branch": "claude/project-thread-1v9hrc",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/27339",
      "session": "session_01Utp6CboxRwQPbQZnhxyuzt",
      "premise_still_valid": true,
      "summary": "Three ADR-0144 guards in objectql: (1) validation/record-currency-code.ts refuses a row image holding a record-mode amount beside a blank code field with ERR_CURRENCY_CODE_REQUIRED / 400 (field = code field, amountField), judged on insert, by-id update (prior row + payload) and predicate update (matched rows + payload, read only when the payload touches the pair); the code is registered under @objectstack/objectql in the ADR-0112 ledger and the reference pages regenerated. (2) record-currency-aggregate-door.ts, after the aggregate x field-type door: sum/avg/min/max over a record-mode amount answers INVALID_FIELD / 400 unless groupBy names the code field, prescription first. (3) SchemaRegistry.registerObject refuses a summary roll-up (sum/avg/min/max) over a record-mode child field with INVALID_METADATA / 422 (RecordCurrencySummaryRefusedError), judged at whichever registration completes the pair. Declared rider (the #27184 dev's class-c finding): formula-return.ts currencyOf/inferFormulaReturn carry currencyMode 'record' + currencyField. Base: branch claude/project-thread-0wmk7j (#27268) at 5232c8b1; PR base main, Merge-after #27268, R1 pairing line in the body. File-surface addition approved by the epic PM at 14:03Z: packages/qa/dogfood/test/record-currency-probes.test.ts. Card assignee was set by the PM; not written here.",
      "tests": "Head 4201bb53. objectql src/record-currency-guards.test.ts: Tests 12 passed (12). dogfood test/record-currency-probes.test.ts on SqlDriver better-sqlite3 + SqliteWasmDriver: Tests 6 passed (6). Full objectql local project at a1954847: Test Files 478 passed (478), Tests 8911 passed (8911); full formula at a1954847: 58/58 files, 1534/1534 tests (later commits touch only the two new test files and generated reference pages). objectql typecheck incl. check:test-typecheck OK at 901cbb01; formula typecheck OK at a1954847; dogfood typecheck NOT MEASURED (unbuilt closure, no error line names the new file). Ablation via ablation-replace.mjs --delete on the committed tree, src-imported suite, restore blob == HEAD each leg: aggregate-door call 2 failed/12, insert code check 1 failed/12, registry summary throw 2 failed/12; by-id and predicate update call sites not ablated separately. No driver-memory arm: closed census (check:driver-memory-census); the rows-shaped in-memory aggregation face is covered in the objectql suite.",
      "gates": "dispatch-gates --commands (derived at a1954847, 120 families; includes #27268's paths; warned the base tree is behind origin/main). All 120 run; --ran reconciliation on 4201bb53: 116 run, 4 NOT-MEASURED, 0 UNRUN. Fixed in-PR after the first sweep: spec check:docs + check:generated (reference pages lacked the new code; regenerated via check:generated --fix, re-run exit 0), check:objectql-double-limit + check:query-options-erasure (new test double / option casts; re-run exit 0), check:dts-closure (red once mid spec rebuild; re-run exit 0). NOT MEASURED exit 3: check-plugin-teardown-shape --self-test (shallow), spec check:skill-examples (client-react unbuilt), check:dual-build-cjs-loads, check:i18n. Re-run on new head: check:error-code-casing, check:dispatcher-error-vocabulary, spec check:error-code-provenance, check:nul-bytes, check:engine-double-contract all exit 0. CI check-runs: in_progress at report time (not awaited).",
      "dogfood_battery": "n/a — no ! in the PR title and Clause-②: no without a (narrowing) arm",
      "mcp_calls": "4 — mcp__github__issue_read (get x1, get_comments x3); no MCP write tool",
      "api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls + POST /issues/27339/assignees), relay comment via post-stamped (POST /repos/objectstack-ai/objectstack/issues/27186/comments); plus git pushes",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — ADR-0144 has no rule for a row stored with a record-mode amount and no code before this guard (only reachable outside a released build, since record mode ships in the same R1 release); such a row is refused only when a write touches the amount or its code. In the PR's Acceptance notes."
      ]
    }
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:serverDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpm:epicpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions