agents-inc 0.168.0 → 0.170.1

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 (200) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +18 -15
  3. package/dist/{chunk-JIBCVXXL.js → chunk-3G7X2WKI.js} +4 -4
  4. package/dist/{chunk-JOEA52NR.js → chunk-44TE3RKH.js} +46 -2
  5. package/dist/chunk-44TE3RKH.js.map +1 -0
  6. package/dist/{chunk-NU2K5G54.js → chunk-52HDHJ7I.js} +11 -19
  7. package/dist/chunk-52HDHJ7I.js.map +1 -0
  8. package/dist/{chunk-EH2PGPLP.js → chunk-6HNXYYVF.js} +39 -22
  9. package/dist/chunk-6HNXYYVF.js.map +1 -0
  10. package/dist/{chunk-4UKMQUAU.js → chunk-6ZRH5RHC.js} +10 -11
  11. package/dist/chunk-6ZRH5RHC.js.map +1 -0
  12. package/dist/{chunk-5JUQKGCP.js → chunk-7RDMTR64.js} +14 -34
  13. package/dist/chunk-7RDMTR64.js.map +1 -0
  14. package/dist/{chunk-3LZNY46H.js → chunk-BMRUNMPV.js} +4 -4
  15. package/dist/{chunk-VVRI35SK.js → chunk-CLPUWOSA.js} +4 -4
  16. package/dist/{chunk-VVRI35SK.js.map → chunk-CLPUWOSA.js.map} +1 -1
  17. package/dist/{chunk-TW35AEB4.js → chunk-F2BHT5C4.js} +9 -7
  18. package/dist/chunk-F2BHT5C4.js.map +1 -0
  19. package/dist/{chunk-27AVGFXH.js → chunk-F5EBEATU.js} +2 -2
  20. package/dist/{chunk-GE7NUPMI.js → chunk-HED2DAXZ.js} +3 -3
  21. package/dist/{chunk-7PYXS2QU.js → chunk-KOLDW6SF.js} +3 -3
  22. package/dist/{chunk-7PYXS2QU.js.map → chunk-KOLDW6SF.js.map} +1 -1
  23. package/dist/{chunk-C2UISKIM.js → chunk-MQ6CGZNJ.js} +109 -422
  24. package/dist/chunk-MQ6CGZNJ.js.map +1 -0
  25. package/dist/{chunk-P6I72PR3.js → chunk-NCWDK6L7.js} +115 -196
  26. package/dist/chunk-NCWDK6L7.js.map +1 -0
  27. package/dist/{chunk-VRXX4D6K.js → chunk-NEZ4OAOL.js} +1 -1
  28. package/dist/chunk-NEZ4OAOL.js.map +1 -0
  29. package/dist/chunk-NIHUOWE4.js +106 -0
  30. package/dist/chunk-NIHUOWE4.js.map +1 -0
  31. package/dist/{chunk-OI2H6M5I.js → chunk-NQW25DCF.js} +2 -2
  32. package/dist/chunk-NQW25DCF.js.map +1 -0
  33. package/dist/{chunk-ZUGH4MQG.js → chunk-OYJQUA3D.js} +3 -3
  34. package/dist/{chunk-ZUGH4MQG.js.map → chunk-OYJQUA3D.js.map} +1 -1
  35. package/dist/{chunk-AG3ZVM3B.js → chunk-PJWGTNOX.js} +186 -210
  36. package/dist/chunk-PJWGTNOX.js.map +1 -0
  37. package/dist/{chunk-HR7TK2XW.js → chunk-RIPSGNLU.js} +3 -3
  38. package/dist/chunk-RIPSGNLU.js.map +1 -0
  39. package/dist/{chunk-4DRFEYCE.js → chunk-SZYQISA2.js} +7 -7
  40. package/dist/chunk-SZYQISA2.js.map +1 -0
  41. package/dist/{chunk-W6GO2CYX.js → chunk-USVBYQSQ.js} +2 -2
  42. package/dist/{chunk-H4ZKGGTE.js → chunk-V3KTSP3Q.js} +50 -42
  43. package/dist/chunk-V3KTSP3Q.js.map +1 -0
  44. package/dist/{chunk-KTLKR4YY.js → chunk-WTWMGH2C.js} +2 -2
  45. package/dist/commands/build/marketplace.js +23 -22
  46. package/dist/commands/build/marketplace.js.map +1 -1
  47. package/dist/commands/build/plugins.js +8 -9
  48. package/dist/commands/build/plugins.js.map +1 -1
  49. package/dist/commands/compile.js +19 -20
  50. package/dist/commands/compile.js.map +1 -1
  51. package/dist/commands/doctor.js +17 -18
  52. package/dist/commands/doctor.js.map +1 -1
  53. package/dist/commands/edit.js +118 -297
  54. package/dist/commands/edit.js.map +1 -1
  55. package/dist/commands/eject.js +21 -33
  56. package/dist/commands/eject.js.map +1 -1
  57. package/dist/commands/init.js +17 -45
  58. package/dist/commands/list.js +19 -17
  59. package/dist/commands/list.js.map +1 -1
  60. package/dist/commands/new/marketplace.js +11 -11
  61. package/dist/commands/new/marketplace.js.map +1 -1
  62. package/dist/commands/search.js +12 -13
  63. package/dist/commands/search.js.map +1 -1
  64. package/dist/commands/share.js +11 -12
  65. package/dist/commands/share.js.map +1 -1
  66. package/dist/commands/uninstall.js +18 -20
  67. package/dist/commands/uninstall.js.map +1 -1
  68. package/dist/commands/update.js +8 -9
  69. package/dist/commands/update.js.map +1 -1
  70. package/dist/components/common/removal-plan-confirm.js +2 -2
  71. package/dist/components/common/scroll-affordance.js +9 -0
  72. package/dist/components/common/select-list.js +2 -3
  73. package/dist/components/common/skill-agent-summary.js +11 -0
  74. package/dist/components/common/spinner.js +1 -1
  75. package/dist/{chunk-QWFG7Y3R.js → components/common/summary-panel.js} +57 -31
  76. package/dist/components/common/summary-panel.js.map +1 -0
  77. package/dist/config-exports.js +1 -1
  78. package/dist/hooks/init.js +18 -46
  79. package/dist/hooks/init.js.map +1 -1
  80. package/dist/load-agent-defs-YMDWBFDP.js +14 -0
  81. package/dist/recompile-project-agents-SZ76WNTW.js +18 -0
  82. package/dist/{source-loader-FRJTCSDL.js → source-loader-C5SQXZXI.js} +5 -5
  83. package/dist/src/agents/meta/codex-keeper/playbook.md +2 -3
  84. package/package.json +2 -3
  85. package/src/agents/meta/codex-keeper/playbook.md +2 -3
  86. package/src/schemas/project-config.schema.json +1 -1
  87. package/assets/demo.tape +0 -266
  88. package/dist/chunk-23DNVNFP.js +0 -292
  89. package/dist/chunk-23DNVNFP.js.map +0 -1
  90. package/dist/chunk-3DIDV6H3.js +0 -268
  91. package/dist/chunk-3DIDV6H3.js.map +0 -1
  92. package/dist/chunk-4DRFEYCE.js.map +0 -1
  93. package/dist/chunk-4HWOYYY7.js +0 -92
  94. package/dist/chunk-4HWOYYY7.js.map +0 -1
  95. package/dist/chunk-4UKMQUAU.js.map +0 -1
  96. package/dist/chunk-5JUQKGCP.js.map +0 -1
  97. package/dist/chunk-6WGXTB2L.js +0 -28
  98. package/dist/chunk-6WGXTB2L.js.map +0 -1
  99. package/dist/chunk-AG3ZVM3B.js.map +0 -1
  100. package/dist/chunk-C2UISKIM.js.map +0 -1
  101. package/dist/chunk-CMJBKQUH.js +0 -23
  102. package/dist/chunk-CMJBKQUH.js.map +0 -1
  103. package/dist/chunk-DJEO3F2H.js +0 -230
  104. package/dist/chunk-DJEO3F2H.js.map +0 -1
  105. package/dist/chunk-EH2PGPLP.js.map +0 -1
  106. package/dist/chunk-GRL73YPF.js +0 -197
  107. package/dist/chunk-GRL73YPF.js.map +0 -1
  108. package/dist/chunk-H4ZKGGTE.js.map +0 -1
  109. package/dist/chunk-HI6YB7XP.js +0 -59
  110. package/dist/chunk-HI6YB7XP.js.map +0 -1
  111. package/dist/chunk-HL3GYRMR.js +0 -17
  112. package/dist/chunk-HL3GYRMR.js.map +0 -1
  113. package/dist/chunk-HR7TK2XW.js.map +0 -1
  114. package/dist/chunk-JOEA52NR.js.map +0 -1
  115. package/dist/chunk-JPMV4E4E.js +0 -118
  116. package/dist/chunk-JPMV4E4E.js.map +0 -1
  117. package/dist/chunk-JVUN6AOO.js +0 -237
  118. package/dist/chunk-JVUN6AOO.js.map +0 -1
  119. package/dist/chunk-KQ3PDARZ.js +0 -25
  120. package/dist/chunk-KQ3PDARZ.js.map +0 -1
  121. package/dist/chunk-L3W2JWBA.js +0 -168
  122. package/dist/chunk-L3W2JWBA.js.map +0 -1
  123. package/dist/chunk-LFUJCRCT.js +0 -27
  124. package/dist/chunk-LFUJCRCT.js.map +0 -1
  125. package/dist/chunk-NU2K5G54.js.map +0 -1
  126. package/dist/chunk-OI2H6M5I.js.map +0 -1
  127. package/dist/chunk-P6I72PR3.js.map +0 -1
  128. package/dist/chunk-PCFUXQJA.js +0 -317
  129. package/dist/chunk-PCFUXQJA.js.map +0 -1
  130. package/dist/chunk-PLX2FLEQ.js +0 -48
  131. package/dist/chunk-PLX2FLEQ.js.map +0 -1
  132. package/dist/chunk-QWFG7Y3R.js.map +0 -1
  133. package/dist/chunk-SLBL3WIP.js +0 -121
  134. package/dist/chunk-SLBL3WIP.js.map +0 -1
  135. package/dist/chunk-TSIU7DME.js +0 -43
  136. package/dist/chunk-TSIU7DME.js.map +0 -1
  137. package/dist/chunk-TW35AEB4.js.map +0 -1
  138. package/dist/chunk-VRXX4D6K.js.map +0 -1
  139. package/dist/chunk-W5KEYSOL.js +0 -51
  140. package/dist/chunk-W5KEYSOL.js.map +0 -1
  141. package/dist/chunk-WNLF5EDZ.js +0 -1170
  142. package/dist/chunk-WNLF5EDZ.js.map +0 -1
  143. package/dist/chunk-WTJ3AY33.js +0 -31
  144. package/dist/chunk-WTJ3AY33.js.map +0 -1
  145. package/dist/chunk-X6ZZEYO3.js +0 -53
  146. package/dist/chunk-X6ZZEYO3.js.map +0 -1
  147. package/dist/chunk-XQHZPINL.js +0 -89
  148. package/dist/chunk-XQHZPINL.js.map +0 -1
  149. package/dist/chunk-YN3SWF53.js +0 -35
  150. package/dist/chunk-YN3SWF53.js.map +0 -1
  151. package/dist/components/wizard/category-grid.js +0 -13
  152. package/dist/components/wizard/checkbox-grid.js +0 -12
  153. package/dist/components/wizard/domain-selection.js +0 -18
  154. package/dist/components/wizard/run-wizard-session.js +0 -40
  155. package/dist/components/wizard/run-wizard-session.js.map +0 -1
  156. package/dist/components/wizard/scroll-affordance.js +0 -9
  157. package/dist/components/wizard/skill-agent-summary.js +0 -13
  158. package/dist/components/wizard/source-grid.js +0 -16
  159. package/dist/components/wizard/source-grid.js.map +0 -1
  160. package/dist/components/wizard/stack-selection.js +0 -17
  161. package/dist/components/wizard/stack-selection.js.map +0 -1
  162. package/dist/components/wizard/step-agents.js +0 -18
  163. package/dist/components/wizard/step-agents.js.map +0 -1
  164. package/dist/components/wizard/step-build.js +0 -18
  165. package/dist/components/wizard/step-build.js.map +0 -1
  166. package/dist/components/wizard/step-confirm.js +0 -18
  167. package/dist/components/wizard/step-confirm.js.map +0 -1
  168. package/dist/components/wizard/step-sources.js +0 -19
  169. package/dist/components/wizard/step-sources.js.map +0 -1
  170. package/dist/components/wizard/step-stack.js +0 -18
  171. package/dist/components/wizard/step-stack.js.map +0 -1
  172. package/dist/components/wizard/summary-panel.js +0 -17
  173. package/dist/components/wizard/summary-panel.js.map +0 -1
  174. package/dist/components/wizard/toast.js +0 -9
  175. package/dist/components/wizard/toast.js.map +0 -1
  176. package/dist/components/wizard/wizard-layout.js +0 -22
  177. package/dist/components/wizard/wizard-layout.js.map +0 -1
  178. package/dist/components/wizard/wizard-tabs.js +0 -11
  179. package/dist/components/wizard/wizard-tabs.js.map +0 -1
  180. package/dist/components/wizard/wizard.js +0 -39
  181. package/dist/components/wizard/wizard.js.map +0 -1
  182. package/dist/load-agent-defs-5XMVB3MU.js +0 -14
  183. package/dist/load-agent-defs-5XMVB3MU.js.map +0 -1
  184. package/dist/recompile-project-agents-7PQWYQ6B.js +0 -18
  185. package/dist/recompile-project-agents-7PQWYQ6B.js.map +0 -1
  186. package/dist/source-loader-FRJTCSDL.js.map +0 -1
  187. package/dist/stores/wizard-store.js +0 -24
  188. package/dist/stores/wizard-store.js.map +0 -1
  189. /package/assets/{demo.gif → legacy-wizard.gif} +0 -0
  190. /package/dist/{chunk-JIBCVXXL.js.map → chunk-3G7X2WKI.js.map} +0 -0
  191. /package/dist/{chunk-3LZNY46H.js.map → chunk-BMRUNMPV.js.map} +0 -0
  192. /package/dist/{chunk-27AVGFXH.js.map → chunk-F5EBEATU.js.map} +0 -0
  193. /package/dist/{chunk-GE7NUPMI.js.map → chunk-HED2DAXZ.js.map} +0 -0
  194. /package/dist/{chunk-W6GO2CYX.js.map → chunk-USVBYQSQ.js.map} +0 -0
  195. /package/dist/{chunk-KTLKR4YY.js.map → chunk-WTWMGH2C.js.map} +0 -0
  196. /package/dist/components/{wizard → common}/scroll-affordance.js.map +0 -0
  197. /package/dist/components/{wizard → common}/skill-agent-summary.js.map +0 -0
  198. /package/dist/{components/wizard/category-grid.js.map → load-agent-defs-YMDWBFDP.js.map} +0 -0
  199. /package/dist/{components/wizard/checkbox-grid.js.map → recompile-project-agents-SZ76WNTW.js.map} +0 -0
  200. /package/dist/{components/wizard/domain-selection.js.map → source-loader-C5SQXZXI.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/update.ts"],"sourcesContent":["import { unique } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { EJECT_SOURCE } from \"../consts.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { loadProjectConfig } from \"../lib/configuration/index.js\";\nimport { hostAt } from \"../lib/hosts/host-for.js\";\nimport {\n providerFlag,\n providerNamedBy,\n refuseAnAmbiguousInstallation,\n} from \"../lib/installation/provider-flag.js\";\nimport { unofferablePlacementsFound } from \"../lib/hosts/configured-placements.js\";\nimport type { PluginHost } from \"../lib/hosts/plugin-host.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport {\n ERROR_MESSAGES,\n INFO_MESSAGES,\n hostCliNotFound,\n marketplaceRefreshFailed,\n marketplacesRefreshFailed,\n marketplacesRefreshed,\n} from \"../utils/messages.js\";\nimport type { ProjectConfig, SkillConfig } from \"../types/index.js\";\n\n/** A copy the user owns rather than a plugin the marketplace serves. */\nfunction isEjected(skill: SkillConfig): boolean {\n return skill.origin === EJECT_SOURCE;\n}\n\n/** Entries the installation actually has — an excluded entry is a tombstone, not an install. */\nfunction activeSkills(skills: SkillConfig[]): SkillConfig[] {\n return skills.filter((skill) => !skill.excluded);\n}\n\n/** The marketplaces this installation actually uses, deduplicated, in config order. */\nfunction configuredMarketplaces(skills: SkillConfig[]): string[] {\n return unique(skills.filter((skill) => !isEjected(skill)).map((skill) => skill.origin));\n}\n\nexport default class Update extends BaseCommand {\n static summary = \"Refresh the marketplaces this installation uses\";\n\n static description =\n \"Runs Claude's own marketplace update for every marketplace this installation's config names. Ejected skills are copies you own and are never touched.\";\n\n static flags = { provider: providerFlag() };\n\n static examples = [\"<%= config.bin %> <%= command.id %>\"];\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Update);\n\n // Before the config is loaded, because loading it is already an answer: `loadProjectConfig`\n // and `hostAt` both resolve the provider through `providerInUse`, which picks by ROSTER ORDER\n // where a scope holds one installation of each. So a refresh with no flag read one user's\n // Claude config, refreshed the marketplaces IT names, and reported them as refreshed with\n // nothing saying whose they were.\n await refuseAnAmbiguousInstallation(\n process.cwd(),\n \"update\",\n providerNamedBy(flags.provider),\n (message) => this.error(message, { exit: EXIT_CODES.INVALID_ARGS }),\n );\n // Both configs, not only the one this refresh reads: a project inherits the global config, so\n // a broken global one is a config this folder uses as surely as its own.\n await this.ensureConfigReadable(process.cwd());\n await this.refuseUnofferablePlacements(process.cwd());\n const config = await this.loadInstalledConfig(process.cwd());\n if (!config) {\n this.warn(ERROR_MESSAGES.NO_INSTALLATION);\n return;\n }\n\n const skills = activeSkills(config.skills);\n this.reportEjectedSkills(skills);\n\n const marketplaces = configuredMarketplaces(skills);\n if (marketplaces.length === 0) {\n this.log(INFO_MESSAGES.NO_PLUGIN_MARKETPLACES);\n return;\n }\n\n const host = hostAt(process.cwd());\n await this.requireHost(host);\n await this.refreshMarketplaces(marketplaces, host);\n }\n\n /**\n * Refuses a configuration whose own host cannot place what it asks for.\n *\n * The same reading `compile` and `edit` make, off the same host roster. It matters here because\n * this command REFRESHES the marketplaces a configuration names — so on a configuration whose\n * plugin rows the host can never install, every refresh is work done for rows that will never\n * become an install, reported as a success.\n */\n private async refuseUnofferablePlacements(projectDir: string): Promise<void> {\n const [finding] = await unofferablePlacementsFound(projectDir);\n if (finding !== undefined) this.error(finding, { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * The config this directory's installation runs on — the project's own, or the\n * global one it inherits from. A config file that exists but cannot be loaded is\n * a fault, not an absence, so it is reported rather than read as \"not installed\".\n */\n private async loadInstalledConfig(projectDir: string): Promise<ProjectConfig | null> {\n try {\n const loaded = await loadProjectConfig(projectDir);\n return loaded?.config ?? null;\n } catch (error) {\n this.error(getErrorMessage(error), { exit: EXIT_CODES.ERROR });\n }\n }\n\n /** States the ownership rule once, and only where there is an ejected skill it applies to. */\n private reportEjectedSkills(skills: SkillConfig[]): void {\n if (!skills.some(isEjected)) return;\n this.log(INFO_MESSAGES.EJECTED_SKILLS_USER_OWNED);\n }\n\n /**\n * Gated on there being a marketplace to refresh, so an eject-only installation\n * never fails on a host binary it had no reason to call.\n */\n private async requireHost(host: PluginHost): Promise<void> {\n if (await host.isAvailable()) return;\n // The host's own provider, never a constant: this command reaches either host from C4, and a\n // fixed line tells a Codex user to install Claude Code — not the binary that is missing.\n this.error(hostCliNotFound(host.provider), { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * One marketplace refresh per marketplace, in sequence: they write\n * to the same registry, and interleaved progress lines would not say which\n * marketplace each belongs to. A failure is collected rather than thrown, so one\n * unreachable marketplace cannot hide the state of the others.\n */\n private async refreshMarketplaces(marketplaces: string[], host: PluginHost): Promise<void> {\n const failed: string[] = [];\n\n for (const marketplace of marketplaces) {\n this.log(`Refreshing marketplace ${marketplace}...`);\n try {\n await host.refreshMarketplace(marketplace);\n this.log(` Updated marketplace ${marketplace}`);\n } catch (error) {\n failed.push(marketplace);\n this.warn(marketplaceRefreshFailed(marketplace, getErrorMessage(error)));\n }\n }\n\n if (failed.length > 0) {\n this.error(marketplacesRefreshFailed(failed), { exit: EXIT_CODES.ERROR });\n }\n\n this.logSuccess(marketplacesRefreshed(marketplaces.length));\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,cAAc;AA0BvB,SAAS,UAAU,OAA6B;AAC9C,SAAO,MAAM,WAAW;AAC1B;AAGA,SAAS,aAAa,QAAsC;AAC1D,SAAO,OAAO,OAAO,CAAC,UAAU,CAAC,MAAM,QAAQ;AACjD;AAGA,SAAS,uBAAuB,QAAiC;AAC/D,SAAO,OAAO,OAAO,OAAO,CAAC,UAAU,CAAC,UAAU,KAAK,CAAC,EAAE,IAAI,CAAC,UAAU,MAAM,MAAM,CAAC;AACxF;AAEA,IAAqB,SAArB,MAAqB,gBAAe,YAAY;AAAA,EAC9C,OAAO,UAAU;AAAA,EAEjB,OAAO,cACL;AAAA,EAEF,OAAO,QAAQ,EAAE,UAAU,aAAa,EAAE;AAAA,EAE1C,OAAO,WAAW,CAAC,qCAAqC;AAAA,EAExD,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,OAAM;AAOzC,UAAM;AAAA,MACJ,QAAQ,IAAI;AAAA,MACZ;AAAA,MACA,gBAAgB,MAAM,QAAQ;AAAA,MAC9B,CAAC,YAAY,KAAK,MAAM,SAAS,EAAE,MAAM,WAAW,aAAa,CAAC;AAAA,IACpE;AAGA,UAAM,KAAK,qBAAqB,QAAQ,IAAI,CAAC;AAC7C,UAAM,KAAK,4BAA4B,QAAQ,IAAI,CAAC;AACpD,UAAM,SAAS,MAAM,KAAK,oBAAoB,QAAQ,IAAI,CAAC;AAC3D,QAAI,CAAC,QAAQ;AACX,WAAK,KAAK,eAAe,eAAe;AACxC;AAAA,IACF;AAEA,UAAM,SAAS,aAAa,OAAO,MAAM;AACzC,SAAK,oBAAoB,MAAM;AAE/B,UAAM,eAAe,uBAAuB,MAAM;AAClD,QAAI,aAAa,WAAW,GAAG;AAC7B,WAAK,IAAI,cAAc,sBAAsB;AAC7C;AAAA,IACF;AAEA,UAAM,OAAO,OAAO,QAAQ,IAAI,CAAC;AACjC,UAAM,KAAK,YAAY,IAAI;AAC3B,UAAM,KAAK,oBAAoB,cAAc,IAAI;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAc,4BAA4B,YAAmC;AAC3E,UAAM,CAAC,OAAO,IAAI,MAAM,2BAA2B,UAAU;AAC7D,QAAI,YAAY,OAAW,MAAK,MAAM,SAAS,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,oBAAoB,YAAmD;AACnF,QAAI;AACF,YAAM,SAAS,MAAM,kBAAkB,UAAU;AACjD,aAAO,QAAQ,UAAU;AAAA,IAC3B,SAAS,OAAO;AACd,WAAK,MAAM,gBAAgB,KAAK,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IAC/D;AAAA,EACF;AAAA;AAAA,EAGQ,oBAAoB,QAA6B;AACvD,QAAI,CAAC,OAAO,KAAK,SAAS,EAAG;AAC7B,SAAK,IAAI,cAAc,yBAAyB;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,YAAY,MAAiC;AACzD,QAAI,MAAM,KAAK,YAAY,EAAG;AAG9B,SAAK,MAAM,gBAAgB,KAAK,QAAQ,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,oBAAoB,cAAwB,MAAiC;AACzF,UAAM,SAAmB,CAAC;AAE1B,eAAW,eAAe,cAAc;AACtC,WAAK,IAAI,0BAA0B,WAAW,KAAK;AACnD,UAAI;AACF,cAAM,KAAK,mBAAmB,WAAW;AACzC,aAAK,IAAI,yBAAyB,WAAW,EAAE;AAAA,MACjD,SAAS,OAAO;AACd,eAAO,KAAK,WAAW;AACvB,aAAK,KAAK,yBAAyB,aAAa,gBAAgB,KAAK,CAAC,CAAC;AAAA,MACzE;AAAA,IACF;AAEA,QAAI,OAAO,SAAS,GAAG;AACrB,WAAK,MAAM,0BAA0B,MAAM,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IAC1E;AAEA,SAAK,WAAW,sBAAsB,aAAa,MAAM,CAAC;AAAA,EAC5D;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/update.ts"],"sourcesContent":["import { unique } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { EJECT_SOURCE } from \"../consts.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { loadProjectConfig } from \"../lib/configuration/index.js\";\nimport { hostAt } from \"../lib/hosts/host-for.js\";\nimport {\n providerFlag,\n providerNamedBy,\n refuseAnAmbiguousInstallation,\n} from \"../lib/installation/provider-flag.js\";\nimport { unofferablePlacementsFound } from \"../lib/hosts/configured-placements.js\";\nimport type { PluginHost } from \"../lib/hosts/plugin-host.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport {\n ERROR_MESSAGES,\n INFO_MESSAGES,\n hostCliNotFound,\n marketplaceRefreshFailed,\n marketplacesRefreshFailed,\n marketplacesRefreshed,\n} from \"../utils/messages.js\";\nimport type { ProjectConfig, SkillConfig } from \"../types/index.js\";\n\n/** A copy the user owns rather than a plugin the marketplace serves. */\nfunction isEjected(skill: SkillConfig): boolean {\n return skill.origin === EJECT_SOURCE;\n}\n\n/** Entries the installation actually has — an excluded entry is a tombstone, not an install. */\nfunction activeSkills(skills: SkillConfig[]): SkillConfig[] {\n return skills.filter((skill) => !skill.excluded);\n}\n\n/** The marketplaces this installation actually uses, deduplicated, in config order. */\nfunction configuredMarketplaces(skills: SkillConfig[]): string[] {\n return unique(skills.filter((skill) => !isEjected(skill)).map((skill) => skill.origin));\n}\n\nexport default class Update extends BaseCommand {\n static summary = \"Refresh the marketplaces this installation uses\";\n\n static description =\n \"Runs Claude's own marketplace update for every marketplace this installation's config names. Ejected skills are copies you own and are never touched.\";\n\n static flags = { provider: providerFlag() };\n\n static examples = [\"<%= config.bin %> <%= command.id %>\"];\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Update);\n\n // Before the config is loaded, because loading it is already an answer: `loadProjectConfig`\n // and `hostAt` both resolve the provider through `providerInUse`, which picks by ROSTER ORDER\n // where a scope holds one installation of each. So a refresh with no flag read one user's\n // Claude config, refreshed the marketplaces IT names, and reported them as refreshed with\n // nothing saying whose they were.\n await refuseAnAmbiguousInstallation(\n process.cwd(),\n \"update\",\n providerNamedBy(flags.provider),\n (message) => this.error(message, { exit: EXIT_CODES.INVALID_ARGS }),\n );\n // Both configs, not only the one this refresh reads: a project inherits the global config, so\n // a broken global one is a config this folder uses as surely as its own.\n await this.ensureConfigReadable(process.cwd());\n await this.refuseUnofferablePlacements(process.cwd());\n const config = await this.loadInstalledConfig(process.cwd());\n if (!config) {\n this.warn(ERROR_MESSAGES.NO_INSTALLATION);\n return;\n }\n\n const skills = activeSkills(config.skills);\n this.reportEjectedSkills(skills);\n\n const marketplaces = configuredMarketplaces(skills);\n if (marketplaces.length === 0) {\n this.log(INFO_MESSAGES.NO_PLUGIN_MARKETPLACES);\n return;\n }\n\n const host = hostAt(process.cwd());\n await this.requireHost(host);\n await this.refreshMarketplaces(marketplaces, host);\n }\n\n /**\n * Refuses a configuration whose own host cannot place what it asks for.\n *\n * The same reading `compile` and `edit` make, off the same host roster. It matters here because\n * this command REFRESHES the marketplaces a configuration names — so on a configuration whose\n * plugin rows the host can never install, every refresh is work done for rows that will never\n * become an install, reported as a success.\n */\n private async refuseUnofferablePlacements(projectDir: string): Promise<void> {\n const [finding] = await unofferablePlacementsFound(projectDir);\n if (finding !== undefined) this.error(finding, { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * The config this directory's installation runs on — the project's own, or the\n * global one it inherits from. A config file that exists but cannot be loaded is\n * a fault, not an absence, so it is reported rather than read as \"not installed\".\n */\n private async loadInstalledConfig(projectDir: string): Promise<ProjectConfig | null> {\n try {\n const loaded = await loadProjectConfig(projectDir);\n return loaded?.config ?? null;\n } catch (error) {\n this.error(getErrorMessage(error), { exit: EXIT_CODES.ERROR });\n }\n }\n\n /** States the ownership rule once, and only where there is an ejected skill it applies to. */\n private reportEjectedSkills(skills: SkillConfig[]): void {\n if (!skills.some(isEjected)) return;\n this.log(INFO_MESSAGES.EJECTED_SKILLS_USER_OWNED);\n }\n\n /**\n * Gated on there being a marketplace to refresh, so an eject-only installation\n * never fails on a host binary it had no reason to call.\n */\n private async requireHost(host: PluginHost): Promise<void> {\n if (await host.isAvailable()) return;\n // The host's own provider, never a constant: this command reaches either host from C4, and a\n // fixed line tells a Codex user to install Claude Code — not the binary that is missing.\n this.error(hostCliNotFound(host.provider), { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * One marketplace refresh per marketplace, in sequence: they write\n * to the same registry, and interleaved progress lines would not say which\n * marketplace each belongs to. A failure is collected rather than thrown, so one\n * unreachable marketplace cannot hide the state of the others.\n */\n private async refreshMarketplaces(marketplaces: string[], host: PluginHost): Promise<void> {\n const failed: string[] = [];\n\n for (const marketplace of marketplaces) {\n this.log(`Refreshing marketplace ${marketplace}...`);\n try {\n await host.refreshMarketplace(marketplace);\n this.log(` Updated marketplace ${marketplace}`);\n } catch (error) {\n failed.push(marketplace);\n this.warn(marketplaceRefreshFailed(marketplace, getErrorMessage(error)));\n }\n }\n\n if (failed.length > 0) {\n this.error(marketplacesRefreshFailed(failed), { exit: EXIT_CODES.ERROR });\n }\n\n this.logSuccess(marketplacesRefreshed(marketplaces.length));\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  RemovalPlanConfirm
4
- } from "../../chunk-W6GO2CYX.js";
4
+ } from "../../chunk-USVBYQSQ.js";
5
5
  import "../../chunk-OZXAJNLA.js";
