@modootoday/pmcp 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (846) hide show
  1. package/.agents/plugins/marketplace.json +1157 -0
  2. package/.claude-plugin/marketplace.json +825 -0
  3. package/.claude-plugin/plugin.json +9 -0
  4. package/.mcp.json +9 -0
  5. package/NOTICE +4 -2
  6. package/README.md +67 -4
  7. package/dist/cli.js +1345 -741
  8. package/dist/{config-CJ43_oBS.d.ts → config-BkSpjUG6.d.ts} +1 -0
  9. package/dist/{embed-BW6AWD1e.d.ts → embed-CVCEz2FH.d.ts} +1 -1
  10. package/dist/http.d.ts +3 -3
  11. package/dist/http.js +216 -112
  12. package/dist/index.d.ts +7 -14
  13. package/dist/index.js +382 -262
  14. package/dist/mailbox/index.d.ts +1 -1
  15. package/dist/mailbox/index.js +18 -2
  16. package/dist/{server-9w4R1caM.d.ts → server-DAcT89iv.d.ts} +5 -5
  17. package/dist/stdio.d.ts +1 -1
  18. package/dist/stdio.js +229 -121
  19. package/dist/tui-worker.js +18 -2
  20. package/docs/catalog.json +5422 -0
  21. package/docs/manual-library-skills.md +74 -0
  22. package/docs/skills.md +46 -0
  23. package/docs/terminal-workspace.md +16 -14
  24. package/gemini-extension.json +11 -0
  25. package/mcp.json +10 -0
  26. package/package.json +26 -5
  27. package/plugin.json +10 -0
  28. package/plugins/agent-base-9/.claude-plugin/plugin.json +9 -0
  29. package/plugins/agent-base-9/LICENSE +93 -0
  30. package/plugins/agent-base-9/NOTICE +51 -0
  31. package/plugins/agent-base-9/gemini-extension.json +1 -0
  32. package/plugins/agent-base-9/plugin.json +10 -0
  33. package/plugins/agent-base-9/skills/agent-base/SKILL.md +118 -0
  34. package/plugins/ajv-formats-3/.claude-plugin/plugin.json +9 -0
  35. package/plugins/ajv-formats-3/LICENSE +93 -0
  36. package/plugins/ajv-formats-3/NOTICE +51 -0
  37. package/plugins/ajv-formats-3/gemini-extension.json +1 -0
  38. package/plugins/ajv-formats-3/plugin.json +10 -0
  39. package/plugins/ajv-formats-3/skills/ajv-formats/SKILL.md +178 -0
  40. package/plugins/allure-js-commons-3/.claude-plugin/plugin.json +9 -0
  41. package/plugins/allure-js-commons-3/LICENSE +93 -0
  42. package/plugins/allure-js-commons-3/NOTICE +51 -0
  43. package/plugins/allure-js-commons-3/gemini-extension.json +1 -0
  44. package/plugins/allure-js-commons-3/plugin.json +10 -0
  45. package/plugins/allure-js-commons-3/skills/allure-js-commons/SKILL.md +173 -0
  46. package/plugins/ansi-escapes-7/.claude-plugin/plugin.json +9 -0
  47. package/plugins/ansi-escapes-7/LICENSE +93 -0
  48. package/plugins/ansi-escapes-7/NOTICE +51 -0
  49. package/plugins/ansi-escapes-7/gemini-extension.json +1 -0
  50. package/plugins/ansi-escapes-7/plugin.json +10 -0
  51. package/plugins/ansi-escapes-7/skills/ansi-escapes/SKILL.md +189 -0
  52. package/plugins/ansi-styles-7/.claude-plugin/plugin.json +9 -0
  53. package/plugins/ansi-styles-7/LICENSE +93 -0
  54. package/plugins/ansi-styles-7/NOTICE +51 -0
  55. package/plugins/ansi-styles-7/gemini-extension.json +1 -0
  56. package/plugins/ansi-styles-7/plugin.json +10 -0
  57. package/plugins/ansi-styles-7/skills/ansi-styles/SKILL.md +161 -0
  58. package/plugins/app-builder-lib-26/.claude-plugin/plugin.json +9 -0
  59. package/plugins/app-builder-lib-26/LICENSE +93 -0
  60. package/plugins/app-builder-lib-26/NOTICE +51 -0
  61. package/plugins/app-builder-lib-26/gemini-extension.json +1 -0
  62. package/plugins/app-builder-lib-26/plugin.json +10 -0
  63. package/plugins/app-builder-lib-26/skills/app-builder-lib/SKILL.md +84 -0
  64. package/plugins/autoprefixer-10/.claude-plugin/plugin.json +9 -0
  65. package/plugins/autoprefixer-10/LICENSE +93 -0
  66. package/plugins/autoprefixer-10/NOTICE +51 -0
  67. package/plugins/autoprefixer-10/gemini-extension.json +1 -0
  68. package/plugins/autoprefixer-10/plugin.json +10 -0
  69. package/plugins/autoprefixer-10/skills/autoprefixer/SKILL.md +141 -0
  70. package/plugins/babel-plugin-transform-typescript-8/.claude-plugin/plugin.json +9 -0
  71. package/plugins/babel-plugin-transform-typescript-8/LICENSE +93 -0
  72. package/plugins/babel-plugin-transform-typescript-8/NOTICE +51 -0
  73. package/plugins/babel-plugin-transform-typescript-8/gemini-extension.json +1 -0
  74. package/plugins/babel-plugin-transform-typescript-8/plugin.json +10 -0
  75. package/plugins/babel-plugin-transform-typescript-8/skills/babel-plugin-transform-typescript/SKILL.md +135 -0
  76. package/plugins/bcryptjs-2/.claude-plugin/plugin.json +9 -0
  77. package/plugins/bcryptjs-2/LICENSE +93 -0
  78. package/plugins/bcryptjs-2/NOTICE +51 -0
  79. package/plugins/bcryptjs-2/gemini-extension.json +1 -0
  80. package/plugins/bcryptjs-2/plugin.json +10 -0
  81. package/plugins/bcryptjs-2/skills/bcryptjs/SKILL.md +78 -0
  82. package/plugins/bullmq-5/.claude-plugin/plugin.json +9 -0
  83. package/plugins/bullmq-5/LICENSE +93 -0
  84. package/plugins/bullmq-5/NOTICE +51 -0
  85. package/plugins/bullmq-5/gemini-extension.json +1 -0
  86. package/plugins/bullmq-5/plugin.json +10 -0
  87. package/plugins/bullmq-5/skills/bullmq/SKILL.md +59 -0
  88. package/plugins/bun-types-1/.claude-plugin/plugin.json +9 -0
  89. package/plugins/bun-types-1/LICENSE +93 -0
  90. package/plugins/bun-types-1/NOTICE +51 -0
  91. package/plugins/bun-types-1/gemini-extension.json +1 -0
  92. package/plugins/bun-types-1/plugin.json +10 -0
  93. package/plugins/bun-types-1/skills/bun-types/SKILL.md +119 -0
  94. package/plugins/chai-6/.claude-plugin/plugin.json +9 -0
  95. package/plugins/chai-6/LICENSE +93 -0
  96. package/plugins/chai-6/NOTICE +51 -0
  97. package/plugins/chai-6/gemini-extension.json +1 -0
  98. package/plugins/chai-6/plugin.json +10 -0
  99. package/plugins/chai-6/skills/chai/SKILL.md +160 -0
  100. package/plugins/chalk-6/.claude-plugin/plugin.json +9 -0
  101. package/plugins/chalk-6/LICENSE +93 -0
  102. package/plugins/chalk-6/NOTICE +51 -0
  103. package/plugins/chalk-6/gemini-extension.json +1 -0
  104. package/plugins/chalk-6/plugin.json +10 -0
  105. package/plugins/chalk-6/skills/chalk/SKILL.md +167 -0
  106. package/plugins/cli-cursor-5/.claude-plugin/plugin.json +9 -0
  107. package/plugins/cli-cursor-5/LICENSE +93 -0
  108. package/plugins/cli-cursor-5/NOTICE +51 -0
  109. package/plugins/cli-cursor-5/gemini-extension.json +1 -0
  110. package/plugins/cli-cursor-5/plugin.json +10 -0
  111. package/plugins/cli-cursor-5/skills/cli-cursor/SKILL.md +117 -0
  112. package/plugins/cli-spinners-3/.claude-plugin/plugin.json +9 -0
  113. package/plugins/cli-spinners-3/LICENSE +93 -0
  114. package/plugins/cli-spinners-3/NOTICE +51 -0
  115. package/plugins/cli-spinners-3/gemini-extension.json +1 -0
  116. package/plugins/cli-spinners-3/plugin.json +10 -0
  117. package/plugins/cli-spinners-3/skills/cli-spinners/SKILL.md +101 -0
  118. package/plugins/clickhouse-client-1/.claude-plugin/plugin.json +9 -0
  119. package/plugins/clickhouse-client-1/LICENSE +93 -0
  120. package/plugins/clickhouse-client-1/NOTICE +51 -0
  121. package/plugins/clickhouse-client-1/gemini-extension.json +1 -0
  122. package/plugins/clickhouse-client-1/plugin.json +10 -0
  123. package/plugins/clickhouse-client-1/skills/clickhouse-client/SKILL.md +54 -0
  124. package/plugins/clickhouse-client-web-1/.claude-plugin/plugin.json +9 -0
  125. package/plugins/clickhouse-client-web-1/LICENSE +93 -0
  126. package/plugins/clickhouse-client-web-1/NOTICE +51 -0
  127. package/plugins/clickhouse-client-web-1/gemini-extension.json +1 -0
  128. package/plugins/clickhouse-client-web-1/plugin.json +10 -0
  129. package/plugins/clickhouse-client-web-1/skills/clickhouse-client-web/SKILL.md +52 -0
  130. package/plugins/cliui-9/.claude-plugin/plugin.json +9 -0
  131. package/plugins/cliui-9/LICENSE +93 -0
  132. package/plugins/cliui-9/NOTICE +51 -0
  133. package/plugins/cliui-9/gemini-extension.json +1 -0
  134. package/plugins/cliui-9/plugin.json +10 -0
  135. package/plugins/cliui-9/skills/cliui/SKILL.md +163 -0
  136. package/plugins/cloudflare-workers-types-4/.claude-plugin/plugin.json +9 -0
  137. package/plugins/cloudflare-workers-types-4/LICENSE +93 -0
  138. package/plugins/cloudflare-workers-types-4/NOTICE +51 -0
  139. package/plugins/cloudflare-workers-types-4/gemini-extension.json +1 -0
  140. package/plugins/cloudflare-workers-types-4/plugin.json +10 -0
  141. package/plugins/cloudflare-workers-types-4/skills/cloudflare-workers-types/SKILL.md +63 -0
  142. package/plugins/commander-15/.claude-plugin/plugin.json +9 -0
  143. package/plugins/commander-15/LICENSE +93 -0
  144. package/plugins/commander-15/NOTICE +51 -0
  145. package/plugins/commander-15/gemini-extension.json +1 -0
  146. package/plugins/commander-15/plugin.json +10 -0
  147. package/plugins/commander-15/skills/commander/SKILL.md +204 -0
  148. package/plugins/content-type-3/.claude-plugin/plugin.json +9 -0
  149. package/plugins/content-type-3/LICENSE +93 -0
  150. package/plugins/content-type-3/NOTICE +51 -0
  151. package/plugins/content-type-3/gemini-extension.json +1 -0
  152. package/plugins/content-type-3/plugin.json +10 -0
  153. package/plugins/content-type-3/skills/content-type/SKILL.md +126 -0
  154. package/plugins/croner-10/.claude-plugin/plugin.json +9 -0
  155. package/plugins/croner-10/LICENSE +93 -0
  156. package/plugins/croner-10/NOTICE +51 -0
  157. package/plugins/croner-10/gemini-extension.json +1 -0
  158. package/plugins/croner-10/plugin.json +10 -0
  159. package/plugins/croner-10/skills/croner/SKILL.md +182 -0
  160. package/plugins/css-tree-3/.claude-plugin/plugin.json +9 -0
  161. package/plugins/css-tree-3/LICENSE +93 -0
  162. package/plugins/css-tree-3/NOTICE +51 -0
  163. package/plugins/css-tree-3/gemini-extension.json +1 -0
  164. package/plugins/css-tree-3/plugin.json +10 -0
  165. package/plugins/css-tree-3/skills/css-tree/SKILL.md +165 -0
  166. package/plugins/data-urls-7/.claude-plugin/plugin.json +9 -0
  167. package/plugins/data-urls-7/LICENSE +93 -0
  168. package/plugins/data-urls-7/NOTICE +51 -0
  169. package/plugins/data-urls-7/gemini-extension.json +1 -0
  170. package/plugins/data-urls-7/plugin.json +10 -0
  171. package/plugins/data-urls-7/skills/data-urls/SKILL.md +136 -0
  172. package/plugins/deep-eql-5/.claude-plugin/plugin.json +9 -0
  173. package/plugins/deep-eql-5/LICENSE +93 -0
  174. package/plugins/deep-eql-5/NOTICE +51 -0
  175. package/plugins/deep-eql-5/gemini-extension.json +1 -0
  176. package/plugins/deep-eql-5/plugin.json +10 -0
  177. package/plugins/deep-eql-5/skills/deep-eql/SKILL.md +130 -0
  178. package/plugins/dexie-4/.claude-plugin/plugin.json +9 -0
  179. package/plugins/dexie-4/LICENSE +93 -0
  180. package/plugins/dexie-4/NOTICE +51 -0
  181. package/plugins/dexie-4/gemini-extension.json +1 -0
  182. package/plugins/dexie-4/plugin.json +10 -0
  183. package/plugins/dexie-4/skills/dexie/SKILL.md +192 -0
  184. package/plugins/emittery-2/.claude-plugin/plugin.json +9 -0
  185. package/plugins/emittery-2/LICENSE +93 -0
  186. package/plugins/emittery-2/NOTICE +51 -0
  187. package/plugins/emittery-2/gemini-extension.json +1 -0
  188. package/plugins/emittery-2/plugin.json +10 -0
  189. package/plugins/emittery-2/skills/emittery/SKILL.md +234 -0
  190. package/plugins/eslint-10/.claude-plugin/plugin.json +9 -0
  191. package/plugins/eslint-10/LICENSE +93 -0
  192. package/plugins/eslint-10/NOTICE +51 -0
  193. package/plugins/eslint-10/gemini-extension.json +1 -0
  194. package/plugins/eslint-10/plugin.json +10 -0
  195. package/plugins/eslint-10/skills/eslint/SKILL.md +77 -0
  196. package/plugins/eslint-9/.claude-plugin/plugin.json +9 -0
  197. package/plugins/eslint-9/LICENSE +93 -0
  198. package/plugins/eslint-9/NOTICE +51 -0
  199. package/plugins/eslint-9/gemini-extension.json +1 -0
  200. package/plugins/eslint-9/plugin.json +10 -0
  201. package/plugins/eslint-9/skills/eslint/SKILL.md +93 -0
  202. package/plugins/eslint-plugin-react-hooks-7/.claude-plugin/plugin.json +9 -0
  203. package/plugins/eslint-plugin-react-hooks-7/LICENSE +93 -0
  204. package/plugins/eslint-plugin-react-hooks-7/NOTICE +51 -0
  205. package/plugins/eslint-plugin-react-hooks-7/gemini-extension.json +1 -0
  206. package/plugins/eslint-plugin-react-hooks-7/plugin.json +10 -0
  207. package/plugins/eslint-plugin-react-hooks-7/skills/eslint-plugin-react-hooks/SKILL.md +173 -0
  208. package/plugins/eslint-plugin-testing-library-7/.claude-plugin/plugin.json +9 -0
  209. package/plugins/eslint-plugin-testing-library-7/LICENSE +93 -0
  210. package/plugins/eslint-plugin-testing-library-7/NOTICE +51 -0
  211. package/plugins/eslint-plugin-testing-library-7/gemini-extension.json +1 -0
  212. package/plugins/eslint-plugin-testing-library-7/plugin.json +10 -0
  213. package/plugins/eslint-plugin-testing-library-7/skills/eslint-plugin-testing-library/SKILL.md +193 -0
  214. package/plugins/expect-type-1/.claude-plugin/plugin.json +9 -0
  215. package/plugins/expect-type-1/LICENSE +93 -0
  216. package/plugins/expect-type-1/NOTICE +51 -0
  217. package/plugins/expect-type-1/gemini-extension.json +1 -0
  218. package/plugins/expect-type-1/plugin.json +10 -0
  219. package/plugins/expect-type-1/skills/expect-type/SKILL.md +165 -0
  220. package/plugins/express-5/.claude-plugin/plugin.json +9 -0
  221. package/plugins/express-5/LICENSE +93 -0
  222. package/plugins/express-5/NOTICE +51 -0
  223. package/plugins/express-5/gemini-extension.json +1 -0
  224. package/plugins/express-5/plugin.json +10 -0
  225. package/plugins/express-5/skills/express/SKILL.md +179 -0
  226. package/plugins/fake-indexeddb-6/.claude-plugin/plugin.json +9 -0
  227. package/plugins/fake-indexeddb-6/LICENSE +93 -0
  228. package/plugins/fake-indexeddb-6/NOTICE +51 -0
  229. package/plugins/fake-indexeddb-6/gemini-extension.json +1 -0
  230. package/plugins/fake-indexeddb-6/plugin.json +10 -0
  231. package/plugins/fake-indexeddb-6/skills/fake-indexeddb/SKILL.md +147 -0
  232. package/plugins/fast-check-4/.claude-plugin/plugin.json +9 -0
  233. package/plugins/fast-check-4/LICENSE +93 -0
  234. package/plugins/fast-check-4/NOTICE +51 -0
  235. package/plugins/fast-check-4/gemini-extension.json +1 -0
  236. package/plugins/fast-check-4/plugin.json +10 -0
  237. package/plugins/fast-check-4/skills/fast-check/SKILL.md +168 -0
  238. package/plugins/figures-6/.claude-plugin/plugin.json +9 -0
  239. package/plugins/figures-6/LICENSE +93 -0
  240. package/plugins/figures-6/NOTICE +51 -0
  241. package/plugins/figures-6/gemini-extension.json +1 -0
  242. package/plugins/figures-6/plugin.json +10 -0
  243. package/plugins/figures-6/skills/figures/SKILL.md +99 -0
  244. package/plugins/firebase-12/.claude-plugin/plugin.json +9 -0
  245. package/plugins/firebase-12/LICENSE +93 -0
  246. package/plugins/firebase-12/NOTICE +51 -0
  247. package/plugins/firebase-12/gemini-extension.json +1 -0
  248. package/plugins/firebase-12/plugin.json +10 -0
  249. package/plugins/firebase-12/skills/firebase/SKILL.md +161 -0
  250. package/plugins/firebase-admin-14/.claude-plugin/plugin.json +9 -0
  251. package/plugins/firebase-admin-14/LICENSE +93 -0
  252. package/plugins/firebase-admin-14/NOTICE +51 -0
  253. package/plugins/firebase-admin-14/gemini-extension.json +1 -0
  254. package/plugins/firebase-admin-14/plugin.json +10 -0
  255. package/plugins/firebase-admin-14/skills/firebase-admin/SKILL.md +155 -0
  256. package/plugins/get-uri-8/.claude-plugin/plugin.json +9 -0
  257. package/plugins/get-uri-8/LICENSE +93 -0
  258. package/plugins/get-uri-8/NOTICE +51 -0
  259. package/plugins/get-uri-8/gemini-extension.json +1 -0
  260. package/plugins/get-uri-8/plugin.json +10 -0
  261. package/plugins/get-uri-8/skills/get-uri/SKILL.md +112 -0
  262. package/plugins/google-uuid-1/.claude-plugin/plugin.json +9 -0
  263. package/plugins/google-uuid-1/LICENSE +93 -0
  264. package/plugins/google-uuid-1/NOTICE +51 -0
  265. package/plugins/google-uuid-1/gemini-extension.json +1 -0
  266. package/plugins/google-uuid-1/plugin.json +10 -0
  267. package/plugins/google-uuid-1/skills/google-uuid/SKILL.md +70 -0
  268. package/plugins/graphql-16/.claude-plugin/plugin.json +9 -0
  269. package/plugins/graphql-16/LICENSE +93 -0
  270. package/plugins/graphql-16/NOTICE +51 -0
  271. package/plugins/graphql-16/gemini-extension.json +1 -0
  272. package/plugins/graphql-16/plugin.json +10 -0
  273. package/plugins/graphql-16/skills/graphql/SKILL.md +56 -0
  274. package/plugins/graphql-17/.claude-plugin/plugin.json +9 -0
  275. package/plugins/graphql-17/LICENSE +93 -0
  276. package/plugins/graphql-17/NOTICE +51 -0
  277. package/plugins/graphql-17/gemini-extension.json +1 -0
  278. package/plugins/graphql-17/plugin.json +10 -0
  279. package/plugins/graphql-17/skills/graphql/SKILL.md +159 -0
  280. package/plugins/graphql-yoga-5/.claude-plugin/plugin.json +9 -0
  281. package/plugins/graphql-yoga-5/LICENSE +93 -0
  282. package/plugins/graphql-yoga-5/NOTICE +51 -0
  283. package/plugins/graphql-yoga-5/gemini-extension.json +1 -0
  284. package/plugins/graphql-yoga-5/plugin.json +10 -0
  285. package/plugins/graphql-yoga-5/skills/graphql-yoga/SKILL.md +68 -0
  286. package/plugins/happy-dom-20/.claude-plugin/plugin.json +9 -0
  287. package/plugins/happy-dom-20/LICENSE +93 -0
  288. package/plugins/happy-dom-20/NOTICE +51 -0
  289. package/plugins/happy-dom-20/gemini-extension.json +1 -0
  290. package/plugins/happy-dom-20/plugin.json +10 -0
  291. package/plugins/happy-dom-20/skills/happy-dom/SKILL.md +172 -0
  292. package/plugins/hono-4/.claude-plugin/plugin.json +9 -0
  293. package/plugins/hono-4/LICENSE +93 -0
  294. package/plugins/hono-4/NOTICE +51 -0
  295. package/plugins/hono-4/gemini-extension.json +1 -0
  296. package/plugins/hono-4/plugin.json +10 -0
  297. package/plugins/hono-4/skills/hono/SKILL.md +203 -0
  298. package/plugins/http-proxy-agent-9/.claude-plugin/plugin.json +9 -0
  299. package/plugins/http-proxy-agent-9/LICENSE +93 -0
  300. package/plugins/http-proxy-agent-9/NOTICE +51 -0
  301. package/plugins/http-proxy-agent-9/gemini-extension.json +1 -0
  302. package/plugins/http-proxy-agent-9/plugin.json +10 -0
  303. package/plugins/http-proxy-agent-9/skills/http-proxy-agent/SKILL.md +142 -0
  304. package/plugins/human-signals-8/.claude-plugin/plugin.json +9 -0
  305. package/plugins/human-signals-8/LICENSE +93 -0
  306. package/plugins/human-signals-8/NOTICE +51 -0
  307. package/plugins/human-signals-8/gemini-extension.json +1 -0
  308. package/plugins/human-signals-8/plugin.json +10 -0
  309. package/plugins/human-signals-8/skills/human-signals/SKILL.md +81 -0
  310. package/plugins/inquirer-14/.claude-plugin/plugin.json +9 -0
  311. package/plugins/inquirer-14/LICENSE +93 -0
  312. package/plugins/inquirer-14/NOTICE +51 -0
  313. package/plugins/inquirer-14/gemini-extension.json +1 -0
  314. package/plugins/inquirer-14/plugin.json +10 -0
  315. package/plugins/inquirer-14/skills/inquirer/SKILL.md +152 -0
  316. package/plugins/ioredis-5/.claude-plugin/plugin.json +9 -0
  317. package/plugins/ioredis-5/LICENSE +93 -0
  318. package/plugins/ioredis-5/NOTICE +51 -0
  319. package/plugins/ioredis-5/gemini-extension.json +1 -0
  320. package/plugins/ioredis-5/plugin.json +10 -0
  321. package/plugins/ioredis-5/skills/ioredis/SKILL.md +63 -0
  322. package/plugins/ioredis-6/.claude-plugin/plugin.json +9 -0
  323. package/plugins/ioredis-6/LICENSE +93 -0
  324. package/plugins/ioredis-6/NOTICE +51 -0
  325. package/plugins/ioredis-6/gemini-extension.json +1 -0
  326. package/plugins/ioredis-6/plugin.json +10 -0
  327. package/plugins/ioredis-6/skills/ioredis/SKILL.md +204 -0
  328. package/plugins/ip-address-10/.claude-plugin/plugin.json +9 -0
  329. package/plugins/ip-address-10/LICENSE +93 -0
  330. package/plugins/ip-address-10/NOTICE +51 -0
  331. package/plugins/ip-address-10/gemini-extension.json +1 -0
  332. package/plugins/ip-address-10/plugin.json +10 -0
  333. package/plugins/ip-address-10/skills/ip-address/SKILL.md +184 -0
  334. package/plugins/jackspeak-4/.claude-plugin/plugin.json +9 -0
  335. package/plugins/jackspeak-4/LICENSE +93 -0
  336. package/plugins/jackspeak-4/NOTICE +51 -0
  337. package/plugins/jackspeak-4/gemini-extension.json +1 -0
  338. package/plugins/jackspeak-4/plugin.json +10 -0
  339. package/plugins/jackspeak-4/skills/jackspeak/SKILL.md +162 -0
  340. package/plugins/jake-12/.claude-plugin/plugin.json +9 -0
  341. package/plugins/jake-12/LICENSE +93 -0
  342. package/plugins/jake-12/NOTICE +51 -0
  343. package/plugins/jake-12/gemini-extension.json +1 -0
  344. package/plugins/jake-12/plugin.json +10 -0
  345. package/plugins/jake-12/skills/jake/SKILL.md +182 -0
  346. package/plugins/jasmine-core-7/.claude-plugin/plugin.json +9 -0
  347. package/plugins/jasmine-core-7/LICENSE +93 -0
  348. package/plugins/jasmine-core-7/NOTICE +51 -0
  349. package/plugins/jasmine-core-7/gemini-extension.json +1 -0
  350. package/plugins/jasmine-core-7/plugin.json +10 -0
  351. package/plugins/jasmine-core-7/skills/jasmine-core/SKILL.md +173 -0
  352. package/plugins/jest-cli-30/.claude-plugin/plugin.json +9 -0
  353. package/plugins/jest-cli-30/LICENSE +93 -0
  354. package/plugins/jest-cli-30/NOTICE +51 -0
  355. package/plugins/jest-cli-30/gemini-extension.json +1 -0
  356. package/plugins/jest-cli-30/plugin.json +10 -0
  357. package/plugins/jest-cli-30/skills/jest-cli/SKILL.md +121 -0
  358. package/plugins/jest-extended-7/.claude-plugin/plugin.json +9 -0
  359. package/plugins/jest-extended-7/LICENSE +93 -0
  360. package/plugins/jest-extended-7/NOTICE +51 -0
  361. package/plugins/jest-extended-7/gemini-extension.json +1 -0
  362. package/plugins/jest-extended-7/plugin.json +10 -0
  363. package/plugins/jest-extended-7/skills/jest-extended/SKILL.md +125 -0
  364. package/plugins/jsdom-30/.claude-plugin/plugin.json +9 -0
  365. package/plugins/jsdom-30/LICENSE +93 -0
  366. package/plugins/jsdom-30/NOTICE +51 -0
  367. package/plugins/jsdom-30/gemini-extension.json +1 -0
  368. package/plugins/jsdom-30/plugin.json +10 -0
  369. package/plugins/jsdom-30/skills/jsdom/SKILL.md +64 -0
  370. package/plugins/level-supports-6/.claude-plugin/plugin.json +9 -0
  371. package/plugins/level-supports-6/LICENSE +93 -0
  372. package/plugins/level-supports-6/NOTICE +51 -0
  373. package/plugins/level-supports-6/gemini-extension.json +1 -0
  374. package/plugins/level-supports-6/plugin.json +10 -0
  375. package/plugins/level-supports-6/skills/level-supports/SKILL.md +178 -0
  376. package/plugins/lowdb-7/.claude-plugin/plugin.json +9 -0
  377. package/plugins/lowdb-7/LICENSE +93 -0
  378. package/plugins/lowdb-7/NOTICE +51 -0
  379. package/plugins/lowdb-7/gemini-extension.json +1 -0
  380. package/plugins/lowdb-7/plugin.json +10 -0
  381. package/plugins/lowdb-7/skills/lowdb/SKILL.md +163 -0
  382. package/plugins/make-fetch-happen-16/.claude-plugin/plugin.json +9 -0
  383. package/plugins/make-fetch-happen-16/LICENSE +93 -0
  384. package/plugins/make-fetch-happen-16/NOTICE +51 -0
  385. package/plugins/make-fetch-happen-16/gemini-extension.json +1 -0
  386. package/plugins/make-fetch-happen-16/plugin.json +10 -0
  387. package/plugins/make-fetch-happen-16/skills/make-fetch-happen/SKILL.md +171 -0
  388. package/plugins/mdx-bundler-10/.claude-plugin/plugin.json +9 -0
  389. package/plugins/mdx-bundler-10/LICENSE +93 -0
  390. package/plugins/mdx-bundler-10/NOTICE +51 -0
  391. package/plugins/mdx-bundler-10/gemini-extension.json +1 -0
  392. package/plugins/mdx-bundler-10/plugin.json +10 -0
  393. package/plugins/mdx-bundler-10/skills/mdx-bundler/SKILL.md +133 -0
  394. package/plugins/mocha-12/.claude-plugin/plugin.json +9 -0
  395. package/plugins/mocha-12/LICENSE +93 -0
  396. package/plugins/mocha-12/NOTICE +51 -0
  397. package/plugins/mocha-12/gemini-extension.json +1 -0
  398. package/plugins/mocha-12/plugin.json +10 -0
  399. package/plugins/mocha-12/skills/mocha/SKILL.md +157 -0
  400. package/plugins/modelcontextprotocol-client-2/.claude-plugin/plugin.json +9 -0
  401. package/plugins/modelcontextprotocol-client-2/LICENSE +93 -0
  402. package/plugins/modelcontextprotocol-client-2/NOTICE +51 -0
  403. package/plugins/modelcontextprotocol-client-2/gemini-extension.json +1 -0
  404. package/plugins/modelcontextprotocol-client-2/plugin.json +10 -0
  405. package/plugins/modelcontextprotocol-client-2/skills/modelcontextprotocol-client/SKILL.md +86 -0
  406. package/plugins/modelcontextprotocol-sdk-1/.claude-plugin/plugin.json +9 -0
  407. package/plugins/modelcontextprotocol-sdk-1/LICENSE +93 -0
  408. package/plugins/modelcontextprotocol-sdk-1/NOTICE +51 -0
  409. package/plugins/modelcontextprotocol-sdk-1/gemini-extension.json +1 -0
  410. package/plugins/modelcontextprotocol-sdk-1/plugin.json +10 -0
  411. package/plugins/modelcontextprotocol-sdk-1/skills/modelcontextprotocol-sdk/SKILL.md +80 -0
  412. package/plugins/modelcontextprotocol-server-2/.claude-plugin/plugin.json +9 -0
  413. package/plugins/modelcontextprotocol-server-2/LICENSE +93 -0
  414. package/plugins/modelcontextprotocol-server-2/NOTICE +51 -0
  415. package/plugins/modelcontextprotocol-server-2/gemini-extension.json +1 -0
  416. package/plugins/modelcontextprotocol-server-2/plugin.json +10 -0
  417. package/plugins/modelcontextprotocol-server-2/skills/modelcontextprotocol-server/SKILL.md +80 -0
  418. package/plugins/msw-2/.claude-plugin/plugin.json +9 -0
  419. package/plugins/msw-2/LICENSE +93 -0
  420. package/plugins/msw-2/NOTICE +51 -0
  421. package/plugins/msw-2/gemini-extension.json +1 -0
  422. package/plugins/msw-2/plugin.json +10 -0
  423. package/plugins/msw-2/skills/msw/SKILL.md +182 -0
  424. package/plugins/negotiator-1/.claude-plugin/plugin.json +9 -0
  425. package/plugins/negotiator-1/LICENSE +93 -0
  426. package/plugins/negotiator-1/NOTICE +51 -0
  427. package/plugins/negotiator-1/gemini-extension.json +1 -0
  428. package/plugins/negotiator-1/plugin.json +10 -0
  429. package/plugins/negotiator-1/skills/negotiator/SKILL.md +180 -0
  430. package/plugins/npm-run-path-6/.claude-plugin/plugin.json +9 -0
  431. package/plugins/npm-run-path-6/LICENSE +93 -0
  432. package/plugins/npm-run-path-6/NOTICE +51 -0
  433. package/plugins/npm-run-path-6/gemini-extension.json +1 -0
  434. package/plugins/npm-run-path-6/plugin.json +10 -0
  435. package/plugins/npm-run-path-6/skills/npm-run-path/SKILL.md +137 -0
  436. package/plugins/nyc-18/.claude-plugin/plugin.json +9 -0
  437. package/plugins/nyc-18/LICENSE +93 -0
  438. package/plugins/nyc-18/NOTICE +51 -0
  439. package/plugins/nyc-18/gemini-extension.json +1 -0
  440. package/plugins/nyc-18/plugin.json +10 -0
  441. package/plugins/nyc-18/skills/nyc/SKILL.md +152 -0
  442. package/plugins/ow-3/.claude-plugin/plugin.json +9 -0
  443. package/plugins/ow-3/LICENSE +93 -0
  444. package/plugins/ow-3/NOTICE +51 -0
  445. package/plugins/ow-3/gemini-extension.json +1 -0
  446. package/plugins/ow-3/plugin.json +10 -0
  447. package/plugins/ow-3/skills/ow/SKILL.md +159 -0
  448. package/plugins/pac-proxy-agent-9/.claude-plugin/plugin.json +9 -0
  449. package/plugins/pac-proxy-agent-9/LICENSE +93 -0
  450. package/plugins/pac-proxy-agent-9/NOTICE +51 -0
  451. package/plugins/pac-proxy-agent-9/gemini-extension.json +1 -0
  452. package/plugins/pac-proxy-agent-9/plugin.json +10 -0
  453. package/plugins/pac-proxy-agent-9/skills/pac-proxy-agent/SKILL.md +111 -0
  454. package/plugins/pgsql-ast-parser-12/.claude-plugin/plugin.json +9 -0
  455. package/plugins/pgsql-ast-parser-12/LICENSE +93 -0
  456. package/plugins/pgsql-ast-parser-12/NOTICE +51 -0
  457. package/plugins/pgsql-ast-parser-12/gemini-extension.json +1 -0
  458. package/plugins/pgsql-ast-parser-12/plugin.json +10 -0
  459. package/plugins/pgsql-ast-parser-12/skills/pgsql-ast-parser/SKILL.md +136 -0
  460. package/plugins/playwright-test-1/.claude-plugin/plugin.json +9 -0
  461. package/plugins/playwright-test-1/LICENSE +93 -0
  462. package/plugins/playwright-test-1/NOTICE +51 -0
  463. package/plugins/playwright-test-1/gemini-extension.json +1 -0
  464. package/plugins/playwright-test-1/plugin.json +10 -0
  465. package/plugins/playwright-test-1/skills/playwright-test/SKILL.md +222 -0
  466. package/plugins/pmcp/.claude-plugin/plugin.json +9 -0
  467. package/plugins/pmcp/.mcp.json +9 -0
  468. package/plugins/pmcp/LICENSE +93 -0
  469. package/plugins/pmcp/NOTICE +51 -0
  470. package/plugins/pmcp/gemini-extension.json +11 -0
  471. package/plugins/pmcp/mcp.json +10 -0
  472. package/plugins/pmcp/plugin.json +10 -0
  473. package/plugins/pmcp/skills/package-skill-catalog/SKILL.md +54 -0
  474. package/plugins/pothos-core-4/.claude-plugin/plugin.json +9 -0
  475. package/plugins/pothos-core-4/LICENSE +93 -0
  476. package/plugins/pothos-core-4/NOTICE +51 -0
  477. package/plugins/pothos-core-4/gemini-extension.json +1 -0
  478. package/plugins/pothos-core-4/plugin.json +10 -0
  479. package/plugins/pothos-core-4/skills/pothos-core/SKILL.md +68 -0
  480. package/plugins/prettier-3/.claude-plugin/plugin.json +9 -0
  481. package/plugins/prettier-3/LICENSE +93 -0
  482. package/plugins/prettier-3/NOTICE +51 -0
  483. package/plugins/prettier-3/gemini-extension.json +1 -0
  484. package/plugins/prettier-3/plugin.json +10 -0
  485. package/plugins/prettier-3/skills/prettier/SKILL.md +69 -0
  486. package/plugins/protobufjs-8/.claude-plugin/plugin.json +9 -0
  487. package/plugins/protobufjs-8/LICENSE +93 -0
  488. package/plugins/protobufjs-8/NOTICE +51 -0
  489. package/plugins/protobufjs-8/gemini-extension.json +1 -0
  490. package/plugins/protobufjs-8/plugin.json +10 -0
  491. package/plugins/protobufjs-8/skills/protobufjs/SKILL.md +128 -0
  492. package/plugins/proxy-agent-8/.claude-plugin/plugin.json +9 -0
  493. package/plugins/proxy-agent-8/LICENSE +93 -0
  494. package/plugins/proxy-agent-8/NOTICE +51 -0
  495. package/plugins/proxy-agent-8/gemini-extension.json +1 -0
  496. package/plugins/proxy-agent-8/plugin.json +10 -0
  497. package/plugins/proxy-agent-8/skills/proxy-agent/SKILL.md +120 -0
  498. package/plugins/pydantic-2/.claude-plugin/plugin.json +9 -0
  499. package/plugins/pydantic-2/LICENSE +93 -0
  500. package/plugins/pydantic-2/NOTICE +51 -0
  501. package/plugins/pydantic-2/gemini-extension.json +1 -0
  502. package/plugins/pydantic-2/plugin.json +10 -0
  503. package/plugins/pydantic-2/skills/pydantic/SKILL.md +74 -0
  504. package/plugins/react-19/.claude-plugin/plugin.json +9 -0
  505. package/plugins/react-19/LICENSE +93 -0
  506. package/plugins/react-19/NOTICE +51 -0
  507. package/plugins/react-19/gemini-extension.json +1 -0
  508. package/plugins/react-19/plugin.json +10 -0
  509. package/plugins/react-19/skills/react/SKILL.md +150 -0
  510. package/plugins/react-dom-19/.claude-plugin/plugin.json +9 -0
  511. package/plugins/react-dom-19/LICENSE +93 -0
  512. package/plugins/react-dom-19/NOTICE +51 -0
  513. package/plugins/react-dom-19/gemini-extension.json +1 -0
  514. package/plugins/react-dom-19/plugin.json +10 -0
  515. package/plugins/react-dom-19/skills/react-dom/SKILL.md +178 -0
  516. package/plugins/react-icons-5/.claude-plugin/plugin.json +9 -0
  517. package/plugins/react-icons-5/LICENSE +93 -0
  518. package/plugins/react-icons-5/NOTICE +51 -0
  519. package/plugins/react-icons-5/gemini-extension.json +1 -0
  520. package/plugins/react-icons-5/plugin.json +10 -0
  521. package/plugins/react-icons-5/skills/react-icons/SKILL.md +194 -0
  522. package/plugins/react-is-19/.claude-plugin/plugin.json +9 -0
  523. package/plugins/react-is-19/LICENSE +93 -0
  524. package/plugins/react-is-19/NOTICE +51 -0
  525. package/plugins/react-is-19/gemini-extension.json +1 -0
  526. package/plugins/react-is-19/plugin.json +10 -0
  527. package/plugins/react-is-19/skills/react-is/SKILL.md +131 -0
  528. package/plugins/react-markdown-10/.claude-plugin/plugin.json +9 -0
  529. package/plugins/react-markdown-10/LICENSE +93 -0
  530. package/plugins/react-markdown-10/NOTICE +51 -0
  531. package/plugins/react-markdown-10/gemini-extension.json +1 -0
  532. package/plugins/react-markdown-10/plugin.json +10 -0
  533. package/plugins/react-markdown-10/skills/react-markdown/SKILL.md +163 -0
  534. package/plugins/react-router-8/.claude-plugin/plugin.json +9 -0
  535. package/plugins/react-router-8/LICENSE +93 -0
  536. package/plugins/react-router-8/NOTICE +51 -0
  537. package/plugins/react-router-8/gemini-extension.json +1 -0
  538. package/plugins/react-router-8/plugin.json +10 -0
  539. package/plugins/react-router-8/skills/react-router/SKILL.md +115 -0
  540. package/plugins/release-it-21/.claude-plugin/plugin.json +9 -0
  541. package/plugins/release-it-21/LICENSE +93 -0
  542. package/plugins/release-it-21/NOTICE +51 -0
  543. package/plugins/release-it-21/gemini-extension.json +1 -0
  544. package/plugins/release-it-21/plugin.json +10 -0
  545. package/plugins/release-it-21/skills/release-it/SKILL.md +202 -0
  546. package/plugins/reselect-5/.claude-plugin/plugin.json +9 -0
  547. package/plugins/reselect-5/LICENSE +93 -0
  548. package/plugins/reselect-5/NOTICE +51 -0
  549. package/plugins/reselect-5/gemini-extension.json +1 -0
  550. package/plugins/reselect-5/plugin.json +10 -0
  551. package/plugins/reselect-5/skills/reselect/SKILL.md +215 -0
  552. package/plugins/responselike-4/.claude-plugin/plugin.json +9 -0
  553. package/plugins/responselike-4/LICENSE +93 -0
  554. package/plugins/responselike-4/NOTICE +51 -0
  555. package/plugins/responselike-4/gemini-extension.json +1 -0
  556. package/plugins/responselike-4/plugin.json +10 -0
  557. package/plugins/responselike-4/skills/responselike/SKILL.md +173 -0
  558. package/plugins/rolldown-1/.claude-plugin/plugin.json +9 -0
  559. package/plugins/rolldown-1/LICENSE +93 -0
  560. package/plugins/rolldown-1/NOTICE +51 -0
  561. package/plugins/rolldown-1/gemini-extension.json +1 -0
  562. package/plugins/rolldown-1/plugin.json +10 -0
  563. package/plugins/rolldown-1/skills/rolldown/SKILL.md +182 -0
  564. package/plugins/semver-7/.claude-plugin/plugin.json +9 -0
  565. package/plugins/semver-7/LICENSE +93 -0
  566. package/plugins/semver-7/NOTICE +51 -0
  567. package/plugins/semver-7/gemini-extension.json +1 -0
  568. package/plugins/semver-7/plugin.json +10 -0
  569. package/plugins/semver-7/skills/semver/SKILL.md +55 -0
  570. package/plugins/serde-json-1/.claude-plugin/plugin.json +9 -0
  571. package/plugins/serde-json-1/LICENSE +93 -0
  572. package/plugins/serde-json-1/NOTICE +51 -0
  573. package/plugins/serde-json-1/gemini-extension.json +1 -0
  574. package/plugins/serde-json-1/plugin.json +10 -0
  575. package/plugins/serde-json-1/skills/serde-json/SKILL.md +68 -0
  576. package/plugins/sinon-22/.claude-plugin/plugin.json +9 -0
  577. package/plugins/sinon-22/LICENSE +93 -0
  578. package/plugins/sinon-22/NOTICE +51 -0
  579. package/plugins/sinon-22/gemini-extension.json +1 -0
  580. package/plugins/sinon-22/plugin.json +10 -0
  581. package/plugins/sinon-22/skills/sinon/SKILL.md +215 -0
  582. package/plugins/slice-ansi-9/.claude-plugin/plugin.json +9 -0
  583. package/plugins/slice-ansi-9/LICENSE +93 -0
  584. package/plugins/slice-ansi-9/NOTICE +51 -0
  585. package/plugins/slice-ansi-9/gemini-extension.json +1 -0
  586. package/plugins/slice-ansi-9/plugin.json +10 -0
  587. package/plugins/slice-ansi-9/skills/slice-ansi/SKILL.md +111 -0
  588. package/plugins/smol-toml-1/.claude-plugin/plugin.json +9 -0
  589. package/plugins/smol-toml-1/LICENSE +93 -0
  590. package/plugins/smol-toml-1/NOTICE +51 -0
  591. package/plugins/smol-toml-1/gemini-extension.json +1 -0
  592. package/plugins/smol-toml-1/plugin.json +10 -0
  593. package/plugins/smol-toml-1/skills/smol-toml/SKILL.md +63 -0
  594. package/plugins/socks-proxy-agent-10/.claude-plugin/plugin.json +9 -0
  595. package/plugins/socks-proxy-agent-10/LICENSE +93 -0
  596. package/plugins/socks-proxy-agent-10/NOTICE +51 -0
  597. package/plugins/socks-proxy-agent-10/gemini-extension.json +1 -0
  598. package/plugins/socks-proxy-agent-10/plugin.json +10 -0
  599. package/plugins/socks-proxy-agent-10/skills/socks-proxy-agent/SKILL.md +172 -0
  600. package/plugins/string-width-8/.claude-plugin/plugin.json +9 -0
  601. package/plugins/string-width-8/LICENSE +93 -0
  602. package/plugins/string-width-8/NOTICE +51 -0
  603. package/plugins/string-width-8/gemini-extension.json +1 -0
  604. package/plugins/string-width-8/plugin.json +10 -0
  605. package/plugins/string-width-8/skills/string-width/SKILL.md +101 -0
  606. package/plugins/superstruct-2/.claude-plugin/plugin.json +9 -0
  607. package/plugins/superstruct-2/LICENSE +93 -0
  608. package/plugins/superstruct-2/NOTICE +51 -0
  609. package/plugins/superstruct-2/gemini-extension.json +1 -0
  610. package/plugins/superstruct-2/plugin.json +10 -0
  611. package/plugins/superstruct-2/skills/superstruct/SKILL.md +170 -0
  612. package/plugins/supports-color-11/.claude-plugin/plugin.json +9 -0
  613. package/plugins/supports-color-11/LICENSE +93 -0
  614. package/plugins/supports-color-11/NOTICE +51 -0
  615. package/plugins/supports-color-11/gemini-extension.json +1 -0
  616. package/plugins/supports-color-11/plugin.json +10 -0
  617. package/plugins/supports-color-11/skills/supports-color/SKILL.md +115 -0
  618. package/plugins/tailwindcss-3/.claude-plugin/plugin.json +9 -0
  619. package/plugins/tailwindcss-3/LICENSE +93 -0
  620. package/plugins/tailwindcss-3/NOTICE +51 -0
  621. package/plugins/tailwindcss-3/gemini-extension.json +1 -0
  622. package/plugins/tailwindcss-3/plugin.json +10 -0
  623. package/plugins/tailwindcss-3/skills/tailwindcss/SKILL.md +72 -0
  624. package/plugins/tailwindcss-4/.claude-plugin/plugin.json +9 -0
  625. package/plugins/tailwindcss-4/LICENSE +93 -0
  626. package/plugins/tailwindcss-4/NOTICE +51 -0
  627. package/plugins/tailwindcss-4/gemini-extension.json +1 -0
  628. package/plugins/tailwindcss-4/plugin.json +10 -0
  629. package/plugins/tailwindcss-4/skills/tailwindcss/SKILL.md +82 -0
  630. package/plugins/tanstack-react-router-1/.claude-plugin/plugin.json +9 -0
  631. package/plugins/tanstack-react-router-1/LICENSE +93 -0
  632. package/plugins/tanstack-react-router-1/NOTICE +51 -0
  633. package/plugins/tanstack-react-router-1/gemini-extension.json +1 -0
  634. package/plugins/tanstack-react-router-1/plugin.json +10 -0
  635. package/plugins/tanstack-react-router-1/skills/tanstack-react-router/SKILL.md +96 -0
  636. package/plugins/tedious-20/.claude-plugin/plugin.json +9 -0
  637. package/plugins/tedious-20/LICENSE +93 -0
  638. package/plugins/tedious-20/NOTICE +51 -0
  639. package/plugins/tedious-20/gemini-extension.json +1 -0
  640. package/plugins/tedious-20/plugin.json +10 -0
  641. package/plugins/tedious-20/skills/tedious/SKILL.md +174 -0
  642. package/plugins/testing-library-react-16/.claude-plugin/plugin.json +9 -0
  643. package/plugins/testing-library-react-16/LICENSE +93 -0
  644. package/plugins/testing-library-react-16/NOTICE +51 -0
  645. package/plugins/testing-library-react-16/gemini-extension.json +1 -0
  646. package/plugins/testing-library-react-16/plugin.json +10 -0
  647. package/plugins/testing-library-react-16/skills/testing-library-react/SKILL.md +92 -0
  648. package/plugins/tinyspy-4/.claude-plugin/plugin.json +9 -0
  649. package/plugins/tinyspy-4/LICENSE +93 -0
  650. package/plugins/tinyspy-4/NOTICE +51 -0
  651. package/plugins/tinyspy-4/gemini-extension.json +1 -0
  652. package/plugins/tinyspy-4/plugin.json +10 -0
  653. package/plugins/tinyspy-4/skills/tinyspy/SKILL.md +158 -0
  654. package/plugins/tldts-7/.claude-plugin/plugin.json +9 -0
  655. package/plugins/tldts-7/LICENSE +93 -0
  656. package/plugins/tldts-7/NOTICE +51 -0
  657. package/plugins/tldts-7/gemini-extension.json +1 -0
  658. package/plugins/tldts-7/plugin.json +10 -0
  659. package/plugins/tldts-7/skills/tldts/SKILL.md +120 -0
  660. package/plugins/ts-morph-28/.claude-plugin/plugin.json +9 -0
  661. package/plugins/ts-morph-28/LICENSE +93 -0
  662. package/plugins/ts-morph-28/NOTICE +51 -0
  663. package/plugins/ts-morph-28/gemini-extension.json +1 -0
  664. package/plugins/ts-morph-28/plugin.json +10 -0
  665. package/plugins/ts-morph-28/skills/ts-morph/SKILL.md +219 -0
  666. package/plugins/tsup-8/.claude-plugin/plugin.json +9 -0
  667. package/plugins/tsup-8/LICENSE +93 -0
  668. package/plugins/tsup-8/NOTICE +51 -0
  669. package/plugins/tsup-8/gemini-extension.json +1 -0
  670. package/plugins/tsup-8/plugin.json +10 -0
  671. package/plugins/tsup-8/skills/tsup/SKILL.md +97 -0
  672. package/plugins/tsx-4/.claude-plugin/plugin.json +9 -0
  673. package/plugins/tsx-4/LICENSE +93 -0
  674. package/plugins/tsx-4/NOTICE +51 -0
  675. package/plugins/tsx-4/gemini-extension.json +1 -0
  676. package/plugins/tsx-4/plugin.json +10 -0
  677. package/plugins/tsx-4/skills/tsx/SKILL.md +159 -0
  678. package/plugins/type-fest-5/.claude-plugin/plugin.json +9 -0
  679. package/plugins/type-fest-5/LICENSE +93 -0
  680. package/plugins/type-fest-5/NOTICE +51 -0
  681. package/plugins/type-fest-5/gemini-extension.json +1 -0
  682. package/plugins/type-fest-5/plugin.json +10 -0
  683. package/plugins/type-fest-5/skills/type-fest/SKILL.md +132 -0
  684. package/plugins/typescript-5/.claude-plugin/plugin.json +9 -0
  685. package/plugins/typescript-5/LICENSE +93 -0
  686. package/plugins/typescript-5/NOTICE +51 -0
  687. package/plugins/typescript-5/gemini-extension.json +1 -0
  688. package/plugins/typescript-5/plugin.json +10 -0
  689. package/plugins/typescript-5/skills/typescript/SKILL.md +107 -0
  690. package/plugins/typescript-eslint-8/.claude-plugin/plugin.json +9 -0
  691. package/plugins/typescript-eslint-8/LICENSE +93 -0
  692. package/plugins/typescript-eslint-8/NOTICE +51 -0
  693. package/plugins/typescript-eslint-8/gemini-extension.json +1 -0
  694. package/plugins/typescript-eslint-8/plugin.json +10 -0
  695. package/plugins/typescript-eslint-8/skills/typescript-eslint/SKILL.md +179 -0
  696. package/plugins/typescript-eslint-eslint-plugin-8/.claude-plugin/plugin.json +9 -0
  697. package/plugins/typescript-eslint-eslint-plugin-8/LICENSE +93 -0
  698. package/plugins/typescript-eslint-eslint-plugin-8/NOTICE +51 -0
  699. package/plugins/typescript-eslint-eslint-plugin-8/gemini-extension.json +1 -0
  700. package/plugins/typescript-eslint-eslint-plugin-8/plugin.json +10 -0
  701. package/plugins/typescript-eslint-eslint-plugin-8/skills/typescript-eslint-eslint-plugin/SKILL.md +158 -0
  702. package/plugins/typescript-eslint-estree-8/.claude-plugin/plugin.json +9 -0
  703. package/plugins/typescript-eslint-estree-8/LICENSE +93 -0
  704. package/plugins/typescript-eslint-estree-8/NOTICE +51 -0
  705. package/plugins/typescript-eslint-estree-8/gemini-extension.json +1 -0
  706. package/plugins/typescript-eslint-estree-8/plugin.json +10 -0
  707. package/plugins/typescript-eslint-estree-8/skills/typescript-eslint-estree/SKILL.md +125 -0
  708. package/plugins/typescript-eslint-parser-8/.claude-plugin/plugin.json +9 -0
  709. package/plugins/typescript-eslint-parser-8/LICENSE +93 -0
  710. package/plugins/typescript-eslint-parser-8/NOTICE +51 -0
  711. package/plugins/typescript-eslint-parser-8/gemini-extension.json +1 -0
  712. package/plugins/typescript-eslint-parser-8/plugin.json +10 -0
  713. package/plugins/typescript-eslint-parser-8/skills/typescript-eslint-parser/SKILL.md +141 -0
  714. package/plugins/typescript-eslint-types-8/.claude-plugin/plugin.json +9 -0
  715. package/plugins/typescript-eslint-types-8/LICENSE +93 -0
  716. package/plugins/typescript-eslint-types-8/NOTICE +51 -0
  717. package/plugins/typescript-eslint-types-8/gemini-extension.json +1 -0
  718. package/plugins/typescript-eslint-types-8/plugin.json +10 -0
  719. package/plugins/typescript-eslint-types-8/skills/typescript-eslint-types/SKILL.md +117 -0
  720. package/plugins/typescript-eslint-utils-8/.claude-plugin/plugin.json +9 -0
  721. package/plugins/typescript-eslint-utils-8/LICENSE +93 -0
  722. package/plugins/typescript-eslint-utils-8/NOTICE +51 -0
  723. package/plugins/typescript-eslint-utils-8/gemini-extension.json +1 -0
  724. package/plugins/typescript-eslint-utils-8/plugin.json +10 -0
  725. package/plugins/typescript-eslint-utils-8/skills/typescript-eslint-utils/SKILL.md +195 -0
  726. package/plugins/typescript-eslint-visitor-keys-8/.claude-plugin/plugin.json +9 -0
  727. package/plugins/typescript-eslint-visitor-keys-8/LICENSE +93 -0
  728. package/plugins/typescript-eslint-visitor-keys-8/NOTICE +51 -0
  729. package/plugins/typescript-eslint-visitor-keys-8/gemini-extension.json +1 -0
  730. package/plugins/typescript-eslint-visitor-keys-8/plugin.json +10 -0
  731. package/plugins/typescript-eslint-visitor-keys-8/skills/typescript-eslint-visitor-keys/SKILL.md +116 -0
  732. package/plugins/valibot-1/.claude-plugin/plugin.json +9 -0
  733. package/plugins/valibot-1/LICENSE +93 -0
  734. package/plugins/valibot-1/NOTICE +51 -0
  735. package/plugins/valibot-1/gemini-extension.json +1 -0
  736. package/plugins/valibot-1/plugin.json +10 -0
  737. package/plugins/valibot-1/skills/valibot/SKILL.md +190 -0
  738. package/plugins/vite-7/.claude-plugin/plugin.json +9 -0
  739. package/plugins/vite-7/LICENSE +93 -0
  740. package/plugins/vite-7/NOTICE +51 -0
  741. package/plugins/vite-7/gemini-extension.json +1 -0
  742. package/plugins/vite-7/plugin.json +10 -0
  743. package/plugins/vite-7/skills/vite/SKILL.md +111 -0
  744. package/plugins/vite-8/.claude-plugin/plugin.json +9 -0
  745. package/plugins/vite-8/LICENSE +93 -0
  746. package/plugins/vite-8/NOTICE +51 -0
  747. package/plugins/vite-8/gemini-extension.json +1 -0
  748. package/plugins/vite-8/plugin.json +10 -0
  749. package/plugins/vite-8/skills/vite/SKILL.md +267 -0
  750. package/plugins/vitejs-plugin-react-5/.claude-plugin/plugin.json +9 -0
  751. package/plugins/vitejs-plugin-react-5/LICENSE +93 -0
  752. package/plugins/vitejs-plugin-react-5/NOTICE +51 -0
  753. package/plugins/vitejs-plugin-react-5/gemini-extension.json +1 -0
  754. package/plugins/vitejs-plugin-react-5/plugin.json +10 -0
  755. package/plugins/vitejs-plugin-react-5/skills/vitejs-plugin-react/SKILL.md +67 -0
  756. package/plugins/vitejs-plugin-react-6/.claude-plugin/plugin.json +9 -0
  757. package/plugins/vitejs-plugin-react-6/LICENSE +93 -0
  758. package/plugins/vitejs-plugin-react-6/NOTICE +51 -0
  759. package/plugins/vitejs-plugin-react-6/gemini-extension.json +1 -0
  760. package/plugins/vitejs-plugin-react-6/plugin.json +10 -0
  761. package/plugins/vitejs-plugin-react-6/skills/vitejs-plugin-react/SKILL.md +232 -0
  762. package/plugins/vitest-4/.claude-plugin/plugin.json +9 -0
  763. package/plugins/vitest-4/LICENSE +93 -0
  764. package/plugins/vitest-4/NOTICE +51 -0
  765. package/plugins/vitest-4/gemini-extension.json +1 -0
  766. package/plugins/vitest-4/plugin.json +10 -0
  767. package/plugins/vitest-4/skills/vitest/SKILL.md +127 -0
  768. package/plugins/vitest-5/.claude-plugin/plugin.json +9 -0
  769. package/plugins/vitest-5/LICENSE +93 -0
  770. package/plugins/vitest-5/NOTICE +51 -0
  771. package/plugins/vitest-5/gemini-extension.json +1 -0
  772. package/plugins/vitest-5/plugin.json +10 -0
  773. package/plugins/vitest-5/skills/vitest/SKILL.md +186 -0
  774. package/plugins/whatwg-mimetype-5/.claude-plugin/plugin.json +9 -0
  775. package/plugins/whatwg-mimetype-5/LICENSE +93 -0
  776. package/plugins/whatwg-mimetype-5/NOTICE +51 -0
  777. package/plugins/whatwg-mimetype-5/gemini-extension.json +1 -0
  778. package/plugins/whatwg-mimetype-5/plugin.json +10 -0
  779. package/plugins/whatwg-mimetype-5/skills/whatwg-mimetype/SKILL.md +150 -0
  780. package/plugins/wrangler-4/.claude-plugin/plugin.json +9 -0
  781. package/plugins/wrangler-4/LICENSE +93 -0
  782. package/plugins/wrangler-4/NOTICE +51 -0
  783. package/plugins/wrangler-4/gemini-extension.json +1 -0
  784. package/plugins/wrangler-4/plugin.json +10 -0
  785. package/plugins/wrangler-4/skills/wrangler/SKILL.md +87 -0
  786. package/plugins/wrap-ansi-10/.claude-plugin/plugin.json +9 -0
  787. package/plugins/wrap-ansi-10/LICENSE +93 -0
  788. package/plugins/wrap-ansi-10/NOTICE +51 -0
  789. package/plugins/wrap-ansi-10/gemini-extension.json +1 -0
  790. package/plugins/wrap-ansi-10/plugin.json +10 -0
  791. package/plugins/wrap-ansi-10/skills/wrap-ansi/SKILL.md +119 -0
  792. package/plugins/yaml-2/.claude-plugin/plugin.json +9 -0
  793. package/plugins/yaml-2/LICENSE +93 -0
  794. package/plugins/yaml-2/NOTICE +51 -0
  795. package/plugins/yaml-2/gemini-extension.json +1 -0
  796. package/plugins/yaml-2/plugin.json +10 -0
  797. package/plugins/yaml-2/skills/yaml/SKILL.md +56 -0
  798. package/plugins/yargs-18/.claude-plugin/plugin.json +9 -0
  799. package/plugins/yargs-18/LICENSE +93 -0
  800. package/plugins/yargs-18/NOTICE +51 -0
  801. package/plugins/yargs-18/gemini-extension.json +1 -0
  802. package/plugins/yargs-18/plugin.json +10 -0
  803. package/plugins/yargs-18/skills/yargs/SKILL.md +175 -0
  804. package/plugins/yargs-parser-22/.claude-plugin/plugin.json +9 -0
  805. package/plugins/yargs-parser-22/LICENSE +93 -0
  806. package/plugins/yargs-parser-22/NOTICE +51 -0
  807. package/plugins/yargs-parser-22/gemini-extension.json +1 -0
  808. package/plugins/yargs-parser-22/plugin.json +10 -0
  809. package/plugins/yargs-parser-22/skills/yargs-parser/SKILL.md +179 -0
  810. package/plugins/yeoman-environment-7/.claude-plugin/plugin.json +9 -0
  811. package/plugins/yeoman-environment-7/LICENSE +93 -0
  812. package/plugins/yeoman-environment-7/NOTICE +51 -0
  813. package/plugins/yeoman-environment-7/gemini-extension.json +1 -0
  814. package/plugins/yeoman-environment-7/plugin.json +10 -0
  815. package/plugins/yeoman-environment-7/skills/yeoman-environment/SKILL.md +136 -0
  816. package/plugins/z-schema-12/.claude-plugin/plugin.json +9 -0
  817. package/plugins/z-schema-12/LICENSE +93 -0
  818. package/plugins/z-schema-12/NOTICE +51 -0
  819. package/plugins/z-schema-12/gemini-extension.json +1 -0
  820. package/plugins/z-schema-12/plugin.json +10 -0
  821. package/plugins/z-schema-12/skills/z-schema/SKILL.md +179 -0
  822. package/plugins/zod-schema-validation-3/.claude-plugin/plugin.json +9 -0
  823. package/plugins/zod-schema-validation-3/LICENSE +93 -0
  824. package/plugins/zod-schema-validation-3/NOTICE +51 -0
  825. package/plugins/zod-schema-validation-3/gemini-extension.json +1 -0
  826. package/plugins/zod-schema-validation-3/plugin.json +10 -0
  827. package/plugins/zod-schema-validation-3/skills/zod-schema-validation/SKILL.md +188 -0
  828. package/plugins/zod-schema-validation-4/.claude-plugin/plugin.json +9 -0
  829. package/plugins/zod-schema-validation-4/LICENSE +93 -0
  830. package/plugins/zod-schema-validation-4/NOTICE +51 -0
  831. package/plugins/zod-schema-validation-4/gemini-extension.json +1 -0
  832. package/plugins/zod-schema-validation-4/plugin.json +10 -0
  833. package/plugins/zod-schema-validation-4/skills/zod-schema-validation/SKILL.md +181 -0
  834. package/plugins/zod-validation-error-5/.claude-plugin/plugin.json +9 -0
  835. package/plugins/zod-validation-error-5/LICENSE +93 -0
  836. package/plugins/zod-validation-error-5/NOTICE +51 -0
  837. package/plugins/zod-validation-error-5/gemini-extension.json +1 -0
  838. package/plugins/zod-validation-error-5/plugin.json +10 -0
  839. package/plugins/zod-validation-error-5/skills/zod-validation-error/SKILL.md +212 -0
  840. package/plugins/zustand-5/.claude-plugin/plugin.json +9 -0
  841. package/plugins/zustand-5/LICENSE +93 -0
  842. package/plugins/zustand-5/NOTICE +51 -0
  843. package/plugins/zustand-5/gemini-extension.json +1 -0
  844. package/plugins/zustand-5/plugin.json +10 -0
  845. package/plugins/zustand-5/skills/zustand/SKILL.md +128 -0
  846. package/skills/package-skill-catalog/SKILL.md +37 -222
package/dist/cli.js CHANGED
@@ -159,8 +159,8 @@ var init_encoder = __esm({
159
159
  });
160
160
 
161
161
  // src/config.ts
162
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
163
- import { dirname as dirname3, join as join3, resolve as resolve3 } from "path";
162
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
163
+ import { dirname as dirname3, join as join4, resolve as resolve4 } from "path";
164
164
  import { parse as parse2 } from "smol-toml";
165
165
  function embeddingSection(path, dir, value) {
166
166
  if (value === void 0) return void 0;
@@ -227,8 +227,8 @@ function embeddingSection(path, dir, value) {
227
227
  revision: string("revision"),
228
228
  encoder,
229
229
  enabled: section.enabled,
230
- modelPath: modelPath === void 0 ? void 0 : resolve3(dir, modelPath),
231
- cacheDir: cacheDir === void 0 ? void 0 : resolve3(dir, cacheDir)
230
+ modelPath: modelPath === void 0 ? void 0 : resolve4(dir, modelPath),
231
+ cacheDir: cacheDir === void 0 ? void 0 : resolve4(dir, cacheDir)
232
232
  };
233
233
  try {
234
234
  resolveEncoder(result.modelId, result);
@@ -241,10 +241,10 @@ function embeddingSection(path, dir, value) {
241
241
  return result;
242
242
  }
243
243
  function findConfig(start2) {
244
- let dir = resolve3(start2);
244
+ let dir = resolve4(start2);
245
245
  for (; ; ) {
246
- const candidate2 = join3(dir, CONFIG_FILE);
247
- if (existsSync3(candidate2)) return candidate2;
246
+ const candidate2 = join4(dir, CONFIG_FILE);
247
+ if (existsSync4(candidate2)) return candidate2;
248
248
  const parent = dirname3(dir);
249
249
  if (parent === dir) return null;
250
250
  dir = parent;
@@ -257,11 +257,11 @@ function stringList(path, key, value) {
257
257
  return value;
258
258
  }
259
259
  function readConfig(path) {
260
- const absolute2 = resolve3(path);
260
+ const absolute2 = resolve4(path);
261
261
  const dir = dirname3(absolute2);
262
262
  let raw;
263
263
  try {
264
- raw = parse2(readFileSync3(absolute2, "utf8"));
264
+ raw = parse2(readFileSync4(absolute2, "utf8"));
265
265
  } catch (error) {
266
266
  const reason = error instanceof Error ? error.message : "unreadable";
267
267
  throw new ConfigError(absolute2, reason.split("\n")[0] ?? reason);
@@ -279,10 +279,22 @@ function readConfig(path) {
279
279
  if (!CATALOG_KEYS.has(key)) {
280
280
  throw new ConfigError(absolute2, `unknown key [catalog] ${key}`);
281
281
  }
282
+ if (key === "builtin") {
283
+ if (typeof value !== "boolean")
284
+ throw new ConfigError(absolute2, "[catalog] builtin must be a boolean");
285
+ catalog[key] = value;
286
+ continue;
287
+ }
282
288
  const list2 = stringList(absolute2, key, value);
283
- catalog[key] = key === "scopes" ? list2 : list2.map((p) => resolve3(dir, p));
289
+ catalog[key] = key === "scopes" ? list2 : list2.map((p) => resolve4(dir, p));
284
290
  }
285
- return { path: absolute2, dir, catalog, raw, ...configured };
291
+ return {
292
+ path: absolute2,
293
+ dir,
294
+ catalog,
295
+ raw,
296
+ ...configured
297
+ };
286
298
  }
287
299
  var CONFIG_FILE, ConfigError, PATH_KEYS, CATALOG_KEYS;
288
300
  var init_config = __esm({
@@ -297,7 +309,11 @@ var init_config = __esm({
297
309
  }
298
310
  };
299
311
  PATH_KEYS = ["roots", "workspaces", "packages", "marketplaces"];
300
- CATALOG_KEYS = /* @__PURE__ */ new Set([...PATH_KEYS, "scopes"]);
312
+ CATALOG_KEYS = /* @__PURE__ */ new Set([
313
+ ...PATH_KEYS,
314
+ "scopes",
315
+ "builtin"
316
+ ]);
301
317
  }
302
318
  });
303
319
 
@@ -448,17 +464,17 @@ import { randomUUID } from "crypto";
448
464
  import {
449
465
  closeSync,
450
466
  constants,
451
- existsSync as existsSync5,
467
+ existsSync as existsSync7,
452
468
  fstatSync,
453
469
  mkdirSync as mkdirSync2,
454
470
  openSync,
455
- readFileSync as readFileSync9,
471
+ readFileSync as readFileSync11,
456
472
  renameSync,
457
473
  rmSync,
458
474
  writeFileSync
459
475
  } from "fs";
460
476
  import { homedir } from "os";
461
- import { dirname as dirname8, join as join7, resolve as resolve6 } from "path";
477
+ import { dirname as dirname9, join as join9, resolve as resolve7 } from "path";
462
478
  import { z as z12 } from "zod";
463
479
  function mailboxConfigFrom(project2, env = process.env) {
464
480
  if (project2.raw.mailbox === void 0) return void 0;
@@ -466,17 +482,17 @@ function mailboxConfigFrom(project2, env = process.env) {
466
482
  if (!parsed.success)
467
483
  throw new MailboxError("invalid_config", "Invalid [mailbox] configuration");
468
484
  const section = parsed.data;
469
- const stateRoot = env.XDG_STATE_HOME ?? join7(homedir(), ".local/state");
470
- const stateDir = section.state_dir ? resolve6(project2.dir, section.state_dir) : join7(stateRoot, "pmcp/projects", section.project_id);
485
+ const stateRoot = env.XDG_STATE_HOME ?? join9(homedir(), ".local/state");
486
+ const stateDir = section.state_dir ? resolve7(project2.dir, section.state_dir) : join9(stateRoot, "pmcp/projects", section.project_id);
471
487
  return {
472
488
  projectId: section.project_id,
473
489
  enabled: section.enabled,
474
- databasePath: join7(stateDir, "mailbox.sqlite")
490
+ databasePath: join9(stateDir, "mailbox.sqlite")
475
491
  };
476
492
  }
477
493
  function initializeMailboxConfig(file2, stateDirectory2) {
478
- const path = resolve6(file2);
479
- const original = existsSync5(path) ? readFileSync9(path, "utf8") : void 0;
494
+ const path = resolve7(file2);
495
+ const original = existsSync7(path) ? readFileSync11(path, "utf8") : void 0;
480
496
  if (original !== void 0 && readConfig(path).raw.mailbox !== void 0) {
481
497
  throw new MailboxError("mailbox_exists", "Mailbox is already configured");
482
498
  }
@@ -491,14 +507,14 @@ function initializeMailboxConfig(file2, stateDirectory2) {
491
507
  const text3 = `${original ?? ""}
492
508
  ${lines2.join("\n")}
493
509
  `;
494
- mkdirSync2(dirname8(path), { recursive: true });
510
+ mkdirSync2(dirname9(path), { recursive: true });
495
511
  if (original === void 0) {
496
512
  writeFileSync(path, text3, { flag: "wx", mode: 384 });
497
513
  } else {
498
514
  const temporary = `${path}.${randomUUID()}.tmp`;
499
515
  try {
500
516
  writeFileSync(temporary, text3, { flag: "wx", mode: 384 });
501
- if (readFileSync9(path, "utf8") !== original) {
517
+ if (readFileSync11(path, "utf8") !== original) {
502
518
  throw new MailboxError(
503
519
  "config_conflict",
504
520
  "Configuration changed during initialization"
@@ -527,7 +543,7 @@ function readPrivateJson(file2) {
527
543
  "Credential file must belong to the current user"
528
544
  );
529
545
  }
530
- return JSON.parse(readFileSync9(descriptor, "utf8"));
546
+ return JSON.parse(readFileSync11(descriptor, "utf8"));
531
547
  } finally {
532
548
  closeSync(descriptor);
533
549
  }
@@ -539,7 +555,7 @@ function readBinding(file2) {
539
555
  return bindingSchema.parse(readPrivateJson(file2));
540
556
  }
541
557
  function writePrivateJson(file2, value) {
542
- mkdirSync2(dirname8(resolve6(file2)), { recursive: true, mode: 448 });
558
+ mkdirSync2(dirname9(resolve7(file2)), { recursive: true, mode: 448 });
543
559
  writeFileSync(file2, `${JSON.stringify(value, null, 2)}
544
560
  `, {
545
561
  flag: "wx",
@@ -547,7 +563,7 @@ function writePrivateJson(file2, value) {
547
563
  });
548
564
  }
549
565
  function writeBindingFile(file2, binding) {
550
- if (existsSync5(file2)) {
566
+ if (existsSync7(file2)) {
551
567
  const previous = readBinding(file2);
552
568
  if (previous.projectId !== binding.projectId || previous.actorId !== binding.actorId) {
553
569
  throw new MailboxError(
@@ -725,7 +741,7 @@ UPDATE mailbox_actors SET authority_expires_at_ms = created_at_ms + 60000 WHERE
725
741
 
726
742
  // src/mailbox/sqlite.ts
727
743
  import { chmodSync, mkdirSync as mkdirSync3 } from "fs";
728
- import { dirname as dirname9 } from "path";
744
+ import { dirname as dirname10 } from "path";
729
745
  import { setTimeout as delay } from "timers/promises";
730
746
  function storageError(error) {
731
747
  const detail = error instanceof Error ? error.message : "";
@@ -744,7 +760,7 @@ async function openDatabase2(file2) {
744
760
  let native2;
745
761
  try {
746
762
  if (file2 !== ":memory:")
747
- mkdirSync3(dirname9(file2), { recursive: true, mode: 448 });
763
+ mkdirSync3(dirname10(file2), { recursive: true, mode: 448 });
748
764
  native2 = (await openSqlite(file2)).db;
749
765
  if (file2 !== ":memory:") chmodSync(file2, 384);
750
766
  } catch (error) {
@@ -812,7 +828,7 @@ import {
812
828
  chmodSync as chmodSync2,
813
829
  copyFileSync,
814
830
  constants as constants2,
815
- existsSync as existsSync6,
831
+ existsSync as existsSync8,
816
832
  unlinkSync
817
833
  } from "fs";
818
834
  function hash(secret2) {
@@ -838,8 +854,8 @@ async function restoreBackup(source2, config) {
838
854
  probe.close();
839
855
  }
840
856
  store = await MailboxStore.open(config);
841
- const integrity = store.database.get("PRAGMA integrity_check");
842
- if (integrity?.integrity_check !== "ok" || store.database.all("PRAGMA foreign_key_check").length > 0) {
857
+ const integrity2 = store.database.get("PRAGMA integrity_check");
858
+ if (integrity2?.integrity_check !== "ok" || store.database.all("PRAGMA foreign_key_check").length > 0) {
843
859
  throw new MailboxError(
844
860
  "storage_corrupt",
845
861
  "Restored backup failed integrity checks"
@@ -1256,7 +1272,7 @@ var init_store = __esm({
1256
1272
  "Mailbox storage is closed"
1257
1273
  );
1258
1274
  }
1259
- if (existsSync6(destination)) {
1275
+ if (existsSync8(destination)) {
1260
1276
  throw new MailboxError(
1261
1277
  "destination_exists",
1262
1278
  "Backup destination already exists"
@@ -1580,7 +1596,7 @@ var init_service = __esm({
1580
1596
  });
1581
1597
 
1582
1598
  // src/harness/validation.ts
1583
- function object7(value) {
1599
+ function object8(value) {
1584
1600
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
1585
1601
  throw new Error("invalid_object");
1586
1602
  }
@@ -1665,11 +1681,11 @@ var init_layout = __esm({
1665
1681
  });
1666
1682
 
1667
1683
  // src/harness/adapters/process/artifact.ts
1668
- import { fileURLToPath as fileURLToPath2 } from "url";
1684
+ import { fileURLToPath as fileURLToPath3 } from "url";
1669
1685
  function artifact(name) {
1670
1686
  if (import.meta.url.endsWith(".ts"))
1671
- return fileURLToPath2(new URL(sources[name], import.meta.url));
1672
- return fileURLToPath2(new URL(`./harness-${name}.js`, import.meta.url));
1687
+ return fileURLToPath3(new URL(sources[name], import.meta.url));
1688
+ return fileURLToPath3(new URL(`./harness-${name}.js`, import.meta.url));
1673
1689
  }
1674
1690
  var sources;
1675
1691
  var init_artifact = __esm({
@@ -1700,9 +1716,9 @@ var init_registry = __esm({
1700
1716
  });
1701
1717
 
1702
1718
  // src/harness/runtimes/egress-policy.ts
1703
- import { isAbsolute as isAbsolute7, posix as posix3 } from "path";
1719
+ import { isAbsolute as isAbsolute8, posix as posix3 } from "path";
1704
1720
  function egressPolicy(value) {
1705
- const policy = object7(value);
1721
+ const policy = object8(value);
1706
1722
  const hosts = strings2(policy.hosts, "egress_hosts").map(
1707
1723
  (host) => host.toLowerCase()
1708
1724
  );
@@ -1716,7 +1732,7 @@ function egressPolicy(value) {
1716
1732
  }
1717
1733
  if (policy.bridgeExecutable === void 0) return { hosts };
1718
1734
  const executable = text(policy.bridgeExecutable, "egress_bridge_executable");
1719
- if (!isAbsolute7(executable) || posix3.normalize(executable) !== executable || /[\r\n\x1b]/.test(executable))
1735
+ if (!isAbsolute8(executable) || posix3.normalize(executable) !== executable || /[\r\n\x1b]/.test(executable))
1720
1736
  throw new Error("invalid_egress_bridge_executable");
1721
1737
  return { hosts, bridgeExecutable: executable };
1722
1738
  }
@@ -1728,7 +1744,7 @@ var init_egress_policy = __esm({
1728
1744
  });
1729
1745
 
1730
1746
  // src/harness/runtimes/private-profiles.ts
1731
- import { isAbsolute as isAbsolute8, posix as posix4 } from "path";
1747
+ import { isAbsolute as isAbsolute9, posix as posix4 } from "path";
1732
1748
  function profileName(value) {
1733
1749
  const name = text(value, "private_profile");
1734
1750
  if (!/^[a-z][a-z0-9-]{0,31}$/.test(name))
@@ -1736,13 +1752,13 @@ function profileName(value) {
1736
1752
  return name;
1737
1753
  }
1738
1754
  function privateProfiles(value) {
1739
- const entries = Object.entries(object7(value));
1755
+ const entries = Object.entries(object8(value));
1740
1756
  if (!entries.length || entries.length > 16)
1741
1757
  throw new Error("invalid_private_profile_grants");
1742
1758
  const result = {};
1743
1759
  for (const [name, entry2] of entries) {
1744
1760
  profileName(name);
1745
- const grant = object7(entry2);
1761
+ const grant = object8(entry2);
1746
1762
  const runtime2 = text(grant.runtime, "private_profile_runtime");
1747
1763
  const directory = absolute(grant.directory, "private_profile_directory");
1748
1764
  const lockExecutable = absolute(
@@ -1765,7 +1781,7 @@ function privateProfiles(value) {
1765
1781
  }
1766
1782
  function absolute(value, field) {
1767
1783
  const path = text(value, field);
1768
- if (!isAbsolute8(path) || posix4.normalize(path) !== path || /[\r\n\x1b]/.test(path))
1784
+ if (!isAbsolute9(path) || posix4.normalize(path) !== path || /[\r\n\x1b]/.test(path))
1769
1785
  throw new Error("invalid_private_profile_path");
1770
1786
  return path;
1771
1787
  }
@@ -1784,9 +1800,9 @@ var init_private_profiles = __esm({
1784
1800
  });
1785
1801
 
1786
1802
  // src/harness/runtimes/docker-policy.ts
1787
- import { isAbsolute as isAbsolute9, posix as posix5 } from "path";
1803
+ import { isAbsolute as isAbsolute10, posix as posix5 } from "path";
1788
1804
  function dockerPolicy(value) {
1789
- const policy = object7(value);
1805
+ const policy = object8(value);
1790
1806
  if (policy.schemaVersion !== 1)
1791
1807
  throw new Error("invalid_docker_policy_version");
1792
1808
  if (!/^sha256:[a-f0-9]{64}$/.test(text(policy.image, "docker_image")))
@@ -1795,7 +1811,7 @@ function dockerPolicy(value) {
1795
1811
  throw new Error("docker_network_not_qualified");
1796
1812
  if (policy.workspaceAccess !== "read-only" && policy.workspaceAccess !== "read-write")
1797
1813
  throw new Error("invalid_docker_workspace_access");
1798
- const commands = object7(policy.commands);
1814
+ const commands = object8(policy.commands);
1799
1815
  const entries = Object.entries(commands);
1800
1816
  if (!entries.length || entries.length > 5)
1801
1817
  throw new Error("invalid_docker_runtime_commands");
@@ -1805,7 +1821,7 @@ function dockerPolicy(value) {
1805
1821
  throw new Error("unsupported_docker_runtime");
1806
1822
  const command2 = strings2(value2, "docker_runtime_command");
1807
1823
  const executable = command2[0];
1808
- if (!isAbsolute9(executable) || posix5.normalize(executable) !== executable || command2.some((argument) => /[\r\n\x1b]/.test(argument)))
1824
+ if (!isAbsolute10(executable) || posix5.normalize(executable) !== executable || command2.some((argument) => /[\r\n\x1b]/.test(argument)))
1809
1825
  throw new Error("invalid_docker_runtime_command");
1810
1826
  parsed[runtime2] = command2;
1811
1827
  }
@@ -1836,15 +1852,15 @@ function member(value, allowed3) {
1836
1852
  function records(value) {
1837
1853
  if (!Array.isArray(value) || value.length > 4096)
1838
1854
  throw new Error("invalid_state_collection");
1839
- return value.map(object7);
1855
+ return value.map(object8);
1840
1856
  }
1841
1857
  function unique(values) {
1842
1858
  if (new Set(values).size !== values.length)
1843
1859
  throw new Error("duplicate_state_identity");
1844
1860
  }
1845
1861
  function validateState(value) {
1846
- const state = object7(value);
1847
- const group = object7(state.group);
1862
+ const state = object8(value);
1863
+ const group = object8(state.group);
1848
1864
  member(group.schemaVersion, [1]);
1849
1865
  for (const field of ["owner", "id", "generation"]) id(group[field], field);
1850
1866
  text(group.projectRoot, "project_root");
@@ -1911,12 +1927,12 @@ import {
1911
1927
  fstatSync as fstatSync2,
1912
1928
  fsyncSync,
1913
1929
  openSync as openSync3,
1914
- readFileSync as readFileSync29,
1915
- realpathSync as realpathSync3,
1930
+ readFileSync as readFileSync33,
1931
+ realpathSync as realpathSync4,
1916
1932
  renameSync as renameSync3,
1917
1933
  writeFileSync as writeFileSync9
1918
1934
  } from "fs";
1919
- import { dirname as dirname18, join as join23 } from "path";
1935
+ import { dirname as dirname19, join as join27 } from "path";
1920
1936
  function privateJson(path, value) {
1921
1937
  const temporary = `${path}.${randomUUID4()}.new`;
1922
1938
  const descriptor = openSync3(temporary, "wx", 384);
@@ -1928,7 +1944,7 @@ function privateJson(path, value) {
1928
1944
  closeSync3(descriptor);
1929
1945
  }
1930
1946
  renameSync3(temporary, path);
1931
- const directory = openSync3(dirname18(path), "r");
1947
+ const directory = openSync3(dirname19(path), "r");
1932
1948
  try {
1933
1949
  fsyncSync(directory);
1934
1950
  } finally {
@@ -1942,7 +1958,7 @@ function readPrivateJson2(path) {
1942
1958
  if (!stat.isFile() || (stat.mode & 63) !== 0 || stat.size > 2097152)
1943
1959
  throw new Error("unsafe_state_file");
1944
1960
  if (stat.uid !== process.getuid?.()) throw new Error("foreign_state_file");
1945
- return JSON.parse(readFileSync29(descriptor, "utf8"));
1961
+ return JSON.parse(readFileSync33(descriptor, "utf8"));
1946
1962
  } finally {
1947
1963
  closeSync3(descriptor);
1948
1964
  }
@@ -1957,10 +1973,10 @@ var init_store2 = __esm({
1957
1973
  path;
1958
1974
  state;
1959
1975
  constructor(path) {
1960
- this.path = realpathSync3(path);
1976
+ this.path = realpathSync4(path);
1961
1977
  this.state = validateState(readPrivateJson2(path));
1962
- const metadata2 = object7(
1963
- readPrivateJson2(join23(dirname18(this.path), "harness.json"))
1978
+ const metadata2 = object8(
1979
+ readPrivateJson2(join27(dirname19(this.path), "harness.json"))
1964
1980
  );
1965
1981
  if (this.state.group.schemaVersion !== 1 || this.state.group.owner !== metadata2.owner) {
1966
1982
  throw new Error("foreign_group");
@@ -1982,12 +1998,12 @@ var init_store2 = __esm({
1982
1998
  // src/harness/adapters/process/serialized.ts
1983
1999
  import { spawnSync as spawnSync4 } from "child_process";
1984
2000
  import { randomUUID as randomUUID5 } from "crypto";
1985
- import { existsSync as existsSync19, unlinkSync as unlinkSync2 } from "fs";
1986
- import { dirname as dirname19, join as join24 } from "path";
2001
+ import { existsSync as existsSync22, unlinkSync as unlinkSync2 } from "fs";
2002
+ import { dirname as dirname20, join as join28 } from "path";
1987
2003
  function serialized(operation) {
1988
2004
  const store = new GroupStore(text(operation.groupFile, "group_file"));
1989
- const directory = dirname19(store.path);
1990
- const operationFile = join24(directory, `operation-${randomUUID5()}.json`);
2005
+ const directory = dirname20(store.path);
2006
+ const operationFile = join28(directory, `operation-${randomUUID5()}.json`);
1991
2007
  privateJson(operationFile, operation);
1992
2008
  const worker = artifact("worker");
1993
2009
  try {
@@ -1999,7 +2015,7 @@ function serialized(operation) {
1999
2015
  "--no-fork",
2000
2016
  "--conflict-exit-code",
2001
2017
  "73",
2002
- join24(directory, "group-control.lock"),
2018
+ join28(directory, "group-control.lock"),
2003
2019
  process.execPath,
2004
2020
  worker,
2005
2021
  operationFile
@@ -2015,7 +2031,7 @@ function serialized(operation) {
2015
2031
  if (!result.stdout.trim()) throw new Error("worker_receipt_missing");
2016
2032
  return JSON.parse(result.stdout);
2017
2033
  } finally {
2018
- if (existsSync19(operationFile)) unlinkSync2(operationFile);
2034
+ if (existsSync22(operationFile)) unlinkSync2(operationFile);
2019
2035
  }
2020
2036
  }
2021
2037
  var init_serialized = __esm({
@@ -2050,9 +2066,9 @@ async function attachNative(spec, renew) {
2050
2066
  }, 2e4) : void 0;
2051
2067
  let exitCode;
2052
2068
  try {
2053
- exitCode = await new Promise((resolve19, reject) => {
2069
+ exitCode = await new Promise((resolve22, reject) => {
2054
2070
  client.once("error", reject);
2055
- client.once("exit", (code) => resolve19(code ?? 1));
2071
+ client.once("exit", (code) => resolve22(code ?? 1));
2056
2072
  });
2057
2073
  } finally {
2058
2074
  if (timer) clearInterval(timer);
@@ -2095,11 +2111,11 @@ var init_command = __esm({
2095
2111
  });
2096
2112
 
2097
2113
  // src/harness/adapters/process/identity.ts
2098
- import { readFileSync as readFileSync30 } from "fs";
2114
+ import { readFileSync as readFileSync34 } from "fs";
2099
2115
  function processIdentity(pid) {
2100
2116
  if (!Number.isSafeInteger(pid) || pid < 1)
2101
2117
  throw new Error("invalid_process_id");
2102
- const stat = readFileSync30(`/proc/${pid}/stat`, "utf8");
2118
+ const stat = readFileSync34(`/proc/${pid}/stat`, "utf8");
2103
2119
  const fields = stat.slice(stat.lastIndexOf(")") + 2).split(" ");
2104
2120
  if (!/^\d+$/.test(fields[19] ?? ""))
2105
2121
  throw new Error("process_identity_unknown");
@@ -2139,9 +2155,9 @@ var init_identity2 = __esm({
2139
2155
  });
2140
2156
 
2141
2157
  // src/harness/adapters/docker/claims.ts
2142
- import { createHash as createHash14 } from "crypto";
2158
+ import { createHash as createHash15 } from "crypto";
2143
2159
  function resourceClaim(value, owner) {
2144
- const record = object7(value);
2160
+ const record = object8(value);
2145
2161
  if (record.kind !== "docker" || record.owner !== owner)
2146
2162
  throw new Error("foreign_container_resource");
2147
2163
  if (!/^[a-f0-9]{64}$/.test(text(record.id, "container_id")))
@@ -2170,23 +2186,23 @@ function resourceClaim(value, owner) {
2170
2186
  return record;
2171
2187
  }
2172
2188
  function assertResourceOwner(resource, actual) {
2173
- const config = object7(actual.Config);
2174
- const labels = object7(config.Labels);
2189
+ const config = object8(actual.Config);
2190
+ const labels = object8(config.Labels);
2175
2191
  if (actual.Id !== resource.id || actual.Image !== resource.image || labels[containerLabels.owner] !== resource.owner || labels[containerLabels.nonce] !== resource.nonce || labels[containerLabels.role] !== resource.role)
2176
2192
  throw new Error("foreign_container_identity");
2177
2193
  }
2178
2194
  function configurationDigest(actual) {
2179
- const host = object7(actual.HostConfig);
2195
+ const host = object8(actual.HostConfig);
2180
2196
  if (host.OomKillDisable !== false && host.OomKillDisable !== null)
2181
2197
  throw new Error("container_oom_protection_disabled");
2182
2198
  if (!Array.isArray(actual.Mounts))
2183
2199
  throw new Error("invalid_container_mounts");
2184
- const mounts = actual.Mounts.map(object7).sort(
2200
+ const mounts = actual.Mounts.map(object8).sort(
2185
2201
  (left, right) => text(left.Destination, "mount_destination").localeCompare(
2186
2202
  text(right.Destination, "mount_destination")
2187
2203
  )
2188
2204
  );
2189
- return createHash14("sha256").update(
2205
+ return createHash15("sha256").update(
2190
2206
  JSON.stringify(
2191
2207
  canonicalValue({
2192
2208
  config: actual.Config,
@@ -2217,7 +2233,7 @@ function inspectResource(resource, enforceConfiguration = true) {
2217
2233
  const result = JSON.parse(command("docker", ["inspect", resource.id]));
2218
2234
  if (!Array.isArray(result) || result.length !== 1)
2219
2235
  throw new Error("invalid_container_inspection");
2220
- const actual = object7(result[0]);
2236
+ const actual = object8(result[0]);
2221
2237
  assertResourceOwner(resource, actual);
2222
2238
  if (enforceConfiguration && configurationDigest(actual) !== resource.configurationDigest)
2223
2239
  throw new Error("container_configuration_changed");
@@ -2231,7 +2247,7 @@ function resourceAbsent(error, id2) {
2231
2247
  );
2232
2248
  }
2233
2249
  function assertResourceFresh(resource) {
2234
- const state = object7(inspectResource(resource).State);
2250
+ const state = object8(inspectResource(resource).State);
2235
2251
  if (state.Status !== "created" || state.Running !== false || state.Pid !== 0)
2236
2252
  throw new Error("container_requires_fresh_creation");
2237
2253
  }
@@ -2243,7 +2259,7 @@ function resourceRunning(resource) {
2243
2259
  if (resourceAbsent(error, resource.id)) return false;
2244
2260
  throw error;
2245
2261
  }
2246
- const state = object7(actual.State);
2262
+ const state = object8(actual.State);
2247
2263
  if (typeof state.Running !== "boolean")
2248
2264
  throw new Error("unknown_container_lifecycle");
2249
2265
  return state.Running;
@@ -2331,17 +2347,17 @@ var init_connection = __esm({
2331
2347
  // src/harness/adapters/tmux/records.ts
2332
2348
  import { randomUUID as randomUUID6 } from "crypto";
2333
2349
  import {
2334
- lstatSync as lstatSync4,
2350
+ lstatSync as lstatSync5,
2335
2351
  mkdirSync as mkdirSync9,
2336
- readdirSync as readdirSync9,
2337
- realpathSync as realpathSync4,
2352
+ readdirSync as readdirSync10,
2353
+ realpathSync as realpathSync5,
2338
2354
  writeFileSync as writeFileSync10
2339
2355
  } from "fs";
2340
2356
  import { homedir as homedir7 } from "os";
2341
- import { join as join25 } from "path";
2357
+ import { join as join29 } from "path";
2342
2358
  function stateDirectory() {
2343
- return join25(
2344
- process.env.XDG_STATE_HOME ?? join25(homedir7(), ".local/state"),
2359
+ return join29(
2360
+ process.env.XDG_STATE_HOME ?? join29(homedir7(), ".local/state"),
2345
2361
  "pmcp/harness"
2346
2362
  );
2347
2363
  }
@@ -2368,17 +2384,17 @@ var init_records = __esm({
2368
2384
  configPath;
2369
2385
  owner;
2370
2386
  constructor(directory) {
2371
- const stat = lstatSync4(directory);
2387
+ const stat = lstatSync5(directory);
2372
2388
  if (!stat.isDirectory() || stat.uid !== process.getuid?.() || (stat.mode & 63) !== 0)
2373
2389
  throw new Error("unsafe_group_directory");
2374
- this.directory = realpathSync4(directory);
2375
- this.socket = join25(this.directory, "s");
2390
+ this.directory = realpathSync5(directory);
2391
+ this.socket = join29(this.directory, "s");
2376
2392
  if (Buffer.byteLength(this.socket) > 100)
2377
2393
  throw new Error("socket_path_too_long");
2378
- this.metadataPath = join25(this.directory, "harness.json");
2379
- this.configPath = join25(this.directory, "tmux.conf");
2394
+ this.metadataPath = join29(this.directory, "harness.json");
2395
+ this.configPath = join29(this.directory, "tmux.conf");
2380
2396
  this.owner = text(
2381
- object7(readPrivateJson2(this.metadataPath)).owner,
2397
+ object8(readPrivateJson2(this.metadataPath)).owner,
2382
2398
  "owner"
2383
2399
  );
2384
2400
  runtimeUnit(this.owner);
@@ -2386,17 +2402,17 @@ var init_records = __esm({
2386
2402
  static create() {
2387
2403
  const root = stateDirectory();
2388
2404
  mkdirSync9(root, { recursive: true, mode: 448 });
2389
- const directory = join25(root, randomUUID6().slice(0, 16));
2390
- if (Buffer.byteLength(join25(directory, "s")) > 100)
2405
+ const directory = join29(root, randomUUID6().slice(0, 16));
2406
+ if (Buffer.byteLength(join29(directory, "s")) > 100)
2391
2407
  throw new Error("socket_path_too_long");
2392
2408
  mkdirSync9(directory, { mode: 448 });
2393
- mkdirSync9(join25(directory, "sessions"), { mode: 448 });
2394
- privateJson(join25(directory, "harness.json"), {
2409
+ mkdirSync9(join29(directory, "sessions"), { mode: 448 });
2410
+ privateJson(join29(directory, "harness.json"), {
2395
2411
  owner: randomUUID6(),
2396
2412
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
2397
2413
  });
2398
2414
  writeFileSync10(
2399
- join25(directory, "tmux.conf"),
2415
+ join29(directory, "tmux.conf"),
2400
2416
  [
2401
2417
  "set -g remain-on-exit on",
2402
2418
  "set -g history-limit 2000",
@@ -2412,10 +2428,10 @@ var init_records = __esm({
2412
2428
  }
2413
2429
  path(id2) {
2414
2430
  runtimeUnit(id2);
2415
- return join25(this.directory, "sessions", `${id2}.json`);
2431
+ return join29(this.directory, "sessions", `${id2}.json`);
2416
2432
  }
2417
2433
  read(id2) {
2418
- const record = object7(readPrivateJson2(this.path(id2)));
2434
+ const record = object8(readPrivateJson2(this.path(id2)));
2419
2435
  if (record.id !== id2 || record.owner !== this.owner || record.socket !== this.socket || record.unit !== runtimeUnit(id2))
2420
2436
  throw new Error("foreign_backend_record");
2421
2437
  for (const [field, pattern] of [
@@ -2434,7 +2450,7 @@ var init_records = __esm({
2434
2450
  return record;
2435
2451
  }
2436
2452
  all() {
2437
- return readdirSync9(join25(this.directory, "sessions")).filter((name) => name.endsWith(".json")).map((name) => this.read(name.slice(0, -5)));
2453
+ return readdirSync10(join29(this.directory, "sessions")).filter((name) => name.endsWith(".json")).map((name) => this.read(name.slice(0, -5)));
2438
2454
  }
2439
2455
  save(record) {
2440
2456
  privateJson(this.path(record.id), record);
@@ -2515,17 +2531,17 @@ var init_launch_identity = __esm({
2515
2531
  });
2516
2532
 
2517
2533
  // src/harness/launch/journal.ts
2518
- import { createHash as createHash15 } from "crypto";
2519
- import { existsSync as existsSync20, readdirSync as readdirSync10 } from "fs";
2520
- import { join as join26 } from "path";
2534
+ import { createHash as createHash16 } from "crypto";
2535
+ import { existsSync as existsSync23, readdirSync as readdirSync11 } from "fs";
2536
+ import { join as join30 } from "path";
2521
2537
  function launchJournals(records2) {
2522
- return readdirSync10(records2.directory).filter((name) => name.endsWith(".intent.json")).map((name) => new LaunchJournal(records2, name.slice(0, -12)));
2538
+ return readdirSync11(records2.directory).filter((name) => name.endsWith(".intent.json")).map((name) => new LaunchJournal(records2, name.slice(0, -12)));
2523
2539
  }
2524
2540
  function pendingLaunches(records2) {
2525
2541
  return launchJournals(records2).filter((journal) => {
2526
2542
  const aborted = journal.abortRecord();
2527
2543
  if (aborted) return aborted.state !== "stopped";
2528
- if (!existsSync20(journal.path("committed"))) return true;
2544
+ if (!existsSync23(journal.path("committed"))) return true;
2529
2545
  journal.assertCommitted();
2530
2546
  return false;
2531
2547
  });
@@ -2552,10 +2568,10 @@ var init_journal = __esm({
2552
2568
  path(kind2) {
2553
2569
  if (!["intent", "proof", "grant", "committed", "aborted"].includes(kind2))
2554
2570
  throw new Error("invalid_launch_artifact");
2555
- return join26(this.records.directory, `${this.id}.${kind2}.json`);
2571
+ return join30(this.records.directory, `${this.id}.${kind2}.json`);
2556
2572
  }
2557
2573
  intent() {
2558
- const value = object7(readPrivateJson2(this.path("intent")));
2574
+ const value = object8(readPrivateJson2(this.path("intent")));
2559
2575
  if (value.id !== this.id || value.owner !== this.records.owner || value.socket !== this.records.socket || value.unit !== runtimeUnit(this.id) || value.slice !== budgetSlice(this.records.owner))
2560
2576
  throw new Error("foreign_launch_intent");
2561
2577
  if (!/^\d+:\d+$/.test(text(value.controllerIdentity, "controller")))
@@ -2572,28 +2588,28 @@ var init_journal = __esm({
2572
2588
  if (value.resource !== void 0)
2573
2589
  resourceClaim(value.resource, this.records.owner);
2574
2590
  if (value.dockerCreation !== void 0) {
2575
- const creation = object7(value.dockerCreation);
2576
- const config = object7(creation.configuration);
2577
- const labels = object7(config.Labels);
2591
+ const creation = object8(value.dockerCreation);
2592
+ const config = object8(creation.configuration);
2593
+ const labels = object8(config.Labels);
2578
2594
  if (creation.egress !== void 0) egressPolicy(creation.egress);
2579
2595
  const bridge = creation.egress === void 0 ? void 0 : egressPolicy(creation.egress).bridgeExecutable;
2580
2596
  if (bridge && !/^[a-f0-9]{64}$/.test(String(creation.bridgeSha256)))
2581
2597
  throw new Error("invalid_docker_bridge_digest");
2582
2598
  if (!bridge && creation.bridgeSha256 !== void 0)
2583
2599
  throw new Error("ungranted_docker_bridge_digest");
2584
- const policy = new GroupStore(join26(this.records.directory, "group.json")).state.group.dockerPolicy;
2600
+ const policy = new GroupStore(join30(this.records.directory, "group.json")).state.group.dockerPolicy;
2585
2601
  const profile = selectedProfile(
2586
2602
  policy,
2587
2603
  creation.privateProfile,
2588
2604
  text(value.runtime, "runtime")
2589
2605
  );
2590
- const expectedState = profile?.directory ?? join26(
2606
+ const expectedState = profile?.directory ?? join30(
2591
2607
  this.records.directory,
2592
2608
  "containers",
2593
2609
  text(value.nonce, "nonce"),
2594
2610
  "profile"
2595
2611
  );
2596
- if (value.resource !== void 0 && object7(value.resource).privateProfile !== creation.privateProfile)
2612
+ if (value.resource !== void 0 && object8(value.resource).privateProfile !== creation.privateProfile)
2597
2613
  throw new Error("launch_private_profile_mismatch");
2598
2614
  if (creation.name !== containerName(this.records.owner, this.id) || creation.nonce !== value.nonce || creation.state !== expectedState || labels[containerLabels.owner] !== this.records.owner || labels[containerLabels.role] !== value.role || labels[containerLabels.nonce] !== value.nonce)
2599
2615
  throw new Error("foreign_container_creation");
@@ -2602,8 +2618,8 @@ var init_journal = __esm({
2602
2618
  }
2603
2619
  proof() {
2604
2620
  const intent = this.intent();
2605
- const value = object7(readPrivateJson2(this.path("proof")));
2606
- const session = object7(value.session);
2621
+ const value = object8(readPrivateJson2(this.path("proof")));
2622
+ const session = object8(value.session);
2607
2623
  if (value.nonce !== intent.nonce || session.id !== intent.id || session.owner !== intent.owner || session.socket !== intent.socket || session.unit !== intent.unit || session.cwd !== intent.cwd || session.memoryMb !== intent.memoryMb || session.runtime !== intent.runtime || session.createdAt !== intent.createdAt || JSON.stringify(session.resource) !== JSON.stringify(intent.resource))
2608
2624
  throw new Error("foreign_launch_proof");
2609
2625
  for (const [field, pattern] of [
@@ -2628,12 +2644,12 @@ var init_journal = __esm({
2628
2644
  groupId: intent.groupId,
2629
2645
  generation: intent.generation,
2630
2646
  nonce: intent.nonce,
2631
- proofDigest: createHash15("sha256").update(JSON.stringify(this.proof())).digest("hex")
2647
+ proofDigest: createHash16("sha256").update(JSON.stringify(this.proof())).digest("hex")
2632
2648
  };
2633
2649
  }
2634
2650
  assertRegistered() {
2635
2651
  const intent = this.intent();
2636
- const group = new GroupStore(join26(this.records.directory, "group.json")).state.group;
2652
+ const group = new GroupStore(join30(this.records.directory, "group.json")).state.group;
2637
2653
  if (group.id !== intent.groupId || group.generation !== intent.generation)
2638
2654
  throw new Error("launch_group_generation_mismatch");
2639
2655
  if (intent.dockerCreation && JSON.stringify(intent.dockerCreation.egress) !== JSON.stringify(group.dockerPolicy?.egress))
@@ -2649,13 +2665,13 @@ var init_journal = __esm({
2649
2665
  throw new Error("launch_record_mismatch");
2650
2666
  }
2651
2667
  authorize() {
2652
- if (existsSync20(this.path("aborted"))) throw new Error("launch_was_aborted");
2668
+ if (existsSync23(this.path("aborted"))) throw new Error("launch_was_aborted");
2653
2669
  this.assertRegistered();
2654
2670
  privateJson(this.path("grant"), this.grant());
2655
2671
  }
2656
2672
  assertGrant() {
2657
- if (existsSync20(this.path("aborted"))) throw new Error("launch_was_aborted");
2658
- const grant = object7(readPrivateJson2(this.path("grant")));
2673
+ if (existsSync23(this.path("aborted"))) throw new Error("launch_was_aborted");
2674
+ const grant = object8(readPrivateJson2(this.path("grant")));
2659
2675
  if (JSON.stringify(grant) !== JSON.stringify(this.grant()))
2660
2676
  throw new Error("launch_grant_mismatch");
2661
2677
  }
@@ -2666,13 +2682,13 @@ var init_journal = __esm({
2666
2682
  }
2667
2683
  assertCommitted() {
2668
2684
  this.assertGrant();
2669
- const committed = object7(readPrivateJson2(this.path("committed")));
2685
+ const committed = object8(readPrivateJson2(this.path("committed")));
2670
2686
  if (JSON.stringify(committed) !== JSON.stringify(this.grant()))
2671
2687
  throw new Error("launch_commit_mismatch");
2672
2688
  }
2673
2689
  abortRecord() {
2674
- if (!existsSync20(this.path("aborted"))) return;
2675
- const value = object7(readPrivateJson2(this.path("aborted")));
2690
+ if (!existsSync23(this.path("aborted"))) return;
2691
+ const value = object8(readPrivateJson2(this.path("aborted")));
2676
2692
  if (value.id !== this.id || value.owner !== this.records.owner || !["stopping", "stopped"].includes(String(value.state)))
2677
2693
  throw new Error("foreign_launch_abort");
2678
2694
  return value;
@@ -2690,10 +2706,10 @@ function stopResource(resource) {
2690
2706
  if (resourceAbsent(error, resource.id)) return;
2691
2707
  throw error;
2692
2708
  }
2693
- const state = object7(actual.State);
2709
+ const state = object8(actual.State);
2694
2710
  if (state.Running === true)
2695
2711
  command("docker", ["stop", "--timeout", "2", resource.id]);
2696
- if (object7(inspectResource(resource, false).State).Running !== false)
2712
+ if (object8(inspectResource(resource, false).State).Running !== false)
2697
2713
  throw new Error("container_stop_unconfirmed");
2698
2714
  if (resource.managed) {
2699
2715
  command("docker", ["rm", resource.id]);
@@ -2720,28 +2736,28 @@ import { homedir as homedir8 } from "os";
2720
2736
  import {
2721
2737
  closeSync as closeSync4,
2722
2738
  constants as constants4,
2723
- existsSync as existsSync21,
2739
+ existsSync as existsSync24,
2724
2740
  fstatSync as fstatSync3,
2725
- lstatSync as lstatSync5,
2741
+ lstatSync as lstatSync6,
2726
2742
  openSync as openSync4,
2727
- realpathSync as realpathSync5,
2743
+ realpathSync as realpathSync6,
2728
2744
  statfsSync
2729
2745
  } from "fs";
2730
- import { join as join27, relative as relative10 } from "path";
2746
+ import { join as join31, relative as relative11 } from "path";
2731
2747
  function overlap(left, right) {
2732
- const scope = relative10(left, right);
2748
+ const scope = relative11(left, right);
2733
2749
  return scope === "" || scope !== ".." && !scope.startsWith("../");
2734
2750
  }
2735
2751
  function profileIdentity(directory, projectRoot) {
2736
- if (directory === "/" || directory === realpathSync5(homedir8()) || overlap(directory, projectRoot) || overlap(projectRoot, directory) || realpathSync5(directory) !== directory)
2752
+ if (directory === "/" || directory === realpathSync6(homedir8()) || overlap(directory, projectRoot) || overlap(projectRoot, directory) || realpathSync6(directory) !== directory)
2737
2753
  throw new Error("private_profile_scope_not_admitted");
2738
- const stat = lstatSync5(directory);
2754
+ const stat = lstatSync6(directory);
2739
2755
  if (!stat.isDirectory() || stat.uid !== process.getuid?.() || (stat.mode & 511) !== 448)
2740
2756
  throw new Error("unsafe_private_profile_directory");
2741
2757
  if ([26985, 4283649346, 4266872130].includes(statfsSync(directory).type))
2742
2758
  throw new Error("remote_private_profile_not_admitted");
2743
2759
  const lock = openSync4(
2744
- join27(directory, privateProfileLock),
2760
+ join31(directory, privateProfileLock),
2745
2761
  constants4.O_RDONLY | constants4.O_NOFOLLOW
2746
2762
  );
2747
2763
  try {
@@ -2754,14 +2770,14 @@ function profileIdentity(directory, projectRoot) {
2754
2770
  }
2755
2771
  }
2756
2772
  function captureProfile(grant, projectRoot) {
2757
- const directory = realpathSync5(grant.directory);
2758
- if (directory !== grant.directory || overlap(directory, projectRoot) || overlap(projectRoot, directory) || directory === "/" || directory === realpathSync5(homedir8()))
2773
+ const directory = realpathSync6(grant.directory);
2774
+ if (directory !== grant.directory || overlap(directory, projectRoot) || overlap(projectRoot, directory) || directory === "/" || directory === realpathSync6(homedir8()))
2759
2775
  throw new Error("private_profile_scope_not_admitted");
2760
- const stat = lstatSync5(directory);
2776
+ const stat = lstatSync6(directory);
2761
2777
  if (!stat.isDirectory() || stat.uid !== process.getuid?.() || (stat.mode & 511) !== 448)
2762
2778
  throw new Error("unsafe_private_profile_directory");
2763
- const lock = join27(directory, privateProfileLock);
2764
- if (!existsSync21(lock)) closeSync4(openSync4(lock, "wx", 384));
2779
+ const lock = join31(directory, privateProfileLock);
2780
+ if (!existsSync24(lock)) closeSync4(openSync4(lock, "wx", 384));
2765
2781
  const identity = profileIdentity(directory, projectRoot);
2766
2782
  if (grant.identity && grant.identity !== identity)
2767
2783
  throw new Error("private_profile_identity_changed");
@@ -2779,7 +2795,7 @@ function assertProfileAvailable(grant, projectRoot) {
2779
2795
  "--nonblock",
2780
2796
  "--conflict-exit-code",
2781
2797
  "73",
2782
- join27(grant.directory, privateProfileLock),
2798
+ join31(grant.directory, privateProfileLock),
2783
2799
  "true"
2784
2800
  ]);
2785
2801
  } catch (error) {
@@ -2799,8 +2815,8 @@ var init_private_profile = __esm({
2799
2815
 
2800
2816
  // src/harness/adapters/docker/profile.ts
2801
2817
  import { homedir as homedir9 } from "os";
2802
- import { lstatSync as lstatSync6, realpathSync as realpathSync6 } from "fs";
2803
- import { relative as relative11 } from "path";
2818
+ import { lstatSync as lstatSync7, realpathSync as realpathSync7 } from "fs";
2819
+ import { relative as relative12 } from "path";
2804
2820
  function assertLocalDocker() {
2805
2821
  if (process.env.DOCKER_HOST)
2806
2822
  throw new Error("explicit_docker_host_not_admitted");
@@ -2816,13 +2832,13 @@ function assertLocalDocker() {
2816
2832
  throw new Error("remote_docker_context_not_admitted");
2817
2833
  }
2818
2834
  function loadDockerPolicy(path, projectRoot, runtimes) {
2819
- if (projectRoot === "/" || projectRoot === realpathSync6(homedir9()))
2835
+ if (projectRoot === "/" || projectRoot === realpathSync7(homedir9()))
2820
2836
  throw new Error("docker_project_root_too_broad");
2821
2837
  const inputPath = text(path, "docker_policy_file");
2822
- if (lstatSync6(inputPath).isSymbolicLink())
2838
+ if (lstatSync7(inputPath).isSymbolicLink())
2823
2839
  throw new Error("symlink_docker_policy_not_admitted");
2824
- const source2 = realpathSync6(inputPath);
2825
- const scope = relative11(projectRoot, source2);
2840
+ const source2 = realpathSync7(inputPath);
2841
+ const scope = relative12(projectRoot, source2);
2826
2842
  if (scope === ".." || scope.startsWith("../"))
2827
2843
  throw new Error("docker_policy_outside_project");
2828
2844
  const policy = dockerPolicy(readPrivateJson2(source2));
@@ -2855,21 +2871,21 @@ var init_profile = __esm({
2855
2871
  });
2856
2872
 
2857
2873
  // src/harness/adapters/docker/mounts.ts
2858
- import { lstatSync as lstatSync7, realpathSync as realpathSync7 } from "fs";
2859
- import { join as join28 } from "path";
2874
+ import { lstatSync as lstatSync8, realpathSync as realpathSync8 } from "fs";
2875
+ import { join as join32 } from "path";
2860
2876
  function assertContainerMounts(actual, statePath, projectRoot, directory, nonce, policy, privateProfile, runtime2) {
2861
2877
  const state = text(statePath, "container_state_directory");
2862
2878
  const profile = selectedProfile(policy, privateProfile, runtime2 ?? "");
2863
2879
  if (profile) assertProfileIdentity(profile, projectRoot);
2864
- const expected = profile?.directory ?? join28(directory, "containers", nonce, "profile");
2865
- if (state !== expected || realpathSync7(state) !== expected)
2880
+ const expected = profile?.directory ?? join32(directory, "containers", nonce, "profile");
2881
+ if (state !== expected || realpathSync8(state) !== expected)
2866
2882
  throw new Error("foreign_container_state_directory");
2867
- const stat = lstatSync7(state);
2883
+ const stat = lstatSync8(state);
2868
2884
  if (!stat.isDirectory() || stat.uid !== process.getuid?.() || (stat.mode & 63) !== 0)
2869
2885
  throw new Error("unsafe_container_state_directory");
2870
2886
  if (!Array.isArray(actual.Mounts) || actual.Mounts.length !== 2)
2871
2887
  throw new Error("ungranted_container_mount");
2872
- if (new Set(actual.Mounts.map((value) => object7(value).Destination)).size !== 2)
2888
+ if (new Set(actual.Mounts.map((value) => object8(value).Destination)).size !== 2)
2873
2889
  throw new Error("ungranted_container_mount");
2874
2890
  const expectedMounts = [
2875
2891
  {
@@ -2880,15 +2896,15 @@ function assertContainerMounts(actual, statePath, projectRoot, directory, nonce,
2880
2896
  { Source: state, Destination: "/state", RW: true }
2881
2897
  ];
2882
2898
  for (const value of actual.Mounts) {
2883
- const mount = object7(value);
2899
+ const mount = object8(value);
2884
2900
  if (mount.Type !== "bind" || mount.Propagation !== "rprivate" || !expectedMounts.some(
2885
2901
  (expected2) => mount.Source === expected2.Source && mount.Destination === expected2.Destination && mount.RW === expected2.RW
2886
2902
  ))
2887
2903
  throw new Error("ungranted_container_mount");
2888
2904
  }
2889
- const host = object7(actual.HostConfig);
2905
+ const host = object8(actual.HostConfig);
2890
2906
  if (!Array.isArray(host.Mounts) || host.Mounts.length !== 2 || host.Mounts.some(
2891
- (value) => object7(object7(value).BindOptions).NonRecursive !== true
2907
+ (value) => object8(object8(value).BindOptions).NonRecursive !== true
2892
2908
  ))
2893
2909
  throw new Error("recursive_container_mount_not_admitted");
2894
2910
  }
@@ -2905,9 +2921,9 @@ var init_mounts = __esm({
2905
2921
  function assertContainerIsolation(host, network) {
2906
2922
  if (host.ReadonlyRootfs !== true || host.Privileged !== false || host.NetworkMode !== network || host.CgroupnsMode !== "private")
2907
2923
  throw new Error("invalid_container_isolation_policy");
2908
- if (JSON.stringify(host.CapDrop) !== '["ALL"]' || JSON.stringify(host.SecurityOpt) !== '["no-new-privileges"]' || object7(host.RestartPolicy).Name !== "no")
2924
+ if (JSON.stringify(host.CapDrop) !== '["ALL"]' || JSON.stringify(host.SecurityOpt) !== '["no-new-privileges"]' || object8(host.RestartPolicy).Name !== "no")
2909
2925
  throw new Error("invalid_container_execution_policy");
2910
- if (host.CapAdd !== null || host.PidMode !== "" || host.UTSMode !== "" || host.UsernsMode !== "" || host.CgroupParent !== "" || host.IpcMode !== "private" || hasDevices(host.Devices) || hasDevices(host.DeviceRequests) || host.AutoRemove !== false || host.VolumesFrom !== null || host.GroupAdd !== null || host.Binds !== null || Object.keys(object7(host.PortBindings)).length)
2926
+ if (host.CapAdd !== null || host.PidMode !== "" || host.UTSMode !== "" || host.UsernsMode !== "" || host.CgroupParent !== "" || host.IpcMode !== "private" || hasDevices(host.Devices) || hasDevices(host.DeviceRequests) || host.AutoRemove !== false || host.VolumesFrom !== null || host.GroupAdd !== null || host.Binds !== null || Object.keys(object8(host.PortBindings)).length)
2911
2927
  throw new Error("ungranted_container_host_authority");
2912
2928
  }
2913
2929
  function hasDevices(value) {
@@ -2956,21 +2972,21 @@ var init_entrypoint = __esm({
2956
2972
  });
2957
2973
 
2958
2974
  // src/harness/adapters/docker/admission.ts
2959
- import { lstatSync as lstatSync8, realpathSync as realpathSync8 } from "fs";
2960
- import { join as join29, relative as relative12 } from "path";
2975
+ import { lstatSync as lstatSync9, realpathSync as realpathSync9 } from "fs";
2976
+ import { join as join33, relative as relative13 } from "path";
2961
2977
  function admitResource(path, group, role, directory, memoryMb, runtime2) {
2962
2978
  if (group.profile !== "docker" || !group.dockerPolicy)
2963
2979
  throw new Error("container_requires_docker_profile");
2964
2980
  const { projectRoot } = group;
2965
2981
  assertLocalDocker();
2966
2982
  const inputPath = text(path, "container_file");
2967
- if (lstatSync8(inputPath).isSymbolicLink())
2983
+ if (lstatSync9(inputPath).isSymbolicLink())
2968
2984
  throw new Error("symlink_container_file_not_admitted");
2969
- const source2 = realpathSync8(inputPath);
2970
- const scope = relative12(projectRoot, source2);
2985
+ const source2 = realpathSync9(inputPath);
2986
+ const scope = relative13(projectRoot, source2);
2971
2987
  if (scope === ".." || scope.startsWith("../"))
2972
2988
  throw new Error("container_file_outside_project");
2973
- const claim = object7(readPrivateJson2(source2));
2989
+ const claim = object8(readPrivateJson2(source2));
2974
2990
  if (claim.privateProfile !== void 0)
2975
2991
  throw new Error("private_profile_requires_cli_owned_creation");
2976
2992
  return admitClaim(claim, group, role, directory, memoryMb, runtime2);
@@ -2981,7 +2997,7 @@ function admitClaim(value, group, role, directory, memoryMb, runtime2, cwd = gro
2981
2997
  assertLocalDocker();
2982
2998
  const policy = group.dockerPolicy;
2983
2999
  const { owner, projectRoot } = group;
2984
- const claim = object7(value);
3000
+ const claim = object8(value);
2985
3001
  if (claim.owner !== owner || claim.role !== role || claim.runtime !== runtime2)
2986
3002
  throw new Error("foreign_container_resource");
2987
3003
  const resource = {
@@ -3001,9 +3017,9 @@ function admitClaim(value, group, role, directory, memoryMb, runtime2, cwd = gro
3001
3017
  ))
3002
3018
  throw new Error("invalid_container_resource");
3003
3019
  const actual = inspectResource(resource, false);
3004
- const state = object7(actual.State);
3005
- const config = object7(actual.Config);
3006
- const host = object7(actual.HostConfig);
3020
+ const state = object8(actual.State);
3021
+ const config = object8(actual.Config);
3022
+ const host = object8(actual.HostConfig);
3007
3023
  if (resource.image !== policy.image || JSON.stringify(config.Entrypoint) !== JSON.stringify(
3008
3024
  containerEntrypoint(
3009
3025
  policy,
@@ -3013,7 +3029,7 @@ function admitClaim(value, group, role, directory, memoryMb, runtime2, cwd = gro
3013
3029
  )
3014
3030
  ))
3015
3031
  throw new Error("container_runtime_image_not_granted");
3016
- if (config.WorkingDir !== join29("/workspace", relative12(projectRoot, cwd)))
3032
+ if (config.WorkingDir !== join33("/workspace", relative13(projectRoot, cwd)))
3017
3033
  throw new Error("container_cwd_not_granted");
3018
3034
  assertContainerMounts(
3019
3035
  actual,
@@ -3092,7 +3108,7 @@ var init_engine = __esm({
3092
3108
  if (!/^1\.\d+$/.test(version2))
3093
3109
  throw new Error("invalid_docker_api_version");
3094
3110
  const payload = JSON.stringify(configuration);
3095
- return new Promise((resolve19, reject) => {
3111
+ return new Promise((resolve22, reject) => {
3096
3112
  const req = request2(
3097
3113
  {
3098
3114
  socketPath: new URL(endpoint).pathname,
@@ -3122,12 +3138,12 @@ var init_engine = __esm({
3122
3138
  }
3123
3139
  try {
3124
3140
  const id2 = text(
3125
- object7(JSON.parse(Buffer.concat(chunks).toString("utf8"))).Id,
3141
+ object8(JSON.parse(Buffer.concat(chunks).toString("utf8"))).Id,
3126
3142
  "container_id"
3127
3143
  );
3128
3144
  if (!/^[a-f0-9]{64}$/.test(id2))
3129
3145
  throw new Error("invalid_container_id");
3130
- resolve19(id2);
3146
+ resolve22(id2);
3131
3147
  } catch (error) {
3132
3148
  reject(error);
3133
3149
  }
@@ -3147,25 +3163,25 @@ var init_engine = __esm({
3147
3163
  });
3148
3164
 
3149
3165
  // src/harness/adapters/docker/bridge-artifact.ts
3150
- import { createHash as createHash16 } from "crypto";
3166
+ import { createHash as createHash17 } from "crypto";
3151
3167
  import {
3152
3168
  closeSync as closeSync5,
3153
3169
  constants as constants5,
3154
3170
  fstatSync as fstatSync4,
3155
3171
  fsyncSync as fsyncSync2,
3156
3172
  openSync as openSync5,
3157
- readFileSync as readFileSync31,
3173
+ readFileSync as readFileSync35,
3158
3174
  writeFileSync as writeFileSync11
3159
3175
  } from "fs";
3160
- import { join as join30 } from "path";
3176
+ import { join as join34 } from "path";
3161
3177
  function source() {
3162
3178
  const path = artifact("egress-bridge");
3163
3179
  if (!path.endsWith(".js"))
3164
3180
  throw new Error("docker_bridge_requires_compiled_cli");
3165
- return readFileSync31(path);
3181
+ return readFileSync35(path);
3166
3182
  }
3167
3183
  function digest(value) {
3168
- return createHash16("sha256").update(value).digest("hex");
3184
+ return createHash17("sha256").update(value).digest("hex");
3169
3185
  }
3170
3186
  function bridgeDigest() {
3171
3187
  return digest(source());
@@ -3176,7 +3192,7 @@ function prepareBridge(creation) {
3176
3192
  if (digest(content) !== creation.bridgeSha256)
3177
3193
  throw new Error("docker_bridge_source_changed");
3178
3194
  const descriptor = openSync5(
3179
- join30(creation.state, bridgeName(creation.nonce)),
3195
+ join34(creation.state, bridgeName(creation.nonce)),
3180
3196
  "wx",
3181
3197
  384
3182
3198
  );
@@ -3190,12 +3206,12 @@ function prepareBridge(creation) {
3190
3206
  function assertBridge(creation) {
3191
3207
  if (!creation.egress?.bridgeExecutable) return;
3192
3208
  const descriptor = openSync5(
3193
- join30(creation.state, bridgeName(creation.nonce)),
3209
+ join34(creation.state, bridgeName(creation.nonce)),
3194
3210
  constants5.O_RDONLY | constants5.O_NOFOLLOW
3195
3211
  );
3196
3212
  try {
3197
3213
  const stat = fstatSync4(descriptor);
3198
- if (!stat.isFile() || stat.uid !== process.getuid?.() || stat.nlink !== 1 || (stat.mode & 63) !== 0 || stat.size > 2097152 || digest(readFileSync31(descriptor)) !== creation.bridgeSha256)
3214
+ if (!stat.isFile() || stat.uid !== process.getuid?.() || stat.nlink !== 1 || (stat.mode & 63) !== 0 || stat.size > 2097152 || digest(readFileSync35(descriptor)) !== creation.bridgeSha256)
3199
3215
  throw new Error("docker_bridge_artifact_changed");
3200
3216
  } finally {
3201
3217
  closeSync5(descriptor);
@@ -3210,7 +3226,7 @@ var init_bridge_artifact = __esm({
3210
3226
  });
3211
3227
 
3212
3228
  // src/harness/adapters/docker/creation-plan.ts
3213
- import { join as join31, relative as relative13 } from "path";
3229
+ import { join as join35, relative as relative14 } from "path";
3214
3230
  function creationPlan(group, directory, id2, nonce, role, runtime2, cwd, preparation) {
3215
3231
  if (group.profile !== "docker" || !group.dockerPolicy)
3216
3232
  throw new Error("container_requires_docker_profile");
@@ -3219,15 +3235,15 @@ function creationPlan(group, directory, id2, nonce, role, runtime2, cwd, prepara
3219
3235
  const images = JSON.parse(
3220
3236
  command("docker", ["image", "inspect", policy.image])
3221
3237
  );
3222
- if (!Array.isArray(images) || images.length !== 1 || object7(images[0]).Id !== policy.image)
3238
+ if (!Array.isArray(images) || images.length !== 1 || object8(images[0]).Id !== policy.image)
3223
3239
  throw new Error("docker_image_not_available");
3224
- const imageConfig = object7(object7(images[0]).Config);
3240
+ const imageConfig = object8(object8(images[0]).Config);
3225
3241
  const environment2 = imageConfig.Env;
3226
3242
  if (!Array.isArray(environment2) || environment2.some((entry2) => typeof entry2 !== "string"))
3227
3243
  throw new Error("invalid_container_image_environment");
3228
3244
  const profile = selectedProfile(policy, preparation.privateProfile, runtime2);
3229
3245
  if (profile) assertProfileAvailable(profile, group.projectRoot);
3230
- const state = profile?.directory ?? join31(directory, "containers", nonce, "profile");
3246
+ const state = profile?.directory ?? join35(directory, "containers", nonce, "profile");
3231
3247
  return {
3232
3248
  name: containerName(group.owner, id2),
3233
3249
  nonce,
@@ -3244,7 +3260,7 @@ function creationPlan(group, directory, id2, nonce, role, runtime2, cwd, prepara
3244
3260
  preparation.privateProfile
3245
3261
  ),
3246
3262
  Cmd: preparation.args.length ? preparation.args : null,
3247
- WorkingDir: join31("/workspace", relative13(group.projectRoot, cwd)),
3263
+ WorkingDir: join35("/workspace", relative14(group.projectRoot, cwd)),
3248
3264
  User: `${process.getuid?.()}:${process.getgid?.()}`,
3249
3265
  Env: [
3250
3266
  ...environment2.filter(
@@ -3303,14 +3319,14 @@ function assertCreationConfiguration(actual, creation) {
3303
3319
  if (actual.Name !== `/${creation.name}`)
3304
3320
  throw new Error("foreign_container_creation");
3305
3321
  const expected = creation.configuration;
3306
- const config = object7(actual.Config);
3307
- const host = object7(actual.HostConfig);
3322
+ const config = object8(actual.Config);
3323
+ const host = object8(actual.HostConfig);
3308
3324
  for (const [key, value] of Object.entries(expected)) {
3309
3325
  if (key === "HostConfig" || key === "Image") continue;
3310
3326
  if (!matchesFields(config[key], value))
3311
3327
  throw new Error(`container_creation_configuration_changed_${key}`);
3312
3328
  }
3313
- for (const [key, value] of Object.entries(object7(expected.HostConfig))) {
3329
+ for (const [key, value] of Object.entries(object8(expected.HostConfig))) {
3314
3330
  if (!matchesFields(host[key], value))
3315
3331
  throw new Error(`container_creation_configuration_changed_${key}`);
3316
3332
  }
@@ -3343,12 +3359,12 @@ var init_creation_plan = __esm({
3343
3359
 
3344
3360
  // src/harness/adapters/docker/creation.ts
3345
3361
  import { mkdirSync as mkdirSync10 } from "fs";
3346
- import { join as join32 } from "path";
3362
+ import { join as join36 } from "path";
3347
3363
  async function prepareCreation(journal) {
3348
3364
  const intent = journal.intent();
3349
3365
  const creation = intent.dockerCreation;
3350
3366
  if (!creation) throw new Error("container_creation_missing");
3351
- const group = new GroupStore(join32(journal.records.directory, "group.json")).state.group;
3367
+ const group = new GroupStore(join36(journal.records.directory, "group.json")).state.group;
3352
3368
  const profile = selectedProfile(
3353
3369
  group.dockerPolicy,
3354
3370
  creation.privateProfile,
@@ -3362,7 +3378,7 @@ async function prepareCreation(journal) {
3362
3378
  creation.name,
3363
3379
  creation.configuration
3364
3380
  );
3365
- const current = new GroupStore(join32(journal.records.directory, "group.json")).state.group;
3381
+ const current = new GroupStore(join36(journal.records.directory, "group.json")).state.group;
3366
3382
  if (current.id !== intent.groupId || current.generation !== intent.generation)
3367
3383
  throw new Error("launch_group_generation_mismatch");
3368
3384
  const resource = {
@@ -3387,7 +3403,7 @@ async function prepareCreation(journal) {
3387
3403
  managed: true
3388
3404
  };
3389
3405
  assertCreationConfiguration(
3390
- object7(JSON.parse(command("docker", ["inspect", id2]))[0]),
3406
+ object8(JSON.parse(command("docker", ["inspect", id2]))[0]),
3391
3407
  creation
3392
3408
  );
3393
3409
  privateJson(journal.path("intent"), {
@@ -3409,7 +3425,7 @@ function findCreation(journal) {
3409
3425
  );
3410
3426
  if (!Array.isArray(values) || values.length !== 1)
3411
3427
  throw new Error("invalid_container_inspection");
3412
- actual = object7(values[0]);
3428
+ actual = object8(values[0]);
3413
3429
  } catch (error) {
3414
3430
  if (resourceAbsent(error, creation.name)) return;
3415
3431
  throw error;
@@ -3422,15 +3438,15 @@ function findCreation(journal) {
3422
3438
  role: intent.role,
3423
3439
  image: text(creation.configuration.Image, "container_image"),
3424
3440
  configurationDigest: configurationDigest(actual),
3425
- memoryMb: Number(object7(actual.HostConfig).Memory) / 1048576,
3426
- cpuQuota: Number(object7(actual.HostConfig).CpuQuota),
3441
+ memoryMb: Number(object8(actual.HostConfig).Memory) / 1048576,
3442
+ cpuQuota: Number(object8(actual.HostConfig).CpuQuota),
3427
3443
  managed: true,
3428
3444
  ...creation.privateProfile ? { privateProfile: creation.privateProfile } : {}
3429
3445
  };
3430
3446
  assertResourceOwner(resource, actual);
3431
3447
  assertCreationConfiguration(actual, creation);
3432
3448
  if (!intent.resource) {
3433
- const group = new GroupStore(join32(journal.records.directory, "group.json")).state.group;
3449
+ const group = new GroupStore(join36(journal.records.directory, "group.json")).state.group;
3434
3450
  return {
3435
3451
  ...admitClaim(
3436
3452
  { ...resource, runtime: intent.runtime, state: creation.state },
@@ -3467,7 +3483,7 @@ var init_creation = __esm({
3467
3483
  });
3468
3484
 
3469
3485
  // src/harness/launch/recovery.ts
3470
- import { existsSync as existsSync22 } from "fs";
3486
+ import { existsSync as existsSync25 } from "fs";
3471
3487
  function abortLaunch(connection, journal) {
3472
3488
  const intent = journal.intent();
3473
3489
  if (!controllerExited(intent.controllerIdentity))
@@ -3484,7 +3500,7 @@ function abortLaunch(connection, journal) {
3484
3500
  inputReplayed: false
3485
3501
  };
3486
3502
  }
3487
- if (!existsSync22(journal.path("proof"))) {
3503
+ if (!existsSync25(journal.path("proof"))) {
3488
3504
  const paneUnknown = connection.alive() && (!intent.dockerCreation || connection.tmux(["list-sessions", "-F", "#{session_name}"]).trim().split("\n").includes(`pmcp-${intent.id}`));
3489
3505
  if (paneUnknown || unitActive(intent.unit))
3490
3506
  throw new Error("launch_identity_unknown");
@@ -3511,7 +3527,7 @@ function abortLaunch(connection, journal) {
3511
3527
  assertProof(connection, proof);
3512
3528
  connection.tmux(["kill-pane", "-t", proof.session.paneId]);
3513
3529
  }
3514
- if (existsSync22(journal.records.path(intent.id)))
3530
+ if (existsSync25(journal.records.path(intent.id)))
3515
3531
  journal.records.save({
3516
3532
  ...proof.session,
3517
3533
  stoppedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -3538,9 +3554,9 @@ var init_recovery = __esm({
3538
3554
 
3539
3555
  // src/harness/adapters/tmux/lifecycle.ts
3540
3556
  import { randomUUID as randomUUID7 } from "crypto";
3541
- import { existsSync as existsSync23 } from "fs";
3557
+ import { existsSync as existsSync26 } from "fs";
3542
3558
  import { setTimeout as setTimeout2 } from "timers/promises";
3543
- import { join as join33 } from "path";
3559
+ import { join as join37 } from "path";
3544
3560
  async function start(connection, spec) {
3545
3561
  const records2 = connection.records;
3546
3562
  if (spec.budgetSlice !== budgetSlice(records2.owner))
@@ -3554,7 +3570,7 @@ async function start(connection, spec) {
3554
3570
  const nonce = randomUUID7();
3555
3571
  const journal = new LaunchJournal(records2, id2);
3556
3572
  const dockerCreation = spec.dockerPreparation ? creationPlan(
3557
- new GroupStore(join33(records2.directory, "group.json")).state.group,
3573
+ new GroupStore(join37(records2.directory, "group.json")).state.group,
3558
3574
  records2.directory,
3559
3575
  id2,
3560
3576
  nonce,
@@ -3614,7 +3630,7 @@ async function start(connection, spec) {
3614
3630
  `exec ${argv.map(quote2).join(" ")}`
3615
3631
  ]);
3616
3632
  const deadline = Date.now() + 5e3;
3617
- while (!existsSync23(journal.path("proof"))) {
3633
+ while (!existsSync26(journal.path("proof"))) {
3618
3634
  if (Date.now() >= deadline) throw new Error("launch_proof_timeout");
3619
3635
  await setTimeout2(25);
3620
3636
  }
@@ -3625,7 +3641,7 @@ async function start(connection, spec) {
3625
3641
  }
3626
3642
  function stop(connection, id2) {
3627
3643
  const journal = new LaunchJournal(connection.records, id2);
3628
- if (existsSync23(journal.path("intent"))) {
3644
+ if (existsSync26(journal.path("intent"))) {
3629
3645
  abortLaunch(connection, journal);
3630
3646
  return;
3631
3647
  }
@@ -3652,7 +3668,7 @@ function cleanup(connection) {
3652
3668
  }
3653
3669
  for (const record of records2) {
3654
3670
  if (record.resource) stopResource(record.resource);
3655
- if (record.stoppedAt || !existsSync23(
3671
+ if (record.stoppedAt || !existsSync26(
3656
3672
  new LaunchJournal(connection.records, record.id).path("intent")
3657
3673
  )) {
3658
3674
  stopUnit(record.unit);
@@ -3684,7 +3700,7 @@ var init_lifecycle2 = __esm({
3684
3700
  // src/harness/adapters/tmux/input.ts
3685
3701
  import { randomUUID as randomUUID8 } from "crypto";
3686
3702
  import { closeSync as closeSync6, openSync as openSync6, unlinkSync as unlinkSync3, writeFileSync as writeFileSync12 } from "fs";
3687
- import { join as join34 } from "path";
3703
+ import { join as join38 } from "path";
3688
3704
  function validateText(text3) {
3689
3705
  if (typeof text3 !== "string" || Buffer.byteLength(text3) > 16384)
3690
3706
  throw new Error("invalid_text");
@@ -3715,7 +3731,7 @@ function write(connection, id2, text3, submit) {
3715
3731
  validateText(text3);
3716
3732
  const session = connection.inspect(id2);
3717
3733
  if (!session.alive) throw new Error("runtime_exited");
3718
- const lock = join34(connection.records.directory, `${id2}.input.lock`);
3734
+ const lock = join38(connection.records.directory, `${id2}.input.lock`);
3719
3735
  const descriptor = openSync6(lock, "wx", 384);
3720
3736
  const buffer = `pmcp-${randomUUID8()}`;
3721
3737
  try {
@@ -3874,11 +3890,11 @@ var init_backend = __esm({
3874
3890
  });
3875
3891
 
3876
3892
  // src/harness/adapters/systemd/budget.ts
3877
- import { join as join35 } from "path";
3893
+ import { join as join39 } from "path";
3878
3894
  async function budgetOperation(directory, operation) {
3879
3895
  const backend = openBackend(directory);
3880
- const path = join35(directory, "runtime-policy.json");
3881
- const metadata2 = object7(readPrivateJson2(backend.metadataPath));
3896
+ const path = join39(directory, "runtime-policy.json");
3897
+ const metadata2 = object8(readPrivateJson2(backend.metadataPath));
3882
3898
  const slice = budgetSlice(backend.owner);
3883
3899
  if (operation.action === "configure") {
3884
3900
  if (metadata2.budgetSlice || backend.records().length)
@@ -3900,7 +3916,7 @@ async function budgetOperation(directory, operation) {
3900
3916
  ]);
3901
3917
  return { ok: true };
3902
3918
  }
3903
- const policy = object7(readPrivateJson2(path));
3919
+ const policy = object8(readPrivateJson2(path));
3904
3920
  if (policy.owner !== backend.owner || metadata2.budgetSlice !== slice || policy.slice !== slice)
3905
3921
  throw new Error("foreign_budget_policy");
3906
3922
  if (operation.action === "cleanup") {
@@ -3928,7 +3944,7 @@ async function budgetOperation(directory, operation) {
3928
3944
  });
3929
3945
  if (active.length >= integer(policy.maxActive, "max_active", 1, 5))
3930
3946
  throw new Error("runtime_capacity_exceeded");
3931
- const spec = object7(operation.spec);
3947
+ const spec = object8(operation.spec);
3932
3948
  const memoryMb = integer(spec.memoryMb, "session_memory", 32, 1536);
3933
3949
  const resource = spec.resource === void 0 ? void 0 : resourceClaim(spec.resource, backend.owner);
3934
3950
  const dockerPreparation = spec.dockerPreparation;
@@ -3978,7 +3994,7 @@ var init_budget = __esm({
3978
3994
 
3979
3995
  // src/harness/adapters/systemd/configure.ts
3980
3996
  import { execFileSync as execFileSync3 } from "child_process";
3981
- import { join as join36 } from "path";
3997
+ import { join as join40 } from "path";
3982
3998
  function configureBudget(context, input) {
3983
3999
  const { store, backend } = context;
3984
4000
  assertOwnedRecords(backend);
@@ -4000,9 +4016,9 @@ function configureBudget(context, input) {
4000
4016
  throw new Error("capacity_below_active_sessions");
4001
4017
  if (active.reduce((total, session) => total + session.memoryMb, 0) > memoryMb)
4002
4018
  throw new Error("budget_below_reserved_memory");
4003
- const path = join36(backend.runDirectory, "runtime-policy.json");
4004
- const policy = object7(readPrivateJson2(path));
4005
- const metadata2 = object7(readPrivateJson2(backend.metadataPath));
4019
+ const path = join40(backend.runDirectory, "runtime-policy.json");
4020
+ const policy = object8(readPrivateJson2(path));
4021
+ const metadata2 = object8(readPrivateJson2(backend.metadataPath));
4006
4022
  const slice = budgetSlice(backend.owner);
4007
4023
  if (policy.owner !== backend.owner || policy.slice !== slice || metadata2.budgetSlice !== slice)
4008
4024
  throw new Error("foreign_budget_policy");
@@ -4037,14 +4053,14 @@ var init_configure = __esm({
4037
4053
  });
4038
4054
 
4039
4055
  // src/harness/adapters/process/executable.ts
4040
- import { accessSync, constants as constants6, statSync as statSync15 } from "fs";
4041
- import { delimiter, resolve as resolve18 } from "path";
4056
+ import { accessSync, constants as constants6, statSync as statSync16 } from "fs";
4057
+ import { delimiter, resolve as resolve19 } from "path";
4042
4058
  function locateExecutable(binary, cwd = process.cwd()) {
4043
4059
  for (const directory of (process.env.PATH ?? "").split(delimiter)) {
4044
4060
  if (!directory) continue;
4045
- const path = resolve18(cwd, directory, binary);
4061
+ const path = resolve19(cwd, directory, binary);
4046
4062
  try {
4047
- if (!statSync15(path).isFile()) continue;
4063
+ if (!statSync16(path).isFile()) continue;
4048
4064
  accessSync(path, constants6.X_OK);
4049
4065
  return path;
4050
4066
  } catch {
@@ -4095,11 +4111,11 @@ var init_admission2 = __esm({
4095
4111
 
4096
4112
  // src/harness/groups/service.ts
4097
4113
  import { randomUUID as randomUUID9 } from "crypto";
4098
- import { realpathSync as realpathSync9, statSync as statSync16, unlinkSync as unlinkSync4 } from "fs";
4099
- import { join as join37 } from "path";
4114
+ import { realpathSync as realpathSync10, statSync as statSync17, unlinkSync as unlinkSync4 } from "fs";
4115
+ import { join as join41 } from "path";
4100
4116
  async function createGroup(input) {
4101
- const projectRoot = realpathSync9(text(input.projectRoot, "project_root"));
4102
- if (!statSync16(projectRoot).isDirectory())
4117
+ const projectRoot = realpathSync10(text(input.projectRoot, "project_root"));
4118
+ if (!statSync17(projectRoot).isDirectory())
4103
4119
  throw new Error("invalid_project_root");
4104
4120
  const allowedRuntimes = strings2(input.allowedRuntimes, "allowed_runtimes");
4105
4121
  const profile = input.profile ?? "native";
@@ -4129,7 +4145,7 @@ async function createGroup(input) {
4129
4145
  sessions: [],
4130
4146
  ...dockerPolicy2 ? { dockerPolicy: dockerPolicy2 } : {}
4131
4147
  };
4132
- const groupFile = join37(backend.runDirectory, "group.json");
4148
+ const groupFile = join41(backend.runDirectory, "group.json");
4133
4149
  privateJson(groupFile, { group, leases: [], deliveries: [] });
4134
4150
  try {
4135
4151
  await budgetOperation(backend.runDirectory, {
@@ -4142,7 +4158,7 @@ async function createGroup(input) {
4142
4158
  await budgetOperation(backend.runDirectory, { action: "cleanup" });
4143
4159
  unlinkSync4(groupFile);
4144
4160
  } catch (cleanupError) {
4145
- privateJson(join37(backend.runDirectory, "initialization-failure.json"), {
4161
+ privateJson(join41(backend.runDirectory, "initialization-failure.json"), {
4146
4162
  error: String(error),
4147
4163
  cleanupError: String(cleanupError),
4148
4164
  recoveryRequired: true
@@ -4204,16 +4220,16 @@ var init_service2 = __esm({
4204
4220
  });
4205
4221
 
4206
4222
  // src/harness/groups/catalog.ts
4207
- import { existsSync as existsSync24, readdirSync as readdirSync11 } from "fs";
4208
- import { join as join38 } from "path";
4223
+ import { existsSync as existsSync27, readdirSync as readdirSync12 } from "fs";
4224
+ import { join as join42 } from "path";
4209
4225
  function listGroups() {
4210
4226
  const directory = stateDirectory();
4211
- if (!existsSync24(directory)) return { groups: [] };
4227
+ if (!existsSync27(directory)) return { groups: [] };
4212
4228
  const groups2 = [];
4213
- for (const entry2 of readdirSync11(directory, { withFileTypes: true })) {
4229
+ for (const entry2 of readdirSync12(directory, { withFileTypes: true })) {
4214
4230
  if (!entry2.isDirectory()) continue;
4215
- const path = join38(directory, entry2.name, "group.json");
4216
- if (!existsSync24(path)) continue;
4231
+ const path = join42(directory, entry2.name, "group.json");
4232
+ if (!existsSync27(path)) continue;
4217
4233
  try {
4218
4234
  const store = new GroupStore(path);
4219
4235
  groups2.push({ groupFile: store.path, group: store.state.group });
@@ -4272,10 +4288,10 @@ var init_service3 = __esm({
4272
4288
  });
4273
4289
 
4274
4290
  // src/harness/application/context.ts
4275
- import { dirname as dirname20 } from "path";
4291
+ import { dirname as dirname21 } from "path";
4276
4292
  function openGroup(path) {
4277
4293
  const store = new GroupStore(path);
4278
- const backend = openBackend(dirname20(store.path));
4294
+ const backend = openBackend(dirname21(store.path));
4279
4295
  if (store.state.group.owner !== backend.owner)
4280
4296
  throw new Error("foreign_group");
4281
4297
  return { store, backend };
@@ -4390,7 +4406,7 @@ async function watchSession(operation) {
4390
4406
  )
4391
4407
  });
4392
4408
  if (index + 1 < count)
4393
- await new Promise((resolve19) => setTimeout(resolve19, intervalMs));
4409
+ await new Promise((resolve22) => setTimeout(resolve22, intervalMs));
4394
4410
  }
4395
4411
  return {
4396
4412
  schemaVersion: 1,
@@ -4410,9 +4426,9 @@ var init_watch = __esm({
4410
4426
 
4411
4427
  // src/harness/control/leases.ts
4412
4428
  import { randomUUID as randomUUID10 } from "crypto";
4413
- import { join as join39 } from "path";
4429
+ import { join as join43 } from "path";
4414
4430
  function resolveLease(context, file2, allowExpired = false) {
4415
- const credential2 = object7(readPrivateJson2(file2));
4431
+ const credential2 = object8(readPrivateJson2(file2));
4416
4432
  const lease = context.store.state.leases.find(
4417
4433
  (entry2) => entry2.token === credential2.token
4418
4434
  );
@@ -4454,7 +4470,7 @@ function acquireControl(context, sessionId, controller, mode) {
4454
4470
  );
4455
4471
  store.state.leases.push(lease);
4456
4472
  store.save();
4457
- const leaseFile = join39(backend.runDirectory, `lease-${randomUUID10()}.json`);
4473
+ const leaseFile = join43(backend.runDirectory, `lease-${randomUUID10()}.json`);
4458
4474
  privateJson(leaseFile, { token: lease.token });
4459
4475
  return { sessionId, controller, mode, expiresAt: lease.expiresAt, leaseFile };
4460
4476
  }
@@ -4507,7 +4523,7 @@ var init_leases = __esm({
4507
4523
  });
4508
4524
 
4509
4525
  // src/harness/delivery/service.ts
4510
- import { createHash as createHash17 } from "crypto";
4526
+ import { createHash as createHash18 } from "crypto";
4511
4527
  function deliver(context, operation, leaseFile, requestId, text3) {
4512
4528
  const { store, backend } = context;
4513
4529
  const lease = resolveLease(context, leaseFile);
@@ -4523,7 +4539,7 @@ function deliver(context, operation, leaseFile, requestId, text3) {
4523
4539
  if (/[\r\n\t]/.test(text3))
4524
4540
  throw new Error("unqualified_terminal_control_input");
4525
4541
  id(requestId, "request_id");
4526
- const digest2 = createHash17("sha256").update(
4542
+ const digest2 = createHash18("sha256").update(
4527
4543
  JSON.stringify({
4528
4544
  operation,
4529
4545
  text: text3,
@@ -4601,18 +4617,18 @@ var init_service5 = __esm({
4601
4617
  });
4602
4618
 
4603
4619
  // src/harness/adapters/process/recover-lock.ts
4604
- import { existsSync as existsSync25, lstatSync as lstatSync9, unlinkSync as unlinkSync5 } from "fs";
4605
- import { join as join40 } from "path";
4620
+ import { existsSync as existsSync28, lstatSync as lstatSync10, unlinkSync as unlinkSync5 } from "fs";
4621
+ import { join as join44 } from "path";
4606
4622
  function recoverInputLock(backend, sessionId) {
4607
4623
  backend.inspect(sessionId);
4608
- const path = join40(backend.runDirectory, `${sessionId}.input.lock`);
4609
- if (!existsSync25(path)) return;
4610
- const before = lstatSync9(path);
4611
- const record = object7(readPrivateJson2(path));
4624
+ const path = join44(backend.runDirectory, `${sessionId}.input.lock`);
4625
+ if (!existsSync28(path)) return;
4626
+ const before = lstatSync10(path);
4627
+ const record = object8(readPrivateJson2(path));
4612
4628
  if (record.id !== sessionId) throw new Error("foreign_writer_lock");
4613
4629
  if (!controllerExited(text(record.controller, "controller_identity")))
4614
4630
  throw new Error("writer_still_alive");
4615
- if (lstatSync9(path).ino !== before.ino)
4631
+ if (lstatSync10(path).ino !== before.ino)
4616
4632
  throw new Error("writer_lock_changed");
4617
4633
  unlinkSync5(path);
4618
4634
  }
@@ -4626,7 +4642,7 @@ var init_recover_lock = __esm({
4626
4642
  });
4627
4643
 
4628
4644
  // src/harness/launch/service.ts
4629
- import { existsSync as existsSync26 } from "fs";
4645
+ import { existsSync as existsSync29 } from "fs";
4630
4646
  function assertLaunchAdmission(records2) {
4631
4647
  for (const journal of launchJournals(records2)) {
4632
4648
  if (journal.abortRecord()?.state === "stopped" && unitActive(journal.intent().unit))
@@ -4651,12 +4667,12 @@ function inspectPendingStarts(context) {
4651
4667
  role: journal.intent().role,
4652
4668
  runtime: journal.intent().runtime,
4653
4669
  controllerExited: controllerExited(journal.intent().controllerIdentity),
4654
- proofPresent: existsSync26(journal.path("proof")),
4655
- recordPresent: existsSync26(journal.records.path(journal.id)),
4670
+ proofPresent: existsSync29(journal.path("proof")),
4671
+ recordPresent: existsSync29(journal.records.path(journal.id)),
4656
4672
  registered: context.store.state.group.sessions.some(
4657
4673
  (session) => session.id === journal.id
4658
4674
  ),
4659
- authorizationPresent: existsSync26(journal.path("grant")),
4675
+ authorizationPresent: existsSync29(journal.path("grant")),
4660
4676
  processingConfirmed: false,
4661
4677
  inputReplayed: false
4662
4678
  }));
@@ -4674,8 +4690,8 @@ var init_service6 = __esm({
4674
4690
  });
4675
4691
 
4676
4692
  // src/harness/sessions/service.ts
4677
- import { realpathSync as realpathSync10 } from "fs";
4678
- import { relative as relative14 } from "path";
4693
+ import { realpathSync as realpathSync11 } from "fs";
4694
+ import { relative as relative15 } from "path";
4679
4695
  async function startSession(context, input) {
4680
4696
  const { store, backend } = context;
4681
4697
  const group = store.state.group;
@@ -4708,8 +4724,8 @@ async function startSession(context, input) {
4708
4724
  );
4709
4725
  if (!backend.inspect(main2.id).alive) throw new Error("main_unavailable");
4710
4726
  }
4711
- const cwd = realpathSync10(text(input.cwd ?? group.projectRoot, "cwd"));
4712
- const scope = relative14(group.projectRoot, cwd);
4727
+ const cwd = realpathSync11(text(input.cwd ?? group.projectRoot, "cwd"));
4728
+ const scope = relative15(group.projectRoot, cwd);
4713
4729
  if (scope === ".." || scope.startsWith("../"))
4714
4730
  throw new Error("cwd_outside_project");
4715
4731
  const memoryMb = integer(input.memoryMb ?? 384, "session_memory", 32, 1536);
@@ -5008,7 +5024,7 @@ async function runOperation(operation) {
5008
5024
  return groupOperation(context, action, operation.input);
5009
5025
  if (family === "session") {
5010
5026
  if (action === "start")
5011
- return startSession(context, object7(operation.input));
5027
+ return startSession(context, object8(operation.input));
5012
5028
  if (action === "list") return listSessions(context);
5013
5029
  const sessionId = text(operation.sessionId, "session_id");
5014
5030
  if (action === "stop") return stopSession(context, sessionId);
@@ -5066,7 +5082,7 @@ async function runOperation(operation) {
5066
5082
  if (action === "stop-orphan")
5067
5083
  return stopOrphan(context, text(operation.sessionId, "session_id"));
5068
5084
  if (action === "replace-main")
5069
- return replaceMain(context, object7(operation.input));
5085
+ return replaceMain(context, object8(operation.input));
5070
5086
  }
5071
5087
  throw new Error("unsupported_operation");
5072
5088
  }
@@ -5141,7 +5157,7 @@ async function invoke(operation) {
5141
5157
  return {
5142
5158
  schemaVersion: 1,
5143
5159
  ok: true,
5144
- ...await createGroup(object7(operation.input))
5160
+ ...await createGroup(object8(operation.input))
5145
5161
  };
5146
5162
  }
5147
5163
  if (operation.family === "attach" && operation.action === "open") {
@@ -5171,9 +5187,9 @@ var init_invoke = __esm({
5171
5187
  });
5172
5188
 
5173
5189
  // src/tui/adapters/process/runtime.ts
5174
- import { dirname as dirname21, join as join41 } from "path";
5175
- import { fileURLToPath as fileURLToPath3 } from "url";
5176
- import { existsSync as existsSync27, realpathSync as realpathSync11 } from "fs";
5190
+ import { dirname as dirname22, join as join45 } from "path";
5191
+ import { fileURLToPath as fileURLToPath4 } from "url";
5192
+ import { existsSync as existsSync30, realpathSync as realpathSync12 } from "fs";
5177
5193
  function dependencies() {
5178
5194
  const tmux = locateExecutable("tmux");
5179
5195
  const flock = locateExecutable("flock");
@@ -5205,11 +5221,11 @@ function runtime() {
5205
5221
  const available = dependencies();
5206
5222
  if (!available.supported || !available.node)
5207
5223
  throw new Error("tui_dependencies_unavailable");
5208
- const current = fileURLToPath3(import.meta.url);
5209
- const directory = dirname21(current);
5210
- const bundled = join41(directory, "tui-worker.js");
5211
- if (!existsSync27(bundled)) throw new Error("tui_build_required");
5212
- return { node: realpathSync11(available.node), worker: bundled };
5224
+ const current = fileURLToPath4(import.meta.url);
5225
+ const directory = dirname22(current);
5226
+ const bundled = join45(directory, "tui-worker.js");
5227
+ if (!existsSync30(bundled)) throw new Error("tui_build_required");
5228
+ return { node: realpathSync12(available.node), worker: bundled };
5213
5229
  }
5214
5230
  var init_runtime2 = __esm({
5215
5231
  "src/tui/adapters/process/runtime.ts"() {
@@ -5223,32 +5239,32 @@ var init_runtime2 = __esm({
5223
5239
  // src/tui/state/store.ts
5224
5240
  import { randomUUID as randomUUID12 } from "crypto";
5225
5241
  import {
5226
- existsSync as existsSync28,
5227
- lstatSync as lstatSync10,
5242
+ existsSync as existsSync31,
5243
+ lstatSync as lstatSync11,
5228
5244
  mkdirSync as mkdirSync11,
5229
- realpathSync as realpathSync12,
5245
+ realpathSync as realpathSync13,
5230
5246
  unlinkSync as unlinkSync6,
5231
5247
  writeFileSync as writeFileSync13
5232
5248
  } from "fs";
5233
5249
  import { homedir as homedir10 } from "os";
5234
- import { dirname as dirname22, join as join42 } from "path";
5250
+ import { dirname as dirname23, join as join46 } from "path";
5235
5251
  function createDirectory() {
5236
- const root = join42(
5237
- process.env.XDG_STATE_HOME ?? join42(homedir10(), ".local/state"),
5252
+ const root = join46(
5253
+ process.env.XDG_STATE_HOME ?? join46(homedir10(), ".local/state"),
5238
5254
  "pmcp/tui"
5239
5255
  );
5240
5256
  mkdirSync11(root, { recursive: true, mode: 448 });
5241
- const directory = join42(realpathSync12(root), randomUUID12().slice(0, 16));
5242
- if (Buffer.byteLength(join42(directory, "s")) > 100)
5257
+ const directory = join46(realpathSync13(root), randomUUID12().slice(0, 16));
5258
+ if (Buffer.byteLength(join46(directory, "s")) > 100)
5243
5259
  throw new Error("socket_path_too_long");
5244
5260
  mkdirSync11(directory, { mode: 448 });
5245
5261
  const owner = randomUUID12();
5246
- privateJson(join42(directory, "owner.json"), {
5262
+ privateJson(join46(directory, "owner.json"), {
5247
5263
  owner,
5248
5264
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
5249
5265
  });
5250
5266
  writeFileSync13(
5251
- join42(directory, "tmux.conf"),
5267
+ join46(directory, "tmux.conf"),
5252
5268
  [
5253
5269
  "set -g remain-on-exit on",
5254
5270
  "set -g history-limit 2000",
@@ -5263,13 +5279,13 @@ function createDirectory() {
5263
5279
  return { directory, owner };
5264
5280
  }
5265
5281
  function readView(path) {
5266
- const file2 = realpathSync12(path);
5267
- const directory = dirname22(file2);
5268
- const stat = lstatSync10(directory);
5282
+ const file2 = realpathSync13(path);
5283
+ const directory = dirname23(file2);
5284
+ const stat = lstatSync11(directory);
5269
5285
  if (!stat.isDirectory() || stat.uid !== process.getuid?.() || (stat.mode & 63) !== 0)
5270
5286
  throw new Error("unsafe_view_directory");
5271
- const value = object7(readPrivateJson2(file2));
5272
- const metadata2 = object7(readPrivateJson2(join42(directory, "owner.json")));
5287
+ const value = object8(readPrivateJson2(file2));
5288
+ const metadata2 = object8(readPrivateJson2(join46(directory, "owner.json")));
5273
5289
  if (value.schemaVersion !== 1 || value.directory !== directory || value.owner !== metadata2.owner)
5274
5290
  throw new Error("foreign_view_owner");
5275
5291
  for (const key of [
@@ -5294,7 +5310,7 @@ function readView(path) {
5294
5310
  "uncertain"
5295
5311
  ].includes(String(value.phase)))
5296
5312
  throw new Error("invalid_control_phase");
5297
- const plan2 = object7(value.plan);
5313
+ const plan2 = object8(value.plan);
5298
5314
  planLayout(Number(plan2.columns), Number(plan2.rows));
5299
5315
  for (const [key, pattern] of [
5300
5316
  ["session", /^\$\d+$/],
@@ -5306,10 +5322,10 @@ function readView(path) {
5306
5322
  throw new Error("invalid_view_identity");
5307
5323
  }
5308
5324
  const view = value;
5309
- const fallback = join42(directory, "callback-failure.json");
5310
- if (existsSync28(fallback)) {
5311
- const recorded = object7(readPrivateJson2(fallback));
5312
- const failure2 = object7(recorded.failure);
5325
+ const fallback = join46(directory, "callback-failure.json");
5326
+ if (existsSync31(fallback)) {
5327
+ const recorded = object8(readPrivateJson2(fallback));
5328
+ const failure2 = object8(recorded.failure);
5313
5329
  if (recorded.owner !== view.owner || typeof failure2.code !== "string" || !/^[a-z][a-z0-9_]{0,79}$/.test(failure2.code))
5314
5330
  throw new Error("invalid_view_failure");
5315
5331
  if (!view.failure || String(failure2.at) >= view.failure.at)
@@ -5318,8 +5334,8 @@ function readView(path) {
5318
5334
  return { file: file2, view };
5319
5335
  }
5320
5336
  function dismissFailure(file2, view) {
5321
- const fallback = join42(view.directory, "callback-failure.json");
5322
- if (existsSync28(fallback)) unlinkSync6(fallback);
5337
+ const fallback = join46(view.directory, "callback-failure.json");
5338
+ if (existsSync31(fallback)) unlinkSync6(fallback);
5323
5339
  delete view.failure;
5324
5340
  saveView(file2, view);
5325
5341
  }
@@ -5381,7 +5397,7 @@ var init_lock = __esm({
5381
5397
  });
5382
5398
 
5383
5399
  // src/tui/adapters/process/budget.ts
5384
- import { readFileSync as readFileSync32 } from "fs";
5400
+ import { readFileSync as readFileSync36 } from "fs";
5385
5401
  function viewUnit(owner) {
5386
5402
  if (!/^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$/.test(owner))
5387
5403
  throw new Error("invalid_view_owner");
@@ -5409,7 +5425,7 @@ function startPresentation(owner, args, env) {
5409
5425
  );
5410
5426
  }
5411
5427
  function assertPresentationBudget(owner, pid) {
5412
- if (!readFileSync32(`/proc/${pid}/cgroup`, "utf8").includes(
5428
+ if (!readFileSync36(`/proc/${pid}/cgroup`, "utf8").includes(
5413
5429
  `/${viewUnit(owner)}
5414
5430
  `
5415
5431
  ))
@@ -5424,7 +5440,7 @@ var init_budget2 = __esm({
5424
5440
 
5425
5441
  // src/tui/adapters/tmux/connection.ts
5426
5442
  import { spawn as spawn3 } from "child_process";
5427
- import { join as join43 } from "path";
5443
+ import { join as join47 } from "path";
5428
5444
  var ViewConnection;
5429
5445
  var init_connection2 = __esm({
5430
5446
  "src/tui/adapters/tmux/connection.ts"() {
@@ -5437,7 +5453,7 @@ var init_connection2 = __esm({
5437
5453
  this.directory = directory;
5438
5454
  this.owner = owner;
5439
5455
  this.identity = identity;
5440
- this.socket = join43(directory, "s");
5456
+ this.socket = join47(directory, "s");
5441
5457
  }
5442
5458
  directory;
5443
5459
  owner;
@@ -5450,14 +5466,14 @@ var init_connection2 = __esm({
5450
5466
  "-S",
5451
5467
  this.socket,
5452
5468
  "-f",
5453
- join43(this.directory, "tmux.conf"),
5469
+ join47(this.directory, "tmux.conf"),
5454
5470
  ...args
5455
5471
  ];
5456
5472
  if (args[0] === "new-session" && !this.identity)
5457
5473
  return startPresentation(this.owner, options2, env).trim();
5458
5474
  return command(
5459
5475
  "tmux",
5460
- ["-S", this.socket, "-f", join43(this.directory, "tmux.conf"), ...args],
5476
+ ["-S", this.socket, "-f", join47(this.directory, "tmux.conf"), ...args],
5461
5477
  { env }
5462
5478
  ).trim();
5463
5479
  }
@@ -5511,9 +5527,9 @@ var init_connection2 = __esm({
5511
5527
  ["-S", this.socket, "attach-session", "-E", "-t", view.session],
5512
5528
  { stdio: "inherit", env }
5513
5529
  );
5514
- return new Promise((resolve19, reject) => {
5530
+ return new Promise((resolve22, reject) => {
5515
5531
  client.once("error", reject);
5516
- client.once("exit", (code) => resolve19(code ?? 1));
5532
+ client.once("exit", (code) => resolve22(code ?? 1));
5517
5533
  });
5518
5534
  }
5519
5535
  };
@@ -5521,7 +5537,7 @@ var init_connection2 = __esm({
5521
5537
  });
5522
5538
 
5523
5539
  // src/tui/application/feedback.ts
5524
- import { join as join44 } from "path";
5540
+ import { join as join48 } from "path";
5525
5541
  function describeFailure(action, error) {
5526
5542
  const message = error instanceof Error ? error.message : "view_action_failed";
5527
5543
  const code = error instanceof RangeError ? "terminal_size_invalid" : failureCode(message);
@@ -5919,16 +5935,16 @@ var init_common = __esm({
5919
5935
  });
5920
5936
 
5921
5937
  // src/tui/application/create.ts
5922
- import { join as join45 } from "path";
5923
- import { realpathSync as realpathSync13 } from "fs";
5938
+ import { join as join49 } from "path";
5939
+ import { realpathSync as realpathSync14 } from "fs";
5924
5940
  async function createView(input) {
5925
5941
  const plan2 = planLayout(input.columns, input.rows);
5926
5942
  const helpers = runtime();
5927
5943
  const mailbox = input.mailbox ? {
5928
- config: realpathSync13(input.mailbox.config),
5929
- actorFile: realpathSync13(input.mailbox.actorFile)
5944
+ config: realpathSync14(input.mailbox.config),
5945
+ actorFile: realpathSync14(input.mailbox.actorFile)
5930
5946
  } : void 0;
5931
- const groupFile = realpathSync13(input.groupFile);
5947
+ const groupFile = realpathSync14(input.groupFile);
5932
5948
  const group = new GroupStore(groupFile).state.group;
5933
5949
  const common2 = new CommonHarness({
5934
5950
  groupFile,
@@ -5941,7 +5957,7 @@ async function createView(input) {
5941
5957
  );
5942
5958
  if (!main2) throw new Error("view_requires_live_main");
5943
5959
  const { directory, owner } = createDirectory();
5944
- const file2 = join45(directory, "view.json");
5960
+ const file2 = join49(directory, "view.json");
5945
5961
  const connection = new ViewConnection(directory, owner);
5946
5962
  const argv = [helpers.node, helpers.worker, "attach", file2, main2.id];
5947
5963
  const result = connection.raw([
@@ -6027,7 +6043,7 @@ async function waitFor(predicate, timeoutMs) {
6027
6043
  const deadline = Date.now() + timeoutMs;
6028
6044
  while (Date.now() < deadline) {
6029
6045
  if (await predicate()) return;
6030
- await new Promise((resolve19) => setTimeout(resolve19, 50));
6046
+ await new Promise((resolve22) => setTimeout(resolve22, 50));
6031
6047
  }
6032
6048
  throw new Error("writer_not_ready");
6033
6049
  }
@@ -6169,7 +6185,7 @@ var init_navigation = __esm({
6169
6185
  });
6170
6186
 
6171
6187
  // src/tui/application/history.ts
6172
- import { join as join46 } from "path";
6188
+ import { join as join50 } from "path";
6173
6189
  async function observeHistory(context) {
6174
6190
  const { view, renderer, common: common2, file: file2 } = context;
6175
6191
  await releaseControl(context);
@@ -6177,7 +6193,7 @@ async function observeHistory(context) {
6177
6193
  sessionId: view.target,
6178
6194
  input: { lines: 2e3, maxBytes: 65536 }
6179
6195
  });
6180
- privateJson(join46(view.directory, "history.json"), {
6196
+ privateJson(join50(view.directory, "history.json"), {
6181
6197
  sessionId: view.target,
6182
6198
  content: history.content,
6183
6199
  truncated: history.truncated
@@ -6253,8 +6269,8 @@ var init_mailbox = __esm({
6253
6269
  });
6254
6270
 
6255
6271
  // src/tui/application/lifecycle.ts
6256
- import { existsSync as existsSync29, unlinkSync as unlinkSync7 } from "fs";
6257
- import { join as join47 } from "path";
6272
+ import { existsSync as existsSync32, unlinkSync as unlinkSync7 } from "fs";
6273
+ import { join as join51 } from "path";
6258
6274
  function resizeView({ view, renderer, input }) {
6259
6275
  renderer.resize(view, planLayout(input.columns, input.rows));
6260
6276
  }
@@ -6269,8 +6285,8 @@ async function stopTarget(context) {
6269
6285
  async function closeView(context) {
6270
6286
  await returnToMain(context);
6271
6287
  context.renderer.connection.cleanup();
6272
- const history = join47(context.view.directory, "history.json");
6273
- if (existsSync29(history)) unlinkSync7(history);
6288
+ const history = join51(context.view.directory, "history.json");
6289
+ if (existsSync32(history)) unlinkSync7(history);
6274
6290
  context.view.state = "closed";
6275
6291
  saveView(context.file, context.view);
6276
6292
  }
@@ -6888,16 +6904,16 @@ async function openEntryVectors(path, options2 = {}) {
6888
6904
 
6889
6905
  // src/commands/reindex.ts
6890
6906
  init_encoder();
6891
- import { existsSync as existsSync4, mkdirSync } from "fs";
6892
- import { dirname as dirname4 } from "path";
6907
+ import { existsSync as existsSync6, mkdirSync } from "fs";
6908
+ import { dirname as dirname5 } from "path";
6893
6909
 
6894
6910
  // src/commands/embedding.ts
6895
- import { resolve as resolve4 } from "path";
6911
+ import { resolve as resolve5 } from "path";
6896
6912
  init_encoder();
6897
6913
 
6898
6914
  // src/catalog.ts
6899
- import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync as readdirSync2 } from "fs";
6900
- import { basename as basename2, dirname as dirname2, isAbsolute, join as join2, relative } from "path";
6915
+ import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
6916
+ import { basename as basename2, dirname as dirname2, isAbsolute as isAbsolute2, join as join3, relative as relative2 } from "path";
6901
6917
 
6902
6918
  // src/frontmatter.ts
6903
6919
  import { parse } from "yaml";
@@ -7019,8 +7035,122 @@ function specProblems(front, directory) {
7019
7035
  }
7020
7036
 
7021
7037
  // src/marketplace.ts
7022
- import { existsSync, readFileSync, readdirSync } from "fs";
7023
- import { basename, dirname, join, resolve as resolve2 } from "path";
7038
+ import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync } from "fs";
7039
+ import { basename, dirname, join as join2, resolve as resolve3 } from "path";
7040
+
7041
+ // src/marketplace/local.ts
7042
+ import { existsSync, readFileSync, realpathSync, statSync } from "fs";
7043
+ import { isAbsolute, join, relative, resolve as resolve2, sep } from "path";
7044
+ function object(value) {
7045
+ return value !== null && typeof value === "object" && !Array.isArray(value);
7046
+ }
7047
+ function containedPath(root, path) {
7048
+ const result = resolve2(root, path);
7049
+ const lexical = relative(resolve2(root), result);
7050
+ if (isAbsolute(lexical) || lexical === ".." || lexical.startsWith(`..${sep}`))
7051
+ throw new Error("Path leaves the plugin root");
7052
+ const physical = relative(realpathSync(root), realpathSync(result));
7053
+ if (isAbsolute(physical) || physical === ".." || physical.startsWith(`..${sep}`))
7054
+ throw new Error("Path leaves the plugin root through a symlink");
7055
+ return result;
7056
+ }
7057
+ function pluginManifest(directory) {
7058
+ for (const path of [
7059
+ ".claude-plugin/plugin.json",
7060
+ "plugin.json",
7061
+ ".codex-plugin/plugin.json",
7062
+ ".grok-plugin/plugin.json"
7063
+ ]) {
7064
+ if (!existsSync(join(directory, path))) continue;
7065
+ const value = JSON.parse(
7066
+ readFileSync(containedPath(directory, path), "utf8")
7067
+ );
7068
+ if (!object(value)) throw new Error("Plugin manifest must be an object");
7069
+ return value;
7070
+ }
7071
+ return {};
7072
+ }
7073
+ function localSource(value) {
7074
+ if (typeof value === "string") return value;
7075
+ if (object(value) && value.source === "local" && typeof value.path === "string")
7076
+ return value.path;
7077
+ throw new Error(
7078
+ "Only installed local plugin sources can be read; use the native installer for remote sources"
7079
+ );
7080
+ }
7081
+ function readLocalMarketplace(directory, onReject) {
7082
+ const filename = [
7083
+ ".claude-plugin/marketplace.json",
7084
+ ".agents/plugins/marketplace.json",
7085
+ ".grok-plugin/marketplace.json"
7086
+ ].find((path2) => existsSync(join(directory, path2)));
7087
+ if (!filename) {
7088
+ onReject?.({
7089
+ path: directory,
7090
+ reason: "No supported native marketplace.json found"
7091
+ });
7092
+ return null;
7093
+ }
7094
+ const path = join(directory, filename);
7095
+ let manifest2;
7096
+ try {
7097
+ manifest2 = JSON.parse(
7098
+ readFileSync(containedPath(directory, filename), "utf8")
7099
+ );
7100
+ } catch {
7101
+ onReject?.({
7102
+ path,
7103
+ reason: "marketplace.json is not valid JSON or is outside its root"
7104
+ });
7105
+ return null;
7106
+ }
7107
+ if (!object(manifest2) || !Array.isArray(manifest2.plugins)) {
7108
+ onReject?.({ path, reason: "marketplace.json requires a plugins array" });
7109
+ return null;
7110
+ }
7111
+ const name = typeof manifest2.name === "string" ? manifest2.name : "marketplace";
7112
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/u.test(name)) {
7113
+ onReject?.({ path, reason: "Invalid marketplace name" });
7114
+ return null;
7115
+ }
7116
+ const plugins = [];
7117
+ const seen = /* @__PURE__ */ new Set();
7118
+ for (const item of manifest2.plugins) {
7119
+ try {
7120
+ if (!object(item) || typeof item.name !== "string" || !/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/u.test(item.name))
7121
+ throw new Error("Invalid plugin name");
7122
+ if (seen.has(item.name)) throw new Error("Duplicate plugin name");
7123
+ const source2 = localSource(item.source);
7124
+ if (!source2.startsWith("./") || source2.split(/[\\/]/u).includes(".."))
7125
+ throw new Error("Local plugin source must be a contained ./ path");
7126
+ const pluginDirectory = containedPath(directory, source2);
7127
+ if (!statSync(pluginDirectory).isDirectory())
7128
+ throw new Error("Plugin source must be a directory");
7129
+ const metadata3 = pluginManifest(pluginDirectory);
7130
+ if (metadata3.name !== void 0 && metadata3.name !== item.name)
7131
+ throw new Error("Plugin manifest name differs from marketplace entry");
7132
+ seen.add(item.name);
7133
+ plugins.push({
7134
+ name: item.name,
7135
+ directory: pluginDirectory,
7136
+ manifest: metadata3
7137
+ });
7138
+ } catch (error) {
7139
+ onReject?.({
7140
+ path,
7141
+ reason: error instanceof Error ? error.message : "Invalid plugin source"
7142
+ });
7143
+ }
7144
+ }
7145
+ const metadata2 = object(manifest2.metadata) ? manifest2.metadata : {};
7146
+ return {
7147
+ name,
7148
+ plugins,
7149
+ ...typeof metadata2.tier === "string" ? { tier: metadata2.tier } : {}
7150
+ };
7151
+ }
7152
+
7153
+ // src/marketplace.ts
7024
7154
  function readMetadata(source2) {
7025
7155
  return metadataOf(frontmatterObject(source2));
7026
7156
  }
@@ -7033,16 +7163,27 @@ var asList = (value) => {
7033
7163
  if (typeof value === "string") return [value];
7034
7164
  return Array.isArray(value) ? value : [];
7035
7165
  };
7036
- function readJson(path) {
7166
+ function readJson(path, root) {
7037
7167
  try {
7038
- const parsed = JSON.parse(readFileSync(path, "utf8"));
7168
+ const parsed = JSON.parse(
7169
+ readFileSync2(containedPath(root, path), "utf8")
7170
+ );
7039
7171
  return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
7040
7172
  } catch {
7041
7173
  return null;
7042
7174
  }
7043
7175
  }
7044
7176
  function markdownEntry(context, path, fallbackSlug, shape) {
7045
- const source2 = readFileSync(path, "utf8");
7177
+ let source2;
7178
+ try {
7179
+ source2 = readFileSync2(containedPath(context.pluginDir, path), "utf8");
7180
+ } catch {
7181
+ context.onReject?.({
7182
+ path,
7183
+ reason: "Asset is unreadable or outside the plugin root"
7184
+ });
7185
+ return null;
7186
+ }
7046
7187
  const front = readFrontmatter(source2);
7047
7188
  const description = front["description"] ?? "";
7048
7189
  if (description === "") {
@@ -7074,25 +7215,25 @@ function markdownEntry(context, path, fallbackSlug, shape) {
7074
7215
  };
7075
7216
  }
7076
7217
  function skillEntries(context) {
7077
- const dir = join(context.pluginDir, "skills");
7078
- if (!existsSync(dir)) return [];
7218
+ const dir = join2(context.pluginDir, "skills");
7219
+ if (!existsSync2(dir)) return [];
7079
7220
  const found = [];
7080
7221
  for (const child of readdirSync(dir, { withFileTypes: true })) {
7081
7222
  if (!child.isDirectory()) continue;
7082
- const path = join(dir, child.name, "SKILL.md");
7083
- if (!existsSync(path)) continue;
7223
+ const path = join2(dir, child.name, "SKILL.md");
7224
+ if (!existsSync2(path)) continue;
7084
7225
  const entry2 = markdownEntry(context, path, child.name, {});
7085
7226
  if (entry2) found.push(entry2);
7086
7227
  }
7087
7228
  return found;
7088
7229
  }
7089
7230
  function commandEntries(context) {
7090
- const dir = join(context.pluginDir, "commands");
7091
- if (!existsSync(dir)) return [];
7231
+ const dir = join2(context.pluginDir, "commands");
7232
+ if (!existsSync2(dir)) return [];
7092
7233
  const found = [];
7093
7234
  for (const child of readdirSync(dir, { withFileTypes: true })) {
7094
7235
  if (!child.isFile() || !child.name.endsWith(".md")) continue;
7095
- const path = join(dir, child.name);
7236
+ const path = join2(dir, child.name);
7096
7237
  const entry2 = markdownEntry(context, path, basename(child.name, ".md"), {
7097
7238
  root: path
7098
7239
  });
@@ -7101,22 +7242,22 @@ function commandEntries(context) {
7101
7242
  return found;
7102
7243
  }
7103
7244
  function agentEntries(context) {
7104
- const dir = join(context.pluginDir, "agents");
7105
- if (!existsSync(dir)) return [];
7245
+ const dir = join2(context.pluginDir, "agents");
7246
+ if (!existsSync2(dir)) return [];
7106
7247
  const found = [];
7107
7248
  for (const child of readdirSync(dir, { withFileTypes: true })) {
7108
7249
  let entry2 = null;
7109
7250
  if (child.isFile() && child.name.endsWith(".md")) {
7110
- const path = join(dir, child.name);
7251
+ const path = join2(dir, child.name);
7111
7252
  entry2 = markdownEntry(context, path, basename(child.name, ".md"), {
7112
7253
  kind: "agent",
7113
7254
  root: path,
7114
7255
  namespace: "agents"
7115
7256
  });
7116
- } else if (child.isDirectory() && existsSync(join(dir, child.name, "agent.md"))) {
7257
+ } else if (child.isDirectory() && existsSync2(join2(dir, child.name, "agent.md"))) {
7117
7258
  entry2 = markdownEntry(
7118
7259
  context,
7119
- join(dir, child.name, "agent.md"),
7260
+ join2(dir, child.name, "agent.md"),
7120
7261
  child.name,
7121
7262
  {
7122
7263
  kind: "agent",
@@ -7130,9 +7271,9 @@ function agentEntries(context) {
7130
7271
  }
7131
7272
  function hookEntries(context, manifest2) {
7132
7273
  const declared = typeof manifest2.hooks === "string" ? manifest2.hooks : void 0;
7133
- const path = resolve2(context.pluginDir, declared ?? "hooks/hooks.json");
7134
- if (!existsSync(path)) return [];
7135
- const hooks = readJson(path);
7274
+ const path = resolve3(context.pluginDir, declared ?? "hooks/hooks.json");
7275
+ if (!existsSync2(path)) return [];
7276
+ const hooks = readJson(path, context.pluginDir);
7136
7277
  if (hooks === null) {
7137
7278
  context.onReject?.({ path, reason: "hooks.json is not a JSON object" });
7138
7279
  return [];
@@ -7158,9 +7299,12 @@ function hookEntries(context, manifest2) {
7158
7299
  ];
7159
7300
  }
7160
7301
  function mcpEntries(context) {
7161
- const path = join(context.pluginDir, ".mcp.json");
7162
- if (!existsSync(path)) return [];
7163
- const config = readJson(path);
7302
+ const filename = [".mcp.json", "mcp.json", "mcp_config.json"].find(
7303
+ (name) => existsSync2(join2(context.pluginDir, name))
7304
+ );
7305
+ if (!filename) return [];
7306
+ const path = join2(context.pluginDir, filename);
7307
+ const config = readJson(path, context.pluginDir);
7164
7308
  const servers = config?.["mcpServers"];
7165
7309
  if (servers === null || typeof servers !== "object" || Array.isArray(servers)) {
7166
7310
  context.onReject?.({ path, reason: ".mcp.json has no mcpServers object" });
@@ -7179,48 +7323,24 @@ function mcpEntries(context) {
7179
7323
  }));
7180
7324
  }
7181
7325
  function readMarketplace(dir, onReject) {
7182
- const manifestPath = join(dir, ".claude-plugin", "marketplace.json");
7183
- if (!existsSync(manifestPath)) {
7184
- onReject?.({
7185
- path: dir,
7186
- reason: "no .claude-plugin/marketplace.json here"
7187
- });
7188
- return [];
7189
- }
7190
- let manifest2;
7191
- try {
7192
- manifest2 = JSON.parse(
7193
- readFileSync(manifestPath, "utf8")
7194
- );
7195
- } catch {
7196
- onReject?.({
7197
- path: manifestPath,
7198
- reason: "marketplace.json is not valid JSON"
7199
- });
7200
- return [];
7201
- }
7202
- const marketplace = manifest2.name ?? "marketplace";
7326
+ const marketplace = readLocalMarketplace(dir, onReject);
7327
+ if (!marketplace) return [];
7203
7328
  const found = [];
7204
- for (const plugin of manifest2.plugins ?? []) {
7205
- if (!plugin.name || !plugin.source) continue;
7206
- const pluginDir = resolve2(dir, plugin.source);
7207
- if (!existsSync(pluginDir)) continue;
7208
- const pluginManifest = readJson(
7209
- join(pluginDir, ".claude-plugin", "plugin.json")
7210
- ) ?? {};
7329
+ for (const plugin of marketplace.plugins) {
7330
+ const pluginManifest2 = plugin.manifest;
7211
7331
  const context = {
7212
- marketplace,
7332
+ marketplace: marketplace.name,
7213
7333
  plugin: plugin.name,
7214
- pluginDir,
7215
- pluginDescription: typeof pluginManifest.description === "string" ? pluginManifest.description : void 0,
7216
- tier: manifest2.metadata?.tier,
7334
+ pluginDir: plugin.directory,
7335
+ pluginDescription: typeof pluginManifest2.description === "string" ? pluginManifest2.description : void 0,
7336
+ tier: marketplace.tier,
7217
7337
  onReject
7218
7338
  };
7219
7339
  found.push(
7220
7340
  ...skillEntries(context),
7221
7341
  ...commandEntries(context),
7222
7342
  ...agentEntries(context),
7223
- ...hookEntries(context, pluginManifest),
7343
+ ...hookEntries(context, pluginManifest2),
7224
7344
  ...mcpEntries(context)
7225
7345
  );
7226
7346
  }
@@ -7262,29 +7382,29 @@ function skillFiles(packageDir) {
7262
7382
  }
7263
7383
  for (const entry2 of entries) {
7264
7384
  if (entry2.isFile()) {
7265
- if (entry2.name === "SKILL.md") found.push(join2(dir, entry2.name));
7385
+ if (entry2.name === "SKILL.md") found.push(join3(dir, entry2.name));
7266
7386
  continue;
7267
7387
  }
7268
7388
  if (!entry2.isDirectory()) continue;
7269
7389
  if (SKIPPED_DIRS.has(entry2.name)) continue;
7270
7390
  if (depth + 1 <= MAX_SKILL_DEPTH)
7271
- stack.push([join2(dir, entry2.name), depth + 1]);
7391
+ stack.push([join3(dir, entry2.name), depth + 1]);
7272
7392
  }
7273
7393
  }
7274
7394
  return found.sort();
7275
7395
  }
7276
7396
  function packageDirs(root) {
7277
- if (!existsSync2(root)) return [];
7397
+ if (!existsSync3(root)) return [];
7278
7398
  const found = [];
7279
7399
  for (const entry2 of readdirSync2(root, { withFileTypes: true })) {
7280
7400
  if (!entry2.isDirectory() && !entry2.isSymbolicLink()) continue;
7281
7401
  if (entry2.name === ".bin" || entry2.name === ".cache") continue;
7282
- const path = join2(root, entry2.name);
7402
+ const path = join3(root, entry2.name);
7283
7403
  if (entry2.name.startsWith("@")) {
7284
- if (!existsSync2(path)) continue;
7404
+ if (!existsSync3(path)) continue;
7285
7405
  for (const scoped of readdirSync2(path, { withFileTypes: true })) {
7286
7406
  if (scoped.isDirectory() || scoped.isSymbolicLink()) {
7287
- found.push(join2(path, scoped.name));
7407
+ found.push(join3(path, scoped.name));
7288
7408
  }
7289
7409
  }
7290
7410
  continue;
@@ -7296,7 +7416,7 @@ function packageDirs(root) {
7296
7416
  function readManifest(dir) {
7297
7417
  try {
7298
7418
  const parsed = JSON.parse(
7299
- readFileSync2(join2(dir, "package.json"), "utf8")
7419
+ readFileSync3(join3(dir, "package.json"), "utf8")
7300
7420
  );
7301
7421
  return parsed !== null && typeof parsed === "object" ? parsed : null;
7302
7422
  } catch {
@@ -7330,8 +7450,8 @@ function globDirs(base, pattern) {
7330
7450
  }
7331
7451
  const segment = segments[index];
7332
7452
  if (!segment.includes("*")) {
7333
- const next = join2(dir, segment);
7334
- if (existsSync2(next)) walk(next, index + 1);
7453
+ const next = join3(dir, segment);
7454
+ if (existsSync3(next)) walk(next, index + 1);
7335
7455
  return;
7336
7456
  }
7337
7457
  let entries;
@@ -7343,12 +7463,12 @@ function globDirs(base, pattern) {
7343
7463
  const children = entries.filter((e) => e.isDirectory() || e.isSymbolicLink()).filter((e) => !SKIPPED_DIRS.has(e.name));
7344
7464
  if (segment === "**") {
7345
7465
  walk(dir, index + 1);
7346
- for (const child of children) walk(join2(dir, child.name), index);
7466
+ for (const child of children) walk(join3(dir, child.name), index);
7347
7467
  return;
7348
7468
  }
7349
7469
  const matcher = segmentMatcher(segment);
7350
7470
  for (const child of children) {
7351
- if (matcher.test(child.name)) walk(join2(dir, child.name), index + 1);
7471
+ if (matcher.test(child.name)) walk(join3(dir, child.name), index + 1);
7352
7472
  }
7353
7473
  };
7354
7474
  walk(base, 0);
@@ -7373,7 +7493,7 @@ function workspacePackageDirs(root) {
7373
7493
  }
7374
7494
  }
7375
7495
  }
7376
- const members = [...included].filter((m) => !excluded.has(m) && existsSync2(join2(m, "package.json"))).sort();
7496
+ const members = [...included].filter((m) => !excluded.has(m) && existsSync3(join3(m, "package.json"))).sort();
7377
7497
  for (const member2 of members) expand(member2);
7378
7498
  ordered.push(dir);
7379
7499
  };
@@ -7390,9 +7510,9 @@ function nameOf(dir, named2) {
7390
7510
  }
7391
7511
  function expandRootGlob(dir) {
7392
7512
  if (!dir.includes("*")) return [dir];
7393
- const absolute2 = isAbsolute(dir);
7513
+ const absolute2 = isAbsolute2(dir);
7394
7514
  const base = absolute2 ? "/" : ".";
7395
- return globDirs(base, dir).filter((d) => existsSync2(join2(d, "package.json"))).sort();
7515
+ return globDirs(base, dir).filter((d) => existsSync3(join3(d, "package.json"))).sort();
7396
7516
  }
7397
7517
  function readCatalog(options2) {
7398
7518
  const scopes = options2.scopes ?? [];
@@ -7416,7 +7536,7 @@ function readCatalog(options2) {
7416
7536
  seenPaths.add(path);
7417
7537
  let source2;
7418
7538
  try {
7419
- source2 = readFileSync2(path, "utf8");
7539
+ source2 = readFileSync3(path, "utf8");
7420
7540
  } catch {
7421
7541
  continue;
7422
7542
  }
@@ -7460,7 +7580,7 @@ function readCatalog(options2) {
7460
7580
  }
7461
7581
  seen.add(entry2.name);
7462
7582
  if (kindOf(entry2) === "skill" && basename2(entry2.path) === "SKILL.md") {
7463
- const parsed = frontmatterObject(readFileSync2(entry2.path, "utf8"));
7583
+ const parsed = frontmatterObject(readFileSync3(entry2.path, "utf8"));
7464
7584
  for (const problem of specProblems(
7465
7585
  parsed,
7466
7586
  basename2(dirname2(entry2.path))
@@ -7482,6 +7602,28 @@ function withoutBody({
7482
7602
 
7483
7603
  // src/commands/roots.ts
7484
7604
  init_config();
7605
+
7606
+ // src/marketplace/builtin.ts
7607
+ import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
7608
+ import { dirname as dirname4, join as join5 } from "path";
7609
+ import { fileURLToPath } from "url";
7610
+ function publicMarketplaceRoot(start2 = dirname4(fileURLToPath(import.meta.url))) {
7611
+ let directory = start2;
7612
+ for (; ; ) {
7613
+ const manifest2 = join5(directory, "package.json");
7614
+ if (existsSync5(manifest2)) {
7615
+ const value = JSON.parse(readFileSync5(manifest2, "utf8"));
7616
+ if (value !== null && typeof value === "object" && "name" in value && value.name === "@modootoday/pmcp")
7617
+ return directory;
7618
+ }
7619
+ const parent = dirname4(directory);
7620
+ if (parent === directory)
7621
+ throw new Error("Cannot locate the bundled PMCP marketplace");
7622
+ directory = parent;
7623
+ }
7624
+ }
7625
+
7626
+ // src/commands/roots.ts
7485
7627
  var CATALOG_OPTIONS = [
7486
7628
  {
7487
7629
  name: "root",
@@ -7495,9 +7637,14 @@ var CATALOG_OPTIONS = [
7495
7637
  repeat: true,
7496
7638
  placeholder: "<prefix>"
7497
7639
  },
7640
+ {
7641
+ name: "no-builtin",
7642
+ describe: "Exclude the bundled free PMCP marketplace.",
7643
+ boolean: true
7644
+ },
7498
7645
  {
7499
7646
  name: "marketplace",
7500
- describe: "A plugin marketplace directory (holds .claude-plugin/marketplace.json). Repeatable.",
7647
+ describe: "An installed local Claude, Codex or Grok marketplace directory. Repeatable.",
7501
7648
  repeat: true,
7502
7649
  placeholder: "<dir>"
7503
7650
  },
@@ -7520,7 +7667,7 @@ var CATALOG_OPTIONS = [
7520
7667
  },
7521
7668
  {
7522
7669
  name: "no-config",
7523
- describe: "Ignore pmcp.toml; only the flags given count.",
7670
+ describe: "Ignore pmcp.toml; CLI defaults and the given flags apply.",
7524
7671
  boolean: true
7525
7672
  }
7526
7673
  ];
@@ -7552,12 +7699,15 @@ function catalogOptionsFrom(context, onReject) {
7552
7699
  };
7553
7700
  const scopes = pick("scope", config.scopes);
7554
7701
  const marketplaces = pick("marketplace", config.marketplaces);
7702
+ const selectedMarketplaces = [...marketplaces];
7703
+ if (!context.args.flags.has("no-builtin") && config.builtin !== false)
7704
+ selectedMarketplaces.push(publicMarketplaceRoot());
7555
7705
  const packages = pick("package", config.packages);
7556
7706
  const workspaces = pick("workspace", config.workspaces);
7557
7707
  return {
7558
7708
  roots: rootsFrom(context),
7559
7709
  ...scopes.length > 0 ? { scopes } : {},
7560
- ...marketplaces.length > 0 ? { marketplaces } : {},
7710
+ ...selectedMarketplaces.length > 0 ? { marketplaces: [...new Set(selectedMarketplaces)] } : {},
7561
7711
  ...packages.length > 0 ? { packages } : {},
7562
7712
  ...workspaces.length > 0 ? { workspaces } : {},
7563
7713
  ...onReject ? { onReject } : {}
@@ -7629,8 +7779,8 @@ function embeddingFrom(context) {
7629
7779
  dtype: one(context.args, "dtype") ?? configuration.dtype,
7630
7780
  dimensions: dimension2 === void 0 ? configuration.dimensions : Number(dimension2),
7631
7781
  revision: one(context.args, "model-revision") ?? configuration.revision,
7632
- modelPath: modelPath === void 0 ? configuration.modelPath : resolve4(context.cwd, modelPath),
7633
- cacheDir: cacheDir === void 0 ? configuration.cacheDir : resolve4(context.cwd, cacheDir),
7782
+ modelPath: modelPath === void 0 ? configuration.modelPath : resolve5(context.cwd, modelPath),
7783
+ cacheDir: cacheDir === void 0 ? configuration.cacheDir : resolve5(context.cwd, cacheDir),
7634
7784
  encoder: {
7635
7785
  ...configuration.encoder,
7636
7786
  ...queryPrefix === void 0 ? {} : { queryPrefix },
@@ -7691,7 +7841,7 @@ var indexCommand = {
7691
7841
  );
7692
7842
  const force = context.args.flags.has("force");
7693
7843
  if (dryRun) {
7694
- const existing = existsSync4(path) ? await openEntryVectors(path, { readOnly: true }) : null;
7844
+ const existing = existsSync6(path) ? await openEntryVectors(path, { readOnly: true }) : null;
7695
7845
  try {
7696
7846
  const pending = !force && existing ? existing.stale(selected.indexKey, descriptions) : [...descriptions.keys()];
7697
7847
  for (const name of pending) context.ui.line(` would encode ${name}`);
@@ -7713,7 +7863,7 @@ var indexCommand = {
7713
7863
  context.ui.info("ranking stays lexical until then, which is the default");
7714
7864
  return 3;
7715
7865
  }
7716
- mkdirSync(dirname4(path), { recursive: true });
7866
+ mkdirSync(dirname5(path), { recursive: true });
7717
7867
  const store = await openEntryVectors(path);
7718
7868
  if (store === null) {
7719
7869
  context.ui.error(
@@ -7910,7 +8060,7 @@ function registerSkillPrompts(server, tools) {
7910
8060
  }
7911
8061
 
7912
8062
  // src/resources.ts
7913
- import { statSync as statSync4 } from "fs";
8063
+ import { statSync as statSync5 } from "fs";
7914
8064
  import {
7915
8065
  ResourceNotFoundError,
7916
8066
  ResourceTemplate
@@ -7918,8 +8068,8 @@ import {
7918
8068
 
7919
8069
  // src/files/list.ts
7920
8070
  import { createHash as createHash2 } from "crypto";
7921
- import { readFileSync as readFileSync4, readdirSync as readdirSync3, statSync } from "fs";
7922
- import { basename as basename4, join as join4, relative as relative2, sep } from "path";
8071
+ import { readFileSync as readFileSync6, readdirSync as readdirSync3, statSync as statSync2 } from "fs";
8072
+ import { basename as basename4, join as join6, relative as relative3, sep as sep2 } from "path";
7923
8073
 
7924
8074
  // src/files/redact.ts
7925
8075
  import { basename as basename3 } from "path";
@@ -7956,11 +8106,11 @@ function servedBytes(path, raw) {
7956
8106
  var FILE_LIST_LIMIT = 200;
7957
8107
  var sha256 = (bytes) => createHash2("sha256").update(bytes).digest("hex");
7958
8108
  function describe(path, full) {
7959
- const bytes = servedBytes(full, readFileSync4(full));
8109
+ const bytes = servedBytes(full, readFileSync6(full));
7960
8110
  return { path, bytes: bytes.length, sha256: sha256(bytes) };
7961
8111
  }
7962
8112
  function listSkillFiles(root, limit = FILE_LIST_LIMIT) {
7963
- if (statSync(root).isFile()) {
8113
+ if (statSync2(root).isFile()) {
7964
8114
  return { files: [describe(basename4(root), root)], truncated: false };
7965
8115
  }
7966
8116
  const files = [];
@@ -7969,14 +8119,14 @@ function listSkillFiles(root, limit = FILE_LIST_LIMIT) {
7969
8119
  const dir = stack.pop();
7970
8120
  for (const entry2 of readdirSync3(dir, { withFileTypes: true })) {
7971
8121
  if (entry2.name === "node_modules" || entry2.name === ".git") continue;
7972
- const full = join4(dir, entry2.name);
8122
+ const full = join6(dir, entry2.name);
7973
8123
  if (entry2.isDirectory()) {
7974
8124
  stack.push(full);
7975
8125
  continue;
7976
8126
  }
7977
8127
  if (!entry2.isFile()) continue;
7978
8128
  if (files.length >= limit) return { files, truncated: true };
7979
- files.push(describe(relative2(root, full).split(sep).join("/"), full));
8129
+ files.push(describe(relative3(root, full).split(sep2).join("/"), full));
7980
8130
  }
7981
8131
  }
7982
8132
  files.sort((a, b) => a.path.localeCompare(b.path));
@@ -7984,7 +8134,7 @@ function listSkillFiles(root, limit = FILE_LIST_LIMIT) {
7984
8134
  }
7985
8135
 
7986
8136
  // src/files/read.ts
7987
- import { readFileSync as readFileSync5, statSync as statSync3 } from "fs";
8137
+ import { readFileSync as readFileSync7, statSync as statSync4 } from "fs";
7988
8138
 
7989
8139
  // src/mime.ts
7990
8140
  var TYPES = {
@@ -8090,31 +8240,31 @@ function classify(path, bytes) {
8090
8240
  }
8091
8241
 
8092
8242
  // src/files/resolve.ts
8093
- import { realpathSync, statSync as statSync2 } from "fs";
8094
- import { dirname as dirname5, isAbsolute as isAbsolute2, relative as relative3, resolve as resolve5, sep as sep2 } from "path";
8095
- var ownFile = (entry2) => relative3(assetRoot(entry2), entry2.path).split(sep2).join("/");
8243
+ import { realpathSync as realpathSync2, statSync as statSync3 } from "fs";
8244
+ import { dirname as dirname6, isAbsolute as isAbsolute3, relative as relative4, resolve as resolve6, sep as sep3 } from "path";
8245
+ var ownFile = (entry2) => relative4(assetRoot(entry2), entry2.path).split(sep3).join("/");
8096
8246
  function resolveSkillFile(entry2, wanted = ownFile(entry2)) {
8097
- if (isAbsolute2(wanted) || wanted.split(/[\\/]/u).includes("..")) {
8247
+ if (isAbsolute3(wanted) || wanted.split(/[\\/]/u).includes("..")) {
8098
8248
  return { ok: false, error: "path_outside_skill", detail: wanted };
8099
8249
  }
8100
- const scope = realpathSync(assetRoot(entry2));
8101
- const single = statSync2(scope).isFile();
8102
- const root = single ? dirname5(scope) : scope;
8250
+ const scope = realpathSync2(assetRoot(entry2));
8251
+ const single = statSync3(scope).isFile();
8252
+ const root = single ? dirname6(scope) : scope;
8103
8253
  let target2;
8104
8254
  try {
8105
- target2 = realpathSync(
8106
- single && wanted === "" ? scope : resolve5(root, wanted)
8255
+ target2 = realpathSync2(
8256
+ single && wanted === "" ? scope : resolve6(root, wanted)
8107
8257
  );
8108
8258
  } catch {
8109
8259
  return { ok: false, error: "no_such_file", detail: wanted };
8110
8260
  }
8111
- const inside = single ? target2 === scope : target2 === root || target2.startsWith(root + sep2);
8261
+ const inside = single ? target2 === scope : target2 === root || target2.startsWith(root + sep3);
8112
8262
  if (!inside)
8113
8263
  return { ok: false, error: "path_outside_skill", detail: wanted };
8114
8264
  return {
8115
8265
  ok: true,
8116
8266
  target: target2,
8117
- path: relative3(root, target2).split(sep2).join("/")
8267
+ path: relative4(root, target2).split(sep3).join("/")
8118
8268
  };
8119
8269
  }
8120
8270
 
@@ -8123,7 +8273,7 @@ var READ_BUDGET_BYTES = 256 * 1024;
8123
8273
  function readSkillFile(entry2, wanted, budget = READ_BUDGET_BYTES) {
8124
8274
  const resolved = resolveSkillFile(entry2, wanted);
8125
8275
  if (!resolved.ok) return resolved;
8126
- const size = statSync3(resolved.target).size;
8276
+ const size = statSync4(resolved.target).size;
8127
8277
  if (size > budget) {
8128
8278
  return {
8129
8279
  ok: false,
@@ -8131,7 +8281,7 @@ function readSkillFile(entry2, wanted, budget = READ_BUDGET_BYTES) {
8131
8281
  detail: `${size} bytes > ${budget}`
8132
8282
  };
8133
8283
  }
8134
- const bytes = servedBytes(resolved.target, readFileSync5(resolved.target));
8284
+ const bytes = servedBytes(resolved.target, readFileSync7(resolved.target));
8135
8285
  const { kind: kind2, mimeType } = classify(resolved.path, bytes);
8136
8286
  return {
8137
8287
  ok: true,
@@ -8171,7 +8321,7 @@ function listing(entries) {
8171
8321
  name: entry2.name,
8172
8322
  description: entry2.description,
8173
8323
  mimeType: "text/markdown",
8174
- size: statSync4(entry2.path).size
8324
+ size: statSync5(entry2.path).size
8175
8325
  }));
8176
8326
  }
8177
8327
  function complete(value, entries) {
@@ -8208,7 +8358,7 @@ function registerSkillResources(server, skills) {
8208
8358
  }
8209
8359
 
8210
8360
  // src/server.ts
8211
- import { readFileSync as readFileSync7 } from "fs";
8361
+ import { readFileSync as readFileSync9 } from "fs";
8212
8362
 
8213
8363
  // src/find.ts
8214
8364
  import { createHash as createHash3 } from "crypto";
@@ -8297,11 +8447,11 @@ function rank(matches2, limit) {
8297
8447
  }
8298
8448
 
8299
8449
  // src/files/bundle.ts
8300
- import { readFileSync as readFileSync6, statSync as statSync5 } from "fs";
8301
- import { dirname as dirname6, join as join5 } from "path";
8450
+ import { readFileSync as readFileSync8, statSync as statSync6 } from "fs";
8451
+ import { dirname as dirname7, join as join7 } from "path";
8302
8452
  function bundleSkill(entry2) {
8303
8453
  const root = assetRoot(entry2);
8304
- const base = statSync5(root).isFile() ? dirname6(root) : root;
8454
+ const base = statSync6(root).isFile() ? dirname7(root) : root;
8305
8455
  const listing2 = listSkillFiles(root);
8306
8456
  return {
8307
8457
  name: entry2.name,
@@ -8309,7 +8459,7 @@ function bundleSkill(entry2) {
8309
8459
  files: listing2.files.map((file2) => ({
8310
8460
  ...file2,
8311
8461
  uri: skillFileUri(entry2, file2.path),
8312
- mimeType: classify(file2.path, readFileSync6(join5(base, file2.path))).mimeType
8462
+ mimeType: classify(file2.path, readFileSync8(join7(base, file2.path))).mimeType
8313
8463
  }))
8314
8464
  };
8315
8465
  }
@@ -8476,7 +8626,7 @@ function createSkillTools(options2) {
8476
8626
  describe(name) {
8477
8627
  const entry2 = byName(name);
8478
8628
  if (!entry2) return null;
8479
- const source2 = readFileSync7(entry2.path, "utf8");
8629
+ const source2 = readFileSync9(entry2.path, "utf8");
8480
8630
  const listing2 = listSkillFiles(assetRoot(entry2));
8481
8631
  return {
8482
8632
  name: entry2.name,
@@ -8513,7 +8663,7 @@ function createSkillTools(options2) {
8513
8663
  return {
8514
8664
  name: entry2.name,
8515
8665
  body: readBody(
8516
- servedBytes(entry2.path, readFileSync7(entry2.path)).toString("utf8")
8666
+ servedBytes(entry2.path, readFileSync9(entry2.path)).toString("utf8")
8517
8667
  ),
8518
8668
  files: bundle.files.filter((file2) => file2.path !== own),
8519
8669
  filesTruncated: bundle.truncated
@@ -8533,17 +8683,17 @@ function createSkillTools(options2) {
8533
8683
 
8534
8684
  // src/extension/entry.ts
8535
8685
  import { createHash as createHash4 } from "crypto";
8536
- import { readFileSync as readFileSync8, readdirSync as readdirSync4, statSync as statSync6 } from "fs";
8537
- import { basename as basename5, dirname as dirname7, join as join6, relative as relative4, sep as sep3 } from "path";
8686
+ import { readFileSync as readFileSync10, readdirSync as readdirSync4, statSync as statSync7 } from "fs";
8687
+ import { basename as basename5, dirname as dirname8, join as join8, relative as relative5, sep as sep4 } from "path";
8538
8688
  var MAX_RESOURCES = 512;
8539
8689
  var MAX_SKILL_BYTES = 16 * 1024 * 1024;
8540
8690
  var digests = /* @__PURE__ */ new Map();
8541
8691
  function facts(path) {
8542
- const stat = statSync6(path);
8692
+ const stat = statSync7(path);
8543
8693
  const key = `${stat.mtimeMs}:${stat.size}`;
8544
8694
  const cached = digests.get(path);
8545
8695
  if (cached?.key === key) return cached;
8546
- const bytes = servedBytes(path, readFileSync8(path));
8696
+ const bytes = servedBytes(path, readFileSync10(path));
8547
8697
  const digest2 = `sha256:${createHash4("sha256").update(bytes).digest("hex")}`;
8548
8698
  const fresh = { key, digest: digest2, size: bytes.length };
8549
8699
  digests.set(path, fresh);
@@ -8556,7 +8706,7 @@ function filesUnder(root) {
8556
8706
  const dir = stack.pop();
8557
8707
  for (const entry2 of readdirSync4(dir, { withFileTypes: true })) {
8558
8708
  if (entry2.name === "node_modules" || entry2.name === ".git") continue;
8559
- const full = join6(dir, entry2.name);
8709
+ const full = join8(dir, entry2.name);
8560
8710
  if (entry2.isDirectory()) stack.push(full);
8561
8711
  else if (entry2.isFile()) found.push(full);
8562
8712
  if (found.length > MAX_RESOURCES) return null;
@@ -8567,8 +8717,8 @@ function filesUnder(root) {
8567
8717
  function extensionEntry(entry2) {
8568
8718
  if (kindOf(entry2) !== "skill" || basename5(entry2.path) !== "SKILL.md")
8569
8719
  return null;
8570
- const frontmatter = frontmatterObject(readFileSync8(entry2.path, "utf8"));
8571
- const root = dirname7(entry2.path);
8720
+ const frontmatter = frontmatterObject(readFileSync10(entry2.path, "utf8"));
8721
+ const root = dirname8(entry2.path);
8572
8722
  if (specProblems(frontmatter, basename5(root)).length > 0) return null;
8573
8723
  if (frontmatter?.["name"] !== entry2.slug) return null;
8574
8724
  const files = filesUnder(root);
@@ -8577,7 +8727,7 @@ function extensionEntry(entry2) {
8577
8727
  const resources = files.map((path) => {
8578
8728
  const fact = facts(path);
8579
8729
  total += fact.size;
8580
- const file2 = relative4(root, path).split(sep3).join("/");
8730
+ const file2 = relative5(root, path).split(sep4).join("/");
8581
8731
  return {
8582
8732
  uri: skillFileUri(entry2, file2),
8583
8733
  digest: fact.digest,
@@ -9013,7 +9163,7 @@ function registerMailboxTools(server, service) {
9013
9163
 
9014
9164
  // src/mcp.ts
9015
9165
  var SERVER_NAME = "pmcp";
9016
- var SERVER_VERSION = "0.13.0";
9166
+ var SERVER_VERSION = "0.14.0";
9017
9167
  function registerSkillTools(server, tools) {
9018
9168
  registerCatalogTool(server, tools);
9019
9169
  registerFindTool(server, tools);
@@ -9142,7 +9292,7 @@ async function serveWithMailbox(catalog, mailbox, serving = {}) {
9142
9292
  init_config2();
9143
9293
 
9144
9294
  // src/search.ts
9145
- import { existsSync as existsSync7 } from "fs";
9295
+ import { existsSync as existsSync9 } from "fs";
9146
9296
  init_encoder();
9147
9297
  async function prepareSearch(catalog, options2) {
9148
9298
  const lexical = (reason) => ({
@@ -9150,7 +9300,7 @@ async function prepareSearch(catalog, options2) {
9150
9300
  reason,
9151
9301
  options: {}
9152
9302
  });
9153
- if (!existsSync7(options2.indexPath)) return lexical("index_missing");
9303
+ if (!existsSync9(options2.indexPath)) return lexical("index_missing");
9154
9304
  let store;
9155
9305
  try {
9156
9306
  store = await openEntryVectors(options2.indexPath, { readOnly: true });
@@ -9301,16 +9451,16 @@ import {
9301
9451
  fchmodSync,
9302
9452
  mkdirSync as mkdirSync4,
9303
9453
  openSync as openSync2,
9304
- readFileSync as readFileSync10,
9454
+ readFileSync as readFileSync12,
9305
9455
  rmSync as rmSync2,
9306
9456
  writeSync
9307
9457
  } from "fs";
9308
9458
  import { homedir as homedir2 } from "os";
9309
- import { join as join8 } from "path";
9459
+ import { join as join10 } from "path";
9310
9460
  var DEVICE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
9311
9461
  function globalDir(home = homedir2(), env = process.env) {
9312
9462
  const xdg = env["XDG_CONFIG_HOME"];
9313
- return xdg !== void 0 && xdg !== "" ? join8(xdg, "pmcp") : join8(home, ".pmcp");
9463
+ return xdg !== void 0 && xdg !== "" ? join10(xdg, "pmcp") : join10(home, ".pmcp");
9314
9464
  }
9315
9465
  var form = (fields) => new URLSearchParams(fields).toString();
9316
9466
  var FORM_HEADERS = { "content-type": "application/x-www-form-urlencoded" };
@@ -9420,10 +9570,10 @@ async function pollOnce(metadata2, request3, fetcher2, now = Date.now) {
9420
9570
  return { kind: "denied" };
9421
9571
  }
9422
9572
  }
9423
- var sessionPath = (home) => join8(globalDir(home), "session.json");
9573
+ var sessionPath = (home) => join10(globalDir(home), "session.json");
9424
9574
  function readSession(home) {
9425
9575
  try {
9426
- return JSON.parse(readFileSync10(sessionPath(home), "utf8"));
9576
+ return JSON.parse(readFileSync12(sessionPath(home), "utf8"));
9427
9577
  } catch {
9428
9578
  return null;
9429
9579
  }
@@ -9477,7 +9627,7 @@ var DEFAULT_RESOURCE = "https://api.pmcp.build";
9477
9627
  var DEFAULT_SCOPE = "pmcp:catalog:read pmcp:distribution:read";
9478
9628
  var fetcher = (url, init) => fetch(url, init);
9479
9629
  var setting = (env, name, fallback) => env[name] ?? fallback;
9480
- var wait = (ms) => new Promise((resolve19) => setTimeout(resolve19, ms));
9630
+ var wait = (ms) => new Promise((resolve22) => setTimeout(resolve22, ms));
9481
9631
  var loginCommand = {
9482
9632
  name: "login",
9483
9633
  describe: "Sign in on this machine, to obtain skills this project lacks",
@@ -9645,29 +9795,41 @@ function sayStanding(context, line) {
9645
9795
  }
9646
9796
 
9647
9797
  // src/installed.ts
9648
- import { readFileSync as readFileSync11 } from "fs";
9649
- import { dirname as dirname10, join as join9, resolve as resolve7 } from "path";
9650
- function object(value) {
9798
+ import { existsSync as existsSync10, readFileSync as readFileSync13 } from "fs";
9799
+ import { dirname as dirname11, join as join11, resolve as resolve8 } from "path";
9800
+ function object2(value) {
9651
9801
  return typeof value === "object" && value !== null && !Array.isArray(value);
9652
9802
  }
9653
9803
  function absent(error) {
9654
- return object(error) && (error.code === "ENOENT" || error.code === "ENOTDIR");
9804
+ return object2(error) && (error.code === "ENOENT" || error.code === "ENOTDIR");
9655
9805
  }
9656
9806
  function packageName(name) {
9657
9807
  return /^(?:@[a-z0-9._-]+\/)?[a-z0-9][a-z0-9._-]*$/u.test(name);
9658
9808
  }
9809
+ function installedPackageDirectory(project2, name) {
9810
+ if (!packageName(name)) throw new Error("Invalid installed package name");
9811
+ let directory = resolve8(project2);
9812
+ for (; ; ) {
9813
+ const candidate2 = join11(directory, "node_modules", name);
9814
+ if (existsSync10(join11(candidate2, "package.json"))) return candidate2;
9815
+ const parent = dirname11(directory);
9816
+ if (parent === directory)
9817
+ throw new Error("Installed package manifest was not found");
9818
+ directory = parent;
9819
+ }
9820
+ }
9659
9821
  function locate(name, project2) {
9660
9822
  let directory = project2;
9661
9823
  for (; ; ) {
9662
9824
  let source2;
9663
9825
  try {
9664
- source2 = readFileSync11(
9665
- join9(directory, "node_modules", name, "package.json"),
9826
+ source2 = readFileSync13(
9827
+ join11(directory, "node_modules", name, "package.json"),
9666
9828
  "utf8"
9667
9829
  );
9668
9830
  } catch (error) {
9669
9831
  if (!absent(error)) return { name, reason: "unreadable_manifest" };
9670
- const parent = dirname10(directory);
9832
+ const parent = dirname11(directory);
9671
9833
  if (parent === directory) return { name, reason: "not_installed" };
9672
9834
  directory = parent;
9673
9835
  continue;
@@ -9678,7 +9840,7 @@ function locate(name, project2) {
9678
9840
  } catch {
9679
9841
  return { name, reason: "invalid_manifest" };
9680
9842
  }
9681
- if (!object(manifest2) || typeof manifest2.name !== "string" || !packageName(manifest2.name) || typeof manifest2.version !== "string" || manifest2.version.trim() === "") {
9843
+ if (!object2(manifest2) || typeof manifest2.name !== "string" || !packageName(manifest2.name) || typeof manifest2.version !== "string" || manifest2.version.trim() === "") {
9682
9844
  return { name, reason: "invalid_manifest" };
9683
9845
  }
9684
9846
  return {
@@ -9689,11 +9851,11 @@ function locate(name, project2) {
9689
9851
  }
9690
9852
  }
9691
9853
  function readInstalledDependencies(projectDirectory) {
9692
- const project2 = resolve7(projectDirectory);
9854
+ const project2 = resolve8(projectDirectory);
9693
9855
  const manifest2 = JSON.parse(
9694
- readFileSync11(join9(project2, "package.json"), "utf8")
9856
+ readFileSync13(join11(project2, "package.json"), "utf8")
9695
9857
  );
9696
- if (!object(manifest2))
9858
+ if (!object2(manifest2))
9697
9859
  throw new Error("project package.json must contain an object");
9698
9860
  const names = /* @__PURE__ */ new Set();
9699
9861
  for (const field of [
@@ -9704,7 +9866,7 @@ function readInstalledDependencies(projectDirectory) {
9704
9866
  ]) {
9705
9867
  const declared = manifest2[field];
9706
9868
  if (declared === void 0) continue;
9707
- if (!object(declared)) throw new Error(`${field} must contain an object`);
9869
+ if (!object2(declared)) throw new Error(`${field} must contain an object`);
9708
9870
  for (const [name, range] of Object.entries(declared)) {
9709
9871
  if (!packageName(name) || typeof range !== "string") {
9710
9872
  throw new Error(`invalid dependency declaration in ${field}`);
@@ -9724,8 +9886,8 @@ function readInstalledDependencies(projectDirectory) {
9724
9886
 
9725
9887
  // src/install/plan.ts
9726
9888
  import { createHash as createHash7 } from "crypto";
9727
- import { existsSync as existsSync8, readFileSync as readFileSync12 } from "fs";
9728
- import { dirname as dirname11, join as join10, relative as relative5, resolve as resolve8, sep as sep4 } from "path";
9889
+ import { existsSync as existsSync11, readFileSync as readFileSync14 } from "fs";
9890
+ import { dirname as dirname12, join as join12, relative as relative6, resolve as resolve9, sep as sep5 } from "path";
9729
9891
  import semver from "semver";
9730
9892
  function matchingSkills(catalog, inventory) {
9731
9893
  const matches2 = [];
@@ -9759,7 +9921,7 @@ function fingerprint(files) {
9759
9921
  for (const file2 of files) {
9760
9922
  hash2.update(file2).update("\0");
9761
9923
  try {
9762
- hash2.update(readFileSync12(file2));
9924
+ hash2.update(readFileSync14(file2));
9763
9925
  } catch (error) {
9764
9926
  if (error.code !== "ENOENT") throw error;
9765
9927
  hash2.update("absent");
@@ -9770,32 +9932,32 @@ function fingerprint(files) {
9770
9932
  }
9771
9933
  function manifestAt(directory) {
9772
9934
  const value = JSON.parse(
9773
- readFileSync12(join10(directory, "package.json"), "utf8")
9935
+ readFileSync14(join12(directory, "package.json"), "utf8")
9774
9936
  );
9775
9937
  if (!value || typeof value !== "object" || Array.isArray(value))
9776
9938
  throw new Error("invalid project manifest");
9777
9939
  return value;
9778
9940
  }
9779
9941
  function installContext(directory) {
9780
- const project2 = resolve8(directory);
9942
+ const project2 = resolve9(directory);
9781
9943
  const manifest2 = manifestAt(project2);
9782
9944
  let root = project2;
9783
9945
  let ancestor = project2;
9784
9946
  for (; ; ) {
9785
- if (ancestor !== project2 && existsSync8(join10(ancestor, "package.json"))) {
9947
+ if (ancestor !== project2 && existsSync11(join12(ancestor, "package.json"))) {
9786
9948
  const candidate2 = manifestAt(ancestor);
9787
9949
  if (candidate2.workspaces !== void 0) {
9788
9950
  root = ancestor;
9789
9951
  break;
9790
9952
  }
9791
- if (LOCKS.some((file2) => existsSync8(join10(ancestor, file2)))) break;
9953
+ if (LOCKS.some((file2) => existsSync11(join12(ancestor, file2)))) break;
9792
9954
  }
9793
- if (existsSync8(join10(ancestor, ".git")) || dirname11(ancestor) === ancestor)
9955
+ if (existsSync11(join12(ancestor, ".git")) || dirname12(ancestor) === ancestor)
9794
9956
  break;
9795
- ancestor = dirname11(ancestor);
9957
+ ancestor = dirname12(ancestor);
9796
9958
  }
9797
9959
  const owner = manifestAt(root);
9798
- const lockNames = LOCKS.filter((file2) => existsSync8(join10(root, file2)));
9960
+ const lockNames = LOCKS.filter((file2) => existsSync11(join12(root, file2)));
9799
9961
  const lockManagers = new Set(
9800
9962
  lockNames.map((file2) => {
9801
9963
  if (file2.startsWith("bun.")) return "bun";
@@ -9819,16 +9981,16 @@ function installContext(directory) {
9819
9981
  throw new Error(
9820
9982
  "declare packageManager or install project dependencies first"
9821
9983
  );
9822
- if (root !== project2 && LOCKS.some((file2) => existsSync8(join10(project2, file2)))) {
9984
+ if (root !== project2 && LOCKS.some((file2) => existsSync11(join12(project2, file2)))) {
9823
9985
  throw new Error(
9824
9986
  "nested project has its own lockfile; resolve the workspace boundary first"
9825
9987
  );
9826
9988
  }
9827
9989
  const files = [
9828
9990
  .../* @__PURE__ */ new Set([
9829
- join10(root, "package.json"),
9830
- join10(project2, "package.json"),
9831
- ...LOCKS.map((file2) => join10(root, file2))
9991
+ join12(root, "package.json"),
9992
+ join12(project2, "package.json"),
9993
+ ...LOCKS.map((file2) => join12(root, file2))
9832
9994
  ])
9833
9995
  ];
9834
9996
  return {
@@ -9916,7 +10078,7 @@ function planInstall(options2) {
9916
10078
  ];
9917
10079
  if (context.project !== context.root)
9918
10080
  args.push(
9919
- `--workspace=${relative5(context.root, context.project).split(sep4).join("/")}`
10081
+ `--workspace=${relative6(context.root, context.project).split(sep5).join("/")}`
9920
10082
  );
9921
10083
  } else {
9922
10084
  args = ["add", "--dev", "--exact", "--ignore-scripts"];
@@ -9936,16 +10098,17 @@ function planInstall(options2) {
9936
10098
  }
9937
10099
 
9938
10100
  // src/commands/remote-options.ts
9939
- import { resolve as resolve9 } from "path";
10101
+ import { join as join14, resolve as resolve10 } from "path";
10102
+ import { readFileSync as readFileSync17 } from "fs";
9940
10103
 
9941
10104
  // src/remote/catalog.ts
9942
- import { readFileSync as readFileSync14, statSync as statSync7 } from "fs";
10105
+ import { readFileSync as readFileSync16, statSync as statSync8 } from "fs";
9943
10106
  import semver2 from "semver";
9944
10107
  import { z as z13 } from "zod";
9945
10108
 
9946
10109
  // src/remote/catalog-cache.ts
9947
- import { mkdirSync as mkdirSync5, readFileSync as readFileSync13, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "fs";
9948
- import { join as join11 } from "path";
10110
+ import { mkdirSync as mkdirSync5, readFileSync as readFileSync15, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "fs";
10111
+ import { join as join13 } from "path";
9949
10112
  var MAX_CACHE_BYTES = 8 * 1024 * 1024;
9950
10113
  function memoryCatalogCache() {
9951
10114
  const held = /* @__PURE__ */ new Map();
@@ -9957,11 +10120,11 @@ function memoryCatalogCache() {
9957
10120
  };
9958
10121
  }
9959
10122
  function fileCatalogCache(dir) {
9960
- const path = join11(dir, "catalog-cache.json");
10123
+ const path = join13(dir, "catalog-cache.json");
9961
10124
  return {
9962
10125
  read(origin) {
9963
10126
  try {
9964
- const raw = readFileSync13(path, "utf8");
10127
+ const raw = readFileSync15(path, "utf8");
9965
10128
  if (raw.length > MAX_CACHE_BYTES) return null;
9966
10129
  const held = JSON.parse(raw);
9967
10130
  if (typeof held !== "object" || held === null) return null;
@@ -10081,10 +10244,10 @@ function catalogEndpoint(origin) {
10081
10244
  return new URL("/v1/catalog", url).href;
10082
10245
  }
10083
10246
  function readCatalogFile(path) {
10084
- const stat = statSync7(path);
10247
+ const stat = statSync8(path);
10085
10248
  if (!stat.isFile() || stat.size > MAX_CATALOG_BYTES)
10086
10249
  throw new Error("catalog file exceeds the supported size");
10087
- const bytes = readFileSync14(path);
10250
+ const bytes = readFileSync16(path);
10088
10251
  if (bytes.byteLength > MAX_CATALOG_BYTES)
10089
10252
  throw new Error("catalog file exceeds the supported size");
10090
10253
  return parseCatalog(JSON.parse(bytes.toString("utf8")));
@@ -10155,6 +10318,11 @@ async function request(origin, fetcher2, held, cache) {
10155
10318
 
10156
10319
  // src/commands/remote-options.ts
10157
10320
  var REMOTE_OPTIONS = [
10321
+ {
10322
+ name: "provider",
10323
+ describe: "Public free catalog (default) or explicitly hosted service.",
10324
+ placeholder: "<public|hosted>"
10325
+ },
10158
10326
  {
10159
10327
  name: "project",
10160
10328
  describe: "Project directory containing package.json.",
@@ -10168,18 +10336,41 @@ var REMOTE_OPTIONS = [
10168
10336
  },
10169
10337
  { name: "json", describe: "Print machine-readable results.", boolean: true }
10170
10338
  ];
10339
+ function catalogProvider(context) {
10340
+ const given = one(context.args, "provider");
10341
+ if (given !== void 0 && given !== "public" && given !== "hosted")
10342
+ throw new ArgumentError("Choose --provider public or hosted");
10343
+ const givenApi = one(context.args, "api");
10344
+ const api2 = givenApi ?? context.env.PMCP_API_ORIGIN;
10345
+ if (given === "public" && givenApi)
10346
+ throw new ArgumentError(
10347
+ "The public provider does not accept a hosted API origin"
10348
+ );
10349
+ return given ?? (api2 ? "hosted" : "public");
10350
+ }
10171
10351
  function projectFrom(context) {
10172
- return resolve9(context.cwd, one(context.args, "project") ?? ".");
10352
+ return resolve10(context.cwd, one(context.args, "project") ?? ".");
10173
10353
  }
10174
10354
  function apiOrigin(context) {
10175
10355
  return one(context.args, "api") ?? context.env["PMCP_API_ORIGIN"] ?? DEFAULT_API_ORIGIN;
10176
10356
  }
10177
10357
  async function remoteCatalog(context) {
10358
+ const provider = catalogProvider(context);
10178
10359
  const file2 = one(context.args, "catalog");
10179
10360
  if (file2) {
10180
10361
  if (one(context.args, "api"))
10181
10362
  throw new Error("choose --catalog or --api, not both");
10182
- return readCatalogFile(resolve9(context.cwd, file2));
10363
+ return readCatalogFile(resolve10(context.cwd, file2));
10364
+ }
10365
+ if (provider === "public") {
10366
+ const catalog = JSON.parse(
10367
+ readFileSync17(join14(publicMarketplaceRoot(), "docs/catalog.json"), "utf8")
10368
+ );
10369
+ return parseCatalog({
10370
+ schemaVersion: 1,
10371
+ requestId: "bundled-public",
10372
+ catalog
10373
+ });
10183
10374
  }
10184
10375
  return fetchCatalog(apiOrigin(context), fetch, fileCatalogCache(globalDir()));
10185
10376
  }
@@ -10222,7 +10413,7 @@ var availableCommand = {
10222
10413
  if (matches2.length > 0) {
10223
10414
  context.ui.info(
10224
10415
  "preview",
10225
- `${invocation()} preview <package> shows a full example before you subscribe`
10416
+ `${invocation()} preview <package> shows the contents and a complete example`
10226
10417
  );
10227
10418
  }
10228
10419
  for (const issue of inventory.issues)
@@ -10235,7 +10426,7 @@ var availableCommand = {
10235
10426
  // src/commands/preview.ts
10236
10427
  var previewCommand = {
10237
10428
  name: "preview",
10238
- describe: "Show what a skill contains before subscribing",
10429
+ describe: "Show a skill's contents and a complete example",
10239
10430
  usage: "pmcp preview <skill-package> [--json]",
10240
10431
  options: REMOTE_OPTIONS,
10241
10432
  async run(context) {
@@ -10260,8 +10451,6 @@ var previewCommand = {
10260
10451
  summary: entry2.summary,
10261
10452
  package: `${entry2.delivery.packageName}@${entry2.delivery.version}`,
10262
10453
  evidence: entry2.evidence,
10263
- // A script deciding on our behalf needs the recall as much as a
10264
- // person does, and more so: it will not read the prose.
10265
10454
  line: entry2.line,
10266
10455
  targets: entry2.targets,
10267
10456
  preview: entry2.preview
@@ -10374,11 +10563,11 @@ function applyInstallPlan(plan2, runner = packageManagerRunner) {
10374
10563
  if (fingerprint(plan2.context.files) !== plan2.context.fingerprint)
10375
10564
  throw new Error("project changed after planning; create a new plan");
10376
10565
  for (const entry2 of plan2.changes) {
10377
- const integrity = runner.integrity(
10566
+ const integrity2 = runner.integrity(
10378
10567
  `${entry2.packageName}@${entry2.version}`,
10379
10568
  plan2
10380
10569
  );
10381
- if (integrity !== entry2.integrity)
10570
+ if (integrity2 !== entry2.integrity)
10382
10571
  throw new Error(
10383
10572
  "registry integrity differs from the catalog; nothing was installed"
10384
10573
  );
@@ -10403,8 +10592,8 @@ function applyInstallPlan(plan2, runner = packageManagerRunner) {
10403
10592
 
10404
10593
  // src/install/verify-content.ts
10405
10594
  import { createHash as createHash8 } from "crypto";
10406
- import { readdirSync as readdirSync5, readFileSync as readFileSync15, statSync as statSync8 } from "fs";
10407
- import { join as join12, relative as relative6, resolve as resolve10, sep as sep5 } from "path";
10595
+ import { readdirSync as readdirSync5, readFileSync as readFileSync18, statSync as statSync9 } from "fs";
10596
+ import { join as join15, relative as relative7, resolve as resolve11, sep as sep6 } from "path";
10408
10597
  var SKILL = "SKILL.md";
10409
10598
  var SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", ".cache"]);
10410
10599
  function skillFiles2(root) {
@@ -10418,18 +10607,18 @@ function skillFiles2(root) {
10418
10607
  }
10419
10608
  for (const name of entries) {
10420
10609
  if (SKIP.has(name)) continue;
10421
- const path = join12(dir, name);
10610
+ const path = join15(dir, name);
10422
10611
  let stats;
10423
10612
  try {
10424
- stats = statSync8(path);
10613
+ stats = statSync9(path);
10425
10614
  } catch {
10426
10615
  continue;
10427
10616
  }
10428
10617
  if (stats.isDirectory()) walk(path);
10429
10618
  else if (name === SKILL)
10430
10619
  found.set(
10431
- relative6(root, path).split(sep5).join("/"),
10432
- readFileSync15(path, "utf8")
10620
+ relative7(root, path).split(sep6).join("/"),
10621
+ readFileSync18(path, "utf8")
10433
10622
  );
10434
10623
  }
10435
10624
  };
@@ -10445,7 +10634,12 @@ function contentDigest(files) {
10445
10634
  return `sha256:${hash2.digest("hex")}`;
10446
10635
  }
10447
10636
  function verifyInstalledContent(project2, packageName2, expected) {
10448
- const root = resolve10(project2, "node_modules", ...packageName2.split("/"));
10637
+ let root = resolve11(project2, "node_modules", ...packageName2.split("/"));
10638
+ try {
10639
+ root = installedPackageDirectory(project2, packageName2);
10640
+ } catch {
10641
+ root = resolve11(project2, "node_modules", ...packageName2.split("/"));
10642
+ }
10449
10643
  const files = skillFiles2(root);
10450
10644
  const actual = contentDigest(files);
10451
10645
  return {
@@ -10457,10 +10651,199 @@ function verifyInstalledContent(project2, packageName2, expected) {
10457
10651
  };
10458
10652
  }
10459
10653
 
10654
+ // src/install/public.ts
10655
+ import { lstatSync, readFileSync as readFileSync19, readdirSync as readdirSync6 } from "fs";
10656
+ import { join as join16 } from "path";
10657
+
10658
+ // src/install/archive.ts
10659
+ import { createHash as createHash9 } from "crypto";
10660
+ import { gzipSync, gunzipSync } from "zlib";
10661
+ var maximumSize = 32 * 1024 * 1024;
10662
+ function integrity(bytes) {
10663
+ return `sha512-${createHash9("sha512").update(bytes).digest("base64")}`;
10664
+ }
10665
+ function safePath(path) {
10666
+ if (!/^package\//u.test(path) || path.includes("\\") || path.split("/").some((part) => !part || part === "." || part === ".."))
10667
+ throw new Error("Unsafe archive path");
10668
+ }
10669
+ function readArchive(bytes) {
10670
+ const tar = gunzipSync(bytes, { maxOutputLength: maximumSize });
10671
+ const files = /* @__PURE__ */ new Map();
10672
+ let offset = 0;
10673
+ while (offset + 512 <= tar.length) {
10674
+ const header = tar.subarray(offset, offset + 512);
10675
+ if (header.every((value) => value === 0)) break;
10676
+ const string = (start2, length) => header.subarray(start2, start2 + length).toString("utf8").replace(/\0.*$/su, "");
10677
+ const name = string(0, 100);
10678
+ const prefix = string(345, 155);
10679
+ const path = prefix ? `${prefix}/${name}` : name;
10680
+ safePath(path);
10681
+ if (header[156] !== 0 && header[156] !== 48)
10682
+ throw new Error("Archive contains a non-regular file");
10683
+ const expected = Number.parseInt(string(148, 8).trim(), 8);
10684
+ const actual = header.reduce(
10685
+ (sum, byte, index) => sum + (index >= 148 && index < 156 ? 32 : byte),
10686
+ 0
10687
+ );
10688
+ if (expected !== actual)
10689
+ throw new Error("Archive header checksum mismatch");
10690
+ const size = Number.parseInt(string(124, 12).trim(), 8);
10691
+ if (!Number.isSafeInteger(size) || size < 0 || offset + 512 + size > tar.length)
10692
+ throw new Error("Archive member is truncated");
10693
+ if (files.has(path)) throw new Error("Archive contains duplicate members");
10694
+ files.set(path, tar.subarray(offset + 512, offset + 512 + size));
10695
+ offset += 512 + Math.ceil(size / 512) * 512;
10696
+ }
10697
+ if (!files.size) throw new Error("Archive contains no files");
10698
+ return files;
10699
+ }
10700
+
10701
+ // src/install/public.ts
10702
+ var MAX_ARCHIVE_BYTES = 8 * 1024 * 1024;
10703
+ function publicArchiveUrl(entry2) {
10704
+ if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(entry2.productId) || entry2.line === void 0)
10705
+ throw new Error(
10706
+ "The public catalog requires a product identifier and major line"
10707
+ );
10708
+ return `https://pmcp.build/skills/${entry2.productId}/${entry2.line.major}/releases/${entry2.delivery.version}.tgz`;
10709
+ }
10710
+ function publicEntry(catalog, change) {
10711
+ const entry2 = catalog.entries.find(
10712
+ (item) => item.delivery.packageName === change.packageName && item.delivery.version === change.version
10713
+ );
10714
+ if (!entry2 || entry2.delivery.integrity !== change.integrity)
10715
+ throw new Error("The public delivery is absent from the catalog");
10716
+ return entry2;
10717
+ }
10718
+ function publicInstallPlan(plan2, catalog) {
10719
+ const specs = new Map(
10720
+ plan2.changes.map((change) => [
10721
+ `${change.packageName}@${change.version}`,
10722
+ `${change.packageName}@${publicArchiveUrl(publicEntry(catalog, change))}`
10723
+ ])
10724
+ );
10725
+ return {
10726
+ ...plan2,
10727
+ command: {
10728
+ ...plan2.command,
10729
+ args: plan2.command.args.map(
10730
+ (argument) => specs.get(argument) ?? argument
10731
+ )
10732
+ }
10733
+ };
10734
+ }
10735
+ function publicArchiveFiles(entry2, bytes) {
10736
+ if (bytes.length > MAX_ARCHIVE_BYTES || integrity(bytes) !== entry2.delivery.integrity)
10737
+ throw new Error("Public archive integrity differs from the catalog");
10738
+ const files = readArchive(bytes);
10739
+ const manifest2 = JSON.parse(
10740
+ files.get("package/package.json")?.toString("utf8") ?? "null"
10741
+ );
10742
+ if (!manifest2 || typeof manifest2 !== "object" || Array.isArray(manifest2))
10743
+ throw new Error("Public archive has no package manifest");
10744
+ const metadata2 = manifest2;
10745
+ if (metadata2.name !== entry2.delivery.packageName || metadata2.version !== entry2.delivery.version)
10746
+ throw new Error("Public archive identity differs from the catalog");
10747
+ for (const key of [
10748
+ "scripts",
10749
+ "dependencies",
10750
+ "optionalDependencies",
10751
+ "peerDependencies",
10752
+ "bundledDependencies",
10753
+ "bundleDependencies",
10754
+ "bin",
10755
+ "workspaces"
10756
+ ])
10757
+ if (metadata2[key] !== void 0)
10758
+ throw new Error("Public skill packages must be content-only");
10759
+ const skills = /* @__PURE__ */ new Map();
10760
+ if (!files.has("package/LICENSE"))
10761
+ throw new Error("Public skill packages must include their license");
10762
+ for (const [path, content] of files) {
10763
+ if (path === "package/package.json" || path === "package/LICENSE") continue;
10764
+ if (!/^package\/skills\/[a-z0-9]+(?:-[a-z0-9]+)*\/(?:SKILL\.md|references\/.+)$/u.test(
10765
+ path
10766
+ ))
10767
+ throw new Error("Public archive contains an unexpected resource");
10768
+ if (path.endsWith("/SKILL.md"))
10769
+ skills.set(path.slice("package/".length), content.toString("utf8"));
10770
+ }
10771
+ if (skills.size !== 1 || contentDigest(skills) !== entry2.contentDigest)
10772
+ throw new Error("Public skill content differs from the catalog");
10773
+ return files;
10774
+ }
10775
+ async function downloadArchive(url, fetcher2) {
10776
+ const response = await fetcher2(url, {
10777
+ redirect: "error",
10778
+ signal: AbortSignal.timeout(15e3)
10779
+ });
10780
+ if (!response.ok || !response.body)
10781
+ throw new Error(`Public archive request failed (${response.status})`);
10782
+ const reader = response.body.getReader();
10783
+ const chunks = [];
10784
+ let size = 0;
10785
+ try {
10786
+ for (; ; ) {
10787
+ const { done, value } = await reader.read();
10788
+ if (done) break;
10789
+ size += value.byteLength;
10790
+ if (size > MAX_ARCHIVE_BYTES)
10791
+ throw new Error("Public archive exceeds the download budget");
10792
+ chunks.push(value);
10793
+ }
10794
+ } finally {
10795
+ await reader.cancel().catch(() => void 0);
10796
+ reader.releaseLock();
10797
+ }
10798
+ return Buffer.concat(chunks);
10799
+ }
10800
+ async function preparePublicDelivery(plan2, catalog, fetcher2 = fetch) {
10801
+ const verified = /* @__PURE__ */ new Map();
10802
+ const resources = /* @__PURE__ */ new Map();
10803
+ for (const change of plan2.changes) {
10804
+ const entry2 = publicEntry(catalog, change);
10805
+ const url = publicArchiveUrl(entry2);
10806
+ const bytes = await downloadArchive(url, fetcher2);
10807
+ resources.set(change.packageName, publicArchiveFiles(entry2, bytes));
10808
+ const identity = `${change.packageName}@${change.version}`;
10809
+ verified.set(identity, integrity(bytes));
10810
+ }
10811
+ return { integrity: verified, resources };
10812
+ }
10813
+ function verifyPublicDelivery(project2, delivery) {
10814
+ for (const [name, files] of delivery.resources) {
10815
+ const root = installedPackageDirectory(project2, name);
10816
+ const expected = new Set(
10817
+ [...files.keys()].map((path) => path.slice("package/".length))
10818
+ );
10819
+ const walk = (directory, prefix = "") => {
10820
+ for (const entry2 of readdirSync6(directory, { withFileTypes: true })) {
10821
+ const path = prefix ? `${prefix}/${entry2.name}` : entry2.name;
10822
+ if (entry2.isDirectory()) {
10823
+ walk(join16(directory, entry2.name), path);
10824
+ continue;
10825
+ }
10826
+ if (!entry2.isFile() || !expected.has(path))
10827
+ throw new Error(
10828
+ "Installed public package contains unexpected resources"
10829
+ );
10830
+ }
10831
+ };
10832
+ walk(root);
10833
+ for (const [path, bytes] of files) {
10834
+ const destination = join16(root, path.slice("package/".length));
10835
+ if (!lstatSync(destination).isFile() || !readFileSync19(destination).equals(bytes))
10836
+ throw new Error(
10837
+ "Installed public package differs from its verified archive; inspect the project before retrying"
10838
+ );
10839
+ }
10840
+ }
10841
+ }
10842
+
10460
10843
  // src/remote/distribution.ts
10461
10844
  import { chmodSync as chmodSync4, mkdtempSync, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
10462
10845
  import { tmpdir } from "os";
10463
- import { join as join13 } from "path";
10846
+ import { join as join17 } from "path";
10464
10847
  function api(origin, path) {
10465
10848
  const base = new URL(catalogEndpoint(origin));
10466
10849
  base.pathname = path;
@@ -10600,9 +10983,9 @@ async function revokeDistributionCredential(accessToken, id2, origin = DEFAULT_A
10600
10983
  }
10601
10984
  }
10602
10985
  function temporaryRegistryConfig(value) {
10603
- const directory = mkdtempSync(join13(tmpdir(), "pmcp-registry-"));
10986
+ const directory = mkdtempSync(join17(tmpdir(), "pmcp-registry-"));
10604
10987
  chmodSync4(directory, 448);
10605
- const path = join13(directory, ".npmrc");
10988
+ const path = join17(directory, ".npmrc");
10606
10989
  const registry = new URL(value.registry);
10607
10990
  const auth = `//${registry.host}${registry.pathname}:_authToken=${value.token}`;
10608
10991
  writeFileSync3(path, `${value.scope}:registry=${registry.href}
@@ -10632,10 +11015,11 @@ async function manage(context, sync) {
10632
11015
  throw new ArgumentError("select a skill package or pass --all");
10633
11016
  }
10634
11017
  const project2 = projectFrom(context);
11018
+ const provider = catalogProvider(context);
10635
11019
  const install = installContext(project2);
10636
11020
  const inventory = readInstalledDependencies(project2);
10637
11021
  const catalog = await remoteCatalog(context);
10638
- const plan2 = planInstall({
11022
+ const selectedPlan = planInstall({
10639
11023
  context: install,
10640
11024
  inventory,
10641
11025
  catalog,
@@ -10643,6 +11027,7 @@ async function manage(context, sync) {
10643
11027
  all: context.args.flags.has("all"),
10644
11028
  sync
10645
11029
  });
11030
+ const plan2 = provider === "public" ? publicInstallPlan(selectedPlan, catalog) : selectedPlan;
10646
11031
  const digests2 = new Map(
10647
11032
  catalog.entries.map((entry2) => [
10648
11033
  entry2.delivery.packageName,
@@ -10728,6 +11113,32 @@ async function manage(context, sync) {
10728
11113
  prompt.close();
10729
11114
  }
10730
11115
  }
11116
+ if (provider === "public") {
11117
+ const delivery = await preparePublicDelivery(plan2, catalog);
11118
+ const code = applyInstallPlan(
11119
+ plan2,
11120
+ createPackageManagerRunner(void 0, process.env, delivery.integrity)
11121
+ );
11122
+ if (code !== 0) {
11123
+ context.ui.error(
11124
+ "package manager failed",
11125
+ `exit ${code}; inspect the project before retrying`
11126
+ );
11127
+ return code;
11128
+ }
11129
+ verifyPublicDelivery(project2, delivery);
11130
+ if (context.args.flags.has("json")) {
11131
+ context.ui.data(
11132
+ `${JSON.stringify({ status: "applied", ...report }, null, 2)}
11133
+ `
11134
+ );
11135
+ return 0;
11136
+ }
11137
+ context.ui.success(
11138
+ `${plan2.changes.length} public skill packages installed`
11139
+ );
11140
+ return 0;
11141
+ }
10731
11142
  const session = readSession();
10732
11143
  if (!session || session.expiresAt !== void 0 && session.expiresAt <= Date.now()) {
10733
11144
  throw new Error(
@@ -10825,38 +11236,38 @@ var syncCommand = {
10825
11236
  import { homedir as homedir6 } from "os";
10826
11237
 
10827
11238
  // src/project/apply.ts
10828
- import { createHash as createHash12 } from "crypto";
11239
+ import { createHash as createHash13 } from "crypto";
10829
11240
  import {
10830
- existsSync as existsSync14,
10831
- lstatSync as lstatSync3,
11241
+ existsSync as existsSync17,
11242
+ lstatSync as lstatSync4,
10832
11243
  mkdirSync as mkdirSync7,
10833
- readFileSync as readFileSync20,
10834
- readdirSync as readdirSync8,
11244
+ readFileSync as readFileSync24,
11245
+ readdirSync as readdirSync9,
10835
11246
  readlinkSync as readlinkSync2,
10836
11247
  rmSync as rmSync4,
10837
11248
  symlinkSync,
10838
11249
  writeFileSync as writeFileSync5
10839
11250
  } from "fs";
10840
- import { dirname as dirname15, join as join18, posix as posix2 } from "path";
11251
+ import { dirname as dirname16, join as join22, posix as posix2 } from "path";
10841
11252
  import { parse as parse4 } from "smol-toml";
10842
11253
 
10843
11254
  // src/project/backup.ts
10844
- import { createHash as createHash9 } from "crypto";
11255
+ import { createHash as createHash10 } from "crypto";
10845
11256
  import {
10846
- existsSync as existsSync10,
10847
- lstatSync as lstatSync2,
11257
+ existsSync as existsSync13,
11258
+ lstatSync as lstatSync3,
10848
11259
  mkdirSync as mkdirSync6,
10849
11260
  mkdtempSync as mkdtempSync2,
10850
- readFileSync as readFileSync16,
11261
+ readFileSync as readFileSync20,
10851
11262
  writeFileSync as writeFileSync4
10852
11263
  } from "fs";
10853
11264
  import { homedir as homedir3 } from "os";
10854
- import { dirname as dirname13, isAbsolute as isAbsolute3, join as join15, relative as relative7, resolve as resolve11 } from "path";
11265
+ import { dirname as dirname14, isAbsolute as isAbsolute4, join as join19, relative as relative8, resolve as resolve12 } from "path";
10855
11266
 
10856
11267
  // src/project/package-rules.ts
10857
11268
  import { execFileSync } from "child_process";
10858
- import { existsSync as existsSync9, lstatSync, readdirSync as readdirSync6, readlinkSync } from "fs";
10859
- import { dirname as dirname12, join as join14, posix } from "path";
11269
+ import { existsSync as existsSync12, lstatSync as lstatSync2, readdirSync as readdirSync7, readlinkSync } from "fs";
11270
+ import { dirname as dirname13, join as join18, posix } from "path";
10860
11271
  var ProjectError = class extends Error {
10861
11272
  constructor(message) {
10862
11273
  super(message);
@@ -10893,7 +11304,7 @@ function deriveName(dir, strip) {
10893
11304
  }
10894
11305
  function linkTarget(abs) {
10895
11306
  try {
10896
- if (!lstatSync(abs).isSymbolicLink()) return null;
11307
+ if (!lstatSync2(abs).isSymbolicLink()) return null;
10897
11308
  return readlinkSync(abs);
10898
11309
  } catch {
10899
11310
  return null;
@@ -10901,11 +11312,11 @@ function linkTarget(abs) {
10901
11312
  }
10902
11313
  function legacyLinks(root) {
10903
11314
  const found = /* @__PURE__ */ new Map();
10904
- const dir = join14(root, RULES_DIR);
10905
- if (!existsSync9(dir)) return found;
10906
- for (const entry2 of readdirSync6(dir).sort()) {
11315
+ const dir = join18(root, RULES_DIR);
11316
+ if (!existsSync12(dir)) return found;
11317
+ for (const entry2 of readdirSync7(dir).sort()) {
10907
11318
  if (!entry2.endsWith(".md")) continue;
10908
- const target2 = linkTarget(join14(dir, entry2));
11319
+ const target2 = linkTarget(join18(dir, entry2));
10909
11320
  if (target2 === null || !target2.startsWith("../../")) continue;
10910
11321
  found.set(entry2.slice(0, -3), target2.slice("../../".length));
10911
11322
  }
@@ -10925,14 +11336,14 @@ function packageRuleOutputs(root, spec, owned) {
10925
11336
  const legacyByDir = /* @__PURE__ */ new Map();
10926
11337
  for (const [name, target2] of legacy) {
10927
11338
  if (!byTarget.has(target2)) byTarget.set(target2, name);
10928
- const dir = dirname12(target2);
11339
+ const dir = dirname13(target2);
10929
11340
  if (!legacyByDir.has(dir)) legacyByDir.set(dir, name);
10930
11341
  }
10931
11342
  const outputs = [];
10932
11343
  const taken = /* @__PURE__ */ new Map();
10933
11344
  for (const file2 of files) {
10934
11345
  const pkg = file2.slice(0, -suffix.length);
10935
- const name = byTarget.get(file2) ?? legacyByDir.get(dirname12(file2)) ?? deriveName(pkg, spec.strip);
11346
+ const name = byTarget.get(file2) ?? legacyByDir.get(dirname13(file2)) ?? deriveName(pkg, spec.strip);
10936
11347
  const other = taken.get(name);
10937
11348
  if (other !== void 0) {
10938
11349
  throw new ProjectError(
@@ -10951,13 +11362,13 @@ function packageRuleOutputs(root, spec, owned) {
10951
11362
 
10952
11363
  // src/project/backup.ts
10953
11364
  function backupFiles(root, paths) {
10954
- const base = join15(homedir3(), ".cache/pmcp/project-backups");
10955
- const inside = relative7(resolve11(root), resolve11(base));
10956
- if (!isAbsolute3(inside) && inside !== ".." && !inside.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
11365
+ const base = join19(homedir3(), ".cache/pmcp/project-backups");
11366
+ const inside = relative8(resolve12(root), resolve12(base));
11367
+ if (!isAbsolute4(inside) && inside !== ".." && !inside.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`)) {
10957
11368
  throw new ProjectError("Project backups must be outside the project");
10958
11369
  }
10959
11370
  mkdirSync6(base, { recursive: true, mode: 448 });
10960
- const directory = lstatSync2(base);
11371
+ const directory = lstatSync3(base);
10961
11372
  if (directory.isSymbolicLink() || !directory.isDirectory()) {
10962
11373
  throw new ProjectError("Project backup directory must be a real directory");
10963
11374
  }
@@ -10967,42 +11378,42 @@ function backupFiles(root, paths) {
10967
11378
  );
10968
11379
  }
10969
11380
  const snapshots = [...new Set(paths)].map((path) => {
10970
- const absolute2 = resolve11(root, path);
10971
- const within = relative7(resolve11(root), absolute2);
10972
- if (isAbsolute3(within) || within === ".." || within.startsWith("../") || within.startsWith("..\\")) {
11381
+ const absolute2 = resolve12(root, path);
11382
+ const within = relative8(resolve12(root), absolute2);
11383
+ if (isAbsolute4(within) || within === ".." || within.startsWith("../") || within.startsWith("..\\")) {
10973
11384
  throw new ProjectError("Backup paths must stay inside the project");
10974
11385
  }
10975
- if (!existsSync10(absolute2)) {
11386
+ if (!existsSync13(absolute2)) {
10976
11387
  return { path, contents: null };
10977
11388
  }
10978
- const stat = lstatSync2(absolute2);
11389
+ const stat = lstatSync3(absolute2);
10979
11390
  if (!stat.isFile() || stat.isSymbolicLink()) {
10980
11391
  throw new ProjectError(
10981
11392
  `Refusing to back up a nonregular config file: ${path}`
10982
11393
  );
10983
11394
  }
10984
- return { path, contents: readFileSync16(absolute2) };
11395
+ return { path, contents: readFileSync20(absolute2) };
10985
11396
  });
10986
- const destination = mkdtempSync2(join15(base, "project-"));
11397
+ const destination = mkdtempSync2(join19(base, "project-"));
10987
11398
  const entries = snapshots.map(({ path, contents }) => {
10988
11399
  if (contents === null) {
10989
11400
  return { path, present: false };
10990
11401
  }
10991
- const output = join15(destination, "files", path);
10992
- mkdirSync6(dirname13(output), { recursive: true, mode: 448 });
11402
+ const output = join19(destination, "files", path);
11403
+ mkdirSync6(dirname14(output), { recursive: true, mode: 448 });
10993
11404
  writeFileSync4(output, contents, { mode: 384 });
10994
11405
  return {
10995
11406
  path,
10996
11407
  present: true,
10997
- sha256: createHash9("sha256").update(contents).digest("hex")
11408
+ sha256: createHash10("sha256").update(contents).digest("hex")
10998
11409
  };
10999
11410
  });
11000
11411
  writeFileSync4(
11001
- join15(destination, "receipt.json"),
11412
+ join19(destination, "receipt.json"),
11002
11413
  JSON.stringify(
11003
11414
  {
11004
11415
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
11005
- projectRoot: resolve11(root),
11416
+ projectRoot: resolve12(root),
11006
11417
  entries
11007
11418
  },
11008
11419
  null,
@@ -11028,7 +11439,7 @@ function splitKeyed(path) {
11028
11439
  }
11029
11440
 
11030
11441
  // src/project/mcp.ts
11031
- import { isAbsolute as isAbsolute4, relative as relative8 } from "path";
11442
+ import { isAbsolute as isAbsolute5, relative as relative9 } from "path";
11032
11443
  var runtimeByTool = {
11033
11444
  claude: "claude-code",
11034
11445
  codex: "codex-cli",
@@ -11179,12 +11590,12 @@ function nativeEntry(spec, alias, server, tool) {
11179
11590
  }
11180
11591
  let started;
11181
11592
  if (Object.keys(server.envFrom ?? {}).length > 0) {
11182
- const entry2 = relative8(spec.root, process.argv[1] ?? "");
11593
+ const entry2 = relative9(spec.root, process.argv[1] ?? "");
11183
11594
  const driverEnv = {};
11184
11595
  if (server.mailbox) {
11185
11596
  driverEnv["PMCP_MAILBOX_RUNTIME"] = runtimeByTool[tool];
11186
11597
  }
11187
- if (!isAbsolute4(entry2) && !entry2.startsWith("..")) {
11598
+ if (!isAbsolute5(entry2) && !entry2.startsWith("..")) {
11188
11599
  started = launch({
11189
11600
  command: "node",
11190
11601
  args: [`${ROOT_VAR}/${entry2}`, "project", "exec-mcp", alias],
@@ -11292,16 +11703,16 @@ function mcpOutputs(spec) {
11292
11703
  }
11293
11704
 
11294
11705
  // src/project/hooks.ts
11295
- import { createHash as createHash11 } from "crypto";
11296
- import { existsSync as existsSync12, readFileSync as readFileSync18 } from "fs";
11297
- import { join as join16 } from "path";
11298
- import { fileURLToPath } from "url";
11706
+ import { createHash as createHash12 } from "crypto";
11707
+ import { existsSync as existsSync15, readFileSync as readFileSync22 } from "fs";
11708
+ import { join as join20 } from "path";
11709
+ import { fileURLToPath as fileURLToPath2 } from "url";
11299
11710
 
11300
11711
  // src/project/hook-adapter.ts
11301
11712
  import { spawnSync as spawnSync2 } from "child_process";
11302
- import { createHash as createHash10 } from "crypto";
11303
- import { existsSync as existsSync11, readFileSync as readFileSync17, realpathSync as realpathSync2, statSync as statSync9 } from "fs";
11304
- import { dirname as dirname14, isAbsolute as isAbsolute5, relative as relative9, resolve as resolve12 } from "path";
11713
+ import { createHash as createHash11 } from "crypto";
11714
+ import { existsSync as existsSync14, readFileSync as readFileSync21, realpathSync as realpathSync3, statSync as statSync10 } from "fs";
11715
+ import { dirname as dirname15, isAbsolute as isAbsolute6, relative as relative10, resolve as resolve13 } from "path";
11305
11716
  var denied = () => ({
11306
11717
  decision: "deny",
11307
11718
  reason: "Shell guard failed validation or execution"
@@ -11311,22 +11722,22 @@ function guardPath(root, command2) {
11311
11722
  if (!script?.startsWith(".agents/guards/")) {
11312
11723
  throw new Error("Hook command must execute a script under .agents/guards/");
11313
11724
  }
11314
- const absolute2 = resolve12(root, script);
11315
- const base = resolve12(root, ".agents/guards");
11316
- const inside = relative9(base, absolute2);
11317
- if (isAbsolute5(inside) || inside === ".." || inside.startsWith("../") || inside.startsWith("..\\")) {
11725
+ const absolute2 = resolve13(root, script);
11726
+ const base = resolve13(root, ".agents/guards");
11727
+ const inside = relative10(base, absolute2);
11728
+ if (isAbsolute6(inside) || inside === ".." || inside.startsWith("../") || inside.startsWith("..\\")) {
11318
11729
  throw new Error("Hook guard must stay under .agents/guards/");
11319
11730
  }
11320
- if (!existsSync11(absolute2) || !statSync9(absolute2).isFile()) {
11731
+ if (!existsSync14(absolute2) || !statSync10(absolute2).isFile()) {
11321
11732
  throw new Error("Hook guard script must exist");
11322
11733
  }
11323
- const actual = relative9(base, realpathSync2(absolute2));
11324
- if (isAbsolute5(actual) || actual === ".." || actual.startsWith("../") || actual.startsWith("..\\")) {
11734
+ const actual = relative10(base, realpathSync3(absolute2));
11735
+ if (isAbsolute6(actual) || actual === ".." || actual.startsWith("../") || actual.startsWith("..\\")) {
11325
11736
  throw new Error("Hook guard cannot resolve outside .agents/guards/");
11326
11737
  }
11327
11738
  return absolute2;
11328
11739
  }
11329
- function object2(value) {
11740
+ function object3(value) {
11330
11741
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
11331
11742
  return {};
11332
11743
  }
@@ -11350,9 +11761,9 @@ function scalar(value) {
11350
11761
  }
11351
11762
  function evaluateShellHook(root, policy, tool, payload) {
11352
11763
  try {
11353
- const value = object2(payload);
11354
- const call = object2(value["toolCall"]);
11355
- const input = tool === "antigravity" ? object2(call["args"]) : object2(value["tool_input"]);
11764
+ const value = object3(payload);
11765
+ const call = object3(value["toolCall"]);
11766
+ const input = tool === "antigravity" ? object3(call["args"]) : object3(value["tool_input"]);
11356
11767
  const name = tool === "antigravity" ? call["name"] : value["tool_name"];
11357
11768
  const shellNames = {
11358
11769
  codex: ["Bash", "exec_command", "shell", "shell_command"],
@@ -11400,7 +11811,7 @@ function evaluateShellHook(root, policy, tool, payload) {
11400
11811
  if (result.status !== 0 || result.error) {
11401
11812
  return denied();
11402
11813
  }
11403
- const response = object2(JSON.parse(result.stdout));
11814
+ const response = object3(JSON.parse(result.stdout));
11404
11815
  if (Object.keys(response).some(
11405
11816
  (key) => !["decision", "reason"].includes(key)
11406
11817
  ) || !["allow", "deny"].includes(String(response["decision"])) || response["reason"] !== void 0 && typeof response["reason"] !== "string") {
@@ -11427,7 +11838,7 @@ function nativeHookDecision(tool, decision) {
11427
11838
  return decision;
11428
11839
  }
11429
11840
  async function main() {
11430
- const [, , , tool, file2, integrity] = process.argv;
11841
+ const [, , , tool, file2, integrity2] = process.argv;
11431
11842
  const supported = tool === "codex" || tool === "gemini" || tool === "antigravity";
11432
11843
  if (!supported) {
11433
11844
  process.exitCode = 2;
@@ -11438,10 +11849,10 @@ async function main() {
11438
11849
  if (!file2) {
11439
11850
  throw new Error("Missing hook policy");
11440
11851
  }
11441
- const bytes = readFileSync17(file2);
11442
- const adapter = readFileSync17(process.argv[1]);
11443
- const actual = createHash10("sha256").update(adapter).update(bytes).digest("hex");
11444
- if (actual !== integrity) {
11852
+ const bytes = readFileSync21(file2);
11853
+ const adapter = readFileSync21(process.argv[1]);
11854
+ const actual = createHash11("sha256").update(adapter).update(bytes).digest("hex");
11855
+ if (actual !== integrity2) {
11445
11856
  throw new Error("Hook integrity mismatch");
11446
11857
  }
11447
11858
  const policy = JSON.parse(bytes.toString("utf8"));
@@ -11458,8 +11869,8 @@ async function main() {
11458
11869
  }
11459
11870
  chunks.push(bytes2);
11460
11871
  }
11461
- const root = resolve12(dirname14(file2), "../..");
11462
- const guardSha256 = createHash10("sha256").update(readFileSync17(guardPath(root, policy.command))).digest("hex");
11872
+ const root = resolve13(dirname15(file2), "../..");
11873
+ const guardSha256 = createHash11("sha256").update(readFileSync21(guardPath(root, policy.command))).digest("hex");
11463
11874
  if (policy.contractVersion !== 1 || guardSha256 !== policy.guardSha256) {
11464
11875
  throw new Error(
11465
11876
  "Hook guard source changed; reproject and review native trust"
@@ -11503,7 +11914,7 @@ var native = {
11503
11914
  matcher: "run_command"
11504
11915
  }
11505
11916
  };
11506
- function object3(value) {
11917
+ function object4(value) {
11507
11918
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
11508
11919
  throw new ProjectError(
11509
11920
  "Native hook configuration must be an object; contents are redacted"
@@ -11512,20 +11923,20 @@ function object3(value) {
11512
11923
  return value;
11513
11924
  }
11514
11925
  function groups(root, file2, key) {
11515
- const absolute2 = join16(root, file2);
11516
- if (!existsSync12(absolute2)) {
11926
+ const absolute2 = join20(root, file2);
11927
+ if (!existsSync15(absolute2)) {
11517
11928
  return [];
11518
11929
  }
11519
11930
  let value;
11520
11931
  try {
11521
- value = JSON.parse(readFileSync18(absolute2, "utf8"));
11932
+ value = JSON.parse(readFileSync22(absolute2, "utf8"));
11522
11933
  } catch {
11523
11934
  throw new ProjectError(
11524
11935
  "Cannot parse native hook configuration; contents are redacted"
11525
11936
  );
11526
11937
  }
11527
11938
  for (const part of key) {
11528
- value = object3(value)[part];
11939
+ value = object4(value)[part];
11529
11940
  if (value === void 0) {
11530
11941
  return [];
11531
11942
  }
@@ -11536,21 +11947,21 @@ function groups(root, file2, key) {
11536
11947
  return value;
11537
11948
  }
11538
11949
  function adapterSource() {
11539
- const published = fileURLToPath(
11950
+ const published = fileURLToPath2(
11540
11951
  new URL("./project/hook-adapter.js", import.meta.url)
11541
11952
  );
11542
- const sourceBuild = fileURLToPath(
11953
+ const sourceBuild = fileURLToPath2(
11543
11954
  new URL("../../dist/project/hook-adapter.js", import.meta.url)
11544
11955
  );
11545
- const file2 = existsSync12(published) ? published : sourceBuild;
11546
- if (!existsSync12(file2)) {
11956
+ const file2 = existsSync15(published) ? published : sourceBuild;
11957
+ if (!existsSync15(file2)) {
11547
11958
  throw new ProjectError("Build pmcp before projecting shell hook adapters");
11548
11959
  }
11549
- return readFileSync18(file2, "utf8");
11960
+ return readFileSync22(file2, "utf8");
11550
11961
  }
11551
11962
  function hookOutputs(spec) {
11552
- const lockFile = join16(spec.root, "pmcp.lock");
11553
- const lock = existsSync12(lockFile) ? JSON.parse(readFileSync18(lockFile, "utf8")) : {};
11963
+ const lockFile = join20(spec.root, "pmcp.lock");
11964
+ const lock = existsSync15(lockFile) ? JSON.parse(readFileSync22(lockFile, "utf8")) : {};
11554
11965
  const previous = new Map(
11555
11966
  (lock.outputs ?? []).filter((entry2) => entry2.managed !== void 0).map((entry2) => [entry2.path, entry2.managed])
11556
11967
  );
@@ -11567,17 +11978,17 @@ function hookOutputs(spec) {
11567
11978
  outputs.push({ kind: "file", path: ADAPTER, content: adapter });
11568
11979
  for (const hook of selected) {
11569
11980
  const policyFile = `${HOOK_DIRECTORY}/${hook.name}.json`;
11570
- const guardSha256 = createHash11("sha256").update(readFileSync18(guardPath(spec.root, hook.command))).digest("hex");
11981
+ const guardSha256 = createHash12("sha256").update(readFileSync22(guardPath(spec.root, hook.command))).digest("hex");
11571
11982
  const policy = `${JSON.stringify({ ...hook, contractVersion: 1, guardSha256 }, null, 2)}
11572
11983
  `;
11573
11984
  outputs.push({ kind: "file", path: policyFile, content: policy });
11574
- const integrity = createHash11("sha256").update(adapter).update(policy).digest("hex");
11985
+ const integrity2 = createHash12("sha256").update(adapter).update(policy).digest("hex");
11575
11986
  for (const tool of hook.targets) {
11576
11987
  if (!spec.tools.has(tool)) {
11577
11988
  continue;
11578
11989
  }
11579
11990
  const target2 = native[tool];
11580
- const command2 = `d="$PWD"; while [ ! -f "$d/pmcp.toml" ]; do [ "$d" = / ] && exit 1; d=$(dirname "$d"); done; exec node "$d/${ADAPTER}" --pmcp-shell-hook ${tool} "$d/${policyFile}" ${integrity}`;
11991
+ const command2 = `d="$PWD"; while [ ! -f "$d/pmcp.toml" ]; do [ "$d" = / ] && exit 1; d=$(dirname "$d"); done; exec node "$d/${ADAPTER}" --pmcp-shell-hook ${tool} "$d/${policyFile}" ${integrity2}`;
11581
11992
  const timeout = tool === "gemini" ? hook.timeoutMs + 2e3 : Math.ceil(hook.timeoutMs / 1e3) + 2;
11582
11993
  const value = {
11583
11994
  matcher: target2.matcher,
@@ -11636,8 +12047,8 @@ function splitFrontmatter(source2) {
11636
12047
  const match = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/u.exec(source2);
11637
12048
  if (!match) return { meta: {}, body: source2 };
11638
12049
  const meta = parse3(match[1] ?? "");
11639
- const object8 = meta !== null && typeof meta === "object" && !Array.isArray(meta) ? meta : {};
11640
- return { meta: object8, body: match[2] ?? "" };
12050
+ const object9 = meta !== null && typeof meta === "object" && !Array.isArray(meta) ? meta : {};
12051
+ return { meta: object9, body: match[2] ?? "" };
11641
12052
  }
11642
12053
  function scalar2(value) {
11643
12054
  if (typeof value === "string") return value;
@@ -11665,28 +12076,28 @@ ${lines2.join("\n")}
11665
12076
  }
11666
12077
 
11667
12078
  // src/project/plan.ts
11668
- import { existsSync as existsSync13, readFileSync as readFileSync19, readdirSync as readdirSync7 } from "fs";
11669
- import { join as join17 } from "path";
12079
+ import { existsSync as existsSync16, readFileSync as readFileSync23, readdirSync as readdirSync8 } from "fs";
12080
+ import { join as join21 } from "path";
11670
12081
  var AGENT_FIELDS = {
11671
12082
  claude: ["name", "description", "tools", "model", "effort"],
11672
12083
  gemini: ["name", "description"]
11673
12084
  };
11674
12085
  var SETTINGS = ".claude/settings.json";
11675
12086
  function listDirs(dir) {
11676
- if (!existsSync13(dir)) return [];
11677
- return readdirSync7(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
12087
+ if (!existsSync16(dir)) return [];
12088
+ return readdirSync8(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
11678
12089
  }
11679
12090
  var tomlString = (value) => JSON.stringify(typeof value === "string" ? value : String(value ?? ""));
11680
12091
  function skillNames(root) {
11681
- const dir = join17(root, ".agents/skills");
12092
+ const dir = join21(root, ".agents/skills");
11682
12093
  return listDirs(dir).filter(
11683
- (name) => existsSync13(join17(dir, name, "SKILL.md"))
12094
+ (name) => existsSync16(join21(dir, name, "SKILL.md"))
11684
12095
  );
11685
12096
  }
11686
12097
  function agentNames(root) {
11687
- const dir = join17(root, ".agents/agents");
12098
+ const dir = join21(root, ".agents/agents");
11688
12099
  return listDirs(dir).filter(
11689
- (name) => existsSync13(join17(dir, name, "agent.md"))
12100
+ (name) => existsSync16(join21(dir, name, "agent.md"))
11690
12101
  );
11691
12102
  }
11692
12103
  function skillOutputs(spec) {
@@ -11720,13 +12131,13 @@ policy:
11720
12131
  }
11721
12132
  function ruleOutputs(spec) {
11722
12133
  if (!spec.tools.has("claude")) return [];
11723
- const dir = join17(spec.root, ".agents/rules");
11724
- if (!existsSync13(dir)) return [];
12134
+ const dir = join21(spec.root, ".agents/rules");
12135
+ if (!existsSync16(dir)) return [];
11725
12136
  const outputs = [];
11726
- for (const file2 of readdirSync7(dir).filter((f) => f.endsWith(".md")).sort()) {
12137
+ for (const file2 of readdirSync8(dir).filter((f) => f.endsWith(".md")).sort()) {
11727
12138
  const rel = `.agents/rules/${file2}`;
11728
12139
  const { meta, body } = splitFrontmatter(
11729
- readFileSync19(join17(spec.root, rel), "utf8")
12140
+ readFileSync23(join21(spec.root, rel), "utf8")
11730
12141
  );
11731
12142
  const globs = [meta["globs"] ?? []].flat().filter((g) => typeof g === "string" && g !== "");
11732
12143
  const head = globs.length > 0 ? renderFrontmatter({ paths: globs }) : "";
@@ -11745,7 +12156,7 @@ function agentOutputs(spec) {
11745
12156
  for (const name of agentNames(spec.root)) {
11746
12157
  const rel = `.agents/agents/${name}/agent.md`;
11747
12158
  const { meta, body } = splitFrontmatter(
11748
- readFileSync19(join17(spec.root, rel), "utf8")
12159
+ readFileSync23(join21(spec.root, rel), "utf8")
11749
12160
  );
11750
12161
  const overrides = spec.agents[name] ?? {};
11751
12162
  const note = `<!-- ${MARK} from ${rel} -->
@@ -11822,26 +12233,26 @@ var PREDECESSORS = [
11822
12233
  "by sync-claude-projection.sh",
11823
12234
  "AUTO-GENERATED by scripts/agent/project.mjs"
11824
12235
  ];
11825
- var sha = (text3) => createHash12("sha256").update(text3).digest("hex");
12236
+ var sha = (text3) => createHash13("sha256").update(text3).digest("hex");
11826
12237
  function readLock(root) {
11827
- const path = join18(root, LOCK_FILE);
11828
- if (!existsSync14(path)) return [];
11829
- const lock = JSON.parse(readFileSync20(path, "utf8"));
12238
+ const path = join22(root, LOCK_FILE);
12239
+ if (!existsSync17(path)) return [];
12240
+ const lock = JSON.parse(readFileSync24(path, "utf8"));
11830
12241
  return lock.outputs ?? [];
11831
12242
  }
11832
12243
  function linkOf(abs) {
11833
12244
  try {
11834
- return lstatSync3(abs).isSymbolicLink() ? readlinkSync2(abs) : null;
12245
+ return lstatSync4(abs).isSymbolicLink() ? readlinkSync2(abs) : null;
11835
12246
  } catch {
11836
12247
  return null;
11837
12248
  }
11838
12249
  }
11839
- var exists = (abs) => existsSync14(abs) || linkOf(abs) !== null;
12250
+ var exists = (abs) => existsSync17(abs) || linkOf(abs) !== null;
11840
12251
  function readJson2(abs) {
11841
- if (!existsSync14(abs)) return {};
12252
+ if (!existsSync17(abs)) return {};
11842
12253
  let value;
11843
12254
  try {
11844
- value = JSON.parse(readFileSync20(abs, "utf8"));
12255
+ value = JSON.parse(readFileSync24(abs, "utf8"));
11845
12256
  } catch {
11846
12257
  throw new ProjectError(
11847
12258
  "Cannot parse native JSON configuration; contents are redacted"
@@ -11849,16 +12260,16 @@ function readJson2(abs) {
11849
12260
  }
11850
12261
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
11851
12262
  }
11852
- function getKey(object8, key) {
11853
- let node = object8;
12263
+ function getKey(object9, key) {
12264
+ let node = object9;
11854
12265
  for (const part of key) {
11855
12266
  if (node === null || typeof node !== "object") return void 0;
11856
12267
  node = node[part];
11857
12268
  }
11858
12269
  return node;
11859
12270
  }
11860
- function setKey(object8, key, value) {
11861
- let node = object8;
12271
+ function setKey(object9, key, value) {
12272
+ let node = object9;
11862
12273
  for (const part of key.slice(0, -1)) {
11863
12274
  const next = node[part];
11864
12275
  if (next === null || typeof next !== "object" || Array.isArray(next)) {
@@ -11868,17 +12279,17 @@ function setKey(object8, key, value) {
11868
12279
  }
11869
12280
  node[key[key.length - 1] ?? ""] = value;
11870
12281
  }
11871
- function deleteKey(object8, key) {
12282
+ function deleteKey(object9, key) {
11872
12283
  const [head, ...rest] = key;
11873
- if (head === void 0 || !(head in object8)) return;
12284
+ if (head === void 0 || !(head in object9)) return;
11874
12285
  if (rest.length === 0) {
11875
- delete object8[head];
12286
+ delete object9[head];
11876
12287
  return;
11877
12288
  }
11878
- const child = object8[head];
12289
+ const child = object9[head];
11879
12290
  if (child === null || typeof child !== "object") return;
11880
12291
  deleteKey(child, rest);
11881
- if (Object.keys(child).length === 0) delete object8[head];
12292
+ if (Object.keys(child).length === 0) delete object9[head];
11882
12293
  }
11883
12294
  var same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
11884
12295
  var block = (content) => `${BEGIN}
@@ -11893,19 +12304,19 @@ function withoutBlock(text3) {
11893
12304
  return `${text3.slice(0, start2).replace(/\n+$/u, "\n")}${after}`;
11894
12305
  }
11895
12306
  function present(root, output) {
11896
- const abs = join18(root, "file" in output ? output.file : output.path);
12307
+ const abs = join22(root, "file" in output ? output.file : output.path);
11897
12308
  switch (output.kind) {
11898
12309
  case "link":
11899
12310
  return linkOf(abs) === output.target;
11900
12311
  case "file":
11901
- return existsSync14(abs) && linkOf(abs) === null && readFileSync20(abs, "utf8") === output.content;
12312
+ return existsSync17(abs) && linkOf(abs) === null && readFileSync24(abs, "utf8") === output.content;
11902
12313
  case "json":
11903
12314
  if (output.managed && Array.isArray(output.value) && output.value.length === 0) {
11904
12315
  return getKey(readJson2(abs), output.key) === void 0;
11905
12316
  }
11906
12317
  return same(getKey(readJson2(abs), output.key), output.value);
11907
12318
  case "block":
11908
- return existsSync14(abs) && readFileSync20(abs, "utf8").includes(block(output.content));
12319
+ return existsSync17(abs) && readFileSync24(abs, "utf8").includes(block(output.content));
11909
12320
  }
11910
12321
  }
11911
12322
  function replaceable(root, output, owned) {
@@ -11913,12 +12324,12 @@ function replaceable(root, output, owned) {
11913
12324
  if (output.key[0] !== "mcpServers" || owned.has(output.path)) {
11914
12325
  return true;
11915
12326
  }
11916
- const existing = getKey(readJson2(join18(root, output.file)), output.key);
12327
+ const existing = getKey(readJson2(join22(root, output.file)), output.key);
11917
12328
  return existing === void 0 || same(existing, output.value);
11918
12329
  }
11919
12330
  if (output.kind === "block") {
11920
- const absolute2 = join18(root, output.file);
11921
- const text4 = existsSync14(absolute2) ? readFileSync20(absolute2, "utf8") : "";
12331
+ const absolute2 = join22(root, output.file);
12332
+ const text4 = existsSync17(absolute2) ? readFileSync24(absolute2, "utf8") : "";
11922
12333
  const outside = parse4(withoutBlock(text4));
11923
12334
  const proposed = parse4(output.content);
11924
12335
  const existing = objectKeys(outside["mcp_servers"]);
@@ -11927,14 +12338,14 @@ function replaceable(root, output, owned) {
11927
12338
  );
11928
12339
  }
11929
12340
  if (owned.has(output.path)) return true;
11930
- const abs = join18(root, output.path);
12341
+ const abs = join22(root, output.path);
11931
12342
  if (!exists(abs)) return true;
11932
12343
  const target2 = linkOf(abs);
11933
12344
  if (target2 !== null) {
11934
12345
  return output.kind === "link" && target2 === output.target;
11935
12346
  }
11936
- if (lstatSync3(abs).isDirectory()) return false;
11937
- const text3 = readFileSync20(abs, "utf8");
12347
+ if (lstatSync4(abs).isDirectory()) return false;
12348
+ const text3 = readFileSync24(abs, "utf8");
11938
12349
  if (output.kind === "file" && text3 === output.content) return true;
11939
12350
  return PREDECESSORS.some((mark) => text3.includes(mark));
11940
12351
  }
@@ -11948,16 +12359,16 @@ function undeclared(spec, outputs) {
11948
12359
  const declared = new Set(outputs.map((o) => o.path));
11949
12360
  const found = [];
11950
12361
  for (const dir of censusDirs(spec)) {
11951
- const abs = join18(spec.root, dir);
11952
- if (!existsSync14(abs)) continue;
11953
- for (const entry2 of readdirSync8(abs)) {
12362
+ const abs = join22(spec.root, dir);
12363
+ if (!existsSync17(abs)) continue;
12364
+ for (const entry2 of readdirSync9(abs)) {
11954
12365
  const path = `${dir}/${entry2}`;
11955
12366
  if (!declared.has(path)) found.push(path);
11956
12367
  }
11957
12368
  }
11958
- const rules = join18(spec.root, RULES_DIR);
11959
- if (spec.tools.has("grok") && existsSync14(rules)) {
11960
- for (const entry2 of readdirSync8(rules, { withFileTypes: true })) {
12369
+ const rules = join22(spec.root, RULES_DIR);
12370
+ if (spec.tools.has("grok") && existsSync17(rules)) {
12371
+ for (const entry2 of readdirSync9(rules, { withFileTypes: true })) {
11961
12372
  if (entry2.isDirectory()) continue;
11962
12373
  found.push(`${RULES_DIR}/${entry2.name}`);
11963
12374
  }
@@ -11983,9 +12394,9 @@ function deadGlobs(root, outputs) {
11983
12394
  if (rule.kind === "file") {
11984
12395
  text3 = rule.content;
11985
12396
  } else if (rule.kind === "link") {
11986
- const abs = join18(root, posix2.join(posix2.dirname(rule.path), rule.target));
11987
- if (!existsSync14(abs)) continue;
11988
- text3 = readFileSync20(abs, "utf8");
12397
+ const abs = join22(root, posix2.join(posix2.dirname(rule.path), rule.target));
12398
+ if (!existsSync17(abs)) continue;
12399
+ text3 = readFileSync24(abs, "utf8");
11989
12400
  } else {
11990
12401
  continue;
11991
12402
  }
@@ -12035,7 +12446,7 @@ function project(spec, options2) {
12035
12446
  }
12036
12447
  }
12037
12448
  for (const path of jsonPaths) {
12038
- readJson2(join18(spec.root, path));
12449
+ readJson2(join22(spec.root, path));
12039
12450
  }
12040
12451
  if (options2.check) {
12041
12452
  const problems = [
@@ -12097,8 +12508,8 @@ function project(spec, options2) {
12097
12508
  for (const output of outputs) {
12098
12509
  if (output.kind !== "link" && output.kind !== "file") continue;
12099
12510
  if (present(spec.root, output)) continue;
12100
- const abs = join18(spec.root, output.path);
12101
- mkdirSync7(dirname15(abs), { recursive: true });
12511
+ const abs = join22(spec.root, output.path);
12512
+ mkdirSync7(dirname16(abs), { recursive: true });
12102
12513
  rmSync4(abs, { force: true, recursive: true });
12103
12514
  if (output.kind === "link") symlinkSync(output.target, abs);
12104
12515
  else writeFileSync5(abs, output.content);
@@ -12123,12 +12534,12 @@ function project(spec, options2) {
12123
12534
  group.drops.push(keyed.key);
12124
12535
  jsonFiles.set(keyed.file, group);
12125
12536
  } else {
12126
- rmSync4(join18(spec.root, entry2.path), { force: true, recursive: true });
12537
+ rmSync4(join22(spec.root, entry2.path), { force: true, recursive: true });
12127
12538
  }
12128
12539
  pruned += 1;
12129
12540
  }
12130
12541
  for (const [file2, { sets, drops }] of jsonFiles) {
12131
- const abs = join18(spec.root, file2);
12542
+ const abs = join22(spec.root, file2);
12132
12543
  const before = readJson2(abs);
12133
12544
  const after = structuredClone(before);
12134
12545
  for (const key of drops) deleteKey(after, key);
@@ -12143,21 +12554,21 @@ function project(spec, options2) {
12143
12554
  }
12144
12555
  }
12145
12556
  if (same(before, after)) continue;
12146
- if (!existsSync14(abs) && Object.keys(after).length === 0) continue;
12147
- mkdirSync7(dirname15(abs), { recursive: true });
12557
+ if (!existsSync17(abs) && Object.keys(after).length === 0) continue;
12558
+ mkdirSync7(dirname16(abs), { recursive: true });
12148
12559
  writeFileSync5(abs, `${JSON.stringify(after, null, 2)}
12149
12560
  `);
12150
12561
  }
12151
12562
  for (const [file2, content] of blockFiles) {
12152
- const abs = join18(spec.root, file2);
12153
- const before = existsSync14(abs) ? readFileSync20(abs, "utf8") : "";
12563
+ const abs = join22(spec.root, file2);
12564
+ const before = existsSync17(abs) ? readFileSync24(abs, "utf8") : "";
12154
12565
  let after = withoutBlock(before);
12155
12566
  if (content !== null) {
12156
- const sep6 = after === "" || after.endsWith("\n\n") ? "" : after.endsWith("\n") ? "\n" : "\n\n";
12157
- after = `${after}${sep6}${block(content)}`;
12567
+ const sep7 = after === "" || after.endsWith("\n\n") ? "" : after.endsWith("\n") ? "\n" : "\n\n";
12568
+ after = `${after}${sep7}${block(content)}`;
12158
12569
  }
12159
12570
  if (after === before) continue;
12160
- mkdirSync7(dirname15(abs), { recursive: true });
12571
+ mkdirSync7(dirname16(abs), { recursive: true });
12161
12572
  writeFileSync5(abs, after);
12162
12573
  }
12163
12574
  if (spec.packageRules) {
@@ -12169,15 +12580,15 @@ function project(spec, options2) {
12169
12580
  )
12170
12581
  );
12171
12582
  for (const [name, target2] of legacyLinks(spec.root)) {
12172
- const abs = join18(spec.root, RULES_DIR, `${name}.md`);
12173
- const broken = !existsSync14(abs);
12583
+ const abs = join22(spec.root, RULES_DIR, `${name}.md`);
12584
+ const broken = !existsSync17(abs);
12174
12585
  if (!broken && !linkedDirs.has(posix2.dirname(target2))) continue;
12175
12586
  rmSync4(abs, { force: true });
12176
12587
  pruned += 1;
12177
12588
  }
12178
12589
  }
12179
12590
  writeFileSync5(
12180
- join18(spec.root, LOCK_FILE),
12591
+ join22(spec.root, LOCK_FILE),
12181
12592
  `${JSON.stringify({ version: 1, outputs: outputs.filter((output) => output.kind !== "json" || output.managed === void 0 || output.managed.length > 0).map(lockEntry) }, null, 2)}
12182
12593
  `
12183
12594
  );
@@ -12191,9 +12602,9 @@ function project(spec, options2) {
12191
12602
  }
12192
12603
 
12193
12604
  // src/project/mcp-import.ts
12194
- import { readFileSync as readFileSync21, statSync as statSync10, writeFileSync as writeFileSync6 } from "fs";
12195
- import { createHash as createHash13 } from "crypto";
12196
- import { basename as basename6, dirname as dirname16, resolve as resolve13 } from "path";
12605
+ import { readFileSync as readFileSync25, statSync as statSync11, writeFileSync as writeFileSync6 } from "fs";
12606
+ import { createHash as createHash14 } from "crypto";
12607
+ import { basename as basename6, dirname as dirname17, resolve as resolve14 } from "path";
12197
12608
  import { homedir as homedir4 } from "os";
12198
12609
  import { parse as parse5, stringify } from "smol-toml";
12199
12610
 
@@ -12393,7 +12804,7 @@ var KEYS = /* @__PURE__ */ new Set([
12393
12804
  function fail(path, where, detail) {
12394
12805
  throw new ConfigError(path, `${where} ${detail}`);
12395
12806
  }
12396
- function object4(path, where, value) {
12807
+ function object5(path, where, value) {
12397
12808
  if (value === void 0) {
12398
12809
  return {};
12399
12810
  }
@@ -12416,7 +12827,7 @@ function list(path, where, value, unique2 = true) {
12416
12827
  }
12417
12828
  function mapping(path, where, value) {
12418
12829
  const result = {};
12419
- for (const [key, item] of Object.entries(object4(path, where, value))) {
12830
+ for (const [key, item] of Object.entries(object5(path, where, value))) {
12420
12831
  if (typeof item !== "string") {
12421
12832
  fail(path, where, "values must be strings");
12422
12833
  }
@@ -12434,14 +12845,14 @@ function nativeOptions(path, where, value) {
12434
12845
  };
12435
12846
  const result = {};
12436
12847
  for (const [tool, raw] of Object.entries(
12437
- object4(path, `${where} native`, value)
12848
+ object5(path, `${where} native`, value)
12438
12849
  )) {
12439
12850
  if (!TOOLS.includes(tool)) {
12440
12851
  fail(path, where, `unknown native target ${tool}`);
12441
12852
  }
12442
12853
  const values = {};
12443
12854
  for (const [key, item] of Object.entries(
12444
- object4(path, `${where} native.${tool}`, raw)
12855
+ object5(path, `${where} native.${tool}`, raw)
12445
12856
  )) {
12446
12857
  if (!fields[tool].includes(key) || typeof item !== "number" || !Number.isFinite(item) || item <= 0) {
12447
12858
  fail(path, where, `unsupported native option ${tool}.${key}`);
@@ -12455,12 +12866,12 @@ function nativeOptions(path, where, value) {
12455
12866
  function environmentSources(path, where, value) {
12456
12867
  const result = {};
12457
12868
  for (const [key, raw] of Object.entries(
12458
- object4(path, `${where} env_from`, value)
12869
+ object5(path, `${where} env_from`, value)
12459
12870
  )) {
12460
12871
  if (!ENV_NAME.test(key) || key === "PROJECT_ROOT") {
12461
12872
  fail(path, where, "invalid environment source name");
12462
12873
  }
12463
- const source2 = object4(path, `${where} env_from.${key}`, raw);
12874
+ const source2 = object5(path, `${where} env_from.${key}`, raw);
12464
12875
  if (Object.keys(source2).some((name) => name !== "file" && name !== "pointer")) {
12465
12876
  fail(path, where, "environment sources accept only file and pointer");
12466
12877
  }
@@ -12473,12 +12884,12 @@ function environmentSources(path, where, value) {
12473
12884
  }
12474
12885
  function readMcp(path, value) {
12475
12886
  const servers = {};
12476
- for (const [alias, raw] of Object.entries(object4(path, "[mcp]", value))) {
12887
+ for (const [alias, raw] of Object.entries(object5(path, "[mcp]", value))) {
12477
12888
  const where = `[mcp.${alias}]`;
12478
12889
  if (!/^[a-z0-9][a-z0-9-]*$/u.test(alias)) {
12479
12890
  fail(path, where, "use lowercase, digits and -");
12480
12891
  }
12481
- const entry2 = object4(path, where, raw);
12892
+ const entry2 = object5(path, where, raw);
12482
12893
  for (const key of Object.keys(entry2)) {
12483
12894
  if (!KEYS.has(key)) {
12484
12895
  fail(path, where, `unknown field ${key}`);
@@ -12607,7 +13018,7 @@ function readMcp(path, value) {
12607
13018
  }
12608
13019
 
12609
13020
  // src/project/mcp-import.ts
12610
- function object5(value) {
13021
+ function object6(value) {
12611
13022
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
12612
13023
  throw new ProjectError(
12613
13024
  "MCP source must contain object-valued server entries"
@@ -12623,12 +13034,12 @@ function sourceServers(source2, root) {
12623
13034
  "Use --source <claude|codex|gemini|grok|antigravity>:<file>"
12624
13035
  );
12625
13036
  }
12626
- const path = resolve13(root, source2.slice(split + 1));
12627
- if (statSync10(path).size > 2 * 1024 * 1024) {
13037
+ const path = resolve14(root, source2.slice(split + 1));
13038
+ if (statSync11(path).size > 2 * 1024 * 1024) {
12628
13039
  throw new ProjectError("MCP source exceeds the 2 MiB limit");
12629
13040
  }
12630
- const bytes = readFileSync21(path);
12631
- const sha2562 = createHash13("sha256").update(bytes).digest("hex");
13041
+ const bytes = readFileSync25(path);
13042
+ const sha2562 = createHash14("sha256").update(bytes).digest("hex");
12632
13043
  const text3 = bytes.toString("utf8").replace(/^\uFEFF/u, "");
12633
13044
  let parsed;
12634
13045
  try {
@@ -12637,7 +13048,7 @@ function sourceServers(source2, root) {
12637
13048
  } else if (path.endsWith(".toml")) {
12638
13049
  parsed = parse5(text3);
12639
13050
  } else {
12640
- parsed = object5(JSON.parse(text3));
13051
+ parsed = object6(JSON.parse(text3));
12641
13052
  }
12642
13053
  } catch {
12643
13054
  throw new ProjectError(
@@ -12645,7 +13056,7 @@ function sourceServers(source2, root) {
12645
13056
  );
12646
13057
  }
12647
13058
  const servers = parsed["mcpServers"] ?? parsed["mcp_servers"] ?? {};
12648
- return { tool, path, servers: object5(servers), sha256: sha2562 };
13059
+ return { tool, path, servers: object6(servers), sha256: sha2562 };
12649
13060
  }
12650
13061
  function httpCandidate(tool, entry2) {
12651
13062
  if (tool === "gemini" && entry2["url"] !== void 0) {
@@ -12667,7 +13078,7 @@ function httpCandidate(tool, entry2) {
12667
13078
  const result = { url };
12668
13079
  const headers = {};
12669
13080
  const headerEnv = {};
12670
- const sourceHeaders = object5(entry2["headers"] ?? entry2["http_headers"] ?? {});
13081
+ const sourceHeaders = object6(entry2["headers"] ?? entry2["http_headers"] ?? {});
12671
13082
  for (const [key, value] of Object.entries(sourceHeaders)) {
12672
13083
  if (typeof value !== "string") {
12673
13084
  throw new ProjectError("HTTP header values must be strings");
@@ -12687,7 +13098,7 @@ function httpCandidate(tool, entry2) {
12687
13098
  }
12688
13099
  }
12689
13100
  for (const [key, value] of Object.entries(
12690
- object5(entry2["env_http_headers"] ?? {})
13101
+ object6(entry2["env_http_headers"] ?? {})
12691
13102
  )) {
12692
13103
  if (typeof value !== "string") {
12693
13104
  throw new ProjectError("Environment header references must be strings");
@@ -12751,7 +13162,7 @@ function candidate(tool, entry2, file2, alias) {
12751
13162
  }
12752
13163
  result["args"] = args;
12753
13164
  }
12754
- const env = object5(entry2["env"] ?? {});
13165
+ const env = object6(entry2["env"] ?? {});
12755
13166
  const forwarded = entry2["env_vars"] ?? [];
12756
13167
  if (!Array.isArray(forwarded) || !forwarded.every((item) => typeof item === "string")) {
12757
13168
  throw new ProjectError(
@@ -12818,9 +13229,9 @@ function equivalent(alias, left, right) {
12818
13229
  return JSON.stringify(readMcp("import", { [alias]: left })[alias]) === JSON.stringify(readMcp("import", { [alias]: right })[alias]);
12819
13230
  }
12820
13231
  function planMcpImport(config, sources2, names = []) {
12821
- const original = readFileSync21(config, "utf8");
12822
- const root = dirname16(resolve13(config));
12823
- const existing = object5(parse5(original)["mcp"] ?? {});
13232
+ const original = readFileSync25(config, "utf8");
13233
+ const root = dirname17(resolve14(config));
13234
+ const existing = object6(parse5(original)["mcp"] ?? {});
12824
13235
  const additions = {};
12825
13236
  const entries = [];
12826
13237
  const fingerprints = [];
@@ -12833,11 +13244,11 @@ function planMcpImport(config, sources2, names = []) {
12833
13244
  continue;
12834
13245
  }
12835
13246
  try {
12836
- const proposed = candidate(read2.tool, object5(raw), read2.path, alias);
13247
+ const proposed = candidate(read2.tool, object6(raw), read2.path, alias);
12837
13248
  readMcp(config, { [alias]: proposed });
12838
13249
  const previous = existing[alias] ?? additions[alias];
12839
13250
  if (previous !== void 0) {
12840
- const status = equivalent(alias, object5(previous), proposed) ? "unchanged" : "conflict";
13251
+ const status = equivalent(alias, object6(previous), proposed) ? "unchanged" : "conflict";
12841
13252
  entries.push({ alias, source: read2.path, status });
12842
13253
  continue;
12843
13254
  }
@@ -12869,11 +13280,11 @@ function writeMcpImport(plan2) {
12869
13280
  "Resolve blocked or conflicting MCP entries before importing"
12870
13281
  );
12871
13282
  }
12872
- if (readFileSync21(plan2.config, "utf8") !== plan2.original) {
13283
+ if (readFileSync25(plan2.config, "utf8") !== plan2.original) {
12873
13284
  throw new ProjectError("pmcp.toml changed after planning; plan again");
12874
13285
  }
12875
13286
  for (const source2 of plan2.sources) {
12876
- const current = createHash13("sha256").update(readFileSync21(source2.path)).digest("hex");
13287
+ const current = createHash14("sha256").update(readFileSync25(source2.path)).digest("hex");
12877
13288
  if (current !== source2.sha256) {
12878
13289
  throw new ProjectError("MCP source changed after planning; plan again");
12879
13290
  }
@@ -12883,7 +13294,7 @@ function writeMcpImport(plan2) {
12883
13294
 
12884
13295
  ${additions}`;
12885
13296
  parse5(after);
12886
- const backup = backupFiles(dirname16(resolve13(plan2.config)), [
13297
+ const backup = backupFiles(dirname17(resolve14(plan2.config)), [
12887
13298
  basename6(plan2.config)
12888
13299
  ]);
12889
13300
  writeFileSync6(plan2.config, after);
@@ -12892,22 +13303,22 @@ ${additions}`;
12892
13303
 
12893
13304
  // src/project/mcp-env.ts
12894
13305
  import { spawn } from "child_process";
12895
- import { readFileSync as readFileSync22, statSync as statSync11 } from "fs";
13306
+ import { readFileSync as readFileSync26, statSync as statSync12 } from "fs";
12896
13307
  import { homedir as homedir5 } from "os";
12897
- import { resolve as resolve14 } from "path";
13308
+ import { resolve as resolve15 } from "path";
12898
13309
  import { parse as parse6 } from "smol-toml";
12899
13310
  function sourcePath(file2, root) {
12900
13311
  if (file2.startsWith("~/")) {
12901
- return resolve14(homedir5(), file2.slice(2));
13312
+ return resolve15(homedir5(), file2.slice(2));
12902
13313
  }
12903
- return resolve14(root, file2.replaceAll("${PROJECT_ROOT}", root));
13314
+ return resolve15(root, file2.replaceAll("${PROJECT_ROOT}", root));
12904
13315
  }
12905
13316
  function sourceValue(file2, pointer) {
12906
13317
  try {
12907
- if (statSync11(file2).size > 2 * 1024 * 1024) {
13318
+ if (statSync12(file2).size > 2 * 1024 * 1024) {
12908
13319
  throw new Error("size");
12909
13320
  }
12910
- const text3 = readFileSync22(file2, "utf8").replace(/^\uFEFF/u, "");
13321
+ const text3 = readFileSync26(file2, "utf8").replace(/^\uFEFF/u, "");
12911
13322
  let value;
12912
13323
  if (file2.endsWith(".toml")) {
12913
13324
  value = parse6(text3);
@@ -12988,8 +13399,8 @@ async function execMcp(spec, alias, env) {
12988
13399
 
12989
13400
  // src/project/doctor.ts
12990
13401
  import { spawnSync as spawnSync3 } from "child_process";
12991
- import { existsSync as existsSync15, readFileSync as readFileSync23 } from "fs";
12992
- import { join as join19 } from "path";
13402
+ import { existsSync as existsSync18, readFileSync as readFileSync27 } from "fs";
13403
+ import { join as join23 } from "path";
12993
13404
  import { parse as parse7 } from "smol-toml";
12994
13405
  var spawnRunner = (command2, args, cwd, env) => {
12995
13406
  const result = spawnSync3(command2, [...args], {
@@ -13066,10 +13477,10 @@ function claude(spec, o) {
13066
13477
  }
13067
13478
  function codex(spec, o) {
13068
13479
  const findings = [];
13069
- const config = join19(o.home, ".codex/config.toml");
13480
+ const config = join23(o.home, ".codex/config.toml");
13070
13481
  let trusted = false;
13071
- if (existsSync15(config)) {
13072
- const projects = parse7(readFileSync23(config, "utf8")).projects ?? {};
13482
+ if (existsSync18(config)) {
13483
+ const projects = parse7(readFileSync27(config, "utf8")).projects ?? {};
13073
13484
  const root = spec.root.replace(/\/$/u, "");
13074
13485
  trusted = projects[root]?.trust_level === "trusted" || projects[`${root}/`]?.trust_level === "trusted";
13075
13486
  }
@@ -13195,8 +13606,8 @@ function grok(spec, o) {
13195
13606
  }
13196
13607
  function antigravity(spec, options2) {
13197
13608
  const foreign = agentNames(spec.root).filter((name) => {
13198
- const text3 = readFileSync23(
13199
- join19(spec.root, ".agents/agents", name, "agent.md"),
13609
+ const text3 = readFileSync27(
13610
+ join23(spec.root, ".agents/agents", name, "agent.md"),
13200
13611
  "utf8"
13201
13612
  );
13202
13613
  return splitFrontmatter(text3).meta["tools"] !== void 0;
@@ -13216,7 +13627,7 @@ function antigravity(spec, options2) {
13216
13627
  if (serversForTool(spec, "antigravity").length > 0) {
13217
13628
  const result = options2.run(
13218
13629
  "agy",
13219
- ["plugin", "validate", join19(spec.root, ANTIGRAVITY_MCP_PLUGIN)],
13630
+ ["plugin", "validate", join23(spec.root, ANTIGRAVITY_MCP_PLUGIN)],
13220
13631
  spec.root
13221
13632
  );
13222
13633
  findings.push(
@@ -13247,21 +13658,21 @@ function doctor(spec, options2) {
13247
13658
  }
13248
13659
 
13249
13660
  // src/project/memory.ts
13250
- import { existsSync as existsSync16, readFileSync as readFileSync24 } from "fs";
13251
- import { isAbsolute as isAbsolute6, join as join20, resolve as resolve15 } from "path";
13661
+ import { existsSync as existsSync19, readFileSync as readFileSync28 } from "fs";
13662
+ import { isAbsolute as isAbsolute7, join as join24, resolve as resolve16 } from "path";
13252
13663
  import { parse as parse8 } from "smol-toml";
13253
- function object6(value) {
13664
+ function object7(value) {
13254
13665
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
13255
13666
  throw new Error("Configuration is not an object");
13256
13667
  }
13257
13668
  return value;
13258
13669
  }
13259
13670
  function settings(file2, toml = false) {
13260
- if (!existsSync16(file2)) {
13671
+ if (!existsSync19(file2)) {
13261
13672
  return {};
13262
13673
  }
13263
- const text3 = readFileSync24(file2, "utf8");
13264
- return object6(toml ? parse8(text3) : JSON.parse(text3));
13674
+ const text3 = readFileSync28(file2, "utf8");
13675
+ return object7(toml ? parse8(text3) : JSON.parse(text3));
13265
13676
  }
13266
13677
  function configuredState(value) {
13267
13678
  if (value === true) {
@@ -13273,11 +13684,11 @@ function configuredState(value) {
13273
13684
  return "unknown";
13274
13685
  }
13275
13686
  function located(metadata2, path, pathScope) {
13276
- return { ...metadata2, path, pathScope, exists: existsSync16(path) };
13687
+ return { ...metadata2, path, pathScope, exists: existsSync19(path) };
13277
13688
  }
13278
13689
  function metadata(tool, spec, options2) {
13279
13690
  const env = options2.env ?? {};
13280
- const directory = (name, fallback) => resolve15(spec.root, env[name] ?? join20(options2.home, fallback));
13691
+ const directory = (name, fallback) => resolve16(spec.root, env[name] ?? join24(options2.home, fallback));
13281
13692
  if (tool === "antigravity") {
13282
13693
  return {
13283
13694
  state: "unsupported",
@@ -13301,7 +13712,7 @@ function metadata(tool, spec, options2) {
13301
13712
  state,
13302
13713
  source: result.missing ? "Native CLI not installed" : "codex features list; active session overrides are not inspected"
13303
13714
  },
13304
- join20(home2, "memories"),
13715
+ join24(home2, "memories"),
13305
13716
  "store"
13306
13717
  );
13307
13718
  }
@@ -13314,13 +13725,13 @@ function metadata(tool, spec, options2) {
13314
13725
  }
13315
13726
  if (tool === "claude") {
13316
13727
  const home2 = directory("CLAUDE_CONFIG_DIR", ".claude");
13317
- const user2 = settings(join20(home2, "settings.json"));
13728
+ const user2 = settings(join24(home2, "settings.json"));
13318
13729
  const state = env["CLAUDE_CODE_DISABLE_AUTO_MEMORY"] === "1" ? "disabled" : configuredState(user2["autoMemoryEnabled"]);
13319
13730
  const source2 = "User configuration and disable environment flag; project trust and active session overrides are not inspected";
13320
13731
  const override = user2["autoMemoryDirectory"];
13321
13732
  if (typeof override === "string") {
13322
- const path = override.startsWith("~/") ? join20(options2.home, override.slice(2)) : override;
13323
- if (!isAbsolute6(path)) {
13733
+ const path = override.startsWith("~/") ? join24(options2.home, override.slice(2)) : override;
13734
+ if (!isAbsolute7(path)) {
13324
13735
  return {
13325
13736
  state: "unknown",
13326
13737
  source: "Invalid autoMemoryDirectory metadata; value redacted"
@@ -13332,7 +13743,7 @@ function metadata(tool, spec, options2) {
13332
13743
  if (env["CLAUDE_CONFIG_DIR"] && projectName && !projectName.includes("/") && !projectName.includes("\\") && projectName !== "." && projectName !== "..") {
13333
13744
  return located(
13334
13745
  { state, source: source2 },
13335
- join20(home2, "projects", projectName, "memory"),
13746
+ join24(home2, "projects", projectName, "memory"),
13336
13747
  "store"
13337
13748
  );
13338
13749
  }
@@ -13341,16 +13752,16 @@ function metadata(tool, spec, options2) {
13341
13752
  state,
13342
13753
  source: `${source2}; native project directory encoding is not guessed`
13343
13754
  },
13344
- join20(home2, "projects"),
13755
+ join24(home2, "projects"),
13345
13756
  "base"
13346
13757
  );
13347
13758
  }
13348
13759
  if (tool === "grok") {
13349
- const home2 = join20(options2.home, ".grok");
13350
- const user2 = settings(join20(home2, "config.toml"), true);
13351
- const project2 = settings(join20(spec.root, ".grok/config.toml"), true);
13352
- const userMemory = user2["memory"] === void 0 ? {} : object6(user2["memory"]);
13353
- const projectMemory = project2["memory"] === void 0 ? {} : object6(project2["memory"]);
13760
+ const home2 = join24(options2.home, ".grok");
13761
+ const user2 = settings(join24(home2, "config.toml"), true);
13762
+ const project2 = settings(join24(spec.root, ".grok/config.toml"), true);
13763
+ const userMemory = user2["memory"] === void 0 ? {} : object7(user2["memory"]);
13764
+ const projectMemory = project2["memory"] === void 0 ? {} : object7(project2["memory"]);
13354
13765
  const overridden = projectMemory["enabled"] !== void 0;
13355
13766
  const state = overridden ? "unknown" : configuredState(userMemory["enabled"]);
13356
13767
  return located(
@@ -13358,13 +13769,13 @@ function metadata(tool, spec, options2) {
13358
13769
  state,
13359
13770
  source: "User memory configuration; project trust and workspace encoding are not exposed by a read-only native memory command"
13360
13771
  },
13361
- join20(home2, "memory-v2/workspaces"),
13772
+ join24(home2, "memory-v2/workspaces"),
13362
13773
  "base"
13363
13774
  );
13364
13775
  }
13365
13776
  const home = directory("GEMINI_CLI_HOME", ".gemini");
13366
- const user = settings(join20(home, "settings.json"));
13367
- const context = user["context"] === void 0 ? {} : object6(user["context"]);
13777
+ const user = settings(join24(home, "settings.json"));
13778
+ const context = user["context"] === void 0 ? {} : object7(user["context"]);
13368
13779
  const names = context["fileName"] ?? "GEMINI.md";
13369
13780
  const contextFileNames = typeof names === "string" ? [names] : names;
13370
13781
  if (!Array.isArray(contextFileNames) || !contextFileNames.every((name) => typeof name === "string")) {
@@ -13379,7 +13790,7 @@ function metadata(tool, spec, options2) {
13379
13790
  source: "Global memory file existence and user context filenames; active memory tool enablement is not exposed",
13380
13791
  contextFileNames
13381
13792
  },
13382
- join20(home, "GEMINI.md"),
13793
+ join24(home, "GEMINI.md"),
13383
13794
  "store"
13384
13795
  );
13385
13796
  }
@@ -13412,14 +13823,14 @@ function memoryFindings(spec, options2) {
13412
13823
  // src/project/edit.ts
13413
13824
  import {
13414
13825
  cpSync,
13415
- existsSync as existsSync17,
13826
+ existsSync as existsSync20,
13416
13827
  mkdirSync as mkdirSync8,
13417
- readFileSync as readFileSync25,
13828
+ readFileSync as readFileSync29,
13418
13829
  rmSync as rmSync5,
13419
- statSync as statSync12,
13830
+ statSync as statSync13,
13420
13831
  writeFileSync as writeFileSync7
13421
13832
  } from "fs";
13422
- import { basename as basename7, dirname as dirname17, join as join21 } from "path";
13833
+ import { basename as basename7, dirname as dirname18, join as join25 } from "path";
13423
13834
  var CROSS_TOOL = ["name", "description"];
13424
13835
  var tomlValue2 = (value) => JSON.stringify(value);
13425
13836
  function findEntry(entries, wanted) {
@@ -13443,7 +13854,7 @@ function addEntry(root, entry2) {
13443
13854
  `${entry2.name} is a ${kind2}; only skills and agents are added to .agents/`
13444
13855
  );
13445
13856
  }
13446
- const { meta, body } = splitFrontmatter(readFileSync25(entry2.path, "utf8"));
13857
+ const { meta, body } = splitFrontmatter(readFileSync29(entry2.path, "utf8"));
13447
13858
  const name = basename7(entry2.slug);
13448
13859
  if (!/^[a-z0-9][a-z0-9-]*$/u.test(name)) {
13449
13860
  throw new ProjectError(
@@ -13451,12 +13862,12 @@ function addEntry(root, entry2) {
13451
13862
  );
13452
13863
  }
13453
13864
  if (kind2 === "skill") {
13454
- const dest2 = join21(root, ".agents/skills", name);
13455
- if (existsSync17(dest2))
13865
+ const dest2 = join25(root, ".agents/skills", name);
13866
+ if (existsSync20(dest2))
13456
13867
  throw new ProjectError(`.agents/skills/${name} already exists`);
13457
- const source2 = entry2.root ?? dirname17(entry2.path);
13458
- mkdirSync8(dirname17(dest2), { recursive: true });
13459
- if (statSync12(source2).isDirectory()) {
13868
+ const source2 = entry2.root ?? dirname18(entry2.path);
13869
+ mkdirSync8(dirname18(dest2), { recursive: true });
13870
+ if (statSync13(source2).isDirectory()) {
13460
13871
  cpSync(source2, dest2, { recursive: true });
13461
13872
  } else {
13462
13873
  mkdirSync8(dest2);
@@ -13467,14 +13878,14 @@ function addEntry(root, entry2) {
13467
13878
  description: meta["description"] ?? entry2.description
13468
13879
  });
13469
13880
  writeFileSync7(
13470
- join21(dest2, "SKILL.md"),
13881
+ join25(dest2, "SKILL.md"),
13471
13882
  `${head}
13472
13883
  ${body.replace(/^\n/u, "")}`
13473
13884
  );
13474
13885
  return { kind: kind2, name, path: `.agents/skills/${name}` };
13475
13886
  }
13476
- const dest = join21(root, ".agents/agents", name);
13477
- if (existsSync17(dest))
13887
+ const dest = join25(root, ".agents/agents", name);
13888
+ if (existsSync20(dest))
13478
13889
  throw new ProjectError(`.agents/agents/${name} already exists`);
13479
13890
  const kept = {};
13480
13891
  const moved = {};
@@ -13484,19 +13895,19 @@ ${body.replace(/^\n/u, "")}`
13484
13895
  }
13485
13896
  mkdirSync8(dest, { recursive: true });
13486
13897
  writeFileSync7(
13487
- join21(dest, "agent.md"),
13898
+ join25(dest, "agent.md"),
13488
13899
  `${renderFrontmatter(kept)}
13489
13900
  ${body.replace(/^\n/u, "")}`
13490
13901
  );
13491
13902
  if (Object.keys(moved).length > 0) {
13492
- const config = join21(root, "pmcp.toml");
13903
+ const config = join25(root, "pmcp.toml");
13493
13904
  const lines2 = [
13494
13905
  `[agents.${name}.claude]`,
13495
13906
  ...Object.entries(moved).map(([k, v]) => `${k} = ${tomlValue2(v)}`)
13496
13907
  ];
13497
- const before = existsSync17(config) ? readFileSync25(config, "utf8") : "";
13498
- const sep6 = before === "" || before.endsWith("\n\n") ? "" : "\n";
13499
- writeFileSync7(config, `${before}${sep6}${lines2.join("\n")}
13908
+ const before = existsSync20(config) ? readFileSync29(config, "utf8") : "";
13909
+ const sep7 = before === "" || before.endsWith("\n\n") ? "" : "\n";
13910
+ writeFileSync7(config, `${before}${sep7}${lines2.join("\n")}
13500
13911
  `);
13501
13912
  }
13502
13913
  return { kind: kind2, name, path: `.agents/agents/${name}/agent.md` };
@@ -13517,15 +13928,15 @@ function withoutTables(toml, name) {
13517
13928
  function removeAsset(root, name) {
13518
13929
  const removed = [];
13519
13930
  for (const rel of [`.agents/skills/${name}`, `.agents/agents/${name}`]) {
13520
- if (!existsSync17(join21(root, rel))) continue;
13521
- rmSync5(join21(root, rel), { recursive: true, force: true });
13931
+ if (!existsSync20(join25(root, rel))) continue;
13932
+ rmSync5(join25(root, rel), { recursive: true, force: true });
13522
13933
  removed.push(rel);
13523
13934
  }
13524
13935
  if (removed.length === 0)
13525
13936
  throw new ProjectError(`no skill or agent named ${name} in .agents/`);
13526
- const config = join21(root, "pmcp.toml");
13527
- if (existsSync17(config)) {
13528
- const before = readFileSync25(config, "utf8");
13937
+ const config = join25(root, "pmcp.toml");
13938
+ if (existsSync20(config)) {
13939
+ const before = readFileSync29(config, "utf8");
13529
13940
  const after = withoutTables(before, name);
13530
13941
  if (after !== before) writeFileSync7(config, after);
13531
13942
  }
@@ -13764,16 +14175,16 @@ var doctorCommand = {
13764
14175
  };
13765
14176
 
13766
14177
  // src/validate.ts
13767
- import { existsSync as existsSync18, readFileSync as readFileSync26, statSync as statSync13 } from "fs";
13768
- import { basename as basename8, join as join22, resolve as resolve16 } from "path";
14178
+ import { existsSync as existsSync21, readFileSync as readFileSync30, statSync as statSync14 } from "fs";
14179
+ import { basename as basename8, join as join26, resolve as resolve17 } from "path";
13769
14180
  function validateSkillDir(dir) {
13770
- const root = resolve16(dir);
13771
- const skillMd = basename8(root) === "SKILL.md" ? root : join22(root, "SKILL.md");
13772
- if (!existsSync18(skillMd) || !statSync13(skillMd).isFile()) {
14181
+ const root = resolve17(dir);
14182
+ const skillMd = basename8(root) === "SKILL.md" ? root : join26(root, "SKILL.md");
14183
+ if (!existsSync21(skillMd) || !statSync14(skillMd).isFile()) {
13773
14184
  return [{ path: root, reason: "no SKILL.md", level: "error" }];
13774
14185
  }
13775
- const front = frontmatterObject(readFileSync26(skillMd, "utf8"));
13776
- const directory = basename8(skillMd === root ? join22(root, "..") : root);
14186
+ const front = frontmatterObject(readFileSync30(skillMd, "utf8"));
14187
+ const directory = basename8(skillMd === root ? join26(root, "..") : root);
13777
14188
  return specProblems(front, directory).map((reason) => ({
13778
14189
  path: skillMd,
13779
14190
  reason,
@@ -13818,8 +14229,8 @@ var validateCommand = {
13818
14229
  };
13819
14230
 
13820
14231
  // src/commands/mailbox.ts
13821
- import { readFileSync as readFileSync27, writeFileSync as writeFileSync8 } from "fs";
13822
- import { resolve as resolve17 } from "path";
14232
+ import { readFileSync as readFileSync31, writeFileSync as writeFileSync8 } from "fs";
14233
+ import { resolve as resolve18 } from "path";
13823
14234
  init_config2();
13824
14235
  init_service();
13825
14236
  init_schemas();
@@ -13902,7 +14313,7 @@ var mailboxCommand = {
13902
14313
  }
13903
14314
  if (verb === "init") {
13904
14315
  const config2 = initializeMailboxConfig(
13905
- resolve17(context.cwd, one(context.args, "config") ?? "pmcp.toml"),
14316
+ resolve18(context.cwd, one(context.args, "config") ?? "pmcp.toml"),
13906
14317
  one(context.args, "state-dir")
13907
14318
  );
13908
14319
  const store2 = await MailboxStore.open(config2);
@@ -13927,7 +14338,7 @@ var mailboxCommand = {
13927
14338
  if (verb === "restore") {
13928
14339
  await restoreBackup(required(context, "input"), {
13929
14340
  ...config,
13930
- databasePath: resolve17(context.cwd, required(context, "output"))
14341
+ databasePath: resolve18(context.cwd, required(context, "output"))
13931
14342
  });
13932
14343
  context.ui.data(
13933
14344
  `${JSON.stringify({ ok: true, data: { restored: true } })}
@@ -14001,7 +14412,7 @@ var mailboxCommand = {
14001
14412
  ownsBinding = true;
14002
14413
  }
14003
14414
  const inputFile = one(context.args, "input");
14004
- const input = inputFile ? JSON.parse(readFileSync27(inputFile, "utf8")) : {};
14415
+ const input = inputFile ? JSON.parse(readFileSync31(inputFile, "utf8")) : {};
14005
14416
  const result = await new MailboxService(store, binding).call(
14006
14417
  operation,
14007
14418
  input
@@ -14085,7 +14496,7 @@ var harnessOptions = [
14085
14496
  ];
14086
14497
 
14087
14498
  // src/commands/harness/invocation.ts
14088
- import { readFileSync as readFileSync28, statSync as statSync14 } from "fs";
14499
+ import { readFileSync as readFileSync32, statSync as statSync15 } from "fs";
14089
14500
  init_validation();
14090
14501
  var common = ["group-file", "generation"];
14091
14502
  var options = {
@@ -14122,10 +14533,10 @@ var options = {
14122
14533
  "recovery:abort-start": [...common, "session"]
14123
14534
  };
14124
14535
  function file(path) {
14125
- const stat = statSync14(path);
14536
+ const stat = statSync15(path);
14126
14537
  if (!stat.isFile() || stat.size > 65536)
14127
14538
  throw new ArgumentError("Input file exceeds 65536 bytes");
14128
- return readFileSync28(path, "utf8");
14539
+ return readFileSync32(path, "utf8");
14129
14540
  }
14130
14541
  function parseInvocation(context) {
14131
14542
  const [family, action, ...extra] = context.args.positional;
@@ -14161,7 +14572,7 @@ function parseInvocation(context) {
14161
14572
  action,
14162
14573
  groupFile: one(context.args, "group-file"),
14163
14574
  generation: one(context.args, "generation"),
14164
- input: inputFile ? object7(JSON.parse(file(inputFile))) : void 0,
14575
+ input: inputFile ? object8(JSON.parse(file(inputFile))) : void 0,
14165
14576
  sessionId: one(context.args, "session"),
14166
14577
  leaseFile: one(context.args, "lease-file"),
14167
14578
  controller: one(context.args, "controller"),
@@ -14364,6 +14775,198 @@ var tuiCommand = {
14364
14775
  }
14365
14776
  };
14366
14777
 
14778
+ // src/commands/marketplace.ts
14779
+ import { resolve as resolve21 } from "path";
14780
+
14781
+ // src/marketplace/export.ts
14782
+ import {
14783
+ existsSync as existsSync33,
14784
+ lstatSync as lstatSync12,
14785
+ mkdirSync as mkdirSync12,
14786
+ readFileSync as readFileSync37,
14787
+ readdirSync as readdirSync13,
14788
+ writeFileSync as writeFileSync14
14789
+ } from "fs";
14790
+ import { dirname as dirname24, join as join52, resolve as resolve20 } from "path";
14791
+ var NATIVE_PLUGIN_RUNTIMES = [
14792
+ "claude",
14793
+ "codex",
14794
+ "gemini",
14795
+ "grok",
14796
+ "agy"
14797
+ ];
14798
+ function isNativePluginRuntime(value) {
14799
+ return NATIVE_PLUGIN_RUNTIMES.includes(value);
14800
+ }
14801
+ function publicPlugins(root) {
14802
+ const rejected = [];
14803
+ const marketplace = readLocalMarketplace(
14804
+ root,
14805
+ (item) => rejected.push(item.reason)
14806
+ );
14807
+ if (!marketplace || rejected.length)
14808
+ throw new Error(`Invalid public marketplace: ${rejected.join("; ")}`);
14809
+ return marketplace.plugins;
14810
+ }
14811
+ function readResources(directory, prefix, files) {
14812
+ for (const entry2 of readdirSync13(directory, { withFileTypes: true })) {
14813
+ if (entry2.isSymbolicLink())
14814
+ throw new Error("Plugin exports cannot contain symlinks");
14815
+ const path = join52(directory, entry2.name);
14816
+ const relativePath = `${prefix}/${entry2.name}`;
14817
+ if (entry2.isDirectory()) {
14818
+ if (relativePath.split("/").length > 6)
14819
+ throw new Error("Plugin resources exceed the supported depth");
14820
+ readResources(path, relativePath, files);
14821
+ continue;
14822
+ }
14823
+ if (!entry2.isFile())
14824
+ throw new Error("Plugin resources must be regular files");
14825
+ const stats = lstatSync12(path);
14826
+ if (stats.size > 1024 * 1024 || files.size >= 256)
14827
+ throw new Error("Plugin resources exceed the export budget");
14828
+ files.set(relativePath, readFileSync37(path));
14829
+ }
14830
+ }
14831
+ function pluginExportFiles(root, name, runtime2) {
14832
+ const plugin = publicPlugins(root).find((item) => item.name === name);
14833
+ if (!plugin) throw new Error("No such public plugin");
14834
+ const files = /* @__PURE__ */ new Map();
14835
+ readResources(containedPath(plugin.directory, "skills"), "skills", files);
14836
+ for (const name2 of ["LICENSE", "NOTICE"])
14837
+ files.set(name2, readFileSync37(containedPath(root, name2)));
14838
+ const manifests = {
14839
+ claude: [".claude-plugin/plugin.json", ".mcp.json"],
14840
+ codex: ["plugin.json", "mcp.json"],
14841
+ gemini: ["gemini-extension.json"],
14842
+ grok: [".claude-plugin/plugin.json", ".mcp.json"],
14843
+ agy: []
14844
+ };
14845
+ for (const filename of manifests[runtime2]) {
14846
+ if (existsSync33(join52(plugin.directory, filename)))
14847
+ files.set(
14848
+ filename,
14849
+ readFileSync37(containedPath(plugin.directory, filename))
14850
+ );
14851
+ }
14852
+ if (runtime2 === "agy") {
14853
+ files.set(
14854
+ "plugin.json",
14855
+ Buffer.from(
14856
+ `${JSON.stringify({ name: plugin.name, description: plugin.manifest.description }, null, 2)}
14857
+ `
14858
+ )
14859
+ );
14860
+ const mcp = join52(plugin.directory, ".mcp.json");
14861
+ if (existsSync33(mcp))
14862
+ files.set(
14863
+ "mcp_config.json",
14864
+ readFileSync37(containedPath(plugin.directory, mcp))
14865
+ );
14866
+ }
14867
+ return files;
14868
+ }
14869
+ function exportPublicPlugin(root, name, runtime2, output) {
14870
+ const destination = resolve20(output);
14871
+ const files = pluginExportFiles(root, name, runtime2);
14872
+ mkdirSync12(dirname24(destination), { recursive: true });
14873
+ try {
14874
+ mkdirSync12(destination);
14875
+ } catch (error) {
14876
+ if (error.code === "EEXIST")
14877
+ throw new Error(
14878
+ "Export destination already exists; choose a new directory"
14879
+ );
14880
+ throw error;
14881
+ }
14882
+ for (const [path, bytes] of files) {
14883
+ const target2 = join52(destination, path);
14884
+ mkdirSync12(dirname24(target2), { recursive: true });
14885
+ writeFileSync14(target2, bytes, { flag: "wx" });
14886
+ }
14887
+ return { plugin: name, runtime: runtime2, output: destination, files: files.size };
14888
+ }
14889
+
14890
+ // src/commands/marketplace.ts
14891
+ var marketplaceCommand = {
14892
+ name: "marketplace",
14893
+ describe: "List free public plugins or export a selected native plugin",
14894
+ usage: "pmcp marketplace list | export <plugin> --runtime <runtime> --output <directory> [--json]",
14895
+ options: [
14896
+ {
14897
+ name: "runtime",
14898
+ describe: "Native plugin format: claude, codex, gemini, grok or agy.",
14899
+ placeholder: "<runtime>"
14900
+ },
14901
+ {
14902
+ name: "output",
14903
+ describe: "New directory for the selected plugin; existing paths are preserved.",
14904
+ placeholder: "<directory>"
14905
+ },
14906
+ {
14907
+ name: "json",
14908
+ describe: "Print machine-readable results.",
14909
+ boolean: true
14910
+ }
14911
+ ],
14912
+ run(context) {
14913
+ const [verb, name, ...extra] = context.args.positional;
14914
+ const root = publicMarketplaceRoot();
14915
+ if (verb === "list") {
14916
+ if (name || extra.length || one(context.args, "runtime") || one(context.args, "output"))
14917
+ throw new ArgumentError(
14918
+ "marketplace list takes no plugin or export options"
14919
+ );
14920
+ const plugins = publicPlugins(root).map((plugin) => ({
14921
+ name: plugin.name,
14922
+ version: plugin.manifest.version,
14923
+ description: plugin.manifest.description
14924
+ }));
14925
+ if (context.args.flags.has("json")) {
14926
+ context.ui.data(
14927
+ `${JSON.stringify({ marketplace: "pmcp", plugins }, null, 2)}
14928
+ `
14929
+ );
14930
+ return 0;
14931
+ }
14932
+ context.ui.table(
14933
+ plugins.map((plugin) => [
14934
+ plugin.name,
14935
+ String(plugin.description ?? "")
14936
+ ])
14937
+ );
14938
+ return 0;
14939
+ }
14940
+ if (verb !== "export" || !name || extra.length)
14941
+ throw new ArgumentError(
14942
+ "Use marketplace list or export with exactly one plugin"
14943
+ );
14944
+ const output = one(context.args, "output");
14945
+ if (!output)
14946
+ throw new ArgumentError("Provide --output for the exported plugin");
14947
+ const runtime2 = one(context.args, "runtime");
14948
+ if (!isNativePluginRuntime(runtime2))
14949
+ throw new ArgumentError(
14950
+ "Choose --runtime claude, codex, gemini, grok or agy"
14951
+ );
14952
+ const result = exportPublicPlugin(
14953
+ root,
14954
+ name,
14955
+ runtime2,
14956
+ resolve21(context.cwd, output)
14957
+ );
14958
+ if (context.args.flags.has("json")) {
14959
+ context.ui.data(`${JSON.stringify(result, null, 2)}
14960
+ `);
14961
+ return 0;
14962
+ }
14963
+ context.ui.success(
14964
+ `Exported ${name} for ${runtime2} to ${result.output}; install with the native plugin manager`
14965
+ );
14966
+ return 0;
14967
+ }
14968
+ };
14969
+
14367
14970
  // src/commands/index.ts
14368
14971
  var COMMANDS = [
14369
14972
  serveCommand,
@@ -14382,7 +14985,8 @@ var COMMANDS = [
14382
14985
  validateCommand,
14383
14986
  mailboxCommand,
14384
14987
  harnessCommand,
14385
- tuiCommand
14988
+ tuiCommand,
14989
+ marketplaceCommand
14386
14990
  ];
14387
14991
  var PLANNED = [];
14388
14992
  var GLOBAL = /* @__PURE__ */ new Set(["-q", "--quiet", "--no-color", "--color"]);
@@ -14428,7 +15032,7 @@ function dispatch(argv, options2 = {}) {
14428
15032
  }
14429
15033
  return run(command2, rest, { ui, env, cwd });
14430
15034
  }
14431
- var VERSION = "0.13.0";
15035
+ var VERSION = "0.14.0";
14432
15036
  async function run(command2, argv, context) {
14433
15037
  try {
14434
15038
  return await command2.run({