Uh oh!
There was an error while loading. Please reload this page.
fix(spec): mirror the objectName -> object check onto embedded actions (#7456) - #7895
Conversation
#7456) The third arm #7397 deliberately left open. The registered action walk in validateCrossReferences applies three checks -- flow target, modal target, and objectName -> declared object -- but #7397's PR mirrored only the first two onto config.objects[].actions[]. This closes the third arm (Option A, existence check, per the 2026-08-11/12 maintainer-confirmed ruling): a dangling objectName on an object-embedded action is now refused the same way it already is at the registered position. objectName still gives no new runtime meaning at the embedded position -- mergeActionsIntoObjects continues to read only config.actions -- this only makes a dangling value refused at authoring time. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECjShwqVRAhLy15mgatGjV
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 106 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
⛔ 7 release-owned page(s) also reference the affected code. These are read-only:
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#7456
What
The third arm #7397 deliberately left open. The registered action walk in
validateCrossReferences(packages/spec/src/stack.zod.ts) applies three checks —flow target, modal target, and
objectName→ declared object — but #7397's PR mirroredonly the first two onto
config.objects[].actions[]. The third split the same way thetarget arms did before #7397:
Same action object, two authoring positions, opposite verdicts — the b/f, c/g, d/i pattern
from #7397's probe table, one key over.
Now:
config.objects[].actions[]is walked and every action'sobjectName(when set)is subjected to the same existence check as a registered action's. Message keeps the
registered wording from
referencesonward and changes only the subject, same conventionalready used by the flow/modal arms in this loop:
Ruling this executes
#7456 filed this as an observation-class finding because mirroring the check is an
acceptance-surface change with two live readings: A — existence check (verbatim
mirror, what this PR does) vs B — consistency check (the value must equal the owning
object's own name). Quoted verbatim from the two ruling comments on the issue:
This PR implements exactly Option A. It does not foreclose B or C (retirement): an
embedded action naming a different declared object than its owner is still accepted —
only a dangling value newly refuses. Whether the key should instead be retired at this
position, or made to agree with its owner, remains open and unruled.
objectNamestill gives no new runtime meaning at the embedded position:mergeActionsIntoObjectscontinues to build its map only fromconfig.actions, neverfrom
obj.actions[].objectName. This PR only makes a dangling value refused atauthoring time.
Acceptance-face narrowing / corpus census
A stack carrying a dangling embedded
objectNamenow fails to build where it previouslybuilt clean. Census of the shipped corpus (
find . -name '*.object.ts' | xargs grep objectName, plus a broader repo-wide search filtered toexamples/**andcontent/docs/**) found zero files declaringobjectNameat the embedded positionat all, dangling or otherwise — the key is used only at the registered/top-level position
in shipped metadata today (action registries, flow bindings). No shipped stack is
affected by this change.
Tests
Extends the existing #7397 probe-table conformance file
(
packages/spec/src/stack-inline-action-crossref.test.ts) with a newobjectName → object (#7456)describe block rather than a new file, per the file's own statedconvention — 5 new cases:
objectNamewith the registered rule's wording, subjectadjusted to the owning object (probe row k)
registered
objectNamenaming its own owning objectobjectNamenaming a different declared object — pins thatOption A is existence-only, not consistency (Option B stays open)
objectNamealone — unchanged from beforeReverse verification (predicted direction: red). Reverted
stack.zod.tsalone (keptthe new tests), reran the file: exactly the 2 new assertions that exercise the new check
failed, both for the right reason (
refusals()returned[]instead of the expectedone-element refusal array) — not a broken fixture. Restored the implementation via
git applyfrom a saved patch (nogit stash, per repo policy); all 47 cases in thefile pass again.
Verification
pnpm --filter '@objectstack/spec' build— green (prerequisite; [skill] 新 worktree 里第一次验证之前必须先 build 依赖闭包 —— AGENTS.md §9 的陈旧产物陷阱当日连咬三个 dev(假红 + 假绿两个方向) #6371)pnpm --filter @objectstack/spec exec vitest run src/stack-inline-action-crossref.test.ts— 47/47 passpnpm --filter @objectstack/spec test— 379 files / 9988 tests, all passpnpm --filter @objectstack/spec typecheck— pass (tsc --noEmit,check:scripts-typecheck,check:test-typecheck)pnpm check:nul-bytes— OK (7215 files scanned, no raw control bytes)pnpm check:adr-anchors— OKpnpm check:changeset-gate-self-tests— OKpnpm --filter @objectstack/lint run check:doc-formula-expressions— OK (24/24 self-test cases; had to build@objectstack/lint's deps first — staledist/trap)pnpm check:docs-audit-scope— OKpnpm check:driver-conformance— OK (40/40 cells)pnpm check:i18n— OK (had to build@objectstack/clifirst — gate's documented prerequisite)pnpm check:merge-driver— OKpnpm check:release-body— OKpnpm check:spec-parsed-alias— OKpnpm check:stack-collection-maps— OKpnpm --filter @objectstack/spec check:generated— OK, all 13 generated artifacts up to date (no docs/authorable-surface regen needed by this change)pnpm --filter @objectstack/spec check:authorable-surface— GREEN (baseRevlag vs the upstream anchor is the documented informational-only state, not an error)Not run locally (CI's job, per the local-verification-scope contract): the full
lint.ymlgate farm.Changeset
.changeset/embedded-action-objectname-crossref.md—@objectstack/specminor(acceptance-surface narrowing, so user-visible).
Generated by Claude Code