6
- import "../../chunk-AG3ZVM3B.js";
6
+ import "../../chunk-PJWGTNOX.js";
7
7
  export {
8
8
  RemovalPlanConfirm
9
9
  };
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ ScrollAffordance
4
+ } from "../../chunk-KOLDW6SF.js";
5
+ import "../../chunk-PJWGTNOX.js";
6
+ export {
7
+ ScrollAffordance
8
+ };
9
+ //# sourceMappingURL=scroll-affordance.js.map
@@ -1,9 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SelectList
4
- } from "../../chunk-W5KEYSOL.js";
5
- import "../../chunk-JOEA52NR.js";
6
- import "../../chunk-AG3ZVM3B.js";
4
+ } from "../../chunk-44TE3RKH.js";
5
+ import "../../chunk-PJWGTNOX.js";
7
6
  export {
8
7
  SelectList
9
8
  };
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ SkillAgentSummary
4
+ } from "../../chunk-6ZRH5RHC.js";
5
+ import "../../chunk-NIHUOWE4.js";
6
+ import "../../chunk-52HDHJ7I.js";
7
+ import "../../chunk-PJWGTNOX.js";
8
+ export {
9
+ SkillAgentSummary
10
+ };
11
+ //# sourceMappingURL=skill-agent-summary.js.map
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  Spinner,
4
4
  awaitUnderSpinner
5
- } from "../../chunk-VRXX4D6K.js";
5
+ } from "../../chunk-NEZ4OAOL.js";
6
6
  import "../../chunk-JFLVEFFP.js";
7
7
  export {
8
8
  Spinner,
@@ -1,43 +1,75 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ScrollAffordance
4
- } from "./chunk-7PYXS2QU.js";
5
- import {
6
- getStackName
7
- } from "./chunk-YN3SWF53.js";
8
- import {
9
- useMeasuredHeight
10
- } from "./chunk-TSIU7DME.js";
4
+ } from "../../chunk-KOLDW6SF.js";
11
5
  import {
12
6
  SkillAgentSummary
13
- } from "./chunk-4UKMQUAU.js";
14
- import {
15
- useWizardStore
16
- } from "./chunk-WNLF5EDZ.js";
7
+ } from "../../chunk-6ZRH5RHC.js";
8
+ import "../../chunk-NIHUOWE4.js";
9
+ import "../../chunk-52HDHJ7I.js";
17
10
  import {
18
11
  ALL_SKILLS_EJECTED_LABEL,
19
12
  CLI_COLORS,
20
13
  DEFAULT_PUBLIC_SOURCE_NAME,
21
14
  EJECT_SOURCE,
22
15
  formatSourceDisplayName
23
- } from "./chunk-AG3ZVM3B.js";
16
+ } from "../../chunk-PJWGTNOX.js";
24
17
 
