@cleocode/caamp 2026.10.3 → 2026.10.5-rc.ci.672
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-3OL6CAMT.js → chunk-E2QFVEIS.js} +18 -6
- package/dist/chunk-E2QFVEIS.js.map +1 -0
- package/dist/{chunk-UIXTFV35.js → chunk-JR6T47PC.js} +45 -7
- package/dist/chunk-JR6T47PC.js.map +1 -0
- package/dist/cli.js +205 -179
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +63 -3
- package/dist/index.js +13 -6
- package/dist/index.js.map +1 -1
- package/dist/{injector-KSFK5LF2.js → injector-Q6KCKS76.js} +4 -2
- package/package.json +7 -7
- package/dist/chunk-3OL6CAMT.js.map +0 -1
- package/dist/chunk-UIXTFV35.js.map +0 -1
- /package/dist/{injector-KSFK5LF2.js.map → injector-Q6KCKS76.js.map} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1545,6 +1545,13 @@ interface InstructionUpdateSummary {
|
|
|
1545
1545
|
scope: Scope;
|
|
1546
1546
|
/** The total number of instruction files that were modified. */
|
|
1547
1547
|
updatedFiles: number;
|
|
1548
|
+
/**
|
|
1549
|
+
* Why nothing was written, when the update was skipped: a project-scope
|
|
1550
|
+
* update at the home directory (T13257) — providers load instruction files
|
|
1551
|
+
* from every ancestor directory, so a file there would reach every session
|
|
1552
|
+
* under `$HOME`. Absent when the update ran.
|
|
1553
|
+
*/
|
|
1554
|
+
skipped?: string;
|
|
1548
1555
|
/** Detailed action log per instruction file. */
|
|
1549
1556
|
actions: Array<{
|
|
1550
1557
|
file: string;
|
|
@@ -1566,7 +1573,8 @@ interface InstructionUpdateSummary {
|
|
|
1566
1573
|
* @param content - The instruction content to inject
|
|
1567
1574
|
* @param scope - The scope for instruction updates, defaults to `"project"`
|
|
1568
1575
|
* @param projectDir - The project root directory, defaults to `process.cwd()`
|
|
1569
|
-
* @returns A summary of updated files and actions taken per file
|
|
1576
|
+
* @returns A summary of updated files and actions taken per file; at the
|
|
1577
|
+
* home directory (project scope) nothing is written and `skipped` says why
|
|
1570
1578
|
*
|
|
1571
1579
|
* @example
|
|
1572
1580
|
* ```typescript
|
|
@@ -1623,7 +1631,8 @@ declare function validatePackageArtifact(inventory: PackageArtifactInventory, po
|
|
|
1623
1631
|
/**
|
|
1624
1632
|
* Reject declaration and stray JavaScript output absent from the published CLI
|
|
1625
1633
|
* bundle: only `build.mjs`'s declared entries (the CLI bundle and the hook
|
|
1626
|
-
* runtime)
|
|
1634
|
+
* runtime) and their code-split chunks ({@link CLEO_CLI_CHUNK_PATTERN}) may ship
|
|
1635
|
+
* as `.js` under `dist/`.
|
|
1627
1636
|
*
|
|
1628
1637
|
* @param files - Actual selected package files, not a development directory listing.
|
|
1629
1638
|
* @returns Concrete build-shape failures; this does not load the bundle.
|
|
@@ -4967,6 +4976,33 @@ declare function syncGlobalInstructions(options?: SyncGlobalInstructionsOptions)
|
|
|
4967
4976
|
*/
|
|
4968
4977
|
declare function checkGlobalInstructionStaleness(options?: GlobalInstructionOptions): Promise<GlobalInstructionStalenessReport>;
|
|
4969
4978
|
|
|
4979
|
+
/**
|
|
4980
|
+
* Whether a project is rooted at the home directory (T13227, T13257).
|
|
4981
|
+
* Providers load instruction files from the working directory up through
|
|
4982
|
+
* every ancestor, so a project-scope instruction file at `$HOME` reaches every
|
|
4983
|
+
* session under it. Kept in its own dependency-light module so commands can
|
|
4984
|
+
* check it without loading the injector.
|
|
4985
|
+
*
|
|
4986
|
+
* @task T13257
|
|
4987
|
+
*/
|
|
4988
|
+
/**
|
|
4989
|
+
* Whether `projectDir` is the home directory: a project-scope instruction
|
|
4990
|
+
* file there would be loaded into every session under `$HOME` (T13227).
|
|
4991
|
+
* Compared through the native realpath, case-folded where volumes are
|
|
4992
|
+
* case-insensitive by default (darwin, win32).
|
|
4993
|
+
*
|
|
4994
|
+
* @param projectDir - the project root.
|
|
4995
|
+
* @returns `true` when it is the home directory.
|
|
4996
|
+
*
|
|
4997
|
+
* @example
|
|
4998
|
+
* ```typescript
|
|
4999
|
+
* isHomeProject(os.homedir()); // true
|
|
5000
|
+
* ```
|
|
5001
|
+
*
|
|
5002
|
+
* @public
|
|
5003
|
+
*/
|
|
5004
|
+
declare function isHomeProject(projectDir: string): boolean;
|
|
5005
|
+
|
|
4970
5006
|
/**
|
|
4971
5007
|
* CAAMP marker engine — parsing, damage repair, and canonical block rendering.
|
|
4972
5008
|
*
|
|
@@ -5580,6 +5616,8 @@ declare function checkAllInjections(providers: Provider[], projectDir: string, s
|
|
|
5580
5616
|
* @param scope - Whether to target project or global instruction files
|
|
5581
5617
|
* @param content - Content to inject between CAAMP markers
|
|
5582
5618
|
* @returns Map of file path to action taken (`"created"`, `"added"`, `"consolidated"`, `"updated"`, or `"intact"`)
|
|
5619
|
+
* @throws {@link HomeInstructionFileError} for `scope: 'project'` when the
|
|
5620
|
+
* project is the home directory (T13257); nothing is written
|
|
5583
5621
|
*
|
|
5584
5622
|
* @remarks
|
|
5585
5623
|
* Providers sharing the same instruction file are only written once to avoid
|
|
@@ -5634,6 +5672,24 @@ interface EnsureProviderInstructionFileResult {
|
|
|
5634
5672
|
/** Provider ID. */
|
|
5635
5673
|
providerId: string;
|
|
5636
5674
|
}
|
|
5675
|
+
/**
|
|
5676
|
+
* A provider instruction file was asked for at a project rooted at the home
|
|
5677
|
+
* directory (T13227). Claude Code, Codex and the other providers load
|
|
5678
|
+
* instruction files from the working directory up through every ancestor, so
|
|
5679
|
+
* `~/CLAUDE.md` or `~/AGENTS.md` is loaded into every session anywhere under
|
|
5680
|
+
* `$HOME`: user-global in effect. Nothing is written. The deliberate global
|
|
5681
|
+
* files (`scope: 'global'`, the `~/.agents` hub) are not affected.
|
|
5682
|
+
*
|
|
5683
|
+
* @public
|
|
5684
|
+
*/
|
|
5685
|
+
declare class HomeInstructionFileError extends Error {
|
|
5686
|
+
/** The instruction file that was refused. */
|
|
5687
|
+
readonly filePath: string;
|
|
5688
|
+
/**
|
|
5689
|
+
* @param filePath - the refused file.
|
|
5690
|
+
*/
|
|
5691
|
+
constructor(filePath: string);
|
|
5692
|
+
}
|
|
5637
5693
|
/**
|
|
5638
5694
|
* Ensure a provider's instruction file exists with the correct CAAMP block.
|
|
5639
5695
|
*
|
|
@@ -5654,6 +5710,8 @@ interface EnsureProviderInstructionFileResult {
|
|
|
5654
5710
|
* @param options - References, content, and scope configuration
|
|
5655
5711
|
* @returns Result with file path, action taken, and provider metadata
|
|
5656
5712
|
* @throws Error if the provider ID is not found in the registry
|
|
5713
|
+
* @throws {@link HomeInstructionFileError} for a project-scope file when the
|
|
5714
|
+
* project is the home directory (T13227); nothing is written
|
|
5657
5715
|
*
|
|
5658
5716
|
* @example
|
|
5659
5717
|
* ```typescript
|
|
@@ -8581,6 +8639,8 @@ declare const ErrorCodes: {
|
|
|
8581
8639
|
readonly REMOVE_FAILED: "E_REMOVE_FAILED";
|
|
8582
8640
|
readonly UPDATE_FAILED: "E_UPDATE_FAILED";
|
|
8583
8641
|
readonly VALIDATION_FAILED: "E_VALIDATION_FAILED";
|
|
8642
|
+
/** A project-scope instruction file was refused at the home directory (T13257). */
|
|
8643
|
+
readonly HOME_INSTRUCTION_FILE: "E_HOME_INSTRUCTION_FILE";
|
|
8584
8644
|
readonly AUDIT_FAILED: "E_AUDIT_FAILED";
|
|
8585
8645
|
readonly NETWORK_ERROR: "E_NETWORK_ERROR";
|
|
8586
8646
|
readonly FILE_SYSTEM_ERROR: "E_FILE_SYSTEM_ERROR";
|
|
@@ -9869,4 +9929,4 @@ declare function parseSource(input: string): ParsedSource;
|
|
|
9869
9929
|
*/
|
|
9870
9930
|
declare function isMarketplaceScoped(input: string): boolean;
|
|
9871
9931
|
|
|
9872
|
-
export { type AskToolStatus, type AuditFinding, type AuditResult, type AuditRule, type AuditSeverity, type BatchInstallOptions, type BatchInstallResult, type BlockInsertPosition, CANONICAL_HOOK_EVENTS, CLEO_ARTIFACT_BUDGETS, CLEO_ARTIFACT_REQUIREMENTS, 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, EmbeddedDeliveryDowngradeError, type EnsureProviderInstructionFileOptions, type EnsureProviderInstructionFileResult, type EnsureProviderRuleFileOptions, type EnsureProviderRuleFileResult, type ExclusivityMode, type FileLockOptions, type GatedSkillInstallOptions, type GatedSkillInstallResult, type GlobalInstructionOptions, type GlobalOptions, HITL_REQUEST_FALLBACK, HOOK_CATEGORIES, type Harness, type HarnessScope, type HitlRequestFallback, type HookCategory, type HookEvent, type HookHandlerType, type HookMapping, type HookSupportResult, type HookSystemType, type InjectionCheckResult, type InjectionStatus, type InjectionTemplate, type InstallMcpServerOptions, type InstallMcpServerResult, type InstallSkillOptions, type InstructionUpdateSummary, JsonConfigParseError, 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 NormalizeResult, type NormalizedHookEvent, type NormalizedRecommendationCriteria, PROVIDER_ASK_TOOLS, type ParsedSource, PiHarness, PiRequiredError, type Provider, type ProviderAskTool, 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 ReconcileResult, type RegistryHarnessKind, type RegistryHookCatalog, type RegistryHookFormat, type RemoveMcpServerOptions, type RemoveMcpServerResult, type RepairResult, type ResolveDefaultTargetProvidersOptions, type ResolvedProviderAskTool, type ResolvedSkillSource, type SkillBatchOperation, type SkillEntry, type SkillGateModules, SkillInstallError, type SkillInstallErrorCode, type SkillInstallErrorDetails, type SkillInstallGateOptions, type SkillInstallGateReport, type SkillInstallResult, type SkillIntegrityResult, type SkillIntegrityStatus, type SkillLibrary, type SkillLibraryDispatchMatrix, type SkillLibraryEntry, type SkillLibraryManifest, type SkillLibraryManifestSkill, type SkillLibraryProfile, type SkillLibraryValidationIssue, type SkillLibraryValidationResult, type SkillMetadata, type SkillRowData, type SkillRowSourceType, type SkillSourceProgress, type SkillsPrecedence, type SourceType, type SpawnAdapter, type SpawnMechanism, type SpawnOptions, type SpawnResult, type SubagentHandle, type SubagentResult, type SubagentTask, type SyncGlobalInstructionsOptions, type TransportType, type ValidateCantProfileResult, type ValidationIssue, type ValidationResult, type WriteAgentFileOptions, type WriteAgentFileResult, _resetPlatformPathsCache, assertCleoShippedBuildShape, assertNotTornRead, blockPattern, buildBlock, buildHookMatrix, buildInjectionContent, buildLibraryFromFiles, buildSkillsMap, catalog, catalogEntryFromManifest, checkAllInjections, checkAllSkillIntegrity, checkAllSkillUpdates, checkGlobalInstructionStaleness, checkInjection, checkSkillIntegrity, checkSkillUpdate, classifyPackageFilesEntry, clearRegisteredLibrary, dedupeFile, dedupeFiles, deepMerge, detectAllProviders, detectMcpInstallations, detectProjectProviders, detectProvider, discoverSkill, discoverSkills, ensureAllProviderInstructionFiles, ensureDir, ensureProviderInstructionFile, ensureProviderRuleFile, formatSkillRecommendations, generateInjectionContent, generateSkillsSection, getAgentsConfigPath, getAgentsHome, getAgentsInstructFile, getAgentsLinksDir, getAgentsMcpDir, getAgentsMcpServersPath, getAgentsSpecDir, getAgentsWikiDir, getAllCanonicalEvents, getAllHarnesses, getAllProviders, getCanonicalEvent, getCanonicalEventsByCategory, getCommonEvents, getCommonHookEvents, getEffectiveSkillsPaths, getExclusivityMode, getHarnessFor, getHookConfigPath, getHookMappingsVersion, getHookSupport, getHookSystemType, getInstalledProviders, getInstructionFiles, getLockFilePath, getMappedProviderIds, getNestedValue, getPlatformLocations, getPlatformPaths, getPrimaryHarness, getPrimaryProvider, getProjectAgentsDir, getProvider, getProviderAgentFolder, getProviderAskTool, getProviderCapabilities, getProviderCount, getProviderHookProfile, getProviderInstructionReferences, getProviderOnlyEvents, getProviderSummary, getProvidersByHookEvent, getProvidersByInstructFile, getProvidersByPriority, getProvidersBySkillsPrecedence, getProvidersBySpawnCapability, getProvidersByStatus, getProvidersForEvent, getRegistryVersion, getSpawnCapableProviders, getSupportedEvents, getSystemInfo, getTrackedSkills, getUnsupportedEvents, groupByInstructFile, inferSkillSourceType, inject, injectAll, installBatchWithRollback, installMcpServer, installResolvedSkill, installSkill, installSkillFromSource, instructionFileCascade, isCaampOwnedSkill, isEmbeddedDelivery, isExclusivityMode, isMarketplaceScoped, isQuiet, isVerbose, listAllMcpServers, listCanonicalSkills, listMcpServers, loadLibraryFromModule, mergeBlockBodies, normalizeMarkers, normalizeRecommendationCriteria, parseBlocks, parseCaampBlocks, parseInjectionContent, parseSkillFile, parseSource, providerSupports, providerSupportsById, rankSkills, readConfig, recommendSkills, reconcile, recordSkillInstall, registerSkillLibrary, registerSkillLibraryFromPath, removeConfig, removeInjection, removeMcpServer, removeMcpServerFromAll, removeSkill, removeSkillFromLock, repairContent, repairInstructionFiles, replaceDirectoryFromSource, resetDetectionCache, resetExclusivityModeOverride, resetRegistry, resolveAlias, resolveDefaultTargetProviders, resolveGlobalInstructionPath, resolveInstructionDelivery, resolveMcpConfigPath, resolveNativeEvent, resolveProviderSkillsDirs, resolveRegistryTemplatePath, resolveSkillSource, runSkillInstallGate, scanDirectory, scanFile, scoreSkillRecommendation, searchSkills, selectProvidersByMinimumPriority, setExclusivityMode, setQuiet, setVerbose, shouldOverrideSkill, stageSkillCopy, supportsHook, swapIntoPlace, syncGlobalInstructions, toCanonical, toNative, toNativeBatch, toSarif, tokenizeCriteriaValue, translateToAll, updateInstructionsSingleOperation, updateJsonConfigFile, validateInstructionIntegrity, validatePackageArtifact, validateRecommendationCriteria, validateSkill, withFileLock, writeAgentFileToAllProviders, writeConfig };
|
|
9932
|
+
export { type AskToolStatus, type AuditFinding, type AuditResult, type AuditRule, type AuditSeverity, type BatchInstallOptions, type BatchInstallResult, type BlockInsertPosition, CANONICAL_HOOK_EVENTS, CLEO_ARTIFACT_BUDGETS, CLEO_ARTIFACT_REQUIREMENTS, 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, EmbeddedDeliveryDowngradeError, type EnsureProviderInstructionFileOptions, type EnsureProviderInstructionFileResult, type EnsureProviderRuleFileOptions, type EnsureProviderRuleFileResult, type ExclusivityMode, type FileLockOptions, type GatedSkillInstallOptions, type GatedSkillInstallResult, type GlobalInstructionOptions, type GlobalOptions, HITL_REQUEST_FALLBACK, HOOK_CATEGORIES, type Harness, type HarnessScope, type HitlRequestFallback, HomeInstructionFileError, type HookCategory, type HookEvent, type HookHandlerType, type HookMapping, type HookSupportResult, type HookSystemType, type InjectionCheckResult, type InjectionStatus, type InjectionTemplate, type InstallMcpServerOptions, type InstallMcpServerResult, type InstallSkillOptions, type InstructionUpdateSummary, JsonConfigParseError, 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 NormalizeResult, type NormalizedHookEvent, type NormalizedRecommendationCriteria, PROVIDER_ASK_TOOLS, type ParsedSource, PiHarness, PiRequiredError, type Provider, type ProviderAskTool, 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 ReconcileResult, type RegistryHarnessKind, type RegistryHookCatalog, type RegistryHookFormat, type RemoveMcpServerOptions, type RemoveMcpServerResult, type RepairResult, type ResolveDefaultTargetProvidersOptions, type ResolvedProviderAskTool, type ResolvedSkillSource, type SkillBatchOperation, type SkillEntry, type SkillGateModules, SkillInstallError, type SkillInstallErrorCode, type SkillInstallErrorDetails, type SkillInstallGateOptions, type SkillInstallGateReport, type SkillInstallResult, type SkillIntegrityResult, type SkillIntegrityStatus, type SkillLibrary, type SkillLibraryDispatchMatrix, type SkillLibraryEntry, type SkillLibraryManifest, type SkillLibraryManifestSkill, type SkillLibraryProfile, type SkillLibraryValidationIssue, type SkillLibraryValidationResult, type SkillMetadata, type SkillRowData, type SkillRowSourceType, type SkillSourceProgress, type SkillsPrecedence, type SourceType, type SpawnAdapter, type SpawnMechanism, type SpawnOptions, type SpawnResult, type SubagentHandle, type SubagentResult, type SubagentTask, type SyncGlobalInstructionsOptions, type TransportType, type ValidateCantProfileResult, type ValidationIssue, type ValidationResult, type WriteAgentFileOptions, type WriteAgentFileResult, _resetPlatformPathsCache, assertCleoShippedBuildShape, assertNotTornRead, blockPattern, buildBlock, buildHookMatrix, buildInjectionContent, buildLibraryFromFiles, buildSkillsMap, catalog, catalogEntryFromManifest, checkAllInjections, checkAllSkillIntegrity, checkAllSkillUpdates, checkGlobalInstructionStaleness, checkInjection, checkSkillIntegrity, checkSkillUpdate, classifyPackageFilesEntry, clearRegisteredLibrary, dedupeFile, dedupeFiles, deepMerge, detectAllProviders, detectMcpInstallations, detectProjectProviders, detectProvider, discoverSkill, discoverSkills, ensureAllProviderInstructionFiles, ensureDir, ensureProviderInstructionFile, ensureProviderRuleFile, formatSkillRecommendations, generateInjectionContent, generateSkillsSection, getAgentsConfigPath, getAgentsHome, getAgentsInstructFile, getAgentsLinksDir, getAgentsMcpDir, getAgentsMcpServersPath, getAgentsSpecDir, getAgentsWikiDir, getAllCanonicalEvents, getAllHarnesses, getAllProviders, getCanonicalEvent, getCanonicalEventsByCategory, getCommonEvents, getCommonHookEvents, getEffectiveSkillsPaths, getExclusivityMode, getHarnessFor, getHookConfigPath, getHookMappingsVersion, getHookSupport, getHookSystemType, getInstalledProviders, getInstructionFiles, getLockFilePath, getMappedProviderIds, getNestedValue, getPlatformLocations, getPlatformPaths, getPrimaryHarness, getPrimaryProvider, getProjectAgentsDir, getProvider, getProviderAgentFolder, getProviderAskTool, getProviderCapabilities, getProviderCount, getProviderHookProfile, getProviderInstructionReferences, getProviderOnlyEvents, getProviderSummary, getProvidersByHookEvent, getProvidersByInstructFile, getProvidersByPriority, getProvidersBySkillsPrecedence, getProvidersBySpawnCapability, getProvidersByStatus, getProvidersForEvent, getRegistryVersion, getSpawnCapableProviders, getSupportedEvents, getSystemInfo, getTrackedSkills, getUnsupportedEvents, groupByInstructFile, inferSkillSourceType, inject, injectAll, installBatchWithRollback, installMcpServer, installResolvedSkill, installSkill, installSkillFromSource, instructionFileCascade, isCaampOwnedSkill, isEmbeddedDelivery, isExclusivityMode, isHomeProject, isMarketplaceScoped, isQuiet, isVerbose, listAllMcpServers, listCanonicalSkills, listMcpServers, loadLibraryFromModule, mergeBlockBodies, normalizeMarkers, normalizeRecommendationCriteria, parseBlocks, parseCaampBlocks, parseInjectionContent, parseSkillFile, parseSource, providerSupports, providerSupportsById, rankSkills, readConfig, recommendSkills, reconcile, recordSkillInstall, registerSkillLibrary, registerSkillLibraryFromPath, removeConfig, removeInjection, removeMcpServer, removeMcpServerFromAll, removeSkill, removeSkillFromLock, repairContent, repairInstructionFiles, replaceDirectoryFromSource, resetDetectionCache, resetExclusivityModeOverride, resetRegistry, resolveAlias, resolveDefaultTargetProviders, resolveGlobalInstructionPath, resolveInstructionDelivery, resolveMcpConfigPath, resolveNativeEvent, resolveProviderSkillsDirs, resolveRegistryTemplatePath, resolveSkillSource, runSkillInstallGate, scanDirectory, scanFile, scoreSkillRecommendation, searchSkills, selectProvidersByMinimumPriority, setExclusivityMode, setQuiet, setVerbose, shouldOverrideSkill, stageSkillCopy, supportsHook, swapIntoPlace, syncGlobalInstructions, toCanonical, toNative, toNativeBatch, toSarif, tokenizeCriteriaValue, translateToAll, updateInstructionsSingleOperation, updateJsonConfigFile, validateInstructionIntegrity, validatePackageArtifact, validateRecommendationCriteria, validateSkill, withFileLock, writeAgentFileToAllProviders, writeConfig };
|
package/dist/index.js
CHANGED
|
@@ -82,10 +82,11 @@ import {
|
|
|
82
82
|
validateRecommendationCriteria,
|
|
83
83
|
validateSkill,
|
|
84
84
|
writeConfig
|
|
85
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-E2QFVEIS.js";
|
|
86
86
|
import {
|
|
87
87
|
EmbeddedDeliveryDowngradeError,
|
|
88
88
|
HITL_REQUEST_FALLBACK,
|
|
89
|
+
HomeInstructionFileError,
|
|
89
90
|
JsonConfigParseError,
|
|
90
91
|
PROVIDER_ASK_TOOLS,
|
|
91
92
|
assertNotTornRead,
|
|
@@ -126,6 +127,7 @@ import {
|
|
|
126
127
|
injectAll,
|
|
127
128
|
instructionFileCascade,
|
|
128
129
|
isEmbeddedDelivery,
|
|
130
|
+
isHomeProject,
|
|
129
131
|
mergeBlockBodies,
|
|
130
132
|
normalizeMarkers,
|
|
131
133
|
parseBlocks,
|
|
@@ -144,7 +146,7 @@ import {
|
|
|
144
146
|
updateJsonConfigFile,
|
|
145
147
|
withFileLock,
|
|
146
148
|
writeAgentFileToAllProviders
|
|
147
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-JR6T47PC.js";
|
|
148
150
|
import {
|
|
149
151
|
CANONICAL_HOOK_EVENTS,
|
|
150
152
|
HOOK_CATEGORIES,
|
|
@@ -199,11 +201,14 @@ var CLEO_ARTIFACT_BUDGETS = Object.freeze({
|
|
|
199
201
|
});
|
|
200
202
|
var CLEO_SHIPPED_JS_ENTRIES = /* @__PURE__ */ new Set([
|
|
201
203
|
"dist/cli/index.js",
|
|
202
|
-
"dist/cli/hook-entry.js"
|
|
204
|
+
"dist/cli/hook-entry.js",
|
|
205
|
+
"dist/cli/update-check-entry.js"
|
|
203
206
|
]);
|
|
207
|
+
var CLEO_CLI_CHUNK_PATTERN = /^dist\/cli\/[A-Za-z0-9_.-]+-[A-Z0-9]{8}\.js$/;
|
|
204
208
|
var CLEO_ARTIFACT_REQUIREMENTS = Object.freeze([
|
|
205
209
|
{ id: "cli-entry", path: "dist/cli/index.js", match: "exact" },
|
|
206
210
|
{ id: "cli-hook-entry", path: "dist/cli/hook-entry.js", match: "exact" },
|
|
211
|
+
{ id: "cli-update-check-entry", path: "dist/cli/update-check-entry.js", match: "exact" },
|
|
207
212
|
{ id: "studio-server-entry", path: "studio-dist/index.js", match: "exact" },
|
|
208
213
|
{ id: "studio-handler", path: "studio-dist/handler.js", match: "exact" },
|
|
209
214
|
{ id: "studio-server", path: "studio-dist/server/index.js", match: "exact" },
|
|
@@ -399,11 +404,11 @@ function assertCleoShippedBuildShape(files) {
|
|
|
399
404
|
`${declarations.length} declaration file(s) under dist/ \u2014 the esbuild bundle emits none`
|
|
400
405
|
);
|
|
401
406
|
const stray = dist.filter(
|
|
402
|
-
(file) => file.path.endsWith(".js") && !CLEO_SHIPPED_JS_ENTRIES.has(file.path)
|
|
407
|
+
(file) => file.path.endsWith(".js") && !CLEO_SHIPPED_JS_ENTRIES.has(file.path) && !CLEO_CLI_CHUNK_PATTERN.test(file.path)
|
|
403
408
|
);
|
|
404
409
|
if (stray.length)
|
|
405
410
|
reasons.push(
|
|
406
|
-
`${stray.length} .js file(s) under dist/ outside the declared entries ${[...CLEO_SHIPPED_JS_ENTRIES].join(", ")}, e.g. ${stray[0]?.path}`
|
|
411
|
+
`${stray.length} .js file(s) under dist/ outside the declared entries ${[...CLEO_SHIPPED_JS_ENTRIES].join(", ")} and their chunks, e.g. ${stray[0]?.path}`
|
|
407
412
|
);
|
|
408
413
|
return reasons;
|
|
409
414
|
}
|
|
@@ -525,7 +530,7 @@ function shouldOverrideSkill(skillName, incomingSource, existingEntry) {
|
|
|
525
530
|
return true;
|
|
526
531
|
}
|
|
527
532
|
async function validateInstructionIntegrity(providers, projectDir, scope, expectedContent) {
|
|
528
|
-
const { checkAllInjections: checkAllInjections2 } = await import("./injector-
|
|
533
|
+
const { checkAllInjections: checkAllInjections2 } = await import("./injector-Q6KCKS76.js");
|
|
529
534
|
const results = await checkAllInjections2(providers, projectDir, scope, expectedContent);
|
|
530
535
|
const issues = [];
|
|
531
536
|
for (const result of results) {
|
|
@@ -560,6 +565,7 @@ export {
|
|
|
560
565
|
EmbeddedDeliveryDowngradeError,
|
|
561
566
|
HITL_REQUEST_FALLBACK,
|
|
562
567
|
HOOK_CATEGORIES,
|
|
568
|
+
HomeInstructionFileError,
|
|
563
569
|
JsonConfigParseError,
|
|
564
570
|
MarketplaceClient,
|
|
565
571
|
PROVIDER_ASK_TOOLS,
|
|
@@ -670,6 +676,7 @@ export {
|
|
|
670
676
|
isCaampOwnedSkill,
|
|
671
677
|
isEmbeddedDelivery,
|
|
672
678
|
isExclusivityMode,
|
|
679
|
+
isHomeProject,
|
|
673
680
|
isMarketplaceScoped,
|
|
674
681
|
isQuiet,
|
|
675
682
|
isVerbose,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/artifacts/validation.ts","../src/core/skills/integrity.ts"],"sourcesContent":["/**\n * Pure semantic validation of npm-produced package inventories.\n *\n * Code placed in `packages/caamp/` per Package-Boundary Check — verified\n * against AGENTS.md. No filesystem, process, model, or runtime-store access.\n */\n\nimport { posix } from 'node:path';\nimport type {\n PackageArtifactBudgets,\n PackageArtifactFile,\n PackageArtifactInventory,\n PackageArtifactIssue,\n PackageArtifactPolicy,\n PackageArtifactRequirement,\n PackageArtifactValidation,\n PackageFilesEntry,\n} from '@cleocode/contracts/package-artifact';\n\n/** Existing CLI upper budgets: 20 MiB packed, 36 MiB unpacked, and 800 files. */\nexport const CLEO_ARTIFACT_BUDGETS: Readonly<PackageArtifactBudgets> = Object.freeze({\n packedBytes: 20 * 1024 * 1024,\n unpackedBytes: 36 * 1024 * 1024,\n fileCount: 800,\n});\n\n/**\n * The JavaScript files `build.mjs` declares for the published CLI: the CLI\n * bundle, and the provider hook runtime that `bin/cleo.js` imports directly for\n * `cleo hook heavy-command` (T12983), skipping the CLI bootstrap. Any other\n * `.js` under `dist/` is development output.\n */\nconst CLEO_SHIPPED_JS_ENTRIES: ReadonlySet<string> = new Set([\n 'dist/cli/index.js',\n 'dist/cli/hook-entry.js',\n]);\n\n/** Required CLI and adapter-node resources, independent of historical byte/file-count floors. */\nexport const CLEO_ARTIFACT_REQUIREMENTS: readonly PackageArtifactRequirement[] = Object.freeze([\n { id: 'cli-entry', path: 'dist/cli/index.js', match: 'exact' },\n { id: 'cli-hook-entry', path: 'dist/cli/hook-entry.js', match: 'exact' },\n { id: 'studio-server-entry', path: 'studio-dist/index.js', match: 'exact' },\n { id: 'studio-handler', path: 'studio-dist/handler.js', match: 'exact' },\n { id: 'studio-server', path: 'studio-dist/server/index.js', match: 'exact' },\n { id: 'studio-manifest', path: 'studio-dist/server/manifest.js', match: 'exact' },\n {\n id: 'studio-client-start',\n path: 'studio-dist/client/_app/immutable/entry/start.*.js',\n match: 'glob',\n },\n {\n id: 'studio-client-app',\n path: 'studio-dist/client/_app/immutable/entry/app.*.js',\n match: 'glob',\n },\n]);\n\nconst SHA256 = /^[a-f0-9]{64}$/;\nconst GLOB = /[*?{}[\\]]|[+@!]\\(/;\n\nfunction pathProblem(path: string): string | null {\n if (!path || path.trim() !== path) return 'Path is empty or has surrounding whitespace.';\n if (path.includes('\\\\') || /[\\x00-\\x1f\\x7f]/.test(path))\n return 'Path is not a portable POSIX package path.';\n if (posix.isAbsolute(path) || /^[A-Za-z]:/.test(path))\n return 'Path must be relative to the package.';\n if (path.split('/').some((part) => !part || part === '.' || part === '..')) {\n return 'Path must not contain empty, current-directory, or parent-directory segments.';\n }\n return null;\n}\n\n/**\n * Classify a manifest files entry without evaluating exclusions as disk paths.\n *\n * @param entry - Original npm manifest entry.\n * @returns Classification only; actual selected content must come from the packer.\n * @example\n * ```ts\n * classifyPackageFilesEntry('!dist/index.js.map').kind; // 'exclusion'\n * ```\n */\nexport function classifyPackageFilesEntry(entry: string): PackageFilesEntry {\n const exclusion = entry.startsWith('!');\n const pattern = (exclusion ? entry.slice(1) : entry).replace(/^\\.\\//, '').replace(/\\/$/, '');\n const reason = pattern.startsWith('!')\n ? 'Repeated exclusion markers are not assessed.'\n : pathProblem(pattern);\n return {\n entry,\n pattern,\n kind: reason ? 'invalid' : exclusion ? 'exclusion' : GLOB.test(pattern) ? 'glob' : 'literal',\n reason,\n };\n}\n\nfunction fileProblems(file: PackageArtifactFile): string[] {\n const problems: string[] = [];\n const pathError = pathProblem(file.path);\n if (pathError) problems.push(pathError);\n if (!Number.isSafeInteger(file.size) || file.size < 0)\n problems.push('File size must be a nonnegative safe integer.');\n if (file.sha256 !== undefined && !SHA256.test(file.sha256))\n problems.push('File SHA-256 must be 64 lowercase hexadecimal characters.');\n return problems;\n}\n\n/**\n * Validate nonempty semantic resources, inventory identity, expected hashes and upper budgets.\n *\n * @param inventory - Packer-produced evidence or an explicitly identified fixture.\n * @param policy - Independently specified resources, expected files and cost ceilings.\n * @returns A copied evidence receipt; valid means only the supplied checks passed.\n * @example\n * ```ts\n * const result = validatePackageArtifact(inventory, {\n * requirements: CLEO_ARTIFACT_REQUIREMENTS,\n * budgets: CLEO_ARTIFACT_BUDGETS,\n * });\n * // result.runtime remains 'not-assessed', even when result.valid is true.\n * ```\n */\nexport function validatePackageArtifact(\n inventory: PackageArtifactInventory,\n policy: PackageArtifactPolicy,\n): PackageArtifactValidation {\n const issues: PackageArtifactIssue[] = [];\n const add = (code: PackageArtifactIssue['code'], subject: string, message: string): void => {\n issues.push({ code, subject, message });\n };\n if (!inventory.packageName.trim() || !inventory.version.trim()) {\n add('invalid-inventory', 'identity', 'Package name and version must be recorded.');\n }\n if (!['npm-pack', 'npm-pack-dry-run', 'fixture'].includes(inventory.source)) {\n add('invalid-inventory', 'source', 'Inventory provenance is not recognized.');\n }\n if (!Number.isSafeInteger(inventory.packedBytes) || inventory.packedBytes < 0) {\n add('invalid-inventory', 'packedBytes', 'Packed bytes must be a nonnegative safe integer.');\n }\n if (inventory.tarballSha256 !== undefined && !SHA256.test(inventory.tarballSha256)) {\n add(\n 'invalid-inventory',\n 'tarballSha256',\n 'Tarball SHA-256 must be 64 lowercase hexadecimal characters.',\n );\n }\n if (inventory.source === 'npm-pack-dry-run' && inventory.tarballSha256 !== undefined) {\n add(\n 'invalid-inventory',\n 'tarballSha256',\n 'A dry run cannot establish a retained tarball hash.',\n );\n }\n const files = new Map<string, PackageArtifactFile>();\n let unpackedBytes: number | null = 0;\n for (const file of inventory.files) {\n for (const problem of fileProblems(file)) add('invalid-inventory', file.path, problem);\n if (files.has(file.path)) add('invalid-inventory', file.path, 'Duplicate inventory path.');\n files.set(file.path, file);\n if (unpackedBytes !== null) {\n const total: number = unpackedBytes + file.size;\n unpackedBytes = Number.isSafeInteger(total) && file.size >= 0 ? total : null;\n }\n }\n if (unpackedBytes === null)\n add('invalid-inventory', 'unpackedBytes', 'File bytes cannot be safely totaled.');\n const entries = (policy.filesEntries ?? []).map(classifyPackageFilesEntry);\n for (const entry of entries) {\n if (entry.reason) add('invalid-policy', entry.entry, entry.reason);\n }\n if (!policy.requirements.length)\n add('invalid-policy', 'requirements', 'At least one semantic content requirement is required.');\n const ids = new Set<string>();\n const requirements = policy.requirements.map((requirement) => {\n const invalid = pathProblem(requirement.path);\n const duplicate = ids.has(requirement.id);\n ids.add(requirement.id);\n if (\n !requirement.id.trim() ||\n duplicate ||\n invalid ||\n !['exact', 'glob'].includes(requirement.match)\n ) {\n add(\n 'invalid-policy',\n requirement.id,\n invalid ?? 'Requirement identity or match mode is invalid or duplicated.',\n );\n return { id: requirement.id, matchedPaths: [], satisfied: false };\n }\n const matches = inventory.files.filter((file) =>\n requirement.match === 'exact'\n ? file.path === requirement.path\n : posix.matchesGlob(file.path, requirement.path),\n );\n if (!matches.length)\n add(\n 'missing',\n requirement.id,\n `Required resource ${requirement.path} is absent from the selected inventory.`,\n );\n for (const file of matches) {\n if (file.size === 0) add('empty', file.path, `Required resource ${requirement.id} is empty.`);\n }\n return {\n id: requirement.id,\n matchedPaths: matches.map((file) => file.path),\n satisfied: matches.length > 0 && matches.every((file) => file.size > 0),\n };\n });\n for (const pattern of policy.forbiddenPatterns ?? []) {\n const invalid = pathProblem(pattern);\n if (invalid) {\n add('invalid-policy', pattern, invalid);\n continue;\n }\n for (const file of inventory.files) {\n if (posix.matchesGlob(file.path, pattern))\n add('forbidden', file.path, `Selected file matches forbidden pattern ${pattern}.`);\n }\n }\n let hashComparison: PackageArtifactValidation['hashComparison'] = 'not-requested';\n for (const expected of policy.expectedFiles ?? []) {\n const problems = fileProblems(expected);\n for (const problem of problems) add('invalid-policy', expected.path, problem);\n const actual = files.get(expected.path);\n if (!actual) add('missing', expected.path, 'An independently expected file is missing.');\n else if (actual.size !== expected.size)\n add('mismatch', expected.path, 'File bytes differ from independently expected inventory.');\n if (expected.sha256 !== undefined) {\n if (hashComparison !== 'failed') hashComparison = 'matched';\n if (problems.length || actual?.sha256 !== expected.sha256) {\n hashComparison = 'failed';\n add(\n 'mismatch',\n expected.path,\n 'Actual hash is missing or differs from the independently expected SHA-256.',\n );\n }\n }\n }\n for (const [field, limit] of Object.entries(policy.budgets)) {\n if (!Number.isSafeInteger(limit) || limit < 0)\n add('invalid-policy', field, 'Budget must be a nonnegative safe integer.');\n }\n if (inventory.packedBytes > policy.budgets.packedBytes)\n add('budget', 'packedBytes', 'Packed bytes exceed the configured upper budget.');\n if (unpackedBytes !== null && unpackedBytes > policy.budgets.unpackedBytes)\n add('budget', 'unpackedBytes', 'Unpacked bytes exceed the configured upper budget.');\n if (inventory.files.length > policy.budgets.fileCount)\n add('budget', 'fileCount', 'Selected file count exceeds the configured upper budget.');\n return {\n valid: issues.length === 0,\n inventory: { ...inventory, files: inventory.files.map((file) => ({ ...file })) },\n unpackedBytes,\n issues,\n filesEntries: entries,\n requirements,\n hashComparison,\n runtime: 'not-assessed',\n limitations: [\n 'Manifest entries are classified only; the supplied packer inventory is the content authority.',\n 'Hashes are recorded and compared to supplied expected evidence; this validator does not read or authenticate tarball bytes.',\n 'Installability, module/dependency resolution, local-reference closure and native/dynamic runtime behavior are not assessed.',\n ],\n };\n}\n\n/**\n * Reject declaration and stray JavaScript output absent from the published CLI\n * bundle: only `build.mjs`'s declared entries (the CLI bundle and the hook\n * runtime) may ship as `.js` under `dist/`.\n *\n * @param files - Actual selected package files, not a development directory listing.\n * @returns Concrete build-shape failures; this does not load the bundle.\n * @example\n * ```ts\n * assertCleoShippedBuildShape([{ path: 'dist/cli/index.js', size: 1 }]); // []\n * ```\n */\nexport function assertCleoShippedBuildShape(files: readonly PackageArtifactFile[]): string[] {\n const reasons: string[] = [];\n const dist = files.filter((file) => file.path.startsWith('dist/'));\n const declarations = dist.filter(\n (file) => file.path.endsWith('.d.ts') || file.path.endsWith('.d.ts.map'),\n );\n if (declarations.length)\n reasons.push(\n `${declarations.length} declaration file(s) under dist/ — the esbuild bundle emits none`,\n );\n const stray = dist.filter(\n (file) => file.path.endsWith('.js') && !CLEO_SHIPPED_JS_ENTRIES.has(file.path),\n );\n if (stray.length)\n reasons.push(\n `${stray.length} .js file(s) under dist/ outside the declared entries ${[...CLEO_SHIPPED_JS_ENTRIES].join(', ')}, e.g. ${stray[0]?.path}`,\n );\n return reasons;\n}\n","/**\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 { resolveSkillsRoot } from '@cleocode/core/skills/skill-root.js';\nimport type { LockEntry, Provider } from '../../types.js';\nimport { readLockFile } from '../lock-utils.js';\nimport { 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(resolveSkillsRoot(), 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,SAAS,aAAa;AAaf,IAAM,wBAA0D,OAAO,OAAO;AAAA,EACnF,aAAa,KAAK,OAAO;AAAA,EACzB,eAAe,KAAK,OAAO;AAAA,EAC3B,WAAW;AACb,CAAC;AAQD,IAAM,0BAA+C,oBAAI,IAAI;AAAA,EAC3D;AAAA,EACA;AACF,CAAC;AAGM,IAAM,6BAAoE,OAAO,OAAO;AAAA,EAC7F,EAAE,IAAI,aAAa,MAAM,qBAAqB,OAAO,QAAQ;AAAA,EAC7D,EAAE,IAAI,kBAAkB,MAAM,0BAA0B,OAAO,QAAQ;AAAA,EACvE,EAAE,IAAI,uBAAuB,MAAM,wBAAwB,OAAO,QAAQ;AAAA,EAC1E,EAAE,IAAI,kBAAkB,MAAM,0BAA0B,OAAO,QAAQ;AAAA,EACvE,EAAE,IAAI,iBAAiB,MAAM,+BAA+B,OAAO,QAAQ;AAAA,EAC3E,EAAE,IAAI,mBAAmB,MAAM,kCAAkC,OAAO,QAAQ;AAAA,EAChF;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AACF,CAAC;AAED,IAAM,SAAS;AACf,IAAM,OAAO;AAEb,SAAS,YAAY,MAA6B;AAChD,MAAI,CAAC,QAAQ,KAAK,KAAK,MAAM,KAAM,QAAO;AAC1C,MAAI,KAAK,SAAS,IAAI,KAAK,kBAAkB,KAAK,IAAI;AACpD,WAAO;AACT,MAAI,MAAM,WAAW,IAAI,KAAK,aAAa,KAAK,IAAI;AAClD,WAAO;AACT,MAAI,KAAK,MAAM,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,SAAS,OAAO,SAAS,IAAI,GAAG;AAC1E,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAYO,SAAS,0BAA0B,OAAkC;AAC1E,QAAM,YAAY,MAAM,WAAW,GAAG;AACtC,QAAM,WAAW,YAAY,MAAM,MAAM,CAAC,IAAI,OAAO,QAAQ,SAAS,EAAE,EAAE,QAAQ,OAAO,EAAE;AAC3F,QAAM,SAAS,QAAQ,WAAW,GAAG,IACjC,iDACA,YAAY,OAAO;AACvB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM,SAAS,YAAY,YAAY,cAAc,KAAK,KAAK,OAAO,IAAI,SAAS;AAAA,IACnF;AAAA,EACF;AACF;AAEA,SAAS,aAAa,MAAqC;AACzD,QAAM,WAAqB,CAAC;AAC5B,QAAM,YAAY,YAAY,KAAK,IAAI;AACvC,MAAI,UAAW,UAAS,KAAK,SAAS;AACtC,MAAI,CAAC,OAAO,cAAc,KAAK,IAAI,KAAK,KAAK,OAAO;AAClD,aAAS,KAAK,+CAA+C;AAC/D,MAAI,KAAK,WAAW,UAAa,CAAC,OAAO,KAAK,KAAK,MAAM;AACvD,aAAS,KAAK,2DAA2D;AAC3E,SAAO;AACT;AAiBO,SAAS,wBACd,WACA,QAC2B;AAC3B,QAAM,SAAiC,CAAC;AACxC,QAAM,MAAM,CAAC,MAAoC,SAAiB,YAA0B;AAC1F,WAAO,KAAK,EAAE,MAAM,SAAS,QAAQ,CAAC;AAAA,EACxC;AACA,MAAI,CAAC,UAAU,YAAY,KAAK,KAAK,CAAC,UAAU,QAAQ,KAAK,GAAG;AAC9D,QAAI,qBAAqB,YAAY,4CAA4C;AAAA,EACnF;AACA,MAAI,CAAC,CAAC,YAAY,oBAAoB,SAAS,EAAE,SAAS,UAAU,MAAM,GAAG;AAC3E,QAAI,qBAAqB,UAAU,yCAAyC;AAAA,EAC9E;AACA,MAAI,CAAC,OAAO,cAAc,UAAU,WAAW,KAAK,UAAU,cAAc,GAAG;AAC7E,QAAI,qBAAqB,eAAe,kDAAkD;AAAA,EAC5F;AACA,MAAI,UAAU,kBAAkB,UAAa,CAAC,OAAO,KAAK,UAAU,aAAa,GAAG;AAClF;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU,WAAW,sBAAsB,UAAU,kBAAkB,QAAW;AACpF;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,QAAM,QAAQ,oBAAI,IAAiC;AACnD,MAAI,gBAA+B;AACnC,aAAW,QAAQ,UAAU,OAAO;AAClC,eAAW,WAAW,aAAa,IAAI,EAAG,KAAI,qBAAqB,KAAK,MAAM,OAAO;AACrF,QAAI,MAAM,IAAI,KAAK,IAAI,EAAG,KAAI,qBAAqB,KAAK,MAAM,2BAA2B;AACzF,UAAM,IAAI,KAAK,MAAM,IAAI;AACzB,QAAI,kBAAkB,MAAM;AAC1B,YAAM,QAAgB,gBAAgB,KAAK;AAC3C,sBAAgB,OAAO,cAAc,KAAK,KAAK,KAAK,QAAQ,IAAI,QAAQ;AAAA,IAC1E;AAAA,EACF;AACA,MAAI,kBAAkB;AACpB,QAAI,qBAAqB,iBAAiB,sCAAsC;AAClF,QAAM,WAAW,OAAO,gBAAgB,CAAC,GAAG,IAAI,yBAAyB;AACzE,aAAW,SAAS,SAAS;AAC3B,QAAI,MAAM,OAAQ,KAAI,kBAAkB,MAAM,OAAO,MAAM,MAAM;AAAA,EACnE;AACA,MAAI,CAAC,OAAO,aAAa;AACvB,QAAI,kBAAkB,gBAAgB,wDAAwD;AAChG,QAAM,MAAM,oBAAI,IAAY;AAC5B,QAAM,eAAe,OAAO,aAAa,IAAI,CAAC,gBAAgB;AAC5D,UAAM,UAAU,YAAY,YAAY,IAAI;AAC5C,UAAM,YAAY,IAAI,IAAI,YAAY,EAAE;AACxC,QAAI,IAAI,YAAY,EAAE;AACtB,QACE,CAAC,YAAY,GAAG,KAAK,KACrB,aACA,WACA,CAAC,CAAC,SAAS,MAAM,EAAE,SAAS,YAAY,KAAK,GAC7C;AACA;AAAA,QACE;AAAA,QACA,YAAY;AAAA,QACZ,WAAW;AAAA,MACb;AACA,aAAO,EAAE,IAAI,YAAY,IAAI,cAAc,CAAC,GAAG,WAAW,MAAM;AAAA,IAClE;AACA,UAAM,UAAU,UAAU,MAAM;AAAA,MAAO,CAAC,SACtC,YAAY,UAAU,UAClB,KAAK,SAAS,YAAY,OAC1B,MAAM,YAAY,KAAK,MAAM,YAAY,IAAI;AAAA,IACnD;AACA,QAAI,CAAC,QAAQ;AACX;AAAA,QACE;AAAA,QACA,YAAY;AAAA,QACZ,qBAAqB,YAAY,IAAI;AAAA,MACvC;AACF,eAAW,QAAQ,SAAS;AAC1B,UAAI,KAAK,SAAS,EAAG,KAAI,SAAS,KAAK,MAAM,qBAAqB,YAAY,EAAE,YAAY;AAAA,IAC9F;AACA,WAAO;AAAA,MACL,IAAI,YAAY;AAAA,MAChB,cAAc,QAAQ,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,MAC7C,WAAW,QAAQ,SAAS,KAAK,QAAQ,MAAM,CAAC,SAAS,KAAK,OAAO,CAAC;AAAA,IACxE;AAAA,EACF,CAAC;AACD,aAAW,WAAW,OAAO,qBAAqB,CAAC,GAAG;AACpD,UAAM,UAAU,YAAY,OAAO;AACnC,QAAI,SAAS;AACX,UAAI,kBAAkB,SAAS,OAAO;AACtC;AAAA,IACF;AACA,eAAW,QAAQ,UAAU,OAAO;AAClC,UAAI,MAAM,YAAY,KAAK,MAAM,OAAO;AACtC,YAAI,aAAa,KAAK,MAAM,2CAA2C,OAAO,GAAG;AAAA,IACrF;AAAA,EACF;AACA,MAAI,iBAA8D;AAClE,aAAW,YAAY,OAAO,iBAAiB,CAAC,GAAG;AACjD,UAAM,WAAW,aAAa,QAAQ;AACtC,eAAW,WAAW,SAAU,KAAI,kBAAkB,SAAS,MAAM,OAAO;AAC5E,UAAM,SAAS,MAAM,IAAI,SAAS,IAAI;AACtC,QAAI,CAAC,OAAQ,KAAI,WAAW,SAAS,MAAM,4CAA4C;AAAA,aAC9E,OAAO,SAAS,SAAS;AAChC,UAAI,YAAY,SAAS,MAAM,0DAA0D;AAC3F,QAAI,SAAS,WAAW,QAAW;AACjC,UAAI,mBAAmB,SAAU,kBAAiB;AAClD,UAAI,SAAS,UAAU,QAAQ,WAAW,SAAS,QAAQ;AACzD,yBAAiB;AACjB;AAAA,UACE;AAAA,UACA,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,aAAW,CAAC,OAAO,KAAK,KAAK,OAAO,QAAQ,OAAO,OAAO,GAAG;AAC3D,QAAI,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ;AAC1C,UAAI,kBAAkB,OAAO,4CAA4C;AAAA,EAC7E;AACA,MAAI,UAAU,cAAc,OAAO,QAAQ;AACzC,QAAI,UAAU,eAAe,kDAAkD;AACjF,MAAI,kBAAkB,QAAQ,gBAAgB,OAAO,QAAQ;AAC3D,QAAI,UAAU,iBAAiB,oDAAoD;AACrF,MAAI,UAAU,MAAM,SAAS,OAAO,QAAQ;AAC1C,QAAI,UAAU,aAAa,0DAA0D;AACvF,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB,WAAW,EAAE,GAAG,WAAW,OAAO,UAAU,MAAM,IAAI,CAAC,UAAU,EAAE,GAAG,KAAK,EAAE,EAAE;AAAA,IAC/E;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,aAAa;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAcO,SAAS,4BAA4B,OAAiD;AAC3F,QAAM,UAAoB,CAAC;AAC3B,QAAM,OAAO,MAAM,OAAO,CAAC,SAAS,KAAK,KAAK,WAAW,OAAO,CAAC;AACjE,QAAM,eAAe,KAAK;AAAA,IACxB,CAAC,SAAS,KAAK,KAAK,SAAS,OAAO,KAAK,KAAK,KAAK,SAAS,WAAW;AAAA,EACzE;AACA,MAAI,aAAa;AACf,YAAQ;AAAA,MACN,GAAG,aAAa,MAAM;AAAA,IACxB;AACF,QAAM,QAAQ,KAAK;AAAA,IACjB,CAAC,SAAS,KAAK,KAAK,SAAS,KAAK,KAAK,CAAC,wBAAwB,IAAI,KAAK,IAAI;AAAA,EAC/E;AACA,MAAI,MAAM;AACR,YAAQ;AAAA,MACN,GAAG,MAAM,MAAM,yDAAyD,CAAC,GAAG,uBAAuB,EAAE,KAAK,IAAI,CAAC,UAAU,MAAM,CAAC,GAAG,IAAI;AAAA,IACzI;AACF,SAAO;AACT;;;ACnSA,SAAS,YAAY,WAAW,oBAAoB;AACpD,SAAS,MAAM,eAAe;AAC9B,SAAS,yBAAyB;AAMlC,IAAM,qBAAqB;AA6DpB,SAAS,kBAAkB,WAA4B;AAC5D,SAAO,UAAU,WAAW,kBAAkB;AAChD;AA0BA,eAAsB,oBACpB,WACA,WACA,QAA8B,UAC9B,YAC+B;AAC/B,QAAM,OAAO,MAAM,aAAa;AAChC,QAAM,QAAQ,KAAK,OAAO,SAAS;AACnC,QAAM,eAAe,kBAAkB,SAAS;AAGhD,MAAI,CAAC,OAAO;AACV,UAAMA,iBAAgB,KAAK,kBAAkB,GAAG,SAAS;AACzD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,iBAAiB,WAAWA,cAAa;AAAA,MACzC,eAAe;AAAA,MACf,cAAc,CAAC;AAAA,MACf;AAAA,MACA,OAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,gBAAgB,MAAM;AAC5B,QAAM,kBAAkB,WAAW,aAAa;AAGhD,QAAM,eAAqD,CAAC;AAE5D,aAAW,YAAY,WAAW;AAChC,UAAM,aAAa,0BAA0B,UAAU,OAAO,UAAU;AACxE,eAAW,aAAa,YAAY;AAClC,UAAI,CAAC,UAAW;AAEhB,YAAM,WAAW,KAAK,WAAW,SAAS;AAC1C,YAAM,SAAS,WAAW,QAAQ;AAClC,UAAI,YAAY;AAChB,UAAI,oBAAoB;AAExB,UAAI,QAAQ;AACV,YAAI;AACF,gBAAM,OAAO,UAAU,QAAQ;AAC/B,sBAAY,KAAK,eAAe;AAChC,cAAI,WAAW;AACb,kBAAM,SAAS,QAAQ,aAAa,QAAQ,CAAC;AAC7C,gCAAoB,WAAW,QAAQ,aAAa;AAAA,UACtD;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAEA,mBAAa,KAAK;AAAA,QAChB,YAAY,SAAS;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,CAAC,iBAAiB;AACpB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,gCAAgC,aAAa;AAAA,IACtD;AAAA,EACF;AAEA,QAAM,cAAc,aAAa,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM;AACxD,QAAM,gBAAgB,aAAa,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB;AAEjF,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,GAAG,cAAc,MAAM;AAAA,IAChC;AAAA,EACF;AAEA,MAAI,YAAY,SAAS,GAAG;AAC1B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,GAAG,YAAY,MAAM;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAwBA,eAAsB,uBACpB,WACA,QAA8B,UAC9B,YAC4C;AAC5C,QAAM,OAAO,MAAM,aAAa;AAChC,QAAM,UAAU,oBAAI,IAAkC;AAEtD,aAAW,aAAa,OAAO,KAAK,KAAK,MAAM,GAAG;AAChD,UAAM,SAAS,MAAM,oBAAoB,WAAW,WAAW,OAAO,UAAU;AAChF,YAAQ,IAAI,WAAW,MAAM;AAAA,EAC/B;AAEA,SAAO;AACT;AAyBO,SAAS,oBACd,WACA,gBACA,eACS;AAET,MAAI,CAAC,cAAe,QAAO;AAG3B,MAAI,kBAAkB,SAAS,GAAG;AAEhC,QAAI,cAAc,eAAe,UAAW,QAAO;AAEnD,WAAO;AAAA,EACT;AAGA,SAAO;AACT;AAyBA,eAAsB,6BACpB,WACA,YACA,OACA,iBACqE;AACrE,QAAM,EAAE,oBAAAC,oBAAmB,IAAI,MAAM,OAAO,wBAA6B;AACzE,QAAM,UAAU,MAAMA,oBAAmB,WAAW,YAAY,OAAO,eAAe;AACtF,QAAM,SAAqE,CAAC;AAE5E,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,WAAW,WAAW;AAC/B,aAAO,KAAK;AAAA,QACV,MAAM,OAAO;AAAA,QACb,YAAY,OAAO;AAAA,QACnB,OAAO;AAAA,MACT,CAAC;AAAA,IACH,WAAW,OAAO,WAAW,QAAQ;AACnC,aAAO,KAAK;AAAA,QACV,MAAM,OAAO;AAAA,QACb,YAAY,OAAO;AAAA,QACnB,OAAO;AAAA,MACT,CAAC;AAAA,IACH,WAAW,OAAO,WAAW,YAAY;AACvC,aAAO,KAAK;AAAA,QACV,MAAM,OAAO;AAAA,QACb,YAAY,OAAO;AAAA,QACnB,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;","names":["canonicalPath","checkAllInjections"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/artifacts/validation.ts","../src/core/skills/integrity.ts"],"sourcesContent":["/**\n * Pure semantic validation of npm-produced package inventories.\n *\n * Code placed in `packages/caamp/` per Package-Boundary Check — verified\n * against AGENTS.md. No filesystem, process, model, or runtime-store access.\n */\n\nimport { posix } from 'node:path';\nimport type {\n PackageArtifactBudgets,\n PackageArtifactFile,\n PackageArtifactInventory,\n PackageArtifactIssue,\n PackageArtifactPolicy,\n PackageArtifactRequirement,\n PackageArtifactValidation,\n PackageFilesEntry,\n} from '@cleocode/contracts/package-artifact';\n\n/** Existing CLI upper budgets: 20 MiB packed, 36 MiB unpacked, and 800 files. */\nexport const CLEO_ARTIFACT_BUDGETS: Readonly<PackageArtifactBudgets> = Object.freeze({\n packedBytes: 20 * 1024 * 1024,\n unpackedBytes: 36 * 1024 * 1024,\n fileCount: 800,\n});\n\n/**\n * The JavaScript files `build.mjs` declares for the published CLI: the CLI\n * bundle, the provider hook runtime that `bin/cleo.js` imports directly for\n * `cleo hook heavy-command` (T12983), skipping the CLI bootstrap, and the\n * detached dist-tags check the CLI spawns for its update notice (T13137). Any\n * other `.js` under `dist/` is development output.\n */\nconst CLEO_SHIPPED_JS_ENTRIES: ReadonlySet<string> = new Set([\n 'dist/cli/index.js',\n 'dist/cli/hook-entry.js',\n 'dist/cli/update-check-entry.js',\n]);\n\n/**\n * A code-split chunk of the CLI bundle (T13126): `dist/cli/<name>-<HASH>.js`,\n * where `<HASH>` is esbuild's 8-character content hash.\n *\n * `build.mjs` bundles the CLI with `splitting` so each `import()` loads its own\n * chunk instead of the whole CLI and all of CORE at startup. Its\n * `CLEO_CHUNK_NAMES` (`cli/[name]-[hash]`) writes every chunk directly beside\n * `cli/index.js`; change both together. A chunk in any other directory is not\n * build output and stays rejected. `<name>` is the source file's basename in\n * any case (T13159): a source file named `TaskCard.ts` must not fail the\n * artifact check.\n */\nexport const CLEO_CLI_CHUNK_PATTERN: RegExp = /^dist\\/cli\\/[A-Za-z0-9_.-]+-[A-Z0-9]{8}\\.js$/;\n\n/** Required CLI and adapter-node resources, independent of historical byte/file-count floors. */\nexport const CLEO_ARTIFACT_REQUIREMENTS: readonly PackageArtifactRequirement[] = Object.freeze([\n { id: 'cli-entry', path: 'dist/cli/index.js', match: 'exact' },\n { id: 'cli-hook-entry', path: 'dist/cli/hook-entry.js', match: 'exact' },\n { id: 'cli-update-check-entry', path: 'dist/cli/update-check-entry.js', match: 'exact' },\n { id: 'studio-server-entry', path: 'studio-dist/index.js', match: 'exact' },\n { id: 'studio-handler', path: 'studio-dist/handler.js', match: 'exact' },\n { id: 'studio-server', path: 'studio-dist/server/index.js', match: 'exact' },\n { id: 'studio-manifest', path: 'studio-dist/server/manifest.js', match: 'exact' },\n {\n id: 'studio-client-start',\n path: 'studio-dist/client/_app/immutable/entry/start.*.js',\n match: 'glob',\n },\n {\n id: 'studio-client-app',\n path: 'studio-dist/client/_app/immutable/entry/app.*.js',\n match: 'glob',\n },\n]);\n\nconst SHA256 = /^[a-f0-9]{64}$/;\nconst GLOB = /[*?{}[\\]]|[+@!]\\(/;\n\nfunction pathProblem(path: string): string | null {\n if (!path || path.trim() !== path) return 'Path is empty or has surrounding whitespace.';\n if (path.includes('\\\\') || /[\\x00-\\x1f\\x7f]/.test(path))\n return 'Path is not a portable POSIX package path.';\n if (posix.isAbsolute(path) || /^[A-Za-z]:/.test(path))\n return 'Path must be relative to the package.';\n if (path.split('/').some((part) => !part || part === '.' || part === '..')) {\n return 'Path must not contain empty, current-directory, or parent-directory segments.';\n }\n return null;\n}\n\n/**\n * Classify a manifest files entry without evaluating exclusions as disk paths.\n *\n * @param entry - Original npm manifest entry.\n * @returns Classification only; actual selected content must come from the packer.\n * @example\n * ```ts\n * classifyPackageFilesEntry('!dist/index.js.map').kind; // 'exclusion'\n * ```\n */\nexport function classifyPackageFilesEntry(entry: string): PackageFilesEntry {\n const exclusion = entry.startsWith('!');\n const pattern = (exclusion ? entry.slice(1) : entry).replace(/^\\.\\//, '').replace(/\\/$/, '');\n const reason = pattern.startsWith('!')\n ? 'Repeated exclusion markers are not assessed.'\n : pathProblem(pattern);\n return {\n entry,\n pattern,\n kind: reason ? 'invalid' : exclusion ? 'exclusion' : GLOB.test(pattern) ? 'glob' : 'literal',\n reason,\n };\n}\n\nfunction fileProblems(file: PackageArtifactFile): string[] {\n const problems: string[] = [];\n const pathError = pathProblem(file.path);\n if (pathError) problems.push(pathError);\n if (!Number.isSafeInteger(file.size) || file.size < 0)\n problems.push('File size must be a nonnegative safe integer.');\n if (file.sha256 !== undefined && !SHA256.test(file.sha256))\n problems.push('File SHA-256 must be 64 lowercase hexadecimal characters.');\n return problems;\n}\n\n/**\n * Validate nonempty semantic resources, inventory identity, expected hashes and upper budgets.\n *\n * @param inventory - Packer-produced evidence or an explicitly identified fixture.\n * @param policy - Independently specified resources, expected files and cost ceilings.\n * @returns A copied evidence receipt; valid means only the supplied checks passed.\n * @example\n * ```ts\n * const result = validatePackageArtifact(inventory, {\n * requirements: CLEO_ARTIFACT_REQUIREMENTS,\n * budgets: CLEO_ARTIFACT_BUDGETS,\n * });\n * // result.runtime remains 'not-assessed', even when result.valid is true.\n * ```\n */\nexport function validatePackageArtifact(\n inventory: PackageArtifactInventory,\n policy: PackageArtifactPolicy,\n): PackageArtifactValidation {\n const issues: PackageArtifactIssue[] = [];\n const add = (code: PackageArtifactIssue['code'], subject: string, message: string): void => {\n issues.push({ code, subject, message });\n };\n if (!inventory.packageName.trim() || !inventory.version.trim()) {\n add('invalid-inventory', 'identity', 'Package name and version must be recorded.');\n }\n if (!['npm-pack', 'npm-pack-dry-run', 'fixture'].includes(inventory.source)) {\n add('invalid-inventory', 'source', 'Inventory provenance is not recognized.');\n }\n if (!Number.isSafeInteger(inventory.packedBytes) || inventory.packedBytes < 0) {\n add('invalid-inventory', 'packedBytes', 'Packed bytes must be a nonnegative safe integer.');\n }\n if (inventory.tarballSha256 !== undefined && !SHA256.test(inventory.tarballSha256)) {\n add(\n 'invalid-inventory',\n 'tarballSha256',\n 'Tarball SHA-256 must be 64 lowercase hexadecimal characters.',\n );\n }\n if (inventory.source === 'npm-pack-dry-run' && inventory.tarballSha256 !== undefined) {\n add(\n 'invalid-inventory',\n 'tarballSha256',\n 'A dry run cannot establish a retained tarball hash.',\n );\n }\n const files = new Map<string, PackageArtifactFile>();\n let unpackedBytes: number | null = 0;\n for (const file of inventory.files) {\n for (const problem of fileProblems(file)) add('invalid-inventory', file.path, problem);\n if (files.has(file.path)) add('invalid-inventory', file.path, 'Duplicate inventory path.');\n files.set(file.path, file);\n if (unpackedBytes !== null) {\n const total: number = unpackedBytes + file.size;\n unpackedBytes = Number.isSafeInteger(total) && file.size >= 0 ? total : null;\n }\n }\n if (unpackedBytes === null)\n add('invalid-inventory', 'unpackedBytes', 'File bytes cannot be safely totaled.');\n const entries = (policy.filesEntries ?? []).map(classifyPackageFilesEntry);\n for (const entry of entries) {\n if (entry.reason) add('invalid-policy', entry.entry, entry.reason);\n }\n if (!policy.requirements.length)\n add('invalid-policy', 'requirements', 'At least one semantic content requirement is required.');\n const ids = new Set<string>();\n const requirements = policy.requirements.map((requirement) => {\n const invalid = pathProblem(requirement.path);\n const duplicate = ids.has(requirement.id);\n ids.add(requirement.id);\n if (\n !requirement.id.trim() ||\n duplicate ||\n invalid ||\n !['exact', 'glob'].includes(requirement.match)\n ) {\n add(\n 'invalid-policy',\n requirement.id,\n invalid ?? 'Requirement identity or match mode is invalid or duplicated.',\n );\n return { id: requirement.id, matchedPaths: [], satisfied: false };\n }\n const matches = inventory.files.filter((file) =>\n requirement.match === 'exact'\n ? file.path === requirement.path\n : posix.matchesGlob(file.path, requirement.path),\n );\n if (!matches.length)\n add(\n 'missing',\n requirement.id,\n `Required resource ${requirement.path} is absent from the selected inventory.`,\n );\n for (const file of matches) {\n if (file.size === 0) add('empty', file.path, `Required resource ${requirement.id} is empty.`);\n }\n return {\n id: requirement.id,\n matchedPaths: matches.map((file) => file.path),\n satisfied: matches.length > 0 && matches.every((file) => file.size > 0),\n };\n });\n for (const pattern of policy.forbiddenPatterns ?? []) {\n const invalid = pathProblem(pattern);\n if (invalid) {\n add('invalid-policy', pattern, invalid);\n continue;\n }\n for (const file of inventory.files) {\n if (posix.matchesGlob(file.path, pattern))\n add('forbidden', file.path, `Selected file matches forbidden pattern ${pattern}.`);\n }\n }\n let hashComparison: PackageArtifactValidation['hashComparison'] = 'not-requested';\n for (const expected of policy.expectedFiles ?? []) {\n const problems = fileProblems(expected);\n for (const problem of problems) add('invalid-policy', expected.path, problem);\n const actual = files.get(expected.path);\n if (!actual) add('missing', expected.path, 'An independently expected file is missing.');\n else if (actual.size !== expected.size)\n add('mismatch', expected.path, 'File bytes differ from independently expected inventory.');\n if (expected.sha256 !== undefined) {\n if (hashComparison !== 'failed') hashComparison = 'matched';\n if (problems.length || actual?.sha256 !== expected.sha256) {\n hashComparison = 'failed';\n add(\n 'mismatch',\n expected.path,\n 'Actual hash is missing or differs from the independently expected SHA-256.',\n );\n }\n }\n }\n for (const [field, limit] of Object.entries(policy.budgets)) {\n if (!Number.isSafeInteger(limit) || limit < 0)\n add('invalid-policy', field, 'Budget must be a nonnegative safe integer.');\n }\n if (inventory.packedBytes > policy.budgets.packedBytes)\n add('budget', 'packedBytes', 'Packed bytes exceed the configured upper budget.');\n if (unpackedBytes !== null && unpackedBytes > policy.budgets.unpackedBytes)\n add('budget', 'unpackedBytes', 'Unpacked bytes exceed the configured upper budget.');\n if (inventory.files.length > policy.budgets.fileCount)\n add('budget', 'fileCount', 'Selected file count exceeds the configured upper budget.');\n return {\n valid: issues.length === 0,\n inventory: { ...inventory, files: inventory.files.map((file) => ({ ...file })) },\n unpackedBytes,\n issues,\n filesEntries: entries,\n requirements,\n hashComparison,\n runtime: 'not-assessed',\n limitations: [\n 'Manifest entries are classified only; the supplied packer inventory is the content authority.',\n 'Hashes are recorded and compared to supplied expected evidence; this validator does not read or authenticate tarball bytes.',\n 'Installability, module/dependency resolution, local-reference closure and native/dynamic runtime behavior are not assessed.',\n ],\n };\n}\n\n/**\n * Reject declaration and stray JavaScript output absent from the published CLI\n * bundle: only `build.mjs`'s declared entries (the CLI bundle and the hook\n * runtime) and their code-split chunks ({@link CLEO_CLI_CHUNK_PATTERN}) may ship\n * as `.js` under `dist/`.\n *\n * @param files - Actual selected package files, not a development directory listing.\n * @returns Concrete build-shape failures; this does not load the bundle.\n * @example\n * ```ts\n * assertCleoShippedBuildShape([{ path: 'dist/cli/index.js', size: 1 }]); // []\n * ```\n */\nexport function assertCleoShippedBuildShape(files: readonly PackageArtifactFile[]): string[] {\n const reasons: string[] = [];\n const dist = files.filter((file) => file.path.startsWith('dist/'));\n const declarations = dist.filter(\n (file) => file.path.endsWith('.d.ts') || file.path.endsWith('.d.ts.map'),\n );\n if (declarations.length)\n reasons.push(\n `${declarations.length} declaration file(s) under dist/ — the esbuild bundle emits none`,\n );\n const stray = dist.filter(\n (file) =>\n file.path.endsWith('.js') &&\n !CLEO_SHIPPED_JS_ENTRIES.has(file.path) &&\n !CLEO_CLI_CHUNK_PATTERN.test(file.path),\n );\n if (stray.length)\n reasons.push(\n `${stray.length} .js file(s) under dist/ outside the declared entries ${[...CLEO_SHIPPED_JS_ENTRIES].join(', ')} and their chunks, e.g. ${stray[0]?.path}`,\n );\n return reasons;\n}\n","/**\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 { resolveSkillsRoot } from '@cleocode/core/skills/skill-root.js';\nimport type { LockEntry, Provider } from '../../types.js';\nimport { readLockFile } from '../lock-utils.js';\nimport { 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(resolveSkillsRoot(), 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,SAAS,aAAa;AAaf,IAAM,wBAA0D,OAAO,OAAO;AAAA,EACnF,aAAa,KAAK,OAAO;AAAA,EACzB,eAAe,KAAK,OAAO;AAAA,EAC3B,WAAW;AACb,CAAC;AASD,IAAM,0BAA+C,oBAAI,IAAI;AAAA,EAC3D;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAcM,IAAM,yBAAiC;AAGvC,IAAM,6BAAoE,OAAO,OAAO;AAAA,EAC7F,EAAE,IAAI,aAAa,MAAM,qBAAqB,OAAO,QAAQ;AAAA,EAC7D,EAAE,IAAI,kBAAkB,MAAM,0BAA0B,OAAO,QAAQ;AAAA,EACvE,EAAE,IAAI,0BAA0B,MAAM,kCAAkC,OAAO,QAAQ;AAAA,EACvF,EAAE,IAAI,uBAAuB,MAAM,wBAAwB,OAAO,QAAQ;AAAA,EAC1E,EAAE,IAAI,kBAAkB,MAAM,0BAA0B,OAAO,QAAQ;AAAA,EACvE,EAAE,IAAI,iBAAiB,MAAM,+BAA+B,OAAO,QAAQ;AAAA,EAC3E,EAAE,IAAI,mBAAmB,MAAM,kCAAkC,OAAO,QAAQ;AAAA,EAChF;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AACF,CAAC;AAED,IAAM,SAAS;AACf,IAAM,OAAO;AAEb,SAAS,YAAY,MAA6B;AAChD,MAAI,CAAC,QAAQ,KAAK,KAAK,MAAM,KAAM,QAAO;AAC1C,MAAI,KAAK,SAAS,IAAI,KAAK,kBAAkB,KAAK,IAAI;AACpD,WAAO;AACT,MAAI,MAAM,WAAW,IAAI,KAAK,aAAa,KAAK,IAAI;AAClD,WAAO;AACT,MAAI,KAAK,MAAM,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,SAAS,OAAO,SAAS,IAAI,GAAG;AAC1E,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAYO,SAAS,0BAA0B,OAAkC;AAC1E,QAAM,YAAY,MAAM,WAAW,GAAG;AACtC,QAAM,WAAW,YAAY,MAAM,MAAM,CAAC,IAAI,OAAO,QAAQ,SAAS,EAAE,EAAE,QAAQ,OAAO,EAAE;AAC3F,QAAM,SAAS,QAAQ,WAAW,GAAG,IACjC,iDACA,YAAY,OAAO;AACvB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM,SAAS,YAAY,YAAY,cAAc,KAAK,KAAK,OAAO,IAAI,SAAS;AAAA,IACnF;AAAA,EACF;AACF;AAEA,SAAS,aAAa,MAAqC;AACzD,QAAM,WAAqB,CAAC;AAC5B,QAAM,YAAY,YAAY,KAAK,IAAI;AACvC,MAAI,UAAW,UAAS,KAAK,SAAS;AACtC,MAAI,CAAC,OAAO,cAAc,KAAK,IAAI,KAAK,KAAK,OAAO;AAClD,aAAS,KAAK,+CAA+C;AAC/D,MAAI,KAAK,WAAW,UAAa,CAAC,OAAO,KAAK,KAAK,MAAM;AACvD,aAAS,KAAK,2DAA2D;AAC3E,SAAO;AACT;AAiBO,SAAS,wBACd,WACA,QAC2B;AAC3B,QAAM,SAAiC,CAAC;AACxC,QAAM,MAAM,CAAC,MAAoC,SAAiB,YAA0B;AAC1F,WAAO,KAAK,EAAE,MAAM,SAAS,QAAQ,CAAC;AAAA,EACxC;AACA,MAAI,CAAC,UAAU,YAAY,KAAK,KAAK,CAAC,UAAU,QAAQ,KAAK,GAAG;AAC9D,QAAI,qBAAqB,YAAY,4CAA4C;AAAA,EACnF;AACA,MAAI,CAAC,CAAC,YAAY,oBAAoB,SAAS,EAAE,SAAS,UAAU,MAAM,GAAG;AAC3E,QAAI,qBAAqB,UAAU,yCAAyC;AAAA,EAC9E;AACA,MAAI,CAAC,OAAO,cAAc,UAAU,WAAW,KAAK,UAAU,cAAc,GAAG;AAC7E,QAAI,qBAAqB,eAAe,kDAAkD;AAAA,EAC5F;AACA,MAAI,UAAU,kBAAkB,UAAa,CAAC,OAAO,KAAK,UAAU,aAAa,GAAG;AAClF;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU,WAAW,sBAAsB,UAAU,kBAAkB,QAAW;AACpF;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,QAAM,QAAQ,oBAAI,IAAiC;AACnD,MAAI,gBAA+B;AACnC,aAAW,QAAQ,UAAU,OAAO;AAClC,eAAW,WAAW,aAAa,IAAI,EAAG,KAAI,qBAAqB,KAAK,MAAM,OAAO;AACrF,QAAI,MAAM,IAAI,KAAK,IAAI,EAAG,KAAI,qBAAqB,KAAK,MAAM,2BAA2B;AACzF,UAAM,IAAI,KAAK,MAAM,IAAI;AACzB,QAAI,kBAAkB,MAAM;AAC1B,YAAM,QAAgB,gBAAgB,KAAK;AAC3C,sBAAgB,OAAO,cAAc,KAAK,KAAK,KAAK,QAAQ,IAAI,QAAQ;AAAA,IAC1E;AAAA,EACF;AACA,MAAI,kBAAkB;AACpB,QAAI,qBAAqB,iBAAiB,sCAAsC;AAClF,QAAM,WAAW,OAAO,gBAAgB,CAAC,GAAG,IAAI,yBAAyB;AACzE,aAAW,SAAS,SAAS;AAC3B,QAAI,MAAM,OAAQ,KAAI,kBAAkB,MAAM,OAAO,MAAM,MAAM;AAAA,EACnE;AACA,MAAI,CAAC,OAAO,aAAa;AACvB,QAAI,kBAAkB,gBAAgB,wDAAwD;AAChG,QAAM,MAAM,oBAAI,IAAY;AAC5B,QAAM,eAAe,OAAO,aAAa,IAAI,CAAC,gBAAgB;AAC5D,UAAM,UAAU,YAAY,YAAY,IAAI;AAC5C,UAAM,YAAY,IAAI,IAAI,YAAY,EAAE;AACxC,QAAI,IAAI,YAAY,EAAE;AACtB,QACE,CAAC,YAAY,GAAG,KAAK,KACrB,aACA,WACA,CAAC,CAAC,SAAS,MAAM,EAAE,SAAS,YAAY,KAAK,GAC7C;AACA;AAAA,QACE;AAAA,QACA,YAAY;AAAA,QACZ,WAAW;AAAA,MACb;AACA,aAAO,EAAE,IAAI,YAAY,IAAI,cAAc,CAAC,GAAG,WAAW,MAAM;AAAA,IAClE;AACA,UAAM,UAAU,UAAU,MAAM;AAAA,MAAO,CAAC,SACtC,YAAY,UAAU,UAClB,KAAK,SAAS,YAAY,OAC1B,MAAM,YAAY,KAAK,MAAM,YAAY,IAAI;AAAA,IACnD;AACA,QAAI,CAAC,QAAQ;AACX;AAAA,QACE;AAAA,QACA,YAAY;AAAA,QACZ,qBAAqB,YAAY,IAAI;AAAA,MACvC;AACF,eAAW,QAAQ,SAAS;AAC1B,UAAI,KAAK,SAAS,EAAG,KAAI,SAAS,KAAK,MAAM,qBAAqB,YAAY,EAAE,YAAY;AAAA,IAC9F;AACA,WAAO;AAAA,MACL,IAAI,YAAY;AAAA,MAChB,cAAc,QAAQ,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,MAC7C,WAAW,QAAQ,SAAS,KAAK,QAAQ,MAAM,CAAC,SAAS,KAAK,OAAO,CAAC;AAAA,IACxE;AAAA,EACF,CAAC;AACD,aAAW,WAAW,OAAO,qBAAqB,CAAC,GAAG;AACpD,UAAM,UAAU,YAAY,OAAO;AACnC,QAAI,SAAS;AACX,UAAI,kBAAkB,SAAS,OAAO;AACtC;AAAA,IACF;AACA,eAAW,QAAQ,UAAU,OAAO;AAClC,UAAI,MAAM,YAAY,KAAK,MAAM,OAAO;AACtC,YAAI,aAAa,KAAK,MAAM,2CAA2C,OAAO,GAAG;AAAA,IACrF;AAAA,EACF;AACA,MAAI,iBAA8D;AAClE,aAAW,YAAY,OAAO,iBAAiB,CAAC,GAAG;AACjD,UAAM,WAAW,aAAa,QAAQ;AACtC,eAAW,WAAW,SAAU,KAAI,kBAAkB,SAAS,MAAM,OAAO;AAC5E,UAAM,SAAS,MAAM,IAAI,SAAS,IAAI;AACtC,QAAI,CAAC,OAAQ,KAAI,WAAW,SAAS,MAAM,4CAA4C;AAAA,aAC9E,OAAO,SAAS,SAAS;AAChC,UAAI,YAAY,SAAS,MAAM,0DAA0D;AAC3F,QAAI,SAAS,WAAW,QAAW;AACjC,UAAI,mBAAmB,SAAU,kBAAiB;AAClD,UAAI,SAAS,UAAU,QAAQ,WAAW,SAAS,QAAQ;AACzD,yBAAiB;AACjB;AAAA,UACE;AAAA,UACA,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,aAAW,CAAC,OAAO,KAAK,KAAK,OAAO,QAAQ,OAAO,OAAO,GAAG;AAC3D,QAAI,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ;AAC1C,UAAI,kBAAkB,OAAO,4CAA4C;AAAA,EAC7E;AACA,MAAI,UAAU,cAAc,OAAO,QAAQ;AACzC,QAAI,UAAU,eAAe,kDAAkD;AACjF,MAAI,kBAAkB,QAAQ,gBAAgB,OAAO,QAAQ;AAC3D,QAAI,UAAU,iBAAiB,oDAAoD;AACrF,MAAI,UAAU,MAAM,SAAS,OAAO,QAAQ;AAC1C,QAAI,UAAU,aAAa,0DAA0D;AACvF,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB,WAAW,EAAE,GAAG,WAAW,OAAO,UAAU,MAAM,IAAI,CAAC,UAAU,EAAE,GAAG,KAAK,EAAE,EAAE;AAAA,IAC/E;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,aAAa;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAeO,SAAS,4BAA4B,OAAiD;AAC3F,QAAM,UAAoB,CAAC;AAC3B,QAAM,OAAO,MAAM,OAAO,CAAC,SAAS,KAAK,KAAK,WAAW,OAAO,CAAC;AACjE,QAAM,eAAe,KAAK;AAAA,IACxB,CAAC,SAAS,KAAK,KAAK,SAAS,OAAO,KAAK,KAAK,KAAK,SAAS,WAAW;AAAA,EACzE;AACA,MAAI,aAAa;AACf,YAAQ;AAAA,MACN,GAAG,aAAa,MAAM;AAAA,IACxB;AACF,QAAM,QAAQ,KAAK;AAAA,IACjB,CAAC,SACC,KAAK,KAAK,SAAS,KAAK,KACxB,CAAC,wBAAwB,IAAI,KAAK,IAAI,KACtC,CAAC,uBAAuB,KAAK,KAAK,IAAI;AAAA,EAC1C;AACA,MAAI,MAAM;AACR,YAAQ;AAAA,MACN,GAAG,MAAM,MAAM,yDAAyD,CAAC,GAAG,uBAAuB,EAAE,KAAK,IAAI,CAAC,2BAA2B,MAAM,CAAC,GAAG,IAAI;AAAA,IAC1J;AACF,SAAO;AACT;;;ACxTA,SAAS,YAAY,WAAW,oBAAoB;AACpD,SAAS,MAAM,eAAe;AAC9B,SAAS,yBAAyB;AAMlC,IAAM,qBAAqB;AA6DpB,SAAS,kBAAkB,WAA4B;AAC5D,SAAO,UAAU,WAAW,kBAAkB;AAChD;AA0BA,eAAsB,oBACpB,WACA,WACA,QAA8B,UAC9B,YAC+B;AAC/B,QAAM,OAAO,MAAM,aAAa;AAChC,QAAM,QAAQ,KAAK,OAAO,SAAS;AACnC,QAAM,eAAe,kBAAkB,SAAS;AAGhD,MAAI,CAAC,OAAO;AACV,UAAMA,iBAAgB,KAAK,kBAAkB,GAAG,SAAS;AACzD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,iBAAiB,WAAWA,cAAa;AAAA,MACzC,eAAe;AAAA,MACf,cAAc,CAAC;AAAA,MACf;AAAA,MACA,OAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,gBAAgB,MAAM;AAC5B,QAAM,kBAAkB,WAAW,aAAa;AAGhD,QAAM,eAAqD,CAAC;AAE5D,aAAW,YAAY,WAAW;AAChC,UAAM,aAAa,0BAA0B,UAAU,OAAO,UAAU;AACxE,eAAW,aAAa,YAAY;AAClC,UAAI,CAAC,UAAW;AAEhB,YAAM,WAAW,KAAK,WAAW,SAAS;AAC1C,YAAM,SAAS,WAAW,QAAQ;AAClC,UAAI,YAAY;AAChB,UAAI,oBAAoB;AAExB,UAAI,QAAQ;AACV,YAAI;AACF,gBAAM,OAAO,UAAU,QAAQ;AAC/B,sBAAY,KAAK,eAAe;AAChC,cAAI,WAAW;AACb,kBAAM,SAAS,QAAQ,aAAa,QAAQ,CAAC;AAC7C,gCAAoB,WAAW,QAAQ,aAAa;AAAA,UACtD;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAEA,mBAAa,KAAK;AAAA,QAChB,YAAY,SAAS;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,CAAC,iBAAiB;AACpB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,gCAAgC,aAAa;AAAA,IACtD;AAAA,EACF;AAEA,QAAM,cAAc,aAAa,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM;AACxD,QAAM,gBAAgB,aAAa,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB;AAEjF,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,GAAG,cAAc,MAAM;AAAA,IAChC;AAAA,EACF;AAEA,MAAI,YAAY,SAAS,GAAG;AAC1B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,GAAG,YAAY,MAAM;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAwBA,eAAsB,uBACpB,WACA,QAA8B,UAC9B,YAC4C;AAC5C,QAAM,OAAO,MAAM,aAAa;AAChC,QAAM,UAAU,oBAAI,IAAkC;AAEtD,aAAW,aAAa,OAAO,KAAK,KAAK,MAAM,GAAG;AAChD,UAAM,SAAS,MAAM,oBAAoB,WAAW,WAAW,OAAO,UAAU;AAChF,YAAQ,IAAI,WAAW,MAAM;AAAA,EAC/B;AAEA,SAAO;AACT;AAyBO,SAAS,oBACd,WACA,gBACA,eACS;AAET,MAAI,CAAC,cAAe,QAAO;AAG3B,MAAI,kBAAkB,SAAS,GAAG;AAEhC,QAAI,cAAc,eAAe,UAAW,QAAO;AAEnD,WAAO;AAAA,EACT;AAGA,SAAO;AACT;AAyBA,eAAsB,6BACpB,WACA,YACA,OACA,iBACqE;AACrE,QAAM,EAAE,oBAAAC,oBAAmB,IAAI,MAAM,OAAO,wBAA6B;AACzE,QAAM,UAAU,MAAMA,oBAAmB,WAAW,YAAY,OAAO,eAAe;AACtF,QAAM,SAAqE,CAAC;AAE5E,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,WAAW,WAAW;AAC/B,aAAO,KAAK;AAAA,QACV,MAAM,OAAO;AAAA,QACb,YAAY,OAAO;AAAA,QACnB,OAAO;AAAA,MACT,CAAC;AAAA,IACH,WAAW,OAAO,WAAW,QAAQ;AACnC,aAAO,KAAK;AAAA,QACV,MAAM,OAAO;AAAA,QACb,YAAY,OAAO;AAAA,QACnB,OAAO;AAAA,MACT,CAAC;AAAA,IACH,WAAW,OAAO,WAAW,YAAY;AACvC,aAAO,KAAK;AAAA,QACV,MAAM,OAAO;AAAA,QACb,YAAY,OAAO;AAAA,QACnB,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;","names":["canonicalPath","checkAllInjections"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
HomeInstructionFileError,
|
|
2
3
|
checkAllInjections,
|
|
3
4
|
checkInjection,
|
|
4
5
|
dedupeFile,
|
|
@@ -15,9 +16,10 @@ import {
|
|
|
15
16
|
repairInstructionFiles,
|
|
16
17
|
resolveGlobalInstructionPath,
|
|
17
18
|
writeAgentFileToAllProviders
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-JR6T47PC.js";
|
|
19
20
|
import "./chunk-HDZYZTR2.js";
|
|
20
21
|
export {
|
|
22
|
+
HomeInstructionFileError,
|
|
21
23
|
checkAllInjections,
|
|
22
24
|
checkInjection,
|
|
23
25
|
dedupeFile,
|
|
@@ -35,4 +37,4 @@ export {
|
|
|
35
37
|
resolveGlobalInstructionPath,
|
|
36
38
|
writeAgentFileToAllProviders
|
|
37
39
|
};
|
|
38
|
-
//# sourceMappingURL=injector-
|
|
40
|
+
//# sourceMappingURL=injector-Q6KCKS76.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/caamp",
|
|
3
|
-
"version": "2026.10.
|
|
3
|
+
"version": "2026.10.5-rc.ci.672",
|
|
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,14 +50,14 @@
|
|
|
50
50
|
"jsonc-parser": "^3.3.1",
|
|
51
51
|
"picocolors": "^1.1.1",
|
|
52
52
|
"simple-git": "3.33.0",
|
|
53
|
-
"@cleocode/contracts": "2026.10.
|
|
54
|
-
"@cleocode/cant": "2026.10.
|
|
55
|
-
"@cleocode/core": "2026.10.
|
|
56
|
-
"@cleocode/lafs": "2026.10.
|
|
57
|
-
"@cleocode/paths": "2026.10.
|
|
53
|
+
"@cleocode/contracts": "2026.10.5-rc.ci.672",
|
|
54
|
+
"@cleocode/cant": "2026.10.5-rc.ci.672",
|
|
55
|
+
"@cleocode/core": "2026.10.5-rc.ci.672",
|
|
56
|
+
"@cleocode/lafs": "2026.10.5-rc.ci.672",
|
|
57
|
+
"@cleocode/paths": "2026.10.5-rc.ci.672"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"@cleocode/core": "2026.10.
|
|
60
|
+
"@cleocode/core": "2026.10.5-rc.ci.672"
|
|
61
61
|
},
|
|
62
62
|
"peerDependenciesMeta": {
|
|
63
63
|
"@cleocode/core": {
|