The gap
collectAutomationSummary (packages/cli/src/commands/serve.ts ~5045) builds the os dev / os start startup banner by reading the automation engine's own state — including getFlowRuntimeStates() and getTriggerBindingAudit() — precisely because "a flow that failed to arm emits no log line to find" (2026-07-17 third-party eval, quoted in that function's own docblock).
PR #12026 (for #11997) makes getFlowRuntimeStates() rows carry armedFrom / shadowed for any bare flow name claimed by more than one definition, and adds getShadowedFlows() beside getTriggerBindingAudit(). The banner reads neither: its local states annotation lists the pre-existing fields only, and it prints nothing for shadowing.
So a packaged flow displaced by a same-named runtime overlay is reported in the automation plugin's logs but not in the startup summary — which is the channel that docblock says is the reliable one, since "the boot-quiet stdout window swallows plain warn/info logs".
Suggested shape
Mirror the existing unbound probe exactly — feature-detected so an older @objectstack/service-automation degrades rather than crashing the banner:
letshadowed=[];try{shadowed=automation.getShadowedFlows?.()??[];}catch{/* older engine */}and add a banner line naming each contested flow, which definition is armed, and how many were shadowed.
Dependency
Blocked-by: #11997 — the fields and getShadowedFlows() do not exist until PR #12026 lands. Filing separately because it is in a different package (@objectstack/cli) and was out of that card's scope.
Unassigned, not claimed.
Generated by Claude Code
The gap
collectAutomationSummary(packages/cli/src/commands/serve.ts~5045) builds theos dev/os startstartup banner by reading the automation engine's own state — includinggetFlowRuntimeStates()andgetTriggerBindingAudit()— precisely because "a flow that failed to arm emits no log line to find" (2026-07-17 third-party eval, quoted in that function's own docblock).PR #12026 (for #11997) makes
getFlowRuntimeStates()rows carryarmedFrom/shadowedfor any bare flow name claimed by more than one definition, and addsgetShadowedFlows()besidegetTriggerBindingAudit(). The banner reads neither: its localstatesannotation lists the pre-existing fields only, and it prints nothing for shadowing.So a packaged flow displaced by a same-named runtime overlay is reported in the automation plugin's logs but not in the startup summary — which is the channel that docblock says is the reliable one, since "the boot-quiet stdout window swallows plain warn/info logs".
Suggested shape
Mirror the existing
unboundprobe exactly — feature-detected so an older@objectstack/service-automationdegrades rather than crashing the banner:and add a banner line naming each contested flow, which definition is armed, and how many were shadowed.
Dependency
Blocked-by: #11997 — the fields and
getShadowedFlows()do not exist until PR #12026 lands. Filing separately because it is in a different package (@objectstack/cli) and was out of that card's scope.Unassigned, not claimed.
Generated by Claude Code