You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
analytics seam: grouped results carry a per-row currency; cube door refuses an ungrouped aggregate over a record-mode field; guards on today's surface (multi-currency M0-3, epic #8345) #27187
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
维护者速读
改了什么: 分析契约(contracts/analytics-service.ts)分组结果逐行带 currency;cube 度量门拒收未按币种分组的 record 字段聚合;两条今天就该有的护栏:派生度量跨不同币种相加减拒收、度量写死的币种与 fixed 字段矛盾拒收。
Seam: the contract key (per-row currency on grouped results) — the spec seat owns it; consumer read in service-analytics both strategies (native SQL and in-memory).
Cube door: refuse an ungrouped aggregate over a record-mode field.
Guards: derived measure across differing resolved currencies; measure currency contradicting a fixed field — both at compile, both with ADR-0087 disposition.
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.
{
"issue": 27187,
"status": "done",
"branch": "claude/project-thread-oixqci",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27338",
"session": "session_01Utp6Ca8jzC2P7EAQvqjNBb",
"premise_still_valid": true,
"summary": "Contract key AnalyticsResult.fields[].currencyField (contracts/analytics-service.ts and the AnalyticsResultResponseSchema wire schema) names the dimension column grouping a record-mode amount's code field; service-analytics relays currencyField from sourceFieldMeta under record mode only and sets the pointer in enrichResultColumns (live + draft preview), with no currency on that column. New cube door (cube-record-currency-door.ts, in ensureCube after the field-type door, ahead of both strategies) refuses sum/avg/min/max over a record-mode amount not grouped by its code field, INVALID_FIELD/400, totals groupings included. New compile guards (measure-currency-coherence.ts from compileDataset, DATASET_INVALID/400): a measure currency contradicting a fixed field (or any over a record-mode amount), and a derived measure whose monetary operands provably differ in currency. Built on #27268's branch (Merge-after: #27268); PR is draft, assignee os-bill.",
"tests": "At 1276434b: service-analytics build+typecheck+test under the lock VERDICT command-exit 0, Test Files 195 passed (195), Tests 4724 passed / 282 skipped. New record-currency-analytics.test.ts 26/26 (native + objectql strategies, preview path, guards). Two moved pins: currency-mode-relay m_explicit_fixed JPY->EUR, query-dataset explicit-currency chain over a dynamic field. Spec tsc -p tsconfig.json 0 errors; vitest src/api/analytics.test.ts 34/34; check:generated all 14 up to date after a spec build. Ablations via ablation-replace.mjs (src-resolved, every leg restored blob==HEAD): door 8 failed/26; pointer 5 failed/26; guard A fixed arm 1 failed/26; guard B 6 failed/26 (first door and guard-B attempts were refused by the tool, replacement text not unique, re-run with unique text).",
"gates": "dispatch-gates --commands at 1276434b: 116 commands, each run with exit captured before any pipe; --ran with exit codes: 116 accounted, 112 run (all exit 0), 4 NOT-MEASURED exit 3 (plugin-teardown-shape --self-test: shallow clone; spec check:skill-examples: client SDK unbuilt; check:dual-build-cjs-loads: packages unbuilt; check:i18n: CLI unbuilt). Tree is behind origin/main (base #27268). PR check-runs: in_progress at report time, not awaited.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "0 — no MCP GitHub calls; reads were gh api REST reads",
"api_writes": "2 relay strokes — pr_create (POST /repos/objectstack-ai/objectstack/pulls draft + POST /issues/27338/assignees os-bill); this os-dev-report comment via post-stamped (POST /issues/27187/comments)",
"open_questions": [
{
"question": "Declaration lines: the dispatch fixes Clause-②: yes (widening) / Metadata-protocol: added, but the two compile guards refuse dataset metadata that compiled before (a narrowing).",
"options": [
"A keep yes (widening) / added with the changeset's BREAKING paragraph and adr-0087 not-required (no-migration-prescription), as shipped",
"B switch to yes (narrowing) / narrowed, which also owes the full dogfood battery on the final head"
],
"recommendation": "A for now, since the card and the dispatch chose it and the gates are green, but it is the seat's call: B is the literal AGENTS.md reading of a refused value."
},
{
"question": "Wire key spelling for the per-row currency.",
"options": [
"A currencyField (mirrors the authoring pointer; names a result column, as fields[].name does)",
"B a column-specific name such as currencyColumn"
],
"recommendation": "A, so one concept has one name across spec and wire. The contract review decides."
}
],
"out_of_scope_findings": [
"carrier: #8345 (Q6 third guard) (explicit measure currency over a dynamic field, app-crm precedent) — not in this card; noted in Acceptance notes, not filed",
"carrier: none · the enrichment and compile guards stand down on relationship-path amounts (account.amount), the same tier as the existing compile field-type door; the cube door does judge them · noted, not filed"
]
}
Activity
objectstack-fleet commentedon Oct 28, 2026
Claim: PM loop round 1 · 2026-10-28T14:00Z
Session:
session_01Utp6CbTZrFqRYNgjSaSbN5(epic PM,epic:#8345)Account:
os-billBranch:
claude/project-thread-oixqci(card threadsession_01Utp6Ca8jzC2P7EAQvqjNBb; the platform assigns the thread's one push branch — the recorded platform exception)Worktree:
objectstack-issue-27187Domain:
domain:specSeat:
epic:#8345File surface:
packages/spec/src/contracts/analytics-service.ts(seam key), generated references by tooling,packages/services/service-analytics/src(both strategies), tests,.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: highClause-②: yes (widening)
Metadata-protocol: added
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:dispatchedin 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, #27186, #27188.
Maintainer authority: Bill, project thread, 2026-10-28 「epic的卡你统一派」, 「并发可以5」, 「你自主完成后续阶段」, 「后续开发如何加速」 (audit 6467659191 on #8345).
objectstack-fleet commentedon Oct 28, 2026
epic:#8345#1 · os-bill · session_01Utp6Ca8jzC2P7EAQvqjNBb
os-dev-report
{ "issue": 27187, "status": "done", "branch": "claude/project-thread-oixqci", "pr": "https://github.com/objectstack-ai/objectstack/pull/27338", "session": "session_01Utp6Ca8jzC2P7EAQvqjNBb", "premise_still_valid": true, "summary": "Contract key AnalyticsResult.fields[].currencyField (contracts/analytics-service.ts and the AnalyticsResultResponseSchema wire schema) names the dimension column grouping a record-mode amount's code field; service-analytics relays currencyField from sourceFieldMeta under record mode only and sets the pointer in enrichResultColumns (live + draft preview), with no currency on that column. New cube door (cube-record-currency-door.ts, in ensureCube after the field-type door, ahead of both strategies) refuses sum/avg/min/max over a record-mode amount not grouped by its code field, INVALID_FIELD/400, totals groupings included. New compile guards (measure-currency-coherence.ts from compileDataset, DATASET_INVALID/400): a measure currency contradicting a fixed field (or any over a record-mode amount), and a derived measure whose monetary operands provably differ in currency. Built on #27268's branch (Merge-after: #27268); PR is draft, assignee os-bill.", "tests": "At 1276434b: service-analytics build+typecheck+test under the lock VERDICT command-exit 0, Test Files 195 passed (195), Tests 4724 passed / 282 skipped. New record-currency-analytics.test.ts 26/26 (native + objectql strategies, preview path, guards). Two moved pins: currency-mode-relay m_explicit_fixed JPY->EUR, query-dataset explicit-currency chain over a dynamic field. Spec tsc -p tsconfig.json 0 errors; vitest src/api/analytics.test.ts 34/34; check:generated all 14 up to date after a spec build. Ablations via ablation-replace.mjs (src-resolved, every leg restored blob==HEAD): door 8 failed/26; pointer 5 failed/26; guard A fixed arm 1 failed/26; guard B 6 failed/26 (first door and guard-B attempts were refused by the tool, replacement text not unique, re-run with unique text).", "gates": "dispatch-gates --commands at 1276434b: 116 commands, each run with exit captured before any pipe; --ran with exit codes: 116 accounted, 112 run (all exit 0), 4 NOT-MEASURED exit 3 (plugin-teardown-shape --self-test: shallow clone; spec check:skill-examples: client SDK unbuilt; check:dual-build-cjs-loads: packages unbuilt; check:i18n: CLI unbuilt). Tree is behind origin/main (base #27268). PR check-runs: in_progress at report time, not awaited.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0 — no MCP GitHub calls; reads were gh api REST reads", "api_writes": "2 relay strokes — pr_create (POST /repos/objectstack-ai/objectstack/pulls draft + POST /issues/27338/assignees os-bill); this os-dev-report comment via post-stamped (POST /issues/27187/comments)", "open_questions": [ { "question": "Declaration lines: the dispatch fixes Clause-②: yes (widening) / Metadata-protocol: added, but the two compile guards refuse dataset metadata that compiled before (a narrowing).", "options": [ "A keep yes (widening) / added with the changeset's BREAKING paragraph and adr-0087 not-required (no-migration-prescription), as shipped", "B switch to yes (narrowing) / narrowed, which also owes the full dogfood battery on the final head" ], "recommendation": "A for now, since the card and the dispatch chose it and the gates are green, but it is the seat's call: B is the literal AGENTS.md reading of a refused value." }, { "question": "Wire key spelling for the per-row currency.", "options": [ "A currencyField (mirrors the authoring pointer; names a result column, as fields[].name does)", "B a column-specific name such as currencyColumn" ], "recommendation": "A, so one concept has one name across spec and wire. The contract review decides." } ], "out_of_scope_findings": [ "carrier: #8345 (Q6 third guard) (explicit measure currency over a dynamic field, app-crm precedent) — not in this card; noted in Acceptance notes, not filed", "carrier: none · the enrichment and compile guards stand down on relationship-path amounts (account.amount), the same tier as the existing compile field-type door; the cube door does judge them · noted, not filed" ] }docs(adr): ADR-0144 takes the three should-fixes of contract review 6…
objectstack-fleet commentedon Oct 29, 2026
epic:#8345#1 · os-bill · session_01Utp6CbTZrFqRYNgjSaSbN5
Seat decision on os-dev-report
6480636054open questions (epic PM, 2026-10-29T01:30Z)fixed-only arms (a measurecurrencycontradicting afixedfield's code; a derived measure over two differentfixedcodes) are outside ruling6465431966([Decision] Currency, all of it: resume multi-currency (#8345) and in what shape, and one rule for an amount whose currency is not known (Studio's USD, the template's USD,fixed's CNY, the example's USD) #27119), whose C′ sentence names record-mode fields only, and outside ADR-0144's Decision. R1 has no authority to narrow there. PR feat(spec,service-analytics): record-currency analytics — grouped answers name a per-row currency, the cube door refuses an ungrouped amount aggregate, compile guards on measure currencies #27338 therefore confines both guards to record-mode amounts, and its lines areClause-②: yes (widening)/Metadata-protocol: addedwith no BREAKING paragraph. Tree evidence: feat(spec,service-analytics): record-currency analytics — grouped answers name a per-row currency, the cube door refuses an ungrouped amount aggregate, compile guards on measure currencies #27338 commit507ed8f9. (An interim instruction at 21:06Z on 2026-10-28 chose B; it is superseded by this decision after the ADR contract review on docs(adr): ADR-0144 multi-currency — record currency, dated rates, write-time home projection; dated note on ADR-0104 #27239 flagged the authority gap.) Whether the generalfixed-versus-fixedguard should exist is ADR-0144 Open item 12, carried to the maintainer on epic [Epic] multi-currency (shape C′): record currency, dated exchange rates, write-time home-currency projection — 17 children, R1/R2/R3 release pairing (ruling 6465431966) #8345.currencyFieldstays; the contract review on feat(spec,service-analytics): record-currency analytics — grouped answers name a per-row currency, the cube door refuses an ungrouped amount aggregate, compile guards on measure currencies #27338 may rename it.docs(adr): ADR-0144 takes the three should-fixes of delta review 6485…
Merge #27268 final head 9011464 into #27187
Merge #27268 head b6f152b into #27187