fix(skill): retain candidates across watcher failures
This commit is contained in:
@@ -10,7 +10,19 @@ Source: [`packages/skill/skill/src/index.ts`](../../packages/skill/skill/src/ind
|
||||
|
||||
`ctx.skills` combines local, embedded, remote, or other providers. Registration is synchronous; remote initialization and discovery belong in awaited `list()`. Provider objects, options, and candidates are borrowed readonly, while semantic fields are validated.
|
||||
|
||||
Duplicate names resolve by rank, provider order, then local order; summaries sort by name. A rejected `list()` is logged and omitted from an incomplete observation without caching it, while malformed candidates fail fast. Each provider factory receives a registration-scoped control whose `invalidate()` clears completed catalogs only while that exact registration remains active and whose signal aborts on failed registration or disposal. An in-flight discovery retries when its provider generation changes. Provider and runtime mutations emit the unfiltered `skills/change` invalidation event; it carries no diff, so consumers refetch `snapshot()` with their own lookup options.
|
||||
Duplicate names resolve by rank, provider order, then local order; summaries sort by name. A rejected `list()` is logged and omitted from an incomplete observation, while an explicit incomplete observation contributes usable candidates without making the result cacheable; malformed candidates fail fast. Each provider factory receives a registration-scoped control whose `invalidate()` clears completed catalogs only while that exact registration remains active and whose signal aborts on failed registration or disposal. An in-flight discovery retries when its provider generation changes. Provider and runtime mutations emit the unfiltered `skills/change` invalidation event; it carries no diff, so consumers refetch `snapshot()` with their own lookup options.
|
||||
|
||||
An array returned by `SkillProvider.list()` is complete-discovery shorthand. `SkillProviderObservation` lets a provider expose candidates that remain directly loadable while reporting that the observation is not authoritative.
|
||||
|
||||
```ts type-equiv
|
||||
/** Provider candidates plus whether the current discovery is authoritative. */
|
||||
interface SkillProviderObservation {
|
||||
/** Candidates available from the current provider discovery. */
|
||||
readonly candidates: readonly SkillCandidate[]
|
||||
/** Whether discovery completed and these candidates may be cached. */
|
||||
readonly complete: boolean
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/** Provider interface for one source of skills, such as local directories or a remote registry. */
|
||||
@@ -23,9 +35,10 @@ interface SkillProvider {
|
||||
* authentication, and discovery are awaited inside this method. Implementations
|
||||
* should settle promptly when `options.signal` aborts.
|
||||
* @param options - lookup options; `cwd` selects workspace-sensitive skills and `signal` cancels work.
|
||||
* @returns provider candidates with precedence ranks and opaque locators.
|
||||
* @returns provider candidates as a complete-array shorthand, or an explicit
|
||||
* observation when usable candidates came from incomplete discovery.
|
||||
*/
|
||||
readonly list: (options: SkillLookupOptions) => Promise<readonly SkillCandidate[]>
|
||||
readonly list: (options: SkillLookupOptions) => Promise<readonly SkillCandidate[] | SkillProviderObservation>
|
||||
/**
|
||||
* Load a complete skill body for a previously listed candidate.
|
||||
* @param candidate - the winning candidate originally returned by this provider.
|
||||
@@ -61,7 +74,7 @@ The shipped local provider scans roots in rank order:
|
||||
|
||||
The project root is the nearest ancestor containing `.git`; without one, the current cwd is used. When `ctx.fs` is available, the git-root walk probes `.git` through the filesystem service so remote or sandboxed workspaces do not fall back to the host filesystem boundary. The user DSH root skips its `.system` child. The local provider does not ship built-in system skills; deployments supply built-ins through another provider.
|
||||
|
||||
Chokidar watches existing roots for direct bundle/flat-entry additions and removals plus direct skill-entry changes. A missing root is followed one absent path segment at a time from its nearest existing ancestor until Chokidar can attach. Resource files below a bundle are not catalog changes. Model-facing `write` and `edit` observations synchronously invalidate the provider when their target is catalog-relevant, while the host watcher covers IDE, Git, shell, and external-process mutations. Watcher failures make the current observation incomplete; project-scoped watchers use a configured bounded LRU.
|
||||
Chokidar watches existing roots for direct bundle/flat-entry additions and removals plus direct skill-entry changes. A missing root is followed one absent path segment at a time from its nearest existing ancestor until Chokidar can attach. Resource files below a bundle are not catalog changes. Model-facing `write` and `edit` observations synchronously invalidate the provider when their target is catalog-relevant, while the host watcher covers IDE, Git, shell, and external-process mutations. Watcher failures make the current observation incomplete without hiding readable candidates from direct loads; project-scoped watchers use a configured bounded LRU.
|
||||
|
||||
## Skill identity
|
||||
|
||||
@@ -101,7 +114,7 @@ interface SkillSummary {
|
||||
```ts type-equiv
|
||||
/** One catalog observation plus whether every registered provider completed discovery. */
|
||||
interface SkillCatalogSnapshot {
|
||||
/** Sorted model-invocable summaries from providers that completed. */
|
||||
/** Sorted model-invocable summaries collected in this observation. */
|
||||
readonly skills: SkillSummary[]
|
||||
/** Whether every registered provider completed discovery for this observation. */
|
||||
readonly complete: boolean
|
||||
|
||||
Reference in New Issue
Block a user