Skip to content

spec(data): add a shared NULL-distinct unique conformance case-set beside value-roundtrip and the filter sets, so every driver proves two NULLs do not collide #29377

Closed

Description

@objectstack-fleet

domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

Ruled: 6595804527 · letter A · 2026-11-03T04:55Z
Ruling-ref: 6595804527

Filing gate: ③ escalation of the server lane's contract review on #29278 (record 6577415377), recorded in its landing note 6578310168: the card's "Wanted" case-set lives in packages/spec/src/data, outside the server lane's claim. Handed to the spec lane. ⛔ Not a claim. No grade: triage sets it.
Reader: domain:spec (the case-set and its census registration); each driver's adoption follows in its own lane.

What is missing

PR #29339 (#29278) made driver-mongodb treat two null values in a unique field as distinct, matching driver-sql and driver-memory. The agreement is measured in that PR, but no shared case-set asserts it, so a fourth driver (or a regression in one of the three) can collapse NULLs onto one key and every driver-conformance cell stays green. It is the gap value-roundtrip-conformance.ts describes for value storage: no case-set, no evidence.

Done when

  • packages/spec/src/data/unique-null-distinct-conformance.ts (name per the house pattern) declares the canonical cases: two rows with null in a unique field both insert; an absent value behaves as null; two equal non-null values still collide with the driver's unique refusal; a compound unique key with one null member does not collide (measure what the three drivers do today before writing that row, and cite the measurement — every row is a measured value or a control, as in value-roundtrip).
  • The case-set is registered with the driver-conformance census (scripts/check-driver-conformance.mjs) the way the existing sets are, so a driver that does not run it is scored.
  • Spec patch, Clause-②: no · Metadata-protocol: none (test-support export only; if the census needs a new public export name, it is named in the PR for the maintainer).
  • Driver adoption (driver-sql, driver-memory, driver-mongodb, then the rest) follows in the drivers' lane, one PR each, citing this card.

