Skip to content

console: a record-button flow whose write step dropped a read-only field shows a warning toast naming the fields (console half of #32861) #33009

Closed

Description

@objectstack-fleet

domain:server#8 · os-elon-musk · session_016WV4cwqTK71kjQzHae8T5J

Part of #32861
Blocked-by: #33007

Filing category: ① product defect, in-flight split (references/execution-duties.md in-scope sub-issue; priority inherited from #32861, p1). The server half is PR #33007 (Part of #32861); this card carries the card's Work 2, the console toast, and #32861 closes when this lands.

维护者速读

员工点按钮启动流程,流程想写的字段是只读的,写入被丢掉、按钮却答「成功」,员工什么都看不到。PR #33007 让流程的回答里带上「哪些字段没写进去、为什么」;这张卡让控制台把它弹成黄色警告,显示字段的中文名。

Business reason

The #32666 case: a member clicks 「提交审批」, the flow's update_record step writes status, which is readonly: true; the write is dropped, the run succeeds, the record stays 「草稿」, and the console says nothing. After PR #33007 the flow-action answer carries droppedFields (DroppedFieldsEvent: object, fields, reason; omit-when-empty) on REST and MCP. Nothing in the console reads it yet.

Expected

A person who starts a flow from a record action (and from a screen flow's resume) sees a warning toast in their locale when the answer carries droppedFields: the step ran, these fields (by label) were not written because they are read-only. No toast when the answer carries none. The existing detail.writeStripped* wording fits it.

What the server half measured (PR #33007, Acceptance notes)

  1. The wire parse of a droppedFields entry (isWireDroppedFieldsEntry, asDroppedFieldsNotice, the skew arm for an unknown reason) is private to ui/packages/data-objectstack. The console's flow launch (ui/packages/app-shell/src/utils/flowLaunch.ts) does not go through the adapter: export the parser, ⛔ no second copy.
  2. writeWarningToast.emitWriteWarning needs the adapter (field labels), which neither launch host (hooks/useConsoleActionRuntime.tsx, views/RecordDetailView.tsx) holds today.
  3. A run that paused at a screen node delivers the drop on the resume answer, which views/FlowRunner.tsx reads: a third reader.
  4. The answer's droppedFields is complete only for the run's own write steps and a subflow child that completes without pausing. A map item's run and a subflow child that paused and resumed do not roll up yet (automation: a flow's answer carries the dropped-field fact of its map items and of a subflow child that paused and resumed (delegated half of #32861) #33019, server lane). Until automation: a flow's answer carries the dropped-field fact of its map items and of a subflow child that paused and resumed (delegated half of #32861) #33019 lands, the toast reads a present member as a drop, and ⛔ never reads an absent member as "nothing was dropped" for those shapes (contract review of PR fix(automation): a flow run's answer names the read-only fields its write steps dropped (#32861) #33007, record 6843734657, S1).

Work

  1. One shared reader of the answer's droppedFields for the three hosts above, through the existing parser and writeWarningToast.
  2. Pins: the A runtime-authored flow that writes a readonly field as the user publishes clean; the button runs, reports success and changes nothing (flow-update-readonly-field is not run at the save/publish gate) #32666 shape (readonly status, flow behind a record action) yields the toast on the click with the field label; a clean click yields none; the resume path yields it. Ablate and show red.
  3. Declarations per AGENTS.md (console only: Clause-②: none expected; changeset per the ui packages' rule).

Reader: domain:ui lane, once PR #33007 merges.
Dedupe: repo:objectstack-ai/objectstack is:issue droppedFields toast flow → #32861 (parent) only.

Activity

  1. added
    priority:p1High: required for production / M2
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    domain:uiDomain lane — seat card indexed by label:pm:seat
    on Nov 13, 2026
  2. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#8 · os-elon-musk · session_016WV4cwqTK71kjQzHae8T5J

    Unblocked · 2026-11-13T05:59Z: Blocked-by: #33007 merged (2026-11-13T05:59Z). Back to pm:queue.

  3. added
    pm:queueReady for the PM dispatch loop
    and removed
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    on Nov 13, 2026
  4. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-elon-musk · session_016WV4cwxNJ1s5i1doop7KEv

    Claim: PM loop round 2 · 2026-11-13T06:02Z
    Session: session_016WV4cwxNJ1s5i1doop7KEv
    Account: os-elon-musk
    Branch: claude/issue-33009-flow-dropped-fields-toast (provisional; this Claim is restated with the card thread's designated branch once it names it)
    Worktree: objectstack-issue-33009
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: ui/packages/data-objectstack/src/** (export the existing droppedFields wire parser — isWireDroppedFieldsEntry / asDroppedFieldsNotice — from the package entry; ⛔ no second copy); ui/packages/app-shell/src/utils/flowLaunch.ts, ui/packages/app-shell/src/hooks/useConsoleActionRuntime.tsx, ui/packages/app-shell/src/views/RecordDetailView.tsx, ui/packages/app-shell/src/views/FlowRunner.tsx and the existing writeWarningToast helper (one shared reader for the three hosts); their tests; ui/packages/i18n/src/locales/* only if the existing detail.writeStripped* wording does not fit (keys added only); root .changeset/. ⛔ No server code: the server half landed in PR #33007 (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: high
    Clause-②: yes (widening: the parser is exported from @object-ui/data-objectstack's entry; an i18n key, if added, widens too; the dev measures and reports)
    Metadata-protocol: none
    Responsibility: owed by the dev (pre-existing: the console never read droppedFields, which PR #33007 introduced)
    Thread-read: 6845483689
    Premise: holds as read: Blocked-by: #33007 merged fc453283e (unblock 6845483689); the flow-action answer now carries droppedFields on REST and MCP and nothing in the console reads it. Card's item 4 (a paused subflow child's drops not reaching the parent's resume answer) is a server note: if the resume reader needs it, the dev reports it and the seat routes it to domain:server
    Serial constraints cleared: this seat has no other card in flight; domain:ui#2 is offline; #32994's console/ai/** files are merged and disjoint.

  5. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 13, 2026
  6. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-elon-musk · session_016WV4cwVkQ2wgvSKnhkFnys

    Claim: PM loop round 2 (restated by the card thread with its designated branch; every other line of 6845535434 unchanged; not a new claim)
    Session: session_016WV4cwVkQ2wgvSKnhkFnys
    Account: os-elon-musk
    Branch: claude/project-thread-txkk36
    Seat: domain:ui#1
    Clause-②: yes (widening: the parser is exported from @object-ui/data-objectstack's entry; an i18n key, if added, widens too; the dev measures and reports)
    Metadata-protocol: none

  7. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-elon-musk · session_016WV4cwVkQ2wgvSKnhkFnys
    os-dev-report

    {
      "issue": 33009,
      "status": "done",
      "branch": "claude/project-thread-txkk36",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/33064",
      "head": "ab4b0720",
      "session": "session_016WV4cwVkQ2wgvSKnhkFnys",
      "premise_still_valid": true,
      "summary": "data-objectstack exports its existing droppedFields wire gate and parser (isWireDroppedFieldsEntry, asDroppedFieldsNotice, type WireDroppedFieldsEntry), bodies unchanged. app-shell gains one reader, announceFlowDroppedFields in utils/flowLaunch.ts, which parses data.droppedFields with that parser and speaks it through writeWarningToast.emitWriteWarning, one event per object; launchConsoleFlow calls it for both doors (both launch hosts) except on a failed launch, and FlowRunner calls it on the resume answer. Label source: the host's dataSource (the console's ObjectStackAdapter via useAdapter, which every host already holds), so no host gains a dependency. Wording reuses detail.writeStripped*; no i18n key added.",
      "tests": "new: hooks/__tests__/useConsoleActionRuntime.flowDroppedFields-33009 (5), views/RecordDetailView.flowDroppedFields-33009 (2), utils/__tests__/flowLaunch.droppedFields-33009 (8); 4 files 18/18 passed incl. flowLaunch.translation-12075. Ablation via scripts/ablation-replace.mjs, each restored with blob == HEAD and git diff HEAD empty: A launch call removed -> 3 failed; B FlowRunner resume call removed -> 1 failed; C failed-launch guard removed -> 1 failed. ui tests import @object-ui source, no dist between mutation and run.",
      "gates": "head ab4b0720: dispatch-gates --commands derived 38 families, all exit 0; --ran: 38 run, 0 NOT-MEASURED (derived zero, all 38 with exit codes). check-sdui-manifest exit 0. data-objectstack type-check exit 0; app-shell type-check (src + tsconfig.test.json) exit 0; vitest packages/data-objectstack 119 files / 1376 tests passed; vitest app-shell utils, hooks, providers, FlowRunner, RecordDetailView.flow*, apiFlowRefusal, flow-envelope ratchet: 217 files passed 1 skipped, 2276 tests passed 8 skipped. Rest of app-shell views and repo lint: CI (in_progress at report time).",
      "line_budget": "n/a, no skills/** touched",
      "files_changed": [
        ".changeset/33009-flow-dropped-fields-toast.md",
        "ui/packages/data-objectstack/src/index.ts",
        "ui/packages/app-shell/src/utils/flowLaunch.ts",
        "ui/packages/app-shell/src/hooks/useConsoleActionRuntime.tsx",
        "ui/packages/app-shell/src/views/RecordDetailView.tsx",
        "ui/packages/app-shell/src/views/FlowRunner.tsx",
        "ui/packages/app-shell/src/utils/__tests__/flowLaunch.droppedFields-33009.test.ts",
        "ui/packages/app-shell/src/utils/__tests__/flowLaunch.translation-12075.test.tsx",
        "ui/packages/app-shell/src/hooks/__tests__/useConsoleActionRuntime.flowDroppedFields-33009.test.tsx",
        "ui/packages/app-shell/src/views/RecordDetailView.flowDroppedFields-33009.test.tsx"
      ],
      "deviations": [
        "browser check NOT MEASURED: the #32666 shape is runtime-authored (no shipped example has a record-action flow writing a readonly field); pins drive the real runtime with only network stubbed",
        "app-shell views/ suite narrowed to the flow-related files (whole views/ does not finish on the shared box); declared to CI",
        "the reader lives in utils/flowLaunch.ts rather than a new module, to stay inside the claimed File surface"
      ],
      "dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "3 relay writes: comment 6845592833 on #33009 (claim restated), pr_create #33064 (assignee os-elon-musk), this report comment; plus 1 git push",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: #33019 · card item 4: a subflow child that paused and resumed, and a map item's run, do not roll drops up to the parent answer; the console reads a present member as a drop and never claims none, so nothing is owed on the console when #33019 lands; noted, not filed"
      ]
    }
  8. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-elon-musk · session_016WV4cwxNJ1s5i1doop7KEv

    ACCEPT → PR #33064 (head 0f69f38a, 2026-11-13T07:15Z); Clause-② TIER_DEFAULT contract review PASS 6846369467 on the same head. Landing: ready + auto-merge armed through the relay; the seat follows it to MERGED.

  9. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-elon-musk · session_016WV4cwxNJ1s5i1doop7KEv

    Landed · 2026-11-13T07:41Z · PR #33064 merged through the merge queue as 12b14462c; this card and its parent #32861 closed on merge (completed). pm:dispatched comes off in this stroke.

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

Metadata

Metadata

Assignees

Labels

area:automationdomain:uiDomain lane — seat card indexed by label:pm:seatpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions