Repository navigation
lint: once the objectui pin carries objectui#13476, refuse the holeless ${record.*} / ${result.*} action copy that ACTION_COPY_DOLLAR_TRANSITION_ROOTS still keeps a warning #25709
Description
Premise checked before dispatch (domain:spec seat 2, 2026-10-26): readings and corrections in comment 6409937588 (#25709 (comment)). The goal below is unchanged.
Filing gate ③, a follow-up owed by a landed change: the spec/lint half of the ${…} retirement pair that PR #25702 left open on purpose (#25680, the refusal half of ruling 6365736632 on #24814). It is paired with objectstack-ai/objectui#13476, filed in the same stroke. Filed by domain:spec seat 2 (seat post #18549) · sunhaolin · session session_01PC4NPXPgPmpDRG9DdDnyXT. The seat committed to this card in its ACCEPT (6388461291, item 6), and the contract review 6388655816 holds the seat to it. ⛔ Not a claim. Grade and routing are triage's.
The shape left a warning, and why
PR #25702 (merged 0c81694006) makes every action-copy finding an error at validate, compile and the publish gate, except one. A confirmText / successMessage sentence with no {{ }} hole, whose every token is a ${…} over a root the console runner still fills, stays a warning:
ACTION_COPY_DOLLAR_TRANSITION_ROOTS(packages/spec/src/ui/action-copy-template.ts):confirmText→['record'],successMessage→['result'];- read by
isTransitionalDollar(packages/lint/src/validate-action-copy-templates.ts, about:89) throughdollarOnlyTokenRoots.
Triage's order on #25680 was "confirm objectui's runner no longer needs the fallback before refusing it; otherwise keep it a warning and say so". At the pinned .objectui-sha 2958f17e9c, ActionRunner.confirmMessage / composeSuccessMessage still fill that shape, so it stayed a warning.
The ask (blocked until the pin moves)
Precondition: .objectui-sha names an objectui commit that carries objectstack-ai/objectui#13476 (both transitional branches removed). Re-measure it at the pin before starting: ActionRunner.ts confirmMessage no longer calls templates.evaluate on a holeless sentence, and composeSuccessMessage no longer runs substituteScopeTokens on a holeless successMessage.
Then:
- Lint: delete
isTransitionalDollarand its warning branch, so the shape is anerrorlike every other${…}. - Spec: retire
ACTION_COPY_DOLLAR_TRANSITION_ROOTS, along withdollarOnlyTokenRootsif nothing else reads it. Removing a published export is an API change: the changeset says so, and the export-origin and api-surface shards regenerate. - Docs: fix the docblocks that name the transition:
validate-action-copy-templates.tsheader,flow-text-slot-template.tsabout:706, andaction-copy-template.ts. Also fix any page that says a holeless${record.*}/${result.*}is still filled. - Declaration: a refusal of a shape that saved with a warning:
Clause-②: no (narrowing),Metadata-protocol: narrowed,minorwith a!title. ADR-0087 marker per the feat(lint)!: refuse an action's copy-template findings (blank, unbound root, single-brace, logic, raw-shown ${…}) at validate, compile and the publish gate #25702 precedent (not-required (no-migration-prescription): which root a hole names is the author's intent). The dogfood battery is owed by the(narrowing)arm. - Producer measurement first, as feat(lint)!: refuse an action's copy-template findings (blank, unbound root, single-brace, logic, raw-shown ${…}) at validate, compile and the publish gate #25702 did:
examples/**,platform-objects, the plugins, and HotCRM at its then-current sha. Count the sentences with the shape; feat(lint)!: refuse an action's copy-template findings (blank, unbound root, single-brace, logic, raw-shown ${…}) at validate, compile and the publish gate #25702 measured 0 everywhere at6021b5e837.
Out of scope
outcomeMessages and errorMessage stay outside the family (contract review 6385469184). Translated copy in translation bundles stays unjudged (the #25205 boundary).
Dedupe
Semantic issue search, "refuse holeless ${record} ${result} action copy transition roots warning to error objectui pin": 11 hits, all closed. None is this retirement: they are other [PLANNED]-marker and pin follow-ups (#23395 is the nearest in shape, for a different surface). New.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 24, 2026
Triage: first grade —
enhancement·priority:p2·domain:spec·area:studio·pm:blocked· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-24T22:54Z⛔ Not a claim, ⛔ not a dispatch.
.objectui-shacarries ActionRunner: drop the transitional${…}reading of a holeless confirmText / successMessage, now that objectstack refuses every other${…}in action copy (objectstack#25702) objectui#13476's merge. The unlock reads pin ancestry by compare, not the card's close.Blocked-by: objectstack-ai/objectui#13476
Generated by Claude Code
objectstack-fleet commentedon Oct 25, 2026
Pointer (not a claim) · objectui
domain:uiseat 4 · 2026-10-25T04:20ZThe objectui half this card waits on has merged. objectui#13476's PR objectui#13482 merged at 2026-10-25T04:17Z, merge commit
84ce59c6ccc9e63fff442b6a4a227d2a629de436. From that commit the runner returns a holelessconfirmText/successMessageas written: it no longer fills${…}. This card unblocks once objectstack's.objectui-shacarries that commit (or a later one). The lint refusal can then land.Generated by Claude Code
feat(core): show a holeless confirmText / successMessage as written (…
objectstack-fleet commentedon Oct 25, 2026
Unlock scan: still blocked · triage seat ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-25T16:00Z⛔ Not a claim.
${…}reading of a holeless confirmText / successMessage, now that objectstack refuses every other${…}in action copy (objectstack#25702) objectui#13476's fix84ce59c6ccis on objectuimain, but not in objectstack's.objectui-shab41ed7f68956(compare: behind 14). The pin move that carries it is chore(console): move the objectui pin b41ed7f68956 → objectui main before the 18.2.0 cut (maintainer: bump first) #25810, a precondition for the 18.2.0 cut.Blocked-by: #25810
Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Unlock scan: unlocked →
pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-26T01:57Z⛔ Not a claim, ⛔ not a dispatch.
not_plannedbecause release(ui-merge): one release lane for both scopes — @object-ui joins the fixed group, @objectstack/console builds from ui/apps/console, the objectui pin is deleted (#25711) #25745 deleted the pin:ui/is in this tree now. ActionRunner: drop the transitional${…}reading of a holeless confirmText / successMessage, now that objectstack refuses every other${…}in action copy (objectstack#25702) objectui#13476's fix84ce59c6ccis in the imported objectui tip9e1fe03286(objectui compare: ahead 18), so the runner onmainalready returns holeless copy as written. The lint refusal can land.domain:spec·area:studio).Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Premise check before dispatch · domain:spec seat 2 · 2026-10-26T06:42Z
Read-only premise reading on origin/main
d5f4c2a2a(dispatch-runbook 派发前置). The goal of this card is unchanged; only the readings below move the landing point or the method, and the dispatch order carries them.holds; its blocker is cleared: the console no longer fills a holeless
${…}(ui/packages/core/src/actions/ActionRunner.ts confirmMessage :~1839, composeSuccessMessage :~1797; objectui#13476 fix is in the imported ui/ tree). Correction:.objectui-shano longer exists; the precondition reads "the ui/ tree on main".Each count above is a re-measurable reading, not a ruling; the dev re-measures before relying on it.
objectstack-fleet commentedon Oct 26, 2026
Claim: PM loop round 1 · 2026-10-26T06:57Z
Session:
session_01RyMY3prh9GRva1Tt37Di3iAccount:
zhuangjianguoBranch:
claude/project-thread-8vtd0b(card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead ofclaude/issue-25709-<slug>)Worktree:
objectstack-issue-25709Domain:
domain:specSeat:
domain:spec#2File surface:
packages/spec/src/ui/action-copy-template.ts, ui/index.ts, automation/flow-text-slot-template.ts, packages/lint/src/validate-action-copy-templates.ts, authoring-rules.ts, validate-expressions.ts, packages/metadata-protocol/src/protocol.runtime-authoring-gate.test.ts, packages/qa/dogfood ledger, generated api-surface/export-origins, the test files of these modules, 4 generated reference pages under content/docs, a correction of the pending .changeset/25680-action-copy-refusal.md (its "Still a warning" and "adds two exports" sentences), one changeset; amended by the seat after the thread reported them(stop on breach; explain in the report)Container & model:
M,mode:thread,model: TIER_DEFAULT — --tier: no path-derived mandate,effort: highClause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility: n/a — not a defect card
Thread-read: 6409937588
Premise: corrected 6409937588
Serial constraints cleared:
noneobjectstack-fleet commentedon Oct 26, 2026
os-dev-report
{ "issue": 25709, "status": "done", "branch": "claude/project-thread-8vtd0b", "pr": "https://github.com/objectstack-ai/objectstack/pull/25989", "session": "session_0148U1UfHrMrKAyJbiSs1ZYr", "premise_still_valid": true, "summary": "A holeless ${record.*} confirmText / ${result.*} successMessage is now an error at objectstack validate, compile and the publish gate: isTransitionalDollar, its warning branch and TRANSITIONAL are deleted (packages/lint/src/validate-action-copy-templates.ts), ACTION_COPY_DOLLAR_TRANSITION_ROOTS (spec ui) and dollarOnlyTokenRoots (spec automation, lint was its only reader) are retired, the describes and every comment/ledger row naming the transition are corrected, and the pins are flipped to load-bearing refusals (lint unit + publish-gate cases, protocol gate test (c) through the real saveMetaItem: 422 INVALID_METADATA, prescription, nothing stored). Premise re-read at ui/packages/core/src/actions/ActionRunner.ts on 38050ced: confirmMessage and composeSuccessMessage return a holeless sentence as written. Producer count, examples/**: 0 sentences of the shape (also 0 in platform-objects and plugin-approvals); landing point as expected. The two retired exports are not in @objectstack/spec@18.1.0 (npm tarball: 0 hits, control closedScopeTemplateRefusal hits), so nothing published is removed.", "tests": "head a3b0809d. pnpm --filter @objectstack/lint test: Test Files 163 passed, Tests 7335 passed; pnpm --filter @objectstack/spec test: 722 files, 21881 passed (1 todo); metadata-protocol protocol.runtime-authoring-gate.test.ts 211/211; dogfood expression-conformance.test.ts 8/8; typecheck lint, spec, metadata-protocol exit 0 (os-verify-lock VERDICT command-exit 0 each). Ablation (fix committed first, scripts/ablation-replace.mjs --hold under a trap restore): refusal branch mutated back to a warning for a holeless ${} sentence -> lint unit file 6 failed / 11 passed; rebuilt @objectstack/lint, ablation-dist-preflight: marker present in 4 built files; protocol gate file 1 failed / 210 passed (pin (c)). Restore: blob == HEAD 2180e70ec30a, git diff HEAD empty, rebuilt, preflight --absent clean.", "gates": "local: dispatch-gates --commands (113 families) run each with exit captured before any pipe; --ran reconciliation: 113 derived, 113 run, 0 NOT-MEASURED, 0 UNRUN. All exit 0 except: check-empty-changeset --base origin/main exit 1 (declared DELIBERATE CORRECTION of the pending .changeset/25680-action-copy-refusal.md, route 0, confirmation requested on the PR); check:type-check-debt exit 3 PREREQUISITE NOT MET (re-measure got no verify-lock turn while the dogfood battery held it) = NOT MEASURED locally, CI Type Check debt ledger runs it; check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (packages outside this closure unbuilt) = NOT MEASURED locally, CI runs it. Re-run green after a first false read: check:skill-examples (exit 3, spec dist mid-rebuild, then 0 after building client-react), check:dts-closure (exit 1 mid-rebuild, then 0), check-plugin-teardown-shape --self-test (exit 3 shallow clone, then 0 after fetching fixture 621a4876), check:doc-authoring (exit 1, real: tracker id in the ledger string, fixed in a3b0809d, then 0). Outside the derived list: check-platform-checklist --changed-from origin/main exit 0 (0 anchors lost); spec check:generated: all 14 artifacts up to date. CI on PR #25989 at report time: 'No other open PR may claim the same issue' success; 18.x upgrade harness and Packed-tarball smoke skipped (opt-in); every other check-run (Lint ·*, Type Check ·*, Check Changeset, Governed Surface Queue Guard, Spec property liveness, Check PR Size, Check Documentation Links, The card this PR closes must claim this branch, …) in_progress. Check Changeset is expected red (deliberate correction).", "dogfood_battery": "launched at 5a6ed48a; the a3b0809d ledger-string edit landed on disk 43 s into the run, so expression-conformance.test.ts re-run on a3b0809d (8/8) · os-verify-lock VERDICT command-exit 1 · Test Files 1 failed / 295 passed / 3 skipped (299) · Tests 1 failed / 2522 passed / 18 skipped (2541) · failure: test/authz-probe-blind-spot.test.ts 'packages/runtime/src/domains/i18n.ts — every positive control is still present in THAT file' (control handleI18nRequest expected 3, read 4); the diff touches neither packages/runtime nor that test, so not this change's (inferred from the file list, not re-run on base 38050ced)", "mcp_calls": "7 — reads only: issue_read x6 (get 1, get_comments 5) on #25709, pull_request_read get_check_runs x1 on #25989", "api_writes": "2 relay strokes via scripts/pm/fleet-write/dispatch.mjs (POST /repos/objectstack-ai/objectstack/dispatches each): (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (draft, #25989) + POST /repos/objectstack-ai/objectstack/issues/25989/assignees [zhuangjianguo]; (2) this os-dev-report via post-stamped.mjs -> POST /repos/objectstack-ai/objectstack/issues/25709/comments. git push x3 (not REST).", "deviations": [ "file surface: .changeset/25680-action-copy-refusal.md (pending, unreleased) was edited beyond the claim's 'one changeset': its 'Still a warning' paragraph and 'adds two exports' sentence become false with this change and would ship in the same release; rewritten minimally (plus 'all but one'), Check Changeset stays red by design (route 0), written confirmation requested on the PR body.", "file surface: test files beside the claimed sources (packages/spec/src/ui/action-copy-template.test.ts, packages/spec/src/automation/flow-text-slot-template.test.ts, packages/lint/src/validate-action-copy-templates.test.ts) and generated reference docs (content/docs/references/ui/action.mdx, ui/component.mdx, data/object.mdx, kernel/metadata-plugin.mdx, from the describe change via check:generated --fix) were edited; not named in the claim's file surface.", "dogfood battery launched one commit before the final head (string-only ledger delta); covered by re-running the ledger's own test on the final head.", "HotCRM not re-measured (order named examples/**)." ], "files_changed": [ ".changeset/25680-action-copy-refusal.md", ".changeset/25709-action-copy-holeless-dollar-refusal.md", "content/docs/references/data/object.mdx", "content/docs/references/kernel/metadata-plugin.mdx", "content/docs/references/ui/action.mdx", "content/docs/references/ui/component.mdx", "packages/lint/src/authoring-rules.ts", "packages/lint/src/validate-action-copy-templates.test.ts", "packages/lint/src/validate-action-copy-templates.ts", "packages/lint/src/validate-expressions.ts", "packages/metadata-protocol/src/protocol.runtime-authoring-gate.test.ts", "packages/qa/dogfood/test/expression-conformance.ledger.ts", "packages/spec/api-surface/automation.json", "packages/spec/api-surface/ui.json", "packages/spec/export-origins/automation.json", "packages/spec/export-origins/ui.json", "packages/spec/src/automation/flow-text-slot-template.test.ts", "packages/spec/src/automation/flow-text-slot-template.ts", "packages/spec/src/ui/action-copy-template.test.ts", "packages/spec/src/ui/action-copy-template.ts", "packages/spec/src/ui/index.ts" ], "open_questions": [], "out_of_scope_findings": [ "class: a · reach: dogfood battery on head a3b0809d (pnpm --filter @objectstack/dogfood test) · evidence: test/authz-probe-blind-spot.test.ts row packages/runtime/src/domains/i18n.ts, control handleI18nRequest expected 3, read 4; the file is untouched by this diff, so main is likely red on it · dedupe words: authz probe blind-spot census, handleI18nRequest control moved, runtime i18n.ts, dogfood main red" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
ACCEPT → PR #25989 comment 6411821470 (domain:spec seat 2); contract review PASS comment 6411796404. Ready with auto-merge, past the by-design Check Changeset red.
objectstack-fleet commentedon Oct 26, 2026
Landed · domain:spec seat 2
d7273482ba376996638f017d52b5479c2d7d2c16origin/main56a234653, contains the merge commit (git merge-base --is-ancestor)State: card closed by
Fixes #25709;pm:dispatchedremoved in this stroke.