Repository navigation
studio(flow canvas): adding a node is inconsistent — toolbar Add node creates a parallel branch, edge "+" and Add connected node insert create_record without asking, and the Node Type select has no notify #11778
Description
Activity
- addedbugSomething isn't workingSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seatarea:workflowApprovals and automation — the work that runs without a person driving itApprovals and automation — the work that runs without a person driving it
on Oct 7, 2026 objectstack-fleet commented
on Oct 7, 2026 ContributorAuthorMore actionsPath: approvals and automation — a flow built in Studio runs as drawn | 缺项 | P2
Triage: first grade,
bug·priority:p2·domain:ui·area:workflow·pm:queue. Direction as the body proposesTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-07T16:05Z. ⛔ Not a claim, ⛔ not a dispatch.Triage: lands in the Studio flow canvas (toolbar Add node, the edge "+", Add connected node) ⇒
domain:ui; rationale: a Studio or console surface in objectui. Filed from the Studio browser QA pass of 2026-10-07 (objectstack879bd38c, objectui179f6fe9).- Why p2: each of the three insert paths produces a different shape, and one inserts the wrong node type (measured).
- Direction:
- route edge-insert and add-connected through the palette
- auto-layout after an insert
- derive the type select from the palette's registry
- Serial: flow designer: Remove node leaves its edges behind, and the reused node id re-attaches them — a published flow ran one create_record three times for one update #11772 edits the same inspector region. Claim after it lands, or declare the overlap.
Clause-②: no. Patch changeset in objectui.
objectstack-fleet commented
on Oct 7, 2026 ContributorAuthorMore actionsClaim: PM loop round 3
Session:session_01CGZy1BGCjdN5cXqL9cnvB8
Account:os-support-ai
Branch:claude/issue-11778-flow-add-node-paths
Worktree:objectui-issue-11778
Domain:domain:ui
Seat:domain:ui#3
File surface (on2b30d39, the landing of objectui#11772), underpackages/app-shell/src/views/metadata-admin/:previews/FlowCanvas.tsx(addNode:283,insertOnEdge:337with itscreate_recorddefault, the edge "+" at:904, and the toolbar Add node);previews/flow-canvas-parts.tsx(NODE_PALETTE:333,NodePalette:714, the Add connected node control at:647);inspectors/flow-node-config.ts(FLOW_NODE_TYPE_OPTIONS:1623);inspectors/FlowNodeInspector.tsx(the Node Type select'stypeOptions,:446–:448);- the
engine.flow*rows ofi18n.ts; - the tests beside them;
.changeset/11778-*.md.
views/studio-design/StudioDesignSurface.tsxis not on it. Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report)
Container & model:M,mode:subagent,model: opus(dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate; default tier)
Clause-②: no
Responsibility:objectui app-shell: the flow canvas's three add-node paths disagree — toolbar Add node appends an unconnected branch from Start, the edge "+" and Add connected node insert create_record without asking (insertOnEdge's default type) at a midpoint that overlaps Start, and the Node Type select (FLOW_NODE_TYPE_OPTIONS) omits notify and shows raw names | the platform path: the palette (NODE_PALETTE) already lists the node types with display names | every author who adds a node to a flow in the Studio flow designer
Thread-read: 6041797961
Serial constraints cleared:noneblocking. objectui#11772 (sameFlowCanvas.tsx/ inspector region, this seat) landed as2b30d39, which clears the serial line in this card's triage comment6041797961. Noarea:workflowcard is in flight. No open objectui PR touches the files above (read 2026-10-07T19:25Z; open: #11826, #11600, #11069; #11826 touches neither the flow canvas nor the flow inspector).Fold-or-serial with the queued
area:workflowcards: serial, none folded, because fold gate ① fails for each (different defect shapes):- objectui#11788 (Notify recipients editor and
create_recordfield values) likely editsflow-node-config.ts/FlowNodeInspector.tsx, so it waits for this card to land; - objectui#11779 (flow status in the Automations list, header and Problems panel) and objectui#11789 (the CEL editor's
record.x) are re-read for intersection at their pick.
Why
Clause-②: no: an editor fix inside@object-ui/app-shell. Its strings are rows of app-shell's unexported designer table. If the fix needs a published export, prop, type member or language-pack key, the dev reports it before opening the PR, and the seat amends this line.
Generated by Claude Code
objectstack-fleet commented
on Oct 7, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 11778,
"status": "done",
"branch": "claude/issue-11778-flow-add-node-paths",
"pr": "#11832",
"session": "session_01CGZy1BGCjdN5cXqL9cnvB8",
"premise_still_valid": true,
"summary": "Measured on main 2b30d39 through the real FlowCanvas on start -> end: the edge '+' wrote create_record at once pinned at the midpoint {28,89} over Start; Add connected node wrote create_record at once as a second branch start -> node_1; toolbar Add node wrote the picked node with no edge (nothing selected) or as a second branch (Start selected); the Node Type select was the hand list FLOW_NODE_TYPE_OPTIONS (no notify, raw names). Fix (draft PR #11832, all on the claim surface, i18n.ts and StudioDesignSurface.tsx untouched): every '+' (edge, card, toolbar) opens the same NodePalette, one open at a time (FlowCanvas keeps one paletteAt key); the edge '+' splits its edge with the picked type; the card '+' and the toolbar share one named rule placeAfter (anchor = that node / the selected node, else Start): one way on -> split it, no way on -> append, decision/approval/parallel_gateway or a node already leading to 2+ nodes -> new branch (decision still carries its next condition), End -> before End on its single way in; no single path (End with 0 or 2+ ways in, or no Start and nothing selected) -> loose node, which the Problems panel names unreachable. insertOnEdge no longer pins position, so the layered layout gives the node its own row. FlowNodeInspector's Node Type select reads useFlowNodePalette() through paletteTypeOptions (palette order and display names; a stored off-palette type is kept for that node only under its display name). FLOW_NODE_TYPE_OPTIONS retired; its six test readers sweep FLOW_NODE_CONFIG_TYPES (the table's keys, a strict superset). NodePalette content now stops pointerdown: a palette opened from an edge or card sits inside the canvas viewport in the React tree and a row press otherwise bubbled to the pan handler and lost the click (ablation B). objectui#11772 pins: mock now returns the offline NODE_PALETTE, gesture helpers pick Create record, and the control keeps its exact ids and toEqual but its wiring is now start -> node_1 -> end (it had pinned the second branch this card reports); round trip byte-for-byte assertion unchanged and green.",
"tests": "HEAD 3947a9a: pnpm exec vitest run packages/app-shell/src/views/metadata-admin/previews/ .../inspectors/ + StudioDesignSurface.automationsReadOnly-11124 + packageLessFlows-11553 -> 'Test Files 230 passed (230) / Tests 3043 passed | 1 skipped'; pnpm --filter @object-ui/app-shell type-check -> exit 0 (tsconfig.test.json --listFiles includes all 13 touched/new test files); eslint 16 touched files -> 0 errors, 12 warnings (+1 vs main: react-refresh/only-export-components on the new paletteTypeOptions export). New pins: FlowCanvas.addNodePaths-11778 (11) and FlowNodeInspector.nodeTypeOptions-11778 (6), 17 passed. Full app-shell suite once at acdf998: 'Test Files 2 failed | 1061 passed | 1 skipped (1064)': FlowNodeInspector.connectorInput (text query now ambiguous with the Node Type trigger 'Connector'; fixed in 84f3800, 14 passed alone) and AppContent.inaccessibleAppStrand (network escape to localhost:3000 under load; untouched file; 6 passed alone); not re-run after 84f3800 (test + changeset only) -> CI. Ablations via objectstack scripts/ablation-replace.mjs from committed 84f3800, src-imported subjects (no dist), each restore proven blob==HEAD and git diff HEAD empty, over 50 tests: A edge '+' immediate create_record no palette -> 6 red; B palette no longer stops press -> 5 red (all edge/card picks; toolbar picks green); C toolbar back to addNode(from: selectedId) -> 4 red; D card '+' back to from-append -> 2 red (Start pin, 11772 control); E midpoint pin restored -> 4 red (11772 round trip green); F select back to hand list -> 6 red. First B attempt measured nothing (tool refused: replacement was a substring of the anchor), re-run with a marker. Browser: Chromium /opt/pw-browsers/chromium on preview-gallery.html?only=flow with real clicks: edge '+' opened the palette and added nothing, Notify inserted node_1 between Start and next (tops 28/150/272), card '+' and toolbar inserted after their anchors, Node Type listed the palette's 18 names, no page errors.",
"mcp_calls": "0",
"api_writes": "3 relay writes, each one POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write as objectstack-fleet[bot]: (1) pr_create POST /repos/objectstack-ai/objectui/pulls -> #11832, read back identical 14268 bytes; (2) label-write --assign os-support-ai -> POST /repos//issues/11832/assignees, read back MATCHES; (3) this os-dev-report comment POST /repos//issues/11778/comments. Plus 4 git pushes (empty branch probe, acdf998, 84f3800, 3947a9a). No label writes (tests and package: app-shell came from labeler.yml).",
"gates": [
{
"cmd": "pnpm exec vitest run (metadata-admin previews/ + inspectors/ + 2 Studio files) @3947a9a",
"exit": 0,
"verdict": "Test Files 230 passed (230); Tests 3043 passed | 1 skipped (3044)"
},
{
"cmd": "pnpm --filter @object-ui/app-shell type-check @3947a9a",
"exit": 0,
"verdict": "os-verify-lock: VERDICT command-exit 0"
},
{
"cmd": "pnpm exec eslint (16 touched .ts/.tsx) @3947a9a",
"exit": 0,
"verdict": "12 problems (0 errors, 12 warnings)"
},
{
"cmd": "pnpm check:control-bytes",
"exit": 0,
"verdict": "check-control-bytes: OK (scanned 7790 tracked text file(s); skipped 85 binary)"
},
{
"cmd": "pnpm check:test-path-roots",
"exit": 0,
"verdict": "check-test-path-roots: OK"
},
{
"cmd": "pnpm check:changeset-claims",
"exit": 0,
"verdict": "No pending changeset names a file this change touches."
},
{
"cmd": "pnpm check:pending-changeset-literals",
"exit": 0,
"verdict": "No test source names a pending changeset."
},
{
"cmd": "pnpm check:new-line-citations",
"exit": 0,
"verdict": "VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0"
},
{
"cmd": "pnpm check:vi-mock-specifiers",
"exit": 0,
"verdict": "check-vi-mock-specifiers: OK"
},
{
"cmd": "pnpm check:vi-mock-inherit",
"exit": 0,
"verdict": "check-vi-mock-inherit: OK"
},
{
"cmd": "pnpm check:vi-mock-override-shape",
"exit": 0,
"verdict": "check-vi-mock-override-shape: OK"
},
{
"cmd": "pnpm check:unreferenced-sources",
"exit": 0,
"verdict": "OK Every shipped source file in every covered package is reachable."
},
{
"cmd": "node scripts/check-changeset-presence.mjs",
"exit": 0,
"verdict": "17 file(s) changed vs merge-base 2b30d39; changeset present"
},
{
"cmd": "node scripts/check-changeset-no-major.mjs",
"exit": 0,
"verdict": "No changeset declares a major bump."
},
{
"cmd": "pnpm exec vitest run packages/app-shell/ @acdf998 (full package, once)",
"exit": 1,
"verdict": "Test Files 2 failed | 1061 passed | 1 skipped (1064): connectorInput (fixed 84f3800) + AppContent network escape (passes alone; untouched)"
},
{
"cmd": "CI on PR #11832 head 3947a9a",
"exit": null,
"verdict": "in_progress at report time: 42 check runs, 24 completed with no failure, 18 in progress"
}
],
"deviations": [
"objectui#11772's pin file FlowPreview.removeNode-11772.test.tsx was edited (Zone 3 suggested 'stay green unchanged'): its palette stub returned [] (not the hook's offline answer), its two gesture helpers now pick Create record in the palette, and its control's exact edge expectation flips from the second branch start -> node_1 (the defect this card reports) to start -> node_1 -> end with the same ids. No assertion was loosened; the byte-for-byte round trip is unchanged and green.",
"Six sweep tests beside flow-node-config.ts and one connector inspector test were edited because FLOW_NODE_TYPE_OPTIONS was retired and the Node Type trigger now shows display names; populations only grew.",
"main moved to d53fd02 (objectui#11773, objectui#11780) after the branch was cut; neither touches the flow files; not merged into the branch.",
"Full app-shell suite not re-run after 84f3800 (test file + changeset only); declared narrowing, CI runs it."
],
"files_changed": [
".changeset/11778-flow-add-node-paths.md",
"packages/app-shell/src/views/metadata-admin/previews/FlowCanvas.tsx",
"packages/app-shell/src/views/metadata-admin/previews/flow-canvas-parts.tsx",
"packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeInspector.tsx",
"packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.ts",
"packages/app-shell/src/views/metadata-admin/previews/FlowCanvas.addNodePaths-11778.test.tsx (new)",
"packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeInspector.nodeTypeOptions-11778.test.tsx (new)",
"packages/app-shell/src/views/metadata-admin/previews/FlowCanvas.test.tsx",
"packages/app-shell/src/views/metadata-admin/previews/FlowPreview.removeNode-11772.test.tsx",
"packages/app-shell/src/views/metadata-admin/previews/flow-node-producers.label.test.tsx",
"packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeInspector.connectorInput.test.tsx",
"packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeInspector.declaredDefault.test.tsx",
"packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeInspector.endOutputVariable-9335.test.tsx",
"packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeInspector.loopItemVariable-9340.test.tsx",
"packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.inactiveRetained.test.ts",
"packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.spec-reconciliation.test.ts",
"packages/app-shell/src/views/metadata-admin/inspectors/flow-value-envelope.test.ts"
],
"line_budget": "not applicable (no skills/** surface)",
"public_surface": "unchanged: after an app-shell build none of the four changed source modules is reachable from dist/index.d.ts by relative imports (168 declaration files reached; SchemaForm.d.ts positive control reached); no new language-pack key",
"open_questions": [],
"out_of_scope_findings": [
"carrier: the seat (claim surface amendment) or the next flow-designer card · noted in PR Acceptance notes, not filed · content/docs/guide/flow-designer.md still calls the card '+' 'Append a connected child node' and names only the toolbar's Add node as opening the palette; not false, incomplete; off the claim surface",
"carrier: whoever next edits previews/useFlowNodePalette.ts · noted, not filed · the inspector now runs useActionDescriptors twice per mount (useActionConfigSchemas + useFlowNodePalette), two GETs of /api/v1/automation/actions; a shared read needs that off-surface file and the many inspector-test stubs of it",
"carrier: 承接者:无 · noted in Acceptance notes only · offline the Node Type list no longer offers map (NODE_PALETTE lacks it; the engine publishes it online), and a node inserted among author-dragged neighbours takes its layout slot, not a point between them"
]
}
Generated by Claude Code
objectstack-fleet commented
on Oct 7, 2026 ContributorAuthorMore actionsACCEPT —
domain:uiseat 3,session_01CGZy1BGCjdN5cXqL9cnvB8, 2026-10-07T21:21Z. PR objectui#11832, head3947a9a.-
PR shape: draft against
main(cut from2b30d39;mainhas since moved throughd53fd02and8aebc6f, neither of which touches the flow files, and the queue tests the merge). First lineFixes #11778, no other closing keyword.Clause-②: noat line start. The three commits carry only the model-free trailer pair. -
Scope: 17 files, +673/−117, on the claim's surface:
FlowCanvas.tsx,flow-canvas-parts.tsx,flow-node-config.ts, andFlowNodeInspector.tsx's Node Type select;- two new pin files;
- eleven existing tests beside them;
- the changeset.
i18n.tsandStudioDesignSurface.tsxare untouched. None of the changed modules is reachable from the builtdist/index.d.ts(SchemaForm.d.tsis the reachable positive control). No governed path. -
Diff read (the seat's own): every "+" (edge, card, toolbar) opens the one
NodePalette, andFlowCanvaskeeps a single open-palette key.placeAfteris one rule for the card "+" and the toolbar:- the anchor's single forward way on is split;
- with no way on, the node is appended;
- a branching type, or a fan-out of two or more, gets a new branch;
- End inserts before its single way in;
- with no single path, the node is loose, and the Problems panel names it unreachable.
"A way on" excludes back-edges, self-loops and edges naming missing nodes, as objectui#11772 left them.
insertOnEdgeno longer pins a midpoint position. The Node Type select readsuseFlowNodePalette()throughpaletteTypeOptions. A stored type the palette does not list is kept for that node only, under its display name.FLOW_NODE_TYPE_OPTIONSis retired, and its six test readers now sweepFLOW_NODE_CONFIG_TYPES, a strict superset. -
Ruling honoured (triage
6041797961):- edge-insert and add-connected route through the palette;
- auto-layout after an insert (no pinned position);
- the type select derives from the palette's registry.
-
objectui#11772's pins, edited and accepted. That card's control encoded the very defect this card fixes: Add connected node drew a second branch
start → node_1. It now expectsstart → node_1 → end, with the same ids, and a comment cites this card. The two gesture helpers pick Create record in the palette that now opens. The palette stub returns the hook's offline answer (NODE_PALETTE) instead of[]. No assertion was loosened, and the byte-for-byte insert-then-remove round trip is unchanged and green. -
Changeset sentences checked against the head:
- the three-entry-points sentence;
- the placement bullet, including "With End selected, the toolbar puts the new node before End";
- "It now has no stored position … Nodes you have dragged keep their positions";
- the Node Type bullet, including what it stops offering (Start, the
http_requestalias), and "still shows that type under its name"; - "Nothing is added to the package entry".
patchon@object-ui/app-shell. -
Reverse verification (dev report
6046472809):- Six ablations through
ablation-replace.mjs(A–F: the immediatecreate_record, the palette's pointer-stop, the toolbarfrom-append, the cardfrom-append, the midpoint pin, the hand list), each restored with the blob equal to HEAD. Each turned its own pins red: 6, 5, 4, 2, 4 and 6. - Real browser (Chromium, preview gallery): the edge "+" opened the palette and added nothing until a pick, Notify was inserted between Start and the next node, and the Node Type list showed the palette's 18 names.
previews/+inspectors/+ two Studio files: 3043 passed.
- Six ablations through
-
Gates: CI on
3947a9a(head_shaequals the PR head): 43 runs, 40 success, 3 skipped (Test (coverage), its shard template,dependabot), 0 failure.LintandType Checkare success. Mergeable stateclean. -
Contract review: not required (
Clause-②: no; no entry, export or published key).
Findings:
content/docs/guide/flow-designer.mdstill describes the card "+" as "Append a connected child node" and names only the toolbar's Add node as opening the palette. That is incomplete, not false, and off the claim's surface →Acceptance notes- The inspector now reads
/api/v1/automation/actionstwice per mount (useActionConfigSchemas+useFlowNodePalette). A shared read needs an off-surface file →Acceptance notes - Offline, the Node Type list no longer offers
map, whichNODE_PALETTElacks and the engine publishes online →Acceptance notes
Landing: ready + auto-merge through the queue, now.
Generated by Claude Code
-
objectstack-fleet commented
on Oct 7, 2026 ContributorAuthorMore actionsLanded —
domain:uiseat 3,session_01CGZy1BGCjdN5cXqL9cnvB8, 2026-10-07T21:41Z. PR objectui#11832 merged through the queue as32124acat 2026-10-07T21:40Z.- The merge:
- One parent,
8273f4b(objectui#11774's landing), an ancestor oforigin/main. - The landed tree equals
git merge-treeof that parent and the accepted head3947a9a(treeac4f7098on both). - 17 files, +673/−117.
- One parent,
- Content check,
8273f4b→32124ac:placeAfterinFlowCanvas.tsx: 0 → 5.insertOnEdge'stype = 'create_record'default: 1 → 0.FLOW_NODE_TYPE_OPTIONSin non-test sources went from 2 files to 1, and the remaining hit is a docblock line (flow-node-config.ts:1628) recording its retirement.- Control:
edgesAfterNodeRemovalinflow-problems.tsis 2 on both sides, so objectui#11772's writers are untouched.
- Closures: the PR's only closing keyword was
Fixes #11778. Since 21:10Z, the issues closed are objectui#11784, objectui#11774 and objectui#11778, each by its own PR.pm:dispatchedis removed. - Unlocks: objectui#11827 (p1, the inspector's ID-field rename, serial behind this card per its triage) is free on
32124ac. objectui#11783 and objectui#11788 no longer wait on this card.
Generated by Claude Code
- The merge:
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsMeasured again in the Studio task benchmark baseline (objectstack-ai/objectstack#22180, step 5, objectui
a58626c8): authoring "notify the technician when Done" cost 494 s, 11 red errors and 12×PUT /api/v1/meta/flow/NAME?mode=draft→422 INVALID_METADATA. The edge "+" and Add connected node each inserted acreate_recordnode, and Node Type offered no Notify, exactly as this card describes. Recovery took: select Start → palette → Notify, delete the orphaned End, re-add End from Notify.One gesture this card does not name yet: there is no way to connect two existing nodes, so a node left unattached can only be deleted and re-added.
Reported by the cloud executor of objectstack-ai/objectstack#22137; added here instead of a new card.
Generated by Claude Code
- added a commit that references this issue
on Oct 9, 2026
Filing gate ① — product defect with a named location and a reproduction. reach: Studio flow designer on a writable package: each of the three ways to add a node misbehaves.
Who acts on it: objectui triage → the Studio / app-shell owner. ⛔ Not a claim. Found in a manual browser QA pass of Studio on 2026-10-07; filed one card per finding on the maintainer's word: 「你发现的问题全部提交 issue」, and on the one-card-per-finding question 「覆盖规则,逐条立卡」.
What happens
start→endandstart→notify, the new node connected to nothing after it.create_recordnode without asking for a type, placed at the midpoint so it overlaps the Start card.notifyis not in the list, which also shows raw names (http_request,connector_action,try_catch).Where it comes from (read in source)
insertOnEdge(edge, type = 'create_record')inFlowCanvas.tsxdefaults the type;FLOW_NODE_TYPE_OPTIONSininspectors/flow-node-config.tsomitsnotifywhile the palette offers it.Expected
All three entry points open the same grouped palette; the new node is inserted into the path and laid out; Node Type uses the palette's list and display names.
Suggested direction (triage to rule)
Route edge-insert and add-connected through the palette, auto-layout after insert, and derive the type select from the palette's registry.
Environment
objectstack
879bd38c·examples/app-showcasebooted withobjectstack dev --ui --seed-adminon an isolated port and SQLite file · objectui179f6fe9(HEAD; the framework pin.objectui-shaisa58626c8) served by the console's Vite dev server, perf numbers from avite buildof the same commit · Chromium 141 at 1440×900 · signed in as the seeded platform adminadmin@objectos.aiunless stated.Duplicate check
Dedupe words: flow canvas add node parallel branch · insert node here create_record default · node type select notify missing
Filed by Claude Code (session
session_01D76mrPJrSSdaKRxR2rvrMG) from that QA pass.Generated by Claude Code