@cleocode/caamp 1.8.1 → 1.9.0
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-ER3FIOTM.js +244 -0
- package/dist/chunk-ER3FIOTM.js.map +1 -0
- package/dist/{chunk-CPHF5IM4.js → chunk-MFWBR2NY.js} +20 -290
- package/dist/chunk-MFWBR2NY.js.map +1 -0
- package/dist/{chunk-LDTYDQGR.js → chunk-OLJZ23W3.js} +7 -5
- package/dist/{chunk-LDTYDQGR.js.map → chunk-OLJZ23W3.js.map} +1 -1
- package/dist/chunk-TRIXT4T7.js +276 -0
- package/dist/chunk-TRIXT4T7.js.map +1 -0
- package/dist/cli.js +199 -87
- package/dist/cli.js.map +1 -1
- package/dist/hooks-LV6VU7QJ.js +56 -0
- package/dist/index.d.ts +207 -2
- package/dist/index.js +71 -19
- package/dist/index.js.map +1 -1
- package/dist/{injector-TIUEM4X2.js → injector-P2OL6RK3.js} +3 -2
- package/dist/injector-P2OL6RK3.js.map +1 -0
- package/package.json +1 -1
- package/providers/hook-mappings.json +302 -0
- package/providers/registry.json +599 -156
- package/dist/chunk-CPHF5IM4.js.map +0 -1
- /package/dist/{injector-TIUEM4X2.js.map → hooks-LV6VU7QJ.js.map} +0 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CANONICAL_HOOK_EVENTS,
|
|
3
|
+
HOOK_CATEGORIES,
|
|
4
|
+
buildHookMatrix,
|
|
5
|
+
getAllCanonicalEvents,
|
|
6
|
+
getCanonicalEvent,
|
|
7
|
+
getCanonicalEventsByCategory,
|
|
8
|
+
getCommonEvents,
|
|
9
|
+
getHookConfigPath,
|
|
10
|
+
getHookMappingsVersion,
|
|
11
|
+
getHookSupport,
|
|
12
|
+
getHookSystemType,
|
|
13
|
+
getMappedProviderIds,
|
|
14
|
+
getProviderHookProfile,
|
|
15
|
+
getProviderOnlyEvents,
|
|
16
|
+
getProviderSummary,
|
|
17
|
+
getProvidersForEvent,
|
|
18
|
+
getSupportedEvents,
|
|
19
|
+
getUnsupportedEvents,
|
|
20
|
+
resetHookMappings,
|
|
21
|
+
resolveNativeEvent,
|
|
22
|
+
supportsHook,
|
|
23
|
+
toCanonical,
|
|
24
|
+
toNative,
|
|
25
|
+
toNativeBatch,
|
|
26
|
+
translateToAll
|
|
27
|
+
} from "./chunk-ER3FIOTM.js";
|
|
28
|
+
import "./chunk-TRIXT4T7.js";
|
|
29
|
+
export {
|
|
30
|
+
CANONICAL_HOOK_EVENTS,
|
|
31
|
+
HOOK_CATEGORIES,
|
|
32
|
+
buildHookMatrix,
|
|
33
|
+
getAllCanonicalEvents,
|
|
34
|
+
getCanonicalEvent,
|
|
35
|
+
getCanonicalEventsByCategory,
|
|
36
|
+
getCommonEvents,
|
|
37
|
+
getHookConfigPath,
|
|
38
|
+
getHookMappingsVersion,
|
|
39
|
+
getHookSupport,
|
|
40
|
+
getHookSystemType,
|
|
41
|
+
getMappedProviderIds,
|
|
42
|
+
getProviderHookProfile,
|
|
43
|
+
getProviderOnlyEvents,
|
|
44
|
+
getProviderSummary,
|
|
45
|
+
getProvidersForEvent,
|
|
46
|
+
getSupportedEvents,
|
|
47
|
+
getUnsupportedEvents,
|
|
48
|
+
resetHookMappings,
|
|
49
|
+
resolveNativeEvent,
|
|
50
|
+
supportsHook,
|
|
51
|
+
toCanonical,
|
|
52
|
+
toNative,
|
|
53
|
+
toNativeBatch,
|
|
54
|
+
translateToAll
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=hooks-LV6VU7QJ.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
type SkillsPrecedence = "vendor-only" | "agents-canonical" | "agents-first" | "agents-supported" | "vendor-global-agents-project";
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* @deprecated Use `CanonicalHookEvent` from `../hooks/types.js` for the
|
|
4
|
+
* normalized CAAMP taxonomy. This type remains for backward compatibility
|
|
5
|
+
* with registry.json's `capabilities.hooks.supported` string arrays.
|
|
6
|
+
*/
|
|
7
|
+
type HookEvent = string;
|
|
3
8
|
type SpawnMechanism = "native" | "mcp" | "cli" | "api";
|
|
4
9
|
|
|
5
10
|
/**
|
|
@@ -3167,6 +3172,206 @@ declare function writeConfig(filePath: string, format: ConfigFormat, key: string
|
|
|
3167
3172
|
*/
|
|
3168
3173
|
declare function removeConfig(filePath: string, format: ConfigFormat, key: string, serverName: string): Promise<boolean>;
|
|
3169
3174
|
|
|
3175
|
+
/**
|
|
3176
|
+
* CAAMP Hooks Normalizer - Type Definitions
|
|
3177
|
+
*
|
|
3178
|
+
* Defines the canonical CAAMP hook event taxonomy and provider mapping types.
|
|
3179
|
+
* CAAMP provides a unified hook interface across all providers — consumers
|
|
3180
|
+
* use canonical event names, and the normalizer translates to/from
|
|
3181
|
+
* provider-native names.
|
|
3182
|
+
*/
|
|
3183
|
+
declare const HOOK_CATEGORIES: readonly ["session", "prompt", "tool", "agent", "context"];
|
|
3184
|
+
type HookCategory = (typeof HOOK_CATEGORIES)[number];
|
|
3185
|
+
declare const CANONICAL_HOOK_EVENTS: readonly ["SessionStart", "SessionEnd", "PromptSubmit", "ResponseComplete", "PreToolUse", "PostToolUse", "PostToolUseFailure", "PermissionRequest", "SubagentStart", "SubagentStop", "PreModel", "PostModel", "PreCompact", "PostCompact", "Notification", "ConfigChange"];
|
|
3186
|
+
type CanonicalHookEvent = (typeof CANONICAL_HOOK_EVENTS)[number];
|
|
3187
|
+
interface CanonicalEventDefinition {
|
|
3188
|
+
category: HookCategory;
|
|
3189
|
+
description: string;
|
|
3190
|
+
canBlock: boolean;
|
|
3191
|
+
}
|
|
3192
|
+
type HookSystemType = "config" | "plugin" | "none";
|
|
3193
|
+
type HookHandlerType = "command" | "http" | "prompt" | "agent" | "plugin";
|
|
3194
|
+
interface HookMapping {
|
|
3195
|
+
nativeName: string | null;
|
|
3196
|
+
supported: boolean;
|
|
3197
|
+
notes?: string;
|
|
3198
|
+
}
|
|
3199
|
+
interface ProviderHookProfile {
|
|
3200
|
+
hookSystem: HookSystemType;
|
|
3201
|
+
hookConfigPath: string | null;
|
|
3202
|
+
hookFormat: string | null;
|
|
3203
|
+
handlerTypes: HookHandlerType[];
|
|
3204
|
+
experimental: boolean;
|
|
3205
|
+
mappings: Record<CanonicalHookEvent, HookMapping>;
|
|
3206
|
+
providerOnlyEvents: string[];
|
|
3207
|
+
}
|
|
3208
|
+
interface NormalizedHookEvent {
|
|
3209
|
+
canonical: CanonicalHookEvent;
|
|
3210
|
+
native: string;
|
|
3211
|
+
providerId: string;
|
|
3212
|
+
category: HookCategory;
|
|
3213
|
+
canBlock: boolean;
|
|
3214
|
+
}
|
|
3215
|
+
interface HookSupportResult {
|
|
3216
|
+
canonical: CanonicalHookEvent;
|
|
3217
|
+
supported: boolean;
|
|
3218
|
+
native: string | null;
|
|
3219
|
+
notes?: string;
|
|
3220
|
+
}
|
|
3221
|
+
interface ProviderHookSummary {
|
|
3222
|
+
providerId: string;
|
|
3223
|
+
hookSystem: HookSystemType;
|
|
3224
|
+
experimental: boolean;
|
|
3225
|
+
supportedCount: number;
|
|
3226
|
+
totalCanonical: number;
|
|
3227
|
+
supported: CanonicalHookEvent[];
|
|
3228
|
+
unsupported: CanonicalHookEvent[];
|
|
3229
|
+
providerOnly: string[];
|
|
3230
|
+
coverage: number;
|
|
3231
|
+
}
|
|
3232
|
+
interface CrossProviderMatrix {
|
|
3233
|
+
events: CanonicalHookEvent[];
|
|
3234
|
+
providers: string[];
|
|
3235
|
+
matrix: Record<CanonicalHookEvent, Record<string, HookMapping>>;
|
|
3236
|
+
}
|
|
3237
|
+
|
|
3238
|
+
/**
|
|
3239
|
+
* CAAMP Hooks Normalizer
|
|
3240
|
+
*
|
|
3241
|
+
* Translates between CAAMP canonical hook events and provider-native
|
|
3242
|
+
* event names. Provides query functions for hook support, cross-provider
|
|
3243
|
+
* comparison, and event normalization.
|
|
3244
|
+
*
|
|
3245
|
+
* This module follows the same pattern as `src/core/mcp/transforms.ts` —
|
|
3246
|
+
* a translation layer that lets consumers use one canonical interface
|
|
3247
|
+
* while CAAMP handles provider-specific differences.
|
|
3248
|
+
*/
|
|
3249
|
+
|
|
3250
|
+
/**
|
|
3251
|
+
* Get the canonical event definition (category, description, canBlock).
|
|
3252
|
+
*/
|
|
3253
|
+
declare function getCanonicalEvent(event: CanonicalHookEvent): CanonicalEventDefinition;
|
|
3254
|
+
/**
|
|
3255
|
+
* Get all canonical event definitions.
|
|
3256
|
+
*/
|
|
3257
|
+
declare function getAllCanonicalEvents(): Record<CanonicalHookEvent, CanonicalEventDefinition>;
|
|
3258
|
+
/**
|
|
3259
|
+
* Get canonical events filtered by category.
|
|
3260
|
+
*/
|
|
3261
|
+
declare function getCanonicalEventsByCategory(category: HookCategory): CanonicalHookEvent[];
|
|
3262
|
+
/**
|
|
3263
|
+
* Get the full hook profile for a provider.
|
|
3264
|
+
*/
|
|
3265
|
+
declare function getProviderHookProfile(providerId: string): ProviderHookProfile | undefined;
|
|
3266
|
+
/**
|
|
3267
|
+
* Get all provider IDs that have hook mappings.
|
|
3268
|
+
*/
|
|
3269
|
+
declare function getMappedProviderIds(): string[];
|
|
3270
|
+
/**
|
|
3271
|
+
* Translate a CAAMP canonical event name to the provider's native name.
|
|
3272
|
+
*
|
|
3273
|
+
* @returns The native event name, or `null` if unsupported
|
|
3274
|
+
*
|
|
3275
|
+
* @example
|
|
3276
|
+
* ```typescript
|
|
3277
|
+
* toNative("PreToolUse", "claude-code"); // "PreToolUse"
|
|
3278
|
+
* toNative("PreToolUse", "gemini-cli"); // "BeforeTool"
|
|
3279
|
+
* toNative("PreToolUse", "cursor"); // "preToolUse"
|
|
3280
|
+
* toNative("PreToolUse", "kimi"); // null
|
|
3281
|
+
* ```
|
|
3282
|
+
*/
|
|
3283
|
+
declare function toNative(canonical: CanonicalHookEvent, providerId: string): string | null;
|
|
3284
|
+
/**
|
|
3285
|
+
* Translate a provider-native event name to the CAAMP canonical name.
|
|
3286
|
+
*
|
|
3287
|
+
* @returns The canonical event name, or `null` if no mapping exists
|
|
3288
|
+
*
|
|
3289
|
+
* @example
|
|
3290
|
+
* ```typescript
|
|
3291
|
+
* toCanonical("BeforeTool", "gemini-cli"); // "PreToolUse"
|
|
3292
|
+
* toCanonical("stop", "cursor"); // "ResponseComplete"
|
|
3293
|
+
* toCanonical("UserPromptSubmit", "claude-code"); // "PromptSubmit"
|
|
3294
|
+
* ```
|
|
3295
|
+
*/
|
|
3296
|
+
declare function toCanonical(nativeName: string, providerId: string): CanonicalHookEvent | null;
|
|
3297
|
+
/**
|
|
3298
|
+
* Batch-translate multiple canonical events to native names for a provider.
|
|
3299
|
+
*
|
|
3300
|
+
* @returns Array of normalized events (only supported ones included)
|
|
3301
|
+
*/
|
|
3302
|
+
declare function toNativeBatch(canonicals: CanonicalHookEvent[], providerId: string): NormalizedHookEvent[];
|
|
3303
|
+
/**
|
|
3304
|
+
* Check if a provider supports a specific canonical hook event.
|
|
3305
|
+
*/
|
|
3306
|
+
declare function supportsHook(canonical: CanonicalHookEvent, providerId: string): boolean;
|
|
3307
|
+
/**
|
|
3308
|
+
* Get full hook support details for a canonical event on a provider.
|
|
3309
|
+
*/
|
|
3310
|
+
declare function getHookSupport(canonical: CanonicalHookEvent, providerId: string): HookSupportResult;
|
|
3311
|
+
/**
|
|
3312
|
+
* Get all supported canonical events for a provider.
|
|
3313
|
+
*/
|
|
3314
|
+
declare function getSupportedEvents(providerId: string): CanonicalHookEvent[];
|
|
3315
|
+
/**
|
|
3316
|
+
* Get all unsupported canonical events for a provider.
|
|
3317
|
+
*/
|
|
3318
|
+
declare function getUnsupportedEvents(providerId: string): CanonicalHookEvent[];
|
|
3319
|
+
/**
|
|
3320
|
+
* Get providers that support a specific canonical event.
|
|
3321
|
+
*/
|
|
3322
|
+
declare function getProvidersForEvent(canonical: CanonicalHookEvent): string[];
|
|
3323
|
+
/**
|
|
3324
|
+
* Get canonical events common to all specified providers.
|
|
3325
|
+
*/
|
|
3326
|
+
declare function getCommonEvents(providerIds: string[]): CanonicalHookEvent[];
|
|
3327
|
+
/**
|
|
3328
|
+
* Get a summary of hook support for a provider.
|
|
3329
|
+
*/
|
|
3330
|
+
declare function getProviderSummary(providerId: string): ProviderHookSummary | undefined;
|
|
3331
|
+
/**
|
|
3332
|
+
* Build a cross-provider hook support matrix.
|
|
3333
|
+
*
|
|
3334
|
+
* Shows which canonical events are supported by which providers,
|
|
3335
|
+
* with native name translations.
|
|
3336
|
+
*/
|
|
3337
|
+
declare function buildHookMatrix(providerIds?: string[]): CrossProviderMatrix;
|
|
3338
|
+
/**
|
|
3339
|
+
* Get the hook system type for a provider.
|
|
3340
|
+
*/
|
|
3341
|
+
declare function getHookSystemType(providerId: string): HookSystemType;
|
|
3342
|
+
/**
|
|
3343
|
+
* Get the resolved hook config path for a provider.
|
|
3344
|
+
*/
|
|
3345
|
+
declare function getHookConfigPath(providerId: string): string | null;
|
|
3346
|
+
/**
|
|
3347
|
+
* Get provider-only events (native events with no canonical mapping).
|
|
3348
|
+
*/
|
|
3349
|
+
declare function getProviderOnlyEvents(providerId: string): string[];
|
|
3350
|
+
/**
|
|
3351
|
+
* Translate a canonical event to native names across multiple providers.
|
|
3352
|
+
* Returns only providers that support the event.
|
|
3353
|
+
*
|
|
3354
|
+
* @example
|
|
3355
|
+
* ```typescript
|
|
3356
|
+
* const result = translateToAll("PreToolUse", ["claude-code", "gemini-cli", "kimi"]);
|
|
3357
|
+
* // { "claude-code": "PreToolUse", "gemini-cli": "BeforeTool" }
|
|
3358
|
+
* // (kimi excluded — unsupported)
|
|
3359
|
+
* ```
|
|
3360
|
+
*/
|
|
3361
|
+
declare function translateToAll(canonical: CanonicalHookEvent, providerIds: string[]): Record<string, string>;
|
|
3362
|
+
/**
|
|
3363
|
+
* Find the best canonical match for a native event name across all providers.
|
|
3364
|
+
* Useful when you have a native name but don't know which provider it's from.
|
|
3365
|
+
*/
|
|
3366
|
+
declare function resolveNativeEvent(nativeName: string): Array<{
|
|
3367
|
+
providerId: string;
|
|
3368
|
+
canonical: CanonicalHookEvent;
|
|
3369
|
+
}>;
|
|
3370
|
+
/**
|
|
3371
|
+
* Get the version of the hook mappings data.
|
|
3372
|
+
*/
|
|
3373
|
+
declare function getHookMappingsVersion(): string;
|
|
3374
|
+
|
|
3170
3375
|
/**
|
|
3171
3376
|
* Simple logger with verbose/quiet mode support.
|
|
3172
3377
|
*
|
|
@@ -3226,4 +3431,4 @@ declare function isVerbose(): boolean;
|
|
|
3226
3431
|
*/
|
|
3227
3432
|
declare function isQuiet(): boolean;
|
|
3228
3433
|
|
|
3229
|
-
export { type AuditFinding, type AuditResult, type AuditRule, type AuditSeverity, type BatchInstallOptions, type BatchInstallResult, type CaampLockFile, type CleoChannel, type CleoProfileBuildResult, type ConfigFormat, type ConflictPolicy, type CtDispatchMatrix, type CtManifest, type CtManifestSkill, type CtProfileDefinition, type CtSkillEntry, type CtValidationIssue, type CtValidationResult, type DetectionCacheOptions, type DetectionResult, type DualScopeConfigureOptions, type DualScopeConfigureResult, type EnsureProviderInstructionFileOptions, type EnsureProviderInstructionFileResult, type GlobalOptions, type HookEvent, type InferredLockData, type InjectionCheckResult, type InjectionStatus, type InjectionTemplate, type InstallResult, type InstructionUpdateSummary, type LockEntry, MarketplaceClient, type MarketplaceResult, type MarketplaceSearchResult, type MarketplaceSkill, type McpBatchOperation, type McpConflict, type McpConflictCode, type McpPlanApplyResult, type McpServerConfig, type McpServerEntry, type NormalizedRecommendationCriteria, type ParsedSource, type PlatformPaths, type Provider, type ProviderCapabilities, type ProviderHooksCapability, 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 ReconcileOptions, type ReconcileResult, 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 SkillsPrecedence, type SourceType, type SpawnAdapter, type SpawnMechanism, type SpawnOptions, type SpawnResult, type SystemInfo, type TransportType, type ValidationIssue, type ValidationResult, _resetPlatformPathsCache, applyMcpInstallWithPolicy, buildCleoProfile, buildInjectionContent, buildLibraryFromFiles, buildServerConfig, buildSkillsMap, catalog, checkAllInjections, checkAllSkillIntegrity, checkAllSkillUpdates, checkCommandReachability, checkInjection, checkSkillIntegrity, checkSkillUpdate, clearRegisteredLibrary, configureProviderGlobalAndProject, deepMerge, detectAllProviders, detectMcpConfigConflicts, detectProjectProviders, detectProvider, discoverSkill, discoverSkills, ensureAllProviderInstructionFiles, ensureDir, ensureProviderInstructionFile, extractVersionTag, formatSkillRecommendations, generateInjectionContent, generateSkillsSection, getAgentsConfigPath, getAgentsHome, getAgentsInstructFile, getAgentsLinksDir, getAgentsMcpDir, getAgentsMcpServersPath, getAgentsSpecDir, getAgentsWikiDir, getAllProviders, getCanonicalSkillsDir, getCommonHookEvents, getEffectiveSkillsPaths, getInstalledProviders, getInstructionFiles, getLastSelectedAgents, getLockFilePath, getNestedValue, getPlatformLocations, getPlatformPaths, getProjectAgentsDir, getProvider, getProviderCapabilities, getProviderCount, getProvidersByHookEvent, getProvidersByInstructFile, getProvidersByPriority, getProvidersBySkillsPrecedence, getProvidersBySpawnCapability, getProvidersByStatus, getRegistryVersion, getSpawnCapableProviders, getSystemInfo, getTrackedMcpServers, getTrackedSkills, getTransform, groupByInstructFile, inferCleoLockData, inject, injectAll, installBatchWithRollback, installMcpServer, installMcpServerToAll, installSkill, isCaampOwnedSkill, isCleoSource, isMarketplaceScoped, isQuiet, isVerbose, listAgentsMcpServers, listAllMcpServers, listCanonicalSkills, listMcpServers, loadLibraryFromModule, normalizeCleoChannel, normalizeRecommendationCriteria, parseEnvAssignments, parseInjectionContent, parseSkillFile, parseSource, providerSupports, providerSupportsById, rankSkills, readConfig, readLockFile, recommendSkills, reconcileCleoLock, recordMcpInstall, recordSkillInstall, registerSkillLibrary, registerSkillLibraryFromPath, removeConfig, removeInjection, removeMcpFromLock, removeMcpServer, removeSkill, removeSkillFromLock, resetDetectionCache, resolveAlias, resolveChannelFromServerName, resolveCleoServerName, resolveConfigPath, resolveProviderSkillsDirs, resolveRegistryTemplatePath, saveLastSelectedAgents, scanDirectory, scanFile, scoreSkillRecommendation, searchSkills, selectProvidersByMinimumPriority, setQuiet, setVerbose, shouldOverrideSkill, toSarif, tokenizeCriteriaValue, updateInstructionsSingleOperation, validateInstructionIntegrity, validateRecommendationCriteria, validateSkill, writeConfig };
|
|
3434
|
+
export { type AuditFinding, type AuditResult, type AuditRule, type AuditSeverity, type BatchInstallOptions, type BatchInstallResult, CANONICAL_HOOK_EVENTS, type CaampLockFile, type CanonicalEventDefinition, type CanonicalHookEvent, type CleoChannel, type CleoProfileBuildResult, type ConfigFormat, type ConflictPolicy, type CrossProviderMatrix, type CtDispatchMatrix, type CtManifest, type CtManifestSkill, type CtProfileDefinition, type CtSkillEntry, type CtValidationIssue, type CtValidationResult, type DetectionCacheOptions, type DetectionResult, type DualScopeConfigureOptions, type DualScopeConfigureResult, type EnsureProviderInstructionFileOptions, type EnsureProviderInstructionFileResult, type GlobalOptions, HOOK_CATEGORIES, type HookCategory, type HookEvent, type HookHandlerType, type HookMapping, type HookSupportResult, type HookSystemType, type InferredLockData, type InjectionCheckResult, type InjectionStatus, type InjectionTemplate, type InstallResult, type InstructionUpdateSummary, type LockEntry, MarketplaceClient, type MarketplaceResult, type MarketplaceSearchResult, type MarketplaceSkill, type McpBatchOperation, type McpConflict, type McpConflictCode, type McpPlanApplyResult, type McpServerConfig, type McpServerEntry, type NormalizedHookEvent, type NormalizedRecommendationCriteria, type ParsedSource, type PlatformPaths, type Provider, type ProviderCapabilities, type ProviderHookProfile, type ProviderHookSummary, type ProviderHooksCapability, 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 ReconcileOptions, type ReconcileResult, 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 SkillsPrecedence, type SourceType, type SpawnAdapter, type SpawnMechanism, type SpawnOptions, type SpawnResult, type SystemInfo, type TransportType, type ValidationIssue, type ValidationResult, _resetPlatformPathsCache, applyMcpInstallWithPolicy, buildCleoProfile, buildHookMatrix, buildInjectionContent, buildLibraryFromFiles, buildServerConfig, buildSkillsMap, catalog, checkAllInjections, checkAllSkillIntegrity, checkAllSkillUpdates, checkCommandReachability, checkInjection, checkSkillIntegrity, checkSkillUpdate, clearRegisteredLibrary, configureProviderGlobalAndProject, deepMerge, detectAllProviders, detectMcpConfigConflicts, detectProjectProviders, detectProvider, discoverSkill, discoverSkills, ensureAllProviderInstructionFiles, ensureDir, ensureProviderInstructionFile, extractVersionTag, formatSkillRecommendations, generateInjectionContent, generateSkillsSection, getAgentsConfigPath, getAgentsHome, getAgentsInstructFile, getAgentsLinksDir, getAgentsMcpDir, getAgentsMcpServersPath, getAgentsSpecDir, getAgentsWikiDir, getAllCanonicalEvents, getAllProviders, getCanonicalEvent, getCanonicalEventsByCategory, getCanonicalSkillsDir, getCommonEvents, getCommonHookEvents, getEffectiveSkillsPaths, getHookConfigPath, getHookMappingsVersion, getHookSupport, getHookSystemType, getInstalledProviders, getInstructionFiles, getLastSelectedAgents, getLockFilePath, getMappedProviderIds, getNestedValue, getPlatformLocations, getPlatformPaths, getProjectAgentsDir, getProvider, getProviderCapabilities, getProviderCount, getProviderHookProfile, getProviderOnlyEvents, getProviderSummary, getProvidersByHookEvent, getProvidersByInstructFile, getProvidersByPriority, getProvidersBySkillsPrecedence, getProvidersBySpawnCapability, getProvidersByStatus, getProvidersForEvent, getRegistryVersion, getSpawnCapableProviders, getSupportedEvents, getSystemInfo, getTrackedMcpServers, getTrackedSkills, getTransform, getUnsupportedEvents, groupByInstructFile, inferCleoLockData, inject, injectAll, installBatchWithRollback, installMcpServer, installMcpServerToAll, installSkill, isCaampOwnedSkill, isCleoSource, isMarketplaceScoped, isQuiet, isVerbose, listAgentsMcpServers, listAllMcpServers, listCanonicalSkills, listMcpServers, loadLibraryFromModule, normalizeCleoChannel, normalizeRecommendationCriteria, parseEnvAssignments, parseInjectionContent, parseSkillFile, parseSource, providerSupports, providerSupportsById, rankSkills, readConfig, readLockFile, recommendSkills, reconcileCleoLock, recordMcpInstall, recordSkillInstall, registerSkillLibrary, registerSkillLibraryFromPath, removeConfig, removeInjection, removeMcpFromLock, removeMcpServer, removeSkill, removeSkillFromLock, resetDetectionCache, resolveAlias, resolveChannelFromServerName, resolveCleoServerName, resolveConfigPath, resolveNativeEvent, resolveProviderSkillsDirs, resolveRegistryTemplatePath, saveLastSelectedAgents, scanDirectory, scanFile, scoreSkillRecommendation, searchSkills, selectProvidersByMinimumPriority, setQuiet, setVerbose, shouldOverrideSkill, supportsHook, toCanonical, toNative, toNativeBatch, toSarif, tokenizeCriteriaValue, translateToAll, updateInstructionsSingleOperation, validateInstructionIntegrity, validateRecommendationCriteria, validateSkill, writeConfig };
|
package/dist/index.js
CHANGED
|
@@ -78,9 +78,8 @@ import {
|
|
|
78
78
|
validateRecommendationCriteria,
|
|
79
79
|
validateSkill,
|
|
80
80
|
writeConfig
|
|
81
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-OLJZ23W3.js";
|
|
82
82
|
import {
|
|
83
|
-
_resetPlatformPathsCache,
|
|
84
83
|
buildInjectionContent,
|
|
85
84
|
buildSkillsMap,
|
|
86
85
|
checkAllInjections,
|
|
@@ -89,23 +88,10 @@ import {
|
|
|
89
88
|
ensureProviderInstructionFile,
|
|
90
89
|
generateInjectionContent,
|
|
91
90
|
generateSkillsSection,
|
|
92
|
-
getAgentsConfigPath,
|
|
93
|
-
getAgentsHome,
|
|
94
|
-
getAgentsInstructFile,
|
|
95
|
-
getAgentsLinksDir,
|
|
96
|
-
getAgentsMcpDir,
|
|
97
|
-
getAgentsMcpServersPath,
|
|
98
|
-
getAgentsSpecDir,
|
|
99
|
-
getAgentsWikiDir,
|
|
100
91
|
getAllProviders,
|
|
101
|
-
getCanonicalSkillsDir,
|
|
102
92
|
getCommonHookEvents,
|
|
103
93
|
getEffectiveSkillsPaths,
|
|
104
94
|
getInstructionFiles,
|
|
105
|
-
getLockFilePath,
|
|
106
|
-
getPlatformLocations,
|
|
107
|
-
getPlatformPaths,
|
|
108
|
-
getProjectAgentsDir,
|
|
109
95
|
getProvider,
|
|
110
96
|
getProviderCapabilities,
|
|
111
97
|
getProviderCount,
|
|
@@ -117,7 +103,6 @@ import {
|
|
|
117
103
|
getProvidersByStatus,
|
|
118
104
|
getRegistryVersion,
|
|
119
105
|
getSpawnCapableProviders,
|
|
120
|
-
getSystemInfo,
|
|
121
106
|
groupByInstructFile,
|
|
122
107
|
inject,
|
|
123
108
|
injectAll,
|
|
@@ -125,10 +110,53 @@ import {
|
|
|
125
110
|
providerSupports,
|
|
126
111
|
providerSupportsById,
|
|
127
112
|
removeInjection,
|
|
128
|
-
resolveAlias
|
|
113
|
+
resolveAlias
|
|
114
|
+
} from "./chunk-MFWBR2NY.js";
|
|
115
|
+
import {
|
|
116
|
+
CANONICAL_HOOK_EVENTS,
|
|
117
|
+
HOOK_CATEGORIES,
|
|
118
|
+
buildHookMatrix,
|
|
119
|
+
getAllCanonicalEvents,
|
|
120
|
+
getCanonicalEvent,
|
|
121
|
+
getCanonicalEventsByCategory,
|
|
122
|
+
getCommonEvents,
|
|
123
|
+
getHookConfigPath,
|
|
124
|
+
getHookMappingsVersion,
|
|
125
|
+
getHookSupport,
|
|
126
|
+
getHookSystemType,
|
|
127
|
+
getMappedProviderIds,
|
|
128
|
+
getProviderHookProfile,
|
|
129
|
+
getProviderOnlyEvents,
|
|
130
|
+
getProviderSummary,
|
|
131
|
+
getProvidersForEvent,
|
|
132
|
+
getSupportedEvents,
|
|
133
|
+
getUnsupportedEvents,
|
|
134
|
+
resolveNativeEvent,
|
|
135
|
+
supportsHook,
|
|
136
|
+
toCanonical,
|
|
137
|
+
toNative,
|
|
138
|
+
toNativeBatch,
|
|
139
|
+
translateToAll
|
|
140
|
+
} from "./chunk-ER3FIOTM.js";
|
|
141
|
+
import {
|
|
142
|
+
_resetPlatformPathsCache,
|
|
143
|
+
getAgentsConfigPath,
|
|
144
|
+
getAgentsHome,
|
|
145
|
+
getAgentsInstructFile,
|
|
146
|
+
getAgentsLinksDir,
|
|
147
|
+
getAgentsMcpDir,
|
|
148
|
+
getAgentsMcpServersPath,
|
|
149
|
+
getAgentsSpecDir,
|
|
150
|
+
getAgentsWikiDir,
|
|
151
|
+
getCanonicalSkillsDir,
|
|
152
|
+
getLockFilePath,
|
|
153
|
+
getPlatformLocations,
|
|
154
|
+
getPlatformPaths,
|
|
155
|
+
getProjectAgentsDir,
|
|
156
|
+
getSystemInfo,
|
|
129
157
|
resolveProviderSkillsDirs,
|
|
130
158
|
resolveRegistryTemplatePath
|
|
131
|
-
} from "./chunk-
|
|
159
|
+
} from "./chunk-TRIXT4T7.js";
|
|
132
160
|
|
|
133
161
|
// src/core/skills/integrity.ts
|
|
134
162
|
import { existsSync, lstatSync, readlinkSync } from "fs";
|
|
@@ -246,7 +274,7 @@ function shouldOverrideSkill(skillName, incomingSource, existingEntry) {
|
|
|
246
274
|
return true;
|
|
247
275
|
}
|
|
248
276
|
async function validateInstructionIntegrity(providers, projectDir, scope, expectedContent) {
|
|
249
|
-
const { checkAllInjections: checkAllInjections2 } = await import("./injector-
|
|
277
|
+
const { checkAllInjections: checkAllInjections2 } = await import("./injector-P2OL6RK3.js");
|
|
250
278
|
const results = await checkAllInjections2(providers, projectDir, scope, expectedContent);
|
|
251
279
|
const issues = [];
|
|
252
280
|
for (const result of results) {
|
|
@@ -273,11 +301,14 @@ async function validateInstructionIntegrity(providers, projectDir, scope, expect
|
|
|
273
301
|
return issues;
|
|
274
302
|
}
|
|
275
303
|
export {
|
|
304
|
+
CANONICAL_HOOK_EVENTS,
|
|
305
|
+
HOOK_CATEGORIES,
|
|
276
306
|
MarketplaceClient,
|
|
277
307
|
RECOMMENDATION_ERROR_CODES,
|
|
278
308
|
_resetPlatformPathsCache,
|
|
279
309
|
applyMcpInstallWithPolicy,
|
|
280
310
|
buildCleoProfile,
|
|
311
|
+
buildHookMatrix,
|
|
281
312
|
buildInjectionContent,
|
|
282
313
|
buildLibraryFromFiles,
|
|
283
314
|
buildServerConfig,
|
|
@@ -314,14 +345,23 @@ export {
|
|
|
314
345
|
getAgentsMcpServersPath,
|
|
315
346
|
getAgentsSpecDir,
|
|
316
347
|
getAgentsWikiDir,
|
|
348
|
+
getAllCanonicalEvents,
|
|
317
349
|
getAllProviders,
|
|
350
|
+
getCanonicalEvent,
|
|
351
|
+
getCanonicalEventsByCategory,
|
|
318
352
|
getCanonicalSkillsDir,
|
|
353
|
+
getCommonEvents,
|
|
319
354
|
getCommonHookEvents,
|
|
320
355
|
getEffectiveSkillsPaths,
|
|
356
|
+
getHookConfigPath,
|
|
357
|
+
getHookMappingsVersion,
|
|
358
|
+
getHookSupport,
|
|
359
|
+
getHookSystemType,
|
|
321
360
|
getInstalledProviders,
|
|
322
361
|
getInstructionFiles,
|
|
323
362
|
getLastSelectedAgents,
|
|
324
363
|
getLockFilePath,
|
|
364
|
+
getMappedProviderIds,
|
|
325
365
|
getNestedValue,
|
|
326
366
|
getPlatformLocations,
|
|
327
367
|
getPlatformPaths,
|
|
@@ -329,18 +369,24 @@ export {
|
|
|
329
369
|
getProvider,
|
|
330
370
|
getProviderCapabilities,
|
|
331
371
|
getProviderCount,
|
|
372
|
+
getProviderHookProfile,
|
|
373
|
+
getProviderOnlyEvents,
|
|
374
|
+
getProviderSummary,
|
|
332
375
|
getProvidersByHookEvent,
|
|
333
376
|
getProvidersByInstructFile,
|
|
334
377
|
getProvidersByPriority,
|
|
335
378
|
getProvidersBySkillsPrecedence,
|
|
336
379
|
getProvidersBySpawnCapability,
|
|
337
380
|
getProvidersByStatus,
|
|
381
|
+
getProvidersForEvent,
|
|
338
382
|
getRegistryVersion,
|
|
339
383
|
getSpawnCapableProviders,
|
|
384
|
+
getSupportedEvents,
|
|
340
385
|
getSystemInfo,
|
|
341
386
|
getTrackedMcpServers,
|
|
342
387
|
getTrackedSkills,
|
|
343
388
|
getTransform,
|
|
389
|
+
getUnsupportedEvents,
|
|
344
390
|
groupByInstructFile,
|
|
345
391
|
inferCleoLockData,
|
|
346
392
|
inject,
|
|
@@ -387,6 +433,7 @@ export {
|
|
|
387
433
|
resolveChannelFromServerName,
|
|
388
434
|
resolveCleoServerName,
|
|
389
435
|
resolveConfigPath,
|
|
436
|
+
resolveNativeEvent,
|
|
390
437
|
resolveProviderSkillsDirs,
|
|
391
438
|
resolveRegistryTemplatePath,
|
|
392
439
|
saveLastSelectedAgents,
|
|
@@ -398,8 +445,13 @@ export {
|
|
|
398
445
|
setQuiet,
|
|
399
446
|
setVerbose,
|
|
400
447
|
shouldOverrideSkill,
|
|
448
|
+
supportsHook,
|
|
449
|
+
toCanonical,
|
|
450
|
+
toNative,
|
|
451
|
+
toNativeBatch,
|
|
401
452
|
toSarif,
|
|
402
453
|
tokenizeCriteriaValue,
|
|
454
|
+
translateToAll,
|
|
403
455
|
updateInstructionsSingleOperation,
|
|
404
456
|
validateInstructionIntegrity,
|
|
405
457
|
validateRecommendationCriteria,
|
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 { getCanonicalSkillsDir, resolveProviderSkillsDirs } from \"../paths/standard.js\";\nimport { readLockFile, updateLockFile } from \"../lock-utils.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 */\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 */\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 * @param skillName - Skill name to check\n * @returns `true` if the skill name starts with `ct-`\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 * Validates:\n * - Canonical directory exists on disk\n * - Lock file entry matches actual state\n * - Symlinks from provider skill directories 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 */\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 * @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 */\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 * 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 */\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 * Checks that CAAMP blocks exist and are current in all relevant\n * instruction files.\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 */\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 { getCanonicalSkillsDir, resolveProviderSkillsDirs } from \"../paths/standard.js\";\nimport { readLockFile, updateLockFile } from \"../lock-utils.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 */\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 */\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 * @param skillName - Skill name to check\n * @returns `true` if the skill name starts with `ct-`\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 * Validates:\n * - Canonical directory exists on disk\n * - Lock file entry matches actual state\n * - Symlinks from provider skill directories 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 */\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 * @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 */\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 * 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 */\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 * Checks that CAAMP blocks exist and are current in all relevant\n * instruction files.\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 */\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"]}
|
|
@@ -6,7 +6,8 @@ import {
|
|
|
6
6
|
inject,
|
|
7
7
|
injectAll,
|
|
8
8
|
removeInjection
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-MFWBR2NY.js";
|
|
10
|
+
import "./chunk-TRIXT4T7.js";
|
|
10
11
|
export {
|
|
11
12
|
checkAllInjections,
|
|
12
13
|
checkInjection,
|
|
@@ -16,4 +17,4 @@ export {
|
|
|
16
17
|
injectAll,
|
|
17
18
|
removeInjection
|
|
18
19
|
};
|
|
19
|
-
//# sourceMappingURL=injector-
|
|
20
|
+
//# sourceMappingURL=injector-P2OL6RK3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|