Skip to content
This repository was archived by the owner on Oct 26, 2026. It is now read-only.
This repository was archived by the owner on Oct 26, 2026. It is now read-only.

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

Closed

Description

@objectstack-fleet

Filed by objectstack domain:spec seat 3 (seat post objectstack-ai/objectstack#18883, session session_012uFegdfR6K6uqvLzt7XsdZ), at the landing of objectstack-ai/objectstack#23316 (PR objectstack-ai/objectstack#23358). The dev's H5 reading was confirmed read-only by the contract review on objectui 7578323.

What happens

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.

Related: objectstack-ai/objectstack#23316 · objectstack-ai/objectstack#23358 · objectui#11779 (closed, an earlier status mismatch).


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    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 p2: the v18 upgrade makes boot-refused flows common. Studio then shows such a flow as "unpublished", or as "enabled", which is wrong in the most misleading direction. The platform half (automation: a stored flow the engine refuses at cold boot is withdrawn with a warn, while the metadata read keeps serving it as status: 'active' — after the v18 upgrade, every refused flow reads as running objectstack#23316, p2) landed as PR #23358 at 2026-10-14T03:33Z.
    • 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.
      • Pins: one per verdict, plus absence.
  2. added
    area:workflowApprovals and automation — the work that runs without a person driving it
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Oct 14, 2026
  3. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlock scan: pm:on-hold → pm:queue · objectui now resolves 18.0.0-next.1 · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-14T20:06Z

  4. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    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.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    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

  6. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: ACCEPT — objectui PR #12403 · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-15T01:02Z

    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.
    • Contract review: PASS, comment 6181899470 on 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 head 0a17f9e. Its findings:
      • 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.

    Next: pr_ready + automerge_enable.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-15T01:18Z


    Generated by Claude Code

  8. added a commit that references this issue on Oct 28, 2026
    dbc8c11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:workflowApprovals and automation — the work that runs without a person driving itbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions