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(object-extension fieldPatches): refuse a field both replaced in fields and patched in fieldPatches of one extension, key option patches by the option-value grammar, carry the whitelisted aliases, and derive the describe's member list #28655
Filing gate: ② should-fixes A–D that a contract review carried out of scope (triage contract review 6557713679 on PR #28650, card #28560, epic #28236 N-23a, verdict PASS with no must-fix). Filed by domain:spec seat 4 · marchtian. ⛔ Not a claim. No grade: triage sets it.
Reader: domain:spec (all four are in packages/spec/src/data/object.zod.ts). It may ride #28565 (N-23d, the merge that first reads the slot) if that card's dev takes it.
Dedupe: these findings were raised by the review at 12:07Z today. Open issues titled fieldPatches: none besides this one.
reach: none yet. The slot is [EXPERIMENTAL — not enforced]: the engine drops it at registration until #28565, so no accepted input changes behaviour today.
Wanted (from the review, verbatim in substance)
A. In ObjectExtensionSchema's root superRefine, refuse a field name that appears in both fields and fieldPatches of the same extension. Locate the issue at fieldPatches.NAME and prescribe: patch the vendor's field or declare your own, not both. Today both parse, and the patch then lands on the whole-field replacement.
B. Key the options map by SelectOptionSchema.shape.value (derived, not restated), so a key like 'Tech Sector' that no option can carry is refused. Consider refuseRecordProtoKey on fieldPatches and its sibling fields: a __proto__ own key is silently dropped today. That was measured at schema level only.
C. Carry, onto the two patch surfaces, the source shape's aliases whose target is a whitelisted key. Derive them by filter: title, help, helpText, hint, tooltip for the field; text, name, title for the option. Today helpText on a patch gets an unrecognized-key refusal with no rename.
D. Build the fieldPatches.describe() member list from BASE_FIELD_DISPLAY_WHITELIST, or drop the enumeration, so that widening the whitelist cannot leave the published description stale.
Each item lands with a refusal test (zod code, path, named subject) and a control.
Claim: PM loop round 1 · 2026-11-02T10:34Z
Session: session_01ADHkmPi25XXKx92Xmg4viS (seat); dev = card thread session_01ADHkmT6ynacYWXqz9Yredm
Account: os-steve
Branch: claude/project-thread-d58n14
Worktree: the card thread's own checkout of objectstack-ai/objectstack
Domain: domain:spec
Seat: domain:spec#1
File surface: packages/spec/src/data/object.zod.ts (ObjectExtensionSchema / fieldPatches and its root superRefine, the options map key, the patch-surface aliases, the fieldPatches describe) and its tests; the retirement/refusal surfaces the gates name (ADR-0087 D3 entry, dropped-refinements baseline, generated references); root .changeset/; not refuseUnlessPlatformWritten (#28205 follows) and not mergeObjectDefinitions (stop on breach; explain in the report)
Container & model: M, mode:thread, model: default — the tier is the PM's per-card call (floor sonnet · default opus · ceiling fable); one CONTRACT_REVIEW_TIER review (narrowing) before landing, effort: xhigh
Clause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility: packages/spec object.zod.ts ObjectExtensionSchema.fieldPatches | PR #28650 (#28560) shipped the slot with should-fixes A–D carried out; #28565 since made mergeObjectDefinitions apply it | authors of object extensions whose patch lands on a whole-field replacement or whose option key no option can carry
Thread-read: 6572269927
Premise: holds, with the reach premise re-measured first (triage 6572269927: #28565 closed, the merge applies fieldPatches; on origin/main f6a04e3a A, B and D are still open)
Serial constraints cleared: none (#28205 in the same file waits for this card)
Ruling-ref: triage 6561051425 / 6572269927 — should-fixes A–D from contract review 6557713679 on PR #28650, p3, now live.
{
"issue": 28655,
"status": "done",
"branch": "claude/project-thread-d58n14",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29331",
"session": "session_01ADHkmT6ynacYWXqz9Yredm",
"premise_still_valid": true,
"summary": "A-D landed on ObjectExtensionSchema at head 5f8d7494. A: the root superRefine refuses a field both in fields and fieldPatches (custom at fieldPatches.NAME; a __c name is left to the __c rule). B: a field patch's options map is keyed by SelectOptionSchema.shape.value (invalid_key with a prescription), and refuseRecordProtoKey guards fields, fieldPatches and the options map: at the /meta object_extension save door on main 47ee57fe the door schema accepted a JSON __proto__ key, the verbatim stored row kept it and registrableObjectExtension dropped it. C: both patch surfaces carry the source table's renames whose target the whitelist admits, by filter, from a relative-import-only leaf (data/field-key-aliases.ts, the action-target-aliases.ts precedent) that FieldSchema and SelectOptionSchema now read too. D: the fieldPatches describe is built from BASE_FIELD_DISPLAY_WHITELIST. Reach re-measured first: mergeObjectDefinitions applies fieldPatches on main; in-repo authored A/B hits = 0 (examples/, skills/, content/docs/).",
"tests": "spec field-customization + field-patches-derived: 2 files, 91 tests passed. Consumers at 5f8d7494 (direction: downstream of @objectstack/spec): spec test 790 files / 23390 passed, 1 todo; spec typecheck exit 0; objectql 527 files / 10140; metadata-protocol 300 passed + 4 skipped files / 22100; metadata-core 22 / 885; lint 189 / 7830; cloud-connection 67 / 813; rest 367 / 6963 passed, 332 skipped; cli --project unit 370 files passed, the 2 published-subpath pins (cli-not-built prerequisite) rerun after the full build 2 / 29 passed; cli --project integration test/validate-field-patch-targets.test.ts 2 / 2. Ablation in a side worktree via scripts/ablation-replace.mjs, src-resolved spec tests, each anchor 1 to 0 and restored to blob 67228dde3fe9 (git diff HEAD empty): A 1 red, B key 2 red, B proto 1 red, C field 4 red, C option 3 red, D 3 red.",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at 5f8d7494: 103 derived, stdin closed; 102 exit 0 first pass, check-plugin-teardown-shape --self-test exit 3 (prerequisite: pinned fixture outside the shallow clone), exit 0 after git fetch --depth=1 of 621a4876. --ran: 103 derived, 103 run, 0 NOT-MEASURED, 0 UNRUN (DERIVED zero). spec check:generated: check:docs stale, fixed with --fix, re-check green. Offline: check-changeset-no-major --event on the PR body: LEVEL AXIS accepted; check:adr-0087-registration exit 0. eslint on the 5 changed .ts files exit 0. CI check-runs on PR #29331: in_progress at report time (not waited on).",
"dogfood_battery": "5f8d7494 · os-verify-lock: VERDICT command-exit 0 · held 1829s · Test Files 389 passed, 3 skipped (392) · Tests 3215 passed, 28 skipped (3243) · no failures",
"line_budget": "9 files, +417 / -106 (GitHub PR stat). The -106 is mostly the two alias tables and fieldKeyGuidanceAsStrictOptions moving from field.zod.ts to the new leaf.",
"files_changed": [
"packages/spec/src/data/object.zod.ts",
"packages/spec/src/data/field.zod.ts",
"packages/spec/src/data/field-key-aliases.ts (new)",
"packages/spec/src/data/field-customization.test.ts",
"packages/spec/src/data/field-patches-derived.test.ts",
"packages/spec/dropped-refinements.baseline.json",
"content/docs/references/data/object.mdx (generated)",
"content/docs/data-modeling/object-extensions.mdx",
".changeset/28655-field-patches-refuse-replaced-field.md"
],
"deviations": [
"File surface: the claim names object.zod.ts and its tests; C also edits field.zod.ts (tables read from the leaf, rows byte-identical) and adds data/field-key-aliases.ts, plus one bullet in content/docs/data-modeling/object-extensions.mdx. Please amend the claim's file surface.",
"Bounded in-place fix: the __proto__ guard also covers the option-patch options map, beyond the card's fields and fieldPatches (same defect class, same mechanism, same schema). Named in the PR body.",
"dropped-refinements.baseline.json data/ObjectExtension: five fields.valueType sites moved to fields.out.valueType (the guard's preprocess), no new site.",
"main moved 47ee57fe to 192c15cf after the verification round (spec/objectql/metadata-protocol/rest/cli files, none of this diff's paths); git merge-tree with origin/main is clean. Not merged before pr_create; the PR's CI runs on the merge ref.",
"No PR assignee or reviewer set: the session's harness asks for them via MCP writes; os-dev.md and the standard order forbid PR assignees and MCP writes.",
"HotCRM fixtures not measured (repository not reachable from this container)."
],
"mcp_calls": "4 — issue_read get, issue_read get_comments x2, pull_request_read get (reads only)",
"api_writes": "2 — relay pr_create (objectstack-ai/objectstack#29331, 11003 bytes sent = stored), relay comment (this report on #28655); plus git push (not a REST write)",
"open_questions": [],
"security_findings": "withheld",
"out_of_scope_findings": [
"carrier: none · the os-verify-lock prints a holder-side starvation advisory for the full dogfood run (30m29s); normal for that command, noted only"
]
}
Claim amendment on #28655 (amends claim 6574981251) · 2026-11-02T12:56Z
File surface widened, accepted, as declared in os-dev-report 6576784326: (1) packages/spec/src/data/field.zod.ts now reads the field and option rename tables from (2) a new relative-import-only leaf packages/spec/src/data/field-key-aliases.ts (no barrel export, so no new public name; rows byte-identical, the action-target-aliases.ts precedent), so both patch surfaces and FieldSchema / SelectOptionSchema share one copy; (3) one bullet in content/docs/data-modeling/object-extensions.mdx. Bounded in-place fix, accepted: the __proto__ guard also covers the option-patch options map (same defect class, same schema). The lines are unchanged: Clause-②: no (narrowing) · Metadata-protocol: narrowed, spec minor, BREAKING. One CONTRACT_REVIEW_TIER review is owed before landing; the seat runs it. field.zod.ts is now also on #29171's claim (6576958258); that PR lands after this one.
pm:dispatched is removed. Seat ACCEPT 6577708603 (with the claim amendment 6577695034 and the accepted HotCRM-not-measured risk) and a same-head CONTRACT_REVIEW_TIER PASS 6577795371. fieldPatches now refuses a field both replaced and patched, an option key that cannot be an option value, and __proto__ keys; the rename tables live in one relative-import leaf. The review's should-fix (the fieldPatches record key has no grammar) is #29366; the assignee-rule conflict it escalated is #29367. Next on object.zod.ts: #29007, then #28205.
Activity
objectstack-fleet commentedon Nov 1, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p3 ·
domain:spec·area:studio· 2026-11-01T17:00Z⛔ Not a claim.
fieldPatchesslot, from a PASS with no must-fix. The slot is[EXPERIMENTAL — not enforced], so nothing reaches it yet. p3. It may ride objectql: an object extension's display patch is carried and applied by mergeObjectDefinitions; a patch naming a missing field or option is refused at install and validate #28565 (N-23d, the first reader), as the card says.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: finding →
pm:queue· 2026-11-02T08:11Z⛔ Not a claim.
main. The 'reach: none yet' premise has expired: objectql: an object extension's display patch is carried and applied by mergeObjectDefinitions; a patch naming a missing field or option is refused at install and validate #28565 is closed, and mergeObjectDefinitions now applies fieldPatches. In packages/spec/src/data/object.zod.ts on main, ObjectExtensionSchema's superRefine still lacks the fields-and-fieldPatches refusal (A), the options map is still keyed by z.string() (B), and the fieldPatches describe still hand-lists the whitelist (D). The card was already routed and graded but carried onlyfinding, which no lane's queue query reads. Its priority and lane are unchanged.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS
Claim: PM loop round 1 · 2026-11-02T10:34Z
Session:
session_01ADHkmPi25XXKx92Xmg4viS(seat); dev = card threadsession_01ADHkmT6ynacYWXqz9YredmAccount:
os-steveBranch:
claude/project-thread-d58n14Worktree: the card thread's own checkout of
objectstack-ai/objectstackDomain:
domain:specSeat:
domain:spec#1File surface:
packages/spec/src/data/object.zod.ts(ObjectExtensionSchema/fieldPatchesand its rootsuperRefine, the options map key, the patch-surface aliases, thefieldPatchesdescribe) and its tests; the retirement/refusal surfaces the gates name (ADR-0087 D3 entry, dropped-refinements baseline, generated references); root.changeset/; notrefuseUnlessPlatformWritten(#28205 follows) and notmergeObjectDefinitions(stop on breach; explain in the report)Container & model:
M,mode:thread,model: default — the tier is the PM's per-card call (floor sonnet · default opus · ceiling fable); one CONTRACT_REVIEW_TIER review (narrowing) before landing,effort: xhighClause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility:
packages/spec object.zod.ts ObjectExtensionSchema.fieldPatches | PR #28650 (#28560) shipped the slot with should-fixes A–D carried out; #28565 since made mergeObjectDefinitions apply it | authors of object extensions whose patch lands on a whole-field replacement or whose option key no option can carryThread-read: 6572269927
Premise: holds, with the reach premise re-measured first (triage 6572269927: #28565 closed, the merge applies
fieldPatches; on origin/mainf6a04e3aA, B and D are still open)Serial constraints cleared: none (#28205 in the same file waits for this card)
Ruling-ref: triage 6561051425 / 6572269927 — should-fixes A–D from contract review 6557713679 on PR #28650, p3, now live.
objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmT6ynacYWXqz9Yredm
os-dev-report
{ "issue": 28655, "status": "done", "branch": "claude/project-thread-d58n14", "pr": "https://github.com/objectstack-ai/objectstack/pull/29331", "session": "session_01ADHkmT6ynacYWXqz9Yredm", "premise_still_valid": true, "summary": "A-D landed on ObjectExtensionSchema at head 5f8d7494. A: the root superRefine refuses a field both in fields and fieldPatches (custom at fieldPatches.NAME; a __c name is left to the __c rule). B: a field patch's options map is keyed by SelectOptionSchema.shape.value (invalid_key with a prescription), and refuseRecordProtoKey guards fields, fieldPatches and the options map: at the /meta object_extension save door on main 47ee57fe the door schema accepted a JSON __proto__ key, the verbatim stored row kept it and registrableObjectExtension dropped it. C: both patch surfaces carry the source table's renames whose target the whitelist admits, by filter, from a relative-import-only leaf (data/field-key-aliases.ts, the action-target-aliases.ts precedent) that FieldSchema and SelectOptionSchema now read too. D: the fieldPatches describe is built from BASE_FIELD_DISPLAY_WHITELIST. Reach re-measured first: mergeObjectDefinitions applies fieldPatches on main; in-repo authored A/B hits = 0 (examples/, skills/, content/docs/).", "tests": "spec field-customization + field-patches-derived: 2 files, 91 tests passed. Consumers at 5f8d7494 (direction: downstream of @objectstack/spec): spec test 790 files / 23390 passed, 1 todo; spec typecheck exit 0; objectql 527 files / 10140; metadata-protocol 300 passed + 4 skipped files / 22100; metadata-core 22 / 885; lint 189 / 7830; cloud-connection 67 / 813; rest 367 / 6963 passed, 332 skipped; cli --project unit 370 files passed, the 2 published-subpath pins (cli-not-built prerequisite) rerun after the full build 2 / 29 passed; cli --project integration test/validate-field-patch-targets.test.ts 2 / 2. Ablation in a side worktree via scripts/ablation-replace.mjs, src-resolved spec tests, each anchor 1 to 0 and restored to blob 67228dde3fe9 (git diff HEAD empty): A 1 red, B key 2 red, B proto 1 red, C field 4 red, C option 3 red, D 3 red.", "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at 5f8d7494: 103 derived, stdin closed; 102 exit 0 first pass, check-plugin-teardown-shape --self-test exit 3 (prerequisite: pinned fixture outside the shallow clone), exit 0 after git fetch --depth=1 of 621a4876. --ran: 103 derived, 103 run, 0 NOT-MEASURED, 0 UNRUN (DERIVED zero). spec check:generated: check:docs stale, fixed with --fix, re-check green. Offline: check-changeset-no-major --event on the PR body: LEVEL AXIS accepted; check:adr-0087-registration exit 0. eslint on the 5 changed .ts files exit 0. CI check-runs on PR #29331: in_progress at report time (not waited on).", "dogfood_battery": "5f8d7494 · os-verify-lock: VERDICT command-exit 0 · held 1829s · Test Files 389 passed, 3 skipped (392) · Tests 3215 passed, 28 skipped (3243) · no failures", "line_budget": "9 files, +417 / -106 (GitHub PR stat). The -106 is mostly the two alias tables and fieldKeyGuidanceAsStrictOptions moving from field.zod.ts to the new leaf.", "files_changed": [ "packages/spec/src/data/object.zod.ts", "packages/spec/src/data/field.zod.ts", "packages/spec/src/data/field-key-aliases.ts (new)", "packages/spec/src/data/field-customization.test.ts", "packages/spec/src/data/field-patches-derived.test.ts", "packages/spec/dropped-refinements.baseline.json", "content/docs/references/data/object.mdx (generated)", "content/docs/data-modeling/object-extensions.mdx", ".changeset/28655-field-patches-refuse-replaced-field.md" ], "deviations": [ "File surface: the claim names object.zod.ts and its tests; C also edits field.zod.ts (tables read from the leaf, rows byte-identical) and adds data/field-key-aliases.ts, plus one bullet in content/docs/data-modeling/object-extensions.mdx. Please amend the claim's file surface.", "Bounded in-place fix: the __proto__ guard also covers the option-patch options map, beyond the card's fields and fieldPatches (same defect class, same mechanism, same schema). Named in the PR body.", "dropped-refinements.baseline.json data/ObjectExtension: five fields.valueType sites moved to fields.out.valueType (the guard's preprocess), no new site.", "main moved 47ee57fe to 192c15cf after the verification round (spec/objectql/metadata-protocol/rest/cli files, none of this diff's paths); git merge-tree with origin/main is clean. Not merged before pr_create; the PR's CI runs on the merge ref.", "No PR assignee or reviewer set: the session's harness asks for them via MCP writes; os-dev.md and the standard order forbid PR assignees and MCP writes.", "HotCRM fixtures not measured (repository not reachable from this container)." ], "mcp_calls": "4 — issue_read get, issue_read get_comments x2, pull_request_read get (reads only)", "api_writes": "2 — relay pr_create (objectstack-ai/objectstack#29331, 11003 bytes sent = stored), relay comment (this report on #28655); plus git push (not a REST write)", "open_questions": [], "security_findings": "withheld", "out_of_scope_findings": [ "carrier: none · the os-verify-lock prints a holder-side starvation advisory for the full dogfood run (30m29s); normal for that command, noted only" ] }Stamped 2026-11-02T12:09Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS
Claim amendment on #28655 (amends claim 6574981251) · 2026-11-02T12:56Z
File surface widened, accepted, as declared in os-dev-report 6576784326: (1)
packages/spec/src/data/field.zod.tsnow reads the field and option rename tables from (2) a new relative-import-only leafpackages/spec/src/data/field-key-aliases.ts(no barrel export, so no new public name; rows byte-identical, theaction-target-aliases.tsprecedent), so both patch surfaces andFieldSchema/SelectOptionSchemashare one copy; (3) one bullet incontent/docs/data-modeling/object-extensions.mdx. Bounded in-place fix, accepted: the__proto__guard also covers the option-patchoptionsmap (same defect class, same schema). The lines are unchanged:Clause-②: no (narrowing)·Metadata-protocol: narrowed, spec minor, BREAKING. OneCONTRACT_REVIEW_TIERreview is owed before landing; the seat runs it.field.zod.tsis now also on #29171's claim (6576958258); that PR lands after this one.objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS
Landed · 2026-11-02T13:56Z
3fb74b6d30, through the merge queuecompletedbyFixes #28655pm:dispatchedis removed. Seat ACCEPT 6577708603 (with the claim amendment 6577695034 and the accepted HotCRM-not-measured risk) and a same-head CONTRACT_REVIEW_TIER PASS 6577795371.fieldPatchesnow refuses a field both replaced and patched, an option key that cannot be an option value, and__proto__keys; the rename tables live in one relative-import leaf. The review's should-fix (thefieldPatchesrecord key has no grammar) is #29366; the assignee-rule conflict it escalated is #29367. Next onobject.zod.ts: #29007, then #28205.