Omniscio documentation
Browse all documentation
  1. Getting Started17
  2. Sessions & Agents132
  3. Inbox & Notifications67
  4. Projects & Tasks96
  5. Automation & Scheduling78
  6. Knowledge & Memory27
  7. AI Features71
  8. Integrations106
  9. Plugins & Marketplace34
  10. Cloud & Teams59
  11. Settings & Customization65
  12. Account & Billing28
  13. Troubleshooting79
  14. CLI & API Reference26
  15. Legal & Policies5
  16. Uncategorised17

Dev Pipeline panel — for agents (part 3)

Part 3 of the Dev Pipeline panel page: the developer-facing reference — the virtual project and its integration, the two separate gating settings, the mobile and Web Access rules with the desktop-only list, and how the panel layout and its rails are put together.

What it is

This is part 3 of the Dev Pipeline panel page, following part 2. It is the developer-facing reference for the panel: how it is registered and gated, what it can do on a phone or over Web Access, and how it is put together.

Where to find it

Nowhere in the app. Everything here is a file in the repository, an IPC channel, or a setting for whoever is working on the panel.

How it behaves

Nothing on this page changes what you see on the screen — it is reference for the code behind the panel. The project registration, the two gating settings, the mobile rules and the layout all follow.

For agents

  • Virtual project __dev_pipeline_panel__, integration id dev-pipeline-panel (manifest: src/shared/integrations/dev-pipeline-panel.ts). Distinct from the dev-pipeline skill-bundle integration (which installs the CLI skill).
  • Gating — the reveal and the Dev Pipeline switch are DIFFERENT settings. The panel's visibility comes from the dev-pipeline-panel entry in src/shared/unreleased-features.ts; its status: 'shipped' makes computeVisibility() return true BEFORE it ever looks at a setting, so its settingKey (devPipelinePanelEnabled) does not gate the panel — a shipped entry is filtered out of listInDevelopmentFeatures(), so it generates no Lab row, no reveal toggle and no derived settings-search entry, and AMC_SHOW_DEV_PIPELINE_PANEL is inert. The sidebar row is gated by UNRELEASED_PROJECT_GATES in project-visibility.ts. filterVisibleProjects ALSO reveals it when settings.devPipelineSkillEnabled (the dev-pipeline skill-bundle's featureFlag) is on — a cross-feature coupling so enabling the skill surfaces its dashboard. devPipelinePanelEnabled is the Dev Pipeline's own opt-in, and it defaults to false (session-behavior-settings.ts). It is read directly — never through the registry gate — by four behaviours: whether the auto-lander is armed at all (auto-lander-repos.ts, and resolveAutoLanderRepos returns [] while it is off), the worktree-mutation lockdown (dev-pipeline-repos.ts), daily maintenance (daily-maintenance-supervisor.ts) and git-store maintenance (git-store-maintenance.ts). Two writers touch it: the Setup tab's own on/off switch (SetupView.tsx both reads the setting and writes it back through the settings patch route) and the developer-machine profile (developer-setup-settings.ts, applied by npm run setup). A fresh install has it off and none of the four run. Gate any NEW dev-pipeline-panel surface through isUnreleasedFeatureVisible as usual — never the raw setting — but do not add gating on the assumption the panel is hidden. It isn't.
  • Mobile / Web Access: the manifest declares mobile: { status: 'ready' }, so the panel shows + mounts on mobile via the same filterSidebarOnlyVirtualProjects gate + panelOwnsLayout routing the desktop uses (its IPC channels proxy over Web Access). The desktop-only set (declared mobile: { status: 'desktop-only' }) is exactly THIRTEEN ids — browser, native-browser, running-apps, screen-recordings, screenshots (the five with a real <webview> / desktopCapturer / keyboard constraint), plus journal, gauntlet-loop, phone-control, hooks, teach-recorder, contextdock-native, composio and memory, which are desktop-only for PRODUCT reasons rather than a platform one — contextdock-native and memory share their cause (both read the CONTEXTDOCK_STORE_* channels, which the mobile/web WS bridge blocks), while composio opens a DESKTOP browser sign-in and wires the resulting tools into locally-spawned Claude sessions. Do NOT reason from an older four-, five- or twelve-member list; the authoritative inventory is the ui-registry.test.ts guard, whose test name reads "exactly the THIRTEEN known desktop-only integrations declare mobile: desktop-only", mirrored in dev-pipeline-panel-contract.md available-on-mobile-and-web-access. (shared-sessions moved OFF this list on 2026-09-10 — mobile reached full parity and its WS channels came off the denylist — so do not re-add it.)
  • Layout (renderer): DevPipelinePanel renders a category rail (CategoryRail) of THREE destinations — Runs (live), Stages (timing) and Setup — plus a content pane showing the active one. The DevPipelineCategory union keeps all six values (from DEV_PIPELINE_CATEGORIES in src/shared/dev-pipeline-panel.ts) because a persisted tab and every ?view= deep link are built on it, and a legacy board/autolander NORMALIZES into runsSubView while qafleet normalizes into stagesSubView, so an old deep link still lands. Agent Board, the Auto-lander (AutoLanderView) and QA Fleet (QaFleetView) are each a quiet line inside Runs or Stages that opens the full view (the first two ride RunsView's quiet lines, QA Fleet rides StagesView's); CategoryRail gates only board behind its optional showBoard prop. Agent Board (shown only when agentStatusBoardEnabled, via CategoryRail's optional showBoard prop) renders the shared AgentBoardList — the same board body the global Agent Board view uses — and jumps to a session via navigateToSessionInProject; the panel resets category to Live if the feature is turned off while the tab is open (see agent-status-board.md + dev-pipeline-panel-contract.md L1). Live is LiveView, which unions the flat runs list with the already-per-project worktrees via the pure buildProjectGroups (pipeline-live-grouping.ts) into one collapsible group per project, reusing RunRow + RepoGroup (worktree-rows.tsx) verbatim and one useWorktreeRemoval hook + dialog. Gate/phase labels are humanized + overflow-hardened in pipeline-labels.ts (gateLabel recovers the canonical GATE_n from a noisy value and caps an unknown one; the Waiting pill is width-capped + truncates). Timing is TimingView — a five-tile summary grid (Working · Waiting on you · Stuck · Avg wait · Spend) + a biggest-stall line, over a list of expandable RecentRunRows, each a proportional green/amber/red/idle SplitBar that opens to a per-phase working-time-and-spend + per-gate wait RunBreakdown. See dev-pipeline-panel-contract.md L1–L3.
  • Active runs are derived on demand by derivePipelineRuns() (src/main/services/dev-pipeline/dev-pipeline-panel-service.ts), which reads each non-terminal session's worktree .claude/pipeline/state.md with the same parser the Agent Status Board uses — so it does NOT depend on the (default-off) Agent Status Board feature. It also carries each run's statusChangedAt / needsYouAt so the row can render the live waiting <time> counter. IPC: PIPELINE_RUNS_GET.
  • Run timing (the Timing tab) is captured by Omniscio itself, NOT by the skill: registerPipelineRunTimeline (src/main/services/dev-pipeline/pipeline-run-timeline-service.ts) subscribes once (at handler registration → always-on) to the internal sessionEvents 'statusChanged' bus that SessionStatusManager.updateStatus fires on every committed transition (process-manager.ts notifyStatusChanged), and appends a pipeline_run_events row ONLY for dev-pipeline runs (same phase/gate test as derivePipelineRuns) — so the table is naturally scoped and capture works whether or not the panel is open (deliberately NOT the default-off status-board tick, NOT the ~165-call-site DB chokepoint). Capture is best-effort (guarded, can't perturb the status path) + idempotent (an in-memory last-tuple cache, restart-seeded from the DB via getLatestPipelineRunTuple). The pure reducer derivePipelineRunTimeline (src/shared/pipeline-run-timeline.ts, caller passes nowIso) splits each run into working / gate-wait / stuck (deterministic) + per-phase (best-effort), and summarizePipelineRuns builds the strip. History is a SEPARATE read derivePipelineRunHistory (.../pipeline-run-history-service.ts, IPC PIPELINE_RUN_HISTORY_GET) over the durable events joined to sessions (incl. finished runs), with an inline 90-day prune on write. No AI calls → zero cost. See dev-pipeline-panel-contract.md RT1–RT5.
  • Worktrees are derived on demand by deriveRepoWorktrees() (src/main/services/worktree/dev-pipeline-worktrees-service.ts): per real-repo project it reads git worktree list + branch descriptions + each worktree's state.md, cross-referenced with the sessions table — no stored registry, so it never goes stale and surfaces orphans. Removal runs the pure evaluateWorktreeRemovable guard (precedence main-checkout > not-a-worktree > keep-marker > locked > in-use > uncommitted > unlanded — seven reasons, not six; keep-marker is an ABSOLUTE veto for a branch whose DESCRIPTION carries a do-not-delete directive, so a clean/landed/orphaned-but-PINNED worktree is still refused (locked is what a ledger PIN actually sets). It reads fail-CLOSED at remove time — an unreadable branch description counts as marked. Kill switch AMC_DISABLE_WT_KEEP_MARKER_VETO), RE-gathered with real git reads in Main before any delete; live ownership includes agentDetectedWorkdir (how a self-created worktree is tracked), and deletion goes through the junction-safe removeWorktree. IPC: WORKTREES_GET (read), WORKTREE_REMOVE_ONE / WORKTREE_REMOVE_SAFE_BULK (destructive). Both removals are ALSO CLI control-server routes — POST /project/:id/worktrees/remove ({ worktreePath }) and /remove-safe — so an agent can clean up worktrees headlessly; they reuse the same service verbatim, so the same guard runs and a kept worktree comes back as a normal 200 { removed: false, blockedReason } (cli-server-project-ops-routes.ts; documented in the omniscio-control projects.md spoke). See dev-pipeline-panel-contract.md W1–W7.
  • Run cost is captured by Omniscio, not the skill: each pipeline_run_events row snapshots the owning session's cumulative cost_usd (nullable, additive migration), and the pure derivePipelineRunCost (src/shared/pipeline-run-timeline.ts) turns consecutive snapshots into run + per-phase deltas — run-scoped by construction (a session's total includes pre-pipeline chat), clamped ≥ 0, null = unknown (never a fabricated 0). The Live list closes each open run against the session's current cost via ONE batched getFirstPipelineCostSnapshots read (never N+1). See dev-pipeline-panel-contract.md RT6.
  • Stale runs + Adopt: a worktree is a stale run when it carries a non-complete pipeline state, no live session owns it, and its recorded ## Owner session is gone or terminal (isStalePipelineRun). adoptStalePipelineRun re-verifies everything at click time, serializes concurrent adopts (in-flight set), transfers the state file's ## Owner to a RESERVED session id BEFORE spawning (a failed spawn stays stale → retryable), then spawns via createSessionWithPrompt with reuseWorktree (runs INSIDE the stranded worktree; fails closed pre-insert if the path vanished) and a /dev-pipeline resume prompt — the skill's own STEP-0 discovery matches the new owner and resumes. IPC: PIPELINE_ADOPT_RUN, also the CLI route POST /project/:id/worktrees/adopt-run ({ worktreePath }). Because adopting spawns a real (paid) session, the CLI kind pipeline.adopt_run is NON_TOGGLEABLE + IRREVERSIBLE: the route only ENQUEUES an inbox approval (no in-app-session bypass — an AI can never self-approve it) and requires a source session; the pipeline-adopt-run-handler runs adoptStalePipelineRun only on approval. See dev-pipeline-panel-contract.md A1–A5.
  • Load-failure behavior: a failed panel read toasts once (while un-hydrated) and shows the empty state instead of an infinite "Loading…"; the panel's own interval keeps retrying, and a transient failure after a good load keeps the last-good data. See dev-pipeline-panel-contract.md L8.
  • Gate auto-approval is per-phase: five independent gate toggles (Plan · Red Team · Build · Elegance · Docs) + a select-all master, backed by pipelineGateAutoApprove and resolved by resolveGateAutoApprove (fallback to the deprecated pipelineAutoAdvanceEnabled / pipelineAutoApprovePlanGate; see pipeline-auto-advance-contract.md). This panel and Settings → Features render the SAME controls (GateAutoApprovalControls), so their wording can't drift.
  • The two always-on standards gates (🚦/🔬) also appear as toggles here (panel-only — Settings → Features shows the built-in five). They persist in a separate setting pipelineStandardsGateAutoApprove (NOT pipelineGateAutoApprove), default auto-approve; the panel routes their on/off through the same row list and the setting flows through the manifest so a gate set manual holds the run for you. See dev-pipeline-panel-contract.md L9. (The ops-only DEV_PIPELINE_DISABLE_BUNDLED_STANDARDS kill switch is honored by the pipeline but not reflected in this panel's display.)
  • Custom phases show up here too (when Enable custom phases is on). The panel resolves your phase manifest (phases.json) and feeds it to GateAutoApprovalControls, so BOTH the flow diagram AND the switch list weave each custom phase in at its insert point (with its emoji) — each custom gate gets its own auto-approve switch at its true pipeline position (e.g. 🚦 Standards Check between Red Team and Build), not appended after the built-in five, so the switch order matches the flow diagram above it. One list controls every stop. Settings → Features (no manifest passed) keeps the plain built-in six. See dev-pipeline-panel-contract.md L6/L7.
  • AI code review — a review step after any phase. The AI code review card offers one switch per phase (after Plan, Red Team, Build, Elegance, Docs); each one you turn on inserts a real 🧭 AI Code Review phase right after that phase, where fresh AI reviewers read the work and report what they find. Off everywhere by default, so an untouched install is unchanged. Every step that runs gets a row — including one your repo sets for everyone, which the card labels as such; its switch turns it off for you alone, leaving your team's setup untouched. These gates get NO auto-approve switch in the list above, because there is no third state for a switch to select: the review's own verdict decides. A clean review closes green and the run moves straight on; a review that found something worth your attention parks for you. Each point you turn on spends reviewer tokens on every run. Your choice is saved alongside your custom phases and your own phases are never disturbed by these switches; it applies whether or not Enable custom phases is on. See dev-pipeline-panel-contract.md L11 (ops kill switch: DEV_PIPELINE_DISABLE_BUNDLED_AI_REVIEW). Above those switches, Run AI code review steps (on by default; the devPipelineAiReviewEnabled setting) turns every review step off at once, including in runs already under way: agents stop being given review steps, any reviewer asked for while it is off is refused (the app's own crew mission review has its own separate switch), and a session already waiting at one still moves on. While it is off, the per-step rows hide and the flow diagram shows no review step; the per-step choices stay saved for when it goes back on. It is the one AI-review control stored as a setting, because the app applies it itself — see dev-pipeline-panel-contract.md ai-review-switch-reaches-running-work. Under the switches, How each AI has done is the reviewer scorecard: one row per AI model with how many reviews it ran (and how many got no answer), the serious and minor problems it found that the pipeline checked and confirmed, its false alarms, how often the pipeline approved of its reviews (shown as "75% approved" once any review is rated — never 0% before that), and what it cost in total and per review. Cost is read from each reviewer's own session, so it is exact, and it stays on the scorecard even after you delete that session; a dash means the cost isn't reported (a reviewer that ran inside the pipeline's own session is billed with it, and some AI companies don't report cost to Omniscio yet). Below it, Whose work was reviewed lists each AI whose work the reviews looked at — its reviews, the serious problems found in it, and serious problems per review — so you can see which AIs need more review. Both stay empty until a review step runs. See ai-review-scorecard-contract.md.
  • Who writes the code — pick a cheaper model for the build step. The Who writes the code card sets which model actually writes code during the build phase, and whether it runs as a helper inside the run (the default, cheapest) or as its own session you can watch in Mission Control. Picking a cheaper writer is safe because it turns the pipeline's existing cheap-implementer preference into a rule: the smart model becomes an overseer that writes the failing test, hands the work over, reviews every change that comes back, sends work back with specific fixes, and keeps only what it accepts. Nothing a cheaper model writes is kept unreviewed, and the build gate has to report which model built it and how many changes were accepted versus sent back — a run that quietly skipped the loop has no counts to show. You store a speed level (Genius / Smart / Worker / Basic), never a specific model name, so your choice never goes stale when a new model ships. Default: Worker (Sonnet-level), as a helper in the session. Own-session mode starts a real session per build and costs money — turning it on is what allows the pipeline to start them. Saved alongside your custom phases in phases.json, which is the one file both Omniscio and the Claude skill read — a normal setting would be invisible to the run it configures. See dev-pipeline-panel-contract.md build-model-lives-in-the-manifest-not-settings.
  • What you set is what runs — the editor stays in sync with the project copy. The editor saves to your personal manifest (~/.claude/dev-pipeline/phases.json), but a run resolves project-over-personal, so an edit to a phase a repo ALSO commits (<repo>/.claude/dev-pipeline/phases.json) would otherwise be silently overridden. The panel bridges both directions (phase-manifest-service.ts): on save it writes the edit THROUGH into every repo that already commits that phase (syncCustomPhasesToProjectManifests — your fresh edit wins; it never adds a personal-only phase to a repo, never deletes a project phase, and never commits/pushes — you commit the file), and on read it shows the effective value (overlayProjectValuesOntoPersonal — a phase a repo commits displays that project value, so a switch can't read "on" while "off" is what actually runs). Both are fail-safe. A personal-only phase (no repo commits it) stays yours; a committed project manifest applies to every dev on that project (see dev-pipeline.md "Project-level phases"). AI Code Review steps are the exception both ways: a repo's review steps are the team default, and once you change any review setting for a step, YOUR settings are what run on your machine — so the editor shows your own values for it, and a save never writes a review step into a repo's shared file. A step you switch on without changing anything keeps (and shows) the shared settings, and a save never quietly turns that copy into your own.
  • Auto-lander reuses AutoLanderSettings (per-repo config, force-revealed via its embedded prop) + MergeDaemonStatusCard (live status). The land history is a new auto_lander_events table written fail-open by the auto-lander supervisor's per-tick sink (the three terminal outcomes only — landed / conflict / unlanded — deduped + retention-pruned); IPC: AUTO_LANDER_EVENTS_GET, refetched on the existing AUTO_LANDER_STATUS_UPDATED push. See auto-lander-contract.md.
  • QA Fleet (QaFleetView) is a read + triage surface over the QA fleet ledger at ~/.amc/qa-fleet/ledger.db. Two IPC channels: QA_FLEET_SUMMARY_GET (qa-fleet:summary) for the totals / trend / findings / E2E / coverage read, and QA_FLEET_FINDING_STATUS_SET (qa-fleet:finding-status-set) for the resolve / dismiss / reopen triage write. Its quiet line in StagesView carries the open-findings count and shows it ONLY when it is above zero, so a clean fleet reads no count at all. It carries no unreleasedFeatureId, no visibleWhen and no setting, so it ships to every user of this shipped panel; if that is ever meant to change, the missing gate is the fix, not a doc. The richer developer-facing driver for the same fleet is internal/qa-fleet-desktop-routes.md, which is repo-only (the internal/ tree is excluded from the published mirror, from extraResources and from the packaged app), so this page is deliberately the customer's only route to it.
  • Landed-session attribution + note. On a landed, the sink ALSO resolves the dev-pipeline session that authored the branch — via the SAME owner-resolver the conflict hand-back uses (worktree_branch → the branch's git worktree dir → agent_detected_workdir), so a self-created worktree is found and terminated authors count — and stamps it onto a new nullable auto_lander_events.session_id (migration 20260716130010). Two surfaces read it: the supervisor appends a PASSIVE kinded notable-system "landed" note to that session (landed-session-notify.ts → addMessage + SESSION_OUTPUT push — fail-open, idempotent on a FRESH insert, and it NEVER wakes / reopens / spawns the session, unlike the conflict hand-back's deliverPeerMessage; kill switch AMC_DISABLE_LANDED_SESSION_NOTIFY), and derivePipelineRunHistory marks the Timing run "Landed ✓" via a single listLandedSessionIds join. Runs after the status push, before the worktree retire. See auto-lander-contract.md (S26) + dev-pipeline-panel-contract.md (RT7).
  • Add a repo is Setup's repo-list control for a folder the app has never seen. The renderer is AddRepoDialog.tsx (opened from SetupView.tsx's repo block, replacing the old instruction line); the read is previewRepoFolder in src/main/services/dev-pipeline/repo-preview-service.ts over the read-only channel dev-pipeline-panel:preview-repo (DEV_PIPELINE_REPO_PREVIEW), which the WS bridge serves to a phone or web client like any registered channel. It is ASYNC fs only — no execSync/spawnSync — over a fixed allow-list of manifest paths with a 512 KB per-file ceiling, so a huge or odd repo cannot stall the main process, and every refusal is data (not-a-full-path / cannot-read / not-a-repo), never a throw. It calls the same pure detector a run uses (detectRepoProfile, resolvePipelineChecks, detectBaseBranch, repoProfileHealth in src/shared/repo-pipeline-profile.ts), so the panel and a run can never disagree about one repo, and the four HEALTH_* words are translated in the dialog because the detector's constants have no other user-facing surface. Registration happens only on the confirm click, through the project store's addProject, and the folder is looked up in projects FIRST — addProject answers null for a refusal and for a duplicate alike, so catching an error could not tell the two apart. Contract: dev-pipeline-add-a-repo-contract.md.
  • Worktree cleanup (WorktreeCleanupSection) is a dashboard over the vendored PowerShell cleanup scripts (scripts/worktree-maintenance/, self-contained via $PSScriptRoot). A Windows-gated Main service (src/main/services/worktree-cleanup/) READS the tool outputs (per-run summary.json, the worktrees-*.tsv verdict grid, the wt-deleted-recovery.tsv restore log — read from the out-dir root AND every run-<ts>/ dir, since every app-driven reap writes it into the run dir; tail-bounded with a row cap like the sibling append-only readers, ref probes pinned with -C <resolveMergeRepoRoot()> to the same repo recoverWorktree restores into, and the recoverable flag applied at the render site), and a 5-min supervisor BOTH ingests completed runs into worktree_cleanup_runs (pushing status on-change + raising a deduped stale alert) AND is the in-app scheduler — it fires the reap on a user-configurable cadence + a startup catch-up, load-gated via isBoxHeavyOrSettling, decided by the pure decideScheduledRun (worktree-cleanup-schedule.ts). The cadence is worktreeCleanupIntervalHours (default 1 — WORKTREE_CLEANUP_INTERVAL_HOURS in src/shared/worktree-cleanup.ts, lowered from 2 on 2026-09-02 because idle unlanded worktrees filled a drive overnight; the reap retires a capped batch per run, so cadence is the throughput lever) read through resolveCleanupIntervalHours (clamp [1, 24], bad value → default), and the stale window scales with it (resolveStaleThresholdHours) so a long interval never false-alarms. There is no OS Scheduled Task: worktree-cleanup-ostask.ts removes the legacy one — only while the in-app replacement is active (toggle on + available; fail-safe skips), re-checked every boot and cleanup-settings save so a re-created task is re-detected (no permanent marker) — and worktree-triage-cron.ts auto-seeds the stranded-worktree triage-dispatch cron — active iff isWorktreeTriageActive(settings) (= worktreeCleanupEnabled && worktreeTriageEnabled), so the paid AI triage is an independent on/off while the free cleanup keeps running. The status card's "next run" is derived from the in-app cadence (scheduledTaskState is null; a load-deferred run reads "waiting", not "wedged"; the healthy label is generic, not a fixed interval). The runner is the only mutating spawn surface (a NON-detached argv-array spawn of the wrapper for the reap — a detached spawn silently never runs the script on Windows; git branch for recover — never shell:true). The reaping stays entirely in the scripts, so all their safety invariants are preserved. Flags worktreeCleanupEnabled / worktreeTriageEnabled / worktreeCleanupIntervalHours; IPC WT_CLEANUP_*. See worktree-cleanup-contract.md.
  • Session-based cleanup (worktreeSessionCleanupEnabled, cross-platform, default off) is a SEPARATE createPeriodicTask scheduler (src/main/services/worktree-cleanup/session-cleanup-*.ts) from the reaper above — it runs alongside it. Each tick, for a qualifying repo (active dev-pipeline OR a broad stray-worktree sweep — pure decideRepoCleanup in session-cleanup-decide.ts) it removes every orphaned candidate through the guarded removeOneWorktree — now PR-aware: prMergedConfirmed (gathered authoritatively at remove time via checkBranchHasPR, fail-safe false) relaxes ONLY the unlanded refusal so a squash-merged branch cleans up, while every higher veto (main-checkout / in-use / uncommitted) stays absolute. For a REFUSED residual it does ONE of two things, exclusively: with no cap, load or in-flight session in the way it spawns ONE read-only investigation session (createSessionWithPrompt, isolationOverride:false → repo main checkout, source:'worktree-session-cleanup') that fs-scans for husks and reports in its final message, staying on the board when it found anything; otherwise it raises one deduped inbox alert itself. The card is the app's, never the session's — an app-spawned session is machinery and is not told to raise one (inbox-alert-contract engine-owned-machinery-is-never-told-to-raise) — and the session NEVER deletes. Feature daily session + spend caps (resolveDailyCaps, read-time clamped) sit on top of the global daily budget cap; boot start + a teardown task + a settings-apply reactor mirror the reaper. Settings worktreeSessionCleanupEnabled / ...MaxSessionsPerDay / ...DailyBudgetUsd; kill switch AMC_DISABLE_DEVPIPE_WT_CLEANUP. See worktree-session-cleanup-contract.md (its invariants) + dev-pipeline-panel-contract.md W4.

Related

Last verified 2026-10-06