Live verification showed dropped-CI PRs report mergeable=null and
mergeable_state=unknown indefinitely: the stuck merge-ref computation is
the same failure that dropped their CI, and close/reopen is what
un-sticks it. The pending-mergeability skip therefore made the primary
repair population permanently unsweepable (three real dropped PRs skipped
across three consecutive sweeps). Keep skipping computed conflicts; a
not-yet-computed conflict costs at most one budgeted re-fire.
* feat(cron): add unattended-run preamble to isolated agent turns
Isolated cron and hook agent turns received only the job tag, message,
and time line — no operating contract for unattended execution. Runs
ended in questions, plans, or bare acknowledgements (the runtime even
re-prompts once for interim acks). Append a static per-class preamble:
the final reply is the deliverable, HEARTBEAT_OK when idle, plain
failure statements. Trusted jobs additionally defer to the job's own
instructions on conflict and learn removal-only self-cleanup;
external-hook runs get only the common core so fenced webhook content
cannot use an override clause or a destructive affordance advertised in
the trusted suffix. Free-form job names stay out for the same reason.
* feat(cron): teach watcher authoring rules in the cron tool description
Trigger-script guidance covered only the return contract. Add the
operating rules that keep watchers trustworthy: fire on every
actionable state including failures (success-only watchers go silent
when broken), dedupe via returned state, keep scripts read-only with
actions in the payload, and make the fired message self-contained.
* docs: add The main session concept page and cross-links
* docs: precise memory-priming wording on the main-session page
* docs: update Control UI sidebar description to the Home and zones model
* ci: add hourly PR CI sweeper for dropped pull_request runs
Fresh PRs race GitHub's merge-ref computation: the open-event CI run can
drop entirely or be created as an un-rerunnable startup_failure (~10-16
runs daily). The sweeper lists recently updated open PRs hourly, finds
heads whose only pull_request-event CI runs are startup failures (or
missing), and re-fires the event by close/reopen with the Barnacle app
token (GITHUB_TOKEN events would not trigger workflows).
Safety: 10-minute quiet window, 24h lookback, skips drafts, merge
conflicts, pending mergeability, and auto-merge PRs (close cancels
auto-merge); revalidates state, head, and CI attachment immediately
before mutating; per-PR budget of two sweeper closes and a per-sweep cap
of ten; reopen-on-unknown ownership so a stranded close (silent) always
loses to a spurious reopen (visible); manual dispatch supports dry_run.
Accepted tradeoffs are documented inline: shared-SHA PR topologies can
mask a dropped run (skip-only miss; run.pull_requests matching would
break fork PRs), and app-auth failover at worst doubles the close budget.
* test(ci): exercise pr-ci-sweeper runner with a faked client
* fix(test): lint-clean pr-ci-sweeper runner fakes
* refactor(ui): split lobster-pet into look/plans/element modules
Move existing behavior along appearance and seeded visit-planning ownership seams without changing runtime behavior.
Extract only the bounded logo stand-in, WebAudio chirp, and pure render-template helpers while keeping the state machine in the element. Remove the grandfathered max-lines suppression and baseline entry.
* style(ui): format lobster-pet split modules
* fix(ui): keep lobster split internals unexported, refresh i18n raw-copy baseline
knip flags the split's newly exported internals (strangerLookFor,
renderCrabSvg, lobsterPetSpriteStyle, LobsterPasserKind) — they have no
external consumers; the html-text raw-copy baseline is file-keyed, so the
sprite z/Z markup moving into lobster-pet-look.ts needs a regen.
* fix(ui): satisfy lint for the lobster-pet split (param reassign, max-lines)
* fix(ui): keep moved act-profile internals unexported
* fix(reef): stop leaking the inbox loop across channel crash restarts
* fix(reef): move channel lifecycle helper to its own module for lint/deadcode gates
* test(channels): mock core turn dispatch for delivery traces
* test(telegram): scope bot tests to a fresh state dir
Assembled turns resolve session/agent bindings through the state DB; an
ambient operator Codex binding fails generation reclaim and drops the turn,
adding misleading noise to reply-wait timeouts.
* test(telegram): drive bot turn tests through a prepared-dispatch mock
Core's turn lifecycle hard-wires its own provider dispatcher for assembled
turns, so the harness's injected dispatcher never fires and every reply-wait
turn test hangs to timeout locally. Convert resolved turns to prepared ones
that dispatch through the harness mock, restoring the file's original
authored contract.
* test(telegram): mark trace token as synthetic
* test(telegram): centralize trace dispatch mocks
* test(telegram): preserve assembled dispatch wiring
* test(telegram): guard trace dispatch seam
* test(telegram): avoid duplicate turn lifecycle
* fix(scripts): restore Testbox lease claims to the originating repo after delegated runs
Delegated Blacksmith Testbox runs execute from throwaway sparse-sync checkouts, so Crabbox stamps retained lease claims with that temporary cwd. Restore only claims still pointing at the child checkout after the run on both success and failure, preserving foreign claims and every other field. This repairs the post-run artifact instead of weakening the pre-run ownership guard.
* fix(scripts): restore claims for delegated runs that create retained leases
* fix(macos): harden Quick Chat capture — drop AX-role text, restore bar after area capture, guard overlays post-permission
* chore(i18n): refresh native inventory line numbers after capture hardening