@cleocode/caamp 2026.5.84 → 2026.5.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-QSJSM57K.js → chunk-WXL7RPS4.js} +435 -47
- package/dist/chunk-WXL7RPS4.js.map +1 -0
- package/dist/cli.js +173 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +333 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/dist/chunk-QSJSM57K.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,339 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
1
2
|
import { WorktreeHandle } from '@cleocode/cant';
|
|
2
3
|
import { PlatformPaths, SystemInfo } from '@cleocode/paths';
|
|
3
4
|
export { PlatformPaths, SystemInfo } from '@cleocode/paths';
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* `skills doctor adopt-orphans` — interactive orphan audit + adoption.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* An "orphan" is a skill directory that exists under any tracked path
|
|
11
|
+
* (`~/.cleo/skills/`, legacy `~/.local/share/agents/skills/`,
|
|
12
|
+
* `~/.agents/skills/` as a real dir) but has NO row in the per-user
|
|
13
|
+
* `skills.db` registry described in
|
|
14
|
+
* `docs/architecture/SG-CLEO-SKILLS-architecture-v3.md` §4.
|
|
15
|
+
*
|
|
16
|
+
* The handler offers four per-orphan dispositions:
|
|
17
|
+
*
|
|
18
|
+
* - **canonical-adopt** — REFUSED on a user machine. Canonical writes
|
|
19
|
+
* must flow via PR to `packages/skills/skills/` (architecture-v3 §6
|
|
20
|
+
* invariant). The handler emits a refusal explaining the PR flow.
|
|
21
|
+
* - **user-adopt** — inserts a row into `skills.db` with
|
|
22
|
+
* `source_type='user'`, `lifecycle_state='active'`, `installedAt=now`.
|
|
23
|
+
* - **delete** — archives the directory to
|
|
24
|
+
* `~/.cleo/skills/.archive/<name>-<ts>/` before unlinking from the
|
|
25
|
+
* original location.
|
|
26
|
+
* - **skip** — no action; the orphan is logged but otherwise ignored.
|
|
27
|
+
*
|
|
28
|
+
* All decisions are recorded to a structured JSON audit log at
|
|
29
|
+
* `~/.cleo/skills/.audit-log/adopt-<ISO-ts>.json` regardless of mode.
|
|
30
|
+
*
|
|
31
|
+
* ## Chokepoint compliance (ADR-068)
|
|
32
|
+
*
|
|
33
|
+
* This module emits PURE DATA. The skills.db reads and writes are deferred
|
|
34
|
+
* to caller-supplied callbacks (`loadRegisteredNames`, `recordRow`). The
|
|
35
|
+
* `cleo` dispatch layer in `packages/cleo/src/cli/commands/skills.ts` plugs
|
|
36
|
+
* the canonical `openCleoDb('skills')`/`upsertSkillRow` helpers from
|
|
37
|
+
* `@cleocode/core/store/skills-db`. caamp cannot depend on `@cleocode/core`
|
|
38
|
+
* directly (would invert the dep direction: core dynamically imports caamp).
|
|
39
|
+
*
|
|
40
|
+
* Three execution modes:
|
|
41
|
+
*
|
|
42
|
+
* - default (TTY) — interactive prompt per orphan.
|
|
43
|
+
* - `--non-interactive` — list orphans and exit without action
|
|
44
|
+
* (read-only audit).
|
|
45
|
+
* - `--auto-user-adopt` — bulk user-adopt all orphans without prompting
|
|
46
|
+
* (safe default for `cleo-init`-style scripts).
|
|
47
|
+
*
|
|
48
|
+
* @task T9657
|
|
49
|
+
* @epic T9571
|
|
50
|
+
* @saga T9560
|
|
51
|
+
* @architecture docs/architecture/SG-CLEO-SKILLS-architecture-v3.md §1, §6
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* One orphan disposition decision.
|
|
56
|
+
*
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
type OrphanDecision = 'canonical-adopt' | 'user-adopt' | 'delete' | 'skip';
|
|
60
|
+
/**
|
|
61
|
+
* Reason an action was refused (canonical-adopt on user machine, etc.).
|
|
62
|
+
*
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
65
|
+
interface OrphanRefusal {
|
|
66
|
+
/** Stable code for programmatic handling. */
|
|
67
|
+
code: 'E_CANONICAL_ADOPT_REFUSED';
|
|
68
|
+
/** Human-readable explanation. */
|
|
69
|
+
message: string;
|
|
70
|
+
/** Suggested next step (e.g. PR flow). */
|
|
71
|
+
remediation: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* A single orphan skill directory discovered on disk.
|
|
75
|
+
*
|
|
76
|
+
* @public
|
|
77
|
+
*/
|
|
78
|
+
interface OrphanRecord {
|
|
79
|
+
/** Skill name (basename of the orphan directory). */
|
|
80
|
+
name: string;
|
|
81
|
+
/** Absolute path to the orphan directory on disk. */
|
|
82
|
+
path: string;
|
|
83
|
+
/** Which tracked root this orphan was discovered under. */
|
|
84
|
+
discoveredVia: 'cleo' | 'legacy-agents' | 'home-agents';
|
|
85
|
+
/** Whether a `SKILL.md` sentinel exists at the root. */
|
|
86
|
+
hasSkillMd: boolean;
|
|
87
|
+
/** Size of the directory in bytes (best-effort; 0 on stat failure). */
|
|
88
|
+
sizeBytes: number;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Outcome of acting on a single orphan.
|
|
92
|
+
*
|
|
93
|
+
* @public
|
|
94
|
+
*/
|
|
95
|
+
interface OrphanActionResult {
|
|
96
|
+
/** The orphan that was acted upon. */
|
|
97
|
+
orphan: OrphanRecord;
|
|
98
|
+
/** Decision the user (or flag) made. */
|
|
99
|
+
decision: OrphanDecision;
|
|
100
|
+
/** Whether the action completed successfully. */
|
|
101
|
+
applied: boolean;
|
|
102
|
+
/** Refusal payload when `applied=false` due to a policy block. */
|
|
103
|
+
refusal: OrphanRefusal | null;
|
|
104
|
+
/** Where the directory was archived to (delete only). */
|
|
105
|
+
archivedTo: string | null;
|
|
106
|
+
/** ISO-8601 timestamp when the action was taken. */
|
|
107
|
+
decidedAt: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Top-level result returned in the LAFS envelope.
|
|
111
|
+
*
|
|
112
|
+
* @public
|
|
113
|
+
*/
|
|
114
|
+
interface DoctorAdoptResult {
|
|
115
|
+
/** Total orphans discovered. */
|
|
116
|
+
totalOrphans: number;
|
|
117
|
+
/** Per-orphan action results. */
|
|
118
|
+
results: OrphanActionResult[];
|
|
119
|
+
/** Audit log file path (always written). */
|
|
120
|
+
auditLogPath: string;
|
|
121
|
+
/** Execution mode used. */
|
|
122
|
+
mode: 'interactive' | 'non-interactive' | 'auto-user-adopt';
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Pure-data payload emitted when a `user-adopt` decision is applied.
|
|
126
|
+
*
|
|
127
|
+
* @remarks
|
|
128
|
+
* The dispatch layer translates this into an `upsertSkillRow` call via the
|
|
129
|
+
* `openCleoDb('skills')` chokepoint. Keeping it as pure data means caamp
|
|
130
|
+
* never has to touch sqlite directly.
|
|
131
|
+
*
|
|
132
|
+
* @public
|
|
133
|
+
*/
|
|
134
|
+
interface AdoptedSkillRowData {
|
|
135
|
+
/** Skill name (PK in skills.db). */
|
|
136
|
+
name: string;
|
|
137
|
+
/** Absolute install path on disk. */
|
|
138
|
+
installPath: string;
|
|
139
|
+
/** Wall-clock timestamp the adoption occurred. */
|
|
140
|
+
installedAt: string;
|
|
141
|
+
/** Always `'user'` for the adopt-orphans flow (canonical is refused). */
|
|
142
|
+
sourceType: 'user';
|
|
143
|
+
/** Always `'active'` post-adoption. */
|
|
144
|
+
lifecycleState: 'active';
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Discover orphan skills across all tracked roots.
|
|
148
|
+
*
|
|
149
|
+
* @remarks
|
|
150
|
+
* Visits the three tracked roots in priority order and de-duplicates by
|
|
151
|
+
* basename — the first occurrence of `<name>` wins (so a `~/.cleo/skills/`
|
|
152
|
+
* entry shadows the same-named legacy entry). Symlinks under
|
|
153
|
+
* `~/.agents/skills/` that resolve back into `~/.cleo/skills/` are dropped
|
|
154
|
+
* because those are the bridge symlinks, not real orphans.
|
|
155
|
+
*
|
|
156
|
+
* Read-side IO (the set of names already known to `skills.db`) is supplied
|
|
157
|
+
* via the `registeredNames` callback so this module never opens sqlite
|
|
158
|
+
* directly — see ADR-068 chokepoint compliance in the file header.
|
|
159
|
+
*
|
|
160
|
+
* @param registeredNames - Pre-computed set of skill names known to the
|
|
161
|
+
* registry. Callers in production wire this through `openCleoDb('skills')`;
|
|
162
|
+
* tests wire it through a sandboxed `DatabaseSync` open.
|
|
163
|
+
* @returns Sorted-by-name list of `OrphanRecord`s.
|
|
164
|
+
*
|
|
165
|
+
* @public
|
|
166
|
+
*/
|
|
167
|
+
declare function discoverOrphans(registeredNames: ReadonlySet<string>): OrphanRecord[];
|
|
168
|
+
/**
|
|
169
|
+
* Callback signature for persisting a `user-adopt` decision.
|
|
170
|
+
*
|
|
171
|
+
* @remarks
|
|
172
|
+
* Production wiring lives in `packages/cleo/src/cli/commands/skills.ts` and
|
|
173
|
+
* funnels into `upsertSkillRow` from `@cleocode/core/store/skills-db`,
|
|
174
|
+
* which routes through the canonical `openCleoDb('skills')` chokepoint.
|
|
175
|
+
* Test code passes a sandboxed sqlite write. May be synchronous or async.
|
|
176
|
+
*
|
|
177
|
+
* @public
|
|
178
|
+
*/
|
|
179
|
+
type RecordRowFn = (data: AdoptedSkillRowData) => void | Promise<void>;
|
|
180
|
+
/**
|
|
181
|
+
* Apply a single decision to an orphan, returning a structured outcome.
|
|
182
|
+
*
|
|
183
|
+
* @remarks
|
|
184
|
+
* This is the policy chokepoint — `canonical-adopt` is unconditionally
|
|
185
|
+
* refused, `user-adopt` invokes `recordRow` with the canonical
|
|
186
|
+
* {@link AdoptedSkillRowData} payload, `delete` archives-then-rms, and
|
|
187
|
+
* `skip` records the intent without side effects. Errors during
|
|
188
|
+
* `user-adopt` or `delete` produce an `applied=false` result with a
|
|
189
|
+
* synthesised refusal payload rather than throwing, so the bulk loop can
|
|
190
|
+
* proceed across all orphans.
|
|
191
|
+
*
|
|
192
|
+
* @param orphan - Orphan to act on.
|
|
193
|
+
* @param decision - Decision to apply.
|
|
194
|
+
* @param now - ISO-8601 timestamp to record on the result.
|
|
195
|
+
* @param recordRow - Callback invoked to persist a successful `user-adopt`.
|
|
196
|
+
* Tests pass a sandbox write; production passes the cleo-dispatch wrapper.
|
|
197
|
+
* @returns A populated `OrphanActionResult`.
|
|
198
|
+
*
|
|
199
|
+
* @public
|
|
200
|
+
*/
|
|
201
|
+
declare function applyDecision(orphan: OrphanRecord, decision: OrphanDecision, now: string, recordRow: RecordRowFn): Promise<OrphanActionResult>;
|
|
202
|
+
/**
|
|
203
|
+
* Write the audit log to `~/.cleo/skills/.audit-log/adopt-<ts>.json`.
|
|
204
|
+
*
|
|
205
|
+
* @remarks
|
|
206
|
+
* The log is written atomically (tmp-then-rename) so a SIGINT mid-write
|
|
207
|
+
* cannot leave a half-written file. The payload is a structured object
|
|
208
|
+
* containing the run timestamp, mode, full per-orphan results, and a
|
|
209
|
+
* stable `runId` UUID for cross-referencing in other CLEO audit streams
|
|
210
|
+
* (e.g. release-ship logs).
|
|
211
|
+
*
|
|
212
|
+
* @param result - The doctor-adopt result to persist.
|
|
213
|
+
* @returns Absolute path the audit log was written to.
|
|
214
|
+
*
|
|
215
|
+
* @public
|
|
216
|
+
*/
|
|
217
|
+
declare function writeAuditLog(result: DoctorAdoptResult): string;
|
|
218
|
+
/**
|
|
219
|
+
* Options controlling a `runDoctorAdopt` invocation.
|
|
220
|
+
*
|
|
221
|
+
* @public
|
|
222
|
+
*/
|
|
223
|
+
interface DoctorAdoptOptions {
|
|
224
|
+
/** Skip prompting and write nothing — list-only audit mode. */
|
|
225
|
+
nonInteractive?: boolean;
|
|
226
|
+
/** Skip prompting and bulk-adopt every orphan as `source_type='user'`. */
|
|
227
|
+
autoUserAdopt?: boolean;
|
|
228
|
+
/**
|
|
229
|
+
* Loads the set of skill names already known to the registry.
|
|
230
|
+
*
|
|
231
|
+
* Production wiring opens `skills.db` via `openCleoDb('skills')`; tests
|
|
232
|
+
* inject a sandbox-scoped reader.
|
|
233
|
+
*/
|
|
234
|
+
loadRegisteredNames: () => ReadonlySet<string> | Promise<ReadonlySet<string>>;
|
|
235
|
+
/**
|
|
236
|
+
* Persists a single `user-adopt` decision to `skills.db`.
|
|
237
|
+
*
|
|
238
|
+
* Production wiring calls `upsertSkillRow` from `@cleocode/core/store`;
|
|
239
|
+
* tests inject a sandbox writer.
|
|
240
|
+
*/
|
|
241
|
+
recordRow: RecordRowFn;
|
|
242
|
+
/** Test-only injection of a readline-compatible prompt. */
|
|
243
|
+
prompt?: (orphan: OrphanRecord) => Promise<OrphanDecision>;
|
|
244
|
+
/** Test-only opt-out of writing the audit log to disk. */
|
|
245
|
+
skipAuditLog?: boolean;
|
|
246
|
+
/** Test-only override for the discovery step. */
|
|
247
|
+
discoverFn?: (registeredNames: ReadonlySet<string>) => OrphanRecord[];
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Execute the doctor-adopt workflow and return a structured result.
|
|
251
|
+
*
|
|
252
|
+
* @remarks
|
|
253
|
+
* Designed for both CLI invocation (from {@link registerSkillsDoctorAdopt})
|
|
254
|
+
* and direct testing — every side effect is overridable via
|
|
255
|
+
* {@link DoctorAdoptOptions}. The function never throws on per-orphan
|
|
256
|
+
* failures; instead each failure produces an `applied=false` entry with a
|
|
257
|
+
* refusal payload, so the caller gets a complete report even on partial
|
|
258
|
+
* failure.
|
|
259
|
+
*
|
|
260
|
+
* @param options - Mode flags + dependency-injected callbacks. The
|
|
261
|
+
* `loadRegisteredNames` and `recordRow` callbacks are MANDATORY so the
|
|
262
|
+
* caller (cleo dispatch or test harness) owns the sqlite open via the
|
|
263
|
+
* chokepoint.
|
|
264
|
+
* @returns The populated `DoctorAdoptResult`.
|
|
265
|
+
*
|
|
266
|
+
* @public
|
|
267
|
+
*/
|
|
268
|
+
declare function runDoctorAdopt(options: DoctorAdoptOptions): Promise<DoctorAdoptResult>;
|
|
269
|
+
/**
|
|
270
|
+
* Default skill-name loader bound at CLI dispatch time.
|
|
271
|
+
*
|
|
272
|
+
* @remarks
|
|
273
|
+
* Re-exported so the cleo dispatch layer can construct it once and inject
|
|
274
|
+
* the same instance into {@link runDoctorAdopt}.
|
|
275
|
+
*
|
|
276
|
+
* @public
|
|
277
|
+
*/
|
|
278
|
+
type RegisteredNamesLoader = () => ReadonlySet<string> | Promise<ReadonlySet<string>>;
|
|
279
|
+
/**
|
|
280
|
+
* Adapter callbacks the CLI registrar needs to satisfy
|
|
281
|
+
* {@link DoctorAdoptOptions}'s mandatory deps.
|
|
282
|
+
*
|
|
283
|
+
* @remarks
|
|
284
|
+
* The caamp CLI (`caamp skills doctor adopt-orphans`) supplies a no-op pair
|
|
285
|
+
* — caamp is the registry-author-tool and never touches a live skills.db.
|
|
286
|
+
* The cleo CLI overrides both with chokepoint-routed implementations.
|
|
287
|
+
*
|
|
288
|
+
* @public
|
|
289
|
+
*/
|
|
290
|
+
interface DoctorAdoptCliAdapters {
|
|
291
|
+
loadRegisteredNames: RegisteredNamesLoader;
|
|
292
|
+
recordRow: RecordRowFn;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Standalone-`caamp` defaults — no DB access, every directory is an orphan.
|
|
296
|
+
*
|
|
297
|
+
* @remarks
|
|
298
|
+
* In the standalone caamp CLI, there's no skills.db (caamp is the
|
|
299
|
+
* registry-author tool, not the user-runtime). We treat every directory as
|
|
300
|
+
* an orphan and refuse all user-adopt writes by surfacing an explanatory
|
|
301
|
+
* error through `recordRow`. The cleo CLI overrides this with the real
|
|
302
|
+
* chokepoint-routed adapters.
|
|
303
|
+
*
|
|
304
|
+
* @public
|
|
305
|
+
*/
|
|
306
|
+
declare const caampStandaloneAdapters: DoctorAdoptCliAdapters;
|
|
307
|
+
/**
|
|
308
|
+
* Register the `skills doctor adopt-orphans` subcommand on the parent
|
|
309
|
+
* `skills` Commander group.
|
|
310
|
+
*
|
|
311
|
+
* @remarks
|
|
312
|
+
* The handler creates the `doctor` subgroup if it doesn't already exist on
|
|
313
|
+
* the parent, so registration order is tolerant of co-registration with
|
|
314
|
+
* `registerSkillsDoctor` (T9655 bridge). Adapters default to
|
|
315
|
+
* {@link caampStandaloneAdapters} which surface a clear error — pass the
|
|
316
|
+
* cleo-chokepoint adapters when wiring under `packages/cleo/`.
|
|
317
|
+
*
|
|
318
|
+
* Default output is LAFS JSON. Pass `--human` for the colorised summary.
|
|
319
|
+
*
|
|
320
|
+
* @param parent - The parent `skills` Command from
|
|
321
|
+
* {@link registerSkillsCommands}.
|
|
322
|
+
* @param adapters - DB read/write hooks. Defaults to
|
|
323
|
+
* {@link caampStandaloneAdapters} so the standalone caamp CLI surfaces a
|
|
324
|
+
* helpful error rather than silently no-op'ing.
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```bash
|
|
328
|
+
* cleo skills doctor adopt-orphans # interactive
|
|
329
|
+
* cleo skills doctor adopt-orphans --non-interactive
|
|
330
|
+
* cleo skills doctor adopt-orphans --auto-user-adopt --json
|
|
331
|
+
* ```
|
|
332
|
+
*
|
|
333
|
+
* @public
|
|
334
|
+
*/
|
|
335
|
+
declare function registerSkillsDoctorAdopt(parent: Command, adapters?: DoctorAdoptCliAdapters): void;
|
|
336
|
+
|
|
5
337
|
/**
|
|
6
338
|
* `cleo skills doctor bridge` — single bridge symlink + per-skill symlink removal.
|
|
7
339
|
*
|
|
@@ -8720,4 +9052,4 @@ declare function parseSource(input: string): ParsedSource;
|
|
|
8720
9052
|
*/
|
|
8721
9053
|
declare function isMarketplaceScoped(input: string): boolean;
|
|
8722
9054
|
|
|
8723
|
-
export { AgentsSkillsRealDirError, type AuditFinding, type AuditResult, type AuditRule, type AuditSeverity, type BatchInstallOptions, type BatchInstallResult, type BridgeSymlinkRecord, CANONICAL_HOOK_EVENTS, type CaampBlock, type CaampLockFile, type CanonicalEventDefinition, type CanonicalHookEvent, type CantProfileCounts, type CantProfileEntry, type CantValidationDiagnostic, type ConfigFormat, type CrossProviderMatrix, type CtDispatchMatrix, type CtManifest, type CtManifestSkill, type CtProfileDefinition, type CtSkillEntry, type CtValidationIssue, type CtValidationResult, DEFAULT_EXCLUSIVITY_MODE, type DedupeResult, type DetectionCacheOptions, type DetectionResult, type DoctorBridgeOptions, type DoctorBridgeResult, EXCLUSIVITY_MODE_ENV_VAR, type EnsureProviderInstructionFileOptions, type EnsureProviderInstructionFileResult, type ExclusivityMode, type GlobalOptions, HOOK_CATEGORIES, type Harness, type HarnessScope, type HookCategory, type HookEvent, type HookHandlerType, type HookMapping, type HookSupportResult, type HookSystemType, type InjectionCheckResult, type InjectionStatus, type InjectionTemplate, type InstallMcpServerOptions, type InstallMcpServerResult, type InstallSkillOptions, type InstructionUpdateSummary, type KnownProviderAgentFolderId, type LockEntry, MarketplaceClient, type MarketplaceResult, type MarketplaceSearchResult, type MarketplaceSkill, type McpConfigFormat, type McpDetectionEntry, type McpScope, type McpServerConfig, type McpServerEntriesByProvider, type McpServerEntry, type McpTransportType, type NormalizedHookEvent, type NormalizedRecommendationCriteria, type ParsedSource, type PerSkillSymlinkRemoval, PiHarness, PiRequiredError, type Provider, type ProviderCapabilities, type ProviderHarnessCapability, type ProviderHookProfile, type ProviderHookSummary, type ProviderHooksCapability, type ProviderMcpCapability, type ProviderPriority, type ProviderSkillsCapability, type ProviderSpawnCapability, type ProviderStatus, RECOMMENDATION_ERROR_CODES, type RankedSkillRecommendation, type RecommendSkillsResult, type RecommendationCriteriaInput, type RecommendationErrorCode, type RecommendationOptions, type RecommendationReason, type RecommendationReasonCode, type RecommendationScoreBreakdown, type RecommendationValidationIssue, type RecommendationValidationResult, type RecommendationWeights, type RegistryHarnessKind, type RegistryHookCatalog, type RegistryHookFormat, type RemoveMcpServerOptions, type RemoveMcpServerResult, type ResolveDefaultTargetProvidersOptions, type SkillBatchOperation, type SkillEntry, type SkillInstallResult, type SkillIntegrityResult, type SkillIntegrityStatus, type SkillLibrary, type SkillLibraryDispatchMatrix, type SkillLibraryEntry, type SkillLibraryManifest, type SkillLibraryManifestSkill, type SkillLibraryProfile, type SkillLibraryValidationIssue, type SkillLibraryValidationResult, type SkillMetadata, type SkillRowData, type SkillRowSourceType, type SkillsPrecedence, type SourceType, type SpawnAdapter, type SpawnMechanism, type SpawnOptions, type SpawnResult, type SubagentHandle, type SubagentResult, type SubagentTask, type TransportType, type ValidateCantProfileResult, type ValidationIssue, type ValidationResult, type WriteAgentFileOptions, type WriteAgentFileResult, _resetLegacySkillsWarning, _resetPlatformPathsCache, buildBackupTimestamp, buildHookMatrix, buildInjectionContent, buildLibraryFromFiles, buildSkillsMap, catalog, checkAllInjections, checkAllSkillIntegrity, checkAllSkillUpdates, checkInjection, checkSkillIntegrity, checkSkillUpdate, clearRegisteredLibrary, dedupeFile, dedupeFiles, deepMerge, detectAllProviders, detectMcpInstallations, detectProjectProviders, detectProvider, discoverSkill, discoverSkills, ensureAllProviderInstructionFiles, ensureDir, ensureProviderInstructionFile, formatSkillRecommendations, generateInjectionContent, generateSkillsSection, getAgentsConfigPath, getAgentsHome, getAgentsInstructFile, getAgentsLinksDir, getAgentsMcpDir, getAgentsMcpServersPath, getAgentsSpecDir, getAgentsWikiDir, getAllCanonicalEvents, getAllHarnesses, getAllProviders, getCanonicalEvent, getCanonicalEventsByCategory, getCanonicalSkillsDir, getCanonicalSkillsRoot, getCommonEvents, getCommonHookEvents, getEffectiveSkillsPaths, getExclusivityMode, getHarnessFor, getHookConfigPath, getHookMappingsVersion, getHookSupport, getHookSystemType, getInstalledProviders, getInstructionFiles, getLockFilePath, getMappedProviderIds, getNestedValue, getPlatformLocations, getPlatformPaths, getPrimaryHarness, getPrimaryProvider, getProjectAgentsDir, getProvider, getProviderAgentFolder, getProviderCapabilities, getProviderCount, getProviderHookProfile, getProviderInstructionReferences, getProviderOnlyEvents, getProviderSummary, getProvidersByHookEvent, getProvidersByInstructFile, getProvidersByPriority, getProvidersBySkillsPrecedence, getProvidersBySpawnCapability, getProvidersByStatus, getProvidersForEvent, getRegistryVersion, getSpawnCapableProviders, getSupportedEvents, getSystemInfo, getTrackedSkills, getUnsupportedEvents, groupByInstructFile, inferSkillSourceType, inject, injectAll, installBatchWithRollback, installMcpServer, installSkill, isCaampOwnedSkill, isExclusivityMode, isMarketplaceScoped, isQuiet, isVerbose, listAllMcpServers, listCanonicalSkills, listMcpServers, loadLibraryFromModule, normalizeRecommendationCriteria, parseCaampBlocks, parseInjectionContent, parseSkillFile, parseSource, providerSupports, providerSupportsById, rankSkills, readConfig, recommendSkills, recordSkillInstall, registerSkillLibrary, registerSkillLibraryFromPath, removeConfig, removeInjection, removeMcpServer, removeMcpServerFromAll, removeSkill, removeSkillFromLock, resetDetectionCache, resetExclusivityModeOverride, resolveAlias, resolveDefaultTargetProviders, resolveMcpConfigPath, resolveNativeEvent, resolveProviderSkillsDirs, resolveRegistryTemplatePath, runDoctorBridge, scanDirectory, scanFile, scoreSkillRecommendation, searchSkills, selectProvidersByMinimumPriority, setExclusivityMode, setQuiet, setVerbose, shouldOverrideSkill, supportsHook, toCanonical, toNative, toNativeBatch, toSarif, tokenizeCriteriaValue, translateToAll, updateInstructionsSingleOperation, validateInstructionIntegrity, validateRecommendationCriteria, validateSkill, writeAgentFileToAllProviders, writeConfig };
|
|
9055
|
+
export { type AdoptedSkillRowData, AgentsSkillsRealDirError, type AuditFinding, type AuditResult, type AuditRule, type AuditSeverity, type BatchInstallOptions, type BatchInstallResult, type BridgeSymlinkRecord, CANONICAL_HOOK_EVENTS, type CaampBlock, type CaampLockFile, type CanonicalEventDefinition, type CanonicalHookEvent, type CantProfileCounts, type CantProfileEntry, type CantValidationDiagnostic, type ConfigFormat, type CrossProviderMatrix, type CtDispatchMatrix, type CtManifest, type CtManifestSkill, type CtProfileDefinition, type CtSkillEntry, type CtValidationIssue, type CtValidationResult, DEFAULT_EXCLUSIVITY_MODE, type DedupeResult, type DetectionCacheOptions, type DetectionResult, type DoctorAdoptCliAdapters, type DoctorAdoptOptions, type DoctorAdoptResult, type DoctorBridgeOptions, type DoctorBridgeResult, EXCLUSIVITY_MODE_ENV_VAR, type EnsureProviderInstructionFileOptions, type EnsureProviderInstructionFileResult, type ExclusivityMode, type GlobalOptions, HOOK_CATEGORIES, type Harness, type HarnessScope, type HookCategory, type HookEvent, type HookHandlerType, type HookMapping, type HookSupportResult, type HookSystemType, type InjectionCheckResult, type InjectionStatus, type InjectionTemplate, type InstallMcpServerOptions, type InstallMcpServerResult, type InstallSkillOptions, type InstructionUpdateSummary, type KnownProviderAgentFolderId, type LockEntry, MarketplaceClient, type MarketplaceResult, type MarketplaceSearchResult, type MarketplaceSkill, type McpConfigFormat, type McpDetectionEntry, type McpScope, type McpServerConfig, type McpServerEntriesByProvider, type McpServerEntry, type McpTransportType, type NormalizedHookEvent, type NormalizedRecommendationCriteria, type OrphanActionResult, type OrphanDecision, type OrphanRecord, type OrphanRefusal, type ParsedSource, type PerSkillSymlinkRemoval, PiHarness, PiRequiredError, type Provider, type ProviderCapabilities, type ProviderHarnessCapability, type ProviderHookProfile, type ProviderHookSummary, type ProviderHooksCapability, type ProviderMcpCapability, type ProviderPriority, type ProviderSkillsCapability, type ProviderSpawnCapability, type ProviderStatus, RECOMMENDATION_ERROR_CODES, type RankedSkillRecommendation, type RecommendSkillsResult, type RecommendationCriteriaInput, type RecommendationErrorCode, type RecommendationOptions, type RecommendationReason, type RecommendationReasonCode, type RecommendationScoreBreakdown, type RecommendationValidationIssue, type RecommendationValidationResult, type RecommendationWeights, type RecordRowFn, type RegisteredNamesLoader, type RegistryHarnessKind, type RegistryHookCatalog, type RegistryHookFormat, type RemoveMcpServerOptions, type RemoveMcpServerResult, type ResolveDefaultTargetProvidersOptions, type SkillBatchOperation, type SkillEntry, type SkillInstallResult, type SkillIntegrityResult, type SkillIntegrityStatus, type SkillLibrary, type SkillLibraryDispatchMatrix, type SkillLibraryEntry, type SkillLibraryManifest, type SkillLibraryManifestSkill, type SkillLibraryProfile, type SkillLibraryValidationIssue, type SkillLibraryValidationResult, type SkillMetadata, type SkillRowData, type SkillRowSourceType, type SkillsPrecedence, type SourceType, type SpawnAdapter, type SpawnMechanism, type SpawnOptions, type SpawnResult, type SubagentHandle, type SubagentResult, type SubagentTask, type TransportType, type ValidateCantProfileResult, type ValidationIssue, type ValidationResult, type WriteAgentFileOptions, type WriteAgentFileResult, _resetLegacySkillsWarning, _resetPlatformPathsCache, applyDecision, buildBackupTimestamp, buildHookMatrix, buildInjectionContent, buildLibraryFromFiles, buildSkillsMap, caampStandaloneAdapters, catalog, checkAllInjections, checkAllSkillIntegrity, checkAllSkillUpdates, checkInjection, checkSkillIntegrity, checkSkillUpdate, clearRegisteredLibrary, dedupeFile, dedupeFiles, deepMerge, detectAllProviders, detectMcpInstallations, detectProjectProviders, detectProvider, discoverOrphans, discoverSkill, discoverSkills, ensureAllProviderInstructionFiles, ensureDir, ensureProviderInstructionFile, formatSkillRecommendations, generateInjectionContent, generateSkillsSection, getAgentsConfigPath, getAgentsHome, getAgentsInstructFile, getAgentsLinksDir, getAgentsMcpDir, getAgentsMcpServersPath, getAgentsSpecDir, getAgentsWikiDir, getAllCanonicalEvents, getAllHarnesses, getAllProviders, getCanonicalEvent, getCanonicalEventsByCategory, getCanonicalSkillsDir, getCanonicalSkillsRoot, getCommonEvents, getCommonHookEvents, getEffectiveSkillsPaths, getExclusivityMode, getHarnessFor, getHookConfigPath, getHookMappingsVersion, getHookSupport, getHookSystemType, getInstalledProviders, getInstructionFiles, getLockFilePath, getMappedProviderIds, getNestedValue, getPlatformLocations, getPlatformPaths, getPrimaryHarness, getPrimaryProvider, getProjectAgentsDir, getProvider, getProviderAgentFolder, getProviderCapabilities, getProviderCount, getProviderHookProfile, getProviderInstructionReferences, getProviderOnlyEvents, getProviderSummary, getProvidersByHookEvent, getProvidersByInstructFile, getProvidersByPriority, getProvidersBySkillsPrecedence, getProvidersBySpawnCapability, getProvidersByStatus, getProvidersForEvent, getRegistryVersion, getSpawnCapableProviders, getSupportedEvents, getSystemInfo, getTrackedSkills, getUnsupportedEvents, groupByInstructFile, inferSkillSourceType, inject, injectAll, installBatchWithRollback, installMcpServer, installSkill, isCaampOwnedSkill, isExclusivityMode, isMarketplaceScoped, isQuiet, isVerbose, listAllMcpServers, listCanonicalSkills, listMcpServers, loadLibraryFromModule, normalizeRecommendationCriteria, parseCaampBlocks, parseInjectionContent, parseSkillFile, parseSource, providerSupports, providerSupportsById, rankSkills, readConfig, recommendSkills, recordSkillInstall, registerSkillLibrary, registerSkillLibraryFromPath, registerSkillsDoctorAdopt, removeConfig, removeInjection, removeMcpServer, removeMcpServerFromAll, removeSkill, removeSkillFromLock, resetDetectionCache, resetExclusivityModeOverride, resolveAlias, resolveDefaultTargetProviders, resolveMcpConfigPath, resolveNativeEvent, resolveProviderSkillsDirs, resolveRegistryTemplatePath, runDoctorAdopt, runDoctorBridge, scanDirectory, scanFile, scoreSkillRecommendation, searchSkills, selectProvidersByMinimumPriority, setExclusivityMode, setQuiet, setVerbose, shouldOverrideSkill, supportsHook, toCanonical, toNative, toNativeBatch, toSarif, tokenizeCriteriaValue, translateToAll, updateInstructionsSingleOperation, validateInstructionIntegrity, validateRecommendationCriteria, validateSkill, writeAgentFileToAllProviders, writeAuditLog, writeConfig };
|
package/dist/index.js
CHANGED
|
@@ -6,8 +6,10 @@ import {
|
|
|
6
6
|
PiHarness,
|
|
7
7
|
PiRequiredError,
|
|
8
8
|
RECOMMENDATION_ERROR_CODES,
|
|
9
|
+
applyDecision,
|
|
9
10
|
buildBackupTimestamp,
|
|
10
11
|
buildLibraryFromFiles,
|
|
12
|
+
caampStandaloneAdapters,
|
|
11
13
|
catalog_exports,
|
|
12
14
|
checkAllSkillUpdates,
|
|
13
15
|
checkSkillUpdate,
|
|
@@ -17,6 +19,7 @@ import {
|
|
|
17
19
|
detectMcpInstallations,
|
|
18
20
|
detectProjectProviders,
|
|
19
21
|
detectProvider,
|
|
22
|
+
discoverOrphans,
|
|
20
23
|
discoverSkill,
|
|
21
24
|
discoverSkills,
|
|
22
25
|
ensureDir,
|
|
@@ -50,6 +53,7 @@ import {
|
|
|
50
53
|
recordSkillInstall,
|
|
51
54
|
registerSkillLibrary,
|
|
52
55
|
registerSkillLibraryFromPath,
|
|
56
|
+
registerSkillsDoctorAdopt,
|
|
53
57
|
removeConfig,
|
|
54
58
|
removeMcpServer,
|
|
55
59
|
removeMcpServerFromAll,
|
|
@@ -59,6 +63,7 @@ import {
|
|
|
59
63
|
resetExclusivityModeOverride,
|
|
60
64
|
resolveDefaultTargetProviders,
|
|
61
65
|
resolveMcpConfigPath,
|
|
66
|
+
runDoctorAdopt,
|
|
62
67
|
runDoctorBridge,
|
|
63
68
|
scanDirectory,
|
|
64
69
|
scanFile,
|
|
@@ -73,8 +78,9 @@ import {
|
|
|
73
78
|
updateInstructionsSingleOperation,
|
|
74
79
|
validateRecommendationCriteria,
|
|
75
80
|
validateSkill,
|
|
81
|
+
writeAuditLog,
|
|
76
82
|
writeConfig
|
|
77
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-WXL7RPS4.js";
|
|
78
84
|
import {
|
|
79
85
|
buildInjectionContent,
|
|
80
86
|
buildSkillsMap,
|
|
@@ -317,11 +323,13 @@ export {
|
|
|
317
323
|
RECOMMENDATION_ERROR_CODES,
|
|
318
324
|
_resetLegacySkillsWarning,
|
|
319
325
|
_resetPlatformPathsCache,
|
|
326
|
+
applyDecision,
|
|
320
327
|
buildBackupTimestamp,
|
|
321
328
|
buildHookMatrix,
|
|
322
329
|
buildInjectionContent,
|
|
323
330
|
buildLibraryFromFiles,
|
|
324
331
|
buildSkillsMap,
|
|
332
|
+
caampStandaloneAdapters,
|
|
325
333
|
catalog_exports as catalog,
|
|
326
334
|
checkAllInjections,
|
|
327
335
|
checkAllSkillIntegrity,
|
|
@@ -337,6 +345,7 @@ export {
|
|
|
337
345
|
detectMcpInstallations,
|
|
338
346
|
detectProjectProviders,
|
|
339
347
|
detectProvider,
|
|
348
|
+
discoverOrphans,
|
|
340
349
|
discoverSkill,
|
|
341
350
|
discoverSkills,
|
|
342
351
|
ensureAllProviderInstructionFiles,
|
|
@@ -429,6 +438,7 @@ export {
|
|
|
429
438
|
recordSkillInstall,
|
|
430
439
|
registerSkillLibrary,
|
|
431
440
|
registerSkillLibraryFromPath,
|
|
441
|
+
registerSkillsDoctorAdopt,
|
|
432
442
|
removeConfig,
|
|
433
443
|
removeInjection,
|
|
434
444
|
removeMcpServer,
|
|
@@ -443,6 +453,7 @@ export {
|
|
|
443
453
|
resolveNativeEvent,
|
|
444
454
|
resolveProviderSkillsDirs,
|
|
445
455
|
resolveRegistryTemplatePath,
|
|
456
|
+
runDoctorAdopt,
|
|
446
457
|
runDoctorBridge,
|
|
447
458
|
scanDirectory,
|
|
448
459
|
scanFile,
|
|
@@ -465,6 +476,7 @@ export {
|
|
|
465
476
|
validateRecommendationCriteria,
|
|
466
477
|
validateSkill,
|
|
467
478
|
writeAgentFileToAllProviders,
|
|
479
|
+
writeAuditLog,
|
|
468
480
|
writeConfig
|
|
469
481
|
};
|
|
470
482
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/skills/integrity.ts"],"sourcesContent":["/**\n * Skill integrity checking\n *\n * Validates that installed skills have intact symlinks, correct canonical paths,\n * and enforces ct-* prefix priority for CAAMP-shipped skills.\n */\n\nimport { existsSync, lstatSync, readlinkSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport type { LockEntry, Provider } from '../../types.js';\nimport { readLockFile } from '../lock-utils.js';\nimport { getCanonicalSkillsDir, resolveProviderSkillsDirs } from '../paths/standard.js';\n\n/** CAAMP-reserved skill prefix. Skills with this prefix are owned by CAAMP. */\nconst CAAMP_SKILL_PREFIX = 'ct-';\n\n/**\n * Status of a single skill's integrity check.\n *\n * @public\n */\nexport type SkillIntegrityStatus =\n | 'intact'\n | 'broken-symlink'\n | 'missing-canonical'\n | 'missing-link'\n | 'not-tracked'\n | 'tampered';\n\n/**\n * Result of checking a single skill's integrity.\n *\n * @public\n */\nexport interface SkillIntegrityResult {\n /** Skill name. */\n name: string;\n /** Overall integrity status. */\n status: SkillIntegrityStatus;\n /** Whether the canonical directory exists. */\n canonicalExists: boolean;\n /** Expected canonical path from lock file. */\n canonicalPath: string | null;\n /** Provider link statuses — which agents have valid symlinks. */\n linkStatuses: Array<{\n providerId: string;\n linkPath: string;\n exists: boolean;\n isSymlink: boolean;\n pointsToCanonical: boolean;\n }>;\n /** Whether this is a CAAMP-reserved (ct-*) skill. */\n isCaampOwned: boolean;\n /** Human-readable issue description, if any. */\n issue?: string;\n}\n\n/**\n * Check whether a skill name is reserved by CAAMP (ct-* prefix).\n *\n * @remarks\n * Skills with the `ct-` prefix are considered CAAMP-owned and receive\n * special treatment during installation conflict resolution.\n *\n * @param skillName - Skill name to check\n * @returns `true` if the skill name starts with `ct-`\n *\n * @example\n * ```typescript\n * isCaampOwnedSkill(\"ct-research-agent\"); // true\n * isCaampOwnedSkill(\"my-custom-skill\"); // false\n * ```\n *\n * @public\n */\nexport function isCaampOwnedSkill(skillName: string): boolean {\n return skillName.startsWith(CAAMP_SKILL_PREFIX);\n}\n\n/**\n * Check the integrity of a single installed skill.\n *\n * @remarks\n * Validates that the canonical directory exists on disk, the lock file entry\n * matches the actual state, and symlinks from provider skill directories\n * point to the canonical path.\n *\n * @param skillName - Name of the skill to check\n * @param providers - Providers to check symlinks for\n * @param scope - Whether to check global or project links\n * @param projectDir - Project directory (for project scope)\n * @returns Integrity check result\n *\n * @example\n * ```typescript\n * const result = await checkSkillIntegrity(\"ct-research-agent\", providers, \"global\");\n * if (result.status !== \"intact\") {\n * console.log(`Issue: ${result.issue}`);\n * }\n * ```\n *\n * @public\n */\nexport async function checkSkillIntegrity(\n skillName: string,\n providers: Provider[],\n scope: 'global' | 'project' = 'global',\n projectDir?: string,\n): Promise<SkillIntegrityResult> {\n const lock = await readLockFile();\n const entry = lock.skills[skillName];\n const isCaampOwned = isCaampOwnedSkill(skillName);\n\n // Not tracked in lock file\n if (!entry) {\n const canonicalPath = join(getCanonicalSkillsDir(), skillName);\n return {\n name: skillName,\n status: 'not-tracked',\n canonicalExists: existsSync(canonicalPath),\n canonicalPath: null,\n linkStatuses: [],\n isCaampOwned,\n issue: 'Skill is not tracked in the CAAMP lock file',\n };\n }\n\n const canonicalPath = entry.canonicalPath;\n const canonicalExists = existsSync(canonicalPath);\n\n // Check symlinks for each provider\n const linkStatuses: SkillIntegrityResult['linkStatuses'] = [];\n\n for (const provider of providers) {\n const targetDirs = resolveProviderSkillsDirs(provider, scope, projectDir);\n for (const skillsDir of targetDirs) {\n if (!skillsDir) continue;\n\n const linkPath = join(skillsDir, skillName);\n const exists = existsSync(linkPath);\n let isSymlink = false;\n let pointsToCanonical = false;\n\n if (exists) {\n try {\n const stat = lstatSync(linkPath);\n isSymlink = stat.isSymbolicLink();\n if (isSymlink) {\n const target = resolve(readlinkSync(linkPath));\n pointsToCanonical = target === resolve(canonicalPath);\n }\n } catch {\n // Can't stat — treat as broken\n }\n }\n\n linkStatuses.push({\n providerId: provider.id,\n linkPath,\n exists,\n isSymlink,\n pointsToCanonical,\n });\n }\n }\n\n // Determine overall status\n if (!canonicalExists) {\n return {\n name: skillName,\n status: 'missing-canonical',\n canonicalExists,\n canonicalPath,\n linkStatuses,\n isCaampOwned,\n issue: `Canonical directory missing: ${canonicalPath}`,\n };\n }\n\n const brokenLinks = linkStatuses.filter((l) => !l.exists);\n const tamperedLinks = linkStatuses.filter((l) => l.exists && !l.pointsToCanonical);\n\n if (tamperedLinks.length > 0) {\n return {\n name: skillName,\n status: 'tampered',\n canonicalExists,\n canonicalPath,\n linkStatuses,\n isCaampOwned,\n issue: `${tamperedLinks.length} link(s) do not point to canonical path`,\n };\n }\n\n if (brokenLinks.length > 0) {\n return {\n name: skillName,\n status: 'broken-symlink',\n canonicalExists,\n canonicalPath,\n linkStatuses,\n isCaampOwned,\n issue: `${brokenLinks.length} symlink(s) missing`,\n };\n }\n\n return {\n name: skillName,\n status: 'intact',\n canonicalExists,\n canonicalPath,\n linkStatuses,\n isCaampOwned,\n };\n}\n\n/**\n * Check integrity of all tracked skills.\n *\n * @remarks\n * Iterates over every skill in the lock file and runs\n * {@link checkSkillIntegrity} on each.\n *\n * @param providers - Providers to check symlinks for\n * @param scope - Whether to check global or project links\n * @param projectDir - Project directory (for project scope)\n * @returns Map of skill name to integrity result\n *\n * @example\n * ```typescript\n * const results = await checkAllSkillIntegrity(providers);\n * for (const [name, result] of results) {\n * console.log(`${name}: ${result.status}`);\n * }\n * ```\n *\n * @public\n */\nexport async function checkAllSkillIntegrity(\n providers: Provider[],\n scope: 'global' | 'project' = 'global',\n projectDir?: string,\n): Promise<Map<string, SkillIntegrityResult>> {\n const lock = await readLockFile();\n const results = new Map<string, SkillIntegrityResult>();\n\n for (const skillName of Object.keys(lock.skills)) {\n const result = await checkSkillIntegrity(skillName, providers, scope, projectDir);\n results.set(skillName, result);\n }\n\n return results;\n}\n\n/**\n * Resolve a skill name conflict where a user-installed skill collides\n * with a CAAMP-owned (ct-*) skill.\n *\n * @remarks\n * CAAMP-owned skills always win. Returns `true` if the incoming skill\n * should take precedence over the existing installation.\n *\n * @param skillName - Skill name to check\n * @param incomingSource - Source of the incoming skill installation\n * @param existingEntry - Existing lock entry, if any\n * @returns `true` if the incoming installation should proceed\n *\n * @example\n * ```typescript\n * const proceed = shouldOverrideSkill(\"ct-research-agent\", \"library\", existingEntry);\n * if (proceed) {\n * // Safe to install/override\n * }\n * ```\n *\n * @public\n */\nexport function shouldOverrideSkill(\n skillName: string,\n incomingSource: string,\n existingEntry: LockEntry | undefined,\n): boolean {\n // No existing entry — always allow\n if (!existingEntry) return true;\n\n // For ct-* skills, CAAMP package source always wins\n if (isCaampOwnedSkill(skillName)) {\n // If incoming is from CAAMP package (library source), it always wins\n if (existingEntry.sourceType === 'library') return true;\n // If existing is from CAAMP but incoming is user, CAAMP wins (block user)\n return true;\n }\n\n // Non-ct-* skills: user always wins\n return true;\n}\n\n/**\n * Validate instruction file injection status across all providers.\n *\n * @remarks\n * Checks that CAAMP blocks exist and are current in all relevant\n * instruction files (CLAUDE.md, AGENTS.md, GEMINI.md).\n *\n * @param providers - Providers to check\n * @param projectDir - Project directory\n * @param scope - Whether to check global or project files\n * @param expectedContent - Expected CAAMP block content\n * @returns Array of file paths with issues\n *\n * @example\n * ```typescript\n * const issues = await validateInstructionIntegrity(providers, process.cwd(), \"project\");\n * for (const issue of issues) {\n * console.log(`${issue.providerId}: ${issue.issue} (${issue.file})`);\n * }\n * ```\n *\n * @public\n */\nexport async function validateInstructionIntegrity(\n providers: Provider[],\n projectDir: string,\n scope: 'project' | 'global',\n expectedContent?: string,\n): Promise<Array<{ file: string; providerId: string; issue: string }>> {\n const { checkAllInjections } = await import('../instructions/injector.js');\n const results = await checkAllInjections(providers, projectDir, scope, expectedContent);\n const issues: Array<{ file: string; providerId: string; issue: string }> = [];\n\n for (const result of results) {\n if (result.status === 'missing') {\n issues.push({\n file: result.file,\n providerId: result.provider,\n issue: 'Instruction file does not exist',\n });\n } else if (result.status === 'none') {\n issues.push({\n file: result.file,\n providerId: result.provider,\n issue: 'No CAAMP injection block found',\n });\n } else if (result.status === 'outdated') {\n issues.push({\n file: result.file,\n providerId: result.provider,\n issue: 'CAAMP injection block is outdated',\n });\n }\n }\n\n return issues;\n}\n"],"mappings":"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","names":["canonicalPath","checkAllInjections"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/skills/integrity.ts"],"sourcesContent":["/**\n * Skill integrity checking\n *\n * Validates that installed skills have intact symlinks, correct canonical paths,\n * and enforces ct-* prefix priority for CAAMP-shipped skills.\n */\n\nimport { existsSync, lstatSync, readlinkSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport type { LockEntry, Provider } from '../../types.js';\nimport { readLockFile } from '../lock-utils.js';\nimport { getCanonicalSkillsDir, resolveProviderSkillsDirs } from '../paths/standard.js';\n\n/** CAAMP-reserved skill prefix. Skills with this prefix are owned by CAAMP. */\nconst CAAMP_SKILL_PREFIX = 'ct-';\n\n/**\n * Status of a single skill's integrity check.\n *\n * @public\n */\nexport type SkillIntegrityStatus =\n | 'intact'\n | 'broken-symlink'\n | 'missing-canonical'\n | 'missing-link'\n | 'not-tracked'\n | 'tampered';\n\n/**\n * Result of checking a single skill's integrity.\n *\n * @public\n */\nexport interface SkillIntegrityResult {\n /** Skill name. */\n name: string;\n /** Overall integrity status. */\n status: SkillIntegrityStatus;\n /** Whether the canonical directory exists. */\n canonicalExists: boolean;\n /** Expected canonical path from lock file. */\n canonicalPath: string | null;\n /** Provider link statuses — which agents have valid symlinks. */\n linkStatuses: Array<{\n providerId: string;\n linkPath: string;\n exists: boolean;\n isSymlink: boolean;\n pointsToCanonical: boolean;\n }>;\n /** Whether this is a CAAMP-reserved (ct-*) skill. */\n isCaampOwned: boolean;\n /** Human-readable issue description, if any. */\n issue?: string;\n}\n\n/**\n * Check whether a skill name is reserved by CAAMP (ct-* prefix).\n *\n * @remarks\n * Skills with the `ct-` prefix are considered CAAMP-owned and receive\n * special treatment during installation conflict resolution.\n *\n * @param skillName - Skill name to check\n * @returns `true` if the skill name starts with `ct-`\n *\n * @example\n * ```typescript\n * isCaampOwnedSkill(\"ct-research-agent\"); // true\n * isCaampOwnedSkill(\"my-custom-skill\"); // false\n * ```\n *\n * @public\n */\nexport function isCaampOwnedSkill(skillName: string): boolean {\n return skillName.startsWith(CAAMP_SKILL_PREFIX);\n}\n\n/**\n * Check the integrity of a single installed skill.\n *\n * @remarks\n * Validates that the canonical directory exists on disk, the lock file entry\n * matches the actual state, and symlinks from provider skill directories\n * point to the canonical path.\n *\n * @param skillName - Name of the skill to check\n * @param providers - Providers to check symlinks for\n * @param scope - Whether to check global or project links\n * @param projectDir - Project directory (for project scope)\n * @returns Integrity check result\n *\n * @example\n * ```typescript\n * const result = await checkSkillIntegrity(\"ct-research-agent\", providers, \"global\");\n * if (result.status !== \"intact\") {\n * console.log(`Issue: ${result.issue}`);\n * }\n * ```\n *\n * @public\n */\nexport async function checkSkillIntegrity(\n skillName: string,\n providers: Provider[],\n scope: 'global' | 'project' = 'global',\n projectDir?: string,\n): Promise<SkillIntegrityResult> {\n const lock = await readLockFile();\n const entry = lock.skills[skillName];\n const isCaampOwned = isCaampOwnedSkill(skillName);\n\n // Not tracked in lock file\n if (!entry) {\n const canonicalPath = join(getCanonicalSkillsDir(), skillName);\n return {\n name: skillName,\n status: 'not-tracked',\n canonicalExists: existsSync(canonicalPath),\n canonicalPath: null,\n linkStatuses: [],\n isCaampOwned,\n issue: 'Skill is not tracked in the CAAMP lock file',\n };\n }\n\n const canonicalPath = entry.canonicalPath;\n const canonicalExists = existsSync(canonicalPath);\n\n // Check symlinks for each provider\n const linkStatuses: SkillIntegrityResult['linkStatuses'] = [];\n\n for (const provider of providers) {\n const targetDirs = resolveProviderSkillsDirs(provider, scope, projectDir);\n for (const skillsDir of targetDirs) {\n if (!skillsDir) continue;\n\n const linkPath = join(skillsDir, skillName);\n const exists = existsSync(linkPath);\n let isSymlink = false;\n let pointsToCanonical = false;\n\n if (exists) {\n try {\n const stat = lstatSync(linkPath);\n isSymlink = stat.isSymbolicLink();\n if (isSymlink) {\n const target = resolve(readlinkSync(linkPath));\n pointsToCanonical = target === resolve(canonicalPath);\n }\n } catch {\n // Can't stat — treat as broken\n }\n }\n\n linkStatuses.push({\n providerId: provider.id,\n linkPath,\n exists,\n isSymlink,\n pointsToCanonical,\n });\n }\n }\n\n // Determine overall status\n if (!canonicalExists) {\n return {\n name: skillName,\n status: 'missing-canonical',\n canonicalExists,\n canonicalPath,\n linkStatuses,\n isCaampOwned,\n issue: `Canonical directory missing: ${canonicalPath}`,\n };\n }\n\n const brokenLinks = linkStatuses.filter((l) => !l.exists);\n const tamperedLinks = linkStatuses.filter((l) => l.exists && !l.pointsToCanonical);\n\n if (tamperedLinks.length > 0) {\n return {\n name: skillName,\n status: 'tampered',\n canonicalExists,\n canonicalPath,\n linkStatuses,\n isCaampOwned,\n issue: `${tamperedLinks.length} link(s) do not point to canonical path`,\n };\n }\n\n if (brokenLinks.length > 0) {\n return {\n name: skillName,\n status: 'broken-symlink',\n canonicalExists,\n canonicalPath,\n linkStatuses,\n isCaampOwned,\n issue: `${brokenLinks.length} symlink(s) missing`,\n };\n }\n\n return {\n name: skillName,\n status: 'intact',\n canonicalExists,\n canonicalPath,\n linkStatuses,\n isCaampOwned,\n };\n}\n\n/**\n * Check integrity of all tracked skills.\n *\n * @remarks\n * Iterates over every skill in the lock file and runs\n * {@link checkSkillIntegrity} on each.\n *\n * @param providers - Providers to check symlinks for\n * @param scope - Whether to check global or project links\n * @param projectDir - Project directory (for project scope)\n * @returns Map of skill name to integrity result\n *\n * @example\n * ```typescript\n * const results = await checkAllSkillIntegrity(providers);\n * for (const [name, result] of results) {\n * console.log(`${name}: ${result.status}`);\n * }\n * ```\n *\n * @public\n */\nexport async function checkAllSkillIntegrity(\n providers: Provider[],\n scope: 'global' | 'project' = 'global',\n projectDir?: string,\n): Promise<Map<string, SkillIntegrityResult>> {\n const lock = await readLockFile();\n const results = new Map<string, SkillIntegrityResult>();\n\n for (const skillName of Object.keys(lock.skills)) {\n const result = await checkSkillIntegrity(skillName, providers, scope, projectDir);\n results.set(skillName, result);\n }\n\n return results;\n}\n\n/**\n * Resolve a skill name conflict where a user-installed skill collides\n * with a CAAMP-owned (ct-*) skill.\n *\n * @remarks\n * CAAMP-owned skills always win. Returns `true` if the incoming skill\n * should take precedence over the existing installation.\n *\n * @param skillName - Skill name to check\n * @param incomingSource - Source of the incoming skill installation\n * @param existingEntry - Existing lock entry, if any\n * @returns `true` if the incoming installation should proceed\n *\n * @example\n * ```typescript\n * const proceed = shouldOverrideSkill(\"ct-research-agent\", \"library\", existingEntry);\n * if (proceed) {\n * // Safe to install/override\n * }\n * ```\n *\n * @public\n */\nexport function shouldOverrideSkill(\n skillName: string,\n incomingSource: string,\n existingEntry: LockEntry | undefined,\n): boolean {\n // No existing entry — always allow\n if (!existingEntry) return true;\n\n // For ct-* skills, CAAMP package source always wins\n if (isCaampOwnedSkill(skillName)) {\n // If incoming is from CAAMP package (library source), it always wins\n if (existingEntry.sourceType === 'library') return true;\n // If existing is from CAAMP but incoming is user, CAAMP wins (block user)\n return true;\n }\n\n // Non-ct-* skills: user always wins\n return true;\n}\n\n/**\n * Validate instruction file injection status across all providers.\n *\n * @remarks\n * Checks that CAAMP blocks exist and are current in all relevant\n * instruction files (CLAUDE.md, AGENTS.md, GEMINI.md).\n *\n * @param providers - Providers to check\n * @param projectDir - Project directory\n * @param scope - Whether to check global or project files\n * @param expectedContent - Expected CAAMP block content\n * @returns Array of file paths with issues\n *\n * @example\n * ```typescript\n * const issues = await validateInstructionIntegrity(providers, process.cwd(), \"project\");\n * for (const issue of issues) {\n * console.log(`${issue.providerId}: ${issue.issue} (${issue.file})`);\n * }\n * ```\n *\n * @public\n */\nexport async function validateInstructionIntegrity(\n providers: Provider[],\n projectDir: string,\n scope: 'project' | 'global',\n expectedContent?: string,\n): Promise<Array<{ file: string; providerId: string; issue: string }>> {\n const { checkAllInjections } = await import('../instructions/injector.js');\n const results = await checkAllInjections(providers, projectDir, scope, expectedContent);\n const issues: Array<{ file: string; providerId: string; issue: string }> = [];\n\n for (const result of results) {\n if (result.status === 'missing') {\n issues.push({\n file: result.file,\n providerId: result.provider,\n issue: 'Instruction file does not exist',\n });\n } else if (result.status === 'none') {\n issues.push({\n file: result.file,\n providerId: result.provider,\n issue: 'No CAAMP injection block found',\n });\n } else if (result.status === 'outdated') {\n issues.push({\n file: result.file,\n providerId: result.provider,\n issue: 'CAAMP injection block is outdated',\n });\n }\n }\n\n return issues;\n}\n"],"mappings":"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","names":["canonicalPath","checkAllInjections"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/caamp",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.86",
|
|
4
4
|
"description": "Central AI Agent Managed Packages - unified provider registry and package manager for AI coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -50,10 +50,10 @@
|
|
|
50
50
|
"jsonc-parser": "^3.3.1",
|
|
51
51
|
"picocolors": "^1.1.1",
|
|
52
52
|
"simple-git": "3.33.0",
|
|
53
|
-
"@cleocode/
|
|
54
|
-
"@cleocode/
|
|
55
|
-
"@cleocode/
|
|
56
|
-
"@cleocode/
|
|
53
|
+
"@cleocode/cant": "2026.5.86",
|
|
54
|
+
"@cleocode/lafs": "2026.5.86",
|
|
55
|
+
"@cleocode/paths": "2026.5.86",
|
|
56
|
+
"@cleocode/contracts": "2026.5.86"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@biomejs/biome": "2.4.11",
|