Repository navigation
fix(app-shell): a flow that dropped a read-only field warns the person who clicked, naming the field by its label - #33064
Merged
Conversation
…n who clicked, naming the field Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cwVkQ2wgvSKnhkFnys
…h, inside the claimed file surface Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cwVkQ2wgvSKnhkFnys
…c names the reader where it lives Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cwVkQ2wgvSKnhkFnys
This was referenced Nov 13, 2026
Contributor
Author
|
domain:ui#1 · os-elon-musk · session_016WV4cwxNJ1s5i1doop7KEv Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
Contributor
Author
|
domain:ui#1 · os-elon-musk · session_016WV4cwxNJ1s5i1doop7KEv 席位核对 · ACCEPT ·
|
This was referenced Nov 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Elon · project thread
Fixes #33009
Fixes #32861
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
Measured: the widening is three new exports of
@object-ui/data-objectstack(isWireDroppedFieldsEntry,asDroppedFieldsNotice, typeWireDroppedFieldsEntry), unchanged in body; no i18n key is added (the existingdetail.writeStripped*wording is reused).维护者速读
droppedFields。员工从记录按钮启动流程(列表/页面和记录页两处),或在流程屏幕点「提交」继续,若流程的写入步骤丢掉了只读字段,会弹出黄色警告,用字段的中文名说明哪个字段没写进去。ui/packages/app-shell/src/utils/flowLaunch.ts(新读取器announceFlowDroppedFields及settled里的调用)、ui/packages/app-shell/src/views/FlowRunner.tsx(继续运行时的调用)、ui/packages/data-objectstack/src/index.ts(只加 export)。ui/下跑pnpm exec vitest run packages/app-shell/src/hooks/__tests__/useConsoleActionRuntime.flowDroppedFields-33009.test.tsx,应见 5 passed。What changes
@object-ui/data-objectstack: the existingdroppedFieldswire gate and parser (isWireDroppedFieldsEntry,asDroppedFieldsNotice, with its skew arm for an unknownreason) and their sharedWireDroppedFieldsEntrytype are exported. Bodies unchanged; no second copy anywhere.@object-ui/app-shellutils/flowLaunch.ts: one reader,announceFlowDroppedFields(json, { t, fieldLabel, dataSource }), parsesdata.droppedFieldswith that parser and speaks it through the existingwriteWarningToast.emitWriteWarning(the record save's own title, per-reason sentence and label lookup), one event per object the entries name.launchConsoleFlowcalls it insettled()for both doors (action door and trigger route), so both launch hosts (useConsoleActionRuntime,RecordDetailView) are covered by one call; it is skipped on a failed launch. Not awaited, so the label lookup never holds the click's outcome or its refresh.views/FlowRunner.tsx: the resume answer goes through the same reader (every non-failed answer).useConsoleActionRuntimeandRecordDetailViewpass{ t, fieldLabel, dataSource }intolaunchConsoleFlow.detail.writeStrippedTitle/detail.writeStripped*keys; no new key.Label source chosen (the order asked which): the host's
dataSource. In the console it IS theObjectStackAdapter(AppContent/ConsoleShell:const dataSource = useAdapter()), every host already holds it (it renders their forms;FlowRunneralready takes it as a prop), and its cachedgetObjectSchemais exactly whatAdapterProviderhands the save toast. So no host gains a dependency, and the flow toast labels fields by the same path the save toast does. A data source withoutgetObjectSchemanames fields by api name. Alternatives measured and not taken: building a schema source from the hosts'objects(would miss an object the flow writes that is not in the loaded list, and would be a second label path);useAdapter()inside each host (a new hook call in three places for a value they already hold).Per object, not per click: a flow can write any object, so each entry is labelled on the object it names; an off-spec entry with no
objectis named by api name rather than guessed onto the clicked record's object (wherestatuswould get the wrong object's label).Tests
New, all against the real runtime (real
ActionRunner, flow handler, launch module, reader,writeWarningToast,FlowRunner, en pack; only the network, router, toaster andgetObjectSchemastubbed):hooks/__tests__/useConsoleActionRuntime.flowDroppedFields-33009.test.tsx(5): 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 through the action door → one warningSaved — but some fields did not take effect/Read-only, so it did not take effect: Approval status; a clean click → none; the trigger route → the same warning; the resume path (paused, then Submit answered with the drop) → the warning; CONTROL: a resume answer withoutdroppedFieldscloses withFlow "Submit" completedand no warning.views/RecordDetailView.flowDroppedFields-33009.test.tsx(2): 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 on the record page → the warning namingApproval status; CONTROL: a clean click → none.utils/__tests__/flowLaunch.droppedFields-33009.test.ts(8): parse through data-objectstack's parser incl. skew arm and a no-stringfieldsentry dropped; per-object labelling across two objects; unknown reason →Not applied by the server: …; noobject→ api name, no schema lookup; data source withoutgetObjectSchema→ api name; CONTROL: no member → no toast; a failed launch carrying the member → no warning.utils/__tests__/flowLaunch.translation-12075.test.tsx: passes the new required input.Ablation (fix commented out, red, restored by `scripts/ablation-replace.mjs`)
flowLaunch.tssettled()call removed → 3 failed (record page 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, runtime 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, trigger route); restored,git diff HEADempty.FlowRunner.tsxresume call removed → 1 failed (the resume path); restored,git diff HEADempty.git diff HEADempty.ui tests import
@object-ui/*source, so no dist rebuild sits between mutation and run.Acceptance notes
domain:server): the resume reader reads whatever the resume answer carries; asubflowchild that paused and resumed, and amapitem's run, do not roll their drops up to the parent answer yet. Tracked by 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; the console reads a present member as a drop and never claims "nothing was dropped", so no console change is owed when 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.Verification
All local runs on head
ab4b0720(origin/mainc54a23d2merged; main had not moved since the branch point).dispatch-gates --commandsderived 38 families; all 38 ran, exit 0 each;--ranreconciliation: "38 run, 0 NOT-MEASURED (a DERIVED zero — all 38 recorded an exit code and none of them is 3)". Includesnode scripts/check-sdui-manifest.mjs(exit 0) andpnpm check:test-source-alias(exit 0).pnpm --filter @object-ui/data-objectstack run type-check:: exit 0;pnpm --filter @object-ui/app-shell run type-check(src +tsconfig.test.json) :: exit 0.vitest run packages/data-objectstack/:: 119 files, 1376 tests passed.vitest runapp-shellutils/,hooks/,providers/,views/__tests__/FlowRunner*,views/RecordDetailView.flow*,views/RecordDetailView.apiFlowRefusal*,flow-envelope.ratchet.test.ts:: 217 files passed, 1 skipped; 2276 tests passed, 8 skipped. The rest ofviews/(does not finish on the shared box) is declared to CI.pnpm lintand the full farm: CI.