Skip to content

fix(studio): the flow Problems list reads the draft's publish verdict, and a blank expression says it needs one - #27826

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-6sfxmc
Oct 30, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-6sfxmc

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe

Requested by Bill · project thread

Fixes #27799

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:Studio「自动化」里流程的「问题」面板接上了草稿读回时服务器给出的发布判定(之前只有步骤检查器在读它);值写成表达式却留空时,节点和问题面板都改说「这个值需要一个表达式」,不再显示信封的线上格式。
  • 为什么改:节点按 spec 的值槽规则报错,发布门禁也按同一规则拒绝,但问题面板只看画布结构,于是一边报错一边说「没有问题——该流程结构有效」,作者照此发布会被拒。
  • 风险与回滚:只动 ui(app-shell 私有包 + i18n 两条文案);问题面板现在会多出服务器判定里的条目(包括以前就存在、但 Studio 没显示的 schema 错误),属预期;回滚即 revert 本 PR。
  • 先看:StudioDesignSurface.tsx(把 flowVerdict 交给画布的那一处)、previews/flow-problems.ts(服务器条目的定位与文案)、inspectors/flow-value-envelope.ts(isBlankExpressionRefusal)。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/app-shell/src/views/studio-design/AutomationsPillar.problemsAgree-27799.test.tsx,预期 3 个用例全绿。
  • 需要你做的:无,席位落地。

What changes

Measured first, on main at 86aaff32, with the Studio Automations page mounted against a server double that judges as the server does (the save door parses FlowSchema; the draft read folds in the publish gate's finding from the real validateStackExpressions). A record-change flow, an Update Records node, a value id switched to an expression and left blank:

  • the value cell showed the spec's refusal (AssignmentValueSchema, run live): "A value carrying a dialect key is read as an expression envelope … Write { dialect: 'cel', source: '…' }";
  • the draft save was accepted (the flow parse does not run the value-slot rule, by design: flow-value-slot-template.ts, "The doors that run it"), and the draft read's _diagnostics carried the publish gate's expression-invalid finding with the same message;
  • the Problems tab read "No problems — this flow is structurally valid.", because the page handed the served verdict to the inspectors (objectstack#26858) and never to the canvas: FlowPreview got no diagnostics there.

So the blank expression is a defect (the publish refuses it), and the one judge is the spec's value-slot rule, which both the cell and the publish gate run. The fix wires Problems to that verdict; no client-side validator is added.

  • Problems reads the served verdict. The Automations page hands flowVerdict (the draft read's _diagnostics, re-read after each autosave) to the flow preview as diagnostics, through verdictPreviewEntries in draftVerdict.ts, with messages through translateValidationMessage as the metadata edit page does.
  • The row names the node and the field. The publish gate locates a finding on a node's config value in words (flow 'touch_account' · node 'write' (update_record) update_record field value at config.fields.id), not as an item path, so it cannot be placed on a node. A server row on no element now shows the server's locator as its target instead of the bare word "flow".
  • Business words, from the spec's own verdict. isBlankExpressionRefusal recognises the spec's refusal of a blank expression by asking the spec once what that refusal reads (valueEnvelopeRefusal({ dialect: 'cel', source: '' })), never by restating the rule. The value cell and the Problems row both say "This value needs an expression. Write one, or switch the value back to text." (zh: 「这个值需要一个表达式。请填写表达式,或把这个值切回文本。」). Every other refusal shows as before.

Tests

  • New studio-design/AutomationsPillar.problemsAgree-27799.test.tsx (real FlowPreview + real FlowInspector, server double as above):
    • one judge: for the blank value the flow parse passes and the publish verdict's messages equal the cell's live spec refusal;
    • the cell and the Problems row both show the business sentence; the row's target names node 'write' and config.fields.id; the tab count is 1;
    • control: writing record.id clears the cell, and after the autosave Problems reads "No problems" again.
  • FlowKeyValueField.valueEnvelope.test.tsx: the blank-expression case now expects the business sentence (the malformed-template case still shows the spec's sentence).

Acceptance notes

Verification

Repro on main (before)

The measurement test, run on 86aaff32 before the change: cell alert = the spec's envelope sentence; 1 save, 0 refused; served verdict valid: false with the same message at the where locator; Problems showed the empty-state sentence, 0 rows.

Ablations (each through scripts/ablation-replace.mjs, restored to HEAD)
  • diagnostics: flowPreviewDiagnostics ablated → 2 of 3 new cases red (Problems stays empty).
  • the Problems-row business wording ablated → 1 red.
  • the value-cell business wording ablated → 2 red (the new case and the updated valueEnvelope case).
Local runs

All at head 7c47a855, under scripts/pm/os-verify-lock.sh:

  • pnpm --filter @object-ui/app-shell run type-check (both tsc programs) → exit 0.
  • pnpm --dir ui exec vitest run over packages/app-shell/src/views/studio-design/ plus the 91 test files that name FlowPreview, ProblemsPanel, flow-problems, FlowKeyValueField, flow-value-envelope, draftVerdict, FlowNodeConfigField or FlowNodeInspector → Test Files 357 passed (357), Tests 3097 passed (3097).
  • pnpm --dir ui exec vitest run packages/i18n/ → Test Files 90 passed (90), Tests 1380 passed, 13 skipped.
  • pnpm check:new-line-citations (ui) → 0 new citations, exit 0.
  • Not run locally, declared to CI: the whole Test UI shards and the rest of the lint farm.
Gates

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 7c47a855 derived 34 families; each run and recorded as command :: exit code before any pipe; all 34 exit 0, including node scripts/check-sdui-manifest.mjs and pnpm --dir ui exec vitest run scripts/ (169 passed, 2 skipped files; run alone under the lock). --ran reconciliation: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN.


Generated by Claude Code

…, and a blank expression is said in business words

Studio's Automations page kept the draft read's served verdict for the
inspectors but never handed it to the canvas, so Problems read "No
problems" for a flow whose publish refuses a blank expression value.
The preview now gets the same verdict; a finding the server locates in
words keeps that locator as the row's target. The spec's refusal of a
blank expression is recognised from the spec's own judge and said as
"This value needs an expression" in both the value cell and Problems.

Claude-Session: https://claude.ai/code/session_01Utp6CaycqDGtn6KeXgc8hp
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe

席位核对

ACCEPT · head 7c47a8554764d57606803453d2d56f4d7ceda543 · 2026-10-30T01:18Z


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 30, 2026 01:19
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 30, 2026 01:19
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit ddab8b9 Oct 30, 2026
60 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-6sfxmc branch October 30, 2026 01:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

1 participant