Commit Graph

81192 Commits

Author SHA1 Message Date
Dallin Romney cb7f9178db test(ui): split cron view interaction coverage 2026-08-20 21:58:18 -07:00
sinner 1fb4857e3c fix(cron): reject blank/invalid --webhook before delivery.mode flip (#121533)
* fix(cron): reject blank/invalid --webhook before delivery.mode flip

Presence-only typeof checks treated empty or non-http --webhook as a
delivery edit, forging mode=webhook with no URL and clearing the prior
chat destination on merge. Validate with normalizeHttpWebhookUrl first.

Co-authored-by: Peter Steinberger <steipete@gmail.com>

* test(cron): cover webhook validation boundaries

Amp-Thread-ID: https://ampcode.com/threads/T-01a0220d-eaa0-76b4-adb9-68841f015b75

---------

Co-authored-by: zyw02 <zyw02@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 21:52:30 -07:00
Peter Steinberger 4ba2c46cc4 fix(qa): own container first-run onboarding journey (#126981)
Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 21:47:44 -07:00
Goutam Adwant 2b190b2122 fix(doctor): migrate markerless multi-agent rosters (#126595) 2026-08-20 21:44:05 -07:00
Peter Steinberger 2e1b882845 fix(doctor): report degraded gateway secret owners (#126998) 2026-08-20 21:43:45 -07:00
sinner 9bc772ba50 fix(cron): mutex blank --model/--thinking with matching clear flags (#119894)
* fix(cron): reject blank --model/--thinking on cron edit

Empty Commander values skipped the clear-* mutex after normalize, so
--model '' --clear-model still cleared the override. Align with fallbacks
and delivery clear presence checks.

Co-authored-by: Peter Steinberger <steipete@gmail.com>

* test(cron): align empty model/thinking edit expectation with blank reject

The legacy cron-cli suite still expected blank --model/--thinking to be omitted; that contradicts the fail-closed blank validation and broke CI.

Co-authored-by: Peter Steinberger <steipete@gmail.com>

* fix(cron): mutex blank --model/--thinking with matching clear flags

Standalone blank overrides stay omitted. Flag presence now conflicts with
--clear-model/--clear-thinking instead of silently applying the clear.

Co-authored-by: Peter Steinberger <steipete@gmail.com>

* test(cron): focus blank clear mutex coverage

Amp-Thread-ID: https://ampcode.com/threads/T-01a0220d-eaa0-76b4-adb9-68841f015b75

---------

Co-authored-by: zyw02 <zyw02@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 21:41:30 -07:00
Peter Steinberger 371f8ce80f fix(skills): point a ClawHub miss at search, not at the local skill list (#126987)
`openclaw skills install <slug>` and `skills verify <slug>` both answered a
ClawHub 404 with:

    Skill "nonexistent-skill-xyz" not found. Run `openclaw skills list` to see available skills.

ClawHub is saying the slug is not in the registry. `skills list` lists the skills
already installed locally, so it cannot resolve a registry miss -- the operator
is sent to look at what they already have when they were trying to acquire
something new. `skills search` exists for exactly this and is one line away in
`skills --help`.

The sibling gets this right, which is what makes it a defect rather than a
preference: `plugins install <unknown>` answers with "Run `openclaw plugins
list` to see installed plugins, or `openclaw plugins search <name>` to look for
installable plugins."

The 404 branch now names ClawHub as the source of the miss and suggests
`skills search <slug>`. It also routes through `formatCliCommand` like the rest
of the file's sibling messages, so the suggestion stays correct under `--profile`
or `--container`; the hardcoded string did not.

The local-lookup message in `skills-cli.format.ts` is unchanged: there
`skills list` is the right answer, because that path is looking for a skill the
operator should already have.

Production +4/-1.
2026-08-20 21:40:59 -07:00
Peter Steinberger 9737026237 improve(agents): avoid repeated model suppression planning (#126982)
* perf(agents): cache model suppression by generation

* test(agents): narrow model suppression spies

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 21:40:44 -07:00
Peter Steinberger 3186e22382 fix(doctor): name the unreadable state database instead of dying on a SQLite string (#126985)
Doctor is the designated repair owner and nearly every CLI failure footer in this
product ends with `Try: openclaw doctor`. With a corrupt shared state database it
produced this, and nothing else:

    ┌  OpenClaw doctor
    database disk image is malformed

No path. No indication of which database. No next step. `doctor --fix` printed
the identical two lines and repaired nothing, `OPENCLAW_DEBUG=1` added nothing,
and the standard `Reason:`/`Debug:`/`Try:` envelope never appeared. The operator
was in a closed loop: every command told them to run doctor, and doctor told
them a SQLite string with no object attached to it.

Corrupt the agent database instead and doctor already does the right thing --
names the file, names the reason, warns visibly, completes the full run, exits 0.
Same corruption class, two databases, opposite treatment.

The mechanism: `assertDoctorDatabaseSchemasCompatible` read
`preflightOpenClawDatabaseSchemas` and inspected only `incompatible`, silently
discarding `indeterminate`, which is exactly where an unreadable shared database
is recorded with its path and reason already populated. Doctor then proceeded and
died deeper with the context stripped, at
`src/infra/sqlite-readonly-location.ts:428` by way of state ownership inspection
and the config preflight.

Doctor now consumes that dropped signal and stops with a diagnosis that names the
file, the reason, what it deliberately did not do, and how to recover. It stops
rather than continuing like the agent-database path because shared state owns
write admission and holds the persisted plugin index the health context is built
from; disabling migrations still fails on that index, so continuing would mean a
bespoke degraded doctor. It does not recreate the database: that file holds auth
profiles among other things, so silent rebuild is data loss.

Also fixes an adjacent leak found in the same investigation: `io.load.ts` passed
a raw `Error` to the logger, so `doctor --session-sqlite inspect` printed a stack
trace with absolute `dist/*.js` frames without `OPENCLAW_DEBUG=1`, contradicting
the CLI's own debug-gating convention. It now logs formatted message text.

`doctor --lint` exiting 1 while bare `doctor --json` exits 0 was investigated and
left alone: commit 6e5bf3ec55 established that advisory JSON exit behavior
deliberately, and register.maintenance.test.ts covers it.

Production +11/-1.
2026-08-20 21:38:28 -07:00
Ayaan Zaidi 1aa211be4a fix(qa): make Mantis backfills reliable (#126980)
Preserve honest blocked proof outcomes and publish visible stop-reports without marking them passed. Serialize burst runs through the authoritative Telegram-user lease while reserving time for proof and cleanup.
2026-08-21 10:01:58 +05:30
Peter Steinberger a4b3f63a87 fix(ui): use active scheduler trigger capability (#126945)
Control UI automation trigger authoring now reflects the running scheduler across unsaved and saved-but-unapplied config edits and reconnects.
2026-08-20 21:28:44 -07:00
EricCai aea1ca60e6 fix(doctor): fail closed on newer cron schema (#115447)
Amp-Thread-ID: https://ampcode.com/threads/T-01a0220e-399b-73e8-8e77-a1d872a68848

Co-authored-by: EricCai <287630876+ericcaiwx-star@users.noreply.github.com>
2026-08-20 21:21:28 -07:00
Dallin Romney 997af9c02d fix(release): keep packed SDK smoke on public types (#126992) 2026-08-20 21:21:20 -07:00
Peter Steinberger 747a49e7a7 fix(cli): reject invalid gateway status timeouts (#126977)
Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-b547-7788-a916-d4a94cbd3e3b

Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 21:13:48 -07:00
Peter Steinberger 9be871245b fix(channels): answer the channel question, and stop calling ECONNREFUSED an auth failure (#126984)
Two defects in one command, both on the path a brand-new operator is on
immediately after `openclaw onboard`.

`channels status` never mentioned channels when none were configured. With the
gateway up it printed `Gateway reachable.` and a tip about `status --deep`;
without it, two blank lines where the channel list belongs. The operator asked
for the status of their channels and got gateway reachability. Its siblings
already handle this -- `channels list` prints `- no configured chat channels
(run \`openclaw channels list --all\` to see installable channels)` and
`openclaw status` prints `No channels configured` -- so `channels status` was
the lone holdout. Both renderers now emit that same line, moved to a shared
constant so the three surfaces cannot drift apart again.

The second is worse because it sends the operator somewhere wrong. The fallback
computed `gatewayAuthUnavailable = expectedError || isGatewaySecretRefUnavailableError(err)`,
and `isExpectedCliError` returns true for `isGatewayTransportError` -- a plain
ECONNREFUSED. So a gateway that simply was not running reported `Gateway auth
unavailable; showing config-only status.`, contradicting the `Gateway not
reachable at ws://... (ECONNREFUSED)` line printed three lines above it. Someone
who runs `channels status` before starting the gateway went hunting for a token
problem that did not exist. The flag now consults only the two genuinely
auth-related predicates; `expectedError` keeps its separate job of selecting the
canonical CLI failure output.

`isGatewayCredentialsCliError` becomes exported for that check. The JSON shape is
unchanged; only the truth of `gatewayAuthUnavailable` changes, and no test or
documented contract depended on transport errors setting it.

Production +27/-9.
2026-08-20 21:12:33 -07:00
Peter Steinberger 2acfc47b7f fix(ui): expose all automation schedule filters (#126962)
* fix(ui): expose all automation schedule filters

Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-b547-7788-a916-d4a94cbd3e3b

* refactor(ui): derive cron filters from protocol

Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-b547-7788-a916-d4a94cbd3e3b

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 21:10:49 -07:00
Bek e2a48d4b70 fix(cron): prune terminal task history after seven days (#126095) 2026-08-21 00:10:11 -04:00
Peter Steinberger 46dcc57c54 fix(cli): reject an unconfigured --agent across every operator selector (#126983)
`skills` (#126954) turned out to be one instance of a class. Two more surfaces
accepted an agent id that names nothing, and one of them wrote it to disk:

- `sandbox explain --agent nope-agent` exited 0 and printed a complete policy
  report, including `Elevated: enabled: true` and a workspace root that does
  not exist, for an agent `openclaw agents list` does not know.
- `approvals allowlist add "<pattern>" --agent nope-agent` exited 0, printed
  `Writing local approvals.`, and persisted the entry under a key nothing will
  ever read. The operator believes they approved an exec pattern; nothing was
  approved. This is the severe one: a false record of an approval.

Sweeping `option("--agent"` across the CLI found the rest. Each hit was
classified as a selector (names the thing operated on, must validate) or a
filter (narrows a list, may legitimately return empty). Selectors now route the
explicit value through `resolveConfiguredAgentId`, the helper that already backs
`models`, `memory`, `sessions list`, `hooks`, and every capability surface:
`channels resolve`, `sessions export-trajectory`, `sessions archive/delete`,
`backup enable`, `backup git create`, `backup sqlite create`. Blank-only guards
close the empty-shell-variable hole in `hooks`, `sessions` list/cleanup/tail/
compact, `migrate`, and agent turns.

Filters are deliberately unchanged: `audit`, `usage-cost`, agent bindings,
`backup verify/restore`, and `sandbox recreate` all match existing records and
correctly report no matches. Cron is gateway-owned and already rejects an
unavailable agent server-side; it is untouched.

`sessions archive/delete` was not silent -- it failed with `Session not found.
Run openclaw sessions list --agent ghost --json to choose a valid key.` But that
suggested command itself exits 1 with `Unknown agent id "ghost"`, so the
remediation handed to the operator could not run. Validating locally, exactly as
`sessions list` already does, keeps the hint runnable without adding a roster
round-trip to the gateway.

Production +140/-38.
2026-08-20 21:08:38 -07:00
Peter Steinberger 514d148519 fix(qa): reject skipped-only confidence lanes (#126975) 2026-08-20 21:01:38 -07:00
Dallin Romney d0091b001c fix(browser): isolate startup upload cleanup runtime (#126136)
* fix(browser): keep node-host cleanup lazy

* fix(browser): isolate upload cleanup runtime
2026-08-20 20:52:41 -07:00
astra-openclaw 7b15dcb3ed fix(context-engine): ignore terminal blocked outbox rows (#126593)
Keep terminal blocked records available as audit evidence while excluding them from pending advancement selection.\n\nRefs #126591

Co-authored-by: astra-openclaw <266500838+astra-openclaw@users.noreply.github.com>
2026-08-20 20:47:09 -07:00
Dallin Romney 579f9b8a8a fix(package): account for bundled docs growth (#126970) 2026-08-20 20:43:09 -07:00
Peter Steinberger 0f2facaf14 test: remove Docker seed source guards (#126949)
* test: remove Docker seed source guards

* ci: route Docker seed edits to owner lanes
2026-08-20 20:36:38 -07:00
Peter Steinberger bf5d408437 docs: fix onboarding setup command (#126964)
Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 20:33:26 -07:00
Dallin Romney 5e00a07db8 fix(qa): stop lifecycle CI failing on reused PGIDs (#123161)
* test(qa): avoid reused PGID lifecycle assertion

* test(qa): drop reused PID cleanup fallback
2026-08-20 20:31:39 -07:00
Dallin Romney 49c168a529 test(wizard): avoid global exec path mutation (#126969) 2026-08-20 20:31:23 -07:00
Peter Steinberger 3c004d360b perf(plugins): reuse web channel plugin record (#126966)
Amp-Thread-ID: https://ampcode.com/threads/T-01a021f5-984a-7628-a30c-491c166ff247

Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 20:28:50 -07:00
Dallin Romney 59e9765e77 fix(ci): accept extended-stable patch successors (#126936)
* fix(ci): accept extended-stable patch successors

* fix(ci): align Telegram extended-stable successors
2026-08-20 20:13:26 -07:00
Dallin Romney 45db176a64 test(openai): drop upstream realtime outcome assumption (#126025) 2026-08-20 20:09:32 -07:00
openclaw-mantis[bot] bafa32fd54 chore(ui): refresh control ui locales (#126927)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-20 20:03:25 -07:00
Josh Lehman b6bf9a7154 fix(ui): preserve active commentary on steer (#126886)
Control UI now preserves active-run commentary and tool progress when a follow-up steers the same run, while fresh sends still clear stale projection state.

Fixes #126938.
Reviewed-by: @shakkernerd
2026-08-21 04:01:29 +01:00
Dallin Romney be891d2ac0 fix(e2e): follow shared auth ownership in onboarding proof (#126958) 2026-08-20 20:01:25 -07:00
Dallin Romney 630175d87f chore(release): refresh config docs baseline (#126956) 2026-08-20 19:58:27 -07:00
Peter Steinberger ee337708de fix(ui): label composer textareas (#126952)
Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-b547-7788-a916-d4a94cbd3e3b

Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 19:54:49 -07:00
Peter Steinberger 41069d9747 fix(skills): reject an unknown --agent instead of inventing one (#126954)
`openclaw skills check --agent nope-agent` exited 0 and printed a full report
headed "Agent: nope-agent" with 53 skills / 44 eligible, while the install's only
real agent reported 57 / 48. It did not fall back to the default -- it fabricated
an agent and produced confident, different numbers for it. `skills list` behaved
the same way.

Every sibling --agent surface already rejects an unknown id: `models auth list`,
`models list`, `models status`, `memory status`, and `sessions list` all exit 1
with "Unknown agent id". Skills was the only holdout, and the canonical helper
for it already exists -- `resolveConfiguredAgentId`, added for this exact class
when `memory --agent` had the same hole.

`resolveSkillsWorkspace` took the explicit --agent value verbatim while both the
workspace-inferred and default paths were validated. Route the explicit value
through `resolveConfiguredAgentId` so the message and behavior match the
siblings, including the profile-aware hint, and reject a blank --agent the way
memory does. Workspace inference and default resolution are unchanged.

Production +9 LOC.
2026-08-20 19:54:24 -07:00
Vito Cappello 6d7bc062e3 fix(session-catalog): hide OpenClaw-managed provider sessions (#125424)
* fix(session-catalog): hide OpenClaw-managed upstream sessions

* fix(codex): filter managed paired-node sessions

* fix(codex): classify legacy managed sessions

* fix(session-catalog): classify managed provider sessions

* fix(session-catalog): backfill inter-session ownership

* fix(session-catalog): classify Claude internal prompts

* fix(session-catalog): retain durable provenance

* fix(codex): keep rollout home derivation private

* fix(anthropic): declare catalog schema dependency

* fix(anthropic): avoid catalog schema dependency

* fix(session-catalog): scope managed ownership to Codex

* fix(codex): contain catalog provenance reads

* fix(codex): bind managed threads to catalog home

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com>
2026-08-20 19:51:55 -07:00
Peter Steinberger 5e52850584 fix(auth): pick the display store from persisted sources, not runtime ones (#126955)
With an external CLI credential discoverable, `models status` printed
"Auth store: <state>/agents/main/agent/openclaw-agent.sqlite" while
`models auth list` printed "<state>/state/openclaw.sqlite" -- two commands, one
install, different answers, and the agent database held no auth rows at all.

`resolveAuthStorePathForDisplay` chose between the agent-local file and the
shared owner with `hasLocalAuthProfileStoreSource`, which returns true for a
runtime snapshot. External-CLI discovery populates an agent-scoped runtime
snapshot, so `models status` -- which performs that discovery -- concluded the
agent owned a local store file. Those credentials live in the external tool's own
files, never in the agent database. Pointing HOME at an empty dir removes the
discovery and both commands already agreed, which isolates the trigger.

The displayed value is a file path, and only persisted state lives in a file, so
the decision now uses the persisted store probe. A genuinely local persisted
store still wins, including without an ownership record.
2026-08-20 19:49:59 -07:00
Peter Steinberger fd22f7a1c8 fix(skills): keep restart drain out of review backoff (#126948)
Refs #125899

Co-authored-by: Vishal Doshi <vishal.doshi@gmail.com>
2026-08-20 19:28:25 -07:00
Peter Steinberger eb07eecd40 fix(onboard): infer interactive provider auth from credential flags (#126946) 2026-08-20 19:17:50 -07:00
Peter Steinberger 94f042ba86 fix(nostr): retain SecretRef-backed accounts (#126934) 2026-08-20 19:14:08 -07:00
Peter Steinberger 718dacc46a fix(fleet): publish backups without partial finals (#126942) 2026-08-20 19:13:53 -07:00
Peter Steinberger dec620f279 fix(cron): reset trigger state on owner changes (#126940) 2026-08-20 19:11:47 -07:00
Dallin Romney 1c40eee82e fix(ci): route recurring validation through SHA helper (#126766) 2026-08-20 19:11:27 -07:00
Dallin Romney 56e32bb723 fix(ui): surface onboarding memory import load failures (#126738) 2026-08-20 19:10:54 -07:00
EJ 979eff535c fix(agents): retire terminal-only recovery residue (#126671)
Clear completed restart-recovery ownership before admission and during Gateway startup while preserving live recovery fences.

Co-authored-by: EJ Campbell <ej.campbell@gmail.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-21 07:40:48 +05:30
Peter Steinberger ab2bbd42df test: trim UI and tooling test seams (#126937) 2026-08-20 19:04:18 -07:00
Peter Steinberger 8bc6ab08f8 fix(sessions): stop persisting runtime-only skill catalogs (#126931)
* fix(sessions): keep resolved skills out of durable state

Repair runtime-only skill persistence across SQLite, legacy stores, bounded Doctor cleanup, and lightweight health reads.

Refs #126663

Co-authored-by: ruel225 <ruel225@users.noreply.github.com>

* test(health): assert lightweight session list projection

---------

Co-authored-by: ruel225 <ruel225@users.noreply.github.com>
2026-08-20 19:04:11 -07:00
Peter Steinberger a6a58d827c chore: prepare fresh Amp orb lifecycle (#126933)
* chore: prepare Amp orb lifecycle

Amp-Thread-ID: https://ampcode.com/threads/T-01a01dec-e5b8-75b8-be47-c1a67e993602

* fix: harden orb toolchain bootstrap

Amp-Thread-ID: https://ampcode.com/threads/T-01a01dec-e5b8-75b8-be47-c1a67e993602

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 19:03:46 -07:00
Peter Steinberger 2ebd80cc96 fix: speech-only supplements silently complete agent replies (#126925)
* fix: keep supplemental speech from settling agent replies

* fix: tolerate malformed supplemental reply media
2026-08-20 18:48:44 -07:00
Peter Steinberger da8196c40b fix(onboard): keep gateway credentials out of plaintext in ref mode (#126928)
* fix(onboard): keep gateway credentials out of plaintext in ref mode

* test(onboard): preserve credential table tuple types
2026-08-20 18:48:11 -07:00