@amsterdamdatalabs/enact-extensions 0.1.37 → 0.1.47

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 (577) hide show
  1. package/README.md +67 -108
  2. package/bundled-extensions.json +6 -0
  3. package/dist/create/enact.d.ts.map +1 -1
  4. package/dist/create/enact.js +2 -0
  5. package/dist/create/enact.js.map +1 -1
  6. package/dist/create/index.d.ts +3 -0
  7. package/dist/create/index.d.ts.map +1 -1
  8. package/dist/create/index.js +6 -0
  9. package/dist/create/index.js.map +1 -1
  10. package/dist/create/kimi.d.ts +16 -0
  11. package/dist/create/kimi.d.ts.map +1 -0
  12. package/dist/create/kimi.js +87 -0
  13. package/dist/create/kimi.js.map +1 -0
  14. package/dist/create/opencode.d.ts +129 -0
  15. package/dist/create/opencode.d.ts.map +1 -0
  16. package/dist/create/opencode.js +696 -0
  17. package/dist/create/opencode.js.map +1 -0
  18. package/dist/index.d.ts +12 -16
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +10 -10
  21. package/dist/index.js.map +1 -1
  22. package/dist/internal/agents.d.ts +12 -2
  23. package/dist/internal/agents.d.ts.map +1 -1
  24. package/dist/internal/agents.js +119 -3
  25. package/dist/internal/agents.js.map +1 -1
  26. package/dist/internal/extensions-table.d.ts +58 -0
  27. package/dist/internal/extensions-table.d.ts.map +1 -0
  28. package/dist/internal/extensions-table.js +134 -0
  29. package/dist/internal/extensions-table.js.map +1 -0
  30. package/dist/internal/file-ops.d.ts +36 -0
  31. package/dist/internal/file-ops.d.ts.map +1 -0
  32. package/dist/internal/file-ops.js +89 -0
  33. package/dist/internal/file-ops.js.map +1 -0
  34. package/dist/internal/hooks.d.ts +56 -0
  35. package/dist/internal/hooks.d.ts.map +1 -0
  36. package/dist/internal/hooks.js +128 -0
  37. package/dist/internal/hooks.js.map +1 -0
  38. package/dist/internal/json-merge.d.ts +63 -0
  39. package/dist/internal/json-merge.d.ts.map +1 -0
  40. package/dist/internal/json-merge.js +122 -0
  41. package/dist/internal/json-merge.js.map +1 -0
  42. package/dist/internal/lock-ownership.d.ts +41 -0
  43. package/dist/internal/lock-ownership.d.ts.map +1 -0
  44. package/dist/internal/lock-ownership.js +24 -0
  45. package/dist/internal/lock-ownership.js.map +1 -0
  46. package/dist/internal/platform.d.ts.map +1 -1
  47. package/dist/internal/platform.js +90 -4
  48. package/dist/internal/platform.js.map +1 -1
  49. package/dist/internal/schema.js.map +1 -1
  50. package/dist/internal/toml-block.d.ts +59 -0
  51. package/dist/internal/toml-block.d.ts.map +1 -0
  52. package/dist/internal/toml-block.js +113 -0
  53. package/dist/internal/toml-block.js.map +1 -0
  54. package/dist/internal/types.d.ts +2 -1
  55. package/dist/internal/types.d.ts.map +1 -1
  56. package/dist/projection.d.ts +47 -0
  57. package/dist/projection.d.ts.map +1 -0
  58. package/dist/projection.js +180 -0
  59. package/dist/projection.js.map +1 -0
  60. package/dist/validate/index.d.ts +9 -4
  61. package/dist/validate/index.d.ts.map +1 -1
  62. package/dist/validate/index.js +56 -7
  63. package/dist/validate/index.js.map +1 -1
  64. package/dist/validate/kimi.d.ts +3 -0
  65. package/dist/validate/kimi.d.ts.map +1 -0
  66. package/dist/validate/kimi.js +11 -0
  67. package/dist/validate/kimi.js.map +1 -0
  68. package/dist/validate/opencode.d.ts +3 -0
  69. package/dist/validate/opencode.d.ts.map +1 -0
  70. package/dist/validate/opencode.js +11 -0
  71. package/dist/validate/opencode.js.map +1 -0
  72. package/dist/validate/run.d.ts +39 -0
  73. package/dist/validate/run.d.ts.map +1 -0
  74. package/dist/validate/run.js +63 -0
  75. package/dist/validate/run.js.map +1 -0
  76. package/extensions/enact-loop/.agents/plugin.json +12 -8
  77. package/extensions/enact-loop/scripts/validate.mjs +113 -2
  78. package/extensions/enact-loop/skills/enact-loop/SKILL.md +36 -466
  79. package/extensions/enact-loop/skills/enact-loop/references/loop-contract.md +114 -0
  80. package/extensions/enact-loop/skills/loop-budget/SKILL.md +57 -0
  81. package/extensions/enact-loop/skills/loop-intake/SKILL.md +59 -0
  82. package/extensions/enact-repo/.agents/plugin.json +55 -0
  83. package/extensions/enact-repo/.mcp.json +20 -0
  84. package/extensions/enact-repo/README.md +90 -0
  85. package/extensions/enact-repo/hooks/hooks.json +98 -0
  86. package/extensions/enact-repo/lean-ctx/config.toml +35 -0
  87. package/extensions/enact-repo/lean-ctx/layout.toml +5 -0
  88. package/extensions/enact-repo/skills/aca-sandboxes/SKILL.md +53 -0
  89. package/extensions/enact-repo/skills/aca-sandboxes/references/capabilities.md +52 -0
  90. package/extensions/enact-repo/skills/aca-sandboxes/references/install.md +87 -0
  91. package/extensions/enact-repo/skills/aca-sandboxes/references/prerequisites.md +52 -0
  92. package/extensions/enact-repo/skills/aca-sandboxes/references/quickstart.md +164 -0
  93. package/extensions/enact-repo/skills/aca-sandboxes/references/reference-advanced.md +251 -0
  94. package/extensions/enact-repo/skills/aca-sandboxes/references/reference.md +287 -0
  95. package/extensions/enact-repo/skills/aca-sandboxes/references/response-cues.md +71 -0
  96. package/extensions/enact-repo/skills/aca-sandboxes/references/scenarios.md +219 -0
  97. package/extensions/enact-repo/skills/aca-sandboxes/version.json +4 -0
  98. package/extensions/enact-repo/skills/backend-remove-deadcode/SKILL.md +96 -0
  99. package/extensions/enact-repo/skills/cmux-leader/SKILL.md +61 -0
  100. package/extensions/enact-repo/skills/cmux-send/SKILL.md +61 -0
  101. package/extensions/enact-repo/skills/code-review/SKILL.md +100 -0
  102. package/extensions/enact-repo/skills/codebase-design/SKILL.md +98 -0
  103. package/extensions/enact-repo/skills/codebase-design/references/DEEPENING.md +37 -0
  104. package/extensions/enact-repo/skills/codebase-design/references/DESIGN-IT-TWICE.md +44 -0
  105. package/extensions/enact-repo/skills/codebase-design/references/TESTABILITY.md +29 -0
  106. package/extensions/enact-repo/skills/computer-use/SKILL.md +76 -0
  107. package/extensions/enact-repo/skills/debug-issue/SKILL.md +40 -0
  108. package/extensions/enact-repo/skills/diagnosing-bugs/SKILL.md +100 -0
  109. package/extensions/enact-repo/skills/diagnosing-bugs/references/FEEDBACK-LOOP-TACTICS.md +34 -0
  110. package/extensions/enact-repo/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +41 -0
  111. package/extensions/enact-repo/skills/domain-modeling/SKILL.md +86 -0
  112. package/extensions/enact-repo/skills/domain-modeling/references/ADR-FORMAT.md +47 -0
  113. package/extensions/enact-repo/skills/domain-modeling/references/CONTEXT-FORMAT.md +60 -0
  114. package/extensions/enact-repo/skills/explore-codebase/SKILL.md +41 -0
  115. package/extensions/enact-repo/skills/frontend-design/LICENSE.txt +177 -0
  116. package/extensions/enact-repo/skills/frontend-design/SKILL.md +56 -0
  117. package/extensions/enact-repo/skills/grill-me/SKILL.md +20 -0
  118. package/extensions/enact-repo/skills/grill-with-docs/SKILL.md +20 -0
  119. package/extensions/enact-repo/skills/handoff/SKILL.md +28 -0
  120. package/extensions/enact-repo/skills/http-contract-migration/SKILL.md +74 -0
  121. package/extensions/enact-repo/skills/http-contract-migration/references/compatibility-and-gates.md +26 -0
  122. package/extensions/enact-repo/skills/http-contract-migration/references/hexagonal-boundary.md +16 -0
  123. package/extensions/enact-repo/skills/http-contract-migration/references/publication-and-adoption.md +31 -0
  124. package/extensions/enact-repo/skills/http-contract-migration/references/wire-fidelity-and-dto.md +31 -0
  125. package/extensions/enact-repo/skills/implement/SKILL.md +28 -0
  126. package/extensions/enact-repo/skills/improve-codebase-architecture/SKILL.md +80 -0
  127. package/extensions/enact-repo/skills/improve-codebase-architecture/references/HTML-REPORT.md +123 -0
  128. package/extensions/enact-repo/skills/interaction-design/SKILL.md +30 -0
  129. package/extensions/enact-repo/skills/interaction-design/references/Workflow.md +146 -0
  130. package/extensions/enact-repo/skills/interaction-design/references/animation-libraries-gsap.md +220 -0
  131. package/extensions/enact-repo/skills/interaction-design/references/animation-libraries-native.md +110 -0
  132. package/extensions/enact-repo/skills/interaction-design/references/animation-libraries.md +178 -0
  133. package/extensions/enact-repo/skills/interaction-design/references/interaction-patterns.md +166 -0
  134. package/extensions/enact-repo/skills/interaction-design/references/microinteraction-patterns-advanced.md +285 -0
  135. package/extensions/enact-repo/skills/interaction-design/references/microinteraction-patterns.md +254 -0
  136. package/extensions/enact-repo/skills/interaction-design/references/scroll-animations-reveals.md +213 -0
  137. package/extensions/enact-repo/skills/interaction-design/references/scroll-animations.md +209 -0
  138. package/extensions/enact-repo/skills/lean-ctx/SKILL.md +81 -0
  139. package/extensions/enact-repo/skills/orca-cli/SKILL.md +88 -0
  140. package/extensions/enact-repo/skills/orchestration/SKILL.md +80 -0
  141. package/extensions/enact-repo/skills/prototype/SKILL.md +37 -0
  142. package/extensions/enact-repo/skills/prototype/references/LOGIC.md +79 -0
  143. package/extensions/enact-repo/skills/prototype/references/UI.md +112 -0
  144. package/extensions/enact-repo/skills/refactor-safely/SKILL.md +44 -0
  145. package/extensions/enact-repo/skills/remove-deadcode/SKILL.md +54 -0
  146. package/extensions/enact-repo/skills/research/SKILL.md +27 -0
  147. package/extensions/enact-repo/skills/resolving-merge-conflicts/SKILL.md +28 -0
  148. package/extensions/enact-repo/skills/review-changes/SKILL.md +45 -0
  149. package/extensions/enact-repo/skills/tailwind-4-docs/SKILL.md +88 -0
  150. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/accent-color.mdx +149 -0
  151. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/adding-custom-styles.mdx +635 -0
  152. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/align-content.mdx +300 -0
  153. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/align-items.mdx +241 -0
  154. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/align-self.mdx +294 -0
  155. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/animation.mdx +286 -0
  156. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/appearance.mdx +180 -0
  157. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/aspect-ratio.mdx +98 -0
  158. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-blur.mdx +109 -0
  159. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-brightness.mdx +82 -0
  160. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-contrast.mdx +82 -0
  161. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-grayscale.mdx +99 -0
  162. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-hue-rotate.mdx +173 -0
  163. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-invert.mdx +99 -0
  164. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-opacity.mdx +103 -0
  165. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-saturate.mdx +98 -0
  166. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-sepia.mdx +95 -0
  167. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter.mdx +113 -0
  168. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backface-visibility.mdx +110 -0
  169. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-attachment.mdx +126 -0
  170. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-blend-mode.mdx +79 -0
  171. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-clip.mdx +85 -0
  172. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-color.mdx +176 -0
  173. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-image.mdx +349 -0
  174. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-origin.mdx +64 -0
  175. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-position.mdx +171 -0
  176. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-repeat.mdx +127 -0
  177. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-size.mdx +100 -0
  178. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/block-size.mdx +190 -0
  179. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/border-collapse.mdx +181 -0
  180. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/border-color.mdx +316 -0
  181. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/border-radius.mdx +347 -0
  182. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/border-spacing.mdx +117 -0
  183. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/border-style.mdx +129 -0
  184. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/border-width.mdx +344 -0
  185. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/box-decoration-break.mdx +71 -0
  186. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/box-shadow.mdx +497 -0
  187. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/box-sizing.mdx +175 -0
  188. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/break-after.mdx +38 -0
  189. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/break-before.mdx +38 -0
  190. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/break-inside.mdx +34 -0
  191. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/caption-side.mdx +190 -0
  192. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/caret-color.mdx +66 -0
  193. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/clear.mdx +224 -0
  194. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/color-scheme.mdx +81 -0
  195. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/color.mdx +125 -0
  196. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/colors.mdx +927 -0
  197. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/columns.mdx +310 -0
  198. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/compatibility.mdx +193 -0
  199. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/content.mdx +129 -0
  200. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/cursor.mdx +104 -0
  201. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/dark-mode.mdx +191 -0
  202. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/detecting-classes-in-source-files.mdx +315 -0
  203. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/display.mdx +523 -0
  204. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/editor-setup.mdx +90 -0
  205. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/field-sizing.mdx +75 -0
  206. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/fill.mdx +100 -0
  207. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-blur.mdx +114 -0
  208. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-brightness.mdx +102 -0
  209. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-contrast.mdx +102 -0
  210. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-drop-shadow.mdx +230 -0
  211. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-grayscale.mdx +101 -0
  212. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-hue-rotate.mdx +171 -0
  213. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-invert.mdx +93 -0
  214. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-saturate.mdx +109 -0
  215. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-sepia.mdx +92 -0
  216. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter.mdx +113 -0
  217. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/flex-basis.mdx +144 -0
  218. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/flex-direction.mdx +130 -0
  219. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/flex-grow.mdx +129 -0
  220. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/flex-shrink.mdx +95 -0
  221. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/flex-wrap.mdx +118 -0
  222. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/flex.mdx +164 -0
  223. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/float.mdx +197 -0
  224. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-family.mdx +119 -0
  225. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-feature-settings.mdx +52 -0
  226. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-size.mdx +184 -0
  227. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-smoothing.mdx +67 -0
  228. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-stretch.mdx +138 -0
  229. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-style.mdx +62 -0
  230. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-variant-numeric.mdx +228 -0
  231. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-weight.mdx +105 -0
  232. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/forced-color-adjust.mdx +152 -0
  233. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/functions-and-directives.mdx +322 -0
  234. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/gap.mdx +100 -0
  235. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-auto-columns.mdx +43 -0
  236. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-auto-flow.mdx +58 -0
  237. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-auto-rows.mdx +43 -0
  238. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-column.mdx +124 -0
  239. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-row.mdx +115 -0
  240. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-template-columns.mdx +101 -0
  241. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-template-rows.mdx +108 -0
  242. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/height.mdx +260 -0
  243. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/hover-focus-and-other-states.mdx +4935 -0
  244. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/hyphens.mdx +112 -0
  245. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/inline-size.mdx +191 -0
  246. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/isolation.mdx +30 -0
  247. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/justify-content.mdx +348 -0
  248. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/justify-items.mdx +286 -0
  249. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/justify-self.mdx +282 -0
  250. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/letter-spacing.mdx +100 -0
  251. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/line-clamp.mdx +110 -0
  252. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/line-height.mdx +147 -0
  253. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/list-style-image.mdx +80 -0
  254. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/list-style-position.mdx +67 -0
  255. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/list-style-type.mdx +86 -0
  256. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/margin.mdx +397 -0
  257. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-clip.mdx +66 -0
  258. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-composite.mdx +70 -0
  259. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-image.mdx +933 -0
  260. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-mode.mdx +114 -0
  261. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-origin.mdx +66 -0
  262. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-position.mdx +117 -0
  263. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-repeat.mdx +169 -0
  264. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-size.mdx +104 -0
  265. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-type.mdx +98 -0
  266. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/max-block-size.mdx +153 -0
  267. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/max-height.mdx +164 -0
  268. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/max-inline-size.mdx +185 -0
  269. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/max-width.mdx +214 -0
  270. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/min-block-size.mdx +146 -0
  271. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/min-height.mdx +150 -0
  272. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/min-inline-size.mdx +153 -0
  273. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/min-width.mdx +153 -0
  274. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mix-blend-mode.mdx +103 -0
  275. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/object-fit.mdx +147 -0
  276. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/object-position.mdx +182 -0
  277. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/opacity.mdx +84 -0
  278. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/order.mdx +94 -0
  279. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/outline-color.mdx +130 -0
  280. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/outline-offset.mdx +72 -0
  281. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/outline-style.mdx +134 -0
  282. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/outline-width.mdx +91 -0
  283. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/overflow-wrap.mdx +130 -0
  284. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/overflow.mdx +665 -0
  285. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/overscroll-behavior.mdx +151 -0
  286. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/padding.mdx +232 -0
  287. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/perspective-origin.mdx +127 -0
  288. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/perspective.mdx +137 -0
  289. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/place-content.mdx +257 -0
  290. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/place-items.mdx +269 -0
  291. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/place-self.mdx +257 -0
  292. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/pointer-events.mdx +101 -0
  293. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/position.mdx +399 -0
  294. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/preflight.mdx +291 -0
  295. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/resize.mdx +110 -0
  296. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/responsive-design.mdx +666 -0
  297. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/rotate.mdx +291 -0
  298. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scale.mdx +360 -0
  299. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scroll-behavior.mdx +39 -0
  300. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scroll-margin.mdx +268 -0
  301. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scroll-padding.mdx +255 -0
  302. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scroll-snap-align.mdx +281 -0
  303. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scroll-snap-stop.mdx +198 -0
  304. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scroll-snap-type.mdx +284 -0
  305. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/skew.mdx +352 -0
  306. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/stroke-width.mdx +74 -0
  307. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/stroke.mdx +103 -0
  308. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/styling-with-utility-classes.mdx +1020 -0
  309. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/table-layout.mdx +212 -0
  310. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-align.mdx +162 -0
  311. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-decoration-color.mdx +155 -0
  312. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-decoration-line.mdx +143 -0
  313. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-decoration-style.mdx +75 -0
  314. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-decoration-thickness.mdx +75 -0
  315. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-indent.mdx +74 -0
  316. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-overflow.mdx +103 -0
  317. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-shadow.mdx +177 -0
  318. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-transform.mdx +106 -0
  319. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-underline-offset.mdx +74 -0
  320. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-wrap.mdx +144 -0
  321. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/theme.mdx +1142 -0
  322. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/top-right-bottom-left.mdx +296 -0
  323. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/touch-action.mdx +95 -0
  324. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transform-origin.mdx +130 -0
  325. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transform-style.mdx +110 -0
  326. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transform.mdx +51 -0
  327. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transition-behavior.mdx +76 -0
  328. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transition-delay.mdx +76 -0
  329. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transition-duration.mdx +82 -0
  330. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transition-property.mdx +137 -0
  331. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transition-timing-function.mdx +89 -0
  332. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/translate.mdx +487 -0
  333. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/upgrade-guide.mdx +910 -0
  334. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/user-select.mdx +114 -0
  335. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/vertical-align.mdx +194 -0
  336. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/visibility.mdx +287 -0
  337. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/white-space.mdx +211 -0
  338. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/width.mdx +264 -0
  339. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/will-change.mdx +47 -0
  340. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/word-break.mdx +94 -0
  341. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/z-index.mdx +104 -0
  342. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs-catalog.md +251 -0
  343. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs-index.tsx +237 -0
  344. package/extensions/enact-repo/skills/tailwind-4-docs/references/docs-source.txt +6 -0
  345. package/extensions/enact-repo/skills/tailwind-4-docs/references/gotchas.md +18 -0
  346. package/extensions/enact-repo/skills/tailwind-4-docs/scripts/sync_tailwind_docs.py +183 -0
  347. package/extensions/enact-repo/skills/tdd/SKILL.md +49 -0
  348. package/extensions/enact-repo/skills/tdd/references/mocking.md +59 -0
  349. package/extensions/enact-repo/skills/tdd/references/tests.md +77 -0
  350. package/extensions/enact-repo/skills/teach/SKILL.md +88 -0
  351. package/extensions/enact-repo/skills/teach/references/GLOSSARY-FORMAT.md +35 -0
  352. package/extensions/enact-repo/skills/teach/references/LEARNING-RECORD-FORMAT.md +46 -0
  353. package/extensions/enact-repo/skills/teach/references/MISSION-FORMAT.md +31 -0
  354. package/extensions/enact-repo/skills/teach/references/PHILOSOPHY.md +65 -0
  355. package/extensions/enact-repo/skills/teach/references/RESOURCES-FORMAT.md +32 -0
  356. package/extensions/enact-repo/skills/testing/SKILL.md +54 -0
  357. package/extensions/enact-repo/skills/to-spec/SKILL.md +85 -0
  358. package/extensions/enact-repo/skills/to-tickets/SKILL.md +75 -0
  359. package/extensions/enact-repo/skills/to-tickets/references/TICKET-TEMPLATES.md +39 -0
  360. package/extensions/enact-repo/skills/triage/SKILL.md +99 -0
  361. package/extensions/enact-repo/skills/triage/references/AGENT-BRIEF.md +207 -0
  362. package/extensions/enact-repo/skills/triage/references/NEEDS-INFO-TEMPLATE.md +17 -0
  363. package/extensions/enact-repo/skills/triage/references/OUT-OF-SCOPE.md +105 -0
  364. package/extensions/enact-repo/skills/ui-ux-pro-max/SKILL.md +32 -0
  365. package/extensions/enact-repo/skills/ui-ux-pro-max/references/Workflow.md +207 -0
  366. package/extensions/enact-repo/skills/ui-ux-pro-max/references/workflow-reference.md +175 -0
  367. package/extensions/enact-repo/skills/wayfinder/SKILL.md +100 -0
  368. package/extensions/enact-repo/skills/wayfinder/references/TEMPLATES.md +35 -0
  369. package/extensions/enact-repo/skills/wayfinder/references/TICKET-TYPES.md +8 -0
  370. package/extensions/enact-repo/skills/writing-great-skills/SKILL.md +93 -0
  371. package/extensions/enact-repo/skills/writing-great-skills/references/GLOSSARY.md +201 -0
  372. package/package.json +18 -14
  373. package/scripts/enact-extensions.mjs +255 -873
  374. package/scripts/lib/allowed-plugins.mjs +52 -0
  375. package/scripts/lib/run-repo-doctor.mjs +571 -0
  376. package/scripts/lib/run-repo-install.mjs +1579 -0
  377. package/scripts/lib/run-sync.mjs +1 -1
  378. package/scripts/lib/run-validate.mjs +23 -37
  379. package/scripts/lib/skill-validator.mjs +872 -0
  380. package/spec/enact.json +21 -3
  381. package/spec/enact.md +13 -12
  382. package/spec/kimi.json +100 -0
  383. package/spec/opencode.json +64 -0
  384. package/dist/install.d.ts +0 -235
  385. package/dist/install.d.ts.map +0 -1
  386. package/dist/install.js +0 -697
  387. package/dist/install.js.map +0 -1
  388. package/dist/internal/claude.d.ts +0 -65
  389. package/dist/internal/claude.d.ts.map +0 -1
  390. package/dist/internal/claude.js +0 -200
  391. package/dist/internal/claude.js.map +0 -1
  392. package/dist/internal/codex.d.ts +0 -43
  393. package/dist/internal/codex.d.ts.map +0 -1
  394. package/dist/internal/codex.js +0 -211
  395. package/dist/internal/codex.js.map +0 -1
  396. package/dist/internal/cursor.d.ts +0 -2
  397. package/dist/internal/cursor.d.ts.map +0 -1
  398. package/dist/internal/cursor.js +0 -6
  399. package/dist/internal/cursor.js.map +0 -1
  400. package/dist/principles.d.ts +0 -28
  401. package/dist/principles.d.ts.map +0 -1
  402. package/dist/principles.js +0 -159
  403. package/dist/principles.js.map +0 -1
  404. package/dist/provision.d.ts +0 -30
  405. package/dist/provision.d.ts.map +0 -1
  406. package/dist/provision.js +0 -202
  407. package/dist/provision.js.map +0 -1
  408. package/extensions/dev-state/.agents/plugin.json +0 -36
  409. package/extensions/dev-state/skills/dev-state-plan-graduation/SKILL.md +0 -194
  410. package/extensions/dev-state/skills/dev-state-plan-graduation/agents/openai.yaml +0 -4
  411. package/extensions/dev-state/skills/dev-state-plan-graduation/references/reference.md +0 -130
  412. package/extensions/enact-context/.agents/plugin.json +0 -41
  413. package/extensions/enact-context/.mcp.json +0 -8
  414. package/extensions/enact-context/README.md +0 -25
  415. package/extensions/enact-context/assets/icon.png +0 -0
  416. package/extensions/enact-context/assets/logo.png +0 -0
  417. package/extensions/enact-context/hooks/hooks.json +0 -115
  418. package/extensions/enact-context/skills/enact-context/SKILL.md +0 -151
  419. package/extensions/enact-context/skills/enact-context/scripts/install.sh +0 -69
  420. package/extensions/enact-core/.agents/plugin.json +0 -40
  421. package/extensions/enact-core/OPERATING-PRINCIPLES.md +0 -7
  422. package/extensions/enact-core/hooks/hooks.json +0 -26
  423. package/extensions/enact-evolve/.agents/plugin.json +0 -47
  424. package/extensions/enact-evolve/agents/evolve-session-analyst.toml +0 -37
  425. package/extensions/enact-evolve/assets/icon.png +0 -0
  426. package/extensions/enact-evolve/assets/logo.png +0 -0
  427. package/extensions/enact-evolve/skills/mined-investigate-loop/SKILL.md +0 -68
  428. package/extensions/enact-evolve/skills/session-analysis/SKILL.md +0 -98
  429. package/extensions/enact-evolve/skills/session-analysis/scripts/run-evolve-analysis.sh +0 -343
  430. package/extensions/enact-factory/.agents/plugin.json +0 -49
  431. package/extensions/enact-factory/.mcp.json +0 -8
  432. package/extensions/enact-factory/agents/architect.toml +0 -34
  433. package/extensions/enact-factory/agents/code-reviewer.toml +0 -33
  434. package/extensions/enact-factory/agents/critic.toml +0 -39
  435. package/extensions/enact-factory/agents/executor.toml +0 -26
  436. package/extensions/enact-factory/agents/explore.toml +0 -25
  437. package/extensions/enact-factory/agents/planner.toml +0 -26
  438. package/extensions/enact-factory/agents/verifier.toml +0 -33
  439. package/extensions/enact-factory/assets/icon.png +0 -0
  440. package/extensions/enact-factory/assets/logo.png +0 -0
  441. package/extensions/enact-factory/skills/advisor/SKILL.md +0 -82
  442. package/extensions/enact-factory/skills/ai-slop-cleaner/SKILL.md +0 -57
  443. package/extensions/enact-factory/skills/autonomous-runner/SKILL.md +0 -353
  444. package/extensions/enact-factory/skills/azdo-ci-strategy/SKILL.md +0 -309
  445. package/extensions/enact-factory/skills/azdo-ci-strategy/references/build-failures.md +0 -60
  446. package/extensions/enact-factory/skills/azdo-ci-strategy/references/cli-reference.md +0 -87
  447. package/extensions/enact-factory/skills/azdo-ci-strategy/references/policies-and-pipelines.md +0 -132
  448. package/extensions/enact-factory/skills/azdo-ci-strategy/references/troubleshooting.md +0 -53
  449. package/extensions/enact-factory/skills/cmux-leader/SKILL.md +0 -74
  450. package/extensions/enact-factory/skills/cmux-send/SKILL.md +0 -50
  451. package/extensions/enact-factory/skills/committee/SKILL.md +0 -80
  452. package/extensions/enact-factory/skills/deep-interview/SKILL.md +0 -68
  453. package/extensions/enact-factory/skills/drive-loop/SKILL.md +0 -394
  454. package/extensions/enact-factory/skills/drive-loop/references/contract-schema.md +0 -127
  455. package/extensions/enact-factory/skills/handoff/SKILL.md +0 -75
  456. package/extensions/enact-factory/skills/hyperplan/SKILL.md +0 -59
  457. package/extensions/enact-factory/skills/looplan/SKILL.md +0 -120
  458. package/extensions/enact-factory/skills/plan/SKILL.md +0 -103
  459. package/extensions/enact-factory/skills/remove-deadcode/SKILL.md +0 -46
  460. package/extensions/enact-factory/skills/research/SKILL.md +0 -83
  461. package/extensions/enact-factory/skills/review/SKILL.md +0 -67
  462. package/extensions/enact-factory/skills/security-research/SKILL.md +0 -57
  463. package/extensions/enact-factory/skills/tdd/SKILL.md +0 -62
  464. package/extensions/enact-factory/skills/testing-strategy/SKILL.md +0 -172
  465. package/extensions/enact-factory/skills/trace/SKILL.md +0 -42
  466. package/extensions/enact-factory/skills/ultraqa/SKILL.md +0 -85
  467. package/extensions/enact-factory/skills/work-with-workitem/SKILL.md +0 -56
  468. package/extensions/enact-factory/skills/workitem-triage/SKILL.md +0 -42
  469. package/extensions/enact-wiki/.agents/plugin.json +0 -43
  470. package/extensions/enact-wiki/.mcp.json +0 -15
  471. package/extensions/enact-wiki/README.md +0 -44
  472. package/extensions/enact-wiki/assets/icon.png +0 -0
  473. package/extensions/enact-wiki/assets/logo.png +0 -0
  474. package/extensions/enact-wiki/skills/document-parser/SKILL.md +0 -17
  475. package/extensions/enact-wiki/skills/document-parser/scripts/parse.sh +0 -60
  476. package/extensions/enact-wiki/skills/document-parser/skill.json +0 -9
  477. package/extensions/enact-wiki/skills/enact-wiki/SKILL.md +0 -30
  478. package/extensions/enact-wiki/skills/enact-wiki/references/ingest.md +0 -62
  479. package/extensions/enact-wiki/skills/enact-wiki/references/manage.md +0 -34
  480. package/extensions/enact-wiki/skills/enact-wiki/references/query.md +0 -59
  481. package/extensions/enact-wiki/skills/search-lab/SKILL.md +0 -57
  482. package/extensions/enact-wiki/skills/search-lab/scripts/analyze.ts +0 -23
  483. package/extensions/enact-wiki/skills/wiki/SKILL.md +0 -42
  484. package/extensions/net-revenue-management/.agents/plugin.json +0 -40
  485. package/extensions/net-revenue-management/.mcp.json +0 -9
  486. package/extensions/net-revenue-management/skills/net-revenue-risks/SKILL.md +0 -30
  487. package/extensions/net-revenue-management/skills/net-revenue-scenario/SKILL.md +0 -31
  488. package/extensions/plugin-dev/.agents/plugin.json +0 -41
  489. package/extensions/plugin-dev/agents/agent-creator.md +0 -199
  490. package/extensions/plugin-dev/agents/plugin-validator.md +0 -91
  491. package/extensions/plugin-dev/agents/skill-reviewer.md +0 -212
  492. package/extensions/plugin-dev/skills/agent-development/SKILL.md +0 -641
  493. package/extensions/plugin-dev/skills/agent-development/examples/agent-creation-prompt.md +0 -250
  494. package/extensions/plugin-dev/skills/agent-development/examples/complete-agent-examples.md +0 -461
  495. package/extensions/plugin-dev/skills/agent-development/references/advanced-agent-fields.md +0 -246
  496. package/extensions/plugin-dev/skills/agent-development/references/agent-creation-system-prompt.md +0 -216
  497. package/extensions/plugin-dev/skills/agent-development/references/permission-modes-rules.md +0 -226
  498. package/extensions/plugin-dev/skills/agent-development/references/system-prompt-design.md +0 -464
  499. package/extensions/plugin-dev/skills/agent-development/references/triggering-examples.md +0 -474
  500. package/extensions/plugin-dev/skills/agent-development/scripts/create-agent-skeleton.sh +0 -176
  501. package/extensions/plugin-dev/skills/agent-development/scripts/test-agent-trigger.sh +0 -227
  502. package/extensions/plugin-dev/skills/agent-development/scripts/validate-agent.sh +0 -227
  503. package/extensions/plugin-dev/skills/create-plugin/SKILL.md +0 -505
  504. package/extensions/plugin-dev/skills/hook-development/SKILL.md +0 -861
  505. package/extensions/plugin-dev/skills/hook-development/examples/load-context.sh +0 -55
  506. package/extensions/plugin-dev/skills/hook-development/examples/validate-bash.sh +0 -57
  507. package/extensions/plugin-dev/skills/hook-development/examples/validate-write.sh +0 -48
  508. package/extensions/plugin-dev/skills/hook-development/references/advanced.md +0 -871
  509. package/extensions/plugin-dev/skills/hook-development/references/hook-input-schemas.md +0 -145
  510. package/extensions/plugin-dev/skills/hook-development/references/migration.md +0 -392
  511. package/extensions/plugin-dev/skills/hook-development/references/patterns.md +0 -430
  512. package/extensions/plugin-dev/skills/hook-development/scripts/README.md +0 -181
  513. package/extensions/plugin-dev/skills/hook-development/scripts/hook-linter.sh +0 -153
  514. package/extensions/plugin-dev/skills/hook-development/scripts/test-hook.sh +0 -276
  515. package/extensions/plugin-dev/skills/hook-development/scripts/validate-hook-schema.sh +0 -159
  516. package/extensions/plugin-dev/skills/mcp-integration/SKILL.md +0 -775
  517. package/extensions/plugin-dev/skills/mcp-integration/examples/http-server.json +0 -20
  518. package/extensions/plugin-dev/skills/mcp-integration/examples/sse-server.json +0 -19
  519. package/extensions/plugin-dev/skills/mcp-integration/examples/stdio-server.json +0 -38
  520. package/extensions/plugin-dev/skills/mcp-integration/examples/ws-server.json +0 -26
  521. package/extensions/plugin-dev/skills/mcp-integration/references/authentication.md +0 -601
  522. package/extensions/plugin-dev/skills/mcp-integration/references/server-discovery.md +0 -190
  523. package/extensions/plugin-dev/skills/mcp-integration/references/server-types.md +0 -572
  524. package/extensions/plugin-dev/skills/mcp-integration/references/tool-usage.md +0 -623
  525. package/extensions/plugin-dev/skills/plugin-dev-guide/SKILL.md +0 -221
  526. package/extensions/plugin-dev/skills/plugin-structure/SKILL.md +0 -705
  527. package/extensions/plugin-dev/skills/plugin-structure/examples/advanced-plugin.md +0 -774
  528. package/extensions/plugin-dev/skills/plugin-structure/examples/minimal-plugin.md +0 -83
  529. package/extensions/plugin-dev/skills/plugin-structure/examples/standard-plugin.md +0 -611
  530. package/extensions/plugin-dev/skills/plugin-structure/references/advanced-topics.md +0 -289
  531. package/extensions/plugin-dev/skills/plugin-structure/references/component-patterns.md +0 -592
  532. package/extensions/plugin-dev/skills/plugin-structure/references/github-actions.md +0 -233
  533. package/extensions/plugin-dev/skills/plugin-structure/references/headless-ci-mode.md +0 -193
  534. package/extensions/plugin-dev/skills/plugin-structure/references/manifest-reference.md +0 -625
  535. package/extensions/plugin-dev/skills/plugin-structure/references/output-styles.md +0 -116
  536. package/extensions/plugin-dev/skills/skill-development/SKILL.md +0 -562
  537. package/extensions/plugin-dev/skills/skill-development/examples/complete-skill.md +0 -465
  538. package/extensions/plugin-dev/skills/skill-development/examples/frontmatter-templates.md +0 -167
  539. package/extensions/plugin-dev/skills/skill-development/examples/minimal-skill.md +0 -111
  540. package/extensions/plugin-dev/skills/skill-development/references/advanced-frontmatter.md +0 -225
  541. package/extensions/plugin-dev/skills/skill-development/references/commands-vs-skills.md +0 -39
  542. package/extensions/plugin-dev/skills/skill-development/references/skill-creation-workflow.md +0 -379
  543. package/extensions/plugin-dev/skills/skill-development/references/skill-creator-original.md +0 -210
  544. package/extensions/plugin-dev/skills/start/SKILL.md +0 -82
  545. package/scripts/check-hooks.mjs +0 -174
  546. package/scripts/check-principles.mjs +0 -116
  547. package/scripts/hooks/session-start-drift-check.mjs +0 -48
  548. package/scripts/install.sh +0 -70
  549. package/scripts/lib/auto-update.mjs +0 -75
  550. package/scripts/lib/bundle-hash.mjs +0 -137
  551. package/scripts/lib/hooks.mjs +0 -585
  552. package/scripts/lib/ledger.mjs +0 -163
  553. package/scripts/lib/migrate-artifacts.mjs +0 -144
  554. package/scripts/lib/outdated.mjs +0 -144
  555. package/scripts/lib/postinstall-offer.mjs +0 -83
  556. package/scripts/lib/principles.mjs +0 -109
  557. package/scripts/lib/provision-mcp.mjs +0 -16
  558. package/scripts/lib/resolve-plugin-root.mjs +0 -9
  559. package/scripts/lib/run-install.mjs +0 -500
  560. package/scripts/lib/run-prune.mjs +0 -94
  561. package/scripts/lib/run-uninstall.mjs +0 -244
  562. package/scripts/lib/run-update.mjs +0 -152
  563. package/scripts/lib/serve.mjs +0 -472
  564. package/scripts/lib/ups-router.mjs +0 -392
  565. package/scripts/postinstall.mjs +0 -101
  566. package/scripts/setup-enact-context.sh +0 -28
  567. package/scripts/version-bump.sh +0 -484
  568. package/web/assets/README.md +0 -111
  569. package/web/assets/logo-full.png +0 -0
  570. package/web/assets/logo-slim.png +0 -0
  571. package/web/assets/tokens/base.css +0 -45
  572. package/web/assets/tokens/colors.css +0 -248
  573. package/web/assets/tokens/effects.css +0 -24
  574. package/web/assets/tokens/fonts.css +0 -8
  575. package/web/assets/tokens/index.css +0 -18
  576. package/web/assets/tokens/spacing.css +0 -50
  577. package/web/index.html +0 -1188
