Skip to content

feat(studio): R09 trigger host respects meta.enabled - #1114

Merged
LinuxDevil merged 4 commits into
mainfrom
fb-r09-enabled-gate
Nov 14, 2026
Merged

LinuxDevil merged 4 commits into
mainfrom
fb-r09-enabled-gate

Conversation

@LinuxDevil

Copy link
Copy Markdown
Owner

Summary

  • TriggerHost caches meta.enabled per agent, refreshed inside reload() (every agent.changed, incl. reason: 'meta'); dispatch() rejects with reason: 'disabled' first, and an enabled→disabled transition drops + logs queued runs (Dropped <n> queued runs: the agent was turned off) while the in-flight run finishes
  • Webhook: 409 { error: 'Agent is turned off', code: 'LOUSHO_AGENT_DISABLED' } immediately after signature auth — no abort listeners, filter or dispatch for a turned-off agent; the dispatch-level disabled reason maps to the same 409
  • Channel: 200 { ok: true, skipped: 'disabled' } before the SDK handler so platforms don't retry; cron's existing disabled branch logs Cron trigger <id> skipped: the agent is turned off with the cursor already advanced; chain dispatches inherit the same reason through the host
  • Manual runs (/run, /message, test pane) are not gated
  • UI: Overview Triggers card .triggers-off-note (warning-soft/--warning-border, shares .agent-detail-notice box styles) with the auto_failure_streak copy variant; non-chat trigger nodes get node-trigger-off (opacity .6) + title="Off — triggers won't fire"; chat triggers never dim

Test plan

  • triggerHost.test.ts +3: disabled dispatch/isEnabled, drop-on-disable with running run finishing, no re-drop/re-log
  • hooksRoute.test.ts +2: 409 path, auth-before-gate order (unsigned remote still 403)
  • cronTriggers.test.ts +1: skip log + cursor advance; channelTriggers.test.ts +1: 200 skipped disabled
  • AgentOverviewTab.test.tsx +3: off note both copies, hidden when enabled/chat-only
  • server+client typecheck clean; eslint clean; fallow dupes/health clean on touched files

Stacked on #1113 (needs the R08b channel path + R03b webhook abort-listener ordering).

Generated with Devin

LinuxDevil and others added 3 commits November 13, 2026 02:38
Channel triggers (telegram, slack, github, teams, discord, http) now
mount per agent through the SDK's own channel factories, so signature
verification, sessions, replies and approval buttons behave exactly as
under `lousho dev`.

- server/triggers/channelTriggers.ts: CHANNEL_SECRET_KEYS aligned with
  the spec schema's required sets, channelFromTrigger secret resolution
  (github botName falls back to the spec name), one mountChannels call
  per agent, duplicate-kind and missing-secret errors surfaced via
  status(), remount on every TriggerHost reload via a new onReload hook
- The channel middleware buffers the raw body itself and replays the
  exact bytes into the SDK handler, so platform signatures verify;
  registered before the /hooks express.raw mount, ahead of the JSON
  parser, with workspaceOf resolved earlier for the same reason
- Abort listeners run before SDK handling on { channel, headers, body }
  (abortListeners.ts - the R03b core the webhook route will reuse);
  a non-true filter answers 200 { ok, skipped: 'filter' } without
  touching the SDK
- Channel turns build the working-copy agent through buildRunnableAgent
  with trace-file + observe exporters; they land in Runs/Traces, never
  the test-pane queue
- GET /agents/:id/triggers/status + runtimeClient.channelTriggerStatus;
  the Overview Triggers card shows each channel's webhook URL, Copy,
  mount errors, and the Runs/Traces note

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The webhook route now runs applyAbortListeners after signature
verification and before the filter/dispatch (the channel path already
did): a `when: true` listener cancels matching queued/running runs of
the watched trigger with reason abort_listener:<id>, and the 202
response lists the cancelled runKeys. Stopped runs end 'stopped', so
the L12 failure streak never counts them. Unit coverage for scopes,
strict-true when, expression-error skip and trigger matching, plus two
route tests (cancel on matching PR, no cancel on a different one).

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
TriggerHost caches meta.enabled per agent (refreshed on every reload,
which agent.changed 'meta' already triggers), rejects dispatch with
'disabled' for turned-off agents, and drops + logs queued runs on the
enabled->disabled transition while a running run finishes. Webhook
answers 409 LOUSHO_AGENT_DISABLED right after auth (no event processing
beyond it); channels answer 200 { ok, skipped: 'disabled' } before the
SDK handler; cron's existing disabled branch logs the contract skip
line and the cursor still advances; chain dispatches inherit the same
reason. Manual runs are untouched. UI: the Overview Triggers card shows
the off note (auto_failure_streak gets the streak copy) and non-chat
trigger nodes dim with node-trigger-off + the contract tooltip.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@LinuxDevil
LinuxDevil force-pushed the fb-r03b-abort-listeners branch from 317b2fc to ef4d3ca Compare November 12, 2026 23:38
@LinuxDevil
LinuxDevil force-pushed the fb-r03b-abort-listeners branch from ef4d3ca to f7610a2 Compare November 14, 2026 10:44
@LinuxDevil
LinuxDevil changed the base branch from fb-r03b-abort-listeners to main November 14, 2026 12:50
# Conflicts:
#	apps/agent-forge/server/__tests__/channelTriggers.test.ts
#	apps/agent-forge/server/__tests__/hooksRoute.test.ts
#	apps/agent-forge/server/__tests__/workspaceSeam.test.ts
#	apps/agent-forge/server/app.ts
#	apps/agent-forge/server/triggers/channelTriggers.ts
#	apps/agent-forge/server/workspace/__tests__/middleware.test.ts
#	apps/agent-forge/server/workspace/context.ts
#	apps/agent-forge/shared/wireTypes.ts
#	apps/agent-forge/src/canvas/NodeCard.tsx
#	apps/agent-forge/src/components/CanvasArea.tsx
#	apps/agent-forge/src/screens/agentDetail/AgentOverviewTab.tsx
#	apps/agent-forge/src/screens/agentDetail/__tests__/AgentOverviewTab.test.tsx
#	apps/agent-forge/src/screens/agentDetail/agentOverview.css
@LinuxDevil
LinuxDevil merged commit b35f362 into main Nov 14, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant