* fix(startup): keep legacy state repair in doctor
Separate current-state startup readiness from explicit Doctor migrations.
Preserve current config recovery, quarantine, device identity checks,
lease fencing and updater completion ownership.
Remove automatic startup migration/checkpoint and node-host import paths.
Keep shipped read-only context and roster projections unchanged.
* test(doctor): align proof callers with repair ownership
Keep survivor fixture setup in caller order and select the shared Doctor
flow separately from the channel-specific proof. Include the complete
isolated diagnostics dependency closure.
Prove ordinary startup preserves legacy directories before explicit
Doctor repair, and await SQLite worker closure before test cleanup.
* test(startup): verify index repair through gateway maintenance
* test(doctor): align cutover fixtures with state owners
Reacquire the database after Doctor retires its generation, retain real session history for startup refusal, and keep pending reads at their actual owners. Distinguish the reused readonly reader from independent snapshot-token children and verify every child settles.
* fix(doctor): preserve image activation and published migration receipts
Run the shared noninteractive Doctor owner before default and Compose Gateway
activation so retained Docker volumes keep their published upgrade path while
ordinary Gateway startup stays readiness-only. Preserve root selectors and
settle interrupted repair before executing the original command.
Retain the path-wide tombstones emitted by the published restart-sentinel
importer, including consumed notices, and validate completed source decisions
before retiring recreated inputs. Add the root-image activation lane and causal
receipt coverage without introducing a schema, option, or second importer.
* test(docker): preserve release state pairs in upgrade proof
Use the existing synthetic v2026.9.2 corpus instead of combining a July shared database with a later agent schema. Preserve its deletion journal, registry, both transcript payloads, paired backups, and unsafe-state controls. Register the two shell-launched helpers with Knip.
* test(docker): normalize persisted schema snapshot rows
Compare node:sqlite schema rows using the same plain-object representation as the saved JSON preimage. Keep strict schema, row, and value-type assertions intact.
* fix(models): retain discovered models after refresh failures
Record successful legacy catalog results at the producer boundary so unavailable refreshes retain the accepted inventory. Preserve explicit outcomes, advisory SDK fallback behavior, and first-discovery starter policy.
* fix(models): preserve skipped catalog outcome semantics
Mark bundled static, configured, and advisory catalog projections with
explicit empty outcomes so legacy success inference cannot promote them
to observed account inventory. Preserve live outcomes and helper types.
Keep exact auth provenance histories and move existing fixture/policy
code into focused owners where required by the line-cap ratchet.
Validation: 447 producer and sibling cases, 56 shared self-hosted cases,
95 auth/policy cases, causal missing-outcome failures, maintained checks,
and independent review.
* test(plugin-sdk): keep discovery loader types acyclic
Move the shared loader type into a leaf consumed by both discovery
contract helpers. Preserve its public provider-test-contracts export
without a child-to-parent type import cycle.
Validation: maintained Madge check reports zero cycles; core, all core
test graphs, extension test types, lint, formatting and independent
review pass. Runtime behavior and previous catalog proof are unchanged.
* fix(plugin-sdk): mark generated static catalogs explicitly
Keep the generated non-live, non-strict catalog adapter from claiming
successful acquisition for manifest or configured rows. Preserve null,
errors, strict and custom callbacks, static catalogs, and public types.
Validation: three existing controls fail before the correction; all49
owner and sibling cases pass afterward, with types, lint, line caps and
fresh independent review clean.
* test(gateway): cover restart import during state retirement
Exercise canonical database close while a legacy notice read is paused. Verify admission rejection, retained canonical and source bytes, no migration receipt, and joined maintenance custody without changing the accepted sidecar-stop drain contract.
* fix(test): drain sharing fixtures before removing state
* test: bind retirement regression to its own worker
* docs(docker): clarify automatic Doctor activation
* test(doctor): keep readiness fixture runtime private
* test: stabilize shared skill watcher fixture roots
(cherry picked from commit 15606be10e)
* perf(tooling): share indexed scope parsing for artifact scans
(cherry picked from commit 6e6eef9f5b)
* fix(team-reports): use source owners in scheduler tests
The source barrel retired in #157819, but the scheduler tests still imported
it, breaking the extension test typecheck on main. Import the Discord and
GitHub owners directly, matching the production caller.
Validated the original TS2307/TS7006 failure, the corrected extension type
graph, all 36 scheduler tests, changed checks, and independent P2 review.
(cherry picked from commit 7c4866c73b)
* test(install): isolate global npm configuration in version fixtures
Use a controlled absent global config inside the fixture home so the
release helper does not query the deliberately narrow npm stub. Keep
predecessor selection, fresh-install behavior, and expected exits intact.
(cherry picked from commit 0a9eefc76c)
* test(docker): verify the complete image activation entrypoint
Include registered archive installs in the existing host-link repair owner so Doctor and post-update convergence can recover stale or dangling SDK links without the original archive. Preserve canonical install-root, path ownership, and lifecycle authority checks.
Reserve busy plugin replacements before gating new agent work, then let
admitted runs finish on their original instance before teardown. Report
queued retained work and completed publication through existing diagnostics.
Preserve the 60-second pre-stop budget, timeout recovery, and shared-resource
cleanup before replacement registration. Cover overlapping runs, installed
version publication, and retained cleanup without introducing configuration.
* refactor: remove TypeScript 6 from plugin runtime and tooling
Keep source plugin loading on Jiti and native module transforms, move development analysis and declaration builds to TypeScript 7, and preserve captured loader and input ownership contracts. Scaffolds compile to the same entry path without shipping a compiler in production.
* refactor: use native checker for restart preflight detection
* fix: keep test-directory docs out of native helper scans
* fix: preserve native compiler tooling across CI runtimes
Keep compiler-backed tests on the supported Node transport, preserve declared Windows aliases and partial-source analysis, and bind relocated SDK reports to their installed compiler. Retain strict package input admission and the existing fixture assertions.
* test: compare messaging guard diagnostics without sorting
* fix: bound native tooling memory and preserve bootstrap loading
* fix: bound native declaration builds with tsdown scheduling
* fix: retire compiler-only helpers from installed packages
* test: migrate routing import scan to native parser
* test(ui): wait for recovered model catalog receipt
* fix(plugins): show the selected entry after reload
Expose the loader-owned selectedEntries map in runtime receipts. Add bounded CLI and tool guidance to rebuild compiled output after source edits while preserving success and restart outcomes.
* fix(protocol): sync generated plugin reload receipt
Regenerate the protocol outputs for optional selectedEntries. The Swift model gains the field, default-nil initializer argument, and wire coding key; Kotlin outputs remain unchanged.
* fix(plugins): report reloads that still require a Gateway restart
Project captured-source facts into plugin runtime receipts so compiled bundled
registrations cannot imply that edited code was swapped. Preserve the restart
requirement through Gateway responses, CLI batches, and compact tool guidance,
while retaining live generation and captured source digests.
Keep external workspace code on the existing generation replacement lifecycle.
Extract the lazy reload command and receipt construction without changing drain
or recovery ownership. Cover unchanged bundled code with a restart-required
regression and verify real CLI/tool reloads on isolated Gateways.
Fixes#156699. Thanks @Loganwoooof for the digest-based proof.
* fix(plugins): avoid restart warnings for unchanged code
Record the original artifact fingerprint with shared module identity. Report a restart for explicitly reloaded code only when a retained module has changed or unverifiable files, while preserving successful channel ownership hand-offs and recovery facts.
## What Problem This Solves
Legacy ClawHub ZIP archives can be rejected when the separate preflight parser and the extractor interpret their filenames differently.
## User Impact
ClawHub verifies the extractor's canonical filenames and SHA-256 hashes before installation. A native-backed CP437 archive that previously failed now installs when its files match the advertised metadata. Harmless backslash aliases may normalize to those exact paths, and root-only records that produce no output are ignored. Unsafe paths, collisions, missing or changed files, extra files, named unsupported records, and archive limits remain enforced.
## Why This Change Was Made
The released extractor's existing entry callback supplies the complete canonical inventory, including named records that extraction cannot materialize. Verification hashes the observed regular files in the fresh, unstripped extraction workspace and retains unsupported records without a digest so they cannot disappear from integrity checks.
This removes the second ZIP read/parser and the later directory walk, reducing production code by 48 lines without adding a library API or changing configuration or stored formats. Server-provided paths and generated `_meta.json` validation remain strict. The install documentation records the canonical-name behavior.
## Evidence
- The real native-backed installer CP437 case failed before this change and passes afterward. Synthetic archive proof also covers canonical aliases, inert root records, named unsupported entries, complete inventory/hash matching, unsafe paths, archive limits, cleanup, and installation authority.
- Focused proof passed 146 tests in 33.20 seconds wall time. The changed ClawHub suite measured 107 tests in 23.77 seconds wall time; the final CI repair rerun passed the same 107 tests in 38.04 seconds of wrapper time.
- All 14 affected checks passed in 181.69 seconds. The assertion-safety baseline shrinks exactly from 7 to 5; no boundary waiver or policy exception was added.
- CI identified a facade export retained only by a negative test spy after its production caller was deleted. Both are now removed; the real installer assertions for single extraction, lost authority, absent persistent installation, and cleanup remain. The exact full production and all-export dependency scans now pass, along with affected type, format, and lint checks.
- Fresh independent scoped reviews found no actionable findings. Lead review checked the released extractor's planning/publication guarantee and the final implementation.
- Proof uses synthetic archives and the actual installer on macOS. No live ClawHub service or Windows execution is claimed.
* fix(plugins): report incomplete installs before capability consent
* fix(plugins): repair install-health test and type boundaries
* fix(doctor): preserve recorded plugin recovery selectors
A plugin generation replacement stopped the previous plugins' services and
channels before it learned that a plugin's admitted work would never settle;
the stop failure then disabled recovery and left the old generation
half-stopped with a stale model runtime, so unrelated Gateway requests
returned UNAVAILABLE indefinitely (team.openclaw.ai, 2026-09-17 22:10 UTC).
Wait up to 60 s for the replaced plugins' admitted calls before anything
irreversible, fail once through the existing pre-stop rollback when they do
not settle, admit channel account monitors as retained consumers like plugin
services so the call-only wait cannot block on them, and republish the
prepared model runtime after every uncommitted failure.
Fix updates and repair aborting during plugin finalization when plugins.load.paths selects a local copy over an npm installation. The plugin ownership resolver classifies that source as operator-managed for maintenance, preserving both the selected payload and its shadowed install record while recording an actionable plugin-operator-managed warning in the outcome and update history.
Channel startup recognizes typed plugin-trust refusals and records the existing terminal state instead of repeatedly retrying. Doctor and update status expose the source and supported installation remedy. Package ownership and plugin trust requirements remain unchanged.
Published OpenClaw 2026.9.4 driving the candidate completed plugin finalization with a persisted warning and unchanged local/npm payloads. The subsequent service refresh failed in a separate dependency-resolution path; complete update success and fixed live repair/channel startup remain unclaimed. Exact-head CI run 35360153214 is green, and all three rebased commits are patch-identical to the scoped-clean review of record.
Fixes#151794. Related: #151795.
Thanks @WhitenessTiger for the reproduction and ownership/trust analysis.
Reuse node version labeling for marketplace list, plugin search, and skills search so already-prefixed versions and opaque build names keep their labels. Numeric versions still gain v; JSON values and install references stay unchanged.
Move marketplace listing and skills search into their own command modules, removing the superseded inline implementations while preserving lazy loading, parent JSON options, and skills text sanitization. Extend command-boundary regressions and retain node status/describe coverage.
Final proof: 185 focused tests, the complete selected gate, fresh P0-P2 review, and six actual CLI calls passed. All three JSON outputs were byte-identical to baseline.
Refs #145975.
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).
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).
* fix(plugins): recover reloads and release retired resources
Restore native Bun dependency resolution, runtime-only refresh, channel
status and cold-account handling. Return contention before Gateway plugin
or Claw-package mutations start, retaining receipts for later failures.
Keep slow service startup cleanup with its lifecycle owner, restore
LanceDB service state on rollback, and retain CLI cleanup warnings.
Remove obsolete generation retirement and duplicate package resolution.
Related: #145484, #145649
* test(gateway): verify startup capability reconnects with real sockets
* fix(agents): release queued preparation before gateway retirement
* fix(plugins): preserve cleanup ownership and machine-readable reloads
* refactor(gateway): group reload recovery proof by lifecycle owner
* fix(plugins): preserve require context on older Bun runtimes
* fix(agents): return explicit queued cleanup completion
Git/dev installations keep the plugin rebuilt from the running source checkout instead of refreshing a same-version npm build with a different Plugin SDK. Doctor records why the registry artifact was not admitted.
Manifest-registry selection owns bundle precedence and dormant install detection. Named plugin updates, --all, and stable/beta release-cohort convergence carry that decision through package-mutation preflight while retaining strict checks for active packages. Existing npm records remain available, explicit plugin paths retain priority, and package-host updates retain their registry behavior.
Fixes#145266
Thanks @DonnieFi for reporting the artifact skew and providing the reproduction evidence.
`docs/cli/plugins/install.md` still described bare plugin specs as installing
from npm "during the launch cutover". There is no cutover: `grep -rni cutover src/`
returns nothing, no flag, date or feature gate exists, and no release note announces
an end. The phrase entered in cf21bcf9bf, which deleted the ClawHub-first
resolution path outright rather than scheduling a migration. Present behaviour is
`isOpenClawTrustedPluginInstallSpec` in `src/plugins/install-provenance.ts`.
Drops the time-relative clause and leaves the behaviour statement, matching the
phrasing already used in docs-audit/fix-accuracy-plugins for the six pages under
`docs/plugins/`.
Structure-only changes: no prose is added or reworded beyond the new
heading titles themselves. Every published anchor id is preserved.
- cli/doctor/checks.md: split the 42-bullet `## Notes` list into nine
H3 groups so individual checks are addressable.
- cli/doctor/sqlite-maintenance.md: sentence-case the one Title Case H3
(slug unchanged).
- cli/mcp/registry.md: move `Saved MCP server definitions` directly after
the intro that introduces its command list; `Codex tool approvals` now
follows it.
- cli/plugins/install.md: promote the nine collapsed accordions to H3
sections (they carry scope gates, `--force`/`--pin` semantics and
install-policy rules), lift the source/locator prose above them, and
head the trailing local-path run.
- cli/plugins.md: add the body H1 used by the other CLI command pages.
- cli/update/how-updates-run.md: add per-topic H4s inside
`Restart handoff`, promote `Plugin sync details` out of
`Git checkout flow`, and head the package-manager install text that was
sitting inside the Git checkout section.
- cli/onboard.md: give the flag list its own `## Flags` heading and demote
`Additional non-interactive flags` under `Non-interactive setup`.
- cli/approvals.md: move the `openclaw exec-policy` section after
`Common options` so the page opens on the command it is titled for.
- cli/infer.md: move the "turn infer into a skill" how-to off the top of
the reference page.
- cli/index.md: file `devices` with pairing/channels to match the sidebar,
and name the `automations` alias on the cron row.
- tools/tts/field-reference.md: drop the stray H3 nested inside the Inworld
accordion (its id is kept as an authored anchor) and lift the SecretRef
paragraph out from between two accordions.
- docs.json: drop the duplicate `tools/tts` nav entry, put browser
agent-tools before troubleshooting and existing-session beside profiles,
file `cli/wiki` with memory/models and `cli/openclaw` with onboard/setup.
docs/cli/plugins.md was 55,872 characters and 11 H2 sections mixing a CLI
synopsis, an authoring how-to, install-policy explanation, lifecycle
reference, diagnostics, and marketplace feed trust. It is now a short index
over six children, one per reader job:
- cli/plugins/authoring Author, Feature scaffold, Provider scaffold
- cli/plugins/install Install, Marketplace shorthand
- cli/plugins/list List, Plugin index
- cli/plugins/uninstall-and-update Uninstall, Update
- cli/plugins/inspect-and-diagnose Inspect, Doctor, Registry
- cli/plugins/marketplace Marketplace
The index keeps the intro, the CardGroup, the full `## Commands` synopsis with
its trace/Nix/bundled notes, and `## Related`.
Anchor strategy: per-anchor redirects are impossible, because redirectSource()
in scripts/lib/docs-redirects.mjs throws on any source containing [?#]. Every
original anchor therefore stays alive on the parent index as an authored
<a id="..." /> stub pointing at its new home. Ids were computed with
parseDocsDocument, not a slug approximation, so the nine Accordion titles, the
two Tab titles, and the three ParamField ids are covered alongside the
headings. 34 pre-split ids: 32 stubbed, 2 (commands, related) still published
by the index itself, so no duplicate authored/canonical ID is raised. All 34
verified to resolve on /cli/plugins, and all 32 stub targets verified to
resolve on their child page. Collisions are empty on the index and on each of
the six children.
Losslessness, asserted mechanically against the pre-split file:
- index prefix + the six children (frontmatter and lede removed) + index
suffix reassemble byte-identically, sha256
c462b672a341344fca6dc46d623f6136f337844080b97bd469faffacb12265f8
- fences 17 -> 17, every one identical on info string and body sha256
- table rows 6 -> 14 (+8 = the new index page table)
- links: 27/27 original targets retained
- words 7,266 -> 8,023 (+757 = index page table, anchor map, child ledes)
- index 55,872 -> 8,662 chars; children 3,935-22,363 chars
No prose was rewritten and no prose exception was needed. The page had zero
intra-page anchor links and zero self-route links, and the one directional
reference the orphan check finds ("the trusted plugin id replacement above")
keeps its target on the same child page.
Closes audit findings: r3-0126, r3-1163 (partially: the accordions keep their
authored anchors and are no longer buried under a 2,065-word H2)