* feat(plugins): default unprefixed packages to ClawHub
Use the shared source planner for CLI, chat, and assistant installs. Keep explicit npm and local sources, preserve canonical built-in shortcuts, and retain the selected registry in update and repair records.
Autoreview findings addressed:
- [P2] Preserve ClawHub provenance in search hints that match aliases
Route scoped packages through ClawHub and add @latest to ambiguous unscoped search hints.
- [P2] Preserve usable search hints for scoped names with file suffixes
Treat file-suffixed package names as registry specs, migrate source-selection tests, and retain npm in retry guidance.
- [P2] Update the remaining source-selection test expectations
Treat file-suffixed package names as registry specs, migrate source-selection tests, and retain npm in retry guidance.
- [P2] Keep npm prerelease retry hints on npm
Treat file-suffixed package names as registry specs, migrate source-selection tests, and retain npm in retry guidance.
- [P2] Restrict catalog shortcuts to canonical plugin IDs
Restrict bare shortcuts to canonical IDs and retain npm in shared hook-pack prerelease guidance.
- [P2] Preserve npm in hook-pack prerelease guidance
Restrict bare shortcuts to canonical IDs and retain npm in shared hook-pack prerelease guidance.
* docs(plugins): show ClawHub as the default install source
Update setup examples and generated inventory instructions to omit the ClawHub prefix. Document explicit npm selection and canonical plugin-ID shortcuts.
* fix(plugins): keep recovery tied to the selected source
* test(plugins): cover search commands and saved registry choices
* test(plugins): align pre-action recovery with selected sources
* test(plugins): prove source-bound recovery through the CLI
* fix(plugins): retain official identity during config recovery
Closes#158009
## What Problem This Solves
Fixes empty native OpenCode session catalogs and failed transcript/activity reads after upgrading the OpenCode CLI to v2.
## User Impact
OpenCode sessions remain browsable with either CLI generation, and failed CLI calls now leave a useful Gateway warning instead of only a generic catalog error. No configuration or stored-data migration is required.
## Why This Change Was Made
Detect the installed CLI major version. Keep the v1 database/export commands; use v2's global session API, session export, and bounded event-head probe. Normalize the v2 transcript at the plugin boundary so browsing and upstream human-turn detection share the same interpretation. V2 calls use a private standalone server, an empty temporary config directory, and disabled project configuration; the restricted subprocess environment remains in place.
V2 listing follows API cursors in batches of at least 100 until it has enough unarchived sessions. The complete scan shares the existing 30-second CLI budget and reports an error if exhausted, rather than returning a false empty catalog.
## Evidence
- Real OpenCode 2.0.16, installed from the official `@opencode/cli` package in an isolated prefix: baseline Gateway `sessions.catalog.list` returned no sessions and `LOCAL_READ_FAILED`; the invoked CLI rejected `--pure` and `--format`. The candidate lists both locally seeded sessions, and `sessions.catalog.read` returns the seeded user text.
- Real installed OpenCode 1.18.32 with isolated data: the same Gateway catalog RPC lists the seeded session before and after the change. Neither global CLI installation nor user OpenCode data was changed; no model inference was used.
- Real v2 activity probe: baseline marker established, one external user turn detected, unchanged cursor suppressed, and a confirmed missing session distinguished from read failure. This supplemental probe invokes the plugin activity owner directly; catalog listing and reading above use the actual Gateway RPC.
- Gateway logs now show `OpenCode catalog CLI failed: Error: Session not found: ses_missing158009` for a failed v2 transcript read.
- Focused catalog and activity suites: 37 tests passed, 30.97 seconds wall time including worker preparation. The v2 catalog regression fails against the unchanged baseline with `OpenCode exited with code 2`.
- V1/v2 transcript, activity cursor, transient failure, and missing-session coverage. Broader checks are left to CI.
- Archived-first real v2 store: two recently archived sessions precede one live session. With `limitPerHost: 1`, the earlier candidate returned an empty Gateway catalog; the repaired candidate follows the API cursor and returns the live session. The archived-first regression also fails before the repair and passes afterward.
- Archived-heavy real v2 fixture: 100 archived sessions precede one live session. The actual Gateway `sessions.catalog.list` request with `limitPerHost: 1` returned the live session in 2,430 ms. The regression also verifies that exhausting the shared scan deadline produces an error rather than an empty catalog.
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
* docs(plugins): mark generated reference pages and fix their shared template
Two generator files change; the other 153 files are their regenerated
output from `pnpm plugins:inventory:gen`.
- Emit a "generated, do not edit" banner naming the regeneration command
and the manual-block markers. None of the 151 reference pages said they
were generated, so a contributor edit was silently overwritten.
- Give generated reference titles a `reference` suffix. Eight of them
collided with a hand-written guide title (beam, geolocation,
google-meet, logbook, teams-meetings, webhooks, workboard,
zoom-meetings). Duplicate frontmatter titles across docs/ now total 0.
- Render the surface list as a list instead of a semicolon-joined
sentence, and use plain conjunctions for install routes. Strict STE
hard violations across docs/plugins/reference/ drop from 178 to 20.
- Drop the body H1, which duplicated the frontmatter title Mintlify
already renders.
- Fix a generator bug found while testing: the marker-less fallback in
`extractManualReferenceSections` matched only the first line under
`## Surface`, so a second `--write` run captured later bullets into a
fabricated manual block. `--write` is now idempotent and `--check`
passes across repeated runs.
All 12 hand-written manual blocks are preserved.
* test(scripts): follow resolvePluginSurface to its list contract
resolvePluginSurface now returns one string per surface item instead of
a semicolon-joined sentence, so the generator can render a list. The
four assertions move from toBe(<joined string>) to toEqual(<array>) and
pick up the capitalised labels.
The "generic fallback" case changes meaning rather than disappearing.
The empty manifest now yields [], and renderSurface() prints "This
plugin declares no channels, providers, commands, or contracts." for an
empty list, which tells a reader more than the old "plugin". The test
is renamed to say what it now checks, with a comment pointing at the
new home of the fallback.
No generated page has an empty Surface section, so no page changes
because of this.
* fix(plugins): import adopted catalog history into the OpenClaw transcript
Import native Pi and OpenCode history when a catalog session is adopted so the OpenClaw transcript reflects the full conversation immediately.
Mark imported user rows with mirrorOrigin because they are transcript mirrors, not new external turns. This preserves watcher deduplication and prevents adopted history from being reported as fresh upstream input.
* refactor(plugins): split catalog history importer
Keep the session catalog contract module leaf-like by moving transcript mutation into a dedicated runtime module. This breaks the registry-to-transcript import cycle while preserving the Plugin SDK entrypoint and importer behavior.