@pi-harness/pi-harness 0.1.30 → 0.1.32

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 (288) hide show
  1. package/README.md +1 -1
  2. package/apps/web/dist/assets/index-BqOM0elx.css +2 -0
  3. package/apps/web/dist/assets/index-x2UhIAWm.js +25 -0
  4. package/apps/web/dist/index.html +2 -2
  5. package/apps/web/package.json +1 -1
  6. package/apps/web/profile/cordis.yml +0 -221
  7. package/apps/web/server-dist/bin.js +11 -3
  8. package/apps/web/server-dist/bin.js.map +1 -1
  9. package/apps/web/src/server/bin.ts +10 -2
  10. package/apps/web/src/style.css +30 -1
  11. package/node_modules/@pi-harness/api-gateway/dist/index.d.ts.map +1 -1
  12. package/node_modules/@pi-harness/api-gateway/dist/index.js +70 -18
  13. package/node_modules/@pi-harness/api-gateway/dist/index.js.map +1 -1
  14. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/agent-teams.json +1 -1
  15. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
  16. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/annotation.json +1 -1
  17. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
  18. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/at-file.json +1 -9
  19. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
  20. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
  21. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-fetch.json +1 -8
  22. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-session.json +1 -8
  23. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/canvas-draw.json +2 -2
  24. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
  25. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cleaner.json +1 -9
  26. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cli-notifier.json +1 -1
  27. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/code2skill.json +1 -1
  28. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -1
  29. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context-doctor.json +1 -8
  30. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context.json +1 -7
  31. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cordis-group.json +1 -1
  32. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cordis-logger-console.json +1 -1
  33. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cordis-timer.json +1 -1
  34. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cost-meter.json +1 -1
  35. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/dependency-checker.json +2 -10
  36. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +1 -9
  37. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/fail-logger.json +1 -8
  38. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/genui.json +1 -1
  39. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +1 -8
  40. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/graph-memory.json +1 -1
  41. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/history-compressor.json +2 -2
  42. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/hol-guard.json +2 -2
  43. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/i18n-pair.json +1 -7
  44. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/image-compressor.json +2 -2
  45. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
  46. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-client.json +2 -8
  47. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
  48. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
  49. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
  50. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
  51. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/modlens.json +1 -1
  52. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
  53. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
  54. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/openpets.json +2 -8
  55. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
  56. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
  57. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-dev.json +1 -1
  58. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
  59. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
  60. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-stars.json +1 -8
  61. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-guard.json +2 -2
  62. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
  63. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/readme-gen.json +1 -9
  64. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/recall-unread.json +1 -8
  65. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reverse-skill.json +2 -2
  66. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
  67. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
  68. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
  69. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
  70. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bridge.json +1 -9
  71. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
  72. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
  73. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-insights.json +1 -9
  74. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
  75. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
  76. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-guard.json +2 -9
  77. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/sql-lens.json +1 -8
  78. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
  79. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
  80. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
  81. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
  82. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/test-harness.json +2 -10
  83. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
  84. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/token-guard.json +1 -9
  85. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/turn-rewind.json +1 -8
  86. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
  87. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +1 -7
  88. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
  89. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
  90. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-search.json +2 -2
  91. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/yaml-validator.json +1 -7
  92. package/node_modules/@pi-harness/api-gateway/dist/marketplace.d.ts +18 -2
  93. package/node_modules/@pi-harness/api-gateway/dist/marketplace.d.ts.map +1 -1
  94. package/node_modules/@pi-harness/api-gateway/dist/marketplace.js +93 -10
  95. package/node_modules/@pi-harness/api-gateway/dist/marketplace.js.map +1 -1
  96. package/node_modules/@pi-harness/api-gateway/package.json +1 -27
  97. package/node_modules/@pi-harness/cli/dist/main.d.ts.map +1 -1
  98. package/node_modules/@pi-harness/cli/dist/main.js +19 -3
  99. package/node_modules/@pi-harness/cli/dist/main.js.map +1 -1
  100. package/node_modules/@pi-harness/cli/package.json +1 -1
  101. package/node_modules/@pi-harness/cli/profiles/default/cordis.yml +0 -87
  102. package/node_modules/@pi-harness/host-webserver/package.json +1 -1
  103. package/node_modules/@pi-harness/web-app/package.json +1 -1
  104. package/package.json +6 -79
  105. package/packages/api-gateway/dist/index.d.ts.map +1 -1
  106. package/packages/api-gateway/dist/index.js +70 -18
  107. package/packages/api-gateway/dist/index.js.map +1 -1
  108. package/packages/api-gateway/dist/marketplace-entries/official/agent-teams.json +1 -1
  109. package/packages/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
  110. package/packages/api-gateway/dist/marketplace-entries/official/annotation.json +1 -1
  111. package/packages/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
  112. package/packages/api-gateway/dist/marketplace-entries/official/at-file.json +1 -9
  113. package/packages/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
  114. package/packages/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
  115. package/packages/api-gateway/dist/marketplace-entries/official/browser-fetch.json +1 -8
  116. package/packages/api-gateway/dist/marketplace-entries/official/browser-session.json +1 -8
  117. package/packages/api-gateway/dist/marketplace-entries/official/canvas-draw.json +2 -2
  118. package/packages/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
  119. package/packages/api-gateway/dist/marketplace-entries/official/cleaner.json +1 -9
  120. package/packages/api-gateway/dist/marketplace-entries/official/cli-notifier.json +1 -1
  121. package/packages/api-gateway/dist/marketplace-entries/official/code2skill.json +1 -1
  122. package/packages/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -1
  123. package/packages/api-gateway/dist/marketplace-entries/official/context-doctor.json +1 -8
  124. package/packages/api-gateway/dist/marketplace-entries/official/context.json +1 -7
  125. package/packages/api-gateway/dist/marketplace-entries/official/cordis-group.json +1 -1
  126. package/packages/api-gateway/dist/marketplace-entries/official/cordis-logger-console.json +1 -1
  127. package/packages/api-gateway/dist/marketplace-entries/official/cordis-timer.json +1 -1
  128. package/packages/api-gateway/dist/marketplace-entries/official/cost-meter.json +1 -1
  129. package/packages/api-gateway/dist/marketplace-entries/official/dependency-checker.json +2 -10
  130. package/packages/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +1 -9
  131. package/packages/api-gateway/dist/marketplace-entries/official/fail-logger.json +1 -8
  132. package/packages/api-gateway/dist/marketplace-entries/official/genui.json +1 -1
  133. package/packages/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +1 -8
  134. package/packages/api-gateway/dist/marketplace-entries/official/graph-memory.json +1 -1
  135. package/packages/api-gateway/dist/marketplace-entries/official/history-compressor.json +2 -2
  136. package/packages/api-gateway/dist/marketplace-entries/official/hol-guard.json +2 -2
  137. package/packages/api-gateway/dist/marketplace-entries/official/i18n-pair.json +1 -7
  138. package/packages/api-gateway/dist/marketplace-entries/official/image-compressor.json +2 -2
  139. package/packages/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
  140. package/packages/api-gateway/dist/marketplace-entries/official/mcp-client.json +2 -8
  141. package/packages/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
  142. package/packages/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
  143. package/packages/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
  144. package/packages/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
  145. package/packages/api-gateway/dist/marketplace-entries/official/modlens.json +1 -1
  146. package/packages/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
  147. package/packages/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
  148. package/packages/api-gateway/dist/marketplace-entries/official/openpets.json +2 -8
  149. package/packages/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
  150. package/packages/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
  151. package/packages/api-gateway/dist/marketplace-entries/official/plugin-dev.json +1 -1
  152. package/packages/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
  153. package/packages/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
  154. package/packages/api-gateway/dist/marketplace-entries/official/plugin-stars.json +1 -8
  155. package/packages/api-gateway/dist/marketplace-entries/official/prompt-guard.json +2 -2
  156. package/packages/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
  157. package/packages/api-gateway/dist/marketplace-entries/official/readme-gen.json +1 -9
  158. package/packages/api-gateway/dist/marketplace-entries/official/recall-unread.json +1 -8
  159. package/packages/api-gateway/dist/marketplace-entries/official/reverse-skill.json +2 -2
  160. package/packages/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
  161. package/packages/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
  162. package/packages/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
  163. package/packages/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
  164. package/packages/api-gateway/dist/marketplace-entries/official/session-bridge.json +1 -9
  165. package/packages/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
  166. package/packages/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
  167. package/packages/api-gateway/dist/marketplace-entries/official/session-insights.json +1 -9
  168. package/packages/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
  169. package/packages/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
  170. package/packages/api-gateway/dist/marketplace-entries/official/skill-guard.json +2 -9
  171. package/packages/api-gateway/dist/marketplace-entries/official/sql-lens.json +1 -8
  172. package/packages/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
  173. package/packages/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
  174. package/packages/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
  175. package/packages/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
  176. package/packages/api-gateway/dist/marketplace-entries/official/test-harness.json +2 -10
  177. package/packages/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
  178. package/packages/api-gateway/dist/marketplace-entries/official/token-guard.json +1 -9
  179. package/packages/api-gateway/dist/marketplace-entries/official/turn-rewind.json +1 -8
  180. package/packages/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
  181. package/packages/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +1 -7
  182. package/packages/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
  183. package/packages/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
  184. package/packages/api-gateway/dist/marketplace-entries/official/workspace-search.json +2 -2
  185. package/packages/api-gateway/dist/marketplace-entries/official/yaml-validator.json +1 -7
  186. package/packages/api-gateway/dist/marketplace.d.ts +18 -2
  187. package/packages/api-gateway/dist/marketplace.d.ts.map +1 -1
  188. package/packages/api-gateway/dist/marketplace.js +93 -10
  189. package/packages/api-gateway/dist/marketplace.js.map +1 -1
  190. package/packages/api-gateway/package.json +1 -27
  191. package/packages/api-gateway/src/index.ts +85 -23
  192. package/packages/api-gateway/src/marketplace-entries/official/agent-teams.json +1 -1
  193. package/packages/api-gateway/src/marketplace-entries/official/anchored-standard.json +1 -1
  194. package/packages/api-gateway/src/marketplace-entries/official/annotation.json +1 -1
  195. package/packages/api-gateway/src/marketplace-entries/official/archify.json +1 -1
  196. package/packages/api-gateway/src/marketplace-entries/official/at-file.json +1 -9
  197. package/packages/api-gateway/src/marketplace-entries/official/auto-mode.json +1 -1
  198. package/packages/api-gateway/src/marketplace-entries/official/better-sidebar.json +1 -1
  199. package/packages/api-gateway/src/marketplace-entries/official/browser-fetch.json +1 -8
  200. package/packages/api-gateway/src/marketplace-entries/official/browser-session.json +1 -8
  201. package/packages/api-gateway/src/marketplace-entries/official/canvas-draw.json +2 -2
  202. package/packages/api-gateway/src/marketplace-entries/official/change-verifier.json +1 -1
  203. package/packages/api-gateway/src/marketplace-entries/official/cleaner.json +1 -9
  204. package/packages/api-gateway/src/marketplace-entries/official/cli-notifier.json +1 -1
  205. package/packages/api-gateway/src/marketplace-entries/official/code2skill.json +1 -1
  206. package/packages/api-gateway/src/marketplace-entries/official/colleague-skill.json +1 -1
  207. package/packages/api-gateway/src/marketplace-entries/official/context-doctor.json +1 -8
  208. package/packages/api-gateway/src/marketplace-entries/official/context.json +1 -7
  209. package/packages/api-gateway/src/marketplace-entries/official/cordis-group.json +1 -1
  210. package/packages/api-gateway/src/marketplace-entries/official/cordis-logger-console.json +1 -1
  211. package/packages/api-gateway/src/marketplace-entries/official/cordis-timer.json +1 -1
  212. package/packages/api-gateway/src/marketplace-entries/official/cost-meter.json +1 -1
  213. package/packages/api-gateway/src/marketplace-entries/official/dependency-checker.json +2 -10
  214. package/packages/api-gateway/src/marketplace-entries/official/docker-sandbox.json +1 -9
  215. package/packages/api-gateway/src/marketplace-entries/official/fail-logger.json +1 -8
  216. package/packages/api-gateway/src/marketplace-entries/official/genui.json +1 -1
  217. package/packages/api-gateway/src/marketplace-entries/official/git-time-capsule.json +1 -8
  218. package/packages/api-gateway/src/marketplace-entries/official/graph-memory.json +1 -1
  219. package/packages/api-gateway/src/marketplace-entries/official/history-compressor.json +2 -2
  220. package/packages/api-gateway/src/marketplace-entries/official/hol-guard.json +2 -2
  221. package/packages/api-gateway/src/marketplace-entries/official/i18n-pair.json +1 -7
  222. package/packages/api-gateway/src/marketplace-entries/official/image-compressor.json +2 -2
  223. package/packages/api-gateway/src/marketplace-entries/official/llm-verifier.json +1 -1
  224. package/packages/api-gateway/src/marketplace-entries/official/mcp-client.json +2 -8
  225. package/packages/api-gateway/src/marketplace-entries/official/mcp-panel.json +1 -1
  226. package/packages/api-gateway/src/marketplace-entries/official/memory.json +1 -1
  227. package/packages/api-gateway/src/marketplace-entries/official/mirage-bridge.json +1 -1
  228. package/packages/api-gateway/src/marketplace-entries/official/mock-server.json +1 -1
  229. package/packages/api-gateway/src/marketplace-entries/official/modlens.json +1 -1
  230. package/packages/api-gateway/src/marketplace-entries/official/module-search.json +1 -1
  231. package/packages/api-gateway/src/marketplace-entries/official/obsidian-sync.json +1 -1
  232. package/packages/api-gateway/src/marketplace-entries/official/openpets.json +2 -8
  233. package/packages/api-gateway/src/marketplace-entries/official/plan-execute.json +1 -1
  234. package/packages/api-gateway/src/marketplace-entries/official/plugin-check.json +1 -1
  235. package/packages/api-gateway/src/marketplace-entries/official/plugin-dev.json +1 -1
  236. package/packages/api-gateway/src/marketplace-entries/official/plugin-finder.json +1 -1
  237. package/packages/api-gateway/src/marketplace-entries/official/plugin-radar.json +1 -1
  238. package/packages/api-gateway/src/marketplace-entries/official/plugin-stars.json +1 -8
  239. package/packages/api-gateway/src/marketplace-entries/official/prompt-guard.json +2 -2
  240. package/packages/api-gateway/src/marketplace-entries/official/prompt-library.json +1 -1
  241. package/packages/api-gateway/src/marketplace-entries/official/readme-gen.json +1 -9
  242. package/packages/api-gateway/src/marketplace-entries/official/recall-unread.json +1 -8
  243. package/packages/api-gateway/src/marketplace-entries/official/reverse-skill.json +2 -2
  244. package/packages/api-gateway/src/marketplace-entries/official/reviewer-bot.json +1 -1
  245. package/packages/api-gateway/src/marketplace-entries/official/runtime-doctor.json +1 -1
  246. package/packages/api-gateway/src/marketplace-entries/official/secure-audit.json +1 -1
  247. package/packages/api-gateway/src/marketplace-entries/official/session-bookmarks.json +1 -1
  248. package/packages/api-gateway/src/marketplace-entries/official/session-bridge.json +1 -9
  249. package/packages/api-gateway/src/marketplace-entries/official/session-compare.json +1 -1
  250. package/packages/api-gateway/src/marketplace-entries/official/session-export.json +1 -1
  251. package/packages/api-gateway/src/marketplace-entries/official/session-insights.json +1 -9
  252. package/packages/api-gateway/src/marketplace-entries/official/session-search.json +1 -1
  253. package/packages/api-gateway/src/marketplace-entries/official/skill-catalog.json +1 -1
  254. package/packages/api-gateway/src/marketplace-entries/official/skill-guard.json +2 -9
  255. package/packages/api-gateway/src/marketplace-entries/official/sql-lens.json +1 -8
  256. package/packages/api-gateway/src/marketplace-entries/official/synapse.json +1 -1
  257. package/packages/api-gateway/src/marketplace-entries/official/tab-manager.json +1 -1
  258. package/packages/api-gateway/src/marketplace-entries/official/taskboard.json +1 -1
  259. package/packages/api-gateway/src/marketplace-entries/official/telemetry-blocker.json +1 -1
  260. package/packages/api-gateway/src/marketplace-entries/official/test-harness.json +2 -10
  261. package/packages/api-gateway/src/marketplace-entries/official/theme-studio.json +1 -1
  262. package/packages/api-gateway/src/marketplace-entries/official/token-guard.json +1 -9
  263. package/packages/api-gateway/src/marketplace-entries/official/turn-rewind.json +1 -8
  264. package/packages/api-gateway/src/marketplace-entries/official/undo-savepoint.json +1 -1
  265. package/packages/api-gateway/src/marketplace-entries/official/vision-toolkit.json +1 -7
  266. package/packages/api-gateway/src/marketplace-entries/official/web-research.json +1 -1
  267. package/packages/api-gateway/src/marketplace-entries/official/workspace-navigator.json +1 -1
  268. package/packages/api-gateway/src/marketplace-entries/official/workspace-search.json +2 -2
  269. package/packages/api-gateway/src/marketplace-entries/official/yaml-validator.json +1 -7
  270. package/packages/api-gateway/src/marketplace.ts +113 -12
  271. package/packages/api-gateway/test/index.test.ts +297 -5
  272. package/packages/api-gateway/test/marketplace-schema.test.ts +12 -0
  273. package/packages/api-gateway/test/marketplace.test.ts +172 -240
  274. package/packages/api-gateway/test/packed-package.test.ts +18 -6
  275. package/packages/api-gateway/test/release-contract.test.ts +8 -4
  276. package/packages/bundle-web-app/package.json +1 -1
  277. package/packages/cli/dist/main.d.ts.map +1 -1
  278. package/packages/cli/dist/main.js +19 -3
  279. package/packages/cli/dist/main.js.map +1 -1
  280. package/packages/cli/package.json +1 -1
  281. package/packages/cli/profiles/default/cordis.yml +0 -87
  282. package/packages/cli/src/main.ts +18 -3
  283. package/packages/cli/test/cli.test.ts +20 -0
  284. package/packages/cli/test/profiles/plugins/cordis.yml +122 -0
  285. package/packages/cli/test/profiles.integration.test.ts +40 -23
  286. package/packages/host-webserver/package.json +1 -1
  287. package/apps/web/dist/assets/index-B7pwZ76Z.js +0 -25
  288. package/apps/web/dist/assets/index-xF647pQJ.css +0 -2
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "vitest";
1
+ import { describe, expect, test, vi } from "vitest";
2
2
  import {
3
3
  MARKETPLACE_CAPABILITIES,
4
4
  MARKETPLACE_CATEGORIES,
@@ -40,14 +40,7 @@ describe("plugin marketplace registry", () => {
40
40
  expect(official.get("plugin-stars")?.description).toMatch(
41
41
  /curated.*raw\.githubusercontent\.com.*descriptor-safe.*bounded.*cancellable.*fail-closed.*panel/iu,
42
42
  );
43
- expect(official.get("plugin-stars")?.capabilities).toEqual([
44
- "curated GitHub ranking search",
45
- "strict bounded snapshot validation",
46
- "redirect-free source fetch",
47
- "cancellable request lifecycle",
48
- "bounded panel inventory",
49
- "validated fail-closed panel reporting",
50
- ]);
43
+ expect(official.get("plugin-stars")?.capabilities).toEqual(["network-access"]);
51
44
  expect(official.get("plugin-stars")?.hooks).toEqual(["ranking search tool", "raw GitHub snapshot", "plugin UI"]);
52
45
  expect(official.get("plugin-stars")?.profile.config).toEqual({
53
46
  sourceUrl: "https://raw.githubusercontent.com/ywsldxk/dsh-plugin-stars/main/data/plugins.json",
@@ -56,135 +49,58 @@ describe("plugin marketplace registry", () => {
56
49
  });
57
50
  expect(official.get("vision-toolkit")?.category.id).toBe("multimodal");
58
51
  expect(official.get("vision-toolkit")?.description).toMatch(/signature-verified.*PNG.*JPEG.*GIF.*WebP.*bounded header.*cancellable.*local/iu);
59
- expect(official.get("vision-toolkit")?.capabilities).toEqual([
60
- "bounded workspace image catalog",
61
- "signature-verified image metadata",
62
- "PNG JPEG GIF and WebP dimensions",
63
- "cancellable bounded traversal",
64
- "bounded normalized panel",
65
- ]);
52
+ expect(official.get("vision-toolkit")?.capabilities).toEqual(["read-only", "reads-files"]);
66
53
  expect(official.get("vision-toolkit")?.hooks).toEqual(["image metadata tools", "workspace access", "plugin UI"]);
67
54
  expect(official.get("vision-toolkit")?.profile.config).toEqual({});
68
55
  expect(official.get("session-bridge")?.category.id).toBe("workflow");
69
56
  expect(official.get("session-bridge")?.description).toMatch(/preview.*export.*confirmed import.*strictly validated.*bounded.*LLM context.*duplicate/iu);
70
- expect(official.get("session-bridge")?.capabilities).toEqual([
71
- "strict bounded handoff format",
72
- "five-part review preview",
73
- "confirmed context import",
74
- "active-session targeting",
75
- "duplicate import protection",
76
- "bounded operation status",
77
- "bounded normalized panel",
78
- ]);
57
+ expect(official.get("session-bridge")?.capabilities).toEqual(["read-only", "session-data"]);
79
58
  expect(official.get("session-bridge")?.hooks).toEqual(["session bridge tools", "active session manager", "custom context messages", "plugin UI"]);
80
59
  expect(official.get("session-bridge")?.profile.config).toEqual({});
81
60
  expect(official.get("skill-guard")?.category.id).toBe("security");
82
61
  expect(official.get("skill-guard")?.description).toMatch(/loaded Skill entry.*bounded heuristic.*does not disable/iu);
83
- expect(official.get("skill-guard")?.capabilities).toEqual([
84
- "bounded loaded-entry audit",
85
- "instruction-override heuristics",
86
- "secret-exfiltration heuristics",
87
- "destructive-command and obfuscation heuristics",
88
- "descriptor-safe cancellable scans",
89
- "bounded normalized panel",
90
- ]);
62
+ expect(official.get("skill-guard")?.capabilities).toEqual(["read-only", "reads-files"]);
91
63
  expect(official.get("skill-guard")?.hooks).toEqual(["skill scan tool", "resource loader", "plugin UI"]);
92
64
  expect(official.get("skill-guard")?.profile.config).toEqual({});
93
65
  expect(official.get("cost-meter")?.category.id).toBe("observability");
94
66
  expect(official.get("cost-meter")?.description).toMatch(/runtime-reported.*UTC daily increments.*bounded local ledger/iu);
95
- expect(official.get("cost-meter")?.capabilities).toEqual([
96
- "UTC daily cost ledger",
97
- "session cost snapshots",
98
- "daily budget monitoring",
99
- "bounded local persistence",
100
- ]);
67
+ expect(official.get("cost-meter")?.capabilities).toEqual(["session-data", "reads-files", "writes-files"]);
101
68
  expect(official.get("cost-meter")?.hooks).toEqual(["agent end", "cost report tool", "plugin UI"]);
102
69
  expect(official.get("cost-meter")?.profile.config).toEqual({ dailyBudget: 0, maxEntries: 365 });
103
70
  expect(official.get("skill-catalog")?.category.id).toBe("discovery");
104
71
  expect(official.get("prompt-guard")?.category.id).toBe("security");
105
72
  expect(official.get("browser-fetch")?.category.id).toBe("web");
106
73
  expect(official.get("browser-fetch")?.description).toMatch(/bounded.*text.*descriptor-safe.*DNS.*pinn.*redirect.*private.*timeout.*validated.*panel/iu);
107
- expect(official.get("browser-fetch")?.capabilities).toEqual([
108
- "bounded textual HTTP fetch",
109
- "DNS rebinding protection",
110
- "per-hop SSRF validation",
111
- "cancellable request lifecycle",
112
- "bounded browser preview",
113
- "validated fail-closed panel reporting",
114
- ]);
74
+ expect(official.get("browser-fetch")?.capabilities).toEqual(["network-access"]);
115
75
  expect(official.get("browser-fetch")?.profile.config).toEqual({ allowPrivate: false, timeoutMs: 20_000 });
116
76
  expect(official.get("web-research")?.category.id).toBe("web");
117
77
  expect(official.get("mcp-client")?.category.id).toBe("tools");
118
78
  expect(official.get("mcp-client")?.description).toMatch(/MCP stdio.*bounded.*pagination.*tool.*resource.*prompt.*cancellable.*lifecycle/iu);
119
- expect(official.get("mcp-client")?.capabilities).toEqual([
120
- "bounded MCP stdio transport",
121
- "bounded inventory pagination",
122
- "tool resource and prompt bridging",
123
- "persistent server lifecycle",
124
- "cancellable queued requests",
125
- ]);
79
+ expect(official.get("mcp-client")?.capabilities).toEqual(["runs-commands"]);
126
80
  expect(official.get("mcp-client")?.hooks).toEqual(["MCP stdio tools", "managed server lifecycle", "plugin UI"]);
127
81
  expect(official.get("mcp-client")?.profile.config).toEqual({ servers: [] });
128
82
  expect(official.get("at-file")?.category.id).toBe("context");
129
83
  expect(official.get("at-file")?.description).toMatch(/bounded 256 KiB.*UTF-8.*canonical.*untrusted.*closing-tag.*cancellable.*sequential/iu);
130
- expect(official.get("at-file")?.capabilities).toEqual([
131
- "256 KiB strict UTF-8 text attachments",
132
- "canonical workspace path confinement",
133
- "no-follow regular-file reads",
134
- "untrusted context framing",
135
- "closing-tag neutralization",
136
- "cancellable sequential execution",
137
- "descriptor-safe normalized panel",
138
- ]);
84
+ expect(official.get("at-file")?.capabilities).toEqual(["read-only", "reads-files"]);
139
85
  expect(official.get("at-file")?.hooks).toEqual(["file context tool", "workspace file read", "plugin UI"]);
140
86
  expect(official.get("at-file")?.profile.config).toEqual({});
141
87
  expect(official.get("dependency-checker")?.category.id).toBe("developer");
142
88
  expect(official.get("dependency-checker")?.description).toMatch(/bounded.*offline.*read-only.*package\.json.*requirements.*presence.*unresolved/iu);
143
- expect(official.get("dependency-checker")?.capabilities).toEqual([
144
- "2000-declaration local presence scan",
145
- "4096-entry workspace-contained virtualenv scan",
146
- "npm common-intersection conflict detection",
147
- "bounded Python numeric constraint analysis",
148
- "unresolved constraint and directive reporting",
149
- "optional dependency reporting",
150
- "descriptor-safe normalized panel",
151
- ]);
89
+ expect(official.get("dependency-checker")?.capabilities).toEqual(["read-only", "reads-files"]);
152
90
  expect(official.get("dependency-checker")?.hooks).toEqual(["dependency check tool", "workspace manifest read", "plugin UI"]);
153
91
  expect(official.get("token-guard")?.category.id).toBe("observability");
154
92
  expect(official.get("token-guard")?.description).toMatch(/descriptor-safe.*one abort.*per run.*context.*billed run-token.*cached.*normalized panel/iu);
155
- expect(official.get("token-guard")?.capabilities).toEqual([
156
- "strict context percentage budget",
157
- "optional billed run-token budget",
158
- "one abort request per run",
159
- "resilient descriptor-safe monitoring",
160
- "bounded streaming inspection cadence",
161
- "bounded abort error status",
162
- "cached normalized panel",
163
- ]);
93
+ expect(official.get("token-guard")?.capabilities).toEqual(["read-only", "session-data"]);
164
94
  expect(official.get("token-guard")?.hooks).toEqual(["Pi session lifecycle", "active runtime abort", "session usage and statistics", "plugin UI"]);
165
95
  expect(official.get("token-guard")?.profile.config).toEqual({ maxPercent: 90, maxRunTokens: 0 });
166
96
  expect(official.get("recall-unread")?.category.id).toBe("workflow");
167
97
  expect(official.get("recall-unread")?.description).toMatch(/read-only.*bounded.*strict UTF-8.*current workspace.*unanswered.*cached/iu);
168
- expect(official.get("recall-unread")?.capabilities).toEqual([
169
- "bounded current-workspace JSONL discovery",
170
- "strict UTF-8 no-follow session reads",
171
- "unanswered-tail detection",
172
- "cached startup and manual rescans",
173
- "descriptor-safe cancellable queries",
174
- "bounded normalized panel",
175
- ]);
98
+ expect(official.get("recall-unread")?.capabilities).toEqual(["read-only", "session-data", "reads-files"]);
176
99
  expect(official.get("recall-unread")?.hooks).toEqual(["recall unread tool", "native session storage", "active session manager", "plugin UI"]);
177
100
  expect(official.get("recall-unread")?.profile.config).toEqual({});
178
101
  expect(official.get("turn-rewind")?.category.id).toBe("workflow");
179
102
  expect(official.get("turn-rewind")?.description).toMatch(/bounded.*current branch.*queued.*cancellable.*native session tree/iu);
180
- expect(official.get("turn-rewind")?.capabilities).toEqual([
181
- "bounded current-branch candidate scan",
182
- "settled-state queued navigation",
183
- "preserved native session branches",
184
- "optional branch summarization",
185
- "cancellable serialized rewinds",
186
- "bounded normalized operation panel",
187
- ]);
103
+ expect(official.get("turn-rewind")?.capabilities).toEqual(["read-only", "session-data"]);
188
104
  expect(official.get("turn-rewind")?.hooks).toEqual(["session rewind tool", "active session tree", "agent settled lifecycle", "plugin UI"]);
189
105
  expect(official.get("turn-rewind")?.profile.config).toEqual({});
190
106
  expect(official.get("context-doctor")?.category.id).toBe("observability");
@@ -198,82 +114,41 @@ describe("plugin marketplace registry", () => {
198
114
  expect(official.get("image-compressor")?.category.id).toBe("multimodal");
199
115
  expect(official.get("code2skill")?.category.id).toBe("tools");
200
116
  expect(official.get("code2skill")?.description).toMatch(/selected workspace source files/iu);
201
- expect(official.get("code2skill")?.capabilities).toEqual(["bounded skill packaging", "source file preservation", "SKILL.md generation"]);
117
+ expect(official.get("code2skill")?.capabilities).toEqual(["reads-files", "writes-files"]);
202
118
  expect(official.get("workspace-search")?.category.id).toBe("context");
203
119
  expect(official.get("plugin-check")?.category.id).toBe("security");
204
120
  expect(official.get("test-harness")?.category.id).toBe("testing");
205
121
  expect(official.get("test-harness")?.description).toMatch(
206
122
  /five fixed npm script.*trusted workspace.*12 KiB.*UTF-8.*untrusted.*timeout.*cancellable process-tree/iu,
207
123
  );
208
- expect(official.get("test-harness")?.capabilities).toEqual([
209
- "five-script verification allowlist",
210
- "real npm exit status and signal reporting",
211
- "12 KiB UTF-8-safe output tail",
212
- "terminal-control sanitization and untrusted framing",
213
- "configurable bounded timeout",
214
- "cancellable process-tree cleanup",
215
- "descriptor-safe normalized panel",
216
- ]);
124
+ expect(official.get("test-harness")?.capabilities).toEqual(["runs-commands"]);
217
125
  expect(official.get("test-harness")?.hooks).toEqual(["project verification tool", "workspace npm scripts", "plugin UI"]);
218
126
  expect(official.get("test-harness")?.profile.config).toEqual({ timeoutMs: 120_000 });
219
127
  expect(official.get("git-time-capsule")?.category.id).toBe("workflow");
220
128
  expect(official.get("git-time-capsule")?.description).toMatch(/unstaged tracked Git diff.*byte.*validated.*reverse/iu);
221
- expect(official.get("git-time-capsule")?.capabilities).toEqual([
222
- "byte-exact validated unstaged diff capture",
223
- "exclusive no-clobber capsule publication",
224
- "confirmed deterministic reverse apply",
225
- "bounded 256-capsule inventory",
226
- "cancellable serialized Git operations",
227
- "descriptor-safe normalized panel",
228
- ]);
129
+ expect(official.get("git-time-capsule")?.capabilities).toEqual(["reads-files", "writes-files", "runs-commands"]);
229
130
  expect(official.get("git-time-capsule")?.hooks).toEqual(["Git snapshot tool", "Git restore tool", "plugin UI"]);
230
131
  expect(official.get("git-time-capsule")?.profile.config).toEqual({ timeoutMs: 15_000 });
231
132
  expect(official.get("graph-memory")?.description).toMatch(/bounded typed.*directed relations.*atomic.*cross-session/iu);
232
- expect(official.get("graph-memory")?.capabilities).toEqual([
233
- "bounded typed nodes",
234
- "validated directed relations",
235
- "ranked graph search",
236
- "atomic locked persistence",
237
- ]);
133
+ expect(official.get("graph-memory")?.capabilities).toEqual(["reads-files", "writes-files"]);
238
134
  expect(official.get("graph-memory")?.hooks).toEqual(["graph memory tools", "local graph file", "plugin UI"]);
239
135
  expect(official.get("graph-memory")?.profile.config).toEqual({ fileName: "graph-memory.json", maxNodes: 2_000, maxRelations: 5_000 });
240
136
  expect(official.get("yaml-validator")?.category.id).toBe("developer");
241
137
  expect(official.get("yaml-validator")?.description).toMatch(/workspace-contained.*UTF-8.*multi-document.*bounded.*cancellable/iu);
242
- expect(official.get("yaml-validator")?.capabilities).toEqual([
243
- "workspace-contained bounded reads",
244
- "strict UTF-8 multi-document YAML",
245
- "line-aware error and warning diagnostics",
246
- "cancellable validation lifecycle",
247
- "bounded panel previews",
248
- ]);
138
+ expect(official.get("yaml-validator")?.capabilities).toEqual(["read-only", "reads-files"]);
249
139
  expect(official.get("yaml-validator")?.hooks).toEqual(["YAML validation tool", "workspace files", "plugin UI"]);
250
140
  expect(official.get("yaml-validator")?.profile.config).toEqual({});
251
141
  expect(official.get("browser-session")?.category.id).toBe("web");
252
142
  expect(official.get("browser-session")?.category).toEqual(official.get("browser-fetch")?.category);
253
143
  expect(official.get("browser-session")?.description).toMatch(/loopback-only.*descriptor-safe.*bounded.*cancellable.*screenshot.*validated.*panel/iu);
254
- expect(official.get("browser-session")?.capabilities).toEqual([
255
- "loopback-only CDP endpoint",
256
- "bounded tab discovery",
257
- "navigation read click and screenshot tools",
258
- "cancellable request lifecycle",
259
- "bounded panel previews",
260
- "validated fail-closed panel reporting",
261
- ]);
144
+ expect(official.get("browser-session")?.capabilities).toEqual(["network-access"]);
262
145
  expect(official.get("browser-session")?.hooks).toEqual(["browser session tools", "Chrome DevTools Protocol", "plugin UI"]);
263
146
  expect(official.get("browser-session")?.profile.config).toEqual({ endpoint: "http://127.0.0.1:9222" });
264
147
  expect(official.get("docker-sandbox")?.category.id).toBe("security");
265
148
  expect(official.get("docker-sandbox")?.description).toMatch(
266
149
  /descriptor-safe.*local-only.*no container network.*read-only workspace.*CPU.*memory.*PID.*sanitized output.*strict panel.*cancellation cleanup/iu,
267
150
  );
268
- expect(official.get("docker-sandbox")?.capabilities).toEqual([
269
- "local-only image execution",
270
- "no-network containers",
271
- "read-only workspace by default",
272
- "CPU memory and PID limits",
273
- "sanitized bounded output",
274
- "strict panel reporting",
275
- "cancellation cleanup",
276
- ]);
151
+ expect(official.get("docker-sandbox")?.capabilities).toEqual(["reads-files", "writes-files", "runs-commands"]);
277
152
  expect(official.get("docker-sandbox")?.hooks).toEqual(["sandbox execution tool", "Docker CLI", "plugin UI"]);
278
153
  expect(official.get("docker-sandbox")?.profile.config).toEqual({});
279
154
  expect(official.get("mock-server")?.category.id).toBe("tools");
@@ -281,27 +156,14 @@ describe("plugin marketplace registry", () => {
281
156
  expect(official.get("sql-lens")?.description).toMatch(
282
157
  /workspace.*SQLite.*strict.*descriptor-safe.*single.*read-only.*bounded.*symlink.*timed.*cancellation.*fail-closed.*panel/iu,
283
158
  );
284
- expect(official.get("sql-lens")?.capabilities).toEqual([
285
- "single-statement SQLite inspection",
286
- "isolated read-only query worker",
287
- "bounded rows cells and result bytes",
288
- "workspace and symlink safety checks",
289
- "timeout and cancellation termination",
290
- "validated fail-closed panel reporting",
291
- ]);
159
+ expect(official.get("sql-lens")?.capabilities).toEqual(["reads-files", "runs-commands"]);
292
160
  expect(official.get("sql-lens")?.hooks).toEqual(["SQL read-only tool", "workspace SQLite files", "plugin UI"]);
293
161
  expect(official.get("sql-lens")?.profile.config).toEqual({ timeoutMs: 5_000 });
294
162
  expect(official.get("i18n-pair")?.category.id).toBe("workflow");
295
163
  expect(official.get("i18n-pair")?.description).toMatch(
296
164
  /strict read-only.*bounded JSON locale.*no-follow workspace.*collision-safe missing.*extra.*stable failures.*cancellation.*validated panel/iu,
297
165
  );
298
- expect(official.get("i18n-pair")?.capabilities).toEqual([
299
- "collision-safe locale key parity",
300
- "strict bounded workspace-only JSON reads",
301
- "no-follow symbolic-link safety",
302
- "stable sequential cancellable inspection",
303
- "validated bounded panel reporting",
304
- ]);
166
+ expect(official.get("i18n-pair")?.capabilities).toEqual(["read-only", "reads-files"]);
305
167
  expect(official.get("i18n-pair")?.hooks).toEqual(["i18n check tool", "workspace locale files", "plugin UI"]);
306
168
  expect(official.get("i18n-pair")?.profile.config).toEqual({});
307
169
  expect(official.get("plugin-finder")?.category.id).toBe("discovery");
@@ -309,15 +171,7 @@ describe("plugin marketplace registry", () => {
309
171
  expect(official.get("readme-gen")?.description).toMatch(
310
172
  /strictly bounded manifest.*descriptor-safe loader.*Markdown-safe.*confirmed.*no-clobber atomic.*explicit overwrite.*cancellable/iu,
311
173
  );
312
- expect(official.get("readme-gen")?.capabilities).toEqual([
313
- "bounded manifest metadata",
314
- "descriptor-safe loader inventory",
315
- "Markdown-safe rendering",
316
- "confirmed no-clobber atomic writes",
317
- "explicit overwrite confirmation",
318
- "cancellable sequential tools",
319
- "bounded normalized operation panel",
320
- ]);
174
+ expect(official.get("readme-gen")?.capabilities).toEqual(["reads-files", "writes-files"]);
321
175
  expect(official.get("readme-gen")?.hooks).toEqual([
322
176
  "README report and write tools",
323
177
  "workspace manifest and files",
@@ -332,28 +186,14 @@ describe("plugin marketplace registry", () => {
332
186
  expect(official.get("openpets")?.description).toMatch(
333
187
  /bounded.*companion state.*validated.*session entr.*without retaining message contents.*persistence/iu,
334
188
  );
335
- expect(official.get("openpets")?.capabilities).toEqual([
336
- "bounded durable companion state",
337
- "validated session recovery",
338
- "descriptor-safe pet actions",
339
- "session event reactions",
340
- "persistence health panel",
341
- ]);
189
+ expect(official.get("openpets")?.capabilities).toEqual(["read-only", "session-data"]);
342
190
  expect(official.get("openpets")?.hooks).toEqual(["session events", "pet reaction tool", "session storage", "plugin UI"]);
343
191
  expect(official.get("openpets")?.profile.config).toEqual({});
344
192
  expect(official.get("session-insights")?.category.id).toBe("observability");
345
193
  expect(official.get("session-insights")?.description).toMatch(
346
194
  /descriptor-safe.*validated.*cached.*session.*statistics.*confirmed.*settled.*compaction.*model.*usage.*cost.*cancellable/iu,
347
195
  );
348
- expect(official.get("session-insights")?.capabilities).toEqual([
349
- "validated detached session statistics",
350
- "message token cache cost and context accounting",
351
- "cached active-session panel",
352
- "confirmed settled-session compaction",
353
- "dedicated compaction cancellation",
354
- "single-flight bounded operation status",
355
- "normalized fail-closed browser view",
356
- ]);
196
+ expect(official.get("session-insights")?.capabilities).toEqual(["read-only", "session-data"]);
357
197
  expect(official.get("session-insights")?.hooks).toEqual(["session report tool", "active runtime session", "Pi session lifecycle", "plugin UI"]);
358
198
  expect(official.get("session-insights")?.profile.config).toEqual({});
359
199
  expect(official.get("mcp-panel")?.category.id).toBe("tools");
@@ -361,31 +201,14 @@ describe("plugin marketplace registry", () => {
361
201
  expect(official.get("fail-logger")?.description).toMatch(
362
202
  /bounded.*extension.*Agent.*non-aborted compaction.*descriptor-safe event inspection.*safe diagnostic.*occurrence counts/iu,
363
203
  );
364
- expect(official.get("fail-logger")?.capabilities).toEqual([
365
- "bounded failure aggregation",
366
- "descriptor-safe event inspection",
367
- "abort-aware compaction diagnostics",
368
- "occurrence counting",
369
- "safe diagnostic summaries",
370
- "capacity visibility",
371
- ]);
204
+ expect(official.get("fail-logger")?.capabilities).toEqual(["read-only"]);
372
205
  expect(official.get("fail-logger")?.hooks).toEqual(["extension error", "agent end", "compaction end", "plugin UI"]);
373
206
  expect(official.get("genui")?.description).toMatch(/bounded.*text, badge, and decimal progress.*plain text/iu);
374
- expect(official.get("genui")?.capabilities).toEqual([
375
- "bounded structured cards",
376
- "typed text badge and progress blocks",
377
- "decimal progress validation",
378
- "plain-text HTML handling",
379
- ]);
207
+ expect(official.get("genui")?.capabilities).toEqual(["read-only"]);
380
208
  expect(official.get("genui")?.hooks).toEqual(["GenUI render tool", "plugin UI"]);
381
209
  expect(official.get("plugin-dev")?.category.id).toBe("developer");
382
210
  expect(official.get("plugin-dev")?.description).toMatch(/defer.*session resource.*agent.*settled.*single.*reload.*bounded.*trusted.*development/iu);
383
- expect(official.get("plugin-dev")?.capabilities).toEqual([
384
- "settled-session resource reload",
385
- "single-flight reload guard",
386
- "bounded reload status",
387
- "cancellable caller wait",
388
- ]);
211
+ expect(official.get("plugin-dev")?.capabilities).toEqual(["read-only", "session-data"]);
389
212
  expect(official.get("plugin-dev")?.hooks).toEqual(["session resource reload tool", "Pi session lifecycle", "plugin UI"]);
390
213
  expect(official.get("plugin-dev")?.profile.config).toEqual({});
391
214
  expect(official.get("session-export")?.category.id).toBe("workflow");
@@ -403,25 +226,12 @@ describe("plugin marketplace registry", () => {
403
226
  expect(official.get("context-insights")?.description).toMatch(
404
227
  /descriptor-safe.*bounded message composition.*cached.*active-session.*lifecycle.*normalized browser/iu,
405
228
  );
406
- expect(official.get("context-insights")?.capabilities).toEqual([
407
- "descriptor-safe bounded message composition",
408
- "resilient context usage inspection",
409
- "active-session lifecycle counters",
410
- "cached session-aware panel",
411
- "bounded normalized browser view",
412
- ]);
229
+ expect(official.get("context-insights")?.capabilities).toEqual(["read-only", "session-data"]);
413
230
  expect(official.get("context-insights")?.hooks).toEqual(["context inspection tool", "active runtime session", "Pi session lifecycle", "plugin UI"]);
414
231
  expect(official.get("context-insights")?.profile.config).toEqual({});
415
232
  expect(official.get("context-doctor")?.category.id).toBe("observability");
416
233
  expect(official.get("context-doctor")?.description).toMatch(/descriptor-safe.*bounded.*queued.*agent.*settled.*confirmed.*model.*cost.*cancellable/iu);
417
- expect(official.get("context-doctor")?.capabilities).toEqual([
418
- "descriptor-safe bounded context audit",
419
- "pressure oversized uninspectable and tool-error diagnostics",
420
- "confirmed settled-session compaction",
421
- "dedicated compaction cancellation",
422
- "single-flight bounded operation status",
423
- "cached normalized panel",
424
- ]);
234
+ expect(official.get("context-doctor")?.capabilities).toEqual(["read-only", "session-data"]);
425
235
  expect(official.get("context-doctor")?.hooks).toEqual([
426
236
  "context doctor tool",
427
237
  "session messages and usage",
@@ -431,40 +241,27 @@ describe("plugin marketplace registry", () => {
431
241
  ]);
432
242
  expect(official.get("context-doctor")?.profile.config).toEqual({});
433
243
  expect(official.get("cordis-group")?.category.id).toBe("composition");
434
- expect(official.get("cordis-group")?.capabilities).toEqual(["nested plugin composition", "transactional rollback", "lifecycle ownership"]);
244
+ expect(official.get("cordis-group")?.capabilities).toEqual(["read-only"]);
435
245
  expect(official.get("cordis-group")?.hooks).toEqual(["loader entry tree"]);
436
246
  expect(official.get("cordis-logger-console")?.category.id).toBe("observability");
437
- expect(official.get("cordis-logger-console")?.capabilities).toEqual(["bounded console logging", "per-logger severity filtering", "safe recent-log panel"]);
247
+ expect(official.get("cordis-logger-console")?.capabilities).toEqual(["read-only"]);
438
248
  expect(official.get("cordis-logger-console")?.hooks).toEqual(["Cordis logger exporter", "plugin UI"]);
439
249
  expect(official.get("cordis-logger-console")?.profile.config).toEqual({ levels: { default: 2 }, maxLength: 8_192 });
440
250
  expect(official.get("cordis-timer")?.category.id).toBe("runtime");
441
- expect(official.get("cordis-timer")?.capabilities).toEqual([
442
- "scheduling",
443
- "lifecycle-owned cancellation",
444
- "async interval iteration",
445
- "throttle and debounce",
446
- ]);
251
+ expect(official.get("cordis-timer")?.capabilities).toEqual(["read-only"]);
447
252
  expect(official.get("cordis-timer")?.hooks).toEqual(["Cordis timer service", "plugin UI"]);
448
253
  expect(official.get("prompt-library")?.category.id).toBe("workflow");
449
254
  expect(official.get("cleaner")?.category.id).toBe("developer");
450
255
  expect(official.get("cleaner")?.description).toMatch(
451
256
  /strict.*descriptor-safe.*display-safe.*bounded.*Git capsule.*explicit confirmation.*retention.*symlink.*replacement.*cancellable.*fail-closed/iu,
452
257
  );
453
- expect(official.get("cleaner")?.capabilities).toEqual([
454
- "strict configuration and parameters",
455
- "bounded capsule inventory",
456
- "display-safe capsule filtering",
457
- "confirmed retention cleanup",
458
- "symlink and replacement defenses",
459
- "cancellable serialized cleanup",
460
- "fail-closed normalized panel",
461
- ]);
258
+ expect(official.get("cleaner")?.capabilities).toEqual(["reads-files", "writes-files"]);
462
259
  expect(official.get("cleaner")?.hooks).toEqual(["capsule cleanup tool", "agent capsule directory", "plugin UI"]);
463
260
  expect(official.get("cleaner")?.profile.config).toEqual({});
464
261
  expect(official.get("cli-notifier")?.category.id).toBe("workflow");
465
262
  expect(official.get("cli-notifier")?.description).toMatch(/local desktop notifications/iu);
466
263
  expect(official.get("cli-notifier")?.description).not.toMatch(/webhook/iu);
467
- expect(official.get("cli-notifier")?.capabilities).toEqual(["desktop notification", "completion notice", "failure and abort notice"]);
264
+ expect(official.get("cli-notifier")?.capabilities).toEqual(["runs-commands"]);
468
265
  expect(official.get("cli-notifier")?.hooks).toEqual(["agent end", "compaction error", "plugin UI"]);
469
266
  expect(official.get("obsidian-sync")?.category.id).toBe("workflow");
470
267
  expect(official.get("tab-manager")?.category.id).toBe("workflow");
@@ -481,7 +278,7 @@ describe("plugin marketplace registry", () => {
481
278
  });
482
279
 
483
280
  test("filters by query and capability without mutating the registry", () => {
484
- const result = searchMarketplace("timer", "scheduling");
281
+ const result = searchMarketplace("timer", "read-only");
485
282
  expect(result.map((plugin) => plugin.packageName)).toEqual(["@deepseek-ai/cordis-plugin-timer"]);
486
283
  expect(searchMarketplace("does-not-exist")).toEqual([]);
487
284
  expect(MARKETPLACE_PLUGINS.length).toBeGreaterThan(3);
@@ -503,7 +300,44 @@ describe("plugin marketplace registry", () => {
503
300
  pageSize: 2,
504
301
  hasNext: MARKETPLACE_PLUGINS.length > 4,
505
302
  });
506
- expect(MARKETPLACE_CAPABILITIES).toContain("scheduling");
303
+ });
304
+
305
+ // The filter is the first thing a reader touches before installing anything, so what it offers has to be a fixed set that says what a plugin does to the machine, and every entry has to answer it.
306
+ test("describes every entry with the same closed capability vocabulary", () => {
307
+ const vocabulary = MARKETPLACE_CAPABILITIES.map((capability) => capability.id);
308
+ expect(vocabulary).toEqual(["read-only", "session-data", "reads-files", "writes-files", "runs-commands", "local-server", "network-access", "model-calls"]);
309
+ expect(MARKETPLACE_CAPABILITIES.every((capability) => capability.label !== "" && capability.count > 0)).toBe(true);
310
+ expect(MARKETPLACE_CAPABILITIES.reduce((sum, capability) => sum + capability.count, 0)).toBe(
311
+ MARKETPLACE_PLUGINS.reduce((sum, plugin) => sum + plugin.capabilities.length, 0),
312
+ );
313
+ for (const plugin of MARKETPLACE_PLUGINS) {
314
+ expect(plugin.capabilities.length).toBeGreaterThan(0);
315
+ expect(plugin.capabilities.filter((capability) => vocabulary.includes(capability))).toEqual(plugin.capabilities);
316
+ expect(new Set(plugin.capabilities).size).toBe(plugin.capabilities.length);
317
+ // A plugin that says it changes nothing cannot also say it writes, executes, listens, dials out, or spends money.
318
+ if (plugin.capabilities.includes("read-only"))
319
+ expect(
320
+ plugin.capabilities.some((capability) => ["writes-files", "runs-commands", "local-server", "network-access", "model-calls"].includes(capability)),
321
+ ).toBe(false);
322
+ }
323
+ });
324
+
325
+ // The tabs take their label from whichever entry happens to be read first, so two spellings of one category would make the console's own vocabulary depend on file order.
326
+ test("spells each category the same way in every entry", () => {
327
+ const labels = new Map<string, string>();
328
+ for (const plugin of MARKETPLACE_PLUGINS) {
329
+ expect(labels.get(plugin.category.id) ?? plugin.category.label).toBe(plugin.category.label);
330
+ labels.set(plugin.category.id, plugin.category.label);
331
+ }
332
+ expect(labels.size).toBe(MARKETPLACE_CATEGORIES.length);
333
+ });
334
+
335
+ // The ids are what the filter and the URL carry, and the labels are what the reader sees, so a search for either has to find the same plugin.
336
+ test("finds a plugin by a capability id and by its label", () => {
337
+ const byId = searchMarketplace("local-server");
338
+ expect(byId.map((plugin) => plugin.id)).toEqual(["mock-server"]);
339
+ expect(searchMarketplace("监听本地端口").map((plugin) => plugin.id)).toEqual(["mock-server"]);
340
+ expect(searchMarketplace("", "local-server").map((plugin) => plugin.id)).toEqual(["mock-server"]);
507
341
  });
508
342
 
509
343
  test("maps plugin entry points to their published npm package", () => {
@@ -658,6 +492,104 @@ describe("plugin marketplace registry", () => {
658
492
  expect(requests).toBe(3);
659
493
  });
660
494
 
495
+ test("serves the statistics already cached and warms the missing ones in the background", async () => {
496
+ const requests: string[] = [];
497
+ const fetcher = (url: string): Promise<Response> => {
498
+ requests.push(url);
499
+ if (url.startsWith("https://registry.npmjs.org/-/v1/search"))
500
+ return Promise.resolve(
501
+ Response.json({
502
+ objects: [
503
+ {
504
+ package: { name: new URL(url).searchParams.get("text"), date: "2026-08-30T13:14:00.557Z" },
505
+ score: { detail: { quality: 0.9 } },
506
+ },
507
+ ],
508
+ }),
509
+ );
510
+ return Promise.resolve(Response.json({ downloads: 4_200 }));
511
+ };
512
+ const load = createMarketplaceStatisticsLoader({ fetcher, ttlMs: 60_000 });
513
+ const plugin = MARKETPLACE_PLUGINS.find((item) => item.id === "cordis-timer")!;
514
+
515
+ expect(load.readCached([plugin])).toEqual({ ready: false, statistics: new Map() });
516
+ await vi.waitFor(() => expect(requests).toHaveLength(2));
517
+
518
+ expect(load.readCached([plugin])).toEqual({
519
+ ready: true,
520
+ statistics: new Map([["@deepseek-ai/cordis-plugin-timer", { downloads30d: 4_200, quality: 0.9, updatedAt: "2026-08-30T13:14:00.557Z" }]]),
521
+ });
522
+ expect(requests).toHaveLength(2);
523
+ });
524
+
525
+ test("stays ready once a lookup has expired so the catalogue is not reordered back to its unsorted form mid-session", async () => {
526
+ let timestamp = 1_000;
527
+ const fetcher = (url: string): Promise<Response> => {
528
+ if (url.startsWith("https://registry.npmjs.org/-/v1/search"))
529
+ return Promise.resolve(Response.json({ objects: [{ package: { name: "@deepseek-ai/cordis-plugin-timer" }, score: { detail: { quality: 0.5 } } }] }));
530
+ return Promise.resolve(Response.json({ downloads: 10 }));
531
+ };
532
+ const load = createMarketplaceStatisticsLoader({ fetcher, now: () => timestamp, ttlMs: 100 });
533
+ const plugin = MARKETPLACE_PLUGINS.find((item) => item.id === "cordis-timer")!;
534
+
535
+ await load([plugin]);
536
+ timestamp += 101;
537
+
538
+ // The entry is stale and is refreshed in the background, but it has been looked up, so the caller keeps sorting on statistics instead of dropping the whole grid back to catalogue order for one poll.
539
+ const cached = load.readCached([plugin]);
540
+ expect(cached.ready).toBe(true);
541
+ expect(cached.statistics.size).toBe(0);
542
+ });
543
+
544
+ test("keeps the npm fan-out below the configured concurrency instead of asking for every package at once", async () => {
545
+ let active = 0;
546
+ let peak = 0;
547
+ const fetcher = async (): Promise<Response> => {
548
+ active += 1;
549
+ peak = Math.max(peak, active);
550
+ await new Promise((resolve) => setTimeout(resolve, 0));
551
+ active -= 1;
552
+ return Response.json({ objects: [] });
553
+ };
554
+ const base = MARKETPLACE_PLUGINS.find((plugin) => plugin.id === "cordis-timer")!;
555
+ const plugins = Array.from({ length: 12 }, (_, index) => ({ ...base, id: `bulk-${index}`, packageName: `bulk-package-${index}` }));
556
+ const load = createMarketplaceStatisticsLoader({ concurrency: 3, fetcher });
557
+
558
+ await load(plugins);
559
+
560
+ expect(peak).toBe(3);
561
+ });
562
+
563
+ test("backs off further on every consecutive npm failure so an open console stops re-issuing the same lookups", async () => {
564
+ let timestamp = 1_000;
565
+ let requests = 0;
566
+ const fetcher = (): Promise<Response> => {
567
+ requests += 1;
568
+ throw new Error("npm unavailable");
569
+ };
570
+ const load = createMarketplaceStatisticsLoader({ failureMaxTtlMs: 400, failureTtlMs: 100, fetcher, now: () => timestamp });
571
+ const plugin = MARKETPLACE_PLUGINS.find((item) => item.id === "cordis-timer")!;
572
+
573
+ await load([plugin]);
574
+ timestamp += 101;
575
+ await load([plugin]);
576
+ expect(requests).toBe(2);
577
+
578
+ // The second failure doubles the retry window, so the poll that would have retried under a flat window finds the cache still valid.
579
+ timestamp += 101;
580
+ await load([plugin]);
581
+ expect(requests).toBe(2);
582
+
583
+ timestamp += 100;
584
+ await load([plugin]);
585
+ expect(requests).toBe(3);
586
+
587
+ // The window is capped rather than doubling forever, so the package is retried again once the ceiling elapses.
588
+ timestamp += 401;
589
+ await load([plugin]);
590
+ expect(requests).toBe(4);
591
+ });
592
+
661
593
  test("sorts recommendations before pagination using verification, npm quality, downloads and recency", () => {
662
594
  const base = MARKETPLACE_PLUGINS.find((plugin) => plugin.id === "cordis-timer")!;
663
595
  const plugins = [