Commit Graph

15830 Commits

Author SHA1 Message Date
Shakker
ef6c44f10b fix: route ClickClack replies through runtime policy 2026-07-13 19:57:34 +01:00
Shakker
9b5cd4cd0d fix: reconcile durable ClickClack sends 2026-07-13 19:57:34 +01:00
Shakker
0039c066c1 feat: add ClickClack nonce recovery lookups 2026-07-13 19:57:34 +01:00
Jacqueline Henriksen
ba00bd7bb4 fix: deliver ClickClack media and configurable model replies 2026-07-13 19:57:34 +01:00
Peter Steinberger
e3c5821d98 feat(ui): redesign Channels page with guided channel setup wizard (#106469)
* feat(ui): redesign Channels page with guided channel setup wizard

Adds wizard.start flow=channels gateway RPC (additive protocol change) that
drives the shared channel-setup wizard (openclaw channels add) over the
session step protocol. Control UI Channels page becomes a card hub with
plugin-art covers, guided per-channel setup modal (WhatsApp QR pairing via
web.login.*, BotFather/Slack/Discord helper links), and a detail overlay
hosting the full schema config form.

* test(ui): cover channel wizard controller; refresh channels view test props

* chore(mock): use non-token-shaped wizard placeholder

* test(gateway): scanner-safe auth local in channels wizard test

* fix(ui): cancel gateway wizard session on channels page disconnect

* fix(ui): adopt browse-all channel pick and guard dirty config before setup

* fix(ui): cancel gateway session created by a stale wizard.start

* fix(ui): adopt multiselect channel picks; drop redundant String()

* fix(ui): track all wizard-adopted channels so WhatsApp QR runs regardless of pick order

* feat(gateway): report configured channels on terminal channel-wizard result

Replaces the Control UI's channel-adoption heuristic with the authoritative
outcome: the channels flow reports its actual selection after config commit,
the wizard session surfaces it as an additive channels field on the terminal
wizard.next result, and the UI keys WhatsApp QR linking off that.

* refactor(ui): align channels hub with the unified settings design language

Hub becomes settings-language rows (44px art tiles, status dots, uppercase
section headings, hairline groups) instead of a card gallery; the detail
overlay hosts the migrated per-channel settings sections with Run setup in
the header. Wizard dialog and tile/cover styles move to spacing tokens.

* chore(i18n): translate channels hub/setup strings; refresh raw-copy baseline

* refactor: satisfy LOC ratchet and dead-export gates

Split mock-dev channel/plugin fixtures into their own modules, move wizard
runner types/defaults to server-methods/wizard.ts, extract the channels page
wizard host and nostr profile HTTP ops, and unexport internal-only types
(incl. the unused config-form SECTION_META barrel re-export).

* chore(i18n): retranslate channels strings on rebased locale bundles

* fix(test): drop redundant String() in channels wizard e2e

* fix: address channel-wizard review findings

- lock wizard cancellation before durable installs/config writes
- report configured channel accounts on the terminal wizard result and
  start WhatsApp QR pairing for that account (web.login accountId)
- forward request options through the browser gateway client so wizard
  RPC timeouts apply
- render skipped setup as a no-change completion
- keep detail/advanced config reachable for unconfigured channels
- surface the dirty-config warning inside the detail overlay
- adopt the picked channel for wizard title/links in browse-all flows

* fix(ui): local wizard RPC timeout; translate no-change completion strings
2026-07-13 11:49:42 -07:00
Peter Steinberger
faa0e1712a refactor(bonjour): use ciao runtime contract 2026-07-13 11:35:48 -07:00
dwc1997
f07ea10869 fix(deepgram): validate realtime base URL overrides, preserving ws(s):// endpoints (#105334)
* fix(deepgram): reject malformed and non-http(s) realtime base URL overrides

* fix(deepgram): accept direct ws(s):// realtime base URL overrides

Preserve released behavior: v2026.6.11 passes wss:// (and ws://) base URL
overrides straight through to the WebSocket URL builder. The prior validator
rejected every non-http(s) scheme, breaking custom Deepgram realtime proxies
that use a direct wss:// endpoint. Accept ws:/wss: alongside http(s):, keep
rejecting malformed and unrelated schemes, and preserve a direct ws(s):
override's protocol/path/port through toDeepgramRealtimeWsUrl.

* fix(deepgram): keep secure ws:// -> wss:// upgrade for realtime base URL

A prior change preserved direct ws:/wss: overrides unchanged, which also
stopped upgrading a plaintext ws:// override to wss://. That regressed the
released behavior where every accepted non-http: scheme maps to wss:, so an
existing ws:// endpoint would begin sending Deepgram realtime audio and
provider auth over an unencrypted socket. Restore the release mapping
(http: -> ws:, all others -> wss:), which still preserves a direct wss://
override and keeps the ws:// -> wss:// secure upgrade.

* fix(deepgram): preserve custom websocket transport

Co-authored-by: dwc1997 <du.wenchi@xydigit.com>

* test(deepgram): use placeholder credential fixture

* test(deepgram): clarify loopback callbacks

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 11:33:53 -07:00
Alix-007
676d3f0230 fix(qqbot): clear voice send timeouts after delivery settles (#105885)
* fix(qqbot): clear voice send timeouts after delivery settles

* chore(deadcode): allowlist test-only timeout constant exports

* test(qqbot): cover timeout race lifecycle

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 11:16:18 -07:00
Peter Steinberger
db02a96c4c refactor(process): route bounded commands through Execa (#106495)
* refactor(process): centralize bounded command execution

* refactor(process): migrate core one-shot commands

* refactor(plugins): migrate one-shot commands

* fix(process): await Windows tree termination

* chore(plugin-sdk): refresh process runtime surface

* refactor(process): migrate remaining bounded commands

* refactor(process): normalize command result handling

* refactor(process): split execution responsibilities

* chore(plugin-sdk): refresh API baseline

* chore(process): remove release-owned changelog entry

* fix(process): narrow binary command input checks

* fix(process): cap sandbox command output

* fix(qa-lab): preserve exact node probe env

* chore(ci): refresh dead export baseline

* fix(process): preserve force-kill command deadlines

* fix(process): avoid post-exit timeout reclassification

* test(process): update scp staging wrapper mock

* test(process): update remaining wrapper mocks

* refactor(qa-lab): preserve Execa tar execution
2026-07-13 11:07:35 -07:00
Peter Steinberger
409d13f94f refactor(active-memory): split runtime modules (#106285)
* refactor(active-memory): split runtime modules

* fix(active-memory): annotate hook deadline result

* refactor(active-memory): keep runtime modules bounded

* fix(active-memory): use type-only recall imports

* refactor(active-memory): supersede partial split

* fix(gateway): type pruned worker manifest
2026-07-13 10:45:01 -07:00
wings1029
fd49e97ee5 fix(discord): inherit default_auto_archive_duration in createThreadDiscord (#103413)
* fix(discord): inherit default_auto_archive_duration in createThreadDiscord

When createThreadForBinding hardcoded autoArchiveMinutes: 60, the
parent channel's default_auto_archive_duration (configured by
operators at 1440, 4320, or 10080) was silently overridden. This is
the same pattern fixed in #103033 for sendMessageDiscord's implicit
forum thread creation.

- Move the auto_archive_duration set after the channel fetch in
  createThreadDiscord so channel.default_auto_archive_duration can
  serve as a fallback when autoArchiveMinutes is not provided.
- Remove the hardcoded autoArchiveMinutes: 60 from
  createThreadForBinding so it inherits the channel default for
  forum/media channels and omits the field for text channels
  (preserving Discord's server-side default).
- Explicit autoArchiveMinutes from callers (thread-create action,
  auto-thread config) still take priority via the ?? operator.

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor(discord): preserve parent thread archive defaults

Co-authored-by: 陈志强0668000989 <chen.zhiqiang1@xydigit.com>

* docs(changelog): credit Discord archive default fix

Co-authored-by: 陈志强0668000989 <chen.zhiqiang1@xydigit.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 10:31:46 -07:00
Peter Steinberger
e8290c699e refactor(codex): split app-server attempt helpers (#106550)
* refactor(codex): split app-server attempt helpers

* fix(codex): mark harness imports type-only
2026-07-13 09:58:01 -07:00
Peter Steinberger
fc4b6a4254 feat(codex): show the account email with app-server usage windows (#106500)
* feat(codex): read the account email with app-server usage

The Codex-harness usage snapshot now carries the account identity: the
usage fetch runs account/rateLimits/read and account/read over one
app-server session (new withCodexAppServerJsonClient seam, which the
single-request helper now delegates to), so the email is guaranteed to
belong to the same account as the windows. Identity stays best-effort;
rate limits survive an account read failure.

* style(test): scanner-safe app-server marker fixture

* test(codex): keep scanner-neutral hunks around app-server marker literals

* fix(codex): bound the best-effort account read within the usage deadline

Review P2: account/read shared the outer usage deadline, so a slow or hung
identity read could reject the whole snapshot with a timeout instead of
returning the already-fetched rate-limit windows. Race the account read
against a local timer bounded to min(4s, usageTimeoutMs/3) and drop the
identity on timeout; a regression test hangs account/read and asserts the
windows still return.

* fix(codex): send account/read params and bound identity by the remaining deadline

Second review round: account/read (GetAccount) requires a params object per
the app-server protocol, so send an empty {} (refreshToken defaults false);
without it a real app-server rejects the request. Bound the best-effort
identity read by the time left before the shared usage deadline (minus a
margin) instead of the original budget, so a slow rate-limit read can no
longer let the identity read trip the outer timeout and discard the
already-fetched windows.

* fix(codex): reserve the isolated shutdown budget in the usage deadline

Third review round: withCodexAppServerJsonClient awaits the isolated
client's closeAndWait inside the outer timeout, so a hung account/read
could reach the deadline during force-kill/exit cleanup and discard the
already-fetched windows. The usage read now passes a cheap isolatedShutdown
(force-kill 200ms + exit 300ms) and the identity bound reserves that plus a
250ms margin (750ms) of the remaining deadline, so cleanup always finishes
before the outer timeout.

* style(codex): rename scoped-request generic to avoid shadowing
2026-07-13 09:56:47 -07:00
Peter Steinberger
2ec0299f9f fix(crabbox): keep setup runs from syncing the gateway checkout
crabbox run rsyncs the invoking repo by default, which blew the setup
budget when the gateway provisioned from a source checkout. Workspace
transfer is owned by the worker tunnel, so setup passes --no-sync.
2026-07-13 09:54:49 -07:00
cxbAsDev
7abc6665dc fix(discord): retry reply session init conflicts to prevent silent message loss (#103562)
* fix(discord): retry session conflicts without duplicate inbound work

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* refactor(discord): split session retry policy

* refactor(discord): keep retry error private

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 09:50:26 -07:00
Peter Steinberger
0665c16dd6 refactor(diagnostics): split OTEL content helpers (#106554) 2026-07-13 09:48:23 -07:00
Peter Steinberger
5d12f6bfb5 refactor(policy): remove remaining unused exports (#106591)
* refactor(policy): remove unused exports

* chore(deadcode): regenerate policy export baseline
2026-07-13 09:47:31 -07:00
Peter Steinberger
d8fb5b404e refactor(policy): split doctor evaluator modules (#106313)
* refactor(policy): split doctor evaluator modules

* refactor(policy): split runtime shape owners

* refactor(policy): split doctor policy domains
2026-07-13 09:35:11 -07:00
Peter Steinberger
c87941e523 refactor(active-memory): split recall helpers (#106539) 2026-07-13 09:33:39 -07:00
Peter Steinberger
11cd600c2d refactor(qa): split WhatsApp live runtime (#106547) 2026-07-13 09:31:51 -07:00
Peter Steinberger
5a37cdbae1 feat(crabbox): run an optional profile setup command on provisioned leases
Live AWS E2E hit the designed fail-stop: worker bootstrap requires Node on
the leased host, and bare AWS leases ship without it. Implement the plan's
provider setup phase as an opt-in `setup` profile key: after the lease is
SSH-ready the provider runs the command via `crabbox run --keep=true`,
gets its own timeout budget on top of provision, and stops the lease
before surfacing a failure so no unbootstrapped box leaks. Setup runs on
every provision attempt (including replay adoption), so commands must be
idempotent.
2026-07-13 09:31:37 -07:00
Peter Steinberger
4a84117188 refactor(telegram): split bot handler runtime (#106324)
* refactor(telegram): split bot handler runtime

* fix(telegram): keep extracted helper types local

* refactor(telegram): bound bot handler modules

* fix(telegram): name callback action results

* fix(telegram): keep inbound input types local
2026-07-13 09:28:55 -07:00
Peter Steinberger
8867a9da0b refactor(extensions): remove unused Discord and QA Lab exports (#106286)
* refactor(extensions): remove unused major-plugin exports

* refactor(qa-lab): preserve existing test seams

* chore(deadcode): regenerate export baseline

* refactor(qa-lab): share evidence environment resolver
2026-07-13 09:25:45 -07:00
Peter Steinberger
e0facfcf9a refactor(qa-lab): split web UI renderer (#106537)
* refactor(qa-lab): split web UI renderer

* refactor(qa-lab): split web UI renderer
2026-07-13 09:21:29 -07:00
Peter Steinberger
7a0efada74 improve: speed up lifecycle tests (#106501)
* test: remove fixed waits from lifecycle tests

* test: harden cron process liveness probe
2026-07-13 09:14:04 -07:00
Souvik Ghosh
da629045d9 feat(workboard): expose dispatch --max-starts to raise the per-pass start cap (#100174)
* feat(workboard): expose configurable dispatch cap

Co-authored-by: Souvik Ghosh <gshsouvik01@gmail.com>

* refactor(workboard): split gateway dispatch helpers

* docs(changelog): note Workboard dispatch cap

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Souvik Ghosh <gshsouvik01@gmail.com>
2026-07-13 08:58:08 -07:00
Peter Steinberger
2d5803a250 fix(reef): use bundled-channel-entry contract so channelConfigs surfaces load 2026-07-13 08:52:14 -07:00
Jason (Json)
b32f59c8c1 feat(ui): create catalog sessions from the sidebar (#105810)
* feat(ui): create sessions from catalog headers

* fix(ui): deduplicate catalog-owned sessions

* fix(ui): preserve catalog session routing state

* fix(ui): keep per-agent session creation in switcher

* fix(anthropic): normalize runtime config snapshot

* test(plugin-sdk): account for model runtime export

* test(plugin-sdk): classify current deprecated surface

* test(ui): follow agent chip menu trigger

* fix(ui): bind catalog drafts to validated agent

* fix(ui): resolve catalog targets from gateway

* refactor(ui): split sidebar session helpers

* chore(ci): complete LOC baseline migration

* fix(ui): extract sidebar session catalog rendering

* fix(anthropic): use provider-relative catalog model id

* chore(ci): ratchet sidebar LOC baselines

* test(ui): cover catalog draft retargeting

* chore(plugin-sdk): refresh API baseline

* style: format catalog session changes

* fix(ui): retry catalog drafts after reconnect

* fix(ui): back off catalog target retries

* fix(ui): keep unresolved catalog drafts locked

* fix(ui): gate catalog creation in core

* fix(ui): keep catalog renderer private

* style(ui): format catalog session target

* chore(plugin-sdk): refresh API baseline

* style(ui): format catalog group state

* Merge latest origin/main CI fixes

* fix(ui): preserve catalog session agent selection

* fix(ui): preserve catalog session agent

* chore(plugin-sdk): refresh API baseline

* fix(ui): type catalog route data

* chore(plugin-sdk): refresh API baseline

* refactor(sessions): centralize transcript path archival

* fix(ui): target expanded agent catalog sessions

* fix(ui): scope catalog actions to expanded agent

* docs(ui): clarify catalog loader fallback

* fix(ui): scope catalog pagination to agent

* test(ui): type sidebar lifecycle refresh

* fix(anthropic): preserve node catalog bindings
2026-07-13 09:25:22 -06:00
Peter Steinberger
2626e97b4c refactor: split oversized catalog and protocol helpers (#106476) 2026-07-13 11:10:42 -04:00
Peter Steinberger
ab7f6dd3c9 refactor(deadcode): trim policy private exports (#106290) 2026-07-13 07:58:12 -07:00
Peter Steinberger
f167089d61 feat(nodes): continue Claude catalog sessions on paired nodes via streaming CLI agent runs (#105833)
* feat(gateway): stream node.invoke progress with idle timeouts and cancel

* feat(node-host): opt-in approval-gated claude cli agent run command

* feat(agents): run node-placed claude-cli turns through streaming node invoke

* feat(anthropic): continue claude catalog sessions on advertising nodes

* docs(nodes): document paired-node claude agent runs and continuation

* chore(plugin-sdk): admit spawn-invocation helper into surface budget

* fix(nodes): harden streaming invoke and node run policy from review findings

* test(node-host): prove multi-token tool-policy argv fails closed

* fix(nodes): allowlist cancel event for apps and break node-host type cycle

* chore(protocol): regenerate Swift gateway models for node invoke progress

* chore(node-host): drop test-only export surface flagged by deadcode ratchet

* style(node-host): merge invoke-types imports

* refactor(nodes): split node agent run modules to satisfy the LOC ratchet

* chore(protocol): regenerate android gateway models and sync export baseline

* chore(plugin-sdk): admit spawn-invocation helper and inherited deprecated drift into surface budget

* chore(plugin-sdk): tolerate inherited agent-core deprecated export

* fix(anthropic): drop node param parser orphaned by upstream catalog split

* ci: sync unused-export baseline with healed main

* test(agents): adopt renamed cli backend prepare helper

* style(node-host): format claude run spawn invocation

* ci: retrigger checks

* chore(plugin-sdk): pin surface budgets to healed-base counts

* fix(protocol): restore untyped lazy validators after upstream style change
2026-07-13 07:39:22 -07:00
Peter Steinberger
507038c456 refactor: split oversized test suites (#106354)
* refactor: split oversized test suites

* test: classify split modules as test utilities

* test: preserve bundled routing after suite splits

* style: format unit-fast routing import

* test: preserve owner routing for split suites
2026-07-13 07:01:08 -07:00
Vincent Koc
c45553089a refactor(slack): trim private reply exports (#106431) 2026-07-13 21:53:34 +08:00
Peter Steinberger
0ff265838b fix(codex): preserve shutdown cleanup across live builds (#106418) 2026-07-13 06:41:19 -07:00
Vitor Cepeda Lopes
93b3f4c45b feat(xai): add native streaming TTS (#103993)
* feat(xai): add streaming TTS via wss://api.x.ai/v1/tts

Expose streamSynthesize on the bundled xAI speech provider so Talk and
Discord streaming playback can use xAI alongside batch REST synthesis.
Adds ws runtime dependency, byte-cap enforcement, and provider tests.

* fix(xai): harden streaming TTS per review feedback

Restrict streaming WS to api.x.ai, decode WebSocket payloads explicitly,
refresh idle timeout on audio.delta, add lifecycle/security tests, and
document the official xAI streaming contract plus non-realtime-voice scope.

* fix(xai): bound streaming TTS text deltas

* fix(xai): require secure native TTS streaming endpoint

* docs(tts): remove duplicate output formats section

* fix(xai): preserve surrogate pairs in tts frames

* fix(xai): bound streaming TTS websocket payloads

* fix(xai): align TTS websocket decoding with ws types

* fix(xai): pin native streaming TTS endpoint

* test(xai): cover native streaming TTS live path

* fix(xai): preserve streaming codec compatibility

* style(xai): format streaming endpoint guard

* docs(tts): describe xAI streaming output policy [skip ci]

* fix(xai): own voice-note TTS format policy [skip ci]

* docs(tts): keep provider summary concise [skip ci]

* test(xai): use explicit placeholder credentials [skip ci]

* test(xai): keep fixtures scanner-safe [skip ci]

---------

Co-authored-by: TheAngryPit <16145902+TheAngryPit@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 06:08:28 -07:00
Vincent Koc
194ed5d34c refactor(acpx): privatize internal helpers (#106394) 2026-07-13 21:01:52 +08:00
VectorPeak
79cc3c333b fix: OpenRouter OAuth denial redirects show provider errors (#105448)
* fix(openrouter): surface pasted OAuth redirect errors

Co-authored-by: chatgpt-codex-connector[bot] <261883814+chatgpt-codex-connector[bot]@users.noreply.github.com>

* fix(openrouter): align callback OAuth error state checks

Co-authored-by: chatgpt-codex-connector[bot] <261883814+chatgpt-codex-connector[bot]@users.noreply.github.com>

* test(openrouter): initialize callback readiness

---------

Co-authored-by: chatgpt-codex-connector[bot] <261883814+chatgpt-codex-connector[bot]@users.noreply.github.com>
Co-authored-by: Altay <altay@hey.com>
2026-07-13 15:37:26 +03:00
Vincent Koc
9f3d3b5672 refactor(oc-path): privatize internal types (#106317) 2026-07-13 20:37:08 +08:00
wangyan2026
5cb4759742 fix(voice-call): restrict classic streaming to Twilio (#102887)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 05:33:16 -07:00
Peter Steinberger
151a259f9a refactor(workboard): split store implementation (#106306)
* refactor(workboard): split store implementation

* fix(workboard): keep store helpers internal
2026-07-13 05:24:49 -07:00
Peter Steinberger
882b2fe900 feat(channels): bundle Reef guarded claw-to-claw channel (#106232)
* feat(channels): bundle Reef guarded claw-to-claw channel

Moves the Reef channel extension from openclaw/reef into the bundled extensions tree with the wire protocol vendored under extensions/reef/protocol. Includes channelConfigs manifest metadata, runtime status reporting via setStatus/buildAccountSnapshot, abort-aware inbox shutdown, monotonic device-auth timestamps, and immutable-model guard admission (dated snapshots plus documented gpt-5.6 ids).

* fix(reef): pin zod exactly per dependency pin guard

* style(reef): satisfy extension lint gates

Curly braces in vendored protocol, explicit type re-exports, typed catch callbacks, Object.assign over map-spread, abort-aware loop restructure.

* fix(reef): CI gates — knip workspace, boundary tsconfig, facade imports, cycle break, contract baselines

- knip: reef workspace project includes vendored protocol/ (owns noble deps)
- tsconfig: conform to canonical extension package-boundary include/exclude; add @openclaw/plugin-sdk devDependency
- imports: channel-inbound/channel-outbound facades instead of deprecated subpaths
- protocol: home ReplayStore contract in envelope.ts to break the envelope<->replay type cycle
- baselines: reef in unguarded runtime-api list; regenerate bundled channel config metadata

* feat(reef): plugin catalog cover art, channel label, changelog revert

* fix(reef): drop unused error-class exports, register lint suppression

* fix(reef): knip entry surface for vendored protocol, explicit WebSocketLike export
2026-07-13 05:17:44 -07:00
Peter Steinberger
6c5084f1ad feat(xai): add realtime voice provider (#106267)
* feat(xai): add realtime voice provider

Co-authored-by: Vitor Cepeda Lopes <vitor@vitorcepedalopes.com>

* fix(xai): satisfy realtime voice validation

* fix(xai): harden realtime relay boundaries

* chore: drop release-owned changelog edit

* chore(i18n): refresh native voice catalogs

* chore(i18n): refresh Control UI raw-copy baseline

* chore(plugin-sdk): refresh API baseline hashes

* chore(i18n): use canonical main catalogs

* chore(i18n): refresh realtime voice source inventory

* chore: refresh xai voice landing head [skip ci]

* chore: refresh integrated protocol artifacts [skip ci]

---------

Co-authored-by: Vitor Cepeda Lopes <vitor@vitorcepedalopes.com>
2026-07-13 05:17:24 -07:00
Peter Steinberger
801ec63f92 refactor(cli): rely on Commander contracts (#106366) 2026-07-13 05:05:31 -07:00
Peter Steinberger
d262cad41f refactor: burn down Matrix, Telegram, and outbound dead exports (#106153)
* refactor(matrix): remove unused internal exports

* refactor(telegram): remove unused internal exports

* refactor(matrix): remove stale thread binding imports

* refactor(outbound): remove unused internal exports

* style(outbound): format dead export cleanup
2026-07-13 04:39:58 -07:00
Peter Steinberger
418dd85e66 improve: speed up focused test execution (#106307)
* test: speed up focused test execution

* style: format vitest config test

* test: preserve targeted watch routing
2026-07-13 04:38:05 -07:00
Peter Steinberger
279f21e02b chore(deps): remove redundant Commander declarations (#106345) 2026-07-13 04:34:19 -07:00
Peter Steinberger
fa963eee06 refactor(copilot): use SDK contracts (#106208) 2026-07-13 04:00:17 -07:00
Joshua West
392a02a396 fix(workboard): resolve parent dependency status via targeted lookups, not a full-corpus scan (#104668)
* fix(workboard): resolve parent dependency status via targeted lookups, not a full-corpus scan

dependencyTargetStatus() called the fully unscoped store.list() (every card,
every board, fully materialized via entries()+readCard()) just to look up the
status of a card's own parent id(s) -- almost always exactly one. dispatch()
calls promoteDependencyReady() once per card in its board-scoped pass, so
every parented card in that pass re-paid for a full-corpus re-scan.

Confirmed via a live CDP CPU profile of a real "openclaw workboard dispatch"
call (--inspect attached to a running gateway, Profiler.start/stop scoped to
the repro, elapsed 161.8s matching a known 160s+ stall): 93.3% of the time
(142s + 8.7s of 162s) was inside native SQLite all()/prepare() bindings, all
funneling through dispatch -> promoteDependencyReady -> dependencyTargetStatus
-> list -> entries -> readCard (readCard issues 4 separate synchronous SQL
statements per card). On a corpus of ~5770 cards, this is O(parented_cards_in_pass
x corpus_size x 4_queries) -- a genuine algorithmic defect, not event-loop
starvation from a concurrent session as originally suspected for this symptom.

Replace the unscoped list()+Map lookup with targeted get(parentId) calls
(already a single indexed-row lookup used everywhere else in this file) --
O(parents.length), normally O(1), instead of O(corpus size). Behavior is
unchanged: parent?.status === "done" on the get() result is exactly what
cards.get(parentId)?.status === "done" computed from the unscoped list().

Adds a regression test asserting the underlying store's entries() is called
at most once while promoting 8 parented cards together in one dispatch pass
(would have been 9 calls before this fix -- 1 outer scoped list() + 1 inner
unscoped list() per parented card).

* fix(workboard): address review feedback on dependency-target-status fastpath

Two findings from the automated PR review, both confirmed real:

- Remove an incomplete, unrelated active-owner fast-path (listActiveOwnerIds()
  in store.ts + its cross-board test in store.test.ts) that leaked into this
  commit from separate, still-in-progress local work. It imported
  WorkboardActiveOwnerQueryable, a type that isn't defined anywhere in this
  PR's tree, breaking typecheck and the bundled-extension lint check. Not
  part of the dependencyTargetStatus fix this PR is scoped to.
- Replace the comparator-free, mutating .sort() calls in the new dependency
  regression test with .toSorted() plus an explicit localeCompare comparator,
  per the repo's lint rules.

Re-ran locally against just these two files (the actual PR diff, review WIP
set aside): pnpm lint --threads=8, pnpm format:check, pnpm tsgo:prod, pnpm
check:test-types, pnpm run lint:extensions:bundled all pass; full workboard
extension suite 111/111 (two removed tests belonged to the unrelated
active-owner code, not this fix).

---------

Co-authored-by: ClawBox <clawbox@cayk.ca>
2026-07-13 03:46:05 -07:00
Peter Steinberger
88e0bbc86f fix(ci): drop unused msteams media placeholder test constants
Companion to 4bb4ffc55c: check-lint (no-unused-vars) still fails on
attachments.helpers.test.ts after #106279 trimmed their usages.
2026-07-13 03:43:17 -07:00
Peter Steinberger
4bb4ffc55c fix(ci): drop dangling msteams attachment placeholder helper 2026-07-13 03:42:39 -07:00