Commit Graph

15919 Commits

Author SHA1 Message Date
Peter Steinberger a2b4c4e17d refactor(signal): trim dead exports (#107217) 2026-07-13 23:43:46 -07:00
Peter Steinberger 6625ea92f0 refactor(codex): evaluate startup deadlines first 2026-07-13 23:40:39 -07:00
Peter Steinberger c953d8ec41 fix(codex): gate startup phases before deadlines 2026-07-13 23:40:39 -07:00
Peter Steinberger cbb5e97dd4 refactor(whatsapp): trim internal exports (#107206) 2026-07-13 23:23:11 -07:00
Peter Steinberger 21382b3755 refactor(qqbot): use silk-wasm buffer inputs 2026-07-13 23:19:54 -07:00
Peter Steinberger d9d3d4b9e3 refactor(matrix): use fake-indexeddb prototype 2026-07-13 23:11:49 -07:00
Peter Steinberger 834810b3d6 refactor(imessage): trim internal exports (#107196)
* refactor(imessage): trim internal exports

* test(imessage): type inbound dispatch mock
2026-07-13 23:05:24 -07:00
ruizcrp 40cf6c51b3 feat(workboard): add manual card movement surfaces (#96554)
Adds consistent manual Workboard movement across CLI, slash commands, and agent tools while preserving operator authority and agent claim isolation.

Co-authored-by: Ross I4JU <ross@i4ju.ch>
2026-07-13 23:01:06 -07:00
Peter Steinberger 83512e1986 refactor(matrix): use native media types 2026-07-13 22:54:26 -07:00
Peter Steinberger 304beb22e1 refactor(concurrency): use p-map skip results 2026-07-13 22:43:26 -07:00
Wynne668 73cb408565 fix(google-meet): reject nondecimal transcript cursors (#106384)
* fix(google-meet): reject nondecimal transcript cursors

Use parseStrictNonNegativeInteger for --since validation so hex,
exponent, and fractional spellings are rejected at the CLI boundary
instead of silently coercing to different cursor offsets.

Remove the redundant file header comment to stay within the
oversized-file LOC ratchet.

* test(google-meet): harden transcript cursor coverage

* style(google-meet): format cursor tests

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 22:28:18 -07:00
zw-xysk 2f11d8752d fix(slack): add 30s timeout to read-mode action API calls (#107103)
* fix(slack): add 30s timeout to read-mode action API calls

* fix(slack): reuse bounded lookup client

* test(slack): use review-safe token fixtures

* test(slack): restore concise token fixtures

* test(slack): mark new auth fixture as placeholder

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 22:26:02 -07:00
Peter Steinberger d8d2f83cc1 feat(terminal): open Codex/Claude catalog sessions in a terminal on their owning host
Catalog session rows (sidebar context menu + click), the built-in viewer
header, and a new "Open Codex/Claude sessions in" preference can launch the
native CLI (codex resume / claude --resume) in the operator terminal on the
machine that owns the session.

- Gateway-local sessions spawn through the existing terminal launch policy
  (sandbox/enabled gates preserved) with the resume command in the session cwd.
- Paired-node sessions run through a new seq-ordered node PTY relay: a
  duplex node-host command streams PTY output via node.invoke.progress and
  receives keystrokes/resize via a new node.invoke.input event, behind the
  unchanged terminal.* client protocol (TerminalSessionManager gains a backend
  abstraction; node relay reuses the streaming-invoke controller).
- Owner boundary: each plugin owns its resume command and builds argv from a
  validated thread id; the gateway routes node opens through the node command
  allowlist and plugin invoke policy (no advertisement-only trust), and nodes
  re-verify session eligibility before spawning.
- UI setting catalogOpenTarget + canOpenTerminal capability gate every entry
  point; capability requires the owning host to actually have the CLI.

Node PATH is normalized before command-availability probes, Windows .cmd/.bat
shims spawn via ComSpec, and catalog terminal opens reattach persisted tabs
before opening the new tab.
2026-07-13 22:20:50 -07:00
Peter Steinberger bdc91cb4af refactor(memory-wiki): trim internal exports (#107157) 2026-07-13 22:19:01 -07:00
yyj-xydt 429bf9383e fix(workboard): avoid timing leaks in claim authorization (#104259)
* test(workboard): cover claim token lifecycle auth

* fix(workboard): compare claim tokens safely

Co-authored-by: 0668001099 <yang.yujie1@xydigit.com>

* refactor(workboard): centralize claim identity checks

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 22:12:45 -07:00
Vincent Koc ee6d6e7e78 refactor(extensions): remove dead local exports (#107146) 2026-07-14 13:09:20 +08:00
Peter Steinberger 9c2dc92dd8 refactor(msteams): trim internal exports (#107148) 2026-07-13 22:01:56 -07:00
Peter Steinberger 05fb55eb7b feat: discover OpenCode and Pi sessions on paired nodes (#106941)
* feat(sessions): add opencode and pi catalogs

* fix(sessions): satisfy catalog lint

* fix(sessions): validate pi storage paths

* fix(sessions): index growing pi transcripts

* refactor(sessions): split pi path resolution

* docs(sessions): refresh catalog map

* refactor(sessions): privatize pi catalog internals

* fix(sessions): validate node catalog payloads

* fix(sessions): harden external catalog discovery

* fix(sessions): normalize catalog transcript data

* refactor(gateway): keep node scope gate compact

* fix(opencode): reject option-like session ids

* fix(sessions): align external id validation
2026-07-13 21:45:53 -07:00
Peter Steinberger 111b3a157e refactor(codex): use native SemVer floor comparison 2026-07-13 21:42:23 -07:00
Peter Steinberger 1dc9d47130 refactor(voice-call): remove dead internal exports (#107130) 2026-07-13 21:42:11 -07:00
mushuiyu886 ef25cefc8e fix(onepassword): validate audit limit strictly (#106926)
* fix(onepassword): validate audit limit strictly

* test(onepassword): strengthen audit limit coverage

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 21:37:07 -07:00
Peter Steinberger 0ecbbe2382 fix(workboard): keep dispatch inside caller workspace authority (#107087)
* fix(workboard): inherit caller workspace authority

* docs(plugin-sdk): refresh API baseline

* fix(workboard): pin restricted worker authority

* fix(workboard): avoid host git for restricted dispatch

* refactor(worktrees): extract owner matching

* refactor(workboard): reuse sdk workspace helpers

* fix(workboard): narrow cleanup owner

* refactor(workboard): clarify claim value handling

* fix(workboard): inherit caller workspace authority

* test(worktrees): use managed temp directories

* chore: keep release notes in PR body

* fix(workboard): keep internal authority helpers private
2026-07-13 21:36:26 -07:00
Peter Steinberger 80399ed19b refactor(matrix): trim internal exports (#107126) 2026-07-13 21:33:55 -07:00
Peter Steinberger 37c7de0148 refactor(ai): remove redundant tool argument finalization 2026-07-13 21:17:38 -07:00
Peter Steinberger 27f2a45c54 fix(onboarding): harden live inference handoff (#107041)
* fix(onboarding): harden live inference handoff

* fix(crestodian): preserve auto runtime probes

* fix(ci): restore current main lint gates
2026-07-13 21:15:36 -07:00
Peter Steinberger 689edddd34 fix(mattermost): restore strict test lint after refactor (#107079)
* test(mattermost): satisfy strict lint contracts

* test(mattermost): type partial response fixture
2026-07-13 21:09:35 -07:00
Peter Steinberger c853064a42 refactor(microsoft): simplify Edge TTS output staging 2026-07-13 21:03:51 -07:00
Peter Steinberger 8d465d71b5 fix(channels): progress drafts only for long tasks, with the model's own preamble as the status headline (#106026)
* fix(channels): time-gate progress drafts and defer narration until visible

Progress drafts started immediately on the second work event, so the 5s
initial delay never filtered small fast tasks and Discord showed narrated
status for turns that finish in seconds. The gate is now purely time-based
(explicit startNow paths like approvals/patches are unchanged), and the
progress narrator no longer spends utility-model completions before the
channel draft is visible - notes buffer so the first visible narration has
full context.

Surface: src/channels/streaming.ts gate, src/auto-reply/reply/progress-narrator.ts,
Discord draft-preview wiring; test updates across discord/matrix/msteams/slack.

Refs #105872

* feat(channels): model-preamble status headline for progress drafts

In progress mode the draft's status line is now the model's own typed pre-tool
preamble whenever it is fresh (always on, no new config); utility-model
narration fills the slot only when the model has been quiet for ~20s or emits
no preamble. Preambles never start the draft early - the time gate still owns
the small-vs-big decision - and narration generation is suppressed while a
fresh preamble exists, saving utility calls. Discord and Telegram render the
headline; the opt-in streaming.progress.commentary lane and its receipt
counters are unchanged.

Refs #105872

* refactor(channels): split status-text and telegram preview helpers to honor the LOC ratchet

The LOC ratchet forbids raising baseline entries, so the headline feature's
growth is paid for with clean splits: reasoning/commentary text normalization
moves to src/channels/progress-draft-status-text.ts, Telegram progress preview
rendering to extensions/telegram/src/progress-draft-preview.ts, and small
ownership moves (formatCompactionModelRef, resolveFollowupAbortSignal, shared
CLI preamble gate, Discord preamble item-event handling) shrink the runners
back under their pins. Baseline entries lowered to exact new counts; the
compositor entry is removed (424 lines, under the 500 ceiling).

Refs #105872

* test(auto-reply): add resolveFollowupAbortSignal to the queue mock factory

The explicit ./queue.js vi.mock factory must export every binding prod touches;
the relocated resolveFollowupAbortSignal was missing and failed the whole
followup-runner suite.

Refs #105872

* fix(channels): sanitize preamble headlines and retry skipped narration

Review findings: preamble headlines now strip inline delivery directives and
reject silent-control tokens (NO_REPLY) before rendering, sharing the
commentary sanitizer; rejected input keeps the previous valid headline. The
narrator schedules cancellation-aware retries when a run is skipped for draft
invisibility or preamble freshness, so single long tool calls still narrate
and the ~20s utility filler fires without needing another event. Silent
preambles no longer stamp freshness or add narration notes.

Refs #105872

* fix(channels): bound narrator visibility polling and gate Telegram headline mode on accepted preambles

Visibility retries stop after 30 one-second attempts (turn completion has no
narrator disposal signal) and re-arm on new activity; Telegram derives its
headline-rendering state from the compositor's sanitized headline instead of
raw payload text, so directive-only or NO_REPLY preambles keep structured
tool-line rendering. Docs scope the preamble headline to Discord and Telegram.

Refs #105872

* fix(telegram): read headline state from the compositor at render time

The progressHeadlineActive mirror flag was set after pushPreambleHeadline had
already rendered, so the first valid preamble arriving after the draft opened
rendered through the structured-line path and the headline never appeared
until the next event. The renderer and formatLine now read the compositor's
sanitized hasStatusHeadline directly and the mirror flag is deleted; adds an
ordering regression test. LOC baseline lowered to the exact new count.

Refs #105872

* fix(channels): let the opt-in commentary lane own preambles and scope narration docs to Discord

With streaming.progress.commentary enabled, the status headline would replace
the documented interleaved 💬 lines for any turn with a preamble (the exact
event the lane consumes). The compositor headline now declines when the
commentary lane is enabled, preserving that lane's shipped shape, and docs
state the utility-model filler is Discord-only today (Telegram's headline is
preamble-only; it has no narrator wiring).

Refs #105872

* fix(msteams): cancel the pending progress gate at finalize

With the purely time-based gate, every fast Teams progress turn leaves a
pending 5s start timer; the SDK resets its stream id on close, so a late
timer fired renderInformativeUpdate against the closed stream and posted a
stale working card below the final answer. finalize() now cancels the gate
and the informative renderer refuses to run once final text is queued.

Refs #105872

* docs(channels): record the headline-vs-commentary ownership decision inline

Refs #105872

* style: oxfmt the late review-fix rounds

Four files from the final review-fix commits were never oxfmt-formatted and
failed the shared CI formatting step; baseline lowered for the one-line
telegram shrink.

Refs #105872

* fix(channels): harden progress draft lifecycle

* fix(channels): refresh repeated preamble items

* fix(plugin-sdk): expose progress lifecycle options

* style(auto-reply): simplify narrator reset

* docs(channels): refresh progress draft docs map

* fix(auto-reply): clear queued narrator request context

* fix(discord): cancel delayed progress gate at final

* docs: refresh plugin sdk api baseline
2026-07-13 20:55:44 -07:00
Peter Steinberger 53f6212488 test(mattermost): fix slash response mock type (#107084) 2026-07-13 20:48:34 -07:00
Peter Steinberger c19b7d2823 refactor(mattermost): trim internal exports (#107062) 2026-07-13 20:27:52 -07:00
Peter Steinberger 604eb6af2d refactor(concurrency): use native p-limit APIs 2026-07-13 20:23:00 -07:00
Peter Steinberger 4da0eb19c5 fix(state): converge legacy startup migrations (#107002)
* fix(state): converge legacy startup migrations

Co-authored-by: Eva <eva@100yen.org>

* refactor(state): split legacy migration helpers

* fix(memory): persist legacy source acknowledgements

* fix(state): remove stale migration imports

* fix(memory): recognize numbered migration archives

* fix(matrix): downgrade archived migration residue

* fix(memory): satisfy migration lint

---------

Co-authored-by: Eva <eva@100yen.org>
2026-07-13 20:05:24 -07:00
Peter Steinberger 069616f33b feat(discord): notify agents of voice participant changes (#107004)
* feat(plugin-sdk): support keyed system event upserts

* feat(discord): notify agents of voice participant changes

* refactor(plugin-sdk): consolidate system event replacement

* fix(discord): keep voice listener dependencies acyclic

* chore: keep release changelog out of PR
2026-07-13 20:03:18 -07:00
Peter Steinberger 877af700bf feat(codex): continue paired-node Codex catalog sessions from the Control UI (#106927)
* feat(codex): continue paired-node Codex catalog sessions from the Control UI

Codex catalog rows on paired nodes were view-only. Node rows are now
continuable when the node advertises and permits the codex threads.list,
thread.turns.list, and cli.session.resume commands. Continue adopts the
session into a locked codex OpenClaw session (deterministic
harness:codex:node-session key, bounded native-history import, two-phase
initializing marker) and installs a webchat conversation binding
(codex-cli-node-session) through the new generic
bindPluginSessionConversation seam with attempt-ID guarded rollback, so
each web turn runs codex exec resume on the owning node via the existing
inbound_claim path. Local continue/archive semantics are unchanged;
archived rows are no longer offered as continuable.

* fix(plugins): serialize plugin session binds per session

Review P2: the bind rollback checked the attempt id and then awaited the
unbind, so a concurrent Continue could install a newer binding between the
two and lose it to the older attempt's rollback. All session binds for one
session key now queue through an in-process tail, so a failing attempt can
only ever roll back its own binding; the attempt-id guard stays as defense
against out-of-band rebinds.

* refactor(codex): extract node-continue and session-bind modules for the LOC ratchet

Pure movement to satisfy the changed-file TypeScript size ratchet: the
paired-node continue flow moves to session-catalog-node-continue.ts and
session-catalog-node-adoption.ts, catalog paging/parsing helpers to
session-catalog-parsing.ts, the Control UI session-bind seam to
session-conversation-binding.ts (+ session-key helpers), and the internal
conversation-id/channel-prefix helpers to utils. transcript-mirror.ts is
restored to main byte-for-byte; the node history builder constructs a plain
CodexThread (only id is required) instead of widening signatures.

* fix(plugins): satisfy preserve-caught-error in the session-bind rollback

* fix(codex): gate node continue on operator.admin and resume by CLI session id

Second review round: (1) bound node turns pass canMutateCodexHost only for
owners/admins, while sessions.catalog.continue is operator.write — a
write-scoped Control UI client could adopt a node session whose every turn
would then be rejected. The gateway now forwards the caller's scopes to the
provider (SessionCatalogContinueProviderParams.clientScopes) and codex fails
node continues closed without operator.admin, before the dedupe join so a
non-admin cannot ride an admin's in-flight operation. (2) The node binding
stored the app-server threadId, but codex exec resume takes the CLI session
id and forked threads share a session tree where the two differ; the binding
now prefers record.sessionId.

* fix(codex): defer node-session restore until the binding is durable

Third review round: continuing an archived adopted node session unarchived
it before the gateway installed the conversation binding, so a failed bind
left a visible session with no node routing. The unarchive now rides
afterConversationBound; finalizeNodeAdoptedSession already covers both the
initializing and finalized marker states, so the eager restore helper is
deleted.
2026-07-13 19:54:31 -07:00
Peter Steinberger 7f73f6e66e test(qa-lab): refresh CLI dispatch expectations (#107018) 2026-07-13 19:36:17 -07:00
Peter Steinberger 44fcbc612d refactor(qa-lab): trim dead export surface (#107016)
* refactor(qa-lab): narrow report and config exports

* refactor(qa-lab): keep live test seams private

* refactor(qa-lab): remove dead runtime wrappers

* chore(deadcode): refresh QA Lab export baseline
2026-07-13 19:32:13 -07:00
Peter Steinberger 6e067f7662 test: restore moving-main quality gates (#106972)
* test(agents): preserve caught abort cause

* refactor(browser): privatize route handler type

* test(lint): cover browser route override
2026-07-13 19:06:30 -07:00
Peter Steinberger 25a18b2d8e refactor(bonjour): use native ciao platform handling 2026-07-13 19:04:16 -07:00
Peter Steinberger b828692089 refactor(webhooks): use native Zod schemas 2026-07-13 18:50:14 -07:00
Peter Steinberger 56e9d3b05f refactor(browser): scope async route lint exception 2026-07-13 18:37:46 -07:00
Peter Steinberger b9c4815403 refactor(config): add canonical group-policy scope-tree resolver and migrate the first six channels (#106846)
* feat(config): add canonical group-policy scope-tree resolver

* chore(plugin-sdk): refresh API baseline hash for scope-tree exports

* refactor(channels): migrate googlechat, imessage, and whatsapp group policy onto the scope tree

* chore(plugin-sdk): refresh API baseline hash for groups scope-tree builder

* refactor(channels): migrate line, qqbot, and mattermost group policy onto the scope tree

* chore(plugin-sdk): refresh API baseline hash for case-insensitive scope key helper

* chore(plugin-sdk): refresh API baseline hash after rebase onto current main

* chore(plugin-sdk): refresh API baseline hash after rebase

* chore(plugin-sdk): refresh API baseline hash after rebase

* chore(plugin-sdk): refresh API baseline hash after rebase
2026-07-13 18:24:52 -07:00
Peter Steinberger 3442825e6b refactor(browser): use Express 5 async routes 2026-07-13 18:21:52 -07:00
sunlit-deng 7aa1aacb8e fix(reef): prevent oversized guard responses from consuming memory (#106439)
* fix(reef): bound guard provider response reads

* test(reef): strengthen guard response bound proof

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 18:02:11 -07:00
Marcus Castro 0934c445d3 refactor(whatsapp): use retryAsync for outbound delivery retries (#105579)
* refactor(whatsapp): reuse shared outbound retry runtime

* refactor(whatsapp): narrow outbound retry classification

* refactor(whatsapp): remove obsolete sleep export
2026-07-13 21:19:32 -03:00
zw-xysk bdd060a40c fix(slack): add 30s timeout to directory client API calls (#106643)
* fix(slack): add 30s timeout to directory client API calls

* fix(slack): bound directory lookups

* fix(slack): reject delayed lookup retries

* fix(slack): preserve directory timeout contract

* fix(slack): keep lookup policy internal

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 17:07:41 -07:00
Peter Steinberger f693ac1b65 refactor(config): share canonical deep merge 2026-07-13 17:06:26 -07:00
Leon-SK668 5864fa2dbf fix(onepassword): preserve Unicode in audit reason truncation (#106424)
* fix(onepassword): preserve Unicode in audit reason truncation

* test(onepassword): strengthen Unicode audit boundary proof

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 17:01:14 -07:00
Vincent Koc cb705226ff test(telegram): avoid promise executor return (#106900) 2026-07-14 07:38:48 +08:00
Peter Steinberger d361b4ccb8 feat(reef): headless openclaw reef CLI for agent-driven registration and pairing
Adds a non-interactive command surface (openclaw reef register|status|friend code|request|list|remove) so an agent can claim a handle and manage guarded friendships when its owner asks, without the interactive wizard. --json emits machine-readable output for automation. Registration is crash-safe and idempotent: guard defaults are provider-coupled, the full config is validated before the single-use magic-link token is consumed, a duplicate-handle claim recovers by proving key ownership and reconciling the relay's request policy, the exchanged session is cached scoped to relay+email (never printed) so reruns recover, one state dir is pinned to one identity, and friend removal revokes both the pin and the allowlist entry. Manifest gains commandAliases/onCommands so the CLI resolves; docs cover the agent-driven path.
2026-07-13 16:23:13 -07:00
Peter Steinberger 33f4856875 refactor(telegram): privatize pure helper surface (#106892) 2026-07-14 00:21:51 +01:00