Commit graph

2224 commits

Author SHA1 Message Date
Peter Steinberger
fe645cd77d
fix(doctor): let the invoking update driver enter maintenance during repair (#147720)
* fix(doctor): admit the invoking update repair driver

Propagate standalone repair ownership to fresh Doctor children and preserve live-driver admission before service effects. Ordinary updater finalization retains parent activation ownership.

Reported by @rogerspires4452-dev (#146860).

* fix(update): pass Doctor run identity without restoring caller environment

Carry the adopted run ID through finalization parameters into the existing Doctor child environment. Preserve intentional environment changes made during plugin convergence.
2026-09-13 21:41:55 -07:00
Peter Steinberger
f6d984fcbe
fix: restore PowerShell completion before later arguments (#147737)
Use the supplied cursor position when deriving completion context, so later words do not hide command and option-value suggestions. Preserve existing end-of-line behavior through the same parser.
2026-09-13 20:26:10 -07:00
Ayaan Zaidi
f9c7173b20
fix(skills): keep sag available with alternate credentials (#147685)
AI-assisted.

Supersedes #147381 by @LiuwqGit.
Closes #147346.

## What Problem This Solves

A working `sag` skill appears unavailable, and `doctor --fix` disables it, when its installed CLI obtains credentials outside the Gateway environment.

## User Impact

Installed `sag` stays available with alternate credentials. The executable checks credentials when it runs. Optional configured-key injection remains available.

Doctor does not automatically re-enable entries disabled by an earlier run. The saved flag does not distinguish Doctor repair from an intentional user choice. If the earlier disablement was incorrect, run `openclaw config set skills.entries.sag.enabled true`. Refresh the Skills list; the next agent turn uses the refreshed skill settings.

## Why This Change Was Made

The bundled skill declaration keeps its executable requirement and removes the incorrect environment prerequisite. The original metadata fix and authorship are preserved. The regression now runs registered `skills info sag --json` and stopped-Gateway `doctor --fix`, including the saved enable flag, instead of calling the status helper directly.

## Evidence

| Check | Main | This change |
| --- | --- | --- |
| Real CLI and Gateway `skills.status` | Needs setup; not visible | Ready; visible |
| Control UI Skills list | Under Needs Setup | Under Ready |
| Skill details | Missing-variable warning | Warning gone; key editor retained |
| Stopped-Gateway Doctor | Saves `enabled=false` | Preserves absent or explicitly true enablement |
| Registered CLI regression | Four expected failures | Four passes |

Correlated request/response frames confirm that both the browser and CLI received `skills.status` from the Gateway. The installed executable's alternate key-file check uses a local test endpoint; live-account validity and audio production are not claimed.

Fresh merge `489365ccffab2e043d676ed3b01cb2e0b5a203d4` has candidate parent `40632360f3ff8162fa27503e08c636223c8cc852` and main parent `4750ff8d2b`. It passes 4 registered CLI regressions, 44 skill tests, 10 Doctor tests, and 153 test-registration checks. Changed-file lint, formatting, and whitespace checks pass. Main's regression run used `d0cf628ff2` with the same test and unchanged main metadata.

The process test uses the existing isolated CLI project. Fixed test owners and CI job counts remain unchanged; generated compact group placement can change as the test inventory grows. Readiness does not establish live-account validity or successful audio output.

### Skills list

| Before | After |
| --- | --- |
| ![sag under Needs Setup](https://gist.githubusercontent.com/obviyus/847a6af1eb35eb2c2d2fa4347bb6843d/raw/dcfea44f39bef00958bd6ef53f80029358f3ec32/base-skills-list.png) | ![sag under Ready](https://gist.githubusercontent.com/obviyus/847a6af1eb35eb2c2d2fa4347bb6843d/raw/dcfea44f39bef00958bd6ef53f80029358f3ec32/candidate-skills-list.png) |

### Missing requirement and key editor

| Before | After |
| --- | --- |
| ![Missing requirement with key editor](https://gist.githubusercontent.com/obviyus/847a6af1eb35eb2c2d2fa4347bb6843d/raw/dcfea44f39bef00958bd6ef53f80029358f3ec32/base-skill-detail.png) | ![Eligible with key editor retained](https://gist.githubusercontent.com/obviyus/847a6af1eb35eb2c2d2fa4347bb6843d/raw/dcfea44f39bef00958bd6ef53f80029358f3ec32/candidate-skill-detail.png) |

## Consumers

- Discovery, Gateway and CLI status, both Doctor skill checks, onboarding, summaries, and recommendations read the same prerequisite declaration.
- The Control UI list and agent controls consume the corrected status; the optional key editor remains available.
- Runtime selection reads the same metadata. New snapshots preserve optional key injection; existing snapshot refresh rules remain unchanged.
- Native clients consume the existing response. The macOS binary-trust reader uses the unchanged binary requirement.
- Explicit disablement, allowlists, agent filters, configured-secret isolation, and automatic-update Doctor protection remain unchanged.

## Compatibility

No new configuration key, schema, protocol, dependency, or runtime credential reader. Existing disabled entries are not automatically re-enabled. The skill prose assigns credential checking to the executable; readiness does not promise valid account credentials or successful speech generation.

Co-authored-by: LiuwqGit <liu.weiqin@xydigit.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-09-14 08:26:59 +05:30
Peter Steinberger
d46f9ebf2b
fix(memory): explain partial search timeouts and allow 30 seconds (#147702) 2026-09-13 19:34:11 -07:00
Peter Steinberger
a8435a1d4f
fix(update): complete Doctor delegation without suspending its checks (#147615)
Keep combined executor/recovery admission before handoff and retain requester/run-only revalidation during the child interval. The existing lease owner still binds the child and settles its process tree before parent use resumes. Document supported repair for an older driver already in memory.
2026-09-13 18:54:52 -07:00
Peter Steinberger
14bb3c0882
fix(update): distinguish unavailable identity and qualify saved advice (#147553)
* fix(update): distinguish unavailable identity and qualify saved advice

Keep failed update history while distinguishing missing identity evidence
from observed version/build disagreement. Qualify saved recovery guidance
with a current health observation without dropping migration constraints.

Refs #145087.
Reported by @freshxiaoyao (#145087).

* test(update): include current health in boot notice expectations

* ci: refresh update report checks on current main
2026-09-13 17:43:11 -07:00
Michael Smith
2adba106d6
fix(doctor): stop flagging every model of a provider that plans no catalog rows (#145076)
`openclaw doctor` no longer flags every model of a provider whose catalog is resolved dynamically (for example OpenRouter) as missing from the local catalog; providers with static rows keep their unknown-model findings. Explicit configured rows remain a validation baseline, legacy-reference migration diagnostics remain available, and model selection explains when offline verification is unavailable.

Thanks @emes (#145076). Closes #132978.
2026-09-13 16:54:45 -07:00
Yuval Dinodia
1e94ceabf1
fix(cli): inherit migrate options placed before the subcommand (#144111)
Fixes #127312.

`openclaw migrate` accepts shared options before or after the subcommand and preserves explicit leaf overrides. `apply` rejects a parent `--dry-run` before it can change state. Source selection, credential opt-outs, item filters, JSON output, and backup options now reach the migration owner consistently.

Reuse the existing source-aware option inheritance helper for list, plan, and apply, document the placement rule, and shrink the assertion baseline from 12 to 10 to record removed casts.

Proof: reversing the production patch yields 6 failed / 7 passed parser tests; restoring it passes 123 parser/inheritance tests and 118 migration command tests. Exact-head CI run 34789592691 passed. The earlier unrelated Code Mode deadline race passed on the refreshed run without changes to that test or product code.

Thanks @yetval (#144111).

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-09-13 16:51:18 -07:00
Peter Steinberger
520442c337
test(agents): add live Code Mode comparison workloads (#147537)
Extend the existing model matrix with isolated Gateway tasks, fixed-workload build comparisons, and separate task and interview evidence. Preserve failed trials, exact source identities, task effects, logical cell completion, and observed preview coverage.

Validation: 187 focused tests, changed-file and targeted type/lint/docs checks, exact-candidate runtime build, actual OpenAI smoke, read-only replay of 24 original trials plus the final smoke, and fresh P2 review. Original scores and interview qualifications remain preserved.
2026-09-13 16:32:28 -07:00
Peter Steinberger
fa5b2d1680
fix(browser): prefer local control over connected nodes (#147446) 2026-09-13 15:59:40 -07:00
Peter Steinberger
c5a57984a1
fix(daemon): verify Windows task handoff before reporting a finished restart (#147437)
* fix(daemon): verify Windows task restart completion

Wait for the outgoing Gateway before requesting launch, and require a matching replacement listener before reporting completion. Record an external recovery command when the handoff cannot verify recovery. Refs #138833.

* fix(daemon): preserve task launch error recovery

Retain the shipped bounded retries and launcher fallback when schtasks rejects a launch. Require the same replacement-listener verification after recovery. Cover the rejected-launch branch with an emitted-batch regression.
2026-09-13 15:18:12 -07:00
shad0wca7
c3d25cfa7a
fix(doctor): preserve MCP OAuth logins during read-only checks (#147454)
Doctor's read-only MCP schema probes no longer refresh OAuth tokens into a disposable snapshot, so diagnostics and update-failure triage cannot log the operator out of a rotating-token MCP server. OAuth-backed servers are reported as skipped with guidance for an authenticated check that persists replacements with their owner; non-OAuth schema inspection remains enabled.

The rotating-token regressions fail on the original lint and triage paths, then pass with the fix. All 98 focused Doctor tests pass. No configuration or database migration is introduced; already invalidated logins require reauthorization.

Thanks @shad0wca7 (#147454). Closes #147449.
2026-09-13 15:10:59 -07:00
Peter Steinberger
4e586f702f
fix: avoid slow system-helper setup and premature timeouts (#147422)
Skip skill discovery for the embedded system helper, whose existing execution contract permits only the OpenClaw system tool. Honor the shared agent timeout setting instead of a private two-minute cap, and clarify when regular agents should delegate system care.
2026-09-13 14:30:57 -07:00
Peter Steinberger
d0100a4264
fix(memory): emit one JSON result for command failures (#147366)
* fix(memory): emit one JSON result for command failures

* test(memory): prepare the SDK before root CLI integration tests
2026-09-13 14:25:55 -07:00
Peter Steinberger
5469328b6c
fix(gateway): preserve live owners through restart (#147242)
Record Gateway owner identity alongside the physical lifecycle coordinator so restart cleanup preserves live and slow-starting Gateways before they begin listening. Route foreground restarts through the recorded owner even when an installed Scheduled Task uses a different launch mode.

Limit Scheduled Task termination to the installed task's recorded owners or exact installed-argv-attributed legacy processes. Revalidate ownership before termination, repair initially unavailable native process identity through the guarded heartbeat, and preserve captured Unix process-group identities through escalation.

Validated by exact-head CI run 34780366323, including the affected Windows batch's 88 passing tests, and a scoped-clean P1 review. Native Windows final-effect proof and a published-updater end-to-end matrix remain accepted proof gaps; the Windows guest was unavailable in startup recovery. Supervisor metadata uses the new owner row's JSON payload without a schema version, table, or retention change.

Reported by @deYangar (#140162).
Fixes #140162
2026-09-13 13:55:49 -07:00
Peter Steinberger
d10ef37bfd
fix(update): retain finalization failure reasons in reports (#147286)
* fix(update): retain finalization failure reasons in reports

Record finalization reason and install facts before triage, preserve explicit parent outcomes, and report the recognized Doctor cause with an explicit standalone package rollback non-outcome. Refs #147160, #146514. Reported by @Navras98 (#147160).

* chore: refresh finalization report CI
2026-09-13 13:17:23 -07:00
Peter Steinberger
ae99b3b980
fix(cli): explain MCP probes with no enabled servers (#147216)
Treat empty and disabled-only registries consistently in plain probe output and show existing add/enable commands. Preserve JSON envelopes, named-disabled errors and mixed-registry execution. Reuse the existing registry fixture writer; production net -1 line.
2026-09-13 11:43:26 -07:00
Peter Steinberger
7bda807a35
fix: keep status polling from stalling the Gateway (#147141)
* fix: keep status polling off the Gateway main thread

* refactor(tasks): finish status summary cutover

* fix: complete status polling verification

* test: run Gateway status ownership checks on the host

* test: verify status host routing across test aggregates
2026-09-13 09:47:39 -07:00
Peter Steinberger
290613f538
fix(update): derive update budgets from measured state instead of fixed literals (#145219)
Derive update inspection, candidate startup, activation, and finalization allowances from measured SQLite state, observed startup, plugin count, and the caller's step budget. Forward the owning allowance through service commands, readiness, Doctor, and migrated finalization instead of imposing competing short cutoffs. Keep metadata and progress probes cancellable in child processes.

Preserve update-activation-timeout settlement, integrity checks, live authority, and unsettled-writer ownership. Expiry alone never authorizes rollback, restart, or lease release. Installer network operations share the documented allowance. No new configuration, dependencies, schema, retries, or persistent retention/recovery semantics.

The activation regression failed with the original resolver and passed with the repair; focused proof passed 102 tests in six files. Native POSIX FIFO cancellation and Chrome boundary proof are recorded in the PR. CI 34767727811 passed 129 jobs with 11 skips on a verified current-base merge checkout. The final refresh commit is tree-identical to the reviewed source.

The maintainer accepts longer recovery waits and the incomplete slow-state published-driver/native Windows recovery qualification. An already-installed driver retains its loaded timers; containing-release delivery and reporter recovery remain unverified.

Reported by @rlosito (#146637); the initiating timeout cause remains unproved. Related update-timeout reports are tracked in #145252.

Refs #144758 #144901 #144890 #143292 #146637 #145252. Preserves the activation boundary from #147019.
2026-09-13 09:41:59 -07:00
Peter Steinberger
05177019f4
fix(update): preserve migrated default agent across restarts (#146246)
Fixes #146195
Refs #146216

Reported by @lilei0311 (#146195).

Preserve the migrated default agent across restarts by reading the roster-validated systemAgent designation under explicit ownership. Agent listing, unscoped session selection, Gateway aliases and identity, and Control UI default badges and Set Default share that recorded owner. Ownerless fleets still require explicit selection.

Keep durable designation separate from sole-agent operation selection and legacy-data ownership. Preserve caller repairs, the Doctor config-flow split, and main-session deletion protection. Omitted hooks honor the persisted global-store owner and its allowlist. ACP legacy metadata follows retained data ownership independently of the runtime default, while sole-agent reads and lifecycle fences remain intact. No code or tests were adopted from #146216.

Validation includes failing-before regression proof, passing touched suites and full changed-file gates, and scoped-clean lead review at be5bbd46c9afc079dbe38fb8136fa94296964a25. Refreshed merge-ref CI passed at https://github.com/openclaw/openclaw/actions/runs/34767412613 after the main-side Control UI budget refresh. The published-updater campaign remains an explicitly waived validation gap.
2026-09-13 09:34:14 -07:00
Vito Cappello
c7f12c5581
fix(doctor): explain surviving service processes during maintenance (#146865)
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
2026-09-13 10:38:25 -04:00
Vincent Koc
6461d6b93f
fix(pairing): QR setup rejects trusted-proxy gateways without a shared secret (#147036)
* fix(pairing): allow QR setup with trusted-proxy authentication

* test(pairing): isolate trusted-proxy setup coverage
2026-09-13 21:36:05 +08:00
Peter Steinberger
ec1cf77054
fix(update): bound activation and accept slow Windows identity reads (#147019)
Bound update activation with the executor's existing multi-step budget, cancel owned commands at expiry, and report update-activation-timeout with next steps in openclaw update status and Doctor. Preserve unsettled writer ownership; timeout alone never authorizes rollback, restart, or lease release and can leave the Gateway stopped.

Use the shared Windows process-start identity reader budget instead of the forced one-second override. Keep InteractiveToken support and PID-reuse checks. Native Windows published-driver upgrade/recovery proof remains a documented gap accepted for this landing; the reporter's identity-query trace remains outstanding.

Refs #146860. Refs #138560.
Reported by @rogerspires4452-dev (#146860).
2026-09-13 06:35:59 -07:00
Peter Steinberger
98b7cf7e58
fix(update): preserve linked plugins during post-core sync (#147009)
Preserve explicitly linked path-source plugins during post-core stable and dev synchronization, including their selected source, install record, configuration, and payload. Keep path records out of package ownership reconciliation through the existing update-source predicate, while retaining strict checks for managed package updates. Record retained-link warnings in post-core status and logs.

The repair uses the candidate-side post-core path invoked by the released updater. Regression evidence covers real discovery and post-core convergence, with failing-before cases and 266 passing focused tests. Full published-driver upgrade and native service restart qualification remain outside this landing's proof.

Fixes #146958.
Related: #146959, #145252, #142681.
Reported by @obviyus (#146958).
2026-09-13 06:32:47 -07:00
Peter Steinberger
f43083ea5c
fix(status): label the session inventory as stored (#146979) 2026-09-13 05:09:55 -07:00
Ayaan Zaidi
4d48e9c1e0
fix(backup): preserve discovery under concurrent state writes (#146912)
## What Problem This Solves

Concurrent state-database writes can make `backup create` report a valid config as invalid. Following its `--no-include-workspace` advice can then produce a verified archive with unresolved agent ownership and declared plugin databases copied as opaque bytes.

## Why This Change Was Made

Discovery and config revalidation now use online SQLite read snapshots. Failed discovery refuses archive publication and reports the underlying error. `--no-include-workspace` changes file selection without changing plugin discovery; `--only-config` remains available for recovery.

#146700 introduced opaque handling, which remains unchanged for genuinely undeclared files.
#146713 made concurrent memory repair reachable from ordinary search, exposing this discovery failure.

## User Impact

Backups retain agent and plugin protection under write load. Invalid or unreadable discovery cannot silently produce a partial state archive.

## Evidence

Before: with a sustained root-database writer, full backup exited 1 blaming config; the no-workspace command exited 0 with empty agent roots and an opaque warning for a declared plugin database.
After: both commands succeed with verification, resolved agent roots, and managed plugin capture. Idle backup and legacy-audit capture remain covered.

## Compatibility

No schema, config key, flag, or archive-format change. Invalid-config state archives now fail closed; `--only-config` still exports the active JSON file. Production growth provides one scoped online-read lifetime shared by discovery and revalidation.

This intentionally replaces the schema-invalid partial state archive supported by #143693. Both state archive modes now require resolved agent and plugin ownership. `--only-config` remains a raw root-file recovery export and does not include referenced config files.

## Consumers

- `backup create`: reliable discovery under concurrent state writes and truthful failure output.
- `backup create --no-include-workspace`: the same agent/plugin ownership protection with workspace files excluded.

The decision `which declared plugin resources backup protects` is made by exactly one mechanism at `src/commands/backup-resource-inventory.ts:126`, supplied with resolved ownership before archive creation.

- Pre-migration backup (`src/commands/migrate/apply.ts:26`) calls the same verified archive command before applying a migration. It consumes the archive path and propagates discovery failures. Only absent local state/config is treated as an empty installation.
- Config staging revalidation (`src/infra/backup-config-capture.ts:119`) takes a fresh scoped state image while retaining authored config bytes, file identity, and include-graph checks.
- Archive result, manifest, and text/JSON output no longer receive unresolved-ownership skipped entries. The existing manifest reader continues to accept earlier archives.

## Invalidation

Each discovery or revalidation operation owns and closes its read snapshot. Config-file identity and include-graph checks remain active. Legacy-audit witnesses continue to read live state.

## Contention

Real CLI backups run alongside a continuous SQLite writer. Both workspace modes retain their declared owners.

## Tests

The registered backup CLI tests cover concurrent root-database writes in both workspace modes and unreadable-state refusal. Retained real CLI captures show the original full-backup failure and no-workspace ownership downgrade on the baseline, then successful verified archives on the candidate tree. Independent archive inspection confirms agent and declared plugin contents, workspace selection, and opaque handling for undeclared SQLite files.

All 79 focused tests passed on a fresh merge of `63ef2a8a4b44` with main `a8a9114fb7`: four CLI cases, 23 command/publication cases, 30 state-reader cases, and 22 config-capture/legacy-audit cases. Workspace-only plugin discovery passes in both workspace modes. Restoring the previous workspace filter makes the no-workspace case fail with an opaque warning for its declared database. Eight real CLI cases also passed on that integration. The final test-only correction passed all 140 backup-create tests, and CI is green at the landing head.

AI-assisted.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-09-13 16:22:55 +05:30
Ayaan Zaidi
e9c1cb7e71
fix(memory): preserve newer indexes and disclose automatic rebuild costs (#146908)
## What Problem This Solves

After a rollback, an ordinary memory search could rebuild an index written by a newer OpenClaw and call the embedding provider without disclosing possible cost.

This corrects a regression introduced by #146713. AI-assisted.

## Why This Change Was Made

Newer versions take precedence over older versions when checking the index. Automatic synchronization preserves newer indexes; explicit reindex remains available.

## User Impact

After an OpenClaw index-format upgrade, the first search can rebuild an older
index before returning results. Rebuilding can take longer and can incur costs
from the configured embedding provider. An index written by a newer OpenClaw
remains paused; upgrade OpenClaw or reindex explicitly. Later searches reuse the
repaired index. Status inspection alone does not rebuild it.

A search that requests a rebuild retains the existing provider-cost disclosure, including on retrieval failure or timeout.

## Evidence

Real CLI runs with two declared runtime-format fixtures reproduced a rebuild on every version switch before this change. On the candidate, the upgrade rebuilt once, rollback made no embedding requests, and switching forward reused the preserved index. These fixtures exercise the real CLI; they are not two separately installed released versions.

Live Gateway searches cover older, current, newer, and mixed stored versions. The retained 2026.7.1-2 state repairs once after current Doctor prepares a copy. Three later searches return known facts without re-embedding documents. Recording providers establish requests, not billed cost. This is search compatibility proof, not an old-updater rerun.

## Compatibility

No schema, configuration, protocol, or public SDK changes. Production code grows to carry repair notices through existing response and error fields without changing the search API.

## Consumers

The classifier serves search admission, the synchronization writer, and status identity. CLI, Gateway, and tool results consume the existing diagnostic formatter. Deep status has its own recovery text. Search can also hand retry work to a separate maintenance manager, so disclosure must cross that handoff. Active Memory preserves successful-search warnings separately from failure state.

## Invalidation

The decision `whether a runtime index is older or newer` is made by exactly one mechanism at `extensions/memory-core/src/memory/manager-reindex-state.ts:153`.

The existing writer lease rechecks identity. Successful repair refreshes the existing index generation; notices apply only to searches that observe a repair request.

## Contention

Concurrent searches share one rebuild and each receives its disclosure. The existing writer and publication leases are unchanged.

## Tests

The retained candidate run passes 69 focused memory tests. A separate Gateway run passes 17 tests. The original-source tool regression run reports 10 failures and two current-version passes. The accepted merge `ed397080e63c06374724c1e4f5b41911edb38d85` now has 311 distinct passing tests: 281 memory/CLI, 13 diagnostics, and 17 Gateway tests. One CLI assertion initially saw forced ANSI colors; the complete CLI file passed with `FORCE_COLOR=0 NO_COLOR=1` on the same unchanged merge. No assertion, source behavior, or timeout was weakened.

<details>
<summary>Test commands on the accepted merge</summary>

```sh
OPENCLAW_E2E_USE_PREBUILT_DIST=1 node node_modules/vitest/vitest.mjs run --config test/vitest/vitest.extension-memory.config.ts extensions/memory-core/src/tools.index-upgrade.test.ts extensions/memory-core/src/tools.index-diagnostic.test.ts extensions/memory-core/src/tools.real-manager.test.ts extensions/memory-core/src/cli.test.ts extensions/memory-core/src/memory/manager-search-upgrade.test.ts extensions/memory-core/src/memory/manager-reindex-state.test.ts extensions/memory-core/src/memory/manager-search.test.ts extensions/memory-core/src/memory/manager.reindex-recovery.test.ts

FORCE_COLOR=0 NO_COLOR=1 OPENCLAW_E2E_USE_PREBUILT_DIST=1 node node_modules/vitest/vitest.mjs run --config test/vitest/vitest.extension-memory.config.ts extensions/memory-core/src/cli.test.ts

FORCE_COLOR=0 NO_COLOR=1 OPENCLAW_E2E_USE_PREBUILT_DIST=1 node node_modules/vitest/vitest.mjs run --config test/vitest/vitest.unit-fast.config.ts packages/memory-host-sdk/src/host/types.test.ts

FORCE_COLOR=0 NO_COLOR=1 OPENCLAW_E2E_USE_PREBUILT_DIST=1 node node_modules/vitest/vitest.mjs run --config test/vitest/vitest.gateway-methods.config.ts src/gateway/server-methods/memory-search.test.ts
```

</details>

## Test movement

The former keyword-only provenance table moved to a recording-provider version matrix. Path, citation, revision, and repeat-search outcomes remain covered. The former zero-query assertion for older/missing keyword-only indexes is not part of that new provider matrix; keyword-only repair is also covered by the real Gateway case and existing tool cases.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-09-13 16:18:26 +05:30
Ayaan Zaidi
e71e0aa145
fix(memory): rebuild outdated provenance on search (#146713)
After upgrading from 2026.7.1-2, existing memories could become unsearchable until a manual reindex. OpenClaw now repairs outdated memory indexes automatically during search or ordinary background synchronization.

A failed repair reports the provider error, confirms the prior index was retained, and directs the user to `openclaw memory status --deep` before retrying.

## Consumers

- Memory CLI, Gateway searches, and `memory_search` recover existing facts automatically.
- Trigger recall, voice fast context, and supplemental wiki memory searches use the same repaired index.
- Ordinary and startup/background memory synchronization repair the same outdated runtime index.
- Active Memory recognizes repaired tool results as successful recall; recovered CLI/tool hits use normal recall tracking when dreaming is enabled.

## Invalidation

The decision `whether to rebuild the index` is made by exactly one mechanism at `extensions/memory-core/src/memory/manager-sync-ops.ts:164`.

The decision `whether a recorded sync failure supersedes runtime-identity guidance` is made by exactly one mechanism at `packages/memory-host-sdk/src/host/types.ts:295`.

Current metadata prevents repeated repairs. The writer rereads it after acquiring the existing writer lease; successful publication invalidates the existing derived caches. Failed publication preserves the prior index and retry state.

Production code grows by 30 lines to share the existing writer lease and select repair errors and guidance once while preserving existing tool, command-line, and Gateway wording.

## Contention

Concurrent searches share one repair, including when an explicit reindex is already running. Active synchronization waits for the writer; reset retains its two-second busy-index refusal. The initial repair can take longer and call the embedding provider. An interactive tool can time out while admitted index work finishes safely.

## Tests

All 92 focused tests pass. Registered Gateway tests detect the original duplicate rebuild; registered tool tests cover missing, old, and current provenance, citations, retained data after failure, and recovery. The combined-corpus case checks that a healthy wiki result retains the memory provider error, preservation warning, and recovery action. Upgrade cases retain ordinary synchronization, read-only status, configuration-only mismatch, and cleanup coverage.

The published 2026.7.1-2 updater reproduced the retrieval failure in a six-agent installation. After repair, three known facts returned with citations, original files remained unchanged, and a repeat search did not rebuild. Two real concurrent requests embed 24 files once, including with a slow provider or an explicit reindex already running. Provider-error checks return concrete failure and deep-status guidance through the tool, command line, and Gateway while retaining the old index.

## Compatibility

No configuration, schema, or protocol changes. Status inspection remains read-only, and configuration-only incompatibilities retain their existing guidance. The reported loss of agent identity was not reproduced; this addresses the retrieval part of #142580.

Thanks @GitHoubi for the report and upgrade evidence.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-09-13 11:56:17 +05:30
Peter Steinberger
b0752a8c55
fix(update): preserve artifact targets in managed handoffs (#146756)
Carry the resolved package spec through already-current finalization so a
managed helper continues the selected artifact. Replacing it with its version
can select a different published package and falsely reject current agent
databases against that release's older schema. Registry version pins and the
extended-stable selector retain their existing behavior.
2026-09-12 23:03:08 -07:00
Ayaan Zaidi
b10035faa9
fix(backup): archive unmanaged SQLite files as opaque bytes (#146700)
## What Problem This Solves

An unrelated SQLite file with foreign-key violations could prevent every backup from completing.

## Why This Change Was Made

Whether an included file gets the live-database snapshot path is decided by exactly one mechanism at `src/commands/backup-resource-inventory.ts:336`, from the core set plus declared plugin resources. The online root snapshot supplies the registry used for discovery and traversal, so planning no longer needs a quiet write-ahead log.

## User Impact

Undeclared files survive backup unchanged with filename warnings. Foreign SQLite symbolic links that exceed the link-resolution limit (`ELOOP`), including loops, are skipped with a filename warning. Corrupt managed databases and unavailable plugin SQLite capabilities still stop publication.

## Evidence

- Pinned main `f0817f23e9`: the real CLI exits 1 on a structurally valid foreign database with a foreign-key violation and publishes no archive.
- Candidate `ce85d13530c4`: CLI create with verification, verify, and restore preserve seven foreign files and sidecars byte-for-byte, with one warning each. Corrupt core and unavailable plugin functions still refuse publication. Managed hardlinks include committed WAL data and restore identical images.
- Tested commit `37f9d97a9d65` (capture behavior unchanged): real CLI backup succeeds during 10 ms commits (309 rows during the 3.6-second run) and in the 100 ms control. Verify/restore retain identical valid root/alias images with writes committed during backup. The unrelated symlink loop is skipped with one warning and the archive restores successfully.
- The full architecture check passes with zero import cycles; five formatter/command tests pass. All 10 managed-refusal/older-schema command cases and changed-test checks pass. The separate macOS planning assertion noted below remains a baseline failure. Type checks and the test-partition check remain for CI.

## Compatibility

No schema, plugin fields, flags, or archive format change. Existing `backupResources` declarations define managed plugin data.

## Consumers

- `backup create`: preserves undeclared SQLite files and reports their filenames.
- `backup verify` and `backup restore`: treat files outside the captured core registry as opaque.
- `src/commands/migrate/apply.ts:26-41`: pre-migration backup now accepts unrelated foreign SQLite, returns only the archive path, and does not forward opaque warnings.
- Fleet backup: uses the shared archive metadata adapter to preserve independent hardlink entries without stalling.

- `formatBackupCreateSummary` moved unchanged to `src/commands/backup-summary.ts`; `src/commands/backup.ts` and `src/infra/backup-create.test.ts` import that owner.

census: generic formatBackupCreateSummary reviewed — 2 callers listed

## Invalidation

Ownership is frozen from the captured root registry for each backup; later registrations belong to the next capture. A plugin declaration changed after planning can be archived with payload classified by the earlier declaration.

## Contention

Registry discovery reads the online root snapshot before archive traversal. The 10 ms sustained-write test and 100 ms control both complete, verify, and restore successfully.

## Tests

- `backupCreateCommand`: all eight managed-refusal cases and both older-schema cases in `src/infra/backup-create.test.ts`; older-schema verification also uses `backupVerifyCommand`.
- `backupVerifyCommand`: all three opaque-file/sidecar cases in `src/commands/backup-verify.test.ts`.
- `backupCreateCommand` and `backupRestoreCommand`: opaque loop handling, declared/core loop refusal, and agent registration captured immediately before the root snapshot.

Those tables retain the complete case mapping, fixtures, and assertions. Source bytes are compared after capture or refusal and before the real outcome recorder runs; the recorder still runs unchanged. The unchanged macOS manifest-path assertion reproduces on base. The added source lines separate resource planning from captured ownership and preserve missing-root checks.

Thanks @clawputerlabs for the report.

Closes #144552.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-09-13 11:31:38 +05:30
Vito Cappello
babe256c05
fix(doctor): avoid redundant cleanup after session imports (#146597)
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
2026-09-13 01:16:51 -04:00
Jason (Json)
28ac6137a0
fix(update): require consent before interactive repair (#146693) 2026-09-12 22:24:18 -06:00
Peter Steinberger
f0817f23e9
fix: bound filesystem reads and keep sandbox reads responsive (#146654)
* fix(sandbox): read pinned file payloads asynchronously

Keep the Gateway event loop available during sandbox file reads while preserving the admitted descriptor, uncapped tool reads, bounded growth checks, and existing overflow errors.

The focused anchored, boundary, and shell suites pass all 43 tests. Both new scheduling regressions failed before the change and pass afterward; they also verify the opened file survives pathname replacement.

* fix(exec): bound reads of growing literal-tilde scripts

Apply the existing fs-safe byte limit while reading the admitted descriptor,
preserving lazy imports and best-effort preflight handling. A real-file growth
regression fails on the old whole-file read and passes with bounded consumption.

Validation: focused regression, complete changed checks including core and core-test
types, and independent review through P2.

* fix(skills): bound file reads and validate scan cache identity

* perf: bound package and skill artifact hashing memory

Keep small package files on a bounded descriptor read and stream larger or growing files through fs-safe. Reuse guarded skill file handles while preserving both provenance digest formats, package modes, ordering, and link policies.

Synthetic interleaved proof reduced large-file payload buffers from 256 MiB to about 2 MiB, with a roughly 21% median latency cost on the warm-cache fixture. Preserve the small-file fast path after unconditional streaming regressed it.

Validation: 50 focused inventory and skill lifecycle tests, an original-code failing hardlink substitution regression, focused core/script lint, formatting, whitespace checks, and independent P0-P2 autoreview. Integrated types and changed gates remain with the parent task owned dependency install.

* fix: keep skill metadata with its captured content hash

Read the selected skill file once during traversal and reuse those bytes for its content hash and frontmatter. Keep candidate priority and digest records unchanged while streaming support files.

Remove the internal byte-or-hash compatibility shape from package inventory entries. Migrate the E2E fixture and use the existing buffer digest owner for the bounded small-file path.

Validation: 82 focused package, skill lifecycle, and first-hop fixture tests; metadata mismatch regression failed against the previous commit; focused lint and format checks; cumulative independent P0-P2 autoreview clean. Final interleaved synthetic runs retain the 256 MiB to about 2 MiB payload allocation reduction. Integrated types remain assigned to the parent task owned install.

* fix: preserve literal tilde names in skill snapshots

Pass listing-derived skill paths to fs-safe through the retained canonical root. This keeps literal tilde directories from expanding to the user home while preserving root confinement and link admission.

Validation: the extended artifact digest fixture fails on 7579ed1d7723 and passes with the fix; 31 focused skill snapshot and lifecycle tests, lint, formatting, whitespace checks, and independent P0-P2 autoreview pass.
2026-09-12 19:41:19 -07:00
Ayaan Zaidi
535fcd9ea8
fix(config): preserve root and recovery backups after failed saves (#146291)
## What Problem This Solves

Fixes root config write regressions introduced by #145983: failed config saves could remove the root and recommend a destructive retry, or discard recovery backups before staging succeeded.

## Why This Change Was Made

Root and included-file saves share staged publication and safe restoration. Backup bytes are prepared asynchronously; rotation follows successful staging. Partial failures report the original error, recovery status, and backup location. The writer rechecks captured include path identities during publication and restoration. Backup permissions change only through admitted regular-file descriptors.

The decision `which backup files may be mutated` is made by exactly one mechanism at `src/config/backup-rotation.ts:78`.

The decision `whether captured include paths are unchanged` is made by exactly one mechanism at `src/config/io.write-safety.ts:80`.

## User Impact

Failed staging preserves all five recovery generations. Interrupted saves restore the original file when safe. Gateway clients receive complete recovery details. Cancelled login and setup writes retain the cancellation reason.

## Evidence

Before: permission-denied fallback plus a concurrent include edit removed the root; following retry advice lost Gateway settings and cold startup failed. Five disk-full saves consumed the backup history. The same CLI scenarios now restore the root, preserve all five root and include backups, and retain Gateway settings on the next save. Authenticated cold health passes; a wrong token is rejected. All three Gateway save methods return complete structured recovery failures. Aliased includes survive denied rename, validate, and cold-start; linked backup targets retain their bytes and permissions. Detailed consumer coverage is retained in `proof/consumers.md`.

## Compatibility

No config keys, stored formats, protocol schema, or protocol version change. Partial publication failures use the existing `UNAVAILABLE` outcome. Plain-root legacy mutation adapters retain their supplied revision; include-bearing adapters without a committed snapshot use the existing unknown revision and can refresh before their next edit.

## Consumers

- Config CLI saves preserve root and include recovery backups, including through symlinked includes, and report restoration outcomes.
- Gateway `config.set`, `config.patch`, and `config.apply` preserve complete recovery messages and structured details.
- Login and service-install writers check live authority immediately before file effects.
- Deferred chat and Telegram native login consent recheck retained flow and caller authority at publication.
- Gateway setup activation carries cancellation through the shared config writer.
- Legacy include mutation adapters receive an unknown revision when no committed composite revision is available.

<details>
<summary>Internal call migration</summary>

The counts below refer to retired adapters and synthetic test-fixture fields. Filesystem options, the public authority callback, and real token/version contracts remain supported.

census: generic assertConfigPathForWrite reviewed — 0 callers listed
census: generic chmod reviewed — 0 callers listed
census: generic copyFallbackOnPermissionError reviewed — 0 callers listed
census: generic copyFile reviewed — 0 callers listed
census: generic dirMode reviewed — 0 callers listed
census: generic fileSystem reviewed — 0 callers listed
census: generic maintainConfigBackups reviewed — 0 callers listed
census: generic mkdir reviewed — 0 callers listed
census: generic open reviewed — 0 callers listed
census: generic overwrite reviewed — 0 callers listed
census: generic promises reviewed — 0 callers listed
census: generic rename reviewed — 0 callers listed
census: generic tempPrefix reviewed — 0 callers listed
census: generic to reviewed — 0 callers listed
census: generic token reviewed — 0 callers listed
census: generic unlink reviewed — 0 callers listed
census: generic version reviewed — 0 callers listed

</details>

## Invalidation

Existing config watchers and runtime refresh remain unchanged. Captured path facts are scoped to one write and its restoration. Failed saves publish no success acknowledgement.

## Contention

Backup preparation yields to unrelated Gateway requests. With a 2,000 ms injected preparation delay, an unrelated health request completed in 90 ms (limit: 1,000 ms). Candidate staging, backup renames, and final checks stay synchronous.

## Tests

374 targeted config-owner and CLI tests passed, including linked backup slots, alias fallback, alias replacement, and missing-parent repair. Registered `openclaw config set`, `config.set`, `config.patch`, `config.apply`, `models.authLogin`, and `wizard.next` cover config writes. Provider login is synthetic. Service-token/install tests use a mocked writer and prove forwarding and refusal, not native service effects. Package-entry consumers cover legacy revision compatibility.

CI hits the same `server-startup-finish.ts:416` type error as [main run 34718269980](https://github.com/openclaw/openclaw/actions/runs/34718269980), introduced by #146275. The config tests, formatting, line limits, assertions, and unused-export checks pass.

Follow-up: Settings reload/save after a missing root can create defaults; that existing UI behavior is tracked separately.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-09-13 08:08:24 +05:30
Peter Steinberger
c07d8a3588
fix(update): continue repair under the owning driver and reconcile dead drivers (#146514)
Allow update repair to continue under its owning driver. Reconcile a dead driver
and restore the Gateway Doctor stopped, recording one takeover fact even when
the owner already terminalized its row. Refuse a live foreign driver with its
identity and actionable diagnostics. Verify Windows ancestry against PID reuse
and retain continuation authority through native task recovery and restart.

Reported via the 2026.9.4 feedback round-up (three operators on 9.3→9.4 dead-ended at "update parent owns Gateway activation").

Validation includes fail-before/pass-after continuation, owner-death and Windows
fence regressions, focused tests, changed-file checks, independent Codex review,
and exact-head CI. Native Windows recovery traces and a final-candidate
published-driver continuation cell remain explicit proof gaps.
2026-09-12 18:46:35 -07:00
Peter Steinberger
3c34fffbf7
fix: preserve custom-plugin sibling imports during updates (#146616) 2026-09-12 18:31:09 -07:00
Peter Steinberger
5c815031c3
fix(cron): recover automations after plugin reloads (#146582)
* fix(cron): recover automations after plugin reloads

Refresh retired script preparation once before execution, preserving the admitted run and deadline. Report failed setup recovery with a closed actionable cause. Group repeated failures into durable incidents and announce only verified recovery, preserving unresolved payload failures across quiet trigger checks.

* fix(cron): reconcile alert incidents during restart recovery

Restore incident state from durable completed runs without replaying historical notifications, including quiet trigger checks. Keep recovered notification traces from reopening the failure cooldown. Cover failed job-row writes followed by restart and recurrence. Extract existing fixtures and event helpers to retain lint limits.

* test(gateway): expect typed plugin retirement errors

* test: match explicit plugin argument in upgrade fixture
2026-09-12 18:29:17 -07:00
Peter Steinberger
292e1618d9
fix(gateway): classify opening timeouts and repair lifetime checks (#146508)
* fix(gateway): classify websocket opening timeouts for recovery

* test: close media handles in cloud dispatch policy proof

* fix(test): serialize mock resolution in the Vitest owner
2026-09-12 17:13:42 -07:00
Ayaan Zaidi
65c9f24448
fix(models): refresh expired provider inventory in background (#146317)
## What Problem This Solves

New provider models stay hidden after saved inventory expires, until an explicit refresh.

## Why This Change Was Made

#136915 removed repeat acquisition when it reused prepared catalogs. This restores expiry-driven discovery without making readers wait. @steipete for awareness.

Production +199/-105 (net +94); test tooling +7/-4; tests/support +214/-6; docs +5. Growth carries original cache deadlines through the existing acquisition path; duplicate normalization and separate inventory maps are removed.

## User Impact

Reads return saved rows immediately, then show new models after renewal. Failed providers keep saved rows and their warning while healthy siblings renew.

## Evidence

Telegram/Gateway with synthetic responses: main kept 8 rows after expiry; saved rows returned in 90 ms, then the ninth appeared. CLI agrees. Post-login reply: 67 ms. 16 valid config shapes started; invalid legacy input rejected. Getter-backed results retain accepted rows. Full consumer details: `consumers.md`.

## Compatibility

No config keys, database changes, migrations, or public plugin API changes.

## Consumers

- `models.list`, CLI, selectors, `/models`, `/think` menus, and sticker vision: renewed metadata.
- Public agent-runtime getters and setup-shell thinking defaults: saved metadata can start background renewal.
- `models status`: renewed metadata for visibility.
- Chat metadata publication listener: invalidates cached metadata after renewal.
- Catalog warnings: persist until the failed scope succeeds or its inputs change. CLI row output omits the warning.

census: generic refreshCommittedProviderCatalogs reviewed — 2 callers listed
census: generic error reviewed — 0 callers listed

## Invalidation

Cache hits and compatible reloads preserve deadlines. Changed credentials, provider settings, or plugins retire old facts. Restart rebuilds inventory. Explicit refresh retries failures; native refresh retains its scope.

## Contention

Existing discovery queue and pending request; concurrent reads return saved rows during a held response.

## Tests

Registered `models.list`: expiry, accepted projection, held responses, coalescing, failed siblings, warning recovery. Reload-auth cases: startup/reload publication and snapshot access. Startup-static and test-harness edits produce reply fixtures. Owner/cache checks pass; the test runner prepares the SDK runtime first. Structural checks pass.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-09-13 05:21:29 +05:30
Peter Steinberger
54a986072f
docs(plugins): remove obsolete Gateway restart guidance (#146516)
* docs(plugins): remove obsolete Gateway restart guidance

* docs(plugins): simplify apply hints and update Session Share guidance
2026-09-12 16:48:13 -07:00
Peter Steinberger
a9d273dc5f
fix(plugins): preserve update failures and prevent duplicate settlement (#146483)
Preserve the original plugin update failure when rollback also fails, keeping rollback errors as additional diagnostics. Consume completed managed install transaction handles and share successful or concurrent settlement, while retaining retryability after failed rollback in the existing recovery owner.

Regression evidence covers primary-error propagation through update finalization and the CLI, handle consumption across managed install sources, and duplicate/concurrent settlement. The authoring lane recorded failing-before/passing-after regressions and 356 passing focused tests; exact-head CI passed. Published-driver × candidate installation smoke remains a disclosed validation gap accepted for this scoped landing.

Fixes #146435
Refs #146434
Reported by @aniruddhaadak80 (#146435, #146434).
2026-09-12 15:17:37 -07:00
Peter Steinberger
5278a8f2ed
feat: share selected sessions read-only with a paired team Gateway (#136253)
* feat(node-host): advertise an explicit node command allowlist

Persist exact node command selection and restrict ancillary publication and hosting. Preserve the unchanged assertion baseline under the work-order stop rule; check:changed requests removing the obsolete runtime.ts count (2 to 0).

* feat(plugin-sdk): session transcript catalog reader

Expose bounded read-only native display pages and portable attribution through the existing runtime subpath. Keep pagination scoped to the original active transcript branch and allow an explicit bounded native cursor length.

* feat(session-share): read-only OpenClaw session catalog across paired gateways

Publish explicitly selected native session groups through two paired node commands. Validate the closed wire contract, reject remote profile claims, and keep receiver identity binding opt-in and display-only.

* fix(gateway): show published session catalogs to view-scoped roles

Let publication consent satisfy catalog read visibility for roles allowed to view others, while owner-only and unprofiled callers stay hidden. Preserve published attribution without accepting a remote local-session adoption claim. Regression tests reproduce four pre-fix failures; final validation stopped at the work-order baseline gate.

* docs: session sharing across gateways

Document sessions-only node setup, explicit publication groups, receiver attribution, view-scoped catalog access, and read-only limits. Add the bundled plugin inventory and generated reference entry. Live proof runbook remains outside the repository; build and rig execution are blocked by the work-order baseline restriction.

* fix(session-share): preserve source storage and paired reconnects

Respect configured stores through listing, paging, and revocation. Keep cold listings available and bound raw transcript reads. Prefer the established paired node credential on service restart, suppress unrelated host metrics, and refresh the approved plugin configuration docs.

* refactor(gateway): separate authorized catalog reads

Keep the catalog dispatcher within its owned scope and preserve post-read role checks and sender projection. Align the rebased tests with their shared setup and imports.
2026-09-12 13:35:17 -07:00
Ayaan Zaidi
8e54ce49af
fix(backup): preserve cyclic symbolic links during archive creation (#146161)
## What Problem This Solves

A state directory containing `loop-a -> loop-b -> loop-a` makes `openclaw backup create --verify --json` fail with `Private update capture marker is unreadable; export refused.` No archive is created.

## Why This Change Was Made

The decision `whether a selected path is a private update-capture location` is made by exactly one mechanism at `src/infra/update-capture-paths.ts:151`. It resolves links component by component with `lstat`, cycle detection, and a depth limit, retains each selected entry name for legacy capture ownership, and checks real selected and resolved directories for privacy markers. The separate canonical scan is removed.

Resolved marked targets remain excluded. Linked directory owners and capture-root aliases still protect legacy capture contents. SQLite snapshots use the same assertion before copying selected contents. The separate update-time backup work in #144005 writes privacy markers and uses this classifier.

## User Impact

Cyclic and dangling links no longer prevent backup creation. Their original link text is preserved. Marked targets and private capture contents stay out of archives, while ordinary unmarked links retain the behavior from #141925.

## Evidence

- Pinned main `c1a39f89`: real CLI exits 1 with the reported error and no archive. Head `6c58557e`: cycle/dangling creation, verification, and restoration succeed with exact links and payload.
- The marked-target archive omits the link and private bytes, then verifies and restores on v2026.9.4. A linked sibling owner also excludes legacy capture contents. Malformed and unreadable real markers refuse without publishing an archive.
- Head `057dbc07`: config selected through a private capture-root alias refuses export with no archive. A containing-workspace archive omits the alias and private bytes, then verifies and restores on both current code and v2026.9.4 with healthy bytes intact.
- All 199 targeted tests passed, including component ordering, repeated links, trailing separators, archive privacy, and support exports. Complete dispositions and compatibility details are retained in `consumers.md`.

## Compatibility

The archive format is unchanged. Capture-root alias and marked-target archives restore on v2026.9.4 with zero links and exact healthy bytes. Plain and portable relative-link archives retain their passing compatibility checks.

Only cyclic/dangling-link output receives the additional old-reader allowance. v2026.9.4 cannot restore preserved cycles and reports `Backup restore failed; the incomplete target was cleaned: <restore-target>`; the updated reader restores them. Existing restrictions on ordinary absolute links predate this fix. No shim is added. Focused CLI proof runs on macOS; Windows junction coverage depends on CI.

## Consumers

- Backup inventory and archive creation preserve unresolved links while excluding resolved private targets and real private ancestors.
- Legacy capture exclusion recognizes sibling owners and capture roots reached through directory links.
- SQLite archive snapshots apply the same content admission before capture or reuse.

## Invalidation

None. Each call inspects current filesystem metadata; no cached classification or persistent state changes.

## Contention

No lock, queue, transaction, or asynchronous publication changes.

## Tests

`backupCreateCommand` and `backupRestoreCommand` cover marked-target omission, linked-owner exclusion, capture-root alias refusal, loop/dangling preservation, and restored bytes. Real and resolved marker refusals remain covered. The canonical database alias test retains refusal of an incomplete hardlink inventory and the unmarked sanitation control. No tests were deleted.

**Follow-ups:** Add command-level coverage for path-resolution edge cases and test path separators on native Windows.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-09-13 00:28:18 +05:30
Peter Steinberger
d1682a0118
fix(gateway): exit cleanly when native shutdown drains time out (#146217)
Bound Gateway stop and restart drains under systemd and launchd to the native service deadline. If in-flight calls still ignore cancellation, record the abandoned work categories and stability diagnostics, exit cleanly, and let the supervisor start a fresh process for a requested restart. Never reuse an abandoned runtime for in-process recovery.

Preserve failure status for foreground shutdown timeouts and explicit server-close failures, including when final provider cleanup crosses the native deadline. An already-running older Gateway retains its old shutdown implementation on the first update hop.

Proof: all 100 run-loop tests passed; the two native close-failure regressions failed before the fix and passed afterward. Changed-file typechecks, targeted lint and selected guards passed. Exact-head CI run 34711135007 passed, and independent fixup review found no actionable P0-P2 issues. Existing Linux systemd behavior proof is recorded in the PR; live launchd and published-driver upgrade proof remain stated limits.

Fixes #146110.
Reported by @waynegault (#146110).
2026-09-12 11:43:46 -07:00
Peter Steinberger
d945743bb2
perf(status): reuse scan snapshots and expose local stage timings (#146228)
* perf(status): reuse scan snapshots and expose stage timings

* test(status): complete probe session fixtures
2026-09-12 11:02:47 -07:00
Peter Steinberger
edc70e2209
fix(update): let JSON failure diagnostics finish before exit (#146229) 2026-09-12 10:58:37 -07:00
Peter Steinberger
d0422c7829
fix(tts): avoid synthesis for unsupported remote output (#146222) 2026-09-12 10:53:20 -07:00
Peter Steinberger
f1bd0471f2
fix(update): recognize custom npm prefix installations (#146091)
Recognize npm ownership for custom prefix installations such as nvm with ~/.npm-global when global-root probes disagree and the prefix has no npm executable. Use npm's configured prefix and the installed OpenClaw launcher, share the resolver with update status, and include inspected paths in unknown-owner refusals. Windows npm shims resolve their package entrypoint instead of the earlier node.exe check.

Keep update target selection on the running package prefix. Older installed updaters still need the explicit NPM_CONFIG_PREFIX workaround for the first hop. Full published-driver-to-candidate upgrade preservation remains unverified; focused ownership, target-selection, status, and CLI admission tests pass, including the failing-before/passing-after complete Windows shim regression.

Fixes #146038

Reported by Discord user Rex Horizon in the support thread "As usual update fails" (#146038).
2026-09-12 10:45:40 -07:00
Peter Steinberger
f76ad6aec4
fix(status): avoid database copies during ownership checks (#146213)
* fix(status): avoid copying agent databases for ownership checks

* refactor(state): reuse schema table introspection

* test(state): accept quoted missing-column diagnostics
2026-09-12 10:41:01 -07:00
Peter Steinberger
ebb6b2af74
fix(update): avoid rejecting equivalent systemd unit names (#146090) 2026-09-12 08:39:14 -07:00