Dedupe: #29278 / PR #29339 (landed, the mongodb fix). New.

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Nov 2, 2026
  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p3 · domain:spec · pm:queue · 2026-11-02T14:55Z

    ⛔ Not a claim.

    • Read fresh. A shared NULL-distinct unique conformance case-set in packages/spec/src/data, so every driver proves that two NULLs do not collide. Each driver adopts it in its own lane. p3.

    Generated by Claude Code

  3. added
    domain:specDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Nov 2, 2026
  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

    Claim: PM loop round 1 · 2026-11-02T15:10Z
    Session: session_01ADHkmPi25XXKx92Xmg4viS (seat); dev = card thread session_01ADHkmR216nE71oPFuQMyRt
    Account: os-steve
    Branch: claude/project-thread-ndw3ol
    Worktree: the card thread's own checkout of objectstack-ai/objectstack
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: new packages/spec/src/data/unique-null-distinct-conformance.ts and its test; its export * line in packages/spec/src/data/index.ts; the case-set entry and the tracked not-yet-covered driver cells in scripts/check-driver-conformance.mjs (and its self-test or baseline if the script keeps one); api-surface and generated ledgers the spec gates move; root .changeset/; no driver package (adoption is the drivers' lane, one PR each, citing this card) (stop on breach; explain in the report)
    Container & model: S, mode:thread, model: default — the tier is the PM's per-card call (floor sonnet · default opus · ceiling fable); one CONTRACT_REVIEW_TIER review (a new export under packages/spec/src) before landing, effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: packages/spec src/data has no NULL-distinct unique case-set | a fourth driver or a regression can collapse NULLs onto one key while every conformance cell stays green | every driver that stores a unique field
    Thread-read: 6580288651
    Premise: holds (on origin/main no *-conformance.ts under packages/spec/src/data covers unique NULL behaviour; PR #29339 measured the agreement but pinned no shared set)
    Serial constraints cleared: no open PR names data/index.ts or check-driver-conformance.mjs

    Every row is a measured value or a control. If the three drivers disagree on the compound row, the dev stops and reports it, because that is a ruling, not a row. The new exported names are listed in the PR body. The seat decides whether the maintainer owes a ruling on them.

  5. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmR216nE71oPFuQMyRt
    os-dev-report

    {
      "issue": 29377,
      "status": "done",
      "branch": "claude/project-thread-ndw3ol",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29509",
      "head": "95584d2d",
      "session": "session_01ADHkmR216nE71oPFuQMyRt",
      "premise_still_valid": true,
      "summary": "New packages/spec/src/data/unique-null-distinct-conformance.ts: UNIQUE_NULL_DISTINCT_CASES (10 cases: null/absent/'' and equal values on a field-level unique; one-null, leading-null, absent-part, equal and differs-in-one-part on a declared two-column unique index, both scopes 'global'), UNIQUE_NULL_DISTINCT_OBJECTS, UniqueNullDistinctCase, uniqueNullDistinctDivergence (judges the second write AND the stored count). Test runs the table on a reference store and proves six wrong readings each fail it. data/index.ts export, census CASE_SETS row plus six DEBT ledger rows citing #29377 (no driver package touched), spec patch changeset, regenerated api-surface and export-origins. The compound row was measured first: driver-memory and driver-sql agree on 10/10; driver-mongodb agrees on the six rows PR #29339 ran on a real mongod, no disagreement, so no ruling was needed.",
      "tests": "Head 95584d2d (main merged at 6af3d295): turbo build packages/** exit 0; spec test Test Files 793 passed (793), Tests 23542 passed, 1 todo; spec typecheck exit 0; new file 23/23. Pre-merge head 7f4de58d: spec test 792 files / 23492 tests green. Driver measurement on origin/main f95d0dba via a scratch tsx script over the built dists: memory 10/10 agree (refusals UNIQUE_VIOLATION), sql better-sqlite3 10/10 agree (refusals SQLITE_CONSTRAINT_UNIQUE), every first write admitted. driver-mongodb mongodb-unique-null-distinct.test.ts 7 passed, 8 skipped (real-mongod opt-in). No ablation: no previously pinned behaviour changed; the test's six wrong readings are the non-vacuity proof.",
      "gates": "dispatch-gates --commands on 95584d2d: 101 derived, all exit 0 (captured per command before any pipe); --ran: 101 run, 0 NOT-MEASURED, 0 UNRUN. check:generated 14/14 current after --fix. check-driver-conformance OK (66 covered, 6 DEBT, 0 exempt) and --self-test OK. check-changeset-no-major --base origin/main --event (PR body) exit 0, Clause-②: no, Metadata-protocol: none. eslint --no-inline-config over the 4 touched sources exit 0. PR check-runs: in_progress at report time (not waited on).",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "files_changed": [
        ".changeset/29377-unique-null-distinct-conformance.md",
        "packages/spec/api-surface/data.json",
        "packages/spec/export-origins/data.json",
        "packages/spec/src/data/index.ts",
        "packages/spec/src/data/unique-null-distinct-conformance.test.ts",
        "packages/spec/src/data/unique-null-distinct-conformance.ts",
        "scripts/check-driver-conformance.mjs"
      ],
      "line_budget": "594 additions / 6 deletions over 7 files (S card); every file inside the claim's file surface",
      "deviations": [
        "driver-mongodb was not measured live: fastdl.mongodb.org is blocked and this session's permission layer refused fetching the conda-forge mongod build. Its six real-mongod rows are cited from PR #29339; the other four are derived from its pinned partial-filter index shape and declared as such in the docblock and the ledger row.",
        "Merged origin/main before opening the PR (main had moved api-surface/data.json and export-origins/data.json): os-regen-merge.sh step 3 refused as designed, then check:generated --fix and a separate regen commit; the full round was rerun on the merged head.",
        "PR opened without assignees or reviewers (os-dev forbids assignees on pr_create and MCP writes); the harness's assign-and-request-review step was skipped.",
        "Did not subscribe to PR activity: the dispatch contract overrides the platform's auto-subscription; the seat drives CI."
      ],
      "mcp_calls": "3 — mcp__github__issue_read (get, get_comments), mcp__github__pull_request_read (get); no write tool",
      "api_writes": "2 — relay pr_create (repository_dispatch fw-20261102T170257Z-6ada1a, PR #29509) and this os-dev-report comment via post-stamped.mjs; plus 3 git pushes (not REST writes)",
      "open_questions": [
        {
          "question": "Four new public names under @objectstack/spec (data): UNIQUE_NULL_DISTINCT_CASES (the census marker), UNIQUE_NULL_DISTINCT_OBJECTS, UniqueNullDistinctCase, uniqueNullDistinctDivergence. Does the maintainer owe a ruling on them?",
          "options": ["A — accept as spelled: they follow the sibling case-sets (VALUE_ROUNDTRIP_CASES / VALUE_ROUNDTRIP_FIELDS / ValueRoundTripCase / valueRoundTripDivergence)", "B — rename before landing"],
          "recommendation": "A, because the census only discovers `export const *_CASES` and each other name mirrors an existing sibling's role and spelling."
        },
        {
          "question": "The census marks ledger growth MAINTAINER-ONLY; this PR adds six DEBT rows because the card lands the case-set ahead of every driver. Is the card plus the maintainer's review of this PR enough agreement, as with FILTER_TEXT's five rows?",
          "options": ["A — yes, the rows ride this PR and each driver's adoption PR deletes its row", "B — enrol one driver in this PR to shrink the ledger (outside the claim's surface)"],
          "recommendation": "A, because the claim forbids touching driver packages and the rows make 'ahead of its suites' a counted fact."
        },
        {
          "question": "driver-odata's syncSchema is a no-op (the remote service owns constraints). Its row is DEBT like the others; should its adoption card make it EXEMPT instead?",
          "options": ["A — leave DEBT; the adoption card decides suite vs EXEMPT", "B — EXEMPT now"],
          "recommendation": "A, because EXEMPT is a measured claim and nothing was measured on odata here."
        }
      ],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: the drivers' lane adoption cards (one per driver, citing #29377) · the update door (clearing a unique field to null by update()) is measured only on driver-mongodb, so it is named as absent from the table; an adoption suite or a follow-up row can add it once memory and sql are measured · noted, not filed"
      ]
    }

    Stamped 2026-11-02T17:04Z.


    Generated by Claude Code

  7. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

    Claim amendment on #29377 (amends claim on this card) · 2026-11-02T17:06Z

    Clause-②: no becomes Clause-②: yes (widening). The case-set adds four public exports to @objectstack/spec (UNIQUE_NULL_DISTINCT_CASES, UNIQUE_NULL_DISTINCT_OBJECTS, UniqueNullDistinctCase, uniqueNullDistinctDivergence), and the lane rule counts widening the public surface as yes. Metadata-protocol: none stays: these are test-support exports with no metadata wire shape. This corrects the seat's own claim line, so it is not a deviation by the implementer.

    The four names are accepted as spelled. They mirror the value-roundtrip set, and choosing a name is the seat's call. odata stays a DEBT row for its own adoption card.

  8. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

    Decision needed · six new DEBT rows in the driver-conformance ledger · 2026-11-02T17:07Z

    维护者速读

    Seat recommendation: A. On A, the seat lands PR #29509 after its review. On B, the card thread adds the three drivers' suites and drops their rows. On C, the census row and its six DEBT rows come out, and each adoption card registers the set.

  9. added
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    and removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Nov 2, 2026
  10. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

    Hand-off · spec seat 1 going offline · 2026-11-02T21:54Z

    Spec seat 1 is closing for the day on the maintainer's word 「spec 车道当前任务处理完就下班」. This card is still waiting on the "Decision needed" above (6583288338), about the six DEBT rows in the ⛔ MAINTAINER-ONLY driver-conformance ledger. It stays needs-user-decision, and the seat releases its hold on it.

    For whichever spec seat picks it up once ruled:

    • PR spec(data): a shared NULL-distinct unique conformance case-set, scored by the driver census #29509 (branch claude/project-thread-ndw3ol, head 0c0e86d0, draft) passed the contract review on that head, with A landable as built.
    • On A:
      1. The head is hours old. Regen-merge origin/main (scripts/pm/os-regen-merge.sh), then run the full spec test + test:repo + check-driver-conformance.
      2. Carry the PASS forward as merge-only.
      3. Ready + automerge.
    • On B: the card thread adds the sql, memory and mongodb suites and drops their three rows. That needs a delta review. Mongo in a container needs conda-forge mongod.
    • On C: take the census row and its six DEBT rows out. That also needs a delta review.
    • The seat-1 brief for this card is /mnt/project-files/spec-seat1/29377-delta.md.
  11. os-support-ai commented on Nov 3, 2026

    @os-support-ai
    Collaborator

    decision thread · os-support-ai · session_01WGufzepGFmf3XtoZaZuheq

    Ruling: decision thread "Discuss pending spec rulings" item 1 · letter A · maintainer 「同意」 2026-11-03T04:55Z

    The maintainer was presented the "Decision needed" above (6583288338) with the recommendation A in the project thread, and answered 「同意」 = the recommendation on every item presented, so this card's letter is A.

    What the ruling binds (letter A):

    Workload of the letter: none beyond PR #29509 as built; the seat regen-merges origin/main, reruns the spec suite + test:repo + check-driver-conformance, carries the PASS forward as merge-only, then ready + automerge (the hand-off's "On A" steps, 6589445500).

    Execution: spec seat 2 (which holds PR #29509) lands it with Ruling-ref: naming this comment; the needs-user-decision → pm:queue / pm:dispatched stroke is that seat's. The Ruled: body line is written by this act.


    Generated by Claude Code

  12. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    on Nov 3, 2026
  13. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-support-ai · session_01WGufzhJG3tKnksHVa1krBz

    Claim: PM loop round 3 (resume, land as built)
    Session: session_01WGufzhJG3tKnksHVa1krBz
    Account: os-support-ai
    Branch: claude/project-thread-polo9l (card thread, executor session_01WGufzfXhPVhbNCfA7cqGdi; the thread can push only its own branch, the measured platform exception to claude/issue-29377-…)
    Worktree: objectstack-issue-29377
    Domain: domain:spec
    Seat: domain:spec#2
    File surface: PR #29509's seven files as built (packages/spec/src/data/unique-null-distinct-conformance.ts + test, packages/spec/src/data/index.ts, api-surface/data.json, export-origins/data.json, scripts/check-driver-conformance.mjs census row and six DEBT rows, .changeset/29377-unique-null-distinct-conformance.md); merge of origin/main only
    Container & model: S, mode:thread, model: TIER_DEFAULT, effort: high
    Clause-②: yes (widening)
    Metadata-protocol: none
    Ruling-ref: 6595804527 (letter A, maintainer 「同意」 2026-11-03T04:55Z)
    Resume-from: claude/project-thread-ndw3ol@0c0e86d0de94111c0c4951867e75a58ea58745fe (PR #29509, contract review PASS 6583589505 on that head)
    Thread-read: 6595804527
    Premise: holds — the ruling takes the six DEBT rows as built; seat 1 released the card (6589445500) and this seat took it over on the maintainer's word.
    Serial constraints cleared: no open PR of this seat edits scripts/check-driver-conformance.mjs or packages/spec/src/data/index.ts; the executor re-reads main's ledger at the merge.

  14. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-support-ai · session_01WGufzfXhPVhbNCfA7cqGdi
    os-dev-report

    {
      "issue": 29377,
      "status": "done",
      "branch": "claude/project-thread-polo9l",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29808",
      "head": "4ee136f065201c8f6edbd7856a651ac212b2f86b",
      "session": "session_01WGufzfXhPVhbNCfA7cqGdi",
      "premise_still_valid": true,
      "summary": "Resumed from claude/project-thread-ndw3ol@0c0e86d0 (draft PR #29509, contract review PASS 6583589505) on the pinned branch per ruling 6595804527 (A). os-regen-merge.sh merged origin/main @ 25450217 with no conflict and took main's side of packages/spec/api-surface/data.json and export-origins/data.json; check:generated --fix re-added exactly the four public names. main had not moved scripts/check-driver-conformance.mjs since the old merge base, so the case-set, its test, the changeset, the census row and the six DEBT rows are byte-identical to 0c0e86d0. New draft PR #29808: Fixes #29377, Supersedes #29509, Ruling-ref 6595804527. Before opening, main had moved 13 more commits (0e4b0fa4); git merge-tree reports no conflict and none touch this PR's files.",
      "tests": "head 4ee136f0, one os-verify-lock script, VERDICT command-exit 0 (22m32s shared box): spec test Test Files 805 passed (805), Tests 23903 passed | 1 todo; spec test:repo Test Files 89 passed (89), Tests 1522 passed. eslint --no-inline-config over the four touched source files exit 0.",
      "gates": "full turbo build --concurrency=2 exit 0 (118/118 tasks). node scripts/check-driver-conformance.mjs exit 0: OK — 66 covered cell(s), 6 in the DEBT ledger, 0 exempt. spec check:generated exit 0. dispatch-gates --commands: 100 derived, all exit 0 after the full build; --ran: 100 derived, 100 run, 0 NOT-MEASURED, 0 UNRUN. check-changeset-no-major --base origin/main --event (PR body) exit 0: Clause-② yes (widening), Metadata-protocol none, spec patch. CI check-runs: pending at report time.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "0 — GitHub reads via unauthenticated REST GETs only",
      "api_writes": "2 relay writes as objectstack-fleet[bot]: pr_create (#29808, 12692 bytes read back identical, no assignees, no reviewers), comment (this report on #29377). Plus 1 git push of the thread branch.",
      "writes": "git push x1; relay pr_create x1; post-stamped comment x1",
      "deviations": [
        "PR opened with no assignee and no review request, per the order and os-dev rule 2, overriding the session prompt's assign/review step.",
        "Worktree ../objectstack-issue-29377 kept for a patch round."
      ],
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  15. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-support-ai · session_01WGufzhJG3tKnksHVa1krBz

    Landed. PR #29808 merged through the queue (merge commit 31204d11); this card closed as completed by its Fixes line.

    Reading Value
    PR #29808 MERGED at 2026-11-03T06:38Z, head 4ee136f0, contract review PASS 6583589505 (on 0c0e86d0) + delta 6596800000
    Card #29377 closed (completed)

    State change: pm:dispatched removed. Ruling A (6595804527) holds from here: the six DEBT rows in scripts/check-driver-conformance.mjs each leave with their driver's adoption PR, in the drivers' lane. #29509 stays closed as superseded.

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

Metadata

Metadata

Assignees

Labels

domain:specDomain lane — seat card indexed by label:pm:seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions