@cleocode/caamp 2026.5.28 → 2026.5.33
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-HFC3WUME.js → chunk-4W35AEYA.js} +5 -22
- package/dist/chunk-4W35AEYA.js.map +1 -0
- package/dist/{chunk-OCQI7UDH.js → chunk-OCI4RYI5.js} +3 -15
- package/dist/chunk-OCI4RYI5.js.map +1 -0
- package/dist/{chunk-YXWL2IXL.js → chunk-OPUPNLUJ.js} +69 -4
- package/dist/chunk-OPUPNLUJ.js.map +1 -0
- package/dist/{chunk-GDEIR34D.js → chunk-SV33CE5X.js} +2 -2
- package/dist/cli.js +6 -6
- package/dist/{hooks-WZ3MTLQF.js → hooks-5EXBKPII.js} +3 -3
- package/dist/index.d.ts +145 -3
- package/dist/index.js +13 -5
- package/dist/index.js.map +1 -1
- package/dist/{injector-J2C4VCJJ.js → injector-F4EHB3CZ.js} +9 -3
- package/package.json +5 -5
- package/providers/registry.json +28 -0
- package/dist/chunk-HFC3WUME.js.map +0 -1
- package/dist/chunk-OCQI7UDH.js.map +0 -1
- package/dist/chunk-YXWL2IXL.js.map +0 -1
- /package/dist/{chunk-GDEIR34D.js.map → chunk-SV33CE5X.js.map} +0 -0
- /package/dist/{hooks-WZ3MTLQF.js.map → hooks-5EXBKPII.js.map} +0 -0
- /package/dist/{injector-J2C4VCJJ.js.map → injector-F4EHB3CZ.js.map} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -669,6 +669,16 @@ interface Provider {
|
|
|
669
669
|
pathProject: string;
|
|
670
670
|
/** Instruction file name (e.g. `"CLAUDE.md"`, `"AGENTS.md"`). */
|
|
671
671
|
instructFile: string;
|
|
672
|
+
/**
|
|
673
|
+
* Instruction file @-reference paths injected during CLEO installation.
|
|
674
|
+
*
|
|
675
|
+
* @remarks
|
|
676
|
+
* Populated for providers that manage instruction files (e.g. `claude-code`,
|
|
677
|
+
* `cursor`, `pi`). Providers that do not manage instruction files (e.g.
|
|
678
|
+
* `claude-sdk`) have an empty array. Values are static `@`-prefixed paths
|
|
679
|
+
* resolved at install time (e.g. `"@~/.cleo/templates/CLEO-INJECTION.md"`).
|
|
680
|
+
*/
|
|
681
|
+
instructionReferences: string[];
|
|
672
682
|
/** Resolved global skills directory path. */
|
|
673
683
|
pathSkills: string;
|
|
674
684
|
/** Project-relative skills directory path. */
|
|
@@ -4343,6 +4353,101 @@ declare function getHookMappingsVersion(): string;
|
|
|
4343
4353
|
* (cleo-subagent.md, seed agent profiles) per provider's native folder.
|
|
4344
4354
|
*/
|
|
4345
4355
|
|
|
4356
|
+
/**
|
|
4357
|
+
* A single parsed CAAMP block extracted from a file.
|
|
4358
|
+
*
|
|
4359
|
+
* @public
|
|
4360
|
+
*/
|
|
4361
|
+
interface CaampBlock {
|
|
4362
|
+
/** Raw text of the entire block including markers. */
|
|
4363
|
+
raw: string;
|
|
4364
|
+
/** Trimmed content between the markers. */
|
|
4365
|
+
content: string;
|
|
4366
|
+
/** Zero-based character offset of the start of the block in the file. */
|
|
4367
|
+
startIndex: number;
|
|
4368
|
+
/** Zero-based character offset immediately after the block in the file. */
|
|
4369
|
+
endIndex: number;
|
|
4370
|
+
}
|
|
4371
|
+
/**
|
|
4372
|
+
* Parse all CAAMP blocks from a file's content string.
|
|
4373
|
+
*
|
|
4374
|
+
* Returns an array of {@link CaampBlock} objects in order of appearance.
|
|
4375
|
+
* Blocks with malformed markers (START without matching END) are silently
|
|
4376
|
+
* skipped to avoid crashing on corrupted files.
|
|
4377
|
+
*
|
|
4378
|
+
* @param fileContent - Raw text content of the file
|
|
4379
|
+
* @returns Array of parsed CAAMP blocks
|
|
4380
|
+
*
|
|
4381
|
+
* @public
|
|
4382
|
+
*/
|
|
4383
|
+
declare function parseCaampBlocks(fileContent: string): CaampBlock[];
|
|
4384
|
+
/**
|
|
4385
|
+
* Result of deduplicating CAAMP blocks in a single file.
|
|
4386
|
+
*
|
|
4387
|
+
* @public
|
|
4388
|
+
*/
|
|
4389
|
+
interface DedupeResult {
|
|
4390
|
+
/** Absolute path to the file that was processed. */
|
|
4391
|
+
filePath: string;
|
|
4392
|
+
/** Number of duplicate blocks removed. */
|
|
4393
|
+
removed: number;
|
|
4394
|
+
/** Number of unique blocks kept. */
|
|
4395
|
+
kept: number;
|
|
4396
|
+
/** `true` if the file was modified on disk; `false` if it was already clean. */
|
|
4397
|
+
modified: boolean;
|
|
4398
|
+
}
|
|
4399
|
+
/**
|
|
4400
|
+
* Deduplicate CAAMP blocks in a file by content.
|
|
4401
|
+
*
|
|
4402
|
+
* Groups all `<!-- CAAMP:START -->...<!-- CAAMP:END -->` blocks by their
|
|
4403
|
+
* trimmed inner content. For each group that has more than one block, keeps
|
|
4404
|
+
* only the **last** occurrence (most recently written) and removes the earlier
|
|
4405
|
+
* duplicates. Blocks with distinct contents are preserved in their original
|
|
4406
|
+
* relative order.
|
|
4407
|
+
*
|
|
4408
|
+
* Idempotent: calling this on an already-clean file returns `modified: false`
|
|
4409
|
+
* and makes no filesystem writes.
|
|
4410
|
+
*
|
|
4411
|
+
* @param filePath - Absolute path to the file to deduplicate
|
|
4412
|
+
* @returns Dedup summary
|
|
4413
|
+
*
|
|
4414
|
+
* @remarks
|
|
4415
|
+
* "Last occurrence wins" matches the behaviour of CLEO's injection chain,
|
|
4416
|
+
* which writes the canonical `@~/.local/share/cleo/…` path on every session.
|
|
4417
|
+
* Stale temp-path blocks from earlier sessions therefore have earlier indices
|
|
4418
|
+
* and are removed, leaving the canonical block.
|
|
4419
|
+
*
|
|
4420
|
+
* @example
|
|
4421
|
+
* ```typescript
|
|
4422
|
+
* const result = await dedupeFile("/home/user/.agents/AGENTS.md");
|
|
4423
|
+
* console.log(`Removed ${result.removed} duplicate(s)`);
|
|
4424
|
+
* ```
|
|
4425
|
+
*
|
|
4426
|
+
* @public
|
|
4427
|
+
*/
|
|
4428
|
+
declare function dedupeFile(filePath: string): Promise<DedupeResult>;
|
|
4429
|
+
/**
|
|
4430
|
+
* Deduplicate CAAMP blocks across multiple files.
|
|
4431
|
+
*
|
|
4432
|
+
* Runs {@link dedupeFile} on each path in order and collects results.
|
|
4433
|
+
* Files that do not exist are skipped silently (their result has `removed: 0`).
|
|
4434
|
+
*
|
|
4435
|
+
* @param filePaths - Array of absolute file paths to process
|
|
4436
|
+
* @returns Array of results, one per input path
|
|
4437
|
+
*
|
|
4438
|
+
* @example
|
|
4439
|
+
* ```typescript
|
|
4440
|
+
* const results = await dedupeFiles([
|
|
4441
|
+
* "/home/user/.agents/AGENTS.md",
|
|
4442
|
+
* "/project/AGENTS.md",
|
|
4443
|
+
* ]);
|
|
4444
|
+
* const totalRemoved = results.reduce((n, r) => n + r.removed, 0);
|
|
4445
|
+
* console.log(`Removed ${totalRemoved} duplicate(s) across ${results.length} files`);
|
|
4446
|
+
* ```
|
|
4447
|
+
*
|
|
4448
|
+
* @public
|
|
4449
|
+
*/
|
|
4450
|
+
declare function dedupeFiles(filePaths: string[]): Promise<DedupeResult[]>;
|
|
4346
4451
|
/**
|
|
4347
4452
|
* Check the status of a CAAMP injection block in an instruction file.
|
|
4348
4453
|
*
|
|
@@ -4477,8 +4582,16 @@ declare function injectAll(providers: Provider[], projectDir: string, scope: 'pr
|
|
|
4477
4582
|
* @public
|
|
4478
4583
|
*/
|
|
4479
4584
|
interface EnsureProviderInstructionFileOptions {
|
|
4480
|
-
/**
|
|
4481
|
-
|
|
4585
|
+
/**
|
|
4586
|
+
* `@` references to inject (e.g. `["@AGENTS.md"]`).
|
|
4587
|
+
*
|
|
4588
|
+
* When omitted or `undefined`, the references declared in the CAAMP provider
|
|
4589
|
+
* registry (`provider.instructionReferences`) are used as the default. Callers
|
|
4590
|
+
* that supply an explicit array always take precedence over the registry default.
|
|
4591
|
+
*
|
|
4592
|
+
* @defaultValue Registry `instructionReferences` for the provider
|
|
4593
|
+
*/
|
|
4594
|
+
references?: string[];
|
|
4482
4595
|
/** Optional inline content blocks. @defaultValue `undefined` */
|
|
4483
4596
|
content?: string[];
|
|
4484
4597
|
/** Whether this is a global or project-level file. @defaultValue `"project"` */
|
|
@@ -6283,6 +6396,35 @@ declare function getSpawnCapableProviders(): Provider[];
|
|
|
6283
6396
|
* @public
|
|
6284
6397
|
*/
|
|
6285
6398
|
declare function getProvidersBySpawnCapability(flag: keyof Omit<ProviderSpawnCapability, 'spawnMechanism' | 'spawnCommand'>): Provider[];
|
|
6399
|
+
/**
|
|
6400
|
+
* Get the default `@` instruction references for a provider from the registry.
|
|
6401
|
+
*
|
|
6402
|
+
* Returns the `instructionReferences` array declared in `providers/registry.json`
|
|
6403
|
+
* for the given provider ID or alias. These references are the canonical defaults
|
|
6404
|
+
* used by {@link ensureProviderInstructionFile} when no explicit `references`
|
|
6405
|
+
* argument is supplied by the caller.
|
|
6406
|
+
*
|
|
6407
|
+
* @remarks
|
|
6408
|
+
* The return value is a fresh copy of the registry array — mutating it has no
|
|
6409
|
+
* effect on the cached registry state. If the provider is not found or it has
|
|
6410
|
+
* no `instructionReferences` entry, an empty array is returned so callers
|
|
6411
|
+
* never receive `undefined`.
|
|
6412
|
+
*
|
|
6413
|
+
* @param idOrAlias - Provider ID (e.g. `"claude-code"`) or alias (e.g. `"claude"`)
|
|
6414
|
+
* @returns Array of `@`-prefixed instruction reference strings, or `[]` if none
|
|
6415
|
+
*
|
|
6416
|
+
* @example
|
|
6417
|
+
* ```typescript
|
|
6418
|
+
* const refs = getProviderInstructionReferences("claude-code");
|
|
6419
|
+
* // ["@~/.cleo/templates/CLEO-INJECTION.md", "@.cleo/memory-bridge.md"]
|
|
6420
|
+
*
|
|
6421
|
+
* const unknown = getProviderInstructionReferences("no-such-provider");
|
|
6422
|
+
* // []
|
|
6423
|
+
* ```
|
|
6424
|
+
*
|
|
6425
|
+
* @public
|
|
6426
|
+
*/
|
|
6427
|
+
declare function getProviderInstructionReferences(idOrAlias: string): string[];
|
|
6286
6428
|
/**
|
|
6287
6429
|
* Filter providers by their skills precedence value.
|
|
6288
6430
|
*
|
|
@@ -8189,4 +8331,4 @@ declare function parseSource(input: string): ParsedSource;
|
|
|
8189
8331
|
*/
|
|
8190
8332
|
declare function isMarketplaceScoped(input: string): boolean;
|
|
8191
8333
|
|
|
8192
|
-
export { type AuditFinding, type AuditResult, type AuditRule, type AuditSeverity, type BatchInstallOptions, type BatchInstallResult, CANONICAL_HOOK_EVENTS, 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 DetectionCacheOptions, type DetectionResult, 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 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, 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 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, _resetPlatformPathsCache, buildHookMatrix, buildInjectionContent, buildLibraryFromFiles, buildSkillsMap, catalog, checkAllInjections, checkAllSkillIntegrity, checkAllSkillUpdates, checkInjection, checkSkillIntegrity, checkSkillUpdate, clearRegisteredLibrary, 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, getCommonEvents, getCommonHookEvents, getEffectiveSkillsPaths, getExclusivityMode, getHarnessFor, getHookConfigPath, getHookMappingsVersion, getHookSupport, getHookSystemType, getInstalledProviders, getInstructionFiles, getLockFilePath, getMappedProviderIds, getNestedValue, getPlatformLocations, getPlatformPaths, getPrimaryHarness, getPrimaryProvider, getProjectAgentsDir, getProvider, getProviderAgentFolder, getProviderCapabilities, getProviderCount, getProviderHookProfile, getProviderOnlyEvents, getProviderSummary, getProvidersByHookEvent, getProvidersByInstructFile, getProvidersByPriority, getProvidersBySkillsPrecedence, getProvidersBySpawnCapability, getProvidersByStatus, getProvidersForEvent, getRegistryVersion, getSpawnCapableProviders, getSupportedEvents, getSystemInfo, getTrackedSkills, getUnsupportedEvents, groupByInstructFile, inject, injectAll, installBatchWithRollback, installMcpServer, installSkill, isCaampOwnedSkill, isExclusivityMode, isMarketplaceScoped, isQuiet, isVerbose, listAllMcpServers, listCanonicalSkills, listMcpServers, loadLibraryFromModule, normalizeRecommendationCriteria, 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, scanDirectory, scanFile, scoreSkillRecommendation, searchSkills, selectProvidersByMinimumPriority, setExclusivityMode, setQuiet, setVerbose, shouldOverrideSkill, supportsHook, toCanonical, toNative, toNativeBatch, toSarif, tokenizeCriteriaValue, translateToAll, updateInstructionsSingleOperation, validateInstructionIntegrity, validateRecommendationCriteria, validateSkill, writeAgentFileToAllProviders, writeConfig };
|
|
8334
|
+
export { type AuditFinding, type AuditResult, type AuditRule, type AuditSeverity, type BatchInstallOptions, type BatchInstallResult, 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, 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 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, 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 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, _resetPlatformPathsCache, 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, 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, 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, scanDirectory, scanFile, scoreSkillRecommendation, searchSkills, selectProvidersByMinimumPriority, setExclusivityMode, setQuiet, setVerbose, shouldOverrideSkill, supportsHook, toCanonical, toNative, toNativeBatch, toSarif, tokenizeCriteriaValue, translateToAll, updateInstructionsSingleOperation, validateInstructionIntegrity, validateRecommendationCriteria, validateSkill, writeAgentFileToAllProviders, writeConfig };
|
package/dist/index.js
CHANGED
|
@@ -70,12 +70,14 @@ import {
|
|
|
70
70
|
validateRecommendationCriteria,
|
|
71
71
|
validateSkill,
|
|
72
72
|
writeConfig
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-4W35AEYA.js";
|
|
74
74
|
import {
|
|
75
75
|
buildInjectionContent,
|
|
76
76
|
buildSkillsMap,
|
|
77
77
|
checkAllInjections,
|
|
78
78
|
checkInjection,
|
|
79
|
+
dedupeFile,
|
|
80
|
+
dedupeFiles,
|
|
79
81
|
ensureAllProviderInstructionFiles,
|
|
80
82
|
ensureProviderInstructionFile,
|
|
81
83
|
generateInjectionContent,
|
|
@@ -89,6 +91,7 @@ import {
|
|
|
89
91
|
getProviderAgentFolder,
|
|
90
92
|
getProviderCapabilities,
|
|
91
93
|
getProviderCount,
|
|
94
|
+
getProviderInstructionReferences,
|
|
92
95
|
getProvidersByHookEvent,
|
|
93
96
|
getProvidersByInstructFile,
|
|
94
97
|
getProvidersByPriority,
|
|
@@ -100,13 +103,14 @@ import {
|
|
|
100
103
|
groupByInstructFile,
|
|
101
104
|
inject,
|
|
102
105
|
injectAll,
|
|
106
|
+
parseCaampBlocks,
|
|
103
107
|
parseInjectionContent,
|
|
104
108
|
providerSupports,
|
|
105
109
|
providerSupportsById,
|
|
106
110
|
removeInjection,
|
|
107
111
|
resolveAlias,
|
|
108
112
|
writeAgentFileToAllProviders
|
|
109
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-OPUPNLUJ.js";
|
|
110
114
|
import {
|
|
111
115
|
CANONICAL_HOOK_EVENTS,
|
|
112
116
|
HOOK_CATEGORIES,
|
|
@@ -132,7 +136,7 @@ import {
|
|
|
132
136
|
toNative,
|
|
133
137
|
toNativeBatch,
|
|
134
138
|
translateToAll
|
|
135
|
-
} from "./chunk-
|
|
139
|
+
} from "./chunk-SV33CE5X.js";
|
|
136
140
|
import {
|
|
137
141
|
_resetPlatformPathsCache,
|
|
138
142
|
getAgentsConfigPath,
|
|
@@ -151,7 +155,7 @@ import {
|
|
|
151
155
|
getSystemInfo,
|
|
152
156
|
resolveProviderSkillsDirs,
|
|
153
157
|
resolveRegistryTemplatePath
|
|
154
|
-
} from "./chunk-
|
|
158
|
+
} from "./chunk-OCI4RYI5.js";
|
|
155
159
|
|
|
156
160
|
// src/core/skills/integrity.ts
|
|
157
161
|
import { existsSync, lstatSync, readlinkSync } from "fs";
|
|
@@ -269,7 +273,7 @@ function shouldOverrideSkill(skillName, incomingSource, existingEntry) {
|
|
|
269
273
|
return true;
|
|
270
274
|
}
|
|
271
275
|
async function validateInstructionIntegrity(providers, projectDir, scope, expectedContent) {
|
|
272
|
-
const { checkAllInjections: checkAllInjections2 } = await import("./injector-
|
|
276
|
+
const { checkAllInjections: checkAllInjections2 } = await import("./injector-F4EHB3CZ.js");
|
|
273
277
|
const results = await checkAllInjections2(providers, projectDir, scope, expectedContent);
|
|
274
278
|
const issues = [];
|
|
275
279
|
for (const result of results) {
|
|
@@ -317,6 +321,8 @@ export {
|
|
|
317
321
|
checkSkillIntegrity,
|
|
318
322
|
checkSkillUpdate,
|
|
319
323
|
clearRegisteredLibrary,
|
|
324
|
+
dedupeFile,
|
|
325
|
+
dedupeFiles,
|
|
320
326
|
deepMerge,
|
|
321
327
|
detectAllProviders,
|
|
322
328
|
detectMcpInstallations,
|
|
@@ -368,6 +374,7 @@ export {
|
|
|
368
374
|
getProviderCapabilities,
|
|
369
375
|
getProviderCount,
|
|
370
376
|
getProviderHookProfile,
|
|
377
|
+
getProviderInstructionReferences,
|
|
371
378
|
getProviderOnlyEvents,
|
|
372
379
|
getProviderSummary,
|
|
373
380
|
getProvidersByHookEvent,
|
|
@@ -399,6 +406,7 @@ export {
|
|
|
399
406
|
listMcpServers,
|
|
400
407
|
loadLibraryFromModule,
|
|
401
408
|
normalizeRecommendationCriteria,
|
|
409
|
+
parseCaampBlocks,
|
|
402
410
|
parseInjectionContent,
|
|
403
411
|
parseSkillFile,
|
|
404
412
|
parseSource,
|
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"]}
|
|
@@ -1,24 +1,30 @@
|
|
|
1
1
|
import {
|
|
2
2
|
checkAllInjections,
|
|
3
3
|
checkInjection,
|
|
4
|
+
dedupeFile,
|
|
5
|
+
dedupeFiles,
|
|
4
6
|
ensureAllProviderInstructionFiles,
|
|
5
7
|
ensureProviderInstructionFile,
|
|
6
8
|
getProviderAgentFolder,
|
|
7
9
|
inject,
|
|
8
10
|
injectAll,
|
|
11
|
+
parseCaampBlocks,
|
|
9
12
|
removeInjection,
|
|
10
13
|
writeAgentFileToAllProviders
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-OPUPNLUJ.js";
|
|
15
|
+
import "./chunk-OCI4RYI5.js";
|
|
13
16
|
export {
|
|
14
17
|
checkAllInjections,
|
|
15
18
|
checkInjection,
|
|
19
|
+
dedupeFile,
|
|
20
|
+
dedupeFiles,
|
|
16
21
|
ensureAllProviderInstructionFiles,
|
|
17
22
|
ensureProviderInstructionFile,
|
|
18
23
|
getProviderAgentFolder,
|
|
19
24
|
inject,
|
|
20
25
|
injectAll,
|
|
26
|
+
parseCaampBlocks,
|
|
21
27
|
removeInjection,
|
|
22
28
|
writeAgentFileToAllProviders
|
|
23
29
|
};
|
|
24
|
-
//# sourceMappingURL=injector-
|
|
30
|
+
//# sourceMappingURL=injector-F4EHB3CZ.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/caamp",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.33",
|
|
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.33",
|
|
54
|
+
"@cleocode/contracts": "2026.5.33",
|
|
55
|
+
"@cleocode/lafs": "2026.5.33",
|
|
56
|
+
"@cleocode/paths": "2026.5.33"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@biomejs/biome": "2.4.11",
|
package/providers/registry.json
CHANGED
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
"pathGlobal": "$HOME/.claude",
|
|
14
14
|
"pathProject": ".claude",
|
|
15
15
|
"instructFile": "CLAUDE.md",
|
|
16
|
+
"instructionReferences": [
|
|
17
|
+
"@~/.cleo/templates/CLEO-INJECTION.md",
|
|
18
|
+
"@.cleo/memory-bridge.md"
|
|
19
|
+
],
|
|
16
20
|
"pathSkills": "$HOME/.claude/skills",
|
|
17
21
|
"pathProjectSkills": ".claude/skills",
|
|
18
22
|
"detection": {
|
|
@@ -87,6 +91,10 @@
|
|
|
87
91
|
"pathGlobal": "$HOME/.cursor",
|
|
88
92
|
"pathProject": ".cursor",
|
|
89
93
|
"instructFile": "AGENTS.md",
|
|
94
|
+
"instructionReferences": [
|
|
95
|
+
"@~/.cleo/templates/CLEO-INJECTION.md",
|
|
96
|
+
"@.cleo/memory-bridge.md"
|
|
97
|
+
],
|
|
90
98
|
"pathSkills": "$HOME/.cursor/skills",
|
|
91
99
|
"pathProjectSkills": ".cursor/skills",
|
|
92
100
|
"detection": {
|
|
@@ -200,6 +208,10 @@
|
|
|
200
208
|
"pathGlobal": "$HOME/.codex",
|
|
201
209
|
"pathProject": ".codex",
|
|
202
210
|
"instructFile": "AGENTS.md",
|
|
211
|
+
"instructionReferences": [
|
|
212
|
+
"@~/.cleo/templates/CLEO-INJECTION.md",
|
|
213
|
+
"@.cleo/memory-bridge.md"
|
|
214
|
+
],
|
|
203
215
|
"pathSkills": "$HOME/.codex/skills",
|
|
204
216
|
"pathProjectSkills": ".codex/skills",
|
|
205
217
|
"detection": {
|
|
@@ -262,6 +274,10 @@
|
|
|
262
274
|
"pathGlobal": "$HOME/.gemini",
|
|
263
275
|
"pathProject": ".gemini",
|
|
264
276
|
"instructFile": "GEMINI.md",
|
|
277
|
+
"instructionReferences": [
|
|
278
|
+
"@~/.cleo/templates/CLEO-INJECTION.md",
|
|
279
|
+
"@.cleo/memory-bridge.md"
|
|
280
|
+
],
|
|
265
281
|
"pathSkills": "$HOME/.gemini/skills",
|
|
266
282
|
"pathProjectSkills": ".gemini/skills",
|
|
267
283
|
"detection": {
|
|
@@ -374,6 +390,10 @@
|
|
|
374
390
|
"pathGlobal": "$CONFIG/opencode",
|
|
375
391
|
"pathProject": ".opencode",
|
|
376
392
|
"instructFile": "AGENTS.md",
|
|
393
|
+
"instructionReferences": [
|
|
394
|
+
"@~/.cleo/templates/CLEO-INJECTION.md",
|
|
395
|
+
"@.cleo/memory-bridge.md"
|
|
396
|
+
],
|
|
377
397
|
"pathSkills": "$CONFIG/opencode/skills",
|
|
378
398
|
"pathProjectSkills": ".opencode/skills",
|
|
379
399
|
"detection": {
|
|
@@ -479,6 +499,10 @@
|
|
|
479
499
|
"pathGlobal": "$HOME/.kimi",
|
|
480
500
|
"pathProject": ".kimi",
|
|
481
501
|
"instructFile": "AGENTS.md",
|
|
502
|
+
"instructionReferences": [
|
|
503
|
+
"@~/.cleo/templates/CLEO-INJECTION.md",
|
|
504
|
+
"@.cleo/memory-bridge.md"
|
|
505
|
+
],
|
|
482
506
|
"pathSkills": "$HOME/.kimi/skills",
|
|
483
507
|
"pathProjectSkills": ".kimi/skills",
|
|
484
508
|
"detection": {
|
|
@@ -1844,6 +1868,10 @@
|
|
|
1844
1868
|
"pathGlobal": "$HOME/.pi/agent",
|
|
1845
1869
|
"pathProject": ".pi",
|
|
1846
1870
|
"instructFile": "AGENTS.md",
|
|
1871
|
+
"instructionReferences": [
|
|
1872
|
+
"@~/.cleo/templates/CLEO-INJECTION.md",
|
|
1873
|
+
"@.cleo/memory-bridge.md"
|
|
1874
|
+
],
|
|
1847
1875
|
"pathSkills": "$HOME/.pi/agent/skills",
|
|
1848
1876
|
"pathProjectSkills": ".pi/skills",
|
|
1849
1877
|
"detection": {
|