@@ -1,30 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import { resolvePluginRoot } from "./lib/resolve-plugin-root.mjs";
3
2
  import { resolveBundlePath } from "./lib/resolve-bundle.mjs";
4
3
  import { listBundles } from "./lib/list-bundles.mjs";
5
4
  import { buildIndex } from "./lib/build-index.mjs";
6
5
  import { runValidate } from "./lib/run-validate.mjs";
7
6
  import { runSync } from "./lib/run-sync.mjs";
8
- import { runInstall } from "./lib/run-install.mjs";
9
- import { runUpdate } from "./lib/run-update.mjs";
10
- import { runPrune } from "./lib/run-prune.mjs";
11
- import { runUninstall } from "./lib/run-uninstall.mjs";
12
- import { readLedger } from "./lib/ledger.mjs";
13
- import { computeOutdated } from "./lib/outdated.mjs";
14
- import { migrateGlobalArtifacts } from "./lib/migrate-artifacts.mjs";
15
- import { startServer, resolveServePort } from "./lib/serve.mjs";
16
- import {
17
- setupPrinciples,
18
- removePrinciples,
19
- checkPrinciples,
20
- runDoctor,
21
- SUPPORTED_PRINCIPLES_SURFACES,
22
- } from "./lib/principles.mjs";
7
+ import { runRepoInstall, runRepoUninstall } from "./lib/run-repo-install.mjs";
8
+ import { runRepoDoctor } from "./lib/run-repo-doctor.mjs";
23
9
  import { dirname, join, resolve } from "node:path";
