Uh oh!
There was an error while loading. Please reload this page.
feat(spec): enforce the documented newTabUrl / opensInNewTab co-constraint on ActionSchema - #12108
Conversation
…raint on ActionSchema A refine now rejects an action declaring newTabUrl whose opensInNewTab is not true, with guidance naming the pre-opened-tab contract and both remedies. Legal pairings are pinned byte-identically; corpus measured at zero lone producers (re-measured at claim). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDGG54XF5gbTLdQzCtnaVV
📓 Docs Drift CheckThis PR changes 1 package(s): 2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 126 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 750f64bd2145bc703245625d7d4f94fc34bc956c && git checkout 750f64bd2145bc703245625d7d4f94fc34bc956c
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin a933ed720ec240e154fdfe433a7aced48b557700 a9e2a0ff406101f74352203423c3303c9e581025 && git checkout -B drift-repro a933ed720ec240e154fdfe433a7aced48b557700 && git merge --no-ff a9e2a0ff406101f74352203423c3303c9e581025
node scripts/docs-audit/affected-docs.mjs --json a933ed720ec240e154fdfe433a7aced48b557700
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#11842
What
ActionSchema.newTabUrl's doc has always said "Only valid together withopensInNewTab", but nothing on the refine chain enforced it: an action declaringnewTabUrlwithoutopensInNewTab: trueparsed clean while no renderer path ever read the key — the ADR-0078 declared-but-unenforced shape, arriving through a documented co-constraint rather than a missing key.A new
.refineonActionSchema(after the #11519 doubled-channel rule, before thelowerRequiresFeaturetransform) now rejectsnewTabUrlwheneveropensInNewTab !== true, with a message located onpath: ['newTabUrl']naming the pre-opened-tab contract and both remedies (addopensInNewTab: trueif a pre-opened tab is intended; otherwise drop the inert key — behavior unchanged, the lone key was never read).Deliberate scope points, pinned in the tests:
opensInNewTab: falsebesidenewTabUrlis refused — opposite of theActionSchema.onSuccessand a handler-returnedredirectUrlare both reachable on onetype: 'script'action, and the spec rules neither — renderer-side precedence is deciding it today #11519 rule's scope, deliberately:newTabUrlhas no meaning outside the pre-opened-tab flow, so a declared-off channel leaves the key exactly as dead as an undeclared one.newTabUrl).InlineActionSchemapicksopensInNewTabbut notnewTabUrl, so the pair cannot occur there; no inline-side change.opensInNewTab: true+newTabUrl,opensInNewTabalone,opensInNewTab: falsealone all parse exactly as before.Corpus sweep (re-run at claim, per triage)
Zero lone-
newTabUrlproducers found anywhere reachable:*.ts/tsx/json/md/mdx, examples/, platform metadata, fixtures): the only metadata-shaped occurrence is the legal pair inaction-doubled-redirect.test.ts:101-107; the rest is docs prose and the generated reference — all already stating the pairing.app-shell/src/utils/consoleServerAction.ts:188) readsaction.opensInNewTab && newTabUrl, confirming the lone key is inert at the renderer; every test fixture declares the pair.skills/objectstack-ui/SKILL.mdandcontent/docs/protocol/objectui/actions.mdxalready document the constraint ("It is valid only alongsideopensInNewTab: true") — description consistency verified, no doc edits needed, noskills/**diff.Verification (all at final head
a9e2a0funless noted)@objectstack/specfull suite: 426 files / 11329 tests passed (run at pre-merge tree1b3c10d; the merge oforigin/mainbrought zeropackages/specpaths, so the tree the suite judged is content-identical for spec) · targeted re-run ata9e2a0f:action-newtaburl-pair+action-doubled-redirect+action.test— 3 files / 164 tests passed.pnpm --filter @objectstack/spec typecheck(tsc +check:scripts-typecheck+check:test-typecheck): green — the new test file compiles undertsconfig.test.json, debt ledger unchanged (55 files / 263 errors).check:generated: all 14 artifacts up to date.check:api-surfaceinitially flagged stale purely via its mtime freshness predicate (the reverse-verification churnedaction.zod.tstimestamps); after rebuild,gen:api-surfacereproduced the snapshot byte-identically (17 entries, 5165 exports; emptygit diff) — the refine changes no exported surface.action.zod.tsto basef7b25c5— mutation proven on disk by marker count (grep -c '11842': 2 → 0); the 5 refusal tests turned red, the 3 legal-pair pins stayed green (5 failed | 3 passed); restored from HEAD (marker 2 again, clean porcelain) — 8/8 green. No dist leg applies: the suite imports./action.zodsource directly (in-package relative import, noexports-resolved dist path).scripts/pm/dispatch-gates.mjs, derivation stamped ata9e2a0f), all green by their own printed verdicts at the final head: changeset-gate-self-tests · objectui-changeset · changeset-no-major · empty-changeset · release-rehearsal-clone --self-test · merge-driver · published-files · slot-lookup · spec-parsed-alias · test-source-alias · type-source-resolution · query-options-erasure · engine-double-contract · where-matcher · cross-package-test-inputs · ci-filter-parity · plugin-teardown-shape · nul-bytes · doc-formula-expressions · spec empty-state / liveness / strictness-ledger / variant-docs · check-adr-0087-registration · type-check-coverage · docs-audit (affected-docs + drift-comment).check:dev-prereqsandcheck:type-check-debt --re-measureboth refuse on this worktree's unbuilt sibling packages (66/67 dists absent — a workspace-state precondition, not a finding; CI builds fresh). Compensating evidence for the ratchet: the only test-layer change compiles clean under spec's test program (check:test-typecheckgreen above), so no upward drift direction exists.Changeset / ADR-0087
@objectstack/spec: minor, declared BREAKING accept-set narrowing (launch-window convention), dispositionnot-required (no-migration-prescription)— validated green bycheck-adr-0087-registration. Mirrors the adjacent #11519 narrowing on the same schema: no key removed/renamed/re-shaped, the parse-site refusal is the channel that reaches an affected author, and the measured population of affected sources is zero in every corpus. Consequence: no migrationsregistry.tsedit, so this PR has no shared-file overlap with batch siblings.Note: #11519 is referenced above as precedent only and remains closed on its own PR; no other card is addressed here.
Generated by Claude Code