25
- // src/cli/components/wizard/summary-panel.tsx
18
+ // src/cli/components/common/summary-panel.tsx
26
19
  import { Box, Text } from "ink";
27
20
  import "react";
28
21
  import { unique } from "remeda";
29
22
 
30
23
  // src/cli/components/hooks/use-panel-scroll.ts
31
- import { useEffect, useRef, useState } from "react";
32
- import { measureElement, useInput } from "ink";
24
+ import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
25
+ import { measureElement as measureElement2, useInput } from "ink";
26
+
27
+ // src/cli/components/hooks/use-measured-height.ts
28
+ import { useRef, useState, useEffect } from "react";
29
+ import { measureElement, useStdout } from "ink";
30
+ function useMeasuredHeight() {
31
+ const ref = useRef(null);
32
+ const [measuredHeight, setMeasuredHeight] = useState(0);
33
+ const { stdout } = useStdout();
34
+ const measure = () => {
35
+ if (ref.current) {
36
+ const { height } = measureElement(ref.current);
37
+ setMeasuredHeight((prev) => prev !== height ? height : prev);
38
+ }
39
+ };
40
+ useEffect(() => {
41
+ measure();
42
+ });
43
+ useEffect(() => {
44
+ const RETRY_DELAYS_MS = [0, 16, 50];
45
+ const timers = [];
46
+ for (const delay of RETRY_DELAYS_MS) {
47
+ timers.push(setTimeout(measure, delay));
48
+ }
49
+ return () => {
50
+ for (const timer of timers) {
51
+ clearTimeout(timer);
52
+ }
53
+ };
54
+ }, []);
55
+ useEffect(() => {
56
+ stdout.on("resize", measure);
57
+ return () => {
58
+ stdout.off("resize", measure);
59
+ };
60
+ }, [stdout]);
61
+ return { ref, measuredHeight };
62
+ }
63
+
64
+ // src/cli/components/hooks/use-panel-scroll.ts
33
65
  function usePanelScroll() {
34
66
  const { ref: viewportRef, measuredHeight: viewportHeight } = useMeasuredHeight();
35
- const contentRef = useRef(null);
36
- const [contentHeight, setContentHeight] = useState(0);
37
- const [scrollOffset, setScrollOffset] = useState(0);
38
- useEffect(() => {
67
+ const contentRef = useRef2(null);
68
+ const [contentHeight, setContentHeight] = useState2(0);
69
+ const [scrollOffset, setScrollOffset] = useState2(0);
70
+ useEffect2(() => {
39
71
  if (!contentRef.current) return;
40
- const { height } = measureElement(contentRef.current);
72
+ const { height } = measureElement2(contentRef.current);
41
73
  setContentHeight((prev) => Math.max(prev, height));
42
74
  });
43
75
  const maxScroll = Math.max(0, contentHeight - viewportHeight);
@@ -55,7 +87,7 @@ function usePanelScroll() {
55
87
  };
56
88
  }
57
89
 
58
- // src/cli/components/wizard/summary-panel.tsx
90
+ // src/cli/components/common/summary-panel.tsx
59
91
  import { jsx, jsxs } from "react/jsx-runtime";
60
92
  function formatSkillMarketplaces(skillConfigs) {
61
93
  if (skillConfigs.length === 0) return formatSourceDisplayName(DEFAULT_PUBLIC_SOURCE_NAME);
@@ -91,14 +123,9 @@ var PanelHeader = ({ sourceNames, stackName }) => /* @__PURE__ */ jsxs(
91
123
  ]
92
124
  }
93
125
  );
94
- var SummaryPanel = () => {
95
- const skillConfigs = useWizardStore((s) => s.skillConfigs);
96
- const agentConfigs = useWizardStore((s) => s.agentConfigs);
97
- const selectedStackId = useWizardStore((s) => s.selectedStackId);
98
- const setupMarketplace = useWizardStore((s) => s.setupMarketplace);
126
+ var SummaryPanel = ({ stackName, ...summary }) => {
99
127
  const { viewportRef, contentRef, contentMarginTop, hiddenAbove, hiddenBelow } = usePanelScroll();
100
- const sourceNames = setupMarketplace === null ? formatSkillMarketplaces(skillConfigs) : formatSourceDisplayName(setupMarketplace);
101
- const stackName = getStackName(selectedStackId);
128
+ const sourceNames = formatSkillMarketplaces(summary.skillConfigs);
102
129
  return /* @__PURE__ */ jsxs(
103
130
  Box,
104
131
  {
@@ -111,15 +138,14 @@ var SummaryPanel = () => {
111
138
  children: [
112
139
  /* @__PURE__ */ jsx(Box, { ref: viewportRef, flexDirection: "column", flexGrow: 1, flexBasis: 0, overflow: "hidden", children: /* @__PURE__ */ jsxs(Box, { ref: contentRef, flexDirection: "column", flexShrink: 0, marginTop: contentMarginTop, children: [
113
140
  /* @__PURE__ */ jsx(PanelHeader, { sourceNames, stackName }),
114
- /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(SkillAgentSummary, { skillConfigs, agentConfigs }) })
141
+ /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(SkillAgentSummary, { ...summary }) })
115
142
  ] }) }),
116
143
  /* @__PURE__ */ jsx(ScrollAffordance, { hiddenAbove, hiddenBelow })
117
144
  ]
118
145
  }
119
146
  );
120
147
  };
121
-
122
148
  export {
123
149
  SummaryPanel
124
150
  };
125
- //# sourceMappingURL=chunk-QWFG7Y3R.js.map
151
+ //# sourceMappingURL=summary-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/cli/components/common/summary-panel.tsx","../../../src/cli/components/hooks/use-panel-scroll.ts","../../../src/cli/components/hooks/use-measured-height.ts"],"sourcesContent":["import { Box, Text } from \"ink\";\nimport React from \"react\";\nimport { unique } from \"remeda\";\nimport {\n ALL_SKILLS_EJECTED_LABEL,\n CLI_COLORS,\n DEFAULT_PUBLIC_SOURCE_NAME,\n EJECT_SOURCE,\n formatSourceDisplayName,\n} from \"../../consts.js\";\nimport type { SkillConfig } from \"../../types/config.js\";\nimport { usePanelScroll } from \"../hooks/use-panel-scroll.js\";\nimport { ScrollAffordance } from \"./scroll-affordance.js\";\nimport { SkillAgentSummary, type SkillAgentSummaryProps } from \"./skill-agent-summary.js\";\n\nexport type SummaryPanelProps = SkillAgentSummaryProps & {\n /** `undefined` when the configuration was built from no stack. */\n stackName: string | undefined;\n};\n\n/**\n * The Marketplace row's value: the distinct marketplaces the summarised skills come from.\n *\n * `SkillConfig.origin` is authoritative for where a skill came from, and holds exactly one\n * of two things: {@link EJECT_SOURCE}, meaning the files were copied locally, or the marketplace's\n * own name as its `marketplace.json` declares it — which is why a project initialised from a\n * different marketplace names that marketplace here without any extra plumbing.\n *\n * Three cases, and the two zero-marketplace ones are NOT the same state:\n * - **No skills at all.** Nothing is claimed yet, so the default public marketplace stands in.\n * - **Skills, but every one ejected.** \"eject\" names no marketplace, so there is none to list;\n * naming the default would assert an origin none of those skills has.\n * - **Any marketplace-sourced skill.** Its marketplace is named. Ejected siblings contribute no\n * name but do not suppress the ones that do.\n *\n * Tombstoned (`excluded`) entries count. One still records a real global install and the\n * marketplace it came from, and `computeScopeDiff` renders it as a row in the summary below, so\n * dropping it here would leave the header disowning a row it sits above.\n *\n * Sorted, so the row cannot reorder between renders on config iteration order alone.\n */\nfunction formatSkillMarketplaces(skillConfigs: SkillConfig[]): string {\n if (skillConfigs.length === 0) return formatSourceDisplayName(DEFAULT_PUBLIC_SOURCE_NAME);\n\n const marketplaceNames = unique(\n skillConfigs.map((config) => config.origin).filter((origin) => origin !== EJECT_SOURCE),\n );\n if (marketplaceNames.length === 0) return ALL_SKILLS_EJECTED_LABEL;\n\n return marketplaceNames\n .map((name) => formatSourceDisplayName(name))\n .sort()\n .join(\" · \");\n}\n\ntype PanelHeaderProps = {\n sourceNames: string;\n stackName: string | undefined;\n};\n\n/**\n * Which marketplaces and which stack the summary below was built from.\n *\n * Rendered inside the scrolled content, so its `marginBottom` scrolls away\n * rather than permanently costing the viewport a row.\n *\n * `flexShrink={0}` is load-bearing: Ink defaults every box to `flexShrink: 1`,\n * so on a short terminal Yoga squeezes this block to fit instead of letting the\n * viewport clip it, and the Marketplace and Stack rows overprint into one\n * unreadable line. Clipping is the panel's job; the header must keep its height.\n */\nconst PanelHeader: React.FC<PanelHeaderProps> = ({ sourceNames, stackName }) => (\n <Box\n flexDirection=\"column\"\n flexShrink={0}\n borderStyle=\"single\"\n borderBottom={true}\n borderTop={false}\n borderLeft={false}\n borderRight={false}\n borderColor={CLI_COLORS.NEUTRAL}\n borderBottomDimColor\n paddingBottom={1}\n marginBottom={1}\n >\n <Box flexDirection=\"row\" columnGap={1}>\n <Text color={CLI_COLORS.WARNING} bold>\n Marketplace\n </Text>\n <Text color={CLI_COLORS.NEUTRAL}>{sourceNames}</Text>\n </Box>\n <Box flexDirection=\"row\" columnGap={1}>\n <Text color={CLI_COLORS.WARNING} bold>\n Stack\n </Text>\n <Text color={CLI_COLORS.NEUTRAL}>{stackName ?? \"none\"}</Text>\n </Box>\n </Box>\n);\n\n/**\n * Marketplace/stack header above a clipped, arrow-scrollable `SkillAgentSummary`.\n *\n * It owns the `↑`/`↓` keys through `usePanelScroll`. A host that needs other\n * keys adds its own `useInput` alongside it.\n *\n * Horizontal padding only. Vertical padding is unshrinkable, so on a short\n * terminal it claims the last row the viewport has and the content measures 0\n * before it has ever been laid out — the panel then paints neither a summary\n * row nor the affordance that would say rows are missing.\n */\nexport const SummaryPanel: React.FC<SummaryPanelProps> = ({ stackName, ...summary }) => {\n const { viewportRef, contentRef, contentMarginTop, hiddenAbove, hiddenBelow } = usePanelScroll();\n\n const sourceNames = formatSkillMarketplaces(summary.skillConfigs);\n\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n flexBasis={0}\n borderStyle=\"single\"\n borderColor={CLI_COLORS.NEUTRAL}\n paddingX={2}\n >\n <Box ref={viewportRef} flexDirection=\"column\" flexGrow={1} flexBasis={0} overflow=\"hidden\">\n <Box ref={contentRef} flexDirection=\"column\" flexShrink={0} marginTop={contentMarginTop}>\n <PanelHeader sourceNames={sourceNames} stackName={stackName} />\n\n <Box width=\"100%\">\n <SkillAgentSummary {...summary} />\n </Box>\n </Box>\n </Box>\n <ScrollAffordance hiddenAbove={hiddenAbove} hiddenBelow={hiddenBelow} />\n </Box>\n );\n};\n","import { useEffect, useRef, useState } from \"react\";\nimport type { Ref, RefObject } from \"react\";\nimport { type DOMElement, measureElement, useInput } from \"ink\";\nimport { useMeasuredHeight } from \"./use-measured-height.js\";\n\nexport type UsePanelScrollResult = {\n /** Attach to the clipping box — the one with `overflow=\"hidden\"`. */\n viewportRef: Ref<DOMElement>;\n /** Attach to the scrolled content box inside the viewport. */\n contentRef: RefObject<DOMElement | null>;\n /** Apply as the content box's `marginTop`; negative by the number of lines scrolled off the top. */\n contentMarginTop: number;\n /** Content lines scrolled off the top of the viewport. */\n hiddenAbove: number;\n /** Content lines clipped below the viewport. */\n hiddenBelow: number;\n};\n\n/**\n * Line scrolling for a single clipped viewport, driven by the `↑`/`↓` keys.\n *\n * The caller renders viewport, content and a `ScrollAffordance` sibling; this\n * owns the offset those three agree on. Distinct from `useSectionScroll`, which\n * moves a viewport to follow focus across variable-height sections — here there\n * is no focus, only the arrow keys.\n *\n * A host that needs other keys adds its own `useInput` alongside it, on keys\n * disjoint from `↑`/`↓`.\n */\nexport function usePanelScroll(): UsePanelScrollResult {\n // Measured on the clipping box itself, inside the border and padding, so it\n // is the height the content actually gets.\n const { ref: viewportRef, measuredHeight: viewportHeight } = useMeasuredHeight();\n const contentRef = useRef<DOMElement>(null);\n const [contentHeight, setContentHeight] = useState(0);\n const [scrollOffset, setScrollOffset] = useState(0);\n\n // Ink's measurement idiom: re-measure on every render, no dependency array\n // on purpose. The setState inside is guarded to fire only when the measured\n // height actually changed, so the chain converges instead of looping — a\n // dependency array here would skip re-measures after layout changes React\n // cannot see.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(() => {\n if (!contentRef.current) return;\n const { height } = measureElement(contentRef.current);\n // Yoga under-reports a wrapped subtree measured inside a viewport too\n // short to lay it out, and reports 0 inside a zero-height one, so the\n // tallest reading is the trustworthy one. Believing a squeezed reading\n // would shrink the hidden-line count until the affordance disappeared,\n // which hands its row back and grows the count again — a render loop.\n setContentHeight((prev) => Math.max(prev, height));\n });\n\n // contentHeight only ever sizes the scroll range and the affordance count.\n // It must never gate the clip — which is why it is not returned: a viewport\n // that stops clipping when it looks too small grows to content height, which\n // makes it look big enough to stop clipping — a stable wrong answer that\n // paints the content over the border.\n const maxScroll = Math.max(0, contentHeight - viewportHeight);\n const hiddenBelow = Math.max(0, maxScroll - scrollOffset);\n\n useInput((_input, key) => {\n if (key.upArrow) setScrollOffset((prev) => Math.max(0, prev - 1));\n if (key.downArrow) setScrollOffset((prev) => Math.min(maxScroll, prev + 1));\n });\n\n return {\n viewportRef,\n contentRef,\n contentMarginTop: scrollOffset > 0 ? -scrollOffset : 0,\n hiddenAbove: scrollOffset,\n hiddenBelow,\n };\n}\n","import { useRef, useState, useEffect } from \"react\";\nimport { type DOMElement, measureElement, useStdout } from \"ink\";\n\n/**\n * Measures the computed height of a Box element using Ink's Yoga layout engine.\n *\n * Returns a ref to attach to a Box with `flexGrow={1}` and the measured height.\n * The Box must be inside a parent chain with a constrained height (e.g., an\n * explicit `height` prop on an ancestor) so Yoga can compute the remaining space.\n *\n * Returns 0 before the first layout pass. Re-measures on terminal resize.\n */\nexport function useMeasuredHeight(): {\n ref: React.Ref<DOMElement>;\n measuredHeight: number;\n} {\n const ref = useRef<DOMElement>(null);\n const [measuredHeight, setMeasuredHeight] = useState(0);\n const { stdout } = useStdout();\n\n const measure = () => {\n if (ref.current) {\n const { height } = measureElement(ref.current);\n setMeasuredHeight((prev) => (prev !== height ? height : prev));\n }\n };\n\n // Re-measure after every render so late-mounted refs get picked up.\n // The state setter avoids unnecessary updates when height is unchanged.\n useEffect(() => {\n measure();\n });\n\n // Yoga may not have computed the layout on the first render, so\n // measureElement() returns 0. Retry with increasing delays to give\n // Yoga time to resolve the full flex constraint chain.\n useEffect(() => {\n const RETRY_DELAYS_MS = [0, 16, 50];\n const timers: ReturnType<typeof setTimeout>[] = [];\n\n for (const delay of RETRY_DELAYS_MS) {\n timers.push(setTimeout(measure, delay));\n }\n\n return () => {\n for (const timer of timers) {\n clearTimeout(timer);\n }\n };\n // Deps are deliberately empty: this is a mount-only retry ladder. `measure`\n // is re-created every render, so listing it would re-arm the timers on every\n // render instead of once.\n }, []);\n\n useEffect(() => {\n stdout.on(\"resize\", measure);\n return () => {\n stdout.off(\"resize\", measure);\n };\n }, [stdout]);\n\n return { ref, measuredHeight };\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","measureElement","useRef","useState","useEffect","measureElement"]}
@@ -4,7 +4,7 @@ import {
4
4
  defaultRules,
5
5
  defaultStacks,
6
6
  defineConfig
7
- } from "./chunk-OI2H6M5I.js";
7
+ } from "./chunk-NQW25DCF.js";
8
8
  export {
9
9
  defaultCategories,
10
10
  defaultRules,
@@ -1,61 +1,33 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDashboardFlow
4
- } from "../chunk-P6I72PR3.js";
5
- import "../chunk-W5KEYSOL.js";
6
- import "../chunk-EH2PGPLP.js";
7
- import "../chunk-X6ZZEYO3.js";
8
- import "../chunk-PCFUXQJA.js";
9
- import "../chunk-KQ3PDARZ.js";
10
- import "../chunk-PLX2FLEQ.js";
11
- import "../chunk-HL3GYRMR.js";
12
- import "../chunk-JVUN6AOO.js";
13
- import "../chunk-QWFG7Y3R.js";
14
- import "../chunk-6WGXTB2L.js";
15
- import "../chunk-L3W2JWBA.js";
16
- import "../chunk-HI6YB7XP.js";
17
- import "../chunk-23DNVNFP.js";
18
- import "../chunk-7PYXS2QU.js";
19
- import "../chunk-GRL73YPF.js";
20
- import "../chunk-DJEO3F2H.js";
21
- import "../chunk-YN3SWF53.js";
22
- import "../chunk-4HWOYYY7.js";
23
- import "../chunk-TSIU7DME.js";
24
- import "../chunk-JOEA52NR.js";
25
- import "../chunk-VRXX4D6K.js";
26
- import "../chunk-3DIDV6H3.js";
27
- import "../chunk-XQHZPINL.js";
28
- import "../chunk-JPMV4E4E.js";
29
- import "../chunk-LFUJCRCT.js";
30
- import "../chunk-WTJ3AY33.js";
31
- import "../chunk-SLBL3WIP.js";
32
- import "../chunk-ZUGH4MQG.js";
4
+ } from "../chunk-NCWDK6L7.js";
5
+ import "../chunk-44TE3RKH.js";
6
+ import "../chunk-6HNXYYVF.js";
7
+ import "../chunk-OYJQUA3D.js";
33
8
  import "../chunk-4AAOOAIN.js";
34
9
  import "../chunk-OZXAJNLA.js";
35
- import "../chunk-27AVGFXH.js";
36
- import "../chunk-5JUQKGCP.js";
37
- import "../chunk-TW35AEB4.js";
38
- import "../chunk-GE7NUPMI.js";
39
- import "../chunk-JIBCVXXL.js";
40
- import "../chunk-3LZNY46H.js";
41
- import "../chunk-4UKMQUAU.js";
10
+ import "../chunk-F5EBEATU.js";
11
+ import "../chunk-7RDMTR64.js";
12
+ import "../chunk-F2BHT5C4.js";
13
+ import "../chunk-HED2DAXZ.js";
14
+ import "../chunk-3G7X2WKI.js";
15
+ import "../chunk-BMRUNMPV.js";
42
16
  import "../chunk-JFLVEFFP.js";
43
- import "../chunk-WNLF5EDZ.js";
44
- import "../chunk-HR7TK2XW.js";
17
+ import "../chunk-RIPSGNLU.js";
45
18
  import {
46
19
  EXIT_CODES
47
- } from "../chunk-H4ZKGGTE.js";
48
- import "../chunk-VVRI35SK.js";
49
- import "../chunk-CMJBKQUH.js";
20
+ } from "../chunk-V3KTSP3Q.js";
21
+ import "../chunk-CLPUWOSA.js";
50
22
  import {
51
23
  findConfigLoadFailures,
52
24
  installationConfigsUnreadable,
53
25
  retiredSourceFolderIn,
54
26
  retiredSourceFolderUnsupported
55
- } from "../chunk-C2UISKIM.js";
56
- import "../chunk-NU2K5G54.js";
57
- import "../chunk-AG3ZVM3B.js";
58
- import "../chunk-OI2H6M5I.js";
27
+ } from "../chunk-MQ6CGZNJ.js";
28
+ import "../chunk-52HDHJ7I.js";
29
+ import "../chunk-PJWGTNOX.js";
30
+ import "../chunk-NQW25DCF.js";
59
31
 
60
32
  // src/cli/hooks/init.ts
61
33
  import os from "os";
@@ -68,7 +40,7 @@ var hook = async function(options) {
68
40
  if (unreadable.length > 0) {
69
41
  this.error(installationConfigsUnreadable(unreadable), { exit: EXIT_CODES.ERROR });
70
42
  }
71
- const dashboard = await runDashboardFlow(projectDir, options.config, "standalone");
43
+ const dashboard = await runDashboardFlow(projectDir, options.config);
72
44
  if (dashboard === "cancelled") this.error("Cancelled", { exit: EXIT_CODES.CANCELLED });
73
45
  if (dashboard === "shown") await endRun(EXIT_CODES.SUCCESS);
74
46
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/hooks/init.ts"],"sourcesContent":["import os from \"os\";\n\nimport { flush, type Hook } from \"@oclif/core\";\nimport { runDashboardFlow } from \"../commands/init.js\";\nimport { findConfigLoadFailures } from \"../lib/configuration/project-config.js\";\nimport { retiredSourceFolderIn } from \"../lib/installation/install-layout.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n installationConfigsUnreadable,\n retiredSourceFolderUnsupported,\n} from \"../utils/messages.js\";\n\nconst hook: Hook<\"init\"> = async function (options) {\n sayTheRetiredSourceFolderIsUnsupported(process.cwd());\n\n // When no command is given and project is already initialized, show dashboard\n if (options.id === undefined) {\n const projectDir = process.cwd();\n // Refused as every command refuses it (`BaseCommand.ensureConfigReadable`). Left to the\n // dashboard, the load error was swallowed by oclif's hook runner and the run printed the root\n // help, as though nothing were installed.\n const unreadable = await findConfigLoadFailures(projectDir);\n if (unreadable.length > 0) {\n this.error(installationConfigsUnreadable(unreadable), { exit: EXIT_CODES.ERROR });\n }\n\n const dashboard = await runDashboardFlow(projectDir, options.config, \"standalone\");\n if (dashboard === \"cancelled\") this.error(\"Cancelled\", { exit: EXIT_CODES.CANCELLED });\n if (dashboard === \"shown\") await endRun(EXIT_CODES.SUCCESS);\n }\n};\n\n/**\n * One bare line, once per run, while the project or HOME holds the retired source folder.\n *\n * Here because every command passes through this hook exactly once, before it runs — so the line\n * is said once however many scopes hold the folder, and by every command alike. It is a notice\n * and nothing more: the run goes on exactly as it would without the folder, which no command\n * reads or writes. On stderr, so a command whose output is piped somewhere is not changed by it.\n */\nfunction sayTheRetiredSourceFolderIsUnsupported(cwd: string): void {\n const replacement = retiredSourceFolderIn([cwd, os.homedir()]);\n if (replacement === null) return;\n process.stderr.write(`${retiredSourceFolderUnsupported(replacement)}\\n`);\n}\n\n/**\n * Ends the run here, once the dashboard is done with it.\n *\n * `this.exit(0)` cannot: oclif swallows an exit 0 thrown from a hook and carries on with the run\n * the hook interrupted — and a run with no command is a request for the root help, so the full help\n * listing printed under every dashboard that was left with Escape or a chosen command. A non-zero\n * exit is not swallowed, which is why Ctrl+C's `this.error` already ended the run. This is the\n * ending oclif's own error handler gives a command's `this.exit()`, with the output flushed first.\n */\nasync function endRun(code: number): Promise<never> {\n await flush();\n process.exit(code);\n}\n\nexport default hook;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,QAAQ;AAEf,SAAS,aAAwB;AAUjC,IAAM,OAAqB,eAAgB,SAAS;AAClD,yCAAuC,QAAQ,IAAI,CAAC;AAGpD,MAAI,QAAQ,OAAO,QAAW;AAC5B,UAAM,aAAa,QAAQ,IAAI;AAI/B,UAAM,aAAa,MAAM,uBAAuB,UAAU;AAC1D,QAAI,WAAW,SAAS,GAAG;AACzB,WAAK,MAAM,8BAA8B,UAAU,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IAClF;AAEA,UAAM,YAAY,MAAM,iBAAiB,YAAY,QAAQ,QAAQ,YAAY;AACjF,QAAI,cAAc,YAAa,MAAK,MAAM,aAAa,EAAE,MAAM,WAAW,UAAU,CAAC;AACrF,QAAI,cAAc,QAAS,OAAM,OAAO,WAAW,OAAO;AAAA,EAC5D;AACF;AAUA,SAAS,uCAAuC,KAAmB;AACjE,QAAM,cAAc,sBAAsB,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC;AAC7D,MAAI,gBAAgB,KAAM;AAC1B,UAAQ,OAAO,MAAM,GAAG,+BAA+B,WAAW,CAAC;AAAA,CAAI;AACzE;AAWA,eAAe,OAAO,MAA8B;AAClD,QAAM,MAAM;AACZ,UAAQ,KAAK,IAAI;AACnB;AAEA,IAAO,eAAQ;","names":[]}
1
+ {"version":3,"sources":["../../src/cli/hooks/init.ts"],"sourcesContent":["import os from \"os\";\n\nimport { flush, type Hook } from \"@oclif/core\";\nimport { runDashboardFlow } from \"../commands/init.js\";\nimport { findConfigLoadFailures } from \"../lib/configuration/project-config.js\";\nimport { retiredSourceFolderIn } from \"../lib/installation/install-layout.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n installationConfigsUnreadable,\n retiredSourceFolderUnsupported,\n} from \"../utils/messages.js\";\n\nconst hook: Hook<\"init\"> = async function (options) {\n sayTheRetiredSourceFolderIsUnsupported(process.cwd());\n\n // No command: the dashboard, over the project's installation or else the global one\n if (options.id === undefined) {\n const projectDir = process.cwd();\n // Left to the dashboard, the load error was swallowed by oclif's hook runner and the run\n // printed the root help, as though nothing were installed.\n const unreadable = await findConfigLoadFailures(projectDir);\n if (unreadable.length > 0) {\n this.error(installationConfigsUnreadable(unreadable), { exit: EXIT_CODES.ERROR });\n }\n\n const dashboard = await runDashboardFlow(projectDir, options.config);\n if (dashboard === \"cancelled\") this.error(\"Cancelled\", { exit: EXIT_CODES.CANCELLED });\n if (dashboard === \"shown\") await endRun(EXIT_CODES.SUCCESS);\n }\n};\n\n/**\n * One bare line, once per run, while the project or HOME holds the retired source folder.\n *\n * Here because every command passes through this hook exactly once, before it runs — so the line\n * is said once however many scopes hold the folder, and by every command alike. It is a notice\n * and nothing more: the run goes on exactly as it would without the folder, which no command\n * reads or writes. On stderr, so a command whose output is piped somewhere is not changed by it.\n */\nfunction sayTheRetiredSourceFolderIsUnsupported(cwd: string): void {\n const replacement = retiredSourceFolderIn([cwd, os.homedir()]);\n if (replacement === null) return;\n process.stderr.write(`${retiredSourceFolderUnsupported(replacement)}\\n`);\n}\n\n/**\n * Ends the run here, once the dashboard is done with it.\n *\n * `this.exit(0)` cannot: oclif swallows an exit 0 thrown from a hook and carries on with the run\n * the hook interrupted — and a run with no command is a request for the root help, so the full help\n * listing printed under every dashboard that was left with Escape or a chosen command. A non-zero\n * exit is not swallowed, which is why Ctrl+C's `this.error` already ended the run. This is the\n * ending oclif's own error handler gives a command's `this.exit()`, with the output flushed first.\n */\nasync function endRun(code: number): Promise<never> {\n await flush();\n process.exit(code);\n}\n\nexport default hook;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,QAAQ;AAEf,SAAS,aAAwB;AAUjC,IAAM,OAAqB,eAAgB,SAAS;AAClD,yCAAuC,QAAQ,IAAI,CAAC;AAGpD,MAAI,QAAQ,OAAO,QAAW;AAC5B,UAAM,aAAa,QAAQ,IAAI;AAG/B,UAAM,aAAa,MAAM,uBAAuB,UAAU;AAC1D,QAAI,WAAW,SAAS,GAAG;AACzB,WAAK,MAAM,8BAA8B,UAAU,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IAClF;AAEA,UAAM,YAAY,MAAM,iBAAiB,YAAY,QAAQ,MAAM;AACnE,QAAI,cAAc,YAAa,MAAK,MAAM,aAAa,EAAE,MAAM,WAAW,UAAU,CAAC;AACrF,QAAI,cAAc,QAAS,OAAM,OAAO,WAAW,OAAO;AAAA,EAC5D;AACF;AAUA,SAAS,uCAAuC,KAAmB;AACjE,QAAM,cAAc,sBAAsB,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC;AAC7D,MAAI,gBAAgB,KAAM;AAC1B,UAAQ,OAAO,MAAM,GAAG,+BAA+B,WAAW,CAAC;AAAA,CAAI;AACzE;AAWA,eAAe,OAAO,MAA8B;AAClD,QAAM,MAAM;AACZ,UAAQ,KAAK,IAAI;AACnB;AAEA,IAAO,eAAQ;","names":[]}
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ loadAgentDefs
4
+ } from "./chunk-HED2DAXZ.js";
5
+ import "./chunk-3G7X2WKI.js";
6
+ import "./chunk-BMRUNMPV.js";
7
+ import "./chunk-MQ6CGZNJ.js";
8
+ import "./chunk-52HDHJ7I.js";
9
+ import "./chunk-PJWGTNOX.js";
10
+ import "./chunk-NQW25DCF.js";
11
+ export {
12
+ loadAgentDefs
13
+ };
14
+ //# sourceMappingURL=load-agent-defs-YMDWBFDP.js.map
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ recompilePropagatedProjectAgents,
4
+ recompileRegisteredProjectAgents
5
+ } from "./chunk-F2BHT5C4.js";
6
+ import "./chunk-HED2DAXZ.js";
7
+ import "./chunk-3G7X2WKI.js";
8
+ import "./chunk-BMRUNMPV.js";
9
+ import "./chunk-CLPUWOSA.js";
10
+ import "./chunk-MQ6CGZNJ.js";
11
+ import "./chunk-52HDHJ7I.js";
12
+ import "./chunk-PJWGTNOX.js";
13
+ import "./chunk-NQW25DCF.js";
14
+ export {
15
+ recompilePropagatedProjectAgents,
16
+ recompileRegisteredProjectAgents
17
+ };
18
+ //# sourceMappingURL=recompile-project-agents-SZ76WNTW.js.map
@@ -5,10 +5,10 @@ import {
5
5
  loadMarketplaceMatrix,
6
6
  loadSkillsMatrixFromSource,
7
7
  mergeLocalSkillsIntoMatrix
8
- } from "./chunk-C2UISKIM.js";
9
- import "./chunk-NU2K5G54.js";
10
- import "./chunk-AG3ZVM3B.js";
11
- import "./chunk-OI2H6M5I.js";
8
+ } from "./chunk-MQ6CGZNJ.js";
9
+ import "./chunk-52HDHJ7I.js";
10
+ import "./chunk-PJWGTNOX.js";
11
+ import "./chunk-NQW25DCF.js";
12
12
  export {
13
13
  MarketplaceManifestRequiredError,
14
14
  convertStackToResolvedStack,
@@ -16,4 +16,4 @@ export {
16
16
  loadSkillsMatrixFromSource,
17
17
  mergeLocalSkillsIntoMatrix
18
18
  };
19
- //# sourceMappingURL=source-loader-FRJTCSDL.js.map
19
+ //# sourceMappingURL=source-loader-C5SQXZXI.js.map
@@ -71,8 +71,7 @@ rather than restating it; a second copy of a count can only drift from the first
71
71
  removed, and a corrected "covers" description where a document's scope moved.
72
72
  6. **Check your own output** before reporting: every path and symbol resolves, every pattern names
73
73
  an instance, every relationship is traceable in an import or a call, every cross-reference points
74
- at a document that exists, and no line number appears anywhere. This is the check the completion
75
- gate cannot make — it runs the project's typecheck, which never reads what you wrote.
74
+ at a document that exists, and no line number appears anywhere.
76
75
  7. **Point the project's `CLAUDE.md` at the map**, once, where nothing there does. A single line
77
76
  naming `.ai-docs/DOCUMENTATION_MAP.md` as the documentation index is the whole edit — no date,
78
77
  because the frontmatter of each document owns that and a second copy goes stale unread.
@@ -206,7 +205,7 @@ area you have not scoped spends the context the document needs on files it will
206
205
  ## Documenting a Monorepo
207
206
 
208
207
  Read the workspace configuration first, and let the package boundaries decide the document
209
- boundaries. Beyond the per-area documents, three things are worth their own:
208
+ boundaries. Beyond the per-area documents, these are worth their own:
210
209
 
211
210
  - **Package relationships** — each package, what it exports, and which apps consume it. This is the
212
211
  question a cross-package change opens with.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-inc",
3
- "version": "0.168.0",
3
+ "version": "0.170.1",
4
4
  "description": "CLI for managing Agents Inc. skills, stacks, and agents for Claude Code",
5
5
  "//generate": "The write path for all four generators, in dependency order: generate:types reads the skills marketplace and writes src/cli/types/generated/, then generate:schemas copies SKILL_SLUGS and CATEGORIES out of it into metadata.schema.json's enums, then generate:matrix vendors the same directory into packages/matrix, then generate:compile vendors this package's own src/agents/ partials and templates into packages/compile. A marketplace change drifts the first three, and .github/workflows/regenerate-catalog.yml runs those three step by step; generate:compile is not on that chain, because an agent-partial edit drifts it and a marketplace change does not. It replaces the write path only: the :check variants stay separate because CI deliberately runs different subsets of them in different jobs.",
6
6
  "//no-shared-vitest-config": "A three-project suite — unit, integration and commands, each with its own include and the retry that separates them — behind one root config that also carries vitest.setup.ts, disableConsoleIntercept for @oclif/test and ink-testing-library, and its own timeouts. @workspace/vitest-config is a single-project node config that turns globals off, which this suite needs on, so merging it in would contradict as much as it contributed. e2e/vitest.config.ts stands under the same decision. Read by scripts/check-shared-vitest-config.ts in packages/cli.",
@@ -129,8 +129,7 @@
129
129
  "react": "^19.2.6",
130
130
  "remeda": "^2.33.6",
131
131
  "yaml": "^2.9.0",
132
- "zod": "^4.4.3",
133
- "zustand": "^5.0.14"
132
+ "zod": "^4.4.3"
134
133
  },