24
10
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
25
11
  import { fileURLToPath } from "node:url";
26
12
  import { cwd as processCwd } from "node:process";
27
- import { homedir } from "node:os";
28
13
  import { Ajv } from "ajv";
29
14
  import addFormatsModule from "ajv-formats";
30
15
 
@@ -36,56 +21,48 @@ const VERSION = PACKAGE_JSON.version ?? "unknown";
36
21
  const HELP = `enact-extensions — Enact multi-platform plugin manifests
37
22
  Version: ${VERSION}
38
23
 
24
+ enact-extensions manages REPO-LOCAL agent setup only. It never installs
25
+ anything into host global homes; global agent wiring belongs to enact-vps.
26
+ install/uninstall/doctor only accept plugin names listed in
27
+ bundled-extensions.json, which names the DEFAULT bundles. Any bundle resolvable
28
+ by name or path can be installed or uninstalled.
29
+
39
30
  Usage:
40
31
  enact-extensions list [dir] List available plugin bundles (default: bundled + cwd/extensions/)
41
32
  enact-extensions list [dir] --json Emit machine-readable JSON array
42
- enact-extensions log Print the install ledger (single global file), newest first
43
- enact-extensions log --json Emit the raw ledger array as JSON
44
- enact-extensions outdated Report freshness drift: installed vs canonical source (per plugin+surface)
45
- enact-extensions outdated --json Emit JSON array [{name, platform, scope, home, status, installedHash, currentHash, version}]
46
- enact-extensions migrate-artifacts [--dry-run] [--json]
47
- Rename legacy factory/loop markdown artifacts to YYMMDDHH-<slug>.md
48
- enact-extensions update <name> Refresh an outdated plugin on every surface it is installed on (ledger-driven)
49
- enact-extensions update --all Refresh EVERY outdated plugin/surface
50
- enact-extensions update <name> --dry-run Show what would be refreshed; change nothing
51
- enact-extensions update --all --dry-run Show every outdated surface that would be refreshed
52
- enact-extensions prune --platform all Remove ledger-installed plugin surfaces whose local source bundle is gone
53
- enact-extensions prune --platform shared Remove orphaned shared skill drops (explicit only)
54
- enact-extensions prune --dry-run Show orphaned surfaces that would be removed
55
33
  enact-extensions index [--out <path>] Generate a discovery index of all bundles (generated artifact, never committed)
56
34
  enact-extensions index --out - Print the discovery index JSON to stdout
57
35
  enact-extensions index --stdout Alias for --out -
58
36
  enact-extensions validate [path|name] Validate manifests (default: cwd)
59
37
  enact-extensions sync [path|name] Sync host manifests from .agents/plugin.json (default: cwd)
60
38
  enact-extensions sync [path|name] --name <id> Create .agents/plugin.json then sync (new plugin)
61
- enact-extensions install [path|name] Sync and install plugin into Codex-compatible homes (default: cwd)
62
- enact-extensions install [path|name] --platform claude Install to Claude Code
63
- enact-extensions install [path|name] --platform cursor Install to Cursor
64
- enact-extensions install [path|name] --platform enact Install to Enact (Codex fork)
65
- enact-extensions install [path|name] --platform codex Install to Codex (explicit)
66
- enact-extensions install [path|name] --platform shared Install skills to host-neutral .agents/skills/
67
- enact-extensions install [path|name] --platform all Install to every plugin platform (codex, claude, cursor, enact)
68
- enact-extensions install [path|name] --platform claude,cursor Install to a subset of platforms
69
- enact-extensions install [path|name] --global Install into the default agent home (default)
70
- enact-extensions install [path|name] --local Install into a project home under cwd (./.codex, ...)
71
- enact-extensions uninstall [path|name] Uninstall plugin from Codex-compatible homes (default: enact)
72
- enact-extensions uninstall [path|name] --platform claude Uninstall from Claude Code
73
- enact-extensions uninstall [path|name] --platform cursor Uninstall from Cursor
74
- enact-extensions uninstall [path|name] --platform enact Uninstall from Enact (Codex fork)
75
- enact-extensions uninstall [path|name] --platform codex Uninstall from Codex (explicit)
76
- enact-extensions uninstall [path|name] --platform shared Remove skills from host-neutral .agents/skills/
77
- enact-extensions uninstall [path|name] --platform all Uninstall from every plugin platform
78
- enact-extensions uninstall [path|name] --platform claude,cursor Uninstall from a subset of platforms
79
- enact-extensions serve [--port N] [--prod] [--host 127.0.0.1] [--open] Start the localhost management UI + API (dev 43217 / prod 53217)
80
- enact-extensions principles setup [--surfaces <list>|--all] [--remove] [--local]
81
- Inject (or remove) the enact-core operating-principles block
82
- into host agent files (CLAUDE.md / AGENTS.md).
83
- enact-extensions principles check [--surfaces <list>|--all] [--local] [--json]
84
- Report principles block drift per surface (present/missing/stale).
85
- Use principles setup or doctor --fix to remediate. Not npm run check:principles.
86
- enact-extensions doctor [--fix] [--surfaces <list>|--all] [--local] [--json]
87
- Check operating-principles block drift per surface; --fix applies blocks.
88
- enact-extensions -v | --version Print version and exit
39
+ enact-extensions install <name> --repo <path> [--host claude,codex,cursor,kimi,opencode] [--force]
40
+ Install a bundle INTO a git repo as committed, relative files
41
+ (per-host project standard; state in .agents/<name>.lock.json)
42
+ enact-extensions install <name> --repo <path> --dry-run Print exactly what install would write/merge, per
43
+ file (action + reason), and exit with the same success/failure
44
+ the real run would have. Touches nothing.
45
+ enact-extensions uninstall <name> --repo <path> [--purge] [--force]
46
+ Remove exactly what the repo lock records (--purge also removes
47
+ the [skills] block install wrote to enact-config.toml, and the
48
+ file itself if install created it and only version = 1 remains)
49
+ enact-extensions uninstall <name> --repo <path> --dry-run [--purge]
50
+ Print exactly what uninstall would remove/restore, per file
51
+ (action + reason), and exit with the same success/failure the
52
+ real run would have. Touches nothing.
53
+ enact-extensions doctor enact-repo --repo <path> [--json]
54
+ Read-only health check for a repo-local enact-repo install:
55
+ installed?, version vs bundle (outdated?), lock integrity
56
+ (missing/drifted managed files), per-host status (claude,
57
+ codex incl. trust_level, cursor, kimi incl. workspace-trust,
58
+ opencode), required global binaries on PATH, the
59
+ enact-config.toml marker ([skills] present; a stale
60
+ .agents/enact-repo.toml is reported), an "enact-hook doctor
61
+ --repo" passthrough when available, and the enact-hook
62
+ deny/activity log paths, existence, row counts, and (deny
63
+ log) the last 5 rows. Never writes anything; exits non-zero
64
+ only when a hard requirement fails.
65
+ enact-extensions -v | --version Print version and exit
89
66
 
90
67
  Options:
91
68
  path|name Plugin root path, or a bare plugin name resolved from bundled extensions.
@@ -93,65 +70,77 @@ Options:
93
70
  --out <path> (index only) Output file path. Use - or --stdout to print to stdout.
94
71
  Default: generated/index.json under the package root.
95
72
  --stdout (index only) Alias for --out -.
96
- --json (list only) Emit a JSON array to stdout instead of a human table.
97
- --platform <name> Target platform: codex (default), claude, cursor, enact, shared.
98
- Use "all" to install to every plugin platform, or a comma-separated list
99
- (e.g. "claude,cursor") to install to a named subset.
100
- --global Install into the agent's default home (default)
101
- --local Install into a project-scoped home under the current dir
102
- --codex-home <path> Install only into the given Codex-compatible home
103
- --enact-home <path> Target a specific local Enact home (default: ~/.enact/agent)
104
- --claude-home <path> Target a specific local Claude home (default: ~/.claude)
105
- --cursor-home <path> Target a specific local Cursor home (default: ~/.cursor)
106
- --shared-home <path> Base dir for shared install (skills land at <path>/.agents/skills/)
107
- --marketplace <name> Marketplace name (default: enact-os-plugins)
108
- --no-enable Install files without enabling the Codex/Enact plugin
109
- --skip-sync Install current manifests without regenerating them
110
- --no-provision Skip auto-provisioning the bundle's MCP-server packages.
111
- By default, install resolves each declared MCP server
112
- (.mcp.json) and provisions its package: uvx → uv tool
113
- install, npx → npm install -g, pipx → pipx install,
114
- pip/pip3 → pip install. Best-effort; never fails install.
73
+ --json (list/doctor) Emit JSON to stdout instead of human output.
74
+ --name <id> (sync only) Plugin name for a new .agents/plugin.json.
75
+ --repo <path> (install/uninstall/doctor) Target the git repository root at <path>.
76
+ Never writes under $HOME; never writes absolute paths.
77
+ --host <list> (install --repo) Hosts to install for: claude,codex,cursor,kimi,opencode
78
+ (default: every repo host the bundle targets).
79
+ --dry-run (install/uninstall --repo) Print exactly what would change, per file, and
80
+ exit with the same success/failure the real run would have. Writes nothing.
81
+ --force (install/uninstall --repo) Overwrite user-edited managed content and take over
82
+ same-named entries not owned by the bundle. Never overwrites a user skill dir.
83
+ --purge (uninstall --repo) Also remove the [skills] block install wrote to enact-config.toml.
115
84
 
116
85
  Name resolution (bare plugin names):
117
86
  When a bare name (no "/" in it) is given, it is resolved in this order:
118
- 1. <this-package-root>/extensions/<name> (bundled extensions in this repo)
87
+ 1. <this-package-root>/extensions/<name> (bundled extensions in this package)
119
88
  2. <cwd>/extensions/<name> (extensions in a sibling product repo)
120
89
  3. <npm-global-root>/@amsterdamdatalabs/enact-extensions/extensions/<name>
121
90
 
122
- Multi-platform notes:
123
- - Platforms are installed sequentially in deterministic order: codex, claude, cursor, enact.
124
- - Per-platform --<platform>-home flags apply to their respective platform in a multi-target run.
125
- - If any platform fails, the others still proceed; a non-zero exit is returned and the summary
126
- of succeeded/failed platforms is printed to stderr.
127
-
128
91
  Examples:
129
92
  enact-extensions list
130
93
  enact-extensions list --json
131
- enact-extensions list /path/to/extensions
132
- enact-extensions index Generate generated/index.json (gitignored, local discovery artifact)
133
94
  enact-extensions index --out - Print discovery index JSON to stdout (pipe-friendly)
134
- enact-extensions index --stdout Same as --out -
135
- enact-extensions index --out /tmp/my-index.json
136
- cd extensions/enact-factory && enact-extensions validate
137
- enact-extensions sync . --name my-plugin
138
- enact-extensions install net-revenue-management --platform enact --global
139
- enact-extensions install net-revenue-management --platform enact --local
140
- enact-extensions install extensions/net-revenue-management --platform enact --global
141
- enact-extensions install enact-factory --platform claude
142
- enact-extensions install enact-factory --platform cursor
143
- enact-extensions install net-revenue-management --platform shared
144
- enact-extensions install net-revenue-management --platform shared --local
145
- enact-extensions install net-revenue-management --platform all
146
- enact-extensions install net-revenue-management --platform claude,cursor
147
- enact-extensions install net-revenue-management --platform all --enact-home /path/to/enact
95
+ cd extensions/enact-repo && enact-extensions validate
148
96
  enact-extensions validate extensions/plugin-dev
149
- enact-extensions validate plugin-dev
97
+ enact-extensions sync . --name my-plugin
98
+ enact-extensions install enact-repo --repo .
99
+ enact-extensions install enact-repo --repo ~/code/my-service --host claude,cursor
100
+ enact-extensions install enact-repo --repo . --dry-run Preview the plan; writes nothing
101
+ enact-extensions uninstall enact-repo --repo . --purge
102
+ enact-extensions uninstall enact-repo --repo . --dry-run Preview what would be removed/restored
103
+ enact-extensions doctor enact-repo --repo . Read-only health check
104
+ enact-extensions doctor enact-repo --repo . --json
150
105
  `;
151
106
 
107
+ const COMMANDS = new Set(["list", "index", "validate", "sync", "install", "uninstall", "doctor"]);
108
+ const REPO_USAGE_HINT =
109
+ "enact-extensions only performs repo-local installs: install|uninstall <name> --repo <path> " +
110
+ "[--host claude,codex,cursor,kimi,opencode]; doctor enact-repo --repo <path>. " +
111
+ "Global host installs were removed (global agent wiring belongs to enact-vps).";
112
+
113
+ /**
114
+ * Unwinds to the top of the module so node can exit on its own.
115
+ *
116
+ * `exit()` must not be used here: `process.stdout` is ASYNCHRONOUS
117
+ * when it is a pipe -- under a test harness, under CI, or whenever a user
118
+ * pipes output into a file or a pager -- and exiting discards whatever is
119
+ * still queued. `install --repo --dry-run` prints ~1500 lines, and calling
120
+ * exit on the next statement silently cut the tail off on Linux agents while
121
+ * appearing fine on a fast local flush.
122
+ */
123
+ class ExitSignal extends Error {
124
+ constructor(code) {
125
+ super(`exit ${code}`);
126
+ this.name = "ExitSignal";
127
+ this.code = code;
128
+ }
129
+ }
130
+
131
+ function exit(code) {
132
+ throw new ExitSignal(code);
133
+ }
134
+
135
+ function fail(message) {
136
+ console.error(message);
137
+ exit(1);
138
+ }
139
+
152
140
  function parseArgs(argv) {
153
141
  const positional = [];
154
142
  const options = {};
143
+ const unknown = [];
155
144
 
156
145
  for (let i = 0; i < argv.length; i++) {
157
146
  const arg = argv[i];
@@ -161,283 +150,170 @@ function parseArgs(argv) {
161
150
  options.out = "-";
162
151
  } else if (arg === "--name" && argv[i + 1]) {
163
152
  options.name = argv[++i];
164
- } else if (arg === "--codex-home" && argv[i + 1]) {
165
- options.codexHome = argv[++i];
166
- } else if (arg === "--marketplace" && argv[i + 1]) {
167
- options.marketplaceName = argv[++i];
168
- } else if (arg === "--no-enable") {
169
- options.enable = false;
170
- } else if (arg === "--skip-sync") {
171
- options.sync = false;
172
- } else if (arg === "--no-provision") {
173
- options.noProvision = true;
174
- } else if (arg === "--platform" && argv[i + 1]) {
175
- options.platform = argv[++i];
176
- } else if (arg === "--claude-home" && argv[i + 1]) {
177
- options.claudeHome = argv[++i];
178
- } else if (arg === "--cursor-home" && argv[i + 1]) {
179
- options.cursorHome = argv[++i];
180
- } else if (arg === "--enact-home" && argv[i + 1]) {
181
- options.enactHome = argv[++i];
182
- } else if (arg === "--shared-home" && argv[i + 1]) {
183
- options.sharedHome = argv[++i];
184
- } else if (arg === "--local") {
185
- options.scope = "local";
186
- } else if (arg === "--global") {
187
- options.scope = "global";
188
- } else if (arg === "--all") {
189
- options.all = true;
153
+ } else if (arg === "--repo" && argv[i + 1]) {
154
+ options.repo = argv[++i];
155
+ } else if (arg === "--host" && argv[i + 1]) {
156
+ options.host = argv[++i];
157
+ } else if (arg === "--force") {
158
+ options.force = true;
159
+ } else if (arg === "--purge") {
160
+ options.purge = true;
190
161
  } else if (arg === "--dry-run") {
191
162
  options.dryRun = true;
192
163
  } else if (arg === "--json") {
193
164
  options.json = true;
194
- } else if (arg === "--port" && argv[i + 1]) {
195
- options.port = parseInt(argv[++i], 10);
196
- } else if (arg === "--host" && argv[i + 1]) {
197
- options.host = argv[++i];
198
- } else if (arg === "--open") {
199
- options.open = true;
200
- } else if (arg === "--prod") {
201
- options.prod = true;
202
- } else if (arg === "--surfaces" && argv[i + 1]) {
203
- // Comma-separated list of surfaces: claude,codex,cursor,enact
204
- options.surfaces = argv[++i].split(",").map((s) => s.trim()).filter(Boolean);
205
- } else if (arg === "--remove") {
206
- options.remove = true;
207
- } else if (arg === "--fix") {
208
- options.fix = true;
209
165
  } else if (arg === "-h" || arg === "--help") {
210
166
  positional.push("help");
211
- } else if (!arg.startsWith("-")) {
167
+ } else if (arg.startsWith("-")) {
168
+ unknown.push(arg);
169
+ } else {
212
170
  positional.push(arg);
213
171
  }
214
172
  }
215
173
 
216
- return { command: positional[0], path: positional[1], options };
174
+ return { command: positional[0], path: positional[1], options, unknown };
217
175
  }
