Desktop
The Shipper desktop app is a supported macOS app for running the Shipper issue lifecycle from a visual pipeline board. It uses the same core engine as the CLI and covers the same workflow stages: issue intake, grooming, design, planning, implementation, PR review, and merge readiness.
Desktop does not create a separate project database. Workflow identity, stage, priority, failed state, workflow history, and issue title/body content live in Shipper’s local issue-state store and append-only workflow event log. GitHub labels, issue content, and Shipper workflow comments are mirrors for users and integrations; PRs and adopted-PR marker comments remain GitHub artifacts. You can switch between desktop and CLI work on the same repository because both entry points read and write the same state.
Next-step presentation
Section titled “Next-step presentation”The five desktop columns are Design · Plan · Implement · Review · Ready. They describe the next work, derived immediately from existing records without migration or reprocessing:
| Completed stage | Next step |
|---|---|
shipper:new | Groom, in the separate New attention area |
shipper:groomed | Design |
shipper:designed, simple route | Implement |
shipper:designed, complex or undecided route | Plan |
shipper:planned | Implement |
shipper:pr-open, with or without a pull request | Review |
shipper:rework | Implement, with a Rework badge |
shipper:ready | Ready for final integration |
Ready is not shipped and does not prove that a merge is currently eligible. A rejected simple implementation that escalates to complex appears in Plan. Auto-ship says Review in either PR mode; Rework is a current-state badge in Implement, including failed or held cards retaining that state. Implementation returns the card to Review and removes the badge. Other bounces, including rejected simple implementation, have no Rework badge.
CLI/MCP retain six next-step groups. For the same issue population, the five desktop columns are Design · Plan · Implement · Review · Ready: desktop Implement equals CLI/MCP Implement plus Rework. New stays in a separate attention area. Closure-held and failed issues are excluded; closure hold takes precedence over failure. Blocked, locked, operator-paused, and running issues retain their route-aware column membership. Attention counts overlap those memberships. MCP blocked rows remain in their next-step groups with blocker and ownership details; only stageless or unknown-stage blocked rows use Blocked attention — no next-step group.
Current open responses add nextStep, and status adds nextStepPipeline. Existing completed-stage
pipeline JSON fields, workflow labels, status filters, commands, and reset arguments keep their
meanings. Closed records have no future next step, and historical records are not rewritten.
Maintained GitHub label descriptions retain completed-work meaning and add next-step guidance. New repositories receive them during setup; existing repositories automatically refresh differing descriptions on their next normal label setup or maintenance, without separate initialization. A successful catalog cache skips repeat maintenance; a changed catalog or force refresh reads again. Existing colors and unrelated labels are preserved. Read-only status, list, and view make no label writes.
Route-specific resets and drops
Section titled “Route-specific resets and drops”Reset choices, previews, successes, and refusals lead with the next step, then the literal
completed-stage target and any route clearing. An eligible Design drop targets groomed and
clears the route to undecided. An eligible Plan drop targets designed for complex or undecided
routes; a simple-route Plan drop is refused with the route unchanged because designed would next
Implement. An eligible Implement drop selects preserving rework when offered by the existing
reset options. Otherwise it targets designed for simple and planned for complex or undecided.
The existing main-process preview validates the package; missing, stale, closed, merged, unreachable,
or unverifiable evidence refuses confirmation without falling back to destructive cleanup.
To deliberately discard work, choose Start over — in the card Reset menu; the existing cleanup
confirmation applies. The Plan column is different from --to planned,
whose next step is Implement. A successful --to designed says Implement for simple and Plan for
complex or undecided. New (--to new) also clears the route.
These translations do not override backward-only eligibility, failed-stage retry, preserving Rework exceptions, active-work restrictions, confirmation, destructive work-loss warnings, or work-preservation guarantees. Review and Ready are not drag-reset destinations. A non-failed same-column drop does nothing, including Rework already in Implement; repeat Rework menu resets remain real preserving operations. Dragging cannot force a route change beyond Design’s existing route clearing.
Desktop or CLI
Section titled “Desktop or CLI”Use desktop when you want visual triage, queue monitoring, headless grooming with native question forms, setup terminal sessions, pause/resume controls, issue run controls, logs, and hands-on operation from one board.
Use the CLI when you want scripts, CI or container execution, direct terminal commands, explicit
stage invocation, or headless automation around commands such as shipper next, shipper ship,
shipper merge, and shipper reset.
Many teams use both: desktop for day-to-day monitoring and control, CLI for repeatable commands and automation.
On macOS, Desktop New Issue preparation, background stages, and Groom sessions use the same idle-sleep protection contract as Terminal and MCP. See Keep the Mac awake during active work.
Install
Section titled “Install”Download the latest macOS arm64 DMG or zip artifact from the private repo’s GitHub Releases (authorized access). The current desktop artifacts are unsigned and not code-signed, so macOS may require manual confirmation before first launch.
Windows and Linux builds are not currently distributed. Desktop can use a GitHub owner/repo entry
or an existing local Git working copy.
The app runs Shipper workflows locally, so the normal local prerequisites still apply:
- Git and either a GitHub-hosted repository or a local primary working tree.
- For GitHub-backed repositories, GitHub CLI installed and authenticated with
gh auth login. - Node.js and the configured coding agent CLI for stages that invoke an agent.
- Repository Shipper settings that select the agent and command behavior.
Repositories whose effective transport has no remote can be opened without GitHub CLI. A GitHub-backed repository shows its own prerequisite guidance when GitHub CLI is missing or unauthenticated; selecting it again rechecks GitHub availability.
Update notice
Section titled “Update notice”Packaged macOS Apple Silicon builds make one best-effort check for a stable release each time the desktop app process launches. The check uses your existing Shipper sign-in and runs independently of app startup. Only a strictly newer release produces a dismissible, display-only notice, which names both the available version and the version you are running.
The check is silent when you are signed out, no stable release exists, the platform is unsupported, the response is rejected or malformed, the service is unavailable, or the request times out or encounters a network failure. None of these outcomes blocks or delays normal app use. Dismissing an update notice hides it for the current app session; a later launch may show it again if a newer release is still available.
The notice’s single upgrade action opens the gated Shipper downloads page. It does not download or install an update, show release notes, restart Shipper, or poll for another release while the app is running.
First Run
Section titled “First Run”-
Launch Shipper desktop.
-
Add or select a GitHub repository in
owner/repoformat, or choose an existing local repository folder from the repo picker. -
If the selected repository is GitHub-backed, install GitHub CLI and authenticate it:
Terminal window gh auth login -
Resolve any prerequisite warning shown by the app. For a signed-out, expired, or terms-outdated Shipper license, select
Sign inin the alert. Desktop opens the browser login flow in its terminal drawer and, after a successful sign-in, automatically rechecks the license and configured repositories, then loads accessible pipeline boards without a relaunch. Missing or unauthenticated GitHub CLI guidance appears only on affected repositories; select an affected repository after resolving the prerequisite to recheck it. -
If the repository is not configured, run setup when prompted. This records repository settings and provisions GitHub workflow labels for mirror-on repositories. Store-only repositories skip GitHub label provisioning and keep Shipper workflow state in the local store.
-
Confirm the pipeline board loads issues from the selected repository.
After the board loads, desktop and CLI commands can operate on the same repository interchangeably.
Adding a local repository
Section titled “Adding a local repository”In the Add repository dialog, choose Choose local folder to register an existing working
copy. You can select the repository root or any folder beneath it; Shipper resolves a nested
selection upward and shows the exact enclosing repository root that it registered. A primary
working tree is accepted whether or not it has a remote, whether its origin points to GitHub, and
whether Shipper setup has already run.
The selected folder must be inside a usable, non-bare Git working tree. Shipper rejects folders outside a Git repository, bare repositories, and linked worktrees—including Shipper’s own ephemeral worktrees—with a specific error. Dirty files and Git operations such as a merge, rebase, cherry-pick, revert, or bisect do not prevent registration; desktop reports that state as informational.
A registered local path is your existing working copy, not an app-managed clone. Shipper uses it directly and does not reset, clean, stash, synchronize, switch, copy, or relocate its primary checkout. Workflow operations may fetch repository data or create and remove Shipper-owned branches and ephemeral worktrees, but those operations do not change the primary checkout’s branch, index, tracked files, or untracked files.
Repository duplicates are determined by resolved filesystem location. If you add a symlink or
another path that resolves to an already configured working copy, desktop selects the first
configured representative instead of adding a second entry. A local path and a GitHub owner/name
entry remain separate even when they describe the same project.
Desktop preserves the configured path exactly across restarts. If the folder is moved, unmounted, deleted, or stops being a usable working tree, its entry remains in the repository list and is shown as unavailable. Restore the repository at that exact path, or explicitly remove the entry and add its new location; Shipper never silently removes, rewrites, or replaces it with a managed clone.
Repository Settings
Section titled “Repository Settings”Use the toolbar’s Settings action to edit per-repository personal values. The dialog does not change user-global or committed repository settings. Each row shows its current effective value and source after all settings layers have been applied.
The Per-stage agent, model, and effort group provides one unit for each of new, groom,
design, plan, implement, pr_review, and setup. Every unit has an
agent selector for Claude, Codex, Copilot, Grok Build, or OpenCode, plus free-text model and reasoning effort
fields. Model and effort values are unconstrained and are not limited to a predefined list. The
group initially expands when this personal scope contains any per-stage agent, model, or reasoning
effort override and starts collapsed otherwise. A single expand/collapse control remains available
at all times.
Choosing Inherit for an agent—shown with the resolved agent, such as Inherit (Claude)—removes
the personal override instead of saving the named agent as a new explicit value. For a stage model
or reasoning effort, empty or whitespace-only input means inherit and removes that personal value.
Its placeholder names the inherited value when one resolves; otherwise it reads
Inherit (coding agent default). The next effective value may come from a broader-scope setting for
that stage or, when no stage-specific setting applies, from the corresponding default preference.
The default model and default reasoning effort rows use the same clearing rule: emptying either field, including entering only whitespace, removes its personal override. Clear override remains an equivalent second path for those default rows. The dialog writes every change only to the selected repository’s per-repository personal settings. Newly started workflows use the saved result, including Desktop Groom sessions started from the board or resumed from the groom drawer.
Review diff ceiling (bytes) is an exact-byte numeric personal override for the complete reduced review input. The row shows the effective source, remains available when pull requests are disabled, and affects subsequent review and implementation rework runs. It accepts only finite positive whole byte counts. Clear override removes only the personal value and reveals the next repository, user-global, or built-in default value.
The footer action is Close. Whenever Save is available, attempting to leave with Close, Escape, a click outside the dialog, or Repair issue data first shows Discard unsaved changes? Choose Return to settings to keep every pending edit intact, or Discard changes to drop the edits and continue the originally requested close or repair. Leave requests are immediate when Save is unavailable and unavailable while a save is in flight.
Saving a changed agent, model, or reasoning effort probes the exact resulting tuple for every affected stage. Verification has one 30-second overall deadline across command preparation, probes, and any retry of independent switches. Repository checkout, settings resolution, writing, and refreshing are additional parts of the complete save outside that deadline. If an agent rejects a value, is missing, is unauthenticated or offline, or does not respond in time, Desktop refuses every submitted agent, model, and reasoning-effort edit for that default or stage switch and retains those drafts. Independent switches and unrelated edits may still save. The dialog identifies the stage, agent, value, and diagnostic beside each refused control and summarizes which edits were saved and which were not. A reasoning effort that Claude or OpenCode accepts without confirming is applied with an inline warning that the value may be ignored. Desktop never offers a save-anyway bypass.
Use Check agent settings to probe all currently stored effective combinations, including the default, and see rejection provenance, including the dotted key and settings file that supplied a value. The check runs only when you select that action: opening the dialog does not launch an agent probe.
Core Workflows
Section titled “Core Workflows”After the first board load, desktop becomes an operating surface for the same issue lifecycle the CLI reference describes. The sections below cover the background queue, logs, terminal sessions, pause state, card actions, shared locks, automation toggles, and reset flow that power users need during day-to-day work.
Superseded work notices
Section titled “Superseded work notices”When Shipper safely preserves issue-owned work before advancing a rewritten remote branch, the issue
card shows a blue, informational Superseded work block. This is not a failed state and does not
use failure styling. Each occurrence names origin/<branch>, abbreviates the recorded and incoming
tips, summarizes unique or indeterminate work, and includes the exact recovery command:
shipper recover S#<localId> --superseded <eventId>Each occurrence remains visible across polling, board reloads, scrolling, and issue-detail views. Those passive actions never acknowledge it. Choose Restore superseded work to create or reuse ordinary operator-owned recovery branches and acknowledge the occurrence after restoration succeeds. Choose Dismiss notice to acknowledge it without restoring branches. Multiple live occurrences appear newest first, and a failed issue can show its existing recovery controls beside these separate informational notices.
Shipper retains the backing hidden refs for the active issue with no age-based expiry or TTL. Elapsed time does not remove the notice or invalidate recovery. Completion, not-planned or external closure, unadoption, and reset-to-New release the Shipper-managed hidden refs only after the logical issue change commits. Earlier reset targets retain them. Ordinary branches created by Restore superseded work are operator-owned and survive issue release.
Issue Details and Reviews
Section titled “Issue Details and Reviews”Open an issue from the board to inspect its canonical detail. When locally retained review rounds
exist, the dialog shows a Reviews section with every round oldest first. Each compact row includes
the round number and stable identity, reviewed revision, disposition, finding count, optional
addressed or superseded handling state, and a pull request reference only when that round recorded
one. Local packaging continues to use the Pending change vocabulary rather than implying that a
pull request exists.
Expand a compact row in place to read that review round in full. Only one round is open at a time, and loaded rounds remain cached while the dialog is open. Full detail includes overall feedback, disposition and revision, every stable finding identity, file path, line, side, optional start range, complete comment and review-rework reply text, optional handled or resolved state, and complete partial coverage. The dialog applies no review or finding truncation; its existing content region scrolls to keep every round and finding reachable.
Issues with no retained rounds omit Reviews. If only the review record is unreadable, Reviews shows the reason while the rest of the issue remains available. The same compact and full views work for active, completed, and not-planned issues. They read local Shipper state only and never change review or handling state. GitHub-sourced inline PR review threads are not shown here; locally retained Shipper review rounds are shown under Reviews.
New Issue
Section titled “New Issue”The New Issue modal accepts a text request for the selected repository. When that repository’s configured agent supports image attachments, you can paste images into the dialog or use the attach image control to choose screenshots from disk.
If the configured agent does not support image attachments, desktop shows the unavailable attachment message in the modal and keeps New Issue text-only for that repository.
Canceling, pressing Escape, or clicking outside the modal with a nonblank request or any attached image shows Discard unsaved work? Choose Continue editing to preserve the exact request, attachments, and repository selection, or Discard to clear the draft before closing. A repository-only change or whitespace-only request with no images closes immediately. Launching a valid issue bypasses this confirmation and submits normally.
Changing to a repository whose agent does not support images—or whose image capability cannot be determined—while one or more images are attached takes effect immediately and then shows Remove attached images? Choose Keep images to restore the previous repository with every image intact, or Remove images to retain the new repository and remove only the attachments. The typed request is preserved either way.
Block Issue
Section titled “Block Issue”Canceling, pressing Escape, or clicking outside the Block Issue modal shows Discard unsaved work? when either the blockers or reason field contains non-whitespace text. Continue editing returns to both intact fields, while Discard clears them and closes the modal. Blank and whitespace-only fields close without a prompt, and a successful Block submission bypasses the confirmation.
Adoption
Section titled “Adoption”The desktop adoption modal lists open untracked issues and, when pull-request access is enabled,
eligible open pull requests from the selected repository. Candidate rows are marked as Issue or
PR so you can distinguish work that starts from an issue from work that adopts an existing pull
request for review. Pull-request policy controls PR reads independently from GitHub issue sourcing:
a repository with a verified GitHub identity can still list issue candidates when PR access is
disabled. When the repository has no GitHub identity, the modal explains that adoption candidates
are unavailable instead of presenting a normal empty result.
In mirror-on repositories, eligible PR rows are open, non-draft, same-repository pull requests
without shipper:* labels. PRs that reference multiple open same-repository closing issues remain
visible but disabled with a reason. If a backing issue is already tracked by Shipper, adoption is
disabled only when that issue still resolves to a different open PR. Draft PRs, fork or
cross-repository PRs, closed or merged PRs, and PRs that already carry a shipper:* label are hidden
from the list. Open issues already recorded as same-repository origins of local Shipper records are
also hidden, even when the source issue has no Shipper label.
In store-only repositories, desktop uses the local issue-state store as the adoption authority. It imports local records, records the GitHub issue or PR origin as read-only provenance, and does not add labels, comments, PR edits, or GitHub tracking issues. Already-imported issue and PR origins are hidden from the list even though the source GitHub artifacts do not carry Shipper labels.
When desktop adopts a foreign-branch PR in mirror-on mode, Shipper records the PR-to-issue link in a
Shipper-owned issue comment instead of editing the pull request body. In store-only mode, the same
association is stored locally. The CLI and desktop both read that durable association. If the
previously adopted PR is closed or superseded, adopt the current PR again from the modal or with
shipper adopt <current-pr-number>; Shipper will not guess a replacement automatically.
Adopt All Issues remains issue-only and never adopts pull requests. In mirror-on mode it skips
GitHub issues that already have Shipper labels or whose same-repository origin is already recorded
locally. In store-only mode it skips by local GitHub origin.
Use a PR row’s individual Adopt action, or the manual field, to adopt a pull request. The manual
field continues to accept an issue or PR number or URL.
Un-adoption
Section titled “Un-adoption”Every live board card—including blocked, failed, closure-held, locked, and queued cards—offers Un-adopt in its ellipsis menu. Closed records do not. Selecting it first opens a read-only confirmation naming the Shipper issue, the surviving GitHub issue, every owned worktree and local or remote branch to remove, and each dependent blocker conversion. Cancel makes no change. If those facts change before apply, Desktop refreshes the preview and requires confirmation again.
Only issues adopted or imported from an existing same-repository GitHub issue are eligible. Shipper-created issues and work items created while adopting a pull request are refused. A running stage must be stopped or allowed to finish; a queued command must be cancelled from the action queue; and every open linked pull request must be merged or closed. There is no force or override.
Mirror-on removes every shipper: label but preserves the GitHub issue body, comments, assignee,
unrelated labels, and its open-or-closed state. Dependents remain blocked on a strict GitHub issue
blocker. Store-only makes no GitHub write and instead refuses while dependents exist, naming each
one so its blocker can be removed or replaced.
Success removes owned development artifacts, the complete local record and event history, and all origin provenance; it leaves no tombstone. A repeated un-adopt fails as not managed. Refresh and reconciliation do not restore or report the source, while a later explicit or bulk adoption treats it as a fresh candidate with a new Shipper ID and history.
Runs and operator attention
Section titled “Runs and operator attention”Repository tabs show started-workflow running counts and needs-you markers across open repositories. Counts exclude queued work; an unavailable observation stays unknown rather than showing zero. Select the relevant repository to inspect its board.
Issue cards show compact condition badges. Their details show the selected run’s status, available
logs, Retry, Stop, and started-elsewhere information. Run status and origin badges do not appear on
cards, including completed history on idle New issues. Current ownership still governs card controls.
External ownership is read-only where required; durable read-only evidence does not gain mutation
controls. Queued runs have no logs, and started merges remain merge-bound and cannot be stopped.
Issue details show
local packaged branches as Pending change and expose PR links only when current policy permits.
Repository setup shows diagnostics and Retry setup or Set up again for setup failure recovery. New Issue board placeholder cards show creation progress and available logs, Stop, Retry, and Dismiss before an issue exists. Successful creation hands off to the real issue card. Placeholder retries require retained original input; if the request or images are unavailable, reopen New Issue and reattach any images. Dismiss hides the placeholder without deleting durable run records or transcripts.
Run status includes Queued, Running, Succeeded, Failed, Refused, Paused, Cancelled,
and Interrupted, with applicable destination vocabulary:
Reached <shipper:label>: a successfulShiporNextrun advanced to its recorded destination. The rawshipper:label is intentional.Returned to <shipper:label>: a successful rejection moved the issue backward to its recorded destination. The attention-needed treatment does not make the command a failure or change Retry or auto-ship backoff behavior. The return reason remains on the issue.
A Refused run that needs an operator closure decision is terminal but not a failure, does not
increment auto-ship failure/backoff state, and never offers Retry. Resolve the closure hold from the
issue card before continuing.
Interruption records a proven dead supervisor, not a workflow failure, retry-exhaustion occurrence,
or repository safety event. Refusals and operator cancellation remain neutral outcomes.
The renderer hydrates current sessions, activity tasks, and durable run outcomes from the
supervision host before applying live events, restoring daemon-hosted work after reload or relaunch.
Retained output may become unavailable while saved metadata persists. Agents can still use
shipper_get_session_logs for recorded agent transcripts and shipper_get_issue_runtime for
current runtime inspection; existing tools and saved run records remain available. Desktop does
not provide an aggregate run-history browser.
Observation health and recovery
Section titled “Observation health and recovery”Operational details show Observation waiting, Observation warning, Observation error,
inactive, or unconfirmed, even with one worker running and three spare. Genuine observation
problems appear in the board banner; observation alone leaves the toolbar pill’s ordinary posture
and slot use intact. Terminal shipper status
(including --json) and repository-scoped MCP shipper_status report the same committed facts:
repository, continuous episode start and age, latest reason, unfinished phase, and actual next check.
When no future check has a scheduled time they say no next observation scheduled. Missing
information is unconfirmed, and an absent reason is reason unknown.
A failed local eligibility read immediately makes eligibility unverified and records diagnostics. The same local condition becomes a warning after 30 seconds and an error after 120 seconds, measured from its first failure, even while dispatch is halted or capacity is full. Repeated failures update the count, latest failure time, and cause without restarting its age. The panel also shows the last successful read and separate local and remote opportunities, or their blocking reasons.
Local checks retry automatically at the ordinary cadence, approximately every four seconds. The first successful local check clears the local condition without Resume, acknowledgement, or restart, including an empty result or success followed by a GitHub failure. This local-read condition is distinct from a GitHub outage. Automatic starts wait for verified eligibility; queued reservations and running work remain, and all quota, ownership, safety, halt, pause, and capacity gates still apply.
A failed read retains the original quiet heartbeat deadline. Once due, safely permitted current observation proceeds independently of the local probe. A blocked heartbeat keeps that deadline and shows its cause and next remote opportunity separately from the next local check. Only complete current and remembered-blocker observation settles it. Recovery completes overdue work once, with no catch-up bursts; blocked and completed observation remain distinct.
Unrelated known observation errors appear immediately. Unexplained non-dispatch while enabled, permitted, and below capacity warns after a fixed five minutes (300,000 ms), including when eligibility is unknown. The same default applies with zero or some workers busy; there is no threshold setting. A previously normal heartbeat or explained retry becomes overdue from its original due time and warns five minutes later. Starting late, probing locally, or acknowledging a retry does not reset that deadline. A complete quiet heartbeat interval, full capacity, explicit halt/disable/safety or ownership stops, and explained waits for future policy retries do not warn merely for no launch. Quota restrictions and pauses still apply.
For unrelated general observation conditions, warning age continues across failed checks and changing reasons. A successful current eligibility check (including no eligible work) with a real future schedule, or verified admission of work, clears the warning automatically. Halting or disabling ends general applicability rather than claiming recovery. Halt does not stop local failure escalation. Disabled local health is inactive, with no local retry or outstanding heartbeat promise. Restart or re-enable starts unverified with a fresh episode, count, and age; retained diagnostic history remains available. Desktop’s elapsed clock only updates the display; it never starts checks or infers health.
Retry observation requests an ordinary check through the current repository owner. The runtime also automatically restores a missing observation obligation when safe. Neither path replaces an unfinished side-effecting inspection: repeated requests coalesce one follow-up, whose start time is unknown. A scheduled/already-in-progress acknowledgement does not establish recovery or clear an episode. Settings, worker counts, issue ownership, queued work, and safety controls are preserved.
For an inspection that remains unfinished, Restart daemon if idle is deliberate shared-daemon recovery. It checks the displayed owner and daemon instance, stops normally, and launches a replacement only after confirmed stop. Any genuine running or queued session, workflow admission, issue-linked continuation/check, or pending/retrying run-record write in any repository refuses stop. The refusal identifies the repository, issue/session/operation, phase, and applicable action; let that work finish or use its existing control. Observation-only work does not block normal stop. Normal stop has one 30-second total budget, reports cleanup/ownership failures truthfully, and never falls through to forced termination. A refused or failed stop never launches a replacement.
The terminal equivalents are shipper auto-ship retry-observation, then if needed
shipper daemon stop, followed by shipper daemon run only if stop succeeded. Retry connects
only to an existing daemon and never enables a repository or starts a daemon. A Terminal-owned
repository must recover through its hosting Terminal. A sticky Desktop fallback offers local retry;
if inspection remains unfinished, close and reopen that hosting Desktop after protected work drains.
It does not restart an unrelated daemon. These actions are separate from safety-stop Resume,
Clear halt, and dispatch-ownership clearing.
A replacement daemon retains durable settings but starts with unconfirmed observation health. It serves status promptly while independent repository resolution, control, history, and observation jobs fill in current evidence. One slow repository cannot prevent healthy peers from progressing. Service readiness does not imply that all repositories or their history have finished loading.
Rotating supervision diagnostics retain episode transitions, reason changes, escalation, recovery or ending, and cumulative count/duration summaries across daemon restarts. They support later reconstruction without logging every four-second poll. Active warning age is in-memory: a restart has no durable age-continuity guarantee and must obtain fresh evidence.
A daemon normally remains resident whenever at least one repository has Auto-ship enabled, even when every enabled repository is remotely quiescent. Quiescence is a quiet scheduling mode: an eligibility-bearing local change wakes that repository on the regular control cadence, and its slow, distributed heartbeat observes externally originated changes. It is not the durable Auto-ship safety stop and needs no operator resume gesture. Disabling Auto-ship for every repository restores normal idle retirement.
During recovery, Desktop first reports Reaching the background service and the absolute time that
phase began. If the bounded connection ladder does not reach a daemon, Desktop reports Starting local supervision and its service/first-snapshot phase with an absolute start time. Launch recovery
and recovery after daemon loss use the same host-selection sequence. Service attachment can finish
while repository resolution, history, or eligibility checks remain pending; those independent jobs
report their own observation evidence. Commands still validate their repository admission requirements.
The local-startup segment has its own approximately 30-second expectation; time spent in the
connection ladder does not consume it. Before that threshold the phase copy is neutral. At and
after it, the current phase is reported as taking longer than expected and the copy states that
workflow actions remain unavailable until recovery finishes. The overrun persists for as long as
startup continues: there is no terminal recovery failure, live ticking duration, retry, abort,
relaunch control, or automatic ceiling. No timer, poll, or availability probe drives the renderer;
the only timed change is the controller’s one threshold transition. When dispatch-ownership
acquisition reads a valid durable mutation-guard record and proves its PID alive, Desktop may add
Waiting on Shipper process <pid> as information. It names no blocker when that fact is absent,
malformed, dead, or indeterminate.
After local startup succeeds, Desktop uses a sticky in-process fallback for the rest of the app
lifetime and shows Desktop is hosting background supervision; Auto-ship remains enabled. A
repository-scoped
Desktop cannot dispatch right now banner appears only when the active repository lacks automatic
dispatch authority. Manual workflow actions remain available through their ordinary reservations
and locks, and unrelated repositories are unaffected. Clean daemon retirement and successor
takeover are event-driven transitions, not polling, and show no error banner.
Only a reachable version-incompatible daemon blocks app-wide readiness. The
Shipper versions are incompatible alert lists the client version, daemon version, and minimum
required daemon version, and identifies the older side when their release major versions allow it.
View upgrade instructions uses the same destination as the startup update notice. The alert is
guidance only: Desktop does not stop, restart, or evict the incompatible daemon.
Daemon-hosted work alone never causes a quit prompt and keeps running after Desktop closes. If a Desktop-owned Setup, Sign in, interactive terminal, or headless groom session is live, the existing confirmation names the sessions that will close and separately states that daemon background work will continue. Disabling Auto-ship remains the way to stop new automatic dispatch and drain work.
Ship and Next share the repository’s ordinary workflow-worker capacity. When every worker for a
repository is occupied, another Ship or Next stays Queued and starts automatically when capacity
becomes available. Workflows for different repositories are not serialized by this rule. Manual
launches can instead use the All workflow workers are busy dialog to queue the command or start it
immediately.
Background Logs
Section titled “Background Logs”Use Logs from an issue card’s overflow menu to open its current-app-run output. The card chooses an
active Ship, Next, Unblock, or Merge run first; when none is active, it chooses the most recently
started eligible run. A queued run has not started and does not make Logs appear, and neither New
nor Setup runs are eligible.
Issue details offer another route to the same selected session in the background log viewer. Running commands stream output into the viewer as it arrives. Running or finished runs that remain accessible during the current app run can retrieve their complete output on demand. Desktop receives transient live chunks and reads retained output pages from the supervision host. The renderer stitches a page’s confirmed byte offset with chunks that arrived during the fetch so each byte appears once. Streamed chunks are not durable run-history events; after the host and its retained output lifetime end, old output is unavailable even though the run record remains.
If a rare transcript failure makes part of the output unavailable, the viewer inserts a notice at the missing position that identifies the unavailable byte range. Complete logs have no notice.
The viewer follows the tail while you are scrolled to the bottom. If you scroll up to inspect earlier
output, it stops auto-following and shows Jump to latest; selecting that control returns to the
tail and resumes following new output.
Use Copy logs to clipboard to copy the visible log content. Any missing-range notice is included in
the copied text so a pasted log cannot be mistaken for a complete record. The copy control is
disabled while the initial transcript is loading or when the viewer has no log content, and changes
to a success icon after the clipboard write succeeds.
Terminal Sessions
Section titled “Terminal Sessions”Groom starts a headless session for the selected issue and opens the global groom drawer on the
right. The drawer remains available while you switch repositories and shows one issue tab for every
live, awaiting-answers, suspended, completed, or failed session. Running tabs show current phase,
round, elapsed time, and recent retained output. Awaiting tabs present ordinary authored
questions as native controls: analysis disclosure, an optional recommendation, candidate options,
and a free-text response for each question. Submit answers is the one explicit action, enabled only once every
question in the batch has a response, and it submits the whole batch at once. There are no decision
or provenance cards, veto controls, or batch-level action to confirm unvetoed decisions. The same
bounded scroller contains every question and the recent retained output; the combined submit, Stop,
and discard actions remain fixed and reachable.
Drafts persist while you switch tabs or close the drawer, and answers submit without exposing a
terminal. Cards show Grooming…, Needs answers, or Resume grooming as
appropriate; the closed groom rail shows an amber count of sessions that need answers across all
connected repositories.
Desktop-owned saved sessions discovered after an app restart appear suspended and wait for an explicit Start. Their detail view shows the saved transcript and answers, read-only pending question batch, grooming notes, answered rounds, and issue-text drift. Starting resumes that owned conversation.
A saved session that still holds the removed compact-confirmation format is incompatible. Shipper discards that saved session, shows an error toast explaining that grooming must restart for the issue, and returns the issue to its ordinary Start grooming card. The removed content is never transformed or resumed, and one incompatible record never hides the other resumable sessions beside it.
A saved session owned by MCP or terminal appears as Review grooming session instead of Resume; a legacy record with no owner appears as Unowned. The drawer shows only issue identity, owner, last-saved time, answered-round count, and whether a pending batch exists. It shows no question, answer, transcript, note, Start, answer, or discard control. Take over is the one forward action. It permanently transfers the full saved conversation to Desktop without launching grooming; the entry then becomes the ordinary Desktop-owned suspended view, and Start remains a separate gesture. While an issue run is live, Take over is disabled and the drawer states why. Elapsed time, an operator pause, or a queued reservation never changes takeover eligibility.
Stop terminates the live worker, unlocks the issue, and preserves saved progress. The destructive live-stop variant requires confirmation and is the only stop action that discards saved progress. After desktop confirms the discard, the session closes its own tab and a brief notification names the issue and confirms that grooming stopped and its saved progress was discarded. If saved progress cannot be discarded, the same notification surface reports that it was not discarded, and the tab remains as an ordinary resumable suspended session. A session blocked by recovery stays on the failed issue card for Recover change rather than offering recovery in the drawer. Only completed and failed receipt tabs can be dismissed during the current app run; suspended tabs remain available for Start.
Setup and authentication remain separate terminal-drawer workflows. Setup opens an interactive
setup session for repository configuration. The Sign in action for a recoverable license alert
opens the existing shipper auth login browser flow in an auth terminal tab. Selecting Setup or
Sign in again while its matching session is live focuses the existing terminal session instead of
launching a duplicate.
When sign-in succeeds, desktop rechecks the license and configured repositories and prepares accessible boards automatically. A cancelled or failed sign-in remains visible in the exited terminal tab and can be retried from the alert without an extra error dialog. A revoked license cannot be restored by signing in again; contact Bare Metal Labs support when the alert directs you to do so.
The terminal drawer shows one tab per Setup or Sign in session. Setup tabs are labeled with the repository, and each tab includes a status dot. The observed terminal session states are:
running: the session has recent output or input activity.waiting: no output has arrived for a short period, so the session may need attention.finalizing: desktop has asked the session to finish gracefully.exited: the process has ended and the tab can be dismissed.
Closing a terminal tab depends on that state. An exited session dismisses immediately. A
finalizable running session is asked to finish gracefully and moves to finalizing. A finalizing
session prompts Force-kill finalizing session?.
A manual renderer reload terminates any live Setup or Sign in terminal session and names the interrupted sessions in a notice. Those terminal sessions are not reattached, and their earlier terminal output is not retained after the reload. Headless Groom sessions are reconciled back into the groom drawer from their current snapshots and saved resumable state.
Pause and Resume
Section titled “Pause and Resume”Pause is scoped to one issue within one repository and is stored as shared operator-pause
ownership, so it persists across Desktop restarts and is visible to CLI and MCP. The former
pause-state.json file is migration input only; successful legacy entries migrate once and the
empty file is removed.
Pause behavior depends on what the issue is doing when you select it:
- Running ship: desktop asks the active ship to halt at the next safe stage boundary, shows pending pause feedback, and atomically hands its run ownership to operator pause at the safe boundary.
- Queued ship: Desktop installs operator-pause ownership with the matching reservation before it
removes/finalizes the queued session.
If the queued item has already raced into
Running, desktop follows the running-ship pause path instead. - Idle issue: Desktop installs operator-pause ownership immediately. A live run or queued reservation visibly refuses the attempt instead of being displaced.
An operator-held card shows an operator hold badge and a Resume action distinct from
active run ownership and repository-wide Auto-ship paused. Resume visibly reports
resumed or already-resumed. Resume-and-Ship/Next first resumes, then performs ordinary
reservation acquisition; Groom also resumes first, without another confirmation. Another
dispatcher can win that intentional race and produce the ordinary busy/run contention result.
Force unlock remains a reviewed deliberate override for an operator hold.
If an operator hold appears that you do not remember setting, use Resume to clear it. Existing
holds are retained as operator intent and are not expired or migrated automatically. Find affected
issues from the operator hold badge on Desktop cards or the per-issue
<issue>: operator-paused - skipped lines printed by shipper unlock --stale. shipper status
reports only an aggregate operator-paused count; it does not identify the held issues.
Issue Card Actions
Section titled “Issue Card Actions”Issue cards expose primary buttons and an ellipsis menu. Availability depends on the card’s current labels, shipping state, and repository prerequisites.
Card badges use lowercase text: failed, needs answers, blocked, operator hold, closed on github, owner stopped or invalid lock, launch failed, parked, mirror pending, recoverable, superseded work, supervision unknown, stopping, pausing, queued, simple, and high or low priority. Normal priority has no badge. Stage badges are omitted; if Rework is folded into Implement, rework identifies that saved stage. The recoverable badge appears only for failed issues with enabled recovery evidence, even when Recover change is temporarily disabled. Missing or uninspectable recovery evidence has no badge. Action availability, live run status, launch reservations, and run origin stay out of the badge row.
A card whose stored route is simple carries a simple badge alongside its other state
badges. Complex and undecided issues show no route indicator, because complex is the uninformative
status quo on a glance surface. The current route also appears as a Route row in the issue detail
Lifecycle section when it is simple or complex, and is omitted when undecided. Both reads come from
Shipper’s local issue state and add no remote lookup.
Ownership is evaluated per issue. When supervision claims are unavailable or stale, an otherwise eligible idle issue that has no known owner or reservation keeps Groom, Ship, Next, Pause, Reset, and drag available; Merge retains its existing supervision requirement. A reservation-only owner, external run, operator hold, queued workflow, or running workflow applies the state-specific rules below. Mutation controls remain visible but disabled when ownership blocks them, without unavailable tooltips or explanatory text, and the card cannot be dragged. Read-only issue details and Logs remain usable, and Groom continues to focus an already-active Desktop Groom session.
Held issues appear in a Closed on GitHub attention section before ordinary failed issues. Issue details
show the observed reason, actor when available, closing pull request or commit evidence, and whether
that pull request matches the issue’s stored PR. A dual held/failed issue appears only in the held
section; its failed state remains saved and becomes visible again if reopening resumes it.
Held cards cannot be dragged or reset, and do not offer Groom, Ship, Next, merge, change recovery,
Pause, Resume, Stop, or Retry. Priority, issue details/comments, block, ordinary unblock, force-unblock, and
the new Resolve closure action remain available. The resolution dialog starts with no selection:
choose Not planned, Reopen and resume, or Complete. Completion first displays Core’s explicit
work-shipped assertion and every affected dependent (or says none), then requires a second
confirmation using the preview token. A failure keeps the card held and displays the reason for
retry. See the canonical
distinction between closure holds and failed state
for the different clearing rules.
Both not-planned choices display a reason textarea. Blank or whitespace-only text keeps the apply
button disabled, while non-blank text is preserved verbatim. Shipper commits it with the tombstone
as an ordinary attributed local note headed Reason for Closing as Not Planned. The note remains
visible in closed issue details and can be retracted like any other ordinary note. In mirror-on mode
it is projected as a GitHub comment—even when the mirror was already closed—after the local commit.
A projection failure leaves the local closure successful and shows a repair-pending notice; run
shipper issue reconcile --repair to converge the one existing note, labels, and closure without
creating duplicates. Store-only retains the same local note and performs no GitHub write.
| Action | Where it appears | Available when | Effect |
|---|---|---|---|
Groom | Primary button on New attention cards; status action on an active or resumable Groom card | The card is not durably failed, owned by a conflicting live or abandoned run, blocked by an invalid lock, or actively shipping; fetch prerequisites are satisfied; and a Groom launch is not already pending. An operator-held card remains actionable and resumes automatically before Groom opens. | Starts or resumes headless grooming, or focuses that issue’s global groom-drawer tab. Native questions appear in the drawer; an operator-held issue is explicitly resumed first when needed. |
Ship | Primary button on non-ready pipeline cards | A repository is active, fetch prerequisites are satisfied, and the card is not blocked, failed, actively shipping, owned by a live or abandoned run, blocked by an invalid lock, or already awaiting a ship launch. An operator-held card remains actionable and opens Resume-and-Ship confirmation. | Starts the next eligible background Ship command after explicitly resuming an operator-held issue when needed. |
Next | First item in the ellipsis menu on non-ready pipeline cards | A repository is active, fetch prerequisites are satisfied, and the card is not blocked, failed, running another Ship or Next, owned by a live or abandoned run, blocked by an invalid lock, or already awaiting a workflow launch. An operator-held card remains actionable and opens Resume-and-Next confirmation. | Runs exactly one eligible workflow stage without merging after explicitly resuming an operator-held issue when needed. |
Stop Ship / Stop Next | Stop control beside a card with an active workflow | A controllable Desktop Ship or Next row for that issue is Queued or Running. A stale or unusable supervision claim does not expose a Stop control that cannot act. | Cancels the queued or running background command for that issue. |
Recover change | Primary button on a failed card with a saved question session, preserved groom output, or packaged work | Desktop inspects the shared recovery union. Unreadable or ambiguous grooming state and ineligible packaged state keep the action visible but disabled without unavailable tooltips or explanatory text; recovery reasons are available in issue details. The button also disables while the issue is locked, actively shipping, already recovering, or busy with another action. | Preserves a saved session and returns it to New for the next ordinary headless groom, validates and applies preserved grooming output, or restores packaged work to shipper:pr-open. The success toast uses generic recovery wording and session recovery includes its answered-round count. |
Pause | Ellipsis menu | The card is not already operator-held and no Next workflow is active. Queued Ship keeps Pause and Stop; queued Next keeps Stop without Pause. Reservation-only ownership and external ownership leave Pause visible but disabled without an explanatory tooltip. | Installs shared operator-pause ownership for idle/queued Ship issues or asks a running Ship to hand off ownership at a safe stage boundary. Active Next work offers Stop instead. |
Resume | Ellipsis menu | The card is operator-held. | Releases operator-pause ownership and visibly reports whether it was resumed or already resumed. |
Reset | Secondary button when recovery is present; primary for failures with no preserved artifact | Backward reset targets exist and the issue is not currently shipping. Packaged complex and undecided issues offer Rework (recommended), Planned, Designed, Groomed, and New; packaged simple issues omit Planned. Failed cards that still carry workflow stage label X also include X when valid. An active local issue lock makes the preview unavailable. | Opens the Reset Issue preview: preserving for Rework and destructive for earlier targets. A failed card with visible enabled or disabled Recover change keeps earlier-stage Reset as the destructive secondary path. |
Priority | Ellipsis menu | The card menu can be opened. | Sets local priority to High, Normal, or Low; priority labels are projected to GitHub only when issue projection is enabled. |
Release lock | Inline on a card whose run owner is no longer running | The card has a stale run lock and a release handler is available. Ship, Next, Groom, merge, and other state mutations remain unavailable until the lock is released. | Removes the abandoned run lock without inferring recovery or resetting workflow state. |
Unlock | Ellipsis menu | The card has an operator hold or invalid lock record; an unlock handler is available; and the issue is not currently shipping. Live runs do not expose Unlock. | Clears an invalid record directly. An operator hold discloses its pause time without a PID and requires a deliberate Force unlock confirmation. |
Unblock | Ellipsis menu | The card has shipper:blocked, is not locked, and is not currently shipping. | Starts a background shipper unblock command. |
Close as not planned | Ellipsis menu | The issue is not locked or shipping, and the required reason textarea contains non-blank text. | Atomically records the verbatim reason as an ordinary local note and the not-planned tombstone; mirror-on then projects the note comment, closes the GitHub issue, and removes Shipper labels. |
Un-adopt | Ellipsis menu on every live card | Preparation authoritatively checks imported origin, running or queued work, open pull requests, dependents, and owned artifacts. No force path exists. | Confirms exact cleanup and conversions, preserves the GitHub issue, then removes the issue from Shipper management. |
Resolve closure | Held card action | The issue has an active external closure hold and is not locked. The not-planned apply choice also requires a non-blank reason; its preview remains reason-free. | Opens the unselected three-choice closure dialog. Reopen restores the saved state; not planned records the ordinary reason note with the tombstone; complete requires the assertion/dependent preview and second confirmation. |
Shared Locks
Section titled “Shared Locks”Desktop, CLI, and MCP clients on the same machine coordinate through local issue lock files under the per-repo Shipper issue-state root. Each lock is keyed by Shipper local issue ID and records either a PID-backed run owner or process-independent operator-pause owner.
If a second local client finds active ownership, it avoids conflicting work. Cards show operator pauses as operator hold, dead run owners as owner stopped, and malformed records as invalid lock. Live run status and origin remain in issue details; the one-line card footer keeps timing and token usage. Live or indeterminate run owners remain active regardless of age; wait for them to finish or use the owning client to stop them. An operator pause remains active regardless of age and is excluded from stale cleanup.
The short reservation-only window before a workflow becomes queued or running is also ownership. The card disables Reset, Pause, Groom, Ship, Next, and drag as applicable without a reservation badge or unavailable explanation. Inspect issue details for ownership guidance. Once a controllable row appears, queued Ship offers Pause and Stop, while queued Next offers Stop. Stop is shown only when Desktop has a real queued or running session it can control.
Release lock removes a dead owner’s run lock; Ship, Next, Groom, merge, and other state mutations
stay unavailable until that explicit release. Unlock cleans invalid records and remains the
cleanup for an invalid record. Use Resume for an operator hold; Force unlock remains available only
as a deliberate, reviewed hold override and releases the hold without performing Resume. For a
healthy or indeterminate live run, wait for it to finish or stop it from the owning client—Force
unlock is not normal recovery and the card exposes no cleanup action. Locks are single-machine only:
two different machines operating on the same repository do not observe each other’s local lock
files.
Auto-Ship and Auto-Merge
Section titled “Auto-Ship and Auto-Merge”Auto-ship and Auto-merge are per-repository toolbar toggles on the pipeline board.
Auto-merge is saved in desktop app config per repository. Select the toggle to enable it for the
active repository; select it again to disable it. Automatic merging requires both Auto-ship and
Auto-merge. With Auto-ship disabled, Desktop does not dispatch Ready work automatically and the
manual merge action on an eligible Ready card remains available and unchanged.
When both toggles are enabled, Desktop fills a single-occupancy automatic merge slot from Ready
issues only, independently of ordinary auto-ship worker capacity. Ready issues are ordered by
priority tier (high, normal, then low), then by the earliest Ready stageEnteredAt time within a
tier. Desktop refreshes that ordering whenever the slot becomes free and dispatches only the current
head. An automatic merge or a Ready issue waiting for the merge slot does not consume an ordinary
worker slot, so groom, design, plan, implement, and other non-merge work continue at the full
configured concurrency.
Automatic Ready waiters stay on their existing Ready cards with a neutral
queued badge, also used for commands queued to start. Coincident queue conditions show one badge.
Waiting creates no spinner, toast, failure, retry affordance, or
failed run. A manually requested merge also waits instead of failing; its issue run details say Another merge is running for this repository. The local repository merge lock remains
the cross-process guard for CLI or other external merge activity.
For adopted foreign-branch PRs, Ready merge uses the durable issue-side association read-only. If
that PR was confirmed closed without merging, use shipper issue reconcile --repair to preserve
the implementation branch and clear the dead association; if it cannot be found, issue details direct
you to re-establish the link.
Desktop and CLI use the same core merge path in both mirror-on and store-only repositories. See
the command reference for canonical
merge method, branch update, dry-run, and remote deletion behavior,
and the state machine for the canonical
merge failure taxonomy and counter semantics.
A successful internal method fallback produces no failed command, Retry action, or retry
count movement. A post-merge remote-deletion refusal is only a warning and does not change the
successful Desktop outcome.
When pull requests are disabled, a Ready card identifies its pending change by packaged source
branch and evaluates the target branch locally. Merge is available when the target branch is not
checked out or its checkout is clean. A dirty checkout waits without changing the Ready styling and
names the exact target branch and checkout path. If no packaged change exists, the card directs you
to reset and re-ship under the current no-PR policy. If Git inspection fails, merge fails closed and
shows the inspection reason. Normal pipeline refreshes silently evaluate these states again, so
Auto-merge starts as soon as a waiting checkout becomes eligible without adding a toast, failure, or
run failure while it waits. Issue detail shows the same packaged branch as Pending change.
When pull requests are enabled, existing GitHub-backed behavior is unchanged for cards with linked
pull requests: issue detail retains the GitHub PR #N link, while Ready checks, external-merge
reconciliation, adoption, and issue details use the policy-approved PR artifact. Change recovery alone
follows the raw stored artifact, so a pinned local change from an earlier posture remains recoverable.
Each normal pipeline refresh includes an externally merged ready-issue reconcile step. It reuses the bulk lookup of open pull requests and performs a targeted lookup only for a ready issue whose stored link is absent from that result. When the linked PR was already merged outside Shipper, desktop completes the issue under the repository merge lock, immediately re-checks dependents, and removes the card in the same refresh without deleting its remote branch. Success and a busy-lock skip are silent, with no toast or notification; a busy lock is retried on the next refresh. If completion fails, the card remains and says that the linked PR was merged externally but Shipper could not complete the issue.
Auto-ship is enabled per repository. Select the toggle to enable it for the active repository;
select it again to disable it. After a ship finishes, desktop looks for the next eligible issue in
that repository and starts it automatically. Auto-ship skips issues that are already active, paused,
blocked, failed, or actively locked. Stale local locks do not block eligibility.
When a daemon-hosted ship or merge session successfully performs a merge, Auto-ship immediately
re-checks that issue’s blocked, non-New direct dependents, whether the run was started automatically
or manually. Targeting includes native Shipper references and GitHub issue numbers mapped to an
active or tombstoned managed issue. It does not wait for repository idleness or worker capacity,
does not preempt running work, and does not promote the released issue. Halt, safety, lock, pause,
quota, dispatch, and bounded-retry controls still apply. Remaining unresolved blockers stay silently
Blocked. Completions observed outside Shipper keep their existing behavior, including the externally
merged Ready-card reconcile path above. When the repository is idle, the untargeted automatic-unblock
sweep remains the backstop for unmapped external GitHub blockers and for dependents a targeted
attempt did not resolve. Targeted activity uses the existing automatic-unblock status.
The enabled state and worker count are machine-global desired state. They survive a Desktop quit and restart; an enabled tracked repository resumes silently at launch without a banner, notification, or starting/armed toast. Another local client can change enabled state, worker count, or record a halt, and Desktop observes the change in approximately five seconds even while its window is minimized or unfocused. Raising capacity makes new slots available; lowering it starts no work beyond the new limit and does not terminate running sessions.
Operational-status pill and details
Section titled “Operational-status pill and details”Desktop refreshes local supervision diagnostics every five seconds, including when the daemon is absent or recovering and the repository list is empty. An enabled, unregistered saved repository appears persistently at app level: owner/repo is enabled but unregistered. Add owner/repo in Desktop. The Add repository action opens the existing picker. The sentence survives restart, tab changes, and failed refreshes, and clears after observed registration or disablement. A failed refresh labels retained evidence Last known; current status unconfirmed.
Tabs use short Unregistered, Unavailable, or Pickup unconfirmed badges; operational details explain actual paths, causes, and recovery. Pickup unconfirmed alone is neutral, uses unknown capacity, and asks for a refresh after roughly five seconds. A connection or live owner alone does not prove pickup; supervision does not imply running work. Unreadable registry choices show Auto-merge unknown and refuse mutation while the repository list and appearance stay usable. Enable refusal says Enablement did not complete, preserves prior intent, and supplies the fix.
Unreadable registrations are preserved unchanged: use a compatible build for newer information,
restore a damaged file from a valid copy, or correct the reported access/lock problem. Discovery
uses existing saved intent and verified checkout mappings, not a new membership catalog. An enabled
legacy schema-1 record without a verified identity is shown by path as an unidentified enabled
saved record with add-repository guidance; corrupt/future records show a discovery limitation
without asserting enabled intent. If all identifying evidence is gone, a name cannot be recovered.
When an enabled repository leaves supervision, the daemon reports a named warning and an
auto-ship-supervision-lost diagnostic.
The board header keeps Auto-merge, Auto-ship, and worker capacity visible beside one compact
operational-status pill. The pill always combines an icon, text, and a health color. It reports
Auto-ship off, Halted, Active, or Idle with trusted N/M slots; when capacity cannot be
confirmed it says slots unavailable. Color is never the only status signal.
Healthy and automatically recovering operation stays quiet: disabled or inactive Auto-ship, idle or
active dispatch, normal or waiting observation, expected or absent ownership, active or quiescent
remote watch, healthy or guarded quota, explained automatic waits, automatically retrying
supervision delivery, intentional halts, and normally progressing workflow activity show no
operational banner. The Halted pill is therefore a quiet repository posture, not a failure.
When operator attention is required, exactly one non-dismissible operational/supervision banner
appears beneath the header. Observation errors, warnings, evidence-based unconfirmed observation,
and unavailable observation facts appear in this banner and operational details while the pill
keeps its ordinary Auto-ship off, Halted, Active, or Idle posture and slot use. Other attention
conditions make the pill say Needs attention with current slot use or slots unavailable.
The banner’s leading plain sentence follows four severity tiers: safety suppression and
control-record compatibility first; unavailable supervision or runtime, a recovering host, unknown
quota or ownership, each applicable repository dispatch failure, and each exhausted delivery area
second; observation errors, severe or floor quota, and secondary-rate-limit pauses third; and
observation warnings or evidence-based unconfirmed observation fourth. An actionable condition
leads within its tier, remaining ties use stable identity order, and the banner reports how many
other conditions remain. It stays present and advances to the next condition until all attention
conditions clear, exposing the union of every currently valid recovery action.
Activate the pill or choose View details to open the same labelled operational details region. It starts closed, never opens automatically when health worsens, remains open or closed while the same repository is selected, and resets closed after a repository switch or a new Desktop session. Details contain all available control, runtime, launch-retry, observation, remote-watch, quota, host, supervision-delivery, dispatch-ownership, repository-failure, compatibility, and recovery facts. Automatically retrying delivery episodes and the informational fact that Desktop is hosting background supervision appear here without creating attention banners. Visible timestamps use the local date and time with timezone context; useful relative elapsed durations remain beside them.
Safety Resume, observation recovery, guarded ownership recovery, host Retry now, and each
exhausted-delivery retry appear in both the banner and details when valid, sharing pending, disabled,
confirmation, result, and focus behavior. Clear halt is details-only and never appears in the
banner. When safety suppression and a halt coexist, the banner offers Resume; after suppression
clears, the quiet Halted pill remains until Clear halt is selected in details. These recovery
actions are not duplicated beside Auto-ship.
Healthy, waiting, busy, and inactive observation offers no observation recovery actions, including in details. Deliberate quota-pacing waits and completed inspections with no dispatchable work stay quiet; elapsed wait time alone does not require recovery. Details retain the wait reason and actual next observation time. Genuine stalled, failing, overdue, or unexplained observation still raises attention with applicable recovery actions.
Per-command command uncertainty alerts and the per-checkout local working copy alert remain independent. They are not operational/supervision conditions and do not count toward the single banner.
Turning Auto-ship off in Desktop cancels queued automatic work and asks running automatic Ships to
stop at their next safe checkpoint. An external not-enabled change has the same effect. Disable is
enabled: false: it drains current automatic work and prevents dispatch until Auto-ship is enabled
again.
A halt is different. It is a persistent operator-requested hold on the repository that preserves the enabled state and worker count, withdraws queued automatic starts, asks running automatic Ships to stop at their next safe checkpoint, and blocks every later automatic stage and merge. It survives an idle repository, wind-down completion, a Desktop, daemon, or machine restart, and disabling and re-enabling Auto-ship. It ends only when an operator clears it.
While a halt is recorded, the quiet operational-status pill reads Halted; draining and unavailable
runtime facts remain available in View details. The Auto-ship toggle continues to communicate
only enablement, and the worker selector stays visible and operable throughout.
The details distinguish Halt requested while running work is Draining from the settled Halted
posture after that work reaches its checkpoint.
Open details and select Clear halt to release the hold. That action does not enable Auto-ship and does not touch the worker count or the safety stop; Resume remains the separate safety-stop recovery gesture and never clears a halt. While the request is in flight only the Clear halt button is disabled, and a refusal is reported inline beside it. Clearing releases repository-control checkpoint Stops that have not yet been consumed, so if the repository is observed enabled and unhalted before a run consumes its request, Desktop clears that run’s pending-stop presentation within the normal observation window and it continues running. Explicit card Pause or Stop remains intact, and manual advances stay available throughout. Clearing does not relaunch stopped work, recreate a withdrawn queue entry, dispatch replacement work, or add a badge, toast, notification, or run entry.
Auto-merge remains a separate Desktop-local per-repository setting. An external client can enable Auto-ship and advance workflow stages, but nothing merges automatically unless the operator has also enabled Auto-merge for that repository in Desktop.
Dispatch ownership
Section titled “Dispatch ownership”The active repository’s on-demand operational details include one Dispatch ownership fact. It reports not held, held by this Desktop’s background owner, a brief direction to the panel above for a competing or unverified holder or an unavailable inspection, or Unknown. Unknown is shown whenever Desktop lacks the expected-owner identity, an operational daemon or in-process host, or a matching represented live repository row; missing evidence is never presented as ordinary ownership.
The ordinary held reading requires the exact running daemon or in-process fallback instance serving this Desktop. Merely having a Desktop or daemon surface is not enough: a same-surface holder with a different instance identity is competing ownership. The ordinary reading is a collapsed disclosure. Open it to see the repository, holder surface and PID, acquisition timestamp, liveness, Last refresh (diagnostic context only), and the consequence statement: While dispatch ownership is held, any other scheduler on this machine stands down rather than dispatching for this repository. Last refresh is diagnostic context, not freshness, expiry, or liveness evidence.
The disclosure also keeps Clear dispatch ownership reachable when the expected owner appears healthy but is no longer delivering work. Use it only when that holder can no longer be trusted to release normally. The first selection is a read-only preview. Desktop opens confirmation only while ownership remains held, repeats the repository and five facts, and warns: Discarding dispatch ownership held by a genuinely running holder means two schedulers will dispatch for this repository concurrently. The confirm action sends the preview’s opaque token. If the owner changed, Desktop keeps the dialog open, says nothing was cleared, disables the prior confirmation, shows the newly observed status, and offers Review current ownership for a fresh preview. A no-owner result is a truthful no-op. An unavailable result names the read failure and offers no blind retry.
A terminal or unrecognized holder, indeterminate liveness, a Desktop or daemon instance other than the expected owner, and any other unverified held state contribute an ownership attention condition to the single banner. Full repository and holder facts, consequence, and guarded recovery remain in details. When inspection itself is unavailable, the condition says Dispatch ownership could not be inspected, names no holder, and offers no clear control.
The operation is repository-scoped and does not change Auto-ship desired state. Clearing one
repository leaves sibling repositories and every state.json unchanged. The normal supervision
observation cadence then reacquires ownership and resumes dispatch for only the affected repository;
no Desktop reload or manual refresh is required.
Desktop consumes the same six current repository-safety identifiers as the CLI:
terminal-stage-failure, merge-retry-exhausted, pending-checks-exhausted,
groom-output-invalid, worktree-setup-contention, and
upstream-merge-wait. Every completed background Ship transports
either literal null or one of those classifications from the validated command-result sidecar.
Missing or invalid sidecars and background process failures become explicit
terminal-stage-failure occurrences. The UI’s leftStuck field controls presentation and retry
behavior only; it never classifies repository safety. Blocked entry refusal and blocked post-work
stop are explicitly neutral. A progressed blocked stop resets an earlier streak before its neutral
blocked outcome is handled.
Pending CI checks are a deferral rather than a failed Ship. Desktop keeps every such command as a
Deferred issue run status in issue details and updates one stable informational notice per repository and local issue.
The notice names the PR, the latest incomplete checks, and the fixed deadline. Deferrals do not move
retry counts, permanently skip the issue, contribute to the repository safety stop,
or show an error toast. Auto-ship reselects the issue after the normal check cadence while manual
merge actions retain the same application-session clock for the next action.
The clock measures total elapsed time for one PR head SHA using
merge.pendingChecksTimeoutMinutes (default 60). A new commit starts a full new window, and
closing, hiding, reopening, reloading, or quitting Desktop preserves the daemon-lifetime window.
Deliberately disabling and re-enabling Auto-ship starts a fresh enabled run. When the same SHA
reaches the deadline,
Desktop changes that issue run status to Failed, suppresses Retry, and reports
CI checks never completed within N minutes for PR #P: CHECKS. After the checks complete, recover
with shipper recover S#123 or Recover change. A required check that never reports any
status is not visible as pending and is outside this bound.
Only checks-pending creates or retains this timer. Required approval, a temporary Ready lookup,
dirty local base, transient publication failure, and other typed run-skip outcomes keep the stage,
show neutral waiting feedback, and skip that issue only for the current enabled run. They create no
deadline, retry count, or repository safety occurrence.
When a clean GitHub outage consumes the full waiting allowance, the command exits 79. Desktop
records the issue run as unsuccessful but non-stuck, keeps the issue at its workflow stage,
and skips it for the rest of the current enabled run. Deliberately disabling and re-enabling
Auto-ship lets the issue be selected normally.
The outcome does not advance the repository safety streak.
Retriable automatic Ship failures use per-issue session backoff. Consecutive failures wait 30, 60,
120, and 240 seconds before that issue can be selected again; the delay is silent, affects only that
issue, and lets other eligible issues continue. Only temporary failures participate in this retry
count. Determined conditions leave Ready immediately for Rework or normal review and create no
separate cycle. A confirmed, non-halted merge clears the retry count. Closing, hiding, reopening,
reloading, or quitting Desktop preserves timers and counts while the daemon drain remains alive.
Disabling and explicitly re-enabling Auto-ship starts a fresh enabled run with new retry tracking. Attempts
one through four do not raise notifications; retry state appears in issue run details.
On the fifth consecutive retriable automatic failure, Desktop stops redispatching that issue for
the current enabled run, suppresses Retry, and records one repository-scoped
merge-retry-exhausted safety occurrence. It does not persist failed state. A later explicit
enable starts a fresh retry sequence and can select the issue without Recover change; attempts
one through four remain silent and do not move the safety counter. Three retry-exhaustion
occurrences pause Auto-ship for the repository.
For non-Ready work, Desktop uses the same store-backed auto-ship ordering as the CLI: priority tier
first, then workflow stage preference, then FIFO by the local issue-state replica’s stageEnteredAt
timestamp. Ready issues never participate in that ordinary queue; the independent merge slot uses
the Ready-only ordering described above. If the replica is absent or unreadable, desktop reports the
shipper issue reconcile --repair recovery message and does not fall back to GitHub timeline
selection.
Store-only and mirrored candidates participate in auto-ship and auto-unblock the same way. Desktop dispatches them by Shipper local ID and uses GitHub issue numbers only as optional display and projection metadata. Store-only merge deferral, timeout, and failure reporting remain local and make no GitHub writes.
Required PR approval leaves a card Ready with neutral waiting feedback and consumes no retry; an approved later dispatch can merge. No usable merge method fails immediately with repository setting guidance. Missing Ready package, mirror, link, or PR records also fail durably with their specific reset, reconcile, PR-open, or adopt recovery instead of repeatedly returning to the queue.
The shared merge failure taxonomy routes by structured cause rather than console wording. Merge conflicts atomically return the issue to Rework for implementation. Failed checks, a blocked merge, a still-behind branch, a branch-update failure, and an unknown determined condition return it to PR Open (or Change Packaged) for normal review. Both destinations suppress a direct Retry action because the normal workflow owns the next step, and neither route contributes to repository safety. Temporary causes remain at Ready and use the bounded retry schedule; missing merge capability and divergent base publication fail immediately.
For pending-check expiry and other durable failures, use Recover change
when the failed card’s packaged artifact remains recoverable. It preserves the packaged work,
clears durable failed state, and clears the current Desktop session guard. Retry exhaustion needs
only a later explicit Auto-ship enable after the transient condition clears. Use Reset only when
the source branch is missing or no longer contains the pinned revision, the linked pull request is
no longer open, or no packaged artifact exists. Store-only exhaustion and recovery reporting remain
local and perform no GitHub writes.
Auto-ship uses the
canonical failure-outcome and repository-safety contract
shared with CLI automatic runs. Three distinct qualifying condition instances suppress Auto-ship for
the repository by engaging a durable safety stop. Unchanged repeats—including identical surviving
workspace processes—share one strike. The machine-global desired state remains enabled, and
Desktop keeps the control pressed while changing it to the warning presentation
Auto-ship suppressed. The repository panel retains the three distinct conditions that engaged the
stop, the engagement time, and the lifetime engagement count across Desktop and daemon restarts.
Automatic dispatch remains suppressed until an operator deliberately clears the stop. Enabled
therefore means requested rather than dispatching: a halt, a safety stop, or another closed gate can
keep an enabled repository from starting any automatic work.
Pre-start automatic Ship, Merge, and Unblock failures use two separate board states. Launch retry scheduled shows whether the repository or one issue is cooled, its consecutive attempt count, and
the effective next-attempt time. After the fifth failure, Launch recovery-only shows the same
scope and count plus the automatic wake conditions: a cooled-scope change or the ordinary heartbeat.
The pressed Auto-ship control remains enabled in both states. The existing notice and affected issue
cards update in place and provide no Resume or clear-retry action and no next-pass promise. A successful
automatic or manual start clears the repository episode and the started issue’s episode, an
ineligible issue’s episode retires, and disable followed by re-enable clears the enablement ledger.
Notice dismissal and Desktop or daemon restart do not clear it.
Select Resume in the operational banner or details to clear only the safety stop in one action. Resume preserves
the repository’s enabled state, worker count, and halt value, and is never a halt-clear gesture; use
Clear halt for an operator hold. When both coexist, Resume is in the banner and details while
Clear halt remains details-only, and the two actions are independent.
The pressed Auto-ship control remains a separate Disable action; turning it off and then genuinely
enabling it again is the alternate reset gesture. A dedicated resume or disable/re-enable transition from another client updates the
board back to its normal enabled presentation automatically, without a Desktop restart, reload, or
manual refresh. When multiple repositories are suppressed, each tab has its own warning marker and
opens that repository’s retained diagnosis and Resume action.
Disabling Auto-ship prevents new Ready auto-merge dispatches as well as ordinary auto-ship work. A
successful workflow advancement advances the repository’s durable progress generation before any
later condition from that command is classified. Earlier strikes remain, while the same condition
observed after that progress is retained as a recurrence. Closing, hiding, reopening, reloading, or
quitting Desktop does not reset the pending ledger, durable safety stop, skipped-issue set,
pending-check deadline or retry state. The CLI uses the same failure contract for each
invocation, but stops selecting or refilling work, drains already-running work, reports any eligible
unattempted issue, and exits 1.
The five desktop columns remain visible even when empty in every repository policy presentation. Resetting eligible packaged work to Rework places the card in Implement with a current-state Rework badge. Rework is the recommended preserving menu choice and drop target on simple, complex, and undecided routes. The main-process preview confirms the package and shows its branch, revision, route and preservation guarantees. Missing or unverifiable evidence disables confirmation with an explanation.
Desktop sends the original previewToken back on confirmation; missing or changed tokens require a fresh preview. Rework uses a normal confirmation, preserves all packaged work and history, and may be repeated. After Reset committed; local recovery pending, confirmation is disabled and the board refreshes; do not repeat the operation. Next and auto-ship run implementation for Rework. Failed Rework recovery clears failure while retaining Rework and its existing trigger.
The cleanup flow below describes destructive earlier targets. Rework is the separate preserving choice; --to planned deletes managed branches under existing safeguards.
For a failed, non-held card with a saved grooming question session, preserved groom output, or a packaged artifact, Recover change is
the primary action. Groom recovery validates the preserved tree and, only if needed, runs one
unattended correction without restarting discovery or re-asking answered questions. Packaged
recovery preserves the exact revision, source branch, artifact, and completed review history. The
action remains visible but disabled for unreadable or ambiguous recovery state, ineligible packaged
work, locks, or another active action, without unavailable tooltips or explanatory text. Recovery
reasons and ownership guidance are available in issue details. Earlier-stage Reset remains the destructive secondary
path. Rework is the preserving reset choice.
Session recovery runs no agent and asks no questions. It clears failed state, returns the issue to New, reports the preserved answered-round count, and keeps the conversation with its owner unchanged. Desktop can resume normally only when it owns the session; an MCP- or terminal-owned session must be taken over first, and an unowned legacy session must be claimed through takeover. A session takes precedence over simultaneous groom output while retaining both.
Reset targets are route-aware. Packaged simple-route issues offer Rework, Implement (completed target
designed), Design (groomed), and Groom (new). Packaged complex and undecided issues offer Rework,
Implement (planned), Plan (designed), Design (groomed), and Groom (new). Only eligible choices are
rendered. Resetting to Groomed or New clears the stored route back to undecided because Design
will re-run; resetting to Designed, Planned, or Rework preserves it.
Reset is a two-phase flow. It is not a one-click destructive menu action.
Phase 1 is preview. Selecting a valid target opens Reset Issue and scans what will be cleaned
up: the target stage, labels to remove, pull requests to close, remote branches to delete, local
branches to delete, worktrees to remove, preserved grooming output to discard, and issue comment
count. A saved grooming question session appears as its own item with its answered-round count,
separate from preserved grooming output. Preview can fail before showing a summary if the issue is closed, the issue has an active
local issue lock, the target is the current stage for a non-failed issue, or the target is ahead of
the current stage. Preview is advisory and does not acquire or preflight a workflow reservation.
If preview finds a pinned local change, the dialog renders a destructive alert with its full
packaged revision and source branch and recommends Recover change for an eligible failed issue.
This local warning does not request a pull-request acknowledgement. If preview finds an open pull
request, the dialog instead names it and states that reset will close it and clear the stored
association. The pull request number shown in preview is sent back as the reset acknowledgement.
Reset-to-New also names preserved grooming output and saved question sessions before the confirmation
button can be used; Recover change is the preserving alternative.
Phase 2 is execute. Pressing Reset repeats validation, acquires the issue lock, runs cleanup,
commits the target stage to the local issue-state store, optionally projects workflow labels and the
reset notice to GitHub, and releases the lock. If the execute-time rescan finds an open PR that was
not acknowledged in preview, desktop makes no changes, keeps the dialog open, and requires a fresh
preview. Preserved grooming output and saved sessions are deleted only after the local Reset-to-New
transition commits. Execute’s atomic issue-lock acquisition is authoritative: a reservation or run
that wins after preview refuses Reset before cleanup, preventing a second pipeline execution.
Reset normally works backward and only on open issues. If a failed card still carries workflow stage label X, desktop includes X as a same-stage recovery target; the reset clears failed state, preserves X-stage work, removes artifacts after X, and posts the standard reset notice. The Reset action is hidden while the issue is currently shipping, and both preview and execute refuse active local locks.
Out of Scope
Section titled “Out of Scope”The desktop app does not currently provide these capabilities:
- Application-level keyboard shortcuts for issue-card actions.
- Right-click issue-card context menus.
- Permanent archival of command output after the supervision host’s retained-output lifetime.
- Changing paused issues so they hide Ship, Next, or Groom; paused cards keep normal actions as described above.
State and Artifacts
Section titled “State and Artifacts”Shipper stores shared workflow identity in the local issue-state store. When issue projection is enabled, it mirrors these fields and artifacts to GitHub:
- Workflow labels such as
shipper:new,shipper:planned,shipper:pr-open,shipper:rework, andshipper:ready. - Control labels such as
shipper:blockedandshipper:failed. - Local issue lock files used by CLI, desktop, and MCP clients on the same machine.
- Priority labels used by auto-ship ordering.
- Issue comments containing grooming, design, plan, implementation, review, and summary artifacts.
- Pull requests and CI checks used by review, implementation review-rework, and merge.
Desktop also has local state. Legacy pause state is migrated into the shared issue-owner store. The renderer rehydrates current background sessions, activity tasks, durable interrupted outcomes, Auto-ship state, and retained output pages from the daemon or sticky in-process fallback. Live output chunks and setup/auth terminal output remain transient. Local stage output, terminal sessions, settings, and the shared local issue-state store follow the same Shipper conventions the CLI uses. The issue-state store and workflow event log are authoritative for Shipper-managed workflow stage, priority, failed state, workflow history, and issue title/body content, and those fields plus workflow comment projections are projected to GitHub only when mirror-on policy permits issue-side effects. Desktop is a UI and supervision client over that shared model.
Current Constraints
Section titled “Current Constraints”- Desktop distribution is macOS arm64-only today.
- Release artifacts are unsigned and not code-signed today.
- Windows and Linux desktop artifacts are not currently provided.
- GitHub-backed repositories require GitHub CLI authentication; repositories with no remote transport remain usable without it.
- Release tags, package publishes, and desktop release uploads are maintainer-owned release tasks, not actions performed by the desktop app.
Related References
Section titled “Related References”- Getting Started
- CLI reference
- Settings reference
- Architecture
- GitHub Releases (private; authorized access)
Required-check obstruction and stalled remediation
Section titled “Required-check obstruction and stalled remediation”New automatic check stops apply only to independently acquired hosted checks. Shipper stops in Failed over Rework when current hosted evidence establishes an external obstruction after useful same-pass fixes, or when a completed, answered check-only review repeats with the same failing evidence on the exact unchanged revision. Both stops retain the package, branch, PR association, unpublished fixes, canonical answers, evidence and outstanding findings. Pending remote answer delivery remains visible separately from handled and resolved findings.
An external obstruction records concrete evidence, causal reasoning, an external remedy and why the failure still applies to final HEAD. For example, a required service explicitly rejects an expired organization credential while local code fixes pass: its owner must rotate the credential. A red check, a matching failure on main, or a missing tool alone does not establish that cause. Uncertainty calls for investigation; sandbox limitations and transient failures retain their normal verification and rerun opportunities.
Stalled remediation makes no external causal claim. For example, a completed V4 review’s only blocker is a required hosted verification failure, its canonical answer is retained, no code changes follow, and a fresh hosted acquisition repeats the identical identity and diagnostic evidence. Detection runs after existing refresh/rerun/flake handling and before another review agent. Nits are neutral. Changed HEAD, a passing check, a new blocker, materially changed evidence/procedure/source, pending or unavailable outcomes, incomplete evidence, legacy baselines, unanswered blockers, or request-changes review bodies prevent this mechanical stop. It does not execute a saved arbitrary local command.
Local verification is reported in existing prose summaries and relevant comments, without a
structured local evidence report. Every attempted non-permission local failure, including an
apparently unrelated or pre-existing failure, requires an anchored 🔴 must-fix: comment on the
most relevant changed line and REQUEST_CHANGES, followed by ordinary Rework fixes or prose
replies. Permission-denied and unattempted checks are limitations, never passes or waivers.
All previously required checks stay required. Local-only workflows have no local-evidence
automatic stop; the ordinary review-round cap still applies.
Historical local observations and failure records remain readable without migration. Outstanding historical local findings receive ordinary prose replies and never authorize a new automatic stop. Upgrade alone does not clear findings, renew allowance, or recover Failed. Publication and hook diagnostics and required hook execution remain unchanged.
Each applicable stop records one terminal safety occurrence. A skipped review creates no held round and consumes no review allowance. All required checks remain required: answers, reports, thread resolution and retry actions cannot authorize shipping or merging red checks.
Applying a remedy or restarting Shipper alone leaves the issue Failed. Inspect the durable diagnosis
with shipper issue view S#123 (or --json), then explicitly retry with preserving
shipper reset S#123 --to rework, or shipper recover S#123 when recovery is eligible. Existing
eligibility, locks, closure holds and confirmation rules apply. Both explicit paths renew the
five-round review allowance on unchanged HEAD without a dummy commit, preserve history and useful
unpublished work, and start a fresh attempt. Missing or divergent retained source refs refuse retry;
restore the source history first. Normal integration, hooks, verification and review must confirm
the remedy before advancement. Retained failure evidence becomes historical after renewal or
completion and remains available on Desktop, CLI and MCP, including failures with zero rounds.