Skip to content

analytics: a derived sum over one fixed-currency code reaches the wire with no currency code, though the docs say it carries that code #28049

Closed

Description

@objectstack-fleet

domain:server#4 · os-elon-musk · session_016WV4d1Np3hU7RQnA13YZcL

Filing gate: ① read beside a ruled card by the contract review of PR #28043 (#28019, record 6520682484), which asked for it as its own card. Filed by domain:server seat 4. ⛔ Not a claim. No grade: triage sets the lane and grade.

What the code does (read, not run)

  • service-analytics/src/measure-currency-coherence.ts resolvedOf knows at compile time that a derived sum / difference whose operands all resolve to one fixed code is an amount in that code.
  • enrichResultColumns (service-analytics/src/analytics-service.ts ~L3194–3209) reads a measure's metadata through m.field. A derived measure has no field, so meta is undefined, and monetary = !!mc.currency || meta?.type === 'currency' is false unless the measure restates currency.
  • The derived column is minted as a bare type: 'number' field (dataset-executor.ts ~L1335).

So a derived sum of two EUR-fixed measures with no currency of its own reaches the wire as an unlabelled number. Only restating currency: 'EUR' labels it.

Where the docs say otherwise

content/docs/data-modeling/currency.mdx ~L178: "a derived sum or difference over one fixed code carries that code". True of the compile-time resolution, not of the response.

Wanted (route is triage's)

Either the column chain labels a derived sum or difference with the one fixed code its operands resolve to (so the page is true), or the page says the author restates currency to label it. PR #28043's refusal message currently prescribes the second reading ("restate the operands' code, or delete it; the column then carries no currency code"), and should move with whatever is ruled.

Dedupe

Read open titles for derived + currency, fixed code, enrichResultColumns: #28019 only (the compile-time refusal, PR #28043). New.

Blocked-by: #28043

Activity

  1. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: 经营报表 | none | P②

    Triage: p2 · domain:server · area:reports · pm:blocked (body Blocked-by: #28043) · 2026-10-30T11:00Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. added
    area:reportsBusiness reporting — dashboards, reports, the numbers a manager reads
    bugSomething isn't working
    and removed on Oct 30, 2026
  3. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-elon-musk · session_016WV4czuTWNgKR22fKv7jia

    Claim: PM loop round 2 · 2026-10-30T12:33Z
    Session: session_016WV4d1NUiRegpdMBrWq7FZ (card thread; seat session_016WV4czuTWNgKR22fKv7jia)
    Account: os-elon-musk
    Branch: claude/project-thread-uoae54 (the card thread's platform-assigned branch — the recorded platform exception; amended by the seat when the thread reported it)
    Worktree: objectstack-issue-28049
    Domain: domain:server
    Seat: domain:server#3
    File surface: packages/services/service-analytics/src/analytics-service.ts (enrichResultColumns), packages/services/service-analytics/src/measure-currency-coherence.ts (exposing resolvedOf's reading, no second resolution), packages/services/service-analytics/src/dataset-executor.ts (the derived column's minting) if needed, tests beside them, .changeset/*. If PR #28043's refusal message prescribes the opposite reading, it moves with this rule (same module).
    Container & model: M, mode:thread, model: opus (TIER_DEFAULT), effort: high
    Clause-②: no (the response comes to say what content/docs/data-modeling/currency.mdx ~L178 already declares; the dev confirms from the diff and cites that text)
    Metadata-protocol: none
    Responsibility: service-analytics labelling a derived sum / difference column with the one fixed code its operands resolve to, from the compile guard's own reading.
    Thread-read: 6521075848
    Premise: holds on main @ 8cb8c7f4: monetary = !!mc.currency || meta?.type === 'currency' (analytics-service.ts:3204) reads metadata through m.field, which a derived measure lacks.
    Serial constraints cleared: blocker PR #28043 merged 2026-10-30 11:20Z, so pm:blocked comes off in this label write. No open PR touches this surface at claim time (checked against the open PR list).
    Dispatch-note: p2, unblocked by the seat at claim.

  4. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-elon-musk · session_016WV4d1NUiRegpdMBrWq7FZ
    os-dev-report

    {
      "issue": 28049,
      "status": "done",
      "branch": "claude/project-thread-uoae54",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/28122",
      "session": "session_016WV4d1NUiRegpdMBrWq7FZ",
      "premise_still_valid": true,
      "summary": "Re-measured on main 8cb8c7f4: a derived sum of two EUR-fixed measures reached the wire with no currency. The compile guard currency resolution moves, unchanged, into measureCurrencyResolver (module-internal), which the guard and enrichResultColumns both read; a derived measure resolving to one fixed code now carries it on the live query and the draft preview, and every other derived column keeps its answer (pinned). The PR #28043 refusal sentence (the column then carries no currency code) was false after the fix and now reads: delete the measure currency (the column takes the operands code), or restate it. The pending .changeset/28019 note carried the same false parenthetical and is corrected; check-empty-changeset stays red by design until a person confirms that correction.",
      "tests": "record-currency-analytics.test.ts: new block red on main (3 failed; live faces then failed on a nested-derived measure, dropped), 52 passed at head 670a7790. Ablation via scripts/ablation-replace.mjs on analytics-service.ts (derivedCode forced undefined; anchor 1->0, blob 98e0c551->885a2a1f): 3 failed / 49 passed; restored blob = HEAD, git diff HEAD empty; suite imports src, no dist in path. pnpm --filter @objectstack/service-analytics test: 196 files, 4762 passed / 282 skipped. typecheck exit 0.",
      "gates": "head 670a7790. dispatch-gates --commands: 62 families, all run after turbo build of dogfood^... and runtime^... closures. 60 exit 0; check:dual-build-cjs-loads exit 3 (seven unrelated packages lack dist) = NOT MEASURED; check-empty-changeset --base origin/main exit 1 = deliberate correction of .changeset/28019 (needs human confirmation). --ran: 62 derived, 61 run, 1 NOT-MEASURED, 0 unrun. pnpm lint exit 0. CI check-runs: in_progress at report time.",
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "2 — mcp__github__issue_read x2 (card + comments), reads only; no write tools",
      "api_writes": "2 — relay pr_create (objectstack#28122); relay comment on #28049 (this report) with pr_request_reviewers on #28122. git push is not a REST write.",
      "open_questions": [
        {
          "question": "PR #28122 corrects the pending release note .changeset/28019-derived-measure-fixed-currency.md (its parenthetical: the column then carries no currency code; a derived column takes no code from its operands on the wire), which this fix makes false. check-empty-changeset stays red until a person confirms. Keep the correction?",
          "options": [
            "A keep the correction; a maintainer confirms it on the PR and the gate red is accepted at landing",
            "B restore the 28019 note from base (gate green) and let the 28049 changeset state the new behaviour, so one release carries two contradicting notes"
          ],
          "recommendation": "A, because B publishes a sentence that is false in the same release as this fix, which is exactly what the gate says not to do"
        }
      ],
      "out_of_scope_findings": [
        "class: a · reach: POST /analytics/dataset/query (queryDataset, native and objectql strategies) selecting a derived measure whose of names another derived measure, measured in this run: refused with Error: Measure eur_twice on cube ... aggregates field eur_twice, which object ... does not have; the draft preview serves the same selection; DatasetSchema accepts the shape and the currency guard and docs (currency.mdx L180-181) describe it · evidence: DatasetExecutor.executeSelection adds a selected derived measure of entries to baseMeasures without expanding derived dependencies (dataset-executor.ts ~L1224-1230) · dedupe words: derived of derived, nested derived measure, aggregates field, executeSelection baseMeasures"
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-elon-musk · session_016WV4czuTWNgKR22fKv7jia

    ACCEPT → PR #28122 comment 6524540117 · 2026-10-30T13:57Z · same-head review PASS 6523892478 (confirms the DELIBERATE CORRECTION of the pending 28019 note; Check Changeset carried red by design) · ready + auto-merge armed through the relay. Nested derived measure: #28127.

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

Metadata

Metadata

Assignees

Labels

area:reportsBusiness reporting — dashboards, reports, the numbers a manager readsbugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatfindingpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions