* fix(slack): terminalize a progress card detached by a concurrent mention
Rapid mentions in one Slack conversation fire the draft-message boundary
notifier, which calls forceNewMessage and clears the draft stream's message
identity so later output lands below the human message. The already-posted
Working card survives in Slack but becomes unreachable: finalize(), clear(),
and the drop-on-failed-finalize fallback all key on the stream's current
identity, so the card stays at Working forever.
Retain messages the draft stream abandons while un-finalized, expose
dropDetachedMessages(), and drain it from the card's finalize path so final
delivery, error closeout, and turn rotation all terminalize. Also implement
onQueuedFollowupSettled so a queued turn draining after its dispatch already
returned cannot leave a card in Working state. Both cleanups are gated on the
session-card mode: partial/append previews hold streamed assistant text the
human already replied to and must stay visible.
* fix(slack): drain detached cards appended during an in-flight delete
The detached-card drain snapshotted its queue, so a human message routed
synchronously through the conversation boundary during an awaited delete
appended a card the same drain would never remove. The silent-turn closeout
also dropped before its clear(), leaving that window unowned.
Drain until the queue is stable and make the drain the last act on the silent
exit path, so a card detached mid-cleanup still reaches removal.
* feat(deploy): add experimental Cloudflare template
* fix(deploy): keep container SSH debug access opt-in
* fix(deploy): satisfy scripts tsgo lane and model wrangler entrypoint in knip
* fix(deploy): model wrangler-consumed exports and isolated dependency in knip
The Worker default export and Durable Object class are instantiated by
wrangler from wrangler.jsonc, and @cloudflare/containers lives in the
template's isolated package.json — modeled per the deadcode checks' own
guidance rather than root-manifest changes.
* docs(deploy): align SSH bootstrap flow with the disabled-by-default policy
On a pristine profile, onboarding/doctor printed "Auto-migrated legacy
state: Recorded Matrix inbound dedupe migration completion (0 SQLite
roots, 0 JSON roots scanned)" even though nothing was migrated. Keep
the durable empty-scan receipt (it still prevents later historical
databases from being opened) but only emit the user-visible change line
when at least one SQLite/JSON root was scanned.
* fix(ui): preserve archive state across stale refreshes
* fix(ui): retain archive state across navigation
* fix(ui): ignore stale archive events
* fix(ui): scope archive state to session identity
* fix(ui): require session identity for presentation metadata
* fix(ui): require exact archive identity
* refactor(plugins): retire deactivate hook alias
* refactor(plugin-sdk): prune retired facade exports
* test(logging): isolate logger test controls
* refactor(logging): internalize file transport controls
* test(plugin-sdk): preserve retired facade coverage
* test(auto-reply): remove stale diagnostic imports
* refactor(logging): delete dead config-read guard
shouldSkipMutatingLoggingConfigRead had no production caller even on main;
it survived the dead-export scan only via logger's testApi re-export. The
test-isolation commit removed that mask, exposing the fossil. Delete the
guard, its test-only re-export, its mock entry, and its dedicated test file.
* refactor(plugin-sdk): retire due compatibility subpaths
* test(plugin-sdk): type group policy predicates
* refactor(plugin-sdk): split removed subpath records
* refactor(secrets): remove retired collector barrel
* test(plugin-sdk): tighten wildcard surface pin
* refactor(plugin-sdk): retire matrix facade metadata
* style(plugin-sdk): format facade metadata
* fix(ci): load channel setup contracts from source
Repair the main-owned regression from 99d662473c (Peter Steinberger): the new env-contract test could consume stale ignored dist metadata instead of the checked-in plugin declaration.
* test(plugin-sdk): refresh API baseline after rebase
* feat(linux): suspend the local gateway across host sleep via logind
Mirror the macOS sleep cycle in the Tauri companion: a logind
PrepareForSleep listener with a delay inhibitor best-effort prepares a
local gateway suspension before sleep and resumes it on wake with a
reconnect nudge and bounded retries; leases are route-bound, always
cleared on wake, and late prepare responses resume immediately.
* fix(linux): keep the sleep listener alive when inhibitor re-acquire fails
* fix(linux): activate the driver for sleep cycles and bound driver-side sleep RPCs
Sleep cycles temporarily unpark the gateway driver so prepare/resume work
without the Quick Chat window; suspend RPCs carry a 3s driver-side budget
that recycles a hung socket instead of starving wake retries; a mock-logind
integration test exercises the Linux listener end to end.
* fix(linux): count overlapping sleep cycles instead of a boolean flag
An older wake task ending late cleared the shared activation flag and
parked the driver mid-cycle; a saturating depth counter keeps the driver
active until the last cycle ends.
* fix(linux): gate sleep-cycle activation on loopback routes and never block wake on logind
Remote or unconfigured routes no longer activate the driver during
sleep, the paired end hook runs only for cycles that began, and wake
recovery is spawned before the inhibitor re-acquire so a slow logind
cannot delay reconnect/resume.