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
spec: an emptied optional multi-value field stores and reads null, as never set — amend the #9447 sentence in FieldSchema's multiple / required docs (ruling A on #29343) #29652
Filing gate: ② a maintainer ruling's spec half. Ruling A on #29343 (record 6591577985) reverses #9447's empty representation for optional multi-value fields; per pm-dispatch SKILL.md a protocol change is its own card, landed before the defect card that consumes it. Filed by domain:server seat 4. ⛔ Not a claim. Suggested-grade: p3 (blocks #29343, p3).
What to change
packages/spec/src/data/field.zod.ts on origin/main3482f3d8d:
The multiple doc block (:1357-1363) and the multiple describe say an emptied multi-value lookup "reads back as [], never null", binding every writer.
Re-check: git grep -n "#9447" origin/main -- packages/spec/src/data/field.zod.ts → 1316, 1357.
The required doc block (:1311-1319) says "the empty set is always representable (it reads back as [], never null — see multiple)".
Amend both to the ruled rule:
A cleared optional multi-value field (every type isMultiValueField answers true for) is stored as null by the write door, the same as one never set. [] and '' written to it store null.
required on a multi-value field still means a non-empty list: [] fails required (unchanged).
The $empty table's multi_value row (filter-empty-operator.ts:77) is unchanged: null and [] both read as empty.
Claim: PM loop round 2
Session: session_01WGufzfgvGexKn9vLHsy89K
Account: os-support-ai
Branch: the card thread's own claude/project-thread-* branch, named in the dev's hand-back and recorded in an amendment to this claim (a measured platform exception to claude/issue-29652-…)
Worktree: objectstack-issue-29652
Domain: domain:spec
Seat: domain:spec#3
File surface: packages/spec/src/data/field.zod.ts (the required and multiple doc blocks and the multiple describe only), generated content/docs/references/data/field.mdx and whatever check:generated names, other packages/spec/** prose making the same "[], never null" claim, a SemanticMigration entry under packages/spec/src/migrations/entries/semantic/ only if the ADR-0087 gate demands one, .changeset/29652-*.md
Container & model: S text with an ADR-0087 judgment, treated as M, mode:thread, model: TIER_DEFAULT build; CONTRACT_REVIEW_TIER review owed (requested from triage), effort: high
Clause-②: yes
Metadata-protocol: semantic
Responsibility: n/a — not a defect card (the spec half of ruling A on #29343, record 6591577985)
Thread-read: 6592466576
Premise: holds. On origin/main the #9447 cites sit at field.zod.ts:1316 and :1357; no merged commit since the ruling touched those blocks.
Serial constraints cleared: PR #29553 (#29415, spec seat 2) edits field.zod.ts near L1822, a different region; ordinary concurrency, the later lander merges main. #29343's PR lands after this one (it is pm:blocked on this card).
Claim: PM loop round 2
Session: session_01WGufzfgvGexKn9vLHsy89K
Account: os-support-ai
Branch: claude/project-thread-ztk9p3 (the card thread's own branch, reported by the dev; a measured platform exception to claude/issue-29652-…). This restates the seat's earlier claim with the branch named.
Worktree: objectstack-issue-29652
Domain: domain:spec
Seat: domain:spec#3
File surface: packages/spec/src/data/field.zod.ts (the required and multiple doc blocks and the multiple describe only), generated content/docs/references/data/field.mdx and whatever check:generated names, other packages/spec/** prose making the same "[], never null" claim, a SemanticMigration entry under packages/spec/src/migrations/entries/semantic/ only if the ADR-0087 gate demands one, .changeset/29652-*.md
Container & model: S text with an ADR-0087 judgment, treated as M, mode:thread, model: TIER_DEFAULT build; CONTRACT_REVIEW_TIER review owed (requested from triage), effort: high
Clause-②: yes
Metadata-protocol: semantic
Responsibility: n/a — not a defect card (the spec half of ruling A on #29343, record 6591577985)
Thread-read: 6593272974
Premise: holds. On origin/main the #9447 cites sit at field.zod.ts:1316 and :1357; no merged commit since the ruling touched those blocks.
Serial constraints cleared: PR #29553 (#29415, spec seat 2) edits field.zod.ts near L1822, a different region; ordinary concurrency, the later lander merges main. #29343's PR lands after this one (it is pm:blocked on this card).
{
"issue": 29652,
"status": "done",
"branch": "claude/project-thread-ztk9p3",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29763",
"session": "session_01WGufzeW5cprrZRccVNgPFr",
"premise_still_valid": true,
"summary": "Amended FieldSchema's required doc block, multiple doc block and multiple describe (packages/spec/src/data/field.zod.ts) to ruling A on #29343 (record 6591577985): a cleared optional multi-value field is stored as null at the write door, [] and '' store null, required still means a non-empty list, the $empty table is unchanged; #29343 is cited beside #9447 in the doc blocks, 'readers never need a null branch' is dropped, and the describe carries the rule only. One other packages/spec hit was amended (filter-empty-operator.ts:91 comment). gen:docs regenerated the multiple row in three reference pages (field.mdx, object.mdx, migration.mdx). Changeset: @objectstack/spec minor, Clause-②: yes, Metadata-protocol: semantic (measured against the WHICH LEVEL row 'the meaning or default of an authorable key changes'). The ADR-0087 gate asks for no entry (no breaking declaration), so no SemanticMigration entry was written. origin/main was merged twice; the second merge brought #29623 (87956dcc, field.zod.ts, a different region).",
"tests": "Final head 3e61ed73, under os-verify-lock: pnpm --filter @objectstack/spec test && typecheck: VERDICT command-exit 0, Test Files 803 passed (803), Tests 23795 passed | 1 todo. Earlier heads: f05af6cb 803/803 files, 23786 passed; 8b1ecbbc 803/803, 23792 passed. Text-only change, no tested behaviour moved, so no ablation and no new tests.",
"gates": "Final head 3e61ed73: turbo build 118/118 (VERDICT 0); spec check:generated 'All 14 generated artifacts are up to date'; dispatch-gates --commands derived 96, all 96 exit 0, --ran: '96 derived, 96 run, 0 NOT-MEASURED, 0 UNRUN'; check-changeset-no-major with the PR body as event: exit 0 (LEVEL AXIS clause-② yes, semantic); check-adr-0087-registration: exit 0. On f05af6cb 7 families first exited 3 (unbuilt dist / shallow fixture) and exited 0 after a full build and git fetch of 621a4876. CI check-runs: not yet read (in_progress at report time).",
"line_budget": "6 files, +45/-20 vs origin/main; no skills/** touched",
"files_changed": [
".changeset/29652-multi-value-empty-null-docs.md",
"content/docs/references/data/field.mdx",
"content/docs/references/data/object.mdx",
"content/docs/references/system/migration.mdx",
"packages/spec/src/data/field.zod.ts",
"packages/spec/src/data/filter-empty-operator.ts"
],
"deviations": [
"The PR body's first non-empty line is the harness attribution block, then 'Fixes #29652', not the signature line. The relay pr_create door exempts PR bodies from the first-line rule, and the signature sits in the Acceptance notes instead.",
"The PR carries no assignee or reviewer. os-dev.md and the order's no-MCP-writes rule outrank the session's assignee/reviewer step; the seat hands off.",
"One shell command expanded backticked body text as commands (an unquoted heredoc), running build, check and lint commands locally for about 2 minutes. The task was stopped. The worktree stayed clean, no stray process was left, and nothing was written to git or GitHub. After a full rebuild, every reading was retaken on the final head.",
"Two stray empty scratch files (/gates-cmds.txt, /gates-cmds.err) and /spectest.pid sit at the container root from a mis-scoped redirect; the safety check refused their removal, so they are left (outside any repo)."
],
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"mcp_calls": "0",
"api_writes": "2 — relay pr_create (PR #29763, read back byte-identical, 11761 bytes) and this os-dev-report comment via post-stamped.mjs (POST issues/29652/comments). git push is not a REST write.",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: #29343 · noted, not filed: six hand-written docs pages still say an emptied multiple: true set is written/read back as [] never null, most citing the multiple doc block this PR amends: content/docs/api/data-api.mdx:279, content/docs/data-modeling/field-types.mdx:1025, content/docs/data-modeling/fields.mdx:295, content/docs/data-modeling/validation-rules.mdx:265 (#9447 cite :274), content/docs/deployment/troubleshooting.mdx:254, content/docs/protocol/objectql/types.mdx:730. They describe today's runtime, which changes with #29343's write-door PR, so they belong in that PR.",
"carrier: none · noted, not filed: the required describe still says 'On a multi-value lookup (multiple: true)', narrower than the ruled rule (every multi-value type) but not false; outside the claimed file surface.",
"carrier: none · noted: packages/spec/src/data/value-roundtrip-conformance.ts:216 (m_empty, 'empty array must not degrade to null') is the driver round-trip table below the write door; the ruling does not change driver injectivity, left as is."
]
}
Landed · PR #29763 merged as 4ab2e7e6 · 2026-11-03T04:38Z
The spec text now states ruling A (record 6591577985 on #29343): an emptied optional multi-value field stores null, the same as never set; required still needs a non-empty value; $empty is unchanged. Contract review 6595089655 PASS, ACCEPT 6595283412.
#29343's write-door PR is unblocked by this landing. It carries the six hand-written content/docs/** pages and the runtime prose and pins named in the review's ③ (pointer 6595092412). Removing pm:dispatched and pm:blocking here.
Activity
objectstack-fleet commentedon Nov 3, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p2 ·
pm:queue· 2026-11-03T00:53Z⛔ Not a claim.
null, meaning never set. Amend the [Decision] Multi-value lookup after set_null member removal: does the emptied array read back as[]ornull? #9447 sentence inFieldSchema'smultiple/requireddocs. A semantic change already ruled, so p2. It blocks objectql: a multi-value unique column (multiselect, or lookup with multiple: true) cleared to [] on two records refuses the second with 409 UNIQUE_VIOLATION #29343 (pm:blockingkept).Generated by Claude Code
objectstack-fleet commentedon Nov 3, 2026
domain:spec#3 · os-support-ai · session_01WGufzfgvGexKn9vLHsy89K
Claim: PM loop round 2
Session:
session_01WGufzfgvGexKn9vLHsy89KAccount:
os-support-aiBranch: the card thread's own
claude/project-thread-*branch, named in the dev's hand-back and recorded in an amendment to this claim (a measured platform exception toclaude/issue-29652-…)Worktree:
objectstack-issue-29652Domain:
domain:specSeat:
domain:spec#3File surface:
packages/spec/src/data/field.zod.ts(therequiredandmultipledoc blocks and themultipledescribe only), generatedcontent/docs/references/data/field.mdxand whatevercheck:generatednames, otherpackages/spec/**prose making the same "[], nevernull" claim, aSemanticMigrationentry underpackages/spec/src/migrations/entries/semantic/only if the ADR-0087 gate demands one,.changeset/29652-*.mdContainer & model:
Stext with an ADR-0087 judgment, treated asM,mode:thread,model: TIER_DEFAULT build; CONTRACT_REVIEW_TIER review owed (requested from triage),effort: highClause-②: yes
Metadata-protocol: semantic
Responsibility:
n/a — not a defect card(the spec half of ruling A on #29343, record 6591577985)Thread-read: 6592466576
Premise: holds. On
origin/mainthe #9447 cites sit atfield.zod.ts:1316and:1357; no merged commit since the ruling touched those blocks.Serial constraints cleared: PR #29553 (#29415, spec seat 2) edits
field.zod.tsnear L1822, a different region; ordinary concurrency, the later lander mergesmain. #29343's PR lands after this one (it ispm:blockedon this card).objectstack-fleet commentedon Nov 3, 2026
domain:spec#3 · os-support-ai · session_01WGufzfgvGexKn9vLHsy89K
Claim: PM loop round 2
Session:
session_01WGufzfgvGexKn9vLHsy89KAccount:
os-support-aiBranch:
claude/project-thread-ztk9p3(the card thread's own branch, reported by the dev; a measured platform exception toclaude/issue-29652-…). This restates the seat's earlier claim with the branch named.Worktree:
objectstack-issue-29652Domain:
domain:specSeat:
domain:spec#3File surface:
packages/spec/src/data/field.zod.ts(therequiredandmultipledoc blocks and themultipledescribe only), generatedcontent/docs/references/data/field.mdxand whatevercheck:generatednames, otherpackages/spec/**prose making the same "[], nevernull" claim, aSemanticMigrationentry underpackages/spec/src/migrations/entries/semantic/only if the ADR-0087 gate demands one,.changeset/29652-*.mdContainer & model:
Stext with an ADR-0087 judgment, treated asM,mode:thread,model: TIER_DEFAULT build; CONTRACT_REVIEW_TIER review owed (requested from triage),effort: highClause-②: yes
Metadata-protocol: semantic
Responsibility:
n/a — not a defect card(the spec half of ruling A on #29343, record 6591577985)Thread-read: 6593272974
Premise: holds. On
origin/mainthe #9447 cites sit atfield.zod.ts:1316and:1357; no merged commit since the ruling touched those blocks.Serial constraints cleared: PR #29553 (#29415, spec seat 2) edits
field.zod.tsnear L1822, a different region; ordinary concurrency, the later lander mergesmain. #29343's PR lands after this one (it ispm:blockedon this card).objectstack-fleet commentedon Nov 3, 2026
domain:spec#3 · os-support-ai · session_01WGufzeW5cprrZRccVNgPFr
os-dev-report
{ "issue": 29652, "status": "done", "branch": "claude/project-thread-ztk9p3", "pr": "https://github.com/objectstack-ai/objectstack/pull/29763", "session": "session_01WGufzeW5cprrZRccVNgPFr", "premise_still_valid": true, "summary": "Amended FieldSchema's required doc block, multiple doc block and multiple describe (packages/spec/src/data/field.zod.ts) to ruling A on #29343 (record 6591577985): a cleared optional multi-value field is stored as null at the write door, [] and '' store null, required still means a non-empty list, the $empty table is unchanged; #29343 is cited beside #9447 in the doc blocks, 'readers never need a null branch' is dropped, and the describe carries the rule only. One other packages/spec hit was amended (filter-empty-operator.ts:91 comment). gen:docs regenerated the multiple row in three reference pages (field.mdx, object.mdx, migration.mdx). Changeset: @objectstack/spec minor, Clause-②: yes, Metadata-protocol: semantic (measured against the WHICH LEVEL row 'the meaning or default of an authorable key changes'). The ADR-0087 gate asks for no entry (no breaking declaration), so no SemanticMigration entry was written. origin/main was merged twice; the second merge brought #29623 (87956dcc, field.zod.ts, a different region).", "tests": "Final head 3e61ed73, under os-verify-lock: pnpm --filter @objectstack/spec test && typecheck: VERDICT command-exit 0, Test Files 803 passed (803), Tests 23795 passed | 1 todo. Earlier heads: f05af6cb 803/803 files, 23786 passed; 8b1ecbbc 803/803, 23792 passed. Text-only change, no tested behaviour moved, so no ablation and no new tests.", "gates": "Final head 3e61ed73: turbo build 118/118 (VERDICT 0); spec check:generated 'All 14 generated artifacts are up to date'; dispatch-gates --commands derived 96, all 96 exit 0, --ran: '96 derived, 96 run, 0 NOT-MEASURED, 0 UNRUN'; check-changeset-no-major with the PR body as event: exit 0 (LEVEL AXIS clause-② yes, semantic); check-adr-0087-registration: exit 0. On f05af6cb 7 families first exited 3 (unbuilt dist / shallow fixture) and exited 0 after a full build and git fetch of 621a4876. CI check-runs: not yet read (in_progress at report time).", "line_budget": "6 files, +45/-20 vs origin/main; no skills/** touched", "files_changed": [ ".changeset/29652-multi-value-empty-null-docs.md", "content/docs/references/data/field.mdx", "content/docs/references/data/object.mdx", "content/docs/references/system/migration.mdx", "packages/spec/src/data/field.zod.ts", "packages/spec/src/data/filter-empty-operator.ts" ], "deviations": [ "The PR body's first non-empty line is the harness attribution block, then 'Fixes #29652', not the signature line. The relay pr_create door exempts PR bodies from the first-line rule, and the signature sits in the Acceptance notes instead.", "The PR carries no assignee or reviewer. os-dev.md and the order's no-MCP-writes rule outrank the session's assignee/reviewer step; the seat hands off.", "One shell command expanded backticked body text as commands (an unquoted heredoc), running build, check and lint commands locally for about 2 minutes. The task was stopped. The worktree stayed clean, no stray process was left, and nothing was written to git or GitHub. After a full rebuild, every reading was retaken on the final head.", "Two stray empty scratch files (/gates-cmds.txt, /gates-cmds.err) and /spectest.pid sit at the container root from a mis-scoped redirect; the safety check refused their removal, so they are left (outside any repo)." ], "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 — relay pr_create (PR #29763, read back byte-identical, 11761 bytes) and this os-dev-report comment via post-stamped.mjs (POST issues/29652/comments). git push is not a REST write.", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "carrier: #29343 · noted, not filed: six hand-written docs pages still say an emptied multiple: true set is written/read back as [] never null, most citing the multiple doc block this PR amends: content/docs/api/data-api.mdx:279, content/docs/data-modeling/field-types.mdx:1025, content/docs/data-modeling/fields.mdx:295, content/docs/data-modeling/validation-rules.mdx:265 (#9447 cite :274), content/docs/deployment/troubleshooting.mdx:254, content/docs/protocol/objectql/types.mdx:730. They describe today's runtime, which changes with #29343's write-door PR, so they belong in that PR.", "carrier: none · noted, not filed: the required describe still says 'On a multi-value lookup (multiple: true)', narrower than the ruled rule (every multi-value type) but not false; outside the claimed file surface.", "carrier: none · noted: packages/spec/src/data/value-roundtrip-conformance.ts:216 (m_empty, 'empty array must not degrade to null') is the driver round-trip table below the write door; the ruling does not change driver injectivity, left as is." ] }objectstack-fleet commentedon Nov 3, 2026
domain:spec#3 · os-support-ai · session_01WGufzfgvGexKn9vLHsy89K
ACCEPT → PR #29763 comment 6595283412 (head
3e61ed73, contract review 6595089655 PASS). Ready + auto-merge next.objectstack-fleet commentedon Nov 3, 2026
domain:spec#3 · os-support-ai · session_01WGufzfgvGexKn9vLHsy89K
Landed · PR #29763 merged as
4ab2e7e6· 2026-11-03T04:38ZThe spec text now states ruling A (record 6591577985 on #29343): an emptied optional multi-value field stores
null, the same as never set;requiredstill needs a non-empty value;$emptyis unchanged. Contract review 6595089655 PASS, ACCEPT 6595283412.#29343's write-door PR is unblocked by this landing. It carries the six hand-written
content/docs/**pages and the runtime prose and pins named in the review's ③ (pointer 6595092412). Removingpm:dispatchedandpm:blockinghere.