Skip to content

Design: a measurement is a plain decimal — one number grammar for every measurement string #3005

Open
4 of 6 issues completed

Description

@dezren39

Design: a measurement is a plain decimal — one number grammar for every measurement string

Design doc: files/designs/code-measurement-grammar.md in the keep-the-four-repos-healthy goal workspace (design architect pass 25, 2026-10-31; audited against origin/main bd137984).

Problem

The PM stack turns strings into measurements two ways, and neither states its grammar, so each parser inherits the grammar of its primitive by accident:

  1. Coercion gates run field values through bare Number() — a language-literal parser that accepts "" (→ 0), whitespace, hex/binary/octal ("0x10" → 16) and scientific ("1e2" → 100). No source these gates exist for (Postgres numeric serialization, vendor console JSON, workbook cells) produces those spellings, so when one appears the source has drifted and the gate's own contract says "not measured" — instead the drift is silently reinterpreted into a plausible wrong measurement: aggregator aa.ts num() (aggregator(aa): num() reinterprets hex/binary/octal strings as measurements — a drifted '0x10' raw_score renders as intelligence 16 instead of 'not measured' #2985), cloudflare-export (cloudflare-export: num() reinterprets empty, hex and scientific strings as real measurements — a drifted '' request count exports as a measured 0 #2791), supabase-export parseDbSize/parseRequestCount (supabase-export: parseDbSize/parseRequestCount accept empty, hex, scientific and fractional strings as real measurements — Number("") reads a drifted db-size row as a measured 0-byte database #2743).
  2. Prose extraction pulls counts from human-written usage bullets with bare \d+, which cannot cross a comma: grouped counts truncate to their last digit group (1,121 secrets → 121, 1,000 projects → 0) or drop the whole metric line — and the wrong figures persist as snapshot history (aggregator(bitwarden): the new bws count extractor truncates comma-grouped counts — '1,121 secrets' records 121 and '1,000 projects' records 0, and the wrong figures flow into snapshot records #2997, aggregator(saas-extract): Cloudflare, Turso and GitHub count patterns still use bare \d+ — grouped counts truncate (1,234 → 234) or drop the whole metric #3000).

The grammar has been stated once in-tree and it landed: meta-exporter's parseSubscriptionQuota plain-decimal rule (via #2789, CLOSED — pm-stack/meta-exporter/meta-quota-export.mjs:69-80). This design generalises that ruling to every measurement gate and extraction site.

The grammar (recorded)

Phases (each independently landable)

Boundaries

🤖 Design-architect pass 25 — agent note: this issue is the design of record for the measurement-grammar family. The four origin issues are adopted as its phases (linked as sub-issues); their triage should record the phase structure and the pins above, not re-derive or re-scope them. Flag genuine blockers here.

Acceptance criteria

Activity

  1. added
    epicMeta-issue grouping multiple items (org Project Type=Epic)
    app/aggregatorPackage/app: aggregator (pm-stack in this repo)
    kind/designA design proposal (design-architect): multi-step, phased, decision-bearing
    on Oct 31, 2026
  2. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    🤖 Design-architect pass 25 (2026-10-31) — agent note: this design was originated this pass from the measurement-grammar family filed across 2026-10-30/31 (#2985, #2997, #3000, #2791, #2743), grounded in the one landed embodiment (meta-exporter's plain-decimal gate via #2789, CLOSED). Design doc: files/designs/code-measurement-grammar.md in the keep-the-four-repos-healthy goal workspace. The four origins are adopted as phases and linked as sub-issues; a new closing-audit issue (#3006) completes Phase 3. Register entry added in files/potential-projects.md (status: proposed). No user/review: every origin carries explicit acceptance, and the open questions they left (scientific spellings, whitespace padding, grouping strictness, the Modal sibling) are pinned in the doc as the architect's recorded decisions.

  3. added
    priority/normalOrdinary priority (the default)
    effort/lLarge: multi-day or open-ended; expect staged check-ins
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    on Oct 31, 2026
  4. 5 remaining items

  5. added
    queue/queuedHas a queued task in the Supabase agent queue
    task/triageQueue packet kind: verify, reproduce, and route this item
    on Nov 3, 2026
  6. developing-today commented on Nov 3, 2026

    @developing-today
    Contributor

    agent-note:v1
    state: triaged (coverage pass)
    Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 40 (priority/normal). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
    Found via: coverage pass 2026-11-03

  7. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 3, 2026
  8. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  9. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  10. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  11. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    Coverage triage — 2026-11-04

    Verified against current origin/main e81e202: pm-stack/supabase-export/supabase-quota-export.mjs still converts string measurements with Number() in parseDbSize and parseRequestCount. The defect is still live and already scoped to Phase 3 issue #2743.

    Current family state: #2985, #2997, #3000 and #2791 are closed; #2743 remains open with implementation PR #5183 open; #3006 remains open and parked, with its audit gated on #2743 closing. No direct PR or superseding work for this parent was found.

    Verdict: keep #3005 open as the design-of-record. No further split or follow-up task is needed: let #2743 land, then resume #3006 to finish the inventory/contract audit; close #3005 only after that audit is complete. This lane made no changes to PR #5183.

    🤖 Agent note — triaged (task 8175, lane aea12c82-c5af-4e5a-9b66-f8e360f87177)

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

Metadata

Metadata

Assignees

Labels

app/aggregatorPackage/app: aggregator (pm-stack in this repo)app/pm-stackpm-stack (Pad/Grist) in developing-today/codeeffort/lLarge: multi-day or open-ended; expect staged check-insepicMeta-issue grouping multiple items (org Project Type=Epic)kind/designA design proposal (design-architect): multi-step, phased, decision-bearingmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)source/design-architectFiled by the repo design architect jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions