agents-inc 0.170.0 → 0.170.2

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.
Files changed (163) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/{chunk-BMRUNMPV.js → chunk-2YA4DDRM.js} +35 -35
  3. package/dist/chunk-2YA4DDRM.js.map +1 -0
  4. package/dist/{chunk-44TE3RKH.js → chunk-3ED3KHHD.js} +5 -4
  5. package/dist/chunk-3ED3KHHD.js.map +1 -0
  6. package/dist/{chunk-3G7X2WKI.js → chunk-5BNX73OU.js} +18 -38
  7. package/dist/chunk-5BNX73OU.js.map +1 -0
  8. package/dist/{chunk-7RDMTR64.js → chunk-66AEVERM.js} +785 -256
  9. package/dist/chunk-66AEVERM.js.map +1 -0
  10. package/dist/{chunk-PJWGTNOX.js → chunk-7C3PFRBU.js} +144 -186
  11. package/dist/chunk-7C3PFRBU.js.map +1 -0
  12. package/dist/{chunk-52HDHJ7I.js → chunk-AUNRHWH4.js} +32 -21
  13. package/dist/chunk-AUNRHWH4.js.map +1 -0
  14. package/dist/{chunk-KOLDW6SF.js → chunk-BBDGYJHX.js} +2 -2
  15. package/dist/chunk-BBDGYJHX.js.map +1 -0
  16. package/dist/{chunk-SZYQISA2.js → chunk-ELV5WDS3.js} +43 -29
  17. package/dist/chunk-ELV5WDS3.js.map +1 -0
  18. package/dist/{chunk-MQ6CGZNJ.js → chunk-GAKVZNTX.js} +1879 -2019
  19. package/dist/chunk-GAKVZNTX.js.map +1 -0
  20. package/dist/chunk-GEMW5RQ2.js +1169 -0
  21. package/dist/chunk-GEMW5RQ2.js.map +1 -0
  22. package/dist/{chunk-NQW25DCF.js → chunk-GHHJYNAN.js} +1 -7
  23. package/dist/chunk-GHHJYNAN.js.map +1 -0
  24. package/dist/{chunk-WTWMGH2C.js → chunk-HACRR422.js} +2 -2
  25. package/dist/chunk-HACRR422.js.map +1 -0
  26. package/dist/{chunk-F2BHT5C4.js → chunk-IWY5IR4F.js} +129 -151
  27. package/dist/chunk-IWY5IR4F.js.map +1 -0
  28. package/dist/{chunk-JFLVEFFP.js → chunk-KIK5EZYD.js} +1 -1
  29. package/dist/chunk-KIK5EZYD.js.map +1 -0
  30. package/dist/{chunk-USVBYQSQ.js → chunk-O4LN3HFI.js} +16 -6
  31. package/dist/chunk-O4LN3HFI.js.map +1 -0
  32. package/dist/{chunk-RIPSGNLU.js → chunk-OCAVW6N5.js} +3 -3
  33. package/dist/chunk-OCAVW6N5.js.map +1 -0
  34. package/dist/{chunk-4AAOOAIN.js → chunk-P6CYS4JK.js} +2 -2
  35. package/dist/chunk-P6CYS4JK.js.map +1 -0
  36. package/dist/chunk-PLFANHRZ.js +35 -0
  37. package/dist/chunk-PLFANHRZ.js.map +1 -0
  38. package/dist/{chunk-6ZRH5RHC.js → chunk-PMUZR4XO.js} +4 -4
  39. package/dist/chunk-PMUZR4XO.js.map +1 -0
  40. package/dist/{chunk-F5EBEATU.js → chunk-PSUTNOQ2.js} +34 -46
  41. package/dist/chunk-PSUTNOQ2.js.map +1 -0
  42. package/dist/chunk-RIK45Q4I.js +103 -0
  43. package/dist/chunk-RIK45Q4I.js.map +1 -0
  44. package/dist/{chunk-HED2DAXZ.js → chunk-THO7LO5B.js} +5 -5
  45. package/dist/chunk-THO7LO5B.js.map +1 -0
  46. package/dist/{chunk-OYJQUA3D.js → chunk-YGDWHDOY.js} +31 -13
  47. package/dist/chunk-YGDWHDOY.js.map +1 -0
  48. package/dist/{chunk-NCWDK6L7.js → chunk-YXKTY5WM.js} +254 -379
  49. package/dist/chunk-YXKTY5WM.js.map +1 -0
  50. package/dist/{chunk-NEZ4OAOL.js → chunk-ZEGM3MVR.js} +3 -5
  51. package/dist/chunk-ZEGM3MVR.js.map +1 -0
  52. package/dist/commands/build/marketplace.js +46 -46
  53. package/dist/commands/build/marketplace.js.map +1 -1
  54. package/dist/commands/build/plugins.js +25 -28
  55. package/dist/commands/build/plugins.js.map +1 -1
  56. package/dist/commands/compile.js +87 -178
  57. package/dist/commands/compile.js.map +1 -1
  58. package/dist/commands/doctor.js +510 -360
  59. package/dist/commands/doctor.js.map +1 -1
  60. package/dist/commands/edit.js +451 -357
  61. package/dist/commands/edit.js.map +1 -1
  62. package/dist/commands/eject.js +144 -125
  63. package/dist/commands/eject.js.map +1 -1
  64. package/dist/commands/init.js +20 -27
  65. package/dist/commands/list.js +39 -55
  66. package/dist/commands/list.js.map +1 -1
  67. package/dist/commands/new/marketplace.js +6 -11
  68. package/dist/commands/new/marketplace.js.map +1 -1
  69. package/dist/commands/search.js +35 -32
  70. package/dist/commands/search.js.map +1 -1
  71. package/dist/commands/share.js +17 -77
  72. package/dist/commands/share.js.map +1 -1
  73. package/dist/commands/uninstall.js +159 -222
  74. package/dist/commands/uninstall.js.map +1 -1
  75. package/dist/commands/update.js +9 -32
  76. package/dist/commands/update.js.map +1 -1
  77. package/dist/components/common/prompt-confirm.js +2 -2
  78. package/dist/components/common/removal-plan-confirm.js +2 -2
  79. package/dist/components/common/scroll-affordance.js +2 -2
  80. package/dist/components/common/select-list.js +2 -2
  81. package/dist/components/common/skill-agent-summary.js +4 -4
  82. package/dist/components/common/spinner.js +2 -4
  83. package/dist/components/common/summary-panel.js +5 -5
  84. package/dist/components/common/summary-panel.js.map +1 -1
  85. package/dist/config-exports.js +7 -3
  86. package/dist/config-exports.js.map +1 -1
  87. package/dist/hooks/init.js +18 -19
  88. package/dist/hooks/init.js.map +1 -1
  89. package/dist/index.js.map +1 -1
  90. package/dist/load-agent-defs-6QUUMGHK.js +14 -0
  91. package/dist/recompile-project-agents-I33KQJFB.js +65 -0
  92. package/dist/recompile-project-agents-I33KQJFB.js.map +1 -0
  93. package/dist/{source-loader-C5SQXZXI.js → source-loader-TTJVW2ER.js} +5 -5
  94. package/dist/src/agents/developer/ai-developer/playbook.md +2 -5
  95. package/dist/src/agents/developer/api-developer/playbook.md +2 -5
  96. package/dist/src/agents/developer/cli-developer/playbook.md +2 -5
  97. package/dist/src/agents/developer/web-developer/playbook.md +2 -5
  98. package/dist/src/agents/meta/agent-summoner/output.md +2 -2
  99. package/dist/src/agents/meta/agent-summoner/playbook.md +1 -13
  100. package/dist/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
  101. package/dist/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
  102. package/dist/src/agents/tester/ai-tester/critical-requirements.md +1 -2
  103. package/dist/src/agents/tester/ai-tester/playbook.md +2 -0
  104. package/dist/src/agents/tester/api-tester/critical-requirements.md +1 -2
  105. package/dist/src/agents/tester/api-tester/playbook.md +2 -0
  106. package/dist/src/agents/tester/cli-tester/critical-requirements.md +1 -2
  107. package/dist/src/agents/tester/cli-tester/playbook.md +2 -0
  108. package/dist/src/agents/tester/web-tester/critical-requirements.md +1 -2
  109. package/dist/src/agents/tester/web-tester/playbook.md +2 -0
  110. package/package.json +9 -8
  111. package/src/agents/developer/ai-developer/playbook.md +2 -5
  112. package/src/agents/developer/api-developer/playbook.md +2 -5
  113. package/src/agents/developer/cli-developer/playbook.md +2 -5
  114. package/src/agents/developer/web-developer/playbook.md +2 -5
  115. package/src/agents/meta/agent-summoner/output.md +2 -2
  116. package/src/agents/meta/agent-summoner/playbook.md +1 -13
  117. package/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
  118. package/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
  119. package/src/agents/tester/ai-tester/critical-requirements.md +1 -2
  120. package/src/agents/tester/ai-tester/playbook.md +2 -0
  121. package/src/agents/tester/api-tester/critical-requirements.md +1 -2
  122. package/src/agents/tester/api-tester/playbook.md +2 -0
  123. package/src/agents/tester/cli-tester/critical-requirements.md +1 -2
  124. package/src/agents/tester/cli-tester/playbook.md +2 -0
  125. package/src/agents/tester/web-tester/critical-requirements.md +1 -2
  126. package/src/agents/tester/web-tester/playbook.md +2 -0
  127. package/src/schemas/project-config.schema.json +0 -3
  128. package/src/schemas/project-source-config.schema.json +0 -6
  129. package/dist/chunk-3G7X2WKI.js.map +0 -1
  130. package/dist/chunk-44TE3RKH.js.map +0 -1
  131. package/dist/chunk-4AAOOAIN.js.map +0 -1
  132. package/dist/chunk-52HDHJ7I.js.map +0 -1
  133. package/dist/chunk-6HNXYYVF.js +0 -373
  134. package/dist/chunk-6HNXYYVF.js.map +0 -1
  135. package/dist/chunk-6ZRH5RHC.js.map +0 -1
  136. package/dist/chunk-7RDMTR64.js.map +0 -1
  137. package/dist/chunk-BMRUNMPV.js.map +0 -1
  138. package/dist/chunk-CLPUWOSA.js +0 -46
  139. package/dist/chunk-CLPUWOSA.js.map +0 -1
  140. package/dist/chunk-F2BHT5C4.js.map +0 -1
  141. package/dist/chunk-F5EBEATU.js.map +0 -1
  142. package/dist/chunk-HED2DAXZ.js.map +0 -1
  143. package/dist/chunk-JFLVEFFP.js.map +0 -1
  144. package/dist/chunk-KOLDW6SF.js.map +0 -1
  145. package/dist/chunk-MQ6CGZNJ.js.map +0 -1
  146. package/dist/chunk-NCWDK6L7.js.map +0 -1
  147. package/dist/chunk-NEZ4OAOL.js.map +0 -1
  148. package/dist/chunk-NIHUOWE4.js +0 -106
  149. package/dist/chunk-NIHUOWE4.js.map +0 -1
  150. package/dist/chunk-NQW25DCF.js.map +0 -1
  151. package/dist/chunk-OYJQUA3D.js.map +0 -1
  152. package/dist/chunk-PJWGTNOX.js.map +0 -1
  153. package/dist/chunk-RIPSGNLU.js.map +0 -1
  154. package/dist/chunk-SZYQISA2.js.map +0 -1
  155. package/dist/chunk-USVBYQSQ.js.map +0 -1
  156. package/dist/chunk-V3KTSP3Q.js +0 -940
  157. package/dist/chunk-V3KTSP3Q.js.map +0 -1
  158. package/dist/chunk-WTWMGH2C.js.map +0 -1
  159. package/dist/load-agent-defs-YMDWBFDP.js +0 -14
  160. package/dist/recompile-project-agents-SZ76WNTW.js +0 -18
  161. package/dist/source-loader-C5SQXZXI.js.map +0 -1
  162. /package/dist/{load-agent-defs-YMDWBFDP.js.map → load-agent-defs-6QUUMGHK.js.map} +0 -0
  163. /package/dist/{recompile-project-agents-SZ76WNTW.js.map → source-loader-TTJVW2ER.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/doctor.ts","../../src/cli/lib/source-validator.ts","../../src/cli/lib/content-validator.ts"],"sourcesContent":["import os from \"os\";\nimport path from \"path\";\nimport { BaseCommand } from \"../base-command\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport { EXIT_CODES } from \"../lib/exit-codes\";\nimport {\n effectivelyExcludedSkillIds,\n findConfigLoadFailures,\n loadInstalledConfig,\n validateProjectConfig,\n SOURCE_ENV_VAR,\n type ResolvedConfig,\n} from \"../lib/configuration\";\nimport { loadSource, detectProject, type DetectedProject } from \"../lib/operations\";\nimport { matrix } from \"../lib/matrix/matrix-provider\";\nimport { discoverLocalSkills } from \"../lib/skills\";\nimport { getStackSkillIds } from \"../lib/stacks\";\nimport { filterExcludedEntries, listAgentFilesOf } from \"../lib/agents\";\nimport { getVerifiedPluginInstallPaths, parseMarketplacePluginRef } from \"../lib/plugins\";\nimport {\n declaresNoContent,\n isHomeDirectory,\n installBaseDir,\n resolveInstallPaths,\n} from \"../lib/installation\";\nimport {\n agentCodec,\n type AgentCodec,\n hostCompilesAgent,\n providerInUse,\n relativeConfigPath,\n skillsDir,\n skillsPathPrefix,\n} from \"../lib/installation/install-layout\";\nimport { ambiguityFinding } from \"../lib/installation/provider-flag\";\nimport { unofferablePlacementsFound } from \"../lib/hosts/configured-placements\";\nimport {\n sourceScopesInPlay,\n type ScopeKind,\n type SourceScope,\n} from \"../lib/installation/source-scopes\";\nimport { layoutIsCurrent, recreateConfigFrom, scopeLabel, scopeNoun } from \"../utils/messages\";\nimport { getInstalledConfigPath } from \"../lib/installation/install-base-dir\";\nimport { isSourceRepo } from \"../lib/source-validator\";\nimport {\n listInstalledArtifacts,\n validateInstalledAgents,\n validateInstalledPlugins,\n validateInstalledSkills,\n validateProjectConfigFile,\n validateRegisteredSources,\n type ContentIssue,\n type ContentValidation,\n} from \"../lib/content-validator\";\nimport type { SourceLoadResult } from \"../lib/loading\";\nimport type {\n AgentName,\n AgentScopeConfig,\n MergedSkillsMatrix,\n ProjectConfig,\n SkillConfig,\n SkillId,\n SkillScope,\n} from \"../types\";\nimport { fileExists, directoryExists } from \"../utils/fs\";\nimport { plural } from \"../utils/string\";\nimport {\n CLI_INVOKE_COMMAND,\n DEFAULT_BRANDING,\n EJECT_SOURCE,\n STANDARD_FILES,\n UI_SYMBOLS,\n type Provider,\n} from \"../consts\";\nimport { countBy, unique } from \"remeda\";\n\ntype CheckKind =\n | \"config\"\n | \"config-empty\"\n | \"layout\"\n | \"placements\"\n | \"skills\"\n | \"agents\"\n | \"orphans\"\n | \"orphans-unowned\"\n | \"installed\"\n | \"plugins\"\n | \"source\"\n | \"content-config\"\n | \"content-sources\"\n | \"content-plugins\"\n | \"content-skills\"\n | \"content-agents\";\n\ntype CheckResult = {\n kind: CheckKind;\n status: \"pass\" | \"fail\" | \"warn\" | \"skip\";\n message: string;\n details?: string[];\n};\n\ntype ConfigCheckOutput = {\n result: CheckResult;\n config: ProjectConfig | null;\n};\n\n/**\n * Which state the config these rows describe is in. `detectInstallation` answers \"is there an\n * installation here\", not \"is there a config here\", and hands back the same `null` for an absent\n * file and for one that loads while declaring neither skills nor agents — two states that need\n * different sentences. The state missing from this union is the one that cannot reach this layer:\n * a config that cannot be READ is the content layer's finding, and it skips the operational layer.\n *\n * A loaded config says whether it is this directory's own or the global one it inherits: a\n * directory with no config of its own under a global installation reads the global config, and a\n * row naming this directory's path for it describes a file that is not there.\n */\ntype ConfigState =\n | { kind: \"absent\" }\n | { kind: \"declares-nothing\"; config: ProjectConfig }\n | { kind: \"loaded\"; config: ProjectConfig; inherited: boolean };\n\n/**\n * The config in THIS directory, and what state it is in. Only this directory: the global fallback\n * is `detectInstallation`'s to make and it has already made it, so a project with no config of its\n * own is absent here whatever the home directory holds — `init` writes exactly the declares-nothing\n * shape as the blank global pair on every project setup, and it is not this project's config.\n *\n * The load cannot throw: `configDirsInPlay` is the same set the content layer just read, and any\n * failure in it skipped this layer entirely.\n */\nasync function resolveConfigState(\n detected: DetectedProject | null,\n projectDir: string,\n): Promise<ConfigState> {\n if (detected?.config) {\n return {\n kind: \"loaded\",\n config: detected.config,\n inherited: inheritsTheGlobalConfig(detected.installation.projectDir, projectDir),\n };\n }\n\n const loaded = await loadInstalledConfig(projectDir);\n if (!loaded) return { kind: \"absent\" };\n\n return declaresNoContent(loaded.config)\n ? { kind: \"declares-nothing\", config: loaded.config }\n : { kind: \"loaded\", config: loaded.config, inherited: false };\n}\n\n/** Whether the config detection read for `projectDir` is the home directory's, inherited. */\nfunction inheritsTheGlobalConfig(readFrom: string, projectDir: string): boolean {\n return isHomeDirectory(readFrom) && !isHomeDirectory(projectDir);\n}\n\n/**\n * `projectDir` rather than a module-level constant for the path this reports about: a scope's\n * source folder depends on the provider read off its disk, so nothing about it exists at module\n * load, and every line below has to name the folder this project is ACTUALLY on.\n */\nfunction checkConfigValid(state: ConfigState, projectDir: string): ConfigCheckOutput {\n const theConfig = (verdict: string) => configRowMessage(state, projectDir, verdict);\n if (state.kind === \"absent\") {\n return {\n result: {\n kind: \"config\",\n status: \"fail\",\n message: theConfig(\"not found\"),\n details: [`Run '${CLI_INVOKE_COMMAND} init' to create a configuration`],\n },\n config: null,\n };\n }\n\n // Not a fault and nothing to repair — the file is valid, it just has nothing in it. The config\n // is still handed on: the rows below describe an empty install truthfully, where a `null` would\n // have them all report `Skipped (config invalid)` about a config that is valid.\n if (state.kind === \"declares-nothing\") {\n return {\n result: {\n kind: \"config-empty\",\n status: \"warn\",\n message: theConfig(\"is valid but declares no skills and no agents\"),\n },\n config: state.config,\n };\n }\n\n const { config } = state;\n const validation = validateProjectConfig(config);\n\n if (!validation.valid) {\n return {\n result: {\n kind: \"config\",\n status: \"fail\",\n message: theConfig(\"has errors\"),\n details: validation.errors,\n },\n config: null,\n };\n }\n\n if (validation.warnings.length > 0) {\n return {\n result: {\n kind: \"config\",\n status: \"warn\",\n message: theConfig(\"has warnings\"),\n details: validation.warnings,\n },\n config,\n };\n }\n\n return {\n result: {\n kind: \"config\",\n status: \"pass\",\n message: theConfig(\"is valid\"),\n },\n config,\n };\n}\n\n/**\n * What a Config Valid row says, led by whose config it is: this project's, or the global\n * installation's — the nouns the Layout rows lead with.\n *\n * A directory with no config of its own under a global installation reads the global one, and the\n * row says so, naming the file it actually read rather than this directory's path for a file that\n * is not there.\n */\nfunction configRowMessage(state: ConfigState, projectDir: string, verdict: string): string {\n if (state.kind === \"loaded\" && state.inherited)\n return `${theInheritedConfig()}, which ${verdict}`;\n return `${theOwnConfig(projectDir)} ${verdict}`;\n}\n\n/** `This project: .agents-inc/claude/config.ts`, or the global installation's from home. */\nfunction theOwnConfig(projectDir: string): string {\n return `${scopeLabel(scopeOf(projectDir))}: ${configNamedFrom(projectDir)}`;\n}\n\n/** A project with no config of its own, and the global one it reads in its place. */\nfunction theInheritedConfig(): string {\n return `${scopeLabel(\"project\")}: no ${STANDARD_FILES.CONFIG_TS}, using ${scopeNoun(\"global\")}'s (${configNamedFrom(os.homedir())})`;\n}\n\n/** The scope whose config a directory holds: the home directory's is the global one. */\nfunction scopeOf(dir: string): ScopeKind {\n return isHomeDirectory(dir) ? \"global\" : \"project\";\n}\n\n/**\n * A config file as a row names it: relative to the project it belongs to, and from home for the\n * global one — named relative to a project, the global config is a file that project does not have.\n */\nfunction configNamedFrom(root: string): string {\n const relPath = relativeConfigPath(root, providerInUse(root));\n return isHomeDirectory(root) ? `~/${relPath}` : relPath;\n}\n\nasync function checkSkillsResolved(\n config: ProjectConfig,\n matrix: MergedSkillsMatrix,\n projectDir: string,\n): Promise<CheckResult> {\n // config.ts declares skills both directly and through the stack. A global-only\n // install has a populated skills array and no stack at all, so keying this check\n // off the stack alone would report \"No skills configured\" for a real install.\n const excludedIds = effectivelyExcludedSkillIds(config.skills);\n const stackIds = config.stack ? getStackSkillIds(config.stack) : [];\n const uniqueSkills = unique([...stackIds, ...config.skills.map((s) => s.id)]).filter(\n (id) => !excludedIds.has(id),\n );\n\n if (uniqueSkills.length === 0) {\n return {\n kind: \"skills\",\n status: \"pass\",\n message: \"No skills configured\",\n };\n }\n\n const [localResult, globalResult] = await Promise.all([\n discoverLocalSkills(projectDir),\n !isHomeDirectory(projectDir) ? discoverLocalSkills(os.homedir()) : null,\n ]);\n const localSkillIds = new Set([\n ...(localResult?.skills.map((s) => s.id) ?? []),\n ...(globalResult?.skills.map((s) => s.id) ?? []),\n ]);\n\n const missingSkills = uniqueSkills.filter(\n (skillId) => !(skillId in matrix.skills) && !localSkillIds.has(skillId),\n );\n\n if (missingSkills.length > 0) {\n return {\n kind: \"skills\",\n status: \"fail\",\n message: `${ratio(uniqueSkills.length - missingSkills.length, uniqueSkills.length, \"skill\")} found`,\n details: missingSkills.map((s) => `- ${s} (not found)`),\n };\n }\n\n return {\n kind: \"skills\",\n status: \"pass\",\n message: `${ratio(uniqueSkills.length, uniqueSkills.length, \"skill\")} found`,\n };\n}\n\n/**\n * Whether every configured sub-agent is compiled where its own host reads it.\n *\n * **Two things here were Claude's and are the host's**, and both were found by running the\n * command on a healthy Codex installation rather than by reading it:\n *\n * - the FILENAME was `${name}.md`. Claude reads `.md` and Codex reads `.toml`, so on Codex this\n * looked for a file no release will ever write. {@link agentCodec} answers the extension, and\n * this is the extension ban's own census in action — the eslint config leaves `.md` unbanned\n * precisely because product modules like this one still spell it.\n * - the VERDICT was \"needs recompilation\", for a sub-agent {@link hostCompilesAgent} says this\n * host does not carry at all. Recompiling writes nothing, so the row asked for a remedy that\n * does not exist and turned an install working exactly as this release intends into a warning.\n * With C5 that is no longer a whole provider but two named sub-agents — `agent-summoner` and\n * `skill-summoner`, which Codex leaves out for v1 — so the row names them rather than the host.\n *\n * The host is read per SCOPE, the way `resolveInstallPaths` reads it beside this: two scopes can\n * be on two providers, and one answer for both is how a row reports about the wrong installation.\n */\nasync function checkAgentsCompiled(\n config: ProjectConfig,\n projectDir: string,\n): Promise<CheckResult> {\n const agents = config.agents;\n\n if (agents.length === 0) {\n return {\n kind: \"agents\",\n status: \"pass\",\n message: \"No agents configured\",\n };\n }\n\n const hosts = {\n global: providerInUse(installBaseDir(projectDir, \"global\")),\n project: providerInUse(installBaseDir(projectDir, \"project\")),\n };\n const dirs = {\n global: resolveInstallPaths(projectDir, \"global\").agentsDir,\n project: resolveInstallPaths(projectDir, \"project\").agentsDir,\n };\n\n const agentChecks = await Promise.all(\n agents.map((agent) => agentCompileCheck(agent, hosts, dirs)),\n );\n\n const unrenderable = agentChecks.filter((c) => c.state === \"unrenderable\");\n const missingAgents = agentChecks.filter((c) => c.state === \"missing\").map((c) => c.name);\n\n // The no-renderer answer leads when it is the whole story, because then nothing is wrong and\n // nothing can be done: a `warn` here would make every `doctor` on a Codex installation read as\n // a fault report about the one thing this release has already said it does not do yet. The\n // providers come off the rows themselves rather than off both scopes, so a project on one host\n // under a global on another names only the host whose sub-agents this is about.\n if (unrenderable.length === agents.length) {\n const hostsLeavingThemOut = unique(unrenderable.map((a) => a.provider)).join(\" or \");\n return {\n kind: \"agents\",\n status: \"pass\",\n message: `No sub-agent in this configuration is carried by ${hostsLeavingThemOut}`,\n details: unrenderable.map((a) => `- ${a.name} (left out of ${a.provider})`),\n };\n }\n\n if (missingAgents.length > 0) {\n return {\n kind: \"agents\",\n status: \"warn\",\n message: `${missingAgents.length} agent${missingAgents.length === 1 ? \"\" : \"s\"} need${missingAgents.length === 1 ? \"s\" : \"\"} recompilation`,\n details: missingAgents.map((a) => `- ${a} (missing)`),\n };\n }\n\n const renderable = agents.length - unrenderable.length;\n return {\n kind: \"agents\",\n status: \"pass\",\n message: `${ratio(renderable, renderable, \"agent\")} compiled`,\n };\n}\n\n/** One configured sub-agent as the Agents Compiled row sees it, and the host that decided it. */\ntype AgentCompileCheck = {\n name: AgentName;\n provider: Provider;\n state: \"unrenderable\" | \"compiled\" | \"missing\";\n};\n\n/**\n * Whether one sub-agent is left out by its scope's host, or else compiled or missing where that\n * host reads it — the extension and the directory are both the host's.\n */\nasync function agentCompileCheck(\n agent: AgentScopeConfig,\n hosts: Record<SkillScope, Provider>,\n agentsDirs: Record<SkillScope, string>,\n): Promise<AgentCompileCheck> {\n const provider = hosts[agent.scope];\n if (!hostCompilesAgent(provider, agent.name)) {\n return { name: agent.name, provider, state: \"unrenderable\" };\n }\n\n const file = `${agent.name}${agentCodec(provider).extension}`;\n const compiled = await fileExists(path.join(agentsDirs[agent.scope], file));\n return { name: agent.name, provider, state: compiled ? \"compiled\" : \"missing\" };\n}\n\nasync function checkNoOrphans(config: ProjectConfig, projectDir: string): Promise<CheckResult> {\n // The host's own agent files — `*.toml` roles on Codex, where a `*.md`-only listing found no\n // compiled agent and so no orphan either (the CLI-896 class, 2026-09-27).\n const codec = agentCodec(providerInUse(projectDir));\n const projectAgentsDir = resolveInstallPaths(projectDir, \"project\").agentsDir;\n const globalAgentsDir = resolveInstallPaths(projectDir, \"global\").agentsDir;\n\n // At home scope both scopes resolve to the same agents directory, so it is\n // listed once and its files are matched against both scopes' known names.\n const scopesShareAgentsDir = isHomeDirectory(projectDir);\n\n const [projectExists, globalExists] = await Promise.all([\n directoryExists(projectAgentsDir),\n !scopesShareAgentsDir ? directoryExists(globalAgentsDir) : false,\n ]);\n\n if (!projectExists && !globalExists) {\n return {\n kind: \"orphans\",\n status: \"pass\",\n message: \"No agents directory\",\n };\n }\n\n const projectMdFiles = projectExists ? await listAgentFilesOf(projectAgentsDir, codec) : [];\n const globalMdFiles = globalExists ? await listAgentFilesOf(globalAgentsDir, codec) : [];\n\n // Project files: only active project-scoped agents should have .md files here\n const activeProjectAgents: Set<string> = new Set(\n config.agents.filter((a) => a.scope === \"project\" && !a.excluded).map((a) => a.name),\n );\n // Global files: all global-scoped agents (including excluded) still serve other projects\n const knownGlobalAgents: Set<string> = new Set(\n config.agents.filter((a) => a.scope === \"global\").map((a) => a.name),\n );\n\n const knownProjectDirAgents = scopesShareAgentsDir\n ? new Set([...activeProjectAgents, ...knownGlobalAgents])\n : activeProjectAgents;\n\n const orphanedFiles = [\n ...orphanedAgentNames(projectMdFiles, knownProjectDirAgents, codec),\n ...orphanedAgentNames(globalMdFiles, knownGlobalAgents, codec),\n ];\n\n if (orphanedFiles.length > 0) {\n return {\n kind: \"orphans\",\n status: \"warn\",\n message: plural(orphanedFiles.length, \"orphaned agent file\"),\n details: orphanedFiles.map((f) => `- ${f}.md (not in config)`),\n };\n }\n\n return {\n kind: \"orphans\",\n status: \"pass\",\n message: \"No orphaned agent files\",\n };\n}\n\n/**\n * The agents whose compiled `.md` sits in a directory whose roster does not name them. The\n * roster differs per directory — a project directory knows only its own active agents, the\n * global one knows every global-scoped agent including the excluded — so it is a parameter.\n */\nfunction orphanedAgentNames(\n mdFiles: string[],\n knownAgents: ReadonlySet<string>,\n codec: AgentCodec,\n): string[] {\n return mdFiles\n .map((fileName) => path.basename(fileName, codec.extension))\n .filter((agentName) => !knownAgents.has(agentName));\n}\n\n/**\n * The same row when there is no configuration at all. Ownership is not unknown here, it is\n * settled: nothing declares any of it, so every artefact this CLI can prove it wrote is an\n * orphan and the row names it. What it CANNOT prove it wrote is left out — a skill directory\n * with no `forkedFrom` and an agent file with no provenance marker are somebody's own work,\n * and naming them here would offer `uninstall` files that command declines. See\n * {@link listInstalledArtifacts}, which asks exactly that question on both axes.\n *\n * A `fail`, where a stray file beside a config is a warning: that warning is earned by the next\n * `compile` pruning what it names, and nothing prunes these unattended. `compile` and `edit`\n * refuse without a config; `uninstall` does not need one, identifying skill directories by\n * their own `forkedFrom` and compiled agents by the marker each carries, which is why the tip\n * beneath this row can promise both halves.\n *\n * With nothing installed the row keeps the skip it has always printed. An empty directory with\n * no config is the state `init` exists for — there is nothing for a configuration to have owned.\n */\nasync function checkUnownedInstallation(projectDir: string): Promise<CheckResult> {\n const { skills, agents } = await listInstalledArtifacts(projectDir);\n if (skills.length === 0 && agents.length === 0) return skippedResult(\"orphans\");\n\n return {\n kind: \"orphans-unowned\",\n status: \"fail\",\n // The per-line \"(not in config)\" the other verdict repeats is said once here instead:\n // with no configuration it is true of every line, and there are as many lines as files.\n message: `${countedArtifacts(skills, agents)} installed here, and no configuration declares them`,\n details: [...skills, ...agents].map((artifact) => `- ${artifact}`),\n };\n}\n\n/** \"1/1 skill\", \"2/3 skills\" — the noun agrees with the count it is out of. */\nfunction ratio(found: number, total: number, noun: string): string {\n return `${found}/${plural(total, noun)}`;\n}\n\n/** \"7 skills and 2 agents\", dropping a half with nothing in it rather than saying \"0 agents\". */\nfunction countedArtifacts(skills: string[], agents: string[]): string {\n return [\n ...(skills.length > 0 ? [plural(skills.length, \"skill\")] : []),\n ...(agents.length > 0 ? [plural(agents.length, \"agent\")] : []),\n ].join(\" and \");\n}\n\n/**\n * Whether every eject-mode skill the configuration names is on disk where its own host reads it.\n *\n * **It composed `<scope root>/.claude/skills/<id>/SKILL.md` for every provider until\n * 2026-09-22**, which made a healthy Codex installation report every one of its skills missing\n * and told the reader to look in a directory that installation does not have. The write path had\n * already moved through the layout — `copyLocalSkills` writes `$CODEX_HOME/skills` and\n * `<repo>/.agents/skills` — so this row was the half that stayed behind, and it is the kind of\n * defect the host-path lint ban cannot report: the path was composed from a CONSTANT, and that\n * ban matches literals.\n *\n * The directory is asked per SKILL rather than once for the row, because scope decides it and a\n * configuration mixes scopes freely. The reader is told the directory that was actually looked\n * in, for the same reason — one sentence naming one folder cannot be true of two scopes on two\n * different hosts.\n */\nasync function checkSkillsInstalled(\n config: ProjectConfig,\n projectDir: string,\n): Promise<CheckResult> {\n const skills: SkillConfig[] = config.skills;\n const ejectSkills = skills.filter((s) => s.origin === EJECT_SOURCE);\n\n if (ejectSkills.length === 0) {\n return {\n kind: \"installed\",\n status: \"pass\",\n message: \"No eject-mode skills configured\",\n };\n }\n\n const skillChecks = await Promise.all(\n ejectSkills.map((skill) => ejectedSkillCheck(skill, projectDir)),\n );\n const missingSkills = skillChecks.filter((c) => !c.installed);\n\n if (missingSkills.length > 0) {\n return {\n kind: \"installed\",\n status: \"warn\",\n message: `${plural(missingSkills.length, \"skill\")} missing from disk`,\n details: missingSkills.map((s) => `- ${s.id} (not found in ${s.lookedIn}/)`),\n };\n }\n\n return {\n kind: \"installed\",\n status: \"pass\",\n message: `${ratio(ejectSkills.length, ejectSkills.length, \"eject-mode skill\")} installed`,\n };\n}\n\n/** One eject-mode skill as the Skills Installed row sees it, and where it was looked for. */\ntype EjectedSkillCheck = { id: SkillId; installed: boolean; lookedIn: string };\n\n/**\n * Whether one eject-mode skill's `SKILL.md` is where its scope's host reads it.\n *\n * The provider is read off the scope's OWN root, the way `resolveInstallPaths` and\n * `discoverLocalProjectSkills` read it: two scopes can be on two different providers, and one\n * probe per skill is what keeps the directory and the reported prefix naming one of them.\n */\nasync function ejectedSkillCheck(\n skill: SkillConfig,\n projectDir: string,\n): Promise<EjectedSkillCheck> {\n const provider = providerInUse(installBaseDir(projectDir, skill.scope));\n const dir = skillsDir(provider, skill.scope, projectDir);\n const installed = await fileExists(path.join(dir, skill.id, STANDARD_FILES.SKILL_MD));\n\n return {\n id: skill.id,\n installed,\n lookedIn: skillsPathPrefix(provider, skill.scope, projectDir),\n };\n}\n\n/**\n * Plugin-mode skills have no files under `.claude/skills/` — they live in the\n * Claude plugin registry. Verifying them means asking the registry for the scope\n * each skill was installed at, not looking on disk.\n */\nasync function checkPluginSkillsInstalled(\n config: ProjectConfig,\n projectDir: string,\n): Promise<CheckResult> {\n const pluginSkills: SkillConfig[] = config.skills.filter((s) => s.origin !== EJECT_SOURCE);\n\n if (pluginSkills.length === 0) {\n return {\n kind: \"plugins\",\n status: \"pass\",\n message: \"No plugin-mode skills configured\",\n };\n }\n\n const baseDirs = unique(pluginSkills.map((s) => installBaseDir(projectDir, s.scope)));\n const missingPerBaseDir = await Promise.all(\n baseDirs.map(async (baseDir) => {\n const installedIds = new Set(\n (await getVerifiedPluginInstallPaths(baseDir)).map((plugin) =>\n parseMarketplacePluginRef(plugin.pluginKey),\n ),\n );\n return pluginSkills\n .filter((skill) => installBaseDir(projectDir, skill.scope) === baseDir)\n .filter((skill) => !installedIds.has(skill.id))\n .map((skill) => skill.id);\n }),\n );\n const missingSkills = missingPerBaseDir.flat();\n\n if (missingSkills.length > 0) {\n return {\n kind: \"plugins\",\n status: \"warn\",\n message: `${plural(missingSkills.length, \"skill\")} not installed as plugins`,\n details: missingSkills.map((s) => `- ${s} (no enabled plugin found)`),\n };\n }\n\n return {\n kind: \"plugins\",\n status: \"pass\",\n message: `${ratio(pluginSkills.length, pluginSkills.length, \"plugin-mode skill\")} installed`,\n };\n}\n\n/**\n * How a marketplace came to be the one this run reads, in the words each rung earns.\n *\n * The `default` sentence is the one that had to exist. With no configuration anywhere the resolver\n * falls back to the public catalogue and this check FETCHES it, so the report a bare directory gets\n * describes a network round trip to a marketplace nobody named — which is the row doing its job,\n * since reachability is its whole subject, and it was doing it without saying so. The other four\n * rungs are here because the map is exhaustive against the union rather than a default with\n * exceptions; `doctor` takes no marketplace flag and reads no environment variable, so it reaches\n * the first two through nothing today.\n */\nconst MARKETPLACE_CHOSEN_BY = {\n flag: \"named by this run\",\n env: `named by ${SOURCE_ENV_VAR}`,\n project: \"named by this project's configuration\",\n global: \"named by the global configuration\",\n default: \"nothing here names one, so this is the default\",\n} as const satisfies Record<ResolvedConfig[\"sourceOrigin\"], string>;\n\n/** How this run got hold of that marketplace — off disk, or over the wire. */\nfunction howItWasReached(source: string, isLocal: boolean): string {\n return isLocal ? `Read ${source} from disk` : `Fetched ${source} over the network`;\n}\n\n/**\n * The row for a marketplace this run did reach.\n *\n * `message` names where the skills were read FROM, which for a remote marketplace is the cache\n * directory it was unpacked into; the provenance line beneath it names the marketplace itself.\n * Both, because neither answers the other's question: a cache path says nothing about whose\n * catalogue it holds, and a ref says nothing about what is on disk to inspect.\n *\n * The count is what that marketplace carries, not the matrix this run loaded: the matrix also\n * holds the skills ejected here and the global installation's, which may come from another\n * marketplace altogether.\n */\nfunction reachedMarketplace(result: SourceLoadResult): CheckResult {\n const { source, sourceOrigin } = result.sourceConfig;\n const skillCount = result.marketplaceSkillIds.size;\n const sourceLabel = result.isLocal ? \"local\" : \"remote\";\n\n return {\n kind: \"source\",\n status: \"pass\",\n message: `Connected to ${sourceLabel}: ${result.sourcePath}`,\n details: [\n `${plural(skillCount, \"skill\")} available`,\n `${howItWasReached(source, result.isLocal)} — ${MARKETPLACE_CHOSEN_BY[sourceOrigin]}`,\n ],\n };\n}\n\nasync function checkSourceReachable(projectDir: string): Promise<CheckResult> {\n try {\n const { sourceResult } = await loadSource({ projectDir });\n return reachedMarketplace(sourceResult);\n } catch (error) {\n const message = getErrorMessage(error);\n return {\n kind: \"source\",\n status: \"fail\",\n message: \"Failed to load marketplace\",\n details: [message],\n };\n }\n}\n\ntype ContentCheck = {\n kind: CheckKind;\n name: string;\n noun: string;\n run: (projectDir: string) => Promise<ContentValidation>;\n};\n\n/**\n * A content check plus the two gates it owns: whether it reads config.ts to know WHAT to validate\n * (see {@link CONFIG_CHECK}), and which operational rows its errors stand down.\n *\n * `blocks` names only the rows that READ what this pass validates, so their own verdict would be\n * this pass's finding in the row's words. A row absent from every `blocks` list reads none of the\n * content on disk and answers as truthfully as ever — an error here is not its business.\n */\ntype GatedContentCheck = ContentCheck & {\n readsConfig: boolean;\n blocks: readonly CheckKind[];\n};\n\n/**\n * The config file every other check is read against, so it is validated before any of them and\n * on its own: a file that exists and cannot be parsed is a finding about that file, and every\n * row underneath would be a cascade of it. It carries no gate of its own — it IS the gate.\n */\nconst CONFIG_CHECK: ContentCheck = {\n kind: \"content-config\",\n name: \"Config\",\n noun: \"config\",\n run: validateProjectConfigFile,\n};\n\n/**\n * The content layer: schema and file-level validation of what is on disk. It runs before the\n * operational layer so that a row whose inputs this layer has already reported broken can stand\n * down rather than re-report the same fault as a finding of its own.\n */\nconst CONTENT_CHECKS: GatedContentCheck[] = [\n {\n kind: \"content-sources\",\n name: \"Marketplaces\",\n noun: \"marketplace\",\n // The registered marketplaces are the ones config.ts names.\n readsConfig: true,\n // A marketplace whose content is broken is missing skills from the matrix every configured\n // id is resolved against, so the skills row would call ids \"not found\" that this row has\n // already accounted for.\n blocks: [\"skills\"],\n run: validateRegisteredSources,\n },\n {\n kind: \"content-plugins\",\n name: \"Plugins\",\n noun: \"plugin\",\n readsConfig: false,\n // `resolvePluginInstallPaths` swallows a registry it cannot parse and returns none, so every\n // plugin-mode skill would read \"no enabled plugin found\" — the registry's finding, once per\n // configured skill, wearing the row's words.\n blocks: [\"plugins\"],\n run: validateInstalledPlugins,\n },\n {\n kind: \"content-skills\",\n name: \"Skills\",\n noun: \"skill\",\n // `~/.claude/skills/` is shared with everything else that installs a skill there, so which of\n // its directories are this installation's is a question only the config can answer for the\n // ones carrying no provenance marker. A config nobody can read leaves that unanswerable.\n readsConfig: true,\n // `extractLocalSkill` DROPS a skill whose metadata.yaml is missing or unusable, so a \"not\n // found\" from the skills row would be this finding re-worded.\n blocks: [\"skills\"],\n run: validateInstalledSkills,\n },\n {\n kind: \"content-agents\",\n name: \"Agents\",\n noun: \"agent\",\n readsConfig: false,\n // Nothing downstream opens an agent .md. `Agents Compiled` asks whether the file is there and\n // `No Orphans` reads the names of the files that are — broken frontmatter changes neither.\n blocks: [],\n run: validateInstalledAgents,\n },\n];\n\nfunction contentStatus(errors: number, warnings: number): CheckResult[\"status\"] {\n if (errors > 0) return \"fail\";\n if (warnings > 0) return \"warn\";\n return \"pass\";\n}\n\nfunction contentMessage(noun: string, count: number, errors: number, warnings: number): string {\n // A pass that walked nothing can still report an issue — an unreadable plugin\n // registry is a finding about the directory, not about a plugin inside it.\n if (errors === 0 && warnings === 0) {\n return count === 0 ? `No ${noun}s to validate` : `${plural(count, noun)} validated`;\n }\n return `${plural(count, noun)}: ${plural(errors, \"error\")}, ${plural(warnings, \"warning\")}`;\n}\n\nfunction formatContentIssue(issue: ContentIssue): string {\n const marker = issue.severity === \"error\" ? \"ERROR\" : \"WARN\";\n return `- [${marker}] ${issue.file}: ${issue.message}`;\n}\n\nfunction toContentResult(check: ContentCheck, validation: ContentValidation): CheckResult {\n const errors = validation.issues.filter((issue) => issue.severity === \"error\").length;\n const warnings = validation.issues.length - errors;\n\n return {\n kind: check.kind,\n status: contentStatus(errors, warnings),\n message: contentMessage(check.noun, validation.count, errors, warnings),\n details: [\n ...validation.notes.map((note) => `- ${note}`),\n ...validation.issues.map(formatContentIssue),\n ],\n };\n}\n\n/**\n * The column every row's status symbol starts at. It has to clear the longest row name\n * the report prints — \"Marketplace Reachable\", 21 characters — or that row's name runs\n * straight into its own tick with no gap.\n */\nconst CHECK_WIDTH = 24;\n\n/** Section headings and the rows underneath them are indented one step apart. */\nconst SECTION_INDENT = \" \";\nconst ROW_INDENT = \" \";\n\nconst SECTION_CONTENT = \"Content checks\";\nconst SECTION_OPERATIONAL = \"Operational checks\";\nconst SKIP_NO_INSTALLATION = \"Skipped — no installation here (marketplace repository)\";\nconst SKIP_CONFIG_UNREADABLE = \"Skipped — the configuration that names them cannot be read\";\n\n/**\n * The whole operational layer standing down, for the one content finding that leaves every row\n * with nothing to say: a config nobody can read. It still says \"errors\" rather than naming that\n * file, because the config row is one of them and whatever else failed is above it too.\n */\nconst SKIP_AFTER_CONFIG_ERROR = \"Skipped — fix the content errors above first\";\n\n/**\n * The sentence a single row stands down with. Unlike its neighbours it names the finding rather\n * than the layer: which pass blocked it is the one thing separating a row that cannot answer from\n * the ones printing verdicts beside it.\n */\nfunction skipRestatingContent(nouns: string[]): string {\n return `Skipped — this row would only restate the ${nouns.join(\" and \")} errors above`;\n}\n\nfunction formatCheckName(name: string): string {\n return name.padEnd(CHECK_WIDTH);\n}\n\n/**\n * The glyph each row is headed with, every one of them from {@link UI_SYMBOLS}.\n *\n * The last two used to be literals here — `\"!\"` and `\"-\"` — and the second was the one that\n * mattered: `UI_SYMBOLS.SKIPPED` is an EN-DASH, so a stood-down row printed a different character\n * from the one the symbol table declares for exactly that state, while `UI_SYMBOLS.REMOVED` is\n * deliberately an ASCII hyphen for diff markers. Two glyphs a reader cannot tell apart, meaning\n * opposite things, and nothing pointing either literal at the table it belonged in.\n */\nfunction formatStatus(status: CheckResult[\"status\"]): string {\n switch (status) {\n case \"pass\":\n return UI_SYMBOLS.CHECK;\n case \"fail\":\n return UI_SYMBOLS.CROSS;\n case \"warn\":\n return UI_SYMBOLS.DISCOURAGED;\n case \"skip\":\n return UI_SYMBOLS.SKIPPED;\n default: {\n const _exhaustive: never = status;\n return _exhaustive;\n }\n }\n}\n\n/** The column a row's details start at, under its message. */\nconst DETAIL_INDENT = `${ROW_INDENT}${\" \".repeat(CHECK_WIDTH)} `;\n\nfunction formatCheckLine(name: string, result: CheckResult): string[] {\n const headerLine = `${ROW_INDENT}${formatCheckName(name)}${formatStatus(result.status)} ${result.message}`;\n const detailLines = (result.details ?? []).flatMap(indentedDetailLines);\n return [headerLine, ...detailLines];\n}\n\n/**\n * A detail can be a whole refusal — a loader's message, paragraphs and all — so every one of its\n * lines is indented, and its blank lines dropped. Indenting the first alone printed the rest at\n * column 0, outside the row they belong to and between the rows below it.\n */\nfunction indentedDetailLines(detail: string): string[] {\n return detail\n .split(\"\\n\")\n .filter((line) => line !== \"\")\n .map((line) => `${DETAIL_INDENT}${line}`);\n}\n\nfunction formatSummary(results: CheckResult[]): string {\n const counts = countBy(results, (r) => r.status);\n\n const parts = [\n `${counts.pass ?? 0} passed`,\n plural(counts.warn ?? 0, \"warning\"),\n plural(counts.fail ?? 0, \"error\"),\n ];\n\n return `${SECTION_INDENT}Summary: ${parts.join(\", \")}`;\n}\n\nconst TIPS: Array<{ kind: CheckKind; status: CheckResult[\"status\"]; tip: string }> = [\n {\n kind: \"agents\",\n status: \"warn\",\n tip: ` Tip: Run '${CLI_INVOKE_COMMAND} compile' to generate missing agent files`,\n },\n {\n kind: \"config\",\n status: \"fail\",\n tip: ` Tip: Run '${CLI_INVOKE_COMMAND} init' to create or fix configuration`,\n },\n {\n // The remedy for a valid config with nothing in it. Not the tip above: there is nothing to\n // create and nothing to fix. `init` on this config opens the editor rather than the dashboard\n // — that is what the detection returning null is FOR — so it is the way to fill it in.\n kind: \"config-empty\",\n status: \"warn\",\n tip: ` Tip: Nothing is configured yet — run '${CLI_INVOKE_COMMAND} init' to choose skills and sub-agents`,\n },\n {\n // Printed beside the config tip above, which says how to get a configuration back and\n // nothing about the files that outlived the old one. Both halves are named with what they\n // actually do: `uninstall` matches skill directories by their own `forked-from` metadata and\n // compiled agents by the marker each one carries, so neither needs the configuration that is\n // gone — which is why the row can name both and this tip can promise both.\n kind: \"orphans-unowned\",\n status: \"fail\",\n tip: ` Tip: Nothing declares the files above — '${CLI_INVOKE_COMMAND} init --from <id>' writes a configuration that can own them again, or '${CLI_INVOKE_COMMAND} uninstall' removes them, the compiled agents included: each file listed carries this CLI's own provenance, which is what that command reads when there is no configuration left`,\n },\n {\n kind: \"skills\",\n status: \"fail\",\n tip: \" Tip: Check skill IDs in config match available skills\",\n },\n {\n kind: \"installed\",\n status: \"warn\",\n // No command is named on purpose: 'eject skills --force' re-copies every skill in the\n // marketplace and always targets project scope, so it cannot repair a global-scoped\n // skill and it litters a plugin-mode project with local skill directories.\n tip: \" Tip: Re-eject the missing skills from the marketplace to restore their files\",\n },\n];\n\nfunction formatTips(results: CheckResult[]): string[] {\n return TIPS.filter((t) => results.some((r) => r.kind === t.kind && r.status === t.status)).map(\n (t) => t.tip,\n );\n}\n\n/**\n * The one remedy that applies to a config that cannot be read, once per such config, naming the\n * folder it is taken from. `init` does not clear such a file — it refuses it — so the config tip\n * would send the reader in a circle; this is the way out every refusing command names, worded the\n * same way and sending the reader to the same folder: the project, or the home directory for the\n * global config.\n *\n * Read again rather than threaded out of the content pass, and only once that pass has failed. A\n * failure it cannot classify is already that pass's own failed row, so it adds no tip of its own.\n */\nasync function recreateConfigTips(\n contentResults: CheckResult[],\n projectDir: string,\n): Promise<string[]> {\n if (!failedContentKinds(contentResults).has(CONFIG_CHECK.kind)) return [];\n\n const failures = await findConfigLoadFailures(projectDir).catch(() => []);\n return failures.map(\n (failure) =>\n ` Tip: There is no automatic repair — recreate the configuration by running ${recreateConfigFrom(failure.scopeRoot)}`,\n );\n}\n\n/** The row name every Layout row is printed under, one per scope. */\nconst LAYOUT_ROW_NAME = \"Layout\";\n\n/** One scope's Layout row: which folder its installation is read from and written to. */\nfunction toLayoutResult(scope: SourceScope): CheckResult {\n return {\n kind: \"layout\",\n status: \"pass\",\n message: layoutIsCurrent(scopeLabel(scope.kind), scope.relName),\n };\n}\n\n/** The row name the placement and installation-ambiguity findings are printed under. */\nconst PLACEMENTS_ROW_NAME = \"Placements Offered\";\n\n/**\n * Whether this installation is one every other command will act on — as a ROW, not a throw.\n *\n * **It carries the two findings that make the rest of this report a claim about nothing.** A\n * configuration asking for a mode/scope cell its host does not offer is refused by `compile`,\n * `edit` and `update`; a scope holding an installation of each provider is refused by `edit`,\n * `uninstall`, `share` and `eject`. Until this row existed, `doctor` — the one command whose job\n * is saying whether an installation is healthy — walked straight past both and pronounced a clean\n * bill of health on a configuration no command would touch. A diagnostic that disagrees with every\n * command it is diagnosing is worse than a missing one.\n *\n * **It reports and never refuses**: a command that changes nothing must not refuse to LOOK,\n * because this is exactly the state a user needs to see in order to fix it.\n *\n * The message is the refusal's own, word for word, off the same host roster — so what a user is\n * told here and what they are told when `compile` stops are one sentence, not two that agree\n * today.\n *\n * **The summary counts FINDINGS, and said \"unusable installation\" until 2026-09-22.** The two\n * are not the same number in either direction: one installation with an unofferable placement AND\n * an ambiguous folder contributes two findings, while the ambiguity finding is itself about a\n * scope holding two installations. A count of one noun printed over a list of another is a\n * sentence a reader cannot check against the lines underneath it.\n */\nasync function checkOfferedPlacements(projectDir: string): Promise<CheckResult> {\n const findings = await everythingThatWouldStopACommandActing(projectDir);\n\n if (findings.length === 0) {\n return { kind: \"placements\", status: \"pass\", message: \"Every configured skill is placeable\" };\n }\n\n return {\n kind: \"placements\",\n status: \"fail\",\n message: `${plural(findings.length, \"finding\")} would stop a command acting here`,\n details: findings.map((finding) => `- ${finding}`),\n };\n}\n\n/**\n * The two findings a command would stop on, in one list: a placement no host can fill, and a scope\n * holding an installation of each provider.\n *\n * Asked together rather than in sequence because neither answer depends on the other, and reported\n * together because they are one question for a user — \"will anything act on this?\" — with two ways\n * of being answered no.\n */\nasync function everythingThatWouldStopACommandActing(projectDir: string): Promise<string[]> {\n const [unofferable, ambiguous] = await Promise.all([\n unofferablePlacementsFound(projectDir),\n ambiguityFinding(projectDir),\n ]);\n\n return ambiguous === null ? unofferable : [...unofferable, ambiguous];\n}\n\nfunction skippedResult(kind: CheckKind): CheckResult {\n return { kind, status: \"skip\", message: \"Skipped (config invalid)\" };\n}\n\n/**\n * The skills row when the marketplace never loaded. Distinct from {@link skippedResult}: the\n * config is fine, and what is missing is the matrix to resolve its skills against.\n */\nfunction sourceUnreachableSkillsResult(): CheckResult {\n return { kind: \"skills\", status: \"skip\", message: \"Skipped (marketplace unreachable)\" };\n}\n\nfunction skippedContentResult(kind: CheckKind): CheckResult {\n return { kind, status: \"skip\", message: SKIP_CONFIG_UNREADABLE };\n}\n\n/** The content passes that failed this run — the set every operational row is gated against. */\nfunction failedContentKinds(contentResults: CheckResult[]): ReadonlySet<CheckKind> {\n return new Set(contentResults.filter((r) => r.status === \"fail\").map((r) => r.kind));\n}\n\n/**\n * An operational row standing down because a content pass it reads through failed, naming what\n * blocked it. `null` — the answer for most rows on most runs — means nothing it reads is broken\n * and it can speak for itself.\n */\nfunction contentBlockedResult(\n row: CheckKind,\n failedContent: ReadonlySet<CheckKind>,\n): CheckResult | null {\n const blockingNouns = CONTENT_CHECKS.filter((check) => failedContent.has(check.kind))\n .filter((check) => check.blocks.includes(row))\n .map((check) => check.noun);\n\n if (blockingNouns.length === 0) return null;\n\n return { kind: row, status: \"skip\", message: skipRestatingContent(blockingNouns) };\n}\n\nfunction runContentCheck(check: ContentCheck, projectDir: string): Promise<CheckResult> {\n return safeCheck(check.kind, async () => toContentResult(check, await check.run(projectDir)));\n}\n\n/**\n * Wrap a check so a thrown exception becomes a `fail` result instead of crashing the\n * whole doctor run. Per-check isolation ensures one broken check does not mask others.\n */\nasync function safeCheck(kind: CheckKind, fn: () => Promise<CheckResult>): Promise<CheckResult> {\n try {\n return await fn();\n } catch (error) {\n return { kind, status: \"fail\", message: \"Check threw\", details: [getErrorMessage(error)] };\n }\n}\n\nexport default class Doctor extends BaseCommand {\n static summary = \"Diagnose common configuration issues\";\n\n static description = `Run diagnostic checks on your ${DEFAULT_BRANDING.NAME} configuration to identify issues with config validity, skill resolution, agent compilation, and marketplace connectivity.`;\n\n static examples = [\"<%= config.bin %> <%= command.id %>\"];\n\n static flags = {};\n\n async run(): Promise<void> {\n await this.parse(Doctor);\n const projectDir = process.cwd();\n\n // The shared `verbose()` logger stays OFF, and nothing here switches it on. `doctor` used to,\n // for the whole run — the mechanical residue of a `--verbose` flag whose removal was meant to\n // make each row's own DETAILS unconditional, which `formatCheckLine` does on its own. What the\n // logger added on top of that was the loaders' trace, spliced between the section headings and\n // the rows they head: for a directory holding nothing, 27 lines of it, every one restating a\n // row printed underneath it.\n this.printHeader(await this.resolveBrandingName(projectDir));\n const contentResults = await this.runContentChecks(projectDir);\n const operationalResults = await this.runOperationalChecks(projectDir, contentResults);\n const results = [...contentResults, ...operationalResults];\n\n this.printResults(results, await recreateConfigTips(contentResults, projectDir));\n\n if (results.some((r) => r.status === \"fail\")) {\n this.exit(EXIT_CODES.ERROR);\n }\n }\n\n private printHeader(brandingName: string): void {\n this.log(\"\");\n this.log(`${brandingName} Doctor`);\n this.log(\"\");\n this.log(`${SECTION_INDENT}Checking configuration health...`);\n this.log(\"\");\n }\n\n /**\n * The config is checked first and alone. A check that reads it to know what to validate would\n * otherwise ask a file already reported as unreadable — and asking is what emitted the loader's\n * own failure line once per read, spliced between these rows. Everything that walks installed\n * content on disk still runs: it says something true whatever the config is in.\n */\n private async runContentChecks(projectDir: string): Promise<CheckResult[]> {\n this.log(`${SECTION_INDENT}${SECTION_CONTENT}`);\n\n const configResult = await runContentCheck(CONFIG_CHECK, projectDir);\n const configUnreadable = configResult.status === \"fail\";\n\n const rows = await Promise.all(\n CONTENT_CHECKS.map(async (check) => ({\n name: check.name,\n result:\n check.readsConfig && configUnreadable\n ? skippedContentResult(check.kind)\n : await runContentCheck(check, projectDir),\n })),\n );\n\n const allRows = [{ name: CONFIG_CHECK.name, result: configResult }, ...rows];\n\n for (const row of allRows) {\n this.logCheck(row.name, row.result);\n }\n\n return allRows.map((row) => row.result);\n }\n\n /**\n * The whole layer stands down for the two findings that leave every row with nothing to say: a\n * config nobody can read — every row is read out of it, so all of them would be cascades of that\n * one file — and a marketplace repository with nothing installed, where a marketplace author has\n * no install for the layer to describe. Every other content error is scoped to the rows that\n * read what it is about; {@link GatedContentCheck} says which those are, per pass.\n */\n private async runOperationalChecks(\n projectDir: string,\n contentResults: CheckResult[],\n ): Promise<CheckResult[]> {\n this.log(\"\");\n this.log(`${SECTION_INDENT}${SECTION_OPERATIONAL}`);\n\n const failedContent = failedContentKinds(contentResults);\n if (failedContent.has(CONFIG_CHECK.kind)) {\n this.log(`${ROW_INDENT}${SKIP_AFTER_CONFIG_ERROR}`);\n return [];\n }\n\n const detected = await detectProject(projectDir);\n if (!detected && (await this.isUninstalledSourceRepo(projectDir))) {\n this.log(`${ROW_INDENT}${SKIP_NO_INSTALLATION}`);\n return [];\n }\n\n const configState = await resolveConfigState(detected, projectDir);\n return this.runAllChecks(projectDir, configState, failedContent);\n }\n\n /**\n * A config file that exists but failed to load also detects as \"no project\", and\n * that is a finding rather than an absence — so the skip requires no config file\n * at all, not merely no usable one.\n */\n private async isUninstalledSourceRepo(projectDir: string): Promise<boolean> {\n if (await fileExists(getInstalledConfigPath(projectDir))) return false;\n return isSourceRepo(projectDir);\n }\n\n private async runAllChecks(\n projectDir: string,\n configState: ConfigState,\n failedContent: ReadonlySet<CheckKind>,\n ): Promise<CheckResult[]> {\n const { result: configResult, config } = checkConfigValid(configState, projectDir);\n this.logCheck(\"Config Valid\", configResult);\n\n const layoutResults = await this.reportLayout(projectDir);\n\n // Directly under Layout, and above every row that reads content: Layout says which FOLDER this\n // report is about and this row says whether any command will act on what is in it.\n const placementsResult = await safeCheck(\"placements\", () =>\n checkOfferedPlacements(projectDir),\n );\n this.logCheck(PLACEMENTS_ROW_NAME, placementsResult);\n\n // loadSource (called by checkSourceReachable) populates the matrix. Run it\n // before checkSkillsResolved so skills lookups see a populated matrix; if\n // source fails, skip skills rather than reporting false \"not found\" errors.\n const sourceResult = await safeCheck(\"source\", () => checkSourceReachable(projectDir));\n\n const filteredConfig = config ? filterExcludedEntries(config) : null;\n\n const skillsResult = await this.resolveSkillsCheck(\n config,\n sourceResult,\n projectDir,\n failedContent,\n );\n this.logCheck(\"Skills Resolved\", skillsResult);\n\n const agentsResult = filteredConfig\n ? await safeCheck(\"agents\", () => checkAgentsCompiled(filteredConfig, projectDir))\n : skippedResult(\"agents\");\n this.logCheck(\"Agents Compiled\", agentsResult);\n\n const orphansResult = await this.resolveOrphansCheck(config, configState, projectDir);\n this.logCheck(\"No Orphans\", orphansResult);\n\n const installedResult = filteredConfig\n ? await safeCheck(\"installed\", () => checkSkillsInstalled(filteredConfig, projectDir))\n : skippedResult(\"installed\");\n this.logCheck(\"Skills Installed\", installedResult);\n\n const pluginsResult = await this.resolvePluginsCheck(filteredConfig, projectDir, failedContent);\n this.logCheck(\"Plugins Installed\", pluginsResult);\n\n this.logCheck(\"Marketplace Reachable\", sourceResult);\n\n return [\n configResult,\n ...layoutResults,\n placementsResult,\n skillsResult,\n agentsResult,\n orphansResult,\n installedResult,\n pluginsResult,\n sourceResult,\n ];\n }\n\n /**\n * One `Layout` row per scope in play.\n *\n * Per scope rather than per machine: a project and the global installation are two\n * installations, and one row for the two can only name one of their folders.\n *\n * Printed right under `Config Valid`, because every row below it is read out of a config file\n * in the folder this row names.\n */\n private async reportLayout(projectDir: string): Promise<CheckResult[]> {\n const rows = (await sourceScopesInPlay(projectDir)).map(toLayoutResult);\n\n for (const row of rows) {\n this.logCheck(LAYOUT_ROW_NAME, row);\n }\n return rows;\n }\n\n /**\n * The orphan row, and which question it can answer. With a config it names the compiled\n * agents that config does not; with no config at all every installed file is unowned and it\n * names all of them. It skips for the one state left — a config that loads and fails\n * validation — because there the file that says who owns what has already been rejected, and\n * an installation must not be called stranded on the strength of one nobody can trust.\n */\n private async resolveOrphansCheck(\n config: ProjectConfig | null,\n configState: ConfigState,\n projectDir: string,\n ): Promise<CheckResult> {\n if (config) return safeCheck(\"orphans\", () => checkNoOrphans(config, projectDir));\n if (configState.kind === \"absent\") {\n return safeCheck(\"orphans\", () => checkUnownedInstallation(projectDir));\n }\n return skippedResult(\"orphans\");\n }\n\n /**\n * The skills row, and the three states in which it cannot be computed: no config to read the\n * skills out of, content it resolves against that the layer above has already reported broken,\n * and a marketplace that never loaded — so there is no populated matrix to resolve them\n * against, and every configured skill would be reported \"not found\".\n */\n private async resolveSkillsCheck(\n config: ProjectConfig | null,\n sourceResult: CheckResult,\n projectDir: string,\n failedContent: ReadonlySet<CheckKind>,\n ): Promise<CheckResult> {\n if (!config) return skippedResult(\"skills\");\n\n const blocked = contentBlockedResult(\"skills\", failedContent);\n if (blocked) return blocked;\n if (sourceResult.status === \"fail\") return sourceUnreachableSkillsResult();\n\n return safeCheck(\"skills\", () => checkSkillsResolved(config, matrix, projectDir));\n }\n\n /**\n * The plugin row, and the two states in which it cannot be computed: no config to read the\n * plugin-mode skills out of, and a plugin registry the layer above could not parse — which\n * resolves as no installs at all, so every configured skill would be reported missing.\n */\n private async resolvePluginsCheck(\n config: ProjectConfig | null,\n projectDir: string,\n failedContent: ReadonlySet<CheckKind>,\n ): Promise<CheckResult> {\n if (!config) return skippedResult(\"plugins\");\n\n const blocked = contentBlockedResult(\"plugins\", failedContent);\n if (blocked) return blocked;\n\n return safeCheck(\"plugins\", () => checkPluginSkillsInstalled(config, projectDir));\n }\n\n private logCheck(name: string, result: CheckResult): void {\n for (const line of formatCheckLine(name, result)) {\n this.log(line);\n }\n }\n\n private printResults(results: CheckResult[], recreateTips: string[]): void {\n this.log(\"\");\n this.log(formatSummary(results));\n\n const tips = [...formatTips(results), ...recreateTips];\n if (tips.length > 0) {\n this.log(\"\");\n for (const tip of tips) {\n this.log(tip);\n }\n }\n\n this.log(\"\");\n }\n}\n","import path from \"path\";\nimport { isRecord } from \"../utils/type-guards.js\";\nimport { parse as parseYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport { glob, readFile, fileExists, directoryExists } from \"../utils/fs\";\nimport {\n DIRS,\n MARKETPLACE_JSON,\n PLUGIN_MANIFEST_DIR,\n SKILL_CATEGORIES_PATH,\n SKILL_RULES_PATH,\n SKILLS_DIR_PATH,\n STACKS_FILE_PATH,\n STANDARD_FILES,\n} from \"../consts\";\nimport {\n agentYamlGenerationSchema,\n metadataValidationSchema,\n splitMetadataValidationIssues,\n validateSkillMetadata,\n skillCategoriesFileSchema,\n skillRulesFileSchema,\n stackConfigValidationSchema,\n stacksConfigSchema,\n} from \"./schemas\";\nimport { parseFrontmatter } from \"./loading/loader\";\nimport { ConfigDefaultExportError, loadConfig, loadSourceRepoConfig } from \"./configuration\";\nimport type { MatrixHealthIssue } from \"./matrix\";\nimport { matrixHealthIssues } from \"./matrix/matrix-health-check\";\nimport {\n loadSkillsMatrixFromSource,\n MarketplaceManifestRequiredError,\n} from \"./loading/source-loader\";\nimport { MarketplaceNameRefusedError } from \"./loading/source-fetcher\";\nimport { matrix } from \"./matrix/matrix-provider\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport { formatZodErrors } from \"./schema-validator\";\n\nexport type SourceValidationIssue = {\n severity: \"error\" | \"warning\";\n file: string;\n message: string;\n};\n\nexport type SourceValidationResult = {\n issues: SourceValidationIssue[];\n skillCount: number;\n errorCount: number;\n warningCount: number;\n};\n\n/**\n * Who this report is for, relative to the marketplace it is about.\n *\n * You are the `\"author\"` of the marketplace being validated when it IS the directory the command\n * ran in; a marketplace anywhere else — fetched, or on disk at another path — is one you are only\n * a `\"consumer\"` of. Not \"is there a marketplace under the cwd\": that says nothing about the OTHER\n * marketplace a config may point at, and the severity turns on the per-marketplace question.\n *\n * It changes one finding. A slug a marketplace's rules dangle is a typo its author can fix and\n * wants the run to fail on, and it is a defect a consumer cannot touch in a file they cannot open\n * — while every skill still installs and still resolves. Whether the reader holds push rights is\n * not knowable here and is not the test: a checkout under your cursor is a file you can edit.\n */\nexport type MarketplaceReader = \"author\" | \"consumer\";\n\n/**\n * True when `dir` is itself a skills source repository — it carries the skills tree\n * `validateSource` walks, at `src/skills/` or wherever its own source config points.\n * A marketplace author's checkout answers yes; a consumer project answers no.\n */\nexport async function isSourceRepo(dir: string): Promise<boolean> {\n // ABORT on an unreadable config, and it is caught rather than fatal at both callers: `doctor`\n // reaches this through `safeCheck`, so the throw becomes a failed row instead of an aborted\n // command, and its other caller asks only where no config file exists at all.\n const sourceConfig = await loadSourceRepoConfig(dir);\n return directoryExists(path.join(dir, sourceConfig?.skillsDir ?? SKILLS_DIR_PATH));\n}\n\n/** Checks if a key uses snake_case (has underscore between lowercase letters) */\nexport function isSnakeCase(key: string): boolean {\n return /[a-z]_[a-z]/.test(key);\n}\n\n/**\n * Checks top-level keys for snake_case usage (camelCase is the convention).\n * Non-object input yields no issues.\n */\nexport function checkSnakeCaseKeys(rawMetadata: unknown, relPath: string): SourceValidationIssue[] {\n if (!isRecord(rawMetadata)) return [];\n\n return Object.keys(rawMetadata)\n .filter(isSnakeCase)\n .map((key) => ({\n severity: \"error\" as const,\n file: relPath,\n message: `Key '${key}' uses snake_case — use camelCase instead`,\n }));\n}\n\n/**\n * Warns when a skill directory's name does not equal the skill's machine id\n * (SKILL.md frontmatter `name`) — the key the loader registers the skill under.\n * Warning, not error: the loader still loads the skill by its id, but the\n * directory no longer signals which skill it contains.\n */\nexport function checkDirNameMatchesSkillId(\n skillId: string,\n relPath: string,\n dirName: string,\n): SourceValidationIssue[] {\n if (skillId === dirName) return [];\n return [\n {\n severity: \"warning\",\n file: relPath,\n message: `Directory name '${dirName}' does not match skill id '${skillId}'`,\n },\n ];\n}\n\n/**\n * Reads a skill directory's SKILL.md frontmatter and checks the directory name\n * against the skill's machine id. When the id cannot be read (unreadable file or\n * missing/invalid frontmatter), reports that the check could not run.\n */\nasync function checkSkillDirName(\n skillsDir: string,\n skillsDirRelPath: string,\n skillDir: string,\n): Promise<SourceValidationIssue[]> {\n const dirName = path.basename(skillDir);\n const skillMdRelPath = path.join(skillsDirRelPath, skillDir, STANDARD_FILES.SKILL_MD);\n\n try {\n const content = await readFile(path.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD));\n const frontmatter = parseFrontmatter(content, skillMdRelPath);\n\n if (frontmatter === null) {\n return [\n {\n severity: \"warning\",\n file: skillMdRelPath,\n message: `Cannot verify directory name '${dirName}': missing or invalid ${STANDARD_FILES.SKILL_MD} frontmatter`,\n },\n ];\n }\n\n return checkDirNameMatchesSkillId(frontmatter.name, skillMdRelPath, dirName);\n } catch (error) {\n return [\n {\n severity: \"warning\",\n file: skillMdRelPath,\n message: `Cannot verify directory name '${dirName}': ${getErrorMessage(error)}`,\n },\n ];\n }\n}\n\n/**\n * Finds missing SKILL.md / metadata.yaml pairs (pure function, no I/O).\n *\n * Returns issues for:\n * - Directories with SKILL.md but no metadata.yaml\n * - Directories with metadata.yaml but no SKILL.md\n */\nexport function validateSkillFilePairs(\n skillMdDirs: Set<string>,\n metadataDirs: Set<string>,\n skillsDir: string,\n): SourceValidationIssue[] {\n const missingMetadata = [...skillMdDirs]\n .filter((dir) => !metadataDirs.has(dir))\n .map((dir) => ({\n severity: \"error\" as const,\n file: path.join(skillsDir, dir),\n message: `Missing ${STANDARD_FILES.METADATA_YAML} — skill directory has ${STANDARD_FILES.SKILL_MD} but no metadata`,\n }));\n\n const missingSkillMd = [...metadataDirs]\n .filter((dir) => !skillMdDirs.has(dir))\n .map((dir) => ({\n severity: \"error\" as const,\n file: path.join(skillsDir, dir),\n message: `Missing ${STANDARD_FILES.SKILL_MD} — skill directory has ${STANDARD_FILES.METADATA_YAML} but no SKILL.md`,\n }));\n\n return [...missingMetadata, ...missingSkillMd];\n}\n\n/**\n * Validates a skills source repository for metadata correctness.\n *\n * Checks:\n * 1. Every metadata.yaml against the strict validation schema\n * (over-length cliDescription is downgraded to a warning)\n * 2. Directory name equals the skill's machine id (SKILL.md frontmatter name)\n * 3. Cross-references resolve to existing skill IDs (via matrixHealthIssues)\n * 4. camelCase key convention (no snake_case)\n * 5. Every skill directory has both SKILL.md and metadata.yaml\n *\n * `reader` decides how loudly one of those findings is stated — see {@link MarketplaceReader}.\n * It defaults to `\"author\"`, the louder verdict: a caller that names nobody has said nothing\n * about who is reading, and under-reporting to the one person who can fix the file is the worse\n * of the two ways to be wrong.\n */\nexport async function validateSource(\n sourcePath: string,\n reader: MarketplaceReader = \"author\",\n): Promise<SourceValidationResult> {\n const resolvedPath = path.isAbsolute(sourcePath) ? sourcePath : path.resolve(sourcePath);\n\n if (!(await directoryExists(resolvedPath))) {\n return buildResult(\n [{ severity: \"error\", file: resolvedPath, message: \"Marketplace directory does not exist\" }],\n 0,\n );\n }\n\n // ABORT on an unreadable config, caught by `validateOneSource`, which turns it into an issue\n // against this marketplace. Defaulting past it would validate whatever sits at `src/skills/` and\n // call a marketplace whose skills live elsewhere empty.\n const sourceProjectConfig = await loadSourceRepoConfig(resolvedPath);\n const skillsDirRelPath = sourceProjectConfig?.skillsDir ?? SKILLS_DIR_PATH;\n const skillsDir = path.join(resolvedPath, skillsDirRelPath);\n\n if (!(await directoryExists(skillsDir))) {\n return buildResult(\n [{ severity: \"error\", file: skillsDir, message: \"Skills directory does not exist\" }],\n 0,\n );\n }\n\n // Phase 1: Check every skill directory has both SKILL.md and metadata.yaml\n const skillMdFiles = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir);\n const metadataFiles = await glob(`**/${STANDARD_FILES.METADATA_YAML}`, skillsDir);\n\n const skillMdDirs = new Set(skillMdFiles.map((f) => path.dirname(f)));\n const metadataDirs = new Set(metadataFiles.map((f) => path.dirname(f)));\n\n const pairIssues = validateSkillFilePairs(skillMdDirs, metadataDirs, skillsDir);\n\n // Phase 2: Validate each metadata.yaml against strict schema and conventions.\n // Pair violations were already reported by phase 1 — validate only complete pairs.\n const validMetadataFiles = metadataFiles.filter((f) => skillMdDirs.has(path.dirname(f)));\n const skillIssues = await validateSkillsInTurn(skillsDir, skillsDirRelPath, validMetadataFiles);\n\n // Phase 3: Cross-reference validation via matrix health check\n const crossReferenceIssues = await checkCrossReferences(resolvedPath, reader);\n\n // Phases 4–6: optional source-repo targets — run in parallel\n // Phase 4: stack skill metadata + stack configs\n // Phase 5: agent metadata\n // Phase 6: config/*.ts runtime exports\n const extraIssues = await Promise.all([\n validateStacks(resolvedPath),\n validateAgents(resolvedPath),\n validateConfigFiles(resolvedPath),\n ]);\n\n return buildResult(\n [...pairIssues, ...skillIssues, ...crossReferenceIssues, ...extraIssues.flat()],\n validMetadataFiles.length,\n );\n}\n\n/** {@link validateOneSkill} over every complete pair, one skill at a time, in the order given. */\nasync function validateSkillsInTurn(\n skillsDir: string,\n skillsDirRelPath: string,\n metadataFiles: string[],\n): Promise<SourceValidationIssue[]> {\n const issues: SourceValidationIssue[] = [];\n for (const metadataFile of metadataFiles) {\n issues.push(...(await validateOneSkill(skillsDir, skillsDirRelPath, metadataFile)));\n }\n return issues;\n}\n\n/**\n * Why a YAML file could not be read, in the parser's own words. Two phases refuse the same\n * way — the skill-pair scan and the stack/agent scan — and they printed different sentences\n * for a while, one carrying the cause and one dropping it; naming the message once is what\n * stops them diverging again.\n */\nfunction yamlParseFailure(error: unknown): string {\n return `Failed to parse YAML: ${getErrorMessage(error)}`;\n}\n\n/**\n * One complete skill pair, judged four ways: its metadata.yaml parses, its keys are camelCase,\n * it satisfies the strict published-skill schema, and its directory is named after the id its\n * SKILL.md declares. A file nothing can be parsed out of reports that and stops — every check\n * after it reads the parsed value, so each would only restate the same fault.\n */\nasync function validateOneSkill(\n skillsDir: string,\n skillsDirRelPath: string,\n metadataFile: string,\n): Promise<SourceValidationIssue[]> {\n const relPath = path.join(skillsDirRelPath, metadataFile);\n\n let rawMetadata: unknown;\n try {\n rawMetadata = parseYaml(await readFile(path.join(skillsDir, metadataFile)));\n } catch (error) {\n return [{ severity: \"error\", file: relPath, message: yamlParseFailure(error) }];\n }\n\n return [\n ...checkSnakeCaseKeys(rawMetadata, relPath),\n ...checkMetadataSchema(rawMetadata, relPath),\n // Independent of metadata validity — the id lives in SKILL.md frontmatter\n ...(await checkSkillDirName(skillsDir, skillsDirRelPath, path.dirname(metadataFile))),\n ];\n}\n\n/**\n * The strict published-skill schema's verdict, as its hard errors plus the one advisory\n * (over-length cliDescription) `splitMetadataValidationIssues` separates out.\n */\nfunction checkMetadataSchema(rawMetadata: unknown, relPath: string): SourceValidationIssue[] {\n const result = validateSkillMetadata(rawMetadata);\n if (result.success) return [];\n\n const { errors, warnings } = splitMetadataValidationIssues(result.error, rawMetadata);\n return [\n ...errors.map((message) => ({ severity: \"error\" as const, file: relPath, message })),\n ...warnings.map((message) => ({ severity: \"warning\" as const, file: relPath, message })),\n ];\n}\n\n/**\n * The manifest as a reader of the report has to type it — the location half of the row\n * `doctor` prints, and therefore the file they open.\n */\nconst MARKETPLACE_MANIFEST_PATH = path.join(PLUGIN_MANIFEST_DIR, MARKETPLACE_JSON);\n\n/**\n * How loud a missing or unreadable manifest is, by who is reading: its author is one build from\n * the fix, and a consumer has nothing to load. Keyed on the whole union, so a new kind of reader\n * does not compile until someone decides this.\n */\nconst MANIFEST_REQUIRED_SEVERITY = {\n author: \"warning\",\n consumer: \"error\",\n} as const satisfies Record<MarketplaceReader, SourceValidationIssue[\"severity\"]>;\n\n/**\n * Whether every relationship the source declares resolves to a skill it actually holds.\n * A load that did not complete is reported by {@link matrixLoadFailure}, which decides\n * whether the failure is this marketplace's fault or merely this pass's.\n *\n * The load has already said each health finding; this pass only files them, so it reads them\n * without saying them again.\n */\nasync function checkCrossReferences(\n resolvedPath: string,\n reader: MarketplaceReader,\n): Promise<SourceValidationIssue[]> {\n try {\n await loadSkillsMatrixFromSource({ sourceFlag: resolvedPath, skipExtraSources: true });\n return matrixHealthIssues(matrix).map((healthIssue) =>\n toSourceIssue(healthIssue, resolvedPath, reader),\n );\n } catch (error) {\n return [matrixLoadFailure(error, reader)];\n }\n}\n\n/**\n * A load this pass could not complete, as the finding a reader can act on.\n *\n * Three answers, because the failures are not one event. A marketplace with no valid\n * manifest cannot be loaded at all, so the finding is the manifest's, filed against the file\n * a reader opens rather than the categories file this pass happened to be reading, at the\n * severity {@link MANIFEST_REQUIRED_SEVERITY} gives its reader. A manifest naming the marketplace\n * something Claude Code registers no plugin under leaves nothing here installable, so it is\n * this marketplace's own ERROR, against the file that holds the name — without it the\n * Marketplaces row counted such a marketplace as validated and printed a tick beneath\n * `doctor`'s own warning about that same file, and a warning above a tick is what a reader\n * stops believing. Everything else only leaves this pass unable to run, so it stays a warning\n * against the file it was reading. Read off the throw's TYPE, so nothing here matches on a\n * sentence.\n */\nfunction matrixLoadFailure(error: unknown, reader: MarketplaceReader): SourceValidationIssue {\n if (error instanceof MarketplaceManifestRequiredError) {\n return {\n severity: MANIFEST_REQUIRED_SEVERITY[reader],\n file: MARKETPLACE_MANIFEST_PATH,\n message: getErrorMessage(error),\n };\n }\n\n if (error instanceof MarketplaceNameRefusedError) {\n return {\n severity: \"error\",\n file: MARKETPLACE_MANIFEST_PATH,\n message: getErrorMessage(error),\n };\n }\n\n return {\n severity: \"warning\",\n file: SKILL_CATEGORIES_PATH,\n message: `Cross-reference validation skipped: failed to load categories/rules: ${getErrorMessage(error)}`,\n };\n}\n\n/**\n * The audit manifest, as a path a reader can open. It is this CLI's own file rather than anything\n * in the marketplace being validated, and it has to be: the verdict a matrix contradicts is\n * recorded there and the marketplace holds no copy of it.\n */\nconst SKILL_AUDIT_PATH = \"src/cli/lib/configuration/skill-audit.ts\";\n\n/**\n * The file a finding's defect is written in — the one `doctor` renders as the location half of the\n * line, and therefore the one the reader opens.\n *\n * Each answer is the file the check actually reads, which is not always the file its name suggests:\n *\n * - a category and the `domain` it omits are both declared in the categories file, and a skill\n * naming a category nothing defines is the same file short an entry (its own metadata.yaml is\n * the other half of that fix, and the message already names the skill);\n * - every relation a resolved skill carries comes from the rules file — no metadata.yaml declares\n * one — so an unresolved reference and the dangling slug behind it are both written there;\n * - a verdict, recorded or missing, is the audit manifest's.\n *\n * Exhaustive on purpose: a seventh finding kind will not compile until someone decides where its\n * defect lives, which is the property one path shared by all six had already lost.\n */\nfunction fileHoldingDefect(finding: MatrixHealthIssue[\"finding\"]): string {\n switch (finding) {\n case \"category-missing-domain\":\n case \"skill-unknown-category\":\n return SKILL_CATEGORIES_PATH;\n case \"skill-unresolved-relation-ref\":\n case \"rule-unresolved-slug\":\n return SKILL_RULES_PATH;\n case \"audit-verdict-contradiction\":\n case \"skill-unaudited\":\n return SKILL_AUDIT_PATH;\n default: {\n const exhaustive: never = finding;\n return exhaustive;\n }\n }\n}\n\n/**\n * One health finding as this reader should hear it. Every kind but one is reported at the\n * severity the health check gave it — that severity is a property of the defect. The exception\n * is the slug a marketplace's own rules dangle, which is a property of the defect AND of who is\n * looking: a typo the author can fix, and a file the consumer cannot open.\n *\n * The reader moves the severity and the wording; it never moves the file, because which file holds\n * the defect is not a fact about who is reading.\n */\nfunction toSourceIssue(\n healthIssue: MatrixHealthIssue,\n marketplacePath: string,\n reader: MarketplaceReader,\n): SourceValidationIssue {\n const file = fileHoldingDefect(healthIssue.finding);\n\n if (reader === \"consumer\" && healthIssue.finding === \"rule-unresolved-slug\") {\n return {\n severity: \"warning\",\n file,\n message: consumedMarketplaceMessage(marketplacePath, healthIssue.details),\n };\n }\n\n return {\n severity: healthIssue.severity,\n file,\n message: healthIssue.details,\n };\n}\n\n/**\n * The same finding, addressed to someone who did not write the rule. It leads with the\n * marketplace because that is the part the slug alone does not tell them, and it says outright\n * that there is nothing here to fix — a warning that sends a reader hunting through their own\n * project for a typo in a file they do not own is worse than no warning at all.\n */\nfunction consumedMarketplaceMessage(marketplacePath: string, details: string): string {\n return `Marketplace '${marketplacePath}': ${details}. Nothing to fix here — the rule is that marketplace's, not this project's`;\n}\n\n/**\n * Validates stack-embedded skill metadata.yaml files and stack config.yaml files.\n * Skips silently when src/stacks/ does not exist.\n */\nasync function validateStacks(resolvedPath: string): Promise<SourceValidationIssue[]> {\n const stacksDir = path.join(resolvedPath, DIRS.stacks);\n if (!(await directoryExists(stacksDir))) return [];\n\n const [skillMetaIssues, configIssues] = await Promise.all([\n validateYamlFiles({\n baseDir: stacksDir,\n relBaseDir: DIRS.stacks,\n pattern: `**/skills/**/${STANDARD_FILES.METADATA_YAML}`,\n schema: metadataValidationSchema,\n }),\n validateYamlFiles({\n baseDir: stacksDir,\n relBaseDir: DIRS.stacks,\n pattern: `*/${STANDARD_FILES.CONFIG_YAML}`,\n schema: stackConfigValidationSchema,\n }),\n ]);\n return [...skillMetaIssues, ...configIssues];\n}\n\n/**\n * Validates each hand-authored agent `metadata.yaml` under `DIRS.agents` against\n * `agentYamlGenerationSchema` — compilation's INPUT schema rather than an output one, since\n * compiling an agent writes one `.md` file and no YAML at all. Skips silently when src/agents/\n * does not exist.\n */\nasync function validateAgents(resolvedPath: string): Promise<SourceValidationIssue[]> {\n const agentsDir = path.join(resolvedPath, DIRS.agents);\n if (!(await directoryExists(agentsDir))) return [];\n\n return validateYamlFiles({\n baseDir: agentsDir,\n relBaseDir: DIRS.agents,\n pattern: `**/${STANDARD_FILES.AGENT_METADATA_YAML}`,\n schema: agentYamlGenerationSchema,\n });\n}\n\n/**\n * Validates TypeScript config files (skill-categories.ts, skill-rules.ts, stacks.ts)\n * by runtime-loading them via loadConfig and validating the default export.\n * Skips silently when a file does not exist.\n */\nasync function validateConfigFiles(resolvedPath: string): Promise<SourceValidationIssue[]> {\n const results = await Promise.all([\n validateTsConfig(resolvedPath, SKILL_CATEGORIES_PATH, skillCategoriesFileSchema),\n validateTsConfig(resolvedPath, SKILL_RULES_PATH, skillRulesFileSchema),\n validateTsConfig(resolvedPath, STACKS_FILE_PATH, stacksConfigSchema),\n ]);\n return results.flat();\n}\n\n/** One kind of YAML file a source may carry: where it lives, and the schema each must satisfy. */\ntype YamlFileScan = {\n baseDir: string;\n /**\n * `baseDir` as issues report it, so their locations match the project-relative form used\n * elsewhere.\n */\n relBaseDir: string;\n pattern: string;\n schema: z.ZodType<unknown>;\n};\n\n/**\n * {@link validateYamlFile} over every file the scan's pattern matches, one file at a time, in\n * glob order.\n */\nasync function validateYamlFiles(scan: YamlFileScan): Promise<SourceValidationIssue[]> {\n const issues: SourceValidationIssue[] = [];\n const files = await glob(scan.pattern, scan.baseDir);\n\n for (const relFile of files) {\n issues.push(...(await validateYamlFile(scan, relFile)));\n }\n return issues;\n}\n\n/**\n * One YAML file judged against the scan's schema: its parse error if it cannot be read, otherwise\n * the schema's errors as field-path messages — none when it passes.\n */\nasync function validateYamlFile(\n scan: YamlFileScan,\n relFile: string,\n): Promise<SourceValidationIssue[]> {\n const displayPath = path.join(scan.relBaseDir, relFile);\n\n let parsed: unknown;\n try {\n parsed = parseYaml(await readFile(path.join(scan.baseDir, relFile)));\n } catch (error) {\n return [{ severity: \"error\", file: displayPath, message: yamlParseFailure(error) }];\n }\n\n const result = scan.schema.safeParse(parsed);\n if (result.success) return [];\n\n return formatZodErrors(result.error).map((message) => ({\n severity: \"error\" as const,\n file: displayPath,\n message,\n }));\n}\n\n/**\n * Runtime-loads a TypeScript config file via loadConfig and reports validation failures.\n * Absent files are not errors — only report when the file exists but fails to load or validate.\n *\n * The two ways a file can say nothing are reported apart, because the author's next move differs\n * and they used to arrive wearing each other's words. A `null` is a file that exported nothing at\n * all; a module that exported only named bindings raises {@link ConfigDefaultExportError}, which\n * is the one this file's own config files get wrong — `export const skillRules = {...}` reads to\n * `loadConfig` as a namespace, and validating THAT against the schema reports whichever field the\n * schema names first as missing from a file the author can see it in.\n */\nasync function validateTsConfig(\n resolvedPath: string,\n relConfigPath: string,\n schema: z.ZodType<unknown>,\n): Promise<SourceValidationIssue[]> {\n const absPath = path.join(resolvedPath, relConfigPath);\n if (!(await fileExists(absPath))) return [];\n\n try {\n const loaded = await loadConfig(absPath, schema);\n if (loaded === null) {\n return [{ severity: \"error\", file: relConfigPath, message: \"Config is empty\" }];\n }\n return [];\n } catch (error) {\n if (error instanceof ConfigDefaultExportError) {\n return [{ severity: \"error\", file: relConfigPath, message: \"Config has no default export\" }];\n }\n return [\n { severity: \"error\", file: relConfigPath, message: formatLoadError(relConfigPath, error) },\n ];\n }\n}\n\n/**\n * Normalizes a loadConfig error so the message references the relative config path,\n * not the absolute path embedded by loadConfig's own template string.\n */\nfunction formatLoadError(relConfigPath: string, error: unknown): string {\n const raw = getErrorMessage(error);\n const stripped = raw.replace(/Failed to load config from '[^']+':\\s*/, \"\");\n return `Failed to load ${relConfigPath}: ${stripped}`;\n}\n\nfunction buildResult(issues: SourceValidationIssue[], skillCount: number): SourceValidationResult {\n const errorCount = issues.filter((i) => i.severity === \"error\").length;\n const warningCount = issues.filter((i) => i.severity === \"warning\").length;\n return { issues, skillCount, errorCount, warningCount };\n}\n","import os from \"os\";\nimport path from \"path\";\nimport { partition } from \"remeda\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { PLUGIN_MANIFEST_DIR, STANDARD_FILES } from \"../consts.js\";\nimport { directoryExists, fileExists, listDirectories } from \"../utils/fs.js\";\nimport { listAgentMdFiles, splitAgentsByProvenance } from \"./agents/index.js\";\nimport { readSkillMetadata } from \"./loading/index.js\";\nimport {\n configDirsInPlay,\n findConfigLoadFailures,\n isLocalSource,\n loadInstalledConfig,\n resolvePrimarySourceEntry,\n type ConfigLoadError,\n type LoadedProjectConfig,\n type SourceEntry,\n} from \"./configuration/index.js\";\nimport { isHomeDirectory, resolveInstallPaths } from \"./installation/index.js\";\nimport { getInstalledConfigPath } from \"./installation/install-base-dir.js\";\nimport {\n getInstalledPluginsRegistryPath,\n getProjectPluginsDir,\n getUserPluginsDir,\n listRegisteredPluginInstalls,\n validateAgentFrontmatter,\n validateAllPlugins,\n validatePlugin,\n validateSkillFrontmatter,\n type ResolvedPlugin,\n} from \"./plugins/index.js\";\nimport { splitMetadataValidationIssues, validateSkillMetadata } from \"./schemas.js\";\nimport { readForkedFromMetadata } from \"./skills/index.js\";\nimport { isSourceRepo, validateSource, type MarketplaceReader } from \"./source-validator.js\";\nimport { invalidResult, mergeValidationResults, validResult } from \"./validation-result.js\";\nimport { scopeLabel } from \"../utils/messages.js\";\nimport { plural } from \"../utils/string.js\";\nimport type { ValidationResult } from \"../types/index.js\";\n\n/** How a source repository under the cwd is labelled when it is not a registered source. */\nconst CWD_SOURCE_NAME = \"current directory\";\n\n/** What a compiled agent is called on disk; `splitAgentsByProvenance` answers in bare names. */\nconst AGENT_FILE_EXTENSION = \".md\";\n\nexport type ContentIssue = {\n severity: \"error\" | \"warning\";\n /** The file or directory a reader has to open to fix the issue. */\n file: string;\n message: string;\n};\n\n/**\n * One content pass: what it walked, what it found, and what it deliberately did\n * not check. `notes` carries neither errors nor warnings — it is the record of\n * which sources were reached and which were skipped.\n */\nexport type ContentValidation = {\n count: number;\n issues: ContentIssue[];\n notes: string[];\n};\n\nconst NOTHING_VALIDATED: ContentValidation = { count: 0, issues: [], notes: [] };\n\nfunction mergeValidations(parts: ContentValidation[]): ContentValidation {\n return parts.reduce(\n (acc, part) => ({\n count: acc.count + part.count,\n issues: [...acc.issues, ...part.issues],\n notes: [...acc.notes, ...part.notes],\n }),\n NOTHING_VALIDATED,\n );\n}\n\n/** Render an absolute path with a `~/` prefix when it's under the user's home directory. */\nfunction displayDir(absolutePath: string): string {\n const home = os.homedir();\n if (absolutePath === home) return \"~\";\n if (absolutePath.startsWith(home + path.sep)) {\n return `~${path.sep}${path.relative(home, absolutePath)}`;\n }\n return absolutePath;\n}\n\nfunction toIssues(file: string, result: ValidationResult): ContentIssue[] {\n return [\n ...result.errors.map((message) => ({ severity: \"error\" as const, file, message })),\n ...result.warnings.map((message) => ({ severity: \"warning\" as const, file, message })),\n ];\n}\n\n/** Says which of the three load outcomes a config file is in, without restating the loader. */\nconst CONFIG_UNREADABLE = \"exists but could not be loaded\";\n\n/**\n * Validates the config files this run reads: the project's own and the global one it inlines.\n *\n * A config that exists and cannot be parsed is reported here rather than left to the operational\n * layer, for the reason that layer exists to be gated on — every operational row is read OUT of\n * this file, so each would be a cascade of the same fault. It is also the only report that can\n * carry the loader's reason: the layers below re-read the file per check, and their own\n * diagnostics for it are what used to arrive spliced between the rows.\n *\n * An ABSENT config is not a finding here. It is the legitimate state `init` exists for, and the\n * operational layer already names it and offers the remedy that fits it.\n */\nexport async function validateProjectConfigFile(projectDir: string): Promise<ContentValidation> {\n const [present, failures] = await Promise.all([\n countExistingConfigs(projectDir),\n findConfigLoadFailures(projectDir),\n ]);\n\n return { count: present, issues: failures.map(toUnreadableConfigIssue), notes: [] };\n}\n\n/**\n * Led by whose config it is, as every config row `doctor` prints is: from a project, the file can\n * be its own or the global one it inherits.\n */\nfunction toUnreadableConfigIssue(failure: ConfigLoadError): ContentIssue {\n return {\n severity: \"error\",\n file: `${scopeLabel(failure.scope)}'s ${displayDir(failure.configPath)}`,\n message: `${CONFIG_UNREADABLE}: ${failure.reason}`,\n };\n}\n\nasync function countExistingConfigs(projectDir: string): Promise<number> {\n const present = await Promise.all(\n configDirsInPlay(projectDir).map((dir) => fileExists(getInstalledConfigPath(dir))),\n );\n return present.filter(Boolean).length;\n}\n\n/**\n * Validates the marketplace this installation reads from when it is local, plus the current\n * directory when that is itself a skills source repository — that repository is the content a\n * marketplace author runs this against, and it is not the source they read skills from.\n * A remote marketplace is recorded as skipped rather than fetched.\n *\n * Each one is validated as the reader's own or as someone else's — see {@link readerFor}.\n */\nexport async function validateRegisteredSources(projectDir: string): Promise<ContentValidation> {\n // DEGRADE on an unreadable config. This pass declares `readsConfig: true`, so `doctor` stands it\n // down before it runs whenever the config check has already reported the file — and if it is\n // reached anyway, `safeCheck` turns the throw into a failed row rather than an aborted run. A\n // command whose job is naming what is wrong here must survive the thing it is naming.\n const primary = await resolvePrimarySourceEntry(projectDir);\n const registered = [primary];\n const remote = registered.filter((source) => !isLocalSource(source.url));\n const local = await localSourcesToValidate(projectDir, registered);\n\n const outcomes = await Promise.all(\n local.map((source) => validateOneSource(source, readerFor(projectDir, source))),\n );\n\n return {\n count: local.length,\n issues: outcomes.flatMap((outcome) => outcome.issues),\n notes: [\n ...outcomes.map((outcome) => outcome.note),\n ...remote.map((source) => `${source.name} (${source.url}) — skipped (remote)`),\n ],\n };\n}\n\nasync function localSourcesToValidate(\n projectDir: string,\n registered: SourceEntry[],\n): Promise<SourceEntry[]> {\n const local = registered.filter((source) => isLocalSource(source.url));\n const alreadyCovered = local.some((source) => isCwdMarketplace(projectDir, source));\n\n if (alreadyCovered || !(await isSourceRepo(projectDir))) return local;\n\n return [...local, { name: CWD_SOURCE_NAME, url: projectDir }];\n}\n\n/** Whether this marketplace IS the directory the command ran in, however the config spells it. */\nfunction isCwdMarketplace(projectDir: string, source: SourceEntry): boolean {\n return path.resolve(projectDir, source.url) === projectDir;\n}\n\n/**\n * Where this layer decides what the reader's relationship to a marketplace is — the one place\n * that holds both the directory the command ran in and the path of each marketplace it validates.\n * The appended `CWD_SOURCE_NAME` entry answers `\"author\"` by construction, which is the whole of\n * why a marketplace author's own repository is judged the way they need it to be.\n */\nfunction readerFor(projectDir: string, source: SourceEntry): MarketplaceReader {\n return isCwdMarketplace(projectDir, source) ? \"author\" : \"consumer\";\n}\n\ntype SourceOutcome = { note: string; issues: ContentIssue[] };\n\nasync function validateOneSource(\n source: SourceEntry,\n reader: MarketplaceReader,\n): Promise<SourceOutcome> {\n const label = `${source.name} (${source.url})`;\n try {\n const result = await validateSource(source.url, reader);\n return { note: `${label} — ${plural(result.skillCount, \"skill\")}`, issues: result.issues };\n } catch (error) {\n return {\n note: `${label} — failed`,\n issues: [{ severity: \"error\", file: source.url, message: getErrorMessage(error) }],\n };\n }\n}\n\n/** Validates every installed plugin bundle in the global and project plugin directories. */\nexport async function validateInstalledPlugins(projectDir: string): Promise<ContentValidation> {\n const dirs = [\n getUserPluginsDir(),\n ...(isHomeDirectory(projectDir) ? [] : [getProjectPluginsDir(projectDir)]),\n ];\n return mergeValidations(await Promise.all(dirs.map(validatePluginsDirectory)));\n}\n\nasync function validatePluginsDirectory(pluginsDir: string): Promise<ContentValidation> {\n if (!(await directoryExists(pluginsDir))) return NOTHING_VALIDATED;\n\n if (await fileExists(getInstalledPluginsRegistryPath(pluginsDir))) {\n const registryValidation = await validateRegistryPlugins(pluginsDir);\n if (registryValidation !== undefined) return registryValidation;\n }\n\n const pluginDirs = await findPluginDirectories(pluginsDir);\n if (pluginDirs.length === 0) return NOTHING_VALIDATED;\n\n const { results } = await validateAllPlugins(pluginsDir);\n\n return {\n count: results.length,\n issues: results.flatMap(({ name, result }) => toIssues(name, result)),\n notes: [],\n };\n}\n\n/**\n * Validates the installs recorded in the plugins directory's `installed_plugins.json`\n * (claude CLI >=2.1.220 cache layout). Returns undefined when the registry records no\n * installs so the caller can fall back to the direct-children scan (older/manual layouts).\n */\nasync function validateRegistryPlugins(pluginsDir: string): Promise<ContentValidation | undefined> {\n let installs: ResolvedPlugin[];\n try {\n installs = await listRegisteredPluginInstalls(pluginsDir);\n } catch (error) {\n return {\n count: 0,\n issues: [\n {\n severity: \"error\",\n file: displayDir(getInstalledPluginsRegistryPath(pluginsDir)),\n message: getErrorMessage(error),\n },\n ],\n notes: [],\n };\n }\n\n if (installs.length === 0) return undefined;\n\n // A recorded installPath that no longer exists surfaces as an invalid plugin\n // via validatePlugin's structure check, not a crash.\n const results = await Promise.all(\n installs.map(async ({ pluginKey, installPath }) =>\n toIssues(pluginKey, await validatePlugin(installPath)),\n ),\n );\n\n return { count: installs.length, issues: results.flat(), notes: [] };\n}\n\nasync function findPluginDirectories(pluginsDir: string): Promise<string[]> {\n const entries = await listDirectories(pluginsDir);\n const checks = await Promise.all(\n entries.map(async (name) => ({\n name,\n isPlugin: await directoryExists(path.join(pluginsDir, name, PLUGIN_MANIFEST_DIR)),\n })),\n );\n return checks.filter((check) => check.isPlugin).map((check) => check.name);\n}\n\n/**\n * Validates the SKILL.md and metadata.yaml of every installed skill this installation owns, both\n * scopes.\n *\n * Ownership has to be asked because `~/.claude/skills/` is CLAUDE CODE's directory, shared with\n * everything else that installs a skill there — not this CLI's private space. Judging every\n * directory in it against this CLI's schema reported a skill some other tool put there as a fault\n * in the user's install, in a file they never wrote and cannot fix from here.\n *\n * Two claims make a directory this installation's, and either is enough:\n *\n * - **The configuration in play names its id.** Both configs a run reads, because both scopes are\n * walked. This is the claim that keeps `doctor` loud where it matters most: the provenance\n * marker lives INSIDE metadata.yaml, so a skill whose metadata is missing or unparseable — the\n * plainest breakage there is — can carry no marker to be recognised by.\n * - **The directory carries `forkedFrom`.** The marker this CLI stamps into every skill directory\n * it writes, and the same question `uninstall` asks before removing anything. It answers for the\n * skills a configuration has stopped naming, or never got the chance to.\n *\n * A directory neither claim reaches is not judged and not counted. It IS named — see\n * {@link foreignSkillNote}: a check that quietly walks past a directory is indistinguishable from\n * one that missed it.\n */\nexport async function validateInstalledSkills(projectDir: string): Promise<ContentValidation> {\n const configuredIds = await configuredSkillIds(projectDir);\n return mergeValidations(\n await Promise.all(\n installedDirs(projectDir, \"skillsDir\").map((dir) =>\n validateSkillsDirectory(dir, configuredIds),\n ),\n ),\n );\n}\n\n/** Every skill id the configs this run reads name, across both scopes and both install modes. */\nasync function configuredSkillIds(projectDir: string): Promise<ReadonlySet<string>> {\n const loaded = await Promise.all(\n configDirsInPlay(projectDir).map((dir) => loadInstalledConfig(dir)),\n );\n return new Set(loaded.flatMap(configuredIdsOf));\n}\n\nfunction configuredIdsOf(loaded: LoadedProjectConfig | null): string[] {\n if (!loaded) return [];\n return loaded.config.skills.map((skill) => skill.id);\n}\n\n/** Validates the frontmatter of every compiled agent file, both scopes. */\nexport async function validateInstalledAgents(projectDir: string): Promise<ContentValidation> {\n return mergeValidations(\n await Promise.all(installedDirs(projectDir, \"agentsDir\").map(validateAgentsDirectory)),\n );\n}\n\n/**\n * The directories to walk for an installed-content pass. At the home directory both\n * scopes resolve to the same place, so it is walked once instead of twice.\n */\nfunction installedDirs(projectDir: string, key: \"skillsDir\" | \"agentsDir\"): string[] {\n const global = resolveInstallPaths(projectDir, \"global\")[key];\n if (isHomeDirectory(projectDir)) return [global];\n return [global, resolveInstallPaths(projectDir, \"project\")[key]];\n}\n\n/** What an installed-content pass walked, named rather than validated. */\nexport type InstalledArtifacts = {\n /** Every skill directory this CLI can prove it wrote, both scopes, as display paths. */\n skills: string[];\n /** Every compiled agent file this CLI can prove it wrote, both scopes, as display paths. */\n agents: string[];\n};\n\n/**\n * The same two walks {@link validateInstalledSkills} and {@link validateInstalledAgents} count,\n * naming what belongs to this installation instead of judging it. `doctor` reports this when no\n * configuration exists to compare the installation against: there is nothing to validate the\n * files AGAINST, and naming them is the whole finding.\n *\n * Each walk applies the same ownership question its own pass asks, minus the half that needs a\n * config to answer — see {@link listSkillDirsWithOurProvenance} and\n * {@link listAgentFilesWithOurProvenance}. Both are the question the command this row sends the\n * reader to asks before it removes anything, so what is named here is what `uninstall` takes.\n */\nexport async function listInstalledArtifacts(projectDir: string): Promise<InstalledArtifacts> {\n const [skills, agents] = await Promise.all([\n listAcrossScopes(installedDirs(projectDir, \"skillsDir\"), listSkillDirsWithOurProvenance),\n listAcrossScopes(installedDirs(projectDir, \"agentsDir\"), listAgentFilesWithOurProvenance),\n ]);\n return { skills, agents };\n}\n\n/**\n * The compiled agent files in one tree that this CLI can prove it wrote.\n *\n * The agent axis's counterpart to {@link listSkillDirsWithOurProvenance}, and deliberately\n * `splitAgentsByProvenance` rather than a second reading of the same marker: `uninstall` decides\n * what to remove with no configuration by asking that function, so a listing built any other way\n * could offer a file it then refused. It did — every `*.md` in the directory was named here while\n * the remover took only the marked ones, so a hand-authored agent was offered by one screen and\n * declined by the next.\n *\n * A file that cannot be read carries no marker and is not listed, which is that function's own\n * rule: \"cannot prove it is ours\" and \"is not ours\" call for the same answer. Nothing goes\n * unmentioned either way — {@link validateInstalledAgents} walks every agent file whatever state\n * the config is in.\n */\nasync function listAgentFilesWithOurProvenance(agentsDir: string): Promise<string[]> {\n const { marked } = await splitAgentsByProvenance(agentsDir);\n return marked.map((name) => `${name}${AGENT_FILE_EXTENSION}`);\n}\n\n/**\n * The skill directories in one tree that this CLI can prove it wrote.\n *\n * With no configuration left to name an id, the provenance marker is the only claim a directory\n * can carry — and it is the claim `uninstall` reads before removing anything, so every directory\n * listed here is one that command would actually remove. Listing a directory it would refuse is\n * the CLI recommending what it then declines to do.\n *\n * The marker lives INSIDE `metadata.yaml`, so a directory whose metadata is missing or unreadable\n * can carry no marker and is not listed. That is deliberate rather than a gap: \"cannot prove it is\n * ours\" and \"is not ours\" call for the same answer — leave it alone — which is the rule\n * `splitAgentsByProvenance` already applies to compiled agents. Nothing goes unmentioned either\n * way: {@link validateInstalledSkills} runs whatever state the config is in, and names every\n * directory it stepped over.\n */\nasync function listSkillDirsWithOurProvenance(skillsDir: string): Promise<string[]> {\n const names = await listDirectories(skillsDir);\n const judged = await Promise.all(\n names.map(async (name) => ({ name, ours: await carriesOurProvenance(skillsDir, name) })),\n );\n return judged.filter((entry) => entry.ours).map((entry) => entry.name);\n}\n\nasync function listAcrossScopes(\n dirs: string[],\n listEntries: (dir: string) => Promise<string[]>,\n): Promise<string[]> {\n const perDir = await Promise.all(dirs.map((dir) => listDisplayPaths(dir, listEntries)));\n return perDir.flat();\n}\n\n/** One directory's entries as display paths, or nothing when the directory is absent. */\nasync function listDisplayPaths(\n dir: string,\n listEntries: (dir: string) => Promise<string[]>,\n): Promise<string[]> {\n if (!(await directoryExists(dir))) return [];\n const entries = await listEntries(dir);\n return entries.map((entry) => displayDir(path.join(dir, entry)));\n}\n\nasync function validateSkillsDirectory(\n skillsDir: string,\n configuredIds: ReadonlySet<string>,\n): Promise<ContentValidation> {\n if (!(await directoryExists(skillsDir))) return NOTHING_VALIDATED;\n\n const skillDirs = await listDirectories(skillsDir);\n if (skillDirs.length === 0) return NOTHING_VALIDATED;\n\n const judged = await Promise.all(\n skillDirs.map(async (name) => ({\n name,\n ours: await isOurSkillDirectory(skillsDir, name, configuredIds),\n })),\n );\n const [ours, foreign] = partition(judged, (entry) => entry.ours);\n\n const results = await Promise.all(\n ours.map(async ({ name }) => {\n const skillDir = path.join(skillsDir, name);\n return toIssues(displayDir(skillDir), await validateInstalledSkill(skillDir));\n }),\n );\n\n return {\n count: ours.length,\n issues: results.flat(),\n notes: foreign.map(({ name }) => foreignSkillNote(skillsDir, name)),\n };\n}\n\n/** Either claim this installation has on a skill directory — see {@link validateInstalledSkills}. */\nasync function isOurSkillDirectory(\n skillsDir: string,\n name: string,\n configuredIds: ReadonlySet<string>,\n): Promise<boolean> {\n if (configuredIds.has(name)) return true;\n return carriesOurProvenance(skillsDir, name);\n}\n\n/**\n * The claim a skill directory carries on its own, independent of any configuration: the\n * `forkedFrom` block the copier stamps into every directory this CLI writes. One definition,\n * because the union above and the no-config listing are the same judgement with and without its\n * other half — and `uninstall` decides what to remove by asking exactly this.\n */\nasync function carriesOurProvenance(skillsDir: string, name: string): Promise<boolean> {\n return (await readForkedFromMetadata(path.join(skillsDir, name))) !== null;\n}\n\n/**\n * A directory this pass declined to judge, named so the count and the directory listing do not\n * silently disagree. Not a warning: nothing here is wrong, and a reader sent to fix a skill they\n * did not install is worse off than one told plainly that it is not this CLI's to police.\n */\nfunction foreignSkillNote(skillsDir: string, name: string): string {\n return `${displayDir(path.join(skillsDir, name))} — not installed by this CLI and named by no configuration here: not validated`;\n}\n\nasync function validateAgentsDirectory(agentsDir: string): Promise<ContentValidation> {\n if (!(await directoryExists(agentsDir))) return NOTHING_VALIDATED;\n\n const agentFiles = await listAgentMdFiles(agentsDir);\n if (agentFiles.length === 0) return NOTHING_VALIDATED;\n\n const results = await Promise.all(\n agentFiles.map(async (fileName) => {\n const agentPath = path.join(agentsDir, fileName);\n return toIssues(displayDir(agentPath), await validateAgentFrontmatter(agentPath));\n }),\n );\n\n return { count: agentFiles.length, issues: results.flat(), notes: [] };\n}\n\nasync function validateInstalledSkill(skillDir: string): Promise<ValidationResult> {\n const skillMd = await validateSkillFile(\n skillDir,\n STANDARD_FILES.SKILL_MD,\n validateSkillFrontmatter,\n );\n const metadata = await validateSkillFile(\n skillDir,\n STANDARD_FILES.METADATA_YAML,\n validateInstalledSkillMetadata,\n );\n\n return mergeValidationResults([skillMd, metadata]);\n}\n\n/** One of an installed skill's files judged by `validate`, or the error of its absence. */\nasync function validateSkillFile(\n skillDir: string,\n fileName: string,\n validate: (filePath: string) => Promise<ValidationResult>,\n): Promise<ValidationResult> {\n const filePath = path.join(skillDir, fileName);\n if (!(await fileExists(filePath))) return invalidResult(`Missing ${fileName}`);\n return validate(filePath);\n}\n\nasync function validateInstalledSkillMetadata(metadataPath: string): Promise<ValidationResult> {\n // Same judgment `compile` refuses on and local-skill discovery skips on: a file\n // that describes no skill is reported here as the error it is. The strict\n // published-skill checks below are layered on top of that verdict, never against\n // it — doctor reports what the other two passes refuse, and then some.\n const read = await readSkillMetadata(metadataPath);\n if (!read.usable) {\n return invalidResult(`${STANDARD_FILES.METADATA_YAML}: ${read.reason}`);\n }\n\n const metadata = read.metadata;\n const result = validateSkillMetadata(metadata);\n if (result.success) {\n return validResult();\n }\n\n // Over-length cliDescription is advisory — only hard schema violations invalidate the skill\n const { errors, warnings } = splitMetadataValidationIssues(result.error, metadata);\n return {\n valid: errors.length === 0,\n errors: errors.map((e) => `${STANDARD_FILES.METADATA_YAML}: ${e}`),\n warnings: warnings.map((w) => `${STANDARD_FILES.METADATA_YAML}: ${w}`),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAOA,SAAQ;AACf,OAAOC,WAAU;;;ACDjB,OAAO,UAAU;AAEjB,SAAS,SAAS,iBAAiB;AACnC,OAAkB;AAoElB,eAAsB,aAAa,KAA+B;AAIhE,QAAM,eAAe,MAAM,qBAAqB,GAAG;AACnD,SAAO,gBAAgB,KAAK,KAAK,KAAK,cAAc,aAAa,eAAe,CAAC;AACnF;AAGO,SAAS,YAAY,KAAsB;AAChD,SAAO,cAAc,KAAK,GAAG;AAC/B;AAMO,SAAS,mBAAmB,aAAsB,SAA0C;AACjG,MAAI,CAAC,SAAS,WAAW,EAAG,QAAO,CAAC;AAEpC,SAAO,OAAO,KAAK,WAAW,EAC3B,OAAO,WAAW,EAClB,IAAI,CAAC,SAAS;AAAA,IACb,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS,QAAQ,GAAG;AAAA,EACtB,EAAE;AACN;AAQO,SAAS,2BACd,SACA,SACA,SACyB;AACzB,MAAI,YAAY,QAAS,QAAO,CAAC;AACjC,SAAO;AAAA,IACL;AAAA,MACE,UAAU;AAAA,MACV,MAAM;AAAA,MACN,SAAS,mBAAmB,OAAO,8BAA8B,OAAO;AAAA,IAC1E;AAAA,EACF;AACF;AAOA,eAAe,kBACbC,YACA,kBACA,UACkC;AAClC,QAAM,UAAU,KAAK,SAAS,QAAQ;AACtC,QAAM,iBAAiB,KAAK,KAAK,kBAAkB,UAAU,eAAe,QAAQ;AAEpF,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,KAAK,KAAKA,YAAW,UAAU,eAAe,QAAQ,CAAC;AACtF,UAAM,cAAc,iBAAiB,SAAS,cAAc;AAE5D,QAAI,gBAAgB,MAAM;AACxB,aAAO;AAAA,QACL;AAAA,UACE,UAAU;AAAA,UACV,MAAM;AAAA,UACN,SAAS,iCAAiC,OAAO,yBAAyB,eAAe,QAAQ;AAAA,QACnG;AAAA,MACF;AAAA,IACF;AAEA,WAAO,2BAA2B,YAAY,MAAM,gBAAgB,OAAO;AAAA,EAC7E,SAAS,OAAO;AACd,WAAO;AAAA,MACL;AAAA,QACE,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS,iCAAiC,OAAO,MAAM,gBAAgB,KAAK,CAAC;AAAA,MAC/E;AAAA,IACF;AAAA,EACF;AACF;AASO,SAAS,uBACd,aACA,cACAA,YACyB;AACzB,QAAM,kBAAkB,CAAC,GAAG,WAAW,EACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,IAAI,GAAG,CAAC,EACtC,IAAI,CAAC,SAAS;AAAA,IACb,UAAU;AAAA,IACV,MAAM,KAAK,KAAKA,YAAW,GAAG;AAAA,IAC9B,SAAS,WAAW,eAAe,aAAa,+BAA0B,eAAe,QAAQ;AAAA,EACnG,EAAE;AAEJ,QAAM,iBAAiB,CAAC,GAAG,YAAY,EACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,IAAI,GAAG,CAAC,EACrC,IAAI,CAAC,SAAS;AAAA,IACb,UAAU;AAAA,IACV,MAAM,KAAK,KAAKA,YAAW,GAAG;AAAA,IAC9B,SAAS,WAAW,eAAe,QAAQ,+BAA0B,eAAe,aAAa;AAAA,EACnG,EAAE;AAEJ,SAAO,CAAC,GAAG,iBAAiB,GAAG,cAAc;AAC/C;AAkBA,eAAsB,eACpB,YACA,SAA4B,UACK;AACjC,QAAM,eAAe,KAAK,WAAW,UAAU,IAAI,aAAa,KAAK,QAAQ,UAAU;AAEvF,MAAI,CAAE,MAAM,gBAAgB,YAAY,GAAI;AAC1C,WAAO;AAAA,MACL,CAAC,EAAE,UAAU,SAAS,MAAM,cAAc,SAAS,uCAAuC,CAAC;AAAA,MAC3F;AAAA,IACF;AAAA,EACF;AAKA,QAAM,sBAAsB,MAAM,qBAAqB,YAAY;AACnE,QAAM,mBAAmB,qBAAqB,aAAa;AAC3D,QAAMA,aAAY,KAAK,KAAK,cAAc,gBAAgB;AAE1D,MAAI,CAAE,MAAM,gBAAgBA,UAAS,GAAI;AACvC,WAAO;AAAA,MACL,CAAC,EAAE,UAAU,SAAS,MAAMA,YAAW,SAAS,kCAAkC,CAAC;AAAA,MACnF;AAAA,IACF;AAAA,EACF;AAGA,QAAM,eAAe,MAAM,KAAK,MAAM,eAAe,QAAQ,IAAIA,UAAS;AAC1E,QAAM,gBAAgB,MAAM,KAAK,MAAM,eAAe,aAAa,IAAIA,UAAS;AAEhF,QAAM,cAAc,IAAI,IAAI,aAAa,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC;AACpE,QAAM,eAAe,IAAI,IAAI,cAAc,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC;AAEtE,QAAM,aAAa,uBAAuB,aAAa,cAAcA,UAAS;AAI9E,QAAM,qBAAqB,cAAc,OAAO,CAAC,MAAM,YAAY,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC;AACvF,QAAM,cAAc,MAAM,qBAAqBA,YAAW,kBAAkB,kBAAkB;AAG9F,QAAM,uBAAuB,MAAM,qBAAqB,cAAc,MAAM;AAM5E,QAAM,cAAc,MAAM,QAAQ,IAAI;AAAA,IACpC,eAAe,YAAY;AAAA,IAC3B,eAAe,YAAY;AAAA,IAC3B,oBAAoB,YAAY;AAAA,EAClC,CAAC;AAED,SAAO;AAAA,IACL,CAAC,GAAG,YAAY,GAAG,aAAa,GAAG,sBAAsB,GAAG,YAAY,KAAK,CAAC;AAAA,IAC9E,mBAAmB;AAAA,EACrB;AACF;AAGA,eAAe,qBACbA,YACA,kBACA,eACkC;AAClC,QAAM,SAAkC,CAAC;AACzC,aAAW,gBAAgB,eAAe;AACxC,WAAO,KAAK,GAAI,MAAM,iBAAiBA,YAAW,kBAAkB,YAAY,CAAE;AAAA,EACpF;AACA,SAAO;AACT;AAQA,SAAS,iBAAiB,OAAwB;AAChD,SAAO,yBAAyB,gBAAgB,KAAK,CAAC;AACxD;AAQA,eAAe,iBACbA,YACA,kBACA,cACkC;AAClC,QAAM,UAAU,KAAK,KAAK,kBAAkB,YAAY;AAExD,MAAI;AACJ,MAAI;AACF,kBAAc,UAAU,MAAM,SAAS,KAAK,KAAKA,YAAW,YAAY,CAAC,CAAC;AAAA,EAC5E,SAAS,OAAO;AACd,WAAO,CAAC,EAAE,UAAU,SAAS,MAAM,SAAS,SAAS,iBAAiB,KAAK,EAAE,CAAC;AAAA,EAChF;AAEA,SAAO;AAAA,IACL,GAAG,mBAAmB,aAAa,OAAO;AAAA,IAC1C,GAAG,oBAAoB,aAAa,OAAO;AAAA;AAAA,IAE3C,GAAI,MAAM,kBAAkBA,YAAW,kBAAkB,KAAK,QAAQ,YAAY,CAAC;AAAA,EACrF;AACF;AAMA,SAAS,oBAAoB,aAAsB,SAA0C;AAC3F,QAAM,SAAS,sBAAsB,WAAW;AAChD,MAAI,OAAO,QAAS,QAAO,CAAC;AAE5B,QAAM,EAAE,QAAQ,SAAS,IAAI,8BAA8B,OAAO,OAAO,WAAW;AACpF,SAAO;AAAA,IACL,GAAG,OAAO,IAAI,CAAC,aAAa,EAAE,UAAU,SAAkB,MAAM,SAAS,QAAQ,EAAE;AAAA,IACnF,GAAG,SAAS,IAAI,CAAC,aAAa,EAAE,UAAU,WAAoB,MAAM,SAAS,QAAQ,EAAE;AAAA,EACzF;AACF;AAMA,IAAM,4BAA4B,KAAK,KAAK,qBAAqB,gBAAgB;AAOjF,IAAM,6BAA6B;AAAA,EACjC,QAAQ;AAAA,EACR,UAAU;AACZ;AAUA,eAAe,qBACb,cACA,QACkC;AAClC,MAAI;AACF,UAAM,2BAA2B,EAAE,YAAY,cAAc,kBAAkB,KAAK,CAAC;AACrF,WAAO,mBAAmB,MAAM,EAAE;AAAA,MAAI,CAAC,gBACrC,cAAc,aAAa,cAAc,MAAM;AAAA,IACjD;AAAA,EACF,SAAS,OAAO;AACd,WAAO,CAAC,kBAAkB,OAAO,MAAM,CAAC;AAAA,EAC1C;AACF;AAiBA,SAAS,kBAAkB,OAAgB,QAAkD;AAC3F,MAAI,iBAAiB,kCAAkC;AACrD,WAAO;AAAA,MACL,UAAU,2BAA2B,MAAM;AAAA,MAC3C,MAAM;AAAA,MACN,SAAS,gBAAgB,KAAK;AAAA,IAChC;AAAA,EACF;AAEA,MAAI,iBAAiB,6BAA6B;AAChD,WAAO;AAAA,MACL,UAAU;AAAA,MACV,MAAM;AAAA,MACN,SAAS,gBAAgB,KAAK;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS,wEAAwE,gBAAgB,KAAK,CAAC;AAAA,EACzG;AACF;AAOA,IAAM,mBAAmB;AAkBzB,SAAS,kBAAkB,SAA+C;AACxE,UAAQ,SAAS;AAAA,IACf,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,SAAS;AACP,YAAM,aAAoB;AAC1B,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAWA,SAAS,cACP,aACA,iBACA,QACuB;AACvB,QAAM,OAAO,kBAAkB,YAAY,OAAO;AAElD,MAAI,WAAW,cAAc,YAAY,YAAY,wBAAwB;AAC3E,WAAO;AAAA,MACL,UAAU;AAAA,MACV;AAAA,MACA,SAAS,2BAA2B,iBAAiB,YAAY,OAAO;AAAA,IAC1E;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU,YAAY;AAAA,IACtB;AAAA,IACA,SAAS,YAAY;AAAA,EACvB;AACF;AAQA,SAAS,2BAA2B,iBAAyB,SAAyB;AACpF,SAAO,gBAAgB,eAAe,MAAM,OAAO;AACrD;AAMA,eAAe,eAAe,cAAwD;AACpF,QAAM,YAAY,KAAK,KAAK,cAAc,KAAK,MAAM;AACrD,MAAI,CAAE,MAAM,gBAAgB,SAAS,EAAI,QAAO,CAAC;AAEjD,QAAM,CAAC,iBAAiB,YAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,IACxD,kBAAkB;AAAA,MAChB,SAAS;AAAA,MACT,YAAY,KAAK;AAAA,MACjB,SAAS,gBAAgB,eAAe,aAAa;AAAA,MACrD,QAAQ;AAAA,IACV,CAAC;AAAA,IACD,kBAAkB;AAAA,MAChB,SAAS;AAAA,MACT,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK,eAAe,WAAW;AAAA,MACxC,QAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AACD,SAAO,CAAC,GAAG,iBAAiB,GAAG,YAAY;AAC7C;AAQA,eAAe,eAAe,cAAwD;AACpF,QAAM,YAAY,KAAK,KAAK,cAAc,KAAK,MAAM;AACrD,MAAI,CAAE,MAAM,gBAAgB,SAAS,EAAI,QAAO,CAAC;AAEjD,SAAO,kBAAkB;AAAA,IACvB,SAAS;AAAA,IACT,YAAY,KAAK;AAAA,IACjB,SAAS,MAAM,eAAe,mBAAmB;AAAA,IACjD,QAAQ;AAAA,EACV,CAAC;AACH;AAOA,eAAe,oBAAoB,cAAwD;AACzF,QAAM,UAAU,MAAM,QAAQ,IAAI;AAAA,IAChC,iBAAiB,cAAc,uBAAuB,yBAAyB;AAAA,IAC/E,iBAAiB,cAAc,kBAAkB,oBAAoB;AAAA,IACrE,iBAAiB,cAAc,kBAAkB,kBAAkB;AAAA,EACrE,CAAC;AACD,SAAO,QAAQ,KAAK;AACtB;AAkBA,eAAe,kBAAkB,MAAsD;AACrF,QAAM,SAAkC,CAAC;AACzC,QAAM,QAAQ,MAAM,KAAK,KAAK,SAAS,KAAK,OAAO;AAEnD,aAAW,WAAW,OAAO;AAC3B,WAAO,KAAK,GAAI,MAAM,iBAAiB,MAAM,OAAO,CAAE;AAAA,EACxD;AACA,SAAO;AACT;AAMA,eAAe,iBACb,MACA,SACkC;AAClC,QAAM,cAAc,KAAK,KAAK,KAAK,YAAY,OAAO;AAEtD,MAAI;AACJ,MAAI;AACF,aAAS,UAAU,MAAM,SAAS,KAAK,KAAK,KAAK,SAAS,OAAO,CAAC,CAAC;AAAA,EACrE,SAAS,OAAO;AACd,WAAO,CAAC,EAAE,UAAU,SAAS,MAAM,aAAa,SAAS,iBAAiB,KAAK,EAAE,CAAC;AAAA,EACpF;AAEA,QAAM,SAAS,KAAK,OAAO,UAAU,MAAM;AAC3C,MAAI,OAAO,QAAS,QAAO,CAAC;AAE5B,SAAO,gBAAgB,OAAO,KAAK,EAAE,IAAI,CAAC,aAAa;AAAA,IACrD,UAAU;AAAA,IACV,MAAM;AAAA,IACN;AAAA,EACF,EAAE;AACJ;AAaA,eAAe,iBACb,cACA,eACA,QACkC;AAClC,QAAM,UAAU,KAAK,KAAK,cAAc,aAAa;AACrD,MAAI,CAAE,MAAM,WAAW,OAAO,EAAI,QAAO,CAAC;AAE1C,MAAI;AACF,UAAM,SAAS,MAAM,WAAW,SAAS,MAAM;AAC/C,QAAI,WAAW,MAAM;AACnB,aAAO,CAAC,EAAE,UAAU,SAAS,MAAM,eAAe,SAAS,kBAAkB,CAAC;AAAA,IAChF;AACA,WAAO,CAAC;AAAA,EACV,SAAS,OAAO;AACd,QAAI,iBAAiB,0BAA0B;AAC7C,aAAO,CAAC,EAAE,UAAU,SAAS,MAAM,eAAe,SAAS,+BAA+B,CAAC;AAAA,IAC7F;AACA,WAAO;AAAA,MACL,EAAE,UAAU,SAAS,MAAM,eAAe,SAAS,gBAAgB,eAAe,KAAK,EAAE;AAAA,IAC3F;AAAA,EACF;AACF;AAMA,SAAS,gBAAgB,eAAuB,OAAwB;AACtE,QAAM,MAAM,gBAAgB,KAAK;AACjC,QAAM,WAAW,IAAI,QAAQ,0CAA0C,EAAE;AACzE,SAAO,kBAAkB,aAAa,KAAK,QAAQ;AACrD;AAEA,SAAS,YAAY,QAAiC,YAA4C;AAChG,QAAM,aAAa,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO,EAAE;AAChE,QAAM,eAAe,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,SAAS,EAAE;AACpE,SAAO,EAAE,QAAQ,YAAY,YAAY,aAAa;AACxD;;;AC3oBA,OAAO,QAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,iBAAiB;AAsC1B,IAAM,kBAAkB;AAGxB,IAAM,uBAAuB;AAoB7B,IAAM,oBAAuC,EAAE,OAAO,GAAG,QAAQ,CAAC,GAAG,OAAO,CAAC,EAAE;AAE/E,SAAS,iBAAiB,OAA+C;AACvE,SAAO,MAAM;AAAA,IACX,CAAC,KAAK,UAAU;AAAA,MACd,OAAO,IAAI,QAAQ,KAAK;AAAA,MACxB,QAAQ,CAAC,GAAG,IAAI,QAAQ,GAAG,KAAK,MAAM;AAAA,MACtC,OAAO,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,KAAK;AAAA,IACrC;AAAA,IACA;AAAA,EACF;AACF;AAGA,SAAS,WAAW,cAA8B;AAChD,QAAM,OAAO,GAAG,QAAQ;AACxB,MAAI,iBAAiB,KAAM,QAAO;AAClC,MAAI,aAAa,WAAW,OAAOC,MAAK,GAAG,GAAG;AAC5C,WAAO,IAAIA,MAAK,GAAG,GAAGA,MAAK,SAAS,MAAM,YAAY,CAAC;AAAA,EACzD;AACA,SAAO;AACT;AAEA,SAAS,SAAS,MAAc,QAA0C;AACxE,SAAO;AAAA,IACL,GAAG,OAAO,OAAO,IAAI,CAAC,aAAa,EAAE,UAAU,SAAkB,MAAM,QAAQ,EAAE;AAAA,IACjF,GAAG,OAAO,SAAS,IAAI,CAAC,aAAa,EAAE,UAAU,WAAoB,MAAM,QAAQ,EAAE;AAAA,EACvF;AACF;AAGA,IAAM,oBAAoB;AAc1B,eAAsB,0BAA0B,YAAgD;AAC9F,QAAM,CAAC,SAAS,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC5C,qBAAqB,UAAU;AAAA,IAC/B,uBAAuB,UAAU;AAAA,EACnC,CAAC;AAED,SAAO,EAAE,OAAO,SAAS,QAAQ,SAAS,IAAI,uBAAuB,GAAG,OAAO,CAAC,EAAE;AACpF;AAMA,SAAS,wBAAwB,SAAwC;AACvE,SAAO;AAAA,IACL,UAAU;AAAA,IACV,MAAM,GAAG,WAAW,QAAQ,KAAK,CAAC,MAAM,WAAW,QAAQ,UAAU,CAAC;AAAA,IACtE,SAAS,GAAG,iBAAiB,KAAK,QAAQ,MAAM;AAAA,EAClD;AACF;AAEA,eAAe,qBAAqB,YAAqC;AACvE,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,iBAAiB,UAAU,EAAE,IAAI,CAAC,QAAQ,WAAW,uBAAuB,GAAG,CAAC,CAAC;AAAA,EACnF;AACA,SAAO,QAAQ,OAAO,OAAO,EAAE;AACjC;AAUA,eAAsB,0BAA0B,YAAgD;AAK9F,QAAM,UAAU,MAAM,0BAA0B,UAAU;AAC1D,QAAM,aAAa,CAAC,OAAO;AAC3B,QAAM,SAAS,WAAW,OAAO,CAAC,WAAW,CAAC,cAAc,OAAO,GAAG,CAAC;AACvE,QAAM,QAAQ,MAAM,uBAAuB,YAAY,UAAU;AAEjE,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,MAAM,IAAI,CAAC,WAAW,kBAAkB,QAAQ,UAAU,YAAY,MAAM,CAAC,CAAC;AAAA,EAChF;AAEA,SAAO;AAAA,IACL,OAAO,MAAM;AAAA,IACb,QAAQ,SAAS,QAAQ,CAAC,YAAY,QAAQ,MAAM;AAAA,IACpD,OAAO;AAAA,MACL,GAAG,SAAS,IAAI,CAAC,YAAY,QAAQ,IAAI;AAAA,MACzC,GAAG,OAAO,IAAI,CAAC,WAAW,GAAG,OAAO,IAAI,KAAK,OAAO,GAAG,2BAAsB;AAAA,IAC/E;AAAA,EACF;AACF;AAEA,eAAe,uBACb,YACA,YACwB;AACxB,QAAM,QAAQ,WAAW,OAAO,CAAC,WAAW,cAAc,OAAO,GAAG,CAAC;AACrE,QAAM,iBAAiB,MAAM,KAAK,CAAC,WAAW,iBAAiB,YAAY,MAAM,CAAC;AAElF,MAAI,kBAAkB,CAAE,MAAM,aAAa,UAAU,EAAI,QAAO;AAEhE,SAAO,CAAC,GAAG,OAAO,EAAE,MAAM,iBAAiB,KAAK,WAAW,CAAC;AAC9D;AAGA,SAAS,iBAAiB,YAAoB,QAA8B;AAC1E,SAAOA,MAAK,QAAQ,YAAY,OAAO,GAAG,MAAM;AAClD;AAQA,SAAS,UAAU,YAAoB,QAAwC;AAC7E,SAAO,iBAAiB,YAAY,MAAM,IAAI,WAAW;AAC3D;AAIA,eAAe,kBACb,QACA,QACwB;AACxB,QAAM,QAAQ,GAAG,OAAO,IAAI,KAAK,OAAO,GAAG;AAC3C,MAAI;AACF,UAAM,SAAS,MAAM,eAAe,OAAO,KAAK,MAAM;AACtD,WAAO,EAAE,MAAM,GAAG,KAAK,WAAM,OAAO,OAAO,YAAY,OAAO,CAAC,IAAI,QAAQ,OAAO,OAAO;AAAA,EAC3F,SAAS,OAAO;AACd,WAAO;AAAA,MACL,MAAM,GAAG,KAAK;AAAA,MACd,QAAQ,CAAC,EAAE,UAAU,SAAS,MAAM,OAAO,KAAK,SAAS,gBAAgB,KAAK,EAAE,CAAC;AAAA,IACnF;AAAA,EACF;AACF;AAGA,eAAsB,yBAAyB,YAAgD;AAC7F,QAAM,OAAO;AAAA,IACX,kBAAkB;AAAA,IAClB,GAAI,gBAAgB,UAAU,IAAI,CAAC,IAAI,CAAC,qBAAqB,UAAU,CAAC;AAAA,EAC1E;AACA,SAAO,iBAAiB,MAAM,QAAQ,IAAI,KAAK,IAAI,wBAAwB,CAAC,CAAC;AAC/E;AAEA,eAAe,yBAAyB,YAAgD;AACtF,MAAI,CAAE,MAAM,gBAAgB,UAAU,EAAI,QAAO;AAEjD,MAAI,MAAM,WAAW,gCAAgC,UAAU,CAAC,GAAG;AACjE,UAAM,qBAAqB,MAAM,wBAAwB,UAAU;AACnE,QAAI,uBAAuB,OAAW,QAAO;AAAA,EAC/C;AAEA,QAAM,aAAa,MAAM,sBAAsB,UAAU;AACzD,MAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,QAAM,EAAE,QAAQ,IAAI,MAAM,mBAAmB,UAAU;AAEvD,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ,QAAQ,CAAC,EAAE,MAAM,OAAO,MAAM,SAAS,MAAM,MAAM,CAAC;AAAA,IACpE,OAAO,CAAC;AAAA,EACV;AACF;AAOA,eAAe,wBAAwB,YAA4D;AACjG,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,6BAA6B,UAAU;AAAA,EAC1D,SAAS,OAAO;AACd,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN;AAAA,UACE,UAAU;AAAA,UACV,MAAM,WAAW,gCAAgC,UAAU,CAAC;AAAA,UAC5D,SAAS,gBAAgB,KAAK;AAAA,QAChC;AAAA,MACF;AAAA,MACA,OAAO,CAAC;AAAA,IACV;AAAA,EACF;AAEA,MAAI,SAAS,WAAW,EAAG,QAAO;AAIlC,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,SAAS;AAAA,MAAI,OAAO,EAAE,WAAW,YAAY,MAC3C,SAAS,WAAW,MAAM,eAAe,WAAW,CAAC;AAAA,IACvD;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,SAAS,QAAQ,QAAQ,QAAQ,KAAK,GAAG,OAAO,CAAC,EAAE;AACrE;AAEA,eAAe,sBAAsB,YAAuC;AAC1E,QAAM,UAAU,MAAM,gBAAgB,UAAU;AAChD,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B,QAAQ,IAAI,OAAO,UAAU;AAAA,MAC3B;AAAA,MACA,UAAU,MAAM,gBAAgBA,MAAK,KAAK,YAAY,MAAM,mBAAmB,CAAC;AAAA,IAClF,EAAE;AAAA,EACJ;AACA,SAAO,OAAO,OAAO,CAAC,UAAU,MAAM,QAAQ,EAAE,IAAI,CAAC,UAAU,MAAM,IAAI;AAC3E;AAyBA,eAAsB,wBAAwB,YAAgD;AAC5F,QAAM,gBAAgB,MAAM,mBAAmB,UAAU;AACzD,SAAO;AAAA,IACL,MAAM,QAAQ;AAAA,MACZ,cAAc,YAAY,WAAW,EAAE;AAAA,QAAI,CAAC,QAC1C,wBAAwB,KAAK,aAAa;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AACF;AAGA,eAAe,mBAAmB,YAAkD;AAClF,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B,iBAAiB,UAAU,EAAE,IAAI,CAAC,QAAQ,oBAAoB,GAAG,CAAC;AAAA,EACpE;AACA,SAAO,IAAI,IAAI,OAAO,QAAQ,eAAe,CAAC;AAChD;AAEA,SAAS,gBAAgB,QAA8C;AACrE,MAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,SAAO,OAAO,OAAO,OAAO,IAAI,CAAC,UAAU,MAAM,EAAE;AACrD;AAGA,eAAsB,wBAAwB,YAAgD;AAC5F,SAAO;AAAA,IACL,MAAM,QAAQ,IAAI,cAAc,YAAY,WAAW,EAAE,IAAI,uBAAuB,CAAC;AAAA,EACvF;AACF;AAMA,SAAS,cAAc,YAAoB,KAA0C;AACnF,QAAM,SAAS,oBAAoB,YAAY,QAAQ,EAAE,GAAG;AAC5D,MAAI,gBAAgB,UAAU,EAAG,QAAO,CAAC,MAAM;AAC/C,SAAO,CAAC,QAAQ,oBAAoB,YAAY,SAAS,EAAE,GAAG,CAAC;AACjE;AAqBA,eAAsB,uBAAuB,YAAiD;AAC5F,QAAM,CAAC,QAAQ,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,IACzC,iBAAiB,cAAc,YAAY,WAAW,GAAG,8BAA8B;AAAA,IACvF,iBAAiB,cAAc,YAAY,WAAW,GAAG,+BAA+B;AAAA,EAC1F,CAAC;AACD,SAAO,EAAE,QAAQ,OAAO;AAC1B;AAiBA,eAAe,gCAAgC,WAAsC;AACnF,QAAM,EAAE,OAAO,IAAI,MAAM,wBAAwB,SAAS;AAC1D,SAAO,OAAO,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,oBAAoB,EAAE;AAC9D;AAiBA,eAAe,+BAA+BC,YAAsC;AAClF,QAAM,QAAQ,MAAM,gBAAgBA,UAAS;AAC7C,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B,MAAM,IAAI,OAAO,UAAU,EAAE,MAAM,MAAM,MAAM,qBAAqBA,YAAW,IAAI,EAAE,EAAE;AAAA,EACzF;AACA,SAAO,OAAO,OAAO,CAAC,UAAU,MAAM,IAAI,EAAE,IAAI,CAAC,UAAU,MAAM,IAAI;AACvE;AAEA,eAAe,iBACb,MACA,aACmB;AACnB,QAAM,SAAS,MAAM,QAAQ,IAAI,KAAK,IAAI,CAAC,QAAQ,iBAAiB,KAAK,WAAW,CAAC,CAAC;AACtF,SAAO,OAAO,KAAK;AACrB;AAGA,eAAe,iBACb,KACA,aACmB;AACnB,MAAI,CAAE,MAAM,gBAAgB,GAAG,EAAI,QAAO,CAAC;AAC3C,QAAM,UAAU,MAAM,YAAY,GAAG;AACrC,SAAO,QAAQ,IAAI,CAAC,UAAU,WAAWD,MAAK,KAAK,KAAK,KAAK,CAAC,CAAC;AACjE;AAEA,eAAe,wBACbC,YACA,eAC4B;AAC5B,MAAI,CAAE,MAAM,gBAAgBA,UAAS,EAAI,QAAO;AAEhD,QAAM,YAAY,MAAM,gBAAgBA,UAAS;AACjD,MAAI,UAAU,WAAW,EAAG,QAAO;AAEnC,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B,UAAU,IAAI,OAAO,UAAU;AAAA,MAC7B;AAAA,MACA,MAAM,MAAM,oBAAoBA,YAAW,MAAM,aAAa;AAAA,IAChE,EAAE;AAAA,EACJ;AACA,QAAM,CAAC,MAAM,OAAO,IAAI,UAAU,QAAQ,CAAC,UAAU,MAAM,IAAI;AAE/D,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,KAAK,IAAI,OAAO,EAAE,KAAK,MAAM;AAC3B,YAAM,WAAWD,MAAK,KAAKC,YAAW,IAAI;AAC1C,aAAO,SAAS,WAAW,QAAQ,GAAG,MAAM,uBAAuB,QAAQ,CAAC;AAAA,IAC9E,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,OAAO,KAAK;AAAA,IACZ,QAAQ,QAAQ,KAAK;AAAA,IACrB,OAAO,QAAQ,IAAI,CAAC,EAAE,KAAK,MAAM,iBAAiBA,YAAW,IAAI,CAAC;AAAA,EACpE;AACF;AAGA,eAAe,oBACbA,YACA,MACA,eACkB;AAClB,MAAI,cAAc,IAAI,IAAI,EAAG,QAAO;AACpC,SAAO,qBAAqBA,YAAW,IAAI;AAC7C;AAQA,eAAe,qBAAqBA,YAAmB,MAAgC;AACrF,SAAQ,MAAM,uBAAuBD,MAAK,KAAKC,YAAW,IAAI,CAAC,MAAO;AACxE;AAOA,SAAS,iBAAiBA,YAAmB,MAAsB;AACjE,SAAO,GAAG,WAAWD,MAAK,KAAKC,YAAW,IAAI,CAAC,CAAC;AAClD;AAEA,eAAe,wBAAwB,WAA+C;AACpF,MAAI,CAAE,MAAM,gBAAgB,SAAS,EAAI,QAAO;AAEhD,QAAM,aAAa,MAAM,iBAAiB,SAAS;AACnD,MAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,WAAW,IAAI,OAAO,aAAa;AACjC,YAAM,YAAYD,MAAK,KAAK,WAAW,QAAQ;AAC/C,aAAO,SAAS,WAAW,SAAS,GAAG,MAAM,yBAAyB,SAAS,CAAC;AAAA,IAClF,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,OAAO,WAAW,QAAQ,QAAQ,QAAQ,KAAK,GAAG,OAAO,CAAC,EAAE;AACvE;AAEA,eAAe,uBAAuB,UAA6C;AACjF,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,IACA,eAAe;AAAA,IACf;AAAA,EACF;AACA,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA,eAAe;AAAA,IACf;AAAA,EACF;AAEA,SAAO,uBAAuB,CAAC,SAAS,QAAQ,CAAC;AACnD;AAGA,eAAe,kBACb,UACA,UACA,UAC2B;AAC3B,QAAM,WAAWA,MAAK,KAAK,UAAU,QAAQ;AAC7C,MAAI,CAAE,MAAM,WAAW,QAAQ,EAAI,QAAO,cAAc,WAAW,QAAQ,EAAE;AAC7E,SAAO,SAAS,QAAQ;AAC1B;AAEA,eAAe,+BAA+B,cAAiD;AAK7F,QAAM,OAAO,MAAM,kBAAkB,YAAY;AACjD,MAAI,CAAC,KAAK,QAAQ;AAChB,WAAO,cAAc,GAAG,eAAe,aAAa,KAAK,KAAK,MAAM,EAAE;AAAA,EACxE;AAEA,QAAM,WAAW,KAAK;AACtB,QAAM,SAAS,sBAAsB,QAAQ;AAC7C,MAAI,OAAO,SAAS;AAClB,WAAO,YAAY;AAAA,EACrB;AAGA,QAAM,EAAE,QAAQ,SAAS,IAAI,8BAA8B,OAAO,OAAO,QAAQ;AACjF,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB,QAAQ,OAAO,IAAI,CAAC,MAAM,GAAG,eAAe,aAAa,KAAK,CAAC,EAAE;AAAA,IACjE,UAAU,SAAS,IAAI,CAAC,MAAM,GAAG,eAAe,aAAa,KAAK,CAAC,EAAE;AAAA,EACvE;AACF;;;AF5eA,SAAS,SAAS,cAAc;AAyDhC,eAAe,mBACb,UACA,YACsB;AACtB,MAAI,UAAU,QAAQ;AACpB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ,SAAS;AAAA,MACjB,WAAW,wBAAwB,SAAS,aAAa,YAAY,UAAU;AAAA,IACjF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,oBAAoB,UAAU;AACnD,MAAI,CAAC,OAAQ,QAAO,EAAE,MAAM,SAAS;AAErC,SAAO,kBAAkB,OAAO,MAAM,IAClC,EAAE,MAAM,oBAAoB,QAAQ,OAAO,OAAO,IAClD,EAAE,MAAM,UAAU,QAAQ,OAAO,QAAQ,WAAW,MAAM;AAChE;AAGA,SAAS,wBAAwB,UAAkB,YAA6B;AAC9E,SAAO,gBAAgB,QAAQ,KAAK,CAAC,gBAAgB,UAAU;AACjE;AAOA,SAAS,iBAAiB,OAAoB,YAAuC;AACnF,QAAM,YAAY,CAAC,YAAoB,iBAAiB,OAAO,YAAY,OAAO;AAClF,MAAI,MAAM,SAAS,UAAU;AAC3B,WAAO;AAAA,MACL,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,UAAU,WAAW;AAAA,QAC9B,SAAS,CAAC,QAAQ,kBAAkB,kCAAkC;AAAA,MACxE;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AAKA,MAAI,MAAM,SAAS,oBAAoB;AACrC,WAAO;AAAA,MACL,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,UAAU,+CAA+C;AAAA,MACpE;AAAA,MACA,QAAQ,MAAM;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM,aAAa,sBAAsB,MAAM;AAE/C,MAAI,CAAC,WAAW,OAAO;AACrB,WAAO;AAAA,MACL,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,UAAU,YAAY;AAAA,QAC/B,SAAS,WAAW;AAAA,MACtB;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,WAAW,SAAS,SAAS,GAAG;AAClC,WAAO;AAAA,MACL,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,UAAU,cAAc;AAAA,QACjC,SAAS,WAAW;AAAA,MACtB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,UAAU,UAAU;AAAA,IAC/B;AAAA,IACA;AAAA,EACF;AACF;AAUA,SAAS,iBAAiB,OAAoB,YAAoB,SAAyB;AACzF,MAAI,MAAM,SAAS,YAAY,MAAM;AACnC,WAAO,GAAG,mBAAmB,CAAC,WAAW,OAAO;AAClD,SAAO,GAAG,aAAa,UAAU,CAAC,IAAI,OAAO;AAC/C;AAGA,SAAS,aAAa,YAA4B;AAChD,SAAO,GAAG,WAAW,QAAQ,UAAU,CAAC,CAAC,KAAK,gBAAgB,UAAU,CAAC;AAC3E;AAGA,SAAS,qBAA6B;AACpC,SAAO,GAAG,WAAW,SAAS,CAAC,QAAQ,eAAe,SAAS,WAAW,UAAU,QAAQ,CAAC,OAAO,gBAAgBE,IAAG,QAAQ,CAAC,CAAC;AACnI;AAGA,SAAS,QAAQ,KAAwB;AACvC,SAAO,gBAAgB,GAAG,IAAI,WAAW;AAC3C;AAMA,SAAS,gBAAgB,MAAsB;AAC7C,QAAM,UAAU,mBAAmB,MAAM,cAAc,IAAI,CAAC;AAC5D,SAAO,gBAAgB,IAAI,IAAI,KAAK,OAAO,KAAK;AAClD;AAEA,eAAe,oBACb,QACAC,SACA,YACsB;AAItB,QAAM,cAAc,4BAA4B,OAAO,MAAM;AAC7D,QAAM,WAAW,OAAO,QAAQ,iBAAiB,OAAO,KAAK,IAAI,CAAC;AAClE,QAAM,eAAe,OAAO,CAAC,GAAG,UAAU,GAAG,OAAO,OAAO,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE;AAAA,IAC5E,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE;AAAA,EAC7B;AAEA,MAAI,aAAa,WAAW,GAAG;AAC7B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,CAAC,aAAa,YAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,IACpD,oBAAoB,UAAU;AAAA,IAC9B,CAAC,gBAAgB,UAAU,IAAI,oBAAoBD,IAAG,QAAQ,CAAC,IAAI;AAAA,EACrE,CAAC;AACD,QAAM,gBAAgB,oBAAI,IAAI;AAAA,IAC5B,GAAI,aAAa,OAAO,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC;AAAA,IAC7C,GAAI,cAAc,OAAO,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC;AAAA,EAChD,CAAC;AAED,QAAM,gBAAgB,aAAa;AAAA,IACjC,CAAC,YAAY,EAAE,WAAWC,QAAO,WAAW,CAAC,cAAc,IAAI,OAAO;AAAA,EACxE;AAEA,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,GAAG,MAAM,aAAa,SAAS,cAAc,QAAQ,aAAa,QAAQ,OAAO,CAAC;AAAA,MAC3F,SAAS,cAAc,IAAI,CAAC,MAAM,KAAK,CAAC,cAAc;AAAA,IACxD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,GAAG,MAAM,aAAa,QAAQ,aAAa,QAAQ,OAAO,CAAC;AAAA,EACtE;AACF;AAqBA,eAAe,oBACb,QACA,YACsB;AACtB,QAAM,SAAS,OAAO;AAEtB,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,QAAQ;AAAA,IACZ,QAAQ,cAAc,eAAe,YAAY,QAAQ,CAAC;AAAA,IAC1D,SAAS,cAAc,eAAe,YAAY,SAAS,CAAC;AAAA,EAC9D;AACA,QAAM,OAAO;AAAA,IACX,QAAQ,oBAAoB,YAAY,QAAQ,EAAE;AAAA,IAClD,SAAS,oBAAoB,YAAY,SAAS,EAAE;AAAA,EACtD;AAEA,QAAM,cAAc,MAAM,QAAQ;AAAA,IAChC,OAAO,IAAI,CAAC,UAAU,kBAAkB,OAAO,OAAO,IAAI,CAAC;AAAA,EAC7D;AAEA,QAAM,eAAe,YAAY,OAAO,CAAC,MAAM,EAAE,UAAU,cAAc;AACzE,QAAM,gBAAgB,YAAY,OAAO,CAAC,MAAM,EAAE,UAAU,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAOxF,MAAI,aAAa,WAAW,OAAO,QAAQ;AACzC,UAAM,sBAAsB,OAAO,aAAa,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,KAAK,MAAM;AACnF,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,oDAAoD,mBAAmB;AAAA,MAChF,SAAS,aAAa,IAAI,CAAC,MAAM,KAAK,EAAE,IAAI,iBAAiB,EAAE,QAAQ,GAAG;AAAA,IAC5E;AAAA,EACF;AAEA,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,GAAG,cAAc,MAAM,SAAS,cAAc,WAAW,IAAI,KAAK,GAAG,QAAQ,cAAc,WAAW,IAAI,MAAM,EAAE;AAAA,MAC3H,SAAS,cAAc,IAAI,CAAC,MAAM,KAAK,CAAC,YAAY;AAAA,IACtD;AAAA,EACF;AAEA,QAAM,aAAa,OAAO,SAAS,aAAa;AAChD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,GAAG,MAAM,YAAY,YAAY,OAAO,CAAC;AAAA,EACpD;AACF;AAaA,eAAe,kBACb,OACA,OACA,YAC4B;AAC5B,QAAM,WAAW,MAAM,MAAM,KAAK;AAClC,MAAI,CAAC,kBAAkB,UAAU,MAAM,IAAI,GAAG;AAC5C,WAAO,EAAE,MAAM,MAAM,MAAM,UAAU,OAAO,eAAe;AAAA,EAC7D;AAEA,QAAM,OAAO,GAAG,MAAM,IAAI,GAAG,WAAW,QAAQ,EAAE,SAAS;AAC3D,QAAM,WAAW,MAAM,WAAWC,MAAK,KAAK,WAAW,MAAM,KAAK,GAAG,IAAI,CAAC;AAC1E,SAAO,EAAE,MAAM,MAAM,MAAM,UAAU,OAAO,WAAW,aAAa,UAAU;AAChF;AAEA,eAAe,eAAe,QAAuB,YAA0C;AAG7F,QAAM,QAAQ,WAAW,cAAc,UAAU,CAAC;AAClD,QAAM,mBAAmB,oBAAoB,YAAY,SAAS,EAAE;AACpE,QAAM,kBAAkB,oBAAoB,YAAY,QAAQ,EAAE;AAIlE,QAAM,uBAAuB,gBAAgB,UAAU;AAEvD,QAAM,CAAC,eAAe,YAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,IACtD,gBAAgB,gBAAgB;AAAA,IAChC,CAAC,uBAAuB,gBAAgB,eAAe,IAAI;AAAA,EAC7D,CAAC;AAED,MAAI,CAAC,iBAAiB,CAAC,cAAc;AACnC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,iBAAiB,gBAAgB,MAAM,iBAAiB,kBAAkB,KAAK,IAAI,CAAC;AAC1F,QAAM,gBAAgB,eAAe,MAAM,iBAAiB,iBAAiB,KAAK,IAAI,CAAC;AAGvF,QAAM,sBAAmC,IAAI;AAAA,IAC3C,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,aAAa,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,EACrF;AAEA,QAAM,oBAAiC,IAAI;AAAA,IACzC,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,EACrE;AAEA,QAAM,wBAAwB,uBAC1B,oBAAI,IAAI,CAAC,GAAG,qBAAqB,GAAG,iBAAiB,CAAC,IACtD;AAEJ,QAAM,gBAAgB;AAAA,IACpB,GAAG,mBAAmB,gBAAgB,uBAAuB,KAAK;AAAA,IAClE,GAAG,mBAAmB,eAAe,mBAAmB,KAAK;AAAA,EAC/D;AAEA,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,OAAO,cAAc,QAAQ,qBAAqB;AAAA,MAC3D,SAAS,cAAc,IAAI,CAAC,MAAM,KAAK,CAAC,qBAAqB;AAAA,IAC/D;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS;AAAA,EACX;AACF;AAOA,SAAS,mBACP,SACA,aACA,OACU;AACV,SAAO,QACJ,IAAI,CAAC,aAAaA,MAAK,SAAS,UAAU,MAAM,SAAS,CAAC,EAC1D,OAAO,CAAC,cAAc,CAAC,YAAY,IAAI,SAAS,CAAC;AACtD;AAmBA,eAAe,yBAAyB,YAA0C;AAChF,QAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,uBAAuB,UAAU;AAClE,MAAI,OAAO,WAAW,KAAK,OAAO,WAAW,EAAG,QAAO,cAAc,SAAS;AAE9E,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA;AAAA;AAAA,IAGR,SAAS,GAAG,iBAAiB,QAAQ,MAAM,CAAC;AAAA,IAC5C,SAAS,CAAC,GAAG,QAAQ,GAAG,MAAM,EAAE,IAAI,CAAC,aAAa,KAAK,QAAQ,EAAE;AAAA,EACnE;AACF;AAGA,SAAS,MAAM,OAAe,OAAe,MAAsB;AACjE,SAAO,GAAG,KAAK,IAAI,OAAO,OAAO,IAAI,CAAC;AACxC;AAGA,SAAS,iBAAiB,QAAkB,QAA0B;AACpE,SAAO;AAAA,IACL,GAAI,OAAO,SAAS,IAAI,CAAC,OAAO,OAAO,QAAQ,OAAO,CAAC,IAAI,CAAC;AAAA,IAC5D,GAAI,OAAO,SAAS,IAAI,CAAC,OAAO,OAAO,QAAQ,OAAO,CAAC,IAAI,CAAC;AAAA,EAC9D,EAAE,KAAK,OAAO;AAChB;AAkBA,eAAe,qBACb,QACA,YACsB;AACtB,QAAM,SAAwB,OAAO;AACrC,QAAM,cAAc,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,YAAY;AAElE,MAAI,YAAY,WAAW,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,cAAc,MAAM,QAAQ;AAAA,IAChC,YAAY,IAAI,CAAC,UAAU,kBAAkB,OAAO,UAAU,CAAC;AAAA,EACjE;AACA,QAAM,gBAAgB,YAAY,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS;AAE5D,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,GAAG,OAAO,cAAc,QAAQ,OAAO,CAAC;AAAA,MACjD,SAAS,cAAc,IAAI,CAAC,MAAM,KAAK,EAAE,EAAE,kBAAkB,EAAE,QAAQ,IAAI;AAAA,IAC7E;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,GAAG,MAAM,YAAY,QAAQ,YAAY,QAAQ,kBAAkB,CAAC;AAAA,EAC/E;AACF;AAYA,eAAe,kBACb,OACA,YAC4B;AAC5B,QAAM,WAAW,cAAc,eAAe,YAAY,MAAM,KAAK,CAAC;AACtE,QAAM,MAAM,UAAU,UAAU,MAAM,OAAO,UAAU;AACvD,QAAM,YAAY,MAAM,WAAWA,MAAK,KAAK,KAAK,MAAM,IAAI,eAAe,QAAQ,CAAC;AAEpF,SAAO;AAAA,IACL,IAAI,MAAM;AAAA,IACV;AAAA,IACA,UAAU,iBAAiB,UAAU,MAAM,OAAO,UAAU;AAAA,EAC9D;AACF;AAOA,eAAe,2BACb,QACA,YACsB;AACtB,QAAM,eAA8B,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,YAAY;AAEzF,MAAI,aAAa,WAAW,GAAG;AAC7B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,WAAW,OAAO,aAAa,IAAI,CAAC,MAAM,eAAe,YAAY,EAAE,KAAK,CAAC,CAAC;AACpF,QAAM,oBAAoB,MAAM,QAAQ;AAAA,IACtC,SAAS,IAAI,OAAO,YAAY;AAC9B,YAAM,eAAe,IAAI;AAAA,SACtB,MAAM,8BAA8B,OAAO,GAAG;AAAA,UAAI,CAAC,WAClD,0BAA0B,OAAO,SAAS;AAAA,QAC5C;AAAA,MACF;AACA,aAAO,aACJ,OAAO,CAAC,UAAU,eAAe,YAAY,MAAM,KAAK,MAAM,OAAO,EACrE,OAAO,CAAC,UAAU,CAAC,aAAa,IAAI,MAAM,EAAE,CAAC,EAC7C,IAAI,CAAC,UAAU,MAAM,EAAE;AAAA,IAC5B,CAAC;AAAA,EACH;AACA,QAAM,gBAAgB,kBAAkB,KAAK;AAE7C,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,GAAG,OAAO,cAAc,QAAQ,OAAO,CAAC;AAAA,MACjD,SAAS,cAAc,IAAI,CAAC,MAAM,KAAK,CAAC,4BAA4B;AAAA,IACtE;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,GAAG,MAAM,aAAa,QAAQ,aAAa,QAAQ,mBAAmB,CAAC;AAAA,EAClF;AACF;AAaA,IAAM,wBAAwB;AAAA,EAC5B,MAAM;AAAA,EACN,KAAK,YAAY,cAAc;AAAA,EAC/B,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AACX;AAGA,SAAS,gBAAgB,QAAgB,SAA0B;AACjE,SAAO,UAAU,QAAQ,MAAM,eAAe,WAAW,MAAM;AACjE;AAcA,SAAS,mBAAmB,QAAuC;AACjE,QAAM,EAAE,QAAQ,aAAa,IAAI,OAAO;AACxC,QAAM,aAAa,OAAO,oBAAoB;AAC9C,QAAM,cAAc,OAAO,UAAU,UAAU;AAE/C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,gBAAgB,WAAW,KAAK,OAAO,UAAU;AAAA,IAC1D,SAAS;AAAA,MACP,GAAG,OAAO,YAAY,OAAO,CAAC;AAAA,MAC9B,GAAG,gBAAgB,QAAQ,OAAO,OAAO,CAAC,WAAM,sBAAsB,YAAY,CAAC;AAAA,IACrF;AAAA,EACF;AACF;AAEA,eAAe,qBAAqB,YAA0C;AAC5E,MAAI;AACF,UAAM,EAAE,aAAa,IAAI,MAAM,WAAW,EAAE,WAAW,CAAC;AACxD,WAAO,mBAAmB,YAAY;AAAA,EACxC,SAAS,OAAO;AACd,UAAM,UAAU,gBAAgB,KAAK;AACrC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,SAAS,CAAC,OAAO;AAAA,IACnB;AAAA,EACF;AACF;AA2BA,IAAM,eAA6B;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,KAAK;AACP;AAOA,IAAM,iBAAsC;AAAA,EAC1C;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA;AAAA,IAEN,aAAa;AAAA;AAAA;AAAA;AAAA,IAIb,QAAQ,CAAC,QAAQ;AAAA,IACjB,KAAK;AAAA,EACP;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA,IAIb,QAAQ,CAAC,SAAS;AAAA,IAClB,KAAK;AAAA,EACP;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA;AAAA;AAAA;AAAA,IAIN,aAAa;AAAA;AAAA;AAAA,IAGb,QAAQ,CAAC,QAAQ;AAAA,IACjB,KAAK;AAAA,EACP;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA,IAGb,QAAQ,CAAC;AAAA,IACT,KAAK;AAAA,EACP;AACF;AAEA,SAAS,cAAc,QAAgB,UAAyC;AAC9E,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,WAAW,EAAG,QAAO;AACzB,SAAO;AACT;AAEA,SAAS,eAAe,MAAc,OAAe,QAAgB,UAA0B;AAG7F,MAAI,WAAW,KAAK,aAAa,GAAG;AAClC,WAAO,UAAU,IAAI,MAAM,IAAI,kBAAkB,GAAG,OAAO,OAAO,IAAI,CAAC;AAAA,EACzE;AACA,SAAO,GAAG,OAAO,OAAO,IAAI,CAAC,KAAK,OAAO,QAAQ,OAAO,CAAC,KAAK,OAAO,UAAU,SAAS,CAAC;AAC3F;AAEA,SAAS,mBAAmB,OAA6B;AACvD,QAAM,SAAS,MAAM,aAAa,UAAU,UAAU;AACtD,SAAO,MAAM,MAAM,KAAK,MAAM,IAAI,KAAK,MAAM,OAAO;AACtD;AAEA,SAAS,gBAAgB,OAAqB,YAA4C;AACxF,QAAM,SAAS,WAAW,OAAO,OAAO,CAAC,UAAU,MAAM,aAAa,OAAO,EAAE;AAC/E,QAAM,WAAW,WAAW,OAAO,SAAS;AAE5C,SAAO;AAAA,IACL,MAAM,MAAM;AAAA,IACZ,QAAQ,cAAc,QAAQ,QAAQ;AAAA,IACtC,SAAS,eAAe,MAAM,MAAM,WAAW,OAAO,QAAQ,QAAQ;AAAA,IACtE,SAAS;AAAA,MACP,GAAG,WAAW,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE;AAAA,MAC7C,GAAG,WAAW,OAAO,IAAI,kBAAkB;AAAA,IAC7C;AAAA,EACF;AACF;AAOA,IAAM,cAAc;AAGpB,IAAM,iBAAiB;AACvB,IAAM,aAAa;AAEnB,IAAM,kBAAkB;AACxB,IAAM,sBAAsB;AAC5B,IAAM,uBAAuB;AAC7B,IAAM,yBAAyB;AAO/B,IAAM,0BAA0B;AAOhC,SAAS,qBAAqB,OAAyB;AACrD,SAAO,kDAA6C,MAAM,KAAK,OAAO,CAAC;AACzE;AAEA,SAAS,gBAAgB,MAAsB;AAC7C,SAAO,KAAK,OAAO,WAAW;AAChC;AAWA,SAAS,aAAa,QAAuC;AAC3D,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO,WAAW;AAAA,IACpB,KAAK;AACH,aAAO,WAAW;AAAA,IACpB,KAAK;AACH,aAAO,WAAW;AAAA,IACpB,KAAK;AACH,aAAO,WAAW;AAAA,IACpB,SAAS;AACP,YAAM,cAAqB;AAC3B,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAGA,IAAM,gBAAgB,GAAG,UAAU,GAAG,IAAI,OAAO,WAAW,CAAC;AAE7D,SAAS,gBAAgB,MAAc,QAA+B;AACpE,QAAM,aAAa,GAAG,UAAU,GAAG,gBAAgB,IAAI,CAAC,GAAG,aAAa,OAAO,MAAM,CAAC,KAAK,OAAO,OAAO;AACzG,QAAM,eAAe,OAAO,WAAW,CAAC,GAAG,QAAQ,mBAAmB;AACtE,SAAO,CAAC,YAAY,GAAG,WAAW;AACpC;AAOA,SAAS,oBAAoB,QAA0B;AACrD,SAAO,OACJ,MAAM,IAAI,EACV,OAAO,CAAC,SAAS,SAAS,EAAE,EAC5B,IAAI,CAAC,SAAS,GAAG,aAAa,GAAG,IAAI,EAAE;AAC5C;AAEA,SAAS,cAAc,SAAgC;AACrD,QAAM,SAAS,QAAQ,SAAS,CAAC,MAAM,EAAE,MAAM;AAE/C,QAAM,QAAQ;AAAA,IACZ,GAAG,OAAO,QAAQ,CAAC;AAAA,IACnB,OAAO,OAAO,QAAQ,GAAG,SAAS;AAAA,IAClC,OAAO,OAAO,QAAQ,GAAG,OAAO;AAAA,EAClC;AAEA,SAAO,GAAG,cAAc,YAAY,MAAM,KAAK,IAAI,CAAC;AACtD;AAEA,IAAM,OAA+E;AAAA,EACnF;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,KAAK,eAAe,kBAAkB;AAAA,EACxC;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,KAAK,eAAe,kBAAkB;AAAA,EACxC;AAAA,EACA;AAAA;AAAA;AAAA;AAAA,IAIE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,KAAK,gDAA2C,kBAAkB;AAAA,EACpE;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAME,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,KAAK,mDAA8C,kBAAkB,0EAA0E,kBAAkB;AAAA,EACnK;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,KAAK;AAAA,EACP;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA;AAAA;AAAA;AAAA,IAIR,KAAK;AAAA,EACP;AACF;AAEA,SAAS,WAAW,SAAkC;AACpD,SAAO,KAAK,OAAO,CAAC,MAAM,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE;AAAA,IACzF,CAAC,MAAM,EAAE;AAAA,EACX;AACF;AAYA,eAAe,mBACb,gBACA,YACmB;AACnB,MAAI,CAAC,mBAAmB,cAAc,EAAE,IAAI,aAAa,IAAI,EAAG,QAAO,CAAC;AAExE,QAAM,WAAW,MAAM,uBAAuB,UAAU,EAAE,MAAM,MAAM,CAAC,CAAC;AACxE,SAAO,SAAS;AAAA,IACd,CAAC,YACC,oFAA+E,mBAAmB,QAAQ,SAAS,CAAC;AAAA,EACxH;AACF;AAGA,IAAM,kBAAkB;AAGxB,SAAS,eAAe,OAAiC;AACvD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,gBAAgB,WAAW,MAAM,IAAI,GAAG,MAAM,OAAO;AAAA,EAChE;AACF;AAGA,IAAM,sBAAsB;AA0B5B,eAAe,uBAAuB,YAA0C;AAC9E,QAAM,WAAW,MAAM,sCAAsC,UAAU;AAEvE,MAAI,SAAS,WAAW,GAAG;AACzB,WAAO,EAAE,MAAM,cAAc,QAAQ,QAAQ,SAAS,sCAAsC;AAAA,EAC9F;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,GAAG,OAAO,SAAS,QAAQ,SAAS,CAAC;AAAA,IAC9C,SAAS,SAAS,IAAI,CAAC,YAAY,KAAK,OAAO,EAAE;AAAA,EACnD;AACF;AAUA,eAAe,sCAAsC,YAAuC;AAC1F,QAAM,CAAC,aAAa,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,IACjD,2BAA2B,UAAU;AAAA,IACrC,iBAAiB,UAAU;AAAA,EAC7B,CAAC;AAED,SAAO,cAAc,OAAO,cAAc,CAAC,GAAG,aAAa,SAAS;AACtE;AAEA,SAAS,cAAc,MAA8B;AACnD,SAAO,EAAE,MAAM,QAAQ,QAAQ,SAAS,2BAA2B;AACrE;AAMA,SAAS,gCAA6C;AACpD,SAAO,EAAE,MAAM,UAAU,QAAQ,QAAQ,SAAS,oCAAoC;AACxF;AAEA,SAAS,qBAAqB,MAA8B;AAC1D,SAAO,EAAE,MAAM,QAAQ,QAAQ,SAAS,uBAAuB;AACjE;AAGA,SAAS,mBAAmB,gBAAuD;AACjF,SAAO,IAAI,IAAI,eAAe,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AACrF;AAOA,SAAS,qBACP,KACA,eACoB;AACpB,QAAM,gBAAgB,eAAe,OAAO,CAAC,UAAU,cAAc,IAAI,MAAM,IAAI,CAAC,EACjF,OAAO,CAAC,UAAU,MAAM,OAAO,SAAS,GAAG,CAAC,EAC5C,IAAI,CAAC,UAAU,MAAM,IAAI;AAE5B,MAAI,cAAc,WAAW,EAAG,QAAO;AAEvC,SAAO,EAAE,MAAM,KAAK,QAAQ,QAAQ,SAAS,qBAAqB,aAAa,EAAE;AACnF;AAEA,SAAS,gBAAgB,OAAqB,YAA0C;AACtF,SAAO,UAAU,MAAM,MAAM,YAAY,gBAAgB,OAAO,MAAM,MAAM,IAAI,UAAU,CAAC,CAAC;AAC9F;AAMA,eAAe,UAAU,MAAiB,IAAsD;AAC9F,MAAI;AACF,WAAO,MAAM,GAAG;AAAA,EAClB,SAAS,OAAO;AACd,WAAO,EAAE,MAAM,QAAQ,QAAQ,SAAS,eAAe,SAAS,CAAC,gBAAgB,KAAK,CAAC,EAAE;AAAA,EAC3F;AACF;AAEA,IAAqB,SAArB,MAAqB,gBAAe,YAAY;AAAA,EAC9C,OAAO,UAAU;AAAA,EAEjB,OAAO,cAAc,iCAAiC,iBAAiB,IAAI;AAAA,EAE3E,OAAO,WAAW,CAAC,qCAAqC;AAAA,EAExD,OAAO,QAAQ,CAAC;AAAA,EAEhB,MAAM,MAAqB;AACzB,UAAM,KAAK,MAAM,OAAM;AACvB,UAAM,aAAa,QAAQ,IAAI;AAQ/B,SAAK,YAAY,MAAM,KAAK,oBAAoB,UAAU,CAAC;AAC3D,UAAM,iBAAiB,MAAM,KAAK,iBAAiB,UAAU;AAC7D,UAAM,qBAAqB,MAAM,KAAK,qBAAqB,YAAY,cAAc;AACrF,UAAM,UAAU,CAAC,GAAG,gBAAgB,GAAG,kBAAkB;AAEzD,SAAK,aAAa,SAAS,MAAM,mBAAmB,gBAAgB,UAAU,CAAC;AAE/E,QAAI,QAAQ,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM,GAAG;AAC5C,WAAK,KAAK,WAAW,KAAK;AAAA,IAC5B;AAAA,EACF;AAAA,EAEQ,YAAY,cAA4B;AAC9C,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,GAAG,YAAY,SAAS;AACjC,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,GAAG,cAAc,kCAAkC;AAC5D,SAAK,IAAI,EAAE;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,iBAAiB,YAA4C;AACzE,SAAK,IAAI,GAAG,cAAc,GAAG,eAAe,EAAE;AAE9C,UAAM,eAAe,MAAM,gBAAgB,cAAc,UAAU;AACnE,UAAM,mBAAmB,aAAa,WAAW;AAEjD,UAAM,OAAO,MAAM,QAAQ;AAAA,MACzB,eAAe,IAAI,OAAO,WAAW;AAAA,QACnC,MAAM,MAAM;AAAA,QACZ,QACE,MAAM,eAAe,mBACjB,qBAAqB,MAAM,IAAI,IAC/B,MAAM,gBAAgB,OAAO,UAAU;AAAA,MAC/C,EAAE;AAAA,IACJ;AAEA,UAAM,UAAU,CAAC,EAAE,MAAM,aAAa,MAAM,QAAQ,aAAa,GAAG,GAAG,IAAI;AAE3E,eAAW,OAAO,SAAS;AACzB,WAAK,SAAS,IAAI,MAAM,IAAI,MAAM;AAAA,IACpC;AAEA,WAAO,QAAQ,IAAI,CAAC,QAAQ,IAAI,MAAM;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,qBACZ,YACA,gBACwB;AACxB,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,GAAG,cAAc,GAAG,mBAAmB,EAAE;AAElD,UAAM,gBAAgB,mBAAmB,cAAc;AACvD,QAAI,cAAc,IAAI,aAAa,IAAI,GAAG;AACxC,WAAK,IAAI,GAAG,UAAU,GAAG,uBAAuB,EAAE;AAClD,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,WAAW,MAAM,cAAc,UAAU;AAC/C,QAAI,CAAC,YAAa,MAAM,KAAK,wBAAwB,UAAU,GAAI;AACjE,WAAK,IAAI,GAAG,UAAU,GAAG,oBAAoB,EAAE;AAC/C,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,cAAc,MAAM,mBAAmB,UAAU,UAAU;AACjE,WAAO,KAAK,aAAa,YAAY,aAAa,aAAa;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,wBAAwB,YAAsC;AAC1E,QAAI,MAAM,WAAW,uBAAuB,UAAU,CAAC,EAAG,QAAO;AACjE,WAAO,aAAa,UAAU;AAAA,EAChC;AAAA,EAEA,MAAc,aACZ,YACA,aACA,eACwB;AACxB,UAAM,EAAE,QAAQ,cAAc,OAAO,IAAI,iBAAiB,aAAa,UAAU;AACjF,SAAK,SAAS,gBAAgB,YAAY;AAE1C,UAAM,gBAAgB,MAAM,KAAK,aAAa,UAAU;AAIxD,UAAM,mBAAmB,MAAM;AAAA,MAAU;AAAA,MAAc,MACrD,uBAAuB,UAAU;AAAA,IACnC;AACA,SAAK,SAAS,qBAAqB,gBAAgB;AAKnD,UAAM,eAAe,MAAM,UAAU,UAAU,MAAM,qBAAqB,UAAU,CAAC;AAErF,UAAM,iBAAiB,SAAS,sBAAsB,MAAM,IAAI;AAEhE,UAAM,eAAe,MAAM,KAAK;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,SAAK,SAAS,mBAAmB,YAAY;AAE7C,UAAM,eAAe,iBACjB,MAAM,UAAU,UAAU,MAAM,oBAAoB,gBAAgB,UAAU,CAAC,IAC/E,cAAc,QAAQ;AAC1B,SAAK,SAAS,mBAAmB,YAAY;AAE7C,UAAM,gBAAgB,MAAM,KAAK,oBAAoB,QAAQ,aAAa,UAAU;AACpF,SAAK,SAAS,cAAc,aAAa;AAEzC,UAAM,kBAAkB,iBACpB,MAAM,UAAU,aAAa,MAAM,qBAAqB,gBAAgB,UAAU,CAAC,IACnF,cAAc,WAAW;AAC7B,SAAK,SAAS,oBAAoB,eAAe;AAEjD,UAAM,gBAAgB,MAAM,KAAK,oBAAoB,gBAAgB,YAAY,aAAa;AAC9F,SAAK,SAAS,qBAAqB,aAAa;AAEhD,SAAK,SAAS,yBAAyB,YAAY;AAEnD,WAAO;AAAA,MACL;AAAA,MACA,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,aAAa,YAA4C;AACrE,UAAM,QAAQ,MAAM,mBAAmB,UAAU,GAAG,IAAI,cAAc;AAEtE,eAAW,OAAO,MAAM;AACtB,WAAK,SAAS,iBAAiB,GAAG;AAAA,IACpC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,oBACZ,QACA,aACA,YACsB;AACtB,QAAI,OAAQ,QAAO,UAAU,WAAW,MAAM,eAAe,QAAQ,UAAU,CAAC;AAChF,QAAI,YAAY,SAAS,UAAU;AACjC,aAAO,UAAU,WAAW,MAAM,yBAAyB,UAAU,CAAC;AAAA,IACxE;AACA,WAAO,cAAc,SAAS;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,mBACZ,QACA,cACA,YACA,eACsB;AACtB,QAAI,CAAC,OAAQ,QAAO,cAAc,QAAQ;AAE1C,UAAM,UAAU,qBAAqB,UAAU,aAAa;AAC5D,QAAI,QAAS,QAAO;AACpB,QAAI,aAAa,WAAW,OAAQ,QAAO,8BAA8B;AAEzE,WAAO,UAAU,UAAU,MAAM,oBAAoB,QAAQ,QAAQ,UAAU,CAAC;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,oBACZ,QACA,YACA,eACsB;AACtB,QAAI,CAAC,OAAQ,QAAO,cAAc,SAAS;AAE3C,UAAM,UAAU,qBAAqB,WAAW,aAAa;AAC7D,QAAI,QAAS,QAAO;AAEpB,WAAO,UAAU,WAAW,MAAM,2BAA2B,QAAQ,UAAU,CAAC;AAAA,EAClF;AAAA,EAEQ,SAAS,MAAc,QAA2B;AACxD,eAAW,QAAQ,gBAAgB,MAAM,MAAM,GAAG;AAChD,WAAK,IAAI,IAAI;AAAA,IACf;AAAA,EACF;AAAA,EAEQ,aAAa,SAAwB,cAA8B;AACzE,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,cAAc,OAAO,CAAC;AAE/B,UAAM,OAAO,CAAC,GAAG,WAAW,OAAO,GAAG,GAAG,YAAY;AACrD,QAAI,KAAK,SAAS,GAAG;AACnB,WAAK,IAAI,EAAE;AACX,iBAAW,OAAO,MAAM;AACtB,aAAK,IAAI,GAAG;AAAA,MACd;AAAA,IACF;AAEA,SAAK,IAAI,EAAE;AAAA,EACb;AACF;","names":["os","path","skillsDir","path","path","skillsDir","os","matrix","path"]}
1
+ {"version":3,"sources":["../../src/cli/commands/doctor.ts","../../src/cli/lib/doctor/installation-reads.ts","../../src/cli/lib/doctor/ownership.ts","../../src/cli/lib/content-validator.ts","../../src/cli/lib/source-validator.ts"],"sourcesContent":["import os from \"os\";\nimport path from \"path\";\nimport { BaseCommand } from \"../base-command\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport { EXIT_CODES } from \"../lib/exit-codes\";\nimport {\n effectivelyExcludedSkillIds,\n findConfigLoadFailures,\n MarketplaceRefusedError,\n validateProjectConfig,\n SOURCE_ENV_VAR,\n type ResolvedConfig,\n} from \"../lib/configuration\";\nimport { loadSkillsMatrixFromSource, type SourceLoadResult } from \"../lib/loading\";\nimport { matrix } from \"../lib/matrix/matrix-provider\";\nimport { getStackSkillIds } from \"../lib/stacks\";\nimport { filterExcludedEntries } from \"../lib/agents\";\nimport { isHomeDirectory, installBaseDir } from \"../lib/installation\";\nimport {\n agentCodec,\n agentsDir,\n hostCompilesAgent,\n relativeConfigPath,\n skillsDir,\n skillsPathPrefix,\n} from \"../lib/installation/install-layout\";\nimport { ambiguityFinding } from \"../lib/installation/provider-flag\";\nimport {\n sourceScopesInPlay,\n type ScopeKind,\n type SourceScope,\n} from \"../lib/installation/source-scopes\";\nimport {\n hostsOf,\n hostsOnDisk,\n installedPluginSkillIds,\n providersInPlay,\n resolveConfigState,\n unofferablePlacements,\n type CheckedInstallation,\n type ConfigState,\n} from \"../lib/doctor/installation-reads\";\nimport { judgeOwnership, type Orphans, type Ownership } from \"../lib/doctor/ownership\";\nimport {\n layoutIsCurrent,\n providerArgument,\n recreateConfigFrom,\n scopeLabel,\n scopeNoun,\n} from \"../utils/messages\";\nimport { isSourceRepo } from \"../lib/source-validator\";\nimport {\n validateInstalledAgents,\n validateInstalledPlugins,\n validateInstalledSkills,\n validateProjectConfigFile,\n validateRegisteredSources,\n type ContentIssue,\n type ContentValidation,\n} from \"../lib/content-validator\";\nimport type {\n AgentName,\n AgentScopeConfig,\n MergedSkillsMatrix,\n ProjectConfig,\n SkillConfig,\n SkillId,\n SkillScope,\n} from \"../types\";\nimport { fileExists } from \"../utils/fs\";\nimport { plural } from \"../utils/string\";\nimport {\n CLI_INVOKE_COMMAND,\n DEFAULT_BRANDING,\n EJECT_SOURCE,\n STANDARD_FILES,\n UI_SYMBOLS,\n type Provider,\n} from \"../consts\";\nimport { countBy, unique } from \"remeda\";\n\ntype CheckKind =\n | \"config\"\n | \"config-empty\"\n | \"installations\"\n | \"source-repo\"\n | \"layout\"\n | \"placements\"\n | \"skills\"\n | \"agents\"\n | \"orphans\"\n | \"orphans-unowned\"\n | \"installed\"\n | \"plugins\"\n | \"source\"\n | \"content-config\"\n | \"content-sources\"\n | \"content-plugins\"\n | \"content-skills\"\n | \"content-agents\";\n\ntype CheckResult = {\n kind: CheckKind;\n status: \"pass\" | \"fail\" | \"warn\" | \"skip\";\n message: string;\n details?: string[];\n /** The installation a block's row is about, where the scope holds two. */\n provider?: Provider;\n};\n\ntype ConfigCheckOutput = {\n result: CheckResult;\n config: ProjectConfig | null;\n};\n\nfunction checkConfigValid(\n state: ConfigState,\n installation: CheckedInstallation,\n): ConfigCheckOutput {\n const theConfig = (verdict: string) => configRowMessage(state, installation, verdict);\n if (state.kind === \"absent\") {\n return {\n result: {\n kind: \"config\",\n status: \"fail\",\n message: theConfig(\"not found\"),\n details: [`Run '${CLI_INVOKE_COMMAND} init' to create a configuration`],\n },\n config: null,\n };\n }\n\n if (state.kind === \"unreadable\") {\n return {\n result: {\n kind: \"config\",\n status: \"fail\",\n message: theConfig(\"exists but could not be loaded\"),\n details: [state.failure.reason],\n },\n config: null,\n };\n }\n\n // Valid but empty: handed on so the rows below don't report \"config invalid\".\n if (state.kind === \"declares-nothing\") {\n return {\n result: {\n kind: \"config-empty\",\n status: \"warn\",\n message: theConfig(\"is valid but declares no skills and no agents\"),\n },\n config: state.config,\n };\n }\n\n const { config } = state;\n const validation = validateProjectConfig(config);\n\n if (!validation.valid) {\n return {\n result: {\n kind: \"config\",\n status: \"fail\",\n message: theConfig(\"has errors\"),\n details: validation.errors,\n },\n config: null,\n };\n }\n\n if (validation.warnings.length > 0) {\n return {\n result: {\n kind: \"config\",\n status: \"warn\",\n message: theConfig(\"has warnings\"),\n details: validation.warnings,\n },\n config,\n };\n }\n\n return {\n result: {\n kind: \"config\",\n status: \"pass\",\n message: theConfig(\"is valid\"),\n },\n config,\n };\n}\n\n/** Names the file actually read: the global config when this directory inherits it. */\nfunction configRowMessage(\n state: ConfigState,\n { projectDir, hosts }: CheckedInstallation,\n verdict: string,\n): string {\n if (state.kind === \"loaded\" && state.inherited)\n return `${theInheritedConfig(hosts.global)}, which ${verdict}`;\n if (state.kind === \"unreadable\") {\n const { scopeRoot, scope } = state.failure;\n return `${theConfigAt(scopeRoot, hosts[scope])} ${verdict}`;\n }\n return `${theConfigAt(projectDir, hosts.project)} ${verdict}`;\n}\n\nfunction theConfigAt(root: string, provider: Provider): string {\n return `${scopeLabel(scopeOf(root))}: ${configNamedFrom(root, provider)}`;\n}\n\nfunction theInheritedConfig(provider: Provider): string {\n return `${scopeLabel(\"project\")}: no ${STANDARD_FILES.CONFIG_TS}, using ${scopeNoun(\"global\")}'s (${configNamedFrom(os.homedir(), provider)})`;\n}\n\nfunction scopeOf(dir: string): ScopeKind {\n return isHomeDirectory(dir) ? \"global\" : \"project\";\n}\n\nfunction configNamedFrom(root: string, provider: Provider): string {\n const relPath = relativeConfigPath(root, provider);\n return isHomeDirectory(root) ? `~/${relPath}` : relPath;\n}\n\n/** The loader has already merged in every local skill it accepts, from both scopes. */\nfunction checkSkillsResolved(config: ProjectConfig, matrix: MergedSkillsMatrix): CheckResult {\n const uniqueSkills = skillIdsToResolve(config);\n\n if (uniqueSkills.length === 0) {\n return {\n kind: \"skills\",\n status: \"pass\",\n message: \"No skills configured\",\n };\n }\n\n const missingSkills = uniqueSkills.filter((skillId) => !(skillId in matrix.skills));\n\n if (missingSkills.length > 0) {\n return {\n kind: \"skills\",\n status: \"fail\",\n message: `${ratio(uniqueSkills.length - missingSkills.length, uniqueSkills.length, \"skill\")} found`,\n details: missingSkills.map((s) => `- ${s} (not found)`),\n };\n }\n\n return {\n kind: \"skills\",\n status: \"pass\",\n message: `${ratio(uniqueSkills.length, uniqueSkills.length, \"skill\")} found`,\n };\n}\n\n/** Both sources: a global-only install has skills but no stack. */\nfunction skillIdsToResolve(config: ProjectConfig): SkillId[] {\n const excludedIds = effectivelyExcludedSkillIds(config.skills);\n const stackIds = config.stack ? getStackSkillIds(config.stack) : [];\n return unique([...stackIds, ...config.skills.map((s) => s.id)]).filter(\n (id) => !excludedIds.has(id),\n );\n}\n\nasync function checkAgentsCompiled(\n config: ProjectConfig,\n installation: CheckedInstallation,\n): Promise<CheckResult> {\n if (config.agents.length === 0) {\n return {\n kind: \"agents\",\n status: \"pass\",\n message: \"No agents configured\",\n };\n }\n\n const agentChecks = await Promise.all(\n config.agents.map((agent) => agentCompileCheck(agent, installation)),\n );\n const unrenderable = agentChecks.filter((c) => c.state === \"unrenderable\");\n const missingAgents = agentChecks.filter((c) => c.state === \"missing\").map((c) => c.name);\n\n // A sub-agent the host leaves out by design is a pass, not a recompile warning.\n if (unrenderable.length === config.agents.length) {\n const hostsLeavingThemOut = unique(unrenderable.map((a) => a.provider)).join(\" or \");\n return {\n kind: \"agents\",\n status: \"pass\",\n message: `No sub-agent in this configuration is carried by ${hostsLeavingThemOut}`,\n details: unrenderable.map((a) => `- ${a.name} (left out of ${a.provider})`),\n };\n }\n\n if (missingAgents.length > 0) {\n return {\n kind: \"agents\",\n status: \"warn\",\n message: needRecompilation(missingAgents.length),\n details: missingAgents.map((a) => `- ${a} (missing)`),\n };\n }\n\n const renderable = config.agents.length - unrenderable.length;\n return {\n kind: \"agents\",\n status: \"pass\",\n message: `${ratio(renderable, renderable, \"agent\")} compiled`,\n };\n}\n\nfunction needRecompilation(count: number): string {\n return `${plural(count, \"agent\")} ${count === 1 ? \"needs\" : \"need\"} recompilation`;\n}\n\ntype AgentCompileCheck = {\n name: AgentName;\n provider: Provider;\n state: \"unrenderable\" | \"compiled\" | \"missing\";\n};\n\n/** Host read per scope: two scopes can be on two providers. */\nasync function agentCompileCheck(\n agent: AgentScopeConfig,\n { projectDir, hosts }: CheckedInstallation,\n): Promise<AgentCompileCheck> {\n const provider = hosts[agent.scope];\n if (!hostCompilesAgent(provider, agent.name)) {\n return { name: agent.name, provider, state: \"unrenderable\" };\n }\n\n const file = `${agent.name}${agentCodec(provider).extension}`;\n const compiled = await fileExists(path.join(agentsDir(provider, agent.scope, projectDir), file));\n return { name: agent.name, provider, state: compiled ? \"compiled\" : \"missing\" };\n}\n\nasync function checkNoOrphans(\n state: ConfigState,\n config: ProjectConfig | null,\n installation: CheckedInstallation,\n): Promise<CheckResult> {\n return ownershipResult(state, await judgeOwnership(state, config, installation));\n}\n\nfunction ownershipResult(state: ConfigState, { unowned, orphans }: Ownership): CheckResult {\n if (unowned.skills.length > 0 || unowned.agents.length > 0) {\n return {\n kind: \"orphans-unowned\",\n status: \"fail\",\n message: `${countedArtifacts(unowned.skills, unowned.agents)} installed here, and no configuration declares them`,\n details: [...unowned.skills, ...unowned.agents, ...orphanLines(orphans)].map(\n (line) => `- ${line}`,\n ),\n };\n }\n\n if (orphans.skills.length > 0 || orphans.agents.length > 0) {\n return {\n kind: \"orphans\",\n status: \"warn\",\n message: countedOrphans(orphans),\n details: orphanLines(orphans).map((line) => `- ${line}`),\n };\n }\n\n // With no configuration and nothing this CLI wrote, there is nothing to own: `init`'s state.\n if (state.kind === \"absent\") return skippedResult(\"orphans\");\n\n return { kind: \"orphans\", status: \"pass\", message: \"No orphaned skills or agent files\" };\n}\n\nfunction orphanLines({ skills, agents }: Orphans): string[] {\n return [...skills, ...agents].map((name) => `${name} (not in config)`);\n}\n\nfunction countedOrphans({ skills, agents }: Orphans): string {\n return nonZeroCounts([skills.length, \"orphaned skill\"], [agents.length, \"orphaned agent file\"]);\n}\n\nfunction ratio(found: number, total: number, noun: string): string {\n return `${found}/${plural(total, noun)}`;\n}\n\nfunction countedArtifacts(skills: string[], agents: string[]): string {\n return nonZeroCounts([skills.length, \"skill\"], [agents.length, \"agent\"]);\n}\n\ntype Count = [count: number, noun: string];\n\n/** `2 skills and 1 agent`: a zero is left out rather than counted. */\nfunction nonZeroCounts(...counts: Count[]): string {\n return counts\n .filter(([count]) => count > 0)\n .map(([count, noun]) => plural(count, noun))\n .join(\" and \");\n}\n\n/** The directory is resolved per skill, since scope (and so host) varies within one config. */\nasync function checkSkillsInstalled(\n config: ProjectConfig,\n installation: CheckedInstallation,\n): Promise<CheckResult> {\n const ejectSkills = config.skills.filter((s) => s.origin === EJECT_SOURCE);\n\n if (ejectSkills.length === 0) {\n return {\n kind: \"installed\",\n status: \"pass\",\n message: \"No eject-mode skills configured\",\n };\n }\n\n const skillChecks = await Promise.all(\n ejectSkills.map((skill) => ejectedSkillCheck(skill, installation)),\n );\n const missingSkills = skillChecks.filter((c) => !c.installed);\n\n if (missingSkills.length > 0) {\n return {\n kind: \"installed\",\n status: \"warn\",\n message: `${plural(missingSkills.length, \"skill\")} missing from disk`,\n details: missingSkills.map((s) => `- ${s.id} (not found in ${s.lookedIn}/)`),\n };\n }\n\n return {\n kind: \"installed\",\n status: \"pass\",\n message: `${ratio(ejectSkills.length, ejectSkills.length, \"eject-mode skill\")} installed`,\n };\n}\n\ntype EjectedSkillCheck = { id: SkillId; installed: boolean; lookedIn: string };\n\nasync function ejectedSkillCheck(\n skill: SkillConfig,\n { projectDir, hosts }: CheckedInstallation,\n): Promise<EjectedSkillCheck> {\n const provider = hosts[skill.scope];\n const dir = skillsDir(provider, skill.scope, projectDir);\n const installed = await fileExists(path.join(dir, skill.id, STANDARD_FILES.SKILL_MD));\n\n return {\n id: skill.id,\n installed,\n lookedIn: skillsPathPrefix(provider, skill.scope, projectDir),\n };\n}\n\n/** Plugin-mode skills are checked against the plugin registry per scope, not on disk. */\nasync function checkPluginSkillsInstalled(\n config: ProjectConfig,\n installation: CheckedInstallation,\n): Promise<CheckResult> {\n const pluginSkills = config.skills.filter((s) => s.origin !== EJECT_SOURCE);\n\n if (pluginSkills.length === 0) {\n return {\n kind: \"plugins\",\n status: \"pass\",\n message: \"No plugin-mode skills configured\",\n };\n }\n\n const scopes = unique(pluginSkills.map((s) => s.scope));\n const missingPerScope = await Promise.all(\n scopes.map((scope) => pluginSkillsMissingAt(scope, pluginSkills, installation)),\n );\n const missingSkills = missingPerScope.flat();\n\n if (missingSkills.length > 0) {\n return {\n kind: \"plugins\",\n status: \"warn\",\n message: `${plural(missingSkills.length, \"skill\")} not installed as plugins`,\n details: missingSkills.map((s) => `- ${s} (no enabled plugin found)`),\n };\n }\n\n return {\n kind: \"plugins\",\n status: \"pass\",\n message: `${ratio(pluginSkills.length, pluginSkills.length, \"plugin-mode skill\")} installed`,\n };\n}\n\nasync function pluginSkillsMissingAt(\n scope: SkillScope,\n pluginSkills: SkillConfig[],\n { projectDir, hosts }: CheckedInstallation,\n): Promise<SkillId[]> {\n const installedIds = await installedPluginSkillIds(\n installBaseDir(projectDir, scope),\n hosts[scope],\n );\n return pluginSkills\n .filter((skill) => skill.scope === scope)\n .filter((skill) => !installedIds.has(skill.id))\n .map((skill) => skill.id);\n}\n\nconst MARKETPLACE_CHOSEN_BY = {\n flag: \"named by this run\",\n env: `named by ${SOURCE_ENV_VAR}`,\n project: \"named by this project's configuration\",\n global: \"named by the global configuration\",\n default: \"nothing here names one, so this is the default\",\n} as const satisfies Record<ResolvedConfig[\"sourceOrigin\"], string>;\n\nfunction howItWasReached(source: string, isLocal: boolean): string {\n return isLocal ? `Read ${source} from disk` : `Fetched ${source} over the network`;\n}\n\n/** Counts the marketplace's own skills, not the loaded matrix, which also holds local ones. */\nfunction reachedMarketplace(result: SourceLoadResult): CheckResult {\n const { source, sourceOrigin } = result.sourceConfig;\n const available = `${plural(result.marketplaceSkillIds.size, \"skill\")} available`;\n const chosenBy = MARKETPLACE_CHOSEN_BY[sourceOrigin];\n\n if (result.unreachable) {\n return {\n kind: \"source\",\n status: \"warn\",\n message: `Could not reach ${source} — read its cached copy instead`,\n details: [available, `The copy at ${result.sourcePath} may be out of date — ${chosenBy}`],\n };\n }\n\n return {\n kind: \"source\",\n status: \"pass\",\n message: `Connected to ${result.isLocal ? \"local\" : \"remote\"}: ${result.sourcePath}`,\n details: [available, `${howItWasReached(source, result.isLocal)} — ${chosenBy}`],\n };\n}\n\nasync function checkSourceReachable({\n projectDir,\n hosts,\n}: CheckedInstallation): Promise<CheckResult> {\n try {\n return reachedMarketplace(\n await loadSkillsMatrixFromSource({ projectDir, provider: hosts.project }),\n );\n } catch (error) {\n return {\n kind: \"source\",\n status: \"fail\",\n message: refusedOr(error, \"Failed to load marketplace\"),\n details: [getErrorMessage(error)],\n };\n }\n}\n\ntype ContentCheck = {\n kind: CheckKind;\n name: string;\n noun: string;\n run: (projectDir: string) => Promise<ContentValidation>;\n};\n\n/** `blocks`: operational rows that would only restate this pass's errors, so stand down. */\ntype GatedContentCheck = ContentCheck & {\n readsConfig: boolean;\n blocks: readonly CheckKind[];\n};\n\n/** Validated first and alone: every other row would cascade from an unreadable config. */\nconst CONFIG_CHECK: ContentCheck = {\n kind: \"content-config\",\n name: \"Config\",\n noun: \"config\",\n run: validateProjectConfigFile,\n};\n\n/** Runs before the operational layer so rows with broken inputs can stand down. */\nconst CONTENT_CHECKS: GatedContentCheck[] = [\n {\n kind: \"content-sources\",\n name: \"Marketplaces\",\n noun: \"marketplace\",\n readsConfig: true,\n // A broken marketplace leaves skills out of the matrix ids resolve against.\n blocks: [\"skills\"],\n run: validateRegisteredSources,\n },\n {\n kind: \"content-plugins\",\n name: \"Plugins\",\n noun: \"plugin\",\n readsConfig: false,\n // An unparseable registry resolves as no installs at all.\n blocks: [\"plugins\"],\n run: validateInstalledPlugins,\n },\n {\n kind: \"content-skills\",\n name: \"Skills\",\n noun: \"skill\",\n // Only the config says which unmarked shared-skills directories are this installation's.\n readsConfig: true,\n // `extractLocalSkill` drops a skill with unusable metadata.\n blocks: [\"skills\"],\n run: validateInstalledSkills,\n },\n {\n kind: \"content-agents\",\n name: \"Agents\",\n noun: \"agent\",\n readsConfig: false,\n // No operational row reads agent file contents.\n blocks: [],\n run: validateInstalledAgents,\n },\n];\n\nfunction contentStatus(errors: number, warnings: number): CheckResult[\"status\"] {\n if (errors > 0) return \"fail\";\n if (warnings > 0) return \"warn\";\n return \"pass\";\n}\n\nfunction contentMessage(noun: string, count: number, errors: number, warnings: number): string {\n // A pass that walked nothing can still report an issue (e.g. an unreadable registry).\n if (errors === 0 && warnings === 0) {\n return count === 0 ? `No ${noun}s to validate` : `${plural(count, noun)} validated`;\n }\n return `${plural(count, noun)}: ${plural(errors, \"error\")}, ${plural(warnings, \"warning\")}`;\n}\n\nfunction formatContentIssue(issue: ContentIssue): string {\n const marker = issue.severity === \"error\" ? \"ERROR\" : \"WARN\";\n return `- [${marker}] ${issue.file}: ${issue.message}`;\n}\n\nfunction toContentResult(check: ContentCheck, validation: ContentValidation): CheckResult {\n const errors = validation.issues.filter((issue) => issue.severity === \"error\").length;\n const warnings = validation.issues.length - errors;\n\n return {\n kind: check.kind,\n status: contentStatus(errors, warnings),\n message: contentMessage(check.noun, validation.count, errors, warnings),\n details: [\n ...validation.notes.map((note) => `- ${note}`),\n ...validation.issues.map(formatContentIssue),\n ],\n };\n}\n\n/** Must clear the longest row name (\"Marketplace Repository\"). */\nconst CHECK_WIDTH = 24;\n\nconst SECTION_INDENT = \" \";\nconst ROW_INDENT = \" \";\n\nconst SECTION_CONTENT = \"Content checks\";\nconst SECTION_OPERATIONAL = \"Operational checks\";\nconst SKIP_NO_INSTALLATION = \"Skipped — no installation here (marketplace repository)\";\nconst SKIP_CONFIG_UNREADABLE = \"Skipped — the configuration that names them cannot be read\";\n\nconst SKIP_AFTER_CONFIG_ERROR = \"Skipped — fix the content errors above first\";\n\nfunction skipRestatingContent(nouns: string[]): string {\n return `Skipped — this row would only restate the ${nouns.join(\" and \")} errors above`;\n}\n\nfunction formatCheckName(name: string): string {\n return name.padEnd(CHECK_WIDTH);\n}\n\nfunction formatStatus(status: CheckResult[\"status\"]): string {\n switch (status) {\n case \"pass\":\n return UI_SYMBOLS.CHECK;\n case \"fail\":\n return UI_SYMBOLS.CROSS;\n case \"warn\":\n return UI_SYMBOLS.DISCOURAGED;\n case \"skip\":\n return UI_SYMBOLS.SKIPPED;\n default: {\n const _exhaustive: never = status;\n return _exhaustive;\n }\n }\n}\n\nconst DETAIL_INDENT = `${ROW_INDENT}${\" \".repeat(CHECK_WIDTH)} `;\n\nfunction formatCheckLine(name: string, result: CheckResult): string[] {\n const headerLine = `${ROW_INDENT}${formatCheckName(name)}${formatStatus(result.status)} ${result.message}`;\n const detailLines = (result.details ?? []).flatMap(indentedDetailLines);\n return [headerLine, ...detailLines];\n}\n\n/** A detail can be a multi-paragraph refusal, so every line is indented. */\nfunction indentedDetailLines(detail: string): string[] {\n return detail\n .split(\"\\n\")\n .filter((line) => line !== \"\")\n .map((line) => `${DETAIL_INDENT}${line}`);\n}\n\nfunction formatSummary(results: CheckResult[]): string {\n const counts = countBy(results, (r) => r.status);\n\n const parts = [\n `${counts.pass ?? 0} passed`,\n plural(counts.warn ?? 0, \"warning\"),\n plural(counts.fail ?? 0, \"error\"),\n ];\n\n return `${SECTION_INDENT}Summary: ${parts.join(\", \")}`;\n}\n\ntype Tip = {\n kind: CheckKind;\n status: CheckResult[\"status\"];\n /** Handed the installation the finding is about, which a command acting on it must be told. */\n line: (provider: Provider | undefined) => string;\n};\n\nconst TIPS: Tip[] = [\n {\n kind: \"agents\",\n status: \"warn\",\n line: (provider) =>\n ` Tip: Run '${commandActingOn(provider, \"compile\")}' to generate missing agent files`,\n },\n {\n kind: \"config\",\n status: \"fail\",\n line: () => ` Tip: Run '${CLI_INVOKE_COMMAND} init' to create or fix configuration`,\n },\n {\n kind: \"config-empty\",\n status: \"warn\",\n line: () =>\n ` Tip: Nothing is configured yet — run '${CLI_INVOKE_COMMAND} init' to choose skills and sub-agents`,\n },\n {\n kind: \"orphans-unowned\",\n status: \"fail\",\n line: (provider) =>\n ` Tip: Nothing declares the files above — '${commandActingOn(provider, \"init --from <id>\")}' writes a configuration that can own them again, or '${commandActingOn(provider, \"uninstall\")}' removes them, the compiled agents included: each file listed carries this CLI's own provenance, which is what that command reads when there is no configuration left`,\n },\n {\n kind: \"skills\",\n status: \"fail\",\n line: () => \" Tip: Check skill IDs in config match available skills\",\n },\n {\n kind: \"installed\",\n status: \"warn\",\n // No command named: `eject skills --force` copies every skill, and only at project scope.\n line: () => \" Tip: Re-eject the missing skills from the marketplace to restore their files\",\n },\n];\n\nfunction commandActingOn(provider: Provider | undefined, command: string): string {\n return `${CLI_INVOKE_COMMAND} ${command}${providerArgument(provider)}`;\n}\n\n/** Once per installation a finding names, and once only where the tip names none. */\nfunction formatTips(results: CheckResult[]): string[] {\n return unique(TIPS.flatMap((tip) => linesOf(tip, results)));\n}\n\nfunction linesOf(tip: Tip, results: CheckResult[]): string[] {\n return results\n .filter((result) => answers(tip, result))\n .map((result) => tip.line(result.provider));\n}\n\nfunction answers(tip: Tip, result: CheckResult): boolean {\n return result.kind === tip.kind && result.status === tip.status;\n}\n\n/** `init` refuses an unreadable config, so the remedy is recreating it, once per such config. */\nasync function recreateConfigTips(\n contentResults: CheckResult[],\n projectDir: string,\n): Promise<string[]> {\n if (!failedContentKinds(contentResults).has(CONFIG_CHECK.kind)) return [];\n\n const failures = await findConfigLoadFailures(projectDir).catch(() => []);\n return failures.map(\n (failure) =>\n ` Tip: There is no automatic repair — recreate the configuration by running ${recreateConfigFrom(failure)}`,\n );\n}\n\nconst INSTALLATIONS_ROW_NAME = \"Installations\";\n\n/** Still a finding beside the blocks below: every acting command refuses to guess between them. */\nasync function checkInstallationsInPlay(\n projectDir: string,\n providers: Provider[],\n): Promise<CheckResult> {\n const finding = await ambiguityFinding(projectDir);\n return {\n kind: \"installations\",\n status: \"fail\",\n message: `${providers.length} installations here, each checked below`,\n details: finding === null ? [] : [`- ${finding}`],\n };\n}\n\nfunction installationHeading(provider: Provider): string {\n return `${SECTION_INDENT}The ${provider} installation`;\n}\n\nconst SOURCE_REPO_ROW_NAME = \"Marketplace Repository\";\n\n/** A skip for a marketplace repository nothing is installed in, `null` for any other directory. */\nasync function uninstalledSourceRepo(projectDir: string): Promise<CheckResult | null> {\n // Aborts on the repository's own unreadable config, which `safeCheck` makes this row's finding.\n if (!(await isSourceRepo(projectDir))) return null;\n return { kind: \"source-repo\", status: \"skip\", message: SKIP_NO_INSTALLATION };\n}\n\nconst LAYOUT_ROW_NAME = \"Layout\";\n\n/** Each scope with this installation's source folder on disk, global first. */\nasync function checkLayout({ projectDir, hosts }: CheckedInstallation): Promise<CheckResult[]> {\n const scopes = await sourceScopesInPlay(projectDir, ({ kind }) => hosts[kind]);\n return scopes.map(toLayoutResult);\n}\n\nfunction toLayoutResult(scope: SourceScope): CheckResult {\n return {\n kind: \"layout\",\n status: \"pass\",\n message: layoutIsCurrent(scopeLabel(scope.kind), scope.relName),\n };\n}\n\nconst PLACEMENTS_ROW_NAME = \"Placements Offered\";\n\n/** Reports, as a row, the refusals other commands would stop on; never refuses itself. */\nasync function checkOfferedPlacements(installation: CheckedInstallation): Promise<CheckResult> {\n const findings = await unofferablePlacements(installation);\n\n if (findings.length === 0) {\n return { kind: \"placements\", status: \"pass\", message: \"Every configured skill is placeable\" };\n }\n\n return {\n kind: \"placements\",\n status: \"fail\",\n message: `${plural(findings.length, \"finding\")} would stop a command acting here`,\n details: findings.map((finding) => `- ${finding}`),\n };\n}\n\nfunction skippedResult(kind: CheckKind): CheckResult {\n return { kind, status: \"skip\", message: \"Skipped (config invalid)\" };\n}\n\nfunction sourceUnreachableSkillsResult(): CheckResult {\n return { kind: \"skills\", status: \"skip\", message: \"Skipped (marketplace unreachable)\" };\n}\n\nfunction skippedContentResult(kind: CheckKind): CheckResult {\n return { kind, status: \"skip\", message: SKIP_CONFIG_UNREADABLE };\n}\n\nfunction failedContentKinds(contentResults: CheckResult[]): ReadonlySet<CheckKind> {\n return new Set(contentResults.filter((r) => r.status === \"fail\").map((r) => r.kind));\n}\n\n/** `null` when no content pass this row reads through failed. */\nfunction contentBlockedResult(\n row: CheckKind,\n failedContent: ReadonlySet<CheckKind>,\n): CheckResult | null {\n const blockingNouns = CONTENT_CHECKS.filter((check) => failedContent.has(check.kind))\n .filter((check) => check.blocks.includes(row))\n .map((check) => check.noun);\n\n if (blockingNouns.length === 0) return null;\n\n return { kind: row, status: \"skip\", message: skipRestatingContent(blockingNouns) };\n}\n\nfunction runContentCheck(check: ContentCheck, projectDir: string): Promise<CheckResult> {\n return safeCheck(check.kind, async () => toContentResult(check, await check.run(projectDir)));\n}\n\nasync function runGatedContentCheck(\n check: GatedContentCheck,\n projectDir: string,\n configUnreadable: boolean,\n): Promise<CheckResult> {\n if (check.readsConfig && configUnreadable) return skippedContentResult(check.kind);\n return runContentCheck(check, projectDir);\n}\n\n/** One item after another, each step's results after the last's. */\nasync function flatMapInTurn<Item, Result>(\n items: readonly Item[],\n step: (item: Item) => Promise<Result[]>,\n): Promise<Result[]> {\n return items.reduce<Promise<Result[]>>(\n async (earlier, item) => [...(await earlier), ...(await step(item))],\n Promise.resolve([]),\n );\n}\n\n/** A throw becomes that row's `fail`, so one broken check can't abort the run. */\nasync function safeCheck<Result extends CheckResult | null>(\n kind: CheckKind,\n fn: () => Result | Promise<Result>,\n): Promise<Result | CheckResult> {\n try {\n return await fn();\n } catch (error) {\n return {\n kind,\n status: \"fail\",\n message: refusedOr(error, \"Check threw\"),\n details: [getErrorMessage(error)],\n };\n }\n}\n\n/** A marketplace the check refused is a finding about the config, not a fault in the check. */\nfunction refusedOr(error: unknown, otherwise: string): string {\n return error instanceof MarketplaceRefusedError ? \"Refused\" : otherwise;\n}\n\nexport default class Doctor extends BaseCommand {\n static summary = \"Diagnose common configuration issues\";\n\n static description = `Run diagnostic checks on your ${DEFAULT_BRANDING.NAME} configuration to identify issues with config validity, skill resolution, agent compilation, and marketplace connectivity.`;\n\n static examples = [\"<%= config.bin %> <%= command.id %>\"];\n\n static flags = {};\n\n async run(): Promise<void> {\n await this.parse(Doctor);\n const projectDir = process.cwd();\n\n // `verbose()` stays off: the loaders' trace would interleave with and restate the rows.\n this.printHeader(await this.resolveBrandingName(projectDir));\n const contentResults = await this.runContentChecks(projectDir);\n const operationalResults = await this.runOperationalChecks(projectDir, contentResults);\n const results = [...contentResults, ...operationalResults];\n\n this.printResults(results, await recreateConfigTips(contentResults, projectDir));\n\n if (results.some((r) => r.status === \"fail\")) {\n this.exit(EXIT_CODES.ERROR);\n }\n }\n\n private printHeader(brandingName: string): void {\n this.log(\"\");\n this.log(`${brandingName} Doctor`);\n this.log(\"\");\n this.log(`${SECTION_INDENT}Checking configuration health...`);\n this.log(\"\");\n }\n\n private async runContentChecks(projectDir: string): Promise<CheckResult[]> {\n this.log(`${SECTION_INDENT}${SECTION_CONTENT}`);\n\n const configResult = await runContentCheck(CONFIG_CHECK, projectDir);\n const configUnreadable = configResult.status === \"fail\";\n\n const rows = await Promise.all(\n CONTENT_CHECKS.map(async (check) => ({\n name: check.name,\n result: await runGatedContentCheck(check, projectDir, configUnreadable),\n })),\n );\n\n const allRows = [{ name: CONFIG_CHECK.name, result: configResult }, ...rows];\n\n for (const row of allRows) {\n this.logCheck(row.name, row.result);\n }\n\n return allRows.map((row) => row.result);\n }\n\n private async runOperationalChecks(\n projectDir: string,\n contentResults: CheckResult[],\n ): Promise<CheckResult[]> {\n this.log(\"\");\n this.log(`${SECTION_INDENT}${SECTION_OPERATIONAL}`);\n\n const failedContent = failedContentKinds(contentResults);\n if (failedContent.has(CONFIG_CHECK.kind)) {\n this.log(`${ROW_INDENT}${SKIP_AFTER_CONFIG_ERROR}`);\n return [];\n }\n\n const providers = await providersInPlay(projectDir);\n if (providers.length > 1) {\n return this.checkEachInstallation(projectDir, providers, failedContent);\n }\n return this.checkTheInstallation(projectDir, failedContent);\n }\n\n private async checkTheInstallation(\n projectDir: string,\n failedContent: ReadonlySet<CheckKind>,\n ): Promise<CheckResult[]> {\n const installation = { projectDir, hosts: hostsOnDisk(projectDir) };\n const configState = await resolveConfigState(installation);\n\n if (configState.kind === \"absent\") {\n const sourceRepo = await safeCheck(\"source-repo\", () => uninstalledSourceRepo(projectDir));\n if (sourceRepo !== null) return this.reportSourceRepo(sourceRepo);\n }\n\n return this.runAllChecks(installation, configState, failedContent);\n }\n\n /** A repository nothing is installed in skips the layer; one whose own config breaks is a row. */\n private reportSourceRepo(sourceRepo: CheckResult): CheckResult[] {\n if (sourceRepo.status === \"skip\") {\n this.log(`${ROW_INDENT}${sourceRepo.message}`);\n return [];\n }\n\n this.logCheck(SOURCE_REPO_ROW_NAME, sourceRepo);\n return [sourceRepo];\n }\n\n /** In turn rather than at once: each block prints as it runs, and each load seats the matrix. */\n private async checkEachInstallation(\n projectDir: string,\n providers: Provider[],\n failedContent: ReadonlySet<CheckKind>,\n ): Promise<CheckResult[]> {\n const installations = await safeCheck(\"installations\", () =>\n checkInstallationsInPlay(projectDir, providers),\n );\n this.logCheck(INSTALLATIONS_ROW_NAME, installations);\n\n const blocks = await flatMapInTurn(providers, (provider) =>\n this.checkOneOf(projectDir, provider, failedContent),\n );\n return [installations, ...blocks];\n }\n\n private async checkOneOf(\n projectDir: string,\n provider: Provider,\n failedContent: ReadonlySet<CheckKind>,\n ): Promise<CheckResult[]> {\n this.log(\"\");\n this.log(installationHeading(provider));\n\n const installation = { projectDir, hosts: hostsOf(provider) };\n const results = await this.runAllChecks(\n installation,\n await resolveConfigState(installation),\n failedContent,\n );\n return results.map((result) => ({ ...result, provider }));\n }\n\n private async runAllChecks(\n installation: CheckedInstallation,\n configState: ConfigState,\n failedContent: ReadonlySet<CheckKind>,\n ): Promise<CheckResult[]> {\n const { result: configResult, config } = checkConfigValid(configState, installation);\n this.logCheck(\"Config Valid\", configResult);\n\n const layoutResults = await this.reportLayout(installation);\n\n const placementsResult = await safeCheck(\"placements\", () =>\n checkOfferedPlacements(installation),\n );\n this.logCheck(PLACEMENTS_ROW_NAME, placementsResult);\n\n // Populates the matrix that the skills check reads, so it runs first.\n const sourceResult = await safeCheck(\"source\", () => checkSourceReachable(installation));\n\n const filteredConfig = config ? filterExcludedEntries(config) : null;\n\n const skillsResult = await this.resolveSkillsCheck(config, sourceResult, failedContent);\n this.logCheck(\"Skills Resolved\", skillsResult);\n\n const agentsResult = await this.resolveAgentsCheck(filteredConfig, installation);\n this.logCheck(\"Agents Compiled\", agentsResult);\n\n const orphansResult = await this.resolveOrphansCheck(config, configState, installation);\n this.logCheck(\"No Orphans\", orphansResult);\n\n const installedResult = await this.resolveInstalledCheck(filteredConfig, installation);\n this.logCheck(\"Skills Installed\", installedResult);\n\n const pluginsResult = await this.resolvePluginsCheck(\n filteredConfig,\n installation,\n failedContent,\n );\n this.logCheck(\"Plugins Installed\", pluginsResult);\n\n this.logCheck(\"Marketplace Reachable\", sourceResult);\n\n return [\n configResult,\n ...layoutResults,\n placementsResult,\n skillsResult,\n agentsResult,\n orphansResult,\n installedResult,\n pluginsResult,\n sourceResult,\n ];\n }\n\n private async reportLayout(installation: CheckedInstallation): Promise<CheckResult[]> {\n const rows = await checkLayout(installation);\n\n for (const row of rows) {\n this.logCheck(LAYOUT_ROW_NAME, row);\n }\n return rows;\n }\n\n /** Skips on a config the checks rejected: ownership can't be judged from a rejected file. */\n private async resolveOrphansCheck(\n config: ProjectConfig | null,\n configState: ConfigState,\n installation: CheckedInstallation,\n ): Promise<CheckResult> {\n if (!config && configState.kind !== \"absent\") return skippedResult(\"orphans\");\n return safeCheck(\"orphans\", () => checkNoOrphans(configState, config, installation));\n }\n\n private async resolveSkillsCheck(\n config: ProjectConfig | null,\n sourceResult: CheckResult,\n failedContent: ReadonlySet<CheckKind>,\n ): Promise<CheckResult> {\n if (!config) return skippedResult(\"skills\");\n\n const blocked = contentBlockedResult(\"skills\", failedContent);\n if (blocked) return blocked;\n if (sourceResult.status === \"fail\") return sourceUnreachableSkillsResult();\n\n return safeCheck(\"skills\", () => checkSkillsResolved(config, matrix));\n }\n\n private async resolveAgentsCheck(\n config: ProjectConfig | null,\n installation: CheckedInstallation,\n ): Promise<CheckResult> {\n if (!config) return skippedResult(\"agents\");\n return safeCheck(\"agents\", () => checkAgentsCompiled(config, installation));\n }\n\n private async resolveInstalledCheck(\n config: ProjectConfig | null,\n installation: CheckedInstallation,\n ): Promise<CheckResult> {\n if (!config) return skippedResult(\"installed\");\n return safeCheck(\"installed\", () => checkSkillsInstalled(config, installation));\n }\n\n private async resolvePluginsCheck(\n config: ProjectConfig | null,\n installation: CheckedInstallation,\n failedContent: ReadonlySet<CheckKind>,\n ): Promise<CheckResult> {\n if (!config) return skippedResult(\"plugins\");\n\n const blocked = contentBlockedResult(\"plugins\", failedContent);\n if (blocked) return blocked;\n\n return safeCheck(\"plugins\", () => checkPluginSkillsInstalled(config, installation));\n }\n\n private logCheck(name: string, result: CheckResult): void {\n for (const line of formatCheckLine(name, result)) {\n this.log(line);\n }\n }\n\n private printResults(results: CheckResult[], recreateTips: string[]): void {\n this.log(\"\");\n this.log(formatSummary(results));\n\n const tips = [...formatTips(results), ...recreateTips];\n if (tips.length > 0) {\n this.log(\"\");\n for (const tip of tips) {\n this.log(tip);\n }\n }\n\n this.log(\"\");\n }\n}\n","/**\n * `doctor`'s reads of one installation, each asked of a named provider rather than the one\n * `providerInUse` picks, so one run can report on both installations a scope holds. Two re-express\n * helpers that read the provider only through process state — `getVerifiedPluginInstallPaths` and\n * `unofferablePlacementsFound` — and answer as they do when the hosts are read off the disk.\n */\n\nimport os from \"os\";\n\nimport { ConfigLoadError, loadProjectConfigFromDir } from \"../configuration/project-config.js\";\nimport { scopeRootsInPlay } from \"../installation/source-scopes.js\";\nimport { declaresNoContent } from \"../installation/installation.js\";\nimport { detectInstallations } from \"../installation/detect-installations.js\";\nimport { isHomeDirectory } from \"../installation/is-home-directory.js\";\nimport { providerInUse } from \"../installation/install-layout.js\";\nimport { hostFor } from \"../hosts/host-for.js\";\nimport type { HostPlugin } from \"../hosts/plugin-host.js\";\nimport { refuseUnofferedPlacements } from \"../hosts/offered-placements.js\";\nimport { getPluginManifestPath } from \"../plugins/plugin-finder.js\";\nimport { parseMarketplacePluginRef } from \"../plugins/plugin-ref.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport { fileExists } from \"../../utils/fs.js\";\nimport { verbose } from \"../../utils/logger.js\";\nimport type { Provider } from \"../../consts.js\";\nimport type { ProjectConfig, SkillConfig, SkillScope } from \"../../types/index.js\";\n\n/**\n * The provider each scope's paths are read with: off the disk, as a run naming no provider reads\n * them, or one installation's for both, as a run naming `--provider` does. Never set as the run's\n * provider, so one doctor run can ask of each installation in turn.\n */\nexport type Hosts = Record<SkillScope, Provider>;\n\n/** One installation's rows: the directory they are about and the hosts its paths resolve with. */\nexport type CheckedInstallation = { projectDir: string; hosts: Hosts };\n\nexport function hostsOnDisk(projectDir: string): Hosts {\n return { project: providerInUse(projectDir), global: providerInUse(os.homedir()) };\n}\n\nexport function hostsOf(provider: Provider): Hosts {\n return { project: provider, global: provider };\n}\n\n/** The project's installations, or the global ones where the project holds none. */\nexport async function providersInPlay(projectDir: string): Promise<Provider[]> {\n const found = await detectInstallations(projectDir);\n const inTheProject = found.filter((installation) => installation.scope === \"project\");\n const inPlay = inTheProject.length > 0 ? inTheProject : found;\n return inPlay.map((installation) => installation.provider);\n}\n\n/**\n * Unreadable only where a scope holds two installations: the content layer reads the configs in\n * use, so a broken one of those has already stood the operational layer down.\n */\nexport type ConfigState =\n | { kind: \"absent\" }\n | { kind: \"unreadable\"; failure: ConfigLoadError }\n | { kind: \"declares-nothing\"; config: ProjectConfig }\n | { kind: \"loaded\"; config: ProjectConfig; inherited: boolean };\n\n/** The project's own config, else the global one it inherits, each read with its scope's host. */\nexport async function resolveConfigState({\n projectDir,\n hosts,\n}: CheckedInstallation): Promise<ConfigState> {\n try {\n return await readConfigState(projectDir, hosts);\n } catch (error) {\n if (error instanceof ConfigLoadError) return { kind: \"unreadable\", failure: error };\n throw error;\n }\n}\n\nasync function readConfigState(projectDir: string, hosts: Hosts): Promise<ConfigState> {\n const own = await loadProjectConfigFromDir(projectDir, hosts.project);\n if (own && !declaresNoContent(own.config)) {\n return { kind: \"loaded\", config: own.config, inherited: false };\n }\n\n const inherited = isHomeDirectory(projectDir)\n ? null\n : await loadProjectConfigFromDir(os.homedir(), hosts.global);\n if (inherited && !declaresNoContent(inherited.config)) {\n return { kind: \"loaded\", config: inherited.config, inherited: true };\n }\n\n return own ? { kind: \"declares-nothing\", config: own.config } : { kind: \"absent\" };\n}\n\n/**\n * `getVerifiedPluginInstallPaths` asked of a named host rather than the one in use at `baseDir`:\n * enabled plugins whose manifest is still on disk, none at all from a registry it cannot read.\n */\nexport async function installedPluginSkillIds(\n baseDir: string,\n provider: Provider,\n): Promise<ReadonlySet<string>> {\n const plugins = await verifiedPlugins(baseDir, provider);\n return new Set(plugins.map((plugin) => parseMarketplacePluginRef(plugin.pluginKey)));\n}\n\nasync function verifiedPlugins(baseDir: string, provider: Provider): Promise<HostPlugin[]> {\n const enabled = (await pluginsListedBy(provider, baseDir)).filter((plugin) => plugin.enabled);\n const onDisk = await Promise.all(\n enabled.map((plugin) => fileExists(getPluginManifestPath(plugin.installPath))),\n );\n return enabled.filter((_, index) => onDisk[index] === true);\n}\n\nasync function pluginsListedBy(provider: Provider, baseDir: string): Promise<HostPlugin[]> {\n try {\n return await hostFor(provider).listPlugins(baseDir);\n } catch (error) {\n verbose(`Failed to list installed plugins: ${getErrorMessage(error)}`);\n return [];\n }\n}\n\n/**\n * `unofferablePlacementsFound` asked of each scope's named host: both scopes, each refused by its\n * own host, since the two can be on different providers. Project first, as that one walks them.\n */\nexport async function unofferablePlacements({\n projectDir,\n hosts,\n}: CheckedInstallation): Promise<string[]> {\n const projectFirst = [...scopeRootsInPlay(projectDir)].reverse();\n const findings = await Promise.all(\n projectFirst.map(({ kind, root }) => unofferablePlacementIn(root, hosts[kind])),\n );\n return findings.filter((finding): finding is string => finding !== null);\n}\n\nasync function unofferablePlacementIn(root: string, provider: Provider): Promise<string | null> {\n const skills = await configuredSkillsAt(root, provider);\n if (skills === null) return null;\n\n try {\n refuseUnofferedPlacements(skills, hostFor(provider));\n return null;\n } catch (error) {\n return getErrorMessage(error);\n }\n}\n\n/** Degrades on `ConfigLoadError` only, which the Config Valid row reports by name. */\nasync function configuredSkillsAt(root: string, provider: Provider): Promise<SkillConfig[] | null> {\n try {\n const loaded = await loadProjectConfigFromDir(root, provider);\n return loaded?.config.skills ?? null;\n } catch (error) {\n if (error instanceof ConfigLoadError) return null;\n throw error;\n }\n}\n","/**\n * What an installation holds that its configuration does not account for: `doctor`'s No Orphans\n * row. Agent files are judged against the configuration whatever wrote them; a skill folder only\n * when it carries `forkedFrom`, so a user's own folder is never an orphan.\n */\n\nimport path from \"path\";\nimport { groupBy } from \"remeda\";\n\nimport type { CheckedInstallation, ConfigState, Hosts } from \"./installation-reads.js\";\nimport { listAgentFilesOf } from \"../agents/index.js\";\nimport {\n agentFilesWithOurProvenanceIn,\n listSkillDirsWithOurProvenance,\n skillDirsWithOurProvenanceIn,\n} from \"../content-validator.js\";\nimport {\n agentCodec,\n agentsDir,\n skillsDir,\n type AgentCodec,\n} from \"../installation/install-layout.js\";\nimport { directoryExists } from \"../../utils/fs.js\";\nimport { typedValues } from \"../../utils/typed-object.js\";\nimport type { ProjectConfig, SkillScope } from \"../../types/index.js\";\n\nexport type Orphans = { skills: string[]; agents: string[] };\n\nexport type Ownership = {\n /** Display paths of what this CLI provably wrote into a folder no configuration declares. */\n unowned: Orphans;\n /** File and folder names, not paths, in a declared folder its configuration does not claim. */\n orphans: Orphans;\n};\n\n/**\n * One folder of one kind, once however many scopes share it, and the names a configuration claims\n * in it: `null` where none declares its scope, so only what this CLI provably wrote there is named.\n */\ntype JudgedFolder = { dir: string; claimed: ReadonlySet<string> | null };\n\ntype JudgedAgentFolder = JudgedFolder & { codec: AgentCodec };\n\n/** `config` is `null` only where `state` is absent: a config the checks rejected is not judged. */\nexport async function judgeOwnership(\n state: ConfigState,\n config: ProjectConfig | null,\n installation: CheckedInstallation,\n): Promise<Ownership> {\n const agentFolders = agentFoldersToJudge(state, config, installation);\n const skillFolders = skillFoldersToJudge(state, config, installation);\n\n const [unowned, orphans] = await Promise.all([\n unownedIn(agentFolders, skillFolders),\n orphansIn(agentFolders, skillFolders),\n ]);\n return { unowned, orphans };\n}\n\nfunction agentFoldersToJudge(\n state: ConfigState,\n config: ProjectConfig | null,\n { projectDir, hosts }: CheckedInstallation,\n): JudgedAgentFolder[] {\n return oncePerFolder(\n scopesToJudge(state, hosts).map((scope) => ({\n dir: agentsDir(hosts[scope], scope, projectDir),\n codec: agentCodec(hosts[scope]),\n claimed: claimed(state, scope, config && agentNamesClaimedIn(config, scope)),\n })),\n );\n}\n\nfunction skillFoldersToJudge(\n state: ConfigState,\n config: ProjectConfig | null,\n { projectDir, hosts }: CheckedInstallation,\n): JudgedFolder[] {\n return oncePerFolder(\n scopesToJudge(state, hosts).map((scope) => ({\n dir: skillsDir(hosts[scope], scope, projectDir),\n claimed: claimed(state, scope, config && skillIdsClaimedIn(config, scope)),\n })),\n );\n}\n\n/**\n * Project first. Beside its own config a project is judged in the global folders only when they\n * are its provider's: another provider's global ones belong to an installation this config does\n * not describe.\n */\nfunction scopesToJudge(state: ConfigState, hosts: Hosts): SkillScope[] {\n const ownConfig = state.kind !== \"absent\" && !inherits(state);\n return ownConfig && hosts.global !== hosts.project ? [\"project\"] : [\"project\", \"global\"];\n}\n\nfunction inherits(state: ConfigState): boolean {\n return state.kind === \"loaded\" && state.inherited;\n}\n\n/** `null` for a scope no configuration declares: none at all, or a project inheriting one. */\nfunction claimed(\n state: ConfigState,\n scope: SkillScope,\n names: string[] | null,\n): ReadonlySet<string> | null {\n if (names === null || state.kind === \"absent\") return null;\n if (inherits(state) && scope === \"project\") return null;\n return new Set(names);\n}\n\nfunction agentNamesClaimedIn(config: ProjectConfig, scope: SkillScope): string[] {\n return config.agents.filter((agent) => claimsAt(agent, scope)).map((agent) => agent.name);\n}\n\nfunction skillIdsClaimedIn(config: ProjectConfig, scope: SkillScope): string[] {\n return config.skills.filter((skill) => claimsAt(skill, scope)).map((skill) => skill.id);\n}\n\n/** An excluded global entry still serves other projects; an excluded project one serves nothing. */\nfunction claimsAt(entry: { scope: SkillScope; excluded?: boolean }, scope: SkillScope): boolean {\n return entry.scope === scope && (scope === \"global\" || !entry.excluded);\n}\n\n/** Two scopes can share a folder (Claude's at home): judged once, against both claims. */\nfunction oncePerFolder<Folder extends JudgedFolder>(folders: Folder[]): Folder[] {\n return typedValues(groupBy(folders, (folder) => folder.dir)).map((sharing) =>\n sharing.reduce(joinClaims),\n );\n}\n\nfunction joinClaims<Folder extends JudgedFolder>(into: Folder, from: Folder): Folder {\n if (into.claimed === null) return from;\n if (from.claimed === null) return into;\n return { ...into, claimed: new Set([...into.claimed, ...from.claimed]) };\n}\n\nasync function unownedIn(\n agentFolders: JudgedAgentFolder[],\n skillFolders: JudgedFolder[],\n): Promise<Orphans> {\n const [skills, agents] = await Promise.all([\n Promise.all(\n skillFolders.filter(isUnclaimed).map(({ dir }) => skillDirsWithOurProvenanceIn(dir)),\n ),\n Promise.all(\n agentFolders\n .filter(isUnclaimed)\n .map(({ dir, codec }) => agentFilesWithOurProvenanceIn(dir, codec)),\n ),\n ]);\n return { skills: skills.flat(), agents: agents.flat() };\n}\n\nasync function orphansIn(\n agentFolders: JudgedAgentFolder[],\n skillFolders: JudgedFolder[],\n): Promise<Orphans> {\n const [skills, agents] = await Promise.all([\n Promise.all(skillFolders.map(unclaimedSkillDirs)),\n Promise.all(agentFolders.map(unclaimedAgentFiles)),\n ]);\n return { skills: skills.flat(), agents: agents.flat() };\n}\n\nfunction isUnclaimed(folder: JudgedFolder): boolean {\n return folder.claimed === null;\n}\n\nasync function unclaimedSkillDirs({ dir, claimed }: JudgedFolder): Promise<string[]> {\n if (claimed === null) return [];\n const ours = await listSkillDirsWithOurProvenance(dir);\n return ours.filter((name) => !claimed.has(name));\n}\n\nasync function unclaimedAgentFiles({ dir, codec, claimed }: JudgedAgentFolder): Promise<string[]> {\n if (claimed === null || !(await directoryExists(dir))) return [];\n const files = await listAgentFilesOf(dir, codec);\n return files.filter((file) => !claimed.has(path.basename(file, codec.extension)));\n}\n","import os from \"os\";\nimport path from \"path\";\nimport { partition } from \"remeda\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { STANDARD_FILES } from \"../consts.js\";\nimport { directoryExists, fileExists, listDirectories } from \"../utils/fs.js\";\nimport { listAgentMdFiles, splitAgentsByProvenance } from \"./agents/index.js\";\nimport { readSkillMetadata } from \"./loading/index.js\";\nimport {\n configDirsInPlay,\n findConfigLoadFailures,\n isLocalSource,\n loadInstalledConfig,\n resolvePrimarySourceEntry,\n type ConfigLoadError,\n type LoadedProjectConfig,\n type SourceEntry,\n} from \"./configuration/index.js\";\nimport { isHomeDirectory, resolveInstallPaths } from \"./installation/index.js\";\nimport { getInstalledConfigPath } from \"./installation/install-base-dir.js\";\nimport type { AgentCodec } from \"./installation/install-layout.js\";\nimport {\n getInstalledPluginsRegistryPath,\n getProjectPluginsDir,\n getUserPluginsDir,\n listPluginDirNames,\n listRegisteredPluginInstalls,\n validateAgentFrontmatter,\n validateAllPlugins,\n validatePlugin,\n validateSkillFrontmatter,\n type ResolvedPlugin,\n} from \"./plugins/index.js\";\nimport { splitMetadataValidationIssues, validateSkillMetadata } from \"./schemas.js\";\nimport { readForkedFromMetadata } from \"./skills/index.js\";\nimport { isSourceRepo, validateSource, type MarketplaceReader } from \"./source-validator.js\";\nimport { invalidResult, mergeValidationResults, validResult } from \"./validation-result.js\";\nimport { scopeLabel } from \"../utils/messages.js\";\nimport { plural } from \"../utils/string.js\";\nimport type { ValidationResult } from \"../types/index.js\";\n\n/** How a source repository under the cwd is labelled when it is not a registered source. */\nconst CWD_SOURCE_NAME = \"current directory\";\n\nexport type ContentIssue = {\n severity: \"error\" | \"warning\";\n /** The file or directory a reader has to open to fix the issue. */\n file: string;\n message: string;\n};\n\n/** `notes` records which sources were reached and which skipped; neither errors nor warnings. */\nexport type ContentValidation = {\n count: number;\n issues: ContentIssue[];\n notes: string[];\n};\n\nconst NOTHING_VALIDATED: ContentValidation = { count: 0, issues: [], notes: [] };\n\nfunction mergeValidations(parts: ContentValidation[]): ContentValidation {\n return parts.reduce(\n (acc, part) => ({\n count: acc.count + part.count,\n issues: [...acc.issues, ...part.issues],\n notes: [...acc.notes, ...part.notes],\n }),\n NOTHING_VALIDATED,\n );\n}\n\nfunction displayDir(absolutePath: string): string {\n const home = os.homedir();\n if (absolutePath === home) return \"~\";\n if (absolutePath.startsWith(home + path.sep)) {\n return `~${path.sep}${path.relative(home, absolutePath)}`;\n }\n return absolutePath;\n}\n\nfunction toIssues(file: string, result: ValidationResult): ContentIssue[] {\n return [\n ...result.errors.map((message) => ({ severity: \"error\" as const, file, message })),\n ...result.warnings.map((message) => ({ severity: \"warning\" as const, file, message })),\n ];\n}\n\nconst CONFIG_UNREADABLE = \"exists but could not be loaded\";\n\n/** Reported here, since every operational row reads the config; an absent one is no finding. */\nexport async function validateProjectConfigFile(projectDir: string): Promise<ContentValidation> {\n const [present, failures] = await Promise.all([\n countExistingConfigs(projectDir),\n findConfigLoadFailures(projectDir),\n ]);\n\n return { count: present, issues: failures.map(toUnreadableConfigIssue), notes: [] };\n}\n\n/** Led by whose config it is: from a project, its own or the inherited global one. */\nfunction toUnreadableConfigIssue(failure: ConfigLoadError): ContentIssue {\n return {\n severity: \"error\",\n file: `${scopeLabel(failure.scope)}'s ${displayDir(failure.configPath)}`,\n message: `${CONFIG_UNREADABLE}: ${failure.reason}`,\n };\n}\n\nasync function countExistingConfigs(projectDir: string): Promise<number> {\n const present = await Promise.all(\n configDirsInPlay(projectDir).map((dir) => fileExists(getInstalledConfigPath(dir))),\n );\n return present.filter(Boolean).length;\n}\n\n/** The local marketplace, plus the cwd when it is a skills source repo; remote is skipped. */\nexport async function validateRegisteredSources(projectDir: string): Promise<ContentValidation> {\n // Degrades on an unreadable config: `safeCheck` turns a throw into a failed row.\n const primary = await resolvePrimarySourceEntry(projectDir);\n const registered = [primary];\n const remote = registered.filter((source) => !isLocalSource(source.url));\n const local = await localSourcesToValidate(projectDir, registered);\n\n const outcomes = await Promise.all(\n local.map((source) => validateOneSource(source, readerFor(projectDir, source))),\n );\n\n return {\n count: local.length,\n issues: outcomes.flatMap((outcome) => outcome.issues),\n notes: [\n ...outcomes.map((outcome) => outcome.note),\n ...remote.map((source) => `${source.name} (${source.url}) — skipped (remote)`),\n ],\n };\n}\n\nasync function localSourcesToValidate(\n projectDir: string,\n registered: SourceEntry[],\n): Promise<SourceEntry[]> {\n const local = registered.filter((source) => isLocalSource(source.url));\n const alreadyCovered = local.some((source) => isCwdMarketplace(projectDir, source));\n\n if (alreadyCovered || !(await isSourceRepo(projectDir))) return local;\n\n return [...local, { name: CWD_SOURCE_NAME, url: projectDir }];\n}\n\n/** Whether this marketplace IS the directory the command ran in, however the config spells it. */\nfunction isCwdMarketplace(projectDir: string, source: SourceEntry): boolean {\n return path.resolve(projectDir, source.url) === projectDir;\n}\n\n/** The one place knowing the cwd and each marketplace path; the cwd entry answers `\"author\"`. */\nfunction readerFor(projectDir: string, source: SourceEntry): MarketplaceReader {\n return isCwdMarketplace(projectDir, source) ? \"author\" : \"consumer\";\n}\n\ntype SourceOutcome = { note: string; issues: ContentIssue[] };\n\nasync function validateOneSource(\n source: SourceEntry,\n reader: MarketplaceReader,\n): Promise<SourceOutcome> {\n const label = `${source.name} (${source.url})`;\n try {\n const result = await validateSource(source.url, reader);\n return { note: `${label} — ${plural(result.skillCount, \"skill\")}`, issues: result.issues };\n } catch (error) {\n return {\n note: `${label} — failed`,\n issues: [{ severity: \"error\", file: source.url, message: getErrorMessage(error) }],\n };\n }\n}\n\nexport async function validateInstalledPlugins(projectDir: string): Promise<ContentValidation> {\n const dirs = [\n getUserPluginsDir(),\n ...(isHomeDirectory(projectDir) ? [] : [getProjectPluginsDir(projectDir)]),\n ];\n return mergeValidations(await Promise.all(dirs.map(validatePluginsDirectory)));\n}\n\nasync function validatePluginsDirectory(pluginsDir: string): Promise<ContentValidation> {\n if (!(await directoryExists(pluginsDir))) return NOTHING_VALIDATED;\n\n if (await fileExists(getInstalledPluginsRegistryPath(pluginsDir))) {\n const registryValidation = await validateRegistryPlugins(pluginsDir);\n if (registryValidation !== undefined) return registryValidation;\n }\n\n const pluginDirs = await listPluginDirNames(pluginsDir);\n if (pluginDirs.length === 0) return NOTHING_VALIDATED;\n\n const { results } = await validateAllPlugins(pluginsDir);\n\n return {\n count: results.length,\n issues: results.flatMap(({ name, result }) => toIssues(name, result)),\n notes: [],\n };\n}\n\n/** Undefined when the registry records no installs; the caller then scans direct children. */\nasync function validateRegistryPlugins(pluginsDir: string): Promise<ContentValidation | undefined> {\n let installs: ResolvedPlugin[];\n try {\n installs = await listRegisteredPluginInstalls(pluginsDir);\n } catch (error) {\n return {\n count: 0,\n issues: [\n {\n severity: \"error\",\n file: displayDir(getInstalledPluginsRegistryPath(pluginsDir)),\n message: getErrorMessage(error),\n },\n ],\n notes: [],\n };\n }\n\n if (installs.length === 0) return undefined;\n\n // A vanished installPath fails validatePlugin's structure check rather than crashing.\n const results = await Promise.all(\n installs.map(async ({ pluginKey, installPath }) =>\n toIssues(pluginKey, await validatePlugin(installPath)),\n ),\n );\n\n return { count: installs.length, issues: results.flat(), notes: [] };\n}\n\n/**\n * Only skills this installation owns, since `~/.claude/skills/` is shared: a directory is ours when\n * a config in play names its id or it carries `forkedFrom`. Any other is named, not judged.\n */\nexport async function validateInstalledSkills(projectDir: string): Promise<ContentValidation> {\n const configuredIds = await configuredSkillIds(projectDir);\n return mergeValidations(\n await Promise.all(\n installedDirs(projectDir, \"skillsDir\").map((dir) =>\n validateSkillsDirectory(dir, configuredIds),\n ),\n ),\n );\n}\n\n/** Every skill id the configs this run reads name, across both scopes and both install modes. */\nasync function configuredSkillIds(projectDir: string): Promise<ReadonlySet<string>> {\n const loaded = await Promise.all(\n configDirsInPlay(projectDir).map((dir) => loadInstalledConfig(dir)),\n );\n return new Set(loaded.flatMap(configuredIdsOf));\n}\n\nfunction configuredIdsOf(loaded: LoadedProjectConfig | null): string[] {\n if (!loaded) return [];\n return loaded.config.skills.map((skill) => skill.id);\n}\n\nexport async function validateInstalledAgents(projectDir: string): Promise<ContentValidation> {\n return mergeValidations(\n await Promise.all(installedDirs(projectDir, \"agentsDir\").map(validateAgentsDirectory)),\n );\n}\n\n/** At the home directory both scopes resolve to one place, walked once. */\nfunction installedDirs(projectDir: string, key: \"skillsDir\" | \"agentsDir\"): string[] {\n const global = resolveInstallPaths(projectDir, \"global\")[key];\n if (isHomeDirectory(projectDir)) return [global];\n return [global, resolveInstallPaths(projectDir, \"project\")[key]];\n}\n\n/** Skill folders this CLI provably wrote, as `uninstall` takes them, as display paths. */\nexport async function skillDirsWithOurProvenanceIn(skillsDir: string): Promise<string[]> {\n return listDisplayPaths(skillsDir, listSkillDirsWithOurProvenance);\n}\n\n/** Compiled agent files this CLI provably wrote, as `uninstall` takes them, as display paths. */\nexport async function agentFilesWithOurProvenanceIn(\n agentsDir: string,\n codec: AgentCodec,\n): Promise<string[]> {\n return listDisplayPaths(agentsDir, (dir) => listAgentFilesWithOurProvenance(dir, codec));\n}\n\n/**\n * Asks `splitAgentsByProvenance`, as `uninstall` does, so this lists exactly what it would remove.\n */\nasync function listAgentFilesWithOurProvenance(\n agentsDir: string,\n codec: AgentCodec,\n): Promise<string[]> {\n const { marked } = await splitAgentsByProvenance(agentsDir, codec);\n return marked.map((name) => `${name}${codec.extension}`);\n}\n\n/** By `forkedFrom` alone, as `uninstall` reads it; unreadable metadata carries none. */\nexport async function listSkillDirsWithOurProvenance(skillsDir: string): Promise<string[]> {\n const [ours] = await partitionByVerdict(await listDirectories(skillsDir), (name) =>\n carriesOurProvenance(skillsDir, name),\n );\n return ours;\n}\n\nasync function partitionByVerdict(\n names: string[],\n verdict: (name: string) => Promise<boolean>,\n): Promise<[string[], string[]]> {\n const verdicts = await Promise.all(names.map(verdict));\n return partition(names, (_, index) => verdicts[index] === true);\n}\n\nasync function listDisplayPaths(\n dir: string,\n listEntries: (dir: string) => Promise<string[]>,\n): Promise<string[]> {\n if (!(await directoryExists(dir))) return [];\n const entries = await listEntries(dir);\n return entries.map((entry) => displayDir(path.join(dir, entry)));\n}\n\nasync function validateSkillsDirectory(\n skillsDir: string,\n configuredIds: ReadonlySet<string>,\n): Promise<ContentValidation> {\n if (!(await directoryExists(skillsDir))) return NOTHING_VALIDATED;\n\n const skillDirs = await listDirectories(skillsDir);\n if (skillDirs.length === 0) return NOTHING_VALIDATED;\n\n const [ours, foreign] = await partitionByVerdict(skillDirs, (name) =>\n isOurSkillDirectory(skillsDir, name, configuredIds),\n );\n\n const results = await Promise.all(\n ours.map(async (name) => {\n const skillDir = path.join(skillsDir, name);\n return toIssues(displayDir(skillDir), await validateInstalledSkill(skillDir));\n }),\n );\n\n return {\n count: ours.length,\n issues: results.flat(),\n notes: foreign.map((name) => foreignSkillNote(skillsDir, name)),\n };\n}\n\n/** Either claim this installation has on a skill directory. */\nasync function isOurSkillDirectory(\n skillsDir: string,\n name: string,\n configuredIds: ReadonlySet<string>,\n): Promise<boolean> {\n if (configuredIds.has(name)) return true;\n return carriesOurProvenance(skillsDir, name);\n}\n\n/** The `forkedFrom` block the copier stamps; `uninstall` asks exactly this. */\nasync function carriesOurProvenance(skillsDir: string, name: string): Promise<boolean> {\n return (await readForkedFromMetadata(path.join(skillsDir, name))) !== null;\n}\n\n/** Named so the count and the listing do not silently disagree; not a warning. */\nfunction foreignSkillNote(skillsDir: string, name: string): string {\n return `${displayDir(path.join(skillsDir, name))} — not installed by this CLI and named by no configuration here: not validated`;\n}\n\nasync function validateAgentsDirectory(agentsDir: string): Promise<ContentValidation> {\n if (!(await directoryExists(agentsDir))) return NOTHING_VALIDATED;\n\n const agentFiles = await listAgentMdFiles(agentsDir);\n if (agentFiles.length === 0) return NOTHING_VALIDATED;\n\n const results = await Promise.all(\n agentFiles.map(async (fileName) => {\n const agentPath = path.join(agentsDir, fileName);\n return toIssues(displayDir(agentPath), await validateAgentFrontmatter(agentPath));\n }),\n );\n\n return { count: agentFiles.length, issues: results.flat(), notes: [] };\n}\n\nasync function validateInstalledSkill(skillDir: string): Promise<ValidationResult> {\n const [skillMd, metadata] = await Promise.all([\n validateSkillFile(skillDir, STANDARD_FILES.SKILL_MD, validateSkillFrontmatter),\n validateSkillFile(skillDir, STANDARD_FILES.METADATA_YAML, validateInstalledSkillMetadata),\n ]);\n\n return mergeValidationResults([skillMd, metadata]);\n}\n\n/** One of an installed skill's files judged by `validate`, or the error of its absence. */\nasync function validateSkillFile(\n skillDir: string,\n fileName: string,\n validate: (filePath: string) => Promise<ValidationResult>,\n): Promise<ValidationResult> {\n const filePath = path.join(skillDir, fileName);\n if (!(await fileExists(filePath))) return invalidResult(`Missing ${fileName}`);\n return validate(filePath);\n}\n\nasync function validateInstalledSkillMetadata(metadataPath: string): Promise<ValidationResult> {\n // The same verdict compile and discovery use; the strict published-skill checks layer on top.\n const read = await readSkillMetadata(metadataPath);\n if (!read.usable) {\n return invalidResult(`${STANDARD_FILES.METADATA_YAML}: ${read.reason}`);\n }\n\n const metadata = read.metadata;\n const result = validateSkillMetadata(metadata);\n if (result.success) {\n return validResult();\n }\n\n const { errors, warnings } = splitMetadataValidationIssues(result.error, metadata);\n return {\n valid: errors.length === 0,\n errors: errors.map((e) => `${STANDARD_FILES.METADATA_YAML}: ${e}`),\n warnings: warnings.map((w) => `${STANDARD_FILES.METADATA_YAML}: ${w}`),\n };\n}\n","import path from \"path\";\nimport { isRecord } from \"../utils/type-guards.js\";\nimport { parse as parseYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport { glob, readFile, fileExists, directoryExists } from \"../utils/fs\";\nimport {\n DIRS,\n MARKETPLACE_JSON,\n PLUGIN_MANIFEST_DIR,\n SKILL_CATEGORIES_PATH,\n SKILL_RULES_PATH,\n SKILLS_DIR_PATH,\n STACKS_FILE_PATH,\n STANDARD_FILES,\n} from \"../consts\";\nimport {\n agentYamlGenerationSchema,\n metadataValidationSchema,\n splitMetadataValidationIssues,\n validateSkillMetadata,\n skillCategoriesFileSchema,\n skillRulesFileSchema,\n stackConfigValidationSchema,\n stacksConfigSchema,\n} from \"./schemas\";\nimport { parseFrontmatter } from \"./loading/loader\";\nimport { ConfigDefaultExportError, loadConfig, loadSourceRepoConfig } from \"./configuration\";\nimport type { MatrixHealthIssue } from \"./matrix\";\nimport { matrixHealthIssues } from \"./matrix/matrix-health-check\";\nimport {\n loadSkillsMatrixFromSource,\n MarketplaceManifestRequiredError,\n} from \"./loading/source-loader\";\nimport { MarketplaceNameRefusedError } from \"./loading/source-fetcher\";\nimport { matrix } from \"./matrix/matrix-provider\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport { formatZodErrors } from \"./schema-validator\";\n\ntype SourceValidationIssue = {\n severity: \"error\" | \"warning\";\n file: string;\n message: string;\n};\n\nexport type SourceValidationResult = {\n issues: SourceValidationIssue[];\n skillCount: number;\n errorCount: number;\n warningCount: number;\n};\n\n/**\n * `\"author\"` when the marketplace IS the directory the command ran in, else `\"consumer\"`. It\n * changes one finding: a dangling rule slug is the author's to fix and a consumer's to ignore.\n */\nexport type MarketplaceReader = \"author\" | \"consumer\";\n\n/** True when `dir` carries a skills tree, at `src/skills/` or where its source config points. */\nexport async function isSourceRepo(dir: string): Promise<boolean> {\n // Aborts on an unreadable config; `doctor` catches it via `safeCheck`.\n const sourceConfig = await loadSourceRepoConfig(dir);\n return directoryExists(path.join(dir, sourceConfig?.skillsDir ?? SKILLS_DIR_PATH));\n}\n\nfunction isSnakeCase(key: string): boolean {\n return /[a-z]_[a-z]/.test(key);\n}\n\nfunction checkSnakeCaseKeys(rawMetadata: unknown, relPath: string): SourceValidationIssue[] {\n if (!isRecord(rawMetadata)) return [];\n\n return Object.keys(rawMetadata)\n .filter(isSnakeCase)\n .map((key) => ({\n severity: \"error\" as const,\n file: relPath,\n message: `Key '${key}' uses snake_case — use camelCase instead`,\n }));\n}\n\n/** A warning, not an error: the loader still registers the skill by its id. */\nfunction checkDirNameMatchesSkillId(\n skillId: string,\n relPath: string,\n dirName: string,\n): SourceValidationIssue[] {\n if (skillId === dirName) return [];\n return [\n {\n severity: \"warning\",\n file: relPath,\n message: `Directory name '${dirName}' does not match skill id '${skillId}'`,\n },\n ];\n}\n\nasync function checkSkillDirName(\n skillsDir: string,\n skillsDirRelPath: string,\n skillDir: string,\n): Promise<SourceValidationIssue[]> {\n const dirName = path.basename(skillDir);\n const skillMdRelPath = path.join(skillsDirRelPath, skillDir, STANDARD_FILES.SKILL_MD);\n\n try {\n const content = await readFile(path.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD));\n const frontmatter = parseFrontmatter(content, skillMdRelPath);\n\n if (frontmatter === null) {\n return [\n {\n severity: \"warning\",\n file: skillMdRelPath,\n message: `Cannot verify directory name '${dirName}': missing or invalid ${STANDARD_FILES.SKILL_MD} frontmatter`,\n },\n ];\n }\n\n return checkDirNameMatchesSkillId(frontmatter.name, skillMdRelPath, dirName);\n } catch (error) {\n return [\n {\n severity: \"warning\",\n file: skillMdRelPath,\n message: `Cannot verify directory name '${dirName}': ${getErrorMessage(error)}`,\n },\n ];\n }\n}\n\nfunction validateSkillFilePairs(\n skillMdDirs: Set<string>,\n metadataDirs: Set<string>,\n skillsDir: string,\n): SourceValidationIssue[] {\n const missingMetadata = [...skillMdDirs]\n .filter((dir) => !metadataDirs.has(dir))\n .map((dir) => ({\n severity: \"error\" as const,\n file: path.join(skillsDir, dir),\n message: `Missing ${STANDARD_FILES.METADATA_YAML} — skill directory has ${STANDARD_FILES.SKILL_MD} but no metadata`,\n }));\n\n const missingSkillMd = [...metadataDirs]\n .filter((dir) => !skillMdDirs.has(dir))\n .map((dir) => ({\n severity: \"error\" as const,\n file: path.join(skillsDir, dir),\n message: `Missing ${STANDARD_FILES.SKILL_MD} — skill directory has ${STANDARD_FILES.METADATA_YAML} but no SKILL.md`,\n }));\n\n return [...missingMetadata, ...missingSkillMd];\n}\n\n/** `reader` sets how loud findings are; default `\"author\"`, as under-reporting is worse. */\nexport async function validateSource(\n sourcePath: string,\n reader: MarketplaceReader = \"author\",\n): Promise<SourceValidationResult> {\n const resolvedPath = path.isAbsolute(sourcePath) ? sourcePath : path.resolve(sourcePath);\n\n if (!(await directoryExists(resolvedPath))) {\n return buildResult(\n [{ severity: \"error\", file: resolvedPath, message: \"Marketplace directory does not exist\" }],\n 0,\n );\n }\n\n // Aborts on an unreadable config; `validateOneSource` turns it into an issue.\n const sourceProjectConfig = await loadSourceRepoConfig(resolvedPath);\n const skillsDirRelPath = sourceProjectConfig?.skillsDir ?? SKILLS_DIR_PATH;\n const skillsDir = path.join(resolvedPath, skillsDirRelPath);\n\n if (!(await directoryExists(skillsDir))) {\n return buildResult(\n [{ severity: \"error\", file: skillsDir, message: \"Skills directory does not exist\" }],\n 0,\n );\n }\n\n const { pairIssues, validMetadataFiles } = await pairSkillFiles(skillsDir);\n const skillIssues = await validateSkillsInTurn(skillsDir, skillsDirRelPath, validMetadataFiles);\n\n const crossReferenceIssues = await checkCrossReferences(resolvedPath, reader);\n\n const extraIssues = await Promise.all([\n validateStacks(resolvedPath),\n validateAgents(resolvedPath),\n validateConfigFiles(resolvedPath),\n ]);\n\n return buildResult(\n [...pairIssues, ...skillIssues, ...crossReferenceIssues, ...extraIssues.flat()],\n validMetadataFiles.length,\n );\n}\n\n/** A half pair is reported here, so only complete pairs go on to be validated. */\nasync function pairSkillFiles(\n skillsDir: string,\n): Promise<{ pairIssues: SourceValidationIssue[]; validMetadataFiles: string[] }> {\n const skillMdFiles = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir);\n const metadataFiles = await glob(`**/${STANDARD_FILES.METADATA_YAML}`, skillsDir);\n\n const skillMdDirs = new Set(skillMdFiles.map((f) => path.dirname(f)));\n const metadataDirs = new Set(metadataFiles.map((f) => path.dirname(f)));\n\n return {\n pairIssues: validateSkillFilePairs(skillMdDirs, metadataDirs, skillsDir),\n validMetadataFiles: metadataFiles.filter((f) => skillMdDirs.has(path.dirname(f))),\n };\n}\n\nasync function validateSkillsInTurn(\n skillsDir: string,\n skillsDirRelPath: string,\n metadataFiles: string[],\n): Promise<SourceValidationIssue[]> {\n const issues: SourceValidationIssue[] = [];\n for (const metadataFile of metadataFiles) {\n issues.push(...(await validateOneSkill(skillsDir, skillsDirRelPath, metadataFile)));\n }\n return issues;\n}\n\n/** Named once so both YAML-reading phases word the failure alike. */\nfunction yamlParseFailure(error: unknown): string {\n return `Failed to parse YAML: ${getErrorMessage(error)}`;\n}\n\n/** An unparseable file reports that and stops: every later check reads the parsed value. */\nasync function validateOneSkill(\n skillsDir: string,\n skillsDirRelPath: string,\n metadataFile: string,\n): Promise<SourceValidationIssue[]> {\n const relPath = path.join(skillsDirRelPath, metadataFile);\n\n let rawMetadata: unknown;\n try {\n rawMetadata = parseYaml(await readFile(path.join(skillsDir, metadataFile)));\n } catch (error) {\n return [{ severity: \"error\", file: relPath, message: yamlParseFailure(error) }];\n }\n\n return [\n ...checkSnakeCaseKeys(rawMetadata, relPath),\n ...checkMetadataSchema(rawMetadata, relPath),\n // Independent of metadata validity — the id lives in SKILL.md frontmatter\n ...(await checkSkillDirName(skillsDir, skillsDirRelPath, path.dirname(metadataFile))),\n ];\n}\n\nfunction checkMetadataSchema(rawMetadata: unknown, relPath: string): SourceValidationIssue[] {\n const result = validateSkillMetadata(rawMetadata);\n if (result.success) return [];\n\n const { errors, warnings } = splitMetadataValidationIssues(result.error, rawMetadata);\n return [\n ...errors.map((message) => ({ severity: \"error\" as const, file: relPath, message })),\n ...warnings.map((message) => ({ severity: \"warning\" as const, file: relPath, message })),\n ];\n}\n\n/** As a reader types it: the file `doctor` tells them to open. */\nconst MARKETPLACE_MANIFEST_PATH = path.join(PLUGIN_MANIFEST_DIR, MARKETPLACE_JSON);\n\n/** Keyed on the whole reader union, so a new reader does not compile until someone decides. */\nconst MANIFEST_REQUIRED_SEVERITY = {\n author: \"warning\",\n consumer: \"error\",\n} as const satisfies Record<MarketplaceReader, SourceValidationIssue[\"severity\"]>;\n\n/** Files the load's health findings without saying them again. */\nasync function checkCrossReferences(\n resolvedPath: string,\n reader: MarketplaceReader,\n): Promise<SourceValidationIssue[]> {\n try {\n await loadSkillsMatrixFromSource({ sourceFlag: resolvedPath, skipExtraSources: true });\n return matrixHealthIssues(matrix).map((healthIssue) =>\n toSourceIssue(healthIssue, resolvedPath, reader),\n );\n } catch (error) {\n return [matrixLoadFailure(error, reader)];\n }\n}\n\n/**\n * No valid manifest: the manifest's finding, at the reader's severity. A refused name: this\n * marketplace's error, since nothing installs. Anything else: a warning. Read off the throw's type.\n */\nfunction matrixLoadFailure(error: unknown, reader: MarketplaceReader): SourceValidationIssue {\n if (error instanceof MarketplaceManifestRequiredError) {\n return {\n severity: MANIFEST_REQUIRED_SEVERITY[reader],\n file: MARKETPLACE_MANIFEST_PATH,\n message: getErrorMessage(error),\n };\n }\n\n if (error instanceof MarketplaceNameRefusedError) {\n return {\n severity: \"error\",\n file: MARKETPLACE_MANIFEST_PATH,\n message: getErrorMessage(error),\n };\n }\n\n return {\n severity: \"warning\",\n file: SKILL_CATEGORIES_PATH,\n message: `Cross-reference validation skipped: failed to load categories/rules: ${getErrorMessage(error)}`,\n };\n}\n\n/** This CLI's own file: the marketplace holds no copy of the verdicts. */\nconst SKILL_AUDIT_PATH = \"src/cli/lib/configuration/skill-audit.ts\";\n\n/** The file the defect is in, as `doctor` shows it; exhaustive, so new kinds must choose. */\nfunction fileHoldingDefect(finding: MatrixHealthIssue[\"finding\"]): string {\n switch (finding) {\n case \"category-missing-domain\":\n case \"skill-unknown-category\":\n return SKILL_CATEGORIES_PATH;\n case \"skill-unresolved-relation-ref\":\n case \"rule-unresolved-slug\":\n return SKILL_RULES_PATH;\n case \"audit-verdict-contradiction\":\n case \"skill-unaudited\":\n return SKILL_AUDIT_PATH;\n default: {\n const exhaustive: never = finding;\n return exhaustive;\n }\n }\n}\n\n/** Only a marketplace's own dangling rule slug moves with the reader; the file never does. */\nfunction toSourceIssue(\n healthIssue: MatrixHealthIssue,\n marketplacePath: string,\n reader: MarketplaceReader,\n): SourceValidationIssue {\n const file = fileHoldingDefect(healthIssue.finding);\n\n if (reader === \"consumer\" && healthIssue.finding === \"rule-unresolved-slug\") {\n return {\n severity: \"warning\",\n file,\n message: consumedMarketplaceMessage(marketplacePath, healthIssue.details),\n };\n }\n\n return {\n severity: healthIssue.severity,\n file,\n message: healthIssue.details,\n };\n}\n\n/** Leads with the marketplace and says there is nothing here for the reader to fix. */\nfunction consumedMarketplaceMessage(marketplacePath: string, details: string): string {\n return `Marketplace '${marketplacePath}': ${details}. Nothing to fix here — the rule is that marketplace's, not this project's`;\n}\n\nasync function validateStacks(resolvedPath: string): Promise<SourceValidationIssue[]> {\n const stacksDir = path.join(resolvedPath, DIRS.stacks);\n if (!(await directoryExists(stacksDir))) return [];\n\n const [skillMetaIssues, configIssues] = await Promise.all([\n validateYamlFiles({\n baseDir: stacksDir,\n relBaseDir: DIRS.stacks,\n pattern: `**/skills/**/${STANDARD_FILES.METADATA_YAML}`,\n schema: metadataValidationSchema,\n }),\n validateYamlFiles({\n baseDir: stacksDir,\n relBaseDir: DIRS.stacks,\n pattern: `*/${STANDARD_FILES.CONFIG_YAML}`,\n schema: stackConfigValidationSchema,\n }),\n ]);\n return [...skillMetaIssues, ...configIssues];\n}\n\n/** Against compilation's input schema (compiling writes no YAML); skips a missing src/agents/. */\nasync function validateAgents(resolvedPath: string): Promise<SourceValidationIssue[]> {\n const agentsDir = path.join(resolvedPath, DIRS.agents);\n if (!(await directoryExists(agentsDir))) return [];\n\n return validateYamlFiles({\n baseDir: agentsDir,\n relBaseDir: DIRS.agents,\n pattern: `**/${STANDARD_FILES.AGENT_METADATA_YAML}`,\n schema: agentYamlGenerationSchema,\n });\n}\n\n/** Runtime-loads each config/*.ts and validates its default export; absent files are skipped. */\nasync function validateConfigFiles(resolvedPath: string): Promise<SourceValidationIssue[]> {\n const results = await Promise.all([\n validateTsConfig(resolvedPath, SKILL_CATEGORIES_PATH, skillCategoriesFileSchema),\n validateTsConfig(resolvedPath, SKILL_RULES_PATH, skillRulesFileSchema),\n validateTsConfig(resolvedPath, STACKS_FILE_PATH, stacksConfigSchema),\n ]);\n return results.flat();\n}\n\n/** One kind of YAML file a source may carry: where it lives, and the schema each must satisfy. */\ntype YamlFileScan = {\n baseDir: string;\n /** `baseDir` in the project-relative form issues report. */\n relBaseDir: string;\n pattern: string;\n schema: z.ZodType<unknown>;\n};\n\nasync function validateYamlFiles(scan: YamlFileScan): Promise<SourceValidationIssue[]> {\n const issues: SourceValidationIssue[] = [];\n const files = await glob(scan.pattern, scan.baseDir);\n\n for (const relFile of files) {\n issues.push(...(await validateYamlFile(scan, relFile)));\n }\n return issues;\n}\n\nasync function validateYamlFile(\n scan: YamlFileScan,\n relFile: string,\n): Promise<SourceValidationIssue[]> {\n const displayPath = path.join(scan.relBaseDir, relFile);\n\n let parsed: unknown;\n try {\n parsed = parseYaml(await readFile(path.join(scan.baseDir, relFile)));\n } catch (error) {\n return [{ severity: \"error\", file: displayPath, message: yamlParseFailure(error) }];\n }\n\n const result = scan.schema.safeParse(parsed);\n if (result.success) return [];\n\n return formatZodErrors(result.error).map((message) => ({\n severity: \"error\" as const,\n file: displayPath,\n message,\n }));\n}\n\n/** `null` (exported nothing) and named-only exports are reported apart, since the fixes differ. */\nasync function validateTsConfig(\n resolvedPath: string,\n relConfigPath: string,\n schema: z.ZodType<unknown>,\n): Promise<SourceValidationIssue[]> {\n const absPath = path.join(resolvedPath, relConfigPath);\n if (!(await fileExists(absPath))) return [];\n\n try {\n const loaded = await loadConfig(absPath, schema);\n if (loaded === null) {\n return [{ severity: \"error\", file: relConfigPath, message: \"Config is empty\" }];\n }\n return [];\n } catch (error) {\n if (error instanceof ConfigDefaultExportError) {\n return [{ severity: \"error\", file: relConfigPath, message: \"Config has no default export\" }];\n }\n return [\n { severity: \"error\", file: relConfigPath, message: formatLoadError(relConfigPath, error) },\n ];\n }\n}\n\n/** References the relative config path, not the absolute one loadConfig embeds. */\nfunction formatLoadError(relConfigPath: string, error: unknown): string {\n const raw = getErrorMessage(error);\n const stripped = raw.replace(/Failed to load config from '[^']+':\\s*/, \"\");\n return `Failed to load ${relConfigPath}: ${stripped}`;\n}\n\nfunction buildResult(issues: SourceValidationIssue[], skillCount: number): SourceValidationResult {\n const errorCount = issues.filter((i) => i.severity === \"error\").length;\n const warningCount = issues.filter((i) => i.severity === \"warning\").length;\n return { issues, skillCount, errorCount, warningCount };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAOA,SAAQ;AACf,OAAOC,WAAU;;;ACMjB,OAAO,QAAQ;AA6BR,SAAS,YAAY,YAA2B;AACrD,SAAO,EAAE,SAAS,cAAc,UAAU,GAAG,QAAQ,cAAc,GAAG,QAAQ,CAAC,EAAE;AACnF;AAEO,SAAS,QAAQ,UAA2B;AACjD,SAAO,EAAE,SAAS,UAAU,QAAQ,SAAS;AAC/C;AAGA,eAAsB,gBAAgB,YAAyC;AAC7E,QAAM,QAAQ,MAAM,oBAAoB,UAAU;AAClD,QAAM,eAAe,MAAM,OAAO,CAAC,iBAAiB,aAAa,UAAU,SAAS;AACpF,QAAM,SAAS,aAAa,SAAS,IAAI,eAAe;AACxD,SAAO,OAAO,IAAI,CAAC,iBAAiB,aAAa,QAAQ;AAC3D;AAaA,eAAsB,mBAAmB;AAAA,EACvC;AAAA,EACA;AACF,GAA8C;AAC5C,MAAI;AACF,WAAO,MAAM,gBAAgB,YAAY,KAAK;AAAA,EAChD,SAAS,OAAO;AACd,QAAI,iBAAiB,gBAAiB,QAAO,EAAE,MAAM,cAAc,SAAS,MAAM;AAClF,UAAM;AAAA,EACR;AACF;AAEA,eAAe,gBAAgB,YAAoB,OAAoC;AACrF,QAAM,MAAM,MAAM,yBAAyB,YAAY,MAAM,OAAO;AACpE,MAAI,OAAO,CAAC,kBAAkB,IAAI,MAAM,GAAG;AACzC,WAAO,EAAE,MAAM,UAAU,QAAQ,IAAI,QAAQ,WAAW,MAAM;AAAA,EAChE;AAEA,QAAM,YAAY,gBAAgB,UAAU,IACxC,OACA,MAAM,yBAAyB,GAAG,QAAQ,GAAG,MAAM,MAAM;AAC7D,MAAI,aAAa,CAAC,kBAAkB,UAAU,MAAM,GAAG;AACrD,WAAO,EAAE,MAAM,UAAU,QAAQ,UAAU,QAAQ,WAAW,KAAK;AAAA,EACrE;AAEA,SAAO,MAAM,EAAE,MAAM,oBAAoB,QAAQ,IAAI,OAAO,IAAI,EAAE,MAAM,SAAS;AACnF;AAMA,eAAsB,wBACpB,SACA,UAC8B;AAC9B,QAAM,UAAU,MAAM,gBAAgB,SAAS,QAAQ;AACvD,SAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,WAAW,0BAA0B,OAAO,SAAS,CAAC,CAAC;AACrF;AAEA,eAAe,gBAAgB,SAAiB,UAA2C;AACzF,QAAM,WAAW,MAAM,gBAAgB,UAAU,OAAO,GAAG,OAAO,CAAC,WAAW,OAAO,OAAO;AAC5F,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B,QAAQ,IAAI,CAAC,WAAW,WAAW,sBAAsB,OAAO,WAAW,CAAC,CAAC;AAAA,EAC/E;AACA,SAAO,QAAQ,OAAO,CAAC,GAAG,UAAU,OAAO,KAAK,MAAM,IAAI;AAC5D;AAEA,eAAe,gBAAgB,UAAoB,SAAwC;AACzF,MAAI;AACF,WAAO,MAAM,QAAQ,QAAQ,EAAE,YAAY,OAAO;AAAA,EACpD,SAAS,OAAO;AACd,YAAQ,qCAAqC,gBAAgB,KAAK,CAAC,EAAE;AACrE,WAAO,CAAC;AAAA,EACV;AACF;AAMA,eAAsB,sBAAsB;AAAA,EAC1C;AAAA,EACA;AACF,GAA2C;AACzC,QAAM,eAAe,CAAC,GAAG,iBAAiB,UAAU,CAAC,EAAE,QAAQ;AAC/D,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,aAAa,IAAI,CAAC,EAAE,MAAM,KAAK,MAAM,uBAAuB,MAAM,MAAM,IAAI,CAAC,CAAC;AAAA,EAChF;AACA,SAAO,SAAS,OAAO,CAAC,YAA+B,YAAY,IAAI;AACzE;AAEA,eAAe,uBAAuB,MAAc,UAA4C;AAC9F,QAAM,SAAS,MAAM,mBAAmB,MAAM,QAAQ;AACtD,MAAI,WAAW,KAAM,QAAO;AAE5B,MAAI;AACF,8BAA0B,QAAQ,QAAQ,QAAQ,CAAC;AACnD,WAAO;AAAA,EACT,SAAS,OAAO;AACd,WAAO,gBAAgB,KAAK;AAAA,EAC9B;AACF;AAGA,eAAe,mBAAmB,MAAc,UAAmD;AACjG,MAAI;AACF,UAAM,SAAS,MAAM,yBAAyB,MAAM,QAAQ;AAC5D,WAAO,QAAQ,OAAO,UAAU;AAAA,EAClC,SAAS,OAAO;AACd,QAAI,iBAAiB,gBAAiB,QAAO;AAC7C,UAAM;AAAA,EACR;AACF;;;ACtJA,OAAOC,WAAU;AACjB,SAAS,eAAe;;;ACPxB,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,iBAAiB;;;ACF1B,OAAO,UAAU;AAEjB,SAAS,SAAS,iBAAiB;AACnC,OAAkB;AAuDlB,eAAsB,aAAa,KAA+B;AAEhE,QAAM,eAAe,MAAM,qBAAqB,GAAG;AACnD,SAAO,gBAAgB,KAAK,KAAK,KAAK,cAAc,aAAa,eAAe,CAAC;AACnF;AAEA,SAAS,YAAY,KAAsB;AACzC,SAAO,cAAc,KAAK,GAAG;AAC/B;AAEA,SAAS,mBAAmB,aAAsB,SAA0C;AAC1F,MAAI,CAAC,SAAS,WAAW,EAAG,QAAO,CAAC;AAEpC,SAAO,OAAO,KAAK,WAAW,EAC3B,OAAO,WAAW,EAClB,IAAI,CAAC,SAAS;AAAA,IACb,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS,QAAQ,GAAG;AAAA,EACtB,EAAE;AACN;AAGA,SAAS,2BACP,SACA,SACA,SACyB;AACzB,MAAI,YAAY,QAAS,QAAO,CAAC;AACjC,SAAO;AAAA,IACL;AAAA,MACE,UAAU;AAAA,MACV,MAAM;AAAA,MACN,SAAS,mBAAmB,OAAO,8BAA8B,OAAO;AAAA,IAC1E;AAAA,EACF;AACF;AAEA,eAAe,kBACbC,YACA,kBACA,UACkC;AAClC,QAAM,UAAU,KAAK,SAAS,QAAQ;AACtC,QAAM,iBAAiB,KAAK,KAAK,kBAAkB,UAAU,eAAe,QAAQ;AAEpF,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,KAAK,KAAKA,YAAW,UAAU,eAAe,QAAQ,CAAC;AACtF,UAAM,cAAc,iBAAiB,SAAS,cAAc;AAE5D,QAAI,gBAAgB,MAAM;AACxB,aAAO;AAAA,QACL;AAAA,UACE,UAAU;AAAA,UACV,MAAM;AAAA,UACN,SAAS,iCAAiC,OAAO,yBAAyB,eAAe,QAAQ;AAAA,QACnG;AAAA,MACF;AAAA,IACF;AAEA,WAAO,2BAA2B,YAAY,MAAM,gBAAgB,OAAO;AAAA,EAC7E,SAAS,OAAO;AACd,WAAO;AAAA,MACL;AAAA,QACE,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS,iCAAiC,OAAO,MAAM,gBAAgB,KAAK,CAAC;AAAA,MAC/E;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,uBACP,aACA,cACAA,YACyB;AACzB,QAAM,kBAAkB,CAAC,GAAG,WAAW,EACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,IAAI,GAAG,CAAC,EACtC,IAAI,CAAC,SAAS;AAAA,IACb,UAAU;AAAA,IACV,MAAM,KAAK,KAAKA,YAAW,GAAG;AAAA,IAC9B,SAAS,WAAW,eAAe,aAAa,+BAA0B,eAAe,QAAQ;AAAA,EACnG,EAAE;AAEJ,QAAM,iBAAiB,CAAC,GAAG,YAAY,EACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,IAAI,GAAG,CAAC,EACrC,IAAI,CAAC,SAAS;AAAA,IACb,UAAU;AAAA,IACV,MAAM,KAAK,KAAKA,YAAW,GAAG;AAAA,IAC9B,SAAS,WAAW,eAAe,QAAQ,+BAA0B,eAAe,aAAa;AAAA,EACnG,EAAE;AAEJ,SAAO,CAAC,GAAG,iBAAiB,GAAG,cAAc;AAC/C;AAGA,eAAsB,eACpB,YACA,SAA4B,UACK;AACjC,QAAM,eAAe,KAAK,WAAW,UAAU,IAAI,aAAa,KAAK,QAAQ,UAAU;AAEvF,MAAI,CAAE,MAAM,gBAAgB,YAAY,GAAI;AAC1C,WAAO;AAAA,MACL,CAAC,EAAE,UAAU,SAAS,MAAM,cAAc,SAAS,uCAAuC,CAAC;AAAA,MAC3F;AAAA,IACF;AAAA,EACF;AAGA,QAAM,sBAAsB,MAAM,qBAAqB,YAAY;AACnE,QAAM,mBAAmB,qBAAqB,aAAa;AAC3D,QAAMA,aAAY,KAAK,KAAK,cAAc,gBAAgB;AAE1D,MAAI,CAAE,MAAM,gBAAgBA,UAAS,GAAI;AACvC,WAAO;AAAA,MACL,CAAC,EAAE,UAAU,SAAS,MAAMA,YAAW,SAAS,kCAAkC,CAAC;AAAA,MACnF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,EAAE,YAAY,mBAAmB,IAAI,MAAM,eAAeA,UAAS;AACzE,QAAM,cAAc,MAAM,qBAAqBA,YAAW,kBAAkB,kBAAkB;AAE9F,QAAM,uBAAuB,MAAM,qBAAqB,cAAc,MAAM;AAE5E,QAAM,cAAc,MAAM,QAAQ,IAAI;AAAA,IACpC,eAAe,YAAY;AAAA,IAC3B,eAAe,YAAY;AAAA,IAC3B,oBAAoB,YAAY;AAAA,EAClC,CAAC;AAED,SAAO;AAAA,IACL,CAAC,GAAG,YAAY,GAAG,aAAa,GAAG,sBAAsB,GAAG,YAAY,KAAK,CAAC;AAAA,IAC9E,mBAAmB;AAAA,EACrB;AACF;AAGA,eAAe,eACbA,YACgF;AAChF,QAAM,eAAe,MAAM,KAAK,MAAM,eAAe,QAAQ,IAAIA,UAAS;AAC1E,QAAM,gBAAgB,MAAM,KAAK,MAAM,eAAe,aAAa,IAAIA,UAAS;AAEhF,QAAM,cAAc,IAAI,IAAI,aAAa,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC;AACpE,QAAM,eAAe,IAAI,IAAI,cAAc,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC;AAEtE,SAAO;AAAA,IACL,YAAY,uBAAuB,aAAa,cAAcA,UAAS;AAAA,IACvE,oBAAoB,cAAc,OAAO,CAAC,MAAM,YAAY,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC;AAAA,EAClF;AACF;AAEA,eAAe,qBACbA,YACA,kBACA,eACkC;AAClC,QAAM,SAAkC,CAAC;AACzC,aAAW,gBAAgB,eAAe;AACxC,WAAO,KAAK,GAAI,MAAM,iBAAiBA,YAAW,kBAAkB,YAAY,CAAE;AAAA,EACpF;AACA,SAAO;AACT;AAGA,SAAS,iBAAiB,OAAwB;AAChD,SAAO,yBAAyB,gBAAgB,KAAK,CAAC;AACxD;AAGA,eAAe,iBACbA,YACA,kBACA,cACkC;AAClC,QAAM,UAAU,KAAK,KAAK,kBAAkB,YAAY;AAExD,MAAI;AACJ,MAAI;AACF,kBAAc,UAAU,MAAM,SAAS,KAAK,KAAKA,YAAW,YAAY,CAAC,CAAC;AAAA,EAC5E,SAAS,OAAO;AACd,WAAO,CAAC,EAAE,UAAU,SAAS,MAAM,SAAS,SAAS,iBAAiB,KAAK,EAAE,CAAC;AAAA,EAChF;AAEA,SAAO;AAAA,IACL,GAAG,mBAAmB,aAAa,OAAO;AAAA,IAC1C,GAAG,oBAAoB,aAAa,OAAO;AAAA;AAAA,IAE3C,GAAI,MAAM,kBAAkBA,YAAW,kBAAkB,KAAK,QAAQ,YAAY,CAAC;AAAA,EACrF;AACF;AAEA,SAAS,oBAAoB,aAAsB,SAA0C;AAC3F,QAAM,SAAS,sBAAsB,WAAW;AAChD,MAAI,OAAO,QAAS,QAAO,CAAC;AAE5B,QAAM,EAAE,QAAQ,SAAS,IAAI,8BAA8B,OAAO,OAAO,WAAW;AACpF,SAAO;AAAA,IACL,GAAG,OAAO,IAAI,CAAC,aAAa,EAAE,UAAU,SAAkB,MAAM,SAAS,QAAQ,EAAE;AAAA,IACnF,GAAG,SAAS,IAAI,CAAC,aAAa,EAAE,UAAU,WAAoB,MAAM,SAAS,QAAQ,EAAE;AAAA,EACzF;AACF;AAGA,IAAM,4BAA4B,KAAK,KAAK,qBAAqB,gBAAgB;AAGjF,IAAM,6BAA6B;AAAA,EACjC,QAAQ;AAAA,EACR,UAAU;AACZ;AAGA,eAAe,qBACb,cACA,QACkC;AAClC,MAAI;AACF,UAAM,2BAA2B,EAAE,YAAY,cAAc,kBAAkB,KAAK,CAAC;AACrF,WAAO,mBAAmB,MAAM,EAAE;AAAA,MAAI,CAAC,gBACrC,cAAc,aAAa,cAAc,MAAM;AAAA,IACjD;AAAA,EACF,SAAS,OAAO;AACd,WAAO,CAAC,kBAAkB,OAAO,MAAM,CAAC;AAAA,EAC1C;AACF;AAMA,SAAS,kBAAkB,OAAgB,QAAkD;AAC3F,MAAI,iBAAiB,kCAAkC;AACrD,WAAO;AAAA,MACL,UAAU,2BAA2B,MAAM;AAAA,MAC3C,MAAM;AAAA,MACN,SAAS,gBAAgB,KAAK;AAAA,IAChC;AAAA,EACF;AAEA,MAAI,iBAAiB,6BAA6B;AAChD,WAAO;AAAA,MACL,UAAU;AAAA,MACV,MAAM;AAAA,MACN,SAAS,gBAAgB,KAAK;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS,wEAAwE,gBAAgB,KAAK,CAAC;AAAA,EACzG;AACF;AAGA,IAAM,mBAAmB;AAGzB,SAAS,kBAAkB,SAA+C;AACxE,UAAQ,SAAS;AAAA,IACf,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,SAAS;AACP,YAAM,aAAoB;AAC1B,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAGA,SAAS,cACP,aACA,iBACA,QACuB;AACvB,QAAM,OAAO,kBAAkB,YAAY,OAAO;AAElD,MAAI,WAAW,cAAc,YAAY,YAAY,wBAAwB;AAC3E,WAAO;AAAA,MACL,UAAU;AAAA,MACV;AAAA,MACA,SAAS,2BAA2B,iBAAiB,YAAY,OAAO;AAAA,IAC1E;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU,YAAY;AAAA,IACtB;AAAA,IACA,SAAS,YAAY;AAAA,EACvB;AACF;AAGA,SAAS,2BAA2B,iBAAyB,SAAyB;AACpF,SAAO,gBAAgB,eAAe,MAAM,OAAO;AACrD;AAEA,eAAe,eAAe,cAAwD;AACpF,QAAM,YAAY,KAAK,KAAK,cAAc,KAAK,MAAM;AACrD,MAAI,CAAE,MAAM,gBAAgB,SAAS,EAAI,QAAO,CAAC;AAEjD,QAAM,CAAC,iBAAiB,YAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,IACxD,kBAAkB;AAAA,MAChB,SAAS;AAAA,MACT,YAAY,KAAK;AAAA,MACjB,SAAS,gBAAgB,eAAe,aAAa;AAAA,MACrD,QAAQ;AAAA,IACV,CAAC;AAAA,IACD,kBAAkB;AAAA,MAChB,SAAS;AAAA,MACT,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK,eAAe,WAAW;AAAA,MACxC,QAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AACD,SAAO,CAAC,GAAG,iBAAiB,GAAG,YAAY;AAC7C;AAGA,eAAe,eAAe,cAAwD;AACpF,QAAMC,aAAY,KAAK,KAAK,cAAc,KAAK,MAAM;AACrD,MAAI,CAAE,MAAM,gBAAgBA,UAAS,EAAI,QAAO,CAAC;AAEjD,SAAO,kBAAkB;AAAA,IACvB,SAASA;AAAA,IACT,YAAY,KAAK;AAAA,IACjB,SAAS,MAAM,eAAe,mBAAmB;AAAA,IACjD,QAAQ;AAAA,EACV,CAAC;AACH;AAGA,eAAe,oBAAoB,cAAwD;AACzF,QAAM,UAAU,MAAM,QAAQ,IAAI;AAAA,IAChC,iBAAiB,cAAc,uBAAuB,yBAAyB;AAAA,IAC/E,iBAAiB,cAAc,kBAAkB,oBAAoB;AAAA,IACrE,iBAAiB,cAAc,kBAAkB,kBAAkB;AAAA,EACrE,CAAC;AACD,SAAO,QAAQ,KAAK;AACtB;AAWA,eAAe,kBAAkB,MAAsD;AACrF,QAAM,SAAkC,CAAC;AACzC,QAAM,QAAQ,MAAM,KAAK,KAAK,SAAS,KAAK,OAAO;AAEnD,aAAW,WAAW,OAAO;AAC3B,WAAO,KAAK,GAAI,MAAM,iBAAiB,MAAM,OAAO,CAAE;AAAA,EACxD;AACA,SAAO;AACT;AAEA,eAAe,iBACb,MACA,SACkC;AAClC,QAAM,cAAc,KAAK,KAAK,KAAK,YAAY,OAAO;AAEtD,MAAI;AACJ,MAAI;AACF,aAAS,UAAU,MAAM,SAAS,KAAK,KAAK,KAAK,SAAS,OAAO,CAAC,CAAC;AAAA,EACrE,SAAS,OAAO;AACd,WAAO,CAAC,EAAE,UAAU,SAAS,MAAM,aAAa,SAAS,iBAAiB,KAAK,EAAE,CAAC;AAAA,EACpF;AAEA,QAAM,SAAS,KAAK,OAAO,UAAU,MAAM;AAC3C,MAAI,OAAO,QAAS,QAAO,CAAC;AAE5B,SAAO,gBAAgB,OAAO,KAAK,EAAE,IAAI,CAAC,aAAa;AAAA,IACrD,UAAU;AAAA,IACV,MAAM;AAAA,IACN;AAAA,EACF,EAAE;AACJ;AAGA,eAAe,iBACb,cACA,eACA,QACkC;AAClC,QAAM,UAAU,KAAK,KAAK,cAAc,aAAa;AACrD,MAAI,CAAE,MAAM,WAAW,OAAO,EAAI,QAAO,CAAC;AAE1C,MAAI;AACF,UAAM,SAAS,MAAM,WAAW,SAAS,MAAM;AAC/C,QAAI,WAAW,MAAM;AACnB,aAAO,CAAC,EAAE,UAAU,SAAS,MAAM,eAAe,SAAS,kBAAkB,CAAC;AAAA,IAChF;AACA,WAAO,CAAC;AAAA,EACV,SAAS,OAAO;AACd,QAAI,iBAAiB,0BAA0B;AAC7C,aAAO,CAAC,EAAE,UAAU,SAAS,MAAM,eAAe,SAAS,+BAA+B,CAAC;AAAA,IAC7F;AACA,WAAO;AAAA,MACL,EAAE,UAAU,SAAS,MAAM,eAAe,SAAS,gBAAgB,eAAe,KAAK,EAAE;AAAA,IAC3F;AAAA,EACF;AACF;AAGA,SAAS,gBAAgB,eAAuB,OAAwB;AACtE,QAAM,MAAM,gBAAgB,KAAK;AACjC,QAAM,WAAW,IAAI,QAAQ,0CAA0C,EAAE;AACzE,SAAO,kBAAkB,aAAa,KAAK,QAAQ;AACrD;AAEA,SAAS,YAAY,QAAiC,YAA4C;AAChG,QAAM,aAAa,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO,EAAE;AAChE,QAAM,eAAe,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,SAAS,EAAE;AACpE,SAAO,EAAE,QAAQ,YAAY,YAAY,aAAa;AACxD;;;AD9bA,IAAM,kBAAkB;AAgBxB,IAAM,oBAAuC,EAAE,OAAO,GAAG,QAAQ,CAAC,GAAG,OAAO,CAAC,EAAE;AAE/E,SAAS,iBAAiB,OAA+C;AACvE,SAAO,MAAM;AAAA,IACX,CAAC,KAAK,UAAU;AAAA,MACd,OAAO,IAAI,QAAQ,KAAK;AAAA,MACxB,QAAQ,CAAC,GAAG,IAAI,QAAQ,GAAG,KAAK,MAAM;AAAA,MACtC,OAAO,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,KAAK;AAAA,IACrC;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,WAAW,cAA8B;AAChD,QAAM,OAAOC,IAAG,QAAQ;AACxB,MAAI,iBAAiB,KAAM,QAAO;AAClC,MAAI,aAAa,WAAW,OAAOC,MAAK,GAAG,GAAG;AAC5C,WAAO,IAAIA,MAAK,GAAG,GAAGA,MAAK,SAAS,MAAM,YAAY,CAAC;AAAA,EACzD;AACA,SAAO;AACT;AAEA,SAAS,SAAS,MAAc,QAA0C;AACxE,SAAO;AAAA,IACL,GAAG,OAAO,OAAO,IAAI,CAAC,aAAa,EAAE,UAAU,SAAkB,MAAM,QAAQ,EAAE;AAAA,IACjF,GAAG,OAAO,SAAS,IAAI,CAAC,aAAa,EAAE,UAAU,WAAoB,MAAM,QAAQ,EAAE;AAAA,EACvF;AACF;AAEA,IAAM,oBAAoB;AAG1B,eAAsB,0BAA0B,YAAgD;AAC9F,QAAM,CAAC,SAAS,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC5C,qBAAqB,UAAU;AAAA,IAC/B,uBAAuB,UAAU;AAAA,EACnC,CAAC;AAED,SAAO,EAAE,OAAO,SAAS,QAAQ,SAAS,IAAI,uBAAuB,GAAG,OAAO,CAAC,EAAE;AACpF;AAGA,SAAS,wBAAwB,SAAwC;AACvE,SAAO;AAAA,IACL,UAAU;AAAA,IACV,MAAM,GAAG,WAAW,QAAQ,KAAK,CAAC,MAAM,WAAW,QAAQ,UAAU,CAAC;AAAA,IACtE,SAAS,GAAG,iBAAiB,KAAK,QAAQ,MAAM;AAAA,EAClD;AACF;AAEA,eAAe,qBAAqB,YAAqC;AACvE,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,iBAAiB,UAAU,EAAE,IAAI,CAAC,QAAQ,WAAW,uBAAuB,GAAG,CAAC,CAAC;AAAA,EACnF;AACA,SAAO,QAAQ,OAAO,OAAO,EAAE;AACjC;AAGA,eAAsB,0BAA0B,YAAgD;AAE9F,QAAM,UAAU,MAAM,0BAA0B,UAAU;AAC1D,QAAM,aAAa,CAAC,OAAO;AAC3B,QAAM,SAAS,WAAW,OAAO,CAAC,WAAW,CAAC,cAAc,OAAO,GAAG,CAAC;AACvE,QAAM,QAAQ,MAAM,uBAAuB,YAAY,UAAU;AAEjE,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,MAAM,IAAI,CAAC,WAAW,kBAAkB,QAAQ,UAAU,YAAY,MAAM,CAAC,CAAC;AAAA,EAChF;AAEA,SAAO;AAAA,IACL,OAAO,MAAM;AAAA,IACb,QAAQ,SAAS,QAAQ,CAAC,YAAY,QAAQ,MAAM;AAAA,IACpD,OAAO;AAAA,MACL,GAAG,SAAS,IAAI,CAAC,YAAY,QAAQ,IAAI;AAAA,MACzC,GAAG,OAAO,IAAI,CAAC,WAAW,GAAG,OAAO,IAAI,KAAK,OAAO,GAAG,2BAAsB;AAAA,IAC/E;AAAA,EACF;AACF;AAEA,eAAe,uBACb,YACA,YACwB;AACxB,QAAM,QAAQ,WAAW,OAAO,CAAC,WAAW,cAAc,OAAO,GAAG,CAAC;AACrE,QAAM,iBAAiB,MAAM,KAAK,CAAC,WAAW,iBAAiB,YAAY,MAAM,CAAC;AAElF,MAAI,kBAAkB,CAAE,MAAM,aAAa,UAAU,EAAI,QAAO;AAEhE,SAAO,CAAC,GAAG,OAAO,EAAE,MAAM,iBAAiB,KAAK,WAAW,CAAC;AAC9D;AAGA,SAAS,iBAAiB,YAAoB,QAA8B;AAC1E,SAAOA,MAAK,QAAQ,YAAY,OAAO,GAAG,MAAM;AAClD;AAGA,SAAS,UAAU,YAAoB,QAAwC;AAC7E,SAAO,iBAAiB,YAAY,MAAM,IAAI,WAAW;AAC3D;AAIA,eAAe,kBACb,QACA,QACwB;AACxB,QAAM,QAAQ,GAAG,OAAO,IAAI,KAAK,OAAO,GAAG;AAC3C,MAAI;AACF,UAAM,SAAS,MAAM,eAAe,OAAO,KAAK,MAAM;AACtD,WAAO,EAAE,MAAM,GAAG,KAAK,WAAM,OAAO,OAAO,YAAY,OAAO,CAAC,IAAI,QAAQ,OAAO,OAAO;AAAA,EAC3F,SAAS,OAAO;AACd,WAAO;AAAA,MACL,MAAM,GAAG,KAAK;AAAA,MACd,QAAQ,CAAC,EAAE,UAAU,SAAS,MAAM,OAAO,KAAK,SAAS,gBAAgB,KAAK,EAAE,CAAC;AAAA,IACnF;AAAA,EACF;AACF;AAEA,eAAsB,yBAAyB,YAAgD;AAC7F,QAAM,OAAO;AAAA,IACX,kBAAkB;AAAA,IAClB,GAAI,gBAAgB,UAAU,IAAI,CAAC,IAAI,CAAC,qBAAqB,UAAU,CAAC;AAAA,EAC1E;AACA,SAAO,iBAAiB,MAAM,QAAQ,IAAI,KAAK,IAAI,wBAAwB,CAAC,CAAC;AAC/E;AAEA,eAAe,yBAAyB,YAAgD;AACtF,MAAI,CAAE,MAAM,gBAAgB,UAAU,EAAI,QAAO;AAEjD,MAAI,MAAM,WAAW,gCAAgC,UAAU,CAAC,GAAG;AACjE,UAAM,qBAAqB,MAAM,wBAAwB,UAAU;AACnE,QAAI,uBAAuB,OAAW,QAAO;AAAA,EAC/C;AAEA,QAAM,aAAa,MAAM,mBAAmB,UAAU;AACtD,MAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,QAAM,EAAE,QAAQ,IAAI,MAAM,mBAAmB,UAAU;AAEvD,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ,QAAQ,CAAC,EAAE,MAAM,OAAO,MAAM,SAAS,MAAM,MAAM,CAAC;AAAA,IACpE,OAAO,CAAC;AAAA,EACV;AACF;AAGA,eAAe,wBAAwB,YAA4D;AACjG,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,6BAA6B,UAAU;AAAA,EAC1D,SAAS,OAAO;AACd,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN;AAAA,UACE,UAAU;AAAA,UACV,MAAM,WAAW,gCAAgC,UAAU,CAAC;AAAA,UAC5D,SAAS,gBAAgB,KAAK;AAAA,QAChC;AAAA,MACF;AAAA,MACA,OAAO,CAAC;AAAA,IACV;AAAA,EACF;AAEA,MAAI,SAAS,WAAW,EAAG,QAAO;AAGlC,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,SAAS;AAAA,MAAI,OAAO,EAAE,WAAW,YAAY,MAC3C,SAAS,WAAW,MAAM,eAAe,WAAW,CAAC;AAAA,IACvD;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,SAAS,QAAQ,QAAQ,QAAQ,KAAK,GAAG,OAAO,CAAC,EAAE;AACrE;AAMA,eAAsB,wBAAwB,YAAgD;AAC5F,QAAM,gBAAgB,MAAM,mBAAmB,UAAU;AACzD,SAAO;AAAA,IACL,MAAM,QAAQ;AAAA,MACZ,cAAc,YAAY,WAAW,EAAE;AAAA,QAAI,CAAC,QAC1C,wBAAwB,KAAK,aAAa;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AACF;AAGA,eAAe,mBAAmB,YAAkD;AAClF,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B,iBAAiB,UAAU,EAAE,IAAI,CAAC,QAAQ,oBAAoB,GAAG,CAAC;AAAA,EACpE;AACA,SAAO,IAAI,IAAI,OAAO,QAAQ,eAAe,CAAC;AAChD;AAEA,SAAS,gBAAgB,QAA8C;AACrE,MAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,SAAO,OAAO,OAAO,OAAO,IAAI,CAAC,UAAU,MAAM,EAAE;AACrD;AAEA,eAAsB,wBAAwB,YAAgD;AAC5F,SAAO;AAAA,IACL,MAAM,QAAQ,IAAI,cAAc,YAAY,WAAW,EAAE,IAAI,uBAAuB,CAAC;AAAA,EACvF;AACF;AAGA,SAAS,cAAc,YAAoB,KAA0C;AACnF,QAAM,SAAS,oBAAoB,YAAY,QAAQ,EAAE,GAAG;AAC5D,MAAI,gBAAgB,UAAU,EAAG,QAAO,CAAC,MAAM;AAC/C,SAAO,CAAC,QAAQ,oBAAoB,YAAY,SAAS,EAAE,GAAG,CAAC;AACjE;AAGA,eAAsB,6BAA6BC,YAAsC;AACvF,SAAO,iBAAiBA,YAAW,8BAA8B;AACnE;AAGA,eAAsB,8BACpBC,YACA,OACmB;AACnB,SAAO,iBAAiBA,YAAW,CAAC,QAAQ,gCAAgC,KAAK,KAAK,CAAC;AACzF;AAKA,eAAe,gCACbA,YACA,OACmB;AACnB,QAAM,EAAE,OAAO,IAAI,MAAM,wBAAwBA,YAAW,KAAK;AACjE,SAAO,OAAO,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,MAAM,SAAS,EAAE;AACzD;AAGA,eAAsB,+BAA+BD,YAAsC;AACzF,QAAM,CAAC,IAAI,IAAI,MAAM;AAAA,IAAmB,MAAM,gBAAgBA,UAAS;AAAA,IAAG,CAAC,SACzE,qBAAqBA,YAAW,IAAI;AAAA,EACtC;AACA,SAAO;AACT;AAEA,eAAe,mBACb,OACA,SAC+B;AAC/B,QAAM,WAAW,MAAM,QAAQ,IAAI,MAAM,IAAI,OAAO,CAAC;AACrD,SAAO,UAAU,OAAO,CAAC,GAAG,UAAU,SAAS,KAAK,MAAM,IAAI;AAChE;AAEA,eAAe,iBACb,KACA,aACmB;AACnB,MAAI,CAAE,MAAM,gBAAgB,GAAG,EAAI,QAAO,CAAC;AAC3C,QAAM,UAAU,MAAM,YAAY,GAAG;AACrC,SAAO,QAAQ,IAAI,CAAC,UAAU,WAAWD,MAAK,KAAK,KAAK,KAAK,CAAC,CAAC;AACjE;AAEA,eAAe,wBACbC,YACA,eAC4B;AAC5B,MAAI,CAAE,MAAM,gBAAgBA,UAAS,EAAI,QAAO;AAEhD,QAAM,YAAY,MAAM,gBAAgBA,UAAS;AACjD,MAAI,UAAU,WAAW,EAAG,QAAO;AAEnC,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM;AAAA,IAAmB;AAAA,IAAW,CAAC,SAC3D,oBAAoBA,YAAW,MAAM,aAAa;AAAA,EACpD;AAEA,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,KAAK,IAAI,OAAO,SAAS;AACvB,YAAM,WAAWD,MAAK,KAAKC,YAAW,IAAI;AAC1C,aAAO,SAAS,WAAW,QAAQ,GAAG,MAAM,uBAAuB,QAAQ,CAAC;AAAA,IAC9E,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,OAAO,KAAK;AAAA,IACZ,QAAQ,QAAQ,KAAK;AAAA,IACrB,OAAO,QAAQ,IAAI,CAAC,SAAS,iBAAiBA,YAAW,IAAI,CAAC;AAAA,EAChE;AACF;AAGA,eAAe,oBACbA,YACA,MACA,eACkB;AAClB,MAAI,cAAc,IAAI,IAAI,EAAG,QAAO;AACpC,SAAO,qBAAqBA,YAAW,IAAI;AAC7C;AAGA,eAAe,qBAAqBA,YAAmB,MAAgC;AACrF,SAAQ,MAAM,uBAAuBD,MAAK,KAAKC,YAAW,IAAI,CAAC,MAAO;AACxE;AAGA,SAAS,iBAAiBA,YAAmB,MAAsB;AACjE,SAAO,GAAG,WAAWD,MAAK,KAAKC,YAAW,IAAI,CAAC,CAAC;AAClD;AAEA,eAAe,wBAAwBC,YAA+C;AACpF,MAAI,CAAE,MAAM,gBAAgBA,UAAS,EAAI,QAAO;AAEhD,QAAM,aAAa,MAAM,iBAAiBA,UAAS;AACnD,MAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,WAAW,IAAI,OAAO,aAAa;AACjC,YAAM,YAAYF,MAAK,KAAKE,YAAW,QAAQ;AAC/C,aAAO,SAAS,WAAW,SAAS,GAAG,MAAM,yBAAyB,SAAS,CAAC;AAAA,IAClF,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,OAAO,WAAW,QAAQ,QAAQ,QAAQ,KAAK,GAAG,OAAO,CAAC,EAAE;AACvE;AAEA,eAAe,uBAAuB,UAA6C;AACjF,QAAM,CAAC,SAAS,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC5C,kBAAkB,UAAU,eAAe,UAAU,wBAAwB;AAAA,IAC7E,kBAAkB,UAAU,eAAe,eAAe,8BAA8B;AAAA,EAC1F,CAAC;AAED,SAAO,uBAAuB,CAAC,SAAS,QAAQ,CAAC;AACnD;AAGA,eAAe,kBACb,UACA,UACA,UAC2B;AAC3B,QAAM,WAAWF,MAAK,KAAK,UAAU,QAAQ;AAC7C,MAAI,CAAE,MAAM,WAAW,QAAQ,EAAI,QAAO,cAAc,WAAW,QAAQ,EAAE;AAC7E,SAAO,SAAS,QAAQ;AAC1B;AAEA,eAAe,+BAA+B,cAAiD;AAE7F,QAAM,OAAO,MAAM,kBAAkB,YAAY;AACjD,MAAI,CAAC,KAAK,QAAQ;AAChB,WAAO,cAAc,GAAG,eAAe,aAAa,KAAK,KAAK,MAAM,EAAE;AAAA,EACxE;AAEA,QAAM,WAAW,KAAK;AACtB,QAAM,SAAS,sBAAsB,QAAQ;AAC7C,MAAI,OAAO,SAAS;AAClB,WAAO,YAAY;AAAA,EACrB;AAEA,QAAM,EAAE,QAAQ,SAAS,IAAI,8BAA8B,OAAO,OAAO,QAAQ;AACjF,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB,QAAQ,OAAO,IAAI,CAAC,MAAM,GAAG,eAAe,aAAa,KAAK,CAAC,EAAE;AAAA,IACjE,UAAU,SAAS,IAAI,CAAC,MAAM,GAAG,eAAe,aAAa,KAAK,CAAC,EAAE;AAAA,EACvE;AACF;;;ADhYA,eAAsB,eACpB,OACA,QACA,cACoB;AACpB,QAAM,eAAe,oBAAoB,OAAO,QAAQ,YAAY;AACpE,QAAM,eAAe,oBAAoB,OAAO,QAAQ,YAAY;AAEpE,QAAM,CAAC,SAAS,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC3C,UAAU,cAAc,YAAY;AAAA,IACpC,UAAU,cAAc,YAAY;AAAA,EACtC,CAAC;AACD,SAAO,EAAE,SAAS,QAAQ;AAC5B;AAEA,SAAS,oBACP,OACA,QACA,EAAE,YAAY,MAAM,GACC;AACrB,SAAO;AAAA,IACL,cAAc,OAAO,KAAK,EAAE,IAAI,CAAC,WAAW;AAAA,MAC1C,KAAK,UAAU,MAAM,KAAK,GAAG,OAAO,UAAU;AAAA,MAC9C,OAAO,WAAW,MAAM,KAAK,CAAC;AAAA,MAC9B,SAAS,QAAQ,OAAO,OAAO,UAAU,oBAAoB,QAAQ,KAAK,CAAC;AAAA,IAC7E,EAAE;AAAA,EACJ;AACF;AAEA,SAAS,oBACP,OACA,QACA,EAAE,YAAY,MAAM,GACJ;AAChB,SAAO;AAAA,IACL,cAAc,OAAO,KAAK,EAAE,IAAI,CAAC,WAAW;AAAA,MAC1C,KAAK,UAAU,MAAM,KAAK,GAAG,OAAO,UAAU;AAAA,MAC9C,SAAS,QAAQ,OAAO,OAAO,UAAU,kBAAkB,QAAQ,KAAK,CAAC;AAAA,IAC3E,EAAE;AAAA,EACJ;AACF;AAOA,SAAS,cAAc,OAAoB,OAA4B;AACrE,QAAM,YAAY,MAAM,SAAS,YAAY,CAAC,SAAS,KAAK;AAC5D,SAAO,aAAa,MAAM,WAAW,MAAM,UAAU,CAAC,SAAS,IAAI,CAAC,WAAW,QAAQ;AACzF;AAEA,SAAS,SAAS,OAA6B;AAC7C,SAAO,MAAM,SAAS,YAAY,MAAM;AAC1C;AAGA,SAAS,QACP,OACA,OACA,OAC4B;AAC5B,MAAI,UAAU,QAAQ,MAAM,SAAS,SAAU,QAAO;AACtD,MAAI,SAAS,KAAK,KAAK,UAAU,UAAW,QAAO;AACnD,SAAO,IAAI,IAAI,KAAK;AACtB;AAEA,SAAS,oBAAoB,QAAuB,OAA6B;AAC/E,SAAO,OAAO,OAAO,OAAO,CAAC,UAAU,SAAS,OAAO,KAAK,CAAC,EAAE,IAAI,CAAC,UAAU,MAAM,IAAI;AAC1F;AAEA,SAAS,kBAAkB,QAAuB,OAA6B;AAC7E,SAAO,OAAO,OAAO,OAAO,CAAC,UAAU,SAAS,OAAO,KAAK,CAAC,EAAE,IAAI,CAAC,UAAU,MAAM,EAAE;AACxF;AAGA,SAAS,SAAS,OAAkD,OAA4B;AAC9F,SAAO,MAAM,UAAU,UAAU,UAAU,YAAY,CAAC,MAAM;AAChE;AAGA,SAAS,cAA2C,SAA6B;AAC/E,SAAO,YAAY,QAAQ,SAAS,CAAC,WAAW,OAAO,GAAG,CAAC,EAAE;AAAA,IAAI,CAAC,YAChE,QAAQ,OAAO,UAAU;AAAA,EAC3B;AACF;AAEA,SAAS,WAAwC,MAAc,MAAsB;AACnF,MAAI,KAAK,YAAY,KAAM,QAAO;AAClC,MAAI,KAAK,YAAY,KAAM,QAAO;AAClC,SAAO,EAAE,GAAG,MAAM,SAAS,oBAAI,IAAI,CAAC,GAAG,KAAK,SAAS,GAAG,KAAK,OAAO,CAAC,EAAE;AACzE;AAEA,eAAe,UACb,cACA,cACkB;AAClB,QAAM,CAAC,QAAQ,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,IACzC,QAAQ;AAAA,MACN,aAAa,OAAO,WAAW,EAAE,IAAI,CAAC,EAAE,IAAI,MAAM,6BAA6B,GAAG,CAAC;AAAA,IACrF;AAAA,IACA,QAAQ;AAAA,MACN,aACG,OAAO,WAAW,EAClB,IAAI,CAAC,EAAE,KAAK,MAAM,MAAM,8BAA8B,KAAK,KAAK,CAAC;AAAA,IACtE;AAAA,EACF,CAAC;AACD,SAAO,EAAE,QAAQ,OAAO,KAAK,GAAG,QAAQ,OAAO,KAAK,EAAE;AACxD;AAEA,eAAe,UACb,cACA,cACkB;AAClB,QAAM,CAAC,QAAQ,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,IACzC,QAAQ,IAAI,aAAa,IAAI,kBAAkB,CAAC;AAAA,IAChD,QAAQ,IAAI,aAAa,IAAI,mBAAmB,CAAC;AAAA,EACnD,CAAC;AACD,SAAO,EAAE,QAAQ,OAAO,KAAK,GAAG,QAAQ,OAAO,KAAK,EAAE;AACxD;AAEA,SAAS,YAAY,QAA+B;AAClD,SAAO,OAAO,YAAY;AAC5B;AAEA,eAAe,mBAAmB,EAAE,KAAK,SAAAG,SAAQ,GAAoC;AACnF,MAAIA,aAAY,KAAM,QAAO,CAAC;AAC9B,QAAM,OAAO,MAAM,+BAA+B,GAAG;AACrD,SAAO,KAAK,OAAO,CAAC,SAAS,CAACA,SAAQ,IAAI,IAAI,CAAC;AACjD;AAEA,eAAe,oBAAoB,EAAE,KAAK,OAAO,SAAAA,SAAQ,GAAyC;AAChG,MAAIA,aAAY,QAAQ,CAAE,MAAM,gBAAgB,GAAG,EAAI,QAAO,CAAC;AAC/D,QAAM,QAAQ,MAAM,iBAAiB,KAAK,KAAK;AAC/C,SAAO,MAAM,OAAO,CAAC,SAAS,CAACA,SAAQ,IAAIC,MAAK,SAAS,MAAM,MAAM,SAAS,CAAC,CAAC;AAClF;;;AFpGA,SAAS,SAAS,cAAc;AAoChC,SAAS,iBACP,OACA,cACmB;AACnB,QAAM,YAAY,CAAC,YAAoB,iBAAiB,OAAO,cAAc,OAAO;AACpF,MAAI,MAAM,SAAS,UAAU;AAC3B,WAAO;AAAA,MACL,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,UAAU,WAAW;AAAA,QAC9B,SAAS,CAAC,QAAQ,kBAAkB,kCAAkC;AAAA,MACxE;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,MAAM,SAAS,cAAc;AAC/B,WAAO;AAAA,MACL,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,UAAU,gCAAgC;AAAA,QACnD,SAAS,CAAC,MAAM,QAAQ,MAAM;AAAA,MAChC;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AAGA,MAAI,MAAM,SAAS,oBAAoB;AACrC,WAAO;AAAA,MACL,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,UAAU,+CAA+C;AAAA,MACpE;AAAA,MACA,QAAQ,MAAM;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM,aAAa,sBAAsB,MAAM;AAE/C,MAAI,CAAC,WAAW,OAAO;AACrB,WAAO;AAAA,MACL,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,UAAU,YAAY;AAAA,QAC/B,SAAS,WAAW;AAAA,MACtB;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,WAAW,SAAS,SAAS,GAAG;AAClC,WAAO;AAAA,MACL,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,UAAU,cAAc;AAAA,QACjC,SAAS,WAAW;AAAA,MACtB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,UAAU,UAAU;AAAA,IAC/B;AAAA,IACA;AAAA,EACF;AACF;AAGA,SAAS,iBACP,OACA,EAAE,YAAY,MAAM,GACpB,SACQ;AACR,MAAI,MAAM,SAAS,YAAY,MAAM;AACnC,WAAO,GAAG,mBAAmB,MAAM,MAAM,CAAC,WAAW,OAAO;AAC9D,MAAI,MAAM,SAAS,cAAc;AAC/B,UAAM,EAAE,WAAW,MAAM,IAAI,MAAM;AACnC,WAAO,GAAG,YAAY,WAAW,MAAM,KAAK,CAAC,CAAC,IAAI,OAAO;AAAA,EAC3D;AACA,SAAO,GAAG,YAAY,YAAY,MAAM,OAAO,CAAC,IAAI,OAAO;AAC7D;AAEA,SAAS,YAAY,MAAc,UAA4B;AAC7D,SAAO,GAAG,WAAW,QAAQ,IAAI,CAAC,CAAC,KAAK,gBAAgB,MAAM,QAAQ,CAAC;AACzE;AAEA,SAAS,mBAAmB,UAA4B;AACtD,SAAO,GAAG,WAAW,SAAS,CAAC,QAAQ,eAAe,SAAS,WAAW,UAAU,QAAQ,CAAC,OAAO,gBAAgBC,IAAG,QAAQ,GAAG,QAAQ,CAAC;AAC7I;AAEA,SAAS,QAAQ,KAAwB;AACvC,SAAO,gBAAgB,GAAG,IAAI,WAAW;AAC3C;AAEA,SAAS,gBAAgB,MAAc,UAA4B;AACjE,QAAM,UAAU,mBAAmB,MAAM,QAAQ;AACjD,SAAO,gBAAgB,IAAI,IAAI,KAAK,OAAO,KAAK;AAClD;AAGA,SAAS,oBAAoB,QAAuBC,SAAyC;AAC3F,QAAM,eAAe,kBAAkB,MAAM;AAE7C,MAAI,aAAa,WAAW,GAAG;AAC7B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,gBAAgB,aAAa,OAAO,CAAC,YAAY,EAAE,WAAWA,QAAO,OAAO;AAElF,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,GAAG,MAAM,aAAa,SAAS,cAAc,QAAQ,aAAa,QAAQ,OAAO,CAAC;AAAA,MAC3F,SAAS,cAAc,IAAI,CAAC,MAAM,KAAK,CAAC,cAAc;AAAA,IACxD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,GAAG,MAAM,aAAa,QAAQ,aAAa,QAAQ,OAAO,CAAC;AAAA,EACtE;AACF;AAGA,SAAS,kBAAkB,QAAkC;AAC3D,QAAM,cAAc,4BAA4B,OAAO,MAAM;AAC7D,QAAM,WAAW,OAAO,QAAQ,iBAAiB,OAAO,KAAK,IAAI,CAAC;AAClE,SAAO,OAAO,CAAC,GAAG,UAAU,GAAG,OAAO,OAAO,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE;AAAA,IAC9D,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE;AAAA,EAC7B;AACF;AAEA,eAAe,oBACb,QACA,cACsB;AACtB,MAAI,OAAO,OAAO,WAAW,GAAG;AAC9B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,cAAc,MAAM,QAAQ;AAAA,IAChC,OAAO,OAAO,IAAI,CAAC,UAAU,kBAAkB,OAAO,YAAY,CAAC;AAAA,EACrE;AACA,QAAM,eAAe,YAAY,OAAO,CAAC,MAAM,EAAE,UAAU,cAAc;AACzE,QAAM,gBAAgB,YAAY,OAAO,CAAC,MAAM,EAAE,UAAU,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAGxF,MAAI,aAAa,WAAW,OAAO,OAAO,QAAQ;AAChD,UAAM,sBAAsB,OAAO,aAAa,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,KAAK,MAAM;AACnF,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,oDAAoD,mBAAmB;AAAA,MAChF,SAAS,aAAa,IAAI,CAAC,MAAM,KAAK,EAAE,IAAI,iBAAiB,EAAE,QAAQ,GAAG;AAAA,IAC5E;AAAA,EACF;AAEA,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,kBAAkB,cAAc,MAAM;AAAA,MAC/C,SAAS,cAAc,IAAI,CAAC,MAAM,KAAK,CAAC,YAAY;AAAA,IACtD;AAAA,EACF;AAEA,QAAM,aAAa,OAAO,OAAO,SAAS,aAAa;AACvD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,GAAG,MAAM,YAAY,YAAY,OAAO,CAAC;AAAA,EACpD;AACF;AAEA,SAAS,kBAAkB,OAAuB;AAChD,SAAO,GAAG,OAAO,OAAO,OAAO,CAAC,IAAI,UAAU,IAAI,UAAU,MAAM;AACpE;AASA,eAAe,kBACb,OACA,EAAE,YAAY,MAAM,GACQ;AAC5B,QAAM,WAAW,MAAM,MAAM,KAAK;AAClC,MAAI,CAAC,kBAAkB,UAAU,MAAM,IAAI,GAAG;AAC5C,WAAO,EAAE,MAAM,MAAM,MAAM,UAAU,OAAO,eAAe;AAAA,EAC7D;AAEA,QAAM,OAAO,GAAG,MAAM,IAAI,GAAG,WAAW,QAAQ,EAAE,SAAS;AAC3D,QAAM,WAAW,MAAM,WAAWC,MAAK,KAAK,UAAU,UAAU,MAAM,OAAO,UAAU,GAAG,IAAI,CAAC;AAC/F,SAAO,EAAE,MAAM,MAAM,MAAM,UAAU,OAAO,WAAW,aAAa,UAAU;AAChF;AAEA,eAAe,eACb,OACA,QACA,cACsB;AACtB,SAAO,gBAAgB,OAAO,MAAM,eAAe,OAAO,QAAQ,YAAY,CAAC;AACjF;AAEA,SAAS,gBAAgB,OAAoB,EAAE,SAAS,QAAQ,GAA2B;AACzF,MAAI,QAAQ,OAAO,SAAS,KAAK,QAAQ,OAAO,SAAS,GAAG;AAC1D,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,GAAG,iBAAiB,QAAQ,QAAQ,QAAQ,MAAM,CAAC;AAAA,MAC5D,SAAS,CAAC,GAAG,QAAQ,QAAQ,GAAG,QAAQ,QAAQ,GAAG,YAAY,OAAO,CAAC,EAAE;AAAA,QACvE,CAAC,SAAS,KAAK,IAAI;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,OAAO,SAAS,KAAK,QAAQ,OAAO,SAAS,GAAG;AAC1D,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,eAAe,OAAO;AAAA,MAC/B,SAAS,YAAY,OAAO,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE;AAAA,IACzD;AAAA,EACF;AAGA,MAAI,MAAM,SAAS,SAAU,QAAO,cAAc,SAAS;AAE3D,SAAO,EAAE,MAAM,WAAW,QAAQ,QAAQ,SAAS,oCAAoC;AACzF;AAEA,SAAS,YAAY,EAAE,QAAQ,OAAO,GAAsB;AAC1D,SAAO,CAAC,GAAG,QAAQ,GAAG,MAAM,EAAE,IAAI,CAAC,SAAS,GAAG,IAAI,kBAAkB;AACvE;AAEA,SAAS,eAAe,EAAE,QAAQ,OAAO,GAAoB;AAC3D,SAAO,cAAc,CAAC,OAAO,QAAQ,gBAAgB,GAAG,CAAC,OAAO,QAAQ,qBAAqB,CAAC;AAChG;AAEA,SAAS,MAAM,OAAe,OAAe,MAAsB;AACjE,SAAO,GAAG,KAAK,IAAI,OAAO,OAAO,IAAI,CAAC;AACxC;AAEA,SAAS,iBAAiB,QAAkB,QAA0B;AACpE,SAAO,cAAc,CAAC,OAAO,QAAQ,OAAO,GAAG,CAAC,OAAO,QAAQ,OAAO,CAAC;AACzE;AAKA,SAAS,iBAAiB,QAAyB;AACjD,SAAO,OACJ,OAAO,CAAC,CAAC,KAAK,MAAM,QAAQ,CAAC,EAC7B,IAAI,CAAC,CAAC,OAAO,IAAI,MAAM,OAAO,OAAO,IAAI,CAAC,EAC1C,KAAK,OAAO;AACjB;AAGA,eAAe,qBACb,QACA,cACsB;AACtB,QAAM,cAAc,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,YAAY;AAEzE,MAAI,YAAY,WAAW,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,cAAc,MAAM,QAAQ;AAAA,IAChC,YAAY,IAAI,CAAC,UAAU,kBAAkB,OAAO,YAAY,CAAC;AAAA,EACnE;AACA,QAAM,gBAAgB,YAAY,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS;AAE5D,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,GAAG,OAAO,cAAc,QAAQ,OAAO,CAAC;AAAA,MACjD,SAAS,cAAc,IAAI,CAAC,MAAM,KAAK,EAAE,EAAE,kBAAkB,EAAE,QAAQ,IAAI;AAAA,IAC7E;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,GAAG,MAAM,YAAY,QAAQ,YAAY,QAAQ,kBAAkB,CAAC;AAAA,EAC/E;AACF;AAIA,eAAe,kBACb,OACA,EAAE,YAAY,MAAM,GACQ;AAC5B,QAAM,WAAW,MAAM,MAAM,KAAK;AAClC,QAAM,MAAM,UAAU,UAAU,MAAM,OAAO,UAAU;AACvD,QAAM,YAAY,MAAM,WAAWA,MAAK,KAAK,KAAK,MAAM,IAAI,eAAe,QAAQ,CAAC;AAEpF,SAAO;AAAA,IACL,IAAI,MAAM;AAAA,IACV;AAAA,IACA,UAAU,iBAAiB,UAAU,MAAM,OAAO,UAAU;AAAA,EAC9D;AACF;AAGA,eAAe,2BACb,QACA,cACsB;AACtB,QAAM,eAAe,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,YAAY;AAE1E,MAAI,aAAa,WAAW,GAAG;AAC7B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,SAAS,OAAO,aAAa,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACtD,QAAM,kBAAkB,MAAM,QAAQ;AAAA,IACpC,OAAO,IAAI,CAAC,UAAU,sBAAsB,OAAO,cAAc,YAAY,CAAC;AAAA,EAChF;AACA,QAAM,gBAAgB,gBAAgB,KAAK;AAE3C,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,GAAG,OAAO,cAAc,QAAQ,OAAO,CAAC;AAAA,MACjD,SAAS,cAAc,IAAI,CAAC,MAAM,KAAK,CAAC,4BAA4B;AAAA,IACtE;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,GAAG,MAAM,aAAa,QAAQ,aAAa,QAAQ,mBAAmB,CAAC;AAAA,EAClF;AACF;AAEA,eAAe,sBACb,OACA,cACA,EAAE,YAAY,MAAM,GACA;AACpB,QAAM,eAAe,MAAM;AAAA,IACzB,eAAe,YAAY,KAAK;AAAA,IAChC,MAAM,KAAK;AAAA,EACb;AACA,SAAO,aACJ,OAAO,CAAC,UAAU,MAAM,UAAU,KAAK,EACvC,OAAO,CAAC,UAAU,CAAC,aAAa,IAAI,MAAM,EAAE,CAAC,EAC7C,IAAI,CAAC,UAAU,MAAM,EAAE;AAC5B;AAEA,IAAM,wBAAwB;AAAA,EAC5B,MAAM;AAAA,EACN,KAAK,YAAY,cAAc;AAAA,EAC/B,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AACX;AAEA,SAAS,gBAAgB,QAAgB,SAA0B;AACjE,SAAO,UAAU,QAAQ,MAAM,eAAe,WAAW,MAAM;AACjE;AAGA,SAAS,mBAAmB,QAAuC;AACjE,QAAM,EAAE,QAAQ,aAAa,IAAI,OAAO;AACxC,QAAM,YAAY,GAAG,OAAO,OAAO,oBAAoB,MAAM,OAAO,CAAC;AACrE,QAAM,WAAW,sBAAsB,YAAY;AAEnD,MAAI,OAAO,aAAa;AACtB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,mBAAmB,MAAM;AAAA,MAClC,SAAS,CAAC,WAAW,eAAe,OAAO,UAAU,8BAAyB,QAAQ,EAAE;AAAA,IAC1F;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,gBAAgB,OAAO,UAAU,UAAU,QAAQ,KAAK,OAAO,UAAU;AAAA,IAClF,SAAS,CAAC,WAAW,GAAG,gBAAgB,QAAQ,OAAO,OAAO,CAAC,WAAM,QAAQ,EAAE;AAAA,EACjF;AACF;AAEA,eAAe,qBAAqB;AAAA,EAClC;AAAA,EACA;AACF,GAA8C;AAC5C,MAAI;AACF,WAAO;AAAA,MACL,MAAM,2BAA2B,EAAE,YAAY,UAAU,MAAM,QAAQ,CAAC;AAAA,IAC1E;AAAA,EACF,SAAS,OAAO;AACd,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,UAAU,OAAO,4BAA4B;AAAA,MACtD,SAAS,CAAC,gBAAgB,KAAK,CAAC;AAAA,IAClC;AAAA,EACF;AACF;AAgBA,IAAM,eAA6B;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,KAAK;AACP;AAGA,IAAM,iBAAsC;AAAA,EAC1C;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA;AAAA,IAEb,QAAQ,CAAC,QAAQ;AAAA,IACjB,KAAK;AAAA,EACP;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA;AAAA,IAEb,QAAQ,CAAC,SAAS;AAAA,IAClB,KAAK;AAAA,EACP;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA;AAAA,IAEN,aAAa;AAAA;AAAA,IAEb,QAAQ,CAAC,QAAQ;AAAA,IACjB,KAAK;AAAA,EACP;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA;AAAA,IAEb,QAAQ,CAAC;AAAA,IACT,KAAK;AAAA,EACP;AACF;AAEA,SAAS,cAAc,QAAgB,UAAyC;AAC9E,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,WAAW,EAAG,QAAO;AACzB,SAAO;AACT;AAEA,SAAS,eAAe,MAAc,OAAe,QAAgB,UAA0B;AAE7F,MAAI,WAAW,KAAK,aAAa,GAAG;AAClC,WAAO,UAAU,IAAI,MAAM,IAAI,kBAAkB,GAAG,OAAO,OAAO,IAAI,CAAC;AAAA,EACzE;AACA,SAAO,GAAG,OAAO,OAAO,IAAI,CAAC,KAAK,OAAO,QAAQ,OAAO,CAAC,KAAK,OAAO,UAAU,SAAS,CAAC;AAC3F;AAEA,SAAS,mBAAmB,OAA6B;AACvD,QAAM,SAAS,MAAM,aAAa,UAAU,UAAU;AACtD,SAAO,MAAM,MAAM,KAAK,MAAM,IAAI,KAAK,MAAM,OAAO;AACtD;AAEA,SAAS,gBAAgB,OAAqB,YAA4C;AACxF,QAAM,SAAS,WAAW,OAAO,OAAO,CAAC,UAAU,MAAM,aAAa,OAAO,EAAE;AAC/E,QAAM,WAAW,WAAW,OAAO,SAAS;AAE5C,SAAO;AAAA,IACL,MAAM,MAAM;AAAA,IACZ,QAAQ,cAAc,QAAQ,QAAQ;AAAA,IACtC,SAAS,eAAe,MAAM,MAAM,WAAW,OAAO,QAAQ,QAAQ;AAAA,IACtE,SAAS;AAAA,MACP,GAAG,WAAW,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE;AAAA,MAC7C,GAAG,WAAW,OAAO,IAAI,kBAAkB;AAAA,IAC7C;AAAA,EACF;AACF;AAGA,IAAM,cAAc;AAEpB,IAAM,iBAAiB;AACvB,IAAM,aAAa;AAEnB,IAAM,kBAAkB;AACxB,IAAM,sBAAsB;AAC5B,IAAM,uBAAuB;AAC7B,IAAM,yBAAyB;AAE/B,IAAM,0BAA0B;AAEhC,SAAS,qBAAqB,OAAyB;AACrD,SAAO,kDAA6C,MAAM,KAAK,OAAO,CAAC;AACzE;AAEA,SAAS,gBAAgB,MAAsB;AAC7C,SAAO,KAAK,OAAO,WAAW;AAChC;AAEA,SAAS,aAAa,QAAuC;AAC3D,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO,WAAW;AAAA,IACpB,KAAK;AACH,aAAO,WAAW;AAAA,IACpB,KAAK;AACH,aAAO,WAAW;AAAA,IACpB,KAAK;AACH,aAAO,WAAW;AAAA,IACpB,SAAS;AACP,YAAM,cAAqB;AAC3B,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,IAAM,gBAAgB,GAAG,UAAU,GAAG,IAAI,OAAO,WAAW,CAAC;AAE7D,SAAS,gBAAgB,MAAc,QAA+B;AACpE,QAAM,aAAa,GAAG,UAAU,GAAG,gBAAgB,IAAI,CAAC,GAAG,aAAa,OAAO,MAAM,CAAC,KAAK,OAAO,OAAO;AACzG,QAAM,eAAe,OAAO,WAAW,CAAC,GAAG,QAAQ,mBAAmB;AACtE,SAAO,CAAC,YAAY,GAAG,WAAW;AACpC;AAGA,SAAS,oBAAoB,QAA0B;AACrD,SAAO,OACJ,MAAM,IAAI,EACV,OAAO,CAAC,SAAS,SAAS,EAAE,EAC5B,IAAI,CAAC,SAAS,GAAG,aAAa,GAAG,IAAI,EAAE;AAC5C;AAEA,SAAS,cAAc,SAAgC;AACrD,QAAM,SAAS,QAAQ,SAAS,CAAC,MAAM,EAAE,MAAM;AAE/C,QAAM,QAAQ;AAAA,IACZ,GAAG,OAAO,QAAQ,CAAC;AAAA,IACnB,OAAO,OAAO,QAAQ,GAAG,SAAS;AAAA,IAClC,OAAO,OAAO,QAAQ,GAAG,OAAO;AAAA,EAClC;AAEA,SAAO,GAAG,cAAc,YAAY,MAAM,KAAK,IAAI,CAAC;AACtD;AASA,IAAM,OAAc;AAAA,EAClB;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,MAAM,CAAC,aACL,eAAe,gBAAgB,UAAU,SAAS,CAAC;AAAA,EACvD;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,MAAM,MAAM,eAAe,kBAAkB;AAAA,EAC/C;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,MAAM,MACJ,gDAA2C,kBAAkB;AAAA,EACjE;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,MAAM,CAAC,aACL,mDAA8C,gBAAgB,UAAU,kBAAkB,CAAC,yDAAyD,gBAAgB,UAAU,WAAW,CAAC;AAAA,EAC9L;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,MAAM,MAAM;AAAA,EACd;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA;AAAA,IAER,MAAM,MAAM;AAAA,EACd;AACF;AAEA,SAAS,gBAAgB,UAAgC,SAAyB;AAChF,SAAO,GAAG,kBAAkB,IAAI,OAAO,GAAG,iBAAiB,QAAQ,CAAC;AACtE;AAGA,SAAS,WAAW,SAAkC;AACpD,SAAO,OAAO,KAAK,QAAQ,CAAC,QAAQ,QAAQ,KAAK,OAAO,CAAC,CAAC;AAC5D;AAEA,SAAS,QAAQ,KAAU,SAAkC;AAC3D,SAAO,QACJ,OAAO,CAAC,WAAW,QAAQ,KAAK,MAAM,CAAC,EACvC,IAAI,CAAC,WAAW,IAAI,KAAK,OAAO,QAAQ,CAAC;AAC9C;AAEA,SAAS,QAAQ,KAAU,QAA8B;AACvD,SAAO,OAAO,SAAS,IAAI,QAAQ,OAAO,WAAW,IAAI;AAC3D;AAGA,eAAe,mBACb,gBACA,YACmB;AACnB,MAAI,CAAC,mBAAmB,cAAc,EAAE,IAAI,aAAa,IAAI,EAAG,QAAO,CAAC;AAExE,QAAM,WAAW,MAAM,uBAAuB,UAAU,EAAE,MAAM,MAAM,CAAC,CAAC;AACxE,SAAO,SAAS;AAAA,IACd,CAAC,YACC,oFAA+E,mBAAmB,OAAO,CAAC;AAAA,EAC9G;AACF;AAEA,IAAM,yBAAyB;AAG/B,eAAe,yBACb,YACA,WACsB;AACtB,QAAM,UAAU,MAAM,iBAAiB,UAAU;AACjD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,GAAG,UAAU,MAAM;AAAA,IAC5B,SAAS,YAAY,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,EAAE;AAAA,EAClD;AACF;AAEA,SAAS,oBAAoB,UAA4B;AACvD,SAAO,GAAG,cAAc,OAAO,QAAQ;AACzC;AAEA,IAAM,uBAAuB;AAG7B,eAAe,sBAAsB,YAAiD;AAEpF,MAAI,CAAE,MAAM,aAAa,UAAU,EAAI,QAAO;AAC9C,SAAO,EAAE,MAAM,eAAe,QAAQ,QAAQ,SAAS,qBAAqB;AAC9E;AAEA,IAAM,kBAAkB;AAGxB,eAAe,YAAY,EAAE,YAAY,MAAM,GAAgD;AAC7F,QAAM,SAAS,MAAM,mBAAmB,YAAY,CAAC,EAAE,KAAK,MAAM,MAAM,IAAI,CAAC;AAC7E,SAAO,OAAO,IAAI,cAAc;AAClC;AAEA,SAAS,eAAe,OAAiC;AACvD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,gBAAgB,WAAW,MAAM,IAAI,GAAG,MAAM,OAAO;AAAA,EAChE;AACF;AAEA,IAAM,sBAAsB;AAG5B,eAAe,uBAAuB,cAAyD;AAC7F,QAAM,WAAW,MAAM,sBAAsB,YAAY;AAEzD,MAAI,SAAS,WAAW,GAAG;AACzB,WAAO,EAAE,MAAM,cAAc,QAAQ,QAAQ,SAAS,sCAAsC;AAAA,EAC9F;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,GAAG,OAAO,SAAS,QAAQ,SAAS,CAAC;AAAA,IAC9C,SAAS,SAAS,IAAI,CAAC,YAAY,KAAK,OAAO,EAAE;AAAA,EACnD;AACF;AAEA,SAAS,cAAc,MAA8B;AACnD,SAAO,EAAE,MAAM,QAAQ,QAAQ,SAAS,2BAA2B;AACrE;AAEA,SAAS,gCAA6C;AACpD,SAAO,EAAE,MAAM,UAAU,QAAQ,QAAQ,SAAS,oCAAoC;AACxF;AAEA,SAAS,qBAAqB,MAA8B;AAC1D,SAAO,EAAE,MAAM,QAAQ,QAAQ,SAAS,uBAAuB;AACjE;AAEA,SAAS,mBAAmB,gBAAuD;AACjF,SAAO,IAAI,IAAI,eAAe,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AACrF;AAGA,SAAS,qBACP,KACA,eACoB;AACpB,QAAM,gBAAgB,eAAe,OAAO,CAAC,UAAU,cAAc,IAAI,MAAM,IAAI,CAAC,EACjF,OAAO,CAAC,UAAU,MAAM,OAAO,SAAS,GAAG,CAAC,EAC5C,IAAI,CAAC,UAAU,MAAM,IAAI;AAE5B,MAAI,cAAc,WAAW,EAAG,QAAO;AAEvC,SAAO,EAAE,MAAM,KAAK,QAAQ,QAAQ,SAAS,qBAAqB,aAAa,EAAE;AACnF;AAEA,SAAS,gBAAgB,OAAqB,YAA0C;AACtF,SAAO,UAAU,MAAM,MAAM,YAAY,gBAAgB,OAAO,MAAM,MAAM,IAAI,UAAU,CAAC,CAAC;AAC9F;AAEA,eAAe,qBACb,OACA,YACA,kBACsB;AACtB,MAAI,MAAM,eAAe,iBAAkB,QAAO,qBAAqB,MAAM,IAAI;AACjF,SAAO,gBAAgB,OAAO,UAAU;AAC1C;AAGA,eAAe,cACb,OACA,MACmB;AACnB,SAAO,MAAM;AAAA,IACX,OAAO,SAAS,SAAS,CAAC,GAAI,MAAM,SAAU,GAAI,MAAM,KAAK,IAAI,CAAE;AAAA,IACnE,QAAQ,QAAQ,CAAC,CAAC;AAAA,EACpB;AACF;AAGA,eAAe,UACb,MACA,IAC+B;AAC/B,MAAI;AACF,WAAO,MAAM,GAAG;AAAA,EAClB,SAAS,OAAO;AACd,WAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,MACR,SAAS,UAAU,OAAO,aAAa;AAAA,MACvC,SAAS,CAAC,gBAAgB,KAAK,CAAC;AAAA,IAClC;AAAA,EACF;AACF;AAGA,SAAS,UAAU,OAAgB,WAA2B;AAC5D,SAAO,iBAAiB,0BAA0B,YAAY;AAChE;AAEA,IAAqB,SAArB,MAAqB,gBAAe,YAAY;AAAA,EAC9C,OAAO,UAAU;AAAA,EAEjB,OAAO,cAAc,iCAAiC,iBAAiB,IAAI;AAAA,EAE3E,OAAO,WAAW,CAAC,qCAAqC;AAAA,EAExD,OAAO,QAAQ,CAAC;AAAA,EAEhB,MAAM,MAAqB;AACzB,UAAM,KAAK,MAAM,OAAM;AACvB,UAAM,aAAa,QAAQ,IAAI;AAG/B,SAAK,YAAY,MAAM,KAAK,oBAAoB,UAAU,CAAC;AAC3D,UAAM,iBAAiB,MAAM,KAAK,iBAAiB,UAAU;AAC7D,UAAM,qBAAqB,MAAM,KAAK,qBAAqB,YAAY,cAAc;AACrF,UAAM,UAAU,CAAC,GAAG,gBAAgB,GAAG,kBAAkB;AAEzD,SAAK,aAAa,SAAS,MAAM,mBAAmB,gBAAgB,UAAU,CAAC;AAE/E,QAAI,QAAQ,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM,GAAG;AAC5C,WAAK,KAAK,WAAW,KAAK;AAAA,IAC5B;AAAA,EACF;AAAA,EAEQ,YAAY,cAA4B;AAC9C,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,GAAG,YAAY,SAAS;AACjC,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,GAAG,cAAc,kCAAkC;AAC5D,SAAK,IAAI,EAAE;AAAA,EACb;AAAA,EAEA,MAAc,iBAAiB,YAA4C;AACzE,SAAK,IAAI,GAAG,cAAc,GAAG,eAAe,EAAE;AAE9C,UAAM,eAAe,MAAM,gBAAgB,cAAc,UAAU;AACnE,UAAM,mBAAmB,aAAa,WAAW;AAEjD,UAAM,OAAO,MAAM,QAAQ;AAAA,MACzB,eAAe,IAAI,OAAO,WAAW;AAAA,QACnC,MAAM,MAAM;AAAA,QACZ,QAAQ,MAAM,qBAAqB,OAAO,YAAY,gBAAgB;AAAA,MACxE,EAAE;AAAA,IACJ;AAEA,UAAM,UAAU,CAAC,EAAE,MAAM,aAAa,MAAM,QAAQ,aAAa,GAAG,GAAG,IAAI;AAE3E,eAAW,OAAO,SAAS;AACzB,WAAK,SAAS,IAAI,MAAM,IAAI,MAAM;AAAA,IACpC;AAEA,WAAO,QAAQ,IAAI,CAAC,QAAQ,IAAI,MAAM;AAAA,EACxC;AAAA,EAEA,MAAc,qBACZ,YACA,gBACwB;AACxB,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,GAAG,cAAc,GAAG,mBAAmB,EAAE;AAElD,UAAM,gBAAgB,mBAAmB,cAAc;AACvD,QAAI,cAAc,IAAI,aAAa,IAAI,GAAG;AACxC,WAAK,IAAI,GAAG,UAAU,GAAG,uBAAuB,EAAE;AAClD,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,YAAY,MAAM,gBAAgB,UAAU;AAClD,QAAI,UAAU,SAAS,GAAG;AACxB,aAAO,KAAK,sBAAsB,YAAY,WAAW,aAAa;AAAA,IACxE;AACA,WAAO,KAAK,qBAAqB,YAAY,aAAa;AAAA,EAC5D;AAAA,EAEA,MAAc,qBACZ,YACA,eACwB;AACxB,UAAM,eAAe,EAAE,YAAY,OAAO,YAAY,UAAU,EAAE;AAClE,UAAM,cAAc,MAAM,mBAAmB,YAAY;AAEzD,QAAI,YAAY,SAAS,UAAU;AACjC,YAAM,aAAa,MAAM,UAAU,eAAe,MAAM,sBAAsB,UAAU,CAAC;AACzF,UAAI,eAAe,KAAM,QAAO,KAAK,iBAAiB,UAAU;AAAA,IAClE;AAEA,WAAO,KAAK,aAAa,cAAc,aAAa,aAAa;AAAA,EACnE;AAAA;AAAA,EAGQ,iBAAiB,YAAwC;AAC/D,QAAI,WAAW,WAAW,QAAQ;AAChC,WAAK,IAAI,GAAG,UAAU,GAAG,WAAW,OAAO,EAAE;AAC7C,aAAO,CAAC;AAAA,IACV;AAEA,SAAK,SAAS,sBAAsB,UAAU;AAC9C,WAAO,CAAC,UAAU;AAAA,EACpB;AAAA;AAAA,EAGA,MAAc,sBACZ,YACA,WACA,eACwB;AACxB,UAAM,gBAAgB,MAAM;AAAA,MAAU;AAAA,MAAiB,MACrD,yBAAyB,YAAY,SAAS;AAAA,IAChD;AACA,SAAK,SAAS,wBAAwB,aAAa;AAEnD,UAAM,SAAS,MAAM;AAAA,MAAc;AAAA,MAAW,CAAC,aAC7C,KAAK,WAAW,YAAY,UAAU,aAAa;AAAA,IACrD;AACA,WAAO,CAAC,eAAe,GAAG,MAAM;AAAA,EAClC;AAAA,EAEA,MAAc,WACZ,YACA,UACA,eACwB;AACxB,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,oBAAoB,QAAQ,CAAC;AAEtC,UAAM,eAAe,EAAE,YAAY,OAAO,QAAQ,QAAQ,EAAE;AAC5D,UAAM,UAAU,MAAM,KAAK;AAAA,MACzB;AAAA,MACA,MAAM,mBAAmB,YAAY;AAAA,MACrC;AAAA,IACF;AACA,WAAO,QAAQ,IAAI,CAAC,YAAY,EAAE,GAAG,QAAQ,SAAS,EAAE;AAAA,EAC1D;AAAA,EAEA,MAAc,aACZ,cACA,aACA,eACwB;AACxB,UAAM,EAAE,QAAQ,cAAc,OAAO,IAAI,iBAAiB,aAAa,YAAY;AACnF,SAAK,SAAS,gBAAgB,YAAY;AAE1C,UAAM,gBAAgB,MAAM,KAAK,aAAa,YAAY;AAE1D,UAAM,mBAAmB,MAAM;AAAA,MAAU;AAAA,MAAc,MACrD,uBAAuB,YAAY;AAAA,IACrC;AACA,SAAK,SAAS,qBAAqB,gBAAgB;AAGnD,UAAM,eAAe,MAAM,UAAU,UAAU,MAAM,qBAAqB,YAAY,CAAC;AAEvF,UAAM,iBAAiB,SAAS,sBAAsB,MAAM,IAAI;AAEhE,UAAM,eAAe,MAAM,KAAK,mBAAmB,QAAQ,cAAc,aAAa;AACtF,SAAK,SAAS,mBAAmB,YAAY;AAE7C,UAAM,eAAe,MAAM,KAAK,mBAAmB,gBAAgB,YAAY;AAC/E,SAAK,SAAS,mBAAmB,YAAY;AAE7C,UAAM,gBAAgB,MAAM,KAAK,oBAAoB,QAAQ,aAAa,YAAY;AACtF,SAAK,SAAS,cAAc,aAAa;AAEzC,UAAM,kBAAkB,MAAM,KAAK,sBAAsB,gBAAgB,YAAY;AACrF,SAAK,SAAS,oBAAoB,eAAe;AAEjD,UAAM,gBAAgB,MAAM,KAAK;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,SAAK,SAAS,qBAAqB,aAAa;AAEhD,SAAK,SAAS,yBAAyB,YAAY;AAEnD,WAAO;AAAA,MACL;AAAA,MACA,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,aAAa,cAA2D;AACpF,UAAM,OAAO,MAAM,YAAY,YAAY;AAE3C,eAAW,OAAO,MAAM;AACtB,WAAK,SAAS,iBAAiB,GAAG;AAAA,IACpC;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAc,oBACZ,QACA,aACA,cACsB;AACtB,QAAI,CAAC,UAAU,YAAY,SAAS,SAAU,QAAO,cAAc,SAAS;AAC5E,WAAO,UAAU,WAAW,MAAM,eAAe,aAAa,QAAQ,YAAY,CAAC;AAAA,EACrF;AAAA,EAEA,MAAc,mBACZ,QACA,cACA,eACsB;AACtB,QAAI,CAAC,OAAQ,QAAO,cAAc,QAAQ;AAE1C,UAAM,UAAU,qBAAqB,UAAU,aAAa;AAC5D,QAAI,QAAS,QAAO;AACpB,QAAI,aAAa,WAAW,OAAQ,QAAO,8BAA8B;AAEzE,WAAO,UAAU,UAAU,MAAM,oBAAoB,QAAQ,MAAM,CAAC;AAAA,EACtE;AAAA,EAEA,MAAc,mBACZ,QACA,cACsB;AACtB,QAAI,CAAC,OAAQ,QAAO,cAAc,QAAQ;AAC1C,WAAO,UAAU,UAAU,MAAM,oBAAoB,QAAQ,YAAY,CAAC;AAAA,EAC5E;AAAA,EAEA,MAAc,sBACZ,QACA,cACsB;AACtB,QAAI,CAAC,OAAQ,QAAO,cAAc,WAAW;AAC7C,WAAO,UAAU,aAAa,MAAM,qBAAqB,QAAQ,YAAY,CAAC;AAAA,EAChF;AAAA,EAEA,MAAc,oBACZ,QACA,cACA,eACsB;AACtB,QAAI,CAAC,OAAQ,QAAO,cAAc,SAAS;AAE3C,UAAM,UAAU,qBAAqB,WAAW,aAAa;AAC7D,QAAI,QAAS,QAAO;AAEpB,WAAO,UAAU,WAAW,MAAM,2BAA2B,QAAQ,YAAY,CAAC;AAAA,EACpF;AAAA,EAEQ,SAAS,MAAc,QAA2B;AACxD,eAAW,QAAQ,gBAAgB,MAAM,MAAM,GAAG;AAChD,WAAK,IAAI,IAAI;AAAA,IACf;AAAA,EACF;AAAA,EAEQ,aAAa,SAAwB,cAA8B;AACzE,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,cAAc,OAAO,CAAC;AAE/B,UAAM,OAAO,CAAC,GAAG,WAAW,OAAO,GAAG,GAAG,YAAY;AACrD,QAAI,KAAK,SAAS,GAAG;AACnB,WAAK,IAAI,EAAE;AACX,iBAAW,OAAO,MAAM;AACtB,aAAK,IAAI,GAAG;AAAA,MACd;AAAA,IACF;AAEA,SAAK,IAAI,EAAE;AAAA,EACb;AACF;","names":["os","path","path","os","path","skillsDir","agentsDir","os","path","skillsDir","agentsDir","claimed","path","os","matrix","path"]}