218
176
 
177
+ try {
219
178
  const rawArgv = process.argv.slice(2);
220
179
  if (rawArgv.length === 1 && (rawArgv[0] === "-v" || rawArgv[0] === "--version")) {
221
180
  console.log(`enact-extensions ${VERSION}`);
222
- process.exit(0);
181
+ exit(0);
223
182
  }
224
183
 
225
- const { command, path, options } = parseArgs(rawArgv);
184
+ const { command, path, options, unknown } = parseArgs(rawArgv);
226
185
 
227
186
  if (!command || command === "help") {
228
187
  console.log(HELP);
229
- process.exit(command ? 0 : 1);
188
+ exit(command ? 0 : 1);
230
189
  }
231
190
 
232
- // ---------------------------------------------------------------------------
233
- // `hooks` command — register or remove the session-start drift-check hook.
234
- //
235
- // Surfaces: claude, codex, cursor, enact
236
- // Registration is idempotent and reversible.
237
- // ---------------------------------------------------------------------------
238
- // ---------------------------------------------------------------------------
239
- // `principles` command — inject or check operating-principles blocks in host files.
240
- //
241
- // Surfaces: claude, codex, cursor, enact
242
- // ---------------------------------------------------------------------------
243
- if (command === "principles") {
244
- const subCommand = path ?? "setup";
245
-
246
- if (subCommand !== "setup" && subCommand !== "check") {
247
- process.stderr.write(
248
- `[enact-extensions principles] Unknown sub-command: ${subCommand}. Use 'setup' or 'check'.\n`,
249
- );
250
- process.exit(1);
251
- }
191
+ if (!COMMANDS.has(command)) {
192
+ console.error(`Unknown command: ${command}\n\n${REPO_USAGE_HINT}\nRun enact-extensions --help for usage.`);
193
+ exit(1);
194
+ }
252
195
 
253
- const isRemove = options.remove ?? false;
254
- const isLocal = options.scope === "local";
255
- const cwd = processCwd();
256
- const surfacesList = SUPPORTED_PRINCIPLES_SURFACES;
196
+ if (unknown.length > 0) {
197
+ fail(`Unknown option(s) for ${command}: ${unknown.join(", ")}\n${REPO_USAGE_HINT}`);
198
+ }
257
199
 
258
- let surfaces = [];
259
- if (options.all) {
260
- surfaces = [...surfacesList];
261
- } else if (options.surfaces && options.surfaces.length > 0) {
262
- const invalid = options.surfaces.filter((s) => !surfacesList.includes(s));
263
- if (invalid.length > 0) {
264
- process.stderr.write(
265
- `[enact-extensions principles] Unknown surface(s): ${invalid.join(", ")}. Valid: ${surfacesList.join(", ")}\n`,
266
- );
267
- process.exit(1);
268
- }
269
- surfaces = options.surfaces;
270
- } else if (subCommand === "setup" && process.stdin.isTTY) {
271
- const { createInterface } = await import("node:readline");
272
- const rl = createInterface({ input: process.stdin, output: process.stdout });
273
- const question = (prompt) => new Promise((resolve) => rl.question(prompt, resolve));
200
+ if ((command === "install" || command === "uninstall") && !options.repo) {
201
+ fail(`${command} requires --repo <path>.\n${REPO_USAGE_HINT}`);
202
+ }
274
203
 
275
- process.stdout.write(`\nenact-extensions principles setup — interactive surface picker\n`);
276
- process.stdout.write(`Available surfaces: ${surfacesList.map((s, i) => `${i + 1}. ${s}`).join(", ")}\n`);
277
- process.stdout.write(`Enter surface names or numbers (comma-separated), or 'all':\n`);
204
+ if (!["install", "uninstall"].includes(command) && (options.force || options.purge || options.host || options.dryRun)) {
205
+ fail("--host/--force/--purge/--dry-run only apply to install|uninstall <name> --repo <path>");
206
+ }
278
207
 
279
- const answer = await question("> ");
280
- rl.close();
208
+ function printRepoDoctorReport(report) {
209
+ const ok = (b) => (b ? "OK" : "FAIL");
210
+ console.log(`[doctor enact-repo] repo: ${report.repo}`);
211
+ console.log(` installed: ${report.installed ? "yes" : "NO"}`);
212
+ if (!report.installed) {
213
+ for (const p of report.problems) console.error(` problem: ${p}`);
214
+ return;
215
+ }
216
+ console.log(
217
+ ` version: installed=${report.version.installed} bundle=${report.version.bundle ?? "(unknown)"} outdated=${report.version.outdated ? "YES" : "no"}`,
218
+ );
219
+ if (report.version.contentOutdated.length > 0) {
220
+ console.log(` content drifted from current bundle (${report.version.contentOutdated.length}): ${report.version.contentOutdated.join(", ")}`);
221
+ }
222
+ if (report.version.note) console.log(` note: ${report.version.note}`);
281
223
 
282
- if (answer.trim().toLowerCase() === "all") {
283
- surfaces = [...surfacesList];
284
- } else {
285
- surfaces = answer
286
- .split(",")
287
- .map((s) => s.trim())
288
- .filter(Boolean)
289
- .map((s) => {
290
- const idx = parseInt(s, 10);
291
- if (!isNaN(idx) && idx >= 1 && idx <= surfacesList.length) {
292
- return surfacesList[idx - 1];
293
- }
294
- return s.toLowerCase();
295
- })
296
- .filter((s) => surfacesList.includes(s));
224
+ console.log(` lock integrity: ${ok(report.lock.valid)}`);
225
+ if (!report.lock.valid) {
226
+ if (report.lock.missingFiles.length) console.log(` missing: ${report.lock.missingFiles.join(", ")}`);
227
+ if (report.lock.driftedFiles.length) console.log(` drifted: ${report.lock.driftedFiles.join(", ")}`);
228
+ if (report.lock.jsonIssues.length) console.log(` json: ${report.lock.jsonIssues.join(", ")}`);
229
+ if (report.lock.tomlIssues.length) console.log(` toml: ${report.lock.tomlIssues.join(", ")}`);
230
+ }
297
231
 
298
- if (surfaces.length === 0) {
299
- process.stderr.write(`[enact-extensions principles] No valid surfaces selected. Exiting.\n`);
300
- process.exit(0);
301
- }
232
+ for (const [host, info] of Object.entries(report.hosts)) {
233
+ console.log(` host ${host}: targeted=${info.targeted} present=${info.targeted ? ok(info.present) : "n/a"}`);
234
+ if (info.note) console.log(` ${info.note}`);
235
+ if (info.trust) {
236
+ console.log(` codex trust_level: ${info.trust.trustLevel ?? "(none)"}${info.trust.note ? ` -- ${info.trust.note}` : ""}`);
237
+ }
238
+ if (info.globalHooksNote) console.log(` ${info.globalHooksNote}`);
239
+ if (info.workspaceTrust) {
240
+ console.log(
241
+ ` kimi workspace trust: ${info.workspaceTrust.trusted ? "TRUSTED" : "NOT TRUSTED"}${info.workspaceTrust.note ? ` -- ${info.workspaceTrust.note}` : ""}`,
242
+ );
243
+ }
244
+ if (host === "opencode" && info.targeted) {
245
+ console.log(
246
+ ` generated from current bundle: ${info.generatedFromCurrentBundle === false ? "NO (stale)" : info.generatedFromCurrentBundle === true ? "yes" : "n/a"}`,
247
+ );
302
248
  }
303
- } else {
304
- process.stdout.write(
305
- `[enact-extensions principles] No surface specified. Run with --surfaces or --all:\n` +
306
- ` enact-extensions principles ${subCommand} --surfaces claude,codex\n` +
307
- ` enact-extensions principles ${subCommand} --all\n`,
308
- );
309
- process.exit(0);
310
249
  }
311
250
 
312
- const principleOpts = {
313
- claudeHome: options.claudeHome,
314
- codexHome: options.codexHome,
315
- cursorHome: options.cursorHome,
316
- enactHome: options.enactHome,
317
- local: isLocal,
318
- cwd,
319
- };
251
+ console.log(" binaries:");
252
+ for (const [bin, info] of Object.entries(report.binaries)) {
253
+ console.log(` ${bin}: ${info.found ? `${info.version ?? "(unknown version)"} @ ${info.path}` : "NOT FOUND"}`);
254
+ }
320
255
 
321
- let exitCode = 0;
256
+ console.log(` marker (${report.marker.path}): ${ok(report.marker.valid)}${report.marker.note ? ` -- ${report.marker.note}` : ""}`);
257
+ if (report.staleMarker.present) console.log(` stale marker (${report.staleMarker.path}): ${report.staleMarker.note}`);
322
258
 
323
- if (subCommand === "check") {
324
- const rows = [];
325
- for (const surface of surfaces) {
326
- try {
327
- const res = checkPrinciples(surface, principleOpts);
328
- rows.push(res);
329
- if (!options.json) {
330
- process.stdout.write(
331
- ` [principles] ${surface}: ${res.status} → ${res.path}\n`,
332
- );
333
- }
334
- } catch (err) {
335
- const message = err instanceof Error ? err.message : String(err);
336
- rows.push({ surface, path: "", status: "error", error: message });
337
- process.stderr.write(` [principles] ${surface}: error — ${message}\n`);
338
- }
259
+ console.log(` enact-hook doctor --repo: ${report.hookDoctor.available ? `exit ${report.hookDoctor.exitCode}` : `not available -- ${report.hookDoctor.note}`}`);
260
+ if (report.hookDoctor.available && report.hookDoctor.stdout) {
261
+ for (const line of report.hookDoctor.stdout.trim().split("\n")) {
262
+ if (line) console.log(` ${line}`);
339
263
  }
340
-
341
- if (options.json) {
342
- console.log(JSON.stringify(rows, null, 2));
343
- }
344
-
345
- process.exit(0);
346
264
  }
347
265
 
348
- for (const surface of surfaces) {
349
- try {
350
- const res = isRemove
351
- ? removePrinciples(surface, principleOpts)
352
- : setupPrinciples(surface, principleOpts);
353
-
354
- if (res.result === "applied") {
355
- process.stdout.write(
356
- ` [principles] ${surface}: applied (${res.action}) → ${res.path}\n`,
357
- );
358
- } else if (res.result === "already_present") {
359
- process.stdout.write(
360
- ` [principles] ${surface}: already present (noop) → ${res.path}\n`,
361
- );
362
- } else if (res.result === "removed") {
363
- process.stdout.write(` [principles] ${surface}: removed → ${res.path}\n`);
364
- } else if (res.result === "not_found") {
365
- process.stdout.write(
366
- ` [principles] ${surface}: not found (nothing to remove) → ${res.path}\n`,
367
- );
266
+ if (report.hookLogs) {
267
+ const { denyLog, activityLog } = report.hookLogs;
268
+ console.log(
269
+ ` hook logs: ${denyLog.path} ${denyLog.exists ? `(${denyLog.rowCount} row(s))` : "(not present)"}; ${activityLog.path} ${activityLog.exists ? `(${activityLog.rowCount} row(s))` : "(not present)"}`,
270
+ );
271
+ if (denyLog.lastRows.length > 0) {
272
+ console.log(` last ${denyLog.lastRows.length} deny row(s):`);
273
+ for (const row of denyLog.lastRows) {
274
+ console.log(` ${row.timestamp} ${row.surface} ${row.reason_id} ${row.command} ${row.agent_message}`);
368
275
  }
369
- } catch (err) {
370
- exitCode = 1;
371
- const message = err instanceof Error ? err.message : String(err);
372
- process.stderr.write(` [principles] ${surface}: error — ${message}\n`);
373
276
  }
374
277
  }
375
278
 
376
- process.exit(exitCode);
279
+ if (report.problems.length > 0) {
280
+ console.error(`[doctor enact-repo] ${report.problems.length} problem(s):`);
281
+ for (const p of report.problems) console.error(` - ${p}`);
282
+ } else {
283
+ console.log("[doctor enact-repo] all hard requirements OK");
284
+ }
377
285
  }
378
286
 
379
287
  // ---------------------------------------------------------------------------
380
- // `doctor` command — check (and optionally fix) operating-principles drift.
381
- //
382
- // Surfaces: claude, codex, cursor, enact (defaults to all when omitted)
288
+ // `doctor <plugin> --repo <path>` — read-only repo-local health check.
289
+ // Any plugin, bundled or not: bundled-extensions.json is the DEFAULT set, not
290
+ // an allow-list. `<plugin>` is a bundled name or an explicit path, resolved
291
+ // exactly like install/uninstall.
383
292
  // ---------------------------------------------------------------------------
384
293
  if (command === "doctor") {
385
- const isFix = options.fix ?? false;
386
- const isLocal = options.scope === "local";
387
- const cwd = processCwd();
388
- const surfacesList = SUPPORTED_PRINCIPLES_SURFACES;
389
-
390
- let surfaces = [];
391
- if (options.all || !options.surfaces || options.surfaces.length === 0) {
392
- surfaces = [...surfacesList];
393
- } else {
394
- const invalid = options.surfaces.filter((s) => !surfacesList.includes(s));
395
- if (invalid.length > 0) {
396
- process.stderr.write(
397
- `[enact-extensions doctor] Unknown surface(s): ${invalid.join(", ")}. Valid: ${surfacesList.join(", ")}\n`,
398
- );
399
- process.exit(1);
400
- }
401
- surfaces = options.surfaces;
294
+ if (!path || !options.repo) {
295
+ fail(`doctor requires: doctor <plugin> --repo <path> [--json]\n${REPO_USAGE_HINT}`);
402
296
  }
403
-
404
- const principleOpts = {
405
- claudeHome: options.claudeHome,
406
- codexHome: options.codexHome,
407
- cursorHome: options.cursorHome,
408
- enactHome: options.enactHome,
409
- local: isLocal,
410
- cwd,
411
- fix: isFix,
412
- };
413
-
414
- const { rows, exitCode } = runDoctor(surfaces, principleOpts);
415
-
416
- if (!options.json) {
417
- for (const row of rows) {
418
- if (row.error) {
419
- process.stderr.write(` [doctor] ${row.surface}: error — ${row.error}\n`);
420
- continue;
421
- }
422
- if (isFix) {
423
- const note = row.result === "already_present"
424
- ? "already present (noop)"
425
- : `fixed (${row.action ?? row.result})`;
426
- process.stdout.write(` [doctor] ${row.surface}: ${row.status} — ${note} → ${row.path}\n`);
427
- } else {
428
- process.stdout.write(` [doctor] ${row.surface}: ${row.status} → ${row.path}\n`);
429
- }
430
- }
431
- if (!isFix && exitCode !== 0) {
432
- process.stderr.write(
433
- `[enact-extensions doctor] Drift detected. Fix with: enact-extensions doctor --fix --all\n`,
434
- );
435
- }
297
+ let pluginRoot;
298
+ try {
299
+ pluginRoot = resolveBundlePath(path);
300
+ } catch (err) {
301
+ console.error(err instanceof Error ? err.message : String(err));
302
+ exit(1);
303
+ }
304
+ let report;
305
+ try {
306
+ report = runRepoDoctor(pluginRoot, { repo: options.repo });
307
+ } catch (err) {
308
+ console.error(err instanceof Error ? err.message : String(err));
309
+ exit(1);
310
+ }
311
+ if (options.json) {
312
+ console.log(JSON.stringify(report, null, 2));
436
313
  } else {
437
- console.log(JSON.stringify(rows, null, 2));
314
+ printRepoDoctorReport(report);
438
315
  }
439
-
440
- process.exit(exitCode);
316
+ exit(report.exitCode);
441
317
  }
442
318
 
443
319
  // ---------------------------------------------------------------------------
@@ -465,7 +341,7 @@ if (command === "list") {
465
341
 
466
342
  if (options.json) {
467
343
  console.log(JSON.stringify(entries, null, 2));
468
- process.exit(0);
344
+ exit(0);
469
345
  }
470
346
 
471
347
  // Human-readable table.
@@ -477,7 +353,7 @@ if (command === "list") {
477
353
 
478
354
  if (entries.length === 0) {
479
355
  console.log("No plugin bundles found.");
480
- process.exit(0);
356
+ exit(0);
481
357
  }
482
358
 
483
359
  // Header.
@@ -511,7 +387,7 @@ if (command === "list") {
511
387
  }
512
388
  console.log(hr);
513
389
  console.log(`${entries.length} bundle${entries.length === 1 ? "" : "s"} found.`);
514
- process.exit(0);
390
+ exit(0);
515
391
  }
516
392
 
517
393
  // ---------------------------------------------------------------------------
@@ -539,7 +415,7 @@ if (command === "index") {
539
415
  index = buildIndex(roots, { now: new Date().toISOString(), packageRoot: PACKAGE_ROOT });
540
416
  } catch (err) {
541
417
  console.error(`[enact-extensions index] Failed to build index: ${err instanceof Error ? err.message : String(err)}`);
542
- process.exit(1);
418
+ exit(1);
543
419
  }
544
420
 
545
421
  // Validate against spec/index.json before writing.
@@ -549,7 +425,7 @@ if (command === "index") {
549
425
  schema = JSON.parse(readFileSync(schemaPath, "utf8"));
550
426
  } catch (err) {
551
427
  console.error(`[enact-extensions index] Cannot read schema ${schemaPath}: ${err instanceof Error ? err.message : String(err)}`);
552
- process.exit(1);
428
+ exit(1);
553
429
  }
554
430
 
555
431
  const addFormats = addFormatsModule.default ?? addFormatsModule;
@@ -560,7 +436,7 @@ if (command === "index") {
560
436
  if (!valid) {
561
437
  const errs = (validate.errors ?? []).map((e) => ` ${e.instancePath || "/"}: ${e.message}`).join("\n");
562
438
  console.error(`[enact-extensions index] Generated index failed schema validation:\n${errs}`);
563
- process.exit(1);
439
+ exit(1);
564
440
  }
565
441
 
566
442
  const json = JSON.stringify(index, null, 2);
@@ -584,561 +460,67 @@ if (command === "index") {
584
460
  process.stderr.write(`[enact-extensions index] Wrote ${index.count} plugin${index.count === 1 ? "" : "s"} to ${outPath}\n`);
585
461
  }
586
462
 
587
- process.exit(0);
588
- }
589
-
590
- // ---------------------------------------------------------------------------
591
- // `log` command — print the install ledger (single global file), newest first.
592
- //
593
- // Human table to stdout (chrome to stderr) or `--json` (raw ledger array).
594
- // Reading a missing ledger yields an empty list — never an error.
595
- // ---------------------------------------------------------------------------
596
- if (command === "log") {
597
- const entries = readLedger();
598
- // Most-recent-first.
599
- const sorted = [...entries].sort((a, b) =>
600
- String(b.ts ?? "").localeCompare(String(a.ts ?? "")),
601
- );
602
-
603
- if (options.json) {
604
- process.stdout.write(JSON.stringify(sorted, null, 2) + "\n");
605
- process.exit(0);
606
- }
607
-
608
- if (sorted.length === 0) {
609
- process.stderr.write("No install ledger entries found.\n");
610
- process.exit(0);
611
- }
612
-
613
- const COL_TS = 24;
614
- const COL_ACT = 10;
615
- const COL_NAME = 28;
616
- const COL_PLAT = 8;
617
- const COL_SCOPE = 7;
618
- function padR(str, n) { return String(str ?? "").padEnd(n).slice(0, n); }
619
-
620
- const hr = "─".repeat(COL_TS + COL_ACT + COL_NAME + COL_PLAT + COL_SCOPE + 4 + 40);
621
- console.log(hr);
622
- console.log(
623
- padR("Timestamp", COL_TS) + " " +
624
- padR("Action", COL_ACT) + " " +
625
- padR("Name", COL_NAME) + " " +
626
- padR("Platform", COL_PLAT) + " " +
627
- padR("Scope", COL_SCOPE) + " " +
628
- "Home",
629
- );
630
- console.log(hr);
631
- for (const e of sorted) {
632
- console.log(
633
- padR(e.ts, COL_TS) + " " +
634
- padR(e.action, COL_ACT) + " " +
635
- padR(e.name, COL_NAME) + " " +
636
- padR(e.platform, COL_PLAT) + " " +
637
- padR(e.scope, COL_SCOPE) + " " +
638
- String(e.home ?? ""),
639
- );
640
- }
641
- console.log(hr);
642
- process.stderr.write(`${sorted.length} ledger entr${sorted.length === 1 ? "y" : "ies"}.\n`);
643
- process.exit(0);
644
- }
645
-
646
- // ---------------------------------------------------------------------------
647
- // `outdated` command — report drift between installed plugins and canonical source.
648
- //
649
- // Classifies each installed (plugin, platform) surface as:
650
- // fresh → installed hash matches canonical source hash
651
- // outdated → hash mismatch (or recorded hash missing), needs re-install
652
- // orphaned → canonical source does not exist (can't refresh)
653
- //
654
- // Exit code: always 0 (it's a report, not a failure gate).
655
- // Human chrome → stderr; --json stdout is always pure JSON.
656
- // ---------------------------------------------------------------------------
657
- if (command === "outdated") {
658
- let entries;
659
- try {
660
- entries = computeOutdated({ cwd: processCwd() });
661
- } catch (err) {
662
- process.stderr.write(
663
- `[enact-extensions outdated] Error: ${err instanceof Error ? err.message : String(err)}\n`,
664
- );
665
- process.exit(1);
666
- }
667
-
668
- if (options.json) {
669
- process.stdout.write(JSON.stringify(entries, null, 2) + "\n");
670
- process.exit(0);
671
- }
672
-
673
- // Human-readable table.
674
- if (entries.length === 0) {
675
- process.stderr.write("No installed plugins found in the ledger.\n");
676
- process.exit(0);
677
- }
678
-
679
- const COL_NAME = 30;
680
- const COL_PLAT = 10;
681
- const COL_SCOPE = 8;
682
- const COL_VER = 10;
683
- const COL_STAT = 10;
684
-
685
- function padR(str, n) { return String(str ?? "").padEnd(n).slice(0, n); }
686
-
687
- const hr = "─".repeat(COL_NAME + COL_PLAT + COL_SCOPE + COL_VER + COL_STAT + 4 + 8);
688
- console.log(hr);
689
- console.log(
690
- padR("Plugin", COL_NAME) + " " +
691
- padR("Platform", COL_PLAT) + " " +
692
- padR("Scope", COL_SCOPE) + " " +
693
- padR("Version", COL_VER) + " " +
694
- padR("Status", COL_STAT),
695
- );
696
- console.log(hr);
697
-
698
- for (const e of entries) {
699
- console.log(
700
- padR(e.name, COL_NAME) + " " +
701
- padR(e.platform, COL_PLAT) + " " +
702
- padR(e.scope, COL_SCOPE) + " " +
703
- padR(e.version, COL_VER) + " " +
704
- padR(e.status, COL_STAT),
705
- );
706
- }
707
- console.log(hr);
708
- process.stderr.write(`${entries.length} surface${entries.length === 1 ? "" : "s"} checked.\n`);
709
- process.exit(0);
710
- }
711
-
712
- // ---------------------------------------------------------------------------
713
- // `migrate-artifacts` command — rename legacy global markdown artifacts.
714
- if (command === "migrate-artifacts") {
715
- try {
716
- const report = migrateGlobalArtifacts({ dryRun: Boolean(options.dryRun) });
717
- if (options.json) {
718
- process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
719
- } else {
720
- const factoryRenamed = report.factory.flatMap((entry) => entry.renamed);
721
- const loopRenamed = report.loop.flatMap((entry) => entry.renamed);
722
- if (factoryRenamed.length === 0 && loopRenamed.length === 0) {
723
- process.stdout.write("✓ no legacy markdown artifacts to migrate\n");
724
- }
725
- for (const { from, to } of factoryRenamed) {
726
- process.stdout.write(`✓ factory ${from} → ${to}\n`);
727
- }
728
- for (const { from, to } of loopRenamed) {
729
- process.stdout.write(`✓ loop ${from} → ${to}\n`);
730
- }
731
- if (report.fallbacks.length > 0) {
732
- process.stderr.write(
733
- `· ${report.fallbacks.length} ISO-date rename(s) used hour fallback — see --json for details\n`,
734
- );
735
- }
736
- }
737
- process.exit(0);
738
- } catch (err) {
739
- process.stderr.write(
740
- `[enact-extensions migrate-artifacts] Error: ${err instanceof Error ? err.message : String(err)}\n`,
741
- );
742
- process.exit(1);
743
- }
463
+ exit(0);
744
464
  }
745
465
 
746
- // `update` command — refresh outdated installed plugins, driven by the ledger.
747
- //
748
- // Re-installs each OUTDATED (plugin, surface, home) to the EXACT surface + home
749
- // recorded in the ledger — never to a surface the plugin isn't already on.
750
- //
751
- // update <name> → refresh only that plugin (across its installed surfaces)
752
- // update --all → refresh every outdated surface
753
- // update --dry-run→ report what WOULD change; touch nothing
754
- //
755
- // Exit code: non-zero ONLY on a real install failure or a missing target (no
756
- // name + no --all). Orphaned and fresh surfaces are never failures.
757
- // Human chrome → stderr; the ledger self-updates via runInstall.
758
466
  // ---------------------------------------------------------------------------
759
- if (command === "update") {
760
- let summary;
761
- try {
762
- summary = runUpdate({
763
- name: path, // positional[1]: a bare plugin name (or undefined)
764
- all: options.all,
765
- dryRun: options.dryRun,
766
- home: homedir(), // single global ledger home
767
- cwd: processCwd(), // canonical bundle resolution
768
- });
769
- } catch (err) {
770
- process.stderr.write(
771
- `[enact-extensions update] ${err instanceof Error ? err.message : String(err)}\n`,
772
- );
773
- process.exit(1);
774
- }
775
-
776
- const verb = summary.dryRun ? "would update" : "updated";
777
-
778
- if (summary.dryRun) {
779
- if (summary.planned.length === 0) {
780
- process.stderr.write("Nothing to update — no outdated surfaces in scope.\n");
781
- }
782
- for (const e of summary.planned) {
783
- const from = e.installedHash ? String(e.installedHash).slice(0, 12) : "(none)";
784
- const to = e.currentHash ? String(e.currentHash).slice(0, 12) : "(unknown)";
785
- console.log(`${verb}: ${e.name} [${e.platform}] @ ${e.home} ${from} -> ${to}`);
786
- }
787
- } else {
788
- for (const e of summary.updated) {
789
- console.log(`updated: ${e.name} [${e.platform}] @ ${e.home}`);
790
- }
791
- }
792
-
793
- for (const e of summary.skipped) {
794
- process.stderr.write(
795
- `skipped-orphaned: ${e.name} [${e.platform}] @ ${e.home} (canonical source gone)\n`,
796
- );
797
- }
798
- for (const f of summary.failed) {
799
- const e = f.entry;
800
- process.stderr.write(
801
- `failed: ${e.name} [${e.platform}] @ ${e.home}: ${f.error.message}\n`,
802
- );
803
- }
804
-
805
- const doneCount = summary.dryRun ? summary.planned.length : summary.updated.length;
806
- process.stderr.write(
807
- `${doneCount} ${summary.dryRun ? "would be updated" : "updated"}, ` +
808
- `${summary.skipped.length} skipped (orphaned), ${summary.failed.length} failed.\n`,
809
- );
810
-
811
- // Non-zero exit ONLY on a real install failure.
812
- process.exit(summary.failed.length > 0 ? 1 : 0);
813
- }
814
-
815
- // ---------------------------------------------------------------------------
816
- // `prune` command — remove orphaned installed surfaces, driven by the ledger.
817
- //
818
- // A surface is pruned only when:
819
- // - the ledger still says it is installed,
820
- // - it belongs to the requested marketplace,
821
- // - its platform is in scope, and
822
- // - no local source bundle exists for that plugin name.
467
+ // Commands that resolve a plugin root path: validate, sync, install/uninstall --repo.
823
468
  // ---------------------------------------------------------------------------
824
- if (command === "prune") {
825
- let summary;
826
- try {
827
- summary = runPrune({
828
- platform: options.platform ?? "all",
829
- dryRun: options.dryRun,
830
- ledgerHome: homedir(),
831
- cwd: processCwd(),
832
- marketplaceName: options.marketplaceName,
833
- });
834
- } catch (err) {
835
- process.stderr.write(
836
- `[enact-extensions prune] ${err instanceof Error ? err.message : String(err)}\n`,
837
- );
838
- process.exit(1);
839
- }
840
-
841
- if (options.json) {
842
- process.stdout.write(JSON.stringify(summary, null, 2) + "\n");
843
- process.exit(summary.failed.length > 0 ? 1 : 0);
844
- }
845
-
846
- const rows = summary.dryRun ? summary.candidates : summary.pruned;
847
- const verb = summary.dryRun ? "would prune" : "pruned";
848
- if (rows.length === 0) {
849
- process.stderr.write("Nothing to prune — no orphaned installed surfaces in scope.\n");
850
- }
851
- for (const entry of rows) {
852
- console.log(`${verb}: ${entry.name} [${entry.platform}] @ ${entry.home}`);
853
- }
854
- for (const f of summary.failed) {
855
- process.stderr.write(
856
- `failed: ${f.entry.name} [${f.entry.platform}] @ ${f.entry.home}: ${f.error.message}\n`,
857
- );
858
- }
859
- process.stderr.write(
860
- `${rows.length} ${summary.dryRun ? "would be pruned" : "pruned"}, ${summary.failed.length} failed.\n`,
861
- );
862
- process.exit(summary.failed.length > 0 ? 1 : 0);
863
- }
864
-
865
- // ---------------------------------------------------------------------------
866
- // `serve` command — localhost API + static-file server (no pluginRoot needed).
867
- // Handled here (before resolveRoot) because it is async + long-running.
868
- // ---------------------------------------------------------------------------
869
- if (command === "serve") {
870
- const PACKAGE_ROOT = resolve(__dirname, "..");
871
- const port = resolveServePort(options);
872
- const host = options.host ?? "127.0.0.1";
873
-
874
- if (host !== "127.0.0.1" && host !== "localhost" && host !== "::1") {
875
- process.stderr.write(
876
- `[enact-extensions serve] WARNING: binding to ${host} exposes the API to other machines on the network.\n`,
877
- );
878
- }
879
-
880
- // Use async IIFE. The http.Server keeps the event loop alive after this IIFE resolves.
881
- (async () => {
882
- let serverInstance;
883
- let url;
884
- try {
885
- const started = await startServer({
886
- port,
887
- host,
888
- packageRoot: PACKAGE_ROOT,
889
- installDefaults: { ledgerHome: homedir() },
890
- });
891
- serverInstance = started.server;
892
- url = started.url;
893
- } catch (err) {
894
- process.stderr.write(`[enact-extensions serve] Failed to start server: ${err instanceof Error ? err.message : String(err)}\n`);
895
- process.exit(1);
896
- }
897
-
898
- console.log(`enact-extensions serve: listening at ${url}`);
899
-
900
- if (options.open) {
901
- // Best-effort browser open; ignore all errors silently.
902
- const { spawn } = await import("node:child_process");
903
- const opener =
904
- process.platform === "darwin"
905
- ? "open"
906
- : process.platform === "win32"
907
- ? "start"
908
- : "xdg-open";
909
- try {
910
- spawn(opener, [url], { detached: true, stdio: "ignore" }).unref();
911
- } catch {
912
- // xdg-open / open not available in all environments — ignore
913
- }
914
- }
915
-
916
- // SIGINT / SIGTERM → graceful shutdown
917
- const shutdown = () => serverInstance.close(() => process.exit(0));
918
- process.on("SIGINT", shutdown);
919
- process.on("SIGTERM", shutdown);
920
- })();
921
-
922
- // Do NOT fall through to resolveRoot / the plugin-root command block.
923
- // process.exit is intentionally NOT called — the http.Server ref keeps Node alive.
924
- // Use a throw inside a never-reached block OR just let the module end here.
925
- // The trick: throw a synthetic signal so the try/catch-less module scope terminates.
926
- // Actually: we use process.exitCode = 0 and allow the event loop to keep running.
927
- process.exitCode = 0; // signal intent; overridden to 1 on error inside IIFE
928
- }
929
-
930
- // ---------------------------------------------------------------------------
931
- // `hook` command — execute a hook handler by name, reading JSON from stdin.
932
- //
933
- // Currently supported sub-commands:
934
- // enact-extensions hook session-start
935
- // Runs the advisory drift-check and prints a single line only when plugin
936
- // surfaces are outdated.
937
- // enact-extensions hook user-prompt-submit
938
- // Reads a UserPromptSubmit hook payload from stdin, extracts the prompt,
939
- // builds the skill catalog from the bundled extensions dir, routes the
940
- // prompt, and writes the hook response to stdout.
941
- // Set ENACT_EXTENSIONS_UPS_ROUTER=0 to disable this hook locally without
942
- // removing the installed plugin.
943
- //
944
- // Output contract (Claude Code hooks):
945
- // Match: { continue: true, hookSpecificOutput: { hookEventName: "UserPromptSubmit", additionalContext: <string> } }
946
- // No match: { continue: true }
947
- // Error: { continue: true } (never throws/crashes — degrade gracefully)
948
- // ---------------------------------------------------------------------------
949
- if (command === "hook") {
950
- const subCommand = path; // positional[1]
951
-
952
- if (subCommand !== "user-prompt-submit" && subCommand !== "session-start") {
953
- process.stderr.write(
954
- `[enact-extensions hook] Unknown sub-command: ${subCommand ?? "(none)"}. ` +
955
- `Supported: session-start, user-prompt-submit\n`,
956
- );
957
- process.stdout.write(JSON.stringify({ continue: true }) + "\n");
958
- process.exit(0);
959
- }
960
-
961
- // Async IIFE: stdin reading and dynamic import require async context.
962
- (async () => {
963
- if (subCommand === "session-start") {
964
- try {
965
- const { handleSessionStartDrift } = await import("./lib/auto-update.mjs");
966
- // Opt-in is the USER's: gate auto-apply on the env var they set.
967
- const autoApply = !!process.env.ENACT_EXTENSIONS_AUTO_UPDATE;
968
- const result = handleSessionStartDrift({ autoApply });
969
- if (result.line) {
970
- process.stdout.write(`${result.line}\n`);
971
- }
972
- } catch {
973
- // Fail-silent for session-start hooks.
974
- }
975
- process.exit(0);
976
- }
977
-
978
- if (process.env.ENACT_EXTENSIONS_UPS_ROUTER === "0") {
979
- process.stdout.write(JSON.stringify({ continue: true }) + "\n");
980
- process.exit(0);
981
- }
982
-
983
- // Read stdin to get the hook payload JSON.
984
- let payload;
985
- try {
986
- const chunks = [];
987
- for await (const chunk of process.stdin) chunks.push(chunk);
988
- const raw = Buffer.concat(chunks).toString("utf8").trim();
989
- payload = raw ? JSON.parse(raw) : {};
990
- } catch {
991
- // Malformed or empty stdin — safe passthrough.
992
- process.stdout.write(JSON.stringify({ continue: true }) + "\n");
993
- process.exit(0);
994
- }
995
-
996
- try {
997
- // Extract the user prompt from the hook payload.
998
- // `prompt` is the canonical UserPromptSubmit field across surfaces:
999
- // Claude Code (code.claude.com/docs/en/hooks) and Codex
1000
- // (developers.openai.com/codex/hooks) both send { prompt: string, ... };
1001
- // Cursor follows the same Claude-compatible schema. Single field, no fallback.
1002
- const prompt = payload && typeof payload.prompt === "string" ? payload.prompt : null;
1003
-
1004
- if (!prompt) {
1005
- process.stdout.write(JSON.stringify({ continue: true }) + "\n");
1006
- process.exit(0);
1007
- }
1008
-
1009
- // Resolve the extensions dir relative to the installed package root so
1010
- // the hook works whether invoked from the repo or the globally installed package.
1011
- const { buildSkillCatalog, routePrompt } = await import("./lib/ups-router.mjs");
1012
- const extensionsDir = join(PACKAGE_ROOT, "extensions");
1013
- const catalog = buildSkillCatalog(extensionsDir);
1014
-
1015
- const { additionalContext } = routePrompt(prompt, catalog);
1016
-
1017
- if (additionalContext) {
1018
- process.stdout.write(
1019
- JSON.stringify({
1020
- continue: true,
1021
- hookSpecificOutput: {
1022
- hookEventName: "UserPromptSubmit",
1023
- additionalContext,
1024
- },
1025
- }) + "\n",
1026
- );
1027
- } else {
1028
- process.stdout.write(JSON.stringify({ continue: true }) + "\n");
1029
- }
1030
- } catch {
1031
- // Any unexpected error — safe passthrough, never crash.
1032
- process.stdout.write(JSON.stringify({ continue: true }) + "\n");
1033
- }
1034
-
1035
- process.exit(0);
1036
- })();
1037
- }
1038
-
1039
- // ---------------------------------------------------------------------------
1040
- // Commands that require resolving a plugin root path.
1041
- // (Only run when command is not already handled above.)
1042
- // ---------------------------------------------------------------------------
1043
- if (command !== "serve" && command !== "hook") {
1044
-
1045
- // Resolve the plugin root:
1046
- // - If no path arg given → default to cwd (existing behaviour).
1047
- // - If a path arg is given → resolveBundlePath handles both explicit paths and
1048
- // bare plugin names, throwing meaningful errors when nothing resolves.
1049
- const resolveRoot = (pathArg) => {
1050
- if (!pathArg) return resolvePluginRoot(undefined);
1051
- return resolveBundlePath(pathArg);
1052
- };
1053
-
1054
- // A bare name has no path separators (so it is not an explicit filesystem path).
1055
- const isBareName = (arg) =>
1056
- typeof arg === "string" && arg.length > 0 && !arg.includes("/") && !arg.includes("\\");
1057
-
1058
469
  let pluginRoot = null;
1059
470
  try {
1060
- pluginRoot = resolveRoot(path);
471
+ pluginRoot = path ? resolveBundlePath(path) : resolve(processCwd());
1061
472
  } catch (err) {
1062
- // UNINSTALL-ONLY FALLBACK: uninstall must work even when the source bundle is
1063
- // gone. If the arg is a BARE NAME (not an explicit path) that did not resolve
1064
- // to a bundle, fall back to using the arg verbatim as the plugin name. The
1065
- // uninstall handler reads the name from `path` when pluginRoot is null.
1066
- // For an explicit path that does not exist, or for any other command, this is
1067
- // still a hard error.
1068
- if (command === "uninstall" && isBareName(path)) {
1069
- pluginRoot = null; // signal: use the raw `path` as the plugin name
1070
- } else {
1071
- console.error(err instanceof Error ? err.message : String(err));
1072
- process.exit(1);
473
+ // uninstall --repo must work even when the source bundle is gone: a bare
474
+ // name that does not resolve is used verbatim as the plugin name.
475
+ const isBareName = typeof path === "string" && path.length > 0 && !path.includes("/") && !path.includes("\\");
476
+ if (!(command === "uninstall" && isBareName)) {
477
+ fail(err instanceof Error ? err.message : String(err));
1073
478
  }
1074
479
  }
1075
480
 
481
+ function manifestName(root) {
482
+ const manifestPath = root ? join(root, ".agents", "plugin.json") : null;
483
+ return manifestPath && existsSync(manifestPath) ? JSON.parse(readFileSync(manifestPath, "utf8")).name : null;
484
+ }
485
+
1076
486
  try {
1077
487
  if (command === "validate") {
1078
- const ok = runValidate(pluginRoot, undefined, { pluginValidate: true });
1079
- process.exit(ok ? 0 : 1);
488
+ const ok = runValidate(pluginRoot, undefined, { pluginValidate: true, skillValidate: true });
489
+ exit(ok ? 0 : 1);
1080
490
  }
1081
491
 
1082
492
  if (command === "sync") {
1083
493
  runSync(pluginRoot, { name: options.name });
1084
- process.exit(0);
1085
- }
1086
-
1087
- if (command === "install") {
1088
- // Single global ledger: every install (local or global scope) records to
1089
- // <homedir>/.enact/extensions/ledger.jsonl so `log` always finds it,
1090
- // regardless of which per-platform home the bundle was installed to. The
1091
- // local/global distinction is carried in each entry's `scope` field.
1092
- runInstall(pluginRoot, { ...options, ledgerHome: homedir() });
1093
- process.exit(0);
1094
- }
1095
-
1096
- if (command === "uninstall") {
1097
- // Resolve plugin name: if the source bundle resolved on disk, read its
1098
- // manifest name from .agents/plugin.json (or .codex-plugin/plugin.json).
1099
- // Otherwise (source bundle gone / bare-name fallback), treat the raw
1100
- // positional arg as the plugin name. This lets uninstall remove already-
1101
- // installed plugins even when their source bundle has been deleted.
1102
- let pluginName = null;
1103
- if (pluginRoot) {
1104
- try {
1105
- const enactManifestPath = join(pluginRoot, ".agents", "plugin.json");
1106
- if (existsSync(enactManifestPath)) {
1107
- const manifest = JSON.parse(readFileSync(enactManifestPath, "utf8"));
1108
- pluginName = typeof manifest.name === "string" ? manifest.name : null;
1109
- }
1110
- // Fall back to .codex-plugin/plugin.json
1111
- if (!pluginName) {
1112
- const codexManifestPath = join(pluginRoot, ".codex-plugin", "plugin.json");
1113
- if (existsSync(codexManifestPath)) {
1114
- const manifest = JSON.parse(readFileSync(codexManifestPath, "utf8"));
1115
- pluginName = typeof manifest.name === "string" ? manifest.name : null;
1116
- }
1117
- }
1118
- } catch {
1119
- // Source bundle unreadable — fall through to raw name.
494
+ exit(0);
495
+ }
496
+
497
+ // install | uninstall --repo
498
+ const dryRun = options.dryRun === true;
499
+ const repoPluginName = manifestName(pluginRoot) ?? path;
500
+ if (!repoPluginName) {
501
+ fail(`${command} --repo requires a plugin name`);
502
+ }
503
+ const result =
504
+ command === "install"
505
+ ? runRepoInstall(pluginRoot, { repo: options.repo, host: options.host, force: options.force, dryRun })
506
+ : runRepoUninstall(repoPluginName, { repo: options.repo, purge: options.purge, force: options.force, dryRun });
507
+ if (dryRun) {
508
+ if (result.actions.length === 0) {
509
+ console.log("[dry-run] no filesystem changes — nothing touched");
510
+ } else {
511
+ for (const a of result.actions) {
512
+ console.log(`[dry-run] would ${a.action}: ${a.file} — ${a.reason}`);
1120
513
  }
1121
514
  }
1122
- // Fall back: treat the raw positional arg as the plugin name.
1123
- // `path` is the raw positional from the CLI. When the source bundle was gone
1124
- // (pluginRoot === null) this is the only source of the name.
1125
- if (!pluginName) {
1126
- pluginName = path ?? (pluginRoot ? pluginRoot.split("/").pop() : null);
1127
- }
1128
- if (!pluginName) {
1129
- console.error("uninstall requires a plugin name or path.");
1130
- process.exit(1);
1131
- }
1132
- runUninstall(pluginName, { ...options, ledgerHome: homedir() });
1133
- process.exit(0);
1134
515
  }
1135
-
1136
- console.error(`Unknown command: ${command}\n`);
1137
- console.log(HELP);
1138
- process.exit(1);
516
+ exit(0);
1139
517
  } catch (err) {
1140
- console.error(err instanceof Error ? err.message : String(err));
1141
- process.exit(1);
518
+ if (err instanceof ExitSignal) throw err;
519
+ fail(err instanceof Error ? err.message : String(err));
520
+ }
521
+ } catch (err) {
522
+ // The only expected escape: a command asked to finish with a status.
523
+ // Setting exitCode rather than exiting lets node drain stdout first.
524
+ if (!(err instanceof ExitSignal)) throw err;
525
+ process.exitCode = err.code;
1142
526
  }
1143
-
1144
- } // end if (command !== "serve")