agents-inc 0.160.0 → 0.161.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +1 -1
- package/dist/{chunk-PEHYVSJG.js → chunk-264XDRU7.js} +2 -2
- package/dist/{chunk-LJ6V54NR.js → chunk-2MPXMJ2O.js} +7 -7
- package/dist/{chunk-GWPKIXBM.js → chunk-3H42U56X.js} +2 -2
- package/dist/{chunk-CWQLRKWB.js → chunk-3M75HVIM.js} +3 -3
- package/dist/{chunk-YKRPWZ3G.js → chunk-3TM4FHTG.js} +2 -2
- package/dist/{chunk-C5P7RUDR.js → chunk-5DWDT6GM.js} +115 -96
- package/dist/chunk-5DWDT6GM.js.map +1 -0
- package/dist/{chunk-4APXK7ZY.js → chunk-5MML3K36.js} +2 -2
- package/dist/{chunk-J7Q5VYR7.js → chunk-6PVWDTEM.js} +12 -12
- package/dist/{chunk-LX7UXZBN.js → chunk-A2NA377T.js} +6 -6
- package/dist/{chunk-IWUFZ6NR.js → chunk-ADDYIMWN.js} +3 -3
- package/dist/{chunk-OUG6TCQ4.js → chunk-AMZO4YJK.js} +10786 -18653
- package/dist/chunk-AMZO4YJK.js.map +1 -0
- package/dist/{chunk-7JQPIMKD.js → chunk-AO6DXJUK.js} +3 -3
- package/dist/{chunk-CICB4AKA.js → chunk-B3YSTZZC.js} +3 -3
- package/dist/{chunk-XDNGMXOZ.js → chunk-B7YTQVAF.js} +4 -4
- package/dist/{chunk-XX657S4U.js → chunk-BLGETWYI.js} +6 -11
- package/dist/{chunk-XX657S4U.js.map → chunk-BLGETWYI.js.map} +1 -1
- package/dist/{chunk-ITEJARWI.js → chunk-BRHU6J3C.js} +3 -3
- package/dist/{chunk-AU5FS3QK.js → chunk-DGXW2ZFY.js} +3 -3
- package/dist/{chunk-K6MQV6SK.js → chunk-DHRW3MDM.js} +3 -3
- package/dist/{chunk-OJIQOVWB.js → chunk-DTCUZL7S.js} +2 -2
- package/dist/{chunk-Q2HB5SWU.js → chunk-EEFTUZHZ.js} +5 -5
- package/dist/{chunk-6CP3CLDE.js → chunk-EERGAAGE.js} +4 -4
- package/dist/{chunk-EPBUWEW4.js → chunk-EQSMVZGS.js} +10 -10
- package/dist/{chunk-5K33RJ7Z.js → chunk-EY7Z34Y4.js} +15 -15
- package/dist/{chunk-IJ7GWQUR.js → chunk-F6LS2BQD.js} +11 -11
- package/dist/{chunk-SITF5EZM.js → chunk-HB3YIAFD.js} +2 -2
- package/dist/{chunk-XSULY25W.js → chunk-LZPRLHUE.js} +9 -9
- package/dist/{chunk-RJ3JYZJ7.js → chunk-MED6GNV3.js} +288 -203
- package/dist/chunk-MED6GNV3.js.map +1 -0
- package/dist/chunk-N6CILY5A.js +35 -0
- package/dist/chunk-N6CILY5A.js.map +1 -0
- package/dist/{chunk-VI4X5DN5.js → chunk-ODUACQLV.js} +6 -6
- package/dist/{chunk-JQDN7KAZ.js → chunk-QKMT6OOP.js} +2 -2
- package/dist/{chunk-PWPKZNCV.js → chunk-SX57ZIGM.js} +4 -4
- package/dist/{chunk-PIUCYRLP.js → chunk-T4RVCFWN.js} +3 -3
- package/dist/{chunk-4VVKVOOP.js → chunk-UMYEY6BA.js} +2 -2
- package/dist/{chunk-X5PLVOJS.js → chunk-W2RXRWDB.js} +2 -2
- package/dist/{chunk-DEWI5HDF.js → chunk-WVCF7KFV.js} +5 -5
- package/dist/chunk-XA4SWA2Z.js +591 -0
- package/dist/chunk-XA4SWA2Z.js.map +1 -0
- package/dist/{chunk-SLB2SFTX.js → chunk-YOVUXONB.js} +9 -19
- package/dist/chunk-YOVUXONB.js.map +1 -0
- package/dist/chunk-YSQ76LWG.js +8734 -0
- package/dist/chunk-YSQ76LWG.js.map +1 -0
- package/dist/{chunk-OJR3ASZI.js → chunk-ZQZHDYHQ.js} +7 -7
- package/dist/commands/build/marketplace.js +7 -7
- package/dist/commands/build/plugins.js +7 -7
- package/dist/commands/compile.js +13 -13
- package/dist/commands/doctor.js +12 -12
- package/dist/commands/edit.js +44 -44
- package/dist/commands/eject.js +10 -10
- package/dist/commands/init.js +36 -36
- package/dist/commands/list.js +8 -8
- package/dist/commands/new/marketplace.js +7 -7
- package/dist/commands/search.js +10 -10
- package/dist/commands/share.js +10 -9
- package/dist/commands/share.js.map +1 -1
- package/dist/commands/uninstall.js +11 -11
- package/dist/commands/update.js +6 -6
- package/dist/components/common/removal-plan-confirm.js +2 -2
- package/dist/components/common/select-list.js +2 -2
- package/dist/components/wizard/category-grid.js +4 -4
- package/dist/components/wizard/checkbox-grid.js +4 -4
- package/dist/components/wizard/domain-selection.js +9 -9
- package/dist/components/wizard/run-wizard-session.js +26 -26
- package/dist/components/wizard/scroll-affordance.js +2 -2
- package/dist/components/wizard/skill-agent-summary.js +5 -5
- package/dist/components/wizard/source-grid.js +5 -5
- package/dist/components/wizard/stack-selection.js +7 -7
- package/dist/components/wizard/step-agents.js +8 -8
- package/dist/components/wizard/step-build.js +7 -7
- package/dist/components/wizard/step-confirm.js +9 -9
- package/dist/components/wizard/step-sources.js +8 -8
- package/dist/components/wizard/step-stack.js +8 -8
- package/dist/components/wizard/summary-panel.js +8 -8
- package/dist/components/wizard/toast.js +2 -2
- package/dist/components/wizard/wizard-layout.js +12 -12
- package/dist/components/wizard/wizard-tabs.js +2 -2
- package/dist/components/wizard/wizard.js +25 -25
- package/dist/hooks/init.js +36 -36
- package/dist/load-agent-defs-LDSND43G.js +13 -0
- package/dist/recompile-project-agents-GQLODH24.js +17 -0
- package/dist/{source-loader-CDYH2NIM.js → source-loader-TSF5VS6V.js} +4 -4
- package/dist/stores/wizard-store.js +4 -4
- package/package.json +9 -4
- package/dist/chunk-5KB4I5J7.js +0 -262
- package/dist/chunk-5KB4I5J7.js.map +0 -1
- package/dist/chunk-C5P7RUDR.js.map +0 -1
- package/dist/chunk-KCN5N3PB.js +0 -169
- package/dist/chunk-KCN5N3PB.js.map +0 -1
- package/dist/chunk-OUG6TCQ4.js.map +0 -1
- package/dist/chunk-RJ3JYZJ7.js.map +0 -1
- package/dist/chunk-SLB2SFTX.js.map +0 -1
- package/dist/chunk-VH6P7UGF.js +0 -254
- package/dist/chunk-VH6P7UGF.js.map +0 -1
- package/dist/load-agent-defs-KWHG7P7G.js +0 -13
- package/dist/recompile-project-agents-5FTDDHX7.js +0 -17
- /package/dist/{chunk-PEHYVSJG.js.map → chunk-264XDRU7.js.map} +0 -0
- /package/dist/{chunk-LJ6V54NR.js.map → chunk-2MPXMJ2O.js.map} +0 -0
- /package/dist/{chunk-GWPKIXBM.js.map → chunk-3H42U56X.js.map} +0 -0
- /package/dist/{chunk-CWQLRKWB.js.map → chunk-3M75HVIM.js.map} +0 -0
- /package/dist/{chunk-YKRPWZ3G.js.map → chunk-3TM4FHTG.js.map} +0 -0
- /package/dist/{chunk-4APXK7ZY.js.map → chunk-5MML3K36.js.map} +0 -0
- /package/dist/{chunk-J7Q5VYR7.js.map → chunk-6PVWDTEM.js.map} +0 -0
- /package/dist/{chunk-LX7UXZBN.js.map → chunk-A2NA377T.js.map} +0 -0
- /package/dist/{chunk-IWUFZ6NR.js.map → chunk-ADDYIMWN.js.map} +0 -0
- /package/dist/{chunk-7JQPIMKD.js.map → chunk-AO6DXJUK.js.map} +0 -0
- /package/dist/{chunk-CICB4AKA.js.map → chunk-B3YSTZZC.js.map} +0 -0
- /package/dist/{chunk-XDNGMXOZ.js.map → chunk-B7YTQVAF.js.map} +0 -0
- /package/dist/{chunk-ITEJARWI.js.map → chunk-BRHU6J3C.js.map} +0 -0
- /package/dist/{chunk-AU5FS3QK.js.map → chunk-DGXW2ZFY.js.map} +0 -0
- /package/dist/{chunk-K6MQV6SK.js.map → chunk-DHRW3MDM.js.map} +0 -0
- /package/dist/{chunk-OJIQOVWB.js.map → chunk-DTCUZL7S.js.map} +0 -0
- /package/dist/{chunk-Q2HB5SWU.js.map → chunk-EEFTUZHZ.js.map} +0 -0
- /package/dist/{chunk-6CP3CLDE.js.map → chunk-EERGAAGE.js.map} +0 -0
- /package/dist/{chunk-EPBUWEW4.js.map → chunk-EQSMVZGS.js.map} +0 -0
- /package/dist/{chunk-5K33RJ7Z.js.map → chunk-EY7Z34Y4.js.map} +0 -0
- /package/dist/{chunk-IJ7GWQUR.js.map → chunk-F6LS2BQD.js.map} +0 -0
- /package/dist/{chunk-SITF5EZM.js.map → chunk-HB3YIAFD.js.map} +0 -0
- /package/dist/{chunk-XSULY25W.js.map → chunk-LZPRLHUE.js.map} +0 -0
- /package/dist/{chunk-VI4X5DN5.js.map → chunk-ODUACQLV.js.map} +0 -0
- /package/dist/{chunk-JQDN7KAZ.js.map → chunk-QKMT6OOP.js.map} +0 -0
- /package/dist/{chunk-PWPKZNCV.js.map → chunk-SX57ZIGM.js.map} +0 -0
- /package/dist/{chunk-PIUCYRLP.js.map → chunk-T4RVCFWN.js.map} +0 -0
- /package/dist/{chunk-4VVKVOOP.js.map → chunk-UMYEY6BA.js.map} +0 -0
- /package/dist/{chunk-X5PLVOJS.js.map → chunk-W2RXRWDB.js.map} +0 -0
- /package/dist/{chunk-DEWI5HDF.js.map → chunk-WVCF7KFV.js.map} +0 -0
- /package/dist/{chunk-OJR3ASZI.js.map → chunk-ZQZHDYHQ.js.map} +0 -0
- /package/dist/{load-agent-defs-KWHG7P7G.js.map → load-agent-defs-LDSND43G.js.map} +0 -0
- /package/dist/{recompile-project-agents-5FTDDHX7.js.map → recompile-project-agents-GQLODH24.js.map} +0 -0
- /package/dist/{source-loader-CDYH2NIM.js.map → source-loader-TSF5VS6V.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/lib/loading/source-loader.ts","../src/cli/lib/installation/is-home-directory.ts","../src/cli/lib/metadata-keys.ts","../src/cli/utils/errors.ts","../src/cli/utils/fs.ts","../src/cli/lib/config-gate/gate-token.ts","../src/cli/utils/logger.ts","../src/cli/types/generated/source-types.ts","../src/cli/utils/type-guards.ts","../src/cli/lib/configuration/config.ts","../src/cli/lib/validate-kebab-name.ts","../src/cli/utils/messages.ts","../src/cli/lib/schemas.ts","../src/cli/lib/schema-validator.ts","../src/cli/types/matrix.ts","../src/cli/lib/configuration/config-loader.ts","../src/cli/lib/installation/install-base-dir.ts","../../compile/src/seed-to-config.ts","../../compile/src/typed-object.ts","../src/cli/lib/configuration/config-merger.ts","../src/cli/lib/configuration/project-config.ts","../src/cli/lib/stacks/stacks-loader.ts","../../compile/src/config-types-source.ts","../../compile/src/installed-format.ts","../src/cli/lib/configuration/config-types-io.ts","../src/cli/lib/skills/skill-metadata.ts","../src/cli/lib/versioning.ts","../src/cli/utils/yaml-schema.ts","../src/cli/lib/skills/skill-copier.ts","../src/cli/lib/skills/skill-plugin-compiler.ts","../src/cli/lib/plugins/plugin-manifest.ts","../src/cli/lib/plugins/plugin-ref.ts","../src/cli/lib/plugins/plugin-finder.ts","../src/cli/lib/plugins/plugin-info.ts","../src/cli/lib/installation/installation.ts","../src/cli/lib/installation/local-installer.ts","../src/cli/lib/loading/loader.ts","../src/cli/utils/frontmatter.ts","../src/cli/lib/loading/source-fetcher.ts","../src/cli/lib/loading/multi-source-loader.ts","../src/cli/lib/resolver.ts","../src/cli/utils/exec.ts","../src/cli/lib/installation/mode-migrator.ts","../src/cli/lib/plugins/plugin-validator.ts","../src/cli/lib/validation-result.ts","../src/cli/lib/plugins/plugin-settings.ts","../src/cli/lib/plugins/plugin-discovery.ts","../src/cli/lib/skills/local-skill-loader.ts","../src/cli/lib/skills/unresolved-skill-entries.ts","../src/cli/lib/skills/local-skill-mover.ts","../src/cli/lib/matrix/matrix-loader.ts","../src/cli/lib/matrix/skill-resolution.ts","../src/cli/utils/string.ts","../src/cli/lib/matrix/matrix-resolver.ts","../src/cli/lib/configuration/skill-audit.ts","../src/cli/lib/matrix/matrix-health-check.ts"],"sourcesContent":["import os from \"os\";\nimport { unique } from \"remeda\";\nimport path from \"path\";\nimport {\n MARKETPLACE_JSON,\n PROJECT_ROOT,\n SKILL_CATEGORIES_PATH,\n SKILL_RULES_PATH,\n SKILLS_DIR_PATH,\n LOCAL_PSEUDO_CATEGORY,\n STANDARD_FILES,\n} from \"../../consts\";\nimport { defaultCategories } from \"../configuration/default-categories\";\nimport { defaultStacks } from \"../configuration/default-stacks\";\nimport { isHomeDirectory } from \"../installation/is-home-directory\";\nimport { LOCAL_DEFAULTS, METADATA_KEYS } from \"../metadata-keys\";\nimport type {\n AgentDefinition,\n AgentName,\n CategoryDefinition,\n CategoryMap,\n CategoryPath,\n ExtractedSkillMetadata,\n MergedSkillsMatrix,\n ResolvedSkill,\n ResolvedStack,\n SkillAssignment,\n SkillId,\n SkillScope,\n Stack,\n Category,\n} from \"../../types\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { fileExists } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { isAgentName } from \"../../utils/type-guards\";\nimport { typedEntries, typedFromEntries, typedKeys, typedValues } from \"../../utils/typed-object\";\nimport {\n isDefaultSource,\n isLocalSource,\n isPublicCatalogueCheckout,\n loadProjectSourceConfig,\n offersBuiltInStacks,\n resolveSource,\n type ResolvedConfig,\n type SourceCaller,\n} from \"../configuration\";\nimport { discoverLocalSkills, type LocalSkillDiscoveryResult } from \"../skills\";\nimport {\n checkMatrixHealth,\n claimSlug,\n extractAllSkills,\n loadSkillCategories,\n loadSkillRules,\n mergeMatrixWithSkills,\n relationshipsForSource,\n} from \"../matrix\";\nimport { loadAllAgents } from \"./loader\";\nimport {\n fetchFromSource,\n fetchMarketplace,\n MarketplaceManifestAbsentError,\n MarketplaceNameRefusedError,\n} from \"./source-fetcher\";\nimport { loadSkillsFromAllSources } from \"./multi-source-loader\";\nimport { loadStacks, resolveAgentConfigToSkills } from \"../stacks\";\nimport { initializeMatrix, matrix as currentMatrix } from \"../matrix/matrix-provider\";\nimport { BUILT_IN_MATRIX } from \"../../types/generated/matrix\";\n\nexport type SourceLoadOptions = {\n /**\n * Whether this load may reach the init-time source rungs — see {@link SourceCaller}.\n * Defaults to `\"stored\"`: the ambient environment can only be reached by a caller that\n * names itself `init`, so no path arrives there by omission.\n */\n caller?: SourceCaller;\n sourceFlag?: string;\n projectDir?: string;\n devMode?: boolean;\n /** Skip loading skills from extra sources (multi-source). Only needed for wizard UI tagging. */\n skipExtraSources?: boolean;\n /**\n * The caller only needs the matrix, not skill files on disk. For the default\n * source this skips the `fetchFromSource` clone (the matrix is the pre-computed\n * BUILT_IN_MATRIX anyway) so the load stays offline; `sourcePath` comes back\n * empty. Sources that must be read from disk to build the matrix (local paths,\n * custom remotes) are unaffected.\n */\n matrixOnly?: boolean;\n};\n\nexport type SourceLoadResult = {\n matrix: MergedSkillsMatrix;\n sourceConfig: ResolvedConfig;\n sourcePath: string;\n isLocal: boolean;\n marketplace?: string;\n};\n\nexport async function loadSkillsMatrixFromSource(\n options: SourceLoadOptions = {},\n): Promise<SourceLoadResult> {\n const {\n caller = \"stored\",\n sourceFlag,\n projectDir,\n devMode = false,\n matrixOnly = false,\n } = options;\n\n // ABORT on an unreadable config. Every skill this returns is resolved against the marketplace\n // named here, so a run that got past this rung on a config it could not read would install from\n // a marketplace nobody chose — which is the whole of what the refusal exists to stop.\n const sourceConfig = await resolveSource({ caller, flag: sourceFlag, projectDir });\n const { source } = sourceConfig;\n\n verbose(`Loading skills from source: ${source}`);\n\n const result = await resolveBaseResult(source, sourceConfig, devMode, matrixOnly);\n\n const resolvedProjectDir = projectDir || process.cwd();\n\n // Everything the marketplace itself carries, read before any local skill is merged on\n // top: past this point a skill's provenance is no longer legible from the matrix, and\n // an id the merge INTRODUCES is one nothing but the copy on disk backs.\n const marketplaceSkillIds = new Set(typedKeys<SkillId>(result.matrix.skills));\n\n // Load global local skills first, then project local skills — project wins on conflict\n const homeDir = os.homedir();\n if (!isHomeDirectory(resolvedProjectDir)) {\n result.matrix = await mergeDiscoveredLocalSkills(result.matrix, homeDir, \"global\");\n }\n result.matrix = await mergeDiscoveredLocalSkills(result.matrix, resolvedProjectDir, \"project\");\n\n if (!options.skipExtraSources) {\n await loadSkillsFromAllSources(\n result.matrix,\n sourceConfig,\n resolvedProjectDir,\n result.marketplace,\n idsOutsideMarketplace(result.matrix, marketplaceSkillIds),\n );\n }\n\n checkMatrixHealth(result.matrix);\n initializeMatrix(result.matrix);\n\n return result;\n}\n\n/**\n * Skills the merged matrix holds that the marketplace never offered — the local merge's\n * own additions. Eject is the only install any of them can have, so they are the ids the\n * tagging pass must leave a marketplace entry off.\n */\nfunction idsOutsideMarketplace(\n matrix: MergedSkillsMatrix,\n marketplaceSkillIds: ReadonlySet<SkillId>,\n): ReadonlySet<SkillId> {\n return new Set(typedKeys<SkillId>(matrix.skills).filter((id) => !marketplaceSkillIds.has(id)));\n}\n\n/**\n * The shipped catalogue, in a copy this load may write into. Every collection the\n * local-skill merge writes to is copied: `BUILT_IN_MATRIX` is a module constant,\n * so a shared reference would leave one project's local skill in the catalogue\n * every later load reads.\n */\nfunction copyOfBuiltInMatrix(): MergedSkillsMatrix {\n return {\n ...BUILT_IN_MATRIX,\n skills: { ...BUILT_IN_MATRIX.skills },\n categories: { ...BUILT_IN_MATRIX.categories },\n suggestedStacks: [...BUILT_IN_MATRIX.suggestedStacks],\n slugMap: {\n slugToId: { ...BUILT_IN_MATRIX.slugMap.slugToId },\n },\n };\n}\n\n/**\n * Resolves the base matrix for the configured source: the pre-computed\n * BUILT_IN_MATRIX for the default source, otherwise a local or remote load.\n */\nasync function resolveBaseResult(\n source: string,\n sourceConfig: SourceLoadResult[\"sourceConfig\"],\n devMode: boolean,\n matrixOnly: boolean,\n): Promise<SourceLoadResult> {\n if (isDefaultSource(source) && !devMode) {\n // Default source: use pre-computed BUILT_IN_MATRIX instead of loading from disk.\n // Still resolve sourcePath via fetchFromSource so skill files can be read\n // (e.g. for eject-mode copy) — unless the caller declared matrixOnly, in\n // which case the fetch (a network clone on a cold cache) is skipped entirely.\n // The fetch is cached, so no network call if the clone already exists.\n const sourcePath = matrixOnly ? \"\" : (await fetchFromSource(source)).path;\n return {\n matrix: copyOfBuiltInMatrix(),\n sourceConfig,\n sourcePath,\n isLocal: false,\n ...(sourceConfig.marketplace !== undefined && { marketplace: sourceConfig.marketplace }),\n };\n }\n\n const isLocal = isLocalSource(source) || devMode === true;\n return isLocal ? loadFromLocal(source, sourceConfig) : loadFromRemote(source, sourceConfig);\n}\n\ntype MarketplaceLabels = Pick<SourceLoadResult, \"marketplace\">;\n\n/**\n * Which state a marketplace's manifest is in, as far as naming the marketplace goes.\n *\n * Four states rather than two because the failures are not one event: a marketplace with\n * no manifest is an ordinary local directory, one whose manifest is there and unreadable\n * is a broken publication that can still be installed from, and one that publishes under\n * a name Claude Code registers no plugin under can be installed from at all. Collapsing\n * the first two reported every schema violation in that file as an absent file, and a\n * reader who checked found it exactly where the message said it was not; collapsing the\n * last two turned the rule `build marketplace` refuses to publish under into a warning\n * printed above a green tick. `doctor`'s `ConfigState` splits its own the same way and\n * for the same reason.\n */\ntype ManifestState =\n | { kind: \"absent\" }\n | { kind: \"refused\"; reason: string }\n | { kind: \"unreadable\"; reason: string }\n | { kind: \"named\"; name: string };\n\n/**\n * {@link ManifestState} for one marketplace. Which failure it was is read off the throw's\n * TYPE rather than its text: `fetchMarketplace` is the only thing that can tell a file it\n * never found from one it found and refused, and a refused NAME from every other refusal,\n * so it says which and nothing here matches on a sentence.\n */\nasync function readManifestState(source: string): Promise<ManifestState> {\n try {\n const { marketplace } = await fetchMarketplace(source);\n return { kind: \"named\", name: marketplace.name };\n } catch (error) {\n if (error instanceof MarketplaceManifestAbsentError) return { kind: \"absent\" };\n if (error instanceof MarketplaceNameRefusedError) {\n return { kind: \"refused\", reason: getErrorMessage(error) };\n }\n return { kind: \"unreadable\", reason: getErrorMessage(error) };\n }\n}\n\n/** The label a config already recorded, which outlives a manifest this load could not name. */\nfunction configuredLabel(sourceConfig: ResolvedConfig): MarketplaceLabels {\n return sourceConfig.marketplace === undefined ? {} : { marketplace: sourceConfig.marketplace };\n}\n\n/**\n * Resolves the marketplace name from the source's\n * `.claude-plugin/marketplace.json`. A `marketplace` already recorded in the\n * project config wins; sources this load cannot name keep whatever the config had\n * (possibly nothing) and are labelled by their source name.\n *\n * This is where each {@link ManifestState} says whether it ABORTS or DEGRADES, and the\n * two answers are not interchangeable. A manifest that cannot be READ leaves a\n * marketplace whose skills still install, so the load carries on under a label the\n * config or the ref supplies. A manifest that names the marketplace something Claude\n * Code registers no plugin under leaves nothing installable at all, so it ABORTS —\n * carrying on labelled the marketplace by its ref, installed under a name nobody chose,\n * and let `doctor` print a green tick directly beneath its own warning about that file.\n */\nasync function resolveMarketplaceLabels(\n source: string,\n sourceConfig: ResolvedConfig,\n): Promise<MarketplaceLabels> {\n const state = await readManifestState(source);\n\n switch (state.kind) {\n case \"named\": {\n const marketplace = sourceConfig.marketplace ?? state.name;\n verbose(`Using marketplace name from ${MARKETPLACE_JSON}: ${marketplace}`);\n return { marketplace };\n }\n case \"absent\":\n verbose(`Marketplace has no ${MARKETPLACE_JSON} — using its ref as the label`);\n return configuredLabel(sourceConfig);\n case \"refused\":\n throw new MarketplaceNameRefusedError(state.reason);\n case \"unreadable\":\n warn(\n `Marketplace has a ${MARKETPLACE_JSON} this CLI cannot read, so its ref is the label instead:\\n${state.reason}`,\n );\n return configuredLabel(sourceConfig);\n default: {\n const exhaustive: never = state;\n return exhaustive;\n }\n }\n}\n\n/** Merges any discovered local skills for `dir` into the matrix, logging the find. */\nasync function mergeDiscoveredLocalSkills(\n matrix: MergedSkillsMatrix,\n dir: string,\n label: SkillScope,\n): Promise<MergedSkillsMatrix> {\n const discovered = await discoverLocalSkills(dir);\n if (!discovered || discovered.skills.length === 0) return matrix;\n verbose(\n `Found ${discovered.skills.length} ${label} local skill(s) in ${discovered.localSkillsPath}`,\n );\n return mergeLocalSkillsIntoMatrix(matrix, discovered);\n}\n\nasync function loadFromLocal(\n source: string,\n sourceConfig: ResolvedConfig,\n): Promise<SourceLoadResult> {\n // Resolved through `fetchFromSource` — the same call `loadFromRemote` makes — rather\n // than joined here, so a path the user named and the CLI cannot read is REFUSED with\n // the loader's own message. Reading it directly returned an empty matrix instead, and\n // `init`/`edit` went on to mount a wizard over nothing the user asked for.\n const skillsPath = isLocalSource(source) ? (await fetchFromSource(source)).path : PROJECT_ROOT;\n\n verbose(`Loading skills from local path: ${skillsPath}`);\n\n const mergedMatrix = await loadAndMergeFromBasePath(skillsPath, source);\n const labels = await resolveMarketplaceLabels(skillsPath, sourceConfig);\n\n return {\n matrix: mergedMatrix,\n sourceConfig,\n sourcePath: skillsPath,\n isLocal: true,\n ...labels,\n };\n}\n\nasync function loadFromRemote(\n source: string,\n sourceConfig: ResolvedConfig,\n): Promise<SourceLoadResult> {\n verbose(`Fetching skills from remote source: ${source}`);\n\n const fetchResult = await fetchFromSource(source);\n\n verbose(`Fetched to: ${fetchResult.path}`);\n\n const mergedMatrix = await loadAndMergeFromBasePath(fetchResult.path, source);\n const labels = await resolveMarketplaceLabels(source, sourceConfig);\n\n return {\n matrix: mergedMatrix,\n sourceConfig,\n sourcePath: fetchResult.path,\n isLocal: false,\n ...labels,\n };\n}\n\n/**\n * The matrix a marketplace on disk describes — its own skills, its own\n * categories and stacks, and the built-in relationship rules narrowed to the\n * slugs it actually ships.\n *\n * This is the load an AUTHOR's command makes, and it is deliberately not\n * {@link loadSkillsMatrixFromSource}: that one merges the invoking machine's\n * `~/.claude/skills` and the project's own into the result, which is right for\n * an install and wrong for anything published — a catalogue carrying the\n * author's private skills offers consumers skills that exist on one machine.\n * The local merge lives one layer up, in the install path alone.\n *\n * A marketplace's base path is also the only word anything has for WHICH\n * marketplace it is, so it stands as the source string too.\n */\nexport async function loadMarketplaceMatrix(marketplaceDir: string): Promise<MergedSkillsMatrix> {\n const matrix = await loadAndMergeFromBasePath(marketplaceDir, marketplaceDir);\n return { ...matrix, categories: categoriesTheseSkillsAreIn(matrix) };\n}\n\n/**\n * The categories a marketplace's own skills are in, and nothing else.\n *\n * {@link loadAndMergeFromBasePath} merges the built-in taxonomy underneath the\n * marketplace's own, so a skill sitting in a built-in category resolves to that\n * category's real definition rather than the humanized stand-in\n * `synthesizeCategory` writes. Right for the merge and wrong for the artefact: a\n * published catalogue cannot claim categories the marketplace ships nothing in,\n * and 102 of them arrived that way — beside a `skills` and a `suggestedStacks`\n * that were the marketplace's own.\n *\n * Membership is read off the SKILLS rather than off the marketplace's own\n * `skill-categories.ts`, because the two disagree in both directions: a skill may\n * sit in a category its author never declared, and a declared category may hold\n * nothing. Narrowing by what is declared would leave a consumer holding a skill\n * whose category the catalogue does not define, which is this bug with the sides\n * swapped.\n */\nfunction categoriesTheseSkillsAreIn(matrix: MergedSkillsMatrix): CategoryMap {\n const occupied = new Set<CategoryPath>(typedValues(matrix.skills).map((skill) => skill.category));\n\n return typedFromEntries(\n typedEntries<Category, CategoryDefinition>(matrix.categories).filter(([id]) =>\n occupied.has(id),\n ),\n );\n}\n\n/**\n * Builds the matrix for a source read from disk, from the files under\n * `basePath`. `source` is the source string that base path stands for — the\n * loader's only word for WHICH marketplace it is reading, and one of the two\n * things {@link resolveOfferedStacks} decides the built-in catalogue's fate on.\n */\nasync function loadAndMergeFromBasePath(\n basePath: string,\n source: string,\n): Promise<MergedSkillsMatrix> {\n // ABORT on an unreadable config. This file is where a marketplace declares which directories\n // its skills and stacks live in, so falling back to the defaults would walk a tree the\n // marketplace says is somewhere else and report the catalogue as empty.\n const sourceProjectConfig = await loadProjectSourceConfig(basePath);\n\n const skillsDirRelPath = sourceProjectConfig?.skillsDir ?? SKILLS_DIR_PATH;\n const stacksRelFile = sourceProjectConfig?.stacksFile;\n\n // Load source categories and rules (if they exist)\n const sourceCategoriesPath = path.join(basePath, SKILL_CATEGORIES_PATH);\n const sourceRulesPath = path.join(basePath, SKILL_RULES_PATH);\n const hasSourceCategories = await fileExists(sourceCategoriesPath);\n const hasSourceRules = await fileExists(sourceRulesPath);\n\n const sourceCategories = hasSourceCategories\n ? await loadSkillCategories(sourceCategoriesPath)\n : undefined;\n if (sourceCategories) {\n verbose(\n `Loaded source categories: ${sourceCategoriesPath} (${typedKeys(sourceCategories).length} categories)`,\n );\n }\n const categories: CategoryMap = sourceCategories\n ? { ...defaultCategories, ...sourceCategories }\n : defaultCategories;\n\n const sourceRules = hasSourceRules ? await loadSkillRules(sourceRulesPath) : undefined;\n if (sourceRules) {\n verbose(`Loaded source rules: ${sourceRulesPath}`);\n }\n\n if (hasSourceCategories || hasSourceRules) {\n verbose(`Matrix merged: CLI (${typedKeys(defaultCategories).length} categories) + source`);\n } else {\n verbose(`Matrix from CLI only (source has no categories/rules files)`);\n }\n\n const skillsDir = path.join(basePath, skillsDirRelPath);\n verbose(`Skills from source: ${skillsDir}`);\n\n const skills = await extractAllSkills(skillsDir);\n await refuseCatalogueCollisions(basePath, source, skills);\n\n const relationships = relationshipsForSource(skills, sourceRules);\n const mergedMatrix = mergeMatrixWithSkills(categories, relationships, skills);\n initializeMatrix(mergedMatrix);\n\n // Assigned unconditionally: a source offering no stacks is a matrix carrying\n // none, which is the whole of what the wizard needs to skip the stack step.\n const stacks = await resolveOfferedStacks(basePath, stacksRelFile, source);\n mergedMatrix.suggestedStacks = stacks.map((stack) => convertStackToResolvedStack(stack));\n\n // Collect explicit domain definitions from agent metadata.yaml files\n const agents = await loadAllAgents(basePath);\n const agentDefinedDomains = typedFromEntries(\n typedEntries<AgentName, AgentDefinition>(agents).flatMap(([agentId, agentDef]) =>\n agentDef.domain ? [[agentId, agentDef.domain] as const] : [],\n ),\n );\n const domainCount = typedKeys(agentDefinedDomains).length;\n if (domainCount > 0) {\n mergedMatrix.agentDefinedDomains = agentDefinedDomains;\n verbose(`Loaded ${domainCount} agent domain definition(s)`);\n }\n\n return mergedMatrix;\n}\n\n/** Every skill id the shipped catalogue owns — the ids no other marketplace may take. */\nconst CATALOGUE_SKILL_IDS: ReadonlySet<SkillId> = new Set(typedKeys(BUILT_IN_MATRIX.skills));\n\n/** How many colliding ids a refusal lists before summarising the rest. */\nconst MAX_REPORTED_COLLISIONS = 10;\n\n/**\n * Refuses a marketplace shipping skill ids the public catalogue already owns.\n *\n * A skill id is the directory the skill installs into, and Claude reads\n * `~/.claude` and `./.claude` together, so two marketplaces naming one id means\n * one silently shadows the other. `build marketplace` refuses those ids at author\n * time; this is what catches a marketplace that skipped that build, was\n * hand-edited, or is lying — nothing a source ships is unforgeable, so the\n * consumer's own load has to ask the question again.\n *\n * The SOURCE is refused, not the colliding skills: dropping them would hand the\n * user a marketplace quietly missing the skills they chose it for, leave the\n * catalogue's own copies standing in under those ids, and tell the author\n * nothing. One loud refusal naming the fix beats a partial load that hides it.\n */\nasync function refuseCatalogueCollisions(\n basePath: string,\n source: string,\n skills: ExtractedSkillMetadata[],\n): Promise<void> {\n const collidingIds = skills.map((skill) => skill.id).filter((id) => CATALOGUE_SKILL_IDS.has(id));\n if (collidingIds.length === 0) return;\n if (await isPublicCatalogueCheckout(basePath)) return;\n\n throw new Error(catalogueCollisionError(collidingIds, source));\n}\n\nfunction catalogueCollisionError(collidingIds: SkillId[], source: string): string {\n const listed = collidingIds.slice(0, MAX_REPORTED_COLLISIONS).map((id) => ` ${id}`);\n const unlisted = collidingIds.length - listed.length;\n\n return [\n `Marketplace '${source}' ships ${collidingIds.length} skill id(s) the public catalogue ` +\n `already owns:`,\n ...listed,\n ...(unlisted > 0 ? [` ... and ${unlisted} more`] : []),\n `A skill id is the directory the skill installs into, so these would shadow the public ` +\n `catalogue's own skills. Every id must carry its marketplace's name as a namespace — ` +\n `'<marketplace>-<id>'. Rename each skill and the 'name' in its SKILL.md, then re-run ` +\n `'build marketplace', which refuses the same ids before they are published.`,\n ].join(\"\\n\");\n}\n\n/**\n * The stacks a source offers the wizard: the ones it ships, or — for the public\n * catalogue alone — the CLI's built-in catalogue standing in when it ships none.\n *\n * A custom marketplace gets no such stand-in. Handing it one meant offering a\n * catalogue of stacks written against a different catalogue of skills, under a\n * name the user never asked for, with most of each stack silently dropped for\n * naming ids the chosen source does not carry. A marketplace ships its own\n * stacks or offers none, and none means a wizard with no stack step rather than\n * one showing somebody else's list.\n */\nasync function resolveOfferedStacks(\n basePath: string,\n stacksFile: string | undefined,\n source: string,\n): Promise<Stack[]> {\n const sourceStacks = await loadStacks(basePath, stacksFile);\n if (sourceStacks.length > 0) {\n verbose(`Offering the ${sourceStacks.length} stacks the source ships`);\n return sourceStacks;\n }\n\n if (await offersBuiltInStacks(basePath, source)) {\n verbose(\n `The public catalogue ships no stacks — offering the ${defaultStacks.length} built-in stacks`,\n );\n return defaultStacks;\n }\n\n verbose(`Marketplace '${source}' ships no stacks, and gets no built-in stand-in — offering none`);\n return [];\n}\n\n/**\n * A stack's sub-agents split by whether the CLI declares one.\n *\n * The keys are read as the STRINGS a stack file spells: `typedKeys` types them `AgentName` because\n * `Stack[\"agents\"]` is keyed by it, but they arrive from a marketplace's own `config/stacks.ts` and\n * nothing between that file and here narrows them — so the membership test below is a real\n * question rather than a formality, and the widening is what lets it be asked.\n *\n * Narrowed with `isAgentName` and deliberately NOT cast. Only the CLI's own `src/agents/` declares\n * a sub-agent a compile pass can honour — that directory is the whole of the roster (owner ruling\n * 2026-08-21) and is what `AGENT_NAMES` is generated from — so this is the union's own membership\n * test rather than a second list to keep in step.\n */\nfunction declaredAgentsIn(stack: Stack): { declared: AgentName[]; undeclared: string[] } {\n const named: string[] = typedKeys<AgentName>(stack.agents);\n return {\n declared: named.filter(isAgentName),\n undeclared: named.filter((name) => !isAgentName(name)),\n };\n}\n\n/**\n * What a stack naming a sub-agent the CLI does not ship is told to the user.\n *\n * The stack is DROPPED FROM rather than refused, and that posture is deliberate. A stack is a\n * suggestion the wizard offers, not an install contract, so refusing it would take every\n * sub-agent in it — the valid ones included — over one typo in a marketplace the user may not\n * own. It is also the posture the rest of this conversion already takes: `resolveStackAgentSkills`\n * drops a skill id the matrix does not carry, and one function answering the same question two\n * ways is worse than either answer. Contrast `refuseCatalogueCollisions` above, which refuses\n * the whole source because a colliding id is UNSAFE — two marketplaces silently shadowing each\n * other on disk — where an undeclared sub-agent is merely uncompilable.\n *\n * What the drop must not be is SILENT, which is what it was: the wizard narrowed these names\n * out of its own grid and told nobody. `warn()` is buffered during a source load and painted as\n * the wizard's startup band, so this reaches the user rather than a stderr the first repaint\n * scrolls away. The stack is named because a marketplace ships many, and the sub-agents are\n * named rather than counted because only the name says what to fix.\n */\nfunction undeclaredAgentsWarning(stack: Stack, undeclared: readonly string[]): string {\n const named = undeclared.map((name) => `'${name}'`).join(\", \");\n return (\n `Stack '${stack.id}' names ${undeclared.length} sub-agent(s) this CLI does not define: ` +\n `${named}. Left out of the stack — a sub-agent must be one the CLI ships.`\n );\n}\n\n/**\n * What a stack naming a skill the catalogue does not carry is told to the user.\n *\n * The skill counterpart of {@link undeclaredAgentsWarning}, and it exists for the same reason: a\n * marketplace's `config/stacks.ts` is authored by hand against a catalogue that moves, so a stack\n * outliving one of its own skills is an ordinary authoring mistake rather than a corrupt file.\n */\nfunction withdrawnSkillsWarning(stack: Stack, withdrawn: readonly string[]): string {\n const named = withdrawn.map((id) => `'${id}'`).join(\", \");\n return (\n `Stack '${stack.id}' names ${withdrawn.length} skill(s) this marketplace's catalogue does ` +\n `not carry: ${named}. Left out of the stack — selecting it would install nothing.`\n );\n}\n\n// Stack values are already skill IDs — no alias resolution needed\nexport function convertStackToResolvedStack(stack: Stack): ResolvedStack {\n const { declared, undeclared } = declaredAgentsIn(stack);\n if (undeclared.length > 0) warn(undeclaredAgentsWarning(stack, undeclared));\n\n const agentConfigs = declared.flatMap((agentId) => {\n const agentConfig = stack.agents[agentId];\n return agentConfig ? [{ agentId, agentConfig }] : [];\n });\n\n const skills = typedFromEntries(\n agentConfigs.map(\n ({ agentId, agentConfig }) => [agentId, resolveStackAgentSkills(agentConfig)] as const,\n ),\n );\n\n // First-seen order across agents, matching the historical seen-Set accumulation — and filtered\n // against the matrix by the SAME question `resolveStackAgentSkills` asks above. The two used to\n // disagree: the per-category map kept only ids the catalogue carried while this list kept every\n // id the file named, and this is the one that reaches a user. `wizard.tsx` returns it verbatim\n // as the selection when a stack is picked, and the editor's read-model counts and lists it — so\n // a stack outliving one of its own skills selected an id nothing could resolve, and the mismatch\n // surfaced only once somebody picked that stack.\n const named = unique(\n agentConfigs.flatMap(({ agentConfig }) =>\n resolveAgentConfigToSkills(agentConfig).map((ref) => ref.id),\n ),\n );\n const allSkillIds = named.filter((id) => id in currentMatrix.skills);\n const withdrawn = named.filter((id) => !(id in currentMatrix.skills));\n if (withdrawn.length > 0) warn(withdrawnSkillsWarning(stack, withdrawn));\n\n verbose(\n `Stack '${stack.id}' has ${allSkillIds.length} skills from ${agentConfigs.length} agents`,\n );\n\n return {\n id: stack.id,\n name: stack.name,\n description: stack.description,\n skills,\n allSkillIds,\n philosophy: stack.philosophy || \"\",\n };\n}\n\n/** Per-category skill ids for one stack agent, keeping only ids present in the current matrix. */\nfunction resolveStackAgentSkills(\n agentConfig: Partial<Record<Category, SkillAssignment[]>>,\n): Partial<Record<Category, SkillId[]>> {\n const byCategory = typedEntries<Category, SkillAssignment[]>(agentConfig)\n .map(([category, assignments]) => ({\n category,\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n validIds: (assignments ?? []).filter((a) => a.id in currentMatrix.skills).map((a) => a.id),\n }))\n .filter(({ validIds }) => validIds.length > 0);\n return typedFromEntries(\n byCategory.map(({ category, validIds }) => [category, validIds] as const),\n );\n}\n\n/**\n * Whether this matrix carries a definition for the category. `local` never is\n * one — it is the trapdoor a skill wears when it belongs to no category at all.\n */\nfunction declaresCategory(matrix: MergedSkillsMatrix, category: CategoryPath): boolean {\n return category !== LOCAL_PSEUDO_CATEGORY && matrix.categories[category] !== undefined;\n}\n\n/**\n * Why a custom skill was dropped, and which file places it.\n *\n * The categories on offer are deliberately not listed: they are the whole\n * catalogue's, and a refusal that prints a hundred names is one nobody reads.\n * Whatever the user picked the category in renders them already.\n */\nfunction undeclaredCategoryRefusal(\n metadata: ExtractedSkillMetadata,\n category: CategoryPath,\n): string {\n const metadataPath = path.join(metadata.path, STANDARD_FILES.METADATA_YAML);\n return (\n `Skipping local skill '${metadata.id}': ${METADATA_KEYS.CATEGORY} '${category}' is not one this ` +\n `installation declares, so the skill belongs in no grid tab and can be given to no sub-agent. ` +\n `Set ${METADATA_KEYS.CATEGORY} in ${metadataPath} to a category that already exists — a skill ` +\n `is placed in the taxonomy, it does not extend it.`\n );\n}\n\nexport function mergeLocalSkillsIntoMatrix(\n matrix: MergedSkillsMatrix,\n localResult: LocalSkillDiscoveryResult,\n): MergedSkillsMatrix {\n for (const metadata of localResult.skills) {\n const existingSkill = matrix.skills[metadata.id];\n\n // If overwriting an existing remote skill, inherit its category unconditionally.\n // Otherwise, use whatever the local skill declared in its metadata.yaml.\n const category = existingSkill?.category ?? metadata.category;\n const slug = existingSkill?.slug ?? metadata.slug;\n const displayName = existingSkill?.displayName ?? metadata.displayName;\n\n // A custom skill is PLACED in the taxonomy — its category is picked from the\n // ones that exist, never invented — so one naming a category nothing declares\n // means no pick happened. Synthesizing a definition for it is what let a\n // fabricated category read as a real placement while the skill sat in a tab\n // nothing draws. Local skills that claim no `custom` flag keep the old\n // behaviour below; narrowing that is matrix hygiene, not this rule.\n if (metadata.custom === true && !declaresCategory(matrix, category)) {\n warn(undeclaredCategoryRefusal(metadata, category));\n continue;\n }\n\n const resolvedSkill: ResolvedSkill = {\n id: metadata.id,\n slug,\n displayName,\n description: metadata.description,\n ...(metadata.usageGuidance !== undefined && { usageGuidance: metadata.usageGuidance }),\n\n category,\n\n author: LOCAL_DEFAULTS.AUTHOR,\n\n conflictsWith: existingSkill?.conflictsWith ?? [],\n requires: existingSkill?.requires ?? [],\n alternatives: existingSkill?.alternatives ?? [],\n discourages: existingSkill?.discourages ?? [],\n\n path: metadata.path,\n\n local: true,\n ...(metadata.localPath !== undefined && { localPath: metadata.localPath }),\n ...(metadata.custom !== undefined && { custom: metadata.custom }),\n };\n\n matrix.skills[metadata.id] = resolvedSkill;\n\n // Completes the map over the matrix this merge is building: the skill went\n // into `matrix.skills` and the slug map stayed as the source left it, so every\n // slug a user had written themselves resolved to nothing.\n claimSlug(matrix.slugMap, slug, metadata.id);\n\n // Ensure the skill's category exists in matrix.categories so that\n // config-types generation can discover its domain and category.\n // Skip \"local\" — it is a pseudo-category, not a real Category union member.\n if (category !== LOCAL_PSEUDO_CATEGORY && !matrix.categories[category]) {\n matrix.categories[category] = {\n id: category,\n displayName: category,\n description: `Local skill category`,\n domain: metadata.domain,\n exclusive: false,\n order: 0,\n };\n verbose(`Added local category: ${category} (domain: ${metadata.domain})`);\n }\n\n verbose(`Added local skill: ${metadata.id} (category: ${category})`);\n }\n\n return matrix;\n}\n","import fs from \"fs\";\nimport os from \"os\";\n\n/**\n * True when `dir` is the user's home directory — the global installation root.\n *\n * Symlink-safe: compares via `fs.realpathSync` so a symlinked $HOME (common on\n * macOS) still matches. Falls back to a plain string compare when either path\n * cannot be resolved (e.g. does not exist yet). Calls `os.homedir()` at runtime,\n * as every home-dir reader in the codebase now does, so it agrees with test\n * home-dir mocks.\n */\nexport function isHomeDirectory(dir: string): boolean {\n try {\n return fs.realpathSync(dir) === fs.realpathSync(os.homedir());\n } catch {\n return dir === os.homedir();\n }\n}\n","import { STANDARD_FILES, STANDARD_DIRS } from \"../consts\";\n\n/**\n * YAML field names used in skill metadata.yaml files.\n * Centralized to avoid string duplication across loaders and compilers.\n */\nexport const METADATA_KEYS = {\n DISPLAY_NAME: \"displayName\",\n CLI_DESCRIPTION: \"cliDescription\",\n CATEGORY: \"category\",\n FORKED_FROM: \"forkedFrom\",\n CONTENT_HASH: \"contentHash\",\n USAGE_GUIDANCE: \"usageGuidance\",\n CUSTOM: \"custom\",\n} as const;\n\n/**\n * What a skill discovered on disk is attributed to.\n *\n * Forced rather than defaulted: the merge writes it over whatever the file says,\n * because a local skill answers to the machine it sits on and not to a handle.\n *\n * It used to have a `CATEGORY` and a `DOMAIN` beside it — `dummy-category` and\n * `dummy`, a taxonomy in no union, placing a skill in a tab nothing draws and a\n * stack no sub-agent reads. They were scaffold placeholders for `new skill` and\n * `import skill`, and both commands were deleted; nothing has read either since.\n */\nexport const LOCAL_DEFAULTS = {\n AUTHOR: \"@dummy-author\",\n} as const;\n\n/**\n * Files included when computing a skill's content hash.\n * Shared by versioning.ts (for plugin version bumps) and\n * skill-plugin-compiler.ts (for plugin compilation).\n */\nexport const SKILL_CONTENT_FILES = [STANDARD_FILES.SKILL_MD, STANDARD_FILES.REFERENCE_MD] as const;\n\n/**\n * Directories included when computing a skill's content hash.\n * Shared by versioning.ts and skill-plugin-compiler.ts.\n */\nexport const SKILL_CONTENT_DIRS = [STANDARD_DIRS.EXAMPLES, STANDARD_DIRS.SCRIPTS] as const;\n","/** Extract a human-readable message from an unknown error value. */\nexport function getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import fs from \"fs-extra\";\nimport fg from \"fast-glob\";\nimport os from \"os\";\nimport path from \"path\";\nimport { CLAUDE_SRC_DIR, STANDARD_FILES } from \"../consts\";\n// The gate's private token module, imported here by exception (eslint records\n// it): this file is the write choke point every pair write funnels through, and\n// `gate-token.ts` is a dependency-free leaf, so the import cannot cycle.\nimport { assertGateToken } from \"../lib/config-gate/gate-token.js\";\n\n/**\n * True when `child` resolves to `parent` or inside it. Purely lexical\n * (no symlink resolution) — the caller decides throw-vs-warn policy.\n */\nexport function isPathWithin(child: string, parent: string): boolean {\n const resolvedChild = path.resolve(child);\n const resolvedParent = path.resolve(parent);\n return resolvedChild === resolvedParent || resolvedChild.startsWith(resolvedParent + path.sep);\n}\n\nexport async function readFile(filePath: string): Promise<string> {\n return fs.readFile(filePath, \"utf-8\");\n}\n\n/**\n * Reads a file with a size limit check before reading content.\n * Throws if the file exceeds maxSizeBytes. Prevents DoS from oversized files.\n */\nexport async function readFileSafe(filePath: string, maxSizeBytes: number): Promise<string> {\n const stats = await fs.stat(filePath);\n if (stats.size > maxSizeBytes) {\n throw new Error(\n `File too large: '${filePath}' is ${stats.size} bytes (limit: ${maxSizeBytes} bytes)`,\n );\n }\n return fs.readFile(filePath, \"utf-8\");\n}\n\nexport async function readFileOptional(filePath: string, fallback = \"\"): Promise<string> {\n try {\n return await fs.readFile(filePath, \"utf-8\");\n } catch {\n return fallback;\n }\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n return fs.pathExists(filePath);\n}\n\nexport async function directoryExists(dirPath: string): Promise<boolean> {\n try {\n const stat = await fs.stat(dirPath);\n return stat.isDirectory();\n } catch {\n return false;\n }\n}\n\nexport async function listDirectories(dirPath: string): Promise<string[]> {\n try {\n const entries = await fs.readdir(dirPath, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\n/**\n * @param dot Include files and directories whose name starts with a dot. Off by default, which\n * is what a scan LOOKING for something wants; a read that has to reproduce a directory\n * faithfully wants it on, since a file the read skips is one the copy silently loses.\n */\nexport async function glob(\n pattern: string,\n cwd: string,\n { dot = false }: { dot?: boolean } = {},\n): Promise<string[]> {\n return fg(pattern, { cwd, onlyFiles: true, dot });\n}\n\n/**\n * True when `resolvedPath` is one of the two halves of the global config pair.\n *\n * Compares resolved paths rather than matching on the filename, so it holds\n * against every way of naming the same file — a concatenated path, a relative\n * one, a fragment assembled at runtime — which is exactly what a static check\n * cannot do.\n */\nfunction isGlobalPairPath(resolvedPath: string): boolean {\n const globalConfigDir = path.join(os.homedir(), CLAUDE_SRC_DIR);\n return (\n resolvedPath === path.join(globalConfigDir, STANDARD_FILES.CONFIG_TS) ||\n resolvedPath === path.join(globalConfigDir, STANDARD_FILES.CONFIG_TYPES_TS)\n );\n}\n\nexport async function writeFile(filePath: string, content: string): Promise<void> {\n // Runtime tripwire: every write in the CLI funnels through here, so a pair\n // write attempted without the gate's token dies at its first execution\n // whatever route it took to get here. Costs one path compare per write.\n const resolvedPath = path.resolve(filePath);\n if (isGlobalPairPath(resolvedPath)) assertGateToken(resolvedPath);\n\n await fs.ensureDir(path.dirname(filePath));\n await fs.writeFile(filePath, content, \"utf-8\");\n}\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.ensureDir(dirPath);\n}\n\nexport async function remove(filePath: string): Promise<void> {\n await fs.remove(filePath);\n}\n\n/**\n * True when `dirPath` holds nothing, and true when it cannot be read at all —\n * an absent directory holds nothing either. Both callers ask the same question\n * of a directory they are about to write into or remove.\n */\nexport async function isDirectoryEmpty(dirPath: string): Promise<boolean> {\n try {\n const entries = await fs.readdir(dirPath);\n return entries.length === 0;\n } catch {\n return true;\n }\n}\n\n/**\n * Removes `dir` when it exists and holds nothing; true when it was removed.\n *\n * A scope directory (`.claude/skills/`, `.claude/agents/`) is an artefact of\n * what it holds, so the removal that empties it takes it too. Emptiness here is\n * FILESYSTEM emptiness and never roster emptiness — a hand-authored agent or any\n * other user-owned file keeps its directory alive, whatever a config says.\n */\nexport async function removeDirIfEmpty(dir: string): Promise<boolean> {\n if (!(await directoryExists(dir))) return false;\n if (!(await isDirectoryEmpty(dir))) return false;\n await remove(dir);\n return true;\n}\n\n/**\n * Copies a tree into an installation, and makes what it wrote writable by its new owner.\n *\n * **`eject` means the user owns the copy**, so the copy has to be editable however the SOURCE\n * happened to be stored. `fs-extra` preserves mode, and nothing normalised it: a marketplace on a\n * read-only mount, in a Nix store path, or written under a restrictive umask produced skills the\n * user could not subsequently edit — and the failure did not surface at the install. It surfaced\n * later, at an unrelated `edit` or mode switch, as `EACCES` on a file the user never made\n * read-only. Every caller of this function is an install or an eject, so every destination is the\n * user's.\n *\n * The owner's write bit is ADDED rather than the mode replaced. A skill may legitimately ship an\n * executable script, and flattening to `644` would break it on the way in — the destination should\n * differ from the source in exactly one respect, which is that its owner can write it.\n *\n * Directories take the same bit for the same reason: a read-only directory refuses a file added\n * beside the copy, which is what an eject-then-edit does next.\n */\nexport async function copy(src: string, dest: string): Promise<void> {\n await fs.copy(src, dest);\n await grantOwnerWrite(dest);\n}\n\nconst OWNER_WRITE = 0o200;\n\nasync function grantOwnerWrite(target: string): Promise<void> {\n const entry = await fs.stat(target);\n await fs.chmod(target, entry.mode | OWNER_WRITE);\n\n if (!entry.isDirectory()) return;\n\n const children = await fs.readdir(target);\n await Promise.all(children.map((child) => grantOwnerWrite(path.join(target, child))));\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\n\n/**\n * The write privilege for the global config pair (`~/.claude-src/config.ts` and\n * its `config-types.ts` sibling).\n *\n * AsyncLocalStorage rather than a module-level boolean: pair writes are async\n * and interleave, so a flag one write clears while another is still in flight\n * revokes a privilege that is still held. The store is scoped to the call tree\n * that opened it, which is exactly the grant being modelled.\n */\nconst gateToken = new AsyncLocalStorage<true>();\n\n/**\n * Thrown when the global pair is written from outside the gate. Names the\n * offending path and the only supported entry point, because every occurrence\n * is a code path that must be moved rather than a user-recoverable condition.\n */\nexport class GlobalPairWriteViolation extends Error {\n constructor(targetPath: string) {\n super(\n `${targetPath} may only be written through config-gate — see src/cli/lib/config-gate/index.ts`,\n );\n this.name = \"GlobalPairWriteViolation\";\n }\n}\n\n/** Runs `fn` holding the pair-write privilege. */\nexport function withGateToken<T>(fn: () => Promise<T>): Promise<T> {\n return gateToken.run(true, fn);\n}\n\n/** True while the current async call tree holds the pair-write privilege. */\nexport function hasGateToken(): boolean {\n return gateToken.getStore() === true;\n}\n\n/** Throws unless the caller holds the pair-write privilege. */\nexport function assertGateToken(targetPath: string): void {\n if (hasGateToken()) return;\n throw new GlobalPairWriteViolation(targetPath);\n}\n","// Logging utility for lib/ modules that don't have access to oclif command context.\n// In oclif commands, prefer using this.log() instead.\n\nlet verboseMode = false;\n\nexport function setVerbose(enabled: boolean): void {\n verboseMode = enabled;\n}\n\nexport function verbose(msg: string): void {\n if (verboseMode) {\n console.log(` ${msg}`);\n }\n}\n\n// Always visible (not gated by verbose mode).\n// Used for user-facing progress output: compilation ticks, summaries, validation results.\nexport function log(msg: string): void {\n console.log(msg);\n}\n\n// --- Startup message buffering ---\n// When buffer mode is enabled (before Ink takes over the terminal), warn() pushes\n// messages into a buffer instead of writing to stderr. The buffer is drained and\n// handed to the wizard, which paints it as a band above the step — stderr is what\n// the wizard's clearTerminal wipes, so a line written there is a line lost.\n\nexport type StartupMessage = {\n level: \"info\" | \"warn\" | \"error\";\n text: string;\n};\n\nlet bufferMode = false;\nlet messageBuffer: StartupMessage[] = [];\n\nexport function enableBuffering(): void {\n bufferMode = true;\n messageBuffer = [];\n}\n\nexport function drainBuffer(): StartupMessage[] {\n const messages = [...messageBuffer];\n messageBuffer = [];\n return messages;\n}\n\nexport function disableBuffering(): void {\n bufferMode = false;\n messageBuffer = [];\n}\n\n// Always visible (not gated by verbose mode).\n// Used for issues the user should know about, like unresolved references.\n//\n// Error/warning message style guide:\n// - Start with a capital letter (restructure if it would capitalize a function name)\n// - End with a period if it's a complete sentence\n// - End without a period if it's a fragment (e.g., \"Skipping 'foo': missing SKILL.md\")\n// - Wrap dynamic values in single quotes: 'value' (not bare or double-quoted)\n// - Do NOT prefix the message with \"Warning:\" — this function adds it automatically\n// - After a colon, use lowercase (e.g., \"Skipping 'foo': invalid frontmatter\")\n// - Use em dash for supplemental info (e.g., \"Missing category — defaulting to 'local'\")\nexport type WarnOptions = {\n /**\n * When true, suppresses this warning in a UNIT run — the gate reads `VITEST` from the\n * environment of the process evaluating it, so it can only ever mean that. Every E2E runner\n * hands the spawned binary `VITEST: undefined`, so an E2E run of the real binary is a test\n * environment in which this warning IS printed. Which runners those are is not a number worth\n * carrying here — it said \"Both\" while there were three, and the third was clearing nothing at\n * all; `src/cli/lib/__tests__/e2e-runner-environment.test.ts` derives the roster and is the\n * only place that count is correct by construction.\n */\n suppressInTest?: boolean;\n};\n\nexport function warn(msg: string, options?: WarnOptions): void {\n if (options?.suppressInTest && process.env.VITEST) {\n return;\n }\n if (bufferMode) {\n messageBuffer.push({ level: \"warn\", text: msg });\n return;\n }\n console.warn(` Warning: ${msg}`);\n}\n","// AUTO-GENERATED from skills source and agent metadata — do not edit manually\n// Run: bun run generate:types\n\n// ── Skill Map (slug → ID) ─────────────────────────────────────\n\nexport const SKILL_MAP = {\n \"ai-planning\": \"meta-planning-ai-planning\",\n \"ai-reviewing\": \"meta-reviewing-ai-reviewing\",\n \"angular-standalone\": \"web-framework-angular-standalone\",\n \"ant-design\": \"web-ui-ant-design\",\n \"anthropic-sdk\": \"ai-provider-anthropic-sdk\",\n \"api-performance\": \"api-performance-api-performance\",\n \"api-planning\": \"meta-planning-api-planning\",\n \"api-reviewing\": \"meta-reviewing-api-reviewing\",\n \"apollo-server\": \"api-graphql-apollo-server\",\n \"app-links\": \"mobile-deep-linking-app-links\",\n appwrite: \"api-baas-appwrite\",\n astro: \"web-meta-framework-astro\",\n \"auth-security\": \"shared-security-auth-security\",\n \"aws-sdk\": \"infra-platform-aws-sdk\",\n \"axiom-pino-sentry\": \"api-observability-axiom-pino-sentry\",\n \"base-ui\": \"web-ui-base-ui\",\n \"better-auth-drizzle-hono\": \"api-auth-better-auth-drizzle-hono\",\n biome: \"shared-tooling-biome\",\n \"ble-nfc\": \"mobile-hardware-ble-nfc\",\n bullmq: \"api-queue-bullmq\",\n \"chakra-ui\": \"web-ui-chakra-ui\",\n changesets: \"shared-tooling-changesets\",\n chroma: \"api-vector-db-chroma\",\n clack: \"cli-prompts-clack\",\n \"claude-vision\": \"ai-provider-claude-vision\",\n clerk: \"api-auth-clerk\",\n \"cli-commander\": \"cli-framework-cli-commander\",\n \"cli-planning\": \"meta-planning-cli-planning\",\n \"cli-reviewing\": \"meta-reviewing-cli-reviewing\",\n \"cloudflare-workers\": \"infra-platform-cloudflare-workers\",\n cockroachdb: \"api-database-cockroachdb\",\n \"cohere-sdk\": \"ai-provider-cohere-sdk\",\n \"component-library\": \"web-tooling-component-library\",\n \"composable-components\": \"meta-design-composable-components\",\n \"css-animations\": \"web-animation-css-animations\",\n cva: \"web-styling-cva\",\n \"cypress-e2e\": \"web-testing-cypress-e2e\",\n d3: \"web-dataviz-d3\",\n \"date-fns\": \"web-utilities-date-fns\",\n \"design-tokens\": \"web-styling-design-tokens\",\n detox: \"mobile-testing-detox\",\n \"dnd-kit\": \"web-dnd-dnd-kit\",\n docker: \"infra-ci-cd-docker\",\n docusaurus: \"web-meta-framework-docusaurus\",\n drizzle: \"api-database-drizzle\",\n eas: \"mobile-deployment-eas\",\n edgedb: \"api-database-edgedb\",\n elasticsearch: \"api-search-elasticsearch\",\n electron: \"desktop-framework-electron\",\n \"electron-forge\": \"desktop-packaging-electron-forge\",\n \"electron-ipc\": \"desktop-ipc-electron\",\n \"electron-multiwindow\": \"desktop-multiwindow-electron\",\n \"electron-security\": \"desktop-security-electron\",\n \"electron-storage\": \"desktop-storage-electron\",\n \"electron-testing\": \"desktop-testing-electron\",\n \"electron-ui\": \"desktop-ui-electron\",\n \"electron-updater\": \"desktop-updates-electron-updater\",\n elevenlabs: \"ai-provider-elevenlabs\",\n elysia: \"api-framework-elysia\",\n \"error-boundaries\": \"web-error-handling-error-boundaries\",\n \"eslint-prettier\": \"shared-tooling-eslint-prettier\",\n expo: \"mobile-framework-expo\",\n \"expo-router\": \"mobile-navigation-expo-router\",\n express: \"api-framework-express\",\n \"expressive-typescript\": \"meta-design-expressive-typescript\",\n fastify: \"api-framework-fastify\",\n \"file-upload-patterns\": \"web-files-file-upload-patterns\",\n firebase: \"api-baas-firebase\",\n \"framer-motion\": \"web-animation-framer-motion\",\n \"gesture-handler\": \"mobile-animation-gesture-handler\",\n \"git-hooks\": \"shared-tooling-git-hooks\",\n \"github-actions\": \"infra-ci-cd-github-actions\",\n \"google-gemini-sdk\": \"ai-provider-google-gemini-sdk\",\n \"graphql-apollo\": \"web-data-fetching-graphql-apollo\",\n \"graphql-urql\": \"web-data-fetching-graphql-urql\",\n \"headless-ui\": \"web-ui-headless-ui\",\n hono: \"api-framework-hono\",\n \"huggingface-inference\": \"ai-infrastructure-huggingface-inference\",\n \"image-handling\": \"web-files-image-handling\",\n \"infra-reviewing\": \"meta-reviewing-infra-reviewing\",\n jotai: \"web-state-jotai\",\n knex: \"api-database-knex\",\n kubernetes: \"infra-containers-kubernetes\",\n langchain: \"ai-orchestration-langchain\",\n langfuse: \"ai-observability-langfuse\",\n leaflet: \"web-maps-leaflet\",\n lexical: \"web-editor-lexical\",\n litellm: \"ai-infrastructure-litellm\",\n llamaindex: \"ai-orchestration-llamaindex\",\n maestro: \"mobile-testing-maestro\",\n mantine: \"web-ui-mantine\",\n mapbox: \"web-maps-mapbox\",\n meilisearch: \"api-search-meilisearch\",\n mercurius: \"api-graphql-mercurius\",\n \"mistral-sdk\": \"ai-provider-mistral-sdk\",\n mmkv: \"mobile-storage-mmkv\",\n mobx: \"web-state-mobx\",\n modal: \"ai-infrastructure-modal\",\n mongodb: \"api-database-mongodb\",\n mongoose: \"api-database-mongoose\",\n msw: \"web-mocks-msw\",\n mui: \"web-ui-mui\",\n mysql: \"api-database-mysql\",\n \"native-js\": \"web-utilities-native-js\",\n nativewind: \"mobile-styling-nativewind\",\n neon: \"api-baas-neon\",\n nestjs: \"api-framework-nestjs\",\n netlify: \"infra-platform-netlify\",\n \"next-intl\": \"web-i18n-next-intl\",\n nextauth: \"api-auth-nextauth\",\n nextjs: \"web-meta-framework-nextjs\",\n \"ngrx-signalstore\": \"web-state-ngrx-signalstore\",\n nuxt: \"web-meta-framework-nuxt\",\n nx: \"shared-monorepo-nx\",\n \"oclif-ink\": \"cli-framework-oclif-ink\",\n \"offline-first\": \"web-pwa-offline-first\",\n ollama: \"ai-infrastructure-ollama\",\n \"openai-sdk\": \"ai-provider-openai-sdk\",\n \"openai-whisper\": \"ai-provider-openai-whisper\",\n openapi: \"api-specs-openapi\",\n payload: \"api-cms-payload\",\n pinecone: \"api-vector-db-pinecone\",\n pinia: \"web-state-pinia\",\n planetscale: \"api-baas-planetscale\",\n \"playwright-e2e\": \"web-testing-playwright-e2e\",\n \"pnpm-workspaces\": \"shared-monorepo-pnpm-workspaces\",\n postgresql: \"api-database-postgresql\",\n \"posthog-analytics\": \"api-analytics-posthog-analytics\",\n \"posthog-flags\": \"api-flags-posthog-flags\",\n prisma: \"api-database-prisma\",\n promptfoo: \"ai-observability-promptfoo\",\n pulumi: \"infra-iac-pulumi\",\n push: \"mobile-notifications-push\",\n qdrant: \"api-vector-db-qdrant\",\n qwik: \"web-meta-framework-qwik\",\n \"radix-ui\": \"web-ui-radix-ui\",\n react: \"web-framework-react\",\n \"react-hook-form\": \"web-forms-react-hook-form\",\n \"react-intl\": \"web-i18n-react-intl\",\n \"react-native\": \"mobile-framework-react-native\",\n \"react-native-paper\": \"mobile-ui-components-react-native-paper\",\n \"react-native-performance\": \"mobile-performance-react-native\",\n \"react-native-security\": \"mobile-security-react-native\",\n \"react-navigation\": \"mobile-navigation-react-navigation\",\n \"react-query\": \"web-server-state-react-query\",\n \"react-router\": \"web-routing-react-router\",\n \"react-testing-library\": \"web-testing-react-testing-library\",\n \"react-three-fiber\": \"web-3d-react-three-fiber\",\n reanimated: \"mobile-animation-reanimated\",\n recharts: \"web-dataviz-recharts\",\n redis: \"api-database-redis\",\n \"redux-toolkit\": \"web-state-redux-toolkit\",\n remix: \"web-meta-framework-remix\",\n replicate: \"ai-infrastructure-replicate\",\n \"research-methodology\": \"meta-methodology-research-methodology\",\n \"resend-react-email\": \"api-email-resend-react-email\",\n \"result-types\": \"web-error-handling-result-types\",\n reviewing: \"meta-reviewing-reviewing\",\n rxjs: \"web-utilities-rxjs\",\n sanity: \"api-cms-sanity\",\n \"scss-modules\": \"web-styling-scss-modules\",\n sequelize: \"api-database-sequelize\",\n \"service-workers\": \"web-pwa-service-workers\",\n \"setup-axiom-pino-sentry\": \"api-observability-setup-axiom-pino-sentry\",\n \"setup-env\": \"infra-config-setup-env\",\n \"setup-posthog\": \"api-analytics-setup-posthog\",\n \"setup-resend\": \"api-email-setup-resend\",\n \"shadcn-ui\": \"web-ui-shadcn-ui\",\n skia: \"mobile-animation-skia\",\n \"socket-io\": \"web-realtime-socket-io\",\n solidjs: \"web-framework-solidjs\",\n \"sqlite-powersync\": \"mobile-storage-sqlite-powersync\",\n sse: \"web-realtime-sse\",\n sst: \"infra-iac-sst\",\n \"stack-detect\": \"meta-config-stack-detect\",\n storybook: \"web-tooling-storybook\",\n strapi: \"api-cms-strapi\",\n strategies: \"api-caching-strategies\",\n stripe: \"api-commerce-stripe\",\n supabase: \"api-baas-supabase\",\n surrealdb: \"api-database-surrealdb\",\n svelte: \"web-framework-svelte\",\n sveltekit: \"web-meta-framework-sveltekit\",\n swr: \"web-data-fetching-swr\",\n tailwind: \"web-styling-tailwind\",\n tamagui: \"mobile-ui-components-tamagui\",\n \"tanstack-form\": \"web-forms-tanstack-form\",\n \"tanstack-router\": \"web-routing-tanstack-router\",\n \"tanstack-table\": \"web-ui-tanstack-table\",\n tasks: \"mobile-background-tasks\",\n tauri: \"desktop-framework-tauri\",\n \"tauri-backend\": \"desktop-backend-tauri\",\n \"tauri-bundling\": \"desktop-packaging-tauri\",\n \"tauri-mobile\": \"desktop-mobile-tauri\",\n \"tauri-multiwindow\": \"desktop-multiwindow-tauri\",\n \"tauri-plugins\": \"desktop-plugins-tauri\",\n \"tauri-security\": \"desktop-security-tauri\",\n terraform: \"infra-iac-terraform\",\n theming: \"web-styling-theming\",\n tiptap: \"web-editor-tiptap\",\n \"together-ai\": \"ai-infrastructure-together-ai\",\n \"tool-use-patterns\": \"ai-patterns-tool-use-patterns\",\n trpc: \"web-data-fetching-trpc\",\n turborepo: \"shared-monorepo-turborepo\",\n \"turborepo-ci\": \"infra-ci-cd-turborepo-ci\",\n turso: \"api-baas-turso\",\n typeorm: \"api-database-typeorm\",\n \"typescript-config\": \"shared-tooling-typescript-config\",\n unistyles: \"mobile-styling-unistyles\",\n upstash: \"api-database-upstash\",\n \"vee-validate\": \"web-forms-vee-validate\",\n vercel: \"infra-platform-vercel\",\n \"vercel-ai-sdk\": \"ai-orchestration-vercel-ai-sdk\",\n \"vercel-kv\": \"api-database-vercel-kv\",\n \"vercel-postgres\": \"api-database-vercel-postgres\",\n \"view-transitions\": \"web-animation-view-transitions\",\n \"vision-camera\": \"mobile-camera-vision-camera\",\n \"visual-regression\": \"web-testing-visual-regression\",\n vite: \"web-tooling-vite\",\n vitepress: \"web-meta-framework-vitepress\",\n vitest: \"web-testing-vitest\",\n \"vue-composition-api\": \"web-framework-vue-composition-api\",\n \"vue-i18n\": \"web-i18n-vue-i18n\",\n \"vue-test-utils\": \"web-testing-vue-test-utils\",\n vuetify: \"web-ui-vuetify\",\n vueuse: \"web-utilities-vueuse\",\n watermelondb: \"mobile-storage-watermelondb\",\n weaviate: \"api-vector-db-weaviate\",\n \"web-accessibility\": \"web-accessibility-web-accessibility\",\n \"web-performance\": \"web-performance-web-performance\",\n \"web-planning\": \"meta-planning-web-planning\",\n \"web-reviewing\": \"meta-reviewing-web-reviewing\",\n webhooks: \"api-messaging-webhooks\",\n websockets: \"web-realtime-websockets\",\n xquik: \"api-search-xquik\",\n yoga: \"api-graphql-yoga\",\n \"zod-validation\": \"web-forms-zod-validation\",\n zustand: \"web-state-zustand\",\n} as const;\n\nexport type SkillSlug = keyof typeof SKILL_MAP;\nexport type SkillId = (typeof SKILL_MAP)[SkillSlug];\n\n// Derived arrays for Zod enum compatibility\n// (z.enum() requires a readonly tuple, not Object.keys/values)\nexport const SKILL_SLUGS = [\n \"ai-planning\",\n \"ai-reviewing\",\n \"angular-standalone\",\n \"ant-design\",\n \"anthropic-sdk\",\n \"api-performance\",\n \"api-planning\",\n \"api-reviewing\",\n \"apollo-server\",\n \"app-links\",\n \"appwrite\",\n \"astro\",\n \"auth-security\",\n \"aws-sdk\",\n \"axiom-pino-sentry\",\n \"base-ui\",\n \"better-auth-drizzle-hono\",\n \"biome\",\n \"ble-nfc\",\n \"bullmq\",\n \"chakra-ui\",\n \"changesets\",\n \"chroma\",\n \"clack\",\n \"claude-vision\",\n \"clerk\",\n \"cli-commander\",\n \"cli-planning\",\n \"cli-reviewing\",\n \"cloudflare-workers\",\n \"cockroachdb\",\n \"cohere-sdk\",\n \"component-library\",\n \"composable-components\",\n \"css-animations\",\n \"cva\",\n \"cypress-e2e\",\n \"d3\",\n \"date-fns\",\n \"design-tokens\",\n \"detox\",\n \"dnd-kit\",\n \"docker\",\n \"docusaurus\",\n \"drizzle\",\n \"eas\",\n \"edgedb\",\n \"elasticsearch\",\n \"electron\",\n \"electron-forge\",\n \"electron-ipc\",\n \"electron-multiwindow\",\n \"electron-security\",\n \"electron-storage\",\n \"electron-testing\",\n \"electron-ui\",\n \"electron-updater\",\n \"elevenlabs\",\n \"elysia\",\n \"error-boundaries\",\n \"eslint-prettier\",\n \"expo\",\n \"expo-router\",\n \"express\",\n \"expressive-typescript\",\n \"fastify\",\n \"file-upload-patterns\",\n \"firebase\",\n \"framer-motion\",\n \"gesture-handler\",\n \"git-hooks\",\n \"github-actions\",\n \"google-gemini-sdk\",\n \"graphql-apollo\",\n \"graphql-urql\",\n \"headless-ui\",\n \"hono\",\n \"huggingface-inference\",\n \"image-handling\",\n \"infra-reviewing\",\n \"jotai\",\n \"knex\",\n \"kubernetes\",\n \"langchain\",\n \"langfuse\",\n \"leaflet\",\n \"lexical\",\n \"litellm\",\n \"llamaindex\",\n \"maestro\",\n \"mantine\",\n \"mapbox\",\n \"meilisearch\",\n \"mercurius\",\n \"mistral-sdk\",\n \"mmkv\",\n \"mobx\",\n \"modal\",\n \"mongodb\",\n \"mongoose\",\n \"msw\",\n \"mui\",\n \"mysql\",\n \"native-js\",\n \"nativewind\",\n \"neon\",\n \"nestjs\",\n \"netlify\",\n \"next-intl\",\n \"nextauth\",\n \"nextjs\",\n \"ngrx-signalstore\",\n \"nuxt\",\n \"nx\",\n \"oclif-ink\",\n \"offline-first\",\n \"ollama\",\n \"openai-sdk\",\n \"openai-whisper\",\n \"openapi\",\n \"payload\",\n \"pinecone\",\n \"pinia\",\n \"planetscale\",\n \"playwright-e2e\",\n \"pnpm-workspaces\",\n \"postgresql\",\n \"posthog-analytics\",\n \"posthog-flags\",\n \"prisma\",\n \"promptfoo\",\n \"pulumi\",\n \"push\",\n \"qdrant\",\n \"qwik\",\n \"radix-ui\",\n \"react\",\n \"react-hook-form\",\n \"react-intl\",\n \"react-native\",\n \"react-native-paper\",\n \"react-native-performance\",\n \"react-native-security\",\n \"react-navigation\",\n \"react-query\",\n \"react-router\",\n \"react-testing-library\",\n \"react-three-fiber\",\n \"reanimated\",\n \"recharts\",\n \"redis\",\n \"redux-toolkit\",\n \"remix\",\n \"replicate\",\n \"research-methodology\",\n \"resend-react-email\",\n \"result-types\",\n \"reviewing\",\n \"rxjs\",\n \"sanity\",\n \"scss-modules\",\n \"sequelize\",\n \"service-workers\",\n \"setup-axiom-pino-sentry\",\n \"setup-env\",\n \"setup-posthog\",\n \"setup-resend\",\n \"shadcn-ui\",\n \"skia\",\n \"socket-io\",\n \"solidjs\",\n \"sqlite-powersync\",\n \"sse\",\n \"sst\",\n \"stack-detect\",\n \"storybook\",\n \"strapi\",\n \"strategies\",\n \"stripe\",\n \"supabase\",\n \"surrealdb\",\n \"svelte\",\n \"sveltekit\",\n \"swr\",\n \"tailwind\",\n \"tamagui\",\n \"tanstack-form\",\n \"tanstack-router\",\n \"tanstack-table\",\n \"tasks\",\n \"tauri\",\n \"tauri-backend\",\n \"tauri-bundling\",\n \"tauri-mobile\",\n \"tauri-multiwindow\",\n \"tauri-plugins\",\n \"tauri-security\",\n \"terraform\",\n \"theming\",\n \"tiptap\",\n \"together-ai\",\n \"tool-use-patterns\",\n \"trpc\",\n \"turborepo\",\n \"turborepo-ci\",\n \"turso\",\n \"typeorm\",\n \"typescript-config\",\n \"unistyles\",\n \"upstash\",\n \"vee-validate\",\n \"vercel\",\n \"vercel-ai-sdk\",\n \"vercel-kv\",\n \"vercel-postgres\",\n \"view-transitions\",\n \"vision-camera\",\n \"visual-regression\",\n \"vite\",\n \"vitepress\",\n \"vitest\",\n \"vue-composition-api\",\n \"vue-i18n\",\n \"vue-test-utils\",\n \"vuetify\",\n \"vueuse\",\n \"watermelondb\",\n \"weaviate\",\n \"web-accessibility\",\n \"web-performance\",\n \"web-planning\",\n \"web-reviewing\",\n \"webhooks\",\n \"websockets\",\n \"xquik\",\n \"yoga\",\n \"zod-validation\",\n \"zustand\",\n] as const satisfies readonly SkillSlug[];\n\nexport const SKILL_IDS = [\n \"ai-infrastructure-huggingface-inference\",\n \"ai-infrastructure-litellm\",\n \"ai-infrastructure-modal\",\n \"ai-infrastructure-ollama\",\n \"ai-infrastructure-replicate\",\n \"ai-infrastructure-together-ai\",\n \"ai-observability-langfuse\",\n \"ai-observability-promptfoo\",\n \"ai-orchestration-langchain\",\n \"ai-orchestration-llamaindex\",\n \"ai-orchestration-vercel-ai-sdk\",\n \"ai-patterns-tool-use-patterns\",\n \"ai-provider-anthropic-sdk\",\n \"ai-provider-claude-vision\",\n \"ai-provider-cohere-sdk\",\n \"ai-provider-elevenlabs\",\n \"ai-provider-google-gemini-sdk\",\n \"ai-provider-mistral-sdk\",\n \"ai-provider-openai-sdk\",\n \"ai-provider-openai-whisper\",\n \"api-analytics-posthog-analytics\",\n \"api-analytics-setup-posthog\",\n \"api-auth-better-auth-drizzle-hono\",\n \"api-auth-clerk\",\n \"api-auth-nextauth\",\n \"api-baas-appwrite\",\n \"api-baas-firebase\",\n \"api-baas-neon\",\n \"api-baas-planetscale\",\n \"api-baas-supabase\",\n \"api-baas-turso\",\n \"api-caching-strategies\",\n \"api-cms-payload\",\n \"api-cms-sanity\",\n \"api-cms-strapi\",\n \"api-commerce-stripe\",\n \"api-database-cockroachdb\",\n \"api-database-drizzle\",\n \"api-database-edgedb\",\n \"api-database-knex\",\n \"api-database-mongodb\",\n \"api-database-mongoose\",\n \"api-database-mysql\",\n \"api-database-postgresql\",\n \"api-database-prisma\",\n \"api-database-redis\",\n \"api-database-sequelize\",\n \"api-database-surrealdb\",\n \"api-database-typeorm\",\n \"api-database-upstash\",\n \"api-database-vercel-kv\",\n \"api-database-vercel-postgres\",\n \"api-email-resend-react-email\",\n \"api-email-setup-resend\",\n \"api-flags-posthog-flags\",\n \"api-framework-elysia\",\n \"api-framework-express\",\n \"api-framework-fastify\",\n \"api-framework-hono\",\n \"api-framework-nestjs\",\n \"api-graphql-apollo-server\",\n \"api-graphql-mercurius\",\n \"api-graphql-yoga\",\n \"api-messaging-webhooks\",\n \"api-observability-axiom-pino-sentry\",\n \"api-observability-setup-axiom-pino-sentry\",\n \"api-performance-api-performance\",\n \"api-queue-bullmq\",\n \"api-search-elasticsearch\",\n \"api-search-meilisearch\",\n \"api-search-xquik\",\n \"api-specs-openapi\",\n \"api-vector-db-chroma\",\n \"api-vector-db-pinecone\",\n \"api-vector-db-qdrant\",\n \"api-vector-db-weaviate\",\n \"cli-framework-cli-commander\",\n \"cli-framework-oclif-ink\",\n \"cli-prompts-clack\",\n \"desktop-backend-tauri\",\n \"desktop-framework-electron\",\n \"desktop-framework-tauri\",\n \"desktop-ipc-electron\",\n \"desktop-mobile-tauri\",\n \"desktop-multiwindow-electron\",\n \"desktop-multiwindow-tauri\",\n \"desktop-packaging-electron-forge\",\n \"desktop-packaging-tauri\",\n \"desktop-plugins-tauri\",\n \"desktop-security-electron\",\n \"desktop-security-tauri\",\n \"desktop-storage-electron\",\n \"desktop-testing-electron\",\n \"desktop-ui-electron\",\n \"desktop-updates-electron-updater\",\n \"infra-ci-cd-docker\",\n \"infra-ci-cd-github-actions\",\n \"infra-ci-cd-turborepo-ci\",\n \"infra-config-setup-env\",\n \"infra-containers-kubernetes\",\n \"infra-iac-pulumi\",\n \"infra-iac-sst\",\n \"infra-iac-terraform\",\n \"infra-platform-aws-sdk\",\n \"infra-platform-cloudflare-workers\",\n \"infra-platform-netlify\",\n \"infra-platform-vercel\",\n \"meta-config-stack-detect\",\n \"meta-design-composable-components\",\n \"meta-design-expressive-typescript\",\n \"meta-methodology-research-methodology\",\n \"meta-planning-ai-planning\",\n \"meta-planning-api-planning\",\n \"meta-planning-cli-planning\",\n \"meta-planning-web-planning\",\n \"meta-reviewing-ai-reviewing\",\n \"meta-reviewing-api-reviewing\",\n \"meta-reviewing-cli-reviewing\",\n \"meta-reviewing-infra-reviewing\",\n \"meta-reviewing-reviewing\",\n \"meta-reviewing-web-reviewing\",\n \"mobile-animation-gesture-handler\",\n \"mobile-animation-reanimated\",\n \"mobile-animation-skia\",\n \"mobile-background-tasks\",\n \"mobile-camera-vision-camera\",\n \"mobile-deep-linking-app-links\",\n \"mobile-deployment-eas\",\n \"mobile-framework-expo\",\n \"mobile-framework-react-native\",\n \"mobile-hardware-ble-nfc\",\n \"mobile-navigation-expo-router\",\n \"mobile-navigation-react-navigation\",\n \"mobile-notifications-push\",\n \"mobile-performance-react-native\",\n \"mobile-security-react-native\",\n \"mobile-storage-mmkv\",\n \"mobile-storage-sqlite-powersync\",\n \"mobile-storage-watermelondb\",\n \"mobile-styling-nativewind\",\n \"mobile-styling-unistyles\",\n \"mobile-testing-detox\",\n \"mobile-testing-maestro\",\n \"mobile-ui-components-react-native-paper\",\n \"mobile-ui-components-tamagui\",\n \"shared-monorepo-nx\",\n \"shared-monorepo-pnpm-workspaces\",\n \"shared-monorepo-turborepo\",\n \"shared-security-auth-security\",\n \"shared-tooling-biome\",\n \"shared-tooling-changesets\",\n \"shared-tooling-eslint-prettier\",\n \"shared-tooling-git-hooks\",\n \"shared-tooling-typescript-config\",\n \"web-3d-react-three-fiber\",\n \"web-accessibility-web-accessibility\",\n \"web-animation-css-animations\",\n \"web-animation-framer-motion\",\n \"web-animation-view-transitions\",\n \"web-data-fetching-graphql-apollo\",\n \"web-data-fetching-graphql-urql\",\n \"web-data-fetching-swr\",\n \"web-data-fetching-trpc\",\n \"web-dataviz-d3\",\n \"web-dataviz-recharts\",\n \"web-dnd-dnd-kit\",\n \"web-editor-lexical\",\n \"web-editor-tiptap\",\n \"web-error-handling-error-boundaries\",\n \"web-error-handling-result-types\",\n \"web-files-file-upload-patterns\",\n \"web-files-image-handling\",\n \"web-forms-react-hook-form\",\n \"web-forms-tanstack-form\",\n \"web-forms-vee-validate\",\n \"web-forms-zod-validation\",\n \"web-framework-angular-standalone\",\n \"web-framework-react\",\n \"web-framework-solidjs\",\n \"web-framework-svelte\",\n \"web-framework-vue-composition-api\",\n \"web-i18n-next-intl\",\n \"web-i18n-react-intl\",\n \"web-i18n-vue-i18n\",\n \"web-maps-leaflet\",\n \"web-maps-mapbox\",\n \"web-meta-framework-astro\",\n \"web-meta-framework-docusaurus\",\n \"web-meta-framework-nextjs\",\n \"web-meta-framework-nuxt\",\n \"web-meta-framework-qwik\",\n \"web-meta-framework-remix\",\n \"web-meta-framework-sveltekit\",\n \"web-meta-framework-vitepress\",\n \"web-mocks-msw\",\n \"web-performance-web-performance\",\n \"web-pwa-offline-first\",\n \"web-pwa-service-workers\",\n \"web-realtime-socket-io\",\n \"web-realtime-sse\",\n \"web-realtime-websockets\",\n \"web-routing-react-router\",\n \"web-routing-tanstack-router\",\n \"web-server-state-react-query\",\n \"web-state-jotai\",\n \"web-state-mobx\",\n \"web-state-ngrx-signalstore\",\n \"web-state-pinia\",\n \"web-state-redux-toolkit\",\n \"web-state-zustand\",\n \"web-styling-cva\",\n \"web-styling-design-tokens\",\n \"web-styling-scss-modules\",\n \"web-styling-tailwind\",\n \"web-styling-theming\",\n \"web-testing-cypress-e2e\",\n \"web-testing-playwright-e2e\",\n \"web-testing-react-testing-library\",\n \"web-testing-visual-regression\",\n \"web-testing-vitest\",\n \"web-testing-vue-test-utils\",\n \"web-tooling-component-library\",\n \"web-tooling-storybook\",\n \"web-tooling-vite\",\n \"web-ui-ant-design\",\n \"web-ui-base-ui\",\n \"web-ui-chakra-ui\",\n \"web-ui-headless-ui\",\n \"web-ui-mantine\",\n \"web-ui-mui\",\n \"web-ui-radix-ui\",\n \"web-ui-shadcn-ui\",\n \"web-ui-tanstack-table\",\n \"web-ui-vuetify\",\n \"web-utilities-date-fns\",\n \"web-utilities-native-js\",\n \"web-utilities-rxjs\",\n \"web-utilities-vueuse\",\n] as const satisfies readonly SkillId[];\n\n// ── Categories ─────────────────────────────────────────────────\n\nexport const CATEGORIES = [\n \"ai-infrastructure\",\n \"ai-observability\",\n \"ai-orchestration\",\n \"ai-patterns\",\n \"ai-provider\",\n \"api-analytics\",\n \"api-api\",\n \"api-auth\",\n \"api-baas\",\n \"api-caching\",\n \"api-cms\",\n \"api-commerce\",\n \"api-db-host\",\n \"api-document\",\n \"api-email\",\n \"api-graphql\",\n \"api-kv\",\n \"api-messaging\",\n \"api-observability\",\n \"api-orm\",\n \"api-performance\",\n \"api-queue\",\n \"api-search\",\n \"api-specs\",\n \"api-sql-engine\",\n \"api-vector-db\",\n \"cli-framework\",\n \"cli-prompts\",\n \"desktop-backend\",\n \"desktop-framework\",\n \"desktop-ipc\",\n \"desktop-mobile\",\n \"desktop-multiwindow\",\n \"desktop-packaging\",\n \"desktop-plugins\",\n \"desktop-security\",\n \"desktop-storage\",\n \"desktop-testing\",\n \"desktop-ui\",\n \"desktop-updates\",\n \"infra-ci-cd\",\n \"infra-config\",\n \"infra-containers\",\n \"infra-iac\",\n \"infra-platform\",\n \"meta-design\",\n \"meta-methodology\",\n \"meta-planning\",\n \"meta-reviewing\",\n \"mobile-animation\",\n \"mobile-background\",\n \"mobile-camera\",\n \"mobile-deep-linking\",\n \"mobile-deployment\",\n \"mobile-framework\",\n \"mobile-hardware\",\n \"mobile-navigation\",\n \"mobile-notifications\",\n \"mobile-performance\",\n \"mobile-security\",\n \"mobile-storage\",\n \"mobile-styling\",\n \"mobile-testing\",\n \"mobile-ui-components\",\n \"shared-lint\",\n \"shared-monorepo\",\n \"shared-security\",\n \"shared-task-runner\",\n \"shared-tooling\",\n \"web-3d\",\n \"web-accessibility\",\n \"web-animation\",\n \"web-client-state\",\n \"web-dataviz\",\n \"web-dnd\",\n \"web-docs\",\n \"web-e2e\",\n \"web-editor\",\n \"web-error-handling\",\n \"web-file-upload\",\n \"web-files\",\n \"web-form-library\",\n \"web-forms\",\n \"web-framework\",\n \"web-graphql-client\",\n \"web-i18n\",\n \"web-maps\",\n \"web-meta-framework\",\n \"web-mocking\",\n \"web-performance\",\n \"web-pwa\",\n \"web-realtime\",\n \"web-routing\",\n \"web-rpc\",\n \"web-server-state\",\n \"web-streaming\",\n \"web-styling\",\n \"web-testing\",\n \"web-tooling\",\n \"web-ui-components\",\n \"web-ui-kit\",\n \"web-utilities\",\n] as const;\n\nexport type Category = (typeof CATEGORIES)[number];\n\n// ── Domains ────────────────────────────────────────────────────\n\nexport const DOMAINS = [\n \"ai\",\n \"api\",\n \"cli\",\n \"desktop\",\n \"infra\",\n \"meta\",\n \"mobile\",\n \"shared\",\n \"web\",\n] as const;\n\nexport type Domain = (typeof DOMAINS)[number];\n\n// ── Agent Names ────────────────────────────────────────────────\n\nexport const AGENT_NAMES = [\n \"agent-summoner\",\n \"ai-developer\",\n \"ai-researcher\",\n \"ai-tester\",\n \"api-developer\",\n \"api-researcher\",\n \"api-tester\",\n \"cli-developer\",\n \"cli-researcher\",\n \"cli-tester\",\n \"codex-keeper\",\n \"convention-keeper\",\n \"pm\",\n \"reviewer\",\n \"skill-summoner\",\n \"web-developer\",\n \"web-researcher\",\n \"web-tester\",\n] as const;\n\nexport type AgentName = (typeof AGENT_NAMES)[number];\n","import {\n CATEGORIES,\n DOMAINS,\n AGENT_NAMES,\n SKILL_IDS,\n SKILL_SLUGS,\n} from \"../types/generated/source-types\";\nimport type {\n Category,\n Domain,\n AgentName,\n SkillId,\n SkillSlug,\n} from \"../types/generated/source-types\";\nimport type { CategoryPath, SkillAssignment } from \"../types/skills\";\nimport { LOCAL_PSEUDO_CATEGORY } from \"../consts\";\n\n/** Narrows unknown parse output to a plain object record (rejects arrays and primitives). */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Runtime check that a string is a valid Category value from the generated union */\nexport function isCategory(value: string): value is Category {\n return (CATEGORIES as readonly string[]).includes(value);\n}\n\n/** Runtime check that a string is a valid Domain value from the generated union */\nexport function isDomain(value: string): value is Domain {\n return (DOMAINS as readonly string[]).includes(value);\n}\n\n/** Runtime check that a string is a valid AgentName value from the generated union */\nexport function isAgentName(value: string): value is AgentName {\n return (AGENT_NAMES as readonly string[]).includes(value);\n}\n\n/** Runtime check that a string is a valid CategoryPath (Category | \"local\") */\nexport function isCategoryPath(value: string): value is CategoryPath {\n return value === LOCAL_PSEUDO_CATEGORY || isCategory(value);\n}\n\n/** Runtime check that a string is a valid SkillId from the generated union */\nexport function isSkillId(value: string): value is SkillId {\n return (SKILL_IDS as readonly string[]).includes(value);\n}\n\n/** Runtime check that a string is a valid SkillSlug from the generated union */\nexport function isSkillSlug(value: string): value is SkillSlug {\n return (SKILL_SLUGS as readonly string[]).includes(value);\n}\n\n/**\n * Structural check for a SkillAssignment object (`{ id, preloaded? }`).\n * The id's SkillId-ness is structural, not union-checked: assignments flow from\n * runtime sources whose skills may not be in the generated union.\n */\nexport function isSkillAssignment(value: unknown): value is SkillAssignment {\n if (typeof value !== \"object\" || value === null) return false;\n // Boundary cast: probing an unknown object's field inside the guard\n return typeof (value as { id?: unknown }).id === \"string\";\n}\n","import os from \"os\";\nimport path from \"path\";\nimport { z } from \"zod\";\nimport { fileExists, readFileOptional } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport {\n DEFAULT_BRANDING,\n GITHUB_SOURCE,\n PUBLIC_CATALOGUE_PACKAGE,\n STANDARD_FILES,\n} from \"../../consts\";\nimport { configUnreadableError } from \"../../utils/messages\";\nimport { projectSourceConfigSchema } from \"../schemas\";\nimport type { ProjectConfig, SourceEntry } from \"../../types\";\nimport { ConfigDefaultExportError, ConfigSchemaError, loadConfig } from \"./config-loader\";\nimport { getProjectConfigPath } from \"../installation/install-base-dir\";\nimport { isHomeDirectory } from \"../installation/is-home-directory\";\n\nexport const DEFAULT_SOURCE = `${GITHUB_SOURCE.GITHUB_PREFIX}agents-inc/skills`;\nexport const SOURCE_ENV_VAR = \"CC_MARKETPLACE\";\n\n// Re-export types that moved to src/cli/types/config.ts for backward compatibility\nexport type { SourceEntry, BrandingConfig } from \"../../types/config\";\n\n// getProjectConfigPath lives in install-base-dir.ts (a neutral leaf) to avoid an\n// import cycle; re-exported here for existing importers of this module.\nexport { getProjectConfigPath };\n\nexport type ResolvedConfig = {\n source: string;\n sourceOrigin: \"flag\" | \"env\" | \"project\" | \"global\" | \"default\";\n marketplace?: string;\n};\n\n/**\n * Who is asking for a marketplace, and therefore whether this run may CHOOSE one.\n *\n * Choosing is an install-time decision (owner ruling 2026-08-09): `--marketplace` is\n * `init`'s flag and nobody else's, and {@link SOURCE_ENV_VAR} is the same choice made\n * without typing it — so the environment rung is read for `init` and for nothing else.\n * Every later command asks as `\"stored\"` and gets what the install recorded: the\n * project config, then the global one, then {@link DEFAULT_SOURCE}.\n *\n * A `\"stored\"` caller may still NAME a marketplace it is reading for its own sake —\n * `doctor` validating a marketplace repository points the loader at a path — which is why\n * the flag is not tied to the caller. What `init` alone gets is the ambient environment.\n */\nexport type SourceCaller = \"init\" | \"stored\";\n\nexport type ResolveSourceRequest = {\n caller: SourceCaller;\n /** The marketplace this run named, where it named one. */\n flag?: string | undefined;\n /** The project whose `config.ts` is the first stored rung. */\n projectDir?: string | undefined;\n};\n\n/**\n * Reads the settings config at `dir`, or answers `null` when there is none to read.\n *\n * **A file that EXISTS and cannot be loaded is raised, never reported as absence** (owner ruling\n * 2026-08-20). `resolveSource` reads the return value alone, so a swallowed failure was\n * indistinguishable from a config that is not there: the run walked past this rung to\n * {@link DEFAULT_SOURCE} and installed from a marketplace nobody named, while the config naming a\n * private one sat unread on disk. All three ways a config can fail are on the loud side of that\n * line now — a shape the schema refused, a module whose exports are all named, and a file that\n * could not be evaluated at all, which was the one still reported as `null`.\n *\n * A MISSING file keeps its `null`, and that is the whole of what `null` means here: the legitimate\n * state `init` exists for, and the state `edit` reports as \"no installation\".\n *\n * Every call site chose a posture and states it where it stands. All but one ABORT: the marketplace\n * a run installs from is not a thing to guess at, and the two sites that read this file to locate a\n * marketplace's own skills or agent partials would otherwise walk a tree it says is elsewhere. The\n * exception is `validateRegisteredSources`, which DEGRADES — a command whose job is naming what is\n * wrong here has to survive the thing it is naming, so `doctor`'s `safeCheck` turns the raise into\n * a failed row and its `readsConfig: true` rows stand down before reaching here at all. Two further\n * sites are unreachable rather than chosen: `mergeWithExistingConfig` loads the full config first,\n * and `ensureMinimalConfig` reads only where the file is absent.\n */\nasync function loadSourceConfig(\n dir: string,\n scope: \"project\" | \"global\",\n): Promise<Partial<ProjectConfig> | null> {\n const scopeLabel = scope === \"project\" ? \"Project\" : \"Global\";\n const configPath = getProjectConfigPath(dir);\n\n if (!(await fileExists(configPath))) {\n verbose(`${scopeLabel} config not found at ${configPath}`);\n return null;\n }\n\n const data = await readSourceConfigOrRefuse(configPath);\n if (!data) return null;\n\n verbose(`Loaded ${scope} config from ${dir}`);\n return data;\n}\n\n/**\n * The config at `configPath`, or `null` when it evaluated and declared nothing.\n *\n * Every way of failing raises. Split out from {@link loadSourceConfig} so that function's own body\n * reads as the two states it answers — no file, or a config — with the third state, a file that\n * will not load, named once here rather than assembled from a `let` and a `try`.\n */\nasync function readSourceConfigOrRefuse(\n configPath: string,\n): Promise<Partial<ProjectConfig> | null> {\n try {\n return await loadConfig(configPath, projectSourceConfigSchema);\n } catch (error) {\n if (describesItsOwnFault(error)) throw error;\n throw unreadableSourceConfig(error);\n }\n}\n\n/**\n * Whether a load failure already names the field or the export at fault, and so is handed on as\n * itself rather than re-worded.\n *\n * The two it admits fault a LINE of a file the user still owns and can go and correct. Everything\n * else says only that the file would not evaluate, which is what {@link unreadableSourceConfig}\n * exists to turn into a way out.\n */\nfunction describesItsOwnFault(error: unknown): boolean {\n return error instanceof ConfigSchemaError || error instanceof ConfigDefaultExportError;\n}\n\n/**\n * The refusal for a config that exists and cannot be evaluated.\n *\n * `loadConfig` already names the file and the parser's own reason — `Failed to load config from\n * '<path>': ParseError: Missing semicolon` — so the cause is handed straight to\n * {@link configUnreadableError} rather than restated. That builder is what `BaseCommand`'s\n * `ensureConfigReadable` prints for the OTHER loader of this very file, so both readers refuse it\n * in one vocabulary and offer the one route that clears it: `uninstall` still works on a config it\n * cannot read.\n */\nfunction unreadableSourceConfig(cause: unknown): Error {\n return new Error(configUnreadableError(getErrorMessage(cause)), { cause });\n}\n\n/**\n * Load source config from a directory's own `.claude-src/config.ts`.\n *\n * The scope it announces is derived, not assumed: at the home root the file this reads\n * IS the global config, and a caller asking a project question there — `doctor` deciding\n * whether the cwd is a source repository — must not be told a project config was found\n * where none exists.\n */\nexport async function loadProjectSourceConfig(\n projectDir: string,\n): Promise<Partial<ProjectConfig> | null> {\n return loadSourceConfig(projectDir, isHomeDirectory(projectDir) ? \"global\" : \"project\");\n}\n\n/** Load source config from the global home directory (~/.claude-src/config.ts). */\nexport async function loadGlobalSourceConfig(): Promise<Partial<ProjectConfig> | null> {\n return loadSourceConfig(os.homedir(), \"global\");\n}\n\n/** The effective source config plus which scope it was actually loaded from. */\ntype EffectiveSourceConfig = {\n config: Partial<ProjectConfig>;\n origin: \"project\" | \"global\";\n};\n\nasync function loadEffectiveSourceConfig(\n projectDir?: string,\n): Promise<EffectiveSourceConfig | null> {\n const projectConfig = await loadOwnProjectSourceConfig(projectDir);\n if (projectConfig) return { config: projectConfig, origin: \"project\" };\n\n const globalConfig = await loadGlobalSourceConfig();\n if (globalConfig) return { config: globalConfig, origin: \"global\" };\n\n return null;\n}\n\n/**\n * A project's OWN source config, and nothing at the home root.\n *\n * `~/.claude-src/config.ts` is the global config, so reading it as a project's would label\n * one file both things at once: `compile` naming `Marketplace: project` beside\n * `Compiling global agents...`, `edit` announcing `(project)` while refusing scope toggles\n * as a global context. The axis is which FILE the settings were read from — never what\n * scope the skill and agent entries inside it carry.\n */\nasync function loadOwnProjectSourceConfig(\n projectDir: string | undefined,\n): Promise<Partial<ProjectConfig> | null> {\n if (projectDir === undefined || isHomeDirectory(projectDir)) return null;\n return loadProjectSourceConfig(projectDir);\n}\n\n/**\n * Precedence: flag > env > project > global > default, with the first two rungs\n * reachable by `init` alone — see {@link SourceCaller}.\n */\nexport async function resolveSource(request: ResolveSourceRequest): Promise<ResolvedConfig> {\n const { caller, flag, projectDir } = request;\n const effective = await loadEffectiveSourceConfig(projectDir);\n // The stored NAME becomes this result's `marketplace` — the ref it was read beside becomes the\n // `source`. Every return below carries the same name, present only when the config named one.\n const marketplaceName = effective?.config.marketplaceName;\n const marketplaceLabel = marketplaceName !== undefined && { marketplace: marketplaceName };\n\n if (flag !== undefined) {\n assertNamedSourceUsable(flag);\n verbose(`Marketplace named by this run: ${flag}`);\n return { source: flag, sourceOrigin: \"flag\", ...marketplaceLabel };\n }\n\n const envSource = caller === \"init\" ? readEnvSource() : undefined;\n if (envSource !== undefined) {\n return { source: envSource, sourceOrigin: \"env\", ...marketplaceLabel };\n }\n\n if (effective?.config.marketplace) {\n verbose(`Marketplace from ${effective.origin} config: ${effective.config.marketplace}`);\n return {\n source: effective.config.marketplace,\n sourceOrigin: effective.origin,\n ...marketplaceLabel,\n };\n }\n\n verbose(`Using default marketplace: ${DEFAULT_SOURCE}`);\n return { source: DEFAULT_SOURCE, sourceOrigin: \"default\", ...marketplaceLabel };\n}\n\n/**\n * How a marketplace this run NAMED is referred to back to whoever named it.\n *\n * Origin-neutral on purpose: `--marketplace` is `init`'s flag and nobody else's, while a\n * `\"stored\"` caller may still name a marketplace it is reading for its own sake — `doctor`\n * points the loader at a marketplace repository. Naming the flag in a sentence that caller\n * reads blames an option it never passed.\n */\nconst NAMED_SOURCE_LABEL = \"The marketplace\";\n\n/**\n * Refuses a named marketplace that cannot be one. Raised rather than warned: somebody named\n * this, so falling through to another would install from a place they did not name.\n */\nfunction assertNamedSourceUsable(flag: string): void {\n if (flag.trim() === \"\") {\n throw new Error(\n `${NAMED_SOURCE_LABEL} cannot be empty. Provide a valid marketplace: a local directory path or a git repository URL (e.g., './my-skills' or 'https://github.com/user/repo')`,\n );\n }\n validateSourceFormat(flag.trim(), NAMED_SOURCE_LABEL);\n}\n\n/**\n * The marketplace {@link SOURCE_ENV_VAR} names, or undefined when it names none this run.\n *\n * Unset, empty and unusable all fall through to the next rung with a warning rather than\n * a refusal — the environment is ambient, so an exported value nobody meant for this run\n * must not be able to fail it. That is the opposite of {@link assertNamedSourceUsable},\n * and deliberately so: one was typed at this command, the other was already there.\n */\nfunction readEnvSource(): string | undefined {\n const envValue = process.env[SOURCE_ENV_VAR];\n if (!envValue) return undefined;\n\n const trimmed = envValue.trim();\n if (trimmed === \"\") {\n warn(`${SOURCE_ENV_VAR} is set but empty — ignoring and falling back to the next rung.`);\n return undefined;\n }\n\n try {\n validateSourceFormat(trimmed, SOURCE_ENV_VAR);\n } catch (error) {\n warn(\n `${SOURCE_ENV_VAR} has an invalid value — ignoring and falling back to the next rung.\\n${getErrorMessage(error)}`,\n );\n return undefined;\n }\n\n verbose(`Marketplace from ${SOURCE_ENV_VAR} env var: ${trimmed}`);\n return trimmed;\n}\n\nexport async function resolveAuthor(projectDir?: string): Promise<string | undefined> {\n const effective = await loadEffectiveSourceConfig(projectDir);\n return effective?.config.author;\n}\n\n/** Resolved branding with defaults applied for any missing fields */\nexport type ResolvedBranding = {\n name: string;\n};\n\n/**\n * Branding resolved per FIELD: this project's, then the global one's, then the shipped default.\n *\n * Per field rather than per file, and that distinction is the whole of this function. Everything\n * else reads {@link loadEffectiveSourceConfig}, which answers with the project's config if that\n * FILE exists and the global one otherwise — right for `marketplace`, where a project's is its own\n * and inheriting one would install from somewhere nobody named. Branding is the opposite kind of\n * field: it is presentation, a user sets it once for themselves, and a project that says nothing\n * about it is not asking for the shipped name back.\n *\n * Read per file it did exactly that. A user who branded globally stopped seeing their own name the\n * moment any project config existed — which is every installed project — and nothing announced it;\n * the name simply reverted. This function's own docblock described the per-field behaviour for as\n * long as the code did not perform it.\n */\nexport async function resolveBranding(projectDir?: string): Promise<ResolvedBranding> {\n const [own, global] = await Promise.all([\n loadOwnProjectSourceConfig(projectDir),\n loadGlobalSourceConfig(),\n ]);\n\n return {\n name: own?.branding?.name ?? global?.branding?.name ?? DEFAULT_BRANDING.NAME,\n };\n}\n\n/**\n * The one marketplace this installation reads skills from, as a {@link SourceEntry}.\n *\n * Distinct from {@link resolveSource}, which answers the same question as a\n * {@link ResolvedConfig} (source string plus where it came from). This is the shape the\n * surfaces that LIST sources want — `search` and `doctor` — and there is exactly one of\n * them: the registered-extras array this used to return alongside it was withdrawn with\n * the marketplace axis itself.\n */\nexport async function resolvePrimarySourceEntry(projectDir?: string): Promise<SourceEntry> {\n const resolvedConfig = await resolveSource({ caller: \"stored\", projectDir });\n return {\n name: \"marketplace\",\n url: resolvedConfig.source,\n description: \"Primary skills marketplace\",\n };\n}\n\nconst REMOTE_PROTOCOLS = [\n GITHUB_SOURCE.GITHUB_PREFIX, // \"github:\"\n GITHUB_SOURCE.GH_PREFIX, // \"gh:\"\n \"gitlab:\",\n \"bitbucket:\",\n \"sourcehut:\",\n \"https://\",\n \"http://\",\n] as const;\n\n// Minimum length after protocol prefix for a valid remote source (e.g., \"org/repo\" = 8 chars min)\nconst MIN_REMOTE_PATH_LENGTH = 3;\nconst MAX_SOURCE_LENGTH = 512;\n\n// Null bytes must never appear in source strings — they can bypass C-level string termination in downstream tools\nconst NULL_BYTE_PATTERN = /\\0/;\n\n// Path traversal sequences in git refs/branches/tags (e.g., \"?branch=../../etc/passwd\")\nconst PATH_TRAVERSAL_PATTERN = /\\.\\./;\n\n// UNC path prefixes (Windows network paths): \\\\server\\share or //server/share\n// These can trigger SMB authentication to attacker-controlled servers\nconst UNC_PATH_PATTERN = /^(?:\\/\\/|\\\\\\\\)/;\n\n// Private/reserved IPv4 ranges that should not appear in source URLs (SSRF prevention)\n// Matches: 127.x.x.x, 10.x.x.x, 172.16-31.x.x, 192.168.x.x, 0.0.0.0, 169.254.x.x\nconst PRIVATE_IPV4_PATTERN =\n /^(?:127\\.\\d+\\.\\d+\\.\\d+|10\\.\\d+\\.\\d+\\.\\d+|172\\.(?:1[6-9]|2\\d|3[01])\\.\\d+\\.\\d+|192\\.168\\.\\d+\\.\\d+|0\\.0\\.0\\.0|169\\.254\\.\\d+\\.\\d+)$/;\n\n// IPv6 loopback and private addresses in URL hostname brackets\nconst PRIVATE_IPV6_PATTERN =\n /^\\[(?:::1|::ffff:(?:127\\.\\d+\\.\\d+\\.\\d+|10\\.\\d+\\.\\d+\\.\\d+|192\\.168\\.\\d+\\.\\d+)|fd[0-9a-f]{2}:.*|fe80:.*)\\]$/i;\n\n/**\n * Validates a marketplace string format before it reaches giget or filesystem operations.\n * Catches obviously invalid formats early with clear error messages.\n *\n * @param source - The trimmed, non-empty marketplace value to validate\n * @param flagName - What carried this value, as the error messages name it back: `init`'s\n * `--marketplace`, {@link SOURCE_ENV_VAR}, or {@link NAMED_SOURCE_LABEL} when no flag did\n */\nexport function validateSourceFormat(source: string, flagName: string): void {\n // Null bytes can bypass C-level string termination in downstream tools (giget, git)\n if (NULL_BYTE_PATTERN.test(source)) {\n throw new Error(\n `${flagName} contains invalid characters.\\n\\n` +\n `Marketplace values must not contain null bytes.\\n` +\n `Examples:\\n` +\n ` ${flagName} ./my-skills\\n` +\n ` ${flagName} github:user/repo`,\n );\n }\n\n if (source.length > MAX_SOURCE_LENGTH) {\n throw new Error(\n `${flagName} value is too long (${source.length} characters, max ${MAX_SOURCE_LENGTH}).\\n\\n` +\n `Provide a shorter marketplace path or URL.\\n` +\n `Examples:\\n` +\n ` ${flagName} ./my-skills\\n` +\n ` ${flagName} github:user/repo`,\n );\n }\n\n const matchedProtocol = REMOTE_PROTOCOLS.find((prefix) => source.startsWith(prefix));\n\n if (matchedProtocol) {\n validateRemoteSource(source, matchedProtocol, flagName);\n } else {\n validateLocalPath(source, flagName);\n }\n}\n\nfunction validateRemoteSource(source: string, protocol: string, flagName: string): void {\n const pathAfterProtocol = source.slice(protocol.length).trim();\n\n if (pathAfterProtocol.length < MIN_REMOTE_PATH_LENGTH) {\n throw new Error(\n `${flagName} has an incomplete URL: \"${source}\"\\n\\n` +\n `A repository path is required after the protocol prefix.\\n` +\n `Examples:\\n` +\n ` ${flagName} github:user/repo\\n` +\n ` ${flagName} https://github.com/user/repo`,\n );\n }\n\n // Block path traversal in any remote marketplace (refs, branches, query params)\n if (PATH_TRAVERSAL_PATTERN.test(pathAfterProtocol)) {\n throw new Error(\n `${flagName} contains path traversal in URL: \"${source}\"\\n\\n` +\n `Remote marketplace URLs must not contain '..' sequences.\\n` +\n `Examples:\\n` +\n ` ${flagName} github:user/repo\\n` +\n ` ${flagName} https://github.com/user/repo`,\n );\n }\n\n // For https:// and http:// URLs, validate basic URL structure\n if (protocol === \"https://\" || protocol === \"http://\") {\n validateHttpUrl(source, flagName);\n }\n\n // For git shorthand protocols (github:, gh:, gitlab:, etc.), validate org/repo pattern\n if (protocol !== \"https://\" && protocol !== \"http://\") {\n validateGitShorthand(source, pathAfterProtocol, flagName);\n }\n}\n\nfunction validateHttpUrl(source: string, flagName: string): void {\n // Basic URL structure check: must have a hostname with at least one dot or localhost\n const afterProtocol = source.replace(/^https?:\\/\\//, \"\");\n // Strip port number for hostname validation (e.g., \"localhost:8080\" -> \"localhost\")\n const hostnameWithPort = afterProtocol.split(\"/\")[0] ?? \"\";\n const hostname = hostnameWithPort.split(\":\")[0] ?? \"\";\n\n // Allow: dotted hostnames (github.com), localhost, and bracketed IPv6 ([::1])\n const isBracketedIPv6 = hostnameWithPort.startsWith(\"[\") && hostnameWithPort.includes(\"]\");\n if (!hostname || (!hostname.includes(\".\") && hostname !== \"localhost\" && !isBracketedIPv6)) {\n throw new Error(\n `${flagName} has an invalid URL: \"${source}\"\\n\\n` +\n `The URL must include a valid hostname.\\n` +\n `Examples:\\n` +\n ` ${flagName} https://github.com/user/repo\\n` +\n ` ${flagName} https://gitlab.company.com/team/skills`,\n );\n }\n\n // Block private/reserved IP addresses (SSRF prevention via giget)\n if (PRIVATE_IPV4_PATTERN.test(hostname) || PRIVATE_IPV6_PATTERN.test(hostnameWithPort)) {\n throw new Error(\n `${flagName} points to a private or reserved IP address: \"${source}\"\\n\\n` +\n `Marketplace URLs must not target private network addresses.\\n` +\n `Use a public hostname instead.\\n` +\n `Examples:\\n` +\n ` ${flagName} https://github.com/user/repo\\n` +\n ` ${flagName} https://gitlab.company.com/team/skills`,\n );\n }\n}\n\nfunction validateGitShorthand(source: string, repoPath: string, flagName: string): void {\n // Git shorthand format: protocol:owner/repo (must have at least owner/repo)\n if (!repoPath.includes(\"/\")) {\n throw new Error(\n `${flagName} has an invalid repository reference: \"${source}\"\\n\\n` +\n `Git shorthand marketplaces require an owner/repo format.\\n` +\n `Examples:\\n` +\n ` ${flagName} github:user/repo\\n` +\n ` ${flagName} gh:organization/skills`,\n );\n }\n}\n\nfunction validateLocalPath(source: string, flagName: string): void {\n // Check for control characters (except common whitespace)\n // eslint-disable-next-line no-control-regex\n const CONTROL_CHAR_PATTERN = /[\\x00-\\x08\\x0E-\\x1F\\x7F]/u;\n if (CONTROL_CHAR_PATTERN.test(source)) {\n throw new Error(\n `${flagName} contains invalid characters: \"${source}\"\\n\\n` +\n `Marketplace paths must not contain control characters.\\n` +\n `Examples:\\n` +\n ` ${flagName} ./my-skills\\n` +\n ` ${flagName} /home/user/skills`,\n );\n }\n\n // Block UNC paths (Windows network paths like \\\\server\\share or //server/share)\n // These can trigger SMB authentication to attacker-controlled servers, leaking credentials\n if (UNC_PATH_PATTERN.test(source)) {\n throw new Error(\n `${flagName} contains a UNC network path: \"${source}\"\\n\\n` +\n `Network paths (\\\\\\\\server\\\\share or //server/share) are not allowed for security reasons.\\n` +\n `Use a local directory path or a remote URL instead.\\n` +\n `Examples:\\n` +\n ` ${flagName} ./my-skills\\n` +\n ` ${flagName} /home/user/skills\\n` +\n ` ${flagName} https://github.com/user/repo`,\n );\n }\n}\n\n/**\n * Whether a resolved marketplace IS the default public one, asked of the source\n * STRING.\n *\n * The one place that question is answered, because more than one surface asks it\n * and they must agree: the install-mode tagger decides whether the marketplace it\n * labels skills with is public or private, and both stack lookups ask it as half\n * of {@link offersBuiltInStacks}. A marketplace named explicitly — by flag, env\n * or config — is the default one when it spells {@link DEFAULT_SOURCE}.\n *\n * A path is not this question's subject. Nothing in a source STRING that happens\n * to be a path says which repository it holds; {@link isPublicCatalogueCheckout}\n * asks the directory instead, and it is the one to use where a directory is in hand.\n */\nexport function isDefaultSource(source: string): boolean {\n return source === DEFAULT_SOURCE;\n}\n\n/** The only field of a repository's package.json this module reads. */\nconst packageIdentitySchema = z.object({ name: z.string() });\n\n/**\n * Whether the DIRECTORY at `basePath` is a checkout of the public catalogue's own\n * repository, read off package identity.\n *\n * Never off the name in `marketplace.json`: that name is a claim the author\n * writes, so a guard keyed on it would exempt exactly the source it exists to\n * catch. {@link PUBLIC_CATALOGUE_PACKAGE} carries what the signal is and is not\n * worth.\n *\n * The build side asks a different question of the same identity and is spelled\n * apart from this one on purpose: `isCatalogueOwnReservedName` in\n * `marketplace-generator.ts` asks whether a marketplace NAME about to be\n * published is the catalogue's own, and takes the package name it already holds\n * rather than a directory to read one from.\n */\nexport async function isPublicCatalogueCheckout(basePath: string): Promise<boolean> {\n const raw = await readFileOptional(path.join(basePath, STANDARD_FILES.PACKAGE_JSON));\n return declaredPackageName(raw) === PUBLIC_CATALOGUE_PACKAGE;\n}\n\n/** The `name` a package.json declares, or null when there is none to read. */\nfunction declaredPackageName(raw: string): string | null {\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch {\n return null;\n }\n\n const parsed = packageIdentitySchema.safeParse(json);\n return parsed.success ? parsed.data.name : null;\n}\n\n/**\n * Whether the CLI's built-in stack catalogue stands in for a marketplace that\n * ships no stacks of its own.\n *\n * Two spellings of one marketplace, and BOTH stack lookups must read this rather\n * than either half. `resolveOfferedStacks` decides the list the wizard offers and\n * `loadStackById` resolves the id the user then picked; a rule they answer\n * differently offers a stack and refuses to install it.\n *\n * The built-in stacks ARE the public catalogue's stacks — that repository ships\n * no `config/stacks.ts` at all — so a checkout of it read off a path has to reach\n * them too, and the source string cannot say that a path is that repository.\n */\nexport async function offersBuiltInStacks(basePath: string, source: string): Promise<boolean> {\n return isDefaultSource(source) || (await isPublicCatalogueCheckout(basePath));\n}\n\nexport function isLocalSource(source: string): boolean {\n if (source.startsWith(\"/\") || source.startsWith(\".\")) {\n return true;\n }\n\n const hasRemoteProtocol = REMOTE_PROTOCOLS.some((prefix) => source.startsWith(prefix));\n\n if (!hasRemoteProtocol) {\n if (source.includes(\"..\") || source.includes(\"~\")) {\n throw new Error(\n `Invalid marketplace path: ${source}. Path traversal patterns like '..' and '~' are not allowed for security reasons. Use absolute paths or remote URLs instead (e.g., '/home/user/skills' or 'https://github.com/user/repo').`,\n );\n }\n }\n\n return !hasRemoteProtocol;\n}\n","import { unique } from \"remeda\";\n\nimport { KEBAB_CASE_PATTERN } from \"../consts.js\";\n\n/** The characters {@link KEBAB_CASE_PATTERN} is built from, tested one at a time. */\nconst KEBAB_CASE_CHARACTER = /[a-z0-9-]/;\n\n/**\n * The characters a name carries that kebab-case does not admit, deduplicated and in\n * first-appearance order.\n *\n * Empty when the name breaks the rule some other way — a leading digit, a doubled or\n * a trailing hyphen — which is why a refusal states the rule as well as the list: an\n * author handed `@scope/thing` can act on `@` and `/` directly, and one handed\n * `-thing` has nothing to delete.\n */\nexport function charactersOutsideKebabCase(name: string): string[] {\n return unique([...name].filter((character) => !KEBAB_CASE_CHARACTER.test(character)));\n}\n\n/**\n * Validates a user-supplied entity name against the kebab-case convention.\n * Returns an error message naming the entity (e.g. \"Marketplace\", \"Skill\"),\n * or null when the name is valid.\n */\nexport function validateKebabCaseName(name: string, noun: string): string | null {\n if (!name || name.trim() === \"\") {\n return `${noun} name is required`;\n }\n\n if (!KEBAB_CASE_PATTERN.test(name)) {\n return `${noun} name must be kebab-case (lowercase letters, numbers, and hyphens, starting with a letter)`;\n }\n\n return null;\n}\n","import {\n CLI_INVOKE_COMMAND,\n DEFAULT_BRANDING,\n DEFAULT_PLUGIN_NAME,\n EDITOR_URL,\n LOCAL_SKILLS_PATH,\n MARKETPLACE_JSON,\n STANDARD_FILES,\n editorConfigUrl,\n} from \"../consts.js\";\nimport type { UnusableSkillMetadata } from \"../lib/loading/index.js\";\nimport { charactersOutsideKebabCase } from \"../lib/validate-kebab-name.js\";\nimport type { AgentName, SkillId } from \"../types/index.js\";\n\nexport const ERROR_MESSAGES = {\n UNKNOWN_ERROR: \"Unknown error occurred\",\n UNKNOWN_ERROR_SHORT: \"Unknown error\",\n NO_INSTALLATION: `No installation found. Run '${CLI_INVOKE_COMMAND} init' first to set up ${DEFAULT_BRANDING.NAME}`,\n FAILED_RESOLVE_SOURCE: \"Failed to resolve marketplace\",\n FAILED_LOAD_AGENT_PARTIALS: \"Failed to load agent partials\",\n FAILED_COMPILE_AGENTS: \"Failed to compile agents\",\n CLAUDE_CLI_NOT_FOUND: `Claude CLI not found — '${CLI_INVOKE_COMMAND} update' refreshes marketplaces through it. Install Claude Code first: https://claude.ai/code`,\n /**\n * What `compile` refuses with when every pass discovered zero skills. It is reached only\n * after an installation was detected, so the state it describes is a configuration with\n * nothing installed under it — the same state `doctor` reports as `config-empty` and\n * names `init` for, because `init` on a config that declares nothing opens the wizard\n * rather than the dashboard. `edit` is the wrong half of the pair here: it modifies the\n * currently installed skills, and there are none to modify.\n */\n NO_SKILLS_TO_COMPILE: `No skills found. Run '${CLI_INVOKE_COMMAND} init' to choose skills, or add your own under ${LOCAL_SKILLS_PATH}/.`,\n} as const;\n\nexport const SUCCESS_MESSAGES = {\n UNINSTALL_COMPLETE: \"Uninstall complete!\",\n PLUGIN_COMPILE_COMPLETE: \"Plugin compile complete!\",\n} as const;\n\n/**\n * `init`'s closing line, under the name the run prints itself as.\n *\n * A builder rather than a constant because it carries `branding.name`, which is per-installation\n * and cannot be baked in at module load. `init` is its one caller and resolves the name once on\n * its own spine, through `BaseCommand.resolveBrandingName`, which is where the default comes\n * from.\n */\nexport function initSucceeded(brandingName: string): string {\n return `${brandingName} initialized successfully!`;\n}\n\nexport const STATUS_MESSAGES = {\n INSTALLING_PLUGINS: \"Installing skill plugins...\",\n LOADING_SKILLS: \"Loading skills...\",\n LOADING_MARKETPLACE_SOURCE: \"Loading marketplace...\",\n RECOMPILING_AGENTS: \"Recompiling agents...\",\n COMPILING_AGENTS: \"Compiling agents...\",\n DISCOVERING_SKILLS: \"Discovering skills...\",\n RESOLVING_SOURCE: \"Resolving marketplace...\",\n RESOLVING_MARKETPLACE_SOURCE: \"Resolving marketplace...\",\n LOADING_AGENT_PARTIALS: \"Loading agent partials...\",\n FETCHING_REPOSITORY: \"Fetching repository...\",\n COPYING_SKILLS: \"Copying skills...\",\n /**\n * Printed when revalidation found the remote marketplace had moved on. It is the\n * only warning a user gets that this load costs a download rather than a\n * cache read, so it goes out before the download starts, not after.\n */\n MARKETPLACE_HAS_NEWER_CONTENT: \"Marketplace has newer content — fetching the update...\",\n} as const;\n\n/**\n * The partials `readAgentFiles` compiles a sub-agent out of, in the order it reads them —\n * and therefore what `eject agent-partials` puts under the reader's control. Spelled from\n * {@link STANDARD_FILES} rather than as prose so the sentence below cannot name a file the\n * compiler does not read: it named \"templates, agent intro, workflow, and examples\" for\n * years, four nouns matching nothing that ships.\n */\nconst AGENT_PARTIAL_FILES = [\n STANDARD_FILES.IDENTITY_MD,\n STANDARD_FILES.PLAYBOOK_MD,\n STANDARD_FILES.CRITICAL_REQUIREMENTS_MD,\n STANDARD_FILES.CRITICAL_REMINDERS_MD,\n STANDARD_FILES.OUTPUT_MD,\n];\n\nexport const INFO_MESSAGES = {\n NO_CHANGES_MADE: \"No changes made.\",\n RUN_COMPILE: `Run '${CLI_INVOKE_COMMAND} compile' to include imported skills in your agents.`,\n NO_AGENTS_TO_RECOMPILE: \"No agents to recompile\",\n NO_PLUGIN_INSTALLATION: \"No plugin installation found.\",\n NO_LOCAL_INSTALLATION: \"No local installation found.\",\n CONFIG_TYPES_REFRESHED: `Refreshed ${STANDARD_FILES.CONFIG_TYPES_TS}`,\n /**\n * `update` refreshes marketplaces and stops there. An ejected skill is a copy the\n * user owns and may have edited, so overwriting it from the source would discard\n * their work — this line says so once, as information rather than a warning.\n */\n EJECTED_SKILLS_USER_OWNED: `Ejected skills are yours to own — '${CLI_INVOKE_COMMAND} update' does not change them.`,\n NO_PLUGIN_MARKETPLACES: \"No plugin marketplaces are configured — nothing to refresh.\",\n /** Printed under the destination `eject agent-partials` just named, so it names files only. */\n AGENT_PARTIALS_CUSTOMIZABLE: `Each sub-agent directory there holds ${AGENT_PARTIAL_FILES.join(\", \")} — edit those to customize that sub-agent.`,\n} as const;\n\n/**\n * What `uninstall` reports when the directory holds nothing of this CLI's, under the name the run\n * prints itself as.\n *\n * A builder for the same reason as {@link initSucceeded}, and it matters more here: `uninstall`\n * heads its output with the configured name and signs off with it, so a constant would put the\n * shipped name in the middle of a run that says the configured one twice around it.\n */\nexport function notInstalledHere(brandingName: string): string {\n return `${brandingName} is not installed in this project.`;\n}\n\n/** Closing line of a plugin install, printed wherever one runs. */\nexport function pluginsInstalled(count: number): string {\n return `Installed ${count} skill plugins`;\n}\n\n/**\n * What an eject copy did, wherever `edit` performs one — a newly added local skill,\n * or a skill switched from plugin mode back to eject. Both copy through\n * `copyLocalSkills` at each skill's own scope, so both owe the same sentence.\n *\n * A count and no destination, deliberately: the copies are split between the\n * project directory and `$HOME` by each skill's scope, and one hardcoded path\n * would misname the other half.\n */\nexport function localSkillsCopied(count: number): string {\n return `Copied ${count} local skill(s)`;\n}\n\n/**\n * What a recompile pass did, as two numbers rather than one.\n *\n * The count it replaced was the roster the pass walked, so a run that rewrote\n * nothing and a run that rewrote everything printed the same sentence — the line\n * reported intent rather than outcome. `rewritten` is agents whose file this pass\n * wrote; `unchanged` is agents it found already correct and left alone.\n *\n * `subject` is the noun each caller counts in, because `compile` reports per\n * scope pass (\"global agents\") and `edit` reports the whole run's (\"agents\").\n */\nexport function recompileSummary(rewritten: number, unchanged: number, subject: string): string {\n return `${rewritten} ${subject} rewritten, ${unchanged} unchanged`;\n}\n\n/**\n * The sub-agents a recompile pass could not write, named rather than counted.\n *\n * Read off the pass's `failed` roster rather than off the prose it also returns: that roster is\n * the structured answer to \"which ones did not land\", while `warnings` carries entries that are\n * not failures at all — a scope with nothing to compile contributes one on every project-context\n * run, and a summary built from the prose would file that as work owed.\n */\nexport function agentsNotCompiled(agentNames: readonly AgentName[]): string {\n return `${agentNames.length} sub-agent(s) did not compile: ${agentNames.join(\", \")}`;\n}\n\n/**\n * One thing a run set out to do and did not, paired with the one command that finishes it.\n *\n * Both halves are required. A run that names the failure and no way out has told the user their\n * installation is wrong and left them holding it, and one that names a remedy without saying\n * what it remedies is advice about nothing.\n */\nexport type IncompleteWork = {\n /** What did not happen, in the words it was warned about with where they exist. */\n what: string;\n /** The single next thing that finishes it. */\n recovery: string;\n};\n\n/**\n * The ways out a command names when it finishes with work undone.\n *\n * One sentence per KIND of leftover state rather than one per failure site: what a person does\n * about a plugin registration that outlived the skill it was for is the same whichever of the\n * moments left it there, and three spellings of the same instruction read as three different\n * instructions.\n */\nexport const INCOMPLETE_WORK_RECOVERY = {\n RECOMPILE: `Run '${CLI_INVOKE_COMMAND} compile' — the compiled agents on disk are stale until you do.`,\n INSPECT_INSTALLATION: `Run '${CLI_INVOKE_COMMAND} doctor' to see what this installation is left holding.`,\n DELETE_AGENT_FILE:\n \"Delete the file by hand — Claude Code loads a compiled sub-agent this project no longer configures.\",\n} as const;\n\n/**\n * The account a command ends on when its work landed and part of it did not.\n *\n * It restates warnings the run already printed, deliberately: each was emitted where it\n * happened, which is where it is explicable and where the screens of output after it bury it.\n * This block is what a person reads after the fact, and the only place a non-zero exit from a\n * command that finished is explained.\n *\n * The lead-in claims the changes above LANDED, because that is the whole difference between\n * this ending and a refusal, and it is the sentence a reader would dispute.\n */\nexport function completedWithFailures(failures: readonly IncompleteWork[]): string {\n return [\n `Completed with ${failures.length} failure(s) — the changes above landed, these did not:`,\n ...failures.flatMap(failureLines),\n ].join(\"\\n\");\n}\n\n/** One failure as two lines, the remedy indented under the failure it answers. */\nfunction failureLines({ what, recovery }: IncompleteWork): string[] {\n return [` ${what}`, ` ${recovery}`];\n}\n\n/**\n * The same distinction for the fan-out a global change performs across every\n * OTHER registered project: a project whose agents all came back byte-identical\n * was visited and left alone, and says so instead of being counted as recompiled.\n */\nexport function propagatedRecompileSummary(\n rewritten: number,\n unchanged: number,\n failed: number,\n): string {\n const failureSuffix = failed > 0 ? ` (${failed} failed)` : \"\";\n return `Recompiled agents in ${rewritten} registered projects, ${unchanged} unchanged${failureSuffix}`;\n}\n\n/**\n * Warning printed for an installed, actively-selected skill that no sub-agent's stack\n * carries. The install itself is correct — the files are on disk and `config.ts` records\n * them — but nothing will ever load the skill, and every other surface reports the run\n * as clean. This line is the only one that says so.\n */\nexport function skillAssignedToNoAgent(skillId: SkillId): string {\n return `Skill '${skillId}' is assigned to no sub-agent — nothing will load it.`;\n}\n\n/**\n * The reason behind {@link skillAssignedToNoAgent} whenever it is the scope rule: a\n * project-scoped skill never reaches a global-scoped sub-agent. Names every sub-agent the\n * rule kept the skill away from, so one line accounts for every dropped pair.\n *\n * Shared by the save path (`init` / `edit`, where the assignment was never built) and by\n * `compile` (where a hand-edited `config.ts` declares the pair and the compile-time filter\n * drops it). One verdict, one sentence — a second spelling would read as a second rule.\n */\nexport function scopeBlockedStackAssignment(agentNames: AgentName[], skillId: SkillId): string {\n const subject = agentNames.length === 1 ? \"Sub-agent\" : \"Sub-agents\";\n const named = agentNames.map((name) => `'${name}'`).join(\", \");\n return `${subject} ${named} cannot carry project-scoped skill '${skillId}' — global-scoped sub-agents only carry global-scoped skills.`;\n}\n\n/**\n * Hint printed when a project-context compile resolves zero project agents but\n * the config still declares global-scope agents. Names the global context and\n * the count so the \"No agents to recompile\" no-op isn't silent after a global\n * stack change.\n */\nexport function globalScopedAgentsHint(count: number): string {\n const subject = count === 1 ? \"agent is\" : \"agents are\";\n return `${count} ${subject} global-scoped — run '${CLI_INVOKE_COMMAND} compile' from your home directory, or edit from this project, to recompile them.`;\n}\n\n/** Summary printed after `update` refreshed every marketplace its config named. */\nexport function marketplacesRefreshed(count: number): string {\n return `Update complete! ${count} ${count === 1 ? \"marketplace\" : \"marketplaces\"} refreshed.`;\n}\n\n/** Warning printed for one marketplace the Claude CLI could not refresh. */\nexport function marketplaceRefreshFailed(marketplace: string, reason: string): string {\n return `Could not update marketplace ${marketplace}: ${reason}`;\n}\n\n/**\n * Warning printed when a remote source could not be reached to check whether the\n * cached copy is still current, and the copy was used anyway.\n *\n * The load succeeds — an offline user gets the marketplace they already have\n * rather than an error — so the line's whole job is to name what it is they got.\n */\nexport function sourceUnreachableUsingCache(source: string): string {\n return `Could not reach ${source} — using the cached copy, which may be out of date.`;\n}\n\n/**\n * Fatal summary naming every marketplace that failed to refresh. Each cause was\n * already warned individually; this is what makes the run exit non-zero.\n */\nexport function marketplacesRefreshFailed(marketplaces: string[]): string {\n const subject = marketplaces.length === 1 ? \"marketplace\" : \"marketplaces\";\n return `${marketplaces.length} ${subject} could not be updated: ${marketplaces.join(\", \")}`;\n}\n\n/**\n * `build marketplace`'s refusal when package.json names no author, so the manifest\n * would carry an owner with no name.\n *\n * Refused rather than warned because `marketplaceOwnerSchema` requires that name: a\n * manifest written without one is a file this CLI's own reader rejects, and a build\n * that exits 0 having produced it reports success for a marketplace nobody can add.\n */\nexport function marketplaceOwnerHasNoName(packageJsonPath: string): string {\n return [\n `A marketplace's owner must have a name, and no name could be read from 'author' in ${packageJsonPath}.`,\n `Nothing was written: a ${MARKETPLACE_JSON} whose 'owner.name' is empty is refused by this CLI's own reader, so the build would have reported success for a marketplace nobody can install from.`,\n `Set 'author' in that file — either \"Jane Doe <jane@example.com>\" or { \"name\": \"Jane Doe\" } — and build again.`,\n ].join(\"\\n\\n\");\n}\n\n/**\n * `build marketplace`'s refusal when package.json carries a version that is only a version\n * to a reader who does not check it.\n *\n * `marketplaceSchema` requires `min(1)` here, and nothing upstream did: the package.json\n * schema types the field as a bare string, and the generator's `??` default treats `\"\"` as\n * a value because it is not nullish. So an empty version reached the manifest, the build\n * exited 0, and the file was refused the first time this CLI read it back — the same\n * write-then-fail-on-read shape the zero-plugin refusal closed.\n */\nexport function marketplaceHasNoVersion(packageJsonPath: string): string {\n return [\n `A marketplace must have a version, and 'version' in ${packageJsonPath} is empty.`,\n `Nothing was written: a ${MARKETPLACE_JSON} whose 'version' is empty is refused by this CLI's own reader, so the build would have reported success for a marketplace nobody can install from.`,\n `Set 'version' in that file — \"0.1.0\" if this is its first release — and build again.`,\n ].join(\"\\n\\n\");\n}\n\n/**\n * `build marketplace`'s refusal when the name read from package.json is not one a\n * marketplace may publish under.\n *\n * The way out is the flag rather than a rename of the npm package: an npm scoped name\n * is a legitimate thing for a package to have and an illegitimate marketplace name, so\n * the two identities are allowed to differ. Every offending character is named, because\n * `@scope/thing` gives an author two edits to make and a rule alone gives them none.\n */\nexport function marketplaceNameNotPublishable(name: string, packageJsonPath: string): string {\n const offenders = charactersOutsideKebabCase(name);\n return [\n `Marketplace name '${name}', read from 'name' in ${packageJsonPath}, is not a name a marketplace may publish under.`,\n ...(offenders.length > 0\n ? [\n `It carries ${offenders.map((character) => `'${character}'`).join(\" and \")}, which a marketplace name may not.`,\n ]\n : []),\n `A marketplace name is kebab-case: lowercase letters, numbers and hyphens, starting with a letter.`,\n `Publish under a name of your own instead: '${CLI_INVOKE_COMMAND} build marketplace --name <your-marketplace>'.`,\n ].join(\"\\n\\n\");\n}\n\n/**\n * Warning printed when a compile pass finished but the scope's config-types.ts\n * could not be regenerated (e.g. the skills source was unreachable). The compiled\n * agents are fine; only the type unions may still be stale.\n */\nexport function configTypesRefreshFailed(reason: string): string {\n return `Could not refresh ${STANDARD_FILES.CONFIG_TYPES_TS} — type unions may be stale: ${reason}`;\n}\n\n/**\n * Summary printed after a global uninstall pruned the inlined global-scoped\n * config entries from the registered projects.\n */\nexport function registeredProjectsUpdated(count: number): string {\n return `Updated ${count} registered ${count === 1 ? \"project\" : \"projects\"}`;\n}\n\n/**\n * Warning printed when a global uninstall could not update one registered\n * project (missing directory or unreadable config). The uninstall continues.\n */\nexport function registeredProjectUpdateSkipped(projectPath: string): string {\n return `Could not update registered project at ${projectPath} — its config may still reference the uninstalled global content`;\n}\n\n/**\n * The file and the reason behind {@link skillMetadataUnusableError}, LOGGED rather than\n * carried in the error itself: oclif hard-wraps error text at the terminal width, and a path\n * broken across two lines is one nobody can copy. The error names the skills; this names\n * their files, unwrapped, immediately above it.\n *\n * The reason is the reader's own message and can run to several lines — a YAML parse error\n * carries the position and the offending line, which is the point of naming the file at all.\n * For a file that parsed, it is the fields the file leaves out, named as missing.\n */\nexport function skillMetadataUnusableDetail({\n skillDirName,\n metadataPath,\n reason,\n}: UnusableSkillMetadata): string {\n return ` ${skillDirName} — ${metadataPath}\\n ${reason}`;\n}\n\n/**\n * Which skills the refusal is about, and that their files are named above it. Shared by both\n * refusals below because it is one sentence about one verdict — the commands differ on what\n * the file being unreadable COSTS, not on what it says.\n *\n * Every offending skill is named rather than the first, so one run fixes the lot.\n */\nfunction metadataUnusableOpening(entries: UnusableSkillMetadata[]): string {\n const named = entries.map(({ skillDirName }) => `'${skillDirName}'`).join(\", \");\n const subject = entries.length === 1 ? \"that skill\" : \"those skills\";\n return `The ${STANDARD_FILES.METADATA_YAML} of ${named} does not describe ${subject} — the file and the reason are named above.`;\n}\n\n/**\n * The two ways out, and where the whole list of skills in this state is reported. Also shared:\n * a refusal that named a different way out per command would be describing a different fault.\n */\nconst METADATA_UNUSABLE_WAY_OUT = `Fix the file, or delete the skill directory — '${CLI_INVOKE_COMMAND} doctor' reports every skill in this state.`;\n\n/**\n * Refusal printed when `compile` meets an installed skill whose metadata.yaml exists but\n * describes no skill — either nothing can be parsed out of it, or it parses without the\n * fields a skill is described by. It is the sibling of {@link configUnreadableError} one\n * layer down: the file is there, and nothing can be made of it.\n *\n * Compile refuses rather than skips because a skipped skill is invisible. The same file is\n * refused by the local-skill discovery that regenerates `config-types.ts`, so a compile that\n * loaded the skill from its SKILL.md anyway would write agents around a skill the generated\n * types never carry — which is what it used to do, in the same run, silently.\n */\nexport function skillMetadataUnusableError(entries: UnusableSkillMetadata[]): string {\n return [\n metadataUnusableOpening(entries),\n `A skill this file cannot describe is skipped when ${STANDARD_FILES.CONFIG_TYPES_TS} is regenerated, so compiling it would write agents around a skill the generated types never carry.`,\n METADATA_UNUSABLE_WAY_OUT,\n ].join(\"\\n\");\n}\n\n/**\n * The same refusal raised by `init` and `edit`, where what the file costs is different: the\n * wizard resolves the installed roster against the catalogue, and a skill nothing can be\n * loaded for reaches no screen — so the entry naming it is dropped from `config.ts` and\n * reported as a removal the user never asked for.\n *\n * That is the right answer for a skill the marketplace no longer carries and the wrong one\n * here, where the files are sitting in the install and one repairable file stands between\n * them and the catalogue. So the run stops with the entry intact, exactly as `compile` stops\n * over the same verdict about the same file, rather than spending the record of an install\n * on a YAML typo and billing the marketplace for it.\n */\nexport function savedSkillMetadataUnusableError(entries: UnusableSkillMetadata[]): string {\n return [\n metadataUnusableOpening(entries),\n `A config entry naming a skill this file cannot describe is dropped as one this marketplace does not carry — and a file that can be repaired must not cost an install its record.`,\n METADATA_UNUSABLE_WAY_OUT,\n ].join(\"\\n\");\n}\n\n/**\n * `init --from` is greenfield-only. A shared configuration is installed whole — its own\n * `assignments` map REPLACES the ownership-derived stack rather than merging with it — so there is\n * no coherent answer to what it should do when it meets a setup that is already there. Both\n * refusals below name `uninstall`, because that is the whole of the way through.\n */\nconst SHARED_CONFIG_GREENFIELD_HINT =\n \"installing a shared configuration is a fresh setup, not a merge\";\n\n/**\n * Where a freshly minted id can be acted on, which is the whole of what makes it a share.\n *\n * Exactly two things read one — this CLI and the editor the configuration reopens in — and both\n * commands that mint an id (`share`, and `edit --ui`) print both lines, because an id nobody can\n * act on is not a share. One definition rather than two, so the two commands cannot come to\n * describe the same id differently.\n */\nexport function sharedConfigDestinations(id: string): string[] {\n return [\n ` Install it: ${CLI_INVOKE_COMMAND} init --from ${id}`,\n ` Open it: ${editorConfigUrl(id)}`,\n ];\n}\n\n/** Refusal printed when the directory `init --from` was run in is already installed. */\nexport function sharedConfigExistingInstall(configPath: string): string {\n return `An installation already exists at ${configPath}. Run '${CLI_INVOKE_COMMAND} uninstall' first — ${SHARED_CONFIG_GREENFIELD_HINT}.`;\n}\n\n/**\n * Refusal printed when this project is clean but the payload writes into the user's own\n * ~/.claude, which is already installed. Only a payload carrying global-scoped entries can reach\n * that far, so a project-only configuration is never refused for it.\n */\nexport function sharedConfigGlobalInstall(configPath: string): string {\n return `This configuration installs global-scoped content, and a global installation already exists at ${configPath}. Run '${CLI_INVOKE_COMMAND} uninstall' from your home directory first — ${SHARED_CONFIG_GREENFIELD_HINT}.`;\n}\n\n/**\n * Refusal printed when `init --from` runs at the home directory and the payload carries\n * project-scoped entries.\n *\n * It is NOT a greenfield refusal, and deliberately says nothing about `uninstall`: the payload is\n * installable and the location is not, so the way out is another directory rather than a removal.\n * A global installation holds only global-scoped content, and at the home root both scopes resolve\n * to the same files — so a project-scoped entry does not land elsewhere, it lands in the global\n * config wearing a label that contradicts the file it is in.\n *\n * Every offender is named, skills and sub-agents alike, because they are separate decisions in the\n * payload and only the sharer knows which one they meant — the same reason the unwritable-pair\n * refusal names both halves of every pair.\n */\nexport function sharedConfigProjectScopeAtHome(\n skillIds: readonly SkillId[],\n agentNames: readonly AgentName[],\n): string {\n return [\n \"This configuration cannot be installed here: the home directory is the global scope, and a \" +\n \"global installation holds only global-scoped content — so these project-scoped entries \" +\n \"have nowhere to be written:\",\n ...skillIds.map((id) => ` skill ${id} (scope: project)`),\n ...agentNames.map((name) => ` sub-agent ${name} (scope: project)`),\n \"Run this from inside a project directory, or re-share it with each entry above at global scope.\",\n ].join(\"\\n\");\n}\n\n/**\n * The ids a decode could not place, named rather than counted.\n *\n * \"3 skills were skipped\" cannot be acted on; the ids can, and this is the one moment a user\n * can tell whether what was shared is what they are getting. One definition because both\n * consumers of a shared configuration report it — `init --from` on the way into a clean\n * directory, `edit --from` on the way over an installed one — and a skip that read differently\n * per command would look like a different kind of skip.\n */\nexport function skippedUnknownSkills(skillIds: readonly string[]): string {\n return `Skipped ${skillIds.length} skill(s) this catalog does not know: ${skillIds.join(\", \")}`;\n}\n\n/** The sub-agent half of {@link skippedUnknownSkills}, judged against `AGENT_NAMES`. */\nexport function skippedUnknownAgents(agentNames: readonly string[]): string {\n return `Skipped ${agentNames.length} unknown sub-agent(s): ${agentNames.join(\", \")}`;\n}\n\n/**\n * What a shared configuration brought with it rather than named. Named for the same reason the\n * skips are: these are the entries no catalogue can explain, so this line is the only place a\n * user learns what arrived inside the configuration itself.\n */\nexport function carriedSkillsWritten(skillIds: readonly string[]): string {\n return `Wrote ${skillIds.length} skill(s) this configuration carries: ${skillIds.join(\", \")}`;\n}\n\n/**\n * The fixed text of `edit --from`'s removal plan.\n *\n * Applying a shared configuration makes this project MATCH it, so a skill the previous\n * configuration installed and this payload omits is removed. That is the whole reason the\n * command is interactive, and the reason the heading names removal rather than the apply:\n * additions and re-tunings need no permission, and the change summary prints them afterwards.\n */\nexport const SHARED_CONFIG_APPLY = {\n PREVIEW_HEADING: \"Applying this configuration will remove:\",\n SKILLS_HEADING: \"Skills:\",\n AGENTS_HEADING: \"Sub-agents:\",\n /**\n * The two headings a PROJECT run prints instead, for entries that live at global scope. They\n * exist only there: at the home directory every entry is global, so a heading saying so would\n * label the whole list with the one fact the location already states.\n */\n GLOBAL_SKILLS_HEADING: \"Skills installed globally:\",\n GLOBAL_AGENTS_HEADING: \"Sub-agents installed globally:\",\n /** Printed in place of the sections when the payload takes nothing away. */\n NOTHING_REMOVED: \"Nothing is removed — this configuration only adds and re-tunes.\",\n CONFIRM: \"Apply this configuration?\",\n} as const;\n\n/**\n * Refusal printed when `edit --from` has no terminal to confirm its removals at.\n *\n * A confirm nobody can answer must never become a yes, so this refuses rather than applying\n * silently. It names the other command deliberately: `init --from` installs the same\n * configuration into a clean directory and removes nothing, so it is safe headless and is the\n * whole of what a pipeline can do with an id.\n */\nexport function sharedConfigNeedsTerminal(id: string): string {\n return [\n `Applying configuration '${id}' removes whatever it leaves out, so it has to be confirmed — and there is no terminal here to confirm it at.`,\n `Run '${CLI_INVOKE_COMMAND} edit --from ${id}' from a terminal, or '${CLI_INVOKE_COMMAND} init --from ${id}' in a clean directory, which installs without removing anything.`,\n ].join(\"\\n\");\n}\n\n/**\n * The removal plan's statement of CONSEQUENCE for entries a project run removes at global scope.\n *\n * A global install is one installation every registered project reads, so removing one from\n * inside a project changes projects the person confirming is not looking at and did not choose\n * to be looking at. Nothing is refused over that — the ruling is that they may do it — but a yes\n * given without it is a yes to a change nobody described, so the reach is counted AND named:\n * \"2 other projects\" cannot be weighed against anything, and a path can.\n *\n * Printed only from a PROJECT. Inside the global installation the location IS the scope and the\n * person chose it, so the ordinary apply confirm is the whole of the gate there — see\n * `edit`'s two plan branches.\n */\nexport function globallyInstalledRemoved(otherProjects: readonly string[]): string {\n return [\n \"These are installed globally, and a global install is shared by every project on this machine.\",\n ...globalRemovalReach(otherProjects),\n `To keep them, answer no and re-share the configuration with them included.`,\n ].join(\"\\n\");\n}\n\n/** Who else the removal above lands on: every registered project but the one being edited. */\nfunction globalRemovalReach(otherProjects: readonly string[]): string[] {\n if (otherProjects.length === 0) {\n return [\n \"No other project is registered here, so nothing else changes today — a project set up later inherits whatever the global install holds then.\",\n ];\n }\n\n return [\n `Also affects ${otherProjects.length} other registered project(s):`,\n ...otherProjects.map((projectDir) => ` ${projectDir}`),\n ];\n}\n\n/**\n * The removal plan's statement for skills the round trip does not own.\n *\n * `forkedFrom` decides ownership: the CLI stamps it into every skill directory it writes, and a\n * skill written by hand into `.claude/skills/` carries none — so no shared configuration ever\n * carried it, and this one made no statement about it. Deleting it would be this command\n * inventing an instruction nobody gave.\n */\nexport function authoredHereKept(skillIds: readonly SkillId[]): string {\n return [\n \"Kept — written here rather than installed, so a shared configuration never carried them:\",\n ...skillIds.map((id) => ` skill ${id}`),\n `Remove them with '${CLI_INVOKE_COMMAND} edit'.`,\n ].join(\"\\n\");\n}\n\n/**\n * The removal plan's statement for skills this configuration NAMES that this catalogue cannot\n * place.\n *\n * The skips reported earlier say what did not arrive; this says what stayed because of it, and\n * the two are one fact read from either end. A destructive apply removes on intent and never on\n * its own inability: the payload asked for these ids, so their absence from the decode is this\n * catalogue's limit rather than an instruction, and deleting an installed skill over it would\n * delete it because the catalogue moved.\n *\n * The remedy is the catalogue rather than the skill, which is the whole difference from the two\n * statements above: nothing is wrong with what is installed, and nothing the user does to it\n * makes the configuration's instruction applicable.\n */\nexport function unplaceableKept(skillIds: readonly SkillId[]): string {\n return [\n \"Kept — named by this configuration, and this catalogue cannot place them:\",\n ...skillIds.map((id) => ` skill ${id}`),\n `Run '${CLI_INVOKE_COMMAND} update' to refresh this installation's marketplace, then apply the configuration again.`,\n ].join(\"\\n\");\n}\n\n/**\n * Refusal printed when a command that must read an existing configuration meets one it\n * cannot load. There are no versioned migrations, so an unreadable configuration is\n * recreated rather than repaired — and `uninstall` deliberately keeps working on one, which\n * is what makes the first instruction a real way out rather than a suggestion to delete\n * directories by hand. The editor is the other: it builds a configuration the CLI installs\n * by id.\n *\n * `configLoadFailure` is a `ConfigLoadError` message, so the offending file and the reason\n * are already in it and are not restated here.\n *\n * `doctor` is named last and deliberately: it reports this same file as its own finding, with the\n * same way out. It could not be named until it did — it used to call a config that exists but\n * cannot be read `.claude-src/config.ts not found` and send the reader to `init`, contradicting\n * every line below.\n */\nexport function configUnreadableError(configLoadFailure: string): string {\n return [\n configLoadFailure,\n `There is no automatic repair for this — recreate the configuration: '${CLI_INVOKE_COMMAND} uninstall' still works on a config it cannot read, then '${CLI_INVOKE_COMMAND} init'.`,\n `Or build one at ${EDITOR_URL} and install it with '${CLI_INVOKE_COMMAND} init --from <id>'.`,\n `'${CLI_INVOKE_COMMAND} doctor' reports the same file, alongside whatever else is wrong here.`,\n ].join(\"\\n\");\n}\n\n/**\n * Warning printed when a global uninstall could not update the registered\n * projects at all (e.g. the skills source failed to load). The uninstall\n * itself still completes.\n */\nexport function registeredProjectsUpdateFailed(reason: string): string {\n return `Could not update registered projects — their configs may still reference the uninstalled global content: ${reason}`;\n}\n\n/**\n * Statement printed in the uninstall removal plan, and again in the summary, for the agent\n * files this run leaves where they are. Every agent the compiler writes carries a provenance\n * marker, so an agent file without one was written by somebody else — and saying so is what\n * makes the removal beside it a claim about provably-ours rather than about a directory.\n *\n * Printed both before the confirmation and after the removal, from the one plan, so what the\n * user approved and what the run reports cannot disagree.\n */\nexport function unmarkedAgentsKept(agentsDir: string, count: number): string {\n const subject = count === 1 ? \"agent\" : \"agents\";\n const object = count === 1 ? \"it\" : \"them\";\n return `Kept ${count} ${subject} in ${agentsDir}/ — no ${DEFAULT_PLUGIN_NAME} marker, so this CLI did not compile ${object}.`;\n}\n\n/**\n * The uninstall removal plan's fixed text: the heading the whole plan is printed under,\n * and the heading each removal is grouped beneath. A heading is a promise about the lines\n * below it, so one is printed only when the plan carries a removal that sits under it.\n * Both renderers — the `--yes` printer and the confirm UI — read them from here, so the\n * preview a user approves and the list a `--yes` run prints cannot drift apart.\n */\nexport const UNINSTALL_PLAN = {\n PREVIEW_HEADING: \"The following will be removed:\",\n PLUGINS_HEADING: \"Plugins:\",\n CLI_MANAGED_FILES_HEADING: \"CLI-managed files:\",\n CONFIG_HEADING: \"Config:\",\n} as const;\n\n/**\n * The plan's line for the local skills directory. The directory is not removed wholesale —\n * only the skills whose `forked-from` metadata names a marketplace are — so the line says\n * which of its contents the run is claiming.\n */\nexport function localSkillsRemoval(skillsDir: string): string {\n return `${skillsDir}/ (matching the marketplace)`;\n}\n\n/**\n * The plan's line for the compiled agents directory, marking it as the CLI's to delete\n * rather than the user's. Printed when the run can name which agents those are — from the\n * configuration, or from the provenance marker each compiled file carries when the\n * configuration is gone. {@link unmarkedAgentsKept} names the rest.\n */\nexport function compiledAgentsRemoval(agentsDir: string): string {\n return `${agentsDir}/ (CLI-compiled)`;\n}\n","import { z } from \"zod\";\nimport { partition } from \"remeda\";\nimport type { LocalSkillMetadata } from \"./skills/skill-metadata\";\nimport type { LocalRawMetadata } from \"./skills/local-skill-loader\";\nimport {\n AUTHOR_HANDLE_PATTERN,\n KEBAB_CASE_PATTERN,\n LOCAL_PSEUDO_CATEGORY,\n STANDARD_FILES,\n} from \"../consts\";\nimport { METADATA_KEYS } from \"./metadata-keys\";\nimport { formatZodIssue } from \"./schema-validator\";\nimport { isRecord } from \"../utils/type-guards\";\nimport { warn } from \"../utils/logger\";\nimport { SKILL_SLUGS, CATEGORIES } from \"../types/generated/source-types\";\nimport { EFFORT_NAMES, MODEL_NAMES, PERMISSION_MODES } from \"../types/matrix\";\nimport type {\n AgentHookAction,\n AgentHookDefinition,\n AgentName,\n AgentYamlConfig,\n AlternativeGroup,\n CategoryDefinition,\n CategoryPath,\n ConflictRule,\n DiscourageRule,\n Domain,\n EffortLevel,\n Marketplace,\n MarketplaceMetadata,\n MarketplaceOwner,\n MarketplacePlugin,\n MarketplaceRemoteSource,\n ModelName,\n PermissionMode,\n PluginAuthor,\n PluginManifest,\n ProjectConfig,\n RelationshipDefinitions,\n RequireRule,\n SkillAssignment,\n SkillConfig,\n SkillId,\n SkillSlug,\n Category,\n} from \"../types\";\n\nexport const modelNameSchema = z.enum(MODEL_NAMES) as z.ZodType<ModelName>;\n\nexport const effortLevelSchema = z.enum(EFFORT_NAMES) as z.ZodType<EffortLevel>;\n\nexport const permissionModeSchema = z.enum(PERMISSION_MODES) as z.ZodType<PermissionMode>;\n\nexport const skillSlugSchema = z.enum(SKILL_SLUGS) as z.ZodType<SkillSlug>;\n\n// Accepts: known category, \"local\", or any kebab-case string (custom categories)\nexport const categoryPathSchema = z.string().refine(\n (val): val is CategoryPath => {\n if (val === LOCAL_PSEUDO_CATEGORY) return true;\n if ((CATEGORIES as readonly string[]).includes(val)) return true;\n // Accept any kebab-case string for custom categories\n return KEBAB_CASE_PATTERN.test(val);\n },\n {\n message: \"Must be a valid category path (e.g., 'web-framework', 'shared-testing', or 'local')\",\n },\n) as z.ZodType<CategoryPath>;\n\nexport const agentHookActionSchema: z.ZodType<AgentHookAction> = z.object({\n type: z.enum([\"command\", \"script\", \"prompt\"]),\n command: z.string().exactOptional(),\n script: z.string().exactOptional(),\n prompt: z.string().exactOptional(),\n});\n\nexport const agentHookDefinitionSchema: z.ZodType<AgentHookDefinition> = z.object({\n matcher: z.string().exactOptional(),\n hooks: z.array(agentHookActionSchema).exactOptional(),\n});\n\nexport const hooksRecordSchema = z.record(z.string(), z.array(agentHookDefinitionSchema));\n\n/** Strict hook definition — hooks array is required and must have at least one action */\nconst strictAgentHookDefinitionSchema = z.object({\n matcher: z.string().exactOptional(),\n hooks: z.array(agentHookActionSchema).min(1),\n});\n\n/** Strict hooks record for validation schemas (requires at least one hook action per definition) */\nexport const strictHooksRecordSchema = z.record(\n z.string(),\n z.array(strictAgentHookDefinitionSchema),\n);\n\nexport const skillAssignmentSchema: z.ZodType<SkillAssignment> = z.object({\n id: z.string() as z.ZodType<SkillId>,\n preloaded: z.boolean().exactOptional(),\n local: z.boolean().exactOptional(),\n path: z.string().exactOptional(),\n});\n\n// Lenient: accepts any string for `name` since local/custom skills may not follow strict SkillId pattern\nexport const skillFrontmatterLoaderSchema = z.object({\n /** Lenient (any string): local/custom skills have non-builtin IDs */\n name: z.string() as z.ZodType<SkillId>,\n description: z.string(),\n model: modelNameSchema.exactOptional(),\n});\n\n/**\n * Loader schema for a skill's metadata.yaml.\n *\n * `custom` buys its category NOTHING here. It used to: a `custom: true` skill's\n * category was waved through on a bare kebab-case test while every other skill's\n * went to `categoryPathSchema`. A custom skill is placed in a category that\n * already exists rather than bringing one, so the leniency described a freedom it\n * no longer has, and the same field now answers to the same schema either way.\n * Whether the category is one this installation actually declares is asked where\n * the declarations are — `mergeLocalSkillsIntoMatrix`, not here.\n */\nexport const skillMetadataLoaderSchema = z\n .object({\n category: categoryPathSchema.exactOptional(),\n author: z.string().exactOptional(),\n domain: z.string() as z.ZodType<Domain>,\n custom: z.boolean().exactOptional(),\n })\n .passthrough();\n\n/**\n * Raw metadata.yaml shape read by the matrix loader during skill extraction.\n * Preserved verbatim on the move from matrix-loader.ts.\n */\nexport const matrixRawMetadataSchema = z.object({\n category: categoryPathSchema,\n author: z.string(),\n displayName: z.string().exactOptional(),\n slug: z.string() as z.ZodType<SkillSlug>,\n cliDescription: z.string().exactOptional(),\n usageGuidance: z.string().exactOptional(),\n // Boundary cast: domain is a string at the YAML parse boundary; narrowed to Domain type\n domain: z.string() as z.ZodType<Domain>,\n custom: z.boolean().exactOptional(),\n});\n\nexport const pluginAuthorSchema: z.ZodType<PluginAuthor> = z.object({\n name: z.string().min(1),\n email: z.string().exactOptional(),\n});\n\n// Shared plugin.json shape — the lenient (strip) and strict variants below differ only in unknown-key policy\nconst pluginManifestObjectSchema = z.object({\n name: z.string(),\n version: z.string().exactOptional(),\n description: z.string().exactOptional(),\n author: pluginAuthorSchema.exactOptional(),\n /** Lenient: a plugin authored elsewhere may carry any category string or none at all */\n category: z.string().exactOptional(),\n keywords: z.array(z.string()).exactOptional(),\n commands: z.union([z.string(), z.array(z.string())]).exactOptional(),\n agents: z.union([z.string(), z.array(z.string())]).exactOptional(),\n skills: z.union([z.string(), z.array(z.string())]).exactOptional(),\n hooks: z.union([z.string(), hooksRecordSchema]).exactOptional(),\n});\n\n/** Lenient plugin.json schema (strips unknown keys; used at load boundaries) */\nexport const pluginManifestSchema: z.ZodType<PluginManifest> = pluginManifestObjectSchema;\n\n/** Strict plugin.json schema — rejects unrecognized keys (used by plugin-validator) */\nexport const pluginManifestValidationSchema = pluginManifestObjectSchema.strict();\n\nexport const agentYamlConfigSchema: z.ZodType<AgentYamlConfig> = z.object({\n id: z.string() as z.ZodType<AgentName>,\n title: z.string(),\n description: z.string(),\n model: modelNameSchema.exactOptional(),\n effort: effortLevelSchema.exactOptional(),\n tools: z.array(z.string()),\n disallowedTools: z.array(z.string()).exactOptional(),\n permissionMode: permissionModeSchema.exactOptional(),\n hooks: hooksRecordSchema.exactOptional(),\n outputFormat: z.string().exactOptional(),\n domain: (z.string() as z.ZodType<Domain>).exactOptional(),\n custom: z.boolean().exactOptional(),\n});\n\n// Defined before projectConfigLoaderSchema so it can reference stackAgentConfigSchema\n// Single skill assignment element: either a bare SkillId string or an object { id, preloaded? }\nconst skillAssignmentElementSchema = z.union([\n z.string() as z.ZodType<SkillId>,\n skillAssignmentSchema,\n]);\n\n/**\n * Agent config within a stack: maps category to skill assignment(s).\n * Lenient: accepts bare string, object, or array from YAML.\n * Consumers normalize all values to SkillAssignment[] after parsing.\n */\nexport const stackAgentConfigSchema = z.record(\n z.string(),\n z.union([skillAssignmentElementSchema, z.array(skillAssignmentElementSchema)]),\n);\n\n/**\n * The top-level keys a saved config carried before the marketplace fields were renamed, each\n * mapped to the field its value lives on now. Data rather than a check per key because both\n * loader schemas read the same file and have to refuse the same keys — and `satisfies` ties every\n * replacement to a field that really exists, so the next rename cannot leave this list stale.\n */\nconst RENAMED_CONFIG_FIELDS = { source: \"marketplace\" } as const satisfies Record<\n string,\n keyof ProjectConfig\n>;\n\n/** The same, for the keys a saved config's SKILL ENTRIES carried. */\nconst RENAMED_SKILL_ENTRY_FIELDS = { source: \"origin\" } as const satisfies Record<\n string,\n keyof SkillConfig\n>;\n\nfunction renamedFieldMessage(oldKey: string, newKey: string): string {\n return `\"${oldKey}\" was renamed to \"${newKey}\". Rename the key in this config — the CLI does not read \"${oldKey}\" any more and will not fall back to it.`;\n}\n\nfunction reportRenamedKeys(\n record: Record<string, unknown>,\n renames: Record<string, string>,\n path: PropertyKey[],\n ctx: z.RefinementCtx,\n): void {\n for (const [oldKey, newKey] of Object.entries(renames)) {\n if (!(oldKey in record)) continue;\n ctx.addIssue({\n code: \"custom\",\n path: [...path, oldKey],\n message: renamedFieldMessage(oldKey, newKey),\n });\n }\n}\n\n/**\n * Refuses a saved config that still names a field by the key it had before the rename.\n *\n * Reads the raw document rather than parse output because neither schema would show it one: both\n * are `.passthrough()`, so a stale top-level key survives as unrecognised data, and the skills\n * array is declared, so a stale key on an entry is stripped before any refinement runs. Either way\n * the run would look for the value under its NEW name, find nothing, and quietly install from the\n * default marketplace instead of the one the config named.\n */\nfunction refuseRenamedFields(config: unknown, ctx: z.RefinementCtx): void {\n if (!isRecord(config)) return;\n\n reportRenamedKeys(config, RENAMED_CONFIG_FIELDS, [], ctx);\n\n const { skills } = config;\n if (!Array.isArray(skills)) return;\n for (const [index, entry] of skills.entries()) {\n if (!isRecord(entry)) continue;\n reportRenamedKeys(entry, RENAMED_SKILL_ENTRY_FIELDS, [\"skills\", index], ctx);\n }\n}\n\n/**\n * Both loader schemas behind the same refusal, piped so it runs on the file as written. A failure\n * here short-circuits the shape check, so a config carrying an old key is answered with the rename\n * it needs rather than with the missing-field noise the rename causes.\n */\nconst renamedFieldGuard = z.unknown().superRefine(refuseRenamedFields);\n\n/** The shape {@link projectConfigLoaderSchema} admits once the rename guard has passed. */\nconst projectConfigFields = z\n .object({\n /** Project/plugin name in kebab-case */\n name: z.string().exactOptional(),\n description: z.string().exactOptional(),\n /** Per-agent configuration with scope (e.g., [{ name: \"web-developer\", scope: \"project\" }]) */\n agents: z\n .array(\n z.object({\n name: z.string(),\n scope: z.enum([\"project\", \"global\"]),\n /** Per-agent overrides of the agent's own metadata defaults */\n model: modelNameSchema.exactOptional(),\n effort: effortLevelSchema.exactOptional(),\n excluded: z.boolean().exactOptional(),\n }),\n )\n .exactOptional(),\n /** Per-skill configuration with scope and provenance */\n skills: z\n .array(\n z.object({\n id: z.string() as z.ZodType<SkillId>,\n scope: z.enum([\"project\", \"global\"]),\n origin: z.string(),\n excluded: z.boolean().exactOptional(),\n }),\n )\n .exactOptional(),\n\n /** Author handle (e.g., \"@vince\") */\n author: z.string().exactOptional(),\n /** Selected domains from the wizard (persisted for edit mode restoration) */\n selectedDomains: z.array(z.string() as z.ZodType<Domain>).exactOptional(),\n /** Agent-to-category-to-skill mappings from selected stack (accepts same formats as stacks.ts) */\n stack: z.record(z.string(), stackAgentConfigSchema).exactOptional(),\n /** The marketplace this install reads skills from, as a path or URL (e.g., \"github:my-org/skills\") */\n marketplace: z.string().exactOptional(),\n /** The name that marketplace's manifest gives it, which plugins are registered under */\n marketplaceName: z.string().exactOptional(),\n /** Separate source for agents when different from skills source */\n agentsSource: z.string().exactOptional(),\n /** Tracked project installation paths (global config only) */\n projects: z.array(z.string()).exactOptional(),\n })\n .passthrough();\n\n/**\n * Lenient loader for .claude-src/config.ts (ProjectConfig).\n * name/agents optional since partial configs are valid at load time.\n * Full validation happens in validateProjectConfig().\n */\nexport const projectConfigLoaderSchema = renamedFieldGuard.pipe(projectConfigFields);\n\nconst categoryDefinitionSchema: z.ZodType<CategoryDefinition> = z.object({\n id: z.string() as z.ZodType<Category>,\n displayName: z.string(),\n description: z.string(),\n domain: (z.string() as z.ZodType<Domain>).exactOptional(),\n exclusive: z.boolean(),\n order: z.number(),\n icon: z.string().exactOptional(),\n});\n\n/**\n * What a relationship rule naming an unknown skill says back, in place of the whole\n * generated slug union it was tested against.\n *\n * A rule names skills by slug and every one is held to the PUBLIC catalogue's generated\n * union, so a marketplace author naming a skill they themselves ship is handed roughly 250\n * names belonging to somebody else — which answers a question they did not ask and does not\n * contain the answer to the one they did. Zod's own text for an enum reports the options and\n * never the input, so the slug they actually wrote was the one thing missing from it; the\n * function form is what puts it back.\n *\n * It says \"yet\" deliberately. The constraint is this schema's rather than the loader's — a\n * source's own rules are resolved against that source's own slug map — so the refusal names a\n * limit rather than a law. Whether slugs leave the closed union is a separate question.\n */\nfunction unknownSkillSlugRefusal(input: unknown): string {\n const named = typeof input === \"string\" ? `'${input}'` : \"That value\";\n return (\n `${named} is not a slug the public catalogue carries, and a relationship rule may only ` +\n `name skills the public catalogue carries — this marketplace's own skills cannot be named ` +\n `in one yet. Name a catalogue slug, or leave 'relationships' out: it is optional, and a ` +\n `marketplace shipping no relationship rules loads and installs like any other.`\n );\n}\n\n// Skill references in relationship rules: slugs resolved to canonical IDs by matrix-loader\nconst skillRefInRules = z.enum(SKILL_SLUGS, {\n error: (issue) => unknownSkillSlugRefusal(issue.input),\n}) as z.ZodType<SkillSlug>;\n\n// Shared shape for conflict/discourage/compatibility rules: 2+ slugs plus a reason\nconst skillGroupRuleSchema = z.object({\n skills: z.array(skillRefInRules).min(2),\n reason: z.string(),\n});\n\nconst conflictRuleSchema: z.ZodType<ConflictRule> = skillGroupRuleSchema;\n\nconst discourageRuleSchema: z.ZodType<DiscourageRule> = skillGroupRuleSchema;\n\nconst requireRuleSchema: z.ZodType<RequireRule> = z.object({\n skill: skillRefInRules,\n needs: z.array(skillRefInRules).min(1),\n needsAny: z.boolean().exactOptional(),\n reason: z.string(),\n});\n\nconst alternativeGroupSchema: z.ZodType<AlternativeGroup> = z.object({\n purpose: z.string(),\n skills: z.array(skillRefInRules).min(1),\n});\n\nconst relationshipDefinitionsSchema: z.ZodType<RelationshipDefinitions> = z.object({\n conflicts: z.array(conflictRuleSchema),\n discourages: z.array(discourageRuleSchema),\n requires: z.array(requireRuleSchema),\n alternatives: z.array(alternativeGroupSchema),\n});\n\n/**\n * Standalone skill-categories.ts file schema.\n * Top-level object with version string and categories map using existing categoryDefinitionSchema.\n */\nexport const skillCategoriesFileSchema = z.object({\n version: z.string(),\n categories: z.record(z.string(), categoryDefinitionSchema),\n});\n\n/**\n * Standalone skill-rules.ts file schema.\n * Contains version and aggregate relationship rules between skills.\n */\nexport const skillRulesFileSchema = z.object({\n version: z.string(),\n relationships: relationshipDefinitionsSchema.exactOptional(),\n});\n\n/**\n * Raw metadata from a local skill's metadata.yaml.\n * displayName and category are required — the skill must declare both.\n */\nexport const localRawMetadataSchema = z\n .object({\n /** Short name shown in the wizard grid (e.g., \"my-custom-react\") */\n displayName: z.string(),\n /** Kebab-case short key for alias resolution (e.g., \"react\") */\n slug: z.string() as z.ZodType<SkillSlug>,\n /** One-line description for the wizard */\n cliDescription: z.string().exactOptional(),\n /** Category to place this skill in (e.g., \"web-framework\") */\n category: categoryPathSchema,\n /** When an AI agent should invoke this skill */\n usageGuidance: z.string().exactOptional(),\n /** Domain this skill belongs to (e.g., \"web\", \"api\", \"cli\") */\n domain: z.string() as z.ZodType<Domain>,\n /** True if this skill was created outside the CLI's built-in vocabulary */\n custom: z.boolean().exactOptional(),\n })\n // Passthrough widens the output with an index signature; LocalRawMetadata is the\n // honest declared shape consumers read (same round-1 pattern as localSkillMetadataSchema).\n .passthrough() as z.ZodType<LocalRawMetadata>;\n\n/** Metadata for local skills that were forked/copied from a marketplace skill */\nexport const localSkillMetadataSchema = z\n .object({\n forkedFrom: z\n .object({\n /** Original skill ID before forking — lenient (any string) since custom/extra-source skills have non-builtin IDs */\n skillId: z.string() as z.ZodType<SkillId>,\n /** SHA hash of the original content at fork time (for diff detection) */\n contentHash: z.string(),\n /** ISO date when the fork was created */\n date: z.string(),\n /** Source URL the skill was installed from (e.g., \"github:agents-inc/skills\") */\n source: z.string().exactOptional(),\n /** Directory inside that repository, for a skill only its own bytes can install again */\n path: z.string().exactOptional(),\n })\n .exactOptional(),\n })\n // Passthrough widens the output with an index signature; LocalSkillMetadata carries the\n // same index signature, so this is the honest declared shape for parse results.\n .passthrough() as z.ZodType<LocalSkillMetadata>;\n\nconst stackSchema = z.object({\n id: z.string().min(1),\n name: z.string().min(1),\n description: z.string(),\n /** Maps agent IDs to their category-to-skill assignments */\n agents: z.record(z.string(), stackAgentConfigSchema),\n /** High-level philosophy guiding this stack's technology choices */\n philosophy: z.string().exactOptional(),\n});\n\n// Pre-normalization schema: values may be string or string[].\n// loadStacks() normalizes to StacksConfig (all values SkillId[]) after parsing.\nexport const stacksConfigSchema = z.object({\n stacks: z.array(stackSchema).min(1),\n});\n\nconst marketplaceRemoteSourceSchema: z.ZodType<MarketplaceRemoteSource> = z.object({\n source: z.enum([\"github\", \"url\"]),\n repo: z.string().exactOptional(),\n url: z.string().exactOptional(),\n ref: z.string().exactOptional(),\n});\n\nconst marketplacePluginSchema: z.ZodType<MarketplacePlugin> = z.object({\n name: z.string().min(1),\n /** Local directory path (relative to pluginRoot) or remote source config */\n source: z.union([z.string(), marketplaceRemoteSourceSchema]),\n description: z.string().exactOptional(),\n version: z.string().exactOptional(),\n author: pluginAuthorSchema.exactOptional(),\n /** Lenient: external data may have any category string or none at all */\n category: z.string().exactOptional(),\n keywords: z.array(z.string()).exactOptional(),\n});\n\n// MarketplaceOwner aliases PluginAuthor (identical shape, both require name.min(1))\nconst marketplaceOwnerSchema: z.ZodType<MarketplaceOwner> = pluginAuthorSchema;\n\nconst marketplaceMetadataSchema: z.ZodType<MarketplaceMetadata> = z.object({\n /** Base directory for resolving plugin source paths (e.g., \"plugins/\") */\n pluginRoot: z.string().exactOptional(),\n});\n\n/**\n * What a marketplace name being refused says back, in place of the pattern it was tested against.\n *\n * A raw Zod format issue names the regex, which tells a marketplace author what the CLI checks\n * with and nothing about what to write instead. The rule is spelled the way\n * `marketplaceNameNotPublishable` in `utils/messages.ts` already spells it on the emit side, so\n * the two directions of one rule cannot come to say different things about it.\n *\n * Stated as a `message` on the `regex` check rather than in a `refine`, deliberately: a refinement\n * is unrepresentable in JSON Schema, so `src/schemas/marketplace.schema.json` would silently lose\n * the `pattern` an editor validates `marketplace.json` against.\n */\nconst MARKETPLACE_NAME_REFUSAL =\n \"A marketplace name is kebab-case: lowercase letters, numbers and hyphens, starting with a letter (e.g. 'acme-skills'). Rename it in this manifest — Claude Code registers every plugin under it and accepts no other shape.\";\n\nexport const marketplaceSchema: z.ZodType<Marketplace> = z.object({\n $schema: z.string().exactOptional(),\n /**\n * Kebab-case, because this name is the namespace Claude Code registers plugins under and the\n * CLI piggybacks on what Claude Code accepts (owner ruling 2026-08-20). Held to the same rule\n * `build marketplace` refuses to publish under, so what this CLI emits is what it can read back.\n */\n name: z.string().min(1).regex(KEBAB_CASE_PATTERN, { message: MARKETPLACE_NAME_REFUSAL }),\n version: z.string().min(1),\n description: z.string().exactOptional(),\n owner: marketplaceOwnerSchema,\n metadata: marketplaceMetadataSchema.exactOptional(),\n plugins: z.array(marketplacePluginSchema).min(1),\n});\n\n/**\n * What a cached remote source was fetched from, written beside the cache so the\n * next load can ask whether it is still current in one request.\n *\n * `etag` is absent when the host returned none — a copy that cannot be\n * revalidated at all, which is a different state from one that has not been\n * checked yet.\n */\nexport const sourceRevalidationSchema = z.object({\n /** The tarball URL giget resolved for this source. */\n tar: z.string().min(1),\n etag: z.string().min(1).exactOptional(),\n});\n\n/** Tool permission overrides (allow/deny lists for Claude Code tool access) */\nconst permissionConfigSchema = z.object({\n /** Tool names or patterns to explicitly allow */\n allow: z.array(z.string()).exactOptional(),\n /** Tool names or patterns to explicitly deny */\n deny: z.array(z.string()).exactOptional(),\n});\n\n/** Settings file schema (.claude/settings.yaml) for project-level configuration */\nexport const settingsFileSchema = z\n .object({\n permissions: permissionConfigSchema.exactOptional(),\n })\n .passthrough();\n\n/** Branding overrides for white-labeling the CLI */\nconst brandingConfigSchema = z.object({\n /** Custom CLI name (e.g., \"Acme Dev Tools\") */\n name: z.string().exactOptional(),\n});\n\n/** The shape {@link projectSourceConfigSchema} admits once the rename guard has passed. */\nconst projectSourceConfigFields = z\n .object({\n /** The marketplace this install reads skills from, as a path or URL */\n marketplace: z.string().exactOptional(),\n /** Author handle for this project's config */\n author: z.string().exactOptional(),\n /** The name that marketplace's manifest gives it, which plugins are registered under */\n marketplaceName: z.string().exactOptional(),\n /** Separate source for agent definitions (when different from skills) */\n agentsSource: z.string().exactOptional(),\n /** Branding overrides for white-labeling the CLI */\n branding: brandingConfigSchema.exactOptional(),\n /** Custom skills directory override (default: \"src/skills\") */\n skillsDir: z.string().exactOptional(),\n /** Custom agents directory override (default: \"src/agents\") */\n agentsDir: z.string().exactOptional(),\n /** Custom stacks file path override (default: \"config/stacks.ts\") */\n stacksFile: z.string().exactOptional(),\n /** Custom categories file path override (default: \"config/skill-categories.ts\") */\n categoriesFile: z.string().exactOptional(),\n /** Custom rules file path override (default: \"config/skill-rules.ts\") */\n rulesFile: z.string().exactOptional(),\n })\n .passthrough();\n\n/**\n * Project source configuration from .claude-src/config.ts.\n * Stores multi-source settings, custom directory overrides, and bound skills.\n */\nexport const projectSourceConfigSchema = renamedFieldGuard.pipe(projectSourceConfigFields);\n\n// Strict validation schemas enforce all constraints and use .strict() to reject unknown fields,\n// unlike the lenient loader schemas above which use .passthrough() for forward compatibility at parse boundaries\n\n/** Strict schema for compiled agent metadata.yaml output. Lenient id (any string) since marketplace agents may use custom identifiers. */\nexport const agentYamlGenerationSchema = z\n .object({\n $schema: z.string().exactOptional(),\n id: z.string().min(1),\n title: z.string().min(1),\n description: z.string().min(1),\n model: modelNameSchema.exactOptional(),\n effort: effortLevelSchema.exactOptional(),\n tools: z.array(z.string()).min(1),\n disallowedTools: z.array(z.string()).exactOptional(),\n permissionMode: permissionModeSchema.exactOptional(),\n hooks: strictHooksRecordSchema.exactOptional(),\n outputFormat: z.string().exactOptional(),\n domain: (z.string() as z.ZodType<Domain>).exactOptional(),\n custom: z.boolean().exactOptional(),\n })\n .strict();\n\n/** Strict validation for agent AGENT.md frontmatter (used by plugin-validator) */\nexport const agentFrontmatterValidationSchema = z\n .object({\n /** Agent name in kebab-case (becomes the Task tool identifier) */\n name: z.string().regex(KEBAB_CASE_PATTERN).min(1),\n description: z.string().min(1),\n /** Comma-separated list of allowed tools */\n tools: z.string().exactOptional(),\n /** Comma-separated list of denied tools */\n disallowedTools: z.string().exactOptional(),\n model: modelNameSchema.exactOptional(),\n effort: effortLevelSchema.exactOptional(),\n permissionMode: permissionModeSchema.exactOptional(),\n /** Skill names to preload (embed in agent prompt) */\n skills: z.array(z.string().min(1)).exactOptional(),\n hooks: strictHooksRecordSchema.exactOptional(),\n })\n .strict();\n\n/** Strict validation for SKILL.md frontmatter (matches Claude Code plugin spec) */\nexport const skillFrontmatterValidationSchema = z\n .object({\n name: z.string().min(1),\n description: z.string().min(1),\n /** If true, Claude cannot invoke this skill on its own */\n \"disable-model-invocation\": z.boolean().exactOptional(),\n /** If true, user can invoke this skill directly */\n \"user-invocable\": z.boolean().exactOptional(),\n /** Comma-separated list of tools this skill can use */\n \"allowed-tools\": z.string().exactOptional(),\n model: modelNameSchema.exactOptional(),\n /** \"fork\" means skill runs in a forked context (separate conversation) */\n context: z.enum([\"fork\"]).exactOptional(),\n /** Agent name this skill is scoped to */\n agent: z.string().exactOptional(),\n /** Hint text shown when user invokes the skill */\n \"argument-hint\": z.string().exactOptional(),\n })\n .strict();\n\n/**\n * Provenance object shared verbatim by metadataValidationSchema and\n * customMetadataValidationSchema. The forkedFrom variant in\n * localSkillMetadataSchema (no `version`) is deliberately NOT unified here —\n * its shape differs, so sharing would change validation behavior.\n */\nconst forkedFromSchema = z.object({\n /** Original skill ID */\n skillId: z.string(),\n /** Version of the original at fork time */\n version: z.number().int().min(1).exactOptional(),\n /** Content hash of the original at fork time */\n contentHash: z.string(),\n /** Source URL or identifier */\n source: z.string().exactOptional(),\n /** Directory inside that source, for a skill only its own bytes can install again */\n path: z.string().exactOptional(),\n /** ISO date of the fork */\n date: z.string(),\n});\n\n/**\n * Recommended upper bound for cliDescription in published skills. Exceeding it is\n * advisory only — splitMetadataValidationIssues downgrades it to a warning because\n * the runtime schemas accept any length and the value only feeds wizard description\n * text. Empty (min(1)) remains a hard error.\n */\nconst CLI_DESCRIPTION_MAX_LENGTH = 60;\n\n/**\n * Fields shared by metadataValidationSchema (strict, built-in vocabulary) and\n * customMetadataValidationSchema (relaxed). Only `category` and `slug` differ\n * between the two variants — each adds those via .extend().\n */\nconst skillMetadataBaseSchema = z.object({\n /** Author handle — must start with @ (e.g., \"@vince\") */\n author: z.string().regex(AUTHOR_HANDLE_PATTERN),\n /** Short display name for the wizard grid (max 30 chars) */\n displayName: z.string().min(1).max(30),\n /** One-line description for the wizard (max 60 chars recommended; over-length is a validation warning) */\n cliDescription: z.string().min(1).max(CLI_DESCRIPTION_MAX_LENGTH),\n /** When an AI agent should invoke this skill (min 10 chars to ensure usefulness) */\n usageGuidance: z.string().min(10),\n /** 7-char hex SHA of skill content (for change detection) */\n contentHash: z\n .string()\n .regex(/^[a-f0-9]{7}$/)\n .exactOptional(),\n /** ISO date of last update */\n updated: z.string().exactOptional(),\n /** Provenance tracking when skill was forked from another */\n forkedFrom: forkedFromSchema.exactOptional(),\n /** Domain assignment from metadata */\n domain: (z.string() as z.ZodType<Domain>).exactOptional(),\n /** True if this skill was created outside the CLI's built-in vocabulary */\n custom: z.boolean().exactOptional(),\n});\n\n/**\n * What a published skill's `slug` says back when the public catalogue does not carry it, in\n * place of the whole generated slug union it was tested against.\n *\n * The same defect `unknownSkillSlugRefusal` answers one layer over, and the one an author meets\n * FIRST: they write a `metadata.yaml` before they write a rule. Zod's text for an enum reports\n * the options and never the input, so a marketplace author naming a skill they themselves ship\n * was handed roughly 250 names belonging to somebody else with their own slug missing from it.\n *\n * It differs from the rules-side message in the one way that matters: this refusal has a way\n * out and that one does not. `validateSkillMetadata` reads `custom: true` and validates against\n * `customMetadataValidationSchema`, whose `slug` is any kebab-case name — so the flag is what a\n * skill outside the catalogue's vocabulary is CARRIED by rather than a way around the check\n * (owner ruling 2026-08-22: the union stays closed and `custom: true` is the documented\n * mechanism). Nothing said so until now, which is the whole of what made it read as a trick.\n */\nfunction unknownMetadataSlugRefusal(input: unknown): string {\n const named = typeof input === \"string\" ? `'${input}'` : \"That value\";\n return (\n `${named} is not a slug the public catalogue carries. A published skill's slug is held to ` +\n `that catalogue unless the skill declares it is not from it — add '${METADATA_KEYS.CUSTOM}: true' ` +\n `beside it in this ${STANDARD_FILES.METADATA_YAML} and the slug is read as your marketplace's ` +\n `own, any kebab-case name. That declaration is how a skill outside the catalogue's vocabulary ` +\n `is carried; a skill the catalogue does carry names its catalogue slug and leaves it off.`\n );\n}\n\n/** Strict validation for metadata.yaml in published skills (enforces author format, enum-validated category/slug) */\nexport const metadataValidationSchema = skillMetadataBaseSchema\n .extend({\n /** Domain-prefixed category — must be a known built-in category */\n category: z.enum(CATEGORIES),\n /**\n * Kebab-case short key — must be a known built-in slug, unless the file declares\n * `custom: true` and is judged by {@link customMetadataValidationSchema} instead.\n */\n slug: z.enum(SKILL_SLUGS, {\n error: (issue) => unknownMetadataSlugRefusal(issue.input),\n }),\n })\n .strict();\n\n/** Relaxed validation for custom skill metadata.yaml (any category string, kebab-case slug, allows extra fields) */\nexport const customMetadataValidationSchema = skillMetadataBaseSchema.extend({\n /** Any string category — custom skills may define their own categories */\n category: z.string(),\n /** Kebab-case short key for alias resolution, search, and relationship rules */\n slug: z.string().regex(KEBAB_CASE_PATTERN).min(1).max(50),\n});\n\nconst stackSkillAssignmentSchema = z\n .object({\n id: z.string().min(1),\n /** If true, skill content is embedded in the compiled agent prompt */\n preloaded: z.boolean().exactOptional(),\n })\n .strict();\n\n/** Strict validation for published stack config.yaml (marketplace stacks) */\nexport const stackConfigValidationSchema = z\n .object({\n /** Unique stack identifier in kebab-case */\n id: z.string().regex(KEBAB_CASE_PATTERN).exactOptional(),\n name: z.string().min(1),\n version: z.string(),\n author: z.string().min(1),\n description: z.string().exactOptional(),\n /** ISO date when this stack was first created */\n created: z.string().exactOptional(),\n /** ISO date of last update */\n updated: z.string().exactOptional(),\n /** Primary framework this stack is designed for (e.g., \"nextjs\", \"remix\") */\n framework: z.string().exactOptional(),\n /** All skills used in this stack (flat list, at least one required) */\n skills: z.array(stackSkillAssignmentSchema).min(1),\n /** Agent IDs this stack compiles (at least one required) */\n agents: z.array(z.string().regex(KEBAB_CASE_PATTERN)).min(1),\n /** Per-agent skill assignments: { agentId: { category: [skillAssignment] } } */\n agentSkills: z\n .record(z.string(), z.record(z.string(), z.array(stackSkillAssignmentSchema)))\n .exactOptional(),\n /** High-level philosophy guiding technology choices */\n philosophy: z.string().exactOptional(),\n /** Guiding principles for agents using this stack */\n principles: z.array(z.string().min(1)).exactOptional(),\n tags: z.array(z.string().regex(KEBAB_CASE_PATTERN)).exactOptional(),\n /** Per-skill overrides: alternative suggestions and lock status */\n overrides: z\n .record(\n z.string(),\n z\n .object({\n /** Suggested alternative skill IDs if this one is swapped */\n alternatives: z.array(z.string().min(1)).exactOptional(),\n /** If true, this skill cannot be swapped by the user */\n locked: z.boolean().exactOptional(),\n })\n .strict(),\n )\n .exactOptional(),\n /** Community metrics for sorting/ranking */\n metrics: z\n .object({\n upvotes: z.number().int().min(0).exactOptional(),\n downloads: z.number().int().min(0).exactOptional(),\n })\n .strict()\n .exactOptional(),\n /** Lifecycle hooks triggered by file changes or commands */\n hooks: strictHooksRecordSchema.exactOptional(),\n })\n .strict();\n\n/** Format Zod validation issues into a human-readable string (e.g., \"path.to.field: Expected string; other: Required\") */\nexport function formatZodIssues(issues: z.ZodIssue[]): string {\n return issues.map(formatZodIssue).join(\"; \");\n}\n\n/**\n * Validates raw skill metadata using the relaxed schema for custom skills and\n * the strict schema for built-ins — the one place the custom-vs-strict\n * selection policy lives.\n */\nexport function validateSkillMetadata(rawMetadata: unknown) {\n const schema = isCustomMetadata(rawMetadata)\n ? customMetadataValidationSchema\n : metadataValidationSchema;\n return schema.safeParse(rawMetadata);\n}\n\n/**\n * Names a metadata.yaml's schema failure in the words its author needs: the required\n * fields the file leaves out, listed as missing, and whatever else is wrong said per\n * field. Zod's own text for an absent key reads \"expected string, received undefined\",\n * which describes the type system rather than the file.\n */\nexport function describeMetadataSchemaFailure(\n issues: z.ZodIssue[],\n rawMetadata: Record<string, unknown>,\n): string {\n const [absent, malformed] = partition(issues, (issue) => isAbsentField(issue, rawMetadata));\n return [\n ...(absent.length > 0 ? [nameMissingFields(absent)] : []),\n ...malformed.map(formatZodIssue),\n ].join(\"; \");\n}\n\n/** True for a top-level field the file never declared, as against one it declared wrongly. */\nfunction isAbsentField(issue: z.ZodIssue, rawMetadata: Record<string, unknown>): boolean {\n const [field, ...nested] = issue.path;\n return nested.length === 0 && typeof field === \"string\" && rawMetadata[field] === undefined;\n}\n\nfunction nameMissingFields(absent: z.ZodIssue[]): string {\n const fields = absent.map((issue) => issue.path.join(\".\"));\n return `missing required ${fields.length === 1 ? \"field\" : \"fields\"}: ${fields.join(\", \")}`;\n}\n\nexport type MetadataIssueSplit = {\n /** Hard schema violations — the metadata is broken and must be fixed */\n errors: string[];\n /** Advisory violations (over-length cliDescription) — worth fixing, never fatal */\n warnings: string[];\n};\n\n/** True for the over-length `cliDescription` issue — the only advisory metadata violation. */\nfunction isOverLengthCliDescription(issue: z.ZodIssue): boolean {\n return issue.code === \"too_big\" && issue.path.length === 1 && issue.path[0] === \"cliDescription\";\n}\n\n/** Reads `cliDescription` from raw parsed metadata when it is a string. */\nfunction readCliDescription(raw: unknown): string | undefined {\n if (raw == null || typeof raw !== \"object\") return undefined;\n // Boundary cast: raw comes straight from YAML parsing; the typeof check above narrows to object\n const value = (raw as { cliDescription?: unknown }).cliDescription;\n return typeof value === \"string\" ? value : undefined;\n}\n\n/**\n * Warning text for an over-length `cliDescription`, carrying the actual length.\n * The too_big issue only fires when the value is a string, so the undefined\n * branch is defensive — it falls back to the raw zod issue text.\n */\nfunction formatOverLengthWarning(issue: z.ZodIssue, cliDescription: string | undefined): string {\n if (cliDescription === undefined) return formatZodIssue(issue);\n return `cliDescription is ${cliDescription.length} characters — exceeds the recommended maximum of ${CLI_DESCRIPTION_MAX_LENGTH}`;\n}\n\n/**\n * Splits strict-metadata validation issues into hard errors and advisory warnings.\n *\n * Over-length `cliDescription` (> CLI_DESCRIPTION_MAX_LENGTH chars) is advisory: the\n * runtime schemas accept any length and the value only feeds wizard description text,\n * so validate reports it as a warning carrying the actual length. Empty/missing\n * `cliDescription` and every other issue remain errors.\n */\nexport function splitMetadataValidationIssues(\n error: z.ZodError,\n rawMetadata: unknown,\n): MetadataIssueSplit {\n const [overLength, hardFailures] = partition(error.issues, isOverLengthCliDescription);\n\n const cliDescription = readCliDescription(rawMetadata);\n const warnings = overLength.map((issue) => formatOverLengthWarning(issue, cliDescription));\n\n return { errors: hardFailures.map(formatZodIssue), warnings };\n}\n\n/**\n * Validates that a parsed JSON/YAML value does not exceed a maximum nesting depth.\n * Returns true if the structure is within limits, false if it exceeds maxDepth.\n */\nexport function validateNestingDepth(value: unknown, maxDepth: number): boolean {\n function check(val: unknown, depth: number): boolean {\n if (depth > maxDepth) return false;\n if (Array.isArray(val)) {\n return val.every((item) => check(item, depth + 1));\n }\n if (val !== null && typeof val === \"object\") {\n return Object.values(val).every((v) => check(v, depth + 1));\n }\n return true;\n }\n return check(value, 0);\n}\n\n/**\n * Returns true when raw parsed metadata has `custom: true`.\n * Used to pick between strict (built-in vocabulary) and relaxed (user-authored) validation schemas.\n */\nexport function isCustomMetadata(raw: unknown): boolean {\n if (raw == null || typeof raw !== \"object\") return false;\n if (!(\"custom\" in raw)) return false;\n return raw.custom === true;\n}\n\n/**\n * Logs warnings for unknown fields in a parsed object compared to a list of expected keys.\n * Used at security-critical parsing boundaries for files this CLI owns (marketplace.json), where\n * `.passthrough()` is kept for forward compatibility but unexpected fields should be surfaced.\n * A file owned by another tool is not such a boundary: an unfamiliar key there is that tool's\n * business, and a complete expected-key list for it cannot be maintained.\n */\nexport function warnUnknownFields(\n parsed: Record<string, unknown>,\n expectedKeys: readonly string[],\n context: string,\n): void {\n const expectedSet = new Set(expectedKeys);\n const unknownKeys = Object.keys(parsed).filter((k) => !expectedSet.has(k));\n if (unknownKeys.length > 0) {\n warn(`Unknown fields in ${context}: ${unknownKeys.join(\", \")}`);\n }\n}\n","import { z } from \"zod\";\n\n/** One place for the path-prefixed issue rendering shared by every Zod reporter. */\nexport function formatZodIssue(issue: z.ZodIssue): string {\n const path = issue.path.join(\".\");\n if (issue.code === \"unrecognized_keys\") {\n return `Unrecognized key: \"${issue.keys.join('\", \"')}\"`;\n }\n return path ? `${path}: ${issue.message}` : issue.message;\n}\n\nexport function formatZodErrors(error: z.ZodError): string[] {\n return error.issues.map(formatZodIssue);\n}\n","// Vendored byte-for-byte into packages/matrix/src/vendor/ by scripts/generate-matrix-package.ts.\n// ANY edit here — a comment-only one included — obliges `bun run generate:matrix` in packages/cli;\n// `generate:matrix:check` is the gate.\n\nimport type { CategoryPath, SkillSlug, SkillId } from \"./skills\";\nimport type { AgentName } from \"./agents\";\n\nexport type { Category, Domain } from \"./generated/source-types\";\nexport { CATEGORIES, DOMAINS } from \"./generated/source-types\";\n\n// Import locally for use within this file\nimport type { Category, Domain } from \"./generated/source-types\";\n\n/** Claude model selectors for agent configuration */\nexport const MODEL_NAMES = [\"sonnet\", \"opus\", \"haiku\", \"fable\", \"inherit\"] as const;\nexport type ModelName = (typeof MODEL_NAMES)[number];\n\n/** Reasoning effort levels for agent configuration */\nexport const EFFORT_NAMES = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\nexport type EffortLevel = (typeof EFFORT_NAMES)[number];\n\n/** Agent permission modes for Claude Code tool access */\nexport const PERMISSION_MODES = [\n \"default\",\n \"acceptEdits\",\n \"dontAsk\",\n \"bypassPermissions\",\n \"plan\",\n \"delegate\",\n] as const;\nexport type PermissionMode = (typeof PERMISSION_MODES)[number];\n\n/**\n * Category definitions indexed by category ID.\n * Partial because not every Category has a category definition (e.g., a marketplace\n * may only define a subset of all possible categories).\n */\nexport type CategoryMap = Partial<Record<Category, CategoryDefinition>>;\n\n/**\n * Full domain selections used throughout the wizard pipeline (store, components, result).\n *\n * Structure: `{ domain: { category: [skillId, ...] } }`\n *\n * - Outer Partial: not all domains need selections (user may skip \"mobile\" entirely)\n * - Inner Partial: within a domain, only some categories may have selections\n * - SkillId[]: a category can have multiple skills unless `CategoryDefinition.exclusive` is true\n */\nexport type DomainSelections = Partial<Record<Domain, Partial<Record<Category, SkillId[]>>>>;\n\n/** Single category definition from skill-categories.ts */\nexport type CategoryDefinition = {\n id: Category;\n displayName: string;\n description: string;\n /** Domain for wizard domain filtering */\n domain?: Domain;\n /** If true, only one skill can be selected in this category (radio behavior). */\n exclusive: boolean;\n /** Display order within domain (lower = earlier) */\n order: number;\n icon?: string;\n};\n\n/** Relationship rules between skills from skill-rules.ts */\nexport type RelationshipDefinitions = {\n /** Selecting one disables the others */\n conflicts: ConflictRule[];\n /** Selecting one shows warning for others but doesn't disable */\n discourages: DiscourageRule[];\n /** Skill A requires skill B to be selected first */\n requires: RequireRule[];\n /** Groups of interchangeable skills for the same purpose */\n alternatives: AlternativeGroup[];\n};\n\n/** Base shape for skill-group rules: a set of related slugs plus a reason */\nexport type SkillGroupRule = {\n /** Skill slugs (resolved to canonical IDs by matrix-loader) */\n skills: SkillSlug[];\n reason: string;\n};\n\n/** Mutual exclusion rule - selecting any one skill disables ALL others */\nexport type ConflictRule = SkillGroupRule;\n\n/** Soft conflict rule - selecting any one shows a warning for ALL others */\nexport type DiscourageRule = SkillGroupRule;\n\n/** Dependency rule - skill A requires skill B to be selected first */\nexport type RequireRule = {\n skill: SkillSlug;\n /** Skill slugs that must be selected before this one */\n needs: SkillSlug[];\n /**\n * If true, only ONE of the `needs` skills is required (OR logic).\n * If false/undefined, ALL are required (AND logic).\n * @default false\n */\n needsAny?: boolean;\n reason: string;\n};\n\n/** Group of interchangeable skills serving the same purpose */\nexport type AlternativeGroup = {\n purpose: string;\n skills: SkillSlug[];\n};\n\n/** Parsed configuration from skill-rules.ts */\nexport type SkillRulesConfig = {\n version: string;\n /** Aggregate relationship rules between skills */\n relationships: RelationshipDefinitions;\n};\n\n/**\n * Slug -> canonical skill ID. Partial because only extracted skills are present.\n *\n * One direction, not two. A reverse `idToSlug` was carried here until 2026-08-23 and had **zero\n * readers anywhere** — every occurrence was a write, and the only thing consuming it was the\n * duplicate-slug asymmetry it made possible. A map nothing reads cannot be out of step with the\n * one that is read, so deleting it retires that whole class rather than guarding it.\n */\nexport type SkillSlugMap = {\n /** Forward: slug -> canonical skill ID */\n slugToId: Partial<Record<SkillSlug, SkillId>>;\n};\n\n/**\n * Output of mergeMatrixWithSkills() combining skill-categories.ts + skill-rules.ts with extracted metadata.\n * This is the primary read model consumed by the wizard and CLI commands.\n */\nexport type MergedSkillsMatrix = {\n version: string;\n categories: CategoryMap;\n /** Indexed by full skill ID for O(1) lookup */\n skills: Partial<Record<SkillId, ResolvedSkill>>;\n /** Stacks with all skill aliases resolved to canonical IDs */\n suggestedStacks: ResolvedStack[];\n /** Bidirectional slug <-> ID mapping */\n slugMap: SkillSlugMap;\n /**\n * Slugs the relationship rules name that no skill in this matrix carries.\n * Absent when every reference resolved. Resolution drops such a reference and\n * warns; carrying the list is what lets `checkMatrixHealth` report the typo\n * against the source that shipped it rather than only logging it.\n */\n unresolvedSlugs?: SkillSlug[];\n /** Explicit domain definitions from agent metadata files */\n agentDefinedDomains?: Partial<Record<AgentName, Domain>>;\n /** ISO timestamp of when this matrix was generated */\n generatedAt: string;\n};\n\n/**\n * Identity/description fields shared by ExtractedSkillMetadata (pre-merge) and\n * ResolvedSkill (post-merge). Both types are `SkillCore & { extras }`; extracting\n * the common shape keeps the two skill surfaces in sync. Purely structural — no\n * runtime change (the intersection is equivalent to the flattened object).\n */\nexport type SkillCore = {\n id: SkillId;\n /** Kebab-case short key for alias resolution, search, and relationship rules (e.g., \"react\") */\n slug: SkillSlug;\n /** Title-cased label for UI display (e.g., \"React\", \"Apollo Client\") */\n displayName: string;\n description: string;\n /** When an AI agent should invoke this skill (decision criteria) */\n usageGuidance?: string;\n /** Matches key in matrix.categories; determines which wizard category grid this skill appears in */\n category: CategoryPath;\n /** Author handle (e.g., \"@vince\") from metadata.yaml */\n author: string;\n /** Relative path from src/ to the skill directory */\n path: string;\n /** True if from .claude/skills/ (user-defined local skill) */\n local?: boolean;\n /** Absolute path to local skill directory */\n localPath?: string;\n /** True if this skill was created outside the CLI's built-in vocabulary */\n custom?: boolean;\n};\n\n/**\n * Single skill with all computed relationships resolved for CLI rendering.\n * Produced by mergeMatrixWithSkills() after resolving aliases, relationships, and sources.\n */\nexport type ResolvedSkill = SkillCore & {\n /** Selecting this skill disables these others (hard exclusion) */\n conflictsWith: SkillRelation[];\n /** Skills that THIS skill requires (must select first) */\n requires: SkillRequirement[];\n /** Other skills that serve the same purpose (informational, not enforced) */\n alternatives: SkillAlternative[];\n /** Selecting this skill shows a warning for these others (soft conflict) */\n discourages: SkillRelation[];\n /** All known sources that provide this skill (populated by multi-source-loader) */\n availableSources?: SkillSource[];\n /** Currently active/installed source (if any) */\n activeSource?: SkillSource;\n};\n\n/** Skill-to-skill relationship with reason */\nexport type SkillRelation = {\n skillId: SkillId;\n reason: string;\n};\n\n/** Resolved skill dependency with AND/OR logic */\nexport type SkillRequirement = {\n skillIds: SkillId[];\n /**\n * If true, only ONE of skillIds is needed (OR).\n * If false, ALL are needed (AND).\n *\n * Always present. The absence this field could have carried is resolved one step upstream:\n * `resolveRelationships` in `lib/matrix/skill-resolution.ts` writes\n * `rule.needsAny ?? false` from the optional {@link RequireRule.needsAny}, so nothing\n * downstream of resolution ever meets an unset value.\n */\n needsAny: boolean;\n reason: string;\n};\n\n/** Alternative skill that serves the same purpose */\nexport type SkillAlternative = {\n skillId: SkillId;\n purpose: string;\n};\n\n/** Stack with resolved skill IDs and agent mappings */\nexport type ResolvedStack = {\n id: string;\n name: string;\n description: string;\n /** Skill selections with resolved full skill IDs by category */\n skills: Partial<Record<AgentName, Partial<Record<Category, SkillId[]>>>>;\n /** Flat list of all skill IDs in this stack */\n allSkillIds: SkillId[];\n philosophy: string;\n /** UI grouping label for the stack selection screen (e.g., \"React\", \"CLI\") */\n group?: string;\n};\n\n/** Short alias used for category-level search (e.g., \"react\", \"zustand\") */\nexport type SkillAlias = string;\n\n/** Source type classification for skill provenance (where the skill comes from) */\nexport const SKILL_SOURCE_TYPES = [\"public\", \"private\", \"local\"] as const;\nexport type SkillSourceType = (typeof SKILL_SOURCE_TYPES)[number];\n\n/**\n * How a project's skills are installed: fully ejected, fully plugin-based, or a\n * mix of both. Derived at runtime from SkillConfig.origin (see deriveInstallMode).\n */\nexport type InstallMode = \"eject\" | \"plugin\" | \"mixed\";\n\n/** A single source from which a skill can be obtained */\nexport type SkillSource = {\n /** Source identifier: \"public\", marketplace name, \"local\" */\n name: string;\n type: SkillSourceType;\n /** Source URL for remote sources (e.g., \"github:acme-corp/claude-skills\") */\n url?: string;\n /** Whether this source's version is currently installed on disk */\n installed: boolean;\n /** How the skill was installed on disk (separate from provenance) — a single skill is never \"mixed\" */\n installMode?: Exclude<InstallMode, \"mixed\">;\n /** True for the primary marketplace source (scoped or default public). Set by multi-source-loader. */\n primary?: boolean;\n};\n\n/** Advisory visual state for a skill option in the wizard UI */\nexport type OptionState =\n | { status: \"normal\" }\n | { status: \"discouraged\"; reason: string }\n | { status: \"incompatible\"; reason: string };\n\n/**\n * Skill option as displayed in the wizard, computed based on current selections.\n * Recomputed by matrix-resolver on every selection change.\n */\nexport type SkillOption = {\n id: SkillId;\n /** True if this skill is currently selected by the user */\n selected: boolean;\n /** True when this skill is selected but has unmet dependency requirements */\n hasUnmetRequirements: boolean;\n /** Explains which requirements are unmet (only set when hasUnmetRequirements is true) */\n unmetRequirementsReason?: string;\n};\n\n/** Result of validating the current skill selections */\nexport type SelectionValidation = {\n valid: boolean;\n errors: ValidationError[];\n};\n\n/** Advisory validation error (non-blocking) */\nexport type ValidationError = {\n type: \"conflict\" | \"missingRequirement\" | \"categoryExclusive\";\n message: string;\n skills: SkillId[];\n};\n\n/**\n * Skill metadata extracted from SKILL.md frontmatter + metadata.yaml before matrix merge.\n *\n * Relationship fields (conflictsWith, requires, etc.) are resolved from\n * centralized group-based declarations in skill-rules.ts — not from individual skill metadata.\n */\nexport type ExtractedSkillMetadata = SkillCore & {\n /** Directory path for filesystem access, e.g. \"web/framework/react\" */\n directoryPath: string;\n /** Domain this skill belongs to (e.g., \"web\", \"api\", \"cli\") */\n domain: Domain;\n};\n","import path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { createJiti } from \"jiti\";\nimport { fileExists } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { isRecord } from \"../../utils/type-guards\";\nimport { formatZodIssues } from \"../schemas\";\nimport type { z } from \"zod\";\n\n/** Resolve agents-inc/config to the source config-exports.ts so jiti can load it in dev. */\nconst CONFIG_EXPORTS_PATH = path.resolve(\n path.dirname(fileURLToPath(import.meta.url)),\n \"../../config-exports.ts\",\n);\n\n/**\n * Thrown when a config file evaluated cleanly but the schema refused its SHAPE.\n *\n * Named apart from the generic load failure because the two mean different things to a caller:\n * a file that cannot be evaluated says only that something is broken, while a refused shape has\n * said exactly what is wrong with a file the user still owns. A loader may reasonably report the\n * first as \"no config\"; reporting the second that way is how a config carrying a stale key ends\n * up silently repointing an install at the default marketplace.\n */\nexport class ConfigSchemaError extends Error {\n constructor(\n readonly configPath: string,\n readonly issues: string,\n ) {\n super(`Config validation failed at '${configPath}': ${issues}`);\n this.name = \"ConfigSchemaError\";\n }\n}\n\n/**\n * Thrown when a config file evaluated cleanly and exported bindings, none of which is the default\n * one every config in this project is read out of.\n *\n * Distinct from {@link ConfigSchemaError} because the two fault different lines of the file. A\n * refused shape names a field the author can go and correct; a module that exports\n * `export const skillRules = {...}` has nothing wrong with its contents at all, and validating\n * the module NAMESPACE against the schema is what told such an author their `version` was missing\n * from a file they can see it in.\n */\nexport class ConfigDefaultExportError extends Error {\n constructor(readonly configPath: string) {\n super(`Config at '${configPath}' has no default export`);\n this.name = \"ConfigDefaultExportError\";\n }\n}\n\n/**\n * The marker every ES module jiti transpiles carries, and a CommonJS one does not. It is the only\n * thing separating `export const x = {}` — a namespace whose keys are named exports — from\n * `module.exports = { x: {} }`, whose keys ARE the default export: both arrive here as a plain\n * object with no `default` key.\n */\nconst ES_MODULE_MARKER = \"__esModule\";\n\n/**\n * The default export, or the namespace when there is none — jiti documents `import(id, { default:\n * true })` as exactly this, and the namespace is imported whole here because the option throws the\n * distinction away and {@link ConfigDefaultExportError} is made of it.\n */\nfunction unwrapDefaultExport(namespace: unknown): unknown {\n if (isRecord(namespace) && namespace.default !== undefined) return namespace.default;\n return namespace;\n}\n\n/** An ES module that exports bindings, none of them the default one. */\nfunction declaresNoDefaultExport(namespace: unknown): boolean {\n return isRecord(namespace) && ES_MODULE_MARKER in namespace && !(\"default\" in namespace);\n}\n\n/** Nothing was exported: an empty file, `export {}`, or a default export with no keys. */\nfunction exportsNothing(value: unknown): boolean {\n return value == null || (typeof value === \"object\" && Object.keys(value).length === 0);\n}\n\n/**\n * Loads a TypeScript config file using jiti.\n * Returns null when the file does not exist, and when it exists but exports nothing.\n * Throws {@link ConfigDefaultExportError} for a module whose exports are all named,\n * {@link ConfigSchemaError} on validation failure, and a plain Error for a malformed/broken file.\n *\n * @param configPath - Absolute path to the .ts config file\n * @param schema - Optional Zod schema; when provided, T is inferred from it\n */\nexport async function loadConfig<T>(configPath: string, schema?: z.ZodType<T>): Promise<T | null> {\n if (!(await fileExists(configPath))) {\n verbose(`Config not found at ${configPath}`);\n return null;\n }\n\n let namespace: unknown;\n try {\n // A fresh engine per call, and the module cache stays off, because one run both writes a\n // config and reads it back: `init` writes `config.ts`, loads it, writes it again and loads\n // it twice more, and `compile` re-reads that same file from every path that needs it —\n // installation detection, source resolution, each stack warning, the recompile, and the\n // config-types refresh. A cache spanning a run would answer each read that follows a write\n // with the module as it stood BEFORE it, which is a config the user never wrote. What the\n // cache would save has never been measured, and its ceiling is a few hundred milliseconds\n // on a command already waiting on the network and the disk.\n const jiti = createJiti(import.meta.url, {\n moduleCache: false,\n interopDefault: true,\n alias: { \"agents-inc/config\": CONFIG_EXPORTS_PATH },\n });\n\n namespace = await jiti.import(configPath);\n } catch (error) {\n throw new Error(`Failed to load config from '${configPath}': ${getErrorMessage(error)}`, {\n cause: error,\n });\n }\n\n const raw = unwrapDefaultExport(namespace);\n\n // Empty or whitespace-only files produce an empty module object. Treat this the same as a\n // missing file rather than returning a confusing empty object — and ask it BEFORE the export\n // question, because such a file declares no exports of any kind to have opinions about.\n if (exportsNothing(raw)) {\n verbose(`Config at ${configPath} exports nothing`);\n return null;\n }\n\n if (declaresNoDefaultExport(namespace)) {\n throw new ConfigDefaultExportError(configPath);\n }\n\n if (schema) {\n const result = schema.safeParse(raw);\n if (!result.success) {\n throw new ConfigSchemaError(configPath, formatZodIssues(result.error.issues));\n }\n return result.data;\n }\n\n // Boundary cast: jiti returns unknown, caller provides expected type\n return raw as T;\n}\n","import os from \"os\";\nimport path from \"path\";\nimport type { SkillScope } from \"../../types/config.js\";\nimport {\n CLAUDE_DIR,\n CLAUDE_SRC_DIR,\n LOCAL_SKILLS_PATH,\n STANDARD_DIRS,\n STANDARD_FILES,\n} from \"../../consts.js\";\n\n/**\n * Base directory for a scope's installed artifacts: the home directory for\n * `\"global\"` scope, the project directory otherwise (absent scope defaults to\n * project). Calls `os.homedir()` at runtime so test home-dir mocks apply.\n */\nexport function installBaseDir(projectDir: string, scope: SkillScope | undefined): string {\n return scope === \"global\" ? os.homedir() : projectDir;\n}\n\n/** Path to the unified project config (`<dir>/.claude-src/config.ts`). */\nexport function getProjectConfigPath(dir: string): string {\n return path.join(dir, CLAUDE_SRC_DIR, STANDARD_FILES.CONFIG_TS);\n}\n\nexport type InstallPaths = {\n skillsDir: string;\n agentsDir: string;\n configPath: string;\n};\n\nexport function resolveInstallPaths(\n projectDir: string,\n scope: SkillScope = \"project\",\n): InstallPaths {\n const baseDir = installBaseDir(projectDir, scope);\n return {\n skillsDir: path.join(baseDir, LOCAL_SKILLS_PATH),\n agentsDir: path.join(baseDir, CLAUDE_DIR, STANDARD_DIRS.AGENTS),\n configPath: getProjectConfigPath(baseDir),\n };\n}\n","import {\n AGENT_NAMES,\n isSeedScopePairWritable,\n resolveAssignment,\n resolveLoadState,\n seedAgentScope,\n SKILL_IDS,\n type LoadState,\n type SeedAgent,\n type SeedLoadState,\n type SeedPayload,\n type SkillTaxonomy,\n} from \"@workspace/matrix\"\nimport { groupBy, indexBy, partition } from \"remeda\"\n\nimport {\n byCategoryDeclarationOrder,\n categoryDomain,\n type CatalogSkill,\n type CompileCatalog,\n} from \"./catalog.js\"\nimport { seatedCatalog } from \"./catalog-seat.js\"\nimport { diagnostics } from \"./diagnostics.js\"\nimport { orderDomains } from \"./domain-order.js\"\nimport {\n CLI_INVOKE_COMMAND,\n DEFAULT_PUBLIC_SOURCE_NAME,\n EJECT_SOURCE,\n GLOBAL_CONFIG_NAME,\n LOCAL_PSEUDO_CATEGORY,\n} from \"./paths.js\"\nimport {\n activeAgentScopeMap,\n effectivelyExcludedSkillIds,\n isActiveAt,\n} from \"./scope-predicates.js\"\nimport { validateSelection } from \"./selection.js\"\nimport { typedEntries, typedFromEntries, typedKeys } from \"./typed-object.js\"\nimport type {\n AgentName,\n AgentScopeConfig,\n Category,\n CategoryPath,\n Domain,\n DomainSelections,\n ProjectConfig,\n SelectionValidation,\n SkillAssignment,\n SkillConfig,\n SkillId,\n SkillScope,\n Stack,\n StackAgentConfig,\n} from \"./types.js\"\n\nexport type SplitConfigResult = {\n global: ProjectConfig\n project: ProjectConfig\n}\n\nexport type ProjectConfigOptions = {\n description?: string\n author?: string\n}\n\n/** How many catalogue ids the verbose diagnostic names when a lookup misses. */\nconst MATRIX_SAMPLE_SIZE = 5\n\nfunction extractCategoryFromPath(\n categoryPath: CategoryPath\n): Category | undefined {\n if (categoryPath === LOCAL_PSEUDO_CATEGORY) return undefined\n // TypeScript narrows CategoryPath to Category after excluding \"local\"\n return categoryPath\n}\n\ntype StackBuildInputs = {\n agentList: AgentName[]\n activeSkillsByCategory: Map<Category, SkillId[]>\n skillScope: Map<SkillId, SkillScope>\n agentScope: Map<AgentName, SkillScope>\n existingStack: Partial<Record<AgentName, StackAgentConfig>>\n catalog: CompileCatalog\n /**\n * Skills that are new to this session's top-level selection (not in the prior\n * `existing.config.skills`). When `undefined`, the per-agent curation\n * preservation rule is disabled and every scope-compatible, resolver-relevant\n * skill lands on every existing agent (legacy behavior). When defined\n * (possibly empty), the preservation rule applies: skills NOT in an agent's\n * prior stack entry and NOT in this set are omitted from that agent's stack —\n * respecting the user's curation.\n */\n newlyAddedSkillIds?: ReadonlySet<SkillId>\n /**\n * Keys of `(agent, skillId)` pairs whose scope-compatibility was GAINED this\n * session — either the skill's scope was flipped so it now reaches this\n * agent, or the agent's scope was flipped so previously-filtered skills now\n * reach it. Parallel to `newlyAddedSkillIds`: when the caller opts into\n * per-agent curation preservation, this set admits triples that the skill-id\n * diff would miss. Keys are produced by `scopeEligibilityKey()`.\n */\n scopeEligibilityGained?: ReadonlySet<string>\n}\n\n/**\n * Encodes an `(agent, skillId)` pair as a single string for set-membership\n * lookups. Both arguments are typed string unions so a `|` delimiter produces\n * a unique, stable key.\n */\nexport function scopeEligibilityKey(\n agent: AgentName,\n skillId: SkillId\n): string {\n return `${agent}|${skillId}`\n}\n\n/** Runtime check that a string is a valid AgentName from the generated union */\nfunction isAgentName(value: string): value is AgentName {\n return (AGENT_NAMES as readonly string[]).includes(value)\n}\n\n/** Runtime check that a string is a valid SkillId from the generated union */\nfunction isSkillId(value: string): value is SkillId {\n return (SKILL_IDS as readonly string[]).includes(value)\n}\n\n/**\n * What the prior save said about this triple, or `undefined` when it carried\n * no entry for it at all. An entry with no flag is not silence: the generator\n * only ever writes `preloaded` where it is true, so a bare `{ id }` read back\n * off disk is the user's curated lazy and outranks any default.\n */\nfunction priorLoadState(\n existingStack: Partial<Record<AgentName, StackAgentConfig>>,\n agent: AgentName,\n category: Category,\n skillId: SkillId\n): LoadState | undefined {\n const prior = existingStack[agent]?.[category]?.find((a) => a.id === skillId)\n if (prior === undefined) return undefined\n\n return prior.preloaded === true ? \"preloaded\" : \"lazy\"\n}\n\n/**\n * The shared mapping's word for a triple nobody has decided on yet — the same\n * table the editor's default assignments read, so a skill picked in either\n * place arrives loaded the same way.\n *\n * Only catalog skills on roster agents are put to it. The mapping is keyed by\n * generated skill id and agent role, so a local skill, a marketplace one or a\n * hand-written agent has no entry it could ever match — those are lazy by\n * rule, not by rescue. `resolveLoadState` throws on ids it does not know, and\n * catching that throw is what would make this a silent fallback.\n */\nfunction mappedLoadState(skillId: SkillId, agent: AgentName): LoadState {\n if (!isSkillId(skillId) || !isAgentName(agent)) return \"lazy\"\n\n return resolveLoadState({ skillId, agentId: agent })\n}\n\n/**\n * How the shared resolver is told about a skill. Targeting reads a domain and a\n * category, never catalog membership, so what goes is the taxonomy the LOADED\n * catalogue carries: a marketplace's skill wears its marketplace's namespace in\n * its id, belongs to no catalog-keyed table, and is still placed by its domain\n * like any other.\n *\n * A category the catalogue gives no domain leaves no taxonomy to state, so the id\n * goes alone and the resolver answers for it — nobody, unless the catalog knows\n * it. `checkMatrixHealth` reports such a category in its own right.\n */\nfunction taxonomyOrIdOf(\n catalog: CompileCatalog,\n skillId: SkillId,\n category: Category\n): SkillId | SkillTaxonomy {\n // Boundary cast: a catalogue category's `domain` is a Domain, typed `string` on the narrow\n // catalogue shape so the wire `Matrix` satisfies it too.\n const domainId = categoryDomain(catalog, category) as Domain | undefined\n if (domainId === undefined) return skillId\n\n return { id: skillId, domainId, categoryId: category }\n}\n\n/**\n * The shared resolver's word on whether this sub-agent would reasonably use\n * this skill — the same targeting the editor's default assignments read, so a\n * pick lands on the same agents from either surface.\n */\nfunction isRelevantPair(\n catalog: CompileCatalog,\n skillId: SkillId,\n category: Category,\n agent: AgentName\n): boolean {\n return resolveAssignment(taxonomyOrIdOf(catalog, skillId, category)).some(\n (target) => target.agentId === agent\n )\n}\n\n/**\n * The relevance rule as it applies inside a stack build: a triple the prior\n * save carries is the user's curation and rides through wherever it\n * sits, cross-domain included; a triple arriving this session lands only where\n * the shared resolver targets it.\n */\nfunction isPreservedOrRelevant(\n agent: AgentName,\n category: Category,\n skillId: SkillId,\n inputs: StackBuildInputs\n): boolean {\n const hasPriorEntry =\n priorLoadState(inputs.existingStack, agent, category, skillId) !== undefined\n return (\n hasPriorEntry || isRelevantPair(inputs.catalog, skillId, category, agent)\n )\n}\n\nfunction getScopeOrThrow<K>(\n map: Map<K, SkillScope>,\n key: K,\n kind: \"skill\" | \"agent\"\n): SkillScope {\n const scope = map.get(key)\n if (scope === undefined) {\n throw new Error(\n `generateProjectConfigFromSkills: ${kind} '${String(key)}' missing from ` +\n `${kind === \"skill\" ? \"skillConfigs\" : \"agentConfigs\"}. ` +\n `Caller must pass a ${kind === \"skill\" ? \"SkillConfig\" : \"AgentScopeConfig\"} ` +\n `for every selected ${kind}.`\n )\n }\n return scope\n}\n\n/**\n * Project skills never reach global agents; global skills reach any agent.\n *\n * The rule itself lives on the wire contract (`isSeedScopePairWritable` in\n * `@workspace/matrix/seed`), because the editor and this CLI each used to carry a verbatim copy\n * of it and a shared rule with three implementations is a rule three surfaces can disagree about.\n * This stays as the name the CLI's own call sites read it under.\n */\nexport function isScopePairCompatible(\n skillScope: SkillScope,\n agentScope: SkillScope\n): boolean {\n return isSeedScopePairWritable(skillScope, agentScope)\n}\n\nfunction isScopeCompatible(\n skillId: SkillId,\n agent: AgentName,\n skillScope: Map<SkillId, SkillScope>,\n agentScope: Map<AgentName, SkillScope>\n): boolean {\n const sScope = getScopeOrThrow(skillScope, skillId, \"skill\")\n const aScope = getScopeOrThrow(agentScope, agent, \"agent\")\n return isScopePairCompatible(sScope, aScope)\n}\n\n/**\n * Decides whether a given `(agent, category, skillId)` triple lands in the\n * agent's stack for this save. The scope filter has already run in the caller\n * — this function only enforces the per-agent curation rule.\n *\n * Branches:\n * - `agent ∉ existingStack` → seed branch (new agent); every scope-compatible\n * skill the shared resolver targets at this agent lands, and with no prior\n * entry to inherit a `preloaded` flag from, each one takes the shared\n * mapping's default (see `toStackAssignment`).\n * - `agent ∈ existingStack` → preservation branch:\n * * skillId was in `existingStack[agent][category]` → KEEP (idempotent).\n * * skillId ∈ `newlyAddedSkillIds` OR `(agent, skillId)` ∈\n * `scopeEligibilityGained` → APPEND (user's session-level addition or\n * scope-compat flip).\n * * otherwise → OMIT (respect user's prior per-agent curation removal).\n *\n * Legacy path: when `newlyAddedSkillIds` is not provided, the curation check\n * is disabled — every scope-compatible skill passes this gate (the relevance\n * filter in `buildAgentStack` still applies). This preserves the contract of\n * callers that pre-date per-agent curation preservation.\n */\nfunction shouldIncludeTriple(\n agent: AgentName,\n category: Category,\n skillId: SkillId,\n inputs: StackBuildInputs\n): boolean {\n // Legacy path: callers that don't opt in keep the seed-everything behavior.\n if (inputs.newlyAddedSkillIds === undefined) return true\n\n const agentExistingStack = inputs.existingStack[agent]\n if (agentExistingStack === undefined) {\n // Seeding branch: agent is new this session → full ownership-derived stack.\n return true\n }\n\n const priorCategory = agentExistingStack[category]\n if (priorCategory && priorCategory.some((a) => a.id === skillId)) return true\n\n if (inputs.newlyAddedSkillIds.has(skillId)) return true\n const scopeEligibility = inputs.scopeEligibilityGained\n if (\n scopeEligibility &&\n scopeEligibility.has(scopeEligibilityKey(agent, skillId))\n ) {\n return true\n }\n return false\n}\n\n/** The prior stack's word for this triple, or the mapping's when it is new. */\nfunction toStackAssignment(\n id: SkillId,\n agent: AgentName,\n category: Category,\n inputs: StackBuildInputs\n): SkillAssignment {\n const prior = priorLoadState(inputs.existingStack, agent, category, id)\n const load = prior ?? mappedLoadState(id, agent)\n\n return load === \"preloaded\" ? { id, preloaded: true } : { id }\n}\n\n/**\n * The selection's categories in the catalogue's own declaration order, so a newly\n * built stack's key order is a property of the roster rather than of the order\n * the skills happened to be picked in — two sessions that select the same\n * skills emit the same bytes, and an agent whose skill set did not change is\n * not rewritten. The writer holds the same rule for a stack it did not build.\n */\nfunction inCanonicalCategoryOrder(\n activeSkillsByCategory: Map<Category, SkillId[]>,\n catalog: CompileCatalog\n): [Category, SkillId[]][] {\n const byDeclaration = byCategoryDeclarationOrder(catalog)\n return [...activeSkillsByCategory].sort(([a], [b]) => byDeclaration(a, b))\n}\n\nfunction buildAgentStack(\n agent: AgentName,\n inputs: StackBuildInputs\n): StackAgentConfig | undefined {\n const agentStack: StackAgentConfig = {}\n for (const [category, skillIds] of inCanonicalCategoryOrder(\n inputs.activeSkillsByCategory,\n inputs.catalog\n )) {\n const assignments = skillIds\n .filter((id) =>\n isScopeCompatible(id, agent, inputs.skillScope, inputs.agentScope)\n )\n .filter((id) => shouldIncludeTriple(agent, category, id, inputs))\n .filter((id) => isPreservedOrRelevant(agent, category, id, inputs))\n .map((id) => toStackAssignment(id, agent, category, inputs))\n if (assignments.length > 0) {\n agentStack[category] = assignments\n }\n }\n return typedKeys<Category>(agentStack).length > 0 ? agentStack : undefined\n}\n\nfunction buildStackForSelection(\n inputs: StackBuildInputs\n): Partial<Record<AgentName, StackAgentConfig>> | undefined {\n // No agents in play → this caller is not managing the stack. Return\n // `undefined` (key omitted) so the merger preserves any existing stack.\n if (inputs.agentList.length === 0) {\n diagnostics().verbose(\n `buildStackForSelection: no agents — returning undefined (stack untouched)`\n )\n return undefined\n }\n\n // Agents are in play → the generator authoritatively rebuilt the stack from\n // the current selection. An empty result is a real \"nothing preloads\" outcome\n // (e.g. the last categorized skill was removed), so return `{}` — NOT\n // `undefined`. The merger trusts `{}` and drops the stale existing stack,\n // whereas `undefined` would resurrect it (the removed-last-skill bug).\n const result: Partial<Record<AgentName, StackAgentConfig>> = {}\n for (const agent of inputs.agentList) {\n const built = buildAgentStack(agent, inputs)\n if (built) result[agent] = built\n }\n return result\n}\n\ntype ResolvedSkillEntry = { skillId: SkillId; category: Category }\n\n/**\n * Resolves selected ids against the catalogue: reports and drops the ids this marketplace does\n * not carry, extracts each skill's category, and drops ids whose every config entry is\n * excluded. A skill with an excluded global entry AND an active project entry is KEPT —\n * the active entry still needs to reach the stack builder.\n */\nfunction resolveValidSkills(\n selectedSkillIds: SkillId[],\n skillConfigs: SkillConfig[],\n catalog: CompileCatalog\n): {\n validSkills: ResolvedSkillEntry[]\n foundCount: number\n skippedCount: number\n} {\n const looked = selectedSkillIds.map((skillId) => ({\n skillId,\n skill: catalog.skills[skillId],\n }))\n const found = looked.filter(\n (\n entry\n ): entry is typeof entry & { skill: NonNullable<typeof entry.skill> } =>\n entry.skill != null\n )\n const absentSkillIds = looked\n .filter((entry) => entry.skill == null)\n .map((entry) => entry.skillId)\n\n reportAbsentSkills(absentSkillIds, catalog)\n\n const excludedSkillIds = effectivelyExcludedSkillIds(skillConfigs)\n\n const validSkills = found\n .map(({ skillId, skill }) => ({\n skillId,\n // Boundary cast: a catalogue category id is a CategoryPath.\n category: extractCategoryFromPath(skill.category as CategoryPath),\n }))\n .filter(\n (entry): entry is typeof entry & { category: Category } =>\n entry.category != null\n )\n .filter((entry) => !excludedSkillIds.has(entry.skillId))\n\n return {\n validSkills,\n foundCount: found.length,\n skippedCount: absentSkillIds.length,\n }\n}\n\n/**\n * Two audiences, one fact: what the user is told about an id this marketplace does not carry,\n * and what the run's verbose diagnostics keep for whoever is debugging the loader.\n *\n * A sample of catalogue keys belongs to the second audience entirely — five arbitrary ids explain\n * nothing to anyone not comparing them against a catalogue — so it goes where this project's\n * logging convention puts a diagnostic, and the warning carries only what a user can act on.\n */\nfunction reportAbsentSkills(\n absentSkillIds: SkillId[],\n catalog: CompileCatalog\n): void {\n if (absentSkillIds.length === 0) return\n\n for (const skillId of absentSkillIds) {\n diagnostics().warn(absentSkillWarning(skillId), { suppressInTest: true })\n }\n\n const matrixSample = typedKeys<SkillId>(catalog.skills)\n .slice(0, MATRIX_SAMPLE_SIZE)\n .join(\", \")\n diagnostics().verbose(\n `${absentSkillIds.length} skills absent from the matrix. Matrix keys sample: [${matrixSample}]`\n )\n}\n\n/**\n * What an unplaceable id means and what changes it.\n *\n * The outcome first, because it is the part the user cannot see: the entry stays in `config.ts`\n * — nothing here removes it — and the skill reaches no sub-agent, which is what a stack built\n * without it amounts to. Both ways out are named because the fact has two readings: a catalogue\n * that has moved on since this configuration was written, and an id this one never carried.\n */\nfunction absentSkillWarning(skillId: SkillId): string {\n return (\n `Skill '${skillId}' is not in this marketplace — it stays in the configuration and no ` +\n `sub-agent is given it. Run '${CLI_INVOKE_COMMAND} update' to refresh the marketplace, or ` +\n `remove it with '${CLI_INVOKE_COMMAND} edit'.`\n )\n}\n\n/**\n * Per-skill scope, active-entry-authoritative: when a skill has both an excluded\n * and an active entry (excluded global + active project), excluded entries spread\n * first so active entries overwrite them.\n */\nfunction buildSkillScopeMap(\n skillConfigs: SkillConfig[]\n): Map<SkillId, SkillScope> {\n const [excludedConfigs, activeConfigs] = partition(skillConfigs, (s) =>\n Boolean(s.excluded)\n )\n return new Map(\n [...excludedConfigs, ...activeConfigs].map((s) => [s.id, s.scope])\n )\n}\n\n/**\n * One active AgentScopeConfig per selected agent. When the caller provided\n * agentConfigs, every selected agent MUST have a non-excluded entry (invariant\n * throw); otherwise agents default to project scope.\n */\nfunction resolveActiveAgentConfigs(\n agentList: AgentName[],\n providedConfigs: AgentScopeConfig[] | undefined\n): AgentScopeConfig[] {\n const providedByName = providedConfigs\n ? indexBy(\n providedConfigs.filter((a) => !a.excluded),\n (a) => a.name\n )\n : {}\n return agentList.map((agentName) => {\n if (providedConfigs) {\n const provided = providedByName[agentName]\n if (!provided) {\n throw new Error(\n `generateProjectConfigFromSkills: selected agent '${agentName}' has no ` +\n `non-excluded AgentScopeConfig in agentConfigs.`\n )\n }\n return provided\n }\n return { name: agentName, scope: \"project\" as const }\n })\n}\n\n/**\n * Generates a ProjectConfig from a list of selected skill IDs, rebuilding the\n * stack property (agent -> category -> SkillAssignment[]) from the current\n * wizard selection plus any previously-saved stack entries.\n *\n * Ownership rules (what lands in each agent's stack):\n * - agent is selected AND skill is non-excluded AND agent is non-excluded\n * - scope filter: a project-scoped skill never lands on a global-scoped agent\n * - relevance filter: a NEW triple lands only where the shared resolver targets\n * the (skill, agent) pair — a sub-agent carries only skills it would\n * reasonably use. Prior entries are preserved verbatim, wherever\n * they sit.\n *\n * Load state per (agent, category, skill) triple: a triple `options.existingStack`\n * already carries keeps exactly what it carried — flag or no flag, that entry is\n * the author's stack YAML or the user's own curation. A triple that is new to\n * this save has nobody's word to inherit and takes the shared mapping's default,\n * which is what the editor resolves against too.\n *\n * The catalogue comes from {@link seatedCatalog}, not from an argument, and that\n * module's docblock is where the reason lives.\n */\nexport function generateProjectConfigFromSkills(\n name: string,\n selectedSkillIds: SkillId[],\n options?: ProjectConfigOptions & {\n selectedAgents?: AgentName[]\n skillConfigs?: SkillConfig[]\n agentConfigs?: AgentScopeConfig[]\n existingStack?: Partial<Record<AgentName, StackAgentConfig>>\n /**\n * Skills new to this session (not present in the prior on-disk config).\n * Passing this field (even as an empty array) opts into per-agent\n * curation preservation: existing agents' stack entries are treated as\n * authoritative, and skills absent from a given agent's prior stack are\n * only appended when they appear in this set (or in `scopeEligibilityGained`).\n * When undefined, behavior falls back to seed-everything semantics.\n */\n newlyAddedSkillIds?: readonly SkillId[]\n /**\n * `(agent, skillId)` keys whose scope-compat transitioned from incompatible\n * to compatible this session. Admits scope-flip cases that `newlyAddedSkillIds`\n * (keyed by skill id only) cannot express. Keys are built with\n * {@link scopeEligibilityKey}.\n */\n scopeEligibilityGained?: ReadonlySet<string>\n }\n): ProjectConfig {\n const catalog = seatedCatalog()\n const agentList = options?.selectedAgents\n ? [...options.selectedAgents].sort()\n : []\n\n // Invariant: when selectedAgents is provided, callers must also supply the\n // authoritative SkillConfig and AgentScopeConfig entries so scope lookups\n // never silently default.\n if (agentList.length > 0) {\n if (!options?.skillConfigs) {\n throw new Error(\n `generateProjectConfigFromSkills: selectedAgents was passed without skillConfigs. ` +\n `Callers must pass a SkillConfig for every selected skill.`\n )\n }\n if (!options.agentConfigs) {\n throw new Error(\n `generateProjectConfigFromSkills: selectedAgents was passed without agentConfigs. ` +\n `Callers must pass an AgentScopeConfig for every selected agent.`\n )\n }\n }\n\n // Safe after invariant: when agentList is non-empty these are guaranteed present.\n // When agentList is empty, no scope/ownership work runs so `[]` is a valid no-op.\n const skillConfigs = options?.skillConfigs ?? []\n const agentConfigs = options?.agentConfigs ?? []\n\n diagnostics().verbose(\n `generateProjectConfigFromSkills: ${selectedSkillIds.length} skills, ` +\n `matrix has ${typedKeys<SkillId>(catalog.skills).length} entries, ` +\n `agents=[${agentList.join(\", \")}]`\n )\n\n const { validSkills, foundCount, skippedCount } = resolveValidSkills(\n selectedSkillIds,\n skillConfigs,\n catalog\n )\n\n diagnostics().verbose(\n `generateProjectConfigFromSkills: ${foundCount} found, ${skippedCount} not found, ` +\n `${agentList.length} agents in stack`\n )\n\n const activeSkillsByCategory = new Map(\n typedEntries(groupBy(validSkills, (entry) => entry.category)).map(\n ([category, entries]) => [category, entries.map((entry) => entry.skillId)]\n )\n )\n\n const skillScope = buildSkillScopeMap(skillConfigs)\n const agentScope = activeAgentScopeMap(agentConfigs)\n\n // Opt-in per-agent curation preservation: only when the caller provides the delta set.\n const newlyAddedSkillIdsSet: ReadonlySet<SkillId> | undefined =\n options?.newlyAddedSkillIds === undefined\n ? undefined\n : new Set(options.newlyAddedSkillIds)\n\n const stackProperty = buildStackForSelection({\n agentList,\n activeSkillsByCategory,\n skillScope,\n agentScope,\n catalog,\n existingStack: options?.existingStack ?? {},\n ...(newlyAddedSkillIdsSet !== undefined && {\n newlyAddedSkillIds: newlyAddedSkillIdsSet,\n }),\n ...(options?.scopeEligibilityGained !== undefined && {\n scopeEligibilityGained: options.scopeEligibilityGained,\n }),\n })\n\n const skills: SkillConfig[] =\n options?.skillConfigs ??\n selectedSkillIds.map((id) => ({\n id,\n scope: \"project\" as const,\n origin: EJECT_SOURCE,\n }))\n\n const activeAgentConfigs = resolveActiveAgentConfigs(\n agentList,\n options?.agentConfigs\n )\n // Excluded agents aren't in selectedAgents but must be preserved in config\n const excludedAgentConfigs = agentConfigs.filter((ac) => ac.excluded)\n const finalAgentConfigs: AgentScopeConfig[] = [\n ...activeAgentConfigs,\n ...excludedAgentConfigs,\n ]\n\n return {\n name,\n agents: finalAgentConfigs,\n skills,\n ...(stackProperty && { stack: stackProperty }),\n ...(options?.description && { description: options.description }),\n ...(options?.author && { author: options.author }),\n }\n}\n\n/**\n * One stack entry's load. A flag the author wrote is somebody's word and rides\n * through untouched — a third-party source's stacks file is the explicit tier,\n * and `loadStacks` gives even its bare strings an explicit `preloaded: false`.\n * An entry with no flag at all is a stack stating only WHICH skill an agent\n * gets, so HOW it loads is the shared mapping's answer, exactly as it is for a\n * skill picked by hand. The built-in stacks carry no flags, by design.\n */\nfunction toStackPropertyAssignment(\n assignment: SkillAssignment,\n agent: AgentName\n): SkillAssignment {\n if (assignment.preloaded !== undefined) return assignment\n if (mappedLoadState(assignment.id, agent) === \"lazy\") return assignment\n\n return { ...assignment, preloaded: true }\n}\n\n/**\n * Extracts the stack property (agent -> category -> SkillAssignment[]) from a Stack definition.\n *\n * Stack values are already normalized to SkillAssignment[] by loadStacks().\n * Preserves every assignment, and every load its author stated; an assignment\n * that states none takes the shared mapping's, per `(skill, agent)` pair.\n */\nexport function buildStackProperty(\n stack: Stack\n): Partial<Record<AgentName, StackAgentConfig>> {\n return typedFromEntries(\n typedEntries<AgentName, StackAgentConfig>(stack.agents)\n .filter(\n ([, agentConfig]) =>\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n agentConfig && typedKeys<Category>(agentConfig).length > 0\n )\n .map(([agentId, agentConfig]) => {\n const resolvedMappings: StackAgentConfig = typedFromEntries(\n typedEntries<Category, SkillAssignment[]>(agentConfig)\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n .filter(([, assignments]) => assignments && assignments.length > 0)\n .map(([category, assignments]) => [\n category,\n assignments.map((assignment) =>\n toStackPropertyAssignment(assignment, agentId)\n ),\n ])\n )\n return [agentId, resolvedMappings] as const\n })\n .filter(([, mappings]) => typedKeys<Category>(mappings).length > 0)\n )\n}\n\n/** Splits one agent's stack per category: global skills → global config, project skills → project config. */\nfunction splitAgentStack(\n agentStack: StackAgentConfig,\n globalSkillIds: ReadonlySet<SkillId>\n): { global: StackAgentConfig; project: StackAgentConfig } {\n const perCategory = typedEntries<Category, SkillAssignment[]>(agentStack)\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n .filter(([, assignments]) => assignments !== undefined)\n .map(([category, assignments]) => {\n const [globalOnly, projectOnly] = partition(assignments, (a) =>\n globalSkillIds.has(a.id)\n )\n return { category, globalOnly, projectOnly }\n })\n return {\n global: Object.fromEntries(\n perCategory\n .filter((c) => c.globalOnly.length > 0)\n .map((c) => [c.category, c.globalOnly])\n ),\n project: Object.fromEntries(\n perCategory\n .filter((c) => c.projectOnly.length > 0)\n .map((c) => [c.category, c.projectOnly])\n ),\n }\n}\n\n/**\n * Splits a ProjectConfig by scope into global and project partitions.\n * Skills with `scope: \"global\"` go to the global partition, `scope: \"project\"` to the project partition.\n * Agents are split based on which skills reference them in the stack.\n * Selected domains go to BOTH partitions, because a project owns its own domain selection\n * (owner ruling 2026-08-20).\n */\nexport function splitConfigByScope(config: ProjectConfig): SplitConfigResult {\n // Every entry is either active-global or project-owned (project-scoped, or an\n // excluded-global tombstone routed to the project partition as an override).\n const [globalSkills, projectSkills] = partition(config.skills, (s) =>\n isActiveAt(s, \"global\")\n )\n const [globalAgents, projectAgents] = partition(config.agents, (a) =>\n isActiveAt(a, \"global\")\n )\n\n // Split stack by agent partition, filtering global agents' stacks to only reference global skills.\n // Project agents keep ALL skill references (both project and global) since global skills are available everywhere.\n const globalSkillIds = new Set(globalSkills.map((s) => s.id))\n const globalStack: NonNullable<ProjectConfig[\"stack\"]> = {}\n const projectStack: NonNullable<ProjectConfig[\"stack\"]> = {}\n\n if (config.stack) {\n for (const agent of globalAgents) {\n const agentStack = config.stack[agent.name]\n if (!agentStack) continue\n const split = splitAgentStack(agentStack, globalSkillIds)\n if (typedKeys<Category>(split.global).length > 0) {\n globalStack[agent.name] = split.global\n }\n if (typedKeys<Category>(split.project).length > 0) {\n projectStack[agent.name] = split.project\n }\n }\n for (const agent of projectAgents) {\n const agentStack = config.stack[agent.name]\n if (agentStack) {\n projectStack[agent.name] = agentStack\n }\n }\n }\n\n // Domains ride the spread onto BOTH partitions: a project owns its own domain selection\n // rather than inheriting the global one (owner ruling 2026-08-20).\n //\n // `stack` is written on BOTH partitions unconditionally, and that is the whole of what\n // keeps each one to its own rows: the spread above carries the undivided stack, so an\n // override that declines to fire hands a partition every row the other partition earned.\n // A derivation that yielded nothing is a partition with no stack, and `{}` is how that is\n // said — the same word `buildStackForSelection` uses and for the same reason, since the\n // merger reads an absent stack as no statement and keeps the stale one. `generateConfigSource`\n // omits an empty stack from the file it writes, so nothing emits `stack: {}` on this account.\n const globalConfig: ProjectConfig = {\n ...config,\n name: GLOBAL_CONFIG_NAME,\n agents: globalAgents,\n skills: globalSkills,\n stack: globalStack,\n }\n\n const projectConfig: ProjectConfig = {\n ...config,\n name: config.name,\n agents: projectAgents,\n skills: projectSkills,\n stack: projectStack,\n }\n\n return { global: globalConfig, project: projectConfig }\n}\n\n/**\n * What a completed selection hands the install pipeline.\n *\n * Declared here rather than beside the wizard component that produces it, because\n * `seedToWizardResult` below produces one too and this package cannot import a\n * React module. `components/wizard/wizard.tsx` re-exports this name, so every CLI\n * call site reads it where it always did.\n */\nexport type WizardResultV2 = {\n skills: SkillConfig[]\n selectedAgents: AgentName[]\n agentConfigs: AgentScopeConfig[]\n /**\n * What each sub-agent holds and what preloads, when the producer knows per `(skill, sub-agent)`.\n * A shared configuration installed with `init --from` does: it assigns each skill to named\n * sub-agents at a named load state, and that curation is the whole of what was shared.\n *\n * The wizard has no per-agent granularity — a skill is selected for the project, not for one\n * sub-agent — so it leaves this undefined and the install pipeline's ownership rules build the\n * stack as they always have.\n */\n assignedStack?: Partial<Record<AgentName, StackAgentConfig>>\n selectedStackId: string | null\n /**\n * What the written config should record about itself, when the producer already knows.\n *\n * A shared configuration installed with `init --from` does: its payload carries the sharer's own\n * description, because it names no stack for the install to resolve one out of. The wizard leaves\n * this undefined and the install pipeline takes the applied stack's description instead — there\n * IS a loaded stack on that path, and it is the authority on its own sentence.\n */\n description?: string\n domainSelections: DomainSelections\n selectedDomains: Domain[]\n /**\n * Skill ids from the saved config that could not be resolved against the loaded source matrix\n * this session. The wizard could not represent them, so they are absent from `skills` and the\n * merge removes their config entries. Carried out of the wizard so the command can NAME each\n * removal and say why it happened — a removal the user never asked for must never be silent.\n */\n unresolvableSkillIds: SkillId[]\n cancelled: boolean\n validation: SelectionValidation\n}\n\nexport type SeedMapping = {\n result: WizardResultV2\n /** Ids this catalogue does not know. Reported, never fatal — see the decode policy. */\n skippedSkillIds: string[]\n skippedAgentNames: string[]\n}\n\nconst KNOWN_AGENTS = new Set<string>(AGENT_NAMES)\n\n/** A skill's primary source, or the default marketplace. Mirrors the wizard's own resolution. */\nfunction sourceForSkill(skill: CatalogSkill): string {\n return (\n skill.availableSources?.find((s) => s.primary)?.name ??\n DEFAULT_PUBLIC_SOURCE_NAME\n )\n}\n\nfunction addToDomainSelections(\n selections: DomainSelections,\n domain: Domain,\n category: Category,\n skillId: SkillId\n): void {\n const categorySelections = (selections[domain] ??= {})\n const skillList = (categorySelections[category] ??= [])\n if (!skillList.includes(skillId)) skillList.push(skillId)\n}\n\n/**\n * The stack mirror of {@link addToDomainSelections}: one sub-agent's own category lists, appended\n * in payload order. A `(skill, sub-agent)` pair can only occur once — `skills` is keyed by id — so\n * there is nothing to de-duplicate here.\n */\nfunction addToAgentStack(\n stack: Partial<Record<AgentName, StackAgentConfig>>,\n agent: AgentName,\n category: Category,\n assignment: SkillAssignment\n): void {\n const agentStack = (stack[agent] ??= {})\n const assignments = (agentStack[category] ??= [])\n assignments.push(assignment)\n}\n\n/** A load state is per `(skill, sub-agent)`; `preloaded` is the stack's word for the same thing. */\nfunction toSkillAssignment(\n skillId: SkillId,\n load: SeedLoadState\n): SkillAssignment {\n return { id: skillId, preloaded: load === \"preloaded\" }\n}\n\n/** The payload's `agents` map, split by what this catalog can do with each entry. */\ntype SeedAgentMap = {\n /** Known agents the map has something to say about, keyed by name. */\n known: Map<AgentName, SeedAgent>\n /** Names explicitly switched off — dropped, and their assignment rows ignored with them. */\n switchedOff: Set<string>\n /** Names this catalog does not know. Reported, never fatal — same policy as unknown skill ids. */\n unknown: string[]\n}\n\nfunction readAgentMap(agents: SeedPayload[\"agents\"]): SeedAgentMap {\n const known = new Map<AgentName, SeedAgent>()\n const switchedOff = new Set<string>()\n const unknown: string[] = []\n\n for (const [name, entry] of Object.entries(agents)) {\n if (!isAgentName(name)) unknown.push(name)\n else if (entry.on === false) switchedOff.add(name)\n else known.set(name, entry)\n }\n\n return { known, switchedOff, unknown }\n}\n\n/**\n * A sub-agent's own row. Model and effort ride along on the same terms as its scope — an absent\n * key means \"keep whatever the agent's metadata says\".\n */\nfunction agentScopeConfig(\n name: AgentName,\n entry: SeedAgent | undefined\n): AgentScopeConfig {\n return {\n name,\n scope: seedAgentScope(entry),\n ...(entry?.model !== undefined && { model: entry.model }),\n ...(entry?.effort !== undefined && { effort: entry.effort }),\n }\n}\n\n/** A `(skill, sub-agent)` assignment the config model has nowhere to write. */\ntype UnwritableAssignment = { skillId: SkillId; agent: AgentName }\n\n/**\n * Names every unwritable pair, not just the first: a sharer who fixes one only to be refused for\n * the next learns nothing the first message could not have told them. Both halves of each pair are\n * named because neither alone says what to change — the skill can move to global scope, or the\n * sub-agent can be pinned to the project, and only the sharer knows which they meant.\n */\nfunction unwritableAssignmentsError(\n assignments: UnwritableAssignment[]\n): string {\n return [\n \"This configuration cannot be installed: a project-scoped skill never reaches a sub-agent \" +\n \"that rests at global scope, so these assignments have nowhere to be written:\",\n ...assignments.map(({ skillId, agent }) => ` ${skillId} -> ${agent}`),\n \"Re-share it with each sub-agent above pinned to the project, or each skill above at global scope.\",\n ].join(\"\\n\")\n}\n\n/**\n * Turns a shared configuration into the shape the install pipeline already consumes, so\n * `init --from` reuses `writeProjectConfig` -> skill install -> `compileAgentsAllScopes`\n * unchanged rather than growing a second path that can drift from the wizard's.\n *\n * Unknown ids are skipped, never fatal. Payloads carry catalog slugs precisely so they survive\n * catalog churn: a config shared before a skill was renamed should still install everything else,\n * and failing the whole decode would make every rename retroactively break every shared id.\n *\n * A sub-agent reaches the roster two ways: named by a surviving skill's assignment, or switched on\n * in the `agents` map. The map is the only place a configuration can say anything about an agent\n * no skill mentions, which is what makes a bare (skill-less) agent shareable at all; it also\n * carries that agent's model and effort onto its `AgentScopeConfig`.\n *\n * The `assignments` map is per `(skill, sub-agent)` and carries a load state, so it decides three\n * things the wizard cannot express separately: which sub-agents are selected, which skills land in\n * each one's stack entry, and which of those preload. That is why the result carries an\n * `assignedStack` — the install pipeline's ownership rules broadcast every scope-compatible skill\n * to every selected agent, which would hand a bare sub-agent someone else's skills.\n *\n * An unwritable `(skill, sub-agent)` pair is the one thing here that IS fatal, and it is fatal for\n * the opposite reason to the skips: an unknown id is content this catalog does not have, while an\n * unwritable pair is content it has and cannot place. Because `assignedStack` replaces the derived\n * stack wholesale, no scope filter runs on these rows downstream — they reach the writers, which\n * put them in neither half of the split config and say nothing. Refusing at the decode is what\n * keeps a payload from installing as a quieter configuration than the one that was shared.\n */\nexport function seedToWizardResult(\n payload: SeedPayload,\n catalog: CompileCatalog\n): SeedMapping {\n const domainSelections: DomainSelections = {}\n const assignedStack: Partial<Record<AgentName, StackAgentConfig>> = {}\n const skills: SkillConfig[] = []\n const skippedSkillIds: string[] = []\n const unwritable: UnwritableAssignment[] = []\n const agentNames = new Set<AgentName>()\n const agentMap = readAgentMap(payload.agents)\n const skippedAgentNames = new Set<string>(agentMap.unknown)\n\n for (const [skillId, entry] of Object.entries(payload.skills)) {\n const skill = catalog.skills[skillId]\n const domain = skill?.category\n ? categoryDomain(catalog, skill.category)\n : undefined\n\n if (!skill?.category || domain === undefined) {\n skippedSkillIds.push(skillId)\n continue\n }\n\n // Past the guard the catalogue knows this id, and its category is a real one: the `local`\n // pseudo-category has no domain, so it left with the skips.\n // Boundary casts: both were read out of the catalogue's own keys.\n const id = skillId as SkillId\n const category = skill.category as Category\n\n addToDomainSelections(domainSelections, domain as Domain, category, id)\n\n skills.push({\n id,\n scope: entry.scope,\n // \"eject\" is an origin in its own right; anything else names the marketplace it came from.\n origin: entry.install === \"eject\" ? EJECT_SOURCE : sourceForSkill(skill),\n })\n\n // Only assignments on skills that survived — an agent should not be switched on by a skill\n // this catalog cannot install.\n for (const [agentName, load] of Object.entries(entry.assignments)) {\n if (agentMap.switchedOff.has(agentName)) continue\n if (!KNOWN_AGENTS.has(agentName)) {\n skippedAgentNames.add(agentName)\n continue\n }\n\n // Boundary cast: guarded by KNOWN_AGENTS immediately above.\n const agent = agentName as AgentName\n // Rows the decode was going to ignore anyway have already left, so what reaches here is a\n // pair the payload really asked for — and the config model's one rule about pairs applies.\n if (\n !isScopePairCompatible(\n entry.scope,\n seedAgentScope(agentMap.known.get(agent))\n )\n ) {\n unwritable.push({ skillId: id, agent })\n continue\n }\n\n agentNames.add(agent)\n // The assignment is the curation: this sub-agent holds this skill, at this load state, and\n // no sub-agent the payload did not name holds it at all.\n addToAgentStack(\n assignedStack,\n agent,\n category,\n toSkillAssignment(id, load)\n )\n }\n }\n\n if (unwritable.length > 0)\n throw new Error(unwritableAssignmentsError(unwritable))\n\n // Bare agents: switched on by the map alone, with no skill to carry them in.\n for (const [name, entry] of agentMap.known) {\n if (entry.on === true) agentNames.add(name)\n }\n\n const selectedAgents = [...agentNames]\n\n return {\n result: {\n skills,\n selectedAgents,\n agentConfigs: selectedAgents.map((name) =>\n agentScopeConfig(name, agentMap.known.get(name))\n ),\n assignedStack,\n selectedStackId: payload.stackId,\n // Spread-conditional rather than passed through, because absent and present-holding-undefined\n // are different files on disk: a config describing itself with no key is not one describing\n // itself with an empty sentence, and the writer emits whichever key it is handed.\n ...(payload.description !== undefined && {\n description: payload.description,\n }),\n domainSelections,\n selectedDomains: orderDomains(typedKeys<Domain>(domainSelections)),\n // Nothing was dropped from a *saved config* — the skipped ids came off the wire and are\n // reported to the user directly, so there is no config removal to explain.\n unresolvableSkillIds: [],\n cancelled: false,\n // Revalidated here rather than taken on trust from the app that built the payload. That app\n // validated against ITS catalog; this one skips ids it does not know and carries its own\n // relationship rules, so a configuration that was consistent where it was authored can\n // arrive with a requirement genuinely unmet.\n validation: validateSelection(\n skills.map((skill) => skill.id),\n catalog\n ),\n },\n skippedSkillIds,\n skippedAgentNames: [...skippedAgentNames],\n }\n}\n","// Type-safe Object.entries that preserves key types (avoids `as [K, V][]` casts)\nexport function typedEntries<K extends string, V>(\n obj: Partial<Record<K, V>>\n): [K, V][] {\n return Object.entries(obj) as [K, V][]\n}\n\n// Type-safe Object.keys that preserves key types (avoids `as K[]` casts)\nexport function typedKeys<K extends string>(\n obj: Partial<Record<K, unknown>>\n): K[] {\n return Object.keys(obj) as K[]\n}\n\n// Type-safe Object.fromEntries that preserves key types (avoids `as Partial<Record<K, V>>` casts)\nexport function typedFromEntries<K extends string, V>(\n entries: Iterable<readonly [K, V]>\n): Partial<Record<K, V>> {\n return Object.fromEntries(entries) as Partial<Record<K, V>>\n}\n","import { indexBy, uniqueBy } from \"remeda\";\n\nimport type { ProjectConfig } from \"../../types\";\nimport type { AgentScopeConfig, SkillConfig } from \"../../types/config\";\nimport { getProjectConfigPath } from \"../installation/install-base-dir\";\nimport { loadProjectConfig, type LoadedProjectConfig } from \"./project-config\";\nimport { loadProjectSourceConfig } from \"./config\";\nimport { isGlobalTombstone, isProjectOwned, type ScopedEntry } from \"./scope-predicates\";\n\n/**\n * How authoritative `newConfig` is over entries absent from it:\n * - `\"all\"` — global-context EDIT at ~/: the wizard loaded the ENTIRE global config, so any\n * absent agent/skill was removed. Every existing entry is in scope.\n * - `\"owned\"` — project-context EDIT: the wizard loaded the full project roster and owns only\n * PROJECT-OWNED entries (project-scoped + the project's own global tombstones).\n * Inherited global-active entries are read-only and are always preserved.\n * - `undefined` — init / non-edit merges: additive union-preserve (never drop absent entries).\n */\nexport type AuthoritativeScope = \"all\" | \"owned\";\n\nexport type MergeContext = {\n projectDir: string;\n authoritativeScope?: AuthoritativeScope;\n};\n\nexport type MergeResult = {\n config: ProjectConfig;\n merged: boolean;\n existingConfigPath?: string;\n};\n\n/**\n * Compound identity key for an agent entry. Includes scope and the excluded\n * discriminator so that `{name, scope:\"project\"}` and `{name, scope:\"global\"}`\n * (and their tombstone variants) are treated as distinct entries rather than\n * collapsed onto `name` alone.\n */\nconst agentKey = (a: AgentScopeConfig): string =>\n `${a.name}:${a.scope}${a.excluded ? \":excluded\" : \"\"}`;\n\n/**\n * Compound identity key for a skill entry. Same shape as {@link agentKey}:\n * `id:scope` for actives, `id:scope:excluded` for tombstones. Prevents the\n * class of bugs where two distinct-scope entries collide onto `id`.\n */\nconst skillKey = (s: SkillConfig): string => `${s.id}:${s.scope}${s.excluded ? \":excluded\" : \"\"}`;\n\n/** Names of agents carrying a global tombstone — i.e. dual-scope entries the project owns. */\nfunction agentTombstoneNames(agents: AgentScopeConfig[]): Set<string> {\n return new Set(agents.filter(isGlobalTombstone).map((a) => a.name));\n}\n\n/** Ids of skills carrying a global tombstone — i.e. dual-scope entries the project owns. */\nfunction skillTombstoneIds(skills: SkillConfig[]): Set<string> {\n return new Set(skills.filter(isGlobalTombstone).map((s) => s.id));\n}\n\n/**\n * True when an existing entry is within the current edit session's authority, so its absence\n * from `newConfig` means a deliberate removal (drop) rather than an untouched entry (preserve).\n *\n * `\"all\"` (global edit): every entry is owned. `\"owned\"` (project edit): only project-scoped\n * entries and the project's own global tombstones — inherited global-active entries belong to\n * the global config and must never be dropped from a project edit.\n */\nfunction isWithinSessionAuthority(entry: ScopedEntry, scope: AuthoritativeScope): boolean {\n if (scope === \"all\") return true;\n return isProjectOwned(entry);\n}\n\n/**\n * Pure merge logic: existing values take precedence for identity fields;\n * agents and skills are merged so that `newConfig` is authoritative for every\n * `name`/`id` it references. Existing entries survive in-place when their\n * compound key matches a new entry (same name, scope, excluded). Existing\n * entries whose NAME/ID appears in new but whose compound key does NOT match\n * a new entry are dropped — this is how scope migrations (P→G, G→P) remove\n * stale rows and how P→G tombstone removal is honored. Existing entries whose\n * name/ID is absent from new are preserved unchanged — EXCEPT names/ids the\n * project owned as dual-scope this session (they carry a global tombstone in the\n * existing config): when new carries nothing for such a name, the user fully\n * deselected the dual-scope row, so both the lingering active project entry and\n * the stale tombstone are dropped together — the full-deselect case.\n *\n * A final compound-key dedup (keeping first occurrence, which in our concat\n * order is the existing-derived or first-new entry) collapses any pre-existing\n * on-disk corruption rather than carrying multiplied duplicates forward.\n *\n * Dual-scope semantics (active at one scope + excluded tombstone at another)\n * are preserved because `newConfig.agents`/`newConfig.skills` carry BOTH\n * entries for the same name/id when that dual state is legitimate (wizard\n * output from `generateProjectConfigFromSkills` + `toggleAgentScope`).\n *\n * Root cause of the duplicate rows this key fixes: the prior name-only key collapsed\n * distinct-scope entries, and the positional `.map()` over existing rewrote\n * every collision slot — multiplying pre-existing duplicates and failing to\n * drop stale rows on scope migration.\n *\n * `authoritativeScope`: a full `cc edit` pass presents the complete roster\n * the wizard could edit, so an entry within that authority which is absent from `newConfig` was\n * deliberately removed and must be dropped (even a plain active entry with no tombstone), rather\n * than union-preserved. `\"all\"` (global edit) covers every entry; `\"owned\"` (project edit) covers\n * only project-scoped entries and the project's own global tombstones — inherited global-active\n * entries are always preserved. `undefined` (init) keeps additive union-preserve.\n *\n * A skill the wizard could not resolve from the loaded source this session is NOT exempt from that\n * drop: it is removed like any other absent entry, and `edit` names it and says why in its Changes\n * block. Exempting it used to keep an entry in `config.ts` that the same run's summary announced as\n * gone and the compiled agent no longer carried — three surfaces, three answers about one skill.\n */\ntype MergeOptions = Pick<MergeContext, \"authoritativeScope\">;\n\nexport function mergeConfigs(\n newConfig: ProjectConfig,\n existingConfig: ProjectConfig,\n options?: MergeOptions,\n): ProjectConfig {\n const merged = { ...newConfig };\n\n if (existingConfig.name) {\n merged.name = existingConfig.name;\n }\n\n if (existingConfig.description) {\n merged.description = existingConfig.description;\n }\n\n if (existingConfig.marketplace && !newConfig.marketplace) {\n merged.marketplace = existingConfig.marketplace;\n }\n\n if (existingConfig.agents.length > 0) {\n const newAgentsByKey = indexBy(merged.agents, agentKey);\n const newAgentNames = new Set(merged.agents.map((a) => a.name));\n const existingKeys = new Set(existingConfig.agents.map(agentKey));\n // Names the project managed as dual-scope this session: a global tombstone in the\n // existing config marks an agent whose global install the project actively overrode.\n // When newConfig carries NO entry for such a name, the user fully deselected the\n // dual-scope row — both the lingering active project entry and the stale tombstone\n // must drop together, not be preserved — the full-deselect case.\n const dualScopeAgentNames = agentTombstoneNames(existingConfig.agents);\n const updatedExisting = existingConfig.agents.flatMap((existing) => {\n const matching = newAgentsByKey[agentKey(existing)];\n if (matching) return [matching];\n // Name is actively managed by newConfig but this exact (scope, excluded)\n // slot is NOT in new → the wizard intentionally dropped this row\n // (scope migration or tombstone cleanup). Drop it.\n if (newAgentNames.has(existing.name)) return [];\n if (dualScopeAgentNames.has(existing.name)) return [];\n // Authoritative edit: an in-authority agent absent from newConfig (even a plain active\n // one with no tombstone) was deselected and must be dropped.\n if (\n options?.authoritativeScope &&\n isWithinSessionAuthority(existing, options.authoritativeScope)\n )\n return [];\n return [existing];\n });\n const addedAgents = merged.agents.filter((a) => !existingKeys.has(agentKey(a)));\n merged.agents = uniqueBy([...updatedExisting, ...addedAgents], agentKey);\n } else {\n merged.agents = uniqueBy(merged.agents, agentKey);\n }\n\n if (existingConfig.skills.length > 0) {\n const newSkillsByKey = indexBy(merged.skills, skillKey);\n const newSkillIds = new Set(merged.skills.map((s) => s.id));\n const existingKeys = new Set(existingConfig.skills.map(skillKey));\n // Skill-side twin of dualScopeAgentNames — see the agent branch above.\n const dualScopeSkillIds = skillTombstoneIds(existingConfig.skills);\n const updatedExisting = existingConfig.skills.flatMap((existing) => {\n const matching = newSkillsByKey[skillKey(existing)];\n if (matching) return [matching];\n if (newSkillIds.has(existing.id)) return [];\n if (dualScopeSkillIds.has(existing.id)) return [];\n // Skill-side twin — see the agent branch above.\n if (\n options?.authoritativeScope &&\n isWithinSessionAuthority(existing, options.authoritativeScope)\n )\n return [];\n return [existing];\n });\n const addedSkills = merged.skills.filter((s) => !existingKeys.has(skillKey(s)));\n merged.skills = uniqueBy([...updatedExisting, ...addedSkills], skillKey);\n } else {\n merged.skills = uniqueBy(merged.skills, skillKey);\n }\n\n // Stack is the pure output of the mutator — trust newConfig.stack whenever it\n // is defined. Only fall back to existingConfig.stack when the new config has\n // none (preserves existing during non-stack-touching operations).\n if (newConfig.stack === undefined && existingConfig.stack) {\n merged.stack = existingConfig.stack;\n }\n\n if (existingConfig.author) {\n merged.author = existingConfig.author;\n }\n\n if (existingConfig.agentsSource) {\n merged.agentsSource = existingConfig.agentsSource;\n }\n\n if (existingConfig.marketplaceName) {\n merged.marketplaceName = existingConfig.marketplaceName;\n }\n\n // Preserve the registered project paths from the existing (global) config — the wizard\n // result never carries them, and losing them silently disables propagation of global\n // changes to registered projects — the tombstone reconcile never runs.\n if (existingConfig.projects && !newConfig.projects) {\n merged.projects = existingConfig.projects;\n }\n\n return merged;\n}\n\n/**\n * The config the merge reconciles against, wearing an identity this directory can own.\n *\n * `loadProjectConfig` falls back to `os.homedir()` for a project that carries no config of\n * its own, so a first save into a project sitting under an existing global install\n * reconciles against the GLOBAL config — whose `name` identifies that installation and no\n * directory here. `mergeConfigs`' identity-field carry-forward would then stamp it onto the\n * project's own file.\n *\n * The carry-forward itself is intentional and stays: a project's OWN prior config is how a\n * hand-renamed `config.ts` keeps its name across saves. What decides between the two is the\n * provenance of the load, which is known here and nowhere inside the pure merge — so a\n * config that came from the home fallback lends this save every field except its name.\n */\nfunction existingConfigForMerge(\n loaded: LoadedProjectConfig,\n projectDir: string,\n ownName: string,\n): ProjectConfig {\n const isProjectsOwnFile = loaded.configPath === getProjectConfigPath(projectDir);\n return isProjectsOwnFile ? loaded.config : { ...loaded.config, name: ownName };\n}\n\nexport async function mergeWithExistingConfig(\n newConfig: ProjectConfig,\n context: MergeContext,\n): Promise<MergeResult> {\n const existingFullConfig = await loadProjectConfig(context.projectDir);\n if (existingFullConfig) {\n // A full `cc edit` pass loads the complete roster, so newConfig is authoritative over the\n // entries it owns — every entry for a global edit (`\"all\"`), or project-owned entries for a\n // project edit (`\"owned\"`). Absent owned entries were deselected and are dropped rather than\n // union-preserved. Init leaves the scope undefined (additive union).\n const existingConfig = existingConfigForMerge(\n existingFullConfig,\n context.projectDir,\n newConfig.name,\n );\n const config = mergeConfigs(newConfig, existingConfig, {\n ...(context.authoritativeScope !== undefined && {\n authoritativeScope: context.authoritativeScope,\n }),\n });\n\n return {\n config,\n merged: true,\n existingConfigPath: existingFullConfig.configPath,\n };\n }\n\n // No existing full config, try simple project source config for author/agentsSource.\n // ABORT on an unreadable config, and unreachable here: `loadProjectConfig` above reads the same\n // file and already threw `ConfigLoadError` for one it could not load, so this rung is only\n // reached when there is no config to read.\n const localConfig = { ...newConfig };\n const existingProjectConfig = await loadProjectSourceConfig(context.projectDir);\n if (existingProjectConfig?.author) {\n localConfig.author = existingProjectConfig.author;\n }\n if (existingProjectConfig?.agentsSource) {\n localConfig.agentsSource = existingProjectConfig.agentsSource;\n }\n\n return { config: localConfig, merged: false };\n}\n","import os from \"os\";\nimport path from \"path\";\nimport { fileExists } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport type { ProjectConfig, ValidationResult } from \"../../types\";\nimport { normalizeStackRecord } from \"../stacks/stacks-loader\";\nimport { projectConfigLoaderSchema } from \"../schemas\";\nimport { formatZodErrors } from \"../schema-validator\";\nimport { getProjectConfigPath } from \"../installation/install-base-dir\";\nimport { isHomeDirectory } from \"../installation/is-home-directory\";\nimport { loadConfig } from \"./config-loader\";\n\nexport type LoadedProjectConfig = {\n config: ProjectConfig;\n configPath: string;\n};\n\n/**\n * Thrown when a project config file exists on disk but cannot be loaded into a\n * usable config — a syntax/evaluation error, no default export, or a shape the\n * loader schema rejects. This is deliberately distinct from a MISSING file\n * (which is a legitimate `null`): a corrupt config is an error that callers must\n * surface, never swallow into `null`. Collapsing both into `null` let a broken\n * install pass as absent (e.g. `compile` treating it as config-less and\n * resurrecting every built-in agent).\n */\nexport class ConfigLoadError extends Error {\n constructor(\n readonly configPath: string,\n readonly reason: string,\n ) {\n super(`Config at '${configPath}' could not be loaded: ${reason}`);\n this.name = \"ConfigLoadError\";\n }\n}\n\n/**\n * Load project config from a specific directory only (no global fallback).\n *\n * Returns `null` only when the config file does not exist. When the file exists\n * but cannot be parsed into a usable config, throws {@link ConfigLoadError} —\n * the caller decides how to report it.\n *\n * The two lines it announces name the scope of the file it read, the way\n * `loadSourceConfig`'s already do: the config at the home root is the GLOBAL one,\n * and a run there that calls it a project config names a file that is not there.\n */\nexport async function loadProjectConfigFromDir(\n projectDir: string,\n): Promise<LoadedProjectConfig | null> {\n const configPath = getProjectConfigPath(projectDir);\n const scope = isHomeDirectory(projectDir) ? \"global\" : \"project\";\n const scopeLabel = scope === \"project\" ? \"Project\" : \"Global\";\n\n if (!(await fileExists(configPath))) {\n verbose(`${scopeLabel} config not found at ${configPath}`);\n return null;\n }\n\n // The file exists. From here, any failure to produce a usable config means the\n // file is corrupt — surface it as ConfigLoadError rather than returning `null`,\n // which is indistinguishable from \"missing\".\n let raw: unknown;\n try {\n // Load raw object and validate with Zod (lenient schema accepts custom values via z.string() casts)\n raw = await loadConfig<ProjectConfig>(configPath);\n } catch (error) {\n throw new ConfigLoadError(configPath, getErrorMessage(error));\n }\n\n if (!raw || typeof raw !== \"object\") {\n throw new ConfigLoadError(configPath, \"the file has no valid default export\");\n }\n\n const result = projectConfigLoaderSchema.safeParse(raw);\n if (!result.success) {\n throw new ConfigLoadError(configPath, formatZodErrors(result.error).join(\"; \"));\n }\n\n // Normalize the loose stack values (bare strings, objects, arrays) BEFORE claiming\n // ProjectConfig, so the boundary cast below is the only one on this path.\n const parsed = result.data;\n const normalizedStack = parsed.stack ? normalizeStackRecord(parsed.stack) : undefined;\n if (parsed.name === undefined) {\n warn(\n `Project config at '${configPath}' is missing required 'name' field — defaulting to directory name`,\n );\n }\n if (parsed.skills === undefined) {\n warn(`Project config at '${configPath}' is missing 'skills' array — defaulting to empty`);\n }\n\n // The defaults are applied here rather than mutated in afterwards, so the cast is the\n // last thing that happens and ProjectConfig's required fields are genuinely present.\n // `agents` is defaulted for the same reason `skills` is: the loader schema admits its\n // absence, ProjectConfig declares it required, and every caller was paying for the gap\n // with a `?? []` the type said was dead.\n //\n // Boundary cast: the loader schema is lenient about the string unions (category, slug,\n // domain), so the literal still does not satisfy ProjectConfig even with the defaults in\n // place; validateProjectConfig enforces the strict shape after load.\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- see above\n const config = {\n ...parsed,\n name: parsed.name ?? path.basename(projectDir),\n skills: parsed.skills ?? [],\n agents: parsed.agents ?? [],\n ...(normalizedStack && { stack: normalizedStack }),\n } as ProjectConfig;\n\n verbose(`Loaded ${scope} config from ${configPath}`);\n return {\n config,\n configPath,\n };\n}\n\n/**\n * The directories whose config a run reads: the project's own, plus the global one it\n * inlines. At the home root the two collapse into one.\n */\nexport function configDirsInPlay(projectDir: string): string[] {\n return isHomeDirectory(projectDir) ? [projectDir] : [projectDir, os.homedir()];\n}\n\n/**\n * Every config a run would read that exists and cannot be loaded, in the order the run reads\n * them. A directory whose config is absent (legitimate) or loads contributes nothing; any other\n * failure is a real fault and propagates.\n *\n * Exported rather than kept private to its first caller because two surfaces have to agree on\n * exactly which configs are in play: `BaseCommand.ensureConfigReadable`, which refuses to run over\n * one it cannot read, and `doctor`, which reports the same fault. Two answers to that question is\n * how the CLI ended up refusing a file in one command and calling it missing in another.\n */\nexport async function findConfigLoadFailures(projectDir: string): Promise<ConfigLoadError[]> {\n const outcomes = await Promise.all(configDirsInPlay(projectDir).map(configLoadFailure));\n return outcomes.filter((failure): failure is ConfigLoadError => failure !== undefined);\n}\n\nasync function configLoadFailure(dir: string): Promise<ConfigLoadError | undefined> {\n try {\n await loadProjectConfigFromDir(dir);\n return undefined;\n } catch (error) {\n if (error instanceof ConfigLoadError) return error;\n throw error;\n }\n}\n\n/**\n * Load project config with global fallback.\n * Checks the given projectDir first, then falls back to the home directory.\n */\nexport async function loadProjectConfig(projectDir: string): Promise<LoadedProjectConfig | null> {\n const projectResult = await loadProjectConfigFromDir(projectDir);\n if (projectResult) return projectResult;\n\n // Global fallback: try home directory\n const homeDir = os.homedir();\n if (!isHomeDirectory(projectDir)) {\n return loadProjectConfigFromDir(homeDir);\n }\n\n return null;\n}\n\n/**\n * Validates a loaded config value. Shape validity is defined by\n * `projectConfigLoaderSchema` (the single definition); on top of the schema's\n * lenient shape, a usable project config additionally requires `name` and\n * `agents` to be present.\n */\nexport function validateProjectConfig(config: unknown): ValidationResult {\n const result = projectConfigLoaderSchema.safeParse(config);\n if (!result.success) {\n return { valid: false, errors: formatZodErrors(result.error), warnings: [] };\n }\n\n const errors = [\n ...(result.data.name ? [] : [\"name is required and must be a string\"]),\n ...(result.data.agents ? [] : [\"agents is required and must be an array\"]),\n ];\n return { valid: errors.length === 0, errors, warnings: [] };\n}\n","import path from \"path\";\nimport { flatMap, groupBy, mapValues, partition, pipe, unique, uniqueBy } from \"remeda\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { hasSkill, matrix } from \"../matrix/matrix-provider\";\nimport type {\n AgentName,\n SkillAssignment,\n SkillId,\n SkillReference,\n Stack,\n StackAgentConfig,\n Category,\n} from \"../../types\";\nimport { stacksConfigSchema } from \"../schemas\";\nimport { typedEntries } from \"../../utils/typed-object\";\nimport { isSkillAssignment } from \"../../utils/type-guards\";\nimport { LOCAL_PSEUDO_CATEGORY, STACKS_FILE_PATH } from \"../../consts\";\nimport { loadConfig } from \"../configuration/config-loader\";\nimport { offersBuiltInStacks } from \"../configuration/config\";\nimport { defaultStacks } from \"../configuration/default-stacks\";\n\nconst stacksCache = new Map<string, Stack[]>();\n\n/**\n * Normalizes a raw agent config (from Zod-parsed config) to StackAgentConfig.\n * Converts bare strings to `{ id, preloaded: false }` and wraps single values in arrays.\n * Used by both loadStacks() and loadProjectConfig() to handle all 3 config formats:\n * 1. bare string: `framework: \"web-framework-react\"`\n * 2. single object: `framework: { id: \"web-framework-react\", preloaded: true }`\n * 3. array: `methodology: [{ id: ..., preloaded: true }, { id: ... }]`\n */\nexport function normalizeAgentConfig(agentConfig: Record<string, unknown>): StackAgentConfig {\n // Boundary casts: Zod-parsed config has loose types (bare strings, objects, arrays)\n // that are normalized to typed SkillAssignment[] values\n return mapValues(agentConfig, (value) => {\n const items = Array.isArray(value) ? value : [value];\n return items.map((item): SkillAssignment => {\n if (typeof item === \"string\") return { id: item as SkillId, preloaded: false };\n if (isSkillAssignment(item)) return item;\n warn(`Malformed skill assignment in stack data: ${JSON.stringify(item)}`);\n return item as SkillAssignment;\n });\n });\n}\n\n/**\n * Where the live catalog says a skill's entry belongs, or `undefined` when it\n * has nothing to say: an id the matrix does not carry (local, marketplace, or\n * withdrawn) and a skill in the `local` pseudo-category both leave the key the\n * config already spells as the only word available.\n */\nfunction liveCategoryOf(skillId: SkillId): Category | undefined {\n const category = matrix.skills[skillId]?.category;\n if (category === undefined || category === LOCAL_PSEUDO_CATEGORY) return undefined;\n // TypeScript narrows CategoryPath to Category after excluding \"local\"\n return category;\n}\n\ntype PlacedAssignment = {\n storedCategory: Category;\n liveCategory: Category;\n assignment: SkillAssignment;\n};\n\nfunction placeAssignments(agentConfig: StackAgentConfig): PlacedAssignment[] {\n return typedEntries<Category, SkillAssignment[]>(agentConfig).flatMap(\n ([storedCategory, assignments]) =>\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n (assignments ?? []).map((assignment) => ({\n storedCategory,\n liveCategory: liveCategoryOf(assignment.id) ?? storedCategory,\n assignment,\n })),\n );\n}\n\n/**\n * One agent's saved stack re-keyed under each skill's live category.\n *\n * A persisted `stack` block names the category each skill sat in when it was\n * written, and every consumer downstream — the generator's preservation\n * lookup, the load-state lookup, the compiled agent's usage line — asks the\n * live catalog. When a release moves a skill between categories the two stop\n * agreeing, and a saved entry nobody can find is a saved entry nobody keeps.\n * Re-keying here is what keeps the question answerable: the category is where\n * an entry is STORED, the id is which skill it names, and only the id is\n * identity.\n *\n * A skill already under its live category wins any collision with a stale\n * duplicate of itself — it is the current word for that pair, and one skill\n * may appear once per agent.\n */\nfunction rekeyToLiveCategories(agentConfig: StackAgentConfig): StackAgentConfig {\n const [settled, moved] = partition(\n placeAssignments(agentConfig),\n (placed) => placed.liveCategory === placed.storedCategory,\n );\n\n if (moved.length > 0) {\n verbose(\n `Re-keyed stack entries to their live category: ` +\n moved\n .map((p) => `${p.assignment.id} (${p.storedCategory} -> ${p.liveCategory})`)\n .join(\", \"),\n );\n }\n\n return mapValues(\n groupBy([...settled, ...moved], (placed) => placed.liveCategory),\n (placed) =>\n uniqueBy(\n placed.map((p) => p.assignment),\n (assignment) => assignment.id,\n ),\n );\n}\n\n/**\n * Normalizes a raw stack record (agent -> raw category config) to the typed form.\n * Applies normalizeAgentConfig to each agent entry, then re-keys the result to\n * the live catalog (see {@link rekeyToLiveCategories}).\n *\n * This is the PERSISTED-CONFIG boundary — `loadProjectConfigFromDir` and the\n * config gate's writer entry. A source's `stacks.ts` deliberately does not pass\n * through here: its category key is the author's heading for the agent prompt,\n * shipped alongside the catalog it references, so there is no drift to\n * reconcile and nothing to overrule.\n */\nexport function normalizeStackRecord(\n rawStack: Record<string, Record<string, unknown>>,\n): Record<string, StackAgentConfig> {\n return mapValues(rawStack, (agentConfig) =>\n rekeyToLiveCategories(normalizeAgentConfig(agentConfig)),\n );\n}\n\nexport async function loadStacks(configDir: string, stacksFile?: string): Promise<Stack[]> {\n const resolvedStacksFile = stacksFile ?? STACKS_FILE_PATH;\n const cacheKey = `${configDir}:${resolvedStacksFile}`;\n const cached = stacksCache.get(cacheKey);\n if (cached) return cached;\n\n const stacksPath = path.join(configDir, resolvedStacksFile);\n\n try {\n const raw = await loadConfig(stacksPath, stacksConfigSchema);\n\n if (raw == null) {\n verbose(`No stacks file found at ${stacksPath}`);\n return [];\n }\n\n // Normalize: all values to SkillAssignment[] so StackAgentConfig is always SkillAssignment[]\n // Boundary casts: Zod stacksConfigSchema outputs loose Record types;\n // narrowing to Stack[\"agents\"] after normalization guarantees SkillAssignment[] values\n const stacks: Stack[] = raw.stacks.map((stack) => ({\n ...stack,\n agents: mapValues(\n stack.agents as Partial<Record<AgentName, Record<string, unknown>>>,\n (agentConfig) => normalizeAgentConfig(agentConfig),\n ),\n }));\n\n stacksCache.set(cacheKey, stacks);\n verbose(`Loaded ${stacks.length} stacks from ${stacksPath}`);\n\n return stacks;\n } catch (error) {\n const errorMessage = getErrorMessage(error);\n throw new Error(`Failed to load stacks from '${stacksPath}': ${errorMessage}`, {\n cause: error,\n });\n }\n}\n\n/**\n * One stack by id, scoped the way the wizard's stack step is.\n *\n * The source's own stacks answer first. The CLI's built-in catalogue stands in\n * only for the public catalogue — the same rule `resolveOfferedStacks` applies to\n * the list the wizard offers, read from the same {@link offersBuiltInStacks} so\n * the two cannot answer differently. They are a pair: that one decides what is\n * OFFERED and this one resolves what was PICKED, so a rule they disagree on\n * offers a stack and then refuses to install it.\n *\n * Under any other source a built-in id names a stack that source does not have,\n * and answering with one would install stacks written against a different\n * catalogue of skills, under a name the user never asked for. Null is the honest\n * answer there; the callers name the id they asked for.\n */\nexport async function loadStackById(\n stackId: string,\n configDir: string,\n source: string,\n): Promise<Stack | null> {\n const stacks = await loadStacks(configDir);\n const stack = stacks.find((s) => s.id === stackId);\n\n if (stack) {\n verbose(`Found stack: ${stack.name} (${stackId})`);\n return stack;\n }\n\n if (!(await offersBuiltInStacks(configDir, source))) {\n verbose(\n `Marketplace '${source}' does not ship stack '${stackId}', and gets no built-in stand-in`,\n );\n return null;\n }\n\n const defaultStack = defaultStacks.find((s) => s.id === stackId) ?? null;\n if (defaultStack) {\n verbose(`Found default stack: ${defaultStack.name} (${stackId})`);\n } else {\n verbose(`Stack '${stackId}' not found in the default marketplace or the built-ins`);\n }\n return defaultStack;\n}\n\n/**\n * What a null from {@link loadStackById} means, said once.\n *\n * Both callers turn that null into a failure, and both have to name the id they\n * asked for and the source they asked — a stack that cannot be found is only\n * actionable if the message says which stack and where it was looked for. One\n * definition so the two surfaces cannot describe the same rule differently.\n */\nexport function stackNotOfferedMessage(stackId: string, source: string): string {\n return (\n `Stack '${stackId}' is not a stack the source '${source}' offers. ` +\n `A marketplace ships its own stacks; the CLI's built-in ones belong to the default ` +\n `public marketplace alone.`\n );\n}\n\n// Converts a StackAgentConfig (category -> SkillAssignment[]) to an array of SkillReferences.\n// Values are already normalized to SkillAssignment[] by loadStacks().\nexport function resolveAgentConfigToSkills(agentConfig: StackAgentConfig): SkillReference[] {\n return typedEntries<Category, SkillAssignment[]>(agentConfig).flatMap(([category, assignments]) =>\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n (assignments ?? []).map((assignment): SkillReference => {\n if (!hasSkill(assignment.id)) {\n warn(\n `Skill '${assignment.id}' for category '${category}' not found in matrix. It may be a custom or local skill.`,\n { suppressInTest: true },\n );\n }\n return {\n id: assignment.id,\n usage: `when working with ${category}`,\n preloaded: assignment.preloaded ?? false,\n };\n }),\n );\n}\n\n/** Extracts all unique skill IDs from a stack config (agent -> category -> SkillAssignment[]). */\nexport function getStackSkillIds(stack: Record<string, StackAgentConfig>): SkillId[] {\n return pipe(\n Object.values(stack),\n flatMap(resolveAgentConfigToSkills),\n (refs) => refs.map((r) => r.id),\n unique(),\n );\n}\n","import { EFFORT_NAMES, MODEL_NAMES } from \"@workspace/matrix\"\nimport { groupBy, unique } from \"remeda\"\n\nimport { isExclusiveCategory, type CompileCatalog } from \"./catalog.js\"\nimport {\n INDENT_STEP,\n brokenUnionLayout,\n flatUnion,\n quoteText,\n renderKey,\n renderTypeImportLine,\n renderUnionBody,\n spaces,\n unionLayout,\n} from \"./installed-format.js\"\nimport { LOCAL_PSEUDO_CATEGORY } from \"./paths.js\"\nimport {\n activeAgentNames,\n activeProjectAgentNames,\n} from \"./scope-predicates.js\"\nimport { bytewise } from \"./string.js\"\nimport { typedEntries, typedKeys } from \"./typed-object.js\"\nimport type {\n AgentName,\n Category,\n CategoryPath,\n ProjectConfig,\n SkillId,\n} from \"./types.js\"\n\n/**\n * Renders `config-types.ts`; writes nothing. The disk-probing half — deciding\n * whether a project extends a global types file, and computing the relative\n * specifier to it — stayed in the CLI's `config-types-writer.ts`, because a\n * browser has no disk to probe and `path.relative(<project>/.claude-src,\n * $HOME/.claude-src)` is a fact about one machine.\n */\n\n/**\n * Emitted for a union with no members. `never` is the identity element for a\n * union: an empty install must accept NO member, and `never | \"web-framework-react\"`\n * reduces to `\"web-framework-react\"`, so a project types file that extends an empty\n * global union still narrows. Emitting `string` here would instead absorb every\n * literal and silently disable type checking of the generated config.ts.\n */\nconst EMPTY_UNION_TYPE = \"never\"\n\n/**\n * Extra just-created skill IDs / agent names / domains / categories to fold into\n * a regenerated config-types.ts (entities that exist in config but not yet in the\n * loaded matrix). buildProjectTypesExtras returns Required<ConfigTypesExtras>.\n */\nexport type ConfigTypesExtras = {\n extraSkillIds?: string[]\n extraAgentNames?: string[]\n extraDomains?: string[]\n extraCategories?: string[]\n}\n\n/**\n * A vocabulary constant as a single-line TypeScript literal union, inside an\n * emitted property where a break would need a layout of its own.\n *\n * That it stays on one line is an assumption about the lists — both are\n * generated from the matrix and both are short — rather than something this\n * function arranges. Nothing guards it here; what does is the fixed-point\n * assertion in `contract/emission-scenarios.test.ts`, which renders both of\n * these lines in every scenario and reddens the moment either grows past the\n * print width, because prettier would then break what this does not.\n */\nfunction formatLiteralUnion(members: readonly string[]): string {\n return flatUnion(members.map(quoteText))\n}\n\n/**\n * Types emitted before the dynamically-generated StackAgentConfig.\n * Includes InstallMode, SkillConfig, AgentScopeConfig, and the generic SkillAssignment.\n */\nexport const PROJECT_CONFIG_TYPES_BEFORE = `export type InstallMode = 'eject' | 'plugin' | 'mixed'\n\nexport type SkillConfig = {\n id: SkillId\n scope: 'project' | 'global'\n origin: string\n excluded?: boolean\n}\n\nexport type AgentScopeConfig = {\n name: AgentName\n scope: 'project' | 'global'\n model?: ${formatLiteralUnion(MODEL_NAMES)}\n effort?: ${formatLiteralUnion(EFFORT_NAMES)}\n excluded?: boolean\n}\n\nexport type SkillAssignment<S extends SkillId = SkillId> = S | { id: S; preloaded: boolean }\n`\n\n/**\n * The ProjectConfig interface, emitted after StackAgentConfig.\n */\nexport const PROJECT_CONFIG_INTERFACE_AFTER = `export interface ProjectConfig {\n /** Project/plugin name (kebab-case) */\n name: string\n\n /** Project description */\n description?: string\n\n /** Per-agent configuration with scope */\n agents: AgentScopeConfig[]\n\n /** Per-skill configuration with scope and provenance */\n skills: SkillConfig[]\n\n /** Author handle (e.g., \"@vince\") */\n author?: string\n\n /** Stack configuration: agent -> category -> skill assignment */\n stack?: Partial<Record<ProjectAgentName, StackAgentConfig>>\n\n /** The marketplace this install reads skills from, as a path or URL */\n marketplace?: string\n\n /** The name that marketplace's manifest gives it, which plugins are registered under */\n marketplaceName?: string\n\n /** Agents source path or URL (when agents come from a different source than skills) */\n agentsSource?: string\n\n /** Selected domains from the wizard */\n selectedDomains?: Domain[]\n\n /** Tracked project installation paths (global config only) */\n projects?: string[]\n}\n`\n\n/**\n * Loose StackAgentConfig line emitted when no per-category skill constraint applies. Admits a\n * single assignment as well as an array: project configs always get this line, and they carry the\n * bare (unwrapped) form for exclusive categories.\n */\nexport const STACK_AGENT_CONFIG_LOOSE_LINE =\n \"export type StackAgentConfig = Partial<Record<Category, SkillAssignment | SkillAssignment[]>>\"\n\n/**\n * Assembles a config-types.ts source from its per-alias union lines — the single\n * template shared by generateConfigTypesSource, generateProjectConfigTypesSource,\n * and generateBlankGlobalConfigTypesSource. Their emitted text is identical apart\n * from the alias contents, the StackAgentConfig line, and the optional\n * (project-only) import block.\n *\n * The emitted ProjectConfig interface (PROJECT_CONFIG_INTERFACE_AFTER) deliberately\n * diverges from types/config.ts: it uses the narrowed generated aliases\n * (SelectedAgentName, ProjectAgentName, per-category StackAgentConfig) so a user's\n * config.ts is type-checked against only the installed skills/agents rather than\n * the full runtime union.\n */\nexport function assembleConfigTypesSource(parts: {\n importBlock?: string\n skillId: AliasRhs\n agentName: AliasRhs\n selectedAgentName: AliasRhs\n projectAgentName: AliasRhs\n domain: AliasRhs\n category: AliasRhs\n stackAgentConfig: string\n}): string {\n const importSection = parts.importBlock ? `${parts.importBlock}\\n\\n` : \"\"\n return `// AUTO-GENERATED by agents-inc — DO NOT EDIT\n\n${importSection}${renderAlias(\"SkillId\", parts.skillId)}\n\n${renderAlias(\"AgentName\", parts.agentName)}\n\n${renderAlias(\"SelectedAgentName\", parts.selectedAgentName)}\n\n${renderAlias(\"ProjectAgentName\", parts.projectAgentName)}\n\n${renderAlias(\"Domain\", parts.domain)}\n\n${renderAlias(\"Category\", parts.category)}\n\n${PROJECT_CONFIG_TYPES_BEFORE}\n${parts.stackAgentConfig}\n\n${PROJECT_CONFIG_INTERFACE_AFTER}`\n}\n\n/**\n * What one emitted type alias is assigned.\n *\n * Members rather than the finished text, because whether they sit on the\n * declaration's own line, on an indented line below it, or one per line under a\n * leading `|` is decided by how wide they are once the alias NAME is in front\n * of them — which only the assembler knows.\n */\nexport type AliasRhs =\n | { kind: \"plain\"; members: readonly string[] }\n | {\n kind: \"sectioned\"\n custom: readonly string[]\n marketplace: readonly string[]\n }\n\n/** A union over quoted string literals, or `never` when it has no members. */\nfunction literalUnion(members: readonly string[]): AliasRhs {\n return members.length === 0\n ? typeReference(EMPTY_UNION_TYPE)\n : { kind: \"plain\", members: members.map(quoteText) }\n}\n\n/** A bare type name as an alias's whole right-hand side. */\nfunction typeReference(name: string): AliasRhs {\n return { kind: \"plain\", members: [name] }\n}\n\n/** `export type <name> = <rhs>`, laid out the way prettier lays a union out. */\nfunction renderAlias(name: string, rhs: AliasRhs): string {\n const head = `export type ${name} =`\n if (rhs.kind === \"sectioned\") {\n return `${head}\\n${renderSectionedUnion(rhs.custom, rhs.marketplace)}`\n }\n\n const layout = unionLayout(rhs.members, {\n headWidth: head.length + \" \".length,\n tailWidth: 0,\n bodyIndent: INDENT_STEP,\n })\n\n return layout === \"inline\"\n ? `${head} ${flatUnion(rhs.members)}`\n : `${head}\\n${renderUnionBody(rhs.members, layout, INDENT_STEP)}`\n}\n\n/**\n * A union under its `// Custom` and `// Marketplace` headings.\n *\n * `custom` is non-empty by construction — {@link formatMaybeSectionedUnion} is\n * the only producer of a sectioned right-hand side and it answers with a plain\n * one when nothing is custom. Both headings present puts a comment BETWEEN two\n * members, which prettier cannot fold away, so that union stays one member per\n * line however short it is; a single heading only pushes the members off the\n * declaration's line, and they rejoin below it when they fit.\n */\nfunction renderSectionedUnion(\n custom: readonly string[],\n marketplace: readonly string[]\n): string {\n if (marketplace.length > 0) {\n return [\n sectionHeading(\"Custom\"),\n renderUnionBody(custom, \"stacked\", INDENT_STEP),\n sectionHeading(\"Marketplace\"),\n renderUnionBody(marketplace, \"stacked\", INDENT_STEP),\n ].join(\"\\n\")\n }\n\n return [\n sectionHeading(\"Custom\"),\n renderUnionBody(\n custom,\n brokenUnionLayout(custom, INDENT_STEP),\n INDENT_STEP\n ),\n ].join(\"\\n\")\n}\n\n/** A `// Custom` or `// Marketplace` line above the members it introduces. */\nfunction sectionHeading(text: string): string {\n return `${spaces(INDENT_STEP)}// ${text}`\n}\n\n/**\n * Generates a per-category constrained StackAgentConfig type from skill-by-category groupings.\n * Falls back to the loose line when no categories have skills.\n *\n * The union is over WHICH skill may be assigned; exclusivity is about HOW MANY, so an exclusive\n * category emits a bare `SkillAssignment<...>` (no array) however long its candidate list is. A\n * category the catalogue does not declare is not treated as exclusive, on the same reasoning\n * `isExclusiveCategory` takes: a constraint must fire on a flag the data actually carries.\n */\nfunction generateStackAgentConfig(\n skillsByCategory: Map<Category, SkillId[]>,\n catalog: CompileCatalog\n): string {\n if (skillsByCategory.size === 0) {\n return STACK_AGENT_CONFIG_LOOSE_LINE\n }\n\n const properties = [...skillsByCategory.entries()]\n // A project commits its config-types.ts, so the key order has to be the comparator's rather\n // than the collation of whichever machine last ran the CLI.\n .sort(([a], [b]) => bytewise(a, b))\n .map(([category, skills]) => renderStackProperty(category, skills, catalog))\n\n return [\"export type StackAgentConfig = {\", ...properties, \"}\"].join(\"\\n\")\n}\n\n/**\n * One category's property, with its candidate skills laid out where they sit.\n *\n * The union is inside a type ARGUMENT rather than on a declaration's own line,\n * so its indented and one-per-line forms carry the closing `>` down with them —\n * but the widths that choose between the three are the same ones everywhere\n * else, which is why the decision comes from the shared layout rather than from\n * a count of members.\n */\nfunction renderStackProperty(\n category: Category,\n skills: SkillId[],\n catalog: CompileCatalog\n): string {\n const members = [...skills].sort().map(quoteText)\n const tail = `>${isExclusiveCategory(catalog, category) ? \"\" : \"[]\"}`\n const head = `${spaces(INDENT_STEP)}${renderKey(category)}?: SkillAssignment<`\n const bodyIndent = INDENT_STEP * 2\n\n const layout = unionLayout(members, {\n headWidth: head.length,\n tailWidth: tail.length,\n bodyIndent,\n })\n if (layout === \"inline\") return `${head}${flatUnion(members)}${tail}`\n\n return [\n head,\n renderUnionBody(members, layout, bodyIndent),\n `${spaces(INDENT_STEP)}${tail}`,\n ].join(\"\\n\")\n}\n\n/**\n * Builds a Map of Category -> SkillId[] from the catalogue, filtered to only include\n * categories and skills that are in the provided arrays.\n */\nfunction buildSkillsByCategory(\n skillIds: SkillId[],\n categories: Category[],\n catalog: CompileCatalog\n): Map<Category, SkillId[]> {\n const categorySet = new Set(categories)\n const eligible = [...new Set(skillIds)]\n .map((id) => ({ id, category: catalog.skills[id]?.category }))\n .filter(\n (entry): entry is { id: SkillId; category: Category } =>\n entry.category !== undefined &&\n entry.category !== LOCAL_PSEUDO_CATEGORY &&\n // Boundary cast: a catalogue skill's `category` is a Category, typed `string` on the\n // narrow catalogue shape so the wire `Matrix` satisfies it too. The `has` below IS the\n // runtime check the predicate rests on, so the cast only lets the probe be written.\n categorySet.has(entry.category as Category)\n )\n\n return new Map(\n typedEntries(groupBy(eligible, (entry) => entry.category)).map(\n ([category, entries]) => [category, entries.map((entry) => entry.id)]\n )\n )\n}\n\n/**\n * A category no loaded catalogue declares, which is the whole of what makes one custom.\n *\n * Deliberately not \"a category a custom skill is in\": a custom skill is PLACED in a category that\n * already exists rather than bringing one, so the skills that REFERENCE a category say nothing\n * about who declared it — and reading them that way labelled a category the public catalogue\n * ships as the user's own. The same holds for a category arriving as an extra: an extra is every\n * literal a just-written config.ts holds, most of them the catalogue's.\n */\nfunction isUndeclaredCategory(\n category: Category,\n catalog: CompileCatalog\n): boolean {\n return catalog.categories[category] === undefined\n}\n\n/**\n * A skill the loaded catalogue does not declare, or declares as the user's own.\n *\n * The same rule the category axis takes, plus the one signal skills carry that categories do not:\n * `custom: true` is written into a skill's own metadata, so a skill the catalogue holds AND flags\n * is the user's however it got there. What is NOT read is which argument the id arrived in — an\n * extra is a literal the just-written config.ts holds, and on the project standalone path that is\n * the whole configuration, most of it the catalogue's.\n *\n * `local: true` is deliberately not a second signal: an ejected catalogue skill is copied into\n * `.claude/skills/` and rediscovered as local, so it would label the catalogue's own work custom.\n */\nfunction isCustomSkill(skillId: SkillId, catalog: CompileCatalog): boolean {\n const declared = catalog.skills[skillId]\n return declared === undefined || declared.custom === true\n}\n\n/**\n * An agent the loaded source does not declare, or declares as the user's own.\n *\n * `agentNames` is every agent that source ships and `customAgentNames` the ones it marks custom,\n * so the pair is the agent axis's equivalent of the catalogue: anything outside the first is\n * nobody's declaration, anything inside the second is declared as the user's.\n */\nfunction isCustomAgent(\n agentName: AgentName,\n declared: ReadonlySet<AgentName>,\n flaggedCustom: ReadonlySet<AgentName>\n): boolean {\n return !declared.has(agentName) || flaggedCustom.has(agentName)\n}\n\n/**\n * A domain no category the loaded catalogue declares carries.\n */\nfunction isCustomDomain(\n domain: string,\n declared: ReadonlySet<string>\n): boolean {\n return !declared.has(domain)\n}\n\n/**\n * Generates a config-types.ts source from catalogue data.\n * The generated file provides type safety for config.ts via `import type` + `satisfies`.\n *\n * @param customAgentNames Agent names that are custom (from sources with `custom: true`)\n * @param extras Optional extra skill IDs or agent names to include (for just-created entities)\n * @param config Optional ProjectConfig to narrow unions to only installed items.\n * When provided, SkillId/AgentName/Category/Domain are derived from\n * the config's skills[] and agents[] rather than the full catalogue.\n */\nexport function generateConfigTypesSource(\n catalog: CompileCatalog,\n agentNames: AgentName[],\n customAgentNames: AgentName[] = [],\n extras?: ConfigTypesExtras,\n config?: ProjectConfig\n): string {\n // Boundary cast: extra IDs from CLI args may not match strict union patterns\n const extraSkillIds = (extras?.extraSkillIds ?? []) as SkillId[]\n const extraAgentNamesArr = (extras?.extraAgentNames ?? []) as AgentName[]\n const extraDomainsArr = extras?.extraDomains ?? []\n const extraCategoriesArr = (extras?.extraCategories ?? []) as Category[]\n\n let skillIds: SkillId[]\n let sortedAgents: AgentName[]\n let domains: string[]\n let categories: Category[]\n\n if (config) {\n // Narrow to only installed/configured items\n const configSkillIds = config.skills.map((s) => s.id)\n skillIds = unique([...configSkillIds, ...extraSkillIds]).sort()\n\n const configAgentNames = config.agents.map((a) => a.name)\n sortedAgents = unique([...configAgentNames, ...extraAgentNamesArr]).sort()\n\n const configCategories = deriveCategories(configSkillIds, catalog)\n categories = unique([...configCategories, ...extraCategoriesArr]).sort()\n\n // Also include config.selectedDomains (user-selected) that may not have skills in this scope\n const configDomains = deriveDomains(categories, catalog)\n domains = unique([\n ...configDomains,\n ...(config.selectedDomains ?? []),\n ...extraDomainsArr,\n ]).sort()\n } else {\n // Fall back to the full catalogue (e.g., blank global config)\n skillIds = unique([\n ...typedKeys<SkillId>(catalog.skills),\n ...extraSkillIds,\n ]).sort()\n sortedAgents = unique([...agentNames, ...extraAgentNamesArr]).sort()\n domains = unique([...extractDomains(catalog), ...extraDomainsArr]).sort()\n categories = unique([\n ...typedKeys<Category>(catalog.categories),\n ...extraCategoriesArr,\n ]).sort()\n }\n\n const declaredAgents = new Set<AgentName>(agentNames)\n const flaggedCustomAgents = new Set<AgentName>(customAgentNames)\n const declaredDomains = new Set<string>(extractDomains(catalog))\n\n const skillIdLine = formatMaybeSectionedUnion(skillIds, (id) =>\n isCustomSkill(id, catalog)\n )\n const agentNameLine = formatMaybeSectionedUnion(sortedAgents, (name) =>\n isCustomAgent(name, declaredAgents, flaggedCustomAgents)\n )\n const domainLine = formatMaybeSectionedUnion(domains, (domain) =>\n isCustomDomain(domain, declaredDomains)\n )\n const categoryLine = formatMaybeSectionedUnion(categories, (category) =>\n isUndeclaredCategory(category, catalog)\n )\n\n const selectedAgents = config?.agents ? activeAgentNames(config.agents) : []\n const selectedAgentNameLine =\n selectedAgents.length > 0\n ? literalUnion(selectedAgents)\n : typeReference(\"AgentName\")\n\n const projectScopedAgents = config?.agents\n ? activeProjectAgentNames(config.agents)\n : []\n const projectAgentNameLine =\n projectScopedAgents.length > 0\n ? literalUnion(projectScopedAgents)\n : typeReference(\"SelectedAgentName\")\n\n const skillsByCategory = buildSkillsByCategory(skillIds, categories, catalog)\n const stackAgentConfigType = generateStackAgentConfig(\n skillsByCategory,\n catalog\n )\n\n return assembleConfigTypesSource({\n skillId: skillIdLine,\n agentName: agentNameLine,\n selectedAgentName: selectedAgentNameLine,\n projectAgentName: projectAgentNameLine,\n domain: domainLine,\n category: categoryLine,\n stackAgentConfig: stackAgentConfigType,\n })\n}\n\n// Sorted deriveDomains over every category — kept separate: this is the full-catalogue domain\n// union for the standalone types file, not a per-selection derivation.\nfunction extractDomains(catalog: CompileCatalog): string[] {\n return deriveDomains(typedKeys<Category>(catalog.categories), catalog).sort()\n}\n\n/** Category present and not the \"local\" pseudo-category. */\nconst isNonLocalCategory = (\n category: CategoryPath | undefined\n): category is Category =>\n Boolean(category) && category !== LOCAL_PSEUDO_CATEGORY\n\n/**\n * Derives the set of categories that the given skill IDs belong to,\n * by looking up each skill's category in the catalogue.\n */\nexport function deriveCategories(\n skillIds: SkillId[],\n catalog: CompileCatalog\n): Category[] {\n return unique(\n skillIds\n // Boundary cast: CategoryPath to Category for catalogue key lookup\n .map((id) => catalog.skills[id]?.category as CategoryPath | undefined)\n .filter(isNonLocalCategory)\n )\n}\n\n/**\n * Derives the set of domains that the given categories belong to,\n * by looking up each category's domain in the catalogue.\n */\nexport function deriveDomains(\n categories: Category[],\n catalog: CompileCatalog\n): string[] {\n return unique(\n categories\n .map((cat) => catalog.categories[cat]?.domain)\n .filter((domain): domain is string => domain !== undefined)\n )\n}\n\n/**\n * A union split into its `// Custom` and `// Marketplace` sections when it has\n * custom members, and a plain one when it has none.\n */\nfunction formatMaybeSectionedUnion<T extends string>(\n members: T[],\n isCustom: (member: T) => boolean\n): AliasRhs {\n if (members.length === 0) {\n return typeReference(EMPTY_UNION_TYPE)\n }\n\n const custom = members.filter(isCustom)\n const marketplace = members.filter((m) => !isCustom(m))\n\n // No custom members: no headings to draw, so the union is an ordinary one.\n if (custom.length === 0) {\n return literalUnion(members)\n }\n\n return {\n kind: \"sectioned\",\n custom: custom.map(quoteText),\n marketplace: marketplace.map(quoteText),\n }\n}\n\nexport type ProjectConfigTypesOptions = {\n /**\n * Absolute path to the global .claude-src directory.\n * When set, generates import statements that extend global types.\n */\n globalTypesImportPath: string\n /** Project-only skill IDs (not including global) */\n projectSkillIds: string[]\n /** Project-only agent names (not including global) */\n projectAgentNames: string[]\n /** Project-only domains (not including global) */\n projectDomains: string[]\n /** Project-only categories (not including global) */\n projectCategories?: string[]\n /** Selected agent names from config (narrows SelectedAgentName) */\n selectedAgentNames?: string[]\n /** Project-scoped agent names (narrows ProjectAgentName for stack keys) */\n projectScopedAgentNames?: string[]\n}\n\n/**\n * Generates a project config-types.ts source that imports global types and extends them.\n * Each type union is `GlobalType | \"project-item-1\" | \"project-item-2\"`.\n * When projectCategories are provided, Category extends GlobalCategory instead of being `string`.\n */\nexport function generateProjectConfigTypesSource(\n options: ProjectConfigTypesOptions\n): string {\n const importPath = `${options.globalTypesImportPath}/config-types`\n\n const skillIdUnion = formatExtendedUnion(\n \"GlobalSkillId\",\n options.projectSkillIds\n )\n const agentNameUnion = formatExtendedUnion(\n \"GlobalAgentName\",\n options.projectAgentNames\n )\n const domainUnion = formatExtendedUnion(\n \"GlobalDomain\",\n options.projectDomains\n )\n\n const projectCategories = options.projectCategories ?? []\n const categoryUnion = formatExtendedUnion(\"GlobalCategory\", projectCategories)\n\n const selectedAgentNameUnion = options.selectedAgentNames?.length\n ? literalUnion(options.selectedAgentNames)\n : typeReference(\"AgentName\")\n\n const projectAgentNameUnion = options.projectScopedAgentNames?.length\n ? literalUnion(options.projectScopedAgentNames)\n : typeReference(\"SelectedAgentName\")\n\n // Category comes across as GlobalCategory whether or not this project adds\n // any of its own, because the alias is re-exported either way.\n const importBlock = renderTypeImportLine(\n [\n \"SkillId as GlobalSkillId\",\n \"AgentName as GlobalAgentName\",\n \"Domain as GlobalDomain\",\n \"Category as GlobalCategory\",\n ],\n importPath\n )\n\n return assembleConfigTypesSource({\n importBlock,\n skillId: skillIdUnion,\n agentName: agentNameUnion,\n selectedAgentName: selectedAgentNameUnion,\n projectAgentName: projectAgentNameUnion,\n domain: domainUnion,\n category: categoryUnion,\n stackAgentConfig: STACK_AGENT_CONFIG_LOOSE_LINE,\n })\n}\n\n/**\n * Generates blank global config-types source (all types are `never`).\n */\nexport function generateBlankGlobalConfigTypesSource(): string {\n return assembleConfigTypesSource({\n skillId: typeReference(EMPTY_UNION_TYPE),\n agentName: typeReference(EMPTY_UNION_TYPE),\n selectedAgentName: typeReference(EMPTY_UNION_TYPE),\n projectAgentName: typeReference(\"SelectedAgentName\"),\n domain: typeReference(EMPTY_UNION_TYPE),\n category: typeReference(EMPTY_UNION_TYPE),\n stackAgentConfig: STACK_AGENT_CONFIG_LOOSE_LINE,\n })\n}\n\n/**\n * A union that extends a global type alias: `GlobalType` on its own when this\n * project adds nothing, and `GlobalType | \"a\" | \"b\"` when it does.\n */\nfunction formatExtendedUnion(\n globalTypeName: string,\n projectMembers: readonly string[]\n): AliasRhs {\n if (projectMembers.length === 0) {\n return typeReference(globalTypeName)\n }\n\n return {\n kind: \"plain\",\n members: [globalTypeName, ...[...projectMembers].sort().map(quoteText)],\n }\n}\n","/**\n * The one style the two files an install writes are emitted in.\n *\n * Owner ruling, 2026-08-26: `.claude-src/config.ts` and `.claude-src/config-types.ts`\n * land ALREADY FORMATTED, so running prettier over them changes nothing. The\n * settings they are a fixed point of are a USER's rather than this repository's\n * — `parser: \"typescript\", semi: false, singleQuote: true, printWidth: 100,\n * trailingComma: \"all\"` — and they match neither of ours on purpose: the bytes\n * land in somebody else's project, and this repository's own copy is named in\n * `.prettierignore` so nothing here ever formats them.\n *\n * PRETTIER IS DELIBERATELY ABSENT FROM THIS MODULE. It is a devDependency, tsup\n * bundles devDependencies, and calling it from here would inline the TypeScript\n * parser into the published CLI and into the editor's lazily-loaded preview\n * chunk. So what is below reproduces what prettier does to these narrow shapes,\n * and prettier appears only in `contract/emission-scenarios.test.ts`, which runs\n * it over every emitter's output and demands it come back unchanged.\n *\n * The rules were measured against prettier 3.9 rather than reasoned about, and\n * every one of them is the same rule: a construct is flat while its whole line\n * fits in {@link PRINT_WIDTH} counting whatever precedes and follows it, and\n * breaks the moment it does not. Two behaviours are relied on and neither is\n * derivable from that: a `//` line cannot be folded back onto one line, so an\n * array carrying one always breaks; and an object literal whose source has a\n * newline after its `{` stays broken however short it is, which is what lets\n * the `export default` table of contents keep its shape.\n */\n\n/** The column an emitted line may reach — `printWidth` in the settings above. */\nexport const PRINT_WIDTH = 100\n\n/** One level of indentation — `tabWidth` in the settings above. */\nexport const INDENT_STEP = 2\n\n/** The quote `singleQuote: true` asks for, and the one it falls back to. */\nconst PREFERRED_QUOTE = \"'\"\nconst FALLBACK_QUOTE = '\"'\n\n/** A key `quoteProps: \"as-needed\"` leaves unquoted: a plain identifier. */\nconst BARE_KEY = /^[A-Za-z_$][A-Za-z0-9_$]*$/\n\n/** The one form an array and a record with nothing in them can take. */\nconst EMPTY_ARRAY = \"[]\"\nconst EMPTY_RECORD = \"{}\"\n\n/** A JSON object, as distinct from an array, a null or a scalar. */\nexport function isKeyedRecord(\n value: unknown\n): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\n/**\n * A string as a TypeScript literal, in the quote prettier would pick: the\n * preferred one, unless the value holds more of it than of the other and\n * swapping would save escapes. A tie keeps the preferred quote.\n */\nexport function quoteText(value: string): string {\n const preferred = occurrences(value, PREFERRED_QUOTE)\n const fallback = occurrences(value, FALLBACK_QUOTE)\n const quote = preferred > fallback ? FALLBACK_QUOTE : PREFERRED_QUOTE\n\n return `${quote}${escapedFor(value, quote)}${quote}`\n}\n\n/** An object key, quoted only where it has to be. */\nexport function renderKey(key: string): string {\n return BARE_KEY.test(key) ? key : quoteText(key)\n}\n\n/**\n * What can sit inside an emitted array.\n *\n * A comment is an entry rather than something a caller splices in around the\n * printer, because a `//` line is what forces the array to break — a\n * hand-assembled array with a section comment and one short entry would\n * otherwise be folded back onto one line and lose the comment's position.\n */\nexport type ArrayEntry =\n | { kind: \"value\"; value: unknown }\n | { kind: \"source\"; source: string }\n | { kind: \"comment\"; text: string }\n\n/** Plain values as array entries. */\nexport function valueEntries(values: readonly unknown[]): ArrayEntry[] {\n return values.map((value) => ({ kind: \"value\", value }))\n}\n\n/** A `//` line between an array's entries. */\nexport function commentEntry(text: string): ArrayEntry {\n return { kind: \"comment\", text }\n}\n\n/** An expression written into an array as it stands, such as a spread. */\nexport function sourceEntry(source: string): ArrayEntry {\n return { kind: \"source\", source }\n}\n\n/**\n * Where a value sits, which is the whole of what decides whether it stays flat.\n */\nexport type LinePosition = {\n /** Columns of indentation the line starts at, and its closing line returns to. */\n indent: number\n /** What precedes the value on its first line, after the indentation. */\n prefix: string\n /** What follows the value on its last line. */\n suffix: string\n}\n\n/** `<indent><prefix><value><suffix>`, broken across lines when it does not fit. */\nexport function renderValueLine(\n value: unknown,\n position: LinePosition\n): string {\n return line(\n renderValue(value, position),\n movesBelowItsPrefix(value),\n position\n )\n}\n\n/** The same, for an array whose entries may be comments or written-out source. */\nexport function renderArrayLine(\n entries: readonly ArrayEntry[],\n position: LinePosition\n): string {\n return line(renderArray(entries, position), entries.length === 0, position)\n}\n\n/** Which of the three shapes prettier gives a union where it sits. */\nexport type UnionLayout = \"inline\" | \"indented\" | \"stacked\"\n\n/** A union that has already left the line it was introduced on. */\nexport type BrokenUnionLayout = Exclude<UnionLayout, \"inline\">\n\n/** Where a union sits, which is what decides which shape it takes. */\nexport type UnionPosition = {\n /** Columns before the union on the line it would sit inline on. */\n headWidth: number\n /** Columns after it on that same line. */\n tailWidth: number\n /** Indentation the union's own lines take once it leaves that line. */\n bodyIndent: number\n}\n\n/**\n * The shape a union takes, which prettier decides in exactly this order:\n * inline while the whole line fits, then its own indented line while THAT\n * fits, and one member per line under a leading `|` only when neither does.\n */\nexport function unionLayout(\n members: readonly string[],\n position: UnionPosition\n): UnionLayout {\n const flat = flatUnion(members)\n const inlineWidth = position.headWidth + flat.length + position.tailWidth\n\n return inlineWidth <= PRINT_WIDTH\n ? \"inline\"\n : brokenUnionLayout(members, position.bodyIndent)\n}\n\n/**\n * The same decision for a union that cannot be inline whatever its width — the\n * sectioned ones, whose `// Custom` heading has already broken the line.\n */\nexport function brokenUnionLayout(\n members: readonly string[],\n bodyIndent: number\n): BrokenUnionLayout {\n return bodyIndent + flatUnion(members).length <= PRINT_WIDTH\n ? \"indented\"\n : \"stacked\"\n}\n\n/** A union's members as their own indented lines, in the shape `layout` names. */\nexport function renderUnionBody(\n members: readonly string[],\n layout: BrokenUnionLayout,\n bodyIndent: number\n): string {\n const padding = spaces(bodyIndent)\n\n return layout === \"indented\"\n ? `${padding}${flatUnion(members)}`\n : members.map((member) => `${padding}| ${member}`).join(\"\\n\")\n}\n\n/** A union's members joined on one line. */\nexport function flatUnion(members: readonly string[]): string {\n return members.join(\" | \")\n}\n\n/**\n * `import type { … } from '…'`, one specifier per line once the single-line\n * form no longer fits.\n */\nexport function renderTypeImportLine(\n specifiers: readonly string[],\n modulePath: string\n): string {\n const from = ` from ${quoteText(modulePath)}`\n const inline = `import type { ${specifiers.join(\", \")} }${from}`\n if (inline.length <= PRINT_WIDTH) return inline\n\n const lines = specifiers.map(\n (specifier) => `${spaces(INDENT_STEP)}${specifier},`\n )\n return [\"import type {\", ...lines, `}${from}`].join(\"\\n\")\n}\n\n/**\n * The finished line, with the value moved below the `key:` or `= ` that\n * introduces it when it is too wide to stay beside it.\n *\n * A value with a prefix of `\"\"` is an array element, which has nothing above it\n * to move under and stays where it is however wide it runs.\n */\nfunction line(\n rendered: string,\n mayMoveBelowPrefix: boolean,\n position: LinePosition\n): string {\n const prefix = position.prefix.trimEnd()\n if (!mayMoveBelowPrefix || prefix === \"\" || fits(rendered, position)) {\n return asLine(rendered, position)\n }\n\n const body = `${spaces(position.indent + INDENT_STEP)}${rendered}${position.suffix}`\n return `${spaces(position.indent)}${prefix}\\n${body}`\n}\n\n/**\n * Whether prettier moves a value below its prefix rather than leaving it past\n * the print width.\n *\n * Nothing in this set can break INSIDE itself, so moving down is the only\n * shortening available to any of them — and the membership was measured\n * against prettier 3.9 rather than reasoned about, because it is not the set a\n * reader would predict: a string, a `null`, an empty array and an empty record\n * all move, while a number and a boolean stay on the line however far past the\n * width they run.\n */\nfunction movesBelowItsPrefix(value: unknown): boolean {\n if (typeof value === \"string\" || value === null) return true\n if (Array.isArray(value)) return value.length === 0\n return isKeyedRecord(value) && Object.keys(value).length === 0\n}\n\nfunction asLine(rendered: string, position: LinePosition): string {\n return `${spaces(position.indent)}${position.prefix}${rendered}${position.suffix}`\n}\n\n/** A value's own text — continuation lines indented, prefix and suffix excluded. */\nfunction renderValue(value: unknown, position: LinePosition): string {\n if (Array.isArray(value)) return renderArray(valueEntries(value), position)\n if (isKeyedRecord(value)) return renderRecord(value, position)\n return renderScalar(value)\n}\n\nfunction renderArray(\n entries: readonly ArrayEntry[],\n position: LinePosition\n): string {\n const flat = flatArray(entries)\n if (flat !== undefined && fits(flat, position)) return flat\n\n const inner = position.indent + INDENT_STEP\n const lines = entries.map((entry) => renderEntryLine(entry, inner))\n return [\"[\", ...lines, `${spaces(position.indent)}]`].join(\"\\n\")\n}\n\nfunction renderEntryLine(entry: ArrayEntry, indent: number): string {\n if (entry.kind === \"comment\") return `${spaces(indent)}// ${entry.text}`\n if (entry.kind === \"source\") return `${spaces(indent)}${entry.source},`\n return renderValueLine(entry.value, { indent, prefix: \"\", suffix: \",\" })\n}\n\nfunction renderRecord(\n record: Record<string, unknown>,\n position: LinePosition\n): string {\n const properties = Object.entries(record)\n // An empty record has nothing to break onto its own lines, so `{}` is the\n // only form it has however little room is left for it.\n if (properties.length === 0) return EMPTY_RECORD\n\n const flat = flatRecord(record)\n if (fits(flat, position)) return flat\n\n const inner = position.indent + INDENT_STEP\n const lines = properties.map(([key, value]) =>\n renderValueLine(value, {\n indent: inner,\n prefix: `${renderKey(key)}: `,\n suffix: \",\",\n })\n )\n return [\"{\", ...lines, `${spaces(position.indent)}}`].join(\"\\n\")\n}\n\n/** The one-line form of an array, or nothing when a comment forbids one. */\nfunction flatArray(entries: readonly ArrayEntry[]): string | undefined {\n const items: string[] = []\n\n for (const entry of entries) {\n // A `//` line cannot be folded back onto one line, so an array holding one\n // has no flat form at all.\n if (entry.kind === \"comment\") return undefined\n items.push(entry.kind === \"source\" ? entry.source : flatValue(entry.value))\n }\n\n return flatList(items)\n}\n\nfunction flatValue(value: unknown): string {\n if (Array.isArray(value)) return flatList(value.map(flatValue))\n if (isKeyedRecord(value)) return flatRecord(value)\n return renderScalar(value)\n}\n\nfunction flatList(items: readonly string[]): string {\n return items.length === 0 ? EMPTY_ARRAY : `[${items.join(\", \")}]`\n}\n\nfunction flatRecord(record: Record<string, unknown>): string {\n const properties = Object.entries(record).map(\n ([key, value]) => `${renderKey(key)}: ${flatValue(value)}`\n )\n return properties.length === 0 ? EMPTY_RECORD : `{ ${properties.join(\", \")} }`\n}\n\nfunction renderScalar(value: unknown): string {\n return typeof value === \"string\" ? quoteText(value) : String(value)\n}\n\nfunction fits(flat: string, position: LinePosition): boolean {\n const width =\n position.indent +\n position.prefix.length +\n flat.length +\n position.suffix.length\n\n return width <= PRINT_WIDTH\n}\n\nfunction occurrences(value: string, character: string): number {\n return value.split(character).length - 1\n}\n\n/**\n * A string's body under one enclosing quote: JSON's own escaping, with the\n * escape moved off the double quote and onto whichever quote encloses it.\n */\nfunction escapedFor(value: string, quote: string): string {\n const jsonBody = JSON.stringify(value).slice(1, -1)\n if (quote === FALLBACK_QUOTE) return jsonBody\n\n return jsonBody.replaceAll('\\\\\"', '\"').replaceAll(\"'\", \"\\\\'\")\n}\n\n/** That many columns of padding. */\nexport function spaces(count: number): string {\n return \" \".repeat(count)\n}\n","import path from \"path\";\n\nimport type { AgentDefinition, AgentName, MergedSkillsMatrix } from \"../../types\";\nimport { CLAUDE_SRC_DIR, globalInstallRoot, STANDARD_FILES } from \"../../consts\";\n// The gate's private token module, imported here by exception (eslint records\n// it): this is one of the two enforcement guards, and `gate-token.ts` is a\n// dependency-free leaf, so the import cannot cycle back through the gate.\nimport { GlobalPairWriteViolation } from \"../config-gate/gate-token.js\";\nimport { isHomeDirectory } from \"../installation/is-home-directory\";\nimport { fileExists, writeFile } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { typedKeys } from \"../../utils/typed-object\";\nimport {\n generateConfigTypesSource,\n generateProjectConfigTypesSource,\n type ConfigTypesExtras,\n} from \"@workspace/compile/config-types-source\";\n\nimport { loadProjectConfigFromDir } from \"./project-config\";\nimport { activeAgentNames, activeProjectAgentNames } from \"./scope-predicates\";\n\n/**\n * The half of the types writer that reads the machine: whether a global types file exists to\n * extend, the relative specifier to it, and the write itself. Split out from\n * `config-types-writer.ts` when the renderers moved into `@workspace/compile` — those three were\n * the whole reason that module reached `fileExists`, `writeFile`, `loadProjectConfigFromDir` and\n * `globalInstallRoot`, and a browser has none of them. `config-types-writer.ts` re-exports every\n * name below, so no call site moved.\n */\n\n/**\n * Returns the absolute path to the global config-types.ts if it exists, or null.\n * Used to determine whether a project config-types.ts should import from global.\n */\nexport async function getGlobalConfigTypesPath(): Promise<string | null> {\n const globalConfigTypesPath = path.join(\n globalInstallRoot(),\n CLAUDE_SRC_DIR,\n STANDARD_FILES.CONFIG_TYPES_TS,\n );\n if (await fileExists(globalConfigTypesPath)) {\n return globalConfigTypesPath;\n }\n return null;\n}\n\n/**\n * Computes a relative import path from a project's .claude-src/ to the global .claude-src/.\n * Returns a POSIX-style relative path suitable for TypeScript import statements.\n *\n * Deliberately NOT part of the shared package: it is `path.relative` against the running\n * machine's `$HOME`, so a browser has nothing to compute it from and the preview draws a\n * placeholder for that one line instead of inventing a path.\n */\nfunction computeGlobalTypesImportPath(projectDir: string): string {\n const projectClaudeSrc = path.join(projectDir, CLAUDE_SRC_DIR);\n const globalClaudeSrc = path.join(globalInstallRoot(), CLAUDE_SRC_DIR);\n const relativePath = path.relative(projectClaudeSrc, globalClaudeSrc);\n // Convert to POSIX separators for TypeScript imports\n return relativePath.split(path.sep).join(\"/\");\n}\n\nexport type ConfigTypesBackgroundData = {\n matrix: MergedSkillsMatrix;\n agentNames: AgentName[];\n customAgentNames: AgentName[];\n};\n\n/**\n * The one constructor for {@link ConfigTypesBackgroundData}, beside the type it builds.\n *\n * Only `customAgentNames` is derived, and that derivation is the whole reason this is a function\n * rather than an object literal at each call site: it was written out three times — here, in\n * `config-gate/pair-writer.ts` and in `config-gate/propagate.ts` — and three producers of one\n * value are three things that can disagree about which sub-agents an emitted `AgentName` union\n * files under its `// Custom` heading. Closing two of the three would have been worse than\n * closing none: the two that agree make the third read as rigorous while it drifts.\n */\nexport function buildConfigTypesBackgroundData(\n matrix: MergedSkillsMatrix,\n agents: Partial<Record<AgentName, AgentDefinition>>,\n): ConfigTypesBackgroundData {\n const agentNames = typedKeys<AgentName>(agents);\n return {\n matrix,\n agentNames,\n customAgentNames: agentNames.filter((name) => agents[name]?.custom === true),\n };\n}\n\n/**\n * Regenerates config-types.ts with the latest matrix data, merging in any extra entities\n * that were just created (e.g., a new skill or agent). Errors propagate to callers.\n *\n * @param projectDir The project root directory\n * @param backgroundData Promise of the data {@link buildConfigTypesBackgroundData} assembles\n * @param extras Optional extra skill IDs or agent names to include (for just-created entities)\n */\nexport async function regenerateConfigTypes(\n projectDir: string,\n backgroundData: Promise<ConfigTypesBackgroundData>,\n extras?: ConfigTypesExtras,\n): Promise<void> {\n // The home directory's config-types.ts is the global pair's types half, which\n // only config-gate may write. Refusing here rather than leaving it to the\n // write primitive's tripwire names the offending entry point, and — unlike the\n // tripwire — survives a unit test that mocks `utils/fs`.\n if (isHomeDirectory(projectDir)) {\n throw new GlobalPairWriteViolation(\n path.join(projectDir, CLAUDE_SRC_DIR, STANDARD_FILES.CONFIG_TYPES_TS),\n );\n }\n\n const data = await backgroundData;\n\n const claudeSrcDir = path.join(projectDir, CLAUDE_SRC_DIR);\n\n // When a global installation exists and we're regenerating for a project,\n // generate a project config-types.ts that imports from the global one\n const isProjectScope = !isHomeDirectory(projectDir);\n const globalConfigTypes = isProjectScope ? await getGlobalConfigTypesPath() : null;\n const loadedConfig = await loadProjectConfigFromDir(projectDir);\n\n let source: string;\n if (globalConfigTypes) {\n const agents = loadedConfig?.config.agents;\n const selectedAgentNames = agents ? activeAgentNames(agents) : undefined;\n const projectScopedAgentNames = agents ? activeProjectAgentNames(agents) : undefined;\n source = generateProjectConfigTypesSource({\n globalTypesImportPath: computeGlobalTypesImportPath(projectDir),\n projectSkillIds: extras?.extraSkillIds ?? [],\n projectAgentNames: extras?.extraAgentNames ?? [],\n projectDomains: extras?.extraDomains ?? [],\n projectCategories: extras?.extraCategories ?? [],\n ...(selectedAgentNames?.length ? { selectedAgentNames } : {}),\n ...(projectScopedAgentNames?.length ? { projectScopedAgentNames } : {}),\n });\n verbose(\"Using project config-types.ts that imports from global\");\n } else {\n // Narrowed to the config on disk, exactly as the wizard write path narrows the\n // standalone form. The full matrix is the fallback only when there is no config\n // to narrow to — a union covering every skill the source offers would declare\n // literals the sibling config.ts never installs, and `satisfies` would stop\n // catching a config that names one of them.\n source = generateConfigTypesSource(\n data.matrix,\n data.agentNames,\n data.customAgentNames,\n extras,\n loadedConfig?.config,\n );\n }\n\n const configTypesPath = path.join(claudeSrcDir, STANDARD_FILES.CONFIG_TYPES_TS);\n await writeFile(configTypesPath, source);\n verbose(`Regenerated ${STANDARD_FILES.CONFIG_TYPES_TS}`);\n}\n","import path from \"path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\n\nimport { fileExists, readFile, writeFile } from \"../../utils/fs\";\nimport { getCurrentDate } from \"../versioning\";\nimport { SCHEMA_PATHS, STANDARD_FILES, YAML_FORMATTING } from \"../../consts\";\nimport { yamlSchemaComment, stripYamlSchemaComment } from \"../../utils/yaml-schema\";\nimport type { SkillId } from \"../../types\";\nimport { formatZodIssues, localSkillMetadataSchema } from \"../schemas\";\nimport { warn } from \"../../utils/logger\";\nimport { getErrorMessage } from \"../../utils/errors\";\n\n/**\n * Tracks the original marketplace source of a locally-installed skill.\n *\n * Written into each skill's metadata.yaml under the `forkedFrom` key when a skill\n * is copied from a source repository to the local `.claude/skills/` directory.\n * Used for version comparison, update detection, and provenance tracking.\n */\nexport type ForkedFromMetadata = {\n /** Canonical skill ID from the source repository (e.g., \"cc-ts-react-hook-form\") */\n skillId: SkillId;\n /** SHA-256 hash of the source SKILL.md content at the time of installation */\n contentHash: string;\n /** ISO date string (YYYY-MM-DD) when the skill was installed or last updated */\n date: string;\n /** Source URL the skill was installed from (e.g., \"github:agents-inc/skills\") */\n source?: string;\n /**\n * The skill's own DIRECTORY inside the repository `source` names — `skills/brainstorming`,\n * never the SKILL.md.\n *\n * Recorded only where it is the whole address. A marketplace resolves every id it serves, so a\n * skill ejected from one is installed again by its id and where inside that repository it lived\n * is nobody else's business. A skill a shared configuration CARRIED answers to no catalogue at\n * all, and this pair — repository and directory — is the only address it has: without it, the\n * producer that shares this installation can name the id and not the content behind it.\n */\n path?: string;\n};\n\n/**\n * Full metadata.yaml content for a locally-installed skill.\n *\n * Parsed from the `metadata.yaml` file in each skill directory under `.claude/skills/`.\n * Uses an index signature to preserve unknown fields written by other tools.\n */\nexport type LocalSkillMetadata = {\n /** Provenance metadata linking back to the original source skill, if any */\n forkedFrom?: ForkedFromMetadata;\n [key: string]: unknown;\n};\n\n/**\n * Reads forkedFrom metadata from a skill's metadata.yaml file.\n *\n * This metadata tracks the original marketplace source of a locally-installed skill,\n * enabling version comparison and update detection via content hash matching.\n *\n * @param skillDir - Absolute path to the skill directory (e.g., `/project/.claude/skills/react-hook-form`)\n * @returns The `forkedFrom` metadata if present and valid, `null` if the file doesn't exist,\n * has no `forkedFrom` field, or fails Zod validation (warns on invalid metadata)\n *\n * @example\n * ```ts\n * const metadata = await readForkedFromMetadata(\"/project/.claude/skills/react-hook-form\");\n * if (metadata) {\n * console.log(`Installed from ${metadata.skillId} on ${metadata.date}`);\n * }\n * ```\n */\nexport async function readForkedFromMetadata(skillDir: string): Promise<ForkedFromMetadata | null> {\n const metadata = await readLocalSkillMetadata(skillDir);\n return metadata?.forkedFrom ?? null;\n}\n\n/**\n * Reads the full local skill metadata from a skill's metadata.yaml file.\n *\n * Returns the parsed metadata including `forkedFrom` field.\n * Used by the uninstall command to determine whether a skill was installed by the CLI.\n *\n * @param skillDir - Absolute path to the skill directory\n * @returns The parsed metadata if valid, `null` if the file doesn't exist or is invalid\n */\nexport async function readLocalSkillMetadata(skillDir: string): Promise<LocalSkillMetadata | null> {\n const metadataPath = path.join(skillDir, STANDARD_FILES.METADATA_YAML);\n\n if (!(await fileExists(metadataPath))) {\n return null;\n }\n\n const content = await readFile(metadataPath);\n const read = readYaml(content);\n\n if (!read.parsed) {\n warn(`Invalid metadata.yaml at ${metadataPath}: ${read.reason}`);\n return null;\n }\n\n const result = localSkillMetadataSchema.safeParse(read.value);\n\n if (!result.success) {\n warn(`Invalid metadata.yaml at ${metadataPath}: ${formatZodIssues(result.error.issues)}`);\n return null;\n }\n\n return result.data;\n}\n\n/**\n * Writes forked-from provenance metadata into a skill's metadata.yaml.\n *\n * Reads the existing metadata.yaml (preserving any extra fields), sets the\n * `forkedFrom` block with the given skill ID, content hash, and current date,\n * then writes the file back with a YAML language server schema comment.\n *\n * Called during skill installation (by the skill copier) to record where a\n * locally-installed skill originated from.\n *\n * @param destPath - Absolute path to the skill directory containing metadata.yaml.\n * The file must already exist (created during skill copy).\n * @param skillId - Canonical skill ID from the source repository (e.g., \"cc-ts-react-hook-form\")\n * @param contentHash - SHA-256 hash of the source SKILL.md content at install time\n * @param origin - Where the bytes came from: the repository ref, and the directory inside it for\n * a skill nothing but that directory can install again. A bag rather than two\n * positional strings, because two adjacent optional strings can be swapped\n * silently and these two mean entirely different things.\n *\n * @remarks\n * **Side effect:** Overwrites `{destPath}/metadata.yaml` on disk. Existing fields\n * are preserved if the file parses successfully; if parsing fails, only `forkedFrom`\n * is written (with a warning logged).\n */\nexport async function injectForkedFromMetadata(\n destPath: string,\n skillId: SkillId,\n contentHash: string,\n origin: Pick<ForkedFromMetadata, \"source\" | \"path\"> = {},\n): Promise<void> {\n const metadataPath = path.join(destPath, STANDARD_FILES.METADATA_YAML);\n const rawContent = await readFile(metadataPath);\n const { yamlContent } = stripYamlSchemaComment(rawContent);\n\n const metadata: LocalSkillMetadata = {\n ...existingMetadataFields(yamlContent, metadataPath),\n forkedFrom: {\n skillId,\n contentHash,\n date: getCurrentDate(),\n ...(origin.source !== undefined && { source: origin.source }),\n ...(origin.path !== undefined && { path: origin.path }),\n },\n };\n\n await writeMetadataYaml(metadataPath, metadata, `${yamlSchemaComment(SCHEMA_PATHS.metadata)}\\n`);\n}\n\n/**\n * Serializes skill metadata with the standard line-width policy and writes it,\n * optionally prefixed by a yaml-language-server schema comment.\n */\nexport async function writeMetadataYaml(\n filePath: string,\n metadata: unknown,\n schemaComment = \"\",\n): Promise<void> {\n const yamlContent = stringifyYaml(metadata, { lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE });\n await writeFile(filePath, schemaComment + yamlContent);\n}\n\n/** What a YAML read can answer: the document, or why no parser could produce one. */\ntype YamlRead =\n | { readonly parsed: true; readonly value: unknown }\n | { readonly parsed: false; readonly reason: string };\n\n/**\n * Parses YAML without letting a syntax error escape.\n *\n * The two ways a metadata file fails reach a reader by different routes, and only one of them was\n * ever handled here: a wrong SHAPE is caught by the schema's `safeParse`, while a file no parser\n * can read throws out of `parseYaml` BEFORE `safeParse` is called at all. Both readers below\n * promise to survive an invalid file and neither kept that promise for the second kind.\n *\n * `readSkillMetadata` in `lib/loading/loader.ts` is the same guard written out at its own call\n * site; this is that shape, shared by the two readers here rather than repeated.\n */\nfunction readYaml(content: string): YamlRead {\n try {\n return { parsed: true, value: parseYaml(content) };\n } catch (error) {\n return { parsed: false, reason: getErrorMessage(error) };\n }\n}\n\n/**\n * The fields a metadata.yaml already holds, or none of them.\n *\n * Answers empty and warns for EITHER failure — a file no parser can read, or one whose shape the\n * schema refuses. Both are the same event from the author's side: the fields they wrote are about\n * to be replaced by a file carrying only `forkedFrom`, and the warning is the only thing that says\n * so. Keeping the two apart here would mean two warnings for one consequence.\n */\nfunction existingMetadataFields(\n yamlContent: string,\n metadataPath: string,\n): Partial<LocalSkillMetadata> {\n const read = readYaml(yamlContent);\n\n if (read.parsed) {\n const result = localSkillMetadataSchema.safeParse(read.value);\n if (result.success) return result.data;\n }\n\n warn(`Malformed metadata.yaml at '${metadataPath}' — existing fields may be lost`);\n return {};\n}\n","import { createHash } from \"crypto\";\nimport path from \"path\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport { readFile, readFileSafe, writeFile, glob, fileExists } from \"../utils/fs\";\nimport { warn } from \"../utils/logger\";\nimport {\n DEFAULT_VERSION,\n MAX_PLUGIN_FILE_SIZE,\n STANDARD_FILES,\n HASH_PREFIX_LENGTH,\n} from \"../consts\";\nimport { pluginManifestSchema } from \"./schemas\";\nimport { SKILL_CONTENT_FILES, SKILL_CONTENT_DIRS } from \"./metadata-keys\";\n\nconst ISO_DATE_LENGTH = 10;\n\nexport function getCurrentDate(): string {\n return new Date().toISOString().slice(0, ISO_DATE_LENGTH);\n}\n\nexport function computeStringHash(content: string): string {\n const hash = createHash(\"sha256\");\n hash.update(content);\n return hash.digest(\"hex\").slice(0, HASH_PREFIX_LENGTH);\n}\n\nexport async function computeFileHash(filePath: string): Promise<string> {\n const content = await readFile(filePath);\n return computeStringHash(content);\n}\n\nexport async function computeSkillFolderHash(skillPath: string): Promise<string> {\n const contents: string[] = [];\n\n for (const fileName of SKILL_CONTENT_FILES) {\n const filePath = path.join(skillPath, fileName);\n if (await fileExists(filePath)) {\n const content = await readFile(filePath);\n contents.push(`${fileName}:${content}`);\n }\n }\n\n for (const dirName of SKILL_CONTENT_DIRS) {\n const dirPath = path.join(skillPath, dirName);\n if (await fileExists(dirPath)) {\n const files = await glob(\"**/*\", dirPath);\n for (const file of files.sort()) {\n const filePath = path.join(dirPath, file);\n const content = await readFile(filePath);\n contents.push(`${dirName}/${file}:${content}`);\n }\n }\n }\n\n const combined = contents.join(\"\\n---\\n\");\n return computeStringHash(combined);\n}\n\n/**\n * Plugin versioning utilities shared by skill, agent, and stack plugin compilers.\n * Reads existing plugin.json + .content-hash, bumps semver major on content change.\n */\n\nconst CONTENT_HASH_FILE = \".content-hash\";\n\nexport function parseMajorVersion(version: string): number {\n const [, major] = version.match(/^(\\d+)\\./) ?? [];\n return major === undefined ? 1 : parseInt(major, 10);\n}\n\nexport function bumpMajorVersion(version: string): string {\n const major = parseMajorVersion(version);\n return `${major + 1}.0.0`;\n}\n\nasync function readExistingPluginManifest(\n pluginDir: string,\n getManifestPath: (dir: string) => string,\n): Promise<{ version: string; contentHash: string | undefined } | null> {\n const manifestPath = getManifestPath(pluginDir);\n\n if (!(await fileExists(manifestPath))) {\n return null;\n }\n\n try {\n const content = await readFileSafe(manifestPath, MAX_PLUGIN_FILE_SIZE);\n const manifest = pluginManifestSchema.parse(JSON.parse(content));\n\n const hashFilePath = manifestPath.replace(STANDARD_FILES.PLUGIN_JSON, CONTENT_HASH_FILE);\n const contentHash = (await fileExists(hashFilePath))\n ? (await readFile(hashFilePath)).trim()\n : undefined;\n\n return {\n version: manifest.version ?? DEFAULT_VERSION,\n contentHash,\n };\n } catch (error) {\n warn(`Failed to read plugin manifest at '${manifestPath}': ${getErrorMessage(error)}`);\n return null;\n }\n}\n\nexport async function determinePluginVersion(\n newHash: string,\n pluginDir: string,\n getManifestPath: (dir: string) => string,\n): Promise<{ version: string; contentHash: string }> {\n const existing = await readExistingPluginManifest(pluginDir, getManifestPath);\n\n if (!existing) {\n return {\n version: DEFAULT_VERSION,\n contentHash: newHash,\n };\n }\n\n if (existing.contentHash !== newHash) {\n return {\n version: bumpMajorVersion(existing.version),\n contentHash: newHash,\n };\n }\n\n return {\n version: existing.version,\n contentHash: newHash,\n };\n}\n\nexport async function writeContentHash(\n pluginDir: string,\n contentHash: string,\n getManifestPath: (dir: string) => string,\n): Promise<void> {\n const hashFilePath = getManifestPath(pluginDir).replace(\n STANDARD_FILES.PLUGIN_JSON,\n CONTENT_HASH_FILE,\n );\n await writeFile(hashFilePath, contentHash);\n}\n","/** Generates a yaml-language-server schema comment for the top of YAML files. */\nexport function yamlSchemaComment(schemaPath: string): string {\n return `# yaml-language-server: $schema=${schemaPath}`;\n}\n\n/**\n * Splits YAML file content into its leading yaml-language-server schema\n * comment (empty string when absent, trailing newline included when present)\n * and the parseable YAML body.\n */\nexport function stripYamlSchemaComment(content: string): {\n schemaComment: string;\n yamlContent: string;\n} {\n const lines = content.split(\"\\n\");\n if (lines[0]?.startsWith(\"# yaml-language-server:\")) {\n return { schemaComment: `${lines[0]}\\n`, yamlContent: lines.slice(1).join(\"\\n\") };\n }\n return { schemaComment: \"\", yamlContent: content };\n}\n","import path from \"path\";\n\nimport { copy, ensureDir, isPathWithin } from \"../../utils/fs\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { computeFileHash } from \"../versioning\";\nimport { EJECT_SOURCE, SOURCE_SRC_DIR, STANDARD_FILES } from \"../../consts\";\nimport type { ResolvedSkill, SkillId } from \"../../types\";\nimport type { SourceLoadResult } from \"../loading\";\nimport { getSkillById } from \"../matrix/matrix-provider\";\nimport { injectForkedFromMetadata } from \"./skill-metadata\";\n\nexport type CopiedSkill = {\n skillId: SkillId;\n contentHash: string;\n sourcePath: string;\n destPath: string;\n local?: boolean;\n};\n\nconst NULL_BYTE_PATTERN = /\\0/;\n\n/**\n * Validate that a resolved path stays within the expected parent directory.\n * Prevents path traversal attacks where skill.path contains sequences like \"../../sensitive\".\n */\nexport function validateSkillPath(\n resolvedPath: string,\n expectedParent: string,\n skillPath: string,\n): void {\n if (NULL_BYTE_PATTERN.test(skillPath)) {\n throw new Error(`Invalid skill path: '${skillPath}' contains null bytes`);\n }\n\n if (!isPathWithin(resolvedPath, expectedParent)) {\n throw new Error(\n `Invalid skill path: '${skillPath}' escapes expected directory '${path.resolve(expectedParent)}'`,\n );\n }\n}\n\n/**\n * Join basePath + skillPath, validate the result stays within basePath,\n * and return the resolved path. Combines path.join + validateSkillPath\n * to eliminate repeated join-then-validate boilerplate.\n */\nfunction resolveSkillPath(basePath: string, skillPath: string): string {\n const resolved = path.join(basePath, skillPath);\n validateSkillPath(resolved, basePath, skillPath);\n return resolved;\n}\n\nfunction getSkillSourcePath(skill: ResolvedSkill, rootDir: string): string {\n const srcDir = path.join(rootDir, SOURCE_SRC_DIR);\n return resolveSkillPath(srcDir, skill.path);\n}\n\nfunction getSkillDestPath(skill: ResolvedSkill, stackDir: string): string {\n const skillRelativePath = skill.path.replace(/^skills\\//, \"\");\n const skillsDir = path.join(stackDir, \"skills\");\n return resolveSkillPath(skillsDir, skillRelativePath);\n}\n\nasync function generateSkillHash(skillSourcePath: string): Promise<string> {\n const skillMdPath = path.join(skillSourcePath, STANDARD_FILES.SKILL_MD);\n return computeFileHash(skillMdPath);\n}\n\n/** Core copy: hash the source SKILL.md, copy the directory, stamp forkedFrom provenance. */\nasync function copySkillTo(\n skill: ResolvedSkill,\n sourcePath: string,\n destPath: string,\n source?: string,\n): Promise<CopiedSkill> {\n const contentHash = await generateSkillHash(sourcePath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n // No directory: the marketplace this ref names resolves the id itself, so where inside it the\n // skill lived is not part of installing it again. Absent rather than undefined, because that is\n // the difference between \"no ref was given\" and \"the ref is the word undefined\".\n await injectForkedFromMetadata(destPath, skill.id, contentHash, {\n ...(source !== undefined && { source }),\n });\n\n return { skillId: skill.id, contentHash, sourcePath, destPath };\n}\n\nexport async function copySkill(\n skill: ResolvedSkill,\n stackDir: string,\n registryRoot: string,\n source?: string,\n): Promise<CopiedSkill> {\n return copySkillTo(\n skill,\n getSkillSourcePath(skill, registryRoot),\n getSkillDestPath(skill, stackDir),\n source,\n );\n}\n\nexport async function copySkillFromSource(\n skill: ResolvedSkill,\n stackDir: string,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill> {\n return copySkillTo(\n skill,\n getSkillSourcePath(skill, sourceResult.sourcePath),\n getSkillDestPath(skill, stackDir),\n sourceResult.sourceConfig.source,\n );\n}\n\n/**\n * In-place CopiedSkill for a local skill left where it already lives (no copy):\n * source and destination are the skill's own local path.\n */\nasync function resolveLocalCopiedSkill(\n skill: ResolvedSkill,\n localPath: string,\n): Promise<CopiedSkill> {\n const contentHash = await generateSkillHash(localPath);\n return {\n skillId: skill.id,\n sourcePath: localPath,\n destPath: localPath,\n contentHash,\n local: true,\n };\n}\n\n/**\n * Copies every selected skill, and reports the ones that could not be copied BY ID.\n *\n * `Promise.all` alone rejects with whichever error arrived first and discards its siblings', and\n * that error is the filesystem's: an `ENOENT` naming a path inside the source cache. The reader is\n * told a file is missing at an address they did not choose, cannot place, and cannot act on — and\n * they learn about the second missing skill only by fixing the first and running again.\n *\n * The condition is ordinary rather than exotic: the copy walks the MATRIX and reads from the\n * FETCHED directory, so any disagreement between the two lands here. A user whose CLI predates a\n * marketplace change has no way to make them agree, which makes the id the only actionable thing\n * the failure can carry.\n *\n * It still throws. A partial copy would leave an installation missing skills its config records,\n * which is the orphan-entry state the plugin-install path already refuses.\n */\nasync function copyEachSkill(\n selectedSkillIds: SkillId[],\n copyOne: (skillId: SkillId) => Promise<CopiedSkill>,\n): Promise<CopiedSkill[]> {\n const outcomes = await Promise.all(\n selectedSkillIds.map(async (skillId) => attemptCopy(skillId, copyOne)),\n );\n const failures = outcomes.filter(isCopyFailure);\n\n if (failures.length > 0) throw new Error(copyFailureMessage(failures, selectedSkillIds.length));\n\n return outcomes.filter(isCopySuccess).map((outcome) => outcome.copied);\n}\n\ntype CopySuccess = { skillId: SkillId; copied: CopiedSkill };\ntype CopyFailure = { skillId: SkillId; problem: string };\ntype CopyOutcome = CopySuccess | CopyFailure;\n\nasync function attemptCopy(\n skillId: SkillId,\n copyOne: (skillId: SkillId) => Promise<CopiedSkill>,\n): Promise<CopyOutcome> {\n try {\n return { skillId, copied: await copyOne(skillId) };\n } catch (error) {\n return { skillId, problem: getErrorMessage(error) };\n }\n}\n\nfunction isCopyFailure(outcome: CopyOutcome): outcome is CopyFailure {\n return \"problem\" in outcome;\n}\n\nfunction isCopySuccess(outcome: CopyOutcome): outcome is CopySuccess {\n return \"copied\" in outcome;\n}\n\n/** One line per skill that failed, so both what failed and why are named for every one of them. */\nfunction copyFailureMessage(failures: CopyFailure[], attempted: number): string {\n const lines = failures.map((failure) => ` ${failure.skillId}: ${failure.problem}`);\n\n return `Could not copy ${failures.length} of ${attempted} skills:\\n${lines.join(\"\\n\")}`;\n}\n\nfunction getFlattenedSkillDestPath(skill: ResolvedSkill, localSkillsDir: string): string {\n return resolveSkillPath(localSkillsDir, skill.id);\n}\n\nasync function copySkillToLocalFlattened(\n skill: ResolvedSkill,\n localSkillsDir: string,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill> {\n return copySkillTo(\n skill,\n getSkillSourcePath(skill, sourceResult.sourcePath),\n getFlattenedSkillDestPath(skill, localSkillsDir),\n sourceResult.sourceConfig.source,\n );\n}\n\nexport async function copySkillsToLocalFlattened(\n selectedSkillIds: SkillId[],\n localSkillsDir: string,\n sourceResult: SourceLoadResult,\n sourceSelections?: Partial<Record<SkillId, string>>,\n): Promise<CopiedSkill[]> {\n return copyEachSkill(selectedSkillIds, async (skillId) => {\n const skill = getSkillById(skillId);\n\n const selectedSource = sourceSelections?.[skillId];\n const userSelectedRemote = selectedSource && selectedSource !== EJECT_SOURCE;\n if (!skill.local || !skill.localPath || userSelectedRemote) {\n return copySkillToLocalFlattened(skill, localSkillsDir, sourceResult);\n }\n\n const destPath = getFlattenedSkillDestPath(skill, localSkillsDir);\n if (path.resolve(skill.localPath) === path.resolve(destPath)) {\n return resolveLocalCopiedSkill(skill, skill.localPath);\n }\n\n const contentHash = await generateSkillHash(skill.localPath);\n await ensureDir(path.dirname(destPath));\n await copy(skill.localPath, destPath);\n\n return { skillId: skill.id, sourcePath: skill.localPath, destPath, contentHash };\n });\n}\n","import path from \"path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { readFile, writeFile, ensureDir, glob, fileExists, copy } from \"../../utils/fs\";\nimport { log, verbose, warn } from \"../../utils/logger\";\nimport {\n generateSkillPluginManifest,\n writePluginManifest,\n getPluginManifestPath,\n} from \"../plugins\";\nimport { parseFrontmatter } from \"../loading\";\nimport { computeSkillFolderHash, determinePluginVersion, writeContentHash } from \"../versioning\";\nimport type { PluginManifest, SkillFrontmatter } from \"../../types\";\nimport { formatZodIssues, skillMetadataLoaderSchema } from \"../schemas\";\nimport type { z } from \"zod\";\n\ntype SkillMetadata = z.infer<typeof skillMetadataLoaderSchema>;\nimport { DEFAULT_BRANDING, STANDARD_FILES } from \"../../consts\";\nimport { stripYamlSchemaComment } from \"../../utils/yaml-schema\";\nimport { SKILL_CONTENT_FILES, SKILL_CONTENT_DIRS } from \"../metadata-keys\";\n\nexport type SkillPluginOptions = {\n skillPath: string;\n outputDir: string;\n skillName?: string;\n};\n\nexport type CompiledSkillPlugin = {\n pluginPath: string;\n manifest: PluginManifest;\n skillName: string;\n};\n\nexport type SkillCompilationRun = {\n compiled: CompiledSkillPlugin[];\n /** Directory basenames of skills that failed to compile this run. */\n failed: string[];\n};\n\nfunction sanitizeSkillName(name: string): string {\n return name.replace(/\\+/g, \"-\");\n}\n\n/**\n * The optional `author` and `category` a skill's metadata.yaml lends the plugin manifest.\n *\n * Not the `readSkillMetadata` exported from `loading/loader.ts` one import away, whose name this\n * carried until the two proved impossible to tell apart in prose. That one is handed the\n * metadata.yaml's own PATH and answers a verdict — the single judgment of whether a file describes\n * its skill, which `compile`, config-types generation and `doctor` all defer to — and it warns\n * about nothing. This is handed the skill DIRECTORY, answers null for a file that is absent as\n * readily as for one nothing can be read out of, and warns on the way past both, because the\n * compile it feeds runs either way with two manifest fields left off.\n */\nasync function readPluginSkillMetadata(skillPath: string): Promise<SkillMetadata | null> {\n const metadataPath = path.join(skillPath, STANDARD_FILES.METADATA_YAML);\n\n if (!(await fileExists(metadataPath))) {\n return null;\n }\n\n try {\n const content = await readFile(metadataPath);\n const { yamlContent } = stripYamlSchemaComment(content);\n\n const result = skillMetadataLoaderSchema.safeParse(parseYaml(yamlContent));\n if (!result.success) {\n warn(`Invalid metadata.yaml at '${skillPath}': ${formatZodIssues(result.error.issues)}`);\n return null;\n }\n return result.data;\n } catch (error) {\n warn(`Failed to read metadata.yaml at '${skillPath}': ${getErrorMessage(error)}`);\n return null;\n }\n}\n\nfunction generateReadme(skillName: string, frontmatter: SkillFrontmatter): string {\n return `# ${skillName}\n\n${frontmatter.description}\n\n## Installation\n\nAdd this plugin to your Claude Code configuration:\n\n\\`\\`\\`json\n{\n \"plugins\": [\"${skillName}\"]\n}\n\\`\\`\\`\n\n## Usage\n\nThis skill is automatically available when installed.\n\n---\n\n*Generated by ${DEFAULT_BRANDING.NAME} skill-plugin-compiler*\n`;\n}\n\nexport async function compileSkillPlugin(\n options: SkillPluginOptions,\n): Promise<CompiledSkillPlugin> {\n const { skillPath, outputDir, skillName: overrideName } = options;\n\n const dirBasename = path.basename(skillPath);\n\n const skillMdPath = path.join(skillPath, STANDARD_FILES.SKILL_MD);\n if (!(await fileExists(skillMdPath))) {\n throw new Error(\n `Skill '${dirBasename}' is missing required ${STANDARD_FILES.SKILL_MD} file. Expected at: ${skillMdPath}`,\n );\n }\n\n const skillMdContent = await readFile(skillMdPath);\n const frontmatter = parseFrontmatter(skillMdContent, skillMdPath);\n\n if (!frontmatter) {\n throw new Error(\n `Skill '${dirBasename}' has invalid or missing YAML frontmatter in ${STANDARD_FILES.SKILL_MD}. ` +\n `Required fields: 'name' and 'description'. File: ${skillMdPath}`,\n );\n }\n\n const skillName = overrideName ?? sanitizeSkillName(frontmatter.name);\n\n verbose(`Compiling skill plugin: ${skillName} from ${skillPath}`);\n\n const metadata = await readPluginSkillMetadata(skillPath);\n\n const pluginDir = path.join(outputDir, skillName);\n const skillsDir = path.join(pluginDir, \"skills\", skillName);\n\n await ensureDir(pluginDir);\n await ensureDir(skillsDir);\n\n const newHash = await computeSkillFolderHash(skillPath);\n\n const { version, contentHash } = await determinePluginVersion(\n newHash,\n pluginDir,\n getPluginManifestPath,\n );\n\n const manifest = generateSkillPluginManifest({\n skillName,\n description: frontmatter.description,\n ...(metadata?.author !== undefined && { author: metadata.author }),\n ...(metadata?.category !== undefined && { category: metadata.category }),\n version,\n });\n\n await writePluginManifest(pluginDir, manifest);\n\n await writeContentHash(pluginDir, contentHash, getPluginManifestPath);\n\n verbose(` Wrote plugin.json for ${skillName} (v${version})`);\n\n await writeFile(path.join(skillsDir, STANDARD_FILES.SKILL_MD), skillMdContent);\n verbose(` Copied ${STANDARD_FILES.SKILL_MD}`);\n\n for (const fileName of SKILL_CONTENT_FILES) {\n if (fileName === STANDARD_FILES.SKILL_MD) continue;\n\n const sourcePath = path.join(skillPath, fileName);\n if (await fileExists(sourcePath)) {\n const content = await readFile(sourcePath);\n await writeFile(path.join(skillsDir, fileName), content);\n verbose(` Copied ${fileName}`);\n }\n }\n\n for (const dirName of SKILL_CONTENT_DIRS) {\n const sourceDir = path.join(skillPath, dirName);\n if (await fileExists(sourceDir)) {\n await copy(sourceDir, path.join(skillsDir, dirName));\n verbose(` Copied ${dirName}/`);\n }\n }\n\n const readme = generateReadme(skillName, frontmatter);\n await writeFile(path.join(pluginDir, STANDARD_FILES.README_MD), readme);\n verbose(\" Generated README.md\");\n\n return {\n pluginPath: pluginDir,\n manifest,\n skillName,\n };\n}\n\nexport async function compileAllSkillPlugins(\n skillsDir: string,\n outputDir: string,\n): Promise<SkillCompilationRun> {\n const compiled: CompiledSkillPlugin[] = [];\n const failed: string[] = [];\n\n const skillMdFiles = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir);\n\n for (const skillMdFile of skillMdFiles) {\n const skillPath = path.join(skillsDir, path.dirname(skillMdFile));\n\n try {\n const result = await compileSkillPlugin({\n skillPath,\n outputDir,\n });\n compiled.push(result);\n log(` [OK] ${result.skillName}`);\n } catch (error) {\n const errorMessage = getErrorMessage(error);\n const dirBasename = path.basename(skillPath);\n failed.push(dirBasename);\n warn(`Failed to compile skill from '${dirBasename}': ${errorMessage}`);\n }\n }\n\n return { compiled, failed };\n}\n\nexport function printCompilationSummary(results: CompiledSkillPlugin[]): void {\n log(`\\nCompiled ${results.length} skill plugins:`);\n for (const result of results) {\n log(` - ${result.skillName} (v${result.manifest.version})`);\n }\n}\n","import path from \"path\";\n\nimport { ensureDir, writeFile } from \"../../utils/fs\";\nimport { DEFAULT_VERSION, PLUGIN_MANIFEST_DIR, STANDARD_FILES } from \"../../consts\";\nimport type { PluginAuthor, PluginManifest } from \"../../types\";\n\nconst PLUGIN_DIR_NAME = PLUGIN_MANIFEST_DIR;\nconst PLUGIN_MANIFEST_FILE = STANDARD_FILES.PLUGIN_JSON;\nconst AGENT_PLUGIN_PREFIX = \"agent-\";\n\nexport type SkillManifestOptions = {\n skillName: string;\n description?: string;\n author?: string;\n authorEmail?: string;\n category?: string;\n version?: string;\n keywords?: string[];\n};\n\nexport type AgentManifestOptions = {\n agentName: string;\n description?: string;\n version?: string;\n};\n\nfunction buildAuthor(name?: string, email?: string): PluginAuthor | undefined {\n if (!name) {\n return undefined;\n }\n return { name, ...(email ? { email } : {}) };\n}\n\nexport function generateSkillPluginManifest(options: SkillManifestOptions): PluginManifest {\n const author = buildAuthor(options.author, options.authorEmail);\n return {\n name: options.skillName,\n version: options.version ?? DEFAULT_VERSION,\n skills: \"./skills/\",\n ...(options.description ? { description: options.description } : {}),\n ...(author ? { author } : {}),\n ...(options.category ? { category: options.category } : {}),\n ...(options.keywords?.length ? { keywords: options.keywords } : {}),\n };\n}\n\nexport function generateAgentPluginManifest(options: AgentManifestOptions): PluginManifest {\n return {\n name: `${AGENT_PLUGIN_PREFIX}${options.agentName}`,\n version: options.version ?? DEFAULT_VERSION,\n agents: \"./agents/\",\n ...(options.description ? { description: options.description } : {}),\n };\n}\n\nexport async function writePluginManifest(\n outputDir: string,\n manifest: PluginManifest,\n): Promise<string> {\n const pluginDir = path.join(outputDir, PLUGIN_DIR_NAME);\n const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_FILE);\n\n await ensureDir(pluginDir);\n\n const content = JSON.stringify(manifest, null, 2);\n await writeFile(manifestPath, content);\n\n return manifestPath;\n}\n","import type { ClaudePluginScope, SkillScope } from \"../../types/config.js\";\n\n/**\n * Marketplace-qualified plugin reference (`{id}@{marketplace}`) — the form the\n * Claude CLI plugin registry expects. Bare ids do not match registry entries.\n */\nexport function buildMarketplacePluginRef(id: string, marketplace: string): string {\n return `${id}@${marketplace}`;\n}\n\n/**\n * Inverse of buildMarketplacePluginRef: extracts the skill id from a\n * `{id}@{marketplace}` reference. Returns the whole string when no `@` is present.\n */\nexport function parseMarketplacePluginRef(ref: string): string {\n const separator = ref.indexOf(\"@\");\n return separator === -1 ? ref : ref.slice(0, separator);\n}\n\n/**\n * Maps a cc scope to the Claude CLI plugin scope: `\"global\"` installs are\n * user-scoped in Claude (registered in `~/.claude/settings.json`); anything\n * else — including an absent scope — is project-scoped.\n */\nexport function toClaudePluginScope(scope: SkillScope | undefined): ClaudePluginScope {\n return scope === \"global\" ? \"user\" : \"project\";\n}\n","import os from \"os\";\nimport path from \"path\";\n\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { fileExists, readFileSafe } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport {\n CLAUDE_DIR,\n MAX_PLUGIN_FILE_SIZE,\n PLUGINS_SUBDIR,\n PLUGIN_MANIFEST_DIR,\n PLUGIN_MANIFEST_FILE,\n} from \"../../consts\";\nimport type { PluginManifest } from \"../../types\";\nimport { pluginManifestSchema } from \"../schemas\";\n\nexport function getUserPluginsDir(): string {\n return path.join(os.homedir(), CLAUDE_DIR, PLUGINS_SUBDIR);\n}\n\nexport function getProjectPluginsDir(projectDir?: string): string {\n const dir = projectDir ?? process.cwd();\n return path.join(dir, CLAUDE_DIR, PLUGINS_SUBDIR);\n}\n\nexport function getPluginAgentsDir(pluginDir: string): string {\n return path.join(pluginDir, \"agents\");\n}\n\nexport function getPluginManifestPath(pluginDir: string): string {\n return path.join(pluginDir, PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE);\n}\n\nexport async function readPluginManifest(pluginDir: string): Promise<PluginManifest | null> {\n const manifestPath = getPluginManifestPath(pluginDir);\n\n if (!(await fileExists(manifestPath))) {\n verbose(` No manifest at ${manifestPath}`);\n return null;\n }\n\n try {\n const content = await readFileSafe(manifestPath, MAX_PLUGIN_FILE_SIZE);\n const manifest = pluginManifestSchema.parse(JSON.parse(content));\n\n if (!manifest.name || typeof manifest.name !== \"string\") {\n verbose(` Invalid manifest at ${manifestPath}: missing name`);\n return null;\n }\n\n return manifest;\n } catch (error) {\n verbose(` Failed to parse manifest at ${manifestPath}: ${getErrorMessage(error)}`);\n return null;\n }\n}\n","import { readdir } from \"fs/promises\";\nimport type { Dirent } from \"fs\";\n\nimport { DEFAULT_PLUGIN_NAME } from \"../../consts\";\nimport { loadProjectConfig, type LoadedProjectConfig } from \"../configuration\";\nimport {\n detectInstallation,\n isHomeDirectory,\n resolveInstallPaths,\n INSTALL_MODE_LABELS,\n type Installation,\n type InstallMode,\n} from \"../installation\";\nimport type { SkillScope } from \"../../types/config\";\n\nconst AGENT_FILE_EXTENSION = \".md\";\n\nexport type InstallationInfo = {\n mode: InstallMode;\n name: string;\n skillCount: number;\n agentCount: number;\n configPath: string;\n /** Every directory that actually holds compiled agents; empty when no scope has any. */\n agentDirs: string[];\n};\n\nexport async function getInstallationInfo(): Promise<InstallationInfo | null> {\n const installation = await detectInstallation();\n if (!installation) return null;\n\n const loaded = await loadProjectConfig(installation.projectDir);\n const agentDirCounts = await countCompiledAgentsPerScope(\n installation,\n installedScopes(installation),\n );\n\n return {\n mode: installation.mode,\n name: loaded?.config.name || DEFAULT_PLUGIN_NAME,\n skillCount: countManagedSkills(loaded),\n agentCount: sumCounts(agentDirCounts),\n configPath: installation.configPath,\n agentDirs: agentDirCounts.filter(hasEntries).map((scopeCount) => scopeCount.dir),\n };\n}\n\n/**\n * The number of skills the CLI reports it manages, which is what its own configuration declares\n * and nothing else. Neither the plugin registry nor `.claude/skills/` answers that question:\n * each holds only the half of an installation its own install path writes — so a mixed install\n * read from either one reports a fraction of itself — and each also holds entries this CLI never\n * wrote, which it has no business claiming. The install mode is therefore irrelevant here.\n *\n * A tombstone (`excluded: true`) records a skill this project has switched OFF, so it is not one\n * of them; and a skill enabled under both roots is two registrations of one skill, so the entries\n * merge by id.\n */\nfunction countManagedSkills(loaded: LoadedProjectConfig | null): number {\n if (!loaded) return 0;\n\n const managed = loaded.config.skills.filter((skill) => !skill.excluded);\n return new Set(managed.map((skill) => skill.id)).size;\n}\n\n/**\n * Scopes whose compiled agents belong to this installation, in report order\n * (global first, mirroring the init success report). A project context also owns\n * everything installed globally under HOME, so both roots are counted; at the\n * home root the two resolve to the same directory and only one pass runs so\n * nothing is counted twice.\n */\nfunction installedScopes(installation: Installation): SkillScope[] {\n return isHomeDirectory(installation.projectDir) ? [\"project\"] : [\"global\", \"project\"];\n}\n\ntype ScopeCount = {\n dir: string;\n count: number;\n};\n\nfunction hasEntries(scopeCount: ScopeCount): boolean {\n return scopeCount.count > 0;\n}\n\nfunction sumCounts(scopeCounts: ScopeCount[]): number {\n return scopeCounts.reduce((total, scopeCount) => total + scopeCount.count, 0);\n}\n\n/**\n * Compiled-agent count per scope, keyed by the directory it was read from, so\n * callers can both total the counts and name the directories the agents are\n * actually in — a default install driven from a project directory compiles\n * every agent under HOME, and naming the project directory there names a\n * directory that was never written.\n */\nasync function countCompiledAgentsPerScope(\n installation: Installation,\n scopes: SkillScope[],\n): Promise<ScopeCount[]> {\n return Promise.all(\n scopes.map(async (scope) => {\n const dir = resolveInstallPaths(installation.projectDir, scope).agentsDir;\n return { dir, count: await countDirEntries(dir, isCompiledAgentFile) };\n }),\n );\n}\n\nfunction isCompiledAgentFile(entry: Dirent): boolean {\n return entry.isFile() && entry.name.endsWith(AGENT_FILE_EXTENSION);\n}\n\n/** Counts entries in `dir` matching `pred`; 0 when the directory is missing or unreadable. */\nasync function countDirEntries(dir: string, pred: (entry: Dirent) => boolean): Promise<number> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n return entries.filter(pred).length;\n } catch {\n return 0;\n }\n}\n\nexport function formatInstallationDisplay(info: InstallationInfo): string {\n const agentDirLines = info.agentDirs.map((dir) => `\\n Agents: ${dir}`).join(\"\");\n\n return `Installation: ${info.name}\n Mode: ${INSTALL_MODE_LABELS[info.mode]}\n Skills: ${info.skillCount}\n Agents: ${info.agentCount}\n Config: ${info.configPath}${agentDirLines}`;\n}\n","import os from \"os\";\nimport path from \"path\";\nimport { fileExists } from \"../../utils/fs\";\nimport { loadProjectConfigFromDir } from \"../configuration/project-config\";\nimport { CLAUDE_DIR, PLUGINS_SUBDIR, STANDARD_DIRS, EJECT_SOURCE } from \"../../consts\";\nimport { getProjectConfigPath } from \"./install-base-dir\";\nimport type { ProjectConfig, SkillConfig } from \"../../types/config\";\nimport type { InstallMode } from \"../../types/matrix\";\n\n// Re-exported from types/matrix.ts for existing importers of the installation barrel\nexport type { InstallMode };\n\nexport const INSTALL_MODE_LABELS = {\n plugin: \"Plugin\",\n mixed: \"Mixed\",\n eject: \"Eject\",\n} as const satisfies Record<InstallMode, string>;\n\n/**\n * How a mode is described wherever a command tells the user what KIND of install is\n * about to happen — `init`'s install-plan line, and `edit`'s line for the skills it\n * is switching. One definition because it is one statement about one operation:\n * switching a skill to plugin mode installs it natively exactly as a fresh plugin\n * install does, and used to be announced in words `init` never printed.\n *\n * `mixed` is absent by construction. Nothing is switched TO mixed — it is a shape a\n * whole selection can have, described with per-mode counts only the install plan\n * holds, so `init` composes that one line itself.\n */\nexport const INSTALL_MODE_DESCRIPTIONS = {\n plugin: `${INSTALL_MODE_LABELS.plugin} (native install)`,\n eject: `${INSTALL_MODE_LABELS.eject} (copy to .claude/skills/)`,\n} as const satisfies Record<Exclude<InstallMode, \"mixed\">, string>;\n\nexport type Installation = {\n mode: InstallMode;\n configPath: string;\n agentsDir: string;\n skillsDir: string;\n projectDir: string;\n};\n\n/**\n * Whether a successfully-loaded config declares nothing to install — no skills and no agents.\n *\n * Exported rather than kept private to its one caller below because two surfaces have to agree on\n * exactly which configs are content-less: this detection, which maps them to `null` so `init`\n * routes to the wizard instead of the dashboard, and `doctor`, which has to name that state rather\n * than repeat the `null` as `not found`. Two answers to that question is how one screen ended up\n * validating a file and calling it missing four lines apart.\n */\nexport function declaresNoContent(config: ProjectConfig): boolean {\n return config.skills.length === 0 && config.agents.length === 0;\n}\n\n/** Derive install mode from skills array at runtime */\nexport function deriveInstallMode(skills: SkillConfig[]): InstallMode {\n if (skills.length === 0) return \"eject\";\n const hasEject = skills.some((s) => s.origin === EJECT_SOURCE);\n const hasPlugin = skills.some((s) => s.origin !== EJECT_SOURCE);\n if (hasEject && hasPlugin) return \"mixed\";\n return hasEject ? \"eject\" : \"plugin\";\n}\n\n// Use loadProjectConfigFromDir directly (not detectInstallation) to avoid the\n// project→global fallback recursing back into this detection.\nasync function detectInstallationInDir(dir: string): Promise<Installation | null> {\n const configPath = getProjectConfigPath(dir);\n\n if (!(await fileExists(configPath))) {\n return null;\n }\n\n // The config file exists. loadProjectConfigFromDir throws ConfigLoadError for a\n // corrupt config, so a returned value is always a usable config — a corrupt\n // config surfaces to the caller (compile reports it) instead of silently\n // becoming a phantom eject installation that resurrects every built-in agent.\n const loaded = await loadProjectConfigFromDir(dir);\n if (!loaded) {\n // The file vanished between the fileExists check and the load.\n return null;\n }\n\n // A successfully-loaded config that declares neither skills nor agents is\n // content-less and does not count as an installation — init must route to the\n // setup wizard, not the dashboard. This is the shared detection function, so\n // returning null here covers both the project-config and global-config\n // manifestations. A reporting surface must not read this `null` as \"no config\n // here\": see declaresNoContent, which doctor asks the same question of.\n if (declaresNoContent(loaded.config)) {\n return null;\n }\n\n const mode: InstallMode = deriveInstallMode(loaded.config.skills);\n\n return {\n mode,\n configPath,\n agentsDir: path.join(dir, CLAUDE_DIR, STANDARD_DIRS.AGENTS),\n // Mixed mode has local skills in .claude/skills/ and plugins in cache;\n // use .claude/skills/ as the primary skillsDir (same as eject mode)\n skillsDir: path.join(dir, CLAUDE_DIR, mode === \"plugin\" ? PLUGINS_SUBDIR : \"skills\"),\n projectDir: dir,\n };\n}\n\n/** Detect installation in a specific directory only (no global fallback). */\nexport async function detectProjectInstallation(projectDir: string): Promise<Installation | null> {\n return detectInstallationInDir(projectDir);\n}\n\n/** Detect installation in the home directory (global scope). */\nexport async function detectGlobalInstallation(): Promise<Installation | null> {\n return detectInstallationInDir(os.homedir());\n}\n\n/**\n * Detect installation: checks project-level first, then falls back to global (home directory).\n * Project fully overrides global (no merging).\n */\nexport async function detectInstallation(\n projectDir: string = process.cwd(),\n): Promise<Installation | null> {\n // 1. Check project-level first\n const projectInstallation = await detectProjectInstallation(projectDir);\n if (projectInstallation) return projectInstallation;\n\n // 2. Fall back to global (home directory)\n return detectGlobalInstallation();\n}\n","import os from \"os\";\nimport path from \"path\";\nimport { unique } from \"remeda\";\nimport type {\n AgentDefinition,\n AgentName,\n CompileAgentConfig,\n ProjectConfig,\n SkillId,\n Stack,\n StackAgentConfig,\n} from \"../../types\";\nimport { isHomeDirectory } from \"./is-home-directory\";\nimport type { AgentScopeConfig, SkillConfig, SkillScope } from \"../../types/config\";\nimport type { WizardResultV2 } from \"../../components/wizard/wizard\";\nimport {\n type MergeResult,\n type AuthoritativeScope,\n mergeWithExistingConfig,\n loadProjectConfig,\n loadProjectConfigFromDir,\n} from \"../configuration\";\nimport { type SourceLoadResult } from \"../loading\";\nimport { loadStackById, stackNotOfferedMessage } from \"../stacks\";\nimport { buildSkillRefsFromConfig } from \"../resolver\";\nimport { generateProjectConfigFromSkills, buildStackProperty } from \"../configuration\";\nimport { scopeEligibilityKey, isScopePairCompatible } from \"../configuration/config-generator\";\nimport {\n isActiveAt,\n activeSkillScopeMap,\n activeAgentScopeMap,\n effectivelyExcludedSkillIds,\n} from \"../configuration/scope-predicates\";\nimport { verbose } from \"../../utils/logger\";\nimport { typedFromEntries } from \"../../utils/typed-object\";\nimport { DEFAULT_PLUGIN_NAME } from \"../../consts\";\n\n/**\n * Returns the ids of skills active in the CURRENT wizard selection that were\n * NOT active in the persisted PRIOR config. Filters `excluded: true` on both\n * sides — excluded entries don't participate in stack membership, so flipping\n * a skill from excluded back to active counts as \"newly added\".\n *\n * `priorSkills === undefined` (first init) collapses the prior active set to\n * empty — every current skill is new this session. The generator's seeding\n * branch is what actually produces useful output in that case, so treating\n * every skill as \"new\" is safe.\n */\nfunction computeNewlyAddedSkillIds(\n currentSkills: readonly SkillConfig[],\n priorSkills: readonly SkillConfig[] | undefined,\n): readonly SkillId[] {\n const priorActiveIds = new Set((priorSkills ?? []).filter((s) => !s.excluded).map((s) => s.id));\n const currentActiveIds = currentSkills.filter((s) => !s.excluded).map((s) => s.id);\n return unique(currentActiveIds.filter((id) => !priorActiveIds.has(id)));\n}\n\n/**\n * Returns `(agent, skillId)` keys whose scope-compatibility was GAINED this\n * session — the pair is scope-compatible now but was NOT scope-compatible (or\n * was absent entirely) in the persisted config. Admits pure scope-flip cases\n * that `computeNewlyAddedSkillIds` (keyed by id only) cannot express.\n *\n * Scope rule: `isScopePairCompatible` from config-generator — the single\n * definition shared with the generator's own compatibility filter.\n *\n * Keys are produced by `scopeEligibilityKey` so lookup membership matches the\n * generator's internal set-membership check.\n */\nfunction computeScopeEligibilityGained(\n currentSkills: readonly SkillConfig[],\n currentAgents: readonly AgentScopeConfig[],\n priorSkills: readonly SkillConfig[] | undefined,\n priorAgents: readonly AgentScopeConfig[] | undefined,\n): ReadonlySet<string> {\n const priorSkillScope = activeSkillScopeMap(priorSkills);\n const priorAgentScope = activeAgentScopeMap(priorAgents);\n\n const gained = new Set<string>();\n const activeCurrentSkills = currentSkills.filter((s) => !s.excluded);\n const activeCurrentAgents = currentAgents.filter((a) => !a.excluded);\n\n for (const agent of activeCurrentAgents) {\n for (const skill of activeCurrentSkills) {\n if (!isScopePairCompatible(skill.scope, agent.scope)) continue;\n\n const priorSkillScopeValue = priorSkillScope.get(skill.id);\n const priorAgentScopeValue = priorAgentScope.get(agent.name);\n const wasCompatiblePreviously =\n priorSkillScopeValue !== undefined &&\n priorAgentScopeValue !== undefined &&\n isScopePairCompatible(priorSkillScopeValue, priorAgentScopeValue);\n\n if (!wasCompatiblePreviously) {\n gained.add(scopeEligibilityKey(agent.name, skill.id));\n }\n }\n }\n return gained;\n}\n\n/**\n * The stack the written config carries.\n *\n * A producer that knows per-`(skill, agent)` assignments has already decided what every sub-agent\n * holds and what preloads, so its stack REPLACES the ownership-derived one rather than merging\n * with it. Ownership rules hand every scope-compatible skill to every selected agent — exactly the\n * curation a shared configuration exists to carry — and inherit `preloaded` from a prior or\n * stack-YAML entry, which is silent about what the sharer chose. A stack id in such a payload\n * still names the config's description, but its own expansion is not overlaid for the same reason:\n * it would add back the skills and agents the assignments left out.\n *\n * Only a stack the generator itself built is replaced. With no agents selected there is nothing to\n * own, and the absent key is what tells the merger to leave the stack already on disk alone.\n */\nfunction resolveStackProperty(\n generated: ProjectConfig[\"stack\"],\n assigned: WizardResultV2[\"assignedStack\"],\n): ProjectConfig[\"stack\"] {\n return generated && assigned ? assigned : generated;\n}\n\n/**\n * The sentence this config records about itself, from whichever end of the install knows it.\n *\n * The two are never both present, and the two install paths are the reason. A stack loaded HERE is\n * the wizard path, where the stack object is the authority on its own description. A description\n * carried on the wizard result is the `init --from` path, where `configToSeedPayload` writes\n * `stackId: null` on purpose — so `loadedStack` is null, there is no id to resolve a description\n * out of, and before the payload carried one the line was simply dropped.\n *\n * The loaded stack is asked first anyway, so the ordering is stated rather than left to the fact\n * that the cases do not overlap: a stack the install actually read beats a sentence handed to it.\n */\nfunction resolveDescription(\n loadedStack: Stack | null,\n shared: WizardResultV2[\"description\"],\n): string | undefined {\n return loadedStack === null ? shared : loadedStack.description;\n}\n\n/**\n * The identity a freshly-written config carries.\n *\n * A project config is named for the directory it configures — the same identity\n * `eject` passes as its `fallbackName` and the loader repairs a missing `name`\n * to. At `$HOME` there is no project to name: `path.basename(os.homedir())` is\n * the OS account name, which identifies the USER rather than the installation\n * and differs per machine for one logical global install, so the global config\n * keeps the product constant instead.\n *\n * A config already on disk keeps the name it saved either way — `mergeConfigs`\n * carries identity fields over from the existing config, so this seed only ever\n * names a config being created.\n */\nfunction configNameFor(projectDir: string): string {\n return isHomeDirectory(projectDir) ? DEFAULT_PLUGIN_NAME : path.basename(projectDir);\n}\n\n/**\n * The per-agent curation this save must preserve, from every config that carries\n * any.\n *\n * A GLOBAL sub-agent's curation lives in the global config ALONE — a project\n * config's stack is filtered down to project-scoped agents on the way out, so a\n * global agent has no row of its own there. Reading the project config by itself\n * therefore makes a `s` toggle (G→P) look like an agent nobody has ever curated,\n * and the generator's seed branch rebuilds its catalogue from relevance defaults,\n * silently dropping every assignment the shared resolver would not re-derive.\n *\n * Both configs are carriers and both are merged; the project's word wins per\n * agent, since a project-scoped agent's row is the one the project owns. The\n * global config is READ here and never written — a project-context edit moves an\n * agent INTO this project, it never migrates global state out.\n */\nasync function loadCuratedStack(\n projectDir: string,\n projectStack: ProjectConfig[\"stack\"],\n): Promise<Partial<Record<AgentName, StackAgentConfig>>> {\n // At `$HOME` the config already loaded IS the global one — re-reading it would\n // merge it with itself.\n const globalStack = isHomeDirectory(projectDir) ? undefined : await loadGlobalStack();\n\n // ProjectConfig.stack types its agents as Record<string, StackAgentConfig> (it\n // comes from parsed TS/JSON); the declared return type is where those keys are\n // narrowed to AgentName, so this load boundary needs no cast of its own.\n return { ...globalStack, ...projectStack };\n}\n\n/** The global install's per-agent stack, absent until a global config exists. */\nasync function loadGlobalStack(): Promise<ProjectConfig[\"stack\"]> {\n return (await loadProjectConfigFromDir(os.homedir()))?.config.stack;\n}\n\nasync function buildInstallConfig(\n wizardResult: WizardResultV2,\n sourceResult: SourceLoadResult,\n projectDir: string,\n): Promise<{ config: ProjectConfig; loadedStack: Stack | null }> {\n const skillIds = unique(wizardResult.skills.map((s) => s.id));\n verbose(\n `buildInstallConfig: selectedStackId='${wizardResult.selectedStackId}', ` +\n `skills=[${skillIds.join(\", \")}], ` +\n `selectedAgents=[${wizardResult.selectedAgents.join(\", \")}]`,\n );\n\n const { source } = sourceResult.sourceConfig;\n const loadedStack = wizardResult.selectedStackId\n ? await loadStackById(wizardResult.selectedStackId, sourceResult.sourcePath, source)\n : null;\n if (wizardResult.selectedStackId) {\n verbose(\n `buildInstallConfig: loadedStack=${loadedStack ? `found (id='${loadedStack.id}')` : \"NOT FOUND\"}`,\n );\n if (!loadedStack) {\n throw new Error(stackNotOfferedMessage(wizardResult.selectedStackId, source));\n }\n }\n\n const existing = await loadProjectConfig(projectDir);\n const existingStack = await loadCuratedStack(projectDir, existing?.config.stack);\n\n // Per-agent curation delta: skills that are new to this session's top-level selection\n // relative to the persisted config. The diff is filtered to active (non-excluded)\n // skills on BOTH sides — excluded entries are not \"present\" from the perspective\n // of stack membership, so flipping an exclusion back to active should register\n // as a newly-added skill. `existing === null` (first init) collapses to \"every\n // skill is new this session\", which the generator's seeding branch tolerates.\n const newlyAddedSkillIds = computeNewlyAddedSkillIds(\n wizardResult.skills,\n existing?.config.skills,\n );\n\n // Scope-eligibility delta: `(agent, skillId)` pairs that are scope-compatible\n // NOW but were not scope-compatible in the persisted config (either the skill's\n // scope was flipped, the agent's scope was flipped, or one of them was absent\n // before). Admits the scope-flip case that a skill-id-only diff would miss.\n const scopeEligibilityGained = computeScopeEligibilityGained(\n wizardResult.skills,\n wizardResult.agentConfigs,\n existing?.config.skills,\n existing?.config.agents,\n );\n\n // Pass user's agent selection and skill configs to config generator.\n // Both skillConfigs and agentConfigs are always passed when selectedAgents is\n // set — the config generator enforces that invariant to prevent silent\n // \"project\" scope defaults on missing lookups.\n const agentOptions: {\n selectedAgents?: AgentName[];\n skillConfigs: SkillConfig[];\n agentConfigs: AgentScopeConfig[];\n existingStack: Partial<Record<AgentName, StackAgentConfig>>;\n newlyAddedSkillIds: readonly SkillId[];\n scopeEligibilityGained: ReadonlySet<string>;\n } = {\n skillConfigs: wizardResult.skills,\n agentConfigs: wizardResult.agentConfigs,\n existingStack,\n newlyAddedSkillIds,\n scopeEligibilityGained,\n ...(wizardResult.selectedAgents.length > 0 && {\n selectedAgents: wizardResult.selectedAgents,\n }),\n };\n\n // With a stack: overlay the stack as `existingStack` so its (agent, category, skill)\n // triples reach the ownership-based builder with a load already decided — the\n // author's flag where a third-party stacks file wrote one, and the shared mapping's\n // verdict where none was written, which is every entry of a built-in stack.\n // `buildStackProperty` is where that decision is made, so applying a stack is a NEW\n // selection: it never arrives flagless and is never read as a curated lazy.\n // The on-disk stack spreads LAST and wins per agent, so re-running over an installed\n // config preserves what the user saved. Ownership rules still govern which agents and\n // categories land in the final stack, so Phase A (init) and Phase B (edit) produce\n // equivalent stacks for the same selection.\n const effectiveOptions = loadedStack\n ? { ...agentOptions, existingStack: { ...buildStackProperty(loadedStack), ...existingStack } }\n : agentOptions;\n const generated = generateProjectConfigFromSkills(\n configNameFor(projectDir),\n skillIds,\n effectiveOptions,\n );\n const stack = resolveStackProperty(generated.stack, wizardResult.assignedStack);\n const description = resolveDescription(loadedStack, wizardResult.description);\n const localConfig: ProjectConfig = {\n ...generated,\n ...(stack && { stack }),\n ...(description !== undefined && { description }),\n };\n\n verbose(\n `buildInstallConfig result: stack=${localConfig.stack ? Object.keys(localConfig.stack).length + \" agents\" : \"UNDEFINED\"}, ` +\n `agents=[${localConfig.agents.map((a) => a.name).join(\", \")}], skills=${localConfig.skills.length}`,\n );\n\n return { config: localConfig, loadedStack };\n}\n\nexport function setConfigMetadata(\n config: ProjectConfig,\n wizardResult: WizardResultV2,\n sourceResult: SourceLoadResult,\n sourceFlag?: string,\n): ProjectConfig {\n const result = { ...config };\n\n // Only persist selected domains when non-empty (sparse output)\n if (wizardResult.selectedDomains.length > 0) {\n result.selectedDomains = wizardResult.selectedDomains;\n }\n\n if (sourceFlag) {\n result.marketplace = sourceFlag;\n } else if (sourceResult.sourceConfig.source) {\n result.marketplace = sourceResult.sourceConfig.source;\n }\n\n if (sourceResult.marketplace) {\n result.marketplaceName = sourceResult.marketplace;\n }\n\n return result;\n}\n\nexport async function buildAndMergeConfig(\n wizardResult: WizardResultV2,\n sourceResult: SourceLoadResult,\n projectDir: string,\n sourceFlag?: string,\n authoritativeScope?: AuthoritativeScope,\n): Promise<MergeResult> {\n const { config } = await buildInstallConfig(wizardResult, sourceResult, projectDir);\n verbose(\n `buildAndMergeConfig: before merge — stack=${config.stack ? Object.keys(config.stack).length + \" agents\" : \"UNDEFINED\"}`,\n );\n const configWithMetadata = setConfigMetadata(config, wizardResult, sourceResult, sourceFlag);\n const result = await mergeWithExistingConfig(configWithMetadata, {\n projectDir,\n ...(authoritativeScope !== undefined && { authoritativeScope }),\n });\n verbose(\n `buildAndMergeConfig: after merge — stack=${result.config.stack ? Object.keys(result.config.stack).length + \" agents\" : \"UNDEFINED\"}, merged=${result.merged}`,\n );\n return result;\n}\n\nexport function buildCompileAgents(\n config: ProjectConfig,\n agents: Partial<Record<AgentName, AgentDefinition>>,\n): Partial<Record<AgentName, CompileAgentConfig>> {\n const activeAgents = config.agents.filter((a) => !a.excluded);\n const excludedSkillIds = effectivelyExcludedSkillIds(config.skills);\n\n // D7 cross-scope safety net: build set of global skill IDs so global agents only see global skills\n const globalSkillIds = new Set(\n config.skills.filter((s) => isActiveAt(s, \"global\")).map((s) => s.id),\n );\n\n // Attach each skill's `origin` to its SkillReference so the compiler can\n // decide between `${id}:${id}` (plugin) and bare id (eject) on a per-skill\n // basis. Missing entries are intentional — user-authored local skills have no\n // SkillConfig and legitimately carry no origin.\n const sourceById = new Map<SkillId, string>(config.skills.map((s) => [s.id, s.origin]));\n\n const buildAgentCompileEntry = (agentConfig: AgentScopeConfig): CompileAgentConfig => {\n // Model/effort are the agent's own settings, not its skills' — a bare agent with no stack\n // entry still carries them, so they are resolved before the skill-less early-out.\n const tuning: CompileAgentConfig = {\n ...(agentConfig.model !== undefined && { model: agentConfig.model }),\n ...(agentConfig.effort !== undefined && { effort: agentConfig.effort }),\n };\n\n const agentStack = config.stack?.[agentConfig.name];\n if (!agentStack) return tuning;\n // Filter out excluded skills; global agents only see global skills (cross-scope safety net)\n const filteredRefs = buildSkillRefsFromConfig(agentStack)\n .filter(\n (ref) =>\n !excludedSkillIds.has(ref.id) &&\n (agentConfig.scope !== \"global\" || globalSkillIds.has(ref.id)),\n )\n .map((ref) => {\n const source = sourceById.get(ref.id);\n return { ...ref, ...(source !== undefined && { source }) };\n });\n return { ...tuning, skills: filteredRefs };\n };\n\n return typedFromEntries<AgentName, CompileAgentConfig>(\n activeAgents\n .filter((agentConfig) => agents[agentConfig.name])\n .map((agentConfig) => [agentConfig.name, buildAgentCompileEntry(agentConfig)]),\n );\n}\n\nexport function buildAgentScopeMap(config: ProjectConfig): Map<AgentName, SkillScope> {\n return activeAgentScopeMap(config.agents);\n}\n","import { parse as parseYaml } from \"yaml\";\nimport path from \"path\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { extractFrontmatter } from \"../../utils/frontmatter\";\nimport { glob, readFile, directoryExists, fileExists } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport {\n CLAUDE_SRC_DIR,\n DIRS,\n LOCAL_PSEUDO_CATEGORY,\n STANDARD_DIRS,\n STANDARD_FILES,\n PROJECT_ROOT,\n} from \"../../consts\";\nimport type { AgentDefinition, AgentName, SkillDefinitionMap, SkillFrontmatter } from \"../../types\";\nimport {\n describeMetadataSchemaFailure,\n formatZodIssues,\n localRawMetadataSchema,\n skillFrontmatterLoaderSchema,\n agentYamlConfigSchema,\n} from \"../schemas\";\nimport type { LocalRawMetadata } from \"../skills/local-skill-loader\";\nimport { METADATA_KEYS } from \"../metadata-keys\";\n\n/** A skill's metadata.yaml as the fields a skill is described by, or why it describes none. */\nexport type SkillMetadataRead =\n { usable: true; metadata: LocalRawMetadata } | { usable: false; reason: string };\n\n/**\n * Reads one skill's metadata.yaml into the fields a skill is described by — the\n * metadata.yaml counterpart of {@link parseFrontmatter}.\n *\n * This is the single judgment of whether a metadata.yaml describes its skill, and\n * every pass that meets one shares it: `compile`'s skill discovery, the local-skill\n * discovery that feeds config-types generation, and `doctor`'s content layer. What\n * each does about a file that describes nothing differs — compile refuses the run,\n * discovery skips the skill, doctor reports it — but what they CALL describing does\n * not. Compile used to check only that the file existed, and then only that it\n * parsed, so it loaded from SKILL.md a skill the same run's config-types pass had\n * already skipped.\n *\n * Both ways of describing nothing are refused here: a file nothing can be parsed\n * out of, and a file that parses without the fields `localRawMetadataSchema`\n * requires. `doctor` layers its stricter published-skill checks on top of the\n * fields this returns; it does not disagree with them.\n */\nexport async function readSkillMetadata(metadataPath: string): Promise<SkillMetadataRead> {\n let parsed: unknown;\n try {\n parsed = parseYaml(await readFile(metadataPath));\n } catch (error) {\n return { usable: false, reason: getErrorMessage(error) };\n }\n\n if (!isFieldMapping(parsed)) {\n return { usable: false, reason: `expected metadata fields, found ${nameYamlValue(parsed)}` };\n }\n\n const validated = localRawMetadataSchema.safeParse(parsed);\n if (!validated.success) {\n return { usable: false, reason: describeMetadataSchemaFailure(validated.error.issues, parsed) };\n }\n\n return { usable: true, metadata: validated.data };\n}\n\n/**\n * Whether this metadata names the `local` placeholder instead of a real category.\n *\n * `local` is a trapdoor rather than a category: it belongs to no domain, so a skill wearing it\n * joins no grid tab and is dropped from every sub-agent's stack. Both passes that read an\n * installed skill's metadata.yaml share this verdict — the local-skill discovery behind the\n * wizard's matrix, and the discovery behind `compile`'s skill count. One reader loading what the\n * other refused is what printed a discovery total beside a refusal about the same skill, in a\n * single run.\n *\n * The sibling of {@link readSkillMetadata}, one question over: that one asks whether the file\n * describes a skill at all, this one whether the skill it describes can be reached. A file can\n * pass the first and fail this, which is why the two verdicts are separate and why this one is\n * not repairable — nothing in the file is malformed.\n */\nexport function namesPlaceholderCategory(metadata: LocalRawMetadata): boolean {\n return metadata.category === LOCAL_PSEUDO_CATEGORY;\n}\n\nfunction isFieldMapping(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Names what a metadata.yaml holds when it holds no fields — for the refusal's reason. */\nfunction nameYamlValue(value: unknown): string {\n if (value === null || value === undefined) return \"an empty file\";\n if (Array.isArray(value)) return \"a list\";\n return `a ${typeof value}`;\n}\n\nexport function parseFrontmatter(content: string, filePath?: string): SkillFrontmatter | null {\n const rawFrontmatter = extractFrontmatter(content);\n if (rawFrontmatter === null) return null;\n\n const parsed = skillFrontmatterLoaderSchema.safeParse(rawFrontmatter);\n\n if (!parsed.success) {\n const location = filePath ?? \"unknown file\";\n warn(`Invalid SKILL.md frontmatter in '${location}': ${formatZodIssues(parsed.error.issues)}`);\n return null;\n }\n return parsed.data;\n}\n\ntype LoadAgentsFromDirOptions = {\n /** Relative base recorded on each definition (project agents live under .claude-src/agents). */\n agentBaseDir?: string;\n /** Propagate the `custom: true` metadata flag (source/CLI agents only). */\n includeCustomFlag?: boolean;\n /** Label for the per-agent verbose line. */\n verboseLabel: string;\n};\n\n// Boundary cast: agent keys come from agentYamlConfigSchema which types config.id as AgentName;\n// custom agents (not in the union) are accepted by the schema's z.string() base\nasync function loadAgentsFromDir(\n agentsDir: string,\n sourceRoot: string,\n options: LoadAgentsFromDirOptions,\n): Promise<Partial<Record<AgentName, AgentDefinition>>> {\n const agents: Record<string, AgentDefinition> = {};\n const files = await glob(`**/${STANDARD_FILES.AGENT_METADATA_YAML}`, agentsDir);\n\n for (const file of files) {\n const fullPath = path.join(agentsDir, file);\n try {\n const content = await readFile(fullPath);\n const config = agentYamlConfigSchema.parse(parseYaml(content));\n\n agents[config.id] = {\n title: config.title,\n description: config.description,\n ...(config.model !== undefined && { model: config.model }),\n tools: config.tools,\n path: path.dirname(file),\n sourceRoot,\n ...(options.agentBaseDir ? { agentBaseDir: options.agentBaseDir } : {}),\n ...(config.domain ? { domain: config.domain } : {}),\n ...(options.includeCustomFlag && config.custom === true ? { custom: true } : {}),\n };\n\n verbose(`Loaded ${options.verboseLabel}: ${config.id} from ${file}`);\n } catch (error) {\n warn(`Skipping invalid metadata.yaml at '${fullPath}': ${getErrorMessage(error)}`);\n }\n }\n\n return agents;\n}\n\nexport async function loadAllAgents(\n projectRoot: string,\n): Promise<Partial<Record<AgentName, AgentDefinition>>> {\n return loadAgentsFromDir(path.join(projectRoot, DIRS.agents), projectRoot, {\n includeCustomFlag: true,\n verboseLabel: \"agent\",\n });\n}\n\n/**\n * Loads agent definitions from the CLI repo and a skills source in parallel,\n * merged so source definitions take precedence on name collisions.\n */\nexport async function loadMergedAgents(\n sourcePath: string,\n): Promise<Partial<Record<AgentName, AgentDefinition>>> {\n const [cliAgents, sourceAgents] = await Promise.all([\n loadAllAgents(PROJECT_ROOT),\n loadAllAgents(sourcePath),\n ]);\n return { ...cliAgents, ...sourceAgents };\n}\n\nexport async function loadProjectAgents(\n projectRoot: string,\n): Promise<Partial<Record<AgentName, AgentDefinition>>> {\n const projectAgentsDir = path.join(projectRoot, CLAUDE_SRC_DIR, STANDARD_DIRS.AGENTS);\n\n if (!(await directoryExists(projectAgentsDir))) {\n verbose(`No project agents directory at ${projectAgentsDir}`);\n const noAgents: Record<string, AgentDefinition> = {};\n return noAgents;\n }\n\n return loadAgentsFromDir(projectAgentsDir, projectRoot, {\n // Project agents are in .claude-src/agents/\n agentBaseDir: `${CLAUDE_SRC_DIR}/agents`,\n verboseLabel: \"project agent\",\n });\n}\n\nexport type LoadSkillsFromDirOptions = {\n /** Path prefix recorded on each skill's `path` (e.g. LOCAL_SKILLS_PATH or \"skills\"). */\n pathPrefix?: string;\n /**\n * When true, a SKILL.md whose sibling metadata.yaml is missing, or present but\n * describing no skill, is skipped (local-skill registration rule). Plugin\n * discovery passes false — plugin skills carry no metadata.yaml.\n */\n requireMetadata?: boolean;\n};\n\n/** One skill directory whose metadata.yaml exists but describes no skill. */\nexport type UnusableSkillMetadata = {\n /** The skill's directory name, as it appears under `.claude/skills/`. */\n skillDirName: string;\n /** Absolute path to the offending metadata.yaml. */\n metadataPath: string;\n /** The YAML parser's own message, what the file holds instead of fields, or which fields it lacks. */\n reason: string;\n};\n\nexport type LoadedSkills = {\n skills: SkillDefinitionMap;\n /**\n * Skill directories refused by {@link readSkillMetadata}. Only ever non-empty\n * under `requireMetadata` — a plugin skill carries no metadata.yaml to refuse.\n */\n unusableMetadata: UnusableSkillMetadata[];\n};\n\n/**\n * Loads SKILL.md files from a directory, parsing frontmatter for skill metadata.\n * Returns the skillId -> SkillDefinition map plus every skill directory whose\n * metadata.yaml describes no skill. Missing/invalid frontmatter and per-file read\n * errors are logged and skipped, never thrown.\n */\nexport async function loadSkillsFromDir(\n skillsDir: string,\n options: LoadSkillsFromDirOptions = {},\n): Promise<LoadedSkills> {\n const { pathPrefix = \"\", requireMetadata = false } = options;\n const skills: SkillDefinitionMap = {};\n const unusableMetadata: UnusableSkillMetadata[] = [];\n\n if (!(await directoryExists(skillsDir))) {\n return { skills, unusableMetadata };\n }\n\n const skillFiles = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir);\n\n for (const skillFile of skillFiles) {\n const skillPath = path.join(skillsDir, skillFile);\n const skillDir = path.dirname(skillPath);\n const relativePath = path.relative(skillsDir, skillDir);\n const skillDirName = path.basename(skillDir);\n const displayPath = pathPrefix ? `${pathPrefix}/${relativePath}/` : `${relativePath}/`;\n\n if (requireMetadata) {\n const metadataPath = path.join(skillDir, STANDARD_FILES.METADATA_YAML);\n if (!(await fileExists(metadataPath))) {\n warn(\n `Skill '${skillDirName}' in '${displayPath}' is missing ${STANDARD_FILES.METADATA_YAML} — skipped. Add ${STANDARD_FILES.METADATA_YAML} to register it with the CLI.`,\n );\n continue;\n }\n\n // A metadata.yaml that describes no skill is reported to the caller rather\n // than loaded around: the local-skill discovery behind config-types\n // generation refuses the same file, and compile refuses the whole run over it.\n const read = await readSkillMetadata(metadataPath);\n if (!read.usable) {\n unusableMetadata.push({ skillDirName, metadataPath, reason: read.reason });\n verbose(` Unusable ${STANDARD_FILES.METADATA_YAML} in '${skillDirName}'`);\n continue;\n }\n\n // Skipped rather than reported, and silently: the file is intact, so there is nothing\n // here to repair or refuse a run over — and the sentence telling the user which field\n // to fix is `extractLocalSkill`'s, which every command reaching here also runs.\n if (namesPlaceholderCategory(read.metadata)) {\n verbose(` Placeholder ${METADATA_KEYS.CATEGORY} in '${skillDirName}'`);\n continue;\n }\n }\n\n try {\n const content = await readFile(skillPath);\n const frontmatter = parseFrontmatter(content, skillPath);\n\n if (!frontmatter?.name) {\n warn(`Skipping skill in '${skillDirName}': missing or invalid frontmatter name`);\n continue;\n }\n\n const canonicalId = frontmatter.name;\n skills[canonicalId] = {\n id: canonicalId,\n path: displayPath,\n description: frontmatter.description || \"\",\n };\n\n verbose(` Loaded skill: ${canonicalId}`);\n } catch (error) {\n verbose(` Failed to load skill: ${skillFile} - ${getErrorMessage(error)}`);\n }\n }\n\n return { skills, unusableMetadata };\n}\n\n/**\n * Loads skills from a plugin's `skills/` subdirectory. Plugin skills carry no\n * metadata.yaml, so metadata is not required here — and nothing can be refused\n * for one, which is why only the skill map comes back.\n */\nexport async function loadPluginSkills(pluginDir: string): Promise<SkillDefinitionMap> {\n const { skills } = await loadSkillsFromDir(path.join(pluginDir, \"skills\"), {\n pathPrefix: \"skills\",\n requireMetadata: false,\n });\n return skills;\n}\n","import { parse as parseYaml } from \"yaml\";\n\nexport function extractFrontmatter(content: string): unknown {\n const frontmatterRegex = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/;\n const match = content.match(frontmatterRegex);\n\n if (!match || !match[1]) {\n return null;\n }\n\n try {\n return parseYaml(match[1]);\n } catch {\n return null;\n }\n}\n","import { createHash } from \"crypto\";\nimport { isRecord } from \"../../utils/type-guards.js\";\nimport { downloadTemplate, type DownloadTemplateResult } from \"giget\";\nimport os from \"os\";\nimport path from \"path\";\nimport type { z } from \"zod\";\n\nimport {\n cacheRoot,\n CACHE_HASH_LENGTH,\n CACHE_READABLE_PREFIX_LENGTH,\n MAX_MARKETPLACE_FILE_SIZE,\n MAX_JSON_NESTING_DEPTH,\n MAX_MARKETPLACE_PLUGINS,\n MARKETPLACE_JSON,\n marketplaceManifestPath,\n} from \"../../consts\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport {\n ensureDir,\n directoryExists,\n fileExists,\n readFileOptional,\n readFileSafe,\n remove,\n writeFile,\n} from \"../../utils/fs\";\nimport { log, verbose, warn } from \"../../utils/logger\";\nimport { sourceUnreachableUsingCache, STATUS_MESSAGES } from \"../../utils/messages\";\nimport { DEFAULT_SOURCE, isLocalSource } from \"../configuration\";\nimport {\n formatZodIssues,\n marketplaceSchema,\n sourceRevalidationSchema,\n validateNestingDepth,\n warnUnknownFields,\n} from \"../schemas\";\nimport type { Marketplace, MarketplaceFetchResult } from \"../../types\";\n\n/** Safe name pattern: alphanumeric, hyphens, underscores, dots, spaces, @, / (no shell metacharacters) */\nconst SAFE_NAME_PATTERN = /^[a-zA-Z0-9@._/ -]+$/;\nconst MAX_NAME_LENGTH = 200;\n\n/** Matches giget's source protocol regex to extract provider name */\nconst SOURCE_PROTO_RE = /^([\\w-.]+):/;\n\n/**\n * Matches giget's input regex for git URI parsing.\n * Groups: repo (org/name), subdir (optional path), ref (optional #branch)\n */\nconst GIT_URI_RE = /^(?<repo>[\\w.-]+\\/[\\w.-]+)(?<subdir>[^#]+)?(?<ref>#[\\w./@-]+)?/;\n\nexport type FetchOptions = {\n subdir?: string;\n};\n\nexport type FetchResult = {\n path: string;\n fromCache: boolean;\n source: string;\n};\n\nexport function sanitizeSourceForCache(source: string): string {\n const hash = createHash(\"sha256\").update(source).digest(\"hex\").slice(0, CACHE_HASH_LENGTH);\n\n const readable = source\n .replace(/[^a-zA-Z0-9]/g, \"-\")\n .replace(/--+/g, \"-\")\n .replace(/^-|-$/g, \"\")\n .slice(0, CACHE_READABLE_PREFIX_LENGTH);\n\n return readable ? `${readable}-${hash}` : hash;\n}\n\nfunction getCacheDir(source: string): string {\n const sanitized = sanitizeSourceForCache(source) || \"unknown\";\n return path.join(cacheRoot(), \"sources\", sanitized);\n}\n\nexport async function fetchFromSource(\n source: string,\n options: FetchOptions = {},\n): Promise<FetchResult> {\n const { subdir } = options;\n\n if (isLocalSource(source)) {\n return fetchFromLocalSource(source, subdir);\n }\n\n return fetchFromRemoteSource(source, subdir);\n}\n\nasync function fetchFromLocalSource(source: string, subdir?: string): Promise<FetchResult> {\n const fullPath = subdir ? path.join(source, subdir) : source;\n const absolutePath = path.isAbsolute(fullPath) ? fullPath : path.resolve(process.cwd(), fullPath);\n\n if (!(await directoryExists(absolutePath))) {\n throw new Error(\n `Local marketplace not found: '${absolutePath}'\\n\\n` +\n `Nothing is at that path, and a local marketplace must be a directory holding skills.\\n\\n` +\n `Check it for a typo, or name a marketplace that exists:\\n` +\n ` --marketplace ${DEFAULT_SOURCE}`,\n );\n }\n\n verbose(`Using local marketplace: ${absolutePath}`);\n\n return {\n path: absolutePath,\n fromCache: false,\n source,\n };\n}\n\n/**\n * Compute the giget tarball cache directory for a source.\n *\n * Replicates giget's internal cache path logic:\n * `{gigetCacheRoot}/{providerName}/{templateName}`\n *\n * where templateName is `repo.replace(\"/\", \"-\")` sanitized to `[a-zA-Z0-9-]`.\n * Returns undefined if the source format doesn't match giget's git URI pattern.\n */\nexport function getGigetCacheDir(source: string): string | undefined {\n const protoMatch = source.match(SOURCE_PROTO_RE);\n\n // http/https providers use the full URL, not parseable as git URI\n if (protoMatch && (protoMatch[1] === \"http\" || protoMatch[1] === \"https\")) {\n return undefined;\n }\n\n const providerName = protoMatch?.[1] ?? \"github\";\n const rawSource = protoMatch ? source.slice(protoMatch[0].length) : source;\n\n const uriMatch = rawSource.match(GIT_URI_RE);\n if (!uriMatch?.groups?.repo) {\n return undefined;\n }\n\n // Replicate giget's template.name sanitization\n const templateName = uriMatch.groups.repo.replace(\"/\", \"-\").replace(/[^\\da-z-]/gi, \"-\");\n\n const gigetCacheRoot = process.env.XDG_CACHE_HOME\n ? path.resolve(process.env.XDG_CACHE_HOME, \"giget\")\n : path.resolve(os.homedir(), \".cache\", \"giget\");\n\n return path.join(gigetCacheRoot, providerName, templateName);\n}\n\n/**\n * Clear giget's tarball/ETag cache for a source so downloadTemplate()\n * performs a fresh fetch instead of short-circuiting with a stale ETag.\n */\nasync function clearGigetCache(source: string): Promise<void> {\n const gigetDir = getGigetCacheDir(source);\n if (!gigetDir) return;\n\n if (await directoryExists(gigetDir)) {\n verbose(`Clearing giget cache: ${gigetDir}`);\n await remove(gigetDir);\n }\n}\n\nasync function fetchFromRemoteSource(source: string, subdir?: string): Promise<FetchResult> {\n const cacheDir = getCacheDir(source);\n const fullSource = subdir ? `${source}/${subdir}` : source;\n\n verbose(`Fetching from remote: ${fullSource}`);\n verbose(`Cache directory: ${cacheDir}`);\n\n if (await directoryExists(cacheDir)) {\n const verdict = await revalidateCachedCopy(cacheDir, source);\n const cached: FetchResult = { path: cacheDir, fromCache: true, source: fullSource };\n\n if (verdict === \"current\" || verdict === \"unreachable\") {\n verbose(`Using cached marketplace: ${cacheDir}`);\n return cached;\n }\n\n announceRefetch(verdict);\n await clearGigetCache(source);\n await remove(cacheDir);\n }\n\n await ensureDir(path.dirname(cacheDir));\n\n try {\n const result = await downloadTemplate(fullSource, {\n dir: cacheDir,\n force: true, // Always force when downloading to avoid \"already exists\" error\n offline: false,\n });\n\n verbose(`Downloaded to: ${result.dir}`);\n await recordFetchedCopy(cacheDir, result);\n markCopyCurrentForThisRun(cacheDir);\n\n return {\n path: result.dir,\n fromCache: false,\n source: fullSource,\n };\n } catch (error) {\n throw createDetailedFetchError(error, source);\n }\n}\n\n/**\n * What a revalidation learned about the copy in the cache.\n *\n * `unrecorded` is a cache with no fetch record beside it — written before this\n * check existed, or by hand. Nothing can be asked about it, so it is re-fetched\n * once to establish a record, and that re-fetch is not a change to announce.\n */\ntype CacheVerdict = \"current\" | \"superseded\" | \"unrecorded\" | \"unreachable\";\n\ntype SourceRevalidation = z.infer<typeof sourceRevalidationSchema>;\n\n/**\n * How long a revalidation may spend asking before the cached copy is used\n * instead. Against the default marketplace the question costs ~260ms, so five\n * seconds is around twenty times a healthy answer: a link slow enough to need\n * that much is still given the chance to answer, rather than being told its copy\n * may be stale when the source was reachable all along. Being unreachable is the\n * rare case, and a longer honest wait for it is cheaper than a wrong verdict on\n * a slow one. The bound still exists — the platform's own connect timeout is\n * ~10s, which is the wait no user with a dropped connection should sit through\n * for an answer their cache already holds.\n */\nconst REVALIDATION_TIMEOUT_MS = 5000;\n\n/** Where a cache directory's fetch record sits: beside it, never inside it. */\nconst FETCH_RECORD_SUFFIX = \".etag.json\";\n\n/**\n * One question per source per process. A single command loads the same source\n * more than once — the matrix and the marketplace label are separate calls — and\n * the answer cannot change between them.\n */\nconst askedThisRun = new Map<string, Promise<CacheVerdict>>();\n\n/**\n * The one line a re-fetch nobody asked for owes the user — and silence for\n * `unrecorded`, where the CLI cannot place the copy it holds and the re-fetch is\n * housekeeping rather than news.\n *\n * The parameter is the two verdicts that reach a download, not the whole union:\n * a new verdict that must not fall through to one fails here at the call site.\n */\nfunction announceRefetch(verdict: Extract<CacheVerdict, \"superseded\" | \"unrecorded\">): void {\n if (verdict === \"superseded\") {\n log(STATUS_MESSAGES.MARKETPLACE_HAS_NEWER_CONTENT);\n }\n}\n\nfunction revalidateCachedCopy(cacheDir: string, source: string): Promise<CacheVerdict> {\n const asked = askedThisRun.get(cacheDir);\n if (asked) return asked;\n\n const verdict = classifyCachedCopy(cacheDir, source);\n askedThisRun.set(cacheDir, verdict);\n return verdict;\n}\n\n/**\n * The answer for a copy this run has just downloaded, without asking for it: the\n * record written beside it names the tarball the source served a moment ago, so\n * within this run the copy is current by construction. Without it, the later\n * loads of the same command re-read a `superseded` answer that was true when it\n * was given and has been acted on since — and download it all over again.\n */\nfunction markCopyCurrentForThisRun(cacheDir: string): void {\n askedThisRun.set(cacheDir, Promise.resolve(\"current\"));\n}\n\n/**\n * The one question a run asks about a cached copy, and everything that answer\n * owes the user.\n *\n * An unreachable source's staleness is named here rather than at the call site\n * because the verdict is memoised and the line is owed once per source per run:\n * left outside, every later load of the same run repeats a warning about a\n * question that was only asked once.\n */\nasync function classifyCachedCopy(cacheDir: string, source: string): Promise<CacheVerdict> {\n const record = await readFetchRecord(cacheDir);\n if (!record) return \"unrecorded\";\n\n if (record.etag === undefined) {\n verbose(`No ETag was recorded for ${record.tar} — keeping the cached copy`);\n return \"current\";\n }\n\n try {\n const live = await fetchEtag(record.tar);\n if (live === undefined) {\n verbose(`${record.tar} answered without an ETag — keeping the cached copy`);\n return \"current\";\n }\n return live === record.etag ? \"current\" : \"superseded\";\n } catch (error) {\n verbose(`Could not revalidate ${record.tar}: ${getErrorMessage(error)}`);\n warn(sourceUnreachableUsingCache(source));\n return \"unreachable\";\n }\n}\n\n/**\n * The tarball's ETag as the host reports it now, asked for the same way giget\n * asks — a HEAD, from the same runtime — so the two agree on what the value for\n * a given source is. A private repository needs the token giget uses; it is read\n * from the environment per request and never written into the record.\n */\nasync function fetchEtag(tar: string): Promise<string | undefined> {\n const auth = process.env.GIGET_AUTH;\n const response = await fetch(tar, {\n method: \"HEAD\",\n ...(auth && { headers: { Authorization: `Bearer ${auth}` } }),\n signal: AbortSignal.timeout(REVALIDATION_TIMEOUT_MS),\n });\n return response.headers.get(\"etag\") ?? undefined;\n}\n\n/**\n * Where the record for a cached copy lives — exported because a second surface has to agree with\n * this one on the address: `e2e/fixtures/default-source-cache.ts` seeds a copy of the DEFAULT\n * source, and a run over a seeded copy with no record here re-downloads it over the network, which\n * is the one thing that fixture exists to avoid.\n */\nexport function fetchRecordPath(cacheDir: string): string {\n return `${cacheDir}${FETCH_RECORD_SUFFIX}`;\n}\n\nasync function readFetchRecord(cacheDir: string): Promise<SourceRevalidation | undefined> {\n const raw = await readFileOptional(fetchRecordPath(cacheDir));\n if (!raw) return undefined;\n\n const parsed = sourceRevalidationSchema.safeParse(parseJsonOrUndefined(raw));\n if (!parsed.success) {\n verbose(`Unusable fetch record at ${fetchRecordPath(cacheDir)} — re-fetching the marketplace`);\n return undefined;\n }\n\n return parsed.data;\n}\n\n/**\n * Records what would prove this copy current, so the next load can ask in one\n * request.\n *\n * The tarball URL is read off giget's own result rather than rebuilt here, which\n * is what keeps this provider-agnostic — it is whatever giget resolved for the\n * source. giget's result type erases its fields to an index signature, so the\n * value arrives untyped and is narrowed rather than trusted; without one there\n * is nothing to ask about and the copy stays unrecorded.\n */\nasync function recordFetchedCopy(cacheDir: string, result: DownloadTemplateResult): Promise<void> {\n const tar: unknown = result.tar;\n if (typeof tar !== \"string\") {\n verbose(\"No tarball URL came back from the download — the copy cannot be revalidated\");\n return;\n }\n\n const etag = await fetchEtag(tar).catch(() => undefined);\n const record: SourceRevalidation = { tar, ...(etag !== undefined && { etag }) };\n await writeFile(fetchRecordPath(cacheDir), JSON.stringify(record));\n}\n\nfunction parseJsonOrUndefined(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return undefined;\n }\n}\n\nfunction createDetailedFetchError(error: unknown, source: string): Error {\n const message = getErrorMessage(error);\n\n if (message.includes(\"404\") || message.includes(\"Not Found\")) {\n return new Error(\n `Repository not found: ${source}\\n\\n` +\n `This could mean:\\n` +\n ` - The repository doesn't exist\\n` +\n ` - The repository is private and you need to set authentication\\n` +\n ` - There's a typo in the URL\\n\\n` +\n `For private repositories, set the GIGET_AUTH environment variable:\\n` +\n ` export GIGET_AUTH=ghp_your_github_token`,\n );\n }\n\n if (message.includes(\"401\") || message.includes(\"Unauthorized\")) {\n return new Error(\n `Authentication required for: ${source}\\n\\n` +\n `Set the GIGET_AUTH environment variable with a GitHub token:\\n` +\n ` export GIGET_AUTH=ghp_your_github_token\\n\\n` +\n `Create a token at: https://github.com/settings/tokens\\n` +\n `Required scope: repo (for private repos) or public_repo (for public)`,\n );\n }\n\n if (message.includes(\"403\") || message.includes(\"Forbidden\")) {\n return new Error(\n `Access denied to: ${source}\\n\\n` +\n `Your token may not have sufficient permissions.\\n` +\n `Ensure your GIGET_AUTH token has the 'repo' scope for private repositories.`,\n );\n }\n\n if (\n message.includes(\"ENOTFOUND\") ||\n message.includes(\"ETIMEDOUT\") ||\n message.includes(\"network\")\n ) {\n return new Error(\n `Network error fetching: ${source}\\n\\n` +\n `Please check your internet connection.\\n` +\n `If you're behind a corporate proxy, you may need to set:\\n` +\n ` export HTTPS_PROXY=http://your-proxy:port\\n` +\n ` export FORCE_NODE_FETCH=true # Required for Node 20+`,\n );\n }\n\n return new Error(`Failed to fetch ${source}: ${message}`);\n}\n\n/**\n * Thrown when a marketplace has no manifest at all, which every other failure in\n * {@link fetchMarketplace} is not.\n *\n * A type rather than a sentence a caller matches on: absent and unreadable have\n * different remedies — add the file, versus repair the file that is already there —\n * and the only way a caller can report them apart is if the throw says which it is.\n * A caller that does not care still catches an ordinary `Error`.\n */\nexport class MarketplaceManifestAbsentError extends Error {}\n\n/**\n * Thrown when the manifest is there, parses, and names the marketplace something this\n * CLI refuses to publish under.\n *\n * A type of its own for the reason {@link MarketplaceManifestAbsentError} is one, and\n * one step further: this is the only manifest defect whose remedy is not \"repair the\n * file so the marketplace can be named\" but \"there is nothing to install here at all\".\n * The name is the namespace Claude Code registers every plugin under, so a name it will\n * not accept leaves a marketplace that loads and can install nothing — which is the\n * state `build marketplace` refuses to publish and this is the same rule read on load.\n * Every other refusal in {@link fetchMarketplace} leaves the marketplace installable\n * and merely unnameable, so it stays an ordinary `Error` and its reader degrades.\n */\nexport class MarketplaceNameRefusedError extends Error {}\n\n/**\n * The manifest field whose value a load then USES, spelled against the type so a rename\n * of it fails here rather than silently stopping the refusal below from firing.\n */\nconst MANIFEST_NAME_FIELD: keyof Marketplace = \"name\";\n\n/**\n * Whether a manifest's refusal is about its name.\n *\n * Read off the issue's PATH rather than its text, for the reason\n * {@link MarketplaceManifestAbsentError} is a type: a message is prose that gets\n * rewritten, and a caller matching on one is a caller that stops working silently.\n */\nfunction refusesTheName(issues: readonly z.ZodIssue[]): boolean {\n return issues.some((issue) => issue.path.length === 1 && issue.path[0] === MANIFEST_NAME_FIELD);\n}\n\n/**\n * A refused manifest as the throw its readers tell apart — see\n * {@link MarketplaceNameRefusedError} for which refusal earns which type. The message is\n * one sentence either way: what separates them is the remedy, not the wording.\n */\nfunction manifestRefusal(marketplacePath: string, issues: readonly z.ZodIssue[]): Error {\n const message =\n `Invalid ${MARKETPLACE_JSON} at: ${marketplacePath}\\n\\n` +\n `Validation errors: ${formatZodIssues([...issues])}`;\n\n return refusesTheName(issues) ? new MarketplaceNameRefusedError(message) : new Error(message);\n}\n\nexport async function fetchMarketplace(source: string): Promise<MarketplaceFetchResult> {\n const result = await fetchFromSource(source, {\n subdir: \"\", // Root of repo\n });\n\n const marketplacePath = marketplaceManifestPath(result.path);\n\n // The FILE, not its directory: a plugin repository ships `.claude-plugin/plugin.json`\n // with no marketplace beside it, and a directory check calls that manifest readable\n // and leaves the absence to surface as a read error two statements later.\n if (!(await fileExists(marketplacePath))) {\n throw new MarketplaceManifestAbsentError(\n `Marketplace not found at: ${source}\\n\\n` +\n `The .claude-plugin/marketplace.json file is missing from this repository.\\n\\n` +\n `Possible causes:\\n` +\n \" - The marketplace URL may be incorrect\\n\" +\n \" - The repository may not have a marketplace configured\\n\\n\" +\n \"To create a marketplace, add a .claude-plugin/marketplace.json file to your marketplace repository.\",\n );\n }\n\n const content = await readFileSafe(marketplacePath, MAX_MARKETPLACE_FILE_SIZE);\n const parsed: unknown = JSON.parse(content);\n\n if (!validateNestingDepth(parsed, MAX_JSON_NESTING_DEPTH)) {\n throw new Error(\n `Invalid marketplace.json at: ${marketplacePath}\\n\\n` +\n `JSON structure exceeds maximum nesting depth of ${MAX_JSON_NESTING_DEPTH}.`,\n );\n }\n\n const validation = marketplaceSchema.safeParse(parsed);\n\n if (!validation.success) {\n throw manifestRefusal(marketplacePath, validation.error.issues);\n }\n\n const marketplace = validation.data;\n\n const EXPECTED_MARKETPLACE_KEYS = [\n \"$schema\",\n \"name\",\n \"version\",\n \"description\",\n \"owner\",\n \"metadata\",\n \"plugins\",\n ] as const;\n if (isRecord(parsed)) {\n warnUnknownFields(parsed, EXPECTED_MARKETPLACE_KEYS, MARKETPLACE_JSON);\n }\n\n if (marketplace.plugins.length > MAX_MARKETPLACE_PLUGINS) {\n throw new Error(\n `Invalid marketplace.json at: ${marketplacePath}\\n\\n` +\n `Too many plugins: ${marketplace.plugins.length} (limit: ${MAX_MARKETPLACE_PLUGINS}).`,\n );\n }\n\n for (const plugin of marketplace.plugins) {\n if (plugin.name.length > MAX_NAME_LENGTH) {\n warn(\n `Marketplace plugin name too long (${plugin.name.length} chars): '${plugin.name.slice(0, 50)}...'`,\n );\n }\n if (!SAFE_NAME_PATTERN.test(plugin.name)) {\n warn(`Marketplace plugin name contains unsafe characters: '${plugin.name.slice(0, 50)}'`);\n }\n }\n\n verbose(`Loaded marketplace: ${marketplace.name} v${marketplace.version}`);\n\n return {\n marketplace,\n sourcePath: result.path,\n fromCache: result.fromCache,\n };\n}\n","import os from \"os\";\n\nimport { isHomeDirectory } from \"../installation/is-home-directory\";\nimport { DEFAULT_PUBLIC_SOURCE_NAME, EJECT_SOURCE } from \"../../consts\";\nimport type {\n MergedSkillsMatrix,\n ResolvedSkill,\n SkillId,\n SkillSource,\n SkillSourceType,\n} from \"../../types\";\nimport { verbose } from \"../../utils/logger\";\nimport { typedEntries, typedKeys } from \"../../utils/typed-object\";\nimport { isDefaultSource, type ResolvedConfig } from \"../configuration\";\nimport { discoverAllPluginSkills } from \"../plugins\";\n\n/**\n * True when the tagging pass looked at this skill and found only the copy on disk.\n *\n * The one reading of `availableSources` every surface that asks \"can this be a plugin?\"\n * must share: the Sources grid offers a cell on it and the install pipeline refuses on\n * it, and a second copy of the rule is how those two come to disagree. Asked of the\n * tagged sources rather than of `custom` — what a plugin install needs is a marketplace\n * that HAS the skill, and who wrote it decides nothing. A skill the pass never reached\n * carries no sources at all and answers `false`: absence of an answer is not an answer.\n */\nexport function isLocalOnlySkill(skill: ResolvedSkill | undefined): boolean {\n return (\n skill?.availableSources !== undefined &&\n !skill.availableSources.some((source) => source.type !== \"local\")\n );\n}\n\n/**\n * Appends a source to the skill's availableSources, initializing the array on\n * first tag. In-place mutation is this module's documented tagging contract.\n */\nfunction addAvailableSource(\n skill: { availableSources?: SkillSource[] },\n source: SkillSource,\n): void {\n skill.availableSources = skill.availableSources ?? [];\n skill.availableSources.push(source);\n}\n\n/**\n * Annotates every skill in the matrix with its install-mode availability metadata.\n *\n * Runs a four-phase tagging pipeline that mutates `primaryMatrix.skills` in place:\n * 1. **Primary** -- tags every skill the marketplace CARRIES with it (public or private),\n * skipping the ids in `unbackedSkillIds`\n * 2. **Local** -- tags skills with `local: true` as installed via local source\n * 3. **Plugin** -- detects plugin-installed skills via `settings.json` and global cache\n * 4. **Active source** -- sets `activeSource` to the installed variant, or first available\n *\n * After this function completes, each skill in the matrix has `availableSources` -- at most\n * the local copy and the one marketplace, which are the two install modes the Sources step\n * offers -- and `activeSource` (the one currently in use) populated.\n *\n * @param primaryMatrix - The merged skills matrix to annotate. Mutated in place --\n * `availableSources` and `activeSource` are set on each skill.\n * @param sourceConfig - Resolved source configuration, used to determine whether the\n * marketplace is a private one or the default public source\n * @param projectDir - Absolute path to the project root, used to locate plugin directories\n * @param marketplace - Optional marketplace name resolved from the source's marketplace.json.\n * Takes precedence over `sourceConfig.marketplace` when provided.\n * @param unbackedSkillIds - Ids the matrix holds that the marketplace does NOT carry: skills\n * the local merge introduced from `.claude/skills/`. They are left\n * out of the primary tag, because a marketplace entry on a skill no\n * marketplace has is a plugin install that cannot happen. Defaults\n * to empty, which is what a matrix built without a local merge means.\n *\n * @remarks\n * **Side effects:** Mutates `primaryMatrix` in place.\n */\nexport async function loadSkillsFromAllSources(\n primaryMatrix: MergedSkillsMatrix,\n sourceConfig: ResolvedConfig,\n projectDir: string,\n marketplace?: string,\n unbackedSkillIds: ReadonlySet<SkillId> = new Set(),\n): Promise<void> {\n const resolvedMarketplace = marketplace ?? sourceConfig.marketplace;\n const primarySourceName = resolvedMarketplace ?? DEFAULT_PUBLIC_SOURCE_NAME;\n const primarySourceType: SkillSourceType = isDefaultSource(sourceConfig.source)\n ? \"public\"\n : \"private\";\n\n tagPrimarySourceSkills(primaryMatrix, primarySourceName, primarySourceType, unbackedSkillIds);\n tagLocalSkills(primaryMatrix);\n await tagPluginSkills(primaryMatrix, projectDir, primarySourceName, primarySourceType);\n setActiveSources(primaryMatrix);\n}\n\nfunction tagPrimarySourceSkills(\n matrix: MergedSkillsMatrix,\n sourceName: string,\n sourceType: SkillSourceType,\n unbackedSkillIds: ReadonlySet<SkillId>,\n): void {\n for (const [id, skill] of typedEntries(matrix.skills)) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n if (!skill) continue;\n if (unbackedSkillIds.has(id)) continue;\n\n const source: SkillSource = {\n name: sourceName,\n type: sourceType,\n installed: false,\n primary: true,\n };\n\n addAvailableSource(skill, source);\n }\n}\n\nfunction tagLocalSkills(matrix: MergedSkillsMatrix): void {\n let count = 0;\n for (const [, skill] of typedEntries(matrix.skills)) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n if (!skill) continue;\n if (!skill.local) continue;\n\n const source: SkillSource = {\n name: EJECT_SOURCE,\n type: \"local\",\n installed: true,\n installMode: \"eject\",\n };\n\n addAvailableSource(skill, source);\n count++;\n }\n\n verbose(`Tagged ${count} local skills with local source`);\n}\n\nasync function tagPluginSkills(\n matrix: MergedSkillsMatrix,\n projectDir: string,\n primarySourceName: string,\n primarySourceType: SkillSourceType,\n): Promise<void> {\n const allPluginSkillIds = await collectPluginSkillIds(projectDir);\n\n if (allPluginSkillIds.length === 0) {\n return;\n }\n\n for (const skillId of allPluginSkillIds) {\n const skill = matrix.skills[skillId];\n if (!skill) continue;\n\n skill.availableSources = skill.availableSources ?? [];\n\n const existingSource = skill.availableSources.find((s) => s.name === primarySourceName);\n if (existingSource && !existingSource.installMode) {\n existingSource.installed = true;\n existingSource.installMode = \"plugin\";\n } else if (!skill.availableSources.some((s) => s.installMode === \"plugin\")) {\n skill.availableSources.push({\n name: primarySourceName,\n type: primarySourceType,\n installed: true,\n installMode: \"plugin\",\n primary: true,\n });\n }\n }\n\n verbose(`Tagged ${allPluginSkillIds.length} plugin-installed skills`);\n}\n\n/**\n * Collects skill IDs from all enabled plugins via settings.json and global cache.\n * Uses {@link discoverAllPluginSkills} to find skills from the plugin registry.\n */\nasync function collectPluginSkillIds(projectDir: string): Promise<SkillId[]> {\n const pluginSkills = await discoverAllPluginSkills(projectDir);\n const skillIds = typedKeys<SkillId>(pluginSkills);\n\n // Also discover global plugins when editing from a project directory.\n // Follows the same global+project merge pattern as local skills in source-loader.ts.\n const homeDir = os.homedir();\n if (!isHomeDirectory(projectDir)) {\n const globalPluginSkills = await discoverAllPluginSkills(homeDir);\n const globalSkillIds = typedKeys<SkillId>(globalPluginSkills);\n if (globalSkillIds.length > 0) {\n verbose(`Found ${globalSkillIds.length} global plugin skill(s)`);\n const merged = new Set([...skillIds, ...globalSkillIds]);\n return [...merged];\n }\n }\n\n if (skillIds.length === 0) {\n verbose(\"No plugin skills discovered from settings.json\");\n }\n\n return skillIds;\n}\n\n/** Prefers installed source so the wizard shows current state; falls back to first available */\nfunction setActiveSources(matrix: MergedSkillsMatrix): void {\n for (const [, skill] of typedEntries(matrix.skills)) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n if (!skill) continue;\n if (!skill.availableSources || skill.availableSources.length === 0) continue;\n\n // Prefer installed source, then fall back to first available\n const [firstSource] = skill.availableSources;\n if (!firstSource) continue;\n skill.activeSource = skill.availableSources.find((s) => s.installed) ?? firstSource;\n }\n}\n","import type {\n AgentConfig,\n AgentDefinition,\n AgentName,\n CompileAgentConfig,\n CompileConfig,\n Skill,\n SkillDefinitionMap,\n SkillReference,\n StackAgentConfig,\n} from \"../types\";\nimport { verbose } from \"../utils/logger\";\nimport { typedEntries, typedFromEntries, typedKeys } from \"../utils/typed-object\";\nimport { resolveAgentConfigToSkills } from \"./stacks/stacks-loader\";\n\nexport function resolveSkillReference(\n ref: SkillReference,\n skills: SkillDefinitionMap,\n): Skill | null {\n const definition = skills[ref.id];\n if (!definition) {\n verbose(`Skill '${ref.id}' not found in available skills, skipping`);\n return null;\n }\n return {\n ...definition,\n usage: ref.usage,\n preloaded: ref.preloaded ?? false,\n ...(ref.source !== undefined && { source: ref.source }),\n };\n}\n\nexport function resolveSkillReferences(\n skillRefs: SkillReference[],\n skills: SkillDefinitionMap,\n): Skill[] {\n return skillRefs\n .map((ref) => resolveSkillReference(ref, skills))\n .filter((skill): skill is Skill => skill !== null);\n}\n\n/**\n * Builds skill references from a ProjectConfig stack mapping (agent -> category -> SkillAssignment[]).\n *\n * Values are normalized to SkillAssignment[] at load time (by normalizeStackRecord in project-config.ts).\n * Preserves preloaded flags from skill assignments.\n *\n * @param agentStack - Category-to-SkillAssignment[] mapping from ProjectConfig.stack for one agent\n * @returns Skill references with usage hints derived from category names\n */\nexport function buildSkillRefsFromConfig(agentStack: StackAgentConfig): SkillReference[] {\n return resolveAgentConfigToSkills(agentStack);\n}\n\n/**\n * Resolves the skill references an agent compiles with.\n *\n * The compile config is the only source: `buildCompileAgents` has already expanded\n * the project config's stack into `skills` by the time this runs.\n *\n * @param agentConfig - Compile-time agent config\n * @returns The agent's explicit skill references, or an empty array when it names none\n */\nexport function resolveAgentSkillRefs(agentConfig: CompileAgentConfig): SkillReference[] {\n return agentConfig.skills ?? [];\n}\n\n/**\n * Resolves all agents referenced in a compile config into fully populated AgentConfigs\n * with their skill lists materialized from definitions.\n *\n * For each agent in `compileConfig.agents`, this function:\n * 1. Validates the agent exists in the scanned agent definitions\n * 2. Resolves skill references from the agent's compile config\n * 3. Materializes skill references into full Skill objects using the skill definitions map\n * 4. Merges the agent definition with its resolved skills into an AgentConfig\n *\n * @param agents - Available agent definitions keyed by name (from scanning agent directories)\n * @param skills - Available skill definitions keyed by ID (from scanning skill directories)\n * @param compileConfig - Compilation config specifying which agents to compile and their overrides\n * @param _projectRoot - Project root directory (currently unused, reserved for future use)\n * @returns Map of agent names to fully resolved AgentConfig objects ready for compilation\n * @throws When an agent referenced in compileConfig is not found in scanned agents\n */\n// Nothing below is asynchronous any more: `resolveAgentSkillRefs` never was, and\n// dropping its `async` emptied this one too. The `Promise` stays because it is the\n// published shape — two production callers await it and local-installer.test.ts\n// doubles it with `mockResolvedValue`, so unwinding it is a change to the compile\n// pipeline rather than to this line.\n// eslint-disable-next-line @typescript-eslint/require-await -- published shape, see above\nexport async function resolveAgents(\n agents: Partial<Record<AgentName, AgentDefinition>>,\n skills: SkillDefinitionMap,\n compileConfig: CompileConfig,\n _projectRoot: string,\n): Promise<Partial<Record<AgentName, AgentConfig>>> {\n const entries = typedEntries<AgentName, CompileAgentConfig>(compileConfig.agents).map(\n ([agentName, agentConfig]) => {\n const definition = agents[agentName];\n if (!definition) {\n const availableAgents = typedKeys<AgentName>(agents);\n const agentList =\n availableAgents.length > 0\n ? `Available agents: ${availableAgents.slice(0, 5).join(\", \")}${availableAgents.length > 5 ? ` (and ${availableAgents.length - 5} more)` : \"\"}`\n : \"No agents found in scanned directories\";\n throw new Error(\n `Agent '${agentName}' referenced in compile config but not found in scanned agents. ${agentList}. Check that src/agents/${agentName}/metadata.yaml exists.`,\n );\n }\n\n const skillRefs = resolveAgentSkillRefs(agentConfig);\n const resolvedSkills = resolveSkillReferences(skillRefs, skills);\n\n // The project config carries the user's deliberate choice; the agent's own metadata\n // carries the default. Config wins, silently — warning on every compile for a setting\n // someone made on purpose is noise. Neither present leaves the key off entirely.\n const model = agentConfig.model ?? definition.model;\n const effort = agentConfig.effort ?? definition.effort;\n\n return [\n agentName,\n {\n name: agentName,\n title: definition.title,\n description: definition.description,\n ...(model !== undefined && { model }),\n ...(effort !== undefined && { effort }),\n tools: definition.tools,\n skills: resolvedSkills,\n ...(definition.path !== undefined && { path: definition.path }),\n ...(definition.sourceRoot !== undefined && { sourceRoot: definition.sourceRoot }),\n ...(definition.agentBaseDir !== undefined && { agentBaseDir: definition.agentBaseDir }),\n },\n ] as const;\n },\n );\n\n return typedFromEntries(entries);\n}\n","import { spawn } from \"child_process\";\nimport { z } from \"zod\";\nimport os from \"os\";\nimport type { ClaudePluginScope } from \"../types/config\";\nimport { getErrorMessage } from \"./errors\";\nimport { warn } from \"./logger\";\n\n// Argument length limits to prevent oversized CLI arguments\nconst MAX_PLUGIN_PATH_LENGTH = 1024;\nconst MAX_PLUGIN_NAME_LENGTH = 256;\nconst MAX_MARKETPLACE_SOURCE_LENGTH = 1024;\n\n// Marketplace/plugin names: alphanumeric, dashes, underscores, dots, @\nconst SAFE_NAME_PATTERN = /^[a-zA-Z0-9._@/-]+$/;\n\n// Plugin path/ref: alphanumeric, dashes, underscores, dots, slashes, @, colons (for marketplace refs like skill@marketplace)\nconst SAFE_PLUGIN_PATH_PATTERN = /^[a-zA-Z0-9._@/:~-]+$/;\n\n// eslint-disable-next-line no-control-regex\nconst CONTROL_CHAR_PATTERN = /[\\x00-\\x08\\x0E-\\x1F\\x7F]/u;\n\nfunction validatePluginPath(pluginPath: string): void {\n if (!pluginPath || pluginPath.trim().length === 0) {\n throw new Error(\"Plugin path must not be empty.\");\n }\n\n if (pluginPath.length > MAX_PLUGIN_PATH_LENGTH) {\n throw new Error(\n `Plugin path is too long (${pluginPath.length} characters, max ${MAX_PLUGIN_PATH_LENGTH}).`,\n );\n }\n\n if (CONTROL_CHAR_PATTERN.test(pluginPath)) {\n throw new Error(\"Plugin path contains invalid control characters.\");\n }\n\n if (!SAFE_PLUGIN_PATH_PATTERN.test(pluginPath)) {\n throw new Error(\n `Plugin path contains invalid characters: \"${pluginPath}\"\\n` +\n \"Plugin paths may only contain alphanumeric characters, dashes, underscores, dots, slashes, @, and colons.\",\n );\n }\n}\n\nfunction validateMarketplaceSource(source: string): void {\n if (!source || source.trim().length === 0) {\n throw new Error(\"Marketplace must not be empty.\");\n }\n\n if (source.length > MAX_MARKETPLACE_SOURCE_LENGTH) {\n throw new Error(\n `Marketplace is too long (${source.length} characters, max ${MAX_MARKETPLACE_SOURCE_LENGTH}).`,\n );\n }\n\n if (CONTROL_CHAR_PATTERN.test(source)) {\n throw new Error(\"Marketplace contains invalid control characters.\");\n }\n\n if (!SAFE_PLUGIN_PATH_PATTERN.test(source)) {\n throw new Error(\n `Marketplace contains invalid characters: \"${source}\"\\n` +\n \"Marketplaces may only contain alphanumeric characters, dashes, underscores, dots, slashes, @, and colons.\",\n );\n }\n}\n\nfunction validatePluginName(pluginName: string): void {\n if (!pluginName || pluginName.trim().length === 0) {\n throw new Error(\"Plugin name must not be empty.\");\n }\n\n if (pluginName.length > MAX_PLUGIN_NAME_LENGTH) {\n throw new Error(\n `Plugin name is too long (${pluginName.length} characters, max ${MAX_PLUGIN_NAME_LENGTH}).`,\n );\n }\n\n if (CONTROL_CHAR_PATTERN.test(pluginName)) {\n throw new Error(\"Plugin name contains invalid control characters.\");\n }\n\n if (!SAFE_NAME_PATTERN.test(pluginName)) {\n throw new Error(\n `Plugin name contains invalid characters: \"${pluginName}\"\\n` +\n \"Names may only contain alphanumeric characters, dashes, underscores, dots, @, and slashes.\",\n );\n }\n}\n\nexport type ExecResult = {\n stdout: string;\n stderr: string;\n exitCode: number;\n};\n\nexport async function execCommand(\n command: string,\n args: string[],\n options?: { cwd?: string; env?: NodeJS.ProcessEnv },\n): Promise<ExecResult> {\n return new Promise((resolve, reject) => {\n const proc = spawn(command, args, {\n cwd: options?.cwd,\n env: { ...process.env, ...options?.env },\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n proc.stdout.on(\"data\", (data: Buffer) => {\n stdout += data.toString();\n });\n\n proc.stderr.on(\"data\", (data: Buffer) => {\n stderr += data.toString();\n });\n\n proc.on(\"close\", (code) => {\n resolve({\n stdout,\n stderr,\n exitCode: code ?? 1,\n });\n });\n\n proc.on(\"error\", (err) => {\n reject(err);\n });\n });\n}\n\n/** User-scoped plugins run from home dir so Claude CLI only writes to ~/.claude/settings.json */\nfunction resolvePluginCwd(scope: ClaudePluginScope, projectDir: string): string {\n return scope === \"user\" ? os.homedir() : projectDir;\n}\n\n/**\n * Which Claude installation a `claude plugin` call reads and writes.\n *\n * Omitted, the call inherits the one its process already points at — the user's\n * own, in production. `configDir` redirects the entire config tree: the\n * marketplace registry, the installed-plugin registry and user settings all move\n * with it. It is how a test drives the Claude CLI without touching the machine\n * running it.\n */\nexport type ClaudeConfigOptions = { configDir?: string };\n\n/**\n * The `execCommand` options fragment that pins the config dir — empty when there\n * is none, so the call inherits its process's environment untouched.\n *\n * `CLAUDE_CONFIG_DIR` takes precedence over `HOME` in the Claude CLI, so passing\n * it also overrides an exported one rather than merely competing with it.\n */\nfunction configDirEnv(options: ClaudeConfigOptions | undefined): { env?: NodeJS.ProcessEnv } {\n if (options?.configDir === undefined) return {};\n return { env: { CLAUDE_CONFIG_DIR: options.configDir } };\n}\n\nexport async function claudePluginInstall(\n pluginPath: string,\n scope: ClaudePluginScope,\n projectDir: string,\n options?: ClaudeConfigOptions,\n): Promise<void> {\n validatePluginPath(pluginPath);\n\n const cwd = resolvePluginCwd(scope, projectDir);\n const args = [\"plugin\", \"install\", pluginPath, \"--scope\", scope];\n const result = await execCommand(\"claude\", args, { cwd, ...configDirEnv(options) });\n\n if (result.exitCode !== 0) {\n const errorMessage = result.stderr || result.stdout || \"Unknown error\";\n throw new Error(`Plugin installation failed: ${errorMessage.trim()}`);\n }\n}\n\nexport async function isClaudeCLIAvailable(): Promise<boolean> {\n try {\n const result = await execCommand(\"claude\", [\"--version\"], {});\n return result.exitCode === 0;\n } catch {\n return false;\n }\n}\n\nexport type MarketplaceInfo = {\n name: string;\n source: string;\n repo?: string;\n path?: string;\n};\n\nconst marketplaceInfoListSchema: z.ZodType<MarketplaceInfo[]> = z.array(\n z.object({\n name: z.string(),\n source: z.string(),\n repo: z.string().exactOptional(),\n path: z.string().exactOptional(),\n }),\n);\n\nexport async function claudePluginMarketplaceList(\n options?: ClaudeConfigOptions,\n): Promise<MarketplaceInfo[]> {\n try {\n const result = await execCommand(\n \"claude\",\n [\"plugin\", \"marketplace\", \"list\", \"--json\"],\n configDirEnv(options),\n );\n\n if (result.exitCode !== 0) {\n return [];\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(result.stdout);\n } catch {\n warn(\"Failed to parse marketplace list output as JSON\");\n return [];\n }\n\n const listResult = marketplaceInfoListSchema.safeParse(parsed);\n if (!listResult.success) {\n warn(\"Unexpected marketplace list format — expected an array of marketplace entries\");\n return [];\n }\n\n return listResult.data;\n } catch {\n return [];\n }\n}\n\nexport async function claudePluginMarketplaceExists(\n name: string,\n options?: ClaudeConfigOptions,\n): Promise<boolean> {\n const marketplaces = await claudePluginMarketplaceList(options);\n return marketplaces.some((m) => m.name === name);\n}\n\nexport async function claudePluginMarketplaceAdd(\n source: string,\n options?: ClaudeConfigOptions,\n): Promise<void> {\n validateMarketplaceSource(source);\n\n const args = [\"plugin\", \"marketplace\", \"add\", source];\n let result;\n try {\n result = await execCommand(\"claude\", args, configDirEnv(options));\n } catch (err) {\n throw new Error(`Failed to add marketplace: ${getErrorMessage(err)}`, { cause: err });\n }\n\n if (result.exitCode !== 0) {\n const errorMessage = result.stderr || result.stdout || \"Unknown error\";\n if (errorMessage.includes(\"already installed\")) {\n return;\n }\n throw new Error(`Failed to add marketplace: ${errorMessage.trim()}`);\n }\n}\n\nexport async function claudePluginMarketplaceRemove(\n name: string,\n options?: ClaudeConfigOptions,\n): Promise<void> {\n validatePluginName(name);\n\n const args = [\"plugin\", \"marketplace\", \"remove\", name];\n let result;\n try {\n result = await execCommand(\"claude\", args, configDirEnv(options));\n } catch (err) {\n throw new Error(`Failed to remove marketplace: ${getErrorMessage(err)}`, { cause: err });\n }\n\n if (result.exitCode !== 0) {\n const errorMessage = result.stderr || result.stdout || \"Unknown error\";\n if (errorMessage.includes(\"not found\") || errorMessage.includes(\"not installed\")) {\n return;\n }\n throw new Error(`Failed to remove marketplace: ${errorMessage.trim()}`);\n }\n}\n\nexport async function claudePluginMarketplaceUpdate(\n name: string,\n options?: ClaudeConfigOptions,\n): Promise<void> {\n validatePluginName(name);\n\n const args = [\"plugin\", \"marketplace\", \"update\", name];\n let result;\n try {\n result = await execCommand(\"claude\", args, configDirEnv(options));\n } catch (err) {\n throw new Error(`Failed to update marketplace: ${getErrorMessage(err)}`, { cause: err });\n }\n\n if (result.exitCode !== 0) {\n const errorMessage = result.stderr || result.stdout || \"Unknown error\";\n throw new Error(`Failed to update marketplace: ${errorMessage.trim()}`);\n }\n}\n\nexport async function claudePluginUninstall(\n pluginName: string,\n scope: ClaudePluginScope,\n projectDir: string,\n options?: ClaudeConfigOptions,\n): Promise<void> {\n validatePluginName(pluginName);\n\n const cwd = resolvePluginCwd(scope, projectDir);\n const args = [\"plugin\", \"uninstall\", pluginName, \"--scope\", scope];\n const result = await execCommand(\"claude\", args, { cwd, ...configDirEnv(options) });\n\n if (result.exitCode !== 0) {\n const errorMessage = result.stderr || result.stdout || \"Unknown error\";\n // Ignore \"not installed\" errors - plugin may already be removed\n if (errorMessage.includes(\"not installed\") || errorMessage.includes(\"not found\")) {\n return;\n }\n throw new Error(`Plugin uninstall failed: ${errorMessage.trim()}`);\n }\n}\n\n/**\n * Best-effort plugin uninstall that tries both scopes.\n *\n * Use when the plugin's actual registered scope is ambiguous — e.g., a skill\n * was re-scoped after install, or we're cleaning up on uninstall and the config\n * scope may not match the registry entry. Tries the primary scope first, then\n * the fallback, silently swallowing errors from each attempt.\n *\n * The plugin reference must be qualified (e.g., `skill-id@marketplace`), matching\n * the form used at install time — bare skill IDs will not match the registry.\n */\nexport async function claudePluginUninstallBestEffort(\n pluginRef: string,\n primaryScope: ClaudePluginScope,\n projectDir: string,\n options?: ClaudeConfigOptions,\n): Promise<void> {\n const fallbackScope = primaryScope === \"project\" ? \"user\" : \"project\";\n try {\n await claudePluginUninstall(pluginRef, primaryScope, projectDir, options);\n } catch {\n // Best-effort: plugin may not be registered with primary scope\n }\n try {\n await claudePluginUninstall(pluginRef, fallbackScope, projectDir, options);\n } catch {\n // Best-effort: plugin may not be registered with fallback scope either\n }\n}\n","import type { SkillId } from \"../../types\";\nimport type { SkillConfig, SkillScope } from \"../../types/config\";\nimport type { SourceLoadResult } from \"../loading\";\n// Type-only, so no module edge is created: the operations layer imports back into\n// this one, and the shape a plugin install reports is defined where installs live.\nimport type { PluginInstallResult } from \"../operations/skills/install-plugin-skills\";\nimport { deleteLocalSkill, copySkillsToLocalFlattened } from \"../skills\";\nimport { claudePluginInstall, claudePluginUninstall } from \"../../utils/exec\";\nimport { buildMarketplacePluginRef, toClaudePluginScope } from \"../plugins/plugin-ref\";\nimport { installBaseDir, resolveInstallPaths } from \"./install-base-dir\";\nimport { verbose } from \"../../utils/logger\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { CLI_INVOKE_COMMAND, EJECT_SOURCE } from \"../../consts\";\n\nexport type SkillMigration = {\n id: SkillId;\n oldSource: string;\n newSource: string;\n oldScope: SkillScope;\n newScope: SkillScope;\n};\n\nexport type MigrationPlan = {\n toEject: SkillMigration[];\n toPlugin: SkillMigration[];\n scopeChanges: SkillMigration[];\n};\n\n/**\n * What the plugin→eject half copied, in the shape {@link PluginInstallResult} reports the\n * opposite direction, so one command surface reports both and neither can drift into a\n * private idea of what a failure looks like.\n *\n * A non-empty `failed` means this run could NOT honor the user's eject intent for those\n * skills, so the caller MUST hard-error before writing any config — otherwise config.ts\n * records `origin: \"eject\"` for a skill that has no local copy. The asymmetry this\n * replaces is what let that ship: the plugin half returned its failures structurally\n * while the eject half turned them into a warning string nobody could act on.\n */\nexport type EjectCopyResult = {\n copied: SkillId[];\n failed: Array<{ id: SkillId; error: string }>;\n};\n\nexport type MigrationResult = {\n ejectCopies: EjectCopyResult;\n /**\n * What the eject→plugin half installed, in the shape a fresh install returns, so\n * one command surface reports both. The refs are built here because this is where\n * each migration's own scope and marketplace are already resolved.\n *\n * A non-empty `failed` means this run could NOT honor the user's plugin intent for\n * those skills, so the caller MUST hard-error before writing any config — otherwise\n * config.ts records a marketplace `origin` for a skill that has no plugin\n * registration.\n */\n pluginInstalls: PluginInstallResult;\n warnings: string[];\n};\n\n/**\n * Hard-error message for failed eject copies — the twin of `pluginInstallFailureError` in\n * `operations/skills/install-plugin-skills.ts`, worded from the same rule: an install intent\n * this run could not honor must stop the run BEFORE any config records it.\n */\nexport function ejectCopyFailureError(failedCount: number): string {\n return `Failed to copy ${failedCount} skill(s) for eject. Eject intent could not be honored. Check that the destination skills directory is writable, then run '${CLI_INVOKE_COMMAND} edit' again — or switch the affected skills back to plugin mode.`;\n}\n\n/**\n * Detect which skills changed source or scope between old and new configs\n * by comparing SkillConfig[] entries by ID.\n */\nexport function detectMigrations(\n oldSkills: SkillConfig[],\n newSkills: SkillConfig[],\n): MigrationPlan {\n const toEject: SkillMigration[] = [];\n const toPlugin: SkillMigration[] = [];\n const scopeChanges: SkillMigration[] = [];\n\n const oldById = new Map(oldSkills.map((s) => [s.id, s]));\n\n for (const newSkill of newSkills) {\n const oldSkill = oldById.get(newSkill.id);\n if (!oldSkill) continue;\n\n const migration: SkillMigration = {\n id: newSkill.id,\n oldSource: oldSkill.origin,\n newSource: newSkill.origin,\n oldScope: oldSkill.scope,\n newScope: newSkill.scope,\n };\n\n const wasEject = oldSkill.origin === EJECT_SOURCE;\n const isEject = newSkill.origin === EJECT_SOURCE;\n\n if (wasEject && !isEject) {\n toPlugin.push(migration);\n } else if (!wasEject && isEject) {\n toEject.push(migration);\n }\n\n // Detect scope changes (independent of source changes)\n if (oldSkill.scope !== newSkill.scope && wasEject === isEject) {\n scopeChanges.push(migration);\n }\n }\n\n return { toEject, toPlugin, scopeChanges };\n}\n\n/**\n * Execute per-skill migration: delete locals that switch to plugin,\n * copy to local for skills that switch from plugin.\n * Uses per-skill scope from the migration plan.\n */\nexport async function executeMigration(\n plan: MigrationPlan,\n projectDir: string,\n sourceResult: SourceLoadResult,\n): Promise<MigrationResult> {\n const pluginInstalls: PluginInstallResult = { installed: [], failed: [] };\n\n const ejectCopies = await copyMigratedSkillsToLocal(plan.toEject, projectDir, sourceResult);\n // Only the skills whose copy LANDED, which is the toPlugin rule below read the other way\n // round. Dropping the plugin registration of a skill that has no local copy would leave it\n // installed nowhere, so a working install must survive a failed migration exactly as the\n // ejected working copy survives a failed plugin install.\n const warnings = await uninstallMigratedPlugins(\n migrationsWhoseCopyLanded(plan.toEject, ejectCopies),\n projectDir,\n sourceResult,\n );\n\n // Migrate skills from eject to plugin\n if (plan.toPlugin.length > 0) {\n // Plugin install intent is inviolable: without a marketplace NO migration in\n // this list can be installed, so fail before anything is deleted. Deleting\n // first and downgrading to a warning destroys the user's editable working\n // copy and leaves config entries claiming a plugin that was never installed.\n if (!sourceResult.marketplace) {\n throw new Error(\n `Cannot install skills as plugins: marketplace could not be resolved from ` +\n `'${sourceResult.sourceConfig.source}'. Plugin install mode requires a marketplace — ` +\n `fix the marketplace or switch the affected skills to eject mode.`,\n );\n }\n\n // The same rule applies per skill: install FIRST and delete the ejected working\n // copy only once THAT skill's plugin is registered. A failed install then leaves\n // the skill exactly as it was, and the caller hard-errors on\n // `pluginInstalls.failed` before any config claims the plugin source.\n for (const migration of plan.toPlugin) {\n const pluginScope = toClaudePluginScope(migration.newScope);\n const pluginRef = buildMarketplacePluginRef(migration.id, sourceResult.marketplace);\n try {\n await claudePluginInstall(pluginRef, pluginScope, projectDir);\n } catch (error) {\n pluginInstalls.failed.push({ id: migration.id, error: getErrorMessage(error) });\n continue;\n }\n pluginInstalls.installed.push({ id: migration.id, ref: pluginRef });\n verbose(`Installed plugin for ${migration.id}`);\n await deleteEjectedWorkingCopy(migration, projectDir);\n }\n }\n\n return { ejectCopies, pluginInstalls, warnings };\n}\n\n/**\n * Writes the local copy each newly-ejected skill becomes, and names every one it could not\n * write.\n *\n * The mirror of the toPlugin loop in {@link executeMigration}, and per-skill for the same\n * reasons. Each migration resolves its OWN destination from its own scope, so the two scopes\n * are independent by construction rather than by pass ordering — a refused write under $HOME\n * says nothing about the project tree, and one batched `try` around both once let a single\n * project-scope failure cancel every global copy behind one warning line.\n *\n * Failures are COLLECTED rather than aborted on. The caller hard-errors on any of them before\n * writing config, so stopping at the first buys no safety and costs the user the rest of the\n * list — they would learn about the second unwritable destination only by fixing the first and\n * running again. That is the reasoning `copyEachSkill` already gives for reporting its own\n * failures by id rather than throwing on the first.\n */\nasync function copyMigratedSkillsToLocal(\n migrations: SkillMigration[],\n projectDir: string,\n sourceResult: SourceLoadResult,\n): Promise<EjectCopyResult> {\n const copies: EjectCopyResult = { copied: [], failed: [] };\n\n for (const migration of migrations) {\n const { skillsDir } = resolveInstallPaths(projectDir, migration.newScope);\n try {\n const copied = await copySkillsToLocalFlattened([migration.id], skillsDir, sourceResult);\n copies.copied.push(...copied.map((skill) => skill.skillId));\n } catch (error) {\n copies.failed.push({ id: migration.id, error: getErrorMessage(error) });\n }\n }\n\n return copies;\n}\n\n/** The migrations that now have a local copy on disk, and so no longer need their plugin. */\nfunction migrationsWhoseCopyLanded(\n migrations: SkillMigration[],\n copies: EjectCopyResult,\n): SkillMigration[] {\n const landed = new Set(copies.copied);\n return migrations.filter((migration) => landed.has(migration.id));\n}\n\n/**\n * True when a migration must LEAVE the plugin registered: a skill moving from the global\n * install to a project-local copy keeps the global plugin for every other project, and this\n * project's config tombstone (`excluded: true`) is what keeps this project off it.\n */\nfunction keepsGlobalPluginRegistration(migration: SkillMigration): boolean {\n return migration.oldScope === \"global\" && migration.newScope === \"project\";\n}\n\n/**\n * Drops the plugin registration each newly-ejected skill no longer needs, and names every one\n * it could not drop.\n *\n * Diagnostic-only: the local copy IS the install now, so a stale registration is untidy rather\n * than wrong and must not fail the migration. What it must not do is borrow the copy pass's\n * words — this loop lived inside the copy's `try`, so a `claude plugin uninstall` that threw\n * was reported to the user as `Could not copy skills for eject`, naming work that had in fact\n * succeeded one line above the count proving it.\n */\nasync function uninstallMigratedPlugins(\n migrations: SkillMigration[],\n projectDir: string,\n sourceResult: SourceLoadResult,\n): Promise<string[]> {\n const warnings: string[] = [];\n\n for (const migration of migrations) {\n if (keepsGlobalPluginRegistration(migration)) {\n verbose(`Keeping global plugin for ${migration.id} (migrated to project-eject)`);\n continue;\n }\n if (!sourceResult.marketplace) {\n warnings.push(`Could not uninstall plugin for ${migration.id}: no marketplace configured`);\n continue;\n }\n\n // Scope-precise uninstall keyed to this migration's own scope. A best-effort\n // both-scopes sweep would also drop a same-id plugin registered at the OTHER Claude\n // scope (e.g. a project→eject switch uninstalling the still-needed global/user-scope\n // plugin). The registered scope is unambiguous here, so target it exactly.\n // claudePluginUninstall still swallows \"not installed\" / \"not found\".\n const pluginScope = toClaudePluginScope(migration.oldScope);\n const pluginRef = buildMarketplacePluginRef(migration.id, sourceResult.marketplace);\n try {\n await claudePluginUninstall(pluginRef, pluginScope, projectDir);\n } catch (error) {\n warnings.push(`Could not uninstall plugin for ${migration.id}: ${getErrorMessage(error)}`);\n continue;\n }\n verbose(`Uninstalled plugin for ${migration.id}`);\n }\n\n return warnings;\n}\n\n/**\n * Removes the local copy a now-pluginized skill no longer needs, from the scope it was\n * ejected at. A global copy is kept when the skill moves to project scope — the global\n * copy must remain for other projects.\n */\nasync function deleteEjectedWorkingCopy(\n migration: SkillMigration,\n projectDir: string,\n): Promise<void> {\n if (migration.oldScope === \"global\" && migration.newScope === \"project\") {\n verbose(`Keeping global local skill for ${migration.id} (migrated to project-plugin)`);\n return;\n }\n await deleteLocalSkill(installBaseDir(projectDir, migration.oldScope), migration.id);\n}\n","import { isRecord } from \"../../utils/type-guards.js\";\nimport path from \"path\";\nimport fg from \"fast-glob\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport {\n fileExists,\n readFile,\n readFileSafe,\n directoryExists,\n listDirectories,\n} from \"../../utils/fs\";\nimport type { ValidationResult } from \"../../types\";\nimport { validResult, invalidResult, mergeValidationResults } from \"../validation-result\";\nimport { extractFrontmatter } from \"../../utils/frontmatter\";\nimport { log } from \"../../utils/logger\";\nimport { formatZodErrors } from \"../schema-validator\";\nimport {\n pluginManifestValidationSchema,\n skillFrontmatterValidationSchema,\n agentFrontmatterValidationSchema,\n} from \"../schemas\";\nimport {\n KEBAB_CASE_PATTERN,\n MAX_PLUGIN_FILE_SIZE,\n PLUGIN_MANIFEST_DIR,\n STANDARD_FILES,\n} from \"../../consts\";\nimport { getPluginManifestPath } from \"./plugin-finder\";\n\nconst PLUGIN_DIR = PLUGIN_MANIFEST_DIR;\nconst PLUGIN_MANIFEST = STANDARD_FILES.PLUGIN_JSON;\nconst SEMVER_REGEX =\n /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$/;\n\nfunction isKebabCase(str: string): boolean {\n return KEBAB_CASE_PATTERN.test(str);\n}\n\nfunction isValidSemver(str: string): boolean {\n return SEMVER_REGEX.test(str);\n}\n\n/**\n * Validates the directory structure of a plugin.\n *\n * Checks for the required `.claude-plugin/` directory and `plugin.json` manifest file.\n * Warns if README.md is missing (recommended but not required).\n *\n * @param pluginPath - Absolute path to the plugin root directory\n * @returns Validation result with errors for missing required structure\n */\nexport async function validatePluginStructure(pluginPath: string): Promise<ValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!(await directoryExists(pluginPath))) {\n return invalidResult(`Plugin directory does not exist: ${pluginPath}`);\n }\n\n const pluginDir = path.join(pluginPath, PLUGIN_DIR);\n if (!(await directoryExists(pluginDir))) {\n errors.push(`Missing ${PLUGIN_DIR}/ directory`);\n }\n\n const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST);\n if (!(await fileExists(manifestPath))) {\n errors.push(`Missing ${PLUGIN_DIR}/${PLUGIN_MANIFEST}`);\n }\n\n const readmePath = path.join(pluginPath, STANDARD_FILES.README_MD);\n if (!(await fileExists(readmePath))) {\n warnings.push(\"Missing README.md (recommended for documentation)\");\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Validates a plugin manifest file (plugin.json) for correctness and completeness.\n *\n * Performs the following validation checks:\n * 1. File existence and readability\n * 2. Valid JSON syntax (with file size limit via readFileSafe)\n * 3. Zod schema validation (strict mode rejects unrecognized keys)\n * 4. Plugin name is kebab-case\n * 5. Version string is valid semver\n * 6. Description field is present (warning if missing)\n * 7. Skills directory path exists on disk (if specified as string)\n * 8. Agents directory path exists on disk (if specified as string)\n *\n * @param manifestPath - Absolute path to the plugin.json file\n * @returns Validation result with errors for invalid/missing data and warnings for recommendations\n */\nexport async function validatePluginManifest(manifestPath: string): Promise<ValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!(await fileExists(manifestPath))) {\n return invalidResult(`Manifest file not found: ${manifestPath}`);\n }\n\n // `JSON.parse` returns `any`, and every field read below trusts what it\n // returns. Landing it in `unknown` and narrowing with `isRecord` first is what\n // makes `manifest.name` a checked read of a record rather than a property\n // fetched off `any` — and it names the array/string/null cases the schema\n // would otherwise report as a shape mismatch several lines later.\n let manifest: Record<string, unknown>;\n try {\n const content = await readFileSafe(manifestPath, MAX_PLUGIN_FILE_SIZE);\n const parsed: unknown = JSON.parse(content);\n if (!isRecord(parsed)) return invalidResult(`${PLUGIN_MANIFEST} must contain a JSON object`);\n manifest = parsed;\n } catch (err) {\n return invalidResult(`Invalid JSON in ${PLUGIN_MANIFEST}: ${getErrorMessage(err)}`);\n }\n\n const result = pluginManifestValidationSchema.safeParse(manifest);\n\n if (!result.success) {\n errors.push(...formatZodErrors(result.error));\n }\n\n if (manifest.name && typeof manifest.name === \"string\") {\n if (!isKebabCase(manifest.name)) {\n errors.push(`name must be kebab-case: \"${manifest.name}\"`);\n }\n }\n\n if (manifest.version && typeof manifest.version === \"string\") {\n if (!isValidSemver(manifest.version)) {\n errors.push(\n `version \"${manifest.version}\" is not valid semver (expected: major.minor.patch)`,\n );\n }\n }\n\n if (!manifest.description) {\n warnings.push(\"Missing description field (recommended for discoverability)\");\n }\n\n const pluginDir = path.dirname(path.dirname(manifestPath));\n\n if (manifest.skills && typeof manifest.skills === \"string\") {\n const skillsPath = path.join(pluginDir, manifest.skills);\n if (!(await directoryExists(skillsPath))) {\n errors.push(`Skills path does not exist: ${manifest.skills}`);\n }\n }\n\n if (manifest.agents && typeof manifest.agents === \"string\") {\n const agentsPath = path.join(pluginDir, manifest.agents);\n if (!(await directoryExists(agentsPath))) {\n errors.push(`Agents path does not exist: ${manifest.agents}`);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nexport async function validateSkillFrontmatter(skillPath: string): Promise<ValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!(await fileExists(skillPath))) {\n return invalidResult(`Skill file not found: ${skillPath}`);\n }\n\n const content = await readFile(skillPath);\n const frontmatter = extractFrontmatter(content);\n\n if (frontmatter === null) {\n return invalidResult(\"Missing or invalid YAML frontmatter\");\n }\n\n const result = skillFrontmatterValidationSchema.safeParse(frontmatter);\n\n if (!result.success) {\n errors.push(...formatZodErrors(result.error));\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nexport async function validateAgentFrontmatter(agentPath: string): Promise<ValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!(await fileExists(agentPath))) {\n return invalidResult(`Agent file not found: ${agentPath}`);\n }\n\n const content = await readFile(agentPath);\n const frontmatter = extractFrontmatter(content);\n\n if (frontmatter === null) {\n return invalidResult(\"Missing or invalid YAML frontmatter\");\n }\n\n const result = agentFrontmatterValidationSchema.safeParse(frontmatter);\n\n if (!result.success) {\n errors.push(...formatZodErrors(result.error));\n }\n\n // Boundary cast: YAML frontmatter parsed as unknown, narrow to record for field access\n const fm = frontmatter as Record<string, unknown>;\n\n if (fm.name && typeof fm.name === \"string\") {\n if (!isKebabCase(fm.name)) {\n errors.push(`name must be kebab-case: \"${fm.name}\"`);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nfunction prefixResult(result: ValidationResult, prefix: string): ValidationResult {\n return {\n valid: result.valid,\n errors: result.valid ? [] : result.errors.map((e) => `${prefix}: ${e}`),\n warnings: result.warnings.map((w) => `${prefix}: ${w}`),\n };\n}\n\nasync function validatePluginSkillFiles(\n pluginPath: string,\n skillsRelPath: string,\n): Promise<ValidationResult> {\n const skillsDir = path.join(pluginPath, skillsRelPath);\n if (!(await directoryExists(skillsDir))) return validResult();\n\n const files = await fg(`**/${STANDARD_FILES.SKILL_MD}`, { cwd: skillsDir, absolute: true });\n if (files.length === 0) {\n return {\n valid: true,\n errors: [],\n warnings: [`Skills directory exists but contains no SKILL.md files: ${skillsRelPath}`],\n };\n }\n\n const results = await Promise.all(\n files.map(async (f) =>\n prefixResult(await validateSkillFrontmatter(f), path.relative(pluginPath, f)),\n ),\n );\n return mergeValidationResults(results);\n}\n\nasync function validatePluginAgentFiles(\n pluginPath: string,\n agentsRelPath: string,\n): Promise<ValidationResult> {\n const agentsDir = path.join(pluginPath, agentsRelPath);\n if (!(await directoryExists(agentsDir))) return validResult();\n\n const files = await fg(\"*.md\", { cwd: agentsDir, absolute: true });\n if (files.length === 0) {\n return {\n valid: true,\n errors: [],\n warnings: [`Agents directory exists but contains no .md files: ${agentsRelPath}`],\n };\n }\n\n const results = await Promise.all(\n files.map(async (f) =>\n prefixResult(await validateAgentFrontmatter(f), path.relative(pluginPath, f)),\n ),\n );\n return mergeValidationResults(results);\n}\n\nasync function loadManifestForValidation(\n manifestPath: string,\n): Promise<Record<string, unknown> | null> {\n try {\n const content = await readFileSafe(manifestPath, MAX_PLUGIN_FILE_SIZE);\n const parsed: unknown = JSON.parse(content);\n return isRecord(parsed) ? parsed : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Runs comprehensive validation on a plugin: structure, manifest, skill files, and agent files.\n *\n * Short-circuits on structure validation failure (no point checking manifest if\n * the directory structure is wrong). For valid structures, validates the manifest\n * and then checks all SKILL.md and agent .md files for valid frontmatter.\n *\n * @param pluginPath - Absolute path to the plugin root directory\n * @returns Merged validation result from all validation passes\n */\nexport async function validatePlugin(pluginPath: string): Promise<ValidationResult> {\n const structureResult = await validatePluginStructure(pluginPath);\n if (!structureResult.valid) return structureResult;\n\n const manifestPath = getPluginManifestPath(pluginPath);\n const manifestResult = await validatePluginManifest(manifestPath);\n const manifest = await loadManifestForValidation(manifestPath);\n\n const skillsResult =\n manifest?.skills && typeof manifest.skills === \"string\"\n ? await validatePluginSkillFiles(pluginPath, manifest.skills)\n : validResult();\n\n const agentsResult =\n manifest?.agents && typeof manifest.agents === \"string\"\n ? await validatePluginAgentFiles(pluginPath, manifest.agents)\n : validResult();\n\n return mergeValidationResults([structureResult, manifestResult, skillsResult, agentsResult]);\n}\n\n/**\n * Validates all plugins found in a directory, returning individual results and an aggregate summary.\n *\n * Scans subdirectories for `.claude-plugin/` markers to identify plugins, then validates\n * each one. Returns early with an error if the directory doesn't exist or contains no plugins.\n *\n * @param pluginsDir - Absolute path to the directory containing plugin subdirectories\n * @returns Object with overall validity, per-plugin results, and counts summary\n */\nexport async function validateAllPlugins(pluginsDir: string): Promise<{\n valid: boolean;\n results: Array<{ name: string; result: ValidationResult }>;\n summary: {\n total: number;\n valid: number;\n invalid: number;\n withWarnings: number;\n };\n}> {\n const results: Array<{ name: string; result: ValidationResult }> = [];\n\n if (!(await directoryExists(pluginsDir))) {\n return {\n valid: false,\n results: [\n {\n name: pluginsDir,\n result: invalidResult(`Directory does not exist: ${pluginsDir}`),\n },\n ],\n summary: { total: 0, valid: 0, invalid: 1, withWarnings: 0 },\n };\n }\n\n const allDirs = await listDirectories(pluginsDir);\n const dirChecks = await Promise.all(\n allDirs.map(async (dirName) => ({\n dirName,\n isPlugin: await directoryExists(path.join(pluginsDir, dirName, PLUGIN_DIR)),\n })),\n );\n const pluginDirs = dirChecks.filter((c) => c.isPlugin).map((c) => c.dirName);\n\n if (pluginDirs.length === 0) {\n return {\n valid: false,\n results: [\n {\n name: pluginsDir,\n result: invalidResult(\n `No plugins found in directory: ${pluginsDir}. Plugins must contain a ${PLUGIN_DIR}/ directory.`,\n ),\n },\n ],\n summary: { total: 0, valid: 0, invalid: 1, withWarnings: 0 },\n };\n }\n\n for (const pluginName of pluginDirs) {\n const pluginPath = path.join(pluginsDir, pluginName);\n const result = await validatePlugin(pluginPath);\n results.push({ name: pluginName, result });\n }\n\n const validCount = results.filter((r) => r.result.valid).length;\n const summary = {\n total: results.length,\n valid: validCount,\n invalid: results.length - validCount,\n withWarnings: results.filter((r) => r.result.warnings.length > 0).length,\n };\n\n return {\n valid: summary.invalid === 0,\n results,\n summary,\n };\n}\n\nexport function printPluginValidationResult(name: string, result: ValidationResult): void {\n const status = result.valid ? \"\\u2713\" : \"\\u2717\";\n\n if (result.valid && result.warnings.length === 0) {\n return;\n }\n\n log(`\\n ${status} ${name}`);\n\n if (result.errors.length > 0) {\n log(\" Errors:\");\n result.errors.forEach((e) => log(` - ${e}`));\n }\n\n if (result.warnings.length > 0) {\n log(\" Warnings:\");\n result.warnings.forEach((w) => log(` - ${w}`));\n }\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * A passing validation result with no errors or warnings. A factory rather than a\n * shared constant so each caller owns its arrays — callers merge and prefix results,\n * and a shared instance would let one mutation leak into every other holder.\n */\nexport function validResult(): ValidationResult {\n return { valid: true, errors: [], warnings: [] };\n}\n\n/** A failing validation result carrying a single error message. */\nexport function invalidResult(message: string): ValidationResult {\n return { valid: false, errors: [message], warnings: [] };\n}\n\n/**\n * Flattens several validation partials into one result. `valid` is derived from\n * whether any errors were collected. Generic over the error/warning element type\n * so it can serve any {errors, warnings} partial, string-based ValidationResult\n * included.\n */\nexport function mergeValidationResults<E, W>(\n results: ReadonlyArray<{ errors: E[]; warnings: W[] }>,\n): { valid: boolean; errors: E[]; warnings: W[] } {\n const errors = results.flatMap((r) => r.errors);\n const warnings = results.flatMap((r) => r.warnings);\n return { valid: errors.length === 0, errors, warnings };\n}\n","import path from \"path\";\nimport { z } from \"zod\";\nimport { fileExists, readFileSafe } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { typedEntries } from \"../../utils/typed-object\";\nimport { CLAUDE_DIR, MAX_CONFIG_FILE_SIZE, STANDARD_FILES } from \"../../consts\";\nimport { formatZodErrors } from \"../schema-validator\";\nimport { getPluginManifestPath, getUserPluginsDir } from \"./plugin-finder\";\n\n/**\n * Plugin key format: \"plugin-name@marketplace\"\n * e.g., \"web-framework-react@acme-marketplace\"\n *\n * Kept as string — user-extensible identifiers (plugin names and marketplace names).\n */\nexport type PluginKey = string;\n\n/**\n * Resolved plugin with its install path\n */\nexport type ResolvedPlugin = {\n pluginKey: PluginKey;\n installPath: string;\n};\n\n// Zod schemas for JSON parse boundaries\n\nconst pluginSettingsSchema = z\n .object({\n // The one genuine optional here: a settings.json with no plugin enabled omits the\n // key entirely, and `getEnabledPluginKeys` says so in its own diagnostic rather than\n // defaulting it away. `lastUpdated` and `gitCommitSha` used to sit beside the fields\n // below on the same footing and were decoration — declared, never read, and stripped\n // by `z.object` either way.\n enabledPlugins: z.record(z.string(), z.unknown()).exactOptional(),\n })\n .passthrough();\n\n/** The fields every installation record carries, whatever scope it was registered at. */\nconst installationFields = {\n installPath: z.string(),\n version: z.string(),\n installedAt: z.string(),\n};\n\n/**\n * Discriminated on `scope` rather than carrying an optional `projectPath`, because which\n * project a record belongs to is a question only a project-scoped record has: a\n * user-scoped one has no answer, and a project-scoped one without a path is a malformed\n * record that `pickInstallation` would silently decline to match.\n */\nconst pluginInstallationSchema = z.discriminatedUnion(\"scope\", [\n z.object({ scope: z.literal(\"project\"), projectPath: z.string(), ...installationFields }),\n z.object({ scope: z.literal(\"user\"), ...installationFields }),\n z.object({ scope: z.literal(\"local\"), ...installationFields }),\n]);\n\nconst installedPluginsSchema = z\n .object({\n version: z.number(),\n plugins: z.record(z.string(), z.array(pluginInstallationSchema)),\n })\n .passthrough();\n\nconst SETTINGS_FILE = STANDARD_FILES.SETTINGS_JSON;\nconst INSTALLED_PLUGINS_FILE = \"installed_plugins.json\";\n\n/** Absolute path of the claude CLI install registry inside a plugins directory. */\nexport function getInstalledPluginsRegistryPath(pluginsDir: string): string {\n return path.join(pluginsDir, INSTALLED_PLUGINS_FILE);\n}\n\n/**\n * Lists every install recorded in a plugins directory's `installed_plugins.json`\n * (v2 registry — claude CLI >=2.1.220 installs under `cache/<marketplace>/<plugin>/<version>/`),\n * flattened to unique (pluginKey, installPath) pairs across all scopes.\n *\n * Throws when the registry is unreadable or fails schema validation — callers\n * treat the registry as the source of truth for installed plugins, so a broken\n * registry must surface as an error rather than an empty result.\n */\nexport async function listRegisteredPluginInstalls(pluginsDir: string): Promise<ResolvedPlugin[]> {\n const registryPath = getInstalledPluginsRegistryPath(pluginsDir);\n const content = await readFileSafe(registryPath, MAX_CONFIG_FILE_SIZE);\n const raw: unknown = JSON.parse(content);\n const result = installedPluginsSchema.safeParse(raw);\n\n if (!result.success) {\n throw new Error(\n `Invalid ${INSTALLED_PLUGINS_FILE}: ${formatZodErrors(result.error).join(\"; \")}`,\n );\n }\n\n return typedEntries(result.data.plugins).flatMap(([pluginKey, installations]) => {\n const uniquePaths = [...new Set(installations.map((i) => i.installPath))];\n return uniquePaths.map((installPath) => ({ pluginKey, installPath }));\n });\n}\n\n/**\n * Read enabled plugin keys from project's .claude/settings.json\n */\nexport async function getEnabledPluginKeys(projectDir: string): Promise<PluginKey[]> {\n const settingsPath = path.join(projectDir, CLAUDE_DIR, SETTINGS_FILE);\n\n if (!(await fileExists(settingsPath))) {\n verbose(`No settings.json found at '${settingsPath}'`);\n return [];\n }\n\n try {\n const content = await readFileSafe(settingsPath, MAX_CONFIG_FILE_SIZE);\n const raw: unknown = JSON.parse(content);\n const result = pluginSettingsSchema.safeParse(raw);\n\n if (!result.success) {\n verbose(`Invalid settings.json structure: ${getErrorMessage(result.error)}`);\n return [];\n }\n\n const settings = result.data;\n\n if (!settings.enabledPlugins) {\n verbose(`No enabledPlugins found in '${settingsPath}'`);\n return [];\n }\n\n const enabledKeys = typedEntries(settings.enabledPlugins)\n .filter(([, enabled]) => enabled === true)\n .map(([key]) => key);\n\n verbose(`Found ${enabledKeys.length} enabled plugins in settings.json`);\n return enabledKeys;\n } catch (error) {\n verbose(`Failed to read settings.json: ${getErrorMessage(error)}`);\n return [];\n }\n}\n\ntype RegisteredInstallation = z.infer<typeof pluginInstallationSchema>;\n\n/** This project's own project-scoped installation wins; otherwise the user-scoped one. */\nfunction pickInstallation(\n installations: RegisteredInstallation[],\n projectDir: string,\n): RegisteredInstallation | undefined {\n return (\n installations.find((i) => i.scope === \"project\" && i.projectPath === projectDir) ??\n installations.find((i) => i.scope === \"user\")\n );\n}\n\n/**\n * Resolve install paths for the given plugin keys from global registry\n */\nexport async function resolvePluginInstallPaths(\n pluginKeys: PluginKey[],\n projectDir: string,\n): Promise<ResolvedPlugin[]> {\n if (pluginKeys.length === 0) {\n return [];\n }\n\n const registryPath = getInstalledPluginsRegistryPath(getUserPluginsDir());\n\n if (!(await fileExists(registryPath))) {\n verbose(`Plugin registry not found at '${registryPath}'`);\n return [];\n }\n\n try {\n const content = await readFileSafe(registryPath, MAX_CONFIG_FILE_SIZE);\n const raw: unknown = JSON.parse(content);\n const result = installedPluginsSchema.safeParse(raw);\n\n if (!result.success) {\n verbose(`Invalid plugin registry structure: ${getErrorMessage(result.error)}`);\n return [];\n }\n\n const registry = result.data;\n\n return pluginKeys.flatMap((pluginKey) => {\n const installations = registry.plugins[pluginKey];\n if (!installations || installations.length === 0) {\n verbose(`Plugin '${pluginKey}' not found in registry`);\n return [];\n }\n\n const picked = pickInstallation(installations, projectDir);\n if (!picked) {\n verbose(`No matching installation found for '${pluginKey}'`);\n return [];\n }\n\n const scopeSuffix = picked.scope === \"user\" ? \" (user scope)\" : \"\";\n verbose(`Resolved '${pluginKey}' to '${picked.installPath}'${scopeSuffix}`);\n return [{ pluginKey, installPath: picked.installPath }];\n });\n } catch (error) {\n verbose(`Failed to read plugin registry: ${getErrorMessage(error)}`);\n return [];\n }\n}\n\n/**\n * Get verified plugin install paths for the project\n * Combines settings.json reading, registry lookup, and path verification\n */\nexport async function getVerifiedPluginInstallPaths(projectDir: string): Promise<ResolvedPlugin[]> {\n const enabledKeys = await getEnabledPluginKeys(projectDir);\n const resolvedPaths = await resolvePluginInstallPaths(enabledKeys, projectDir);\n\n // Filter out paths that don't exist on disk\n const checks = await Promise.all(\n resolvedPaths.map(async ({ pluginKey, installPath }) => {\n const pluginJsonPath = getPluginManifestPath(installPath);\n const manifestExists = await fileExists(pluginJsonPath);\n if (!manifestExists) {\n verbose(`Plugin '${pluginKey}' manifest does not exist at: '${pluginJsonPath}'`);\n }\n return { pluginKey, installPath, manifestExists };\n }),\n );\n const verified: ResolvedPlugin[] = checks\n .filter((c) => c.manifestExists)\n .map(({ pluginKey, installPath }) => ({ pluginKey, installPath }));\n\n verbose(`Verified ${verified.length} plugin install paths`);\n return verified;\n}\n","import type { SkillDefinitionMap } from \"../../types\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { verbose } from \"../../utils/logger\";\nimport { typedEntries } from \"../../utils/typed-object\";\nimport { loadPluginSkills } from \"../loading\";\nimport { getVerifiedPluginInstallPaths } from \"./plugin-settings\";\n\n/**\n * Discovers all plugin-installed skills from enabled plugins.\n *\n * Reads `.claude/settings.json` to find enabled plugins, then looks up their\n * install paths in the global plugin registry (`~/.claude/plugins/installed_plugins.json`).\n * Loads skills from the plugin cache directories.\n *\n * @param projectDir - Absolute path to the project root\n * @returns Merged map of all discovered plugin skills (later plugins override earlier)\n */\nexport async function discoverAllPluginSkills(projectDir: string): Promise<SkillDefinitionMap> {\n const allSkills: SkillDefinitionMap = {};\n\n try {\n const pluginPaths = await getVerifiedPluginInstallPaths(projectDir);\n\n if (pluginPaths.length === 0) {\n verbose(`No enabled plugins found in settings.json`);\n return allSkills;\n }\n\n const perPluginSkills = await Promise.all(\n pluginPaths.map(async ({ pluginKey, installPath }) => {\n verbose(`Discovering skills from plugin: '${pluginKey}'`);\n try {\n return await loadPluginSkills(installPath);\n } catch (error) {\n verbose(`Failed to load skills from '${pluginKey}': ${getErrorMessage(error)}`);\n return {};\n }\n }),\n );\n // Later plugins override earlier (merge follows pluginPaths order); skip absent entries\n for (const pluginSkills of perPluginSkills) {\n for (const [id, skill] of typedEntries(pluginSkills)) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n if (skill) {\n allSkills[id] = skill;\n }\n }\n }\n } catch (error) {\n verbose(`Plugin discovery failed: ${getErrorMessage(error)}`);\n }\n\n return allSkills;\n}\n\n/**\n * Lists the keys of all enabled plugins.\n *\n * @param projectDir - Absolute path to the project root\n * @returns Array of plugin keys (e.g., [\"web-framework-react@acme-marketplace\"])\n */\nexport async function listPluginNames(projectDir: string): Promise<string[]> {\n try {\n const pluginPaths = await getVerifiedPluginInstallPaths(projectDir);\n return pluginPaths.map(({ pluginKey }) => pluginKey);\n } catch (error) {\n verbose(`Failed to list plugin names: ${getErrorMessage(error)}`);\n return [];\n }\n}\n","import path from \"path\";\nimport { directoryExists, listDirectories, fileExists, readFile } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { LOCAL_PSEUDO_CATEGORY, LOCAL_SKILLS_PATH, STANDARD_FILES } from \"../../consts\";\nimport { namesPlaceholderCategory, parseFrontmatter, readSkillMetadata } from \"../loading\";\nimport type { CategoryPath, Domain, ExtractedSkillMetadata, SkillSlug } from \"../../types\";\nimport { LOCAL_DEFAULTS, METADATA_KEYS } from \"../metadata-keys\";\n\nexport type LocalRawMetadata = {\n displayName: string;\n /** Kebab-case short key for alias resolution */\n slug: SkillSlug;\n cliDescription?: string;\n /** Skill category (e.g., \"web-framework\", \"web-styling\", \"api-api\") */\n category: CategoryPath;\n usageGuidance?: string;\n tags?: string[];\n /** Domain this skill belongs to (e.g., \"web\", \"api\", \"cli\") */\n domain: Domain;\n /** True if this skill was created outside the CLI's built-in vocabulary */\n custom?: boolean;\n};\n\nexport type LocalSkillDiscoveryResult = {\n skills: ExtractedSkillMetadata[];\n localSkillsPath: string;\n};\n\nexport async function discoverLocalSkills(\n projectDir: string,\n): Promise<LocalSkillDiscoveryResult | null> {\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n\n if (!(await directoryExists(localSkillsPath))) {\n verbose(`Local skills directory not found: ${localSkillsPath}`);\n return null;\n }\n\n const skillDirs = await listDirectories(localSkillsPath);\n const extracted = await Promise.all(\n skillDirs.map((skillDirName) => extractLocalSkill(localSkillsPath, skillDirName)),\n );\n const skills = extracted.filter((skill) => skill !== null);\n\n verbose(`Discovered ${skills.length} local skills from ${localSkillsPath}`);\n\n return {\n skills,\n localSkillsPath,\n };\n}\n\nasync function extractLocalSkill(\n localSkillsPath: string,\n skillDirName: string,\n): Promise<ExtractedSkillMetadata | null> {\n const skillDir = path.join(localSkillsPath, skillDirName);\n const metadataPath = path.join(skillDir, STANDARD_FILES.METADATA_YAML);\n const skillMdPath = path.join(skillDir, STANDARD_FILES.SKILL_MD);\n\n if (!(await fileExists(metadataPath))) {\n verbose(`Skipping local skill '${skillDirName}': No metadata.yaml found`);\n return null;\n }\n\n if (!(await fileExists(skillMdPath))) {\n verbose(`Skipping local skill '${skillDirName}': No SKILL.md found`);\n return null;\n }\n\n // One file that describes no skill must skip its own skill, not abort discovery\n // for every command that loads the catalog. `compile` refuses the same judgment's\n // verdict outright, which is what keeps the two passes from disagreeing.\n const read = await readSkillMetadata(metadataPath);\n if (!read.usable) {\n warn(\n `Skipping local skill '${skillDirName}': ${STANDARD_FILES.METADATA_YAML} at ${metadataPath} does not describe it — ${read.reason}`,\n );\n return null;\n }\n\n const metadata = read.metadata;\n\n // The verdict is `namesPlaceholderCategory`'s and is shared with the discovery behind\n // `compile`'s skill count, so neither pass can load what the other refuses. The SENTENCE\n // is this pass's alone: it is the one that reaches every command, so saying it here says\n // it once per run rather than once per reader.\n if (namesPlaceholderCategory(metadata)) {\n warn(\n `Skipping local skill '${skillDirName}': ${METADATA_KEYS.CATEGORY} '${LOCAL_PSEUDO_CATEGORY}' is a placeholder, not a real category, so no sub-agent can be given this skill. Set ${METADATA_KEYS.CATEGORY} in ${metadataPath} to a real one.`,\n );\n return null;\n }\n\n const skillMdContent = await readFile(skillMdPath);\n const frontmatter = parseFrontmatter(skillMdContent, skillMdPath);\n\n if (!frontmatter) {\n verbose(`Skipping local skill '${skillDirName}': invalid SKILL.md frontmatter`);\n return null;\n }\n\n const relativePath = `${LOCAL_SKILLS_PATH}/${skillDirName}/`;\n const absolutePath = path.join(localSkillsPath, skillDirName) + path.sep;\n const skillId = frontmatter.name;\n\n const extracted: ExtractedSkillMetadata = {\n id: skillId,\n directoryPath: skillDirName,\n description: metadata.cliDescription || frontmatter.description,\n ...(metadata.usageGuidance !== undefined && { usageGuidance: metadata.usageGuidance }),\n category: metadata.category,\n author: LOCAL_DEFAULTS.AUTHOR,\n path: relativePath,\n local: true,\n localPath: absolutePath,\n domain: metadata.domain,\n ...(metadata.custom !== undefined && { custom: metadata.custom }),\n slug: metadata.slug,\n displayName: metadata.displayName,\n };\n\n verbose(`Extracted local skill: ${skillId}`);\n return extracted;\n}\n","import path from \"path\";\n\nimport { EJECT_SOURCE, STANDARD_FILES } from \"../../consts\";\nimport type { SkillConfig, SkillId } from \"../../types\";\nimport { directoryExists, fileExists, readFile } from \"../../utils/fs\";\nimport { resolveInstallPaths } from \"../installation/install-base-dir\";\nimport { parseFrontmatter, readSkillMetadata, type UnusableSkillMetadata } from \"../loading\";\n\n/**\n * What became of the skill a saved config entry names, when the loaded catalogue does not\n * carry it.\n *\n * The wizard resolves an installed roster against the catalogue, and an id it cannot find is\n * an id it cannot put on any screen — so the merge drops that entry and `edit` reports a\n * removal the user never asked for. Reporting it is right; reporting all of them the same way\n * was not. A marketplace entry the source no longer carries is gone from the CATALOGUE. A\n * local entry is gone from the DISK — or is not gone at all, and its metadata.yaml simply\n * stopped describing it, which is a file to repair rather than a reason to lose the entry.\n *\n * Told apart at the entry's own install path. A local skill lives at\n * `<skillsDir>/<id>` — the one address `copySkillsToLocalFlattened`, `deleteLocalSkill` and\n * `migrateLocalSkillScope` all write to — so the entry names exactly where to look. What is\n * asked there is borrowed rather than invented: {@link readSkillMetadata} gives the same verdict\n * local-skill discovery, `compile` and `doctor` already share about that file, and\n * {@link parseFrontmatter}'s `name` is the same identity discovery registers the skill under.\n */\ntype SavedSkillFate =\n /** No local copy is claimed: the marketplace this entry names no longer carries the skill. */\n | { kind: \"dropped-by-source\" }\n /** Its local install is gone from the disk — nothing is left at the path it was ejected to. */\n | { kind: \"files-gone\"; skillDir: string }\n /** The directory is there but registers no skill by that name (no metadata.yaml, or a SKILL.md naming another). */\n | { kind: \"not-installed-there\"; skillDir: string }\n /** The skill is installed and intact — its declared category is one no domain in this source claims. */\n | { kind: \"unplaceable-category\"; skillDir: string; category: string }\n /** The directory is there and its metadata.yaml describes no skill — repairable, so the run refuses instead. */\n | { kind: \"unusable-metadata\"; detail: UnusableSkillMetadata };\n\ntype ClassifiedSkill = { id: SkillId; fate: SavedSkillFate };\n\n/**\n * The saved entries whose local skill is installed but whose metadata.yaml describes no skill.\n *\n * A run that meets one must stop rather than drop the entry: the file can be repaired, and\n * `compile` already refuses the whole run over the same verdict about the same file. Dropping\n * the entry instead would spend a config record on a YAML typo, and say the marketplace did it.\n */\nexport async function findUnusableSavedSkillMetadata(\n unresolvedIds: readonly SkillId[],\n savedSkills: readonly SkillConfig[],\n projectDir: string,\n): Promise<UnusableSkillMetadata[]> {\n const classified = await classifyUnresolvedSkills(unresolvedIds, savedSkills, projectDir);\n return classified.flatMap(({ fate }) => (fate.kind === \"unusable-metadata\" ? [fate.detail] : []));\n}\n\n/**\n * Why each unresolvable entry went, for `edit`'s Changes block.\n *\n * These removals are the only ones the user did not ask for: the wizard could not represent\n * the skill, so it never appeared on any screen to be deselected, and the merge drops it.\n * Reporting the id alone would read as \"we removed something you chose to remove\"; the reason\n * says which of the things below happened. Every other removal is a deselection the user\n * watched themselves make and needs no reason.\n *\n * An entry {@link findUnusableSavedSkillMetadata} would name is deliberately absent from the\n * map — that run refuses before any of this is printed, so a sentence for it would only ever\n * be a wrong one.\n */\nexport async function unresolvedSkillRemovalReasons(\n unresolvedIds: readonly SkillId[],\n savedSkills: readonly SkillConfig[],\n projectDir: string,\n sourceLabel: string,\n): Promise<ReadonlyMap<SkillId, string>> {\n const classified = await classifyUnresolvedSkills(unresolvedIds, savedSkills, projectDir);\n return new Map(\n classified.flatMap(({ id, fate }) => {\n const reason = removalReason(id, fate, sourceLabel);\n return reason === null ? [] : [[id, reason] as const];\n }),\n );\n}\n\nasync function classifyUnresolvedSkills(\n unresolvedIds: readonly SkillId[],\n savedSkills: readonly SkillConfig[],\n projectDir: string,\n): Promise<ClassifiedSkill[]> {\n return Promise.all(\n unresolvedIds.map(async (id) => {\n const saved = savedSkills.find((entry) => entry.id === id);\n return { id, fate: await classifySavedSkill(id, saved, projectDir) };\n }),\n );\n}\n\n/**\n * An id with no saved entry behind it — a plugin-discovered skill the config never recorded —\n * is read as the marketplace's: there is no local copy claimed for it to have lost.\n */\nasync function classifySavedSkill(\n id: SkillId,\n saved: SkillConfig | undefined,\n projectDir: string,\n): Promise<SavedSkillFate> {\n if (saved?.origin !== EJECT_SOURCE) return { kind: \"dropped-by-source\" };\n\n const skillDir = path.join(resolveInstallPaths(projectDir, saved.scope).skillsDir, id);\n if (!(await directoryExists(skillDir))) return { kind: \"files-gone\", skillDir };\n\n const metadataPath = path.join(skillDir, STANDARD_FILES.METADATA_YAML);\n // A directory with no metadata.yaml at all is not registered with the CLI, and `compile`\n // skips rather than refuses it — so this one is reported and removed, not stopped over.\n if (!(await fileExists(metadataPath))) return { kind: \"not-installed-there\", skillDir };\n\n const read = await readSkillMetadata(metadataPath);\n if (!read.usable) {\n return {\n kind: \"unusable-metadata\",\n detail: { skillDirName: id, metadataPath, reason: read.reason },\n };\n }\n\n // The metadata describes SOME skill. Whether it describes THIS one is SKILL.md's answer — a\n // local skill is identified by its frontmatter name — so a SKILL.md deleted out from under a\n // live metadata.yaml, or renamed under a directory that was not, lands here.\n if (!(await skillMdNames(skillDir, id))) return { kind: \"not-installed-there\", skillDir };\n\n // Everything about the install is intact, so what could not be placed is the category this\n // metadata.yaml declares — whichever arm brought the id here. `resolveSkillForPopulation` in\n // `stores/wizard-store.ts` returns null both for a skill the catalogue does not carry and for\n // one it carries under a category no domain claims, and an intact install arrives by either:\n // local discovery refuses the placeholder category before the catalogue is built.\n return { kind: \"unplaceable-category\", skillDir, category: read.metadata.category };\n}\n\n/** Whether the SKILL.md installed here names this skill — a local skill's identity is that name. */\nasync function skillMdNames(skillDir: string, id: SkillId): Promise<boolean> {\n const skillMdPath = path.join(skillDir, STANDARD_FILES.SKILL_MD);\n if (!(await fileExists(skillMdPath))) return false;\n\n const frontmatter = parseFrontmatter(await readFile(skillMdPath), skillMdPath);\n return frontmatter?.name === id;\n}\n\n/** The sentence the Changes block puts after the removed row, or null when there is none to give. */\nfunction removalReason(id: SkillId, fate: SavedSkillFate, sourceLabel: string): string | null {\n switch (fate.kind) {\n case \"dropped-by-source\":\n return `not present in ${sourceLabel}`;\n case \"files-gone\":\n return `skill files no longer exist at ${fate.skillDir}`;\n case \"not-installed-there\":\n return `no skill named '${id}' is installed at ${fate.skillDir}`;\n case \"unplaceable-category\":\n return `installed at ${fate.skillDir}, but its category '${fate.category}' is not one this source knows`;\n case \"unusable-metadata\":\n return null;\n default: {\n const exhaustive: never = fate;\n return exhaustive;\n }\n }\n}\n","import path from \"path\";\n\nimport {\n copy,\n directoryExists,\n ensureDir,\n isPathWithin,\n remove,\n removeDirIfEmpty,\n} from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { LOCAL_SKILLS_PATH } from \"../../consts\";\nimport { installBaseDir } from \"../installation/install-base-dir\";\nimport type { SkillId, SkillScope } from \"../../types\";\n\n/**\n * Validates a skill ID is safe for use in filesystem paths.\n * Blocks null bytes and path traversal sequences at runtime\n * since TypeScript template literal types don't prevent malformed data from YAML/JSON.\n */\nfunction validateSkillId(skillId: SkillId): boolean {\n return !(\n skillId.length === 0 ||\n skillId.includes(\"\\0\") ||\n skillId.includes(\"..\") ||\n skillId.includes(\"/\") ||\n skillId.includes(\"\\\\\")\n );\n}\n\n/**\n * Delete a local skill directory at .claude/skills/{skill-id}/\n */\nexport async function deleteLocalSkill(projectDir: string, skillId: SkillId): Promise<void> {\n if (!validateSkillId(skillId)) {\n warn(`Invalid skill ID for deletion: '${skillId}'`);\n return;\n }\n\n const skillPath = path.resolve(path.join(projectDir, LOCAL_SKILLS_PATH, skillId));\n const skillsDir = path.resolve(path.join(projectDir, LOCAL_SKILLS_PATH));\n\n if (!isPathWithin(skillPath, skillsDir)) {\n warn(`Skill ID '${skillId}' resolves outside the skills directory.`);\n return;\n }\n\n try {\n await remove(skillPath);\n } catch {\n // Skill may not exist — silently ignore\n }\n\n // The skills directory only — `.claude/` above it stays whatever happens here.\n // Removing that one is uninstall's decision, not the edit path's.\n await removeDirIfEmpty(skillsDir);\n\n verbose(`Deleted local skill '${skillId}'`);\n}\n\n/**\n * Migrate a local skill's files between project and global directories.\n * Used when a skill's scope changes during edit (e.g., [P] → [G] or [G] → [P]).\n *\n * Copies the skill directory to the new location.\n * For P→G, removes the old project copy. For G→P (override model), the global copy stays untouched.\n * No-op if the source directory doesn't exist (skill may be plugin-mode).\n */\nexport async function migrateLocalSkillScope(\n skillId: SkillId,\n fromScope: SkillScope,\n projectDir: string,\n): Promise<void> {\n if (!validateSkillId(skillId)) {\n warn(`Invalid skill ID for scope migration: '${skillId}'`);\n return;\n }\n\n const toScope: SkillScope = fromScope === \"global\" ? \"project\" : \"global\";\n // installBaseDir resolves os.homedir() at runtime so test home-dir mocks apply.\n const fromBaseDir = installBaseDir(projectDir, fromScope);\n const toBaseDir = installBaseDir(projectDir, toScope);\n\n const fromPath = path.resolve(path.join(fromBaseDir, LOCAL_SKILLS_PATH, skillId));\n const toPath = path.resolve(path.join(toBaseDir, LOCAL_SKILLS_PATH, skillId));\n\n const fromSkillsDir = path.resolve(path.join(fromBaseDir, LOCAL_SKILLS_PATH));\n const toSkillsDir = path.resolve(path.join(toBaseDir, LOCAL_SKILLS_PATH));\n\n if (!isPathWithin(fromPath, fromSkillsDir)) {\n warn(`Skill ID '${skillId}' resolves outside the source skills directory.`);\n return;\n }\n if (!isPathWithin(toPath, toSkillsDir)) {\n warn(`Skill ID '${skillId}' resolves outside the destination skills directory.`);\n return;\n }\n\n if (!(await directoryExists(fromPath))) {\n if (await directoryExists(toPath)) {\n verbose(`Skill '${skillId}' already at ${toScope} scope — no migration needed`);\n return;\n }\n warn(`Could not migrate skill '${skillId}' — not found at either scope`);\n return;\n }\n\n await ensureDir(toSkillsDir);\n await copy(fromPath, toPath);\n\n // G→P is an override — the global copy stays untouched; the project copy overrides it.\n // Only P→G should delete the old directory.\n if (fromScope === \"project\") {\n await remove(fromPath);\n }\n\n verbose(`Migrated skill '${skillId}' from ${fromScope} to ${toScope}`);\n}\n","import { parse as parseYaml } from \"yaml\";\nimport path from \"path\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { glob, readFile, fileExists } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { STANDARD_FILES } from \"../../consts\";\nimport { loadConfig } from \"../configuration/config-loader\";\nimport { METADATA_KEYS } from \"../metadata-keys\";\nimport { parseFrontmatter } from \"../loading\";\nimport {\n skillCategoriesFileSchema,\n skillRulesFileSchema,\n formatZodIssues,\n matrixRawMetadataSchema,\n} from \"../schemas\";\nimport type { CategoryMap, ExtractedSkillMetadata, SkillRulesConfig } from \"../../types\";\n\n/**\n * Loads and validates a skill-categories.ts configuration file.\n *\n * @param configPath - Absolute path to the skill-categories.ts file\n * @returns Parsed and validated categories map\n * @throws When the file cannot be read or fails Zod schema validation\n */\nexport async function loadSkillCategories(configPath: string): Promise<CategoryMap> {\n const data = await loadConfig(configPath, skillCategoriesFileSchema);\n\n if (!data) {\n throw new Error(`Invalid skill categories at '${configPath}': failed to load or validate`);\n }\n\n verbose(`Loaded skill categories: ${configPath}`);\n return data.categories;\n}\n\n/**\n * Loads and validates a skill-rules.ts configuration file.\n *\n * @param configPath - Absolute path to the skill-rules.ts file\n * @returns Parsed and validated skill rules config\n * @throws When the file cannot be read or fails Zod schema validation\n */\nexport async function loadSkillRules(configPath: string): Promise<SkillRulesConfig> {\n const data = await loadConfig(configPath, skillRulesFileSchema);\n\n if (!data) {\n throw new Error(`Invalid skill rules at '${configPath}': failed to load or validate`);\n }\n\n const config: SkillRulesConfig = {\n version: data.version,\n relationships: data.relationships ?? {\n conflicts: [],\n discourages: [],\n requires: [],\n alternatives: [],\n },\n };\n\n verbose(`Loaded skill rules: ${configPath}`);\n return config;\n}\n\n/**\n * Scans a skills directory and extracts metadata from all valid skills.\n *\n * Discovers skills by globbing for `metadata.yaml` files, then for each:\n * 1. Validates a corresponding SKILL.md exists (skips if missing)\n * 2. Parses metadata.yaml and validates it against the raw metadata schema\n * 3. Parses SKILL.md frontmatter for the canonical skill ID\n * 4. Merges metadata fields into an ExtractedSkillMetadata object\n *\n * A metadata.yaml that describes no skill — unparseable, or parseable without the\n * fields the schema requires — is warned by path and skips its own skill; one bad\n * file does not take the scan down with it. Skills missing the required\n * `displayName` field in metadata.yaml cause a hard error.\n *\n * @param skillsDir - Absolute path to the skills root directory (e.g., `{root}/src/skills`)\n * @returns Array of extracted skill metadata, one per valid skill found\n * @throws When a skill's metadata.yaml is missing the required `displayName` field\n */\nexport async function extractAllSkills(skillsDir: string): Promise<ExtractedSkillMetadata[]> {\n const skills: ExtractedSkillMetadata[] = [];\n const metadataFiles = await glob(`**/${STANDARD_FILES.METADATA_YAML}`, skillsDir);\n\n for (const metadataFile of metadataFiles) {\n const skillDir = path.dirname(metadataFile);\n const skillMdPath = path.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);\n const metadataPath = path.join(skillsDir, metadataFile);\n\n if (!(await fileExists(skillMdPath))) {\n verbose(`Skipping ${metadataFile}: No ${STANDARD_FILES.SKILL_MD} found`);\n continue;\n }\n\n const metadataContent = await readFile(metadataPath);\n\n // The safeParse below catches a file that parses without the fields a skill is\n // described by, and cannot catch a file nothing parses out of at all. Both refuse\n // the same way readSkillMetadata does: skip this skill, not the whole scan.\n let rawMetadata: unknown;\n try {\n rawMetadata = parseYaml(metadataContent);\n } catch (error) {\n warn(\n `Skipping '${metadataFile}': unparseable ${STANDARD_FILES.METADATA_YAML} at ${metadataPath} — ${getErrorMessage(error)}`,\n );\n continue;\n }\n\n const metadataResult = matrixRawMetadataSchema.safeParse(rawMetadata);\n\n if (!metadataResult.success) {\n warn(\n `Skipping '${metadataFile}': invalid metadata.yaml — ${formatZodIssues(metadataResult.error.issues)}`,\n );\n continue;\n }\n\n const metadata = metadataResult.data;\n const skillMdContent = await readFile(skillMdPath);\n const frontmatter = parseFrontmatter(skillMdContent, skillMdPath);\n\n if (!frontmatter) {\n verbose(`Skipping ${metadataFile}: Invalid SKILL.md frontmatter`);\n continue;\n }\n\n if (!metadata.displayName) {\n throw new Error(\n `Skill at ${metadataFile} is missing required '${METADATA_KEYS.DISPLAY_NAME}' field in metadata.yaml`,\n );\n }\n\n const skillId = frontmatter.name;\n\n const extracted: ExtractedSkillMetadata = {\n id: skillId,\n directoryPath: skillDir,\n description: metadata.cliDescription || frontmatter.description,\n ...(metadata.usageGuidance !== undefined && { usageGuidance: metadata.usageGuidance }),\n category: metadata.category,\n author: metadata.author,\n path: `skills/${skillDir}/`,\n domain: metadata.domain,\n displayName: metadata.displayName,\n slug: metadata.slug,\n ...(metadata.custom === true ? { custom: true } : {}),\n };\n\n skills.push(extracted);\n verbose(`Extracted skill: ${skillId}`);\n }\n\n return skills;\n}\n","import { verbose, warn } from \"../../utils/logger\";\nimport { unique, uniqueBy } from \"remeda\";\nimport { toTitleCase } from \"../../utils/string\";\nimport { DEFAULT_VERSION, LOCAL_PSEUDO_CATEGORY } from \"../../consts\";\nimport { defaultRules } from \"../configuration/default-rules\";\nimport type {\n CategoryDefinition,\n CategoryMap,\n Domain,\n ExtractedSkillMetadata,\n MergedSkillsMatrix,\n RelationshipDefinitions,\n RequireRule,\n ResolvedSkill,\n SkillAlternative,\n SkillId,\n SkillRelation,\n SkillRequirement,\n SkillRulesConfig,\n SkillSlug,\n SkillSlugMap,\n Category,\n} from \"../../types\";\n\n/** Resolves a slug to a canonical SkillId, or null if unresolvable */\ntype ResolveId = (slug: SkillSlug, context?: string) => SkillId | null;\n\nconst AUTO_SYNTH_ORDER = 999;\n\n/**\n * Synthesizes a basic CategoryDefinition for a category not defined in any\n * skill-categories.ts. This is a safety net — the preferred path is for\n * skill authors to maintain proper skill-categories.ts entries.\n */\n/**\n * Warns when a second skill files an undeclared category under a different domain from the first.\n *\n * A synthesized category takes its domain from **whichever skill the glob reached first**, and the\n * order a directory walk returns is not a decision anybody made. Two skills sharing an undeclared\n * category while declaring different domains therefore file the second under a domain its own\n * `metadata.yaml` contradicts — silently, until now. The value feeds six product readers of\n * `getCategoryDomain`, `config-generator.ts` and `wizard-store.ts` among them, so it shapes both\n * the emitted `config.ts` and where the wizard puts the skill.\n *\n * **Reported, not resolved.** Picking a winner would need a rule the catalogue does not state, and\n * the author is the only one who can say which domain they meant. `checkCategoryDomains` does not\n * cover this — it reports a category with NO domain, and this one has two.\n */\nfunction warnOnDomainDisagreement(\n skill: ExtractedSkillMetadata,\n decidedBy: ExtractedSkillMetadata,\n): void {\n if (skill.domain === decidedBy.domain) return;\n\n warn(\n `Category '${skill.category}' has no definition, so its domain was taken from the first skill ` +\n `naming it — '${decidedBy.id}' (${decidedBy.domain}). '${skill.id}' declares ` +\n `'${skill.domain}' and will be filed under '${decidedBy.domain}'. Declare the category in ` +\n `the marketplace's own config, or make the two skills agree.`,\n );\n}\n\nexport function synthesizeCategory(category: Category, domain: Domain): CategoryDefinition {\n verbose(\n `Category '${category}' has no definition in skill-categories.ts — using auto-generated placeholder`,\n );\n const displayName = toTitleCase(category);\n\n return {\n id: category,\n displayName,\n description: `Auto-generated category for ${category}`,\n domain,\n exclusive: false,\n order: AUTO_SYNTH_ORDER,\n };\n}\n\n/**\n * Registers a skill's claim on a slug, first claim winning and every later one\n * named. Exported because the merge is not the only writer: `source-loader`\n * merges a project's local skills into an already-built map, and two writers\n * deciding a collision differently is how a slug comes to mean one skill here\n * and another there.\n *\n * A skill re-stating a claim it already holds is not a collision — a local skill\n * overriding a matrix id inherits that id's slug and arrives back here with it.\n */\nexport function claimSlug(slugMap: SkillSlugMap, slug: SkillSlug, id: SkillId): void {\n const incumbent = slugMap.slugToId[slug];\n if (incumbent === id) return;\n if (incumbent !== undefined) {\n warn(`Duplicate slug '${slug}': already mapped to '${incumbent}', ignoring '${id}'`);\n return;\n }\n\n slugMap.slugToId[slug] = id;\n}\n\n/** Builds the slug -> ID map from extracted skill metadata. */\nfunction buildSlugMap(skills: ExtractedSkillMetadata[]): SkillSlugMap {\n const slugMap: SkillSlugMap = { slugToId: {} };\n\n for (const skill of skills) {\n claimSlug(slugMap, skill.slug, skill.id);\n }\n\n return slugMap;\n}\n\n/**\n * Resolves every skill into the map the matrix is read through, keyed by id.\n * Warns on duplicate ids (first one wins) — the identity axis {@link buildSlugMap}\n * guards for slugs. Two directories whose SKILL.md declares the same name would\n * otherwise resolve in glob order, and the loser would leave no trace.\n */\nfunction buildResolvedSkillMap(\n skills: ExtractedSkillMetadata[],\n categories: CategoryMap,\n relationships: RelationshipDefinitions,\n slugMap: SkillSlugMap,\n): Partial<Record<SkillId, ResolvedSkill>> {\n const resolvedSkills: Partial<Record<SkillId, ResolvedSkill>> = {};\n\n for (const skill of skills) {\n const existing = resolvedSkills[skill.id];\n if (existing) {\n warn(\n `Duplicate skill id '${skill.id}': already resolved from '${existing.path}', ignoring '${skill.path}'`,\n );\n continue;\n }\n\n resolvedSkills[skill.id] = buildResolvedSkill(skill, categories, relationships, slugMap);\n }\n\n return resolvedSkills;\n}\n\nfunction resolveToCanonicalId(\n slug: SkillSlug,\n slugToId: SkillSlugMap[\"slugToId\"],\n context?: string,\n): SkillId | null {\n const slugResult = slugToId[slug];\n if (slugResult) {\n return slugResult;\n }\n const location = context ? ` in ${context}` : \"\";\n warn(`Unresolved slug '${slug}'${location} — skipping`);\n return null;\n}\n\n/** Every slug the rules name, in the order the four rule kinds declare them. */\nfunction slugsNamedByRules(relationships: RelationshipDefinitions): SkillSlug[] {\n return [\n ...relationships.conflicts.flatMap((rule) => rule.skills),\n ...relationships.discourages.flatMap((rule) => rule.skills),\n ...relationships.requires.flatMap((rule) => [rule.skill, ...rule.needs]),\n ...relationships.alternatives.flatMap((rule) => rule.skills),\n ];\n}\n\n/**\n * The slugs the rules name that no skill carries, deduplicated.\n *\n * Asked of the rules rather than counted off the resolution pass, because that\n * pass walks every rule once per skill: one typo would otherwise be reported as\n * many findings as the source has skills, which is the noise this removed.\n */\nfunction collectUnresolvedSlugs(\n relationships: RelationshipDefinitions,\n slugToId: SkillSlugMap[\"slugToId\"],\n): SkillSlug[] {\n return unique(slugsNamedByRules(relationships).filter((slug) => slugToId[slug] === undefined));\n}\n\n/** Merges relationship rule sets: source rules first, so they win first-match lookups. */\nfunction mergeRelationships(\n source: RelationshipDefinitions,\n defaults: RelationshipDefinitions,\n): RelationshipDefinitions {\n return {\n conflicts: [...source.conflicts, ...defaults.conflicts],\n discourages: [...source.discourages, ...defaults.discourages],\n requires: [...source.requires, ...defaults.requires],\n alternatives: [...source.alternatives, ...defaults.alternatives],\n };\n}\n\n/** Below two present members a group rule relates nothing, so it is dropped whole. */\nconst MIN_RELATABLE_GROUP_MEMBERS = 2;\n\n/** Group rules — conflicts, discourages, alternatives — keeping only present slugs. */\nfunction narrowGroupsToSlugs<Rule extends { skills: SkillSlug[] }>(\n rules: Rule[],\n shipped: ReadonlySet<SkillSlug>,\n): Rule[] {\n return rules\n .map((rule) => ({ ...rule, skills: rule.skills.filter((slug) => shipped.has(slug)) }))\n .filter((rule) => rule.skills.length >= MIN_RELATABLE_GROUP_MEMBERS);\n}\n\n/**\n * Requirements, keeping only those a present skill declares over present skills.\n * A rule left needing nothing states no requirement — resolution already treats it\n * that way — so it goes rather than resolving to an empty `needs`.\n */\nfunction narrowRequirementsToSlugs(\n rules: RequireRule[],\n shipped: ReadonlySet<SkillSlug>,\n): RequireRule[] {\n return rules\n .filter((rule) => shipped.has(rule.skill))\n .map((rule) => ({ ...rule, needs: rule.needs.filter((slug) => shipped.has(slug)) }))\n .filter((rule) => rule.needs.length > 0);\n}\n\nfunction narrowToShippedSlugs(\n rules: RelationshipDefinitions,\n shipped: ReadonlySet<SkillSlug>,\n): RelationshipDefinitions {\n return {\n conflicts: narrowGroupsToSlugs(rules.conflicts, shipped),\n discourages: narrowGroupsToSlugs(rules.discourages, shipped),\n requires: narrowRequirementsToSlugs(rules.requires, shipped),\n alternatives: narrowGroupsToSlugs(rules.alternatives, shipped),\n };\n}\n\n/**\n * The relationships a source's skills can actually express: the source's own rules\n * verbatim, plus the built-ins narrowed to the slugs this source ships.\n *\n * The built-in rules are written against the whole public catalogue — 176 slugs — so\n * a source shipping ten of them left the rest dangling. Resolution dropped those\n * references either way; what it ALSO did was warn once per reference per skill, and\n * since the startup band those warnings are painted over the wizard's step. Narrowing\n * first removes the noise and nothing else: a member that resolves to no skill\n * contributed nothing to the resolved matrix to begin with.\n *\n * A source's OWN rules are never narrowed. A slug its author typed and its skills do\n * not carry is that source's defect, and the warning is the only place it is reported.\n */\nexport function relationshipsForSource(\n skills: ExtractedSkillMetadata[],\n sourceRules?: SkillRulesConfig,\n): RelationshipDefinitions {\n const shipped = new Set(skills.map((skill) => skill.slug));\n const builtIn = narrowToShippedSlugs(defaultRules.relationships, shipped);\n return sourceRules ? mergeRelationships(sourceRules.relationships, builtIn) : builtIn;\n}\n\n/**\n * Merges category definitions, relationship rules, and extracted skill metadata\n * into a fully resolved MergedSkillsMatrix.\n *\n * This is the core resolution step that combines:\n * - Category definitions from skill-categories.ts\n * - Slug-based alias maps derived from metadata\n * - Relationship rules from skill-rules.ts\n * - Extracted skill metadata (from scanning skill directories)\n *\n * Each skill's raw relationship references are resolved to canonical SkillIds.\n * The result is the complete data structure consumed by the wizard UI and validation logic.\n */\nexport function mergeMatrixWithSkills(\n categories: CategoryMap,\n relationships: RelationshipDefinitions,\n skills: ExtractedSkillMetadata[],\n): MergedSkillsMatrix {\n const slugMap = buildSlugMap(skills);\n const resolvedSkills = buildResolvedSkillMap(skills, categories, relationships, slugMap);\n\n // Auto-synthesize missing categories for skills that reference undefined categories\n const synthesizedCategories = { ...categories };\n const synthesizedFrom = new Map<string, ExtractedSkillMetadata>();\n for (const skill of skills) {\n // Skip \"local\" pseudo-category — it's not a real Category union member\n if (skill.category === LOCAL_PSEUDO_CATEGORY) continue;\n\n // A category the catalogue DECLARES is not ours to synthesize, and not ours to judge either:\n // its domain is stated rather than inferred, so two skills disagreeing about it is a different\n // defect that `checkCategoryDomains` owns. Read from the input map rather than the one being\n // built, so a synthesized entry cannot be mistaken for a declared one.\n if (categories[skill.category]) continue;\n\n const already = synthesizedFrom.get(skill.category);\n if (already === undefined) {\n synthesizedCategories[skill.category] = synthesizeCategory(skill.category, skill.domain);\n synthesizedFrom.set(skill.category, skill);\n verbose(`Auto-synthesized category '${skill.category}' for skill '${skill.id}'`);\n continue;\n }\n\n warnOnDomainDisagreement(skill, already);\n }\n\n const unresolvedSlugs = collectUnresolvedSlugs(relationships, slugMap.slugToId);\n\n const merged: MergedSkillsMatrix = {\n version: DEFAULT_VERSION,\n categories: synthesizedCategories,\n skills: resolvedSkills,\n suggestedStacks: [],\n slugMap,\n ...(unresolvedSlugs.length > 0 && { unresolvedSlugs }),\n generatedAt: new Date().toISOString(),\n };\n\n return merged;\n}\n\n/** All resolved relationship data for a single skill */\ntype ResolvedRelationships = {\n conflictsWith: SkillRelation[];\n discourages: SkillRelation[];\n requires: SkillRequirement[];\n alternatives: SkillAlternative[];\n};\n\n/** Resolves a rule's slugs to canonical ids, warning and skipping any that don't resolve. */\nfunction resolveSlugsOrSkip(slugs: SkillSlug[], resolve: ResolveId, context: string): SkillId[] {\n return slugs.map((slug) => resolve(slug, context)).filter((id): id is SkillId => id !== null);\n}\n\n/**\n * A requirement's needs, or null when any one of them names no skill.\n *\n * Keeping what resolved would apply a requirement nobody wrote: under AND an\n * unresolved need narrows the rule to the survivors, under OR it takes an\n * alternative away — and either is presented to the user under the author's own\n * `reason`. A source's rules are its own (the CLI's built-ins are narrowed to\n * what a source ships, and the source's are left untouched), so they are taken\n * whole or not at all. The slug is warned here and reported by\n * `checkMatrixHealth`, which is where the author reads it.\n */\nfunction resolveEveryNeed(needs: SkillSlug[], resolve: ResolveId): SkillId[] | null {\n // A rule needing nothing states no requirement, as it did before any of its\n // members could fail to resolve.\n if (needs.length === 0) return null;\n\n const resolved = resolveSlugsOrSkip(needs, resolve, \"requires.needs\");\n return resolved.length === needs.length ? resolved : null;\n}\n\n/**\n * Members of the symmetric groups containing `skillId` (excluding itself),\n * deduplicated on first occurrence, each paired with its group's rule so the\n * caller can lift the annotation (reason/purpose).\n */\nfunction collectSymmetricGroupMembers<Rule extends { skills: SkillSlug[] }>(\n rules: readonly Rule[],\n skillId: SkillId,\n resolve: ResolveId,\n context: string,\n): Array<{ memberId: SkillId; rule: Rule }> {\n const members = rules.flatMap((rule) => {\n const resolved = resolveSlugsOrSkip(rule.skills, resolve, context);\n if (!resolved.includes(skillId)) return [];\n return resolved.filter((id) => id !== skillId).map((memberId) => ({ memberId, rule }));\n });\n return uniqueBy(members, (m) => m.memberId);\n}\n\n/**\n * Resolves all relationship data for a single skill in one pass across all\n * relationship rule types (conflicts, discourages, compatibility, requirements, alternatives).\n */\nfunction resolveRelationships(\n skillId: SkillId,\n relationships: RelationshipDefinitions,\n resolve: ResolveId,\n): ResolvedRelationships {\n // Symmetric groups: members of every group containing this skill, first-occurrence deduped\n const conflictsWith: SkillRelation[] = collectSymmetricGroupMembers(\n relationships.conflicts,\n skillId,\n resolve,\n \"conflicts\",\n ).map(({ memberId, rule }) => ({ skillId: memberId, reason: rule.reason }));\n\n const discourages: SkillRelation[] = collectSymmetricGroupMembers(\n relationships.discourages,\n skillId,\n resolve,\n \"discourages\",\n ).map(({ memberId, rule }) => ({ skillId: memberId, reason: rule.reason }));\n\n const alternatives: SkillAlternative[] = collectSymmetricGroupMembers(\n relationships.alternatives,\n skillId,\n resolve,\n \"alternatives\",\n ).map(({ memberId, rule }) => ({ skillId: memberId, purpose: rule.purpose }));\n\n // Requirements — directional, skill field identifies the dependent\n const requires: SkillRequirement[] = [];\n for (const rule of relationships.requires) {\n const ruleSkillId = resolve(rule.skill, \"requires.skill\");\n if (ruleSkillId !== skillId) continue;\n const resolvedNeeds = resolveEveryNeed(rule.needs, resolve);\n if (!resolvedNeeds) continue;\n requires.push({\n skillIds: resolvedNeeds,\n needsAny: rule.needsAny ?? false,\n reason: rule.reason,\n });\n }\n\n return {\n conflictsWith,\n discourages,\n requires,\n alternatives,\n };\n}\n\nfunction buildResolvedSkill(\n skill: ExtractedSkillMetadata,\n _categories: CategoryMap,\n relationships: RelationshipDefinitions,\n slugMap: SkillSlugMap,\n): ResolvedSkill {\n const resolve: ResolveId = (slug, context) =>\n resolveToCanonicalId(slug, slugMap.slugToId, context ? `${skill.id} ${context}` : undefined);\n\n const slug = skill.slug;\n\n const resolved = resolveRelationships(skill.id, relationships, resolve);\n\n return {\n id: skill.id,\n slug,\n displayName: skill.displayName,\n description: skill.description,\n ...(skill.usageGuidance !== undefined && { usageGuidance: skill.usageGuidance }),\n category: skill.category,\n author: skill.author,\n ...resolved,\n path: skill.path,\n ...(skill.custom === true ? { custom: true } : {}),\n };\n}\n","export function truncateText(text: string, maxLength: number): string {\n if (text.length <= maxLength) return text;\n return text.slice(0, maxLength - 1) + \"\\u2026\";\n}\n\n/** Converts a kebab-case string to a space-separated Title Case string. */\nexport function toTitleCase(kebabCase: string): string {\n return kebabCase\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n\n/**\n * Locale-free string ordering for anything emitted into a file somebody commits.\n *\n * Declared in `@workspace/compile` because the emitters moved there — `generateStackAgentConfig`\n * orders a config-types.ts property list with it — and re-exported here so no CLI call site\n * moved. The reason it is not `localeCompare` lives with the declaration.\n */\nexport { bytewise } from \"@workspace/compile\";\n","import { truncateText } from \"../../utils/string\";\nimport {\n createSelectionSemantics,\n type IncompatibilityCause,\n type SelectionCatalogFacts,\n type SelectionJudgement,\n type SelectionSemantics,\n} from \"@workspace/matrix\";\nimport { groupBy } from \"remeda\";\nimport { LOCAL_PSEUDO_CATEGORY } from \"../../consts\";\nimport type {\n CategoryPath,\n MergedSkillsMatrix,\n OptionState,\n ResolvedSkill,\n SelectionValidation,\n SkillId,\n SkillOption,\n ValidationError,\n} from \"../../types\";\nimport { typedEntries, typedValues } from \"../../utils/typed-object\";\nimport { matrix, getSkillById, allSkills } from \"./matrix-provider\";\n\nfunction getLabel(skill: Pick<ResolvedSkill, \"displayName\">): string {\n return skill.displayName;\n}\n\nfunction joinWithConjunction(items: string[], conjunction: \"or\" | \"and\"): string {\n if (items.length <= 1) return items[0] ?? \"\";\n if (items.length === 2) return `${items[0]} ${conjunction} ${items[1]}`;\n return `${items.slice(0, -1).join(\", \")} ${conjunction} ${items[items.length - 1]}`;\n}\n\ntype SelectionContext = {\n resolvedSelections: SkillId[];\n selectedSet: Set<SkillId>;\n};\n\nfunction initializeSelectionContext(currentSelections: SkillId[]): SelectionContext {\n const resolvedSelections = currentSelections.map((s) => getSkillById(s).id);\n const selectedSet = new Set<SkillId>(resolvedSelections);\n return { resolvedSelections, selectedSet };\n}\n\n/**\n * The relationship facts the shared selection semantics judge — id, category,\n * conflicts, discourages and requires. Exclusivity defaults to true for a\n * category that does not say, matching the wizard grid's own reading; the\n * `local` pseudo-category is never listed, so it stays non-exclusive here as it\n * does in `validateExclusivity`.\n */\nfunction toSelectionFacts(source: MergedSkillsMatrix): SelectionCatalogFacts {\n return {\n skills: typedValues(source.skills).map((skill) => ({\n id: skill.id,\n categoryId: skill.category,\n conflictsWith: skill.conflictsWith.map((relation) => relation.skillId),\n discourages: skill.discourages.map((relation) => ({\n skillId: relation.skillId,\n reason: relation.reason,\n })),\n requires: skill.requires.map((requirement) => ({\n skillIds: requirement.skillIds,\n needsAny: requirement.needsAny,\n })),\n })),\n exclusiveCategoryIds: new Set(\n typedValues(source.categories)\n .filter((category) => category.exclusive !== false)\n .map((category) => category.id),\n ),\n };\n}\n\n// Rebound whenever `initializeMatrix` swaps the matrix, so the semantics\n// always judge the catalogue currently loaded — merged local skills included.\nlet boundSemantics: SelectionSemantics | undefined;\nlet boundTo: MergedSkillsMatrix | undefined;\n\nfunction judgeSelections(resolvedSelections: SkillId[]): SelectionJudgement {\n if (!boundSemantics || boundTo !== matrix) {\n boundSemantics = createSelectionSemantics(toSelectionFacts(matrix));\n boundTo = matrix;\n }\n return boundSemantics(resolvedSelections);\n}\n\n// The judgement speaks in ids; this surface answers in the wizard's words.\nfunction renderIncompatibility(cause: IncompatibilityCause): string {\n switch (cause.kind) {\n case \"conflict\":\n return `conflicts with ${labelOf(cause.skillId)}`;\n case \"unreachableRequirement\": {\n if (cause.requirement.needsAny) {\n const labels = cause.requirement.skillIds.map(labelOf);\n return `requires ${joinWithConjunction(labels, \"or\")} (all conflict with current selection)`;\n }\n const lostLabels = cause.lostIds.map(labelOf);\n return `requires ${joinWithConjunction(lostLabels, \"and\")} which conflicts with current selection`;\n }\n }\n}\n\nfunction labelOf(skillId: string): string {\n // Boundary cast: every id inside a cause was read out of the matrix's own\n // relationship tables, so it names a skill the matrix holds.\n return getLabel(getSkillById(skillId as SkillId));\n}\n\ntype SkillRequirement = ResolvedSkill[\"requires\"][number];\n\n/** OR (`needsAny`): met when ANY option is selected. AND: met when EVERY id is selected. */\nfunction isRequirementMet(req: SkillRequirement, selectedSet: ReadonlySet<SkillId>): boolean {\n return req.needsAny\n ? req.skillIds.some((id) => selectedSet.has(id))\n : req.skillIds.every((id) => selectedSet.has(id));\n}\n\n/** Ids blocking the requirement: every option for an unmet OR, the absent ids for an AND. */\nfunction missingRequirementIds(\n req: SkillRequirement,\n selectedSet: ReadonlySet<SkillId>,\n): SkillId[] {\n if (isRequirementMet(req, selectedSet)) return [];\n return req.needsAny ? [...req.skillIds] : req.skillIds.filter((id) => !selectedSet.has(id));\n}\n\n/**\n * For an unselected skill, finds the first selected skill that needs it\n * and whose requirement is currently unmet. Returns the dependent's display name,\n * or undefined if no selected skill has an unmet need for this skill.\n */\nexport function getUnmetRequiredBy(\n skillId: SkillId,\n currentSelections: SkillId[],\n): string | undefined {\n getSkillById(skillId); // assert the id exists in the matrix\n const { resolvedSelections, selectedSet } = initializeSelectionContext(currentSelections);\n\n if (selectedSet.has(skillId)) return undefined;\n\n for (const selectedId of resolvedSelections) {\n const selectedSkill = matrix.skills[selectedId];\n if (!selectedSkill) continue;\n\n for (const req of selectedSkill.requires) {\n if (!req.skillIds.includes(skillId)) continue;\n\n if (req.needsAny) {\n // OR: unmet only if NONE of the options are selected\n if (!req.skillIds.some((id) => selectedSet.has(id))) {\n return selectedSkill.displayName;\n }\n } else {\n // AND: unmet if this specific skill isn't selected\n return selectedSkill.displayName;\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Checks if a selected skill has unmet dependency requirements.\n * Only meaningful for skills that are currently selected.\n */\nexport function hasUnmetRequirements(skillId: SkillId, currentSelections: SkillId[]): boolean {\n return getUnmetRequirementsReason(skillId, currentSelections) !== undefined;\n}\n\n/**\n * The verdict a grid cell renders, judged against the selection a click on it\n * would produce. A pick-one category is a radio group: the click drops every\n * same-category member — selected or implied — so a conflict the swap\n * resolves is forgiven, and an impossibility it leaves standing (a requirement\n * the rest of the selection has ruled out) keeps its verdict and its reason,\n * exactly as a multi-select category renders it.\n */\nexport function getCellState(skillId: SkillId, currentSelections: SkillId[]): OptionState {\n const skill = getSkillById(skillId);\n const { resolvedSelections } = initializeSelectionContext(currentSelections);\n\n const verdict = judgeSelections(resolvedSelections).verdictOf(skill.id);\n return verdict.status === \"incompatible\"\n ? { status: \"incompatible\", reason: renderIncompatibility(verdict.cause) }\n : verdict;\n}\n\n/**\n * Returns a human-readable reason for unmet requirements, or undefined if all are met.\n */\nexport function getUnmetRequirementsReason(\n skillId: SkillId,\n currentSelections: SkillId[],\n): string | undefined {\n const skill = getSkillById(skillId);\n\n const { selectedSet } = initializeSelectionContext(currentSelections);\n\n for (const requirement of skill.requires) {\n const missing = missingRequirementIds(requirement, selectedSet);\n if (missing.length === 0) continue;\n const names = missing.map((id) => {\n const s = matrix.skills[id];\n return s ? getLabel(s) : id;\n });\n return withAuthorsReason(namesTheMissing(names, requirement.needsAny), requirement.reason);\n }\n\n return undefined;\n}\n\n/** What is missing, which only the current selection can say. */\nfunction namesTheMissing(names: string[], needsAny: boolean | undefined): string {\n return `requires ${joinWithConjunction(names, needsAny ? \"or\" : \"and\")}`;\n}\n\n/**\n * How much of a rule author's `reason` a grid cell carries.\n *\n * The cell wraps rather than elides, so an unbounded reason grows the tag, grows the frame, and\n * pushes the top of the wizard off the terminal — measured against the shipped catalogue, whose\n * longest reason is 242 characters and whose React Router entry alone cost four lines. A budget is\n * what keeps a variable-length authored string out of a fixed-height layout.\n *\n * 60 covers the median (46) and every reason under it untouched; 24 of 110 shipped rules are\n * clipped. Chosen against the catalogue as it stands rather than derived from the terminal, so a\n * much narrower window can still wrap one line — the frame-fit specs are what would catch that.\n */\nconst REASON_BUDGET = 60;\n\n/**\n * The rule author's own sentence, appended to the synthesised one and clipped to fit.\n *\n * The two halves say different things and neither replaces the other: the synthesis names WHAT is\n * missing, which static prose cannot know, and the author's `reason` says WHY, which the synthesis\n * cannot infer. `reason` is required by `requireRuleSchema` and enforced across the built-ins, so\n * it is a sentence every marketplace author is already made to write — and nothing read it until\n * 2026-08-23. Both siblings render theirs: `discourages[].reason` in the grid,\n * `conflicts[].reason` through `reportValidationErrors`.\n *\n * Guarded on emptiness rather than assumed present: the schema requires the KEY, not a non-empty\n * string, so a rule carrying `reason: \"\"` must not produce a dangling separator.\n */\nfunction withAuthorsReason(synthesised: string, reason: string): string {\n const stated = reason.trim();\n if (stated === \"\") return synthesised;\n\n return `${synthesised} — ${truncateText(stated, REASON_BUDGET)}`;\n}\n\n/**\n * `{ unmetRequirementsReason }` only when there is one to state — an unselected skill,\n * or a selected skill whose requirements are all met, carries no key at all.\n */\nfunction unmetRequirementsReasonFor(\n isSelected: boolean,\n skillId: SkillId,\n currentSelections: SkillId[],\n): { unmetRequirementsReason?: string } {\n if (!isSelected) return {};\n const reason = getUnmetRequirementsReason(skillId, currentSelections);\n return reason === undefined ? {} : { unmetRequirementsReason: reason };\n}\n\nexport function validateConflicts(resolvedSelections: SkillId[]): ValidationError[] {\n const errors: ValidationError[] = [];\n\n for (const [index, skillAId] of resolvedSelections.entries()) {\n const skillA = matrix.skills[skillAId];\n if (!skillA) continue;\n\n for (const skillBId of resolvedSelections.slice(index + 1)) {\n const conflict = skillA.conflictsWith.find((c) => c.skillId === skillBId);\n if (conflict) {\n errors.push({\n type: \"conflict\",\n message: `${getLabel(skillA)} conflicts with ${getLabel(getSkillById(skillBId))}: ${conflict.reason}`,\n skills: [skillA.id, skillBId],\n });\n }\n }\n }\n\n return errors;\n}\n\nexport function validateRequirements(\n resolvedSelections: SkillId[],\n selectedSet: Set<SkillId>,\n): ValidationError[] {\n const errors: ValidationError[] = [];\n\n for (const skillId of resolvedSelections) {\n const skill = matrix.skills[skillId];\n if (!skill) continue;\n\n for (const requirement of skill.requires) {\n if (requirement.needsAny) {\n const hasAny = requirement.skillIds.some((reqId) => selectedSet.has(reqId));\n if (!hasAny) {\n errors.push({\n type: \"missingRequirement\",\n message: `${getLabel(skill)} requires one of: ${requirement.skillIds.map((id) => getLabel(getSkillById(id))).join(\", \")}`,\n skills: [skillId, ...requirement.skillIds],\n });\n }\n } else {\n const missingIds = requirement.skillIds.filter((reqId) => !selectedSet.has(reqId));\n if (missingIds.length > 0) {\n errors.push({\n type: \"missingRequirement\",\n message: `${getLabel(skill)} requires: ${missingIds.map((id) => getLabel(getSkillById(id))).join(\", \")}`,\n skills: [skillId, ...missingIds],\n });\n }\n }\n }\n }\n\n return errors;\n}\n\nexport function validateExclusivity(resolvedSelections: SkillId[]): ValidationError[] {\n const errors: ValidationError[] = [];\n\n const validSkills = resolvedSelections\n .map((skillId) => ({ skillId, skill: matrix.skills[skillId] }))\n .filter((entry): entry is { skillId: SkillId; skill: ResolvedSkill } => entry.skill != null);\n const categorySelections = groupBy(validSkills, (entry) => entry.skill.category);\n\n for (const [categoryId, entries] of typedEntries(categorySelections)) {\n if (entries.length > 1) {\n const skillIds = entries.map((e) => e.skillId);\n // \"local\" is a pseudo-category without exclusivity rules\n if (categoryId === LOCAL_PSEUDO_CATEGORY) continue;\n const category = matrix.categories[categoryId];\n if (category?.exclusive) {\n errors.push({\n type: \"categoryExclusive\",\n message: `Category \"${category.displayName}\" only allows one selection, but multiple selected: ${skillIds.map((id) => getLabel(getSkillById(id))).join(\", \")}`,\n skills: skillIds,\n });\n }\n }\n }\n\n return errors;\n}\n\n/**\n * Validates a complete set of skill selections against all matrix constraints.\n *\n * Runs three validation passes:\n * 1. **Conflicts** - Checks for mutually exclusive skill pairs (errors)\n * 2. **Requirements** - Checks that all required dependencies are selected (errors)\n * 3. **Exclusivity** - Checks that exclusive categories have at most one selection (errors)\n *\n * `valid` is derived from `errors` rather than asserted: a literal `true` beside a populated\n * `errors` array is a comment with a type annotation, and the first `if (validation.valid)`\n * written against it would pass on every rejected selection there is.\n *\n * @param selections - Complete list of selected skill IDs to validate\n * @returns Validation result with `valid` flag and error list\n */\nexport function validateSelection(selections: SkillId[]): SelectionValidation {\n const { resolvedSelections, selectedSet } = initializeSelectionContext(selections);\n\n const errors = [\n ...validateConflicts(resolvedSelections),\n ...validateRequirements(resolvedSelections, selectedSet),\n ...validateExclusivity(resolvedSelections),\n ];\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Builds a list of skill options for a category: which are selected, and which of\n * those are still waiting on a requirement.\n *\n * It deliberately states no advisory verdict. {@link getCellState} is the one that\n * does, because a cell is judged against the selection a click on it would produce\n * — inside a pick-one category the swap forgives a conflict that a raw per-option\n * advisory would still report. The raw advisory this function used to carry was\n * therefore not merely unread but the wrong answer for its only caller,\n * `buildCategoriesForDomain` in `lib/wizard/build-step-logic.ts`, which has always\n * called `getCellState` instead.\n *\n * @param categoryId - Category path to filter skills by\n * @param currentSelections - Currently selected skill IDs\n * @returns Array of skill options with their selection state\n */\nexport function getAvailableSkills(\n categoryId: CategoryPath,\n currentSelections: SkillId[],\n): SkillOption[] {\n const { selectedSet } = initializeSelectionContext(currentSelections);\n\n return getSkillsByCategory(categoryId).map((skill) => {\n const isSelected = selectedSet.has(skill.id);\n return {\n id: skill.id,\n selected: isSelected,\n hasUnmetRequirements: isSelected && hasUnmetRequirements(skill.id, currentSelections),\n ...unmetRequirementsReasonFor(isSelected, skill.id, currentSelections),\n };\n });\n}\n\n/** Returns all resolved skills belonging to the given category. */\nexport function getSkillsByCategory(categoryId: CategoryPath): ResolvedSkill[] {\n return allSkills().filter((skill) => skill.category === categoryId);\n}\n","import type { SkillId, SkillSlug } from \"../../types\";\n\n/**\n * Post-decision-2 vocabulary: conflict groups no longer exist as a mechanism, so a skill is\n * fenced by category exclusivity, by a `requires` rule, or not at all.\n */\nexport type AuditVerdict = \"constrained-via-exclusivity-or-requires\" | \"universal\";\n\n/** The framework-adapter classification rides this manifest — one audit, two products. */\nexport type SkillClass = \"A\" | \"B\" | \"C\";\n\n/** Worksheet batch that produced a verdict — provenance for the adversarial pass. */\nexport type BatchId =\n | \"web-core\"\n | \"web-state\"\n | \"web-ui\"\n | \"web-platform\"\n | \"api-core\"\n | \"api-data\"\n | \"api-services\"\n | \"ai\"\n | \"mobile\"\n | \"desktop\"\n | \"infra-cli\"\n | \"shared-meta\";\n\nexport type SkillAuditEntry = {\n /** ISO date the verdict was established or last re-confirmed. */\n audited: `${number}-${number}-${number}`;\n verdict: AuditVerdict;\n batch: BatchId;\n /**\n * Framework-adapter classification. Omitted for the framework skills themselves\n * (react, nextjs, react-native, electron, tauri, …) which are the binding targets.\n * class A → frameworks: []; class B → exactly one; class C → the adapter set.\n */\n classification?: { class: SkillClass; frameworks: SkillSlug[] };\n /** Cited sources — recorded wherever the entry changed a rule. */\n sources?: string[];\n /** Anything the current vocabulary cannot express, deferred rather than invented here. */\n deferredToD306?: string;\n};\n\n/**\n * Every catalog skill's audit verdict, one entry per skill.\n *\n * Total record, not `Partial`: the type checker enforces \"every SkillId appears\" at compile\n * time, so the \"empty = unaudited, or nobody looked?\" ambiguity is unrepresentable for\n * built-ins. Source-provided skills cannot be covered that way — `checkMatrixHealth` carries\n * the runtime assertion for those.\n *\n * Verdicts were recorded as of the audit, assuming the batches' category dispositions would\n * land; they have, so every row is backed by the live rules and\n * `auditVerdictsPendingApply` below — the exemption list for rows the tree has not caught up\n * with — is empty.\n */\nexport const skillAudit: Record<SkillId, SkillAuditEntry> = {\n // ── B1 — web core: frameworks, meta-frameworks, routing, server state (20) ──\n \"web-framework-react\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n },\n \"web-framework-vue-composition-api\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n },\n \"web-framework-angular-standalone\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n },\n \"web-framework-solidjs\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n },\n \"web-framework-svelte\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n },\n \"web-meta-framework-nextjs\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n },\n \"web-meta-framework-remix\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n },\n \"web-meta-framework-nuxt\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n },\n \"web-meta-framework-sveltekit\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n },\n \"web-meta-framework-astro\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n },\n \"web-meta-framework-qwik\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n },\n \"web-meta-framework-docusaurus\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n classification: { class: \"A\", frameworks: [] },\n sources: [\"https://docusaurus.io\"],\n },\n \"web-meta-framework-vitepress\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n classification: { class: \"A\", frameworks: [] },\n sources: [\"https://github.com/honojs/website\", \"https://vitepress.dev\"],\n },\n \"web-routing-react-router\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n sources: [\"https://reactrouter.com\"],\n },\n \"web-routing-tanstack-router\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n deferredToD306:\n \"Solid trigger: widen to needsAny [react, solidjs] if Solid content lands in the body (the official @tanstack/solid-router adapter already shipped upstream).\",\n },\n \"web-server-state-react-query\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n deferredToD306:\n \"The hey-api MUST beside tRPC: the MUST reads literally (generated query options from hey-api — never write custom React Query hooks) and sits in tension beside tRPC-generated options in a hybrid stack; if that MUST is ever re-cut to claim ALL server data, the coexistence rationale reopens.\",\n },\n \"web-data-fetching-swr\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-data-fetching-trpc\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-data-fetching-graphql-apollo\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-data-fetching-graphql-urql\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-core\",\n classification: {\n class: \"C\",\n frameworks: [\"react\", \"vue-composition-api\", \"solidjs\", \"svelte\"],\n },\n },\n\n // ── B2 — web state, forms, i18n, utilities (19) ──\n \"web-state-jotai\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n deferredToD306:\n \"Jotai beside a store library is a real pattern (atomic UI atoms beside a domain store) with an official bridge extension (jotai-zustand / atomWithStore) but no vendor-documented two-peers steady state; unrepresentable while the zustand skill's MUST is territorial. Reopen trigger: the zustand MUST being re-cut to store-shaped state.\",\n },\n \"web-state-mobx\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-state-redux-toolkit\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-state-zustand\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-state-pinia\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: { class: \"B\", frameworks: [\"vue-composition-api\"] },\n },\n \"web-state-ngrx-signalstore\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: { class: \"B\", frameworks: [\"angular-standalone\"] },\n },\n \"web-forms-react-hook-form\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-forms-tanstack-form\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: {\n class: \"C\",\n frameworks: [\"react\", \"vue-composition-api\", \"angular-standalone\", \"solidjs\"],\n },\n deferredToD306:\n \"Svelte-widening trigger: widen the needsAny to svelte/sveltekit when Svelte content lands in the body (@tanstack/svelte-form is stable upstream; the skill claims React/Vue/Solid/Angular/Lit only).\",\n },\n \"web-forms-vee-validate\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: { class: \"B\", frameworks: [\"vue-composition-api\"] },\n },\n \"web-forms-zod-validation\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-state\",\n classification: { class: \"A\", frameworks: [] },\n sources: [\"https://zod.dev\"],\n },\n \"web-error-handling-error-boundaries\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-error-handling-result-types\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-state\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-i18n-next-intl\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: { class: \"B\", frameworks: [\"nextjs\"] },\n },\n \"web-i18n-react-intl\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-i18n-vue-i18n\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: { class: \"B\", frameworks: [\"vue-composition-api\"] },\n },\n \"web-utilities-rxjs\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-state\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-utilities-date-fns\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-state\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-utilities-vueuse\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-state\",\n classification: { class: \"B\", frameworks: [\"vue-composition-api\"] },\n },\n \"web-utilities-native-js\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-state\",\n classification: { class: \"A\", frameworks: [] },\n },\n\n // ── B3 — web UI, styling, animation, editors (22) ──\n \"web-ui-shadcn-ui\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-ui-mui\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"C\", frameworks: [\"react\", \"nextjs\"] },\n },\n \"web-ui-chakra-ui\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-ui-mantine\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-ui-ant-design\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"C\", frameworks: [\"react\", \"nextjs\"] },\n },\n \"web-ui-vuetify\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"B\", frameworks: [\"vue-composition-api\"] },\n },\n \"web-ui-radix-ui\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-ui-headless-ui\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-ui-base-ui\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n sources: [\"https://base-ui.com\"],\n },\n \"web-ui-tanstack-table\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-styling-tailwind\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-ui\",\n classification: { class: \"C\", frameworks: [] },\n },\n \"web-styling-scss-modules\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-ui\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"tailwind <-> scss-modules coexistence is documented (Tailwind's own compatibility page allows but discourages it) — a discourages-shaped pair, no fence today.\",\n },\n \"web-styling-cva\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-ui\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-styling-theming\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-ui\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-styling-design-tokens\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-ui\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-animation-framer-motion\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-animation-css-animations\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-ui\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-animation-view-transitions\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-ui\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-editor-lexical\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n sources: [\"https://lexical.dev\"],\n },\n \"web-editor-tiptap\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"C\", frameworks: [\"react\", \"vue-composition-api\"] },\n },\n \"web-3d-react-three-fiber\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n sources: [\"https://r3f.docs.pmnd.rs\"],\n },\n \"web-dnd-dnd-kit\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-ui\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n sources: [\n \"skill body (DndContext/useDraggable/useDroppable/useSortable; every import a @dnd-kit/* React package)\",\n 'npm @dnd-kit/core (\"a lightweight React library\")',\n ],\n },\n\n // ── B4 — web platform, testing, tooling (23) ──\n \"web-testing-playwright-e2e\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-platform\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-testing-cypress-e2e\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-platform\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"Cypress component testing beside Playwright E2E is unrepresentable — carried by the cy.mount slice; 2026 guidance keys the CT tool to the incumbent E2E runner, so the radio holds.\",\n },\n \"web-testing-react-testing-library\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-platform\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-testing-vue-test-utils\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-platform\",\n classification: { class: \"B\", frameworks: [\"vue-composition-api\"] },\n },\n \"web-testing-vitest\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-platform\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-testing-visual-regression\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-platform\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"Pairs with a capture harness (playwright / cypress / storybook) — advice only; enumerating the harnesses would misstate BackstopJS/Percy-class setups.\",\n },\n \"web-tooling-storybook\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-platform\",\n classification: {\n class: \"C\",\n frameworks: [\n \"react\",\n \"vue-composition-api\",\n \"angular-standalone\",\n \"solidjs\",\n \"svelte\",\n \"qwik\",\n ],\n },\n sources: [\"https://storybook.js.org/docs/configure/integration/frameworks\"],\n deferredToD306:\n \"A community Astro framework exists (storybook-astro.org) but is not official — astro stays fenced out today. Package-health watch: storybook-framework-qwik 0.6.1, personal repo, trails Storybook 10.x.\",\n },\n \"web-tooling-vite\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-platform\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"vite <-> nextjs and vite <-> docusaurus are dubious combos (discourages-shaped, advice not fence) — with the 6-of-15 vite-carrying default-stack rosters that also pin nextjs named as curation debt for the stack owner.\",\n },\n \"web-tooling-component-library\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-platform\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n sources: [\n 'skill body (self-scope on all three surfaces; 3 of 5 MUSTs React/RSC-keyed; the \"use client\" contract)',\n ],\n },\n \"web-realtime-websockets\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-platform\",\n classification: { class: \"C\", frameworks: [\"react\"] },\n },\n \"web-realtime-socket-io\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-platform\",\n classification: { class: \"C\", frameworks: [\"react\"] },\n deferredToD306:\n \"A native-WebSocket third-party feed beside Socket.IO-to-own-server (the external service dictates the protocol) is a scope split the radio cannot express.\",\n },\n \"web-realtime-sse\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-platform\",\n classification: { class: \"C\", frameworks: [\"react\"] },\n },\n \"web-pwa-service-workers\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-platform\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-pwa-offline-first\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-platform\",\n classification: { class: \"C\", frameworks: [\"react\"] },\n },\n \"web-dataviz-d3\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-platform\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-dataviz-recharts\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-platform\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n sources: [\"https://recharts.org\"],\n },\n \"web-maps-leaflet\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-platform\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-maps-mapbox\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-platform\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"mapbox-gl-leaflet embedding (the Leaflet API drives a non-interactive GL layer, so half the mapbox skill applies and half must not be followed); Mapbox-as-tile-service needs no skill pairing at all.\",\n },\n \"web-mocks-msw\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-platform\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"web-files-file-upload-patterns\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-platform\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-files-image-handling\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"web-platform\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n },\n \"web-performance-web-performance\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-platform\",\n classification: { class: \"C\", frameworks: [\"react\"] },\n },\n \"web-accessibility-web-accessibility\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"web-platform\",\n classification: { class: \"A\", frameworks: [] },\n },\n\n // ── B5 — api core: frameworks, GraphQL, auth, cross-cutting (17) ──\n \"api-framework-hono\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-core\",\n },\n \"api-framework-express\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-core\",\n },\n \"api-framework-fastify\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-core\",\n },\n \"api-framework-nestjs\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-core\",\n },\n \"api-framework-elysia\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-core\",\n },\n \"api-graphql-apollo-server\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-core\",\n classification: { class: \"C\", frameworks: [\"express\", \"fastify\"] },\n },\n \"api-graphql-yoga\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-core\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-graphql-mercurius\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-core\",\n classification: { class: \"B\", frameworks: [\"fastify\"] },\n sources: [\n 'skill body (\"When NOT to use: Not using Fastify (Mercurius is Fastify-only)\")',\n \"mercurius README (npm i fastify mercurius graphql; app.register(mercurius))\",\n ],\n },\n \"api-auth-better-auth-drizzle-hono\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-core\",\n classification: { class: \"B\", frameworks: [\"hono\"] },\n sources: [\n 'skill body (app.on([\"POST\",\"GET\"], \"/auth/*\", …); createMiddleware<{ Variables: AuthVariables }>; c.req.raw)',\n \"https://better-auth.com\",\n ],\n },\n \"api-auth-nextauth\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-core\",\n classification: { class: \"B\", frameworks: [\"nextjs\"] },\n sources: [\"https://authjs.dev\"],\n },\n \"api-auth-clerk\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-core\",\n classification: { class: \"B\", frameworks: [\"nextjs\"] },\n },\n \"api-specs-openapi\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"api-core\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-messaging-webhooks\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"api-core\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-caching-strategies\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"api-core\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-queue-bullmq\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-core\",\n classification: { class: \"A\", frameworks: [] },\n sources: [\n \"https://docs.bullmq.io/guide/redis-tm-compatibility\",\n \"https://upstash.com/docs/redis/integrations/bullmq\",\n ],\n deferredToD306:\n \"BullMQ polls Redis even when idle, so Upstash's per-request Pay-As-You-Go pricing balloons (Upstash recommends a Fixed plan) — curation advice, not a fence.\",\n },\n \"api-performance-api-performance\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"api-core\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-commerce-stripe\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"api-core\",\n classification: { class: \"A\", frameworks: [] },\n },\n\n // ── B6 — api data: databases and BaaS (22) ──\n \"api-database-postgresql\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-database-mysql\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-database-cockroachdb\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-database-drizzle\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-database-prisma\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"Prisma-on-Mongo overlaps mongoose as a full Mongo data layer; the pair is deliberately unfenced across the sql-engine/document radios (accepted over-permissiveness).\",\n },\n \"api-database-sequelize\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-database-typeorm\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-database-knex\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-database-mongodb\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-database-mongoose\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-database-edgedb\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-database-surrealdb\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-database-redis\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-database-upstash\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-database-vercel-kv\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"vercel-kv -> requires [vercel] deferred, not adopted: product-true (only provisionable on Vercel) but the product is discontinued (Dec 2024) and retirement is the better disposition.\",\n },\n \"api-database-vercel-postgres\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"vercel-postgres -> requires [vercel] deferred, not adopted: product-true but the product is discontinued (auto-migrated to Neon) and retirement is the better disposition.\",\n },\n \"api-baas-supabase\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-baas-firebase\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-baas-appwrite\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-baas-neon\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-baas-planetscale\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-baas-turso\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-data\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"turso as an edge-replica secondary beside a primary Postgres host is a real minority pattern the api-db-host radio over-restricts — accepted.\",\n },\n\n // ── B7 — api services: vector, search, CMS, analytics, observability, email (16) ──\n \"api-vector-db-pinecone\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-services\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-vector-db-qdrant\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-services\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-vector-db-chroma\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-services\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"chroma <-> pinecone dev/prod graduation split is the one real minority pattern the vector-db radio blocks.\",\n },\n \"api-vector-db-weaviate\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-services\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-search-elasticsearch\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-services\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"Elasticsearch-for-logs beside Meilisearch-for-product-search is a real dual-role coexistence the api-search radio blocks.\",\n },\n \"api-search-meilisearch\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-services\",\n classification: { class: \"A\", frameworks: [] },\n },\n // Landed by external PR (agents-inc/skills#2) after the B7 batch closed; verdict follows\n // its api-search siblings — the category radio is the constraint, no rules of its own.\n \"api-search-xquik\": {\n audited: \"2026-08-09\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-services\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-cms-payload\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-services\",\n classification: { class: \"C\", frameworks: [\"nextjs\"] },\n deferredToD306:\n \"payload's full surface (admin panel, mounted REST/GraphQL) is Next-hosted today; the taught surface (config, collections, access control, hooks, Local API) is the documented headless mode and host-neutral — the nextjs pairing is recommends-shaped. Re-derive if the body grows Next mounting content, or when the 4.0 framework adapters land.\",\n },\n \"api-cms-sanity\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-services\",\n classification: { class: \"C\", frameworks: [\"react\"] },\n },\n \"api-cms-strapi\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-services\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"api-analytics-setup-posthog\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"api-services\",\n classification: { class: \"C\", frameworks: [\"react\"] },\n },\n \"api-flags-posthog-flags\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"api-services\",\n classification: { class: \"C\", frameworks: [\"react\"] },\n },\n \"api-analytics-posthog-analytics\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"api-services\",\n classification: { class: \"C\", frameworks: [\"react\"] },\n },\n \"api-observability-setup-axiom-pino-sentry\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-services\",\n classification: { class: \"C\", frameworks: [\"nextjs\"] },\n sources: [\n \"skill body (next-axiom, @sentry/nextjs, next.config.ts wrapped withAxiom(withSentryConfig(...)), instrumentation.ts, sentry.{client,server,edge}.config.ts)\",\n 'todo/skills.md — \"Next-only in all but name\"',\n ],\n },\n \"api-observability-axiom-pino-sentry\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"api-services\",\n classification: { class: \"C\", frameworks: [\"react\"] },\n },\n \"api-email-setup-resend\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-services\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n sources: [\"https://react.email/docs\"],\n },\n \"api-email-resend-react-email\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"api-services\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n deferredToD306:\n \"React-as-template-renderer is not React-as-app-framework: React Email runs in any Node backend, but because react sits in the exclusive web-framework radio the rule fences every Vue/Svelte/Angular project out of the catalog's only email-usage skill.\",\n },\n\n // ── B8 — ai (20) ──\n \"ai-provider-anthropic-sdk\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-provider-openai-sdk\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-provider-google-gemini-sdk\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-provider-mistral-sdk\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-provider-cohere-sdk\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-provider-elevenlabs\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-provider-claude-vision\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-provider-openai-whisper\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-infrastructure-huggingface-inference\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-infrastructure-together-ai\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-infrastructure-litellm\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"Wire-protocol reuse is not a skill dependency: litellm's TypeScript client literally is new OpenAI({ baseURL }), but the body carries its own complete client pointed away from OpenAI, so it derives no requires [openai-sdk].\",\n },\n \"ai-infrastructure-replicate\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-infrastructure-modal\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-infrastructure-ollama\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-orchestration-langchain\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-orchestration-llamaindex\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-orchestration-vercel-ai-sdk\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"C\", frameworks: [\"react\"] },\n },\n \"ai-observability-langfuse\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-observability-promptfoo\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"ai-patterns-tool-use-patterns\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"ai\",\n classification: { class: \"A\", frameworks: [] },\n },\n\n // ── B9 — mobile (24) ──\n \"mobile-framework-react-native\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n },\n \"mobile-framework-expo\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n },\n \"mobile-navigation-react-navigation\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\"https://reactnavigation.org\"],\n },\n \"mobile-navigation-expo-router\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"expo\"] },\n sources: [\"https://docs.expo.dev/router/installation/\"],\n },\n \"mobile-styling-nativewind\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\"https://www.nativewind.dev\"],\n },\n \"mobile-styling-unistyles\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\"https://www.unistyl.es\"],\n },\n \"mobile-testing-detox\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\"https://github.com/wix/Detox\"],\n },\n \"mobile-testing-maestro\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"A\", frameworks: [] },\n sources: [\"https://docs.maestro.dev/get-started/supported-platform\"],\n deferredToD306:\n \"Needs an app Maestro can drive; the needsAny enumerates the catalog's current mobile-app producers (react-native, expo, tauri-mobile) — re-derive when that set changes.\",\n },\n \"mobile-ui-components-tamagui\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"C\", frameworks: [\"react-native\", \"react\"] },\n sources: [\"https://tamagui.dev/docs/intro/installation\", \"https://github.com/tamagui/tamagui\"],\n deferredToD306:\n \"Surfaces a mobile-domain UI kit in web-only stacks — a curation question for the web-ui-kit split (group #14), advice-level only.\",\n },\n \"mobile-ui-components-react-native-paper\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\"https://callstack.github.io/react-native-paper/\"],\n },\n \"mobile-animation-reanimated\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\"https://docs.swmansion.com/react-native-reanimated/\"],\n },\n \"mobile-animation-gesture-handler\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\"https://docs.swmansion.com/react-native-gesture-handler/\"],\n },\n \"mobile-animation-skia\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\"https://shopify.github.io/react-native-skia/\"],\n },\n \"mobile-storage-mmkv\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\"https://github.com/mrousavy/react-native-mmkv\"],\n },\n \"mobile-storage-sqlite-powersync\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\"https://docs.powersync.com/resources/supported-platforms\"],\n },\n \"mobile-storage-watermelondb\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\"https://watermelondb.dev/docs/Implementation/DatabaseAdapters\"],\n deferredToD306:\n \"Upstream runs on React web via the LokiJS adapter; widen the binding if and only if the skill body ever covers it.\",\n },\n \"mobile-deployment-eas\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"expo\"] },\n sources: [\"https://docs.expo.dev/build/introduction/\"],\n },\n \"mobile-camera-vision-camera\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\"https://react-native-vision-camera.com\"],\n },\n \"mobile-hardware-ble-nfc\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\n \"https://github.com/dotintent/react-native-ble-plx\",\n \"https://github.com/revtel/react-native-nfc-manager\",\n ],\n },\n \"mobile-notifications-push\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\n \"https://docs.expo.dev/push-notifications/overview/\",\n \"https://rnfirebase.io/messaging/usage\",\n ],\n },\n \"mobile-background-tasks\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\n \"https://docs.expo.dev/versions/latest/sdk/background-task/\",\n \"https://github.com/transistorsoft/react-native-background-fetch\",\n ],\n },\n \"mobile-deep-linking-app-links\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\n \"https://docs.expo.dev/linking/overview/\",\n \"https://reactnavigation.org/docs/deep-linking/\",\n ],\n },\n \"mobile-performance-react-native\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\"https://reactnative.dev/docs/performance\"],\n },\n \"mobile-security-react-native\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"mobile\",\n classification: { class: \"B\", frameworks: [\"react-native\"] },\n sources: [\n \"https://docs.expo.dev/versions/latest/sdk/securestore/\",\n \"https://github.com/oblador/react-native-keychain\",\n ],\n },\n\n // ── B10 — desktop (16) ──\n \"desktop-framework-electron\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n },\n \"desktop-framework-tauri\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n },\n \"desktop-ipc-electron\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"electron\"] },\n sources: [\"https://www.electronjs.org/docs/latest/tutorial/ipc\"],\n },\n \"desktop-storage-electron\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"electron\"] },\n sources: [\n \"https://www.electronjs.org/docs/latest/api/safe-storage\",\n \"https://github.com/sindresorhus/electron-store\",\n ],\n },\n \"desktop-ui-electron\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"electron\"] },\n sources: [\"https://www.electronjs.org/docs/latest/api/tray\"],\n },\n \"desktop-testing-electron\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"electron\"] },\n sources: [\"https://playwright.dev/docs/api/class-electron\"],\n },\n \"desktop-updates-electron-updater\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"electron\"] },\n sources: [\n \"https://github.com/electron-userland/electron-builder\",\n \"https://www.electron.build/auto-update\",\n ],\n deferredToD306:\n \"Defaults to the electron-builder pipeline (reads app-update.yml, written only by electron-builder's PublishManager); Forge apps using the Squirrel maker use Electron's built-in autoUpdater instead; Forge without Squirrel, and custom distributions, can still run electron-updater with custom config / generic provider.\",\n },\n \"desktop-multiwindow-electron\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"electron\"] },\n sources: [\"https://www.electronjs.org/docs/latest/api/base-window\"],\n },\n \"desktop-security-electron\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"electron\"] },\n sources: [\"https://www.electronjs.org/docs/latest/tutorial/fuses\"],\n },\n \"desktop-packaging-electron-forge\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"electron\"] },\n sources: [\"https://www.electronforge.io\"],\n },\n \"desktop-backend-tauri\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"tauri\"] },\n sources: [\"https://v2.tauri.app/develop/calling-rust/\"],\n },\n \"desktop-packaging-tauri\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"tauri\"] },\n sources: [\"https://v2.tauri.app/distribute/\"],\n },\n \"desktop-plugins-tauri\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"tauri\"] },\n sources: [\"https://v2.tauri.app/plugin/\"],\n },\n \"desktop-multiwindow-tauri\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"tauri\"] },\n sources: [\"https://v2.tauri.app/develop/calling-frontend/\"],\n },\n \"desktop-security-tauri\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"tauri\"] },\n sources: [\"https://v2.tauri.app/security/capabilities/\"],\n },\n \"desktop-mobile-tauri\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"desktop\",\n classification: { class: \"B\", frameworks: [\"tauri\"] },\n sources: [\n \"https://v2.tauri.app/reference/cli\",\n \"https://v2.tauri.app/blog/roadmap-to-tauri-2-0\",\n ],\n },\n\n // ── B11 — infra + CLI (15) ──\n \"infra-ci-cd-github-actions\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"infra-cli\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"infra-ci-cd-docker\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"infra-cli\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"infra-ci-cd-turborepo-ci\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"infra-cli\",\n classification: { class: \"B\", frameworks: [\"turborepo\"] },\n sources: [\"https://turborepo.dev/docs\"],\n },\n \"infra-config-setup-env\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"infra-cli\",\n classification: { class: \"C\", frameworks: [\"nextjs\", \"vite\"] },\n },\n \"infra-containers-kubernetes\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"infra-cli\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"infra-iac-terraform\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"infra-cli\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"Layered terraform + pulumi coexistence via Pulumi's RemoteStateReference (a Pulumi program consuming the outputs of a Terraform-managed layer) is real at org scope; the radio models one engine per project.\",\n },\n \"infra-iac-pulumi\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"infra-cli\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"infra-iac-sst\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"infra-cli\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"sst's typical data plane is @aws-sdk/client-* — the sst skill's own handlers import it; the pairing is recommended, not required, and platform-boundness (SST needs AWS-the-platform, which has no catalog anchor) is unrepresentable in the current vocabulary.\",\n },\n \"infra-platform-vercel\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"infra-cli\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"vercel <-> netlify is a same-slot tension (one primary Git-centric host per app; monorepo split-hosting and migrations are the minority) and vercel <-> cloudflare-workers-as-host is the same shape — dubious combos, declined as fences.\",\n },\n \"infra-platform-netlify\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"infra-cli\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"Carries the same dubious-combo record as vercel: vercel <-> netlify is a same-slot tension declined as a fence.\",\n },\n \"infra-platform-cloudflare-workers\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"infra-cli\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"infra-platform-aws-sdk\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"infra-cli\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"cli-framework-cli-commander\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"infra-cli\",\n },\n \"cli-framework-oclif-ink\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"infra-cli\",\n },\n \"cli-prompts-clack\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"infra-cli\",\n classification: { class: \"A\", frameworks: [] },\n },\n\n // ── B12 — shared + meta (23) ──\n \"shared-monorepo-turborepo\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"shared-monorepo-nx\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"shared-monorepo-pnpm-workspaces\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"shared-tooling-biome\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n deferredToD306:\n \"The steady-state Biome-as-formatter plus bare-ESLint-for-plugin-gaps hybrid is real; it is unrepresentable while the catalog's ESLint skill bundles Prettier. A future bare eslint skill reopens this radio's rationale.\",\n },\n \"shared-tooling-eslint-prettier\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"shared-tooling-typescript-config\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"shared-tooling-git-hooks\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"shared-tooling-changesets\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"meta-config-stack-detect\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"shared-security-auth-security\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"meta-design-expressive-typescript\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"meta-design-composable-components\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"shared-meta\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n sources: [\n 'skill body and all four example files (imports from \"react\"; @base-ui/react/use-render; @base-ui/react/merge-props; forwardRef; JSX-part composition)',\n ],\n },\n \"meta-methodology-research-methodology\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"meta-planning-web-planning\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"meta-planning-api-planning\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"meta-planning-cli-planning\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"meta-planning-ai-planning\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"meta-reviewing-reviewing\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"meta-reviewing-web-reviewing\": {\n audited: \"2026-08-07\",\n verdict: \"constrained-via-exclusivity-or-requires\",\n batch: \"shared-meta\",\n classification: { class: \"B\", frameworks: [\"react\"] },\n sources: [\n 'skill body self-scope (description \"Use when reviewing React components\"; When-to-use \".tsx/.jsx with JSX\"; \"React PR review\" auto-detection) plus a React-keyed majority (4 of 5 MUSTs, 6 of 7 patterns)',\n ],\n },\n \"meta-reviewing-api-reviewing\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"meta-reviewing-cli-reviewing\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"meta-reviewing-ai-reviewing\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n \"meta-reviewing-infra-reviewing\": {\n audited: \"2026-08-07\",\n verdict: \"universal\",\n batch: \"shared-meta\",\n classification: { class: \"A\", frameworks: [] },\n },\n};\n\n/**\n * Rows whose verdict was recorded ahead of the category disposition that backs it, with the\n * batch that owns the change. Both audit checks skip exactly these and nothing else, so any\n * other divergence between the manifest and the rules fails immediately.\n *\n * Empty since every disposition the fan-out ruled on landed: the live rules now back all 238\n * verdicts on their own. It stays as the mechanism for the next audit that runs ahead of its\n * taxonomy — add an entry with the batch that owns it, and delete it when that lands. The\n * consistency test asserts this set matches the live gap exactly, so a stale entry fails just\n * as loudly as a missing one.\n */\nexport const auditVerdictsPendingApply: Partial<Record<SkillId, string>> = {};\n","import { warn } from \"../../utils/logger\";\nimport { LOCAL_PSEUDO_CATEGORY } from \"../../consts\";\nimport type {\n CategoryDefinition,\n CategoryPath,\n MergedSkillsMatrix,\n ResolvedSkill,\n SkillId,\n Category,\n} from \"../../types\";\nimport { isSkillId } from \"../../utils/type-guards\";\nimport { typedEntries } from \"../../utils/typed-object\";\nimport { skillAudit, auditVerdictsPendingApply } from \"../configuration/skill-audit\";\nimport type { SkillAuditEntry } from \"../configuration/skill-audit\";\n\n/**\n * Which check produced an issue. A closed union rather than a free string because a caller may\n * branch on one kind — `source-validator` weighs `rule-unresolved-slug` differently for the\n * author of a marketplace than for someone consuming it — and a misspelled branch there must be\n * a compile error rather than a condition that is quietly never true.\n */\ntype MatrixHealthFinding =\n | \"category-missing-domain\"\n | \"skill-unknown-category\"\n | \"skill-unresolved-relation-ref\"\n | \"rule-unresolved-slug\"\n | \"audit-verdict-contradiction\"\n | \"skill-unaudited\";\n\nexport type MatrixHealthIssue = {\n severity: \"warning\" | \"error\";\n finding: MatrixHealthFinding;\n details: string;\n};\n\nexport function checkMatrixHealth(matrix: MergedSkillsMatrix): MatrixHealthIssue[] {\n const issues = [\n ...checkCategoryDomains(matrix),\n ...checkSkillCategories(matrix),\n ...checkSkillRelationRefs(matrix),\n ...checkUnresolvedRuleSlugs(matrix),\n ...checkAuditVerdictContradictions(matrix),\n ...checkUnauditedSkills(matrix),\n ];\n\n for (const issue of issues) {\n warn(`[matrix] ${issue.details}`);\n }\n\n return issues;\n}\n\n// Categories without a domain won't appear in any wizard domain view\nfunction checkCategoryDomains(matrix: MergedSkillsMatrix): MatrixHealthIssue[] {\n return (\n typedEntries<Category, CategoryDefinition>(matrix.categories)\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n .filter(([, cat]) => cat !== undefined && !cat.domain)\n .map(([catId]) => ({\n severity: \"warning\" as const,\n finding: \"category-missing-domain\",\n details: `Category '${catId}' has no domain — it won't appear in any wizard domain view`,\n }))\n );\n}\n\nfunction checkSkillCategories(matrix: MergedSkillsMatrix): MatrixHealthIssue[] {\n return typedEntries<SkillId, ResolvedSkill>(matrix.skills)\n .filter(\n ([, skill]) =>\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n skill !== undefined &&\n // \"local\" is a pseudo-category that won't exist in matrix.categories — skip it\n skill.category !== LOCAL_PSEUDO_CATEGORY &&\n !matrix.categories[skill.category],\n )\n .map(([skillId, skill]) => ({\n severity: \"warning\" as const,\n finding: \"skill-unknown-category\",\n details: `Skill '${skillId}' references category '${skill.category}' which does not exist in the matrix`,\n }));\n}\n\n/** Every outgoing relation reference on a skill, tagged with the field it came from. */\nfunction relationRefs(skill: ResolvedSkill): Array<{ field: string; ref: SkillId }> {\n return [\n ...skill.conflictsWith.map((relation) => ({ field: \"conflictsWith\", ref: relation.skillId })),\n ...skill.requires.flatMap((requirement) =>\n requirement.skillIds.map((ref) => ({ field: \"requires\", ref })),\n ),\n ];\n}\n\nfunction checkSkillRelationRefs(matrix: MergedSkillsMatrix): MatrixHealthIssue[] {\n return typedEntries<SkillId, ResolvedSkill>(matrix.skills).flatMap(([skillId, skill]) =>\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n skill === undefined\n ? []\n : relationRefs(skill)\n .filter(({ ref }) => !matrix.skills[ref])\n .map(({ field, ref }) => ({\n severity: \"warning\" as const,\n finding: \"skill-unresolved-relation-ref\",\n details: `Skill '${skillId}' has unresolved reference '${ref}' in '${field}'`,\n })),\n );\n}\n\n/**\n * A slug a relationship rule names that no skill carries. The rule containing it\n * states nothing — resolution drops the reference — so the source shipped a rule\n * that cannot act, which is a defect in the source rather than an advisory about\n * it. The CLI's own built-in rules are narrowed to the slugs a source ships\n * before resolution, so nothing here can be the CLI's doing.\n *\n * `error` is the AUTHOR's verdict, and it is the only one this module can reach: a matrix says\n * what is wrong with it and cannot say who is reading. Someone who merely installed from the\n * marketplace can neither open the file nor be harmed by it, and `source-validator` — the one\n * layer that knows which of the two is asking — serves them the same finding as a warning.\n */\nfunction checkUnresolvedRuleSlugs(matrix: MergedSkillsMatrix): MatrixHealthIssue[] {\n return (matrix.unresolvedSlugs ?? []).map((slug) => ({\n severity: \"error\" as const,\n finding: \"rule-unresolved-slug\",\n details: `Unresolved slug '${slug}' in the relationship rules — no skill carries it, so every rule naming it states nothing`,\n }));\n}\n\nfunction isExclusiveCategory(matrix: MergedSkillsMatrix, category: CategoryPath): boolean {\n // \"local\" is a pseudo-category with no definition in matrix.categories — never a fence\n if (category === LOCAL_PSEUDO_CATEGORY) return false;\n\n const definition = matrix.categories[category];\n return definition !== undefined && definition.exclusive;\n}\n\n/**\n * The one definition of \"this skill is fenced\" that the audit's two enforcement points — the\n * runtime contradiction check below and the manifest consistency test — must agree on. Post\n * decision 2 the only fences left are category exclusivity and `requires`.\n */\nexport function isFencedByMatrix(matrix: MergedSkillsMatrix, skillId: SkillId): boolean {\n const skill = matrix.skills[skillId];\n if (skill === undefined) return false;\n\n return skill.requires.length > 0 || isExclusiveCategory(matrix, skill.category);\n}\n\n/** Runtime lookup: the manifest is total over built-ins, but a matrix may carry source skills. */\nfunction auditEntryFor(skillId: SkillId): SkillAuditEntry | undefined {\n return Object.hasOwn(skillAudit, skillId) ? skillAudit[skillId] : undefined;\n}\n\nfunction fenceDescription(matrix: MergedSkillsMatrix, skill: ResolvedSkill): string {\n if (skill.requires.length > 0) return \"it carries a 'requires' rule\";\n return `its category '${skill.category}' is exclusive`;\n}\n\n/**\n * A `universal` verdict claims the skill is selectable beside anything; a `requires` rule or an\n * exclusive category says the opposite. Both cannot be true, so the pair is a contradiction and\n * the audit trail would be lying. Rows in `auditVerdictsPendingApply` are exempt — their verdict\n * was recorded ahead of a category disposition that has not landed yet.\n */\nfunction checkAuditVerdictContradictions(matrix: MergedSkillsMatrix): MatrixHealthIssue[] {\n return typedEntries<SkillId, ResolvedSkill>(matrix.skills)\n .filter(([skillId, skill]) => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n if (skill === undefined || auditVerdictsPendingApply[skillId]) return false;\n const audit = auditEntryFor(skillId);\n\n return audit?.verdict === \"universal\" && isFencedByMatrix(matrix, skillId);\n })\n .map(([skillId, skill]) => ({\n severity: \"error\" as const,\n finding: \"audit-verdict-contradiction\",\n details: `Skill '${skillId}' is audited 'universal' but ${fenceDescription(matrix, skill)}`,\n }));\n}\n\n/**\n * \"Unaudited\" means the manifest was expected to carry a verdict and does not, so the population\n * is the ids the manifest is keyed by: the built-in catalog's. A marketplace's skills carry that\n * marketplace's namespace and are outside the manifest by construction, not unaudited — warning\n * per skill for every one of them would cost a screen of noise and put a clean bill of health out\n * of reach for anyone not on the public catalog. Local skills are the user's own and were already\n * out of scope.\n *\n * `Record<SkillId, SkillAuditEntry>` covers the built-ins exhaustively at compile time, so what\n * remains here is that same totality asserted against a matrix whose keys are open strings at\n * runtime.\n */\nfunction checkUnauditedSkills(matrix: MergedSkillsMatrix): MatrixHealthIssue[] {\n return typedEntries<SkillId, ResolvedSkill>(matrix.skills)\n .filter(\n ([skillId, skill]) =>\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typedEntries/Object.entries launders the `| undefined` a Partial<Record> admits out of its result type, so this guard reads as dead while still covering an explicitly-undefined slot\n skill !== undefined &&\n !skill.local &&\n isSkillId(skillId) &&\n auditEntryFor(skillId) === undefined,\n )\n .map(([skillId]) => ({\n severity: \"warning\" as const,\n finding: \"skill-unaudited\",\n details: `Skill '${skillId}' has no audit verdict — the built-in audit manifest is missing an entry it is meant to carry`,\n }));\n}\n"],"mappings":"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A;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAME,aAAY;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIO,IAAM,aAAa;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,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","names":["os","unique","path","fs","os","fs","os","SKILL_IDS","AGENT_NAMES","AGENT_NAMES","SKILL_IDS","os","path","z","configLoadFailure","z","path","MODEL_NAMES","EFFORT_NAMES","z","MODEL_NAMES","EFFORT_NAMES","path","path","path","os","path","os","path","os","CONTROL_CHAR_PATTERN","z","path","partition","typedEntries","typedKeys","typedFromEntries","isAgentName","isSkillId","typedKeys","partition","typedEntries","typedFromEntries","indexBy","uniqueBy","os","path","path","groupBy","partition","unique","partition","groupBy","path","unique","path","os","indexBy","uniqueBy","groupBy","unique","typedEntries","groupBy","unique","typedKeys","path","path","matrix","path","path","path","path","path","NULL_BYTE_PATTERN","path","path","path","path","parseYaml","path","PLUGIN_MANIFEST_FILE","path","os","path","path","os","os","path","path","os","os","path","unique","parseYaml","path","parseYaml","parseYaml","path","createHash","os","path","createHash","path","os","os","matrix","os","unique","path","os","z","os","SAFE_NAME_PATTERN","os","z","path","fg","path","fg","path","z","z","path","allSkills","path","parseYaml","path","path","path","path","path","path","parseYaml","path","path","parseYaml","unique","uniqueBy","unique","uniqueBy","slug","groupBy","groupBy","validateSelection","matrix","isExclusiveCategory","os","matrix","path","unique"]}
|