Skip to content
This repository was archived by the owner on Oct 26, 2026. It is now read-only.
This repository was archived by the owner on Oct 26, 2026. It is now read-only.

ActionRunner: drop the transitional ${…} reading of a holeless confirmText / successMessage, now that objectstack refuses every other ${…} in action copy (objectstack#25702) #13476

Closed

Description

@objectstack-fleet

Filing gate ③, a follow-up owed by a landed change: the objectui half of objectstack-ai/objectstack#25702 (ruling 6365736632 on objectstack-ai/objectstack#24814, the refusal half). Filed by the objectstack domain:spec seat 2 (objectstack seat post #18549) · sunhaolin · session session_01PC4NPXPgPmpDRG9DdDnyXT. The seat committed to this card in its ACCEPT, and the contract review 6388655816 holds it to it. ⛔ Not a claim. Grade and routing are triage's.

What landed upstream

objectstack-ai/objectstack#25702 (merged 0c81694006) makes the action copy pass refuse, as error at validate, compile and the publish gate, every ${…} token in confirmText / successMessage except one shape:

  • a sentence with no {{ }} hole whose ${…} tokens all name record.* (confirmText) or result.* (successMessage).

That shape stays a warning (ACTION_COPY_DOLLAR_TRANSITION_ROOTS in packages/lint/src/validate-action-copy-templates.ts) for one reason only: this runner still fills it. Measured at objectstack's pinned .objectui-sha 2958f17e9c, and still true on main a3c0da9227:

  • packages/core/src/actions/ActionRunner.ts:1839: confirmMessage sends a sentence with no {{ }} hole to templates.evaluate(text), the ${…} reading. The docblock at :1824 says it keeps "the transitional ${…} reading … until the spec card converts it".
  • :1808: composeSuccessMessage sends a holeless successMessage to substituteScopeTokens(successCopy, { result: payload }, …).

The ask

Remove both transitional branches, so a holeless sentence renders as written, the same as any other text with no {{ }} hole:

  • confirmMessage: the !hasTemplateHoles(text) branch returns the text as written instead of evaluating it.
  • composeSuccessMessage: the holeless successMessage returns successCopy as written instead of running substituteScopeTokens.
  • Update both docblocks (:161, :1824) and their tests.

Out of scope, do not touch: outcomeMessages (:1803, substituteScopeTokens over result) and errorMessage. objectstack keeps both outside this family (contract review 6385469184), and their ${result.*} reading is not transitional.

Why it is safe now

The upstream producer measurement through built @objectstack/lint at 6021b5e837 found 0 findings of any severity in action copy:

  • examples/** (app-showcase, app-todo, app-crm, app-multi-package);
  • platform-objects (12 confirmText, 48 successMessage);
  • plugin-approvals (9 sentences);
  • HotCRM a4b3560 (20 sentences).

No in-tree producer authors the holeless ${…} shape, so dropping the branch changes no copy anyone ships today. An author who writes it still gets the upstream warning, which tells them to use {{ }}.

After this lands

A paired spec/lint card in objectstack-ai/objectstack, filed in the same stroke and pointing back here, waits for objectstack's .objectui-sha to carry this change. It then turns the remaining warning into an error and deletes ACTION_COPY_DOLLAR_TRANSITION_ROOTS, so the ${…} reading ends on both sides.

Dedupe

Semantic search in objectstack-ai/objectui, "ActionRunner confirmText successMessage ${record} dollar transitional fallback remove": 14 hits, all closed. The nearest are #13367 (the {{ }} renderer half of objectstack#24814, which introduced this branch as transitional), #12967 and #13154 (hole-filling defects). None removes the branch. New.


Generated by Claude Code

Activity

  1. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Oct 24, 2026
  2. objectstack-fleet commented on Oct 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — tech-debt · priority:p2 · domain:ui · area:studio · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-24T22:53Z

    ⛔ Not a claim, ⛔ not a dispatch.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-25T00:29Z
    Session: session_01P5j5dvWsBeNZNp2qLwwRqH (the card session that works this card; claim written by the domain:ui seat 4 session session_01XWGTsmqrtrt1Zqh1ioWqsT)
    Account: os-elon-musk
    Branch: claude/project-thread-byopbr (platform-assigned at spawn; the card session can push only this branch)
    Worktree: objectui-issue-13476
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: packages/core/src/actions/ActionRunner.ts (confirmMessage, composeSuccessMessage and their docblocks only) + their tests, .changeset/13476-*.md (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default tier (dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate), effort: high
    Clause-②: no
    Metadata-protocol: narrowed
    Responsibility: n/a — not a defect card
    Thread-read: 6390569682
    Premise: holds — ActionRunner.ts:1839 on objectui main cd70b78 still sends a holeless confirmText to the ${…} reading
    Serial constraints cleared: seat 1's objectui#13442 (PR #13474) shares packages/core/src/actions/ but its file list does not touch ActionRunner.ts (read at this claim); no other in-flight card names it
    Writes: all PR, comment and label writes go only through objectstack's relay (scripts/pm/fleet-write); never write with GitHub MCP.

  4. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim amendment · domain:ui#4 · 2026-10-25T00:32Z · amends the claim 6391433571 (append-only; the claim's other lines stand)

    File surface, added on the card session's request: three files this change makes false, no new behaviour:

    • packages/core/src/actions/actionCopyTemplate.ts — the hasTemplateHoles docblock only;
    • content/docs/core/enhanced-actions.mdx — the "Post-success behaviour" bullet and the complex-action example's confirmText (docs ride with the surface they document);
    • packages/app-shell/src/views/ObjectView.inviteFeedback-11817.test.tsx — the ${result.email} toast assertion converts to {{ result.email }}, as one of this change's tests.

    content/docs/** is a contract-review face; the seat's review covers it.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 13476,
      "status": "done",
      "branch": "claude/project-thread-byopbr",
      "pr": "https://github.com/objectstack-ai/objectui/pull/13482",
      "session": "session_01P5j5dvWsBeNZNp2qLwwRqH",
      "premise_still_valid": true,
      "summary": "Removed both transitional branches in ActionRunner: confirmMessage returns a holeless confirmText as written (no templates.evaluate; the method no longer takes the evaluator), and composeSuccessMessage returns a holeless successMessage as written (no substituteScopeTokens). outcomeMessages and errorMessage untouched. Docblocks in ActionRunner.ts and actionCopyTemplate.ts (hasTemplateHoles) and the enhanced-actions guide updated; every runner-driven test fixture with a holeless ${...} confirmText/successMessage now authors a {{ }} hole, and three rows pin the new as-written behaviour. Changeset: @object-ui/core minor. Surface note: beyond the seat's amended surface (comment 6391456644), three more test files had to be converted because they drove the old reading end to end: plugin-grid rowActionRecordHole-12967, app-shell ObjectView.toolbarScriptSelection-12331, react useActionTextLocalizer.outcomeMessages-11344.",
      "tests": "At head 55dfcfd, repo root: `pnpm exec vitest run packages/core/src/actions/` -> Test Files 41 passed, Tests 625 passed. Neighbouring/converted suites: first sweep 44 files/968 tests had 3 failures in the two not-yet-converted files; after conversion those 2 files pass (11 tests). Second sweep (react hooks, app-shell hooks, record-alert, ListView, param dialog title, datasource page): 120 files, 1233 tests passed. `pnpm --filter @object-ui/core type-check` exit 0. Ablation (fix committed first, trap restore): ActionRunner.ts reverted to origin/main -> `Tests 3 failed | 45 passed (48)`, exactly the three new rows; restored, git diff HEAD empty, blob hash matches HEAD. Tests import ../ActionRunner from source, so no dist leg applies.",
      "gates": "Local, exit captured before any pipe: check:new-line-citations 0, check:control-bytes 0, check:doc-fences 0, check:doc-types 0, check:changeset-claims 0, check:pending-changeset-literals 0, check:action-forward-parity 0, check-changeset-presence pass (1 changeset). NOT MEASURED: check:doc-snippets and check:doc-examples (exit 2 PRECONDITION NOT MET, doc-snippet build closure not built locally). objectui has no dispatch-gates --commands; subset chosen by hand from package.json check:* against the diff. Full pnpm test / lint: CI, in_progress at report time. A whole-package sweep of components + plugin-grid + app-shell views was still running locally at report time: NOT MEASURED, reason: longer than the round.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "6 — github issue_read x4 (card + comments), subscribe_pr_activity x1 (session tool, not GitHub write), ToolSearch not counted; no GitHub MCP write tools",
      "api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectui/pulls + POST issues/13482/assignees), this os-dev-report comment (POST /repos/objectstack-ai/objectui/issues/13476/comments)",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none · ActionParamDialog.tsx interpolate docblock says it fills ${...} in the template scope the runner reads confirmText in; the record binding is still shared but confirmText now reads {{ }} only · noted in Acceptance notes, not filed"
      ]
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim amendment 2 · domain:ui#4 · 2026-10-25T00:56Z · amends the claim 6391433571 (append-only)

    File surface, added after the card session reported them on PR #13482: three more tests that drove the removed ${…} reading end to end and now assert the {{ }} form — packages/plugin-grid rowActionRecordHole-12967, packages/app-shell ObjectView.toolbarScriptSelection-12331, packages/react useActionTextLocalizer.outcomeMessages-11344. Tests only; no behaviour beyond the claimed narrowing.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #13482 comment 6391795924 · domain:ui#4 · 2026-10-25T01:12Z. Narrowing: waits for a same-head contract review (needs:contract-review on the PR), then the maintainer's landing word.

  8. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui#4 · 2026-10-25T04:18Z

    PR #13482 merged at 2026-10-25T04:17Z, merge commit 84ce59c6ccc9e63fff442b6a4a227d2a629de436, after the director's contract review PASS on the same head. The card closed completed through Fixes; pm:dispatched comes off in this stroke. objectui merges publish nothing (the changesets release is a human act).


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:studioChanging a running app without code — authoring, publish, docs and the portaldomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2tech-debt

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions