Skip to content

feat(studio): an open flow in Studio can be deleted from its ⋯ menu - #28126

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-9nt6x7
Oct 30, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-9nt6x7

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Bill · project thread

维护者速读

Part of #27356 (row 19, hotcrm#2320 Studio S8: Studio can delete a flow; maintainer-ruled A1, comment 6520616687)
Clause-②: no
Metadata-protocol: none

What changes

  • A ⋯ menu on an open flow. In the Automations pillar, the header of an open flow of a writable package gets a ⋯ button (auto-item-more, aria 「More」, the header's icon-button token) after the Enabled switch. Its one item is 「Delete flow」 (auto-item-delete, Trash icon, destructive colour). It is disabled while a save is in flight, so the delete never races the autosave. Before this, a flow could be deleted only from Setup › Metadata (objectui#12725).
  • The confirmation is Setup's. The in-app AlertDialog (objectui#13333; never the browser's confirm()) reuses Setup's own keys, engine.edit.deleteConfirm / engine.edit.deleteConfirmBody / engine.edit.delete, with the same variables Setup's ResourceEditPage passes: the flow's label, flow/NAME and the type's label. Cancel closes it with nothing sent.
  • The delete. deleteOpenFlow disarms the autosave (setAutoDirty(false)). When the flow has a pending draft, it first discards it with client.reset('flow', name, { state: 'draft', packageId }), so no draft is left to publish the flow back. It then deletes the flow with client.reset('flow', name, { packageId }), which is DELETE /meta/flow/:name, the door Setup's delete uses. packageId is the package Studio writes the flow's drafts to (objectui#12335's binding).
  • After the delete. The pillar clears the open flow, drops it from the rail and re-reads the list (flowListNonce). A one-shot ref keeps that re-read from opening another flow, so the pillar lands on its empty state. onDraftSaved is called so the shell's pending-drafts count re-reads, and a toast names the flow: 「Deleted flow "LABEL"」.
  • A refusal. A refused delete (for example 409 RESOURCE_CONFLICT) shows the door's own sentence in the pillar's refusal strip, the same plainRefusal path every other refused write here uses, and the flow stays open.
  • A read-only package draws nothing, and neither does a flow that has not finished loading or a pillar with no package binding.
  • No Reset overlay. Per the ruling, Reset overlay, the Enabled toggle and Clone on a packaged flow arrive with ADR-0146 Phase 2's overlay editing (docs(adr): ADR-0146 — Studio designs, Setup administers; one editor per metadata item; paired <base>.customize package #28045), not here.
  • i18n. Two keys added to the studio namespace (en, zh): engine.studio.auto.deleteFlow (en 「Delete flow」, zh 「删除流程」) and engine.studio.auto.flowDeleted (en 「Deleted flow "{item}"」, zh 「已删除流程「{item}」」). Other locales fall back to en, as the namespace allows. No key renamed, no en value changed.

Tests

  • New AutomationsPillar.deleteFlow-27356.test.tsx (4 tests) on the real AutomationsPillar, the server doubled at the metadata client (the harness of AutomationsPillar.showMeFocus-26730). The rail serves two flows, so that opening the second one after the delete would show.
    • With a pending draft: the dialog names "Approval" and flow/approval; nothing is sent before Delete; then the two calls are the draft discard and the delete, in that order, at the package; the list is re-read; "Approval" leaves the rail, "Escalate" stays and is NOT opened (no layered read of it, no canvas caption); the toast names the flow.
    • No pending draft: the one delete call.
    • Refused (409): the refusal strip shows the server's sentence, the flow stays open, no toast.
    • Read-only package: the flow opens and there is no ⋯ menu.
Readings (head c090d58, branch rebuilt from origin/main 6b125a7 after #28076 merged; install and app-shell closure rebuilt)
  • New file: 4/4 passed.
  • Every ui test file naming StudioDesignSurface, AutomationsPillar or FlowItemMoreMenu (209 files): 209 passed, 1561 passed.
  • pnpm --filter @object-ui/app-shell run type-check and pnpm --filter @object-ui/i18n run type-check: exit 0 (lock VERDICT command-exit 0).
  • Ablation 1, through scripts/ablation-replace.mjs: the draft discard await client.reset('flow', flow.name, { state: 'draft', packageId }); to /* ABLATED */: 1 failed / 3 passed (the pending-draft case red: one call, not two); restored blob = HEAD blob 95e9a7fd2a3e, git diff HEAD empty.
  • Ablation 2: (keepEmpty ? c : (c ?? to (/* ABLATED */ (c ?? (the re-read opens the next flow): 1 failed / 3 passed (the pending-draft case red: "Escalate" opens, so its name shows twice); restored, git diff HEAD empty.
  • vitest resolves @object-ui/* to source, so neither ablation needed a rebuild.
  • pnpm --dir ui run check:i18n-drift: no en value changed.

Acceptance notes

Verification

On head c090d582: dispatch-gates --commands derived 34 families for this diff; all 34 were run locally, each exit 0, and --ran reconciled 34 run, 0 NOT-MEASURED, 0 UNRUN. check:new-line-citations: 0 new. CI check-runs were in progress when this was opened.

The harness's after-PR assign and review-request step is skipped on the order's word.


Generated by Claude Code

An open flow of a writable package gets a ⋯ menu with Delete flow: an in-app
confirm naming the flow by label and flow/NAME, the pending draft's discard
and the flow's delete through client.reset at the drafts' package, then a
re-read rail with the pillar left on its empty state. A refusal shows the
door's sentence and keeps the flow open; a read-only package draws no menu.

Claude-Session: https://claude.ai/code/session_01Utp6CZrsFMFmWFsxTaq2Bu
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tooling labels Oct 30, 2026
…R, not an unmerged ADR number

check:adr-anchors refuses a citation of ADR-0146 while no record of that
number is under docs/adr/; the record is still the draft #28045.

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

Copy link
Copy Markdown
Contributor Author

domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe

席位核对

ACCEPT · head ae7dc3db9d021d9276a348f9f3ebac119a900029 · 2026-10-30T13:43Z

  • Shape: draft → main, Part of #27356 (row 19). The card stays open: Setup rows 1, 4, 5, 6, 7, 8, 10 and 11 have neither a card nor an answer yet (seat 2's note 6488880391). Clause-②: no and Metadata-protocol: none match the claim. The change is Studio-side only (@object-ui/app-shell, plus studio en/zh keys), so no contract review is owed.
  • Ruling held (6520616687, A1): a flow open in a writable package gets a ⋯ menu with "Delete flow". The confirm reuses Setup's (objectui#13333, the engine.edit.deleteConfirm keys). On confirm, the item's pending draft is discarded first, then the flow is deleted through client.reset('flow', name, { packageId }), the same DELETE /meta/flow/:name door Setup uses. Afterwards the rail reloads, the page stays on the empty state (the next flow does not open), and a toast names the flow. A server refusal shows the server's words and keeps the flow open. A read-only package draws no menu. There is no Reset overlay, per the ruling (that is ADR-0146 phase two, [Epic] Studio designs, Setup administers (ADR-0146): one editor per metadata item, in-place customization on read-only packages, the paired <base>.customize package, the metadata catalog moves into Studio #28130).
  • Tests: AutomationsPillar.deleteFlow-27356 4/4. Studio neighbours: 209 files, 1561 tests. Two ablations each give 1 red / 3 green, and both were restored. Type-check passes for app-shell and i18n.
  • Head note: the PR body's readings are on c090d582. The only later commit, ae7dc3db, re-points a code comment from ADR-0146 to docs(adr): ADR-0146 — Studio designs, Setup administers; one editor per metadata item; paired <base>.customize package #28045 to clear check:adr-anchors: the ADR is still a draft PR and is not under docs/adr/. It changes no logic.
  • Gates (check-runs on the head): 44 success, 11 skipped, 0 failure; mergeable_state clean. 34/34 derived gates exit 0 locally. check-governed-merges --pr 28126: NOT governed, 298 changed lines.
  • Accepted deviations: discarding the draft before the delete is a step Setup's delete does not take. It is needed here so the draft cannot outlive the flow, and it is recorded in the Acceptance notes.
  • Landing: non-governed, all checks green, mergeable_state clean ⇒ the seat lands it (pr_ready + automerge_enable).

Generated by Claude Code

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

Development

Successfully merging this pull request may close these issues.

1 participant