Versioning
Shipper publishes a single canonical version of these docs. The live docs describe the current supported workflow rather than maintaining parallel docs for older releases.
The root @baremetallabs-ai/shipper-core package is the stable production contract for core
helpers. Its declared ./internal subpath exists only for Shipper workspace test/support code,
has no stability guarantee, may change or break at any time, and is not covered by
version-compatibility promises.
Shared issue-state store compatibility
Section titled “Shared issue-state store compatibility”The current issue-state store boundary is V20. V12 fences the persisted shapes from #2393, #2399, and #2401;
V13 additionally fences body acknowledgements and ordinary/note delivery-attempt semantics.
V14 adds durable automatic stage-failure attempts and explicit recovery semantics; V13 stores
advance losslessly with no recorded automatic stage failure. Upgrade all clients sharing the
store before a V14 writer opens it.
V15 fences one-use Blocked retry authorization, independent automatic mirror requests, and the
Blocked ownership boundary. Advancement never infers POST provenance, marker acceptance, or
resolution of an old post-started attempt.
V16 fences generalized workflow authorization, projection record v7 failure discovery metadata,
projection record v8 explicit legacy-repair readiness, and mirror request payload v3 generic group
identity. V1 failures without discovery metadata establish no hold; V2 Blocked requests retain their
original bytes, identity and tokens. The boundary is independent of individual record versions.
V17 fences target-specific V4 obligations, finite retry cycles, sparse mirror-work summaries and historical baselines. Initialization is a one-time resumable local pass with no GitHub reads. It preserves real uncertainty, consumed authorization tokens and ownership evidence; a baseline does not prove delivery, deletion or POST ownership. Clean background and display reads open no settled histories.
V18 fences faithful issue/comment content observations, accepted-edit evidence and read-only content verification. V19 fences queued mirror-content upgrade verification and its recovery semantics. V20 adds the source-aware blockedImportSweepPending metadata flag, invocation-specific delivery evidence and manual-recovery semantics. Lossless V18/V19 advancement preserves snapshots, tombstones, extensions, history prefixes, allocator reservations, stopped retry cycles and both upgrade checkpoints.
The first mirror-on repair performs one complete blocked-import sweep for affected V16–V19 stores, supported V1–V10 stores and unreconciled V11–V15 stores. Reconciled V11–V15 stores retain their exclusion. A current V20 store preserves its recorded flag. Repair durably queues eligible unclaimed Shipper-managed blocked issues before clearing the flag; incomplete discovery keeps it pending. Existing queued imports remain serviceable. Ordinary reads perform no remote discovery and never clear eligibility.
Supported V11, V12, V13, V14, V15, V16, V17, V18, and V19 stores advance automatically and one way, with an atomic metadata update that preserves workflow history, pending work, allocator reservations, and the reconciliation flag. No manual repair is needed for this advance. Untouched V11/V12/V13/V14/V15/V16/V17/V18/V19 snapshots and tombstones may remain beneath the current header; ordinary writes upgrade only the records being edited. Supported earlier headers still use their existing historical conversion rules. This advance adds neither historical-store support nor a downgrade path.
The store boundary is independent of individual record versions. Workflow event envelopes remain
v1. Projection evidence includes v1/v2 records (including projection record v2 for
accepted-but-not-applied evidence) and schema-3 workflow-comment posting records and schema-4 body acknowledgements. Projection v5 records position-scoped retry authorization;
v6 records explicit POST provenance or separately observed marker acceptance. Mirror-state payload
v2 requests have independent generations, retry deadlines, and completion records; v1 error debt
remains independent. Review payloads
have their own versions, including schema-3 feedback progress. A store-wide boundary fences
incompatible known payloads, strict delivery fields, projections, and pending-import sidecars even
when a snapshot gains no new fields.
Recovering from a stale reader
Section titled “Recovering from a stale reader”Independently installed CLI, Desktop, MCP/server, and daemon builds can share a store. An incompatible older build encountering the advanced store refuses it with the existing stale-reader message, stating the observed and supported schema versions. Restart or reconnect running clients and servers. If a freshly launched client or server remains incompatible, update the installed Shipper release or rebuild the source checkout before reconnecting. Preserve the issue-state store unchanged.
An older running reader refuses on its next checked access. An upgrade elsewhere does not terminate an old process or revoke an operation already past its compatibility check. A build on another machine is protected when it encounters the advanced store, rather than merely because another installation upgraded.
Contributor rule
Section titled “Contributor rule”Any change making saved records unreadable or unsafe for older builds must advance
ISSUE_STATE_SCHEMA_VERSION in the same change. This includes strict saved fields, known payload
changes, sidecars, delivery semantics, and recovery semantics. Verify lossless advancement of
supported stores and stale-reader refusal before parsing or repair. Never reuse a shipped boundary
number for a different compatibility rulebook.
Unknown-kind tolerance is narrower than store compatibility. A current reader skips an event only
when its envelope is otherwise valid and its string kind is unknown to that build. It warns once
per event-store directory per process, naming the directory and stating that records from a newer
build were skipped. Known records around the skipped record continue to read normally. This does
not authorize incompatible known payloads, strict delivery fields, projections, ignored sidecars,
malformed JSON, missing envelope fields, unknown entry types, or unsupported record versions.
Delivery evidence and recovery
Section titled “Delivery evidence and recovery”Delivery intent uses projection record v3 (post-ready, post-started, post-rejected). Successful
fitted-body acknowledgements use projection record v4 with a validated receipt and SHA-256 body hash.
V11, V12, V13, V14, and V15 advancement retains adoption evidence, receipts, event-history bytes, and unresolved
attempts. It does not invent readiness for legacy undelivered groups. The historical V13/v4 delivery evidence
boundary protected expanded ordinary-comment and note attempt semantics from older writers that
recognized v3 syntax but could mishandle its meaning. V15 adds the authorization, request, and
ownership fence. Newer stores refuse older readers before incompatible parsing, mutation, or repair.
Upgrade all independently installed clients before introducing V20 recovery evidence into a shared store. Upgrade CLI, Desktop, and MCP clients sharing the store to compatible builds. Do not delete or downgrade persisted evidence to work around a compatibility refusal.
Successful historical ordinary comments with no body hash remain delivered. Blocked ownership requires a currently validated marker for a known local Blocked group or explicit POST provenance for the same comment ID. A heading, matching body, account, saved ID, or hash alone is not proof. Marker acceptance records safe delivery recovery; that saved timestamp alone never grants later PATCH or DELETE rights after the remote marker disappears. Unmarked legacy linkages remain ambiguous and unverifiable copies may require manual removal.
Recovery covers stage comments, notes, PR flake comments, Unblocked and Blocked comments.
Completed explicit repair posts wanted legacy work once when no attributable copy is found and no
concrete ambiguous-send evidence exists. Superseded or retracted absent work is retired without
posting. Closure alone does not retire historical comments, including post-closure notes.
Legacy work without an attempt token directs the operator to shipper issue reconcile --repair.
Uncertain delivery retains automatic duplicate protection: another send cannot be promised automatically.
Use shipper issue recover-comment S#42 to inspect without posting, then authorize one exact
current token with all four options:
shipper issue recover-comment S#42 --group <id> --attempt <token> --retry --accept-duplicate-riskThe earlier attempt may already have posted. Authorizing another attempt can create a duplicate comment.
A found attributable copy wins over authorization. Incomplete, unavailable, malformed or exhausted searches consume no token and never establish absence. Saved authorization, recovered receipt identity, verified body acknowledgement, retirement and cleanup are separate outcomes. Ineffective PATCH and residual cleanup remain pending. Obsolete uncertain work is retired only after evidence or authorization. Routine convergence retains conclusive absence for its matching attempt. Transient unavailable discovery retries at the next due ordinary synchronization without requiring inspection or repair. Explicit repair reuses a completed catalog per actual issue/PR parent and directly validates selected identities before mutation.
shipper issue recover-blocked-comment remains a Blocked-restricted compatibility wrapper using
the same flags and engine. Blocked ownership and slot ordering remain stricter: saved ID, heading or
body alone never establishes ownership. Store-only policy refuses GitHub recovery without writes.
A live stage defers authorization without recording it; rerun after the stage finishes.
Each delivery target permits six failed passes with 1, 2, 4, 8 and 16-second backoff. GitHub holds consume no failure and defer to their deadline. Definitive permission or validation rejection stops immediately. Stopped work remains undelivered with its cause and safest recovery action. Uncertain POSTs retry safe discovery only; another POST requires an exact one-use authorization.
Plain repair may service a stopped target once without resetting its automatic budget. An unsuccessful manual pass leaves it stopped with its prior attempt count; timers and priority changes do not restart that cycle. Active GitHub holds remain in force, including after a priority change. Repair never authorizes an uncertain repost.
A corrupt derived pending-work index stays visible as stopped, non-due work for that issue. Status, issue lists, the desktop board and catch-up remain usable for healthy peers. Explicit repair reconstructs indexes from authoritative local records and removes orphan indexes. Malformed authoritative records or history require correction and remain unchanged.
After successful authorized recovery, pending status updates immediately, before ordinary synchronization. A recovered receipt proves identity; completion still requires the wanted body and required cleanup to be verified. Newer generations, unrelated issue delivery and residual size-limit debt remain pending.
Messaging distinguishes “GitHub delivery held before launch” from “GitHub rejected delivery; automatic retries stopped”. Unknown POST delivery stops without claiming rejection. Causes appear once per target. Authorization-required work explains the exact group/token command instead of promising automatic resumption. Duplicate-risk warnings apply only to unresolved attempted POSTs, never proven-unsent/rejected posts, completed/retired work or accepted-edit observation. Desktop presents stopped delivery as attention, including when local priority was saved successfully.
Local success during a running stage
Section titled “Local success during a running stage”Notes, CLI and desktop priority changes, and explicit mirror synchronization save locally while a stage owns the issue. Automatically eligible work reports:
Saved locally; GitHub delivery pending while a stage owns this issue. Delivery resumes at the next ordinary synchronization after the stage finishes.
Remote delivery still uses the issue lock. Lock release performs no GitHub work and never waits. The next ordinary issue synchronization services due work. An existing daemon or desktop runtime can deliver after a hold, including with Auto Ship disabled. Current store-only policy cancels automatic requests without GitHub operations. Completion consumes only the handled generation, preserving newer requests and independent pending-error debt. Durable note identities prevent duplicate posts.
Historical breaking changes live in the root CHANGELOG.md and in the repository’s release tags.
Those records describe what changed over time while the live docs continue to describe the current
supported workflow.
Issue-lock release is network-free. Foreground stage completion makes one due pass outside release and returns without sleeping. Stopped delivery remains visibly undelivered until an applicable explicit recovery action.
CLI-only pending work survives process exit. Run shipper issue reconcile --repair to service it now; repair also respects GitHub holds. Plain repair comes before duplicate-risk authorization when sufficient. No new CLI background process is required.