@hybridlabor-api/aos 4.6.6 → 4.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (503) hide show
  1. package/.agents/agents.md +9 -3
  2. package/.agents/nodes.json +7 -2
  3. package/.agents/state.schema.json +26 -1
  4. package/.agents/vendor-manifest.json +56 -0
  5. package/.agents/workflows/startcycle-graph.md +2 -2
  6. package/.claude/agents/architect.md +7 -2
  7. package/.claude/agents/security-reviewer.md +1 -1
  8. package/.claude/agents/techlead.md +2 -0
  9. package/.claude/hooks/memb-inject.mjs +257 -135
  10. package/.claude/hooks/trail-relay.mjs +18 -0
  11. package/.claude/settings.json +70 -0
  12. package/.claude/workflows/startcycle-dispatch.mjs +203 -17
  13. package/.opencode/agents/architect.md +7 -2
  14. package/.opencode/agents/techlead.md +2 -0
  15. package/.opencode/plugins/bdb-aos.js +75 -0
  16. package/THIRD_PARTY_NOTICES.md +57 -1
  17. package/bin/aos-doctor.mjs +366 -0
  18. package/bin/aos-store.mjs +167 -0
  19. package/bin/aos-uninstall.mjs +55 -1
  20. package/docs/AUDIT_BRIEF_ECC_STORE.md +122 -0
  21. package/docs/PLAN_AOS_STORE_PHASE1.md +190 -0
  22. package/docs/handover/agenttrail-for-ao.md +58 -0
  23. package/docs/handover/deja-for-ao.md +51 -0
  24. package/installer.js +182 -38
  25. package/lib/aos-archify-contract.mjs +277 -0
  26. package/lib/ecc-store-index.json +1 -0
  27. package/mcp_config.json +8 -0
  28. package/mcps/mcsc/README.md +24 -0
  29. package/mcps/mcsc/package-lock.json +1234 -0
  30. package/mcps/mcsc/package.json +14 -0
  31. package/mcps/mcsc/packages/core/bin/mcsc.js +162 -0
  32. package/mcps/mcsc/packages/core/rulebook.default.yaml +49 -0
  33. package/mcps/mcsc/packages/core/schema/rulebook.schema.json +56 -0
  34. package/mcps/mcsc/packages/core/src/adapters/agy.js +107 -0
  35. package/mcps/mcsc/packages/core/src/adapters/codex.js +179 -0
  36. package/mcps/mcsc/packages/core/src/adapters/native.js +14 -0
  37. package/mcps/mcsc/packages/core/src/adapters/opencode.js +183 -0
  38. package/mcps/mcsc/packages/core/src/adapters/types.js +21 -0
  39. package/mcps/mcsc/packages/core/src/capabilities/buildOfferTable.js +34 -0
  40. package/mcps/mcsc/packages/core/src/capabilities/registry.js +99 -0
  41. package/mcps/mcsc/packages/core/src/capabilities/types.js +24 -0
  42. package/mcps/mcsc/packages/core/src/detect/cache.js +47 -0
  43. package/mcps/mcsc/packages/core/src/detect/inventory.js +73 -0
  44. package/mcps/mcsc/packages/core/src/detect/probes.js +158 -0
  45. package/mcps/mcsc/packages/core/src/detect/types.js +26 -0
  46. package/mcps/mcsc/packages/core/src/rulebook/load.js +53 -0
  47. package/mcps/mcsc/packages/core/src/rulebook/resolve.js +227 -0
  48. package/mcps/mcsc/packages/core/src/rulebook/rulebook.types.js +89 -0
  49. package/mcps/mcsc/packages/core/src/trail.js +17 -0
  50. package/mcps/mcsc/packages/mcp/server.js +302 -0
  51. package/mcps/mcsc/server.js +2 -0
  52. package/package.json +8 -2
  53. package/scripts/build-ecc-store-index.mjs +147 -0
  54. package/skills/basic/bdbmediastorm/SKILL.md +1 -1
  55. package/skills/basic/godmode-ui-ux/SKILL.md +2 -2
  56. package/skills/basic/godmode-ui-ux/references/anti-slop-rules.md +44 -40
  57. package/skills/basic/godmode-ui-ux/references/taste-archetypes.md +49 -0
  58. package/skills/basic/startcycle/SKILL.md +7 -0
  59. package/skills/basic/startcycle-graph/SKILL.md +25 -0
  60. package/skills/basic/startcycle-graph-user/SKILL.md +3 -0
  61. package/skills/basic/teamwork-preview/SKILL.md +2 -0
  62. package/skills/bdbrainstorm/SKILL.md +1 -0
  63. package/skills/global_config/agenttrail/LICENSE +21 -0
  64. package/skills/global_config/agenttrail/SKILL.md +48 -0
  65. package/skills/global_config/agenttrail/bin/agenttrail.mjs +1113 -0
  66. package/skills/global_config/agenttrail/public/index.html +662 -0
  67. package/skills/global_config/aos-project-init/SKILL.md +25 -5
  68. package/skills/global_config/aos-setup/SKILL.md +34 -1
  69. package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +115 -1
  70. package/skills/global_config/archify/LICENSE +22 -0
  71. package/skills/global_config/archify/SKILL.md +140 -0
  72. package/skills/global_config/archify/THIRD_PARTY_NOTICES.md +69 -0
  73. package/skills/global_config/archify/assets/JetBrainsMono-OFL.txt +93 -0
  74. package/skills/global_config/archify/assets/template.html +14937 -0
  75. package/skills/global_config/archify/bin/archify.mjs +2139 -0
  76. package/skills/global_config/archify/bin/open-artifact.mjs +86 -0
  77. package/skills/global_config/archify/bin/preview.mjs +653 -0
  78. package/skills/global_config/archify/bin/visual-check.mjs +829 -0
  79. package/skills/global_config/archify/brand-marks/README.md +31 -0
  80. package/skills/global_config/archify/brand-marks/catalog.json +131 -0
  81. package/skills/global_config/archify/delta/architecture-delta.mjs +1232 -0
  82. package/skills/global_config/archify/examples/agent-run.lifecycle.json +60 -0
  83. package/skills/global_config/archify/examples/agent-tool-call.workflow.json +94 -0
  84. package/skills/global_config/archify/examples/async-job-roundtrip.sequence.json +61 -0
  85. package/skills/global_config/archify/examples/brand-aware-delivery.architecture.json +47 -0
  86. package/skills/global_config/archify/examples/cache-miss-request.sequence.json +82 -0
  87. package/skills/global_config/archify/examples/checkout-platform.base.architecture.json +31 -0
  88. package/skills/global_config/archify/examples/checkout-platform.head.architecture.json +31 -0
  89. package/skills/global_config/archify/examples/dataflow-product-analytics.html +15048 -0
  90. package/skills/global_config/archify/examples/deployment-release.lifecycle.json +49 -0
  91. package/skills/global_config/archify/examples/event-stream.dataflow.json +57 -0
  92. package/skills/global_config/archify/examples/incident-response.workflow.json +64 -0
  93. package/skills/global_config/archify/examples/lifecycle-agent-run.html +14983 -0
  94. package/skills/global_config/archify/examples/product-analytics.dataflow.json +76 -0
  95. package/skills/global_config/archify/examples/production-deployment.architecture.json +71 -0
  96. package/skills/global_config/archify/examples/release-delivery.workflow.json +62 -0
  97. package/skills/global_config/archify/examples/sequence-cache-miss-request.html +15063 -0
  98. package/skills/global_config/archify/examples/web-app-rendered.html +15012 -0
  99. package/skills/global_config/archify/examples/web-app.architecture.json +46 -0
  100. package/skills/global_config/archify/examples/workflow-agent-tool-call-rendered.html +15054 -0
  101. package/skills/global_config/archify/migrations/workflow-v2.mjs +279 -0
  102. package/skills/global_config/archify/package.json +39 -0
  103. package/skills/global_config/archify/recipes/scenarios.mjs +391 -0
  104. package/skills/global_config/archify/references/authoring-contract.md +247 -0
  105. package/skills/global_config/archify/references/brand-marks.md +65 -0
  106. package/skills/global_config/archify/references/delivery-contract.md +138 -0
  107. package/skills/global_config/archify/references/viewer-runtime.md +45 -0
  108. package/skills/global_config/archify/renderers/architecture/grid.mjs +62 -0
  109. package/skills/global_config/archify/renderers/architecture/render-architecture.mjs +1078 -0
  110. package/skills/global_config/archify/renderers/dataflow/README.md +104 -0
  111. package/skills/global_config/archify/renderers/dataflow/render-dataflow.mjs +483 -0
  112. package/skills/global_config/archify/renderers/lifecycle/README.md +115 -0
  113. package/skills/global_config/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
  114. package/skills/global_config/archify/renderers/sequence/README.md +114 -0
  115. package/skills/global_config/archify/renderers/sequence/render-sequence.mjs +464 -0
  116. package/skills/global_config/archify/renderers/shared/brand-marks.mjs +563 -0
  117. package/skills/global_config/archify/renderers/shared/cli.mjs +218 -0
  118. package/skills/global_config/archify/renderers/shared/desktop-readability.mjs +26 -0
  119. package/skills/global_config/archify/renderers/shared/diagnostics.mjs +160 -0
  120. package/skills/global_config/archify/renderers/shared/engineering-profiles.mjs +157 -0
  121. package/skills/global_config/archify/renderers/shared/generated-brand-marks.mjs +2003 -0
  122. package/skills/global_config/archify/renderers/shared/generated-validators.mjs +13 -0
  123. package/skills/global_config/archify/renderers/shared/geometry.mjs +1423 -0
  124. package/skills/global_config/archify/renderers/shared/i18n.mjs +595 -0
  125. package/skills/global_config/archify/renderers/shared/layout-report.mjs +40 -0
  126. package/skills/global_config/archify/renderers/shared/legend.mjs +217 -0
  127. package/skills/global_config/archify/renderers/shared/output-path.mjs +340 -0
  128. package/skills/global_config/archify/renderers/shared/repository-evidence.mjs +239 -0
  129. package/skills/global_config/archify/renderers/shared/repository-location.mjs +58 -0
  130. package/skills/global_config/archify/renderers/shared/text-fit.mjs +49 -0
  131. package/skills/global_config/archify/renderers/shared/utils.mjs +232 -0
  132. package/skills/global_config/archify/renderers/shared/validator.mjs +86 -0
  133. package/skills/global_config/archify/renderers/workflow/README.md +223 -0
  134. package/skills/global_config/archify/renderers/workflow/render-workflow.mjs +35 -0
  135. package/skills/global_config/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
  136. package/skills/global_config/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
  137. package/skills/global_config/archify/schemas/README.md +211 -0
  138. package/skills/global_config/archify/schemas/architecture.schema.json +178 -0
  139. package/skills/global_config/archify/schemas/common.schema.json +115 -0
  140. package/skills/global_config/archify/schemas/dataflow.schema.json +243 -0
  141. package/skills/global_config/archify/schemas/lifecycle.schema.json +266 -0
  142. package/skills/global_config/archify/schemas/sequence.schema.json +223 -0
  143. package/skills/global_config/archify/schemas/workflow.schema.json +428 -0
  144. package/skills/global_config/archify/scripts/check-render-output.mjs +916 -0
  145. package/skills/global_config/archify/scripts/generate-brand-marks.mjs +141 -0
  146. package/skills/global_config/archify/scripts/generate-validators.mjs +66 -0
  147. package/skills/global_config/archify/scripts/render-examples.mjs +26 -0
  148. package/skills/global_config/archify/skill-release.json +10 -0
  149. package/skills/global_config/ask-tim/SKILL.md +10 -0
  150. package/skills/global_config/bdb-security-audit/SKILL.md +109 -0
  151. package/skills/global_config/bdb-security-audit/references/audit-checklists.md +172 -0
  152. package/skills/global_config/bdb-security-audit/references/skylos-guide.md +139 -0
  153. package/skills/global_config/bdb-security-audit/references/xalgorix-bridge.md +110 -0
  154. package/skills/global_config/bdbdesignpro/SKILL.md +4 -4
  155. package/skills/global_config/bdbdesignpro/references/bdb-motion-tokens.md +52 -31
  156. package/skills/global_config/bdbresilience/SKILL.md +10 -0
  157. package/skills/global_config/brag/SKILL.md +179 -0
  158. package/skills/global_config/brag/assets/music/README.md +20 -0
  159. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-1-by-ende-dot-app.music-cues.json +3846 -0
  160. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-1-by-ende-dot-app.music-cues.md +35 -0
  161. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-10-by-ende-dot-app.music-cues.json +1826 -0
  162. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-10-by-ende-dot-app.music-cues.md +35 -0
  163. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-11-by-ende-dot-app.music-cues.json +2266 -0
  164. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-11-by-ende-dot-app.music-cues.md +35 -0
  165. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-12-by-ende-dot-app.music-cues.json +2806 -0
  166. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-12-by-ende-dot-app.music-cues.md +35 -0
  167. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-9-by-ende-dot-app.music-cues.json +2796 -0
  168. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-9-by-ende-dot-app.music-cues.md +35 -0
  169. package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-1-by-ende-dot-app.mp3 +0 -0
  170. package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-10-by-ende-dot-app.mp3 +0 -0
  171. package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-11-by-ende-dot-app.mp3 +0 -0
  172. package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-12-by-ende-dot-app.mp3 +0 -0
  173. package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-9-by-ende-dot-app.mp3 +0 -0
  174. package/skills/global_config/brag/assets/sfx/casino/card-fan-1.ogg +0 -0
  175. package/skills/global_config/brag/assets/sfx/casino/card-fan-2.ogg +0 -0
  176. package/skills/global_config/brag/assets/sfx/casino/card-place-1.ogg +0 -0
  177. package/skills/global_config/brag/assets/sfx/casino/card-place-2.ogg +0 -0
  178. package/skills/global_config/brag/assets/sfx/casino/card-place-3.ogg +0 -0
  179. package/skills/global_config/brag/assets/sfx/casino/card-place-4.ogg +0 -0
  180. package/skills/global_config/brag/assets/sfx/casino/card-shove-1.ogg +0 -0
  181. package/skills/global_config/brag/assets/sfx/casino/card-shove-2.ogg +0 -0
  182. package/skills/global_config/brag/assets/sfx/casino/card-shove-3.ogg +0 -0
  183. package/skills/global_config/brag/assets/sfx/casino/card-shove-4.ogg +0 -0
  184. package/skills/global_config/brag/assets/sfx/casino/card-shuffle.ogg +0 -0
  185. package/skills/global_config/brag/assets/sfx/casino/card-slide-1.ogg +0 -0
  186. package/skills/global_config/brag/assets/sfx/casino/card-slide-2.ogg +0 -0
  187. package/skills/global_config/brag/assets/sfx/casino/card-slide-3.ogg +0 -0
  188. package/skills/global_config/brag/assets/sfx/casino/card-slide-4.ogg +0 -0
  189. package/skills/global_config/brag/assets/sfx/casino/card-slide-5.ogg +0 -0
  190. package/skills/global_config/brag/assets/sfx/casino/card-slide-6.ogg +0 -0
  191. package/skills/global_config/brag/assets/sfx/casino/card-slide-7.ogg +0 -0
  192. package/skills/global_config/brag/assets/sfx/casino/card-slide-8.ogg +0 -0
  193. package/skills/global_config/brag/assets/sfx/casino/cards-pack-open-1.ogg +0 -0
  194. package/skills/global_config/brag/assets/sfx/casino/cards-pack-open-2.ogg +0 -0
  195. package/skills/global_config/brag/assets/sfx/casino/chip-lay-1.ogg +0 -0
  196. package/skills/global_config/brag/assets/sfx/casino/chip-lay-2.ogg +0 -0
  197. package/skills/global_config/brag/assets/sfx/casino/chip-lay-3.ogg +0 -0
  198. package/skills/global_config/brag/assets/sfx/casino/chips-collide-1.ogg +0 -0
  199. package/skills/global_config/brag/assets/sfx/casino/chips-collide-2.ogg +0 -0
  200. package/skills/global_config/brag/assets/sfx/casino/chips-collide-3.ogg +0 -0
  201. package/skills/global_config/brag/assets/sfx/casino/chips-collide-4.ogg +0 -0
  202. package/skills/global_config/brag/assets/sfx/casino/chips-handle-1.ogg +0 -0
  203. package/skills/global_config/brag/assets/sfx/casino/chips-handle-2.ogg +0 -0
  204. package/skills/global_config/brag/assets/sfx/casino/chips-handle-3.ogg +0 -0
  205. package/skills/global_config/brag/assets/sfx/casino/chips-handle-4.ogg +0 -0
  206. package/skills/global_config/brag/assets/sfx/casino/chips-handle-6.ogg +0 -0
  207. package/skills/global_config/brag/assets/sfx/casino/chips-stack-1.ogg +0 -0
  208. package/skills/global_config/brag/assets/sfx/casino/chips-stack-2.ogg +0 -0
  209. package/skills/global_config/brag/assets/sfx/casino/chips-stack-3.ogg +0 -0
  210. package/skills/global_config/brag/assets/sfx/casino/chips-stack-4.ogg +0 -0
  211. package/skills/global_config/brag/assets/sfx/casino/chips-stack-5.ogg +0 -0
  212. package/skills/global_config/brag/assets/sfx/casino/chips-stack-6.ogg +0 -0
  213. package/skills/global_config/brag/assets/sfx/casino/dice-grab-1.ogg +0 -0
  214. package/skills/global_config/brag/assets/sfx/casino/dice-grab-2.ogg +0 -0
  215. package/skills/global_config/brag/assets/sfx/casino/dice-shake-1.ogg +0 -0
  216. package/skills/global_config/brag/assets/sfx/casino/dice-shake-2.ogg +0 -0
  217. package/skills/global_config/brag/assets/sfx/casino/dice-shake-3.ogg +0 -0
  218. package/skills/global_config/brag/assets/sfx/casino/dice-throw-1.ogg +0 -0
  219. package/skills/global_config/brag/assets/sfx/casino/dice-throw-2.ogg +0 -0
  220. package/skills/global_config/brag/assets/sfx/casino/dice-throw-3.ogg +0 -0
  221. package/skills/global_config/brag/assets/sfx/casino/die-throw-1.ogg +0 -0
  222. package/skills/global_config/brag/assets/sfx/casino/die-throw-2.ogg +0 -0
  223. package/skills/global_config/brag/assets/sfx/casino/die-throw-3.ogg +0 -0
  224. package/skills/global_config/brag/assets/sfx/casino/die-throw-4.ogg +0 -0
  225. package/skills/global_config/brag/assets/sfx/impact/footstep_carpet_000.ogg +0 -0
  226. package/skills/global_config/brag/assets/sfx/impact/footstep_carpet_003.ogg +0 -0
  227. package/skills/global_config/brag/assets/sfx/impact/footstep_carpet_004.ogg +0 -0
  228. package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_000.ogg +0 -0
  229. package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_001.ogg +0 -0
  230. package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_002.ogg +0 -0
  231. package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_003.ogg +0 -0
  232. package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_004.ogg +0 -0
  233. package/skills/global_config/brag/assets/sfx/impact/footstep_grass_000.ogg +0 -0
  234. package/skills/global_config/brag/assets/sfx/impact/footstep_grass_001.ogg +0 -0
  235. package/skills/global_config/brag/assets/sfx/impact/footstep_grass_002.ogg +0 -0
  236. package/skills/global_config/brag/assets/sfx/impact/footstep_grass_003.ogg +0 -0
  237. package/skills/global_config/brag/assets/sfx/impact/footstep_grass_004.ogg +0 -0
  238. package/skills/global_config/brag/assets/sfx/impact/footstep_snow_000.ogg +0 -0
  239. package/skills/global_config/brag/assets/sfx/impact/footstep_snow_001.ogg +0 -0
  240. package/skills/global_config/brag/assets/sfx/impact/footstep_snow_002.ogg +0 -0
  241. package/skills/global_config/brag/assets/sfx/impact/footstep_snow_003.ogg +0 -0
  242. package/skills/global_config/brag/assets/sfx/impact/footstep_snow_004.ogg +0 -0
  243. package/skills/global_config/brag/assets/sfx/impact/footstep_wood_000.ogg +0 -0
  244. package/skills/global_config/brag/assets/sfx/impact/footstep_wood_001.ogg +0 -0
  245. package/skills/global_config/brag/assets/sfx/impact/footstep_wood_002.ogg +0 -0
  246. package/skills/global_config/brag/assets/sfx/impact/footstep_wood_003.ogg +0 -0
  247. package/skills/global_config/brag/assets/sfx/impact/footstep_wood_004.ogg +0 -0
  248. package/skills/global_config/brag/assets/sfx/impact/impactBell_heavy_000.ogg +0 -0
  249. package/skills/global_config/brag/assets/sfx/impact/impactBell_heavy_003.ogg +0 -0
  250. package/skills/global_config/brag/assets/sfx/impact/impactBell_heavy_004.ogg +0 -0
  251. package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_000.ogg +0 -0
  252. package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_001.ogg +0 -0
  253. package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_002.ogg +0 -0
  254. package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_003.ogg +0 -0
  255. package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_004.ogg +0 -0
  256. package/skills/global_config/brag/assets/sfx/impact/impactGlass_heavy_002.ogg +0 -0
  257. package/skills/global_config/brag/assets/sfx/impact/impactGlass_light_001.ogg +0 -0
  258. package/skills/global_config/brag/assets/sfx/impact/impactGlass_light_002.ogg +0 -0
  259. package/skills/global_config/brag/assets/sfx/impact/impactGlass_light_003.ogg +0 -0
  260. package/skills/global_config/brag/assets/sfx/impact/impactGlass_medium_000.ogg +0 -0
  261. package/skills/global_config/brag/assets/sfx/impact/impactGlass_medium_002.ogg +0 -0
  262. package/skills/global_config/brag/assets/sfx/impact/impactGlass_medium_004.ogg +0 -0
  263. package/skills/global_config/brag/assets/sfx/impact/impactMetal_heavy_000.ogg +0 -0
  264. package/skills/global_config/brag/assets/sfx/impact/impactMetal_heavy_002.ogg +0 -0
  265. package/skills/global_config/brag/assets/sfx/impact/impactMetal_heavy_004.ogg +0 -0
  266. package/skills/global_config/brag/assets/sfx/impact/impactMetal_light_002.ogg +0 -0
  267. package/skills/global_config/brag/assets/sfx/impact/impactMetal_light_003.ogg +0 -0
  268. package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_000.ogg +0 -0
  269. package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_001.ogg +0 -0
  270. package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_002.ogg +0 -0
  271. package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_003.ogg +0 -0
  272. package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_004.ogg +0 -0
  273. package/skills/global_config/brag/assets/sfx/impact/impactMining_001.ogg +0 -0
  274. package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_000.ogg +0 -0
  275. package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_001.ogg +0 -0
  276. package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_002.ogg +0 -0
  277. package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_003.ogg +0 -0
  278. package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_004.ogg +0 -0
  279. package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_000.ogg +0 -0
  280. package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_001.ogg +0 -0
  281. package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_002.ogg +0 -0
  282. package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_003.ogg +0 -0
  283. package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_004.ogg +0 -0
  284. package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_000.ogg +0 -0
  285. package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_001.ogg +0 -0
  286. package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_002.ogg +0 -0
  287. package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_003.ogg +0 -0
  288. package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_004.ogg +0 -0
  289. package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_000.ogg +0 -0
  290. package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_001.ogg +0 -0
  291. package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_002.ogg +0 -0
  292. package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_003.ogg +0 -0
  293. package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_004.ogg +0 -0
  294. package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_000.ogg +0 -0
  295. package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_001.ogg +0 -0
  296. package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_002.ogg +0 -0
  297. package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_003.ogg +0 -0
  298. package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_004.ogg +0 -0
  299. package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_000.ogg +0 -0
  300. package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_001.ogg +0 -0
  301. package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_002.ogg +0 -0
  302. package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_003.ogg +0 -0
  303. package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_004.ogg +0 -0
  304. package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_000.ogg +0 -0
  305. package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_001.ogg +0 -0
  306. package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_002.ogg +0 -0
  307. package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_003.ogg +0 -0
  308. package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_004.ogg +0 -0
  309. package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_000.ogg +0 -0
  310. package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_001.ogg +0 -0
  311. package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_002.ogg +0 -0
  312. package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_003.ogg +0 -0
  313. package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_004.ogg +0 -0
  314. package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_000.ogg +0 -0
  315. package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_001.ogg +0 -0
  316. package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_002.ogg +0 -0
  317. package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_003.ogg +0 -0
  318. package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_004.ogg +0 -0
  319. package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_000.ogg +0 -0
  320. package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_001.ogg +0 -0
  321. package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_002.ogg +0 -0
  322. package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_003.ogg +0 -0
  323. package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_004.ogg +0 -0
  324. package/skills/global_config/brag/assets/sfx/impact/impactWood_light_000.ogg +0 -0
  325. package/skills/global_config/brag/assets/sfx/impact/impactWood_light_001.ogg +0 -0
  326. package/skills/global_config/brag/assets/sfx/impact/impactWood_light_002.ogg +0 -0
  327. package/skills/global_config/brag/assets/sfx/impact/impactWood_light_003.ogg +0 -0
  328. package/skills/global_config/brag/assets/sfx/impact/impactWood_light_004.ogg +0 -0
  329. package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_000.ogg +0 -0
  330. package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_001.ogg +0 -0
  331. package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_002.ogg +0 -0
  332. package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_003.ogg +0 -0
  333. package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_004.ogg +0 -0
  334. package/skills/global_config/brag/assets/sfx/interface/bong_001.ogg +0 -0
  335. package/skills/global_config/brag/assets/sfx/interface/click_001.ogg +0 -0
  336. package/skills/global_config/brag/assets/sfx/interface/click_002.ogg +0 -0
  337. package/skills/global_config/brag/assets/sfx/interface/click_003.ogg +0 -0
  338. package/skills/global_config/brag/assets/sfx/interface/click_004.ogg +0 -0
  339. package/skills/global_config/brag/assets/sfx/interface/click_005.ogg +0 -0
  340. package/skills/global_config/brag/assets/sfx/interface/drop_001.ogg +0 -0
  341. package/skills/global_config/brag/assets/sfx/interface/drop_002.ogg +0 -0
  342. package/skills/global_config/brag/assets/sfx/interface/drop_003.ogg +0 -0
  343. package/skills/global_config/brag/assets/sfx/interface/error_005.ogg +0 -0
  344. package/skills/global_config/brag/assets/sfx/interface/error_006.ogg +0 -0
  345. package/skills/global_config/brag/assets/sfx/interface/glitch_002.ogg +0 -0
  346. package/skills/global_config/brag/assets/sfx/interface/glitch_004.ogg +0 -0
  347. package/skills/global_config/brag/assets/sfx/interface/select_008.ogg +0 -0
  348. package/skills/global_config/brag/assets/sfx/interface/switch_001.ogg +0 -0
  349. package/skills/global_config/brag/assets/sfx/interface/switch_002.ogg +0 -0
  350. package/skills/global_config/brag/assets/sfx/interface/switch_004.ogg +0 -0
  351. package/skills/global_config/brag/assets/sfx/interface/switch_005.ogg +0 -0
  352. package/skills/global_config/brag/assets/sfx/interface/switch_006.ogg +0 -0
  353. package/skills/global_config/brag/assets/sfx/interface/switch_007.ogg +0 -0
  354. package/skills/global_config/brag/assets/sfx/keyboard/keypress-001.wav +0 -0
  355. package/skills/global_config/brag/assets/sfx/keyboard/keypress-002.wav +0 -0
  356. package/skills/global_config/brag/assets/sfx/keyboard/keypress-003.wav +0 -0
  357. package/skills/global_config/brag/assets/sfx/keyboard/keypress-004.wav +0 -0
  358. package/skills/global_config/brag/assets/sfx/keyboard/keypress-005.wav +0 -0
  359. package/skills/global_config/brag/assets/sfx/keyboard/keypress-006.wav +0 -0
  360. package/skills/global_config/brag/assets/sfx/keyboard/keypress-007.wav +0 -0
  361. package/skills/global_config/brag/assets/sfx/keyboard/keypress-008.wav +0 -0
  362. package/skills/global_config/brag/assets/sfx/keyboard/keypress-009.wav +0 -0
  363. package/skills/global_config/brag/assets/sfx/keyboard/keypress-010.wav +0 -0
  364. package/skills/global_config/brag/assets/sfx/keyboard/keypress-011.wav +0 -0
  365. package/skills/global_config/brag/assets/sfx/keyboard/keypress-012.wav +0 -0
  366. package/skills/global_config/brag/assets/sfx/keyboard/keypress-013.wav +0 -0
  367. package/skills/global_config/brag/assets/sfx/keyboard/keypress-014.wav +0 -0
  368. package/skills/global_config/brag/assets/sfx/keyboard/keypress-015.wav +0 -0
  369. package/skills/global_config/brag/assets/sfx/keyboard/keypress-016.wav +0 -0
  370. package/skills/global_config/brag/assets/sfx/keyboard/keypress-017.wav +0 -0
  371. package/skills/global_config/brag/assets/sfx/keyboard/keypress-018.wav +0 -0
  372. package/skills/global_config/brag/assets/sfx/keyboard/keypress-019.wav +0 -0
  373. package/skills/global_config/brag/assets/sfx/keyboard/keypress-020.wav +0 -0
  374. package/skills/global_config/brag/assets/sfx/keyboard/keypress-021.wav +0 -0
  375. package/skills/global_config/brag/assets/sfx/keyboard/keypress-022.wav +0 -0
  376. package/skills/global_config/brag/assets/sfx/keyboard/keypress-023.wav +0 -0
  377. package/skills/global_config/brag/assets/sfx/keyboard/keypress-024.wav +0 -0
  378. package/skills/global_config/brag/assets/sfx/keyboard/keypress-025.wav +0 -0
  379. package/skills/global_config/brag/assets/sfx/keyboard/keypress-026.wav +0 -0
  380. package/skills/global_config/brag/assets/sfx/keyboard/keypress-027.wav +0 -0
  381. package/skills/global_config/brag/assets/sfx/keyboard/keypress-028.wav +0 -0
  382. package/skills/global_config/brag/assets/sfx/keyboard/keypress-029.wav +0 -0
  383. package/skills/global_config/brag/assets/sfx/keyboard/keypress-030.wav +0 -0
  384. package/skills/global_config/brag/assets/sfx/keyboard/keypress-031.wav +0 -0
  385. package/skills/global_config/brag/assets/sfx/keyboard/keypress-032.wav +0 -0
  386. package/skills/global_config/brag/assets/sfx/sfx-analysis.json +15584 -0
  387. package/skills/global_config/brag/assets/sfx/sfx-analysis.md +75 -0
  388. package/skills/global_config/brag/assets/sfx/ui/click1.ogg +0 -0
  389. package/skills/global_config/brag/assets/sfx/ui/click2.ogg +0 -0
  390. package/skills/global_config/brag/assets/sfx/ui/click3.ogg +0 -0
  391. package/skills/global_config/brag/assets/sfx/ui/click4.ogg +0 -0
  392. package/skills/global_config/brag/assets/sfx/ui/click5.ogg +0 -0
  393. package/skills/global_config/brag/assets/sfx/ui/mouseclick1.ogg +0 -0
  394. package/skills/global_config/brag/assets/sfx/ui/rollover1.ogg +0 -0
  395. package/skills/global_config/brag/assets/sfx/ui/rollover2.ogg +0 -0
  396. package/skills/global_config/brag/assets/sfx/ui/rollover4.ogg +0 -0
  397. package/skills/global_config/brag/assets/sfx/ui/rollover5.ogg +0 -0
  398. package/skills/global_config/brag/assets/sfx/ui/switch1.ogg +0 -0
  399. package/skills/global_config/brag/assets/sfx/ui/switch10.ogg +0 -0
  400. package/skills/global_config/brag/assets/sfx/ui/switch11.ogg +0 -0
  401. package/skills/global_config/brag/assets/sfx/ui/switch12.ogg +0 -0
  402. package/skills/global_config/brag/assets/sfx/ui/switch13.ogg +0 -0
  403. package/skills/global_config/brag/assets/sfx/ui/switch14.ogg +0 -0
  404. package/skills/global_config/brag/assets/sfx/ui/switch15.ogg +0 -0
  405. package/skills/global_config/brag/assets/sfx/ui/switch16.ogg +0 -0
  406. package/skills/global_config/brag/assets/sfx/ui/switch17.ogg +0 -0
  407. package/skills/global_config/brag/assets/sfx/ui/switch18.ogg +0 -0
  408. package/skills/global_config/brag/assets/sfx/ui/switch19.ogg +0 -0
  409. package/skills/global_config/brag/assets/sfx/ui/switch2.ogg +0 -0
  410. package/skills/global_config/brag/assets/sfx/ui/switch20.ogg +0 -0
  411. package/skills/global_config/brag/assets/sfx/ui/switch21.ogg +0 -0
  412. package/skills/global_config/brag/assets/sfx/ui/switch22.ogg +0 -0
  413. package/skills/global_config/brag/assets/sfx/ui/switch23.ogg +0 -0
  414. package/skills/global_config/brag/assets/sfx/ui/switch24.ogg +0 -0
  415. package/skills/global_config/brag/assets/sfx/ui/switch25.ogg +0 -0
  416. package/skills/global_config/brag/assets/sfx/ui/switch26.ogg +0 -0
  417. package/skills/global_config/brag/assets/sfx/ui/switch27.ogg +0 -0
  418. package/skills/global_config/brag/assets/sfx/ui/switch28.ogg +0 -0
  419. package/skills/global_config/brag/assets/sfx/ui/switch29.ogg +0 -0
  420. package/skills/global_config/brag/assets/sfx/ui/switch3.ogg +0 -0
  421. package/skills/global_config/brag/assets/sfx/ui/switch30.ogg +0 -0
  422. package/skills/global_config/brag/assets/sfx/ui/switch31.ogg +0 -0
  423. package/skills/global_config/brag/assets/sfx/ui/switch32.ogg +0 -0
  424. package/skills/global_config/brag/assets/sfx/ui/switch33.ogg +0 -0
  425. package/skills/global_config/brag/assets/sfx/ui/switch34.ogg +0 -0
  426. package/skills/global_config/brag/assets/sfx/ui/switch35.ogg +0 -0
  427. package/skills/global_config/brag/assets/sfx/ui/switch36.ogg +0 -0
  428. package/skills/global_config/brag/assets/sfx/ui/switch37.ogg +0 -0
  429. package/skills/global_config/brag/assets/sfx/ui/switch38.ogg +0 -0
  430. package/skills/global_config/brag/assets/sfx/ui/switch4.ogg +0 -0
  431. package/skills/global_config/brag/assets/sfx/ui/switch5.ogg +0 -0
  432. package/skills/global_config/brag/assets/sfx/ui/switch6.ogg +0 -0
  433. package/skills/global_config/brag/assets/sfx/ui/switch7.ogg +0 -0
  434. package/skills/global_config/brag/assets/sfx/ui/switch8.ogg +0 -0
  435. package/skills/global_config/brag/assets/sfx/ui/switch9.ogg +0 -0
  436. package/skills/global_config/brag/references/audio.md +307 -0
  437. package/skills/global_config/brag/references/step-1-inspect.md +133 -0
  438. package/skills/global_config/brag/references/step-2-plan.md +234 -0
  439. package/skills/global_config/brag/references/step-3-compose.md +210 -0
  440. package/skills/global_config/brag/references/step-4-deliver.md +168 -0
  441. package/skills/global_config/brag/references/tones.md +231 -0
  442. package/skills/global_config/brag/scripts/analyze_music_cues.py +309 -0
  443. package/skills/global_config/brag/scripts/pyproject.toml +14 -0
  444. package/skills/global_config/brag/scripts/uv.lock +819 -0
  445. package/skills/global_config/deja-memory/SKILL.md +42 -0
  446. package/skills/global_config/editable-design/LICENSE +202 -0
  447. package/skills/global_config/editable-design/README.md +34 -0
  448. package/skills/global_config/editable-design/SKILL.md +630 -0
  449. package/skills/global_config/editable-design/THIRD_PARTY_NOTICES.md +10 -0
  450. package/skills/global_config/editable-design/agents/openai.yaml +4 -0
  451. package/skills/global_config/editable-design/assets/editor/layer-editor.css +262 -0
  452. package/skills/global_config/editable-design/assets/editor/layer-editor.js +1929 -0
  453. package/skills/global_config/editable-design/assets/poster-starter/README.md +92 -0
  454. package/skills/global_config/editable-design/assets/poster-starter/assets/.gitkeep +0 -0
  455. package/skills/global_config/editable-design/assets/poster-starter/index.html +91 -0
  456. package/skills/global_config/editable-design/assets/poster-starter/poster.json +6 -0
  457. package/skills/global_config/editable-design/assets/poster-starter/reference/.gitkeep +1 -0
  458. package/skills/global_config/editable-design/assets/replay/icons/assets.png +0 -0
  459. package/skills/global_config/editable-design/assets/replay/icons/html.png +0 -0
  460. package/skills/global_config/editable-design/assets/replay/icons/input.png +0 -0
  461. package/skills/global_config/editable-design/assets/replay/icons/layers.png +0 -0
  462. package/skills/global_config/editable-design/assets/replay/icons/plan.png +0 -0
  463. package/skills/global_config/editable-design/assets/replay/icons/reference.png +0 -0
  464. package/skills/global_config/editable-design/assets/replay/icons/review.png +0 -0
  465. package/skills/global_config/editable-design/assets/replay/index.html +59 -0
  466. package/skills/global_config/editable-design/assets/replay/replay-motion.js +410 -0
  467. package/skills/global_config/editable-design/assets/replay/replay.css +380 -0
  468. package/skills/global_config/editable-design/assets/replay/replay.js +374 -0
  469. package/skills/global_config/editable-design/font-kit/package-lock.json +115 -0
  470. package/skills/global_config/editable-design/font-kit/package.json +19 -0
  471. package/skills/global_config/editable-design/pack.sh +20 -0
  472. package/skills/global_config/editable-design/references/asset-architecture.md +72 -0
  473. package/skills/global_config/editable-design/references/editor-pitfalls.md +70 -0
  474. package/skills/global_config/editable-design/references/editor-runtime.md +131 -0
  475. package/skills/global_config/editable-design/references/font-system.md +89 -0
  476. package/skills/global_config/editable-design/references/imagery.md +145 -0
  477. package/skills/global_config/editable-design/references/layout-typography.md +116 -0
  478. package/skills/global_config/editable-design/references/replay-contract.md +169 -0
  479. package/skills/global_config/editable-design/scripts/_browser.mjs +247 -0
  480. package/skills/global_config/editable-design/scripts/bake.mjs +87 -0
  481. package/skills/global_config/editable-design/scripts/build-replay.mjs +316 -0
  482. package/skills/global_config/editable-design/scripts/check-contract.mjs +293 -0
  483. package/skills/global_config/editable-design/scripts/check-fonts.sh +252 -0
  484. package/skills/global_config/editable-design/scripts/check-poster.sh +70 -0
  485. package/skills/global_config/editable-design/scripts/doctor.sh +78 -0
  486. package/skills/global_config/editable-design/scripts/explode.mjs +115 -0
  487. package/skills/global_config/editable-design/scripts/font-kit.mjs +187 -0
  488. package/skills/global_config/editable-design/scripts/import-asset.sh +23 -0
  489. package/skills/global_config/editable-design/scripts/init-poster.sh +64 -0
  490. package/skills/global_config/editable-design/scripts/install-font-kit.sh +13 -0
  491. package/skills/global_config/editable-design/scripts/package-lock.json +334 -0
  492. package/skills/global_config/editable-design/scripts/package.json +14 -0
  493. package/skills/global_config/editable-design/scripts/remove-chroma-key.py +201 -0
  494. package/skills/global_config/editable-design/scripts/render-poster.sh +202 -0
  495. package/skills/global_config/editable-design/scripts/trace.sh +159 -0
  496. package/skills/global_config/editable-design/scripts/verify-replay.mjs +97 -0
  497. package/skills/global_config/editable-design/scripts/verify.mjs +782 -0
  498. package/skills/global_config/editable-design/scripts/wire-editor.mjs +104 -0
  499. package/skills/global_config/editable-design/tests/fixtures/small-explode/index.html +86 -0
  500. package/skills/global_config/mcsc/SKILL.md +60 -0
  501. package/skills/global_config/plan-canvas/SKILL.md +8 -0
  502. package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/server.js +31 -6
  503. package/skills/global_config/plan-canvas/scripts/plan-canvas.js +4 -2
@@ -0,0 +1,183 @@
1
+ import { spawn } from 'node:child_process';
2
+ import path from 'node:path';
3
+ import { emitTrail } from '../trail.js';
4
+
5
+ const MAX_OUTPUT = 1024 * 1024 * 50; // 50MB, mirrors the old execFile maxBuffer
6
+
7
+ /**
8
+ * CliAdapter shelling out to `opencode run --auto --format json [--model <model>] <prompt>`.
9
+ * Optional `req.variant` is passed through as `--variant <variant>` (model reasoning effort).
10
+ * Reads stdout line by line: assistant text parts are collected and joined as
11
+ * `output`; tool events are forwarded to the live map as PreToolUse/PostToolUse.
12
+ *
13
+ * @param {import('../types.js').DelegationRequest} req
14
+ * @returns {Promise<{ exit: number; output: string; attestation: { kind: 'unavailable'; } }>}
15
+ */
16
+ export async function delegate(req) {
17
+ const cwd = req.cwd || process.cwd();
18
+ const trailEvent = {
19
+ session_id: `mcsc-opencode-${process.pid}-${Date.now()}`,
20
+ cwd,
21
+ agent:
22
+ typeof req.label === 'string' && req.label.length > 0
23
+ ? `opencode:${req.label}`
24
+ : 'opencode',
25
+ };
26
+ emitTrail({ ...trailEvent, hook_event_name: 'SessionStart' });
27
+
28
+ const env = { ...process.env, MCSC_CALLER: 'opencode' };
29
+ const args = ['run', '--auto', '--format', 'json'];
30
+ if (req.model) args.push('--model', req.model);
31
+ if (req.variant) args.push('--variant', String(req.variant));
32
+ args.push(req.prompt);
33
+
34
+ const child = spawn('opencode', args, {
35
+ cwd: req.cwd,
36
+ env,
37
+ stdio: ['ignore', 'pipe', 'pipe'],
38
+ });
39
+
40
+ return new Promise((resolve) => {
41
+ const textParts = [];
42
+ let stdoutBuf = '';
43
+ let stderrBuf = '';
44
+ let stdoutBytes = 0;
45
+ let stderrBytes = 0;
46
+ let overflowed = false;
47
+ let aborted = false;
48
+ let settled = false;
49
+
50
+ const onAbort = () => {
51
+ aborted = true;
52
+ child.kill('SIGKILL');
53
+ };
54
+ if (req.signal) {
55
+ if (req.signal.aborted) onAbort();
56
+ else req.signal.addEventListener('abort', onAbort, { once: true });
57
+ }
58
+
59
+ const finalize = (result) => {
60
+ if (settled) return;
61
+ settled = true;
62
+ if (req.signal) req.signal.removeEventListener('abort', onAbort);
63
+ emitTrail({ ...trailEvent, hook_event_name: 'SessionEnd' });
64
+ resolve(result);
65
+ };
66
+
67
+ const buildToolInput = (input) => {
68
+ const toolInput = {};
69
+ if (!input || typeof input !== 'object') return toolInput;
70
+ const rawPath = input.filePath || input.file_path || input.path || input.file;
71
+ if (typeof rawPath === 'string' && rawPath.length > 0) {
72
+ toolInput.file_path = path.isAbsolute(rawPath)
73
+ ? rawPath
74
+ : path.resolve(cwd, rawPath);
75
+ }
76
+ const rawCommand = input.command || input.cmd;
77
+ if (typeof rawCommand === 'string' && rawCommand.length > 0) {
78
+ toolInput.command = rawCommand;
79
+ }
80
+ return toolInput;
81
+ };
82
+
83
+ const handleLine = (line) => {
84
+ if (!line) return;
85
+ let evt;
86
+ try {
87
+ evt = JSON.parse(line);
88
+ } catch {
89
+ return; // Not valid JSON — ignore.
90
+ }
91
+ if (!evt || typeof evt !== 'object') return;
92
+ const part = evt.part;
93
+ if (!part || typeof part !== 'object') return;
94
+
95
+ if (evt.type === 'text') {
96
+ if (typeof part.text === 'string' && part.text.length > 0) {
97
+ textParts.push(part.text);
98
+ }
99
+ return;
100
+ }
101
+
102
+ if (
103
+ evt.type === 'tool_use' &&
104
+ typeof part.tool === 'string' &&
105
+ part.tool.length > 0
106
+ ) {
107
+ const state = part.state || {};
108
+ const finished = state.status === 'completed' || state.status === 'error';
109
+ emitTrail({
110
+ ...trailEvent,
111
+ hook_event_name: finished ? 'PostToolUse' : 'PreToolUse',
112
+ tool_name: part.tool.charAt(0).toUpperCase() + part.tool.slice(1),
113
+ tool_input: buildToolInput(state.input),
114
+ });
115
+ }
116
+ };
117
+
118
+ child.stdout.setEncoding('utf8');
119
+ child.stdout.on('data', (chunk) => {
120
+ stdoutBytes += Buffer.byteLength(chunk);
121
+ if (stdoutBytes > MAX_OUTPUT) {
122
+ if (!overflowed) {
123
+ overflowed = true;
124
+ child.kill('SIGKILL');
125
+ }
126
+ return;
127
+ }
128
+ stdoutBuf += chunk;
129
+ let idx;
130
+ while ((idx = stdoutBuf.indexOf('\n')) !== -1) {
131
+ const line = stdoutBuf.slice(0, idx).trim();
132
+ stdoutBuf = stdoutBuf.slice(idx + 1);
133
+ handleLine(line);
134
+ }
135
+ });
136
+
137
+ child.stderr.setEncoding('utf8');
138
+ child.stderr.on('data', (chunk) => {
139
+ stderrBytes += Buffer.byteLength(chunk);
140
+ if (stderrBytes > MAX_OUTPUT) return; // cap stderr, never fail on it
141
+ stderrBuf += chunk;
142
+ });
143
+
144
+ child.on('error', (err) => {
145
+ finalize({
146
+ exit: 1,
147
+ output: (stderrBuf || err.message || '').trim(),
148
+ attestation: { kind: 'unavailable' },
149
+ });
150
+ });
151
+
152
+ child.on('close', (code) => {
153
+ const rest = stdoutBuf.trim();
154
+ if (rest) handleLine(rest); // flush a trailing line without newline
155
+ if (aborted) {
156
+ finalize({
157
+ exit: 1,
158
+ output: 'Cancelled by orchestrator',
159
+ attestation: { kind: 'unavailable' },
160
+ });
161
+ return;
162
+ }
163
+ if (overflowed) {
164
+ finalize({
165
+ exit: 1,
166
+ output: 'stdout maxBuffer length exceeded',
167
+ attestation: { kind: 'unavailable' },
168
+ });
169
+ return;
170
+ }
171
+ if (code === 0) {
172
+ const output = textParts.length > 0 ? textParts.join('\n') : stderrBuf;
173
+ finalize({ exit: 0, output, attestation: { kind: 'unavailable' } });
174
+ return;
175
+ }
176
+ finalize({
177
+ exit: 1,
178
+ output: (stderrBuf || `opencode exited with code ${code}`).trim(),
179
+ attestation: { kind: 'unavailable' },
180
+ });
181
+ });
182
+ });
183
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @typedef {Object} DelegationRequest
3
+ * @property {string} taskType
4
+ * @property {string} prompt
5
+ * @property {string} model
6
+ * @property {string} cwd
7
+ * @property {string} [variant] Optional model variant (reasoning effort) passed to `opencode run --variant`.
8
+ */
9
+
10
+ /**
11
+ * @typedef {Object} DelegationResult
12
+ * @property {number} exit
13
+ * @property {string} output
14
+ * @property {{
15
+ * kind: 'confirmed' | 'mismatch' | 'unavailable',
16
+ * modelId?: string,
17
+ * sessionRef?: string,
18
+ * requested?: string,
19
+ * actual?: string
20
+ * }} attestation
21
+ */
@@ -0,0 +1,34 @@
1
+ import { resolveOffer } from './registry.js';
2
+
3
+ /**
4
+ * @param {Array<any>} rules
5
+ * @param {Map<import('./types.js').CliId, any>} inventorySnapshot
6
+ * @param {number} now
7
+ * @returns {Promise<Object>} offerTable
8
+ */
9
+ export async function buildOfferTable(rules, inventorySnapshot, now) {
10
+ const offerTable = {};
11
+
12
+ for (const rule of rules) {
13
+ if (!rule.candidates) continue;
14
+ const tier = rule.id;
15
+
16
+ for (const candidate of rule.candidates) {
17
+ const cliId = candidate.cli;
18
+ if (cliId === 'native') continue;
19
+
20
+ const health = inventorySnapshot.get(cliId);
21
+ if (!health || (health.status !== 'ready' && health.status !== 'degraded')) continue;
22
+
23
+ const offer = await resolveOffer(cliId, tier, now);
24
+ if (offer) {
25
+ if (!offerTable[cliId]) {
26
+ offerTable[cliId] = {};
27
+ }
28
+ offerTable[cliId][rule.id] = offer;
29
+ }
30
+ }
31
+ }
32
+
33
+ return offerTable;
34
+ }
@@ -0,0 +1,99 @@
1
+ import { execFile } from 'child_process';
2
+ import { promisify } from 'util';
3
+
4
+ const execFileAsync = promisify(execFile);
5
+
6
+ /**
7
+ * @param {import('./types.js').CliId} cliId
8
+ * @param {import('./types.js').Tier} tier
9
+ * @param {number} now
10
+ * @returns {Promise<import('./types.js').ModelOffer | null>}
11
+ */
12
+ export async function resolveOffer(cliId, tier, now) {
13
+ if (cliId === 'agy') {
14
+ try {
15
+ const { stdout } = await execFileAsync('agy', ['models']);
16
+ // Expected output format:
17
+ // Fetching available models...
18
+ // gemini-3.8-flash-high Gemini 3.8 Flash (High)
19
+ const lines = stdout.split('\n').map(l => l.trim()).filter(l => l.length > 0 && !l.startsWith('Fetching'));
20
+ const models = lines.map(l => l.split(/\s+/)[0]);
21
+
22
+ let selectedModel = null;
23
+ if (tier === 'complex-code') {
24
+ const claudes = models.filter(m => m.includes('claude'));
25
+ if (claudes.length > 0) {
26
+ selectedModel = claudes[0];
27
+ } else {
28
+ const proModels = models.filter(m => m.includes('pro'));
29
+ if (proModels.length > 0) {
30
+ selectedModel = proModels[0];
31
+ }
32
+ }
33
+ } else if (['deep-research', 'quick-review', 'media-generation'].includes(tier)) {
34
+ const flashes = models.filter(m => m.includes('flash'));
35
+ if (flashes.length > 0) {
36
+ selectedModel = flashes[0];
37
+ }
38
+ }
39
+
40
+ if (!selectedModel && models.length > 0) {
41
+ selectedModel = models[0];
42
+ }
43
+
44
+ if (selectedModel) {
45
+ return {
46
+ cliId,
47
+ modelId: selectedModel,
48
+ tier,
49
+ resolvedAt: now,
50
+ source: 'live-list'
51
+ };
52
+ }
53
+ return null;
54
+ } catch (e) {
55
+ return null;
56
+ }
57
+ }
58
+
59
+ if (cliId === 'opencode') {
60
+ try {
61
+ const { stdout } = await execFileAsync('opencode', ['models']);
62
+ const lines = stdout.split('\n').map(l => l.trim());
63
+ const opencodeFreeModels = lines.filter(l => l.startsWith('opencode/') && l.toLowerCase().includes('free'));
64
+
65
+ let selectedModel = null;
66
+ if (tier === 'complex-code') {
67
+ selectedModel = opencodeFreeModels.find(m => m.includes('ultra') || m.includes('pro'));
68
+ } else if (['deep-research', 'quick-review', 'media-generation'].includes(tier)) {
69
+ selectedModel = opencodeFreeModels.find(m => m.includes('lightning') || m.includes('flash'));
70
+ }
71
+
72
+ let source = 'live-list';
73
+ if (!selectedModel && opencodeFreeModels.length > 0) {
74
+ // v1 heuristic fallback
75
+ selectedModel = opencodeFreeModels[0];
76
+ source = 'pinned';
77
+ }
78
+
79
+ if (selectedModel) {
80
+ return {
81
+ cliId,
82
+ modelId: selectedModel,
83
+ tier,
84
+ resolvedAt: now,
85
+ source
86
+ };
87
+ }
88
+ return null;
89
+ } catch (e) {
90
+ return null;
91
+ }
92
+ }
93
+
94
+ if (cliId === 'native' || cliId === 'codex') {
95
+ return null;
96
+ }
97
+
98
+ return null;
99
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @typedef {'agy' | 'opencode' | 'codex' | 'native'} CliId
3
+ */
4
+
5
+ /**
6
+ * @typedef {'deep-research' | 'complex-code' | 'quick-review' | 'media-generation'} Tier
7
+ */
8
+
9
+ /**
10
+ * @typedef {Object} ModelOffer
11
+ * @property {CliId} cliId
12
+ * @property {string} modelId
13
+ * @property {Tier} tier
14
+ * @property {number} resolvedAt
15
+ * @property {'live-list' | 'pinned' | 'stale-cache'} source
16
+ */
17
+
18
+ /**
19
+ * @typedef {Object} CapabilityRegistryPort
20
+ * @property {(cliId: CliId, tier: Tier, now: number) => Promise<ModelOffer | null>} resolveOffer
21
+ * @property {(cliId: CliId) => Promise<void>} refresh
22
+ */
23
+
24
+ export {};
@@ -0,0 +1,47 @@
1
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+
5
+ const CACHE_DIR = join(homedir(), '.config', 'mcsc');
6
+ const CACHE_FILE = join(CACHE_DIR, 'capabilities.json');
7
+
8
+ /**
9
+ * @param {string} cliId
10
+ * @returns {Promise<import('./types.js').CliHealth | null>}
11
+ */
12
+ export const getCached = async (cliId) => {
13
+ try {
14
+ const data = JSON.parse(await readFile(CACHE_FILE, 'utf8'));
15
+ if (!data[cliId]) return null;
16
+ const entry = data[cliId];
17
+ const now = Date.now(); // must match setCached's Date.now() — performance.now() is a different clock (process-uptime-relative)
18
+ if (now - entry.timestamp > entry.ttl) {
19
+ delete data[cliId];
20
+ await writeFile(CACHE_FILE, JSON.stringify(data, null, 2));
21
+ return null;
22
+ }
23
+ return entry.health;
24
+ } catch {
25
+ return null;
26
+ }
27
+ };
28
+
29
+ /**
30
+ * @param {string} cliId
31
+ * @param {import('./types.js').CliHealth} health
32
+ * @param {number} ttlMs
33
+ */
34
+ export const setCached = async (cliId, health, ttlMs) => {
35
+ try {
36
+ const data = {};
37
+ try {
38
+ const existing = JSON.parse(await readFile(CACHE_FILE, 'utf8'));
39
+ Object.assign(data, existing);
40
+ } catch {}
41
+ data[cliId] = { health, timestamp: Date.now(), ttl: ttlMs };
42
+ await mkdir(CACHE_DIR, { recursive: true });
43
+ await writeFile(CACHE_FILE, JSON.stringify(data, null, 2));
44
+ } catch {
45
+ // cache write failure is non-fatal
46
+ }
47
+ };
@@ -0,0 +1,73 @@
1
+ import { probes } from './probes.js';
2
+ // CliHealth is a JSDoc-only typedef in ./types.js — reference it via
3
+ // `@typedef {import('./types.js').CliHealth} CliHealth` in comments, never
4
+ // as a real import (there is nothing to import at runtime).
5
+ import { execFile as execFileCb } from 'node:child_process';
6
+ import { stat, readFile } from 'node:fs/promises';
7
+
8
+ /** @param {{cliIds: string[], maxAgeMs: number}} opts */
9
+ export const runInventory = async ({ cliIds, maxAgeMs }) => {
10
+ const cliHealthMap = new Map();
11
+
12
+ const sh = {
13
+ cliId: '',
14
+ execFile: (cmd, args, options) =>
15
+ new Promise((resolve, reject) => {
16
+ execFileCb(cmd, args, options, (error, stdout, stderr) => {
17
+ if (error) reject(error);
18
+ else resolve({ stdout, stderr });
19
+ });
20
+ }),
21
+ stat: (p) => stat(p).then((s) => ({ mtime: s.mtimeMs })),
22
+ readFile: (p) => readFile(p, 'utf8'),
23
+ };
24
+
25
+ for (const cliId of cliIds) {
26
+ sh.cliId = cliId;
27
+ const cliProbes = probes.filter((p) => p.cliId === cliId);
28
+ const probesResults = [];
29
+
30
+ for (const probe of cliProbes) {
31
+ try {
32
+ const result = await probe.run(sh);
33
+ probesResults.push(result.pass ? { pass: true } : { pass: false, evidence: result.evidence, reason: result.reason });
34
+ } catch (e) {
35
+ probesResults.push({ pass: false, evidence: e.message, reason: 'probe-error' });
36
+ }
37
+ }
38
+
39
+ const allPass = probesResults.every((r) => r.pass);
40
+ const hasUnusable = probesResults.some(
41
+ (r) => r.reason === 'not-on-path' || r.reason === 'unauthenticated' || r.reason === 'permissions' || r.reason === 'hangs' || r.reason === 'version-unsupported'
42
+ );
43
+
44
+ let status, binary, version, reason;
45
+
46
+ if (allPass) {
47
+ status = 'ready';
48
+ binary = 'resolved';
49
+ version = 'detected';
50
+ } else if (hasUnusable) {
51
+ status = 'unusable';
52
+ const unusableReason = probesResults.find(
53
+ (r) => r.reason && ['not-on-path', 'unauthenticated', 'permissions', 'hangs', 'version-unsupported'].includes(r.reason)
54
+ )?.reason || 'unknown';
55
+ reason = unusableReason;
56
+ // 'missing' only when the binary itself couldn't be resolved — every
57
+ // other reason (unauthenticated, permissions, hangs, version-unsupported)
58
+ // means the binary IS on PATH, just unusable for some other cause.
59
+ // Collapsing all of these to 'missing' told operators a real, installed
60
+ // CLI "wasn't there" when the actual fix was e.g. `codex login`.
61
+ binary = unusableReason === 'not-on-path' ? 'missing' : 'resolved';
62
+ version = binary === 'missing' ? 'n/a' : 'detected';
63
+ } else {
64
+ status = 'degraded';
65
+ binary = 'resolved';
66
+ version = 'detected';
67
+ }
68
+
69
+ cliHealthMap.set(cliId, { status, binary, version, probes: probesResults, ...(status === 'unusable' ? { reason } : {}) });
70
+ }
71
+
72
+ return cliHealthMap;
73
+ };
@@ -0,0 +1,158 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { stat, readFile } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+
6
+ /**
7
+ * @param {string} cmd
8
+ * @param {string[]} args
9
+ * @param {object} options
10
+ * @returns {Promise<{stdout: string, stderr: string, error: any}>}
11
+ */
12
+ const runExecFile = (cmd, args, options) => {
13
+ return new Promise((resolve, reject) => {
14
+ execFile(cmd, args, options, (error, stdout, stderr) => {
15
+ if (error) reject(error);
16
+ else resolve({ stdout, stderr, error });
17
+ });
18
+ });
19
+ };
20
+
21
+ /** @param {string} path */
22
+ const statPath = (path) => stat(path).then((s) => ({ mtime: s.mtimeMs }));
23
+
24
+ /** @param {string} path */
25
+ const readFilePath = (path) => readFile(path, 'utf8');
26
+
27
+ /**
28
+ * @param {{execFile: (cmd: string, args: string[], options?: object) => Promise<any>,
29
+ * stat: (path: string) => Promise<{mtime: number}>,
30
+ * readFile: (path: string) => Promise<string>}} sh
31
+ * @returns {Promise<{pass: boolean, evidence?: string, reason?: string}>}
32
+ */
33
+ const binaryResolvable = async (sh) => {
34
+ const binaryMap = { agy: 'agy', opencode: 'opencode', codex: 'codex' };
35
+ const name = binaryMap[sh.cliId];
36
+ if (!name) return { pass: false, reason: 'unknown-cli' };
37
+ try {
38
+ const which = await runExecFile('which', [name], {});
39
+ const resolvedPath = which.stdout.trim();
40
+ // realpath does no PATH lookup of its own — it needs the actual path
41
+ // `which` just resolved, not the bare command name.
42
+ await runExecFile('realpath', [resolvedPath], {});
43
+ return { pass: true };
44
+ } catch {
45
+ return { pass: false, evidence: `binary '${name}' not resolvable`, reason: 'not-on-path' };
46
+ }
47
+ };
48
+
49
+ /**
50
+ * @param {{execFile: (cmd: string, args: string[], options?: object) => Promise<any>,
51
+ * readFile: (path: string) => Promise<string>}} sh
52
+ * @returns {Promise<{pass: boolean, evidence?: string, reason?: string}>}
53
+ */
54
+ const authLive = async (sh) => {
55
+ try {
56
+ if (sh.cliId === 'agy') {
57
+ await runExecFile('agy', ['models'], { timeout: 15000 });
58
+ return { pass: true };
59
+ }
60
+ if (sh.cliId === 'opencode') {
61
+ await runExecFile('opencode', ['models'], { timeout: 15000 });
62
+ return { pass: true };
63
+ }
64
+ if (sh.cliId === 'codex') {
65
+ await runExecFile('codex', ['models'], { timeout: 15000 });
66
+ return { pass: true };
67
+ }
68
+ return { pass: false, evidence: 'no auth command for this CLI', reason: 'unauthenticated' };
69
+ } catch (e) {
70
+ return { pass: false, evidence: e.message, reason: 'unauthenticated' };
71
+ }
72
+ };
73
+
74
+ /**
75
+ * @param {{execFile: (cmd: string, args: string[], options?: object) => Promise<any>,
76
+ * stat: (path: string) => Promise<{mtime: number}>,
77
+ * readFile: (path: string) => Promise<string>}} sh
78
+ * @returns {Promise<{pass: boolean, evidence?: string, reason?: string}>}
79
+ */
80
+ const opencodeFsOwnership = async (sh) => {
81
+ const configDirs = [
82
+ join(homedir(), '.config', 'opencode'),
83
+ join(homedir(), '.cache', 'opencode'),
84
+ join(homedir(), '.local', 'state', 'opencode'),
85
+ join(homedir(), '.local', 'share', 'opencode'),
86
+ ];
87
+ for (const dir of configDirs) {
88
+ try {
89
+ await statPath(dir);
90
+ } catch {
91
+ return { pass: false, evidence: `config dir '${dir}' not accessible`, reason: 'permissions' };
92
+ }
93
+ }
94
+ return { pass: true };
95
+ };
96
+
97
+ /**
98
+ * @param {{execFile: (cmd: string, args: string[], options?: object) => Promise<any>,
99
+ * readFile: (path: string) => Promise<string>}} sh
100
+ * @returns {Promise<{pass: boolean, evidence?: string, reason?: string}>}
101
+ */
102
+ const agyMcpHeadlessLatency = async (sh) => {
103
+ const start = Date.now();
104
+ try {
105
+ await runExecFile('agy', ['--print-timeout', '20s', '-p', 'OK'], {});
106
+ const duration = Date.now() - start;
107
+ if (duration > 20000) {
108
+ return { pass: false, evidence: `latency ${duration}ms exceeds 20s budget`, reason: 'degrade' };
109
+ }
110
+ return { pass: true };
111
+ } catch (e) {
112
+ return { pass: false, evidence: e.message, reason: 'degrade' };
113
+ }
114
+ };
115
+
116
+ /**
117
+ * @param {{execFile: (cmd: string, args: string[], options?: object) => Promise<any>,
118
+ * readFile: (path: string) => Promise<string>}} sh
119
+ * @returns {Promise<{pass: boolean, evidence?: string, reason?: string}>}
120
+ */
121
+ const tierFreshness = async (sh) => {
122
+ try {
123
+ if (sh.cliId === 'opencode') {
124
+ await runExecFile('opencode', ['models'], { timeout: 15000 });
125
+ return { pass: true };
126
+ }
127
+ if (sh.cliId === 'agy') {
128
+ await runExecFile('agy', ['models'], { timeout: 15000 });
129
+ return { pass: true };
130
+ }
131
+ if (sh.cliId === 'codex') {
132
+ await runExecFile('codex', ['models'], { timeout: 15000 });
133
+ return { pass: true };
134
+ }
135
+ return { pass: true };
136
+ } catch (e) {
137
+ return { pass: false, evidence: e.message, reason: 'stale-tier' };
138
+ }
139
+ };
140
+
141
+ /**
142
+ * @type {Probe[]}
143
+ */
144
+ export const probes = [
145
+ { id: 'agy.binary.resolvable', cliId: 'agy', severity: 'fatal', timeoutMs: 10000, run: binaryResolvable, remedy: { human: 'Install agy via npm/brew', command: 'which agy', autoFixable: true } },
146
+ { id: 'opencode.binary.resolvable', cliId: 'opencode', severity: 'fatal', timeoutMs: 10000, run: binaryResolvable, remedy: { human: 'Install opencode via npm', command: 'which opencode', autoFixable: true } },
147
+ { id: 'codex.binary.resolvable', cliId: 'codex', severity: 'fatal', timeoutMs: 10000, run: binaryResolvable, remedy: { human: 'Install codex CLI', command: 'which codex', autoFixable: true } },
148
+ { id: 'agy.auth.live', cliId: 'agy', severity: 'fatal', timeoutMs: 15000, run: authLive, remedy: { human: 'Re-authenticate agy', command: 'agy login', autoFixable: false } },
149
+ { id: 'opencode.auth.live', cliId: 'opencode', severity: 'fatal', timeoutMs: 15000, run: authLive, remedy: { human: 'Re-authenticate opencode', command: 'opencode login', autoFixable: false } },
150
+ { id: 'codex.auth.live', cliId: 'codex', severity: 'fatal', timeoutMs: 15000, run: authLive, remedy: { human: 'Authenticate codex', command: 'codex login', autoFixable: false } },
151
+ { id: 'opencode.fs.ownership', cliId: 'opencode', severity: 'fatal', timeoutMs: 10000, run: opencodeFsOwnership, remedy: { human: 'Fix opencode config dir ownership', command: 'chown -R $(whoami):staff ~/.config/opencode', autoFixable: true } },
152
+ { id: 'agy.mcp.headless-latency', cliId: 'agy', severity: 'degrade', timeoutMs: 20000, run: agyMcpHeadlessLatency, remedy: { human: 'Investigate MCP server connectivity', command: 'agy mcp list', autoFixable: false } },
153
+ { id: 'opencode.tier.freshness', cliId: 'opencode', severity: 'degrade', timeoutMs: 15000, run: tierFreshness, remedy: { human: 'Refresh opencode model list', command: 'opencode models', autoFixable: false } },
154
+ { id: 'agy.tier.freshness', cliId: 'agy', severity: 'degrade', timeoutMs: 15000, run: tierFreshness, remedy: { human: 'Refresh agy model list', command: 'agy models', autoFixable: false } },
155
+ { id: 'codex.tier.freshness', cliId: 'codex', severity: 'degrade', timeoutMs: 15000, run: tierFreshness, remedy: { human: 'Refresh codex model list', command: 'codex models', autoFixable: false } },
156
+ ];
157
+
158
+ export default probes;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @typedef {'agy'|'opencode'|'codex'|'native'} CliId
3
+ */
4
+
5
+ /**
6
+ * @typedef {{pass: boolean, evidence?: string, reason?: string}} ProbeResult
7
+ */
8
+
9
+ /**
10
+ * @typedef {{id: string, cliId: CliId, severity: 'fatal'|'degrade'|'info', timeoutMs: number,
11
+ * run: (sh: {execFile: (cmd: string, args: string[], options?: object) => Promise<any>,
12
+ * fs: {stat: (path: string) => Promise<{mtime: number}>,
13
+ * readFile: (path: string) => Promise<string>}), ProbeResult,
14
+ * remedy: {human: string, command?: string, autoFixable: boolean}}} Probe
15
+ */
16
+
17
+ /**
18
+ * @typedef {{status: 'ready'|'degraded'|'unusable'|'absent', binary: string, version: string, probes: ProbeResult[]}} CliHealth.ready
19
+ * @typedef {{status: 'unusable', reason: 'not-on-path'|'unauthenticated'|'permissions'|'hangs'|'version-unsupported', probes: ProbeResult[]}} CliHealth.unusable
20
+ * @typedef {{status: 'absent'}} CliHealth.absent
21
+ * @typedef {CliHealth.ready | CliHealth.unusable | CliHealth.absent} CliHealth
22
+ */
23
+
24
+ // These are JSDoc-only typedefs — nothing to export at runtime. Other files
25
+ // reference them via `@typedef {import('./types.js').CliHealth} CliHealth`.
26
+ export {};