135
134
  "//devDependencies": "@workspace/matrix, @workspace/compile and @workspace/api are private and never installed by a consumer, so all three are devDependencies and tsup bundles them (see `noExternal`). matrix is the one home of the seed wire contract, which src/cli/lib/seed/ used to hand-vendor; compile is the one home of the config-pair and compiled-agent renderers, which the editor's output preview draws with; api is the one home of the typed client both front doors reach the worker through, which src/cli/lib/seed/fetch-seed.ts used to hand-write a fetch for. api pulls `hono/client` in with it, and `hono` is deliberately NOT a dependency here: tsup externalises exactly what `dependencies` names, so leaving it out is what inlines it into the bundle rather than adding a runtime install to a CLI that makes one GET. The cost of that was measured before it was accepted — `find dist -name '*.js' -not -name '*.map' | xargs du -cb | tail -1` is the number. @workspace/api-mocks and msw are a different case and are named in neither `noExternal` nor this rule: nothing under src/cli/ imports them, so they reach no bundle at all — they are the one description of the worker this suite's network mocks are resolved from, and the editor's suites read the same one.",
136
135
  "devDependencies": {
@@ -71,8 +71,7 @@ rather than restating it; a second copy of a count can only drift from the first
71
71
  removed, and a corrected "covers" description where a document's scope moved.
72
72
  6. **Check your own output** before reporting: every path and symbol resolves, every pattern names
73
73
  an instance, every relationship is traceable in an import or a call, every cross-reference points
74
- at a document that exists, and no line number appears anywhere. This is the check the completion
75
- gate cannot make — it runs the project's typecheck, which never reads what you wrote.
74
+ at a document that exists, and no line number appears anywhere.
76
75
  7. **Point the project's `CLAUDE.md` at the map**, once, where nothing there does. A single line
77
76
  naming `.ai-docs/DOCUMENTATION_MAP.md` as the documentation index is the whole edit — no date,
78
77
  because the frontmatter of each document owns that and a second copy goes stale unread.
@@ -206,7 +205,7 @@ area you have not scoped spends the context the document needs on files it will
206
205
  ## Documenting a Monorepo
207
206
 
208
207
  Read the workspace configuration first, and let the package boundaries decide the document
209
- boundaries. Beyond the per-area documents, three things are worth their own:
208
+ boundaries. Beyond the per-area documents, these are worth their own:
210
209
 
211
210
  - **Package relationships** — each package, what it exports, and which apps consume it. This is the
212
211
  question a cross-package change opens with.
@@ -3,7 +3,7 @@
3
3
  "$id": "schemas/project-config.schema.json",
4
4
  "title": "Project Configuration",
5
5
  "description": "Schema for .agents-inc/<provider>/config.ts consumer project files (name, agents, stack, skills).",
6
- "$comment": "HAND-MAINTAINED. scripts/generate-json-schemas.ts does NOT emit this file (nor project-source-config.schema.json) — its SCHEMA_ENTRIES list has no entry for either, so `generate:schemas` neither emits nor judges them and writes nothing here. Edit this file by hand and keep it prettier-clean — .ai-docs/reference/features/code-generation.md names the gate that enforces that. Three vocabularies below are copied out of src/cli/types/generated/source-types.ts and drift silently, because no generator and no check re-derives any of them: the stack category enum is the CATEGORIES tuple, verbatim and in that tuple's order; the selectedDomains enum is the DOMAINS tuple; and the skill-id pattern's leading alternation is that same DOMAINS tuple, since a skill id is `<domain>-<category>-<name>`. Re-derive all three whenever a category or domain is added, renamed or removed — a missing domain silently rejects every skill id under it.",
6
+ "$comment": "HAND-MAINTAINED. scripts/generate-json-schemas.ts does NOT emit this file (nor project-source-config.schema.json) — its SCHEMA_ENTRIES list has no entry for either, so `generate:schemas` neither emits nor judges them and writes nothing here. Edit this file by hand and keep it prettier-clean. Three vocabularies below are copied out of src/cli/types/generated/source-types.ts and drift silently, because no generator and no check re-derives any of them: the stack category enum is the CATEGORIES tuple, verbatim and in that tuple's order; the selectedDomains enum is the DOMAINS tuple; and the skill-id pattern's leading alternation is that same DOMAINS tuple, since a skill id is `<domain>-<category>-<name>`. Re-derive all three whenever a category or domain is added, renamed or removed — a missing domain silently rejects every skill id under it.",
7
7
  "type": "object",
8
8
  "properties": {
9
9
  "version": {