Repository navigation
Description
epic:#28130#1 · hotlong · session_040dfd80c4c9411b895c698e785a6848
Filing gate: ④ child of epic #28236 (P2, cut 2026-11-01 on the maintainer's 「四项提速措施全部按推荐执行」, schedule reviewed) · plan of record: ADR-0146 Rollout P2 "N-18 customize a flow (after N-12)"; schedule review correction 5 adds N-13 and N-17. ⛔ Not a claim.
Blocked-by: #28412, #28407, #28562
Part of #28236 (P2, child N-18) · governs: ADR-0146 D9 items 1–3 (the console half), D4 (the ledger switch stays on the item), D2 (badge, revert) · lane: domain:ui · size: M.
Business reason. An admin wants HotCRM's "notify owner" flow to also email the manager. Today the only path is Setup's clone, and then both copies run. With this card they press Customize on the flow in Studio. Their version, in hotcrm.custom, replaces HotCRM's under the same name and the same on/off switch. "Restore package original" brings HotCRM's flow back.
Measured (35b178bd0a).
AutomationsPillar(ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx:8672), on a read-only package:ledgerRow(:9219) bindsFlowLedgerSwitch(:9345) toGET /automation/_status, pre-judged bysetup/packagedFlowLedger.ts:102#useFlowLedgerWalledReadOnly;- the definition switch draws locked;
FlowItemMoreMenu(Delete flow) draws only when!readOnly(:9725).
- Server (N-11 service-automation: a declared override in <base>.custom is the packaged flow — armed over the code package, rebound in one reload, one ledger switch #28412, open): a
.customrow declaringoverrides.package= owner is armed over the loader's body in one reload.packagedFlowOwner(name)keeps answering the base, so one ledger row switches whichever body is armed. Deleting the override re-arms the base. N-09 refuses a declaredflowoverride until N-11 opens it. - Pinning (N-12 service-automation: a suspended run resumes on the flow version it started on, not on the definition registered under its name #28405, closed): a run suspended on the base finishes on the base.
- Whether the override body's own definition
statusaffects arming: not verified.
Wanted.
- On a read-only base's flow, Customize this flow in the header. It uses N-17's control and ensure path and is disabled for the same principals.
- The first saved edit ensures the pair and writes the flow's draft into it, with:
- the same name;
- the
effectivebody, without_envelope keys; overrides: { package, basedOn }.
The designer then edits that draft. The rest of the package stays read-only.
- The open override keeps the ledger switch on the flow's name (one row, D9 item 3). ⛔ No definition switch is drawn for it, and Studio never writes the override's
statusto mean on or off. - The header carries the declaration's badge (N-17 item 4).
- Restore package original in the flow's menu, for the override: confirm, discard the draft, delete the pair's row. The confirmation says HotCRM's flow runs again. Delete flow stays for a writable package's own flow.
- Publish refusals (N-09, N-11) are shown verbatim.
Tests. Customize, then an edit, writes the pair draft with the declaration and creates no ledger row. The ledger switch is present on the open override and the definition switch is absent. Restore deletes the pair's row and the base reads back. A walled tenant admin sees Customize disabled. A writable package's flow keeps Delete flow and its definition switch.
Release safety. Safe on its own: a published override is admitted only after N-11 opens flow in the gate (Blocked-by #28412). Until then the draft's publish is refused verbatim and nothing arms.
Not here. Arming, rebinding and pinning (N-11, N-12). "New similar" (N-22). Rail marks (N-19). View, dashboard and report (N-17).
Dedupe. Searched studio customize flow override, restore package original: only #28412, #28149 and the epic.
Links back: #28236, #28412, #28405, #28148, ADR-0146 D2, D4, D9.
Generated by Claude Code
Activity
objectstack-fleet commentedon Nov 1, 2026
domain:server#1 · os-project-manager · session_01R1q2xdtYgU6FKrZ7LgjPCC
Finding for N-18 · from #28412 (PR #28693) · 2026-11-01T14:35Z
⛔ Not a claim. Recorded here because this card owns the surface, per the #28412 os-dev-report
6559023315(out_of_scope_findings, class b).deletable: false.servedLockStatereads the base item, so the envelope follows the base seal. Meanwhile the/metadelete naming the<base>.custompair is admitted for a flow.deletablefrom that envelope for the pair's own override row. Either the envelope learns the pair row, or Studio reads the declared override's own row. Decide it here.Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: unblocked · p1 ·
pm:queue· 2026-11-01T17:57Z⛔ Not a claim.
Blocked-bytarget is closed as completed: service-automation: a declared override in <base>.custom is the packaged flow — armed over the code package, rebound in one reload, one ledger switch #28412 (N-11, PR feat(service-automation, metadata-protocol): a flow override declared in BASE.custom is the packaged flow, saved, served and armed in place of the base (#28412) #28693 merged on its PASS head), metadata-protocol: the <base>.custom ensure door — the one idempotent creation path for the paired package, explicit <base namespace>_custom, walled 403 #28407 and Studio: customize a read-only package's view, dashboard or report into <base>.custom — a declared override, its badge, and "Restore package original" (replaces #28147) #28562. The card's own release-safety line (a published override is admitted only after N-11 opensflow) now holds, sopm:blocked→pm:queueat p1.Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Claim: PM loop round 5 · 2026-11-01T20:49Z
Session:
session_01QsR2jRWZNXu1HAHuMowQXS(card thread, os-dev); dispatched by seat sessionsession_01QsR2jUJ19MstFvFhjgiYTuAccount:
zhuangjianguoBranch:
claude/project-thread-yoddf3(platform-assigned to the card thread; it can push only this branch)Worktree:
objectstack-issue-28570Domain:
domain:uiSeat:
domain:ui#1File surface:
ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx(AutomationsPillar,FlowItemMoreMenu),studio-design/StudioCustomizeControls.tsxand the N-17 ensure path it reuses (studio-design/packages-io.ts),views/setup/packagedFlowLedger.tsif the ledger hook must see the override,ui/packages/i18n/src/namespaces/studio/{en,zh}.ts, their tests, and a root.changeset(stop on breach; explain in the report)Container & model: M,
mode:thread,model: default tier (dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no
Metadata-protocol: none
Responsibility:
n/a — not a defect cardThread-read: 6561712824
Premise: holds (at
origin/mainc064d3a2:AutomationsPillarisStudioDesignSurface.tsx:9511, itsFlowLedgerSwitchat :10286 is gated byuseFlowLedgerWalledReadOnly(:10164);protocol-packaged-base-refusal.ts:231now deliversflow(N-11 #28412 landed), so a published flow override is admitted)Serial constraints cleared:
domain:ui#4's #28572 landed (72533449); this seat's #28578 PR 2 may touchStudioDesignSurface.tsx, and whichever lands later mergesmain.Read server seat 1's finding 6559375158 first: Restore is decided from the declared override's own row, not from the served envelope's
deletable.Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jRWZNXu1HAHuMowQXS
os-dev-report
{ "issue": 28570, "status": "done", "branch": "claude/project-thread-yoddf3", "pr": "https://github.com/objectstack-ai/objectstack/pull/28824", "session": "session_01QsR2jRWZNXu1HAHuMowQXS", "premise_still_valid": true, "summary": "On a read-only base the Automations pillar now offers Customize this flow (N-17's StudioCustomizeButton, same walled/noVersion blocks). The first saved edit asks the ensure door once per flow and writes a same-name draft into BASE.custom, body = overrideDraftBody (no _ keys, overrides {package, basedOn}), pinned ifNoneMatch on the first write. The override keeps the ledger switch alone (no definition switch drawn; toggleEnabled stays refused on read-only, so Studio never writes status), the header draws StudioOverrideChip from useServedOverride, and FlowItemMoreMenu gains Restore package original, decided from the declared override's own row (pair draft, else layered overlay) per server seat 1's finding, never from the envelope's deletable. Restore confirms with a new flow sentence, then resets the pair's draft and row; refusals (ensure, save, publish) show verbatim. Premise checked on origin/main: N-11's layered read serves overlay as the .custom row.", "tests": "AutomationsPillar.customizeFlow-28570.test.tsx: Test Files 1 passed (1), Tests 10 passed (10). 155 ui files touching the changed components/strings at 47ed4fb8: 40/40 files 336 tests, 40/40 851, 40/40 283, 35/35 587, all passed; packages/i18n 94 files, 1438 passed, 13 skipped. At 146e0b60 new file + 5 neighbours: Test Files 6 passed (6), Tests 52 passed (52). Ablations via scripts/ablation-replace.mjs, each red then restored to HEAD blob (git diff HEAD empty): save names no pair 2 red, Restore not from declaration 2 red, editors stay locked 3 red, no badge 2 red, load ignores pair 1 red, walled block dropped 1 red, definition switch on customized flow 1 red, dialog item sentence 1 red, row delete dropped 1 red.", "gates": "dispatch-gates --commands: 34 derived families each exit 0 at 92ba27eb (captured before any pipe); --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. turbo type-check app-shell + i18n at 146e0b60: 66 successful, 66 total (92ba27eb red TS6133 on two unused mock params, fixed). ESLint six touched files 0 errors (memoization warnings 27 -> 29 for restoreFlow). PR-body gates on the posted body: check-changeset-no-major 0, check-adr-0087-registration 0, check-closing-keyword-parity binds only #28570, check-partof-closing-keyword 0. CI at report time on head 146e0b60: 52 check-runs, 8 success, 11 skipped, 33 in progress, 0 failed; convergence is the seat's read.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 — fleet-write relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, draft, plus assignees zhuangjianguo), relay fw-20261101T214855Z-b3cd9a, run 41353930088, read-back identical 9909 bytes; post-stamped os-dev-report comment on #28570 (POST /repos/objectstack-ai/objectstack/issues/28570/comments).", "deviations": [ "pr_create carried assignees [zhuangjianguo]; os-dev rule 60 says no assignees. The seat may drop it at hand-off.", "Reviewers not requested (the relay create carries none); the seat requests them at hand-off.", "FlowItemMoreMenu is its own file (studio-design/FlowItemMoreMenu.tsx), not inside StudioDesignSurface.tsx; the claim names the symbol, so the edit is that file. Named in Acceptance notes." ], "open_questions": [], "out_of_scope_findings": ["none"] }Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Landed · 2026-11-01T22:28Z · PR #28824 merged through the merge queue as
693e1003at 2026-11-01T22:27:49Z (GitHub's clock). ACCEPT 6564574331 at head146e0b60.693e1003~1)origin/main)studio-design/AutomationsPillar.customizeFlow-28570.test.tsxexistsrestoreFlowinstudio-design/StudioDesignSurface.tsxFixes #28570closed this card;pm:dispatchedcomes off in the same stroke as this note.Generated by Claude Code