@cleocode/caamp 2026.9.20 → 2026.9.22

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/index.d.ts CHANGED
@@ -124,6 +124,62 @@ type RegistryHookCatalog = 'canonical' | 'pi';
124
124
  * @public
125
125
  */
126
126
  type SpawnMechanism = 'native' | 'native-child-process' | 'mcp' | 'cli' | 'api';
127
+ /**
128
+ * Whether a provider exposes a structured-question ("ask the human") tool.
129
+ *
130
+ * - `native` — the harness ships a built-in tool that renders selectable options.
131
+ * - `none` — verified absent from the harness's built-in tool set.
132
+ * - `unknown` — not verified from docs or source; never guessed.
133
+ *
134
+ * @public
135
+ */
136
+ type AskToolStatus = 'native' | 'none' | 'unknown';
137
+ /**
138
+ * Registry record of a provider's structured-question tool.
139
+ *
140
+ * @remarks
141
+ * Data only. `source` says where the fact was verified so a stale entry can be
142
+ * re-checked; `caveat` records availability limits (mode gates, subagent
143
+ * restrictions). When `toolName` is `null` the agent uses
144
+ * {@link HitlRequestFallback} instead.
145
+ *
146
+ * @public
147
+ */
148
+ interface ProviderAskTool {
149
+ /** Verification status of the ask tool. */
150
+ status: AskToolStatus;
151
+ /** Exact tool name the model calls, or `null` when none is known. */
152
+ toolName: string | null;
153
+ /** Availability limits, or `null` when none are known. */
154
+ caveat: string | null;
155
+ /** Where the fact was verified (doc URL, source path, or binary inspected). */
156
+ source: string;
157
+ }
158
+ /**
159
+ * Fallback when a provider has no (known) ask tool: the agent emits ONE LAFS
160
+ * envelope with this operation carrying the payload fields, then stops.
161
+ *
162
+ * @public
163
+ */
164
+ interface HitlRequestFallback {
165
+ /** LAFS operation name of the envelope. */
166
+ operation: 'hitl.request';
167
+ /** Payload fields the envelope `data` carries. */
168
+ fields: readonly ['question', 'options', 'recommended'];
169
+ /** Shape of each option entry. */
170
+ optionFields: readonly ['label', 'description'];
171
+ }
172
+ /**
173
+ * Resolved ask-tool answer for one provider.
174
+ *
175
+ * @public
176
+ */
177
+ interface ResolvedProviderAskTool extends ProviderAskTool {
178
+ /** Canonical provider id (aliases resolved). */
179
+ providerId: string;
180
+ /** The `hitl.request` fallback; use it whenever `toolName` is `null`. */
181
+ fallback: HitlRequestFallback;
182
+ }
127
183
 
128
184
  /**
129
185
  * SkillLibrary interface - SDK standard contract for skill libraries.
@@ -266,6 +322,24 @@ interface SkillLibraryManifestSkill {
266
322
  requires_session: boolean;
267
323
  requires_epic: boolean;
268
324
  };
325
+ /** Delivery class from SKILL.md `metadata.tier` (T12648). */
326
+ deliveryTier?: 'core' | 'on-demand' | 'internal';
327
+ /** Install mode from SKILL.md `metadata.install` (T12648). */
328
+ install?: 'harness' | 'internal';
329
+ /** Whether this is a core skill (catalog field, T12653). */
330
+ core?: boolean;
331
+ /** Catalog category (T12653). */
332
+ category?: SkillLibraryEntry['category'];
333
+ /** Associated protocol name (T12653). */
334
+ protocol?: string | null;
335
+ /** Direct dependency skill names (T12653). */
336
+ dependencies?: string[];
337
+ /** Shared resource names (T12653). */
338
+ sharedResources?: string[];
339
+ /** Compatible agent/context types (T12653). */
340
+ compatibility?: string[];
341
+ /** SPDX license identifier (T12653). */
342
+ license?: string;
269
343
  }
270
344
  /**
271
345
  * Full manifest structure for a skill library.
@@ -3232,10 +3306,11 @@ declare function updateJsonConfigFile(filePath: string, mutate: (config: Record<
3232
3306
  /**
3233
3307
  * Skill installer - canonical + symlink model
3234
3308
  *
3235
- * Skills are stored once in a canonical location (`~/.cleo/skills/<name>/`
3236
- * per architecture-v3 §1, with legacy `~/.local/share/agents/skills/` as a
3237
- * read-only fallback for one release cycle) and symlinked to each target
3238
- * agent's skills directory.
3309
+ * Skills are stored once in a canonical location (`<cleoHome>/skills/<name>/`,
3310
+ * the platform data dir from `resolveSkillsRoot()`; T12598) and linked to each
3311
+ * target agent's skills directory. Every link is verified to resolve after it
3312
+ * is written; where a link cannot be created or does not resolve (Windows
3313
+ * without Developer Mode, filesystems without symlinks) the skill is copied.
3239
3314
  *
3240
3315
  * @task T9659
3241
3316
  * @epic T9571
@@ -7591,6 +7666,47 @@ declare function getProviderCapabilities(idOrAlias: string): ProviderCapabilitie
7591
7666
  * @public
7592
7667
  */
7593
7668
  declare function providerSupportsById(idOrAlias: string, capabilityPath: string): boolean;
7669
+ /**
7670
+ * The fallback every agent uses when its provider has no known ask tool: emit
7671
+ * ONE LAFS envelope `hitl.request` with `{question, options[{label,
7672
+ * description}], recommended}` in `data`, then stop.
7673
+ *
7674
+ * @public
7675
+ */
7676
+ declare const HITL_REQUEST_FALLBACK: HitlRequestFallback;
7677
+ /**
7678
+ * Structured-question ("ask the human") tool per provider id.
7679
+ *
7680
+ * @remarks
7681
+ * DATA, keyed by the canonical id in `providers/registry.json`; every registry
7682
+ * provider has an entry (a test enforces it). Only verified names are
7683
+ * recorded — anything not found in docs or source is `unknown`, never
7684
+ * invented. Researched 2026-09-27 for T12482.
7685
+ *
7686
+ * @public
7687
+ */
7688
+ declare const PROVIDER_ASK_TOOLS: Readonly<Record<string, ProviderAskTool>>;
7689
+ /**
7690
+ * Resolve the structured-question tool for a provider, with the
7691
+ * `hitl.request` fallback attached.
7692
+ *
7693
+ * @remarks
7694
+ * Canonical ids are looked up directly (no registry load); anything else is
7695
+ * alias-resolved through the registry. An id with no entry resolves to
7696
+ * `unknown` so callers always get an answer and a fallback.
7697
+ *
7698
+ * @param idOrAlias - Provider ID or alias (e.g. `"claude"`)
7699
+ * @returns The ask-tool record, its canonical provider id and the fallback
7700
+ *
7701
+ * @example
7702
+ * ```typescript
7703
+ * getProviderAskTool('claude').toolName; // "AskUserQuestion"
7704
+ * getProviderAskTool('aider').toolName; // null -> use fallback (hitl.request)
7705
+ * ```
7706
+ *
7707
+ * @public
7708
+ */
7709
+ declare function getProviderAskTool(idOrAlias: string): ResolvedProviderAskTool;
7594
7710
 
7595
7711
  /**
7596
7712
  * Spawn adapter interface for provider-neutral subagent orchestration.
@@ -7794,7 +7910,7 @@ declare function registerSkillLibrary(library: SkillLibrary): void;
7794
7910
  * @remarks
7795
7911
  * Tries two strategies in order: first attempts module-based loading if
7796
7912
  * the directory contains an `index.js`, then falls back to file-based
7797
- * loading from raw files like `skills.json`. Replaces any previously
7913
+ * loading from `skills.json` or `skills/manifest.json`. Replaces any previously
7798
7914
  * registered library on success.
7799
7915
  *
7800
7916
  * @param root - Absolute path to the skill library root directory
@@ -8983,12 +9099,30 @@ declare function validateInstructionIntegrity(providers: Provider[], projectDir:
8983
9099
  * @public
8984
9100
  */
8985
9101
  declare function loadLibraryFromModule(root: string): SkillLibrary;
9102
+ /**
9103
+ * Derive a catalog entry from a `skills/manifest.json` entry.
9104
+ *
9105
+ * @remarks
9106
+ * The CLEO skills package ships no `skills.json` (T12653): its manifest is
9107
+ * generated from SKILL.md frontmatter and carries every catalog field. The
9108
+ * manifest `path` names the skill directory, so the catalog path appends
9109
+ * `SKILL.md`. `core` falls back to `deliveryTier === 'core'` and absent list
9110
+ * fields default to empty, so an older manifest still maps.
9111
+ *
9112
+ * @param skill - One manifest skill entry.
9113
+ * @returns The equivalent catalog entry.
9114
+ *
9115
+ * @public
9116
+ */
9117
+ declare function catalogEntryFromManifest(skill: SkillLibraryManifestSkill): SkillLibraryEntry;
8986
9118
  /**
8987
9119
  * Build a SkillLibrary from raw files in a directory.
8988
9120
  *
8989
9121
  * @remarks
8990
9122
  * Constructs a full SkillLibrary implementation by reading:
8991
- * - `skills.json` for catalog entries
9123
+ * - `skills.json` for catalog entries, when present (legacy and third-party
9124
+ * libraries); otherwise the catalog is derived from `skills/manifest.json`
9125
+ * entries via {@link catalogEntryFromManifest} (T12653)
8992
9126
  * - `skills/manifest.json` for dispatch matrix
8993
9127
  * - `profiles/*.json` for profile definitions
8994
9128
  * - `skills/<name>/SKILL.md` for skill content
@@ -8997,7 +9131,7 @@ declare function loadLibraryFromModule(root: string): SkillLibrary;
8997
9131
  *
8998
9132
  * @param root - Absolute path to the library root directory
8999
9133
  * @returns A SkillLibrary instance backed by filesystem reads
9000
- * @throws If skills.json is not found at the root
9134
+ * @throws If neither skills.json nor skills/manifest.json is found at the root
9001
9135
  *
9002
9136
  * @example
9003
9137
  * ```typescript
@@ -9733,4 +9867,4 @@ declare function parseSource(input: string): ParsedSource;
9733
9867
  */
9734
9868
  declare function isMarketplaceScoped(input: string): boolean;
9735
9869
 
9736
- export { 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, HOOK_CATEGORIES, type Harness, type HarnessScope, type HookCategory, type HookEvent, type HookHandlerType, type HookMapping, type HookSupportResult, type HookSystemType, type InjectionCheckResult, type InjectionStatus, type InjectionTemplate, type InstallMcpServerOptions, type InstallMcpServerResult, type InstallSkillOptions, type InstructionUpdateSummary, 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, 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 ReconcileResult, type RegistryHarnessKind, type RegistryHookCatalog, type RegistryHookFormat, type RemoveMcpServerOptions, type RemoveMcpServerResult, type RepairResult, type ResolveDefaultTargetProvidersOptions, 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, 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, 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 };
9870
+ 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 };
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  RECOMMENDATION_ERROR_CODES,
8
8
  SkillInstallError,
9
9
  buildLibraryFromFiles,
10
+ catalogEntryFromManifest,
10
11
  catalog_exports,
11
12
  checkAllSkillUpdates,
12
13
  checkGlobalInstructionStaleness,
@@ -81,10 +82,12 @@ import {
81
82
  validateRecommendationCriteria,
82
83
  validateSkill,
83
84
  writeConfig
84
- } from "./chunk-QC6CHW72.js";
85
+ } from "./chunk-3OL6CAMT.js";
85
86
  import {
86
87
  EmbeddedDeliveryDowngradeError,
88
+ HITL_REQUEST_FALLBACK,
87
89
  JsonConfigParseError,
90
+ PROVIDER_ASK_TOOLS,
88
91
  assertNotTornRead,
89
92
  blockPattern,
90
93
  buildBlock,
@@ -106,6 +109,7 @@ import {
106
109
  getPrimaryProvider,
107
110
  getProvider,
108
111
  getProviderAgentFolder,
112
+ getProviderAskTool,
109
113
  getProviderCapabilities,
110
114
  getProviderCount,
111
115
  getProviderInstructionReferences,
@@ -140,7 +144,7 @@ import {
140
144
  updateJsonConfigFile,
141
145
  withFileLock,
142
146
  writeAgentFileToAllProviders
143
- } from "./chunk-JELNPPLN.js";
147
+ } from "./chunk-UIXTFV35.js";
144
148
  import {
145
149
  CANONICAL_HOOK_EVENTS,
146
150
  HOOK_CATEGORIES,
@@ -516,7 +520,7 @@ function shouldOverrideSkill(skillName, incomingSource, existingEntry) {
516
520
  return true;
517
521
  }
518
522
  async function validateInstructionIntegrity(providers, projectDir, scope, expectedContent) {
519
- const { checkAllInjections: checkAllInjections2 } = await import("./injector-7NNSGPGQ.js");
523
+ const { checkAllInjections: checkAllInjections2 } = await import("./injector-KSFK5LF2.js");
520
524
  const results = await checkAllInjections2(providers, projectDir, scope, expectedContent);
521
525
  const issues = [];
522
526
  for (const result of results) {
@@ -549,9 +553,11 @@ export {
549
553
  DEFAULT_EXCLUSIVITY_MODE,
550
554
  EXCLUSIVITY_MODE_ENV_VAR,
551
555
  EmbeddedDeliveryDowngradeError,
556
+ HITL_REQUEST_FALLBACK,
552
557
  HOOK_CATEGORIES,
553
558
  JsonConfigParseError,
554
559
  MarketplaceClient,
560
+ PROVIDER_ASK_TOOLS,
555
561
  PiHarness,
556
562
  PiRequiredError,
557
563
  RECOMMENDATION_ERROR_CODES,
@@ -566,6 +572,7 @@ export {
566
572
  buildLibraryFromFiles,
567
573
  buildSkillsMap,
568
574
  catalog_exports as catalog,
575
+ catalogEntryFromManifest,
569
576
  checkAllInjections,
570
577
  checkAllSkillIntegrity,
571
578
  checkAllSkillUpdates,
@@ -625,6 +632,7 @@ export {
625
632
  getProjectAgentsDir,
626
633
  getProvider,
627
634
  getProviderAgentFolder,
635
+ getProviderAskTool,
628
636
  getProviderCapabilities,
629
637
  getProviderCount,
630
638
  getProviderHookProfile,
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/** 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: '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 bundle.\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') && file.path !== 'dist/cli/index.js',\n );\n if (stray.length)\n reasons.push(\n `${stray.length} .js file(s) under dist/ outside the declared entry dist/cli/index.js, 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":"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","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/** 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: '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 bundle.\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') && file.path !== 'dist/cli/index.js',\n );\n if (stray.length)\n reasons.push(\n `${stray.length} .js file(s) under dist/ outside the declared entry dist/cli/index.js, 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":"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","names":["canonicalPath","checkAllInjections"]}
@@ -15,7 +15,7 @@ import {
15
15
  repairInstructionFiles,
16
16
  resolveGlobalInstructionPath,
17
17
  writeAgentFileToAllProviders
18
- } from "./chunk-JELNPPLN.js";
18
+ } from "./chunk-UIXTFV35.js";
19
19
  import "./chunk-HDZYZTR2.js";
20
20
  export {
21
21
  checkAllInjections,
@@ -35,4 +35,4 @@ export {
35
35
  resolveGlobalInstructionPath,
36
36
  writeAgentFileToAllProviders
37
37
  };
38
- //# sourceMappingURL=injector-7NNSGPGQ.js.map
38
+ //# sourceMappingURL=injector-KSFK5LF2.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleocode/caamp",
3
- "version": "2026.9.20",
3
+ "version": "2026.9.22",
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/core": "2026.9.20",
54
- "@cleocode/paths": "2026.9.20",
55
- "@cleocode/contracts": "2026.9.20",
56
- "@cleocode/cant": "2026.9.20",
57
- "@cleocode/lafs": "2026.9.20"
53
+ "@cleocode/cant": "2026.9.22",
54
+ "@cleocode/contracts": "2026.9.22",
55
+ "@cleocode/lafs": "2026.9.22",
56
+ "@cleocode/core": "2026.9.22",
57
+ "@cleocode/paths": "2026.9.22"
58
58
  },
59
59
  "peerDependencies": {
60
- "@cleocode/core": "2026.9.20"
60
+ "@cleocode/core": "2026.9.22"
61
61
  },
62
62
  "peerDependenciesMeta": {
63
63
  "@cleocode/core": {