agents-inc 0.154.0 → 0.156.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 +55 -0
- package/dist/chunk-2H7UWE2G.js +246 -0
- package/dist/chunk-2H7UWE2G.js.map +1 -0
- package/dist/{chunk-LA3JPESW.js → chunk-4A4L3YIW.js} +5 -5
- package/dist/chunk-4G2YHZIM.js +132 -0
- package/dist/chunk-4G2YHZIM.js.map +1 -0
- package/dist/{chunk-BZ4CZBOM.js → chunk-5F2YR5XV.js} +3 -3
- package/dist/{chunk-CHNA5RVS.js → chunk-5OKLCVM4.js} +3 -3
- package/dist/{chunk-ZU6DAR4S.js → chunk-5QZAK6J7.js} +7 -7
- package/dist/{chunk-ZU6DAR4S.js.map → chunk-5QZAK6J7.js.map} +1 -1
- package/dist/{chunk-NFH6SA62.js → chunk-6RLV45HN.js} +10 -10
- package/dist/{chunk-NFH6SA62.js.map → chunk-6RLV45HN.js.map} +1 -1
- package/dist/{chunk-GUDGCFSF.js → chunk-CLFHC2DK.js} +15 -106
- package/dist/chunk-CLFHC2DK.js.map +1 -0
- package/dist/chunk-D2CAV7MG.js +61 -0
- package/dist/chunk-D2CAV7MG.js.map +1 -0
- package/dist/{chunk-UW44KSYL.js → chunk-F2AMBBIA.js} +6 -6
- package/dist/{chunk-UW44KSYL.js.map → chunk-F2AMBBIA.js.map} +1 -1
- package/dist/{chunk-QQTYMW7N.js → chunk-F5T6TV4Z.js} +206 -73
- package/dist/chunk-F5T6TV4Z.js.map +1 -0
- package/dist/{chunk-K3O3YQYG.js → chunk-G47TDUK3.js} +2 -2
- package/dist/{chunk-AURY6RT6.js → chunk-GS2NZ3GD.js} +8 -8
- package/dist/chunk-GS2NZ3GD.js.map +1 -0
- package/dist/{chunk-5MFJ24VM.js → chunk-H6UTKTLK.js} +104 -250
- package/dist/chunk-H6UTKTLK.js.map +1 -0
- package/dist/{chunk-MJFIO5SX.js → chunk-HG4JPXJT.js} +11 -11
- package/dist/chunk-HG4JPXJT.js.map +1 -0
- package/dist/{chunk-IXEDSKMH.js → chunk-HTYH7CKN.js} +3 -3
- package/dist/{chunk-JC7DBPRD.js → chunk-HXKOIWLU.js} +2 -2
- package/dist/chunk-HXKOIWLU.js.map +1 -0
- package/dist/{chunk-NSJ2S7R5.js → chunk-ILUVL7WM.js} +2 -2
- package/dist/{chunk-R54KIGN2.js → chunk-IO5YBKHV.js} +13 -2
- package/dist/chunk-IO5YBKHV.js.map +1 -0
- package/dist/chunk-IXRZAHZF.js +53 -0
- package/dist/chunk-IXRZAHZF.js.map +1 -0
- package/dist/chunk-JCPANDNR.js +35 -0
- package/dist/chunk-JCPANDNR.js.map +1 -0
- package/dist/{chunk-NKCY2ULI.js → chunk-LJCNUP6M.js} +2 -2
- package/dist/{chunk-PRJD5MMQ.js → chunk-MHRC3KRX.js} +5 -5
- package/dist/chunk-MHRC3KRX.js.map +1 -0
- package/dist/chunk-MO5FGLVS.js +142 -0
- package/dist/chunk-MO5FGLVS.js.map +1 -0
- package/dist/{chunk-Q5FLW4JG.js → chunk-OKH64JZE.js} +2 -2
- package/dist/{chunk-WRRP47PY.js → chunk-PCC4LBKB.js} +2 -2
- package/dist/chunk-PMUABBPG.js +258 -0
- package/dist/chunk-PMUABBPG.js.map +1 -0
- package/dist/{chunk-2IMYK4WN.js → chunk-PNMM5HNX.js} +5 -5
- package/dist/{chunk-AKQ5QISO.js → chunk-QWVXOCXO.js} +6 -6
- package/dist/{chunk-IPJOMAWC.js → chunk-RWOYPOMR.js} +12 -2
- package/dist/{chunk-IPJOMAWC.js.map → chunk-RWOYPOMR.js.map} +1 -1
- package/dist/{chunk-ONWEOS77.js → chunk-SY4X2LND.js} +4 -4
- package/dist/{chunk-XGMOXMS4.js → chunk-TBOVYLQJ.js} +2 -2
- package/dist/{chunk-R7JV22QK.js → chunk-TNGMF4UX.js} +20 -20
- package/dist/{chunk-R7JV22QK.js.map → chunk-TNGMF4UX.js.map} +1 -1
- package/dist/{chunk-7VZV4O6B.js → chunk-UMH2YZKG.js} +14 -5
- package/dist/chunk-UMH2YZKG.js.map +1 -0
- package/dist/{chunk-6CNRMCFM.js → chunk-VPASBA7P.js} +2 -2
- package/dist/{chunk-CBF4ZYV3.js → chunk-WCAUUBHO.js} +1376 -741
- package/dist/chunk-WCAUUBHO.js.map +1 -0
- package/dist/{chunk-V3ENMW7G.js → chunk-WFRTHH3A.js} +3 -3
- package/dist/{chunk-DRKSYJZ2.js → chunk-WTJ3AY33.js} +1 -1
- package/dist/{chunk-DRKSYJZ2.js.map → chunk-WTJ3AY33.js.map} +1 -1
- package/dist/{chunk-XMEIVWAS.js → chunk-WUQ3MTPF.js} +11 -5
- package/dist/{chunk-XMEIVWAS.js.map → chunk-WUQ3MTPF.js.map} +1 -1
- package/dist/{chunk-4VCWL2IG.js → chunk-XAXJWXI4.js} +92 -59
- package/dist/chunk-XAXJWXI4.js.map +1 -0
- package/dist/{chunk-B66SC72V.js → chunk-Y5Y7XHVU.js} +4 -4
- package/dist/{chunk-FMYHWKGG.js → chunk-YO2LTXB4.js} +66 -16
- package/dist/chunk-YO2LTXB4.js.map +1 -0
- package/dist/{chunk-TUQF577Z.js → chunk-ZUAZHDKP.js} +40 -41
- package/dist/chunk-ZUAZHDKP.js.map +1 -0
- package/dist/commands/build/marketplace.js +98 -121
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +8 -8
- package/dist/commands/compile.js +19 -24
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/doctor.js +220 -79
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +549 -75
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +26 -21
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/init.js +41 -39
- package/dist/commands/list.js +11 -11
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/marketplace.js +243 -0
- package/dist/commands/new/marketplace.js.map +1 -0
- package/dist/commands/search.js +16 -14
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/share.js +67 -0
- package/dist/commands/share.js.map +1 -0
- package/dist/commands/uninstall.js +61 -74
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +9 -9
- package/dist/commands/update.js.map +1 -1
- package/dist/components/common/prompt-confirm.js +1 -1
- package/dist/components/common/removal-plan-confirm.js +10 -0
- package/dist/components/common/select-list.js +2 -2
- package/dist/components/wizard/category-grid.js +5 -5
- package/dist/components/wizard/checkbox-grid.js +5 -5
- package/dist/components/wizard/domain-selection.js +11 -11
- package/dist/components/wizard/run-wizard-session.js +29 -28
- package/dist/components/wizard/scroll-affordance.js +2 -2
- package/dist/components/wizard/skill-agent-summary.js +6 -6
- package/dist/components/wizard/source-grid.js +6 -6
- package/dist/components/wizard/stack-selection.js +8 -8
- package/dist/components/wizard/step-agents.js +10 -11
- package/dist/components/wizard/step-build.js +9 -9
- package/dist/components/wizard/step-confirm.js +10 -10
- package/dist/components/wizard/step-sources.js +10 -10
- package/dist/components/wizard/step-stack.js +9 -9
- package/dist/components/wizard/summary-panel.js +9 -9
- package/dist/components/wizard/toast.js +2 -2
- package/dist/components/wizard/wizard-layout.js +14 -14
- package/dist/components/wizard/wizard-tabs.js +2 -2
- package/dist/components/wizard/wizard.js +27 -27
- package/dist/copy-local-skills-NSUTBVLJ.js +14 -0
- package/dist/hooks/init.js +42 -62
- package/dist/hooks/init.js.map +1 -1
- package/dist/load-agent-defs-X4E57I2U.js +15 -0
- package/dist/{loader-JIZDTR4G.js → loader-G6BFG2VA.js} +3 -3
- package/dist/recompile-project-agents-JE4MM72I.js +20 -0
- package/dist/{source-loader-OE6EJFPU.js → source-loader-3DL3NYUX.js} +7 -5
- package/dist/source-loader-3DL3NYUX.js.map +1 -0
- package/dist/src/agents/developer/ai-developer/critical-reminders.md +1 -1
- package/dist/src/agents/developer/ai-developer/critical-requirements.md +1 -1
- package/dist/src/agents/developer/ai-developer/identity.md +1 -1
- package/dist/src/agents/developer/ai-developer/playbook.md +1 -1
- package/dist/src/agents/developer/api-developer/identity.md +1 -1
- package/dist/src/agents/developer/cli-developer/identity.md +1 -1
- package/dist/src/agents/developer/web-developer/identity.md +1 -1
- package/dist/src/agents/meta/codex-keeper/identity.md +1 -1
- package/dist/src/agents/meta/convention-keeper/identity.md +1 -1
- package/dist/src/agents/meta/skill-summoner/identity.md +1 -1
- package/dist/src/agents/researcher/ai-researcher/identity.md +1 -1
- package/dist/src/agents/researcher/api-researcher/identity.md +1 -1
- package/dist/src/agents/researcher/cli-researcher/identity.md +1 -1
- package/dist/src/agents/researcher/web-researcher/identity.md +1 -1
- package/dist/src/agents/reviewer/reviewer/playbook.md +1 -1
- package/dist/src/agents/tester/ai-tester/identity.md +1 -1
- package/dist/src/agents/tester/api-tester/critical-reminders.md +1 -1
- package/dist/src/agents/tester/api-tester/critical-requirements.md +1 -1
- package/dist/src/agents/tester/api-tester/identity.md +2 -2
- package/dist/src/agents/tester/cli-tester/identity.md +1 -1
- package/dist/src/agents/tester/web-tester/identity.md +3 -3
- package/dist/stores/wizard-store.js +7 -5
- package/package.json +10 -7
- package/src/agents/developer/ai-developer/critical-reminders.md +1 -1
- package/src/agents/developer/ai-developer/critical-requirements.md +1 -1
- package/src/agents/developer/ai-developer/identity.md +1 -1
- package/src/agents/developer/ai-developer/playbook.md +1 -1
- package/src/agents/developer/api-developer/identity.md +1 -1
- package/src/agents/developer/cli-developer/identity.md +1 -1
- package/src/agents/developer/web-developer/identity.md +1 -1
- package/src/agents/meta/codex-keeper/identity.md +1 -1
- package/src/agents/meta/convention-keeper/identity.md +1 -1
- package/src/agents/meta/skill-summoner/identity.md +1 -1
- package/src/agents/researcher/ai-researcher/identity.md +1 -1
- package/src/agents/researcher/api-researcher/identity.md +1 -1
- package/src/agents/researcher/cli-researcher/identity.md +1 -1
- package/src/agents/researcher/web-researcher/identity.md +1 -1
- package/src/agents/reviewer/reviewer/playbook.md +1 -1
- package/src/agents/tester/ai-tester/identity.md +1 -1
- package/src/agents/tester/api-tester/critical-reminders.md +1 -1
- package/src/agents/tester/api-tester/critical-requirements.md +1 -1
- package/src/agents/tester/api-tester/identity.md +2 -2
- package/src/agents/tester/cli-tester/identity.md +1 -1
- package/src/agents/tester/web-tester/identity.md +3 -3
- package/src/schemas/custom-metadata.schema.json +3 -0
- package/src/schemas/metadata.schema.json +3 -0
- package/src/schemas/project-config.schema.json +4 -8
- package/src/schemas/project-source-config.schema.json +2 -2
- package/dist/chunk-4VCWL2IG.js.map +0 -1
- package/dist/chunk-5MFJ24VM.js.map +0 -1
- package/dist/chunk-7VZV4O6B.js.map +0 -1
- package/dist/chunk-AURY6RT6.js.map +0 -1
- package/dist/chunk-CBF4ZYV3.js.map +0 -1
- package/dist/chunk-FMYHWKGG.js.map +0 -1
- package/dist/chunk-GUDGCFSF.js.map +0 -1
- package/dist/chunk-JC7DBPRD.js.map +0 -1
- package/dist/chunk-MJFIO5SX.js.map +0 -1
- package/dist/chunk-OJJLYHM3.js +0 -34
- package/dist/chunk-OJJLYHM3.js.map +0 -1
- package/dist/chunk-PRJD5MMQ.js.map +0 -1
- package/dist/chunk-QQTYMW7N.js.map +0 -1
- package/dist/chunk-QUDQTO3O.js +0 -41
- package/dist/chunk-QUDQTO3O.js.map +0 -1
- package/dist/chunk-R54KIGN2.js.map +0 -1
- package/dist/chunk-TUQF577Z.js.map +0 -1
- package/dist/copy-local-skills-WVHJFRPK.js +0 -14
- package/dist/load-agent-defs-5OT54J5M.js +0 -15
- package/dist/recompile-project-agents-VREEPBDV.js +0 -20
- /package/dist/{chunk-LA3JPESW.js.map → chunk-4A4L3YIW.js.map} +0 -0
- /package/dist/{chunk-BZ4CZBOM.js.map → chunk-5F2YR5XV.js.map} +0 -0
- /package/dist/{chunk-CHNA5RVS.js.map → chunk-5OKLCVM4.js.map} +0 -0
- /package/dist/{chunk-K3O3YQYG.js.map → chunk-G47TDUK3.js.map} +0 -0
- /package/dist/{chunk-IXEDSKMH.js.map → chunk-HTYH7CKN.js.map} +0 -0
- /package/dist/{chunk-NSJ2S7R5.js.map → chunk-ILUVL7WM.js.map} +0 -0
- /package/dist/{chunk-NKCY2ULI.js.map → chunk-LJCNUP6M.js.map} +0 -0
- /package/dist/{chunk-Q5FLW4JG.js.map → chunk-OKH64JZE.js.map} +0 -0
- /package/dist/{chunk-WRRP47PY.js.map → chunk-PCC4LBKB.js.map} +0 -0
- /package/dist/{chunk-2IMYK4WN.js.map → chunk-PNMM5HNX.js.map} +0 -0
- /package/dist/{chunk-AKQ5QISO.js.map → chunk-QWVXOCXO.js.map} +0 -0
- /package/dist/{chunk-ONWEOS77.js.map → chunk-SY4X2LND.js.map} +0 -0
- /package/dist/{chunk-XGMOXMS4.js.map → chunk-TBOVYLQJ.js.map} +0 -0
- /package/dist/{chunk-6CNRMCFM.js.map → chunk-VPASBA7P.js.map} +0 -0
- /package/dist/{chunk-V3ENMW7G.js.map → chunk-WFRTHH3A.js.map} +0 -0
- /package/dist/{chunk-B66SC72V.js.map → chunk-Y5Y7XHVU.js.map} +0 -0
- /package/dist/{copy-local-skills-WVHJFRPK.js.map → components/common/removal-plan-confirm.js.map} +0 -0
- /package/dist/{load-agent-defs-5OT54J5M.js.map → copy-local-skills-NSUTBVLJ.js.map} +0 -0
- /package/dist/{loader-JIZDTR4G.js.map → load-agent-defs-X4E57I2U.js.map} +0 -0
- /package/dist/{recompile-project-agents-VREEPBDV.js.map → loader-G6BFG2VA.js.map} +0 -0
- /package/dist/{source-loader-OE6EJFPU.js.map → recompile-project-agents-JE4MM72I.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/lib/loading/loader.ts","../src/cli/utils/errors.ts","../src/cli/utils/frontmatter.ts","../src/cli/utils/fs.ts","../src/cli/lib/config-gate/gate-token.ts","../src/cli/utils/logger.ts","../src/cli/lib/schemas.ts","../src/cli/lib/schema-validator.ts","../src/cli/types/generated/source-types.ts","../src/cli/types/matrix.ts"],"sourcesContent":["import { parse as parseYaml } from \"yaml\";\nimport path from \"path\";\nimport { unique } from \"remeda\";\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 { CLAUDE_SRC_DIR, DIRS, STANDARD_DIRS, STANDARD_FILES, PROJECT_ROOT } from \"../../consts\";\nimport type {\n AgentDefinition,\n AgentName,\n SkillDefinition,\n SkillDefinitionMap,\n SkillFrontmatter,\n SkillId,\n} 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 { typedKeys } from \"../../utils/typed-object\";\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\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\nasync function buildIdToDirectoryPathMap(\n skillsDir: string,\n): Promise<Partial<Record<SkillId, string>>> {\n const files = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir);\n const parsed = await Promise.all(\n files.map(async (file) => {\n const fullPath = path.join(skillsDir, file);\n return { file, frontmatter: parseFrontmatter(await readFile(fullPath), fullPath) };\n }),\n );\n\n // Each skill is reachable by its frontmatter name AND its directory path\n return Object.fromEntries(\n parsed\n .filter((entry): entry is { file: string; frontmatter: SkillFrontmatter } =>\n Boolean(entry.frontmatter?.name),\n )\n .flatMap(({ file, frontmatter }) => {\n const directoryPath = file.replace(`/${STANDARD_FILES.SKILL_MD}`, \"\");\n return [\n [frontmatter.name, directoryPath],\n [directoryPath, directoryPath],\n ];\n }),\n );\n}\n\nexport async function loadSkillsByIds(\n skillIds: Array<{ id: SkillId }>,\n projectRoot: string,\n): Promise<SkillDefinitionMap> {\n const skills: SkillDefinitionMap = {};\n const skillsDir = path.join(projectRoot, DIRS.skills);\n\n const idToDirectoryPath = await buildIdToDirectoryPathMap(skillsDir);\n\n /** A directory reference expands to every skill under it; warns when nothing matches. */\n const expandDirectoryRef = (skillId: SkillId): SkillId[] => {\n const childSkills = typedKeys(idToDirectoryPath).filter((id) =>\n idToDirectoryPath[id]?.startsWith(`${skillId}/`),\n );\n if (childSkills.length === 0) {\n warn(`Unknown skill reference '${skillId}'`);\n return [];\n }\n verbose(`Expanded directory '${skillId}' to ${childSkills.length} skills`);\n return childSkills;\n };\n\n const uniqueSkillIds = unique(\n skillIds.flatMap(({ id }) => (idToDirectoryPath[id] ? [id] : expandDirectoryRef(id))),\n );\n\n for (const skillId of uniqueSkillIds) {\n const directoryPath = idToDirectoryPath[skillId];\n if (!directoryPath) {\n warn(`Could not find skill '${skillId}': no matching skill found`);\n continue;\n }\n\n const skillPath = path.join(skillsDir, directoryPath);\n const skillMdPath = path.join(skillPath, STANDARD_FILES.SKILL_MD);\n\n try {\n const content = await readFile(skillMdPath);\n const frontmatter = parseFrontmatter(content, skillMdPath);\n\n if (!frontmatter) {\n warn(`Skipping '${skillId}': missing or invalid frontmatter`);\n continue;\n }\n\n const canonicalId = frontmatter.name;\n const skillDef: SkillDefinition = {\n id: canonicalId,\n path: `${DIRS.skills}/${directoryPath}/`,\n description: frontmatter.description,\n };\n\n skills[canonicalId] = skillDef;\n\n verbose(`Loaded skill: ${canonicalId} (from ${directoryPath})`);\n } catch (error) {\n warn(`Could not load skill '${skillId}': ${getErrorMessage(error)}`);\n }\n }\n\n return skills;\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 metadata = await readSkillMetadata(metadataPath);\n if (!metadata.usable) {\n unusableMetadata.push({ skillDirName, metadataPath, reason: metadata.reason });\n verbose(` Unusable ${STANDARD_FILES.METADATA_YAML} 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","/** 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 { 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 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\nexport async function glob(pattern: string, cwd: string): Promise<string[]> {\n return fg(pattern, { cwd, onlyFiles: true });\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\nasync 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\nexport async function copy(src: string, dest: string): Promise<void> {\n await fs.copy(src, dest);\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\nexport function pushBufferMessage(level: StartupMessage[\"level\"], text: string): void {\n messageBuffer.push({ level, text });\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 /** When true, suppresses this warning in test environments (VITEST=true). */\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","import { z } from \"zod\";\nimport { partition } from \"remeda\";\nimport type { LocalSkillMetadata } from \"./skills/skill-metadata\";\nimport type { LocalRawMetadata } from \"./skills/local-skill-loader\";\nimport { AUTHOR_HANDLE_PATTERN, KEBAB_CASE_PATTERN, LOCAL_PSEUDO_CATEGORY } from \"../consts\";\nimport { formatZodIssue } from \"./schema-validator\";\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 RelationshipDefinitions,\n RequireRule,\n SkillAssignment,\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/** Validates category: strict categoryPathSchema by default, any kebab-case string when custom: true */\nfunction validateCategoryField(\n val: { category?: string; custom?: boolean },\n ctx: z.RefinementCtx,\n): void {\n if (!val.category) return;\n\n if (val.custom) {\n if (!KEBAB_CASE_PATTERN.test(val.category)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"category\"],\n message: \"Custom category must be kebab-case\",\n });\n }\n return;\n }\n\n const result = categoryPathSchema.safeParse(val.category);\n if (!result.success) {\n for (const issue of result.error.issues) {\n ctx.addIssue({ ...issue, path: [\"category\"] });\n }\n }\n}\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// Loader schema: category strictness depends on custom field (see validateCategoryField)\nexport const skillMetadataLoaderSchema = z\n .object({\n // Field accepts any string; cross-field validation in superRefine enforces strict/custom rules\n category: (z.string() as z.ZodType<CategoryPath>).exactOptional(),\n author: z.string().exactOptional(),\n domain: z.string() as z.ZodType<Domain>,\n custom: z.boolean().exactOptional(),\n })\n .passthrough()\n .superRefine(validateCategoryField);\n\n/**\n * Raw metadata.yaml shape read by the matrix loader during skill extraction.\n * DELIBERATE DIFFERENCE from skillMetadataLoaderSchema / localRawMetadataSchema:\n * this schema validates `category` with categoryPathSchema directly and does NOT\n * run the validateCategoryField superRefine, so a `custom: true` category is not\n * cross-checked against the kebab-case rule. Preserved verbatim on the move from\n * matrix-loader.ts — do not add the superRefine without an explicit decision.\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 * 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 = 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 source */\n skills: z\n .array(\n z.object({\n id: z.string() as z.ZodType<SkillId>,\n scope: z.enum([\"project\", \"global\"]),\n source: 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 /** Skills source path or URL (e.g., \"github:my-org/skills\") */\n source: z.string().exactOptional(),\n /** Marketplace identifier for plugin installation */\n marketplace: 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\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 required: z.boolean(),\n order: z.number(),\n icon: z.string().exactOptional(),\n});\n\n// Skill references in relationship rules: slugs resolved to canonical IDs by matrix-loader\nconst skillRefInRules = skillSlugSchema;\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 // Field accepts any string; cross-field validation in superRefine enforces strict/custom rules\n category: z.string() as z.ZodType<CategoryPath>,\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()\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 .superRefine(validateCategoryField) 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 })\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\nexport const marketplaceSchema: z.ZodType<Marketplace> = z.object({\n $schema: z.string().exactOptional(),\n name: z.string().min(1),\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 /** Custom tagline shown in wizard header */\n tagline: z.string().exactOptional(),\n});\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 = z\n .object({\n /** Primary skills source (path or URL) */\n source: z.string().exactOptional(),\n /** Author handle for this project's config */\n author: z.string().exactOptional(),\n /** Marketplace identifier for plugin installation */\n marketplace: 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// 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 /** 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/** 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 /** Kebab-case short key — must be a known built-in slug */\n slug: z.enum(SKILL_SLUGS),\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\n .string()\n .regex(/^[a-z][a-z0-9-]*$/)\n .min(1)\n .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","// 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 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). @default true */\n exclusive: boolean;\n /** If true, the user must select at least one skill before proceeding. @default false */\n required: 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/** Bidirectional slug <-> skill ID mapping. Partial because only extracted skills are present. */\nexport type SkillSlugMap = {\n /** Forward: slug -> canonical skill ID */\n slugToId: Partial<Record<SkillSlug, SkillId>>;\n /** Reverse: canonical skill ID -> slug */\n idToSlug: Partial<Record<SkillId, SkillSlug>>;\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 /** 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 * @default false\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.source (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 /** Advisory state computed from matrix relationships (incompatible > discouraged > normal) */\n advisoryState: OptionState;\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 /** Other skills that serve the same purpose (for \"or try X\" hints) */\n alternatives: SkillId[];\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"],"mappings":"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EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;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,IAAM,YAAY;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,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMO,IAAM,UAAU;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMO,IAAM,cAAc;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;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;;;ACr2BO,IAAM,cAAc,CAAC,UAAU,QAAQ,SAAS,SAAS,SAAS;AAIlE,IAAM,eAAe,CAAC,OAAO,UAAU,QAAQ,SAAS,KAAK;AAI7D,IAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AHaO,IAAM,kBAAkBC,GAAE,KAAK,WAAW;AAE1C,IAAM,oBAAoBA,GAAE,KAAK,YAAY;AAE7C,IAAM,uBAAuBA,GAAE,KAAK,gBAAgB;AAEpD,IAAM,kBAAkBA,GAAE,KAAK,WAAW;AAGjD,SAAS,sBACP,KACA,KACM;AACN,MAAI,CAAC,IAAI,SAAU;AAEnB,MAAI,IAAI,QAAQ;AACd,QAAI,CAAC,mBAAmB,KAAK,IAAI,QAAQ,GAAG;AAC1C,UAAI,SAAS;AAAA,QACX,MAAM;AAAA,QACN,MAAM,CAAC,UAAU;AAAA,QACjB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AACA;AAAA,EACF;AAEA,QAAM,SAAS,mBAAmB,UAAU,IAAI,QAAQ;AACxD,MAAI,CAAC,OAAO,SAAS;AACnB,eAAW,SAAS,OAAO,MAAM,QAAQ;AACvC,UAAI,SAAS,EAAE,GAAG,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;AAAA,IAC/C;AAAA,EACF;AACF;AAGO,IAAM,qBAAqBA,GAAE,OAAO,EAAE;AAAA,EAC3C,CAAC,QAA6B;AAC5B,QAAI,QAAQ,sBAAuB,QAAO;AAC1C,QAAK,WAAiC,SAAS,GAAG,EAAG,QAAO;AAE5D,WAAO,mBAAmB,KAAK,GAAG;AAAA,EACpC;AAAA,EACA;AAAA,IACE,SAAS;AAAA,EACX;AACF;AAEO,IAAM,wBAAoDA,GAAE,OAAO;AAAA,EACxE,MAAMA,GAAE,KAAK,CAAC,WAAW,UAAU,QAAQ,CAAC;AAAA,EAC5C,SAASA,GAAE,OAAO,EAAE,cAAc;AAAA,EAClC,QAAQA,GAAE,OAAO,EAAE,cAAc;AAAA,EACjC,QAAQA,GAAE,OAAO,EAAE,cAAc;AACnC,CAAC;AAEM,IAAM,4BAA4DA,GAAE,OAAO;AAAA,EAChF,SAASA,GAAE,OAAO,EAAE,cAAc;AAAA,EAClC,OAAOA,GAAE,MAAM,qBAAqB,EAAE,cAAc;AACtD,CAAC;AAEM,IAAM,oBAAoBA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,MAAM,yBAAyB,CAAC;AAGxF,IAAM,kCAAkCA,GAAE,OAAO;AAAA,EAC/C,SAASA,GAAE,OAAO,EAAE,cAAc;AAAA,EAClC,OAAOA,GAAE,MAAM,qBAAqB,EAAE,IAAI,CAAC;AAC7C,CAAC;AAGM,IAAM,0BAA0BA,GAAE;AAAA,EACvCA,GAAE,OAAO;AAAA,EACTA,GAAE,MAAM,+BAA+B;AACzC;AAEO,IAAM,wBAAoDA,GAAE,OAAO;AAAA,EACxE,IAAIA,GAAE,OAAO;AAAA,EACb,WAAWA,GAAE,QAAQ,EAAE,cAAc;AAAA,EACrC,OAAOA,GAAE,QAAQ,EAAE,cAAc;AAAA,EACjC,MAAMA,GAAE,OAAO,EAAE,cAAc;AACjC,CAAC;AAGM,IAAM,+BAA+BA,GAAE,OAAO;AAAA;AAAA,EAEnD,MAAMA,GAAE,OAAO;AAAA,EACf,aAAaA,GAAE,OAAO;AAAA,EACtB,OAAO,gBAAgB,cAAc;AACvC,CAAC;AAGM,IAAM,4BAA4BA,GACtC,OAAO;AAAA;AAAA,EAEN,UAAWA,GAAE,OAAO,EAA8B,cAAc;AAAA,EAChE,QAAQA,GAAE,OAAO,EAAE,cAAc;AAAA,EACjC,QAAQA,GAAE,OAAO;AAAA,EACjB,QAAQA,GAAE,QAAQ,EAAE,cAAc;AACpC,CAAC,EACA,YAAY,EACZ,YAAY,qBAAqB;AAU7B,IAAM,0BAA0BA,GAAE,OAAO;AAAA,EAC9C,UAAU;AAAA,EACV,QAAQA,GAAE,OAAO;AAAA,EACjB,aAAaA,GAAE,OAAO,EAAE,cAAc;AAAA,EACtC,MAAMA,GAAE,OAAO;AAAA,EACf,gBAAgBA,GAAE,OAAO,EAAE,cAAc;AAAA,EACzC,eAAeA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAExC,QAAQA,GAAE,OAAO;AAAA,EACjB,QAAQA,GAAE,QAAQ,EAAE,cAAc;AACpC,CAAC;AAEM,IAAM,qBAA8CA,GAAE,OAAO;AAAA,EAClE,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,OAAOA,GAAE,OAAO,EAAE,cAAc;AAClC,CAAC;AAGD,IAAM,6BAA6BA,GAAE,OAAO;AAAA,EAC1C,MAAMA,GAAE,OAAO;AAAA,EACf,SAASA,GAAE,OAAO,EAAE,cAAc;AAAA,EAClC,aAAaA,GAAE,OAAO,EAAE,cAAc;AAAA,EACtC,QAAQ,mBAAmB,cAAc;AAAA;AAAA,EAEzC,UAAUA,GAAE,OAAO,EAAE,cAAc;AAAA,EACnC,UAAUA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,cAAc;AAAA,EAC5C,UAAUA,GAAE,MAAM,CAACA,GAAE,OAAO,GAAGA,GAAE,MAAMA,GAAE,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc;AAAA,EACnE,QAAQA,GAAE,MAAM,CAACA,GAAE,OAAO,GAAGA,GAAE,MAAMA,GAAE,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc;AAAA,EACjE,QAAQA,GAAE,MAAM,CAACA,GAAE,OAAO,GAAGA,GAAE,MAAMA,GAAE,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc;AAAA,EACjE,OAAOA,GAAE,MAAM,CAACA,GAAE,OAAO,GAAG,iBAAiB,CAAC,EAAE,cAAc;AAChE,CAAC;AAGM,IAAM,uBAAkD;AAGxD,IAAM,iCAAiC,2BAA2B,OAAO;AAEzE,IAAM,wBAAoDA,GAAE,OAAO;AAAA,EACxE,IAAIA,GAAE,OAAO;AAAA,EACb,OAAOA,GAAE,OAAO;AAAA,EAChB,aAAaA,GAAE,OAAO;AAAA,EACtB,OAAO,gBAAgB,cAAc;AAAA,EACrC,QAAQ,kBAAkB,cAAc;AAAA,EACxC,OAAOA,GAAE,MAAMA,GAAE,OAAO,CAAC;AAAA,EACzB,iBAAiBA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,cAAc;AAAA,EACnD,gBAAgB,qBAAqB,cAAc;AAAA,EACnD,OAAO,kBAAkB,cAAc;AAAA,EACvC,cAAcA,GAAE,OAAO,EAAE,cAAc;AAAA,EACvC,QAASA,GAAE,OAAO,EAAwB,cAAc;AAAA,EACxD,QAAQA,GAAE,QAAQ,EAAE,cAAc;AACpC,CAAC;AAID,IAAM,+BAA+BA,GAAE,MAAM;AAAA,EAC3CA,GAAE,OAAO;AAAA,EACT;AACF,CAAC;AAOM,IAAM,yBAAyBA,GAAE;AAAA,EACtCA,GAAE,OAAO;AAAA,EACTA,GAAE,MAAM,CAAC,8BAA8BA,GAAE,MAAM,4BAA4B,CAAC,CAAC;AAC/E;AAOO,IAAM,4BAA4BA,GACtC,OAAO;AAAA;AAAA,EAEN,MAAMA,GAAE,OAAO,EAAE,cAAc;AAAA,EAC/B,aAAaA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEtC,QAAQA,GACL;AAAA,IACCA,GAAE,OAAO;AAAA,MACP,MAAMA,GAAE,OAAO;AAAA,MACf,OAAOA,GAAE,KAAK,CAAC,WAAW,QAAQ,CAAC;AAAA;AAAA,MAEnC,OAAO,gBAAgB,cAAc;AAAA,MACrC,QAAQ,kBAAkB,cAAc;AAAA,MACxC,UAAUA,GAAE,QAAQ,EAAE,cAAc;AAAA,IACtC,CAAC;AAAA,EACH,EACC,cAAc;AAAA;AAAA,EAEjB,QAAQA,GACL;AAAA,IACCA,GAAE,OAAO;AAAA,MACP,IAAIA,GAAE,OAAO;AAAA,MACb,OAAOA,GAAE,KAAK,CAAC,WAAW,QAAQ,CAAC;AAAA,MACnC,QAAQA,GAAE,OAAO;AAAA,MACjB,UAAUA,GAAE,QAAQ,EAAE,cAAc;AAAA,IACtC,CAAC;AAAA,EACH,EACC,cAAc;AAAA;AAAA,EAGjB,QAAQA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEjC,iBAAiBA,GAAE,MAAMA,GAAE,OAAO,CAAsB,EAAE,cAAc;AAAA;AAAA,EAExE,OAAOA,GAAE,OAAOA,GAAE,OAAO,GAAG,sBAAsB,EAAE,cAAc;AAAA;AAAA,EAElE,QAAQA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEjC,aAAaA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEtC,cAAcA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEvC,UAAUA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,cAAc;AAC9C,CAAC,EACA,YAAY;AAEf,IAAM,2BAA0DA,GAAE,OAAO;AAAA,EACvE,IAAIA,GAAE,OAAO;AAAA,EACb,aAAaA,GAAE,OAAO;AAAA,EACtB,aAAaA,GAAE,OAAO;AAAA,EACtB,QAASA,GAAE,OAAO,EAAwB,cAAc;AAAA,EACxD,WAAWA,GAAE,QAAQ;AAAA,EACrB,UAAUA,GAAE,QAAQ;AAAA,EACpB,OAAOA,GAAE,OAAO;AAAA,EAChB,MAAMA,GAAE,OAAO,EAAE,cAAc;AACjC,CAAC;AAGD,IAAM,kBAAkB;AAGxB,IAAM,uBAAuBA,GAAE,OAAO;AAAA,EACpC,QAAQA,GAAE,MAAM,eAAe,EAAE,IAAI,CAAC;AAAA,EACtC,QAAQA,GAAE,OAAO;AACnB,CAAC;AAED,IAAM,qBAA8C;AAEpD,IAAM,uBAAkD;AAExD,IAAM,oBAA4CA,GAAE,OAAO;AAAA,EACzD,OAAO;AAAA,EACP,OAAOA,GAAE,MAAM,eAAe,EAAE,IAAI,CAAC;AAAA,EACrC,UAAUA,GAAE,QAAQ,EAAE,cAAc;AAAA,EACpC,QAAQA,GAAE,OAAO;AACnB,CAAC;AAED,IAAM,yBAAsDA,GAAE,OAAO;AAAA,EACnE,SAASA,GAAE,OAAO;AAAA,EAClB,QAAQA,GAAE,MAAM,eAAe,EAAE,IAAI,CAAC;AACxC,CAAC;AAED,IAAM,gCAAoEA,GAAE,OAAO;AAAA,EACjF,WAAWA,GAAE,MAAM,kBAAkB;AAAA,EACrC,aAAaA,GAAE,MAAM,oBAAoB;AAAA,EACzC,UAAUA,GAAE,MAAM,iBAAiB;AAAA,EACnC,cAAcA,GAAE,MAAM,sBAAsB;AAC9C,CAAC;AAMM,IAAM,4BAA4BA,GAAE,OAAO;AAAA,EAChD,SAASA,GAAE,OAAO;AAAA,EAClB,YAAYA,GAAE,OAAOA,GAAE,OAAO,GAAG,wBAAwB;AAC3D,CAAC;AAMM,IAAM,uBAAuBA,GAAE,OAAO;AAAA,EAC3C,SAASA,GAAE,OAAO;AAAA,EAClB,eAAe,8BAA8B,cAAc;AAC7D,CAAC;AAMM,IAAM,yBAAyBA,GACnC,OAAO;AAAA;AAAA,EAEN,aAAaA,GAAE,OAAO;AAAA;AAAA,EAEtB,MAAMA,GAAE,OAAO;AAAA;AAAA,EAEf,gBAAgBA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA;AAAA,EAGzC,UAAUA,GAAE,OAAO;AAAA;AAAA,EAEnB,eAAeA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAExC,QAAQA,GAAE,OAAO;AAAA;AAAA,EAEjB,QAAQA,GAAE,QAAQ,EAAE,cAAc;AACpC,CAAC,EACA,YAAY,EAGZ,YAAY,qBAAqB;AAG7B,IAAM,2BAA2BA,GACrC,OAAO;AAAA,EACN,YAAYA,GACT,OAAO;AAAA;AAAA,IAEN,SAASA,GAAE,OAAO;AAAA;AAAA,IAElB,aAAaA,GAAE,OAAO;AAAA;AAAA,IAEtB,MAAMA,GAAE,OAAO;AAAA;AAAA,IAEf,QAAQA,GAAE,OAAO,EAAE,cAAc;AAAA,EACnC,CAAC,EACA,cAAc;AACnB,CAAC,EAGA,YAAY;AAEf,IAAM,cAAcA,GAAE,OAAO;AAAA,EAC3B,IAAIA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACpB,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,aAAaA,GAAE,OAAO;AAAA;AAAA,EAEtB,QAAQA,GAAE,OAAOA,GAAE,OAAO,GAAG,sBAAsB;AAAA;AAAA,EAEnD,YAAYA,GAAE,OAAO,EAAE,cAAc;AACvC,CAAC;AAIM,IAAM,qBAAqBA,GAAE,OAAO;AAAA,EACzC,QAAQA,GAAE,MAAM,WAAW,EAAE,IAAI,CAAC;AACpC,CAAC;AAED,IAAM,gCAAoEA,GAAE,OAAO;AAAA,EACjF,QAAQA,GAAE,KAAK,CAAC,UAAU,KAAK,CAAC;AAAA,EAChC,MAAMA,GAAE,OAAO,EAAE,cAAc;AAAA,EAC/B,KAAKA,GAAE,OAAO,EAAE,cAAc;AAAA,EAC9B,KAAKA,GAAE,OAAO,EAAE,cAAc;AAChC,CAAC;AAED,IAAM,0BAAwDA,GAAE,OAAO;AAAA,EACrE,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAEtB,QAAQA,GAAE,MAAM,CAACA,GAAE,OAAO,GAAG,6BAA6B,CAAC;AAAA,EAC3D,aAAaA,GAAE,OAAO,EAAE,cAAc;AAAA,EACtC,SAASA,GAAE,OAAO,EAAE,cAAc;AAAA,EAClC,QAAQ,mBAAmB,cAAc;AAAA;AAAA,EAEzC,UAAUA,GAAE,OAAO,EAAE,cAAc;AAAA,EACnC,UAAUA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,cAAc;AAC9C,CAAC;AAGD,IAAM,yBAAsD;AAE5D,IAAM,4BAA4DA,GAAE,OAAO;AAAA;AAAA,EAEzE,YAAYA,GAAE,OAAO,EAAE,cAAc;AACvC,CAAC;AAEM,IAAM,oBAA4CA,GAAE,OAAO;AAAA,EAChE,SAASA,GAAE,OAAO,EAAE,cAAc;AAAA,EAClC,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,SAASA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACzB,aAAaA,GAAE,OAAO,EAAE,cAAc;AAAA,EACtC,OAAO;AAAA,EACP,UAAU,0BAA0B,cAAc;AAAA,EAClD,SAASA,GAAE,MAAM,uBAAuB,EAAE,IAAI,CAAC;AACjD,CAAC;AAUM,IAAM,2BAA2BA,GAAE,OAAO;AAAA;AAAA,EAE/C,KAAKA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACrB,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,cAAc;AACxC,CAAC;AAGD,IAAM,yBAAyBA,GAAE,OAAO;AAAA;AAAA,EAEtC,OAAOA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,cAAc;AAAA;AAAA,EAEzC,MAAMA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,cAAc;AAC1C,CAAC;AAGM,IAAM,qBAAqBA,GAC/B,OAAO;AAAA,EACN,aAAa,uBAAuB,cAAc;AACpD,CAAC,EACA,YAAY;AAGf,IAAM,uBAAuBA,GAAE,OAAO;AAAA;AAAA,EAEpC,MAAMA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAE/B,SAASA,GAAE,OAAO,EAAE,cAAc;AACpC,CAAC;AAMM,IAAM,4BAA4BA,GACtC,OAAO;AAAA;AAAA,EAEN,QAAQA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEjC,QAAQA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEjC,aAAaA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEtC,cAAcA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEvC,UAAU,qBAAqB,cAAc;AAAA;AAAA,EAE7C,WAAWA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEpC,WAAWA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEpC,YAAYA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAErC,gBAAgBA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEzC,WAAWA,GAAE,OAAO,EAAE,cAAc;AACtC,CAAC,EACA,YAAY;AAMR,IAAM,4BAA4BA,GACtC,OAAO;AAAA,EACN,SAASA,GAAE,OAAO,EAAE,cAAc;AAAA,EAClC,IAAIA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACpB,OAAOA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACvB,aAAaA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC7B,OAAO,gBAAgB,cAAc;AAAA,EACrC,QAAQ,kBAAkB,cAAc;AAAA,EACxC,OAAOA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,IAAI,CAAC;AAAA,EAChC,iBAAiBA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,cAAc;AAAA,EACnD,gBAAgB,qBAAqB,cAAc;AAAA,EACnD,OAAO,wBAAwB,cAAc;AAAA,EAC7C,cAAcA,GAAE,OAAO,EAAE,cAAc;AAAA,EACvC,QAASA,GAAE,OAAO,EAAwB,cAAc;AAAA,EACxD,QAAQA,GAAE,QAAQ,EAAE,cAAc;AACpC,CAAC,EACA,OAAO;AAGH,IAAM,mCAAmCA,GAC7C,OAAO;AAAA;AAAA,EAEN,MAAMA,GAAE,OAAO,EAAE,MAAM,kBAAkB,EAAE,IAAI,CAAC;AAAA,EAChD,aAAaA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAE7B,OAAOA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEhC,iBAAiBA,GAAE,OAAO,EAAE,cAAc;AAAA,EAC1C,OAAO,gBAAgB,cAAc;AAAA,EACrC,QAAQ,kBAAkB,cAAc;AAAA,EACxC,gBAAgB,qBAAqB,cAAc;AAAA;AAAA,EAEnD,QAAQA,GAAE,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,cAAc;AAAA,EACjD,OAAO,wBAAwB,cAAc;AAC/C,CAAC,EACA,OAAO;AAGH,IAAM,mCAAmCA,GAC7C,OAAO;AAAA,EACN,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,aAAaA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAE7B,4BAA4BA,GAAE,QAAQ,EAAE,cAAc;AAAA;AAAA,EAEtD,kBAAkBA,GAAE,QAAQ,EAAE,cAAc;AAAA;AAAA,EAE5C,iBAAiBA,GAAE,OAAO,EAAE,cAAc;AAAA,EAC1C,OAAO,gBAAgB,cAAc;AAAA;AAAA,EAErC,SAASA,GAAE,KAAK,CAAC,MAAM,CAAC,EAAE,cAAc;AAAA;AAAA,EAExC,OAAOA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEhC,iBAAiBA,GAAE,OAAO,EAAE,cAAc;AAC5C,CAAC,EACA,OAAO;AAQV,IAAM,mBAAmBA,GAAE,OAAO;AAAA;AAAA,EAEhC,SAASA,GAAE,OAAO;AAAA;AAAA,EAElB,SAASA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,cAAc;AAAA;AAAA,EAE/C,aAAaA,GAAE,OAAO;AAAA;AAAA,EAEtB,QAAQA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEjC,MAAMA,GAAE,OAAO;AACjB,CAAC;AAQD,IAAM,6BAA6B;AAOnC,IAAM,0BAA0BA,GAAE,OAAO;AAAA;AAAA,EAEvC,QAAQA,GAAE,OAAO,EAAE,MAAM,qBAAqB;AAAA;AAAA,EAE9C,aAAaA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA;AAAA,EAErC,gBAAgBA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,0BAA0B;AAAA;AAAA,EAEhE,eAAeA,GAAE,OAAO,EAAE,IAAI,EAAE;AAAA;AAAA,EAEhC,aAAaA,GACV,OAAO,EACP,MAAM,eAAe,EACrB,cAAc;AAAA;AAAA,EAEjB,SAASA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAElC,YAAY,iBAAiB,cAAc;AAAA;AAAA,EAE3C,QAASA,GAAE,OAAO,EAAwB,cAAc;AAAA;AAAA,EAExD,QAAQA,GAAE,QAAQ,EAAE,cAAc;AACpC,CAAC;AAGM,IAAM,2BAA2B,wBACrC,OAAO;AAAA;AAAA,EAEN,UAAUA,GAAE,KAAK,UAAU;AAAA;AAAA,EAE3B,MAAMA,GAAE,KAAK,WAAW;AAC1B,CAAC,EACA,OAAO;AAGH,IAAM,iCAAiC,wBAAwB,OAAO;AAAA;AAAA,EAE3E,UAAUA,GAAE,OAAO;AAAA;AAAA,EAEnB,MAAMA,GACH,OAAO,EACP,MAAM,mBAAmB,EACzB,IAAI,CAAC,EACL,IAAI,EAAE;AACX,CAAC;AAED,IAAM,6BAA6BA,GAChC,OAAO;AAAA,EACN,IAAIA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAEpB,WAAWA,GAAE,QAAQ,EAAE,cAAc;AACvC,CAAC,EACA,OAAO;AAGH,IAAM,8BAA8BA,GACxC,OAAO;AAAA;AAAA,EAEN,IAAIA,GAAE,OAAO,EAAE,MAAM,kBAAkB,EAAE,cAAc;AAAA,EACvD,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,SAASA,GAAE,OAAO;AAAA,EAClB,QAAQA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACxB,aAAaA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEtC,SAASA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAElC,SAASA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAElC,WAAWA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAEpC,QAAQA,GAAE,MAAM,0BAA0B,EAAE,IAAI,CAAC;AAAA;AAAA,EAEjD,QAAQA,GAAE,MAAMA,GAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC,EAAE,IAAI,CAAC;AAAA;AAAA,EAE3D,aAAaA,GACV,OAAOA,GAAE,OAAO,GAAGA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,MAAM,0BAA0B,CAAC,CAAC,EAC5E,cAAc;AAAA;AAAA,EAEjB,YAAYA,GAAE,OAAO,EAAE,cAAc;AAAA;AAAA,EAErC,YAAYA,GAAE,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,cAAc;AAAA,EACrD,MAAMA,GAAE,MAAMA,GAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC,EAAE,cAAc;AAAA;AAAA,EAElE,WAAWA,GACR;AAAA,IACCA,GAAE,OAAO;AAAA,IACTA,GACG,OAAO;AAAA;AAAA,MAEN,cAAcA,GAAE,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,cAAc;AAAA;AAAA,MAEvD,QAAQA,GAAE,QAAQ,EAAE,cAAc;AAAA,IACpC,CAAC,EACA,OAAO;AAAA,EACZ,EACC,cAAc;AAAA;AAAA,EAEjB,SAASA,GACN,OAAO;AAAA,IACN,SAASA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,cAAc;AAAA,IAC/C,WAAWA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,cAAc;AAAA,EACnD,CAAC,EACA,OAAO,EACP,cAAc;AAAA;AAAA,EAEjB,OAAO,wBAAwB,cAAc;AAC/C,CAAC,EACA,OAAO;AAGH,SAAS,gBAAgB,QAA8B;AAC5D,SAAO,OAAO,IAAI,cAAc,EAAE,KAAK,IAAI;AAC7C;AAOO,SAAS,sBAAsB,aAAsB;AAC1D,QAAM,SAAS,iBAAiB,WAAW,IACvC,iCACA;AACJ,SAAO,OAAO,UAAU,WAAW;AACrC;AAQO,SAAS,8BACd,QACA,aACQ;AACR,QAAM,CAAC,QAAQ,SAAS,IAAI,UAAU,QAAQ,CAAC,UAAU,cAAc,OAAO,WAAW,CAAC;AAC1F,SAAO;AAAA,IACL,GAAI,OAAO,SAAS,IAAI,CAAC,kBAAkB,MAAM,CAAC,IAAI,CAAC;AAAA,IACvD,GAAG,UAAU,IAAI,cAAc;AAAA,EACjC,EAAE,KAAK,IAAI;AACb;AAGA,SAAS,cAAc,OAAmB,aAA+C;AACvF,QAAM,CAAC,OAAO,GAAG,MAAM,IAAI,MAAM;AACjC,SAAO,OAAO,WAAW,KAAK,OAAO,UAAU,YAAY,YAAY,KAAK,MAAM;AACpF;AAEA,SAAS,kBAAkB,QAA8B;AACvD,QAAM,SAAS,OAAO,IAAI,CAAC,UAAU,MAAM,KAAK,KAAK,GAAG,CAAC;AACzD,SAAO,oBAAoB,OAAO,WAAW,IAAI,UAAU,QAAQ,KAAK,OAAO,KAAK,IAAI,CAAC;AAC3F;AAUA,SAAS,2BAA2B,OAA4B;AAC9D,SAAO,MAAM,SAAS,aAAa,MAAM,KAAK,WAAW,KAAK,MAAM,KAAK,CAAC,MAAM;AAClF;AAGA,SAAS,mBAAmB,KAAkC;AAC5D,MAAI,OAAO,QAAQ,OAAO,QAAQ,SAAU,QAAO;AAEnD,QAAM,QAAS,IAAqC;AACpD,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAOA,SAAS,wBAAwB,OAAmB,gBAA4C;AAC9F,MAAI,mBAAmB,OAAW,QAAO,eAAe,KAAK;AAC7D,SAAO,qBAAqB,eAAe,MAAM,yDAAoD,0BAA0B;AACjI;AAUO,SAAS,8BACd,OACA,aACoB;AACpB,QAAM,CAAC,YAAY,YAAY,IAAI,UAAU,MAAM,QAAQ,0BAA0B;AAErF,QAAM,iBAAiB,mBAAmB,WAAW;AACrD,QAAM,WAAW,WAAW,IAAI,CAAC,UAAU,wBAAwB,OAAO,cAAc,CAAC;AAEzF,SAAO,EAAE,QAAQ,aAAa,IAAI,cAAc,GAAG,SAAS;AAC9D;AAMO,SAAS,qBAAqB,OAAgB,UAA2B;AAC9E,WAAS,MAAM,KAAc,OAAwB;AACnD,QAAI,QAAQ,SAAU,QAAO;AAC7B,QAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,aAAO,IAAI,MAAM,CAAC,SAAS,MAAM,MAAM,QAAQ,CAAC,CAAC;AAAA,IACnD;AACA,QAAI,QAAQ,QAAQ,OAAO,QAAQ,UAAU;AAC3C,aAAO,OAAO,OAAO,GAAG,EAAE,MAAM,CAAC,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC;AAAA,IAC5D;AACA,WAAO;AAAA,EACT;AACA,SAAO,MAAM,OAAO,CAAC;AACvB;AAMO,SAAS,iBAAiB,KAAuB;AACtD,MAAI,OAAO,QAAQ,OAAO,QAAQ,SAAU,QAAO;AACnD,MAAI,EAAE,YAAY,KAAM,QAAO;AAC/B,SAAO,IAAI,WAAW;AACxB;AASO,SAAS,kBACd,QACA,cACA,SACM;AACN,QAAM,cAAc,IAAI,IAAI,YAAY;AACxC,QAAM,cAAc,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC;AACzE,MAAI,YAAY,SAAS,GAAG;AAC1B,SAAK,qBAAqB,OAAO,KAAK,YAAY,KAAK,IAAI,CAAC,EAAE;AAAA,EAChE;AACF;;;ANtxBA,eAAsB,kBAAkB,cAAkD;AACxF,MAAI;AACJ,MAAI;AACF,aAASC,WAAU,MAAM,SAAS,YAAY,CAAC;AAAA,EACjD,SAAS,OAAO;AACd,WAAO,EAAE,QAAQ,OAAO,QAAQ,gBAAgB,KAAK,EAAE;AAAA,EACzD;AAEA,MAAI,CAAC,eAAe,MAAM,GAAG;AAC3B,WAAO,EAAE,QAAQ,OAAO,QAAQ,mCAAmC,cAAc,MAAM,CAAC,GAAG;AAAA,EAC7F;AAEA,QAAM,YAAY,uBAAuB,UAAU,MAAM;AACzD,MAAI,CAAC,UAAU,SAAS;AACtB,WAAO,EAAE,QAAQ,OAAO,QAAQ,8BAA8B,UAAU,MAAM,QAAQ,MAAM,EAAE;AAAA,EAChG;AAEA,SAAO,EAAE,QAAQ,MAAM,UAAU,UAAU,KAAK;AAClD;AAEA,SAAS,eAAe,OAAkD;AACxE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAGA,SAAS,cAAc,OAAwB;AAC7C,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,SAAO,KAAK,OAAO,KAAK;AAC1B;AAEO,SAAS,iBAAiB,SAAiB,UAA4C;AAC5F,QAAM,iBAAiB,mBAAmB,OAAO;AACjD,MAAI,mBAAmB,KAAM,QAAO;AAEpC,QAAM,SAAS,6BAA6B,UAAU,cAAc;AAEpE,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,WAAW,YAAY;AAC7B,SAAK,oCAAoC,QAAQ,MAAM,gBAAgB,OAAO,MAAM,MAAM,CAAC,EAAE;AAC7F,WAAO;AAAA,EACT;AACA,SAAO,OAAO;AAChB;AAaA,eAAe,kBACb,WACA,YACA,SACsD;AACtD,QAAM,SAA0C,CAAC;AACjD,QAAM,QAAQ,MAAM,KAAK,MAAM,eAAe,mBAAmB,IAAI,SAAS;AAE9E,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAWC,MAAK,KAAK,WAAW,IAAI;AAC1C,QAAI;AACF,YAAM,UAAU,MAAM,SAAS,QAAQ;AACvC,YAAM,SAAS,sBAAsB,MAAMD,WAAU,OAAO,CAAC;AAE7D,aAAO,OAAO,EAAE,IAAI;AAAA,QAClB,OAAO,OAAO;AAAA,QACd,aAAa,OAAO;AAAA,QACpB,GAAI,OAAO,UAAU,UAAa,EAAE,OAAO,OAAO,MAAM;AAAA,QACxD,OAAO,OAAO;AAAA,QACd,MAAMC,MAAK,QAAQ,IAAI;AAAA,QACvB;AAAA,QACA,GAAI,QAAQ,eAAe,EAAE,cAAc,QAAQ,aAAa,IAAI,CAAC;AAAA,QACrE,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;AAAA,QACjD,GAAI,QAAQ,qBAAqB,OAAO,WAAW,OAAO,EAAE,QAAQ,KAAK,IAAI,CAAC;AAAA,MAChF;AAEA,cAAQ,UAAU,QAAQ,YAAY,KAAK,OAAO,EAAE,SAAS,IAAI,EAAE;AAAA,IACrE,SAAS,OAAO;AACd,WAAK,sCAAsC,QAAQ,MAAM,gBAAgB,KAAK,CAAC,EAAE;AAAA,IACnF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAsB,cACpB,aACsD;AACtD,SAAO,kBAAkBA,MAAK,KAAK,aAAa,KAAK,MAAM,GAAG,aAAa;AAAA,IACzE,mBAAmB;AAAA,IACnB,cAAc;AAAA,EAChB,CAAC;AACH;AAMA,eAAsB,iBACpB,YACsD;AACtD,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,IAClD,cAAc,YAAY;AAAA,IAC1B,cAAc,UAAU;AAAA,EAC1B,CAAC;AACD,SAAO,EAAE,GAAG,WAAW,GAAG,aAAa;AACzC;AAEA,eAAsB,kBACpB,aACsD;AACtD,QAAM,mBAAmBA,MAAK,KAAK,aAAa,gBAAgB,cAAc,MAAM;AAEpF,MAAI,CAAE,MAAM,gBAAgB,gBAAgB,GAAI;AAC9C,YAAQ,kCAAkC,gBAAgB,EAAE;AAC5D,UAAM,WAA4C,CAAC;AACnD,WAAO;AAAA,EACT;AAEA,SAAO,kBAAkB,kBAAkB,aAAa;AAAA;AAAA,IAEtD,cAAc,GAAG,cAAc;AAAA,IAC/B,cAAc;AAAA,EAChB,CAAC;AACH;AAEA,eAAe,0BACb,WAC2C;AAC3C,QAAM,QAAQ,MAAM,KAAK,MAAM,eAAe,QAAQ,IAAI,SAAS;AACnE,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B,MAAM,IAAI,OAAO,SAAS;AACxB,YAAM,WAAWA,MAAK,KAAK,WAAW,IAAI;AAC1C,aAAO,EAAE,MAAM,aAAa,iBAAiB,MAAM,SAAS,QAAQ,GAAG,QAAQ,EAAE;AAAA,IACnF,CAAC;AAAA,EACH;AAGA,SAAO,OAAO;AAAA,IACZ,OACG;AAAA,MAAO,CAAC,UACP,QAAQ,MAAM,aAAa,IAAI;AAAA,IACjC,EACC,QAAQ,CAAC,EAAE,MAAM,YAAY,MAAM;AAClC,YAAM,gBAAgB,KAAK,QAAQ,IAAI,eAAe,QAAQ,IAAI,EAAE;AACpE,aAAO;AAAA,QACL,CAAC,YAAY,MAAM,aAAa;AAAA,QAChC,CAAC,eAAe,aAAa;AAAA,MAC/B;AAAA,IACF,CAAC;AAAA,EACL;AACF;AAEA,eAAsB,gBACpB,UACA,aAC6B;AAC7B,QAAM,SAA6B,CAAC;AACpC,QAAM,YAAYA,MAAK,KAAK,aAAa,KAAK,MAAM;AAEpD,QAAM,oBAAoB,MAAM,0BAA0B,SAAS;AAGnE,QAAM,qBAAqB,CAAC,YAAgC;AAC1D,UAAM,cAAc,UAAU,iBAAiB,EAAE;AAAA,MAAO,CAAC,OACvD,kBAAkB,EAAE,GAAG,WAAW,GAAG,OAAO,GAAG;AAAA,IACjD;AACA,QAAI,YAAY,WAAW,GAAG;AAC5B,WAAK,4BAA4B,OAAO,GAAG;AAC3C,aAAO,CAAC;AAAA,IACV;AACA,YAAQ,uBAAuB,OAAO,QAAQ,YAAY,MAAM,SAAS;AACzE,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB;AAAA,IACrB,SAAS,QAAQ,CAAC,EAAE,GAAG,MAAO,kBAAkB,EAAE,IAAI,CAAC,EAAE,IAAI,mBAAmB,EAAE,CAAE;AAAA,EACtF;AAEA,aAAW,WAAW,gBAAgB;AACpC,UAAM,gBAAgB,kBAAkB,OAAO;AAC/C,QAAI,CAAC,eAAe;AAClB,WAAK,yBAAyB,OAAO,4BAA4B;AACjE;AAAA,IACF;AAEA,UAAM,YAAYA,MAAK,KAAK,WAAW,aAAa;AACpD,UAAM,cAAcA,MAAK,KAAK,WAAW,eAAe,QAAQ;AAEhE,QAAI;AACF,YAAM,UAAU,MAAM,SAAS,WAAW;AAC1C,YAAM,cAAc,iBAAiB,SAAS,WAAW;AAEzD,UAAI,CAAC,aAAa;AAChB,aAAK,aAAa,OAAO,mCAAmC;AAC5D;AAAA,MACF;AAEA,YAAM,cAAc,YAAY;AAChC,YAAM,WAA4B;AAAA,QAChC,IAAI;AAAA,QACJ,MAAM,GAAG,KAAK,MAAM,IAAI,aAAa;AAAA,QACrC,aAAa,YAAY;AAAA,MAC3B;AAEA,aAAO,WAAW,IAAI;AAEtB,cAAQ,iBAAiB,WAAW,UAAU,aAAa,GAAG;AAAA,IAChE,SAAS,OAAO;AACd,WAAK,yBAAyB,OAAO,MAAM,gBAAgB,KAAK,CAAC,EAAE;AAAA,IACrE;AAAA,EACF;AAEA,SAAO;AACT;AAsCA,eAAsB,kBACpB,WACA,UAAoC,CAAC,GACd;AACvB,QAAM,EAAE,aAAa,IAAI,kBAAkB,MAAM,IAAI;AACrD,QAAM,SAA6B,CAAC;AACpC,QAAM,mBAA4C,CAAC;AAEnD,MAAI,CAAE,MAAM,gBAAgB,SAAS,GAAI;AACvC,WAAO,EAAE,QAAQ,iBAAiB;AAAA,EACpC;AAEA,QAAM,aAAa,MAAM,KAAK,MAAM,eAAe,QAAQ,IAAI,SAAS;AAExE,aAAW,aAAa,YAAY;AAClC,UAAM,YAAYA,MAAK,KAAK,WAAW,SAAS;AAChD,UAAM,WAAWA,MAAK,QAAQ,SAAS;AACvC,UAAM,eAAeA,MAAK,SAAS,WAAW,QAAQ;AACtD,UAAM,eAAeA,MAAK,SAAS,QAAQ;AAC3C,UAAM,cAAc,aAAa,GAAG,UAAU,IAAI,YAAY,MAAM,GAAG,YAAY;AAEnF,QAAI,iBAAiB;AACnB,YAAM,eAAeA,MAAK,KAAK,UAAU,eAAe,aAAa;AACrE,UAAI,CAAE,MAAM,WAAW,YAAY,GAAI;AACrC;AAAA,UACE,UAAU,YAAY,SAAS,WAAW,gBAAgB,eAAe,aAAa,wBAAmB,eAAe,aAAa;AAAA,QACvI;AACA;AAAA,MACF;AAKA,YAAM,WAAW,MAAM,kBAAkB,YAAY;AACrD,UAAI,CAAC,SAAS,QAAQ;AACpB,yBAAiB,KAAK,EAAE,cAAc,cAAc,QAAQ,SAAS,OAAO,CAAC;AAC7E,gBAAQ,cAAc,eAAe,aAAa,QAAQ,YAAY,GAAG;AACzE;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,UAAU,MAAM,SAAS,SAAS;AACxC,YAAM,cAAc,iBAAiB,SAAS,SAAS;AAEvD,UAAI,CAAC,aAAa,MAAM;AACtB,aAAK,sBAAsB,YAAY,wCAAwC;AAC/E;AAAA,MACF;AAEA,YAAM,cAAc,YAAY;AAChC,aAAO,WAAW,IAAI;AAAA,QACpB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aAAa,YAAY,eAAe;AAAA,MAC1C;AAEA,cAAQ,mBAAmB,WAAW,EAAE;AAAA,IAC1C,SAAS,OAAO;AACd,cAAQ,2BAA2B,SAAS,MAAM,gBAAgB,KAAK,CAAC,EAAE;AAAA,IAC5E;AAAA,EACF;AAEA,SAAO,EAAE,QAAQ,iBAAiB;AACpC;AAOA,eAAsB,iBAAiB,WAAgD;AACrF,QAAM,EAAE,OAAO,IAAI,MAAM,kBAAkBA,MAAK,KAAK,WAAW,QAAQ,GAAG;AAAA,IACzE,YAAY;AAAA,IACZ,iBAAiB;AAAA,EACnB,CAAC;AACD,SAAO;AACT;","names":["parseYaml","path","z","path","z","parseYaml","path"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/commands/init.tsx","../src/cli/lib/seed/fetch-seed.ts","../src/cli/lib/seed/seed-to-wizard.ts","../src/cli/lib/permission-checker.tsx"],"sourcesContent":["import os from \"os\";\nimport React from \"react\";\n\nimport { Flags, type Interfaces } from \"@oclif/core\";\nimport { Box, Text, useApp } from \"ink\";\nimport { render } from \"../components/render.js\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { type WizardResultV2 } from \"../components/wizard/wizard.js\";\nimport { runWizardSession } from \"../components/wizard/run-wizard-session.js\";\nimport { useTerminalDimensions } from \"../components/hooks/use-terminal-dimensions.js\";\nimport { type SourceLoadResult } from \"../lib/loading/index.js\";\nimport {\n loadSource,\n loadAgentDefs,\n copyLocalSkills,\n writeProjectConfig,\n compileAgentsAllScopes,\n type CompilationResult,\n type SkillCopyResult,\n discoverInstalledSkills,\n} from \"../lib/operations/index.js\";\nimport { fetchSeedConfig } from \"../lib/seed/fetch-seed.js\";\nimport { seedToWizardResult, type SeedMapping } from \"../lib/seed/seed-to-wizard.js\";\nimport { getInstallationInfo } from \"../lib/plugins/plugin-info.js\";\nimport {\n loadProjectConfig,\n loadProjectConfigFromDir,\n} from \"../lib/configuration/project-config.js\";\nimport { activeAgentNames } from \"../lib/configuration/scope-predicates.js\";\nimport {\n type InstallMode,\n detectInstallation,\n detectGlobalInstallation,\n detectProjectInstallation,\n deriveInstallMode,\n resolveInstallPaths,\n buildAgentScopeMap,\n isHomeDirectory,\n INSTALL_MODE_LABELS,\n INSTALL_MODE_DESCRIPTIONS,\n} from \"../lib/installation/index.js\";\nimport { checkPermissions } from \"../lib/permission-checker.js\";\nimport {\n ASCII_LOGO,\n CLAUDE_SRC_DIR,\n CLI_INVOKE_COMMAND,\n DEFAULT_BRANDING,\n EDIT_PROJECT_SETUP_FLAG,\n EJECT_SOURCE,\n STANDARD_FILES,\n} from \"../consts.js\";\nimport { clearTerminalScreen } from \"../utils/terminal.js\";\nimport { SelectList, type SelectListItem } from \"../components/common/select-list.js\";\nimport { promptValue } from \"../components/common/prompt-confirm.js\";\nimport { Spinner } from \"../components/common/spinner.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport type { AgentName, MergedSkillsMatrix, ProjectConfig, SkillScope } from \"../types/index.js\";\nimport { type StartupMessage } from \"../utils/logger.js\";\nimport {\n SUCCESS_MESSAGES,\n STATUS_MESSAGES,\n globalScopedAgentsHint,\n sharedConfigExistingInstall,\n sharedConfigGlobalInstall,\n} from \"../utils/messages.js\";\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\nconst DASHBOARD_OPTIONS = [\n { label: \"Edit\", value: \"edit\" },\n { label: \"Compile\", value: \"compile\" },\n { label: \"Doctor\", value: \"doctor\" },\n { label: \"List\", value: \"list\" },\n] as const satisfies readonly SelectListItem<string>[];\n\n/** The commands offered by the project dashboard (single source: DASHBOARD_OPTIONS). */\nexport type DashboardCommand = (typeof DASHBOARD_OPTIONS)[number][\"value\"];\n\ntype DashboardProps = {\n onSelect: (command: DashboardCommand) => void;\n onCancel: () => void;\n};\n\nconst Dashboard: React.FC<DashboardProps> = ({ onSelect, onCancel }) => {\n const { exit } = useApp();\n const { rows: terminalHeight } = useTerminalDimensions();\n\n return (\n <Box flexDirection=\"column\" height={terminalHeight}>\n <Box marginBottom={1}>\n <Text>{ASCII_LOGO}</Text>\n </Box>\n <SelectList\n items={DASHBOARD_OPTIONS}\n onSelect={(command) => {\n onSelect(command);\n exit();\n }}\n onCancel={() => {\n onCancel();\n exit();\n }}\n />\n </Box>\n );\n};\n\n/** Formats the dashboard summary as plain text lines (for non-interactive/test output). */\nexport function formatDashboardText(data: DashboardData): string {\n const modeLabel = INSTALL_MODE_LABELS[data.mode];\n const lines = [\n DEFAULT_BRANDING.NAME,\n \"\",\n ` Skills: ${data.skillCount} installed`,\n ` Agents: ${data.agentCount} compiled`,\n ` Mode: ${modeLabel}`,\n ];\n if (data.source) {\n lines.push(` Source: ${data.source}`);\n }\n lines.push(\"\");\n lines.push(` [Edit] [Compile] [Doctor] [List]`);\n return lines.join(\"\\n\");\n}\n\n/**\n * Shows the project dashboard and returns the selected command (or null if cancelled).\n * In non-interactive environments (no TTY), prints the summary text and returns null.\n */\nexport async function showDashboard(\n projectDir: string,\n log?: (message: string) => void,\n): Promise<DashboardCommand | null> {\n const data = await getDashboardData(projectDir);\n\n // Non-interactive: print text summary and exit (CI, piped, tests)\n if (!process.stdin.isTTY) {\n const output = log ?? console.log;\n output(formatDashboardText(data));\n return null;\n }\n\n // First-wins resolution via promptValue; clearOnResolve repaints a clean\n // terminal before unmount (dashboard occupies the full height).\n const selectedCommand = await promptValue<DashboardCommand | null>(\n (resolve) => (\n <Dashboard onSelect={(command) => resolve(command)} onCancel={() => resolve(null)} />\n ),\n { onExit: null, clearOnResolve: true },\n );\n\n clearTerminalScreen();\n\n return selectedCommand;\n}\n\n/**\n * Why the dashboard is on screen.\n *\n * `\"init\"` — the user ran `cc init` in an already-installed directory. That is a request\n * to set this project up, so choosing Edit continues the setup: it must materialise the\n * project even if the wizard changes nothing.\n *\n * `\"standalone\"` — the bare `cc` dashboard. Edit is just an editor there; a pass with no\n * changes is an inspection and must leave the filesystem untouched.\n */\nexport type DashboardOrigin = \"init\" | \"standalone\";\n\n/** The extra argv a dashboard selection needs to carry its origin into the command. */\nfunction dashboardCommandArgv(command: DashboardCommand, origin: DashboardOrigin): string[] {\n if (command !== \"edit\" || origin !== \"init\") return [];\n return [`--${EDIT_PROJECT_SETUP_FLAG}`];\n}\n\n/**\n * Shared dashboard entry: when the project is already initialized, shows the\n * dashboard and runs the chosen command. Returns true when the project was\n * initialized (dashboard shown), false otherwise. Never exits the process —\n * callers decide (the init hook exits SUCCESS at its own call site).\n */\nexport async function runDashboardFlow(\n projectDir: string,\n config: Interfaces.Config,\n origin: DashboardOrigin,\n log?: (message: string) => void,\n): Promise<boolean> {\n const installation = await detectInstallation(projectDir);\n if (!installation) return false;\n\n const selectedCommand = await showDashboard(projectDir, log);\n if (selectedCommand) {\n await config.runCommand(selectedCommand, dashboardCommandArgv(selectedCommand, origin));\n }\n return true;\n}\n\n/**\n * What `init` decided to install, and the little each producer knows that the shared spine does\n * not. Keeping these on the value rather than branching on a flag downstream is what stops the\n * two paths growing separate copies of the install sequence.\n */\n/**\n * The source this run was pointed at, as oclif hands it over.\n *\n * `source` is a required key holding `string | undefined` rather than `source?: string`\n * because that is what oclif produces: a non-required flag still gets its key written on\n * the parse result, set to `undefined` when it was not passed. Under\n * `exactOptionalPropertyTypes` the two are different types, and `?` would be describing a\n * producer that never omits the key.\n */\ntype SourceFlags = { source: string | undefined };\n\ntype Selection = {\n result: WizardResultV2;\n sourceResult: SourceLoadResult;\n /** Whether a person is at the terminal, so the permission notice may wait for them. */\n interactive: boolean;\n /** What to say if the selection turns out to be empty — only the producer knows why it is. */\n emptyMessage: string;\n};\n\n/**\n * Whether a decoded selection would write anything into the user's own ~/.claude. Skills and\n * sub-agents are asked separately because either can be globally scoped on its own: a shared\n * configuration can pin every skill to the project and still send a sub-agent home, and the\n * reverse.\n */\nfunction writesGlobalContent(result: WizardResultV2): boolean {\n return (\n result.skills.some((skill) => skill.scope === \"global\") ||\n result.agentConfigs.some((agent) => agent.scope === \"global\")\n );\n}\n\nexport default class Init extends BaseCommand {\n static summary = `Initialize ${DEFAULT_BRANDING.NAME} in this project`;\n static description =\n \"Interactive wizard to set up skills and agents. Supports Plugin Mode (native install) and Eject Mode (copy to .claude/).\";\n\n static examples = [\n {\n description: \"Start the setup wizard\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Initialize from a custom marketplace\",\n command: \"<%= config.bin %> <%= command.id %> --source github:org/marketplace\",\n },\n ];\n\n static flags = {\n source: Flags.string({\n char: \"s\",\n description: \"Skills source path or URL\",\n required: false,\n }),\n from: Flags.string({\n description: \"Install a configuration shared from agentsinc.sh by its id, without the wizard\",\n helpValue: \"<id>\",\n }),\n };\n\n /**\n * One spine, two producers. The wizard and a shared id differ only in *where the selection\n * comes from* — everything after it (the empty guard, the install pipeline) is identical, so it\n * lives here once rather than being written twice and drifting.\n */\n async run(): Promise<void> {\n const { flags } = await this.parse(Init);\n const projectDir = process.cwd();\n\n // Every route below reads the configs first — to show a dashboard, to refuse a shared id, or\n // to inline the global one. One that exists but cannot be read is recreated, not installed\n // over, and saying so here is what keeps the raw loader error off the screen.\n await this.ensureConfigReadable(projectDir);\n\n // Only a bare `init` is diverted to the dashboard. An id is an explicit instruction to install\n // *that* configuration, so it overrides an existing installation instead.\n if (!flags.from && (await this.showDashboardIfInitialized(projectDir))) return;\n\n const selection = flags.from\n ? await this.selectionFromSharedConfig(flags.from, flags, projectDir)\n : await this.selectionFromWizard(flags, projectDir);\n\n if (!selection) this.exit(EXIT_CODES.CANCELLED);\n\n // On the spine rather than in either producer: a broken constraint is a fact about the\n // selection, not about where it came from, and `edit` reports the same fact the same way\n // the moment the wizard hands it one. Both producers run the same validator over the same\n // matrix — the wizard over what was chosen, `--from` over what survived the decode — so\n // what is said here is this catalog's verdict either way.\n this.reportValidationErrors(selection.result.validation);\n\n // A sub-agent is installable on its own — it has front-matter, a prompt and a compiled file\n // without owning a single skill — so only a selection with neither is nothing to install.\n if (selection.result.skills.length === 0 && selection.result.selectedAgents.length === 0) {\n // The producer supplies the wording because only it knows why empty means what it means:\n // nothing chosen, versus a payload this catalog cannot install.\n this.error(selection.emptyMessage, { exit: EXIT_CODES.ERROR });\n }\n\n await this.handleInstallation(\n selection.result,\n selection.sourceResult,\n flags,\n selection.interactive,\n );\n }\n\n /** The interactive producer: load the source, run the wizard, return what was chosen. */\n private async selectionFromWizard(\n flags: SourceFlags,\n projectDir: string,\n ): Promise<Selection | null> {\n // The blank global config is created by writeProjectConfig() once the\n // wizard succeeds, never before it renders: a cancelled init must leave no\n // artifact that the next run could mistake for an existing installation.\n const isGlobalRoot = isHomeDirectory(projectDir);\n\n const { sourceResult, startupMessages, globalConfig } =\n await this.loadWizardInputsUnderSpinner(flags);\n\n const result = await this.runWizard(\n sourceResult,\n startupMessages,\n projectDir,\n globalConfig,\n isGlobalRoot,\n );\n if (!result) return null;\n\n return {\n result,\n sourceResult,\n // A person is already at the terminal, so the permission notice can wait for them.\n interactive: true,\n emptyMessage: \"No skills selected\",\n };\n }\n\n /**\n * Everything the wizard needs, loaded behind a spinner that comes down whichever way the\n * await ends.\n *\n * The cleanup is a `finally` because a source that cannot be loaded refuses the run from\n * inside this await, and oclif would otherwise paint its error under an Ink tree still\n * repainting over it. Never a `catch`: the throw reaches oclif untouched, or both the\n * error rendering and the exit code change with it.\n */\n private async loadWizardInputsUnderSpinner(flags: SourceFlags): Promise<{\n sourceResult: SourceLoadResult;\n startupMessages: StartupMessage[];\n globalConfig: ProjectConfig | null;\n }> {\n const { unmount, clear: clearSpinner } = render(\n <Spinner label={STATUS_MESSAGES.LOADING_SKILLS} />,\n );\n try {\n const [source, globalConfig] = await Promise.all([\n this.loadSourceOrFail(flags),\n this.loadGlobalConfigIfExists(),\n ]);\n return { ...source, globalConfig };\n } finally {\n clearSpinner();\n unmount();\n }\n }\n\n /**\n * The `--from <id>` producer: fetch and map, no wizard. Nothing here may assume a TTY — running\n * headless is most of why the flag exists.\n *\n * It is also greenfield-only, which is what the two refusals are: a shared configuration is\n * installed whole, so anything it would have to install over has to be uninstalled first.\n */\n private async selectionFromSharedConfig(\n id: string,\n flags: SourceFlags,\n projectDir: string,\n ): Promise<Selection> {\n await this.refuseInstalledProject(projectDir);\n\n this.log(`Fetching configuration ${id}...`);\n const fetched = await fetchSeedConfig(id);\n if (!fetched.ok) {\n this.error(fetched.error, { exit: EXIT_CODES.ERROR });\n }\n\n const { sourceResult } = await this.loadSourceOrFail(flags);\n const { result, skippedSkillIds, skippedAgentNames } = this.decodeSeedOrFail(\n fetched.payload,\n sourceResult.matrix,\n );\n\n await this.refuseBlockingGlobalInstall(result);\n\n // Named, not counted. \"3 skills were skipped\" cannot be acted on; the ids can, and this is the\n // one moment the user can tell whether what they shared is what they are getting.\n if (skippedSkillIds.length > 0) {\n this.warn(\n `Skipped ${skippedSkillIds.length} skill(s) this catalog does not know: ${skippedSkillIds.join(\", \")}`,\n );\n }\n if (skippedAgentNames.length > 0) {\n this.warn(\n `Skipped ${skippedAgentNames.length} unknown sub-agent(s): ${skippedAgentNames.join(\", \")}`,\n );\n }\n\n if (result.skills.length > 0) {\n this.log(\n `Installing ${result.skills.length} skill(s) across ${result.selectedAgents.length} sub-agent(s)\\n`,\n );\n }\n\n return {\n result,\n sourceResult,\n interactive: false,\n emptyMessage: `Configuration '${id}' contains no skills this catalog can install.`,\n };\n }\n\n /**\n * Refuses to install a shared configuration into a directory that already has one.\n *\n * Project-scoped detection rather than `detectInstallation`, whose global fallback would refuse\n * every clean project on a machine with a global install — including for a payload that never\n * goes near it. Whether a global install is in the way is a question about the PAYLOAD, and\n * {@link refuseBlockingGlobalInstall} is where it is asked.\n *\n * This runs before the fetch: there is nothing to learn from the network about a directory that\n * is already spoken for.\n */\n private async refuseInstalledProject(projectDir: string): Promise<void> {\n const installation = await detectProjectInstallation(projectDir);\n if (!installation) return;\n\n this.error(sharedConfigExistingInstall(installation.configPath), { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * The other half of the same rule. A payload carrying global-scoped skills or sub-agents writes\n * into the user's own ~/.claude, so an installation there is in its way even when this project\n * is spotless. A payload with nothing global cannot reach that far and is never refused for it.\n */\n private async refuseBlockingGlobalInstall(result: WizardResultV2): Promise<void> {\n if (!writesGlobalContent(result)) return;\n\n const globalInstallation = await detectGlobalInstallation();\n if (!globalInstallation) return;\n\n this.error(sharedConfigGlobalInstall(globalInstallation.configPath), {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n /**\n * The decode refuses a payload the config model has nowhere to write (see `seedToWizardResult`).\n * That is a failure of this command, reported with this command's exit code rather than left to\n * surface as an unhandled throw.\n */\n private decodeSeedOrFail(payload: SeedPayload, matrix: MergedSkillsMatrix): SeedMapping {\n try {\n return seedToWizardResult(payload, matrix);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private async showDashboardIfInitialized(projectDir: string): Promise<boolean> {\n return runDashboardFlow(projectDir, this.config, \"init\", (msg) => this.log(msg));\n }\n\n private async loadGlobalConfigIfExists(): Promise<ProjectConfig | null> {\n const globalInstall = await detectGlobalInstallation();\n if (!globalInstall) return null;\n const loaded = await loadProjectConfigFromDir(os.homedir());\n return loaded?.config ?? null;\n }\n\n private async loadSourceOrFail(\n flags: SourceFlags,\n ): Promise<{ sourceResult: SourceLoadResult; startupMessages: StartupMessage[] }> {\n try {\n const loaded = await loadSource({\n // The one load that may CHOOSE a source rather than read the stored one.\n caller: \"init\",\n ...(flags.source !== undefined && { sourceFlag: flags.source }),\n projectDir: process.cwd(),\n captureStartupMessages: true,\n });\n return { sourceResult: loaded.sourceResult, startupMessages: loaded.startupMessages };\n } catch (error) {\n this.error(getErrorMessage(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n private async runWizard(\n sourceResult: SourceLoadResult,\n startupMessages: StartupMessage[],\n projectDir: string,\n globalConfig: ProjectConfig | null,\n isGlobalRoot: boolean,\n ): Promise<WizardResultV2 | null> {\n const selectedAgents = globalConfig?.agents && activeAgentNames(globalConfig.agents);\n const globalSkills = globalConfig?.skills;\n\n return runWizardSession({\n hydrate: {\n ...(selectedAgents !== undefined && { initialAgents: selectedAgents }),\n ...(globalSkills !== undefined && {\n installedSkillIds: globalSkills.map((s) => s.id),\n installedSkillConfigs: globalSkills,\n }),\n ...(globalConfig?.agents !== undefined && { installedAgentConfigs: globalConfig.agents }),\n isEditingFromGlobalScope: isGlobalRoot,\n },\n props: {\n version: this.config.version,\n logo: ASCII_LOGO,\n initialAgents: selectedAgents,\n installedSkillIds: globalConfig?.skills.map((s) => s.id),\n startupMessages,\n },\n onCancel: () => this.log(\"Setup cancelled\"),\n clearTerminal: () => this.clearTerminal(),\n });\n }\n\n private async handleInstallation(\n result: WizardResultV2,\n sourceResult: SourceLoadResult,\n flags: SourceFlags,\n /**\n * Whether the caller can hold the terminal. The permission notice is an Ink app with no exit\n * of its own, so `waitUntilExit()` only ever resolves because a person is there to end it —\n * which is fine after the wizard and a hang everywhere else. `--from` sets this false: it has\n * to complete over a pipe and in CI.\n */\n interactive = true,\n ): Promise<void> {\n const projectDir = process.cwd();\n const activeSkills = result.skills.filter((s) => !s.excluded);\n const installMode = deriveInstallMode(activeSkills);\n const ejectedSkills = activeSkills.filter((s) => s.source === EJECT_SOURCE);\n const pluginSkills = activeSkills.filter((s) => s.source !== EJECT_SOURCE);\n\n this.logInstallPlan(installMode, ejectedSkills, pluginSkills);\n\n // Resolve marketplace up front — BEFORE any filesystem mutation. If\n // resolution fails in mixed mode, the hard-error must fire before\n // `copyEjectSkillsStep` copies anything to `.claude/skills/`, otherwise\n // we leave an orphaned half-install with no config.ts to recognise it.\n const resolvedMarketplace =\n pluginSkills.length > 0\n ? await this.requireMarketplaceOrExit(\n sourceResult,\n \"install plugin skills\",\n (marketplace) => this.log(`Registering marketplace \"${marketplace}\"...`),\n )\n : null;\n\n const copyResult =\n installMode === \"eject\" || installMode === \"mixed\"\n ? await this.copyEjectSkillsStep(ejectedSkills, projectDir, sourceResult, installMode)\n : null;\n\n if (resolvedMarketplace !== null) {\n await this.installPluginSkillsReported(pluginSkills, resolvedMarketplace, projectDir);\n }\n // The shared install reporter hard-errors on any failure, so reaching here with\n // a resolved marketplace means plugin mode fully succeeded.\n const pluginModeSucceeded = resolvedMarketplace !== null;\n\n try {\n const { configResult, compileResult, agentScopeMap } = await this.writeConfigAndCompile(\n result,\n sourceResult,\n flags,\n );\n this.reportSuccess(\n configResult,\n compileResult,\n agentScopeMap,\n installMode,\n pluginModeSucceeded,\n copyResult,\n );\n\n await this.showPermissionNotice(projectDir, interactive);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /**\n * The permission notice, where there is one to show. It is an Ink app with no exit of its own,\n * so `waitUntilExit()` only ever resolves because a person is there to end it — which is fine\n * after the wizard and a hang everywhere else. Without a terminal to hold, one frame is\n * rendered and let go: the notice is information, not a prompt, so there is nothing to answer\n * and nothing to wait for.\n */\n private async showPermissionNotice(projectDir: string, interactive: boolean): Promise<void> {\n const permissionWarning = await checkPermissions(projectDir);\n if (!permissionWarning) return;\n\n if (!interactive) {\n const { unmount } = render(permissionWarning);\n unmount();\n return;\n }\n\n const { waitUntilExit } = render(permissionWarning);\n await waitUntilExit();\n }\n\n private logInstallPlan(\n installMode: InstallMode,\n ejectedSkills: WizardResultV2[\"skills\"],\n pluginSkills: WizardResultV2[\"skills\"],\n ): void {\n this.log(\"\\n\");\n this.log(`Selected ${ejectedSkills.length + pluginSkills.length} skills`);\n this.log(\n `Install mode: ${\n installMode === \"mixed\"\n ? `${INSTALL_MODE_LABELS.mixed} (${ejectedSkills.length} eject, ${pluginSkills.length} plugin)`\n : INSTALL_MODE_DESCRIPTIONS[installMode]\n }`,\n );\n }\n\n private async copyEjectSkillsStep(\n localSkills: WizardResultV2[\"skills\"],\n projectDir: string,\n sourceResult: SourceLoadResult,\n installMode: InstallMode,\n ): Promise<SkillCopyResult> {\n this.log(\"Copying skills to local directory...\");\n const copyResult = await copyLocalSkills(localSkills, projectDir, sourceResult);\n\n if (installMode === \"mixed\") {\n if (copyResult.projectCopied.length > 0 && copyResult.globalCopied.length > 0) {\n this.log(\n `Copied ${copyResult.totalCopied} local skills (${copyResult.projectCopied.length} project, ${copyResult.globalCopied.length} global)`,\n );\n } else if (copyResult.globalCopied.length > 0) {\n this.log(`Copied ${copyResult.globalCopied.length} local skills to ~/.claude/skills/`);\n } else {\n this.log(`Copied ${copyResult.projectCopied.length} local skills to .claude/skills/`);\n }\n } else {\n this.log(`Copied ${copyResult.totalCopied} skills to .claude/skills/\\n`);\n }\n\n return copyResult;\n }\n\n private async writeConfigAndCompile(\n result: WizardResultV2,\n sourceResult: SourceLoadResult,\n flags: SourceFlags,\n ): Promise<{\n configResult: Awaited<ReturnType<typeof writeProjectConfig>>;\n compileResult: CompilationResult;\n agentScopeMap: Map<AgentName, SkillScope>;\n }> {\n this.log(\"Generating configuration...\");\n const configResult = await writeProjectConfig({\n wizardResult: result,\n sourceResult,\n projectDir: process.cwd(),\n ...(flags.source !== undefined && { sourceFlag: flags.source }),\n });\n\n if (configResult.wasMerged) {\n this.log(`Merged with existing config at ${configResult.existingConfigPath}`);\n }\n\n this.log(`Configuration saved (${configResult.config.agents.length} agents)\\n`);\n this.reportUnassignedSkills(configResult.config);\n\n this.log(STATUS_MESSAGES.COMPILING_AGENTS);\n const cwd = process.cwd();\n const agentDefs = await loadAgentDefs();\n const { allSkills } = await discoverInstalledSkills(cwd);\n const agentScopeMap = buildAgentScopeMap(configResult.config);\n const compileResult = await compileAgentsAllScopes({\n projectDir: cwd,\n sourcePath: agentDefs.sourcePath,\n skills: allSkills,\n agentScopeMap,\n });\n this.log(`Compiled ${compileResult.compiled.length} agents\\n`);\n\n this.reportPropagatedRecompile(configResult.propagation);\n\n return { configResult, compileResult, agentScopeMap };\n }\n\n private reportSuccess(\n configResult: Awaited<ReturnType<typeof writeProjectConfig>>,\n compileResult: CompilationResult,\n agentScopeMap: Map<AgentName, SkillScope>,\n installMode: InstallMode,\n pluginModeSucceeded: boolean,\n copyResult: SkillCopyResult | null,\n ): void {\n this.log(`${SUCCESS_MESSAGES.INIT_SUCCESS}\\n`);\n\n const isEjectOutput =\n installMode === \"eject\" || (installMode === \"mixed\" && !pluginModeSucceeded);\n if (isEjectOutput && copyResult && copyResult.totalCopied > 0) {\n this.reportSkillsCopied(copyResult);\n }\n this.reportAgentsCompiled(compileResult.compiled, agentScopeMap);\n this.reportConfiguration(configResult.configPath, agentScopeMap);\n }\n\n /**\n * Names the config that actually holds this install's assignments, and where a\n * recompile of them has to be run from.\n *\n * Split by the same `agentScopeMap` the two reporters above split on, because the\n * same scope decides both. A project config's `stack` is filtered down to\n * project-scoped agents on the way out, so a wholly GLOBAL install leaves it\n * carrying no assignment at all — naming it sends the user to a file with nothing\n * in it — and `compile` in this cwd runs the PROJECT pass, which recompiles no\n * global agent. At the home root both scopes resolve to one file and one pass, so\n * there is nothing to split and the project wording stands.\n */\n private reportConfiguration(\n projectConfigPath: string,\n agentScopeMap: Map<AgentName, SkillScope>,\n ): void {\n const cwd = process.cwd();\n const paths = {\n global: resolveInstallPaths(cwd, \"global\").configPath,\n project: projectConfigPath,\n };\n const split = splitAgentScopes(cwd, agentScopeMap);\n\n this.log(\"Configuration:\");\n for (const configPath of configsHoldingAssignments(split, paths)) {\n this.log(` ${configPath}`);\n }\n this.log(\"\");\n\n this.log(\"To customize agent-skill assignments:\");\n for (const [index, step] of customizationSteps(split, paths.global).entries()) {\n this.log(` ${index + 1}. ${step}`);\n }\n this.log(\"\");\n }\n\n /**\n * Reports where the skills actually landed. `copyLocalSkills` splits by scope,\n * so a default install driven from a project directory writes every skill\n * under HOME — reporting the project path there names a directory that was\n * never written.\n *\n * This block is a filesystem listing, so the entries are the on-disk directory\n * names — skill ids, not display names. `copySkillsToLocalFlattened` names each\n * destination directory after `skill.id`, so a user can copy any line and `cd`\n * into it.\n */\n private reportSkillsCopied(copyResult: SkillCopyResult): void {\n const cwd = process.cwd();\n const groups = isHomeDirectory(cwd)\n ? [\n {\n dir: resolveInstallPaths(cwd, \"project\").skillsDir,\n copied: [...copyResult.globalCopied, ...copyResult.projectCopied],\n },\n ]\n : [\n { dir: resolveInstallPaths(cwd, \"global\").skillsDir, copied: copyResult.globalCopied },\n { dir: resolveInstallPaths(cwd, \"project\").skillsDir, copied: copyResult.projectCopied },\n ].filter((group) => group.copied.length > 0);\n\n for (const group of groups) {\n this.log(\"Skills copied to:\");\n this.log(` ${group.dir}`);\n for (const copied of group.copied) {\n this.log(` ${copied.skillId}/`);\n }\n this.log(\"\");\n }\n }\n\n /**\n * Reports where the agents actually landed, mirroring the scope split\n * `compileAgentsAllScopes` performs: one pass at the home root, otherwise a\n * global pass under HOME and a project pass under the project directory.\n */\n private reportAgentsCompiled(\n compiled: AgentName[],\n agentScopeMap: Map<AgentName, SkillScope>,\n ): void {\n const cwd = process.cwd();\n const groups = isHomeDirectory(cwd)\n ? [{ dir: resolveInstallPaths(cwd, \"project\").agentsDir, agents: compiled }]\n : [\n {\n dir: resolveInstallPaths(cwd, \"global\").agentsDir,\n agents: compiled.filter((name) => agentScopeMap.get(name) === \"global\"),\n },\n {\n dir: resolveInstallPaths(cwd, \"project\").agentsDir,\n agents: compiled.filter((name) => agentScopeMap.get(name) !== \"global\"),\n },\n ].filter((group) => group.agents.length > 0);\n\n for (const group of groups) {\n this.log(\"Agents compiled to:\");\n this.log(` ${group.dir}`);\n for (const agentName of group.agents) {\n this.log(` ${agentName}.md`);\n }\n this.log(\"\");\n }\n }\n}\n\n/** The two config files an install can write, as the closing block refers to them. */\ntype ConfigPaths = { global: string; project: string };\n\n/** How this install's sub-agents fall across the two scopes, seen from the directory it ran in. */\ntype AgentScopeSplit = { globalAgentCount: number; isGlobalOnly: boolean };\n\n/**\n * At the home root the two scopes resolve to ONE config file and ONE compile pass, so there\n * is nothing to split and the split reports none — which is what leaves the project wording\n * standing there unchanged. Same fork `reportAgentsCompiled` makes over the same question.\n */\nfunction splitAgentScopes(cwd: string, agentScopeMap: Map<AgentName, SkillScope>): AgentScopeSplit {\n if (isHomeDirectory(cwd)) return { globalAgentCount: 0, isGlobalOnly: false };\n\n const scopes = [...agentScopeMap.values()];\n const globalAgentCount = scopes.filter((scope) => scope === \"global\").length;\n return {\n globalAgentCount,\n isGlobalOnly: globalAgentCount > 0 && globalAgentCount === scopes.length,\n };\n}\n\n/**\n * The config file(s) this install's assignments actually landed in. A wholly global install\n * has none in the project file — the writer filters its `stack` down to project-scoped\n * agents — so naming it would send the user to a file with nothing in it.\n */\nfunction configsHoldingAssignments(split: AgentScopeSplit, paths: ConfigPaths): string[] {\n if (split.isGlobalOnly) return [paths.global];\n if (split.globalAgentCount > 0) return [paths.global, paths.project];\n return [paths.project];\n}\n\n/**\n * What changing an assignment takes, in the order it takes it. The compile step is the half\n * that has to be scope-aware: `compile` run in a project directory performs the PROJECT pass\n * only, so it recompiles no global agent — which `globalScopedAgentsHint` already says, in\n * the words `compile` itself says it in when it lands in the mirror image of this state.\n */\nfunction customizationSteps(split: AgentScopeSplit, globalConfigPath: string): string[] {\n if (split.isGlobalOnly) {\n return [`Edit ${globalConfigPath}`, globalScopedAgentsHint(split.globalAgentCount)];\n }\n\n return [\n `Edit ${CLAUDE_SRC_DIR}/${STANDARD_FILES.CONFIG_TS}`,\n `Run '${CLI_INVOKE_COMMAND} compile' to regenerate agents`,\n ...(split.globalAgentCount > 0 ? [globalScopedAgentsHint(split.globalAgentCount)] : []),\n ];\n}\n\nexport type DashboardData = {\n skillCount: number;\n agentCount: number;\n mode: InstallMode;\n source?: string;\n};\n\n/**\n * Gathers dashboard data from the installation and project config.\n *\n * Both counts come from the same scope-aware installation so the summary cannot\n * mix a project-only figure with a global one — a default install driven from a\n * project directory puts every skill and agent under HOME.\n */\nexport async function getDashboardData(projectDir: string): Promise<DashboardData> {\n const [info, loaded] = await Promise.all([getInstallationInfo(), loadProjectConfig(projectDir)]);\n\n const activeSkills = loaded?.config.skills.filter((s) => !s.excluded);\n const skillCount = info?.skillCount ?? 0;\n const agentCount = info?.agentCount ?? 0;\n const mode = info?.mode ?? (activeSkills ? deriveInstallMode(activeSkills) : \"eject\");\n const source = loaded?.config.source;\n\n return { skillCount, agentCount, mode, ...(source !== undefined && { source }) };\n}\n","import { seedPayloadSchema, type SeedPayload } from \"@workspace/matrix/seed\";\n\n/** The config store behind agentsinc.sh. Overridable so tests never touch the network. */\nexport const SEED_API_URL = process.env.AGENTS_INC_API_URL ?? \"https://api.agentsinc.sh\";\n\n/**\n * Identifies this fetch as the CLI rather than a browser.\n *\n * `GET /configs/:id` is the only place either side can observe a config being *installed* rather\n * than merely built, and the worker can only separate that from someone opening a share link if\n * we say so. Without this the conversion signal does not exist.\n */\nexport const SEED_USER_AGENT = \"agents-inc-cli\";\n\nexport type FetchSeedResult = { ok: true; payload: SeedPayload } | { ok: false; error: string };\n\n/**\n * Fetches and validates a shared configuration.\n *\n * Every failure is a message rather than a throw: this runs before anything has been written, so\n * there is nothing to roll back and the caller's job is to explain rather than recover.\n */\nexport async function fetchSeedConfig(id: string): Promise<FetchSeedResult> {\n const url = `${SEED_API_URL}/configs/${encodeURIComponent(id)}`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n headers: { accept: \"application/json\", \"user-agent\": SEED_USER_AGENT },\n });\n } catch {\n return { ok: false, error: `Could not reach ${SEED_API_URL} — check your connection.` };\n }\n\n if (response.status === 404) {\n return { ok: false, error: `No configuration found for id '${id}'.` };\n }\n if (!response.ok) {\n return { ok: false, error: `Fetching configuration failed (HTTP ${response.status}).` };\n }\n\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n return { ok: false, error: \"The configuration store returned something that is not JSON.\" };\n }\n\n const parsed = seedPayloadSchema.safeParse(body);\n if (!parsed.success) {\n // Validated on the way in, so a stored payload that no longer parses means the contract moved\n // underneath it — worth saying plainly rather than reporting a generic failure.\n return {\n ok: false,\n error: `Configuration '${id}' does not match the expected format — it may have been created by a newer version.`,\n };\n }\n\n return { ok: true, payload: parsed.data };\n}\n","import { DEFAULT_SELECTION_OPTIONS } from \"@workspace/matrix\";\n\nimport { AGENT_NAMES } from \"../../types/agents.js\";\nimport { DEFAULT_PUBLIC_SOURCE_NAME } from \"../../consts.js\";\nimport { isScopePairCompatible } from \"../configuration/config-generator.js\";\nimport { getCategoryDomain } from \"../matrix/matrix-provider.js\";\nimport { validateSelection } from \"../matrix/matrix-resolver.js\";\nimport { orderDomains } from \"../wizard/domain-order.js\";\n\nimport type { WizardResultV2 } from \"../../components/wizard/wizard.js\";\nimport type { AgentName } from \"../../types/agents.js\";\nimport type { AgentScopeConfig, SkillConfig, SkillScope } from \"../../types/config.js\";\nimport type {\n Category,\n Domain,\n DomainSelections,\n MergedSkillsMatrix,\n ResolvedSkill,\n} from \"../../types/matrix.js\";\nimport type { SkillAssignment, SkillId } from \"../../types/skills.js\";\nimport type { StackAgentConfig } from \"../../types/stacks.js\";\nimport type { SeedAgent, SeedLoadState, SeedPayload } from \"@workspace/matrix/seed\";\n\nexport type SeedMapping = {\n result: WizardResultV2;\n /** Ids this matrix 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: ResolvedSkill | undefined): string {\n return skill?.availableSources?.find((s) => s.primary)?.name ?? DEFAULT_PUBLIC_SOURCE_NAME;\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(skillId: SkillId, load: SeedLoadState): 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 (!KNOWN_AGENTS.has(name)) unknown.push(name);\n else if (entry.on === false) switchedOff.add(name);\n else known.set(name as AgentName, entry);\n }\n\n return { known, switchedOff, unknown };\n}\n\n/**\n * Where a sub-agent's front-matter is written is the payload's to say, per agent and\n * independently of any skill's scope: an entry may pin its agent into the project, and one that\n * names no scope goes to the user's own ~/.claude — the shared selection default, spelled once in\n * the matrix so the editor and this decode cannot disagree about it.\n */\nfunction seedAgentScope(entry: SeedAgent | undefined): SkillScope {\n return entry?.scope ?? DEFAULT_SELECTION_OPTIONS.scope;\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(name: AgentName, entry: SeedAgent | undefined): 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(assignments: UnwritableAssignment[]): 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(payload: SeedPayload, matrix: MergedSkillsMatrix): 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 = matrix.skills[skillId as SkillId];\n const domain = skill?.category ? getCategoryDomain(skill.category) : undefined;\n\n if (!skill?.category || !domain) {\n skippedSkillIds.push(skillId);\n continue;\n }\n\n // Past the guard the matrix 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 const id = skillId as SkillId;\n const category = skill.category as Category;\n\n addToDomainSelections(domainSelections, domain, category, id);\n\n skills.push({\n id,\n scope: entry.scope,\n // \"eject\" is a source in its own right; anything else names the marketplace it came from.\n source: entry.install === \"eject\" ? \"eject\" : 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 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 (!isScopePairCompatible(entry.scope, seedAgentScope(agentMap.known.get(agent)))) {\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(assignedStack, agent, category, toSkillAssignment(id, load));\n }\n }\n\n if (unwritable.length > 0) 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) => agentScopeConfig(name, agentMap.known.get(name))),\n assignedStack,\n selectedStackId: payload.stackId,\n domainSelections,\n selectedDomains: orderDomains(Object.keys(domainSelections) as Domain[]),\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. Running the same validator the wizard runs\n // makes that this catalog's verdict on what it can install — reported through the spine\n // `init` already has, beside the skips that explain it — rather than a fault in what was\n // shared.\n validation: validateSelection(skills.map((skill) => skill.id)),\n },\n skippedSkillIds,\n skippedAgentNames: [...skippedAgentNames],\n };\n}\n","import React from \"react\";\nimport { z } from \"zod\";\n\nimport { Text, Box } from \"ink\";\nimport path from \"path\";\n\nimport { CLAUDE_DIR, CLI_COLORS, MAX_CONFIG_FILE_SIZE, STANDARD_FILES } from \"../consts\";\nimport { fileExists, readFileSafe } from \"../utils/fs\";\nimport { warn } from \"../utils/logger\";\nimport { settingsFileSchema } from \"./schemas\";\n\ntype SettingsFile = z.infer<typeof settingsFileSchema>;\ntype PermissionConfig = NonNullable<SettingsFile[\"permissions\"]>;\n\n/**\n * Reads one settings file's permissions block; undefined when absent, malformed, or empty.\n *\n * settings.json belongs to Claude Code, which adds keys on its own release schedule. This CLI\n * consumes `permissions` and owns nothing else in the file, so it stays silent about every other\n * field rather than warning about settings it has no standing to judge (D-304).\n */\nasync function readSettingsPermissions(filePath: string): Promise<PermissionConfig | undefined> {\n if (!(await fileExists(filePath))) return undefined;\n try {\n const content = await readFileSafe(filePath, MAX_CONFIG_FILE_SIZE);\n const raw: unknown = JSON.parse(content);\n const result = settingsFileSchema.safeParse(raw);\n const parsed: SettingsFile = result.success ? result.data : {};\n return parsed.permissions;\n } catch {\n warn(`Malformed settings file at '${filePath}' — skipping`);\n return undefined;\n }\n}\n\n/** Permissions from the first settings file that defines them — settings.local.json wins. */\nasync function loadPermissions(projectRoot: string): Promise<PermissionConfig | undefined> {\n const settingsPath = path.join(projectRoot, CLAUDE_DIR, STANDARD_FILES.SETTINGS_JSON);\n const localSettingsPath = path.join(projectRoot, CLAUDE_DIR, STANDARD_FILES.SETTINGS_LOCAL_JSON);\n\n for (const filePath of [localSettingsPath, settingsPath]) {\n const permissions = await readSettingsPermissions(filePath);\n if (permissions) return permissions;\n }\n return undefined;\n}\n\nexport async function checkPermissions(projectRoot: string): Promise<React.ReactElement | null> {\n const permissions = await loadPermissions(projectRoot);\n\n if (!permissions) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={CLI_COLORS.WARNING} padding={1}>\n <Text bold color={CLI_COLORS.WARNING}>\n Permission Notice\n </Text>\n <Text>No permissions configured in .claude/settings.json</Text>\n <Text>Agents will prompt for approval on each tool use.</Text>\n <Text> </Text>\n <Text>For autonomous operation, add to .claude/settings.json:</Text>\n <Text> </Text>\n <Text color={CLI_COLORS.DIM}>{\"{\"}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"permissions\": {'}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"allow\": ['}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"Read(*)\",'}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"Bash(git *)\",'}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"Bash(bun *)\"'}</Text>\n <Text color={CLI_COLORS.DIM}>{\" ]\"}</Text>\n <Text color={CLI_COLORS.DIM}>{\" }\"}</Text>\n <Text color={CLI_COLORS.DIM}>{\"}\"}</Text>\n </Box>\n );\n }\n\n const hasRestrictiveBash = permissions.deny?.some(\n (rule) => rule === \"Bash(*)\" || rule === \"Bash\",\n );\n const hasNoAllows = !permissions.allow || permissions.allow.length === 0;\n\n if (hasRestrictiveBash || hasNoAllows) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={CLI_COLORS.WARNING} padding={1}>\n <Text bold color={CLI_COLORS.WARNING}>\n Permission Warnings\n </Text>\n {hasRestrictiveBash && (\n <Text>\n ⚠ Bash is denied in permissions. Some agents require Bash for git, testing, and build\n commands.\n </Text>\n )}\n {hasNoAllows && (\n <Text>⚠ No allow rules configured. Agents will prompt for each tool use.</Text>\n )}\n </Box>\n );\n }\n\n return null;\n}\n"],"mappings":"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","names":["Box","Text","jsx","jsxs","Box","Text"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/lib/operations/skills/install-plugin-skills.ts"],"sourcesContent":["import { claudePluginInstall } from \"../../../utils/exec.js\";\nimport { buildMarketplacePluginRef, toClaudePluginScope } from \"../../plugins/index.js\";\nimport { getErrorMessage } from \"../../../utils/errors.js\";\nimport { CLI_INVOKE_COMMAND, EJECT_SOURCE } from \"../../../consts.js\";\nimport type { SkillId } from \"../../../types/index.js\";\nimport type { SkillConfig } from \"../../../types/config.js\";\n\nexport type PluginInstallResult = {\n installed: Array<{ id: SkillId; ref: string }>;\n failed: Array<{ id: SkillId; error: string }>;\n};\n\n/**\n * Hard-error message for failed plugin installs. Plugin install intent is\n * inviolable (never fall back to eject) — callers MUST error with this BEFORE\n * config is written, or config.ts gains orphan entries claiming the skill\n * is installed.\n */\nexport function pluginInstallFailureError(failedCount: number): string {\n return `Failed to install ${failedCount} plugin skill(s). Plugin install intent could not be honored. Verify the skill id matches the marketplace, run '${CLI_INVOKE_COMMAND} update' to refresh the marketplace, or switch affected skills to eject mode.`;\n}\n\n/**\n * Installs skill plugins via the Claude CLI, routing by scope.\n *\n * For each skill, constructs the plugin ref as `{skillId}@{marketplace}`\n * and invokes `claudePluginInstall` with the correct scope.\n */\nexport async function installPluginSkills(\n skills: SkillConfig[],\n marketplace: string,\n projectDir: string,\n): Promise<PluginInstallResult> {\n const pluginSkills = skills.filter((s) => s.source !== EJECT_SOURCE);\n const installed: PluginInstallResult[\"installed\"] = [];\n const failed: PluginInstallResult[\"failed\"] = [];\n\n for (const skill of pluginSkills) {\n const pluginRef = buildMarketplacePluginRef(skill.id, marketplace);\n const pluginScope = toClaudePluginScope(skill.scope);\n try {\n await claudePluginInstall(pluginRef, pluginScope, projectDir);\n installed.push({ id: skill.id, ref: pluginRef });\n } catch (error) {\n failed.push({ id: skill.id, error: getErrorMessage(error) });\n }\n }\n\n return { installed, failed };\n}\n"],"mappings":";;;;;;;;;;;;;;;AAkBO,SAAS,0BAA0B,aAA6B;AACrE,SAAO,qBAAqB,WAAW,mHAAmH,kBAAkB;AAC9K;AAQA,eAAsB,oBACpB,QACA,aACA,YAC8B;AAC9B,QAAM,eAAe,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,YAAY;AACnE,QAAM,YAA8C,CAAC;AACrD,QAAM,SAAwC,CAAC;AAE/C,aAAW,SAAS,cAAc;AAChC,UAAM,YAAY,0BAA0B,MAAM,IAAI,WAAW;AACjE,UAAM,cAAc,oBAAoB,MAAM,KAAK;AACnD,QAAI;AACF,YAAM,oBAAoB,WAAW,aAAa,UAAU;AAC5D,gBAAU,KAAK,EAAE,IAAI,MAAM,IAAI,KAAK,UAAU,CAAC;AAAA,IACjD,SAAS,OAAO;AACd,aAAO,KAAK,EAAE,IAAI,MAAM,IAAI,OAAO,gBAAgB,KAAK,EAAE,CAAC;AAAA,IAC7D;AAAA,EACF;AAEA,SAAO,EAAE,WAAW,OAAO;AAC7B;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/components/wizard/source-grid.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport { Box, Text, useInput, type Key } from \"ink\";\nimport type { InstallMode, SkillId, SkillScope } from \"../../types/index.js\";\nimport { CLI_COLORS, INSTALL_MODE_CELL_LABELS, UI_SYMBOLS } from \"../../consts.js\";\nimport { getSkillById } from \"../../lib/matrix/matrix-provider.js\";\nimport { useFocusedListItem } from \"../hooks/use-focused-list-item.js\";\nimport { useSectionScroll } from \"../hooks/use-section-scroll.js\";\nimport { KEY_SPACE } from \"./hotkeys.js\";\nimport { ScrollAffordance } from \"./scroll-affordance.js\";\n\n/**\n * Skill-name cell: the 24 columns the name itself gets, plus the fixed 2-column marker cell that\n * shares the box (see `rowStatusMarker`). Widening by exactly the marker width keeps every name\n * that fitted before the marker was reserved fitting still.\n */\nconst SKILL_NAME_WIDTH = 26;\nconst INSTALL_MODE_COL_WIDTH = 18;\n\n/**\n * Scope gutter: the column of `Global` / `Project` row headers down the left of a scope-grouped\n * grid. Present only in the grouped layout — a single-scope grid has nothing to head, and renders\n * flat with no gutter at all. The header row reserves the width but prints no caption in it: the\n * labels below already name the column, so a caption over them would only repeat them.\n */\nconst SCOPE_COL_WIDTH = 11;\n\n/** Row-header label each scope block is headed by. */\nconst SCOPE_ROW_HEADERS: Record<SkillScope, string> = {\n global: \"Global\",\n project: \"Project\",\n};\n\n/** Blank marker cell — the same two columns a `${glyph} ` marker costs, so names never shift. */\nconst ROW_MARKER_BLANK = \" \";\n\n/**\n * Sources always clips-and-signals rather than bleeding, even at the very short viewports the wizard\n * still renders at (the Sources step is squeezed by the tab bar, dropdown card and footer): a single\n * clipped row plus the overflow affordance beats a bled grid. Distinct from the grid views that fall\n * back to a flex layout below SCROLL_VIEWPORT.MIN_VIEWPORT_ROWS.\n */\nconst SOURCE_GRID_MIN_VIEWPORT_ROWS = 1;\n\n/**\n * One cell of a row's install-mode control. There is no `id`: the two cells ARE the choice, and\n * the `SkillConfig.source` each one writes is the store's to resolve — which is what stops this\n * surface from writing a source value nothing installs from (CLI-450).\n */\nexport type SourceOption = {\n mode: Exclude<InstallMode, \"mixed\">;\n selected: boolean;\n};\n\nexport type SourceRow = {\n skillId: SkillId;\n /** The row's two install-mode cells, in render order. */\n options: SourceOption[];\n scope?: SkillScope;\n readOnly?: boolean;\n /**\n * Saved skill deselected this session — still shown so the user can see what saving removes,\n * but inert. Distinct from `readOnly`, which means \"locked because it is installed globally\".\n */\n disabled?: boolean;\n /**\n * Skill selected this session but absent from the hydration snapshot (D-258). Renders inline in\n * its normal position with the info panel's added marker (`+`) in green, and stays a normal\n * selectable/editable row — unlike `disabled`/`readOnly`, an added row is NOT inert.\n */\n added?: boolean;\n};\n\n/** Rows the user cannot act on: globally locked (`readOnly`) or pending removal (`disabled`). */\nexport function isRowInert(row: SourceRow): boolean {\n return !!row.readOnly || !!row.disabled;\n}\n\n/**\n * Status marker before the skill name. Lock = \"installed globally, not yours to change here\".\n * The removal marker + red colour and the added marker + green colour mirror the info panel's\n * removed/added-diff treatment (DIFF_PREFIX/DIFF_COLOR in skill-agent-summary.tsx) so a\n * pending-removal or added row reads the same on both surfaces. The marker (not the colour) is\n * what carries the meaning in no-color terminals.\n *\n * ALWAYS two columns wide — glyph plus one separating space, or `ROW_MARKER_BLANK` on a row with no\n * status — so every skill name starts in the same column whether or not its row is marked. Same\n * contract as DIFF_PREFIX, which gives even `unchanged` a 2-char prefix. `UI_SYMBOLS.LOCK` is\n * double-width and still renders a locked row one column wider; known and accepted.\n */\nfunction rowStatusMarker(row: SourceRow): string {\n if (row.readOnly) return `${UI_SYMBOLS.LOCK} `;\n if (row.disabled) return `${UI_SYMBOLS.REMOVED} `;\n if (row.added) return `${UI_SYMBOLS.ADDED} `;\n return ROW_MARKER_BLANK;\n}\n\n/**\n * Diff colour for a row's skill name, matching the info panel's palette (DIFF_COLOR in\n * skill-agent-summary.tsx): red = pending removal, green = added. `undefined` means the row carries\n * no diff status, so each caller supplies its own default.\n */\nfunction rowDiffColor(row: SourceRow): string | undefined {\n if (row.disabled) return CLI_COLORS.ERROR;\n if (row.added) return CLI_COLORS.SUCCESS;\n return undefined;\n}\n\n/** Skill-name colour for an unfocused row: its diff colour, or the neutral default. */\nfunction rowLabelColor(row: SourceRow): string {\n return rowDiffColor(row) ?? CLI_COLORS.NEUTRAL;\n}\n\n/**\n * Skill-name colour for the FOCUSED row, which renders on the dark LABEL_BG highlight. A diff row\n * keeps its diff colour — focus is not a reason to lose the added/removed signal. An ordinary row\n * deliberately stays plain WHITE rather than falling through to `rowLabelColor`: NEUTRAL grey on\n * LABEL_BG is the low-contrast pairing, so reusing it here would dim every ordinary focused row to\n * fix rows that have no diff to show in the first place.\n */\nfunction focusedRowLabelColor(row: SourceRow): string {\n return rowDiffColor(row) ?? CLI_COLORS.WHITE;\n}\n\nexport type SourceGridProps = {\n rows: SourceRow[];\n /** Available height in terminal lines for the scrollable viewport. 0 = no constraint. */\n availableHeight?: number;\n onSelect: (skillId: SkillId, mode: Exclude<InstallMode, \"mixed\">) => void;\n /** Optional initial focus row (default: 0). Use with React `key` to reset. */\n defaultFocusedRow?: number;\n /** Optional initial focus col (default: 0). Use with React `key` to reset. */\n defaultFocusedCol?: number;\n /** Optional callback fired whenever the focused position changes */\n onFocusChange?: (row: number, col: number) => void;\n};\n\ntype SourceSectionProps = {\n row: SourceRow;\n isFocused: boolean;\n focusedOptionIndex: number;\n};\n\nconst SourceTag: React.FC<{\n option: SourceOption;\n isFocused: boolean;\n readOnly?: boolean | undefined;\n disabled?: boolean | undefined;\n}> = ({ option, isFocused, readOnly, disabled }) => {\n if (readOnly || disabled) {\n // Inert rows carry selection in the same vocabulary editable ones do — weight, plus brightness\n // on the locked row whose cells are otherwise all dimmed. Never a glyph: a check appears nowhere\n // else in the grid, and on a pending-removal row it would tick the source the row is losing. The\n // prefix slot stays a blank spacer so the source labels line up with every other row's.\n return (\n <Box width={INSTALL_MODE_COL_WIDTH}>\n <Text\n {...(disabled && { color: CLI_COLORS.ERROR })}\n bold={option.selected}\n dimColor={!disabled && !option.selected}\n >\n {`${UI_SYMBOLS.CHEVRON_SPACER} `}\n {INSTALL_MODE_CELL_LABELS[option.mode]}\n </Text>\n </Box>\n );\n }\n\n const textColor = option.selected ? CLI_COLORS.PRIMARY : CLI_COLORS.WHITE;\n const isBold = isFocused || option.selected;\n const prefix = isFocused ? `${UI_SYMBOLS.CHEVRON} ` : `${UI_SYMBOLS.CHEVRON_SPACER} `;\n\n return (\n <Box width={INSTALL_MODE_COL_WIDTH}>\n <Text color={textColor} bold={isBold} dimColor={!option.selected && !isFocused}>\n {prefix}\n {INSTALL_MODE_CELL_LABELS[option.mode]}\n </Text>\n </Box>\n );\n};\n\nconst SourceSection: React.FC<SourceSectionProps> = ({ row, isFocused, focusedOptionIndex }) => {\n const isInert = isRowInert(row);\n const effectiveFocused = isInert ? false : isFocused;\n // Unlike removal, an added row stays a normal editable row — only its marker/colour differ.\n const statusMarker = rowStatusMarker(row);\n\n return (\n <Box flexDirection=\"row\">\n <Box width={SKILL_NAME_WIDTH}>\n {effectiveFocused ? (\n // The marker sits INSIDE the highlight, and the marker's own separating space is the only\n // one before the name — so the band is the same width on every focused row and the name\n // does not shift a column when focus arrives.\n <Text color={focusedRowLabelColor(row)} backgroundColor={CLI_COLORS.LABEL_BG}>\n {statusMarker}\n {`${getSkillById(row.skillId).displayName} `}\n </Text>\n ) : (\n <Text color={rowLabelColor(row)} dimColor={!!row.readOnly}>\n {statusMarker}\n {getSkillById(row.skillId).displayName}\n </Text>\n )}\n </Box>\n\n <Box flexDirection=\"row\" flexWrap=\"wrap\">\n {row.options.map((option, index) => (\n <SourceTag\n key={option.mode}\n option={option}\n isFocused={effectiveFocused && index === focusedOptionIndex}\n readOnly={row.readOnly}\n disabled={row.disabled}\n />\n ))}\n </Box>\n </Box>\n );\n};\n\ntype ScopeGroup = {\n scope: SkillScope;\n rows: { row: SourceRow; originalIndex: number }[];\n};\n\n/**\n * One row's cell in the scope gutter. Only the first row of a block prints the block's label; every\n * other row reserves the same width empty, which is what indents the rest of the block under its\n * header.\n */\nconst ScopeRowHeader: React.FC<{ scope: SkillScope; isGroupStart: boolean }> = ({\n scope,\n isGroupStart,\n}) => (\n <Box width={SCOPE_COL_WIDTH}>\n {isGroupStart && (\n <Text color={CLI_COLORS.WARNING} bold>\n {SCOPE_ROW_HEADERS[scope]}\n </Text>\n )}\n </Box>\n);\n\n/** First focusable row index at or cyclically after `startRow`; `startRow` when every row is inert. */\nfunction firstFocusableRowIndex(rows: SourceRow[], startRow: number): number {\n const cyclicRowOrder = rows.map((_, offset) => (startRow + offset) % rows.length);\n return (\n cyclicRowOrder.find((row) => {\n const candidate = rows[row];\n return candidate && !isRowInert(candidate);\n }) ?? startRow\n );\n}\n\n/** Index of the last focusable (non-inert) row, or -1 when every row is inert. */\nfunction lastFocusableRowIndex(rows: SourceRow[]): number {\n for (let i = rows.length - 1; i >= 0; i--) {\n const candidate = rows[i];\n if (candidate && !isRowInert(candidate)) return i;\n }\n return -1;\n}\n\n/**\n * Groups rows by scope so the two blocks render separated by a blank line, each headed by its scope\n * in the gutter. Returns an empty array when all rows share the same scope: one block needs no\n * header to tell it from another, so that grid renders flat with no gutter at all.\n */\nfunction groupRowsByScope(rows: SourceRow[]): ScopeGroup[] {\n const indexed = rows.map((row, i) => ({ row, originalIndex: i }));\n const globalRows = indexed.filter(({ row }) => row.scope === \"global\");\n const projectRows = indexed.filter(({ row }) => row.scope !== \"global\");\n\n if (globalRows.length === 0 || projectRows.length === 0) return [];\n\n return [\n { scope: \"global\", rows: globalRows },\n { scope: \"project\", rows: projectRows },\n ];\n}\n\nexport const SourceGrid: React.FC<SourceGridProps> = ({\n rows,\n availableHeight = 0,\n onSelect,\n defaultFocusedRow = 0,\n defaultFocusedCol = 0,\n onFocusChange,\n}) => {\n const getColCount = useCallback((row: number): number => rows[row]?.options.length ?? 0, [rows]);\n\n const skipRow = useCallback(\n (row: number): boolean => {\n const candidate = rows[row];\n return !!candidate && isRowInert(candidate);\n },\n [rows],\n );\n\n const effectiveDefaultRow = firstFocusableRowIndex(rows, defaultFocusedRow);\n\n const { focusedRow, focusedCol, moveFocus } = useFocusedListItem(rows.length, getColCount, {\n wrap: true,\n ...(onFocusChange !== undefined && { onChange: onFocusChange }),\n initialRow: effectiveDefaultRow,\n initialCol: defaultFocusedCol,\n skipRow,\n });\n\n const {\n setSectionRef,\n setViewportRef,\n setContentRef,\n scrollEnabled,\n scrollTopPx,\n hiddenAbove,\n hiddenBelow,\n scrollBy,\n } = useSectionScroll({\n sectionCount: rows.length,\n focusedIndex: focusedRow,\n availableHeight,\n minViewportRows: SOURCE_GRID_MIN_VIEWPORT_ROWS,\n });\n\n const lastFocusableRow = useMemo(() => lastFocusableRowIndex(rows), [rows]);\n\n useInput(\n useCallback(\n (input: string, key: Key) => {\n if (input === KEY_SPACE) {\n const currentRow = rows[focusedRow];\n if (!currentRow || isRowInert(currentRow)) return;\n const currentOption = currentRow.options[focusedCol];\n if (currentOption) {\n onSelect(currentRow.skillId, currentOption.mode);\n }\n return;\n }\n\n // With no focusable row (every row inert — a run of locked-global rows plus the\n // pending-removal row) there is no focus to move or to anchor overscroll on, so\n // vertical keys drive the viewport directly. Otherwise, overscroll only kicks in\n // once focus sits on the last focusable row (below it are only inert rows).\n const noFocusableRow = lastFocusableRow === -1;\n const atLastFocusableRow = focusedRow === lastFocusableRow;\n\n if (key.leftArrow) {\n moveFocus(\"left\");\n } else if (key.rightArrow) {\n moveFocus(\"right\");\n } else if (key.upArrow) {\n if (scrollEnabled && noFocusableRow && hiddenAbove > 0) {\n scrollBy(-1);\n } else {\n moveFocus(\"up\");\n }\n } else if (key.downArrow) {\n // Keep scrolling the viewport to reveal trailing inert rows (e.g. the\n // pending-removal row) instead of wrapping. Focus never lands on them, so the\n // viewport travels past the last focusable row (or scrolls on its own when\n // nothing is focusable).\n if (scrollEnabled && (noFocusableRow || atLastFocusableRow) && hiddenBelow > 0) {\n scrollBy(1);\n } else {\n moveFocus(\"down\");\n }\n }\n },\n [\n rows,\n focusedRow,\n focusedCol,\n onSelect,\n moveFocus,\n scrollEnabled,\n lastFocusableRow,\n hiddenAbove,\n hiddenBelow,\n scrollBy,\n ],\n ),\n );\n\n if (rows.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Text dimColor>No skills to display.</Text>\n </Box>\n );\n }\n\n const noShrink = scrollEnabled ? { flexShrink: 0 } : {};\n\n const scopeGroups = groupRowsByScope(rows);\n\n const sectionElements =\n scopeGroups.length > 0\n ? scopeGroups.map((group) => (\n <Box key={group.scope} flexDirection=\"column\" marginTop={1} {...noShrink}>\n {group.rows.map(({ row, originalIndex }, rowIndexInGroup) => (\n <Box\n key={`${row.skillId}-${row.scope ?? \"default\"}`}\n flexDirection=\"row\"\n ref={(el) => setSectionRef(originalIndex, el)}\n {...noShrink}\n >\n <ScopeRowHeader scope={group.scope} isGroupStart={rowIndexInGroup === 0} />\n <SourceSection\n row={row}\n isFocused={originalIndex === focusedRow}\n focusedOptionIndex={focusedCol}\n />\n </Box>\n ))}\n </Box>\n ))\n : rows.map((row, rowIndex) => (\n <Box\n key={`${row.skillId}-${row.scope ?? \"default\"}`}\n ref={(el) => setSectionRef(rowIndex, el)}\n {...noShrink}\n >\n <SourceSection\n row={row}\n isFocused={rowIndex === focusedRow}\n focusedOptionIndex={focusedCol}\n />\n </Box>\n ));\n\n return (\n <Box\n flexDirection=\"column\"\n {...(scrollEnabled\n ? { height: availableHeight, overflow: \"hidden\" as const }\n : { flexGrow: 1 })}\n >\n <Box ref={setViewportRef} flexDirection=\"column\" overflow=\"hidden\" flexGrow={1}>\n <Box\n ref={setContentRef}\n flexDirection=\"column\"\n marginTop={scrollTopPx > 0 ? -scrollTopPx : 0}\n {...noShrink}\n >\n {sectionElements}\n </Box>\n </Box>\n <ScrollAffordance hiddenAbove={hiddenAbove} hiddenBelow={hiddenBelow} />\n </Box>\n );\n};\n"],"mappings":"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","names":[]}
|