You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
studio(automations): read the engine's registration verdict on a flow, so a flow the engine refused at boot no longer reads as "unpublished" or "enabled" (objectstack#23316) #12349
The automation engine can refuse a stored flow at boot, which becomes common after the v18 upgrade. The flow is then withdrawn and never runs, and the console gives the wrong reason or none:
StudioDesignSurface.tsx (about :6412) feeds the open flow the GET /automation/_status row. A refused flow has no row (null), so it reads "unpublished" (Unpublished draft, amber): the wrong reason, though at least not "running".
FlowStatusDot (about :5700) renders nothing without a row.
flow-problems.ts (about :375), deriveFlowRunStatus: with no runtime reading, it falls back to the stored status. So a refused active flow renders "enabled".
What the platform now serves
objectstack-ai/objectstack#23358 adds the engine's verdict to the flow metadata read, beside the stored document and never inside it:
The item read (GET /meta/flow/NAME, on both the default cached branch and the uncached branch) carries registration, an envelope sibling of lock. It is one of:
registered;
refused, with reason: { message, code? } verbatim from the engine;
unregistered.
The flow list carries registrations, keyed by name, beside items.
Absence (no automation service, a draft, a non-flow type) means no engine judged the flow, never registered.
The schema is FlowRegistrationSchema in @objectstack/spec (api/protocol.zod.ts). The verdict is the answering process's engine.
Ask
The Studio surfaces that show a flow's run state read registration / registrations:
a refused flow reads as refused, and shows the engine's reason.message as sent;
a registered flow reads as today;
absence falls back to today's behaviour.
⛔ The console does not rewrite or reinterpret the stored status: the author's declared state and the engine's verdict are two facts. ⛔ It does not parse reason.message.
Triage: first grade, bug · priority:p2 · domain:ui · area:workflow, pm:on-hold until a next release carrying objectstack PR #23358 is what objectui resolves
Triage seat (seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-14T03:51Z. ⛔ Not a claim, ⛔ not a dispatch.
Why on hold: the registration / registrations fields and FlowRegistrationSchema exist on objectstack main only. objectui resolves ^18.0.0-next.0 (objectui#12337), and 18.0.0-next.0 predates them. A cross-repo unlock needs a fix the consumer can install.
Restart-when: a published @objectstack/spec@next that includes objectstack PR #23358 is the version objectui resolves.
Lane:domain:ui (Studio: StudioDesignSurface.tsx, FlowStatusDot, flow-problems.ts). Clause-②: no: it reads a published field.
Direction: the card's ask, as written.
A refused flow reads as refused and shows reason.message as sent. A registered flow reads as today. Absence falls back to today's behaviour.
⛔ The stored status is not rewritten, and ⛔ reason.message is not parsed.
Claim: PM loop round 1
Session: session_01XVp19E1MYUTFM3dnkwz8gB
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-12349-flow-registration-verdict
Worktree: objectui-issue-12349
Domain: domain:ui
Seat: domain:ui#2
File surface: packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (the flow rail state, FlowStatusDot, the open-flow status), packages/app-shell/src/views/metadata-admin/previews/flow-problems.ts (deriveFlowRunStatus), previews/FlowPreview.tsx, the flow item / list read that carries registration / registrations, packages/app-shell/src/views/metadata-admin/i18n.ts (or the Studio string table these surfaces already use), their tests, and a .changeset/ entry (stop on breach; explain in the report)
Container & model: M, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui reads no path-derived mandate)
Clause-②: yes (widening; revised in place at 2026-10-15T00:49Z on the dev's measurement at PR #12403: @object-ui/data-objectstack gains MetadataClient.listResponse and the exported type MetadataListAnswer; was no). A contract-review-tier review is owed before the queue.
Responsibility: objectui's Studio, which reads only the automation _status row and the stored status | the platform now publishes the engine's verdict (objectstack PR #23358, in 18.0.0-next.1) and objectui does not read it | every Studio author whose flow the engine refused at boot, common after the v18 upgrade
Thread-read: 6177296388
Serial constraints cleared: objectui#12326 (PR #12391, which also touched metadata-admin/i18n.ts) landed as 28fb2a0; this card was held behind it for that shared file. objectui#12329 (PR #12389, flow inspectors, simulator and i18n.ts) landed as 52a5d81. In flight: objectui#12375 and objectui#11970, both in plugin-grid / components, disjoint.
{
"issue": 12349,
"status": "done",
"branch": "claude/issue-12349-flow-registration-verdict",
"pr": "https://github.com/objectstack-ai/objectui/pull/12403",
"session": "session_01XVp19E1MYUTFM3dnkwz8gB (subagent; the parent's id)",
"premise_still_valid": true,
"summary": "A1 confirmed on 28fb2a001: a refused flow had no _status row, so the header read Unpublished draft and the rail dot rendered nothing. A2 disproved: no Studio read carried the verdict (MetadataClient.list returned items only; the open flow is read through the draft read and /layers). Smallest place: MetadataClient.listResponse in @object-ui/data-objectstack, the same flow list read returning items plus registrations parsed per entry with the spec's FlowRegistrationSchema, sharing one in-flight request with list. deriveFlowRunStatus takes the verdict as a third argument (refused and unregistered decide; registered and absence read as today); FlowStatusDot and FlowPreview (via a new FlowRegistrationContext) read it. Refused reads 'Refused by the engine' titled with reason.message as sent; unregistered reuses 'Not running here' with a new title row; stored status is never rewritten and the message is never parsed. A3: FlowPreview covered. A4: PackagedAutomationPage/packagedFlows.ts builds rows from _status, so a refused packaged flow is not listed at all (documented by design in that file); noted, not filed. File-surface note: the edit to packages/data-objectstack/src/metadata-client.ts and index.ts is the 'flow item/list read' the claim names; it widens a published export, so Clause-② measured as 'yes (widening)', written as the PR body's second line and in the changeset.",
"tests": "At 23145e359. Targeted under the lock: 9 files / 83 tests passed (the four new 12349 test files, flow-problems.runStatus-11779, FlowStatusDot.test, StudioDesignSurface.flowStatusTruth-11779, metadata-client.test, metadata-client.inflightShare-11797). Full packages/data-objectstack/: 90 files / 1146 tests passed. Reverse check, fix committed first: removing the two verdict lines from deriveFlowRunStatus (grep count 2 to 0 on disk) gave 9 failed / 3 passed across the 12349 derivation and pillar pins (the registered and absence pins stay green, as they should); restored from HEAD (count 2, git diff HEAD empty). Closure build turbo build --filter='@object-ui/app-shell^...' 28/28; type-check for app-shell (tsc --noEmit plus tsconfig.test.json) and data-objectstack exit 0. eslint --no-inline-config on the 10 changed files (json count: 10 files): 5 errors and 150 warnings, the same 5 errors and 150 warnings as the 6 changed source files at 28fb2a001; type-aware linting is not enabled in eslint.config.js, so the diff cannot change the verdict on untouched files. Gates exit 0: phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols (first run exit 1: my MetadataListResponse name collided with a spec export; renamed to MetadataListAnswer, derived from GetMetaItemsResponse), action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, control-bytes, new-line-citations, check-changeset-fixed, check-changeset-presence. check:spec-floors exit 1, the same as on main (objectui#12334). NOT MEASURED: the full app-shell project, and the other 45 app-shell tests that render AutomationsPillar or FlowPreview. Reason: an attempt on studio-design plus previews hit the 570s cap (exit 124), and then three lock attempts timed out in the queue (exit 99) behind holder pid 29039, 'pnpm exec vitest run --maxWorkers=2 packages/app-shell/', which had held the lock for 2198s. Declared to CI.",
"mcp_calls": "0",
"api_writes": "3 — git push of the branch (3 pushes, git, not REST); fleet-write relay pr_create (POST /repos/objectstack-ai/objectui/pulls + POST /issues/12403/assignees, read-back identical 5424 bytes); fleet-write relay comment (this os-dev-report, POST /repos/objectstack-ai/objectui/issues/12349/comments). Labels: zero writes (objectui, none named).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed — Setup's Packaged automations page (packagedFlows.ts joinPackagedFlows) uses _status as the spine, so a refused packaged flow has no row there. Its own docblock says this is deliberate. Read-only observation, never exercised in a running app. Dedupe words: packaged automations refused flow, joinPackagedFlows registrations, packagedFlows _status spine",
"carrier: none · noted, not filed — ProblemsPanel shows a run note only for not-running, so a refused flow's reason appears in the header pill and the rail but not in the Problems panel. Dedupe words: ProblemsPanel run note refused, flow-run-status-note registration"
]
}
Reviewed on GitHub at head 0a17f9e, against the card's ask, triage's direction (6160490285) and the claim (6180675332, revised in place to Clause-②: yes (widening)), not against the dev's report.
Shape: the PR is a draft against main. Its body opens Fixes #12349, the only closing keyword, followed by Clause-②: yes (widening). The governed sweep reads NOT governed, 701 lines, 11 files. packages/data-objectstack/src/metadata-client.ts and index.ts are the flow list read the claim names.
MetadataListAnswer is derived from the spec's GetMetaItemsResponse, not restated, and each verdict is parsed with FlowRegistrationSchema.safeParse;
list is unchanged and shares one GET with listResponse;
absence and registered both fall through to today's reading;
reason.message is shown verbatim, and the stored status is never written.
One patch round: the seat raised @object-ui/data-objectstack from patch to minor before the review (a new method and a new exported type are additive, and objectui has no major). @object-ui/app-shell stays patch; its index exports are unchanged.
The ask, met:
a refused flow reads "Refused by the engine", titled with the engine's message as sent, in the rail dot, the open flow's Status pill and FlowPreview;
unregistered reads "Not running here";
a registered flow, and a flow with no verdict, read as before.
Pins cover each verdict plus absence. Removing the verdict lines from deriveFlowRunStatus turns 9 of them red, while the registered and absence pins stay green.
Evidence: the closure build and both type-checks exit 0. The 9 targeted files (83 tests) and the full data-objectstack project (1146 tests) are green; the battery exits 0. The full app-shell project was NOT MEASURED locally (the lock was held by another card's run), as declared; CI's shards cover it, read below.
Acceptance notes (not filed):
Setup's Packaged automations page builds its rows from _status, so a refused packaged flow has no row there. That file's docblock says this is by design, and it is outside this card's Studio scope.
The Problems panel adds a run note only for not-running. A refused flow is worded in the header and the rail, so nothing reads wrong on this head.
CI at head: 30 success, 3 skipped, 0 failures (filter=latest), Type Check, Spec Main Shape Gate and all 12 test shards included.
Label:needs:contract-review is removed from the PR in this stroke.
Activity
objectstack-fleet commentedon Oct 14, 2026
Triage: first grade,
bug·priority:p2·domain:ui·area:workflow,pm:on-holduntil anextrelease carrying objectstack PR #23358 is what objectui resolvesTriage seat (seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T03:51Z. ⛔ Not a claim, ⛔ not a dispatch.status: 'active'— after the v18 upgrade, every refused flow reads as running objectstack#23316, p2) landed as PR #23358 at 2026-10-14T03:33Z.registration/registrationsfields andFlowRegistrationSchemaexist on objectstackmainonly. objectui resolves^18.0.0-next.0(objectui#12337), and18.0.0-next.0predates them. A cross-repo unlock needs a fix the consumer can install.@objectstack/spec@nextthat includes objectstack PR #23358 is the version objectui resolves.domain:ui(Studio:StudioDesignSurface.tsx,FlowStatusDot,flow-problems.ts).Clause-②: no: it reads a published field.reason.messageas sent. A registered flow reads as today. Absence falls back to today's behaviour.statusis not rewritten, and ⛔reason.messageis not parsed.objectstack-fleet commentedon Oct 14, 2026
Unlock scan:
pm:on-hold→pm:queue· objectui now resolves18.0.0-next.1· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T20:06Zmainnow pins@objectstack/spec^18.0.0-next.1, and its lockfile resolves18.0.0-next.1.d89f491ad0,FlowRegistrationSchema) is an ancestor of the18.0.0-next.1tag commit0c52e43075. The restart condition in6160490285is met.objectstack-fleet commentedon Oct 14, 2026
Claim: PM loop round 1
Session:
session_01XVp19E1MYUTFM3dnkwz8gBAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-12349-flow-registration-verdictWorktree:
objectui-issue-12349Domain:
domain:uiSeat:
domain:ui#2File surface:
packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx(the flow rail state,FlowStatusDot, the open-flow status),packages/app-shell/src/views/metadata-admin/previews/flow-problems.ts(deriveFlowRunStatus),previews/FlowPreview.tsx, the flow item / list read that carriesregistration/registrations,packages/app-shell/src/views/metadata-admin/i18n.ts(or the Studio string table these surfaces already use), their tests, and a.changeset/entry (stop on breach; explain in the report)Container & model:
M,mode:subagent,model: opus(default tier;dispatch-gates --tier --repo objectstack-ai/objectuireads no path-derived mandate)Clause-②: yes (widening; revised in place at 2026-10-15T00:49Z on the dev's measurement at PR #12403:
@object-ui/data-objectstackgainsMetadataClient.listResponseand the exported typeMetadataListAnswer; wasno). A contract-review-tier review is owed before the queue.Responsibility:
objectui's Studio, which reads only the automation _status row and the stored status | the platform now publishes the engine's verdict (objectstack PR #23358, in 18.0.0-next.1) and objectui does not read it | every Studio author whose flow the engine refused at boot, common after the v18 upgradeThread-read: 6177296388
Serial constraints cleared: objectui#12326 (PR #12391, which also touched
metadata-admin/i18n.ts) landed as28fb2a0; this card was held behind it for that shared file. objectui#12329 (PR #12389, flow inspectors, simulator andi18n.ts) landed as52a5d81. In flight: objectui#12375 and objectui#11970, both inplugin-grid/components, disjoint.Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
os-dev-report
{ "issue": 12349, "status": "done", "branch": "claude/issue-12349-flow-registration-verdict", "pr": "https://github.com/objectstack-ai/objectui/pull/12403", "session": "session_01XVp19E1MYUTFM3dnkwz8gB (subagent; the parent's id)", "premise_still_valid": true, "summary": "A1 confirmed on 28fb2a001: a refused flow had no _status row, so the header read Unpublished draft and the rail dot rendered nothing. A2 disproved: no Studio read carried the verdict (MetadataClient.list returned items only; the open flow is read through the draft read and /layers). Smallest place: MetadataClient.listResponse in @object-ui/data-objectstack, the same flow list read returning items plus registrations parsed per entry with the spec's FlowRegistrationSchema, sharing one in-flight request with list. deriveFlowRunStatus takes the verdict as a third argument (refused and unregistered decide; registered and absence read as today); FlowStatusDot and FlowPreview (via a new FlowRegistrationContext) read it. Refused reads 'Refused by the engine' titled with reason.message as sent; unregistered reuses 'Not running here' with a new title row; stored status is never rewritten and the message is never parsed. A3: FlowPreview covered. A4: PackagedAutomationPage/packagedFlows.ts builds rows from _status, so a refused packaged flow is not listed at all (documented by design in that file); noted, not filed. File-surface note: the edit to packages/data-objectstack/src/metadata-client.ts and index.ts is the 'flow item/list read' the claim names; it widens a published export, so Clause-② measured as 'yes (widening)', written as the PR body's second line and in the changeset.", "tests": "At 23145e359. Targeted under the lock: 9 files / 83 tests passed (the four new 12349 test files, flow-problems.runStatus-11779, FlowStatusDot.test, StudioDesignSurface.flowStatusTruth-11779, metadata-client.test, metadata-client.inflightShare-11797). Full packages/data-objectstack/: 90 files / 1146 tests passed. Reverse check, fix committed first: removing the two verdict lines from deriveFlowRunStatus (grep count 2 to 0 on disk) gave 9 failed / 3 passed across the 12349 derivation and pillar pins (the registered and absence pins stay green, as they should); restored from HEAD (count 2, git diff HEAD empty). Closure build turbo build --filter='@object-ui/app-shell^...' 28/28; type-check for app-shell (tsc --noEmit plus tsconfig.test.json) and data-objectstack exit 0. eslint --no-inline-config on the 10 changed files (json count: 10 files): 5 errors and 150 warnings, the same 5 errors and 150 warnings as the 6 changed source files at 28fb2a001; type-aware linting is not enabled in eslint.config.js, so the diff cannot change the verdict on untouched files. Gates exit 0: phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols (first run exit 1: my MetadataListResponse name collided with a spec export; renamed to MetadataListAnswer, derived from GetMetaItemsResponse), action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, control-bytes, new-line-citations, check-changeset-fixed, check-changeset-presence. check:spec-floors exit 1, the same as on main (objectui#12334). NOT MEASURED: the full app-shell project, and the other 45 app-shell tests that render AutomationsPillar or FlowPreview. Reason: an attempt on studio-design plus previews hit the 570s cap (exit 124), and then three lock attempts timed out in the queue (exit 99) behind holder pid 29039, 'pnpm exec vitest run --maxWorkers=2 packages/app-shell/', which had held the lock for 2198s. Declared to CI.", "mcp_calls": "0", "api_writes": "3 — git push of the branch (3 pushes, git, not REST); fleet-write relay pr_create (POST /repos/objectstack-ai/objectui/pulls + POST /issues/12403/assignees, read-back identical 5424 bytes); fleet-write relay comment (this os-dev-report, POST /repos/objectstack-ai/objectui/issues/12349/comments). Labels: zero writes (objectui, none named).", "open_questions": [], "out_of_scope_findings": [ "carrier: none · noted, not filed — Setup's Packaged automations page (packagedFlows.ts joinPackagedFlows) uses _status as the spine, so a refused packaged flow has no row there. Its own docblock says this is deliberate. Read-only observation, never exercised in a running app. Dedupe words: packaged automations refused flow, joinPackagedFlows registrations, packagedFlows _status spine", "carrier: none · noted, not filed — ProblemsPanel shows a run note only for not-running, so a refused flow's reason appears in the header pill and the rail but not in the Problems panel. Dedupe words: ProblemsPanel run note refused, flow-run-status-note registration" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
Review: ACCEPT — objectui PR #12403 ·
domain:uiseat 2 ·session_01XVp19E1MYUTFM3dnkwz8gB· 2026-10-15T01:02ZReviewed on GitHub at head
0a17f9e, against the card's ask, triage's direction (6160490285) and the claim (6180675332, revised in place toClause-②: yes (widening)), not against the dev's report.main. Its body opensFixes #12349, the only closing keyword, followed byClause-②: yes (widening). The governed sweep reads NOT governed, 701 lines, 11 files.packages/data-objectstack/src/metadata-client.tsandindex.tsare the flow list read the claim names.6181899470on PR fix(studio): read the engine registration verdict on a flow, so a refused flow no longer reads as unpublished or enabled #12403, on this head0a17f9e. Its findings:MetadataListAnsweris derived from the spec'sGetMetaItemsResponse, not restated, and each verdict is parsed withFlowRegistrationSchema.safeParse;listis unchanged and shares one GET withlistResponse;registeredboth fall through to today's reading;reason.messageis shown verbatim, and the storedstatusis never written.@object-ui/data-objectstackfrompatchtominorbefore the review (a new method and a new exported type are additive, and objectui has nomajor).@object-ui/app-shellstayspatch; its index exports are unchanged.FlowPreview;unregisteredreads "Not running here";deriveFlowRunStatusturns 9 of them red, while the registered and absence pins stay green.data-objectstackproject (1146 tests) are green; the battery exits 0. The full app-shell project was NOT MEASURED locally (the lock was held by another card's run), as declared; CI's shards cover it, read below._status, so a refused packaged flow has no row there. That file's docblock says this is by design, and it is outside this card's Studio scope.filter=latest),Type Check,Spec Main Shape Gateand all 12 test shards included.needs:contract-reviewis removed from the PR in this stroke.Next:
pr_ready+automerge_enable.Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
Landed ·
domain:uiseat 2 ·session_01XVp19E1MYUTFM3dnkwz8gB· 2026-10-15T01:18Zmaindbc8c11. The card closedcompletedby the PR'sFixes #12349, which is the only closing keyword. No other card closed with it.origin/main, 10 of the 11 files the PR touches are blob-identical to the accepted, contract-reviewed head0a17f9e(PASS6181899470). The 11th,packages/data-objectstack/src/metadata-client.ts, differs from that head by exactly the 17 changed lines of PR fix(data-objectstack,app-shell,plugin-designer): a console reset or discard names the package whose row it removes (objectui#12335) #12396 (d12bc5f, metadata-client:reset()cannot name a package — after objectstack#23165 a console reset or discard of an item two packages hold answers 409, and the remedy?package=is one the console cannot send #12335'sreset()?package=, merged first by another seat), and by nothing else. So this PR'slistResponsehunks landed intact.pm:dispatchedis removed in the same stroke as this comment.Generated by Claude Code