Repository navigation
fix(app-shell): Studio shows the flow state the deployment runs, alike in the rail, the header and Problems (objectui#11779) - #11834
Merged
objectstack-fleet[bot] merged 5 commits intoOct 7, 2026
Conversation
…w header and Problems (objectui#11779) - The header's Trigger pill reads the Start node through the spec's resolveFlowTriggerKind (a record trigger shows its event and object), falling back to the flow type only when no trigger resolves. - deriveFlowRunStatus (flow-problems) is the one derivation the rail's FlowStatusDot, the header's Status pill and the Problems panel read; the pillar hands the open flow's _status row to the preview through FlowRuntimeContext. A published flow with no status key no longer reads "draft". - An enabled flow whose declared trigger is not armed on this deployment reads "Not running here" (grey, the platform reason as its title) in the rail and the header, with a note in Problems; a manual flow still reads On. - A new flow is created switched off (status obsolete), as the bar's "Off by default" promises. Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
…Problems (objectui#11779) New pins: a record-triggered flow's header shows its trigger event and object; a published flow with no status key reads On (runtime) or Enabled (no runtime), never draft; an unbound schedule flow reads "Not running here" in the rail and the header with the platform reason, and Problems notes it without counting it; a manual flow still reads On; a new flow is saved status obsolete and its switch reads Disabled. Updated pins: the objectui#11281 cases that held a policy-unbound flow at a green "On" now read "Not running here"; the pillar suites that waited on the raw "active" Status pill wait on its derived "Enabled". Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
…1779) Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
…t feeds (objectui#11779) The context moves from ProblemsPanel.tsx into flow-problems.ts, next to deriveFlowRunStatus: a context exported from a component module is what react-refresh/only-export-components flags, and the pillar now takes the context and the derivation from one component-free module. Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
Brings in objectui#11778 (flow designer add-node paths, flow-node-config), objectui#11784 (package delete confirm, StudioDesignSurface), objectui#11774 and objectui#11809. No textual conflict. Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
1 similar comment
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #11779
Clause-②: no
Implemented by the os-dev agent dispatched by the seat 3
domain:uiPM under claim comment 6046146169, sessionhttps://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8.What an author reads now
autolaunched(the flow-leveltype)Record updated · task(the Start node's event and object)statuskeydraft(grey)On, from the engine's runtime row, as in the railOn, the reason only on hover; header:active; Problems: "No problems"Not running here, the platform's reason as hover text; Problems: a note carrying the reason, not countedOnOn, titled "no trigger (run manually)"EnabledDisabled(saved withstatus: 'obsolete')How
deriveFlowRunStatus(inflow-problems.ts) maps the engine's runtime row to one ofon/manual/not-running/off; with no row it readsunpublished(the host read_statusand the engine has no row for the flow) or, with no runtime reading at all, the draft's own switch (enabled/disabled, read the way the engine readsstatus:obsoleteandinvalidoff, anything else on).describeFlowRunStatusis the one wording of those states. The rail'sFlowStatusDot, the header's Status pill and the Problems panel's note all read these two functions._statusrow to the preview throughFlowRuntimeContext(a row,nullfor no row, nothing while no runtime answer is in). It is a context rather than aMetadataPreviewPropsmember, so the published preview contract does not change. A host with no provider (the metadata-admin page) gets the draft-switch reading, so a flow with nostatuskey no longer reads draft there either.resolveFlowTriggerKind(@objectstack/spec/automation, the authoring-time mirror of the engine's binding resolution, in the engine's precedence). A record kind shows the Start node'striggerTypeevent and itsobjectName; a time-relative sweep shows its object; schedule and API show their kind; when no kind resolves (a manual or screen flow) the pill falls back to the flowtype, as before. The words are the Start node inspector's own option labels (fieldsForNodeType('start')localized bylocalizeFlowFields), so the header and the inspector name one trigger one way, in en and zh.triggerTypeandbound: falsereads it: the contract's "declared trigger type has no registered trigger" (or a deployment policy). A flow that declares no trigger runs when invoked and keepsOn. The chip is grey; nothing is styled as an error.Measured: what
_statusserves on 17.7.0The published
@objectstack/service-automation@17.7.0engine (installed into a scratch directory),getFlowRuntimeStates()— the rowsGET /api/v1/automation/_statuspasses through — withOS_AUTOMATION_SCHEDULED_WORK_ENABLEDunset and therecord_changeandscheduletriggers registered:record-after-updateontask, nostatuskeyenabled: true, bound: true, status: "draft", triggerType: "record_change", object: "task"status: "draft"statuskeyenabled: true, bound: false, status: "draft", triggerType: "schedule", reason: "disabled by deployment policy — package-authored scheduled work is off on this deployment …"enabled: true, bound: false, status: "draft"— notriggerType, noreasonstatus: "obsolete"enabled: false, bound: false, status: "obsolete", triggerType: "record_change", object: "task"— noreasonstatus: "obsolete", no trigger)enabled: false, bound: false, status: "obsolete"type: "api"with no api trigger registeredenabled: true, bound: false, status: "draft", triggerType: "api", reason: "no 'api' trigger is registered — …"Readings:
FlowSchema.statusdefaults todraft, the engine stores the parsed value, and armsdraftexactly likeactive.triggerType: absent on a manual flow, present on every declared trigger. On 17.7.0 every enabled, unbound row with atriggerTypealso carries areason; the title falls back to "Enabled, but its trigger is not armed on this deployment" only for an older backend that sends none.The one fork: the new flow's default — the default follows the bar
A flow created with New is saved with
status: 'obsolete'; the bar's copy stays.doCreateFlowis Studio's only flow producer (save('flow'has one non-test call site); it wrote nostatus; the spec defaults that todraft; the 17.7.0 engine armsdraft(rows above). A package publish publishes every draft in the package, so a half-built record-triggered flow was armed on live records the first time anything in its package was published. The bar names that risk.obsoleteis a lifecycle word for a flow that was never live; it is the spec's only off value (draftandactiveboth arm).Problems: a note, not a problem
The not-running state shows in the Problems panel as a note above the list: the label and the reason, grey, dashed border. It is not a problem row: it is not counted in the Problems badge, not styled as an error or a warning, and the structural verdict ("No problems — this flow is structurally valid") stands beneath it. A deployment policy is an operator's fact, not an authoring defect. Off and manual flows get no note.
Tests and gates (head
26ec168)New pins:
StudioDesignSurface.flowStatusTruth-11779.test.tsx, through the realAutomationsPillarand the real registeredFlowPreview, with a_statusrouter double: the record flow's Trigger readsRecord updated · task; schedule readsSchedule (cron), manual falls back toautolaunched; the no-statuspublished flow readsOnin the rail and the header, never draft (the control); the unbound schedule flow readsNot running herein both, titled with the reason, and notOn; Problems shows the note with the reason, uncounted, beside "No problems"; the manual flow readsOnand gets no note (the control); a flow the engine has no row for readsUnpublished draft; New savesstatus: obsolete,FlowSchema.safeParsesucceeds on the saved body, and the switch readsDisabledunder the "Off by default" bar.FlowPreview.headerPills-11779.test.tsx: the pills with no runtime provider (record event and object, the zh inspector words, time-relative with its object, the type fallback; nostatusanddraftreadEnabled,obsoletereadsDisabled).flow-problems.runStatus-11779.test.ts: the derivation table, including the disabled row, the runtime row outranking the draft, and that no reading is an error tone.Updated pins: the objectui#11281 cases in
FlowStatusDot.test.tsxandStudioDesignSurface.railUnboundReason-11281.test.tsxheld a policy-unbound flow at a greenOn; they now readNot running here(the reason-verbatim and manual-flow controls are kept). The 11124, 11546, 11553 and 11204 pillar suites waited on the rawactiveStatus pill; they now wait on its derivedEnabled. The plain-language pin (objectui#11659) covers the three new rows.Runs, all at
6916515unless stated, from the worktree root:pnpm exec vitest run packages/app-shell/src/views/studio-design/ packages/app-shell/src/views/metadata-admin/previews/ …(plussrc/__tests__/, the consoleStudioRoutesuites and the i18n suites that read the touched modules): Test Files 217 passed (217), Tests 2287 passed.metadata-admin(__tests__/,datasource/,external/,inspectors/, the 165 root test files): Test Files 303 passed (303), Tests 3597 passed, 1 skipped.pnpm --filter @object-ui/app-shell type-check(tsc --noEmit && tsc -p tsconfig.test.json): exit 0.pnpm exec eslinton the 15 touched files: 0 errors; per-file warning counts equal to the base commit (d53fd02).check:control-bytes,check:test-path-roots,check:changeset-claims,check:pending-changeset-literals,check:i18n-keys,check:i18n-drift,check:i18n-dead-keys,check:i18n-designer-parity,check:new-line-citations,check:vi-mock-specifiers,check:vi-mock-inherit,check:vi-mock-override-shape,check:spec-symbols,scripts/check-changeset-presence.mjs: all exit 0 (verdict lines in the report).studio-design/,metadata-admin/andsrc/__tests__/were not run locally (agit grepfor direct imports of the touched modules found none beyond those run). CI'spnpm testruns them.Ablation
The old Trigger pill source put back (
value={translateFlowMeta('type', String(d.type ?? 'autolaunched'), locale)}overvalue={flowTriggerLabel(d, nodes, locale)}) throughablation-replace.mjs. First leg atcd562f5(anchor 1 → 0, blob1404ef239c15→f12c7b8d4439), running the two 11779 pill files: 5 failed, 10 passed — the record (en and zh), time-relative, record-through-the-pillar and schedule pins red; the type-fallback control and every status pin green. Restore proven: blob back to1404ef239c15== HEAD,git diff HEADempty. Second leg at26ec168(blob172f1cbf7090→7bfb27b575ab): the same 5 red / 10 green; restore proven: blob back to172f1cbf7090== HEAD,git diff HEADempty.Acceptance notes
FlowRuntimeContextand the derivation sit inflow-problems.ts(listed, and the component-free module the preview and the panel already share); a dedicated module would be a cleaner home but is outside the claimed surface. Its objectui#11772 note said "React-free module"; withcreateContextimported it now says "component-free". The context first sat inProblemsPanel.tsxand moved becausereact-refresh/only-export-componentsflagged it there.skeletons.tsuntouched.status: 'obsolete'is added indoCreateFlow, not inbuildFlowSkeleton, to stay inside the surface, socreateConformance.test.ts's skeleton gate does not see the key; the new pillar pin parses the bodydoCreateFlowactually saves withFlowSchema. Moving the key into the skeleton is a one-line follow-up for whoever next touches that file. carrier: none named._statusrows through its own projection (packagedFlows.ts); it is not moved onto this derivation here. Noted, not filed.Generated by Claude Code