Merge remote-tracking branch 'origin/worktree-agent-scope-design' into codex/package-readme-limitations-audit-20260712
# Conflicts: # packages/core/scope/README.md # packages/session-persistence/session-persistence-jsonl/README.md # packages/session-persistence/session-persistence-sqlite/README.md # packages/subagent/subagent-acp/README.md # packages/subagent/subagent-fork/README.md # packages/subagent/subagent-inprocess/README.md # packages/subagent/subagent/README.md # packages/subagent/tool-subagent/README.md # packages/support/invariants/README.md # packages/support/subagent-mock/README.md # packages/workflow/workflow-workerthread/README.md # packages/workflow/workflow/README.md
This commit is contained in:
@@ -8,26 +8,28 @@ This package owns the `ctx.skills` interface. It does not know whether skills co
|
||||
|
||||
### Public API
|
||||
|
||||
- `ctx.skills.registerProvider(provider): () => Promise<void> | void` Registers a provider by unique `provider.name`. Duplicate provider names throw, and `runtime` is reserved for `ctx.skills.register(...)`. The registry snapshots the name and callback identities at registration, so replacing those fields later cannot change lookup or HMR cleanup; callbacks remain bound to the original provider object and can still read its mutable state. The registration is effect-scoped and HMR-safe, and the exact Cordis disposer supports ordered composite teardown.
|
||||
- `ctx.skills.list({ cwd?, signal? })` Returns model-invocable skill summaries for the current workspace, merged across providers and sorted by name.
|
||||
- `ctx.skills.get(name, { cwd?, signal? })` Returns the full winning skill, including disabled-for-model skills.
|
||||
- `ctx.skills.register(skill): () => Promise<void> | void` Registers a runtime embedded skill. Same-name runtime registrations are first-wins: a duplicate logs a warning and gets a no-op disposer. Successful registrations return the exact Cordis disposer for ordered composite teardown.
|
||||
- `ctx.skills.registerProvider(provider): () => Promise<void> | void` Registers a readonly provider by unique `provider.name`. Duplicate provider names throw, and `runtime` is reserved for `ctx.skills.register(...)`. The registry borrows the provider object and invokes its methods directly. The registration is effect-scoped and HMR-safe, and the exact Cordis disposer supports ordered composite teardown.
|
||||
- `ctx.skills.list({ cwd?, signal? })` Borrows the readonly lookup options, then returns model-invocable summaries for the current workspace, merged across providers and sorted by name.
|
||||
- `ctx.skills.get(name, { cwd?, signal? })` Uses the same readonly options and winning candidate for discovery and loading, rechecks cancellation after discovery or a cache hit, races provider loading against the signal, validates the loaded definition, then returns it, including disabled-for-model skills.
|
||||
- `ctx.skills.register(skill): () => Promise<void> | void` Registers a readonly runtime embedded skill, adding `provider: "runtime"` when omitted. Same-name runtime registrations are first-wins: a duplicate logs a warning and gets a no-op disposer. Successful registrations return the exact Cordis disposer for ordered composite teardown.
|
||||
|
||||
### Config
|
||||
|
||||
| Field | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `collectCacheMaxEntries` | `128` | Maximum completed cwd/provider catalog snapshots kept in memory. |
|
||||
| `collectCacheMaxEntries` | `128` | Maximum completed cwd/provider catalogs kept in memory. |
|
||||
|
||||
## Provider Contract
|
||||
|
||||
A provider registers synchronously from its `apply()` and returns `SkillCandidate[]` from `list(options)` when discovery is requested. Registration copies `name` and binds the current `list` and `get` methods once; replacing those fields on the caller-owned object later does not rewrite the live registry entry, and disposal always removes the original name. Remote setup, authentication, and discovery belong in the awaited `list()` call rather than plugin registration. Providers should stop promptly when `options.signal` aborts; the registry also stops awaiting an uncooperative provider so agent cancellation cannot hang prefix composition. The provider later receives the winning candidate back in `get(candidate, options)`. The candidate's `locator` is opaque to the registry, so a local provider can store a file path while a remote provider can store a URL, id, or version token.
|
||||
A provider registers synchronously from its `apply()` and returns `readonly SkillCandidate[]` from `list(options)` when discovery is requested. The provider, lookup options, candidates, and loaded definitions are readonly same-process contracts: the registry borrows them rather than cloning, freezing, or rebinding callbacks. Remote setup, authentication, and discovery belong in the awaited `list()` call rather than plugin registration. Providers should stop promptly when `options.signal` aborts; the registry also stops awaiting uncooperative discovery and loading work so agent cancellation cannot hang prefix composition or skill loading.
|
||||
|
||||
The registry validates candidate names, descriptions, ranks, and provider ownership. Candidate contract violations fail fast because the provider plugin is malformed; a provider `list()` rejection is treated as a transient source failure, logged, skipped for that request, and not cached. Only completed catalogs are cached, and a provider/runtime revision change during discovery discards the stale result and retries. Duplicate skill names are resolved first-wins by `rank`, provider registration order, then the provider's own local order. The final summary list is sorted by skill `name` for deterministic consumers.
|
||||
The registry validates parsed provider candidates before caching them and validates loaded definitions before returning them. The winning provider receives the exact candidate and opaque `locator` identity it returned from `list()`; a local provider can therefore use a file-path handle while a remote provider can use a URL, id, or version token. Callers and providers must honor the readonly contract after handing values to the registry.
|
||||
|
||||
Parsed candidate and loaded-definition fields are validated at the provider boundary: names/descriptions/content use their declared string types, ranks are finite numbers, and `disableModelInvocation` is boolean when present. Candidate contract violations fail fast because the provider or its parser is malformed; a provider `list()` rejection is treated as a transient source failure, logged, skipped for that request, and not cached. Only completed catalogs are cached, and a provider/runtime revision change during discovery discards the stale result and retries. Duplicate skill names are resolved first-wins by `rank`, provider registration order, then the provider's own local order. The final summary list is sorted by skill `name` for deterministic consumers.
|
||||
|
||||
## Runtime Skills
|
||||
|
||||
`ctx.skills.register(...)` is a convenience for embedded runtime skills. Runtime skills use rank `250`: project providers can override them, while they override the shipped local provider's custom and user roots. Runtime registration is also first-wins within runtime contributions, so a duplicate contribution cannot remove the active one through its disposer.
|
||||
`ctx.skills.register(...)` is a convenience for embedded runtime skills. Runtime skills use rank `250`: project providers can override them, while they override the shipped local provider's custom and user roots. Runtime definitions and nested resource metadata are borrowed readonly; the service only materializes the top-level definition needed to supply the default `provider`. Registration is first-wins within runtime contributions, so a duplicate contribution cannot remove the active one through its disposer.
|
||||
|
||||
## Consumer boundary
|
||||
|
||||
|
||||
Reference in New Issue
Block a user