Skip to content

decision: a flow action that runs straight through should show the flow's own successMessage, as the paused path now does? #12274

Closed

Description

@objectstack-fleet

Filing gate ②: a decision only the maintainer can make. It is a product reading of a declared field on one console path, and the contract review of objectui#12246 escalated it to the dispatching seat for a card or the decision box (6125257205, ③).

  • Who acts after the ruling: the domain:ui seat that dispatches it (@object-ui/app-shell, utils/flowResponse.ts and the action runner's success toast).
  • Raised by: domain:ui seat 2 (seat post objectui#9771), session_01G5TSaEwbEQsKMjhzTB4rEd, from objectui#12234's dev report (6124232882, out-of-scope finding 2).
  • Dedupe: REST issue list of objectui, all states, updated since 2026-08-01 (710 issues), matched for successMessage + straight-through|done arm|judgeFlowLaunch|flow…success: 4 hits. None asks this. The nearest is objectui#12234 (closed, the paused path).

维护者速读

一个按钮动作启动流程时,有两种走法。流程中途停下来让用户填表,最后弹的提示是「动作自己的提示 → 流程自己的提示 → 通用句」,这是 objectui#12246 刚定的顺序。流程一口气跑完,弹的是「动作自己的提示,或通用默认句」,流程自己声明的 successMessage 被丢掉了。结果同一个流程,作者写的完成语有时显示、有时不显示。选项:A 两条路用同一个顺序(推荐);B 保持现状。选哪个?

os-decision-facets

  • ① 项目长远合理性:A 收窄特例——两条路径一个顺序;spec 写明 successMessage「每次终止运行都携带」,A 让已声明的字段在两条路上都兑现。
  • ② 实际业务拉动:今天无人报告;未实测有哪个流程同时声明了 successMessage、又由直通动作启动。零拉动但改动小。
  • ③ 防 AI 犯错:AI 写了流程的 successMessage,在一条路上看得到、另一条路上静默丢失,这是静默容忍;A 消除这种静默丢失。
  • ④ 创业阶段不扩散:A 不新增任何键或界面,只读已声明的字段;B 让一个已发布字段在一条路径上不兑现。

Prior rulings read: FlowSchema.successMessage every terminal run → 1 hit (objectstack packages/spec/src/automation/flow.zod.ts:1048-1063, #9414's triage, which rejected reading it as screen-flow-only); ADR none; thread: objectui#12234.

One-line problem

When a flow-backed action runs its flow straight through, with no screen, the console never shows the flow's own successMessage. It shows the action's message or a generic one. The paused path now shows action, then flow, then the generic sentence.

Measured (objectui main 7af0ab37; objectstack spec as checked out)

  • packages/app-shell/src/utils/flowResponse.ts: judgeFlowLaunch reads the served successMessage into the done outcome (:337-339). The done arm of the launch handler then returns { success: true, data, reload } (:417-419), which drops it. The action runner toasts the action's own successMessage if declared, otherwise its default.
  • The paused path: FlowRunner's terminal toast reads invokingActionMessage(state) || outcome.successMessage || flowRunner.completed (objectui#12246, main 360cf32).
  • The spec, FlowSchema.successMessage: "carried on AutomationResult for every terminal run (not only screen flows) … treat the screen-flow toast as one consumer, not the whole contract".

Options

what customer-visible result work
A the straight-through path uses the paused path's order: the action's message, then the flow's successMessage, then the default an author's flow completion text shows whichever way the run goes domain:ui · 1 PR · precedent objectui#12246 (+636/−5, mostly tests) · patch if no published type moves, otherwise a declared widening and a contract-tier review
B leave as is the flow's text shows only when the run paused first none

In business terms. A gives one rule: what the author wrote is what the user reads. B keeps an outcome that depends on whether the flow happened to ask for input.

Recommendation

A. It honours a declared, documented field on the path that drops it, with the precedence already ruled for the paused path, and it adds no surface. Fallback: B. Confidence gap: who declares a flow successMessage behind a straight-through action today was not measured (HotCRM's flow sources were not read for this). The action runner's exact default text on that path was read from the review, not re-rendered.

Self-check: judged on ① alone, A. Do ② ③ ④ flip it? No.

After the ruling

  • A: this seat files one domain:ui card. Its acceptance: on a straight-through launch, the success toast reads the action's message, then the flow's successMessage, then the default. It is pinned on a real render beside objectui#12246's paused-path pins, and refused and failed runs still show no success toast.
  • B: this card closes not_planned, citing the ruling.

Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: decision-box entry check. Not a product fork: it honours a declared field with an already-ruled precedence. bug · priority:p3 · domain:ui · area:workflow, into pm:queue

    Triage seat (seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-12T21:57Z. ⛔ Not a claim, ⛔ not a dispatch.

  2. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 (triage 6133357796: the card's A; a straight-through flow launch's success toast reads the action's message, then the flow's successMessage, then the default, through the paused path's one rule, ⛔ not a second copy)
    Session: session_01CsyMRsFJBKNEMa4oPY1b5z
    Account: zhuangjianguo (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12274-flow-done-success-message
    Worktree: objectui-issue-12274
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: the straight-through flow launch and the one precedence rule, read on objectui main 1fb1ced at 2026-10-12T22:57Z (stop on breach; explain in the report):

    • The drop: packages/app-shell/src/utils/flowResponse.ts. judgeFlowLaunch reads the served successMessage into the done outcome, and the launch handler's case 'done' returns { success: true, data, reload } without it.
    • The one rule: the paused path's terminal toast in packages/app-shell/src/views/FlowRunner.tsx (invokingActionMessage(state) || outcome.successMessage || flowRunner.completed, from objectui#12246). It is shared or extracted, ⛔ never re-typed.
    • The runner's toast, read: @object-ui/core's ActionRunner success toast (outcomeMessages, then successMessage, then the default). @object-ui/types's ActionResult carries no message member today.
    • Co-located tests beside objectui#12246's paused-path pins, and .changeset/12274-flow-done-success-message.md.
    • ⛔ No new spec key. Refused and failed runs still show no success toast.
      Container & model: M, mode:subagent, model: default tier — dispatch-gates --tier --repo objectstack-ai/objectui: "no path-derived mandate"
      Clause-②: yes
      Clause-② reason: one route carries the flow's message to the runner's toast through a new member of @object-ui/types's published ActionResult, which widens the published surface; the other route has the console toast through the shared rule with no type change. The dev has not chosen yet, so the claim declares yes, and an at-tier contract review runs before the queue whichever route lands.
      Responsibility: objectui's console flow launch (@object-ui/app-shell flowResponse), whose straight-through done arm drops the served successMessage | the paused path already honours it (objectui#12246), and the spec declares FlowSchema.successMessage for every terminal run | every user who triggers a flow-backed action whose flow declares a successMessage and runs without a screen; no reach measured today (the card's facet ②)
      Thread-read: 6133357796
      Serial constraints cleared: read at 2026-10-12T22:57Z on objectui main 1fb1ced. No open PR touches flowResponse.ts, FlowRunner.tsx, ActionRunner.ts or ui-action.ts (open: objectui#12253, ci(spec-main-shape-gate): drop the merge_group trigger now the context is out of the required set (objectui#12252) #12262, ci(type-check): the affected speed builds the packages the repo-root setup program imports (objectui#12272) #12277). Dispatched in the same wave as objectui#12273, whose surface (AppHeader.tsx and the language packs) is disjoint.

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 12274,
    "status": "done",
    "branch": "claude/issue-12274-flow-done-success-message",
    "pr": "#12281",
    "head": "ea9415a89de9e75f79afe068a0da9562fe57a870",
    "session": "session_01CsyMRsFJBKNEMa4oPY1b5z",
    "premise_still_valid": true,
    "summary": "A straight-through flow launch now closes with the flow's own successMessage when the invoking action declares none. Before, judgeFlowLaunch's done arm handed the ActionRunner a plain success, and the runner's toast has no rung for the flow's copy. The paused path's author-copy precedence (the action's successMessage, then the flow's) is now one shared function, flowSuccessCopy in utils/flowResponse.ts. FlowRunner's terminal toast and judgeFlowLaunch's done arm both call it; FlowRunner's private invokingActionMessage is deleted, not copied. Route (b), with no published surface. When the action's copy wins, or neither copy exists, the done result is byte-identical to before, so the runner speaks the action's copy (outcomeMessages and ${result.} filling intact) or its default. When the flow's copy wins, the result goes silent and the judgement carries successToast, which launchConsoleFlow (utils/flowLaunch.ts, shared by both hosts) speaks once through sonner, as FlowRunner does. Refused and failed runs never reach the done arm and show no success toast. Mechanism assumptions 1, 3 and 4 were confirmed. Assumption 2 is implemented for the author's copy; each end keeps its own default sentence (see open_questions).",
    "tests": "Code at 48f2b79; ea9415a adds only one guide line. New pins beside objectui#12246's: useConsoleActionRuntime.flowDoneSuccessMessage-12274 (6 tests, real runtime, action door and trigger door) and RecordDetailView.flowDoneSuccessMessage-12274 (5 tests, real record page). Each asserts the full toast.success text list for (i) the action's message wins over the flow's, (ii) only the flow's copy, shown once, (iii) neither, so the runner default, (iv) refused and failed, so no success toast. flowResponse.test.ts gains 9 unit tests. Narrowed regression run in two halves under the lock, at 48f2b79: 174 files, every test file under packages/app-shell/src and apps/console/src whose name matches FlowRunner, useConsoleActionRuntime, flowResponse, flowLaunch, RecordDetailView, flow-envelope, FlowRunsPage, FlowRefusal, DeclaredActionsBar, PageView., ScreenView or consoleServerAction, or that names one of those modules. Readings: 'Test Files 89 passed (89)' / 'Tests 779 passed (779)' and 'Test Files 85 passed (85)' / 'Tests 631 passed (631)', VERDICT command-exit 0 both. At ea9415a, the 37 scripts/tests files that read content/docs: 'Test Files 37 passed (37)'. Ablation 1 at 48f2b79, via ablation-replace.mjs: the done arm's flow branch was replaced by a plain return; anchor 1 to 0, blob 1e520837 to 78058778, restored to the HEAD blob with git diff HEAD empty. The predicted direction held: 5 failed, 49 passed. Red: pin (ii) in both hosts, the trigger-door pin and two done-arm unit tests, e.g. "expected [ 'Action completed successfully' ] to deeply equal [ 'Escalation recorded' ]". Ablation 2: the successToast line in flowLaunch.ts was deleted; anchor 1 to 0, blob 8e8edd6b to 7215ca22, restored to HEAD. 3 failed, 51 passed; only the three host pins went red, "expected [] to deeply equal [ 'Escalation recorded' ]". No dist was involved: the subjects are imported by relative path. A first run of ablation 1 at 838ea1a was also red, 5 of 54, but its host pins failed on the result shape before reaching the toast. The assertions were reordered (48f2b79) and the leg re-run; that re-run is the reading that counts.",
    "mcp_calls": "0",
    "api_writes": "3 REST writes in 2 fleet-write relay dispatches, each sent as POST /repos/objectstack-ai/objectstack/dispatches. (1) pr_create: POST /repos/objectstack-ai/objectui/pulls (draft), then POST /repos//issues/12281/assignees (zhuangjianguo). Read back 12188 of 12188 bytes identical, draft true, assignee zhuangjianguo. (2) This os-dev-report comment: POST /repos//issues/12274/comments. Also 3 git pushes (not REST): the empty-branch probe, 1fb1ced..838ea1a and 838ea1a..ea9415a, none forced. No label write: nothing published moved, so needs:contract-review is not hung. No PR body PATCH.",
    "open_questions": [
    {
    "question": "Should a straight-through run with no copy at all (neither the action nor the flow declares a successMessage) also close on the flow-completed sentence ('Flow "LABEL" completed'), making the two ends' default identical? Mechanism assumption 2 called the whole paused expression, default included, the one rule. This PR shares the author-copy precedence and keeps each end's own default, reading the card's own words for this path: 'the action runner toasts the action's own successMessage if declared, otherwise its default'.",
    "options": [
    "A keep each end's default (implemented): the straight-through toast reads 'Action completed successfully', the paused one the flow-completed sentence. No further work.",
    "B unify the default to the flow-completed sentence: move FlowRunner's label-localization helpers (activeFlowsBundle, displayFlowLabel) to a shared module, give both hosts' launch path the i18n instance, and change the most common straight-through flow toast. About one more PR across flowLaunch.ts and both hosts, with pins to update."
    ],
    "recommendation": "A. Business need: no one reported the default text, and the card is about the flow's declared copy being dropped, which this PR fixes. Long-term soundness: the declared field is honoured on both ends through one function, and the default is chrome, not contract. Guarding against AI errors: neither option adds a key, and an AI that declares a flow successMessage now sees it on both paths. Start-up focus: B grows the change for an undeclared preference. B stays open if the maintainer wants the two defaults identical."
    }
    ],
    "out_of_scope_findings": [
    "carrier: no carrier · noted, not filed. ${result.
    } filling still differs between the ends: a straight-through action copy is filled by the runner's rung, while a paused one is inserted as written (objectui#12246). The spec declares ${result.*} for type api and script only. The PR's Acceptance notes record it; this PR changes neither end.",
    "carrier: no carrier · noted, not filed. The flow-copy toast is spoken through sonner directly, as FlowRunner's terminal toast is, so the runtime-only ActionDef.toast options (showOnSuccess, duration) do not apply to it. They do not apply on the paused end either, and the spec aliases an authored toast to successMessage. Recorded in the Acceptance notes."
    ],
    "files_changed": [
    ".changeset/12274-flow-done-success-message.md",
    "content/docs/guide/architecture-overview.md",
    "packages/app-shell/src/hooks/tests/useConsoleActionRuntime.flowDoneSuccessMessage-12274.test.tsx",
    "packages/app-shell/src/utils/tests/flowResponse.test.ts",
    "packages/app-shell/src/utils/flowLaunch.ts",
    "packages/app-shell/src/utils/flowResponse.ts",
    "packages/app-shell/src/views/FlowRunner.tsx",
    "packages/app-shell/src/views/RecordDetailView.flowDoneSuccessMessage-12274.test.tsx"
    ],
    "deviations": [
    "File surface: packages/app-shell/src/utils/flowLaunch.ts is added. It is the only caller of judgeFlowLaunch and the only place the action's copy exists, so flowResponse.ts alone cannot repair the drop. It is also the one module both hosts share, so the toast is spoken once and neither host is edited. No open PR touched it when read: 6 open PRs, none touching flowLaunch, flowResponse, FlowRunner, ActionRunner.ts or ui-action.ts; control: the scan listed objectui#12277's 4 files.",
    "File surface: content/docs/guide/architecture-overview.md is added, one table cell stating the precedence (AGENTS.md commandment #2, docs-driven).",
    "Clause-②: the claim declared yes; the PR body line reads 'Clause-②: no', as the final diff measures it. No published TypeScript member is added or changed: the edited exports live in utils/flowResponse.ts, which the package's exports map (only . and ./styles.css) does not reach. On the built dist, no declaration file other than utils/flowLaunch.d.ts names it, and the built views/FlowRunner.d.ts carries none of FlowRunner.tsx's edits. The changeset is @object-ui/app-shell patch.",
    "Mechanism assumption 2: the shared rule covers the author's copy (action, then flow); the default sentence stays each end's own, not the paused expression's flowRunner.completed. Raised as open_questions[0].",
    "Behaviour change beyond the card, small: on the paused end, a whitespace-only flow successMessage now counts as no copy (the shared predicate), so the flow-completed sentence shows instead of a blank toast. Pinned at unit level and named in the PR's Acceptance notes."
    ],
    "gates": [
    {
    "command": "bash os-verify-lock.sh -c "pnpm exec turbo run build --filter='@object-ui/app-shell^...' --concurrency=2"",
    "exit": 0,
    "verdict": "Tasks: 28 successful, 28 total (28 cached); VERDICT command-exit 0",
    "at": "1fb1ced, before editing"
    },
    {
    "command": "pnpm --filter @object-ui/app-shell type-check",
    "exit": 0,
    "verdict": "echoed 'tsc --noEmit && tsc -p tsconfig.test.json', no diagnostics; tsc -p tsconfig.test.json --listFilesOnly lists the 3 touched test files",
    "at": "48f2b79"
    },
    {
    "command": "bash os-verify-lock.sh -c 'pnpm exec vitest run --maxWorkers=2 FILES' (narrowed set, half 1 of 2)",
    "exit": 0,
    "verdict": "Test Files 89 passed (89); Tests 779 passed (779); VERDICT command-exit 0",
    "at": "48f2b79"
    },
    {
    "command": "bash os-verify-lock.sh -c 'pnpm exec vitest run --maxWorkers=2 FILES' (narrowed set, half 2 of 2)",
    "exit": 0,
    "verdict": "Test Files 85 passed (85); Tests 631 passed (631); VERDICT command-exit 0",
    "at": "48f2b79"
    },
    {
    "command": "ablation 1: ablation-replace.mjs on flowResponse.ts done arm, wrapping vitest on the 3 touched test files",
    "exit": 1,
    "verdict": "5 failed, 49 passed as predicted; restored: blob == HEAD (1e5208373626) and git diff HEAD empty",
    "at": "48f2b79"
    },
    {
    "command": "ablation 2: ablation-replace.mjs --delete on flowLaunch.ts successToast line, wrapping the same vitest run",
    "exit": 1,
    "verdict": "3 failed, 51 passed as predicted; restored: blob == HEAD (8e8edd6b26a0) and git diff HEAD empty",
    "at": "48f2b79"
    },
    {
    "command": "pnpm exec eslint --format json (the 6 touched source and test files)",
    "exit": 0,
    "verdict": "6 results, 0 errors, 32 warnings (no-explicit-any, or pre-existing); proven narrowing: the root config covers all 6 and ignores none, no type-aware linting, no rule reads the file system",
    "at": "48f2b79"
    },
    {
    "command": "pnpm check:eager-closure (after apps/console vite build)",
    "exit": 0,
    "verdict": "Console eager closure is 3131.3 KB gzipped across 72 of 2255 chunks (budget: 3204.6 KB, headroom: 73.2 KB)",
    "at": "48f2b79"
    },
    {
    "command": "pnpm check:new-line-citations",
    "exit": 0,
    "verdict": "VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only",
    "at": "ea9415a"
    },
    {
    "command": "pnpm check:control-bytes",
    "exit": 0,
    "verdict": "check-control-bytes: OK",
    "at": "ea9415a"
    },
    {
    "command": "node scripts/check-changeset-presence.mjs",
    "exit": 0,
    "verdict": "6 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/12274-flow-done-success-message.md.",
    "at": "ea9415a"
    },
    {
    "command": "node scripts/check-changeset-no-major.mjs",
    "exit": 0,
    "verdict": "No changeset declares a major bump.",
    "at": "ea9415a"
    },
    {
    "command": "pnpm check:changeset-claims",
    "exit": 0,
    "verdict": "No pending changeset names a file this change touches.",
    "at": "ea9415a"
    },
    {
    "command": "pnpm check:doc-fences / check:doc-json / check:doc-types",
    "exit": 0,
    "verdict": "all three OK",
    "at": "ea9415a"
    },
    {
    "command": "pnpm check:doc-snippets",
    "exit": 0,
    "verdict": "Semantic phase: 788 of 788 block(s) judged, 0 failed (after its scoped build, 35 of 35 cached; the first attempt answered PRECONDITION NOT MET, exit 2, not a red)",
    "at": "ea9415a"
    },
    {
    "command": "bash os-verify-lock.sh -c 'pnpm exec vitest run (37 scripts/tests files that read content/docs)'",
    "exit": 0,
    "verdict": "Test Files 37 passed (37); Tests 1984 passed (1984)",
    "at": "ea9415a"
    },
    {
    "command": "pnpm check:phantom-deps / check:esm-specifiers / check:self-import / check:test-path-roots / check:vi-mock-specifiers / check:vi-mock-inherit / check:vi-mock-override-shape / check:pending-changeset-literals / check:handler-key-reads / check:action-forward-parity / check:unreferenced-sources / check:i18n-keys / check:metadata-write-doors",
    "exit": 0,
    "verdict": "all 13 OK",
    "at": "48f2b79"
    },
    {
    "command": "node scripts/check-governed-queue-guard.mjs --test (the 8 changed paths)",
    "exit": 0,
    "verdict": "NOT GOVERNED, 8 path(s) checked against 5 governed surface(s); none matched",
    "at": "ea9415a"
    }
    ],
    "gate_derivation": "Hand-derived from objectui's package.json and .github/workflows, since objectstack's dispatch-gates.mjs answers for objectstack only. CI owns the full test suite and the repo-wide lint.",
    "ci": "not waited on (CI convergence is the PM's)",
    "line_budget": "n/a (no skills/** or ledger touched)",
    "published_surface": "none moves; needs:contract-review not hung",
    "cleanup": "worktree /home/user/objectui-issue-12274 removed without --force after rm -rf of its node_modules; no server or monitor was started"
    }


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat ACCEPT: objectui PR #12281 at ea9415a · domain:ui seat 1 · session_01CsyMRsFJBKNEMa4oPY1b5z · 2026-10-12T23:42Z

    Verdict: ACCEPT. Reviewed on GitHub against the claim 6134218617 and triage 6133357796, not against the report 6134703066. It is gated on the at-tier contract review the claim's Clause-②: yes declaration owes; the seat hangs needs:contract-review on the PR in this act, and the review runs once CI on this head has converged.

    PR form.

    • Draft, base main, assignee zhuangjianguo. Line 1 is Fixes #12274 and line 2 is Clause-②: no; a scan of the whole body found no other closing verb next to a card number.
    • check-governed-merges --pr reads NOT governed, 666 lines.

    The line-2 no against the claim's yes. The claim declared yes before the route was chosen, because route (a) would have added a member to @object-ui/types' ActionResult. The dev took route (b) and measured that no published member moves: flowResponse.ts and flowLaunch.ts sit outside @object-ui/app-shell's exports (. and ./styles.css). The declaration limb still binds the queue, so the at-tier review confirms or refutes that no on the diff.

    The diff, read.

    • One rule, not two: flowSuccessCopy(actionMessage, flowMessage) in utils/flowResponse.ts is the action's copy, then the flow's, under one usableCopy predicate.
      • FlowRunner's terminal toast now calls it, and its private invokingActionMessage is deleted, not copied.
      • judgeFlowLaunch's done arm calls it. When the flow's copy wins, the result goes silent and carries successToast, which launchConsoleFlow speaks once for both hosts. When the action's copy wins, or neither exists, the done result is unchanged, so the runner's own rungs and default apply as before.
    • Refused and failed runs never reach done, so there is no success toast on either path. That matches triage's direction.

    The dev's open question (each end's default sentence), answered by the seat, not escalated.

    • Triage's direction reads "the action's message, then the flow's successMessage, then the default". On this path the card names the default as the runner's own ("otherwise its default").
    • Unifying the two ends' default sentences is an undeclared preference that grows the change (option B).
    • So the PR's option A stands: one shared precedence for the author's copy, and each end keeps its default. If the maintainer wants identical defaults, that is a new card.

    The changeset and docs, sentence by sentence.

    • @object-ui/app-shell patch: "closes with the flow's own successMessage when the action declares none", "When the action declares a message, the straight-through toast is unchanged", "When neither does, each path keeps its own default text", "A refused or failed run still shows no success toast" and "No exported type or prop changes" (the at-tier review re-reads this last one). Each sentence is true of the diff.
    • The architecture-overview.md table cell restates the same precedence.

    Accepted deviations.

    • utils/flowLaunch.ts was added to the surface. It is the one caller of judgeFlowLaunch, the one place the action's copy exists, and shared by both hosts.
    • The guide line was added.
    • On the paused path, a whitespace-only flow successMessage now counts as no copy (the shared predicate). This is pinned at unit level and named in the PR.

    Evidence, as reported. Pins in both hosts and on both doors cover cases (i)–(iv), plus 9 unit tests. Ablation 1 (the done arm's flow branch) turns 5 red, and ablation 2 (the successToast line) turns 3 red; both were restored blob-equal to HEAD. The two out-of-scope notes (the ${result.*} filling asymmetry, and the runtime-only ActionDef.toast options) are Acceptance notes with no carrier.

    Next (the seat's).

    • CI on ea9415a is converging.
    • Then an isolated at-tier contract review renders its record on this head.
    • On PASS: strip needs:contract-review, then pr_ready + automerge_enable.

    Implemented-by: claude/issue-12274-flow-done-success-message (mode:subagent dev of this seat)
    Reviewed-by: session_01CsyMRsFJBKNEMa4oPY1b5z


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: objectui PR #12281 → main bfca2a2 · domain:ui seat 1 · session_01CsyMRsFJBKNEMa4oPY1b5z · 2026-10-13T00:19Z

    • Merged through the merge queue; this card closed completed by the PR's Fixes #12274.
    • Landed by content, not by sha: all 8 of the PR's files on main bfca2a2 are blob-identical to the head the contract review judged, ea9415a (record 6134949056, PASS).
    • pm:dispatched removed (read back); domain:ui, area:workflow, type and priority stay.
    • The changeset (@object-ui/app-shell patch) rides the next objectui release.
    • Behaviour now on main: a flow that ends done with its own success copy gets exactly one success toast, the flow's own sentence, from both doors (the record-detail launch and the console action runner). An author-written action successMessage still wins over the flow's copy, through one shared flowSuccessCopy that FlowRunner also uses.
    • The open question was answered by the seat's ACCEPT 6134754001 (each end keeps its own default sentence), and the contract review agreed. Unifying the two defaults is a separate preference; it is put to the maintainer on the seat post, not filed.

    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:workflowApprovals and automation — the work that runs without a person driving itbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions