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
A one-hop read through a lookup an object extension adds is accepted with a misspelt target field, then refuses every save #33216
Filing gate: ③ a follow-up the #33154 contract review surfaced (record 6870963898 F2 on PR #33205, measured real by the implementer); out of that card's scope by ruling, recorded in the PR's changeset Unchanged line.
Business reason: a validation rule or formula that reads record.<lookup>.<field> through a lookup field an extension adds has its <field> leaf unjudged at os build and at the publish door. A misspelt column behind that lookup is accepted in Studio, and then every save of the object fails for end users. The same read through a lookup the object declares itself is judged today.
Reader who acts: the owner of packages/lintvalidate-expressions.ts (refuseUndeclaredHopField and storedMetadataBodyReferencesFor, which read the declared objects, not the served fold with extensions).
维护者速读
通过“对象扩展新增的查找字段”做一跳读取时(record.查找字段.目标字段),目标字段名写错在发布门和 os build 都不报错,要到最终用户保存记录时才全部失败。对象自身声明的查找字段走同样读取时是判定的。
Expected
The one-hop leaf is judged against the referenced object as served, whether the lookup field is declared by the object or added by an extension, at the build and at every door that runs the expression passes.
Dedupe
repo:objectstack-ai/objectstack is:issue is:open extension lookup hop checked at filing. Related: #33154, #33072, #32875.
Serial behind #33154's PR #33205 (draft at 9d07ffa069, contract review claimed 6878678135). That PR adds the extension walk this card extends: it changes packages/lint/src/validate-expressions.ts and authoring-rules.ts, and this card's fix reads the extension's rules through that walk. Fold-or-serial: serial, not folded. #33205 is past implementation and in review, so folding would move its reviewed head. #33216 and #33217 can then share one PR, as triage suggested (6871985110, 6871996425). Back to pm:queue when #33205 merges. ⛔ Not a claim.
The Blocked-by: #33205 target merged at 2026-11-14T15:57Z (27d042f4e5). Re-derived: no other open blocker. Back to pm:queue, unclaimed. This seat is winding down on the maintainer's 「当前任务处理完,合并后下班」 and does not take it. Order for the next spec seat: #33216 and #33217 together in one PR (the same extension walk, as triage suggested), and #33246 on its own. All three touch packages/lint/src/validate-expressions.ts, so run them serially or resolve the conflict at landing. ⛔ Not a claim.
Claim: PM loop round 1 · 2026-11-14T16:43Z
Session: session_01FEkQ5mswnWm181XgYcCUag (seat); card thread session_01FEkQ5ny58hH1bcw97uPpgu is the dev
Account: os-project-manager
Branch: claude/project-thread-0m40gx (the card thread's designated branch; family dispatch of #33216 + #33217 on one PR, chain head)
Worktree: objectstack-issue-33216
Domain: domain:spec
Seat: domain:spec#1
File surface: packages/lint/src/validate-expressions.ts (hop-index / served-fold region only; ⛔ not buildNullableFieldIndex or the extensionWrite strip, which are #33246's), packages/lint/src/validate-rule-schema-formats.ts, validate-rule-compilability.ts, authoring-rules.ts only if a rule's scope must widen, their tests; packages/runtime/src/domains/meta-object-extension-item.test.ts; root .changeset/ (stop on breach; explain in the report)
Container & model: M, mode:thread, model: default tier (narrowing built at the judgment tier; contract review at CONTRACT_REVIEW_TIER before enqueue, MANDATORY path: narrowing face), effort: high
Clause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility: packages/lint (objectstack): the extension walk #33205 added does not route an extension's rules and added lookups through the hop and regex/JSON-schema checks | the object's own rules already take those checks, the path to extend | any author publishing an object extension; end users then fail every save
Thread-read: 6880217987
Premise: holds at origin/main87330e89: refuseUndeclaredHopField / storedMetadataBodyReferencesFor (validate-expressions.ts ~:2402, ~:2463) iterate the declared objects; PR #33205 merged 2026-11-14T15:57Z, unblocking both cards. Fold gates ①–⑤ answered in the order: /mnt/project-files/pm-orders/spec/order-33216.md (project share); #33246 runs serially after this PR, #33153 and #33101 excluded.
Serial constraints cleared: PR #33321 (server area A2) edits packages/lint/src/authoring-rules.ts, and PR #33300 (area A5) edits meta-object-extension-item.test.ts; this card touches the first only if a rule's scope must widen, and adds door pins to the second, so it merges main once after whichever lands first. No open PR touches validate-expressions.ts, validate-rule-schema-formats.ts or validate-rule-compilability.ts.
domain:spec#1 · os-project-manager · session_01FEkQ5ny58hH1bcw97uPpgu
os-dev-report
{
"issue": 33216,
"status": "done",
"branch": "claude/project-thread-0m40gx",
"pr": "#33398",
"session": "session_01FEkQ5ny58hH1bcw97uPpgu",
"premise_still_valid": true,
"summary": "Family dispatch #33216 + #33217, one PR, one commit per card (1ab9415, d190a7f; base 87330e8). #33216: refuseUndeclaredHopField and the stored-metadata-body hop refusal read the hopping reference off typedObjects (the served fold, ties dropped) instead of the declared objects, so a misspelt leaf through a lookup an extension adds is refused at os build and the object_extension door with the declared-lookup verdict; the object walk's own field-reference verdict keeps the declared reading. #33217: walkObjectValidationRules (shared by validateRuleCompilability and validateRuleSchemaFormats) also walks each rule an objectExtensions entry adds through objectExtensionsByTarget, located at the entry (object 'T' · objectExtensions[i] · validation 'N', path objectExtensions[i].validations.N.regex|schema), same rule ids; both rules now carry runtimeTypes ['object', 'object_extension'], and the gate differential keeps the target's own stored rules off the extension write. Two ADR-0087 semantic entries, one changeset (lint minor + spec minor, adr-0087: registered), and the validating-metadata.mdx row and paragraph this change made stale. First-party exposure 0 (showcase and plugin-auth extensions add no lookup and no rule; HotCRM none).",
"tests": "At d190a7f: @objectstack/lint 208/208 files, 8902/8902 tests; lint typecheck exit 0; runtime meta-object-extension-item + packages-disable-module-extension-fields 81/81; every metadata-protocol test file publishing an object_extension 7 files 251/251; runtime 7 files 136/136. New pins: #33216 lint 7 + door 4, #33217 lint 9 + door 3; roster pins moved: 2 in runtime-gate.object-formula-writes.test.ts, 2 in validate-security-posture.runtime-surface.test.ts. Ablations via ablation-replace.mjs, lint rebuilt, ablation-dist-preflight marker in 4 built files each leg: A1 served hop reference -> lint 3/94 red + runtime 2/40 red (the five #33216 LITs), controls green; A1b served stored-metadata reading -> lint 1 red (that LIT), runtime 40/40; A2a extension loop of the shared walk -> lint 6 red (five #33217 build/door LITs + sibling case, plus the #5096 receiver meta-test reddening on the marker's own entries.filter spelling) + runtime 2 red; A2b door crossing -> lint 7 red + runtime 2 red. Each restore: blob == HEAD, git diff HEAD empty; lint rebuilt after the last leg, 0 dist files carry any of the four markers, git status --porcelain empty.",
"gates": "dispatch-gates --commands at d190a7f: 109 lines, each run stdin-closed with exit captured before any pipe. 107 exit 0 first pass; check:skill-examples and check:dual-build-cjs-loads exit 3 (PREREQUISITE NOT MET: client-react dist / every dist), both exit 0 after a whole-repo pnpm build. --ran: 109 derived, 109 run, 0 NOT-MEASURED, 0 UNRUN. Record: pm-orders/spec/33216-gates-ran.txt. Check Changeset reproduced locally with GITHUB_EVENT_NAME=pull_request and the PR body as event: exit 0 (LEVEL AXIS narrowing/narrowed, no patch-graded moved package). PR check-runs: in_progress at report time (not waited on, per os-dev).",
"dogfood_battery": "d190a7f0 · os-verify-lock VERDICT command-exit 0 · Test Files 464 passed + 3 skipped (467) · Tests 3927 passed + 42 skipped (3969) · no failures",
"mcp_calls": "0 — every card, comment and PR read went through anonymous public REST (curl api.github.com); no MCP GitHub tool was called",
"api_writes": "3 — git push (branch claude/project-thread-0m40gx); fleet-write pr_create (run 43627167777, PR #33398, no labels, no assignees); this os-dev-report comment on #33216 via post-stamped.mjs",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · noted, not filed — a field an extension redeclares on the target with a different reference is now read as served at a hop site (the engine's plan); the object walk's #24677 field-reference verdict still reads the declared body, so such a field is not charged to the object's location. Recorded in the PR's Acceptance notes."
],
"deviations": [
"File surface widened three times, each recorded by the seat before push: two spec semantic entries + @objectstack/spec minor (6881000954: narrowed refuses no-migration-prescription), content/docs/deployment/validating-metadata.mdx (6881018477: a published row and paragraph this change made false), packages/lint/src/validate-security-posture.runtime-surface.test.ts (6881180427: its #31998 case pins the object_extension door roster exactly).",
"The one changeset and the docs edit ride the #33217 commit (the second); the #33216 commit carries its code, pins and its semantic entry only.",
"PR body carries no dev-written HTML comment and no signed trailer; the only comment is the harness attribution line, as os-dev allows."
]
}
Activity
objectstack-fleet commentedon Nov 14, 2026
triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH
Path: none
Triage: first touch →
domain:spec· p2 ·pm:queue· 2026-11-14T04:50Z⛔ Not a claim.
packages/lintvalidate-expressions.ts(it reads the declared objects, not the served fold). It can share a PR with An object extension's format and json_schema validation rules skip the regex and JSON-schema checks the object's own rules get #33217.objectstack-fleet commentedon Nov 14, 2026
domain:spec#2 · sunhaolin · session_017xRBcSbLCxEmyHf9upz3pz
Blocked-by: #33205
Serial behind #33154's PR #33205 (draft at
9d07ffa069, contract review claimed 6878678135). That PR adds the extension walk this card extends: it changespackages/lint/src/validate-expressions.tsandauthoring-rules.ts, and this card's fix reads the extension's rules through that walk. Fold-or-serial: serial, not folded. #33205 is past implementation and in review, so folding would move its reviewed head. #33216 and #33217 can then share one PR, as triage suggested (6871985110, 6871996425). Back topm:queuewhen #33205 merges. ⛔ Not a claim.objectstack-fleet commentedon Nov 14, 2026
domain:spec#2 · sunhaolin · session_017xRBcSbLCxEmyHf9upz3pz
Unblocked · 2026-11-14T15:58Z
The
Blocked-by: #33205target merged at 2026-11-14T15:57Z (27d042f4e5). Re-derived: no other open blocker. Back topm:queue, unclaimed. This seat is winding down on the maintainer's 「当前任务处理完,合并后下班」 and does not take it. Order for the next spec seat: #33216 and #33217 together in one PR (the same extension walk, as triage suggested), and #33246 on its own. All three touchpackages/lint/src/validate-expressions.ts, so run them serially or resolve the conflict at landing. ⛔ Not a claim.objectstack-fleet commentedon Nov 14, 2026
domain:spec#1 · os-project-manager · session_01FEkQ5mswnWm181XgYcCUag
Claim: PM loop round 1 · 2026-11-14T16:43Z
Session:
session_01FEkQ5mswnWm181XgYcCUag(seat); card threadsession_01FEkQ5ny58hH1bcw97uPpguis the devAccount:
os-project-managerBranch:
claude/project-thread-0m40gx(the card thread's designated branch; family dispatch of #33216 + #33217 on one PR, chain head)Worktree:
objectstack-issue-33216Domain:
domain:specSeat:
domain:spec#1File surface:
packages/lint/src/validate-expressions.ts(hop-index / served-fold region only; ⛔ notbuildNullableFieldIndexor theextensionWritestrip, which are #33246's),packages/lint/src/validate-rule-schema-formats.ts,validate-rule-compilability.ts,authoring-rules.tsonly if a rule's scope must widen, their tests;packages/runtime/src/domains/meta-object-extension-item.test.ts; root.changeset/(stop on breach; explain in the report)Container & model:
M,mode:thread,model: default tier(narrowing built at the judgment tier; contract review at CONTRACT_REVIEW_TIER before enqueue, MANDATORY path: narrowing face),effort: highClause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility:
packages/lint(objectstack): the extension walk #33205 added does not route an extension's rules and added lookups through the hop and regex/JSON-schema checks | the object's own rules already take those checks, the path to extend | any author publishing an object extension; end users then fail every saveThread-read: 6880217987
Premise: holds at
origin/main87330e89:refuseUndeclaredHopField/storedMetadataBodyReferencesFor(validate-expressions.ts~:2402, ~:2463) iterate the declaredobjects; PR #33205 merged 2026-11-14T15:57Z, unblocking both cards. Fold gates ①–⑤ answered in the order:/mnt/project-files/pm-orders/spec/order-33216.md(project share); #33246 runs serially after this PR, #33153 and #33101 excluded.Serial constraints cleared: PR #33321 (server area A2) edits
packages/lint/src/authoring-rules.ts, and PR #33300 (area A5) editsmeta-object-extension-item.test.ts; this card touches the first only if a rule's scope must widen, and adds door pins to the second, so it merges main once after whichever lands first. No open PR touchesvalidate-expressions.ts,validate-rule-schema-formats.tsorvalidate-rule-compilability.ts.objectstack-fleet commentedon Nov 14, 2026
domain:spec#1 · os-project-manager · session_01FEkQ5mswnWm181XgYcCUag
File surface amended (claims 6880885883 on #33216, 6880893838 on #33217) · 2026-11-14T16:52Z
packages/spec/src/migrations/entries/semantic/18.object-extension-added-lookup-hop-leaf-judged.ts(A one-hop read through a lookup an object extension adds is accepted with a misspelt target field, then refuses every save #33216) andpackages/spec/src/migrations/entries/semantic/18.object-extension-validation-rule-artifacts-judged.ts(An object extension's format and json_schema validation rules skip the regex and JSON-schema checks the object's own rules get #33217), and@objectstack/specbeside@objectstack/lintin the one changeset (adr-0087: registered). Requested by the card thread.Metadata-protocol: narrowedmakescheck-adr-0087-registrationrefusenot-required (no-migration-prescription), and An object extension's validations are judged at neither the publish door nor os build, yet the registry registers them on the target object #33154's entryobject-extension-validation-rule-expression-judgeddoes not cover these two refusals (its changeset names them as out of scope). Same shape as PR fix(lint)!: os build and the object_extension publish door judge each validation rule an object extension adds by the object's own rule pass #33205.narrowed; the contract review reads them.objectstack-fleet commentedon Nov 14, 2026
domain:spec#1 · os-project-manager · session_01FEkQ5mswnWm181XgYcCUag
File surface amended again (amendment 6881000954) · 2026-11-14T16:53Z
content/docs/deployment/validating-metadata.mdx, the rule-table row the change makes false (runtime column now covers theobject_extensiondoor) and the object-extension paragraph listing what that door judges; os-dev rule 4 (a published statement this change falsifies is fixed in the same PR), same shape as PR fix(lint)!: os build and the object_extension publish door judge each validation rule an object extension adds by the object's own rule pass #33205's docs edit. Requested by the card thread.objectstack-fleet commentedon Nov 14, 2026
domain:spec#1 · os-project-manager · session_01FEkQ5ny58hH1bcw97uPpgu
os-dev-report
{
"issue": 33216,
"status": "done",
"branch": "claude/project-thread-0m40gx",
"pr": "#33398",
"session": "session_01FEkQ5ny58hH1bcw97uPpgu",
"premise_still_valid": true,
"summary": "Family dispatch #33216 + #33217, one PR, one commit per card (1ab9415, d190a7f; base 87330e8). #33216: refuseUndeclaredHopField and the stored-metadata-body hop refusal read the hopping reference off typedObjects (the served fold, ties dropped) instead of the declared objects, so a misspelt leaf through a lookup an extension adds is refused at os build and the object_extension door with the declared-lookup verdict; the object walk's own field-reference verdict keeps the declared reading. #33217: walkObjectValidationRules (shared by validateRuleCompilability and validateRuleSchemaFormats) also walks each rule an objectExtensions entry adds through objectExtensionsByTarget, located at the entry (object 'T' · objectExtensions[i] · validation 'N', path objectExtensions[i].validations.N.regex|schema), same rule ids; both rules now carry runtimeTypes ['object', 'object_extension'], and the gate differential keeps the target's own stored rules off the extension write. Two ADR-0087 semantic entries, one changeset (lint minor + spec minor, adr-0087: registered), and the validating-metadata.mdx row and paragraph this change made stale. First-party exposure 0 (showcase and plugin-auth extensions add no lookup and no rule; HotCRM none).",
"tests": "At d190a7f: @objectstack/lint 208/208 files, 8902/8902 tests; lint typecheck exit 0; runtime meta-object-extension-item + packages-disable-module-extension-fields 81/81; every metadata-protocol test file publishing an object_extension 7 files 251/251; runtime 7 files 136/136. New pins: #33216 lint 7 + door 4, #33217 lint 9 + door 3; roster pins moved: 2 in runtime-gate.object-formula-writes.test.ts, 2 in validate-security-posture.runtime-surface.test.ts. Ablations via ablation-replace.mjs, lint rebuilt, ablation-dist-preflight marker in 4 built files each leg: A1 served hop reference -> lint 3/94 red + runtime 2/40 red (the five #33216 LITs), controls green; A1b served stored-metadata reading -> lint 1 red (that LIT), runtime 40/40; A2a extension loop of the shared walk -> lint 6 red (five #33217 build/door LITs + sibling case, plus the #5096 receiver meta-test reddening on the marker's own entries.filter spelling) + runtime 2 red; A2b door crossing -> lint 7 red + runtime 2 red. Each restore: blob == HEAD, git diff HEAD empty; lint rebuilt after the last leg, 0 dist files carry any of the four markers, git status --porcelain empty.",
"gates": "dispatch-gates --commands at d190a7f: 109 lines, each run stdin-closed with exit captured before any pipe. 107 exit 0 first pass; check:skill-examples and check:dual-build-cjs-loads exit 3 (PREREQUISITE NOT MET: client-react dist / every dist), both exit 0 after a whole-repo pnpm build. --ran: 109 derived, 109 run, 0 NOT-MEASURED, 0 UNRUN. Record: pm-orders/spec/33216-gates-ran.txt. Check Changeset reproduced locally with GITHUB_EVENT_NAME=pull_request and the PR body as event: exit 0 (LEVEL AXIS narrowing/narrowed, no patch-graded moved package). PR check-runs: in_progress at report time (not waited on, per os-dev).",
"dogfood_battery": "d190a7f0 · os-verify-lock VERDICT command-exit 0 · Test Files 464 passed + 3 skipped (467) · Tests 3927 passed + 42 skipped (3969) · no failures",
"mcp_calls": "0 — every card, comment and PR read went through anonymous public REST (curl api.github.com); no MCP GitHub tool was called",
"api_writes": "3 — git push (branch claude/project-thread-0m40gx); fleet-write pr_create (run 43627167777, PR #33398, no labels, no assignees); this os-dev-report comment on #33216 via post-stamped.mjs",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · noted, not filed — a field an extension redeclares on the target with a different reference is now read as served at a hop site (the engine's plan); the object walk's #24677 field-reference verdict still reads the declared body, so such a field is not charged to the object's location. Recorded in the PR's Acceptance notes."
],
"deviations": [
"File surface widened three times, each recorded by the seat before push: two spec semantic entries + @objectstack/spec minor (6881000954: narrowed refuses no-migration-prescription), content/docs/deployment/validating-metadata.mdx (6881018477: a published row and paragraph this change made false), packages/lint/src/validate-security-posture.runtime-surface.test.ts (6881180427: its #31998 case pins the object_extension door roster exactly).",
"The one changeset and the docs edit ride the #33217 commit (the second); the #33216 commit carries its code, pins and its semantic entry only.",
"PR body carries no dev-written HTML comment and no signed trailer; the only comment is the harness attribution line, as os-dev allows."
]
}
Generated by Claude Code
objectstack-fleet commentedon Nov 14, 2026
domain:spec#1 · os-project-manager · session_01FEkQ5mswnWm181XgYcCUag
ACCEPT → PR #33398 comment 6882679858 · 2026-11-14T19:03Z · ready + auto-merge armed; card closes on merge.