@bonesofspring/ai-rules 0.2.21 → 0.2.23

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 (363) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +6 -2
  3. package/bin/cli.js +32 -8
  4. package/bin/mavis-install.js +441 -0
  5. package/package.json +9 -2
  6. package/presets/_shared/core/agent-team/agent-artifact-contracts.md +2 -0
  7. package/presets/_shared/core/meta/preset-pr-checklist.md +1 -0
  8. package/presets/_shared/core/meta/preset-twin-sync.md +17 -1
  9. package/presets/claude/android-kotlin/agents/build-verifier.md +2 -0
  10. package/presets/claude/android-kotlin/agents/code-reviewer.md +2 -0
  11. package/presets/claude/android-kotlin/agents/debugger.md +1 -0
  12. package/presets/claude/android-kotlin/agents/feature-developer.md +3 -0
  13. package/presets/claude/android-kotlin/agents/qa-tester.md +2 -0
  14. package/presets/claude/android-kotlin/agents/task-router.md +4 -0
  15. package/presets/claude/android-kotlin/hooks/chain-team-phases.sh +51 -11
  16. package/presets/claude/android-kotlin/rules/tooling-and-review/preset-pr-checklist.md +1 -0
  17. package/presets/claude/android-kotlin/rules/tooling-and-review/preset-twin-sync.md +17 -1
  18. package/presets/claude/go/agents/build-verifier.md +4 -0
  19. package/presets/claude/go/agents/code-reviewer.md +4 -0
  20. package/presets/claude/go/agents/debugger.md +4 -0
  21. package/presets/claude/go/agents/feature-developer.md +5 -0
  22. package/presets/claude/go/agents/qa-tester.md +4 -0
  23. package/presets/claude/go/agents/task-router.md +4 -0
  24. package/presets/claude/go/hooks/chain-team-phases.sh +51 -11
  25. package/presets/claude/go/rules/tooling-and-review/preset-pr-checklist.md +1 -0
  26. package/presets/claude/go/rules/tooling-and-review/preset-twin-sync.md +17 -1
  27. package/presets/claude/ios-swift/agents/build-verifier.md +2 -0
  28. package/presets/claude/ios-swift/agents/code-reviewer.md +2 -0
  29. package/presets/claude/ios-swift/agents/debugger.md +1 -0
  30. package/presets/claude/ios-swift/agents/feature-developer.md +3 -0
  31. package/presets/claude/ios-swift/agents/qa-tester.md +2 -0
  32. package/presets/claude/ios-swift/agents/task-router.md +4 -0
  33. package/presets/claude/ios-swift/hooks/chain-team-phases.sh +51 -11
  34. package/presets/claude/ios-swift/rules/tooling-and-review/preset-pr-checklist.md +1 -0
  35. package/presets/claude/ios-swift/rules/tooling-and-review/preset-twin-sync.md +17 -1
  36. package/presets/claude/java/agents/build-verifier.md +4 -0
  37. package/presets/claude/java/agents/code-reviewer.md +4 -0
  38. package/presets/claude/java/agents/debugger.md +4 -0
  39. package/presets/claude/java/agents/feature-developer.md +5 -0
  40. package/presets/claude/java/agents/qa-tester.md +4 -0
  41. package/presets/claude/java/agents/task-router.md +4 -0
  42. package/presets/claude/java/hooks/chain-team-phases.sh +51 -11
  43. package/presets/claude/java/rules/tooling-and-review/preset-pr-checklist.md +1 -0
  44. package/presets/claude/java/rules/tooling-and-review/preset-twin-sync.md +17 -1
  45. package/presets/claude/mcp-ts/agents/build-verifier.md +4 -0
  46. package/presets/claude/mcp-ts/agents/feature-developer.md +5 -0
  47. package/presets/claude/mcp-ts/agents/task-router.md +1 -1
  48. package/presets/claude/mcp-ts/hooks/chain-team-phases.sh +51 -11
  49. package/presets/claude/mcp-ts/rules/tooling-and-review/preset-pr-checklist.md +1 -0
  50. package/presets/claude/mcp-ts/rules/tooling-and-review/preset-twin-sync.md +17 -1
  51. package/presets/claude/next/agents/build-verifier.md +2 -0
  52. package/presets/claude/next/agents/code-reviewer.md +2 -0
  53. package/presets/claude/next/agents/debugger.md +4 -0
  54. package/presets/claude/next/agents/feature-developer.md +3 -0
  55. package/presets/claude/next/agents/qa-tester.md +4 -0
  56. package/presets/claude/next/agents/unit-test-generator.md +1 -1
  57. package/presets/claude/next/agents/unit-test-planner.md +1 -1
  58. package/presets/claude/next/hooks/chain-team-phases.sh +51 -11
  59. package/presets/claude/next/rules/api-and-data/http-client.md +1 -1
  60. package/presets/claude/next/rules/architecture/reference-features.md +1 -1
  61. package/presets/claude/next/rules/testing/README.md +1 -1
  62. package/presets/claude/next/rules/testing/tests-e2e-structure.md +2 -0
  63. package/presets/claude/next/rules/testing/tests-unit.md +3 -5
  64. package/presets/claude/next/rules/tooling-and-review/preset-pr-checklist.md +1 -0
  65. package/presets/claude/next/rules/tooling-and-review/preset-twin-sync.md +17 -1
  66. package/presets/claude/next/rules/ui-and-accessibility/react-ui.md +1 -1
  67. package/presets/claude/next/skills/playwright-e2e/SKILL.md +5 -3
  68. package/presets/claude/next/skills/unit-testing/SKILL.md +6 -4
  69. package/presets/claude/nuxt/agents/build-verifier.md +2 -0
  70. package/presets/claude/nuxt/agents/code-reviewer.md +2 -0
  71. package/presets/claude/nuxt/agents/debugger.md +4 -0
  72. package/presets/claude/nuxt/agents/feature-developer.md +3 -0
  73. package/presets/claude/nuxt/agents/qa-tester.md +4 -0
  74. package/presets/claude/nuxt/hooks/chain-team-phases.sh +51 -11
  75. package/presets/claude/nuxt/rules/tooling-and-review/preset-pr-checklist.md +1 -0
  76. package/presets/claude/nuxt/rules/tooling-and-review/preset-twin-sync.md +17 -1
  77. package/presets/claude/php-hexagonal/agents/build-verifier.md +4 -0
  78. package/presets/claude/php-hexagonal/agents/code-reviewer.md +4 -0
  79. package/presets/claude/php-hexagonal/agents/debugger.md +4 -0
  80. package/presets/claude/php-hexagonal/agents/feature-developer.md +5 -0
  81. package/presets/claude/php-hexagonal/agents/qa-tester.md +4 -0
  82. package/presets/claude/php-hexagonal/agents/task-router.md +4 -0
  83. package/presets/claude/php-hexagonal/hooks/chain-team-phases.sh +51 -11
  84. package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-pr-checklist.md +1 -0
  85. package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-twin-sync.md +17 -1
  86. package/presets/claude/php-laravel/agents/build-verifier.md +4 -0
  87. package/presets/claude/php-laravel/agents/code-reviewer.md +4 -0
  88. package/presets/claude/php-laravel/agents/debugger.md +4 -0
  89. package/presets/claude/php-laravel/agents/feature-developer.md +5 -0
  90. package/presets/claude/php-laravel/agents/qa-tester.md +4 -0
  91. package/presets/claude/php-laravel/agents/task-router.md +1 -0
  92. package/presets/claude/php-laravel/hooks/chain-team-phases.sh +51 -11
  93. package/presets/claude/php-laravel/rules/tooling-and-review/preset-pr-checklist.md +1 -0
  94. package/presets/claude/php-laravel/rules/tooling-and-review/preset-twin-sync.md +17 -1
  95. package/presets/claude/svelte/agents/build-verifier.md +2 -0
  96. package/presets/claude/svelte/agents/code-reviewer.md +2 -0
  97. package/presets/claude/svelte/agents/debugger.md +4 -0
  98. package/presets/claude/svelte/agents/feature-developer.md +3 -0
  99. package/presets/claude/svelte/agents/qa-tester.md +4 -0
  100. package/presets/claude/svelte/hooks/chain-team-phases.sh +51 -11
  101. package/presets/claude/svelte/rules/tooling-and-review/preset-pr-checklist.md +1 -0
  102. package/presets/claude/svelte/rules/tooling-and-review/preset-twin-sync.md +17 -1
  103. package/presets/cursor/android-kotlin/agents/build-verifier.md +2 -0
  104. package/presets/cursor/android-kotlin/agents/code-reviewer.md +2 -0
  105. package/presets/cursor/android-kotlin/agents/debugger.md +1 -0
  106. package/presets/cursor/android-kotlin/agents/feature-developer.md +3 -0
  107. package/presets/cursor/android-kotlin/agents/qa-tester.md +2 -0
  108. package/presets/cursor/android-kotlin/agents/task-router.md +4 -0
  109. package/presets/cursor/android-kotlin/hooks/chain-team-phases.sh +51 -11
  110. package/presets/cursor/android-kotlin/rules/preset-pr-checklist.mdc +1 -0
  111. package/presets/cursor/android-kotlin/rules/preset-twin-sync.mdc +17 -1
  112. package/presets/cursor/go/agents/build-verifier.md +4 -0
  113. package/presets/cursor/go/agents/code-reviewer.md +4 -0
  114. package/presets/cursor/go/agents/debugger.md +4 -0
  115. package/presets/cursor/go/agents/feature-developer.md +5 -0
  116. package/presets/cursor/go/agents/qa-tester.md +4 -0
  117. package/presets/cursor/go/agents/task-router.md +4 -0
  118. package/presets/cursor/go/hooks/chain-team-phases.sh +51 -11
  119. package/presets/cursor/go/rules/preset-pr-checklist.mdc +1 -0
  120. package/presets/cursor/go/rules/preset-twin-sync.mdc +17 -1
  121. package/presets/cursor/ios-swift/agents/build-verifier.md +2 -0
  122. package/presets/cursor/ios-swift/agents/code-reviewer.md +2 -0
  123. package/presets/cursor/ios-swift/agents/debugger.md +1 -0
  124. package/presets/cursor/ios-swift/agents/feature-developer.md +3 -0
  125. package/presets/cursor/ios-swift/agents/qa-tester.md +2 -0
  126. package/presets/cursor/ios-swift/agents/task-router.md +4 -0
  127. package/presets/cursor/ios-swift/hooks/chain-team-phases.sh +51 -11
  128. package/presets/cursor/ios-swift/rules/preset-pr-checklist.mdc +1 -0
  129. package/presets/cursor/ios-swift/rules/preset-twin-sync.mdc +17 -1
  130. package/presets/cursor/java/agents/build-verifier.md +4 -0
  131. package/presets/cursor/java/agents/code-reviewer.md +4 -0
  132. package/presets/cursor/java/agents/debugger.md +4 -0
  133. package/presets/cursor/java/agents/feature-developer.md +5 -0
  134. package/presets/cursor/java/agents/qa-tester.md +4 -0
  135. package/presets/cursor/java/agents/task-router.md +4 -0
  136. package/presets/cursor/java/hooks/chain-team-phases.sh +51 -11
  137. package/presets/cursor/java/rules/preset-pr-checklist.mdc +1 -0
  138. package/presets/cursor/java/rules/preset-twin-sync.mdc +17 -1
  139. package/presets/cursor/mcp-ts/agents/build-verifier.md +4 -0
  140. package/presets/cursor/mcp-ts/agents/feature-developer.md +5 -0
  141. package/presets/cursor/mcp-ts/agents/task-router.md +1 -1
  142. package/presets/cursor/mcp-ts/hooks/chain-team-phases.sh +51 -11
  143. package/presets/cursor/mcp-ts/rules/preset-pr-checklist.mdc +1 -0
  144. package/presets/cursor/mcp-ts/rules/preset-twin-sync.mdc +17 -1
  145. package/presets/cursor/next/agents/build-verifier.md +2 -0
  146. package/presets/cursor/next/agents/code-reviewer.md +2 -0
  147. package/presets/cursor/next/agents/debugger.md +4 -0
  148. package/presets/cursor/next/agents/feature-developer.md +3 -0
  149. package/presets/cursor/next/agents/qa-tester.md +4 -0
  150. package/presets/cursor/next/agents/unit-test-generator.md +1 -1
  151. package/presets/cursor/next/agents/unit-test-planner.md +1 -1
  152. package/presets/cursor/next/hooks/chain-team-phases.sh +51 -11
  153. package/presets/cursor/next/rules/http-client.mdc +1 -1
  154. package/presets/cursor/next/rules/preset-pr-checklist.mdc +1 -0
  155. package/presets/cursor/next/rules/preset-twin-sync.mdc +17 -1
  156. package/presets/cursor/next/rules/react-ui.mdc +1 -1
  157. package/presets/cursor/next/rules/reference-features.mdc +1 -1
  158. package/presets/cursor/next/rules/tests-e2e-structure.mdc +2 -0
  159. package/presets/cursor/next/rules/tests-unit.mdc +3 -5
  160. package/presets/cursor/next/skills/playwright-e2e/SKILL.md +5 -3
  161. package/presets/cursor/next/skills/unit-testing/SKILL.md +6 -4
  162. package/presets/cursor/nuxt/agents/build-verifier.md +2 -0
  163. package/presets/cursor/nuxt/agents/code-reviewer.md +2 -0
  164. package/presets/cursor/nuxt/agents/debugger.md +4 -0
  165. package/presets/cursor/nuxt/agents/feature-developer.md +3 -0
  166. package/presets/cursor/nuxt/agents/qa-tester.md +4 -0
  167. package/presets/cursor/nuxt/hooks/chain-team-phases.sh +51 -11
  168. package/presets/cursor/nuxt/rules/preset-pr-checklist.mdc +1 -0
  169. package/presets/cursor/nuxt/rules/preset-twin-sync.mdc +17 -1
  170. package/presets/cursor/php-hexagonal/agents/build-verifier.md +4 -0
  171. package/presets/cursor/php-hexagonal/agents/code-reviewer.md +4 -0
  172. package/presets/cursor/php-hexagonal/agents/debugger.md +4 -0
  173. package/presets/cursor/php-hexagonal/agents/feature-developer.md +5 -0
  174. package/presets/cursor/php-hexagonal/agents/qa-tester.md +4 -0
  175. package/presets/cursor/php-hexagonal/agents/task-router.md +4 -0
  176. package/presets/cursor/php-hexagonal/hooks/chain-team-phases.sh +51 -11
  177. package/presets/cursor/php-hexagonal/rules/preset-pr-checklist.mdc +1 -0
  178. package/presets/cursor/php-hexagonal/rules/preset-twin-sync.mdc +17 -1
  179. package/presets/cursor/php-laravel/agents/build-verifier.md +4 -0
  180. package/presets/cursor/php-laravel/agents/code-reviewer.md +4 -0
  181. package/presets/cursor/php-laravel/agents/debugger.md +4 -0
  182. package/presets/cursor/php-laravel/agents/feature-developer.md +5 -0
  183. package/presets/cursor/php-laravel/agents/qa-tester.md +4 -0
  184. package/presets/cursor/php-laravel/agents/task-router.md +1 -0
  185. package/presets/cursor/php-laravel/hooks/chain-team-phases.sh +51 -11
  186. package/presets/cursor/php-laravel/rules/preset-pr-checklist.mdc +1 -0
  187. package/presets/cursor/php-laravel/rules/preset-twin-sync.mdc +17 -1
  188. package/presets/cursor/svelte/agents/build-verifier.md +2 -0
  189. package/presets/cursor/svelte/agents/code-reviewer.md +2 -0
  190. package/presets/cursor/svelte/agents/debugger.md +4 -0
  191. package/presets/cursor/svelte/agents/feature-developer.md +3 -0
  192. package/presets/cursor/svelte/agents/qa-tester.md +4 -0
  193. package/presets/cursor/svelte/hooks/chain-team-phases.sh +51 -11
  194. package/presets/cursor/svelte/rules/preset-pr-checklist.mdc +1 -0
  195. package/presets/cursor/svelte/rules/preset-twin-sync.mdc +17 -1
  196. package/presets/mavis/README.md +60 -0
  197. package/presets/mavis/next/MAVIS.md +67 -0
  198. package/presets/mavis/next/MCP.md +36 -0
  199. package/presets/mavis/next/README.md +15 -0
  200. package/presets/mavis/next/REPO_AGENTS.md +94 -0
  201. package/presets/mavis/next/adapter-map.json +959 -0
  202. package/presets/mavis/next/agents/README.md +206 -0
  203. package/presets/mavis/next/agents/accessibility-reviewer.md +61 -0
  204. package/presets/mavis/next/agents/api-contract-reviewer.md +57 -0
  205. package/presets/mavis/next/agents/build-verifier.md +110 -0
  206. package/presets/mavis/next/agents/ci-investigator.md +63 -0
  207. package/presets/mavis/next/agents/code-reviewer.md +61 -0
  208. package/presets/mavis/next/agents/codebase-analyzer.md +21 -0
  209. package/presets/mavis/next/agents/debugger.md +80 -0
  210. package/presets/mavis/next/agents/feature-developer.md +101 -0
  211. package/presets/mavis/next/agents/migration-specialist.md +67 -0
  212. package/presets/mavis/next/agents/mockup-reviewer.md +53 -0
  213. package/presets/mavis/next/agents/openspec-author.md +157 -0
  214. package/presets/mavis/next/agents/performance-auditor.md +68 -0
  215. package/presets/mavis/next/agents/playwright-test-generator.md +28 -0
  216. package/presets/mavis/next/agents/playwright-test-healer.md +28 -0
  217. package/presets/mavis/next/agents/playwright-test-planner.md +21 -0
  218. package/presets/mavis/next/agents/qa-tester.md +52 -0
  219. package/presets/mavis/next/agents/security-reviewer.md +54 -0
  220. package/presets/mavis/next/agents/solution-architect.md +68 -0
  221. package/presets/mavis/next/agents/task-analyst.md +166 -0
  222. package/presets/mavis/next/agents/task-router.md +178 -0
  223. package/presets/mavis/next/agents/tech-writer.md +57 -0
  224. package/presets/mavis/next/agents/unit-test-generator.md +31 -0
  225. package/presets/mavis/next/agents/unit-test-healer.md +32 -0
  226. package/presets/mavis/next/agents/unit-test-planner.md +54 -0
  227. package/presets/mavis/next/commands/README.md +49 -0
  228. package/presets/mavis/next/commands/spec-start.md +24 -0
  229. package/presets/mavis/next/commands/task-continue.md +50 -0
  230. package/presets/mavis/next/commands/task.md +50 -0
  231. package/presets/mavis/next/commands/technical-retro.md +80 -0
  232. package/presets/mavis/next/hooks/README.md +22 -0
  233. package/presets/mavis/next/hooks/chain-team-phases.sh +845 -0
  234. package/presets/mavis/next/mcp.json +19 -0
  235. package/presets/mavis/next/rules/README.md +16 -0
  236. package/presets/mavis/next/rules/agent-team-intake.md +11 -0
  237. package/presets/mavis/next/rules/agent-team-orchestrator.md +210 -0
  238. package/presets/mavis/next/rules/ai-local-overlay.md +37 -0
  239. package/presets/mavis/next/rules/anti-sycophancy-discipline.md +23 -0
  240. package/presets/mavis/next/rules/api-services.md +72 -0
  241. package/presets/mavis/next/rules/architecture-boundaries-ui.md +9 -0
  242. package/presets/mavis/next/rules/architecture-boundaries.md +86 -0
  243. package/presets/mavis/next/rules/arrow-functions.md +25 -0
  244. package/presets/mavis/next/rules/code-quality-and-refactoring.md +40 -0
  245. package/presets/mavis/next/rules/code-review-mr.md +40 -0
  246. package/presets/mavis/next/rules/css-property-order-stylelint.md +5 -0
  247. package/presets/mavis/next/rules/design-guidance.md +99 -0
  248. package/presets/mavis/next/rules/feature-delivery-workflow.md +49 -0
  249. package/presets/mavis/next/rules/http-client.md +55 -0
  250. package/presets/mavis/next/rules/layer-barrel-exports.md +68 -0
  251. package/presets/mavis/next/rules/mcp-usage.md +86 -0
  252. package/presets/mavis/next/rules/mockup-review.md +107 -0
  253. package/presets/mavis/next/rules/navigation-router-stack.md +56 -0
  254. package/presets/mavis/next/rules/navigation-router-ui.md +10 -0
  255. package/presets/mavis/next/rules/next-app-core.md +29 -0
  256. package/presets/mavis/next/rules/next-app-router.md +44 -0
  257. package/presets/mavis/next/rules/no-props-spread.md +56 -0
  258. package/presets/mavis/next/rules/no-type-assertion-as-import-export.md +51 -0
  259. package/presets/mavis/next/rules/package-manager.md +11 -0
  260. package/presets/mavis/next/rules/playwright-agents.md +67 -0
  261. package/presets/mavis/next/rules/post-change-lint.md +35 -0
  262. package/presets/mavis/next/rules/preset-layering.md +27 -0
  263. package/presets/mavis/next/rules/preset-no-cross-stack-leakage.md +90 -0
  264. package/presets/mavis/next/rules/preset-pr-checklist.md +35 -0
  265. package/presets/mavis/next/rules/preset-token-budget.md +36 -0
  266. package/presets/mavis/next/rules/preset-twin-sync.md +65 -0
  267. package/presets/mavis/next/rules/product-specs-authoring.md +112 -0
  268. package/presets/mavis/next/rules/product-specs.md +56 -0
  269. package/presets/mavis/next/rules/public-imports.md +50 -0
  270. package/presets/mavis/next/rules/react-a11y-coding.md +31 -0
  271. package/presets/mavis/next/rules/react-next-anti-hallucination.md +60 -0
  272. package/presets/mavis/next/rules/react-ui.md +105 -0
  273. package/presets/mavis/next/rules/reference-features.md +45 -0
  274. package/presets/mavis/next/rules/security-next.md +45 -0
  275. package/presets/mavis/next/rules/store-rtk.md +78 -0
  276. package/presets/mavis/next/rules/technical-retro.md +11 -0
  277. package/presets/mavis/next/rules/tests-e2e-structure.md +72 -0
  278. package/presets/mavis/next/rules/tests-unit.md +72 -0
  279. package/presets/mavis/next/rules/types-jsdoc.md +43 -0
  280. package/presets/mavis/next/rules/ux-design.md +99 -0
  281. package/presets/mavis/next/skills/README.md +21 -0
  282. package/presets/mavis/next/skills/ci-investigation/SKILL.md +39 -0
  283. package/presets/mavis/next/skills/code-review/SKILL.md +39 -0
  284. package/presets/mavis/next/skills/debug-investigation/SKILL.md +26 -0
  285. package/presets/mavis/next/skills/feature-delivery/SKILL.md +34 -0
  286. package/presets/mavis/next/skills/mockup-review/SKILL.md +24 -0
  287. package/presets/mavis/next/skills/playwright-e2e/SKILL.md +28 -0
  288. package/presets/mavis/next/skills/react-performance/SKILL.md +39 -0
  289. package/presets/mavis/next/skills/spec-authoring/SKILL.md +21 -0
  290. package/presets/mavis/next/skills/spec-discovery/SKILL.md +53 -0
  291. package/presets/mavis/next/skills/technical-retro/SKILL.md +49 -0
  292. package/presets/mavis/next/skills/unit-testing/SKILL.md +29 -0
  293. package/presets/mavis/next/skills/ux-design/SKILL.md +31 -0
  294. package/presets/mavis/next/skills/write-adr/SKILL.md +36 -0
  295. package/presets/mavis/next/team/README.md +148 -0
  296. package/presets/mavis/next/team/conventions.md +21 -0
  297. package/presets/mavis/next/team/fixtures/artifact-manifest.example.json +79 -0
  298. package/presets/mavis/next/team/fixtures/bugfix-standard.json +25 -0
  299. package/presets/mavis/next/team/fixtures/feature-full.json +29 -0
  300. package/presets/mavis/next/team/fixtures/feature-light.json +27 -0
  301. package/presets/mavis/next/team/fixtures/feature-with-figma-url.json +17 -0
  302. package/presets/mavis/next/team/fixtures/feature-with-ux-no-figma.json +17 -0
  303. package/presets/mavis/next/team/fixtures/memlog.example.md +9 -0
  304. package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/human-gate/metrics.json +69 -0
  305. package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/missing-ledger/status.json +5 -0
  306. package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/parallel-receipts/metrics.json +79 -0
  307. package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/serial-retry/metrics.json +124 -0
  308. package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/validation-failed/metrics.json +124 -0
  309. package/presets/mavis/next/team/fixtures/metrics.example.json +54 -0
  310. package/presets/mavis/next/team/fixtures/mockup-review-fail-embedded-status.json +8 -0
  311. package/presets/mavis/next/team/fixtures/mockup-review-standalone.json +14 -0
  312. package/presets/mavis/next/team/fixtures/ux-design-standalone.json +15 -0
  313. package/presets/mavis/next/team/tasks/.gitkeep +0 -0
  314. package/presets/mavis/platform-contract.json +131 -0
  315. package/scripts/capture-cli-golden.mjs +44 -0
  316. package/scripts/check-chain-hook-coverage.sh +1 -0
  317. package/scripts/check-mavis-adapter-map.mjs +294 -0
  318. package/scripts/check-mavis-local-overlay.mjs +56 -0
  319. package/scripts/check-mavis-platform-contract.mjs +388 -0
  320. package/scripts/check-mavis-token-budget.mjs +48 -0
  321. package/scripts/check-preset-leakage.sh +35 -3
  322. package/scripts/check-preset-structure.sh +73 -0
  323. package/scripts/check-preset-token-budget.sh +100 -0
  324. package/scripts/check-shared-core-drift.sh +18 -0
  325. package/scripts/check-task-router-intents.sh +154 -0
  326. package/scripts/fixtures/cli-golden/claude/next.json +130 -0
  327. package/scripts/fixtures/cli-golden/cursor/next.json +132 -0
  328. package/scripts/fixtures/cli-golden/mavis/next.json +125 -0
  329. package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/cursor/AGENTS.md +1 -0
  330. package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/cursor/rules/extra.mdc +1 -0
  331. package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/cursor/rules/sample.mdc +2 -0
  332. package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/mavis/MAVIS.md +1 -0
  333. package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/mavis/adapter-map.json +26 -0
  334. package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/mavis/rules/sample.md +2 -0
  335. package/scripts/fixtures/mavis-adapter-map/valid/cursor/AGENTS.md +1 -0
  336. package/scripts/fixtures/mavis-adapter-map/valid/cursor/rules/sample.mdc +2 -0
  337. package/scripts/fixtures/mavis-adapter-map/valid/mavis/MAVIS.md +1 -0
  338. package/scripts/fixtures/mavis-adapter-map/valid/mavis/adapter-map.json +26 -0
  339. package/scripts/fixtures/mavis-adapter-map/valid/mavis/rules/sample.md +2 -0
  340. package/scripts/fixtures/mavis-platform-contract/invalid-minimax-destination.json +131 -0
  341. package/scripts/fixtures/mavis-platform-contract/invalid-missing-capability.json +126 -0
  342. package/scripts/fixtures/mavis-platform-contract/invalid-released-unknown-stack.json +133 -0
  343. package/scripts/fixtures/mavis-platform-contract/invalid-unknown-native-path.json +131 -0
  344. package/scripts/fixtures/mavis-platform-contract/invalid-version-pin.json +132 -0
  345. package/scripts/fixtures/mavis-platform-contract/valid.json +131 -0
  346. package/scripts/fixtures/mavis-probe/AGENTS.md +6 -0
  347. package/scripts/fixtures/mavis-probe/agents/probe-agent.md +6 -0
  348. package/scripts/fixtures/mavis-probe/fake-mcode.mjs +98 -0
  349. package/scripts/fixtures/mavis-probe/output.schema.json +28 -0
  350. package/scripts/fixtures/mavis-probe/rules/probe.md +5 -0
  351. package/scripts/fixtures/mavis-probe/skills/probe/SKILL.md +11 -0
  352. package/scripts/generate-mavis-next.mjs +704 -0
  353. package/scripts/lib/cli-golden.mjs +50 -0
  354. package/scripts/lib/discover-hooks.mjs +72 -0
  355. package/scripts/probe-mavis-capabilities.mjs +480 -0
  356. package/scripts/test-agent-task-metrics-hooks.mjs +120 -16
  357. package/scripts/test-chain-team-phases-coverage.mjs +110 -8
  358. package/scripts/test-cli-init-clean.mjs +256 -0
  359. package/scripts/test-cli-mcp-merge.mjs +23 -0
  360. package/scripts/test-mavis-context-budget.mjs +55 -0
  361. package/scripts/test-mavis-orchestration.mjs +649 -0
  362. package/scripts/test-probe-mavis-capabilities.mjs +205 -0
  363. package/scripts/test-task-router-intents-fixtures.mjs +109 -0
@@ -0,0 +1,50 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import crypto from 'node:crypto';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+
6
+ export function sha256File(filePath) {
7
+ return crypto.createHash('sha256').update(fs.readFileSync(filePath)).digest('hex');
8
+ }
9
+
10
+ export function walkRelativeFiles(root) {
11
+ const files = [];
12
+ const visit = (dir) => {
13
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
14
+ const full = path.join(dir, entry.name);
15
+ if (entry.name === '.DS_Store') {
16
+ continue;
17
+ }
18
+ if (entry.isDirectory()) {
19
+ visit(full);
20
+ } else if (entry.isFile()) {
21
+ files.push(path.relative(root, full).split(path.sep).join('/'));
22
+ }
23
+ }
24
+ };
25
+ visit(root);
26
+ return files.sort();
27
+ }
28
+
29
+ export function snapshotInstall(root) {
30
+ const files = {};
31
+ for (const rel of walkRelativeFiles(root)) {
32
+ files[rel] = sha256File(path.join(root, rel));
33
+ }
34
+ return files;
35
+ }
36
+
37
+ export function runInit(cli, cwd, tool, preset) {
38
+ return execFileSync(process.execPath, [cli, 'init', tool, '--preset', preset, '--cwd', cwd], {
39
+ encoding: 'utf8',
40
+ });
41
+ }
42
+
43
+ export function goldenDocument({ tool, preset, files }) {
44
+ return {
45
+ schemaVersion: 1,
46
+ tool,
47
+ preset,
48
+ files,
49
+ };
50
+ }
@@ -0,0 +1,72 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ export function loadReleasedMavisStacks(presetsRoot) {
5
+ const contractPath = path.join(presetsRoot, 'mavis', 'platform-contract.json');
6
+ if (!fs.existsSync(contractPath)) {
7
+ return [];
8
+ }
9
+ const contract = JSON.parse(fs.readFileSync(contractPath, 'utf8'));
10
+ return Array.isArray(contract.releasedStacks) ? contract.releasedStacks : [];
11
+ }
12
+
13
+ export function discoverChainHooks(presetsRoot) {
14
+ const hooks = [];
15
+ for (const platform of ['cursor', 'claude']) {
16
+ const platformDir = path.join(presetsRoot, platform);
17
+ if (!fs.existsSync(platformDir)) {
18
+ continue;
19
+ }
20
+ for (const stack of fs.readdirSync(platformDir)) {
21
+ const hook = path.join(platformDir, stack, 'hooks', 'chain-team-phases.sh');
22
+ if (fs.existsSync(hook)) {
23
+ hooks.push(hook);
24
+ }
25
+ }
26
+ }
27
+ for (const stack of loadReleasedMavisStacks(presetsRoot)) {
28
+ const hook = path.join(presetsRoot, 'mavis', stack, 'hooks', 'chain-team-phases.sh');
29
+ if (fs.existsSync(hook)) {
30
+ hooks.push(hook);
31
+ }
32
+ }
33
+ return hooks;
34
+ }
35
+
36
+ export function platformFromHook(hookPath) {
37
+ const parts = hookPath.split(path.sep);
38
+ const presetsIndex = parts.lastIndexOf('presets');
39
+ if (presetsIndex >= 0 && parts[presetsIndex + 1]) {
40
+ return parts[presetsIndex + 1];
41
+ }
42
+ if (hookPath.includes(`${path.sep}mavis${path.sep}`)) {
43
+ return 'mavis';
44
+ }
45
+ if (hookPath.includes(`${path.sep}cursor${path.sep}`)) {
46
+ return 'cursor';
47
+ }
48
+ return 'claude';
49
+ }
50
+
51
+ export function expectedLegacyHookCount(presetsRoot) {
52
+ let count = 0;
53
+ for (const platform of ['cursor', 'claude']) {
54
+ const platformDir = path.join(presetsRoot, platform);
55
+ if (!fs.existsSync(platformDir)) {
56
+ continue;
57
+ }
58
+ for (const stack of fs.readdirSync(platformDir)) {
59
+ const hook = path.join(platformDir, stack, 'hooks', 'chain-team-phases.sh');
60
+ if (fs.existsSync(hook)) {
61
+ count += 1;
62
+ }
63
+ }
64
+ }
65
+ return count;
66
+ }
67
+
68
+ export function expectedHookCount(presetsRoot) {
69
+ return expectedLegacyHookCount(presetsRoot) + loadReleasedMavisStacks(presetsRoot).filter((stack) =>
70
+ fs.existsSync(path.join(presetsRoot, 'mavis', stack, 'hooks', 'chain-team-phases.sh')),
71
+ ).length;
72
+ }
@@ -0,0 +1,480 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from 'node:child_process';
3
+ import fs from 'node:fs';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const scriptDirectory = path.dirname(fileURLToPath(import.meta.url));
9
+ const fixtureDirectory = path.join(scriptDirectory, 'fixtures', 'mavis-probe');
10
+
11
+ const LIBRARY_INPUTS = [
12
+ path.join('rules', 'probe.md'),
13
+ path.join('agents', 'probe-agent.md'),
14
+ path.join('skills', 'probe', 'SKILL.md'),
15
+ 'output.schema.json',
16
+ ];
17
+
18
+ function parseArguments(argv) {
19
+ const values = new Map();
20
+ for (let index = 0; index < argv.length; index += 2) {
21
+ const flag = argv[index];
22
+ const value = argv[index + 1];
23
+ if (!['--mcode', '--workdir'].includes(flag) || !value) {
24
+ throw new Error('Usage: probe-mavis-capabilities.mjs --mcode <path> --workdir <path>');
25
+ }
26
+ values.set(flag, value);
27
+ }
28
+ if (!values.has('--mcode') || !values.has('--workdir')) {
29
+ throw new Error('Both --mcode and --workdir are required');
30
+ }
31
+ return {
32
+ mcode: path.resolve(values.get('--mcode')),
33
+ workdir: path.resolve(values.get('--workdir')),
34
+ };
35
+ }
36
+
37
+ function createRedactor({ mcode, workdir, isolatedHome }) {
38
+ const replacements = [
39
+ [mcode, '<MCODE>'],
40
+ [workdir, '<WORKDIR>'],
41
+ [isolatedHome, '<PROBE_HOME>'],
42
+ [os.homedir(), '<HOME>'],
43
+ ]
44
+ .filter(([source]) => Boolean(source))
45
+ .sort(([left], [right]) => right.length - left.length);
46
+
47
+ return (value) => {
48
+ let redacted = String(value ?? '');
49
+ for (const [source, target] of replacements) {
50
+ redacted = redacted.split(source).join(target);
51
+ }
52
+ return redacted
53
+ .replace(/\/(?:Users|home)\/[^/\s"']+\/\.minimax/g, '<HOME>/.minimax')
54
+ .replace(/(Bearer\s+)[^\s"',]+/gi, '$1<REDACTED>')
55
+ .replace(
56
+ /((?:api[_-]?key|token|secret|password)\s*[=:]\s*)[^\s"',]+/gi,
57
+ '$1<REDACTED>',
58
+ )
59
+ .trim();
60
+ };
61
+ }
62
+
63
+ function commandForEvidence(args, redact) {
64
+ return args.map((argument) => redact(argument));
65
+ }
66
+
67
+ function capability({ status, command = null, exitCode = null, observation, executed = false }) {
68
+ return { status, command, exitCode, observation, executed };
69
+ }
70
+
71
+ function loadInlineOutputSchema() {
72
+ return JSON.stringify(JSON.parse(fs.readFileSync(path.join(fixtureDirectory, 'output.schema.json'), 'utf8')));
73
+ }
74
+
75
+ function createCapabilities(redact, mcode, workdir) {
76
+ const documentedMcpCommand = commandForEvidence([mcode, 'mcp', 'list', '--human'], redact);
77
+ const execSafety = ['--permission', 'off', '--timeout', '3m', '--max-steps', '16'];
78
+ const model = process.env.MAVIS_PROBE_MODEL;
79
+ if (model) execSafety.push('--model', model);
80
+ const outputSchema = loadInlineOutputSchema();
81
+ const structuredCommand = [
82
+ mcode,
83
+ 'exec',
84
+ '--cwd',
85
+ workdir,
86
+ '--output-format',
87
+ 'json',
88
+ ...execSafety,
89
+ 'Return the requested capability sentinels.',
90
+ ];
91
+ if (process.env.MAVIS_PROBE_USE_SCHEMA === '1') {
92
+ structuredCommand.splice(structuredCommand.indexOf('json') + 1, 0, '--output-schema', outputSchema);
93
+ }
94
+ const roleCommand = [
95
+ mcode,
96
+ 'exec',
97
+ '--cwd',
98
+ workdir,
99
+ '--file',
100
+ 'agents/probe-agent.md',
101
+ '--output-format',
102
+ 'json',
103
+ ...execSafety,
104
+ 'Return the requested role sentinel.',
105
+ ];
106
+ if (process.env.MAVIS_PROBE_USE_SCHEMA === '1') {
107
+ roleCommand.splice(roleCommand.indexOf('json') + 1, 0, '--output-schema', outputSchema);
108
+ }
109
+ const structuredEvidence = commandForEvidence(structuredCommand, redact);
110
+
111
+ return {
112
+ cliVersion: capability({
113
+ status: 'unknown',
114
+ command: commandForEvidence([mcode, '--version'], redact),
115
+ observation: 'Not executed.',
116
+ }),
117
+ cliHelp: capability({
118
+ status: 'unknown',
119
+ command: commandForEvidence([mcode, '--help'], redact),
120
+ observation: 'Not executed.',
121
+ }),
122
+ freshInit: capability({
123
+ status: 'unknown',
124
+ command: commandForEvidence([mcode, 'init', workdir], redact),
125
+ observation: 'Not executed.',
126
+ }),
127
+ rootAgents: capability({
128
+ status: 'unknown',
129
+ command: structuredEvidence,
130
+ observation: 'Not executed.',
131
+ }),
132
+ referencedRule: capability({
133
+ status: 'unknown',
134
+ command: structuredEvidence,
135
+ observation: 'Not executed.',
136
+ }),
137
+ referencedSkill: capability({
138
+ status: 'unknown',
139
+ command: structuredEvidence,
140
+ observation: 'Not executed.',
141
+ }),
142
+ explicitAgentFile: capability({
143
+ status: 'unknown',
144
+ command: commandForEvidence(roleCommand, redact),
145
+ observation: 'Not executed.',
146
+ }),
147
+ structuredOutput: capability({
148
+ status: 'unknown',
149
+ command: structuredEvidence,
150
+ observation: 'Not executed.',
151
+ }),
152
+ nativeProjectRules: capability({
153
+ status: 'unknown',
154
+ command: structuredEvidence,
155
+ observation: 'Not executed.',
156
+ }),
157
+ nativeWorkspaceSkills: capability({
158
+ status: 'unknown',
159
+ command: structuredEvidence,
160
+ observation: 'Not executed.',
161
+ }),
162
+ nativeWorkspaceAgents: capability({
163
+ status: 'unknown',
164
+ command: structuredEvidence,
165
+ observation: 'Not executed.',
166
+ }),
167
+ projectMcp: capability({
168
+ status: 'unknown',
169
+ command: documentedMcpCommand,
170
+ observation:
171
+ 'Documented inspection command only; not executed to avoid reading or changing user-global MCP state.',
172
+ }),
173
+ projectHooks: capability({
174
+ status: 'unknown',
175
+ command: null,
176
+ observation:
177
+ 'No documented project hook path is assumed; manual chain execution remains the fallback.',
178
+ }),
179
+ slashCommands: capability({
180
+ status: 'unknown',
181
+ command: null,
182
+ observation:
183
+ 'No file-defined slash command API is assumed; command files remain explicit procedures.',
184
+ }),
185
+ pluginSkillMcp: capability({
186
+ status: 'confirmed',
187
+ command: null,
188
+ observation:
189
+ 'Plugin Skill (`skills/**/SKILL.md`) and plugin MCP (`*.mcp.json`) formats are confirmed from official MiniMax documentation; local plugin installation was not executed by this probe.',
190
+ }),
191
+ nativeTeam: capability({
192
+ status: 'partial',
193
+ command: null,
194
+ observation:
195
+ 'Official Team documentation describes Leader, Worker, and Verifier; programmatic bridge controls were not executed and remain unverified.',
196
+ }),
197
+ };
198
+ }
199
+
200
+ function restoreSpawnArgs(command, workdir) {
201
+ return command.slice(1).map((argument) => (argument === '<WORKDIR>' ? workdir : argument));
202
+ }
203
+
204
+ function runMcode(mcode, args, workdir, redact, isolatedHome) {
205
+ const result = spawnSync(mcode, args, {
206
+ cwd: workdir,
207
+ encoding: 'utf8',
208
+ env: {
209
+ ...process.env,
210
+ HOME: isolatedHome,
211
+ },
212
+ });
213
+ const exitCode = Number.isInteger(result.status) ? result.status : null;
214
+ let observation = `${result.stdout ?? ''}${result.stderr ?? ''}`.trim();
215
+ if (result.error?.code === 'ENOENT') {
216
+ observation = 'Executable not found.';
217
+ } else if (result.error) {
218
+ observation = result.error.message;
219
+ }
220
+ return {
221
+ exitCode,
222
+ observation: redact(observation || `Exited with code ${exitCode}.`),
223
+ stdout: result.stdout ?? '',
224
+ };
225
+ }
226
+
227
+ function runInit(mcode, workdir, redact, isolatedHome) {
228
+ return runMcode(mcode, ['init', workdir], workdir, redact, isolatedHome);
229
+ }
230
+
231
+ const AUTH_SEED_ENTRIES = ['cli-auth', 'local-runtime.auth.json', 'config.yaml'];
232
+
233
+ function seedIsolatedAuth(operatorHome, isolatedHome) {
234
+ const sourceRoot = path.join(operatorHome, '.minimax');
235
+ const destinationRoot = path.join(isolatedHome, '.minimax');
236
+ if (!fs.existsSync(sourceRoot)) return { seeded: false, entries: [] };
237
+ const seeded = [];
238
+ for (const entry of AUTH_SEED_ENTRIES) {
239
+ const source = path.join(sourceRoot, entry);
240
+ if (!fs.existsSync(source)) continue;
241
+ const destination = path.join(destinationRoot, entry);
242
+ fs.cpSync(source, destination, { recursive: true });
243
+ seeded.push(entry);
244
+ }
245
+ return { seeded: seeded.length > 0, entries: seeded };
246
+ }
247
+
248
+ function copyProbeInputs(workdir, relativeInputs) {
249
+ for (const relativeInput of relativeInputs) {
250
+ const source = path.join(fixtureDirectory, relativeInput);
251
+ const destination = path.join(workdir, relativeInput);
252
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
253
+ fs.copyFileSync(source, destination);
254
+ }
255
+ }
256
+
257
+ function extractSentinels(value) {
258
+ const text = typeof value === 'string' ? value : JSON.stringify(value ?? '');
259
+ return [...new Set(text.match(/MAVIS_[A-Z_]+_SENTINEL/g) ?? [])];
260
+ }
261
+
262
+ function parseStructuredOutput(stdout) {
263
+ const parsed = JSON.parse(stdout);
264
+ if (parsed?.status === 'ok' && Array.isArray(parsed.sentinels)) {
265
+ return parsed;
266
+ }
267
+ if (parsed?.type === 'exec.result') {
268
+ const sentinels = extractSentinels(parsed.output);
269
+ if (parsed.status === 'succeeded' || sentinels.length > 0) {
270
+ return {
271
+ status: 'ok',
272
+ sentinels,
273
+ observation: `mcode wrapper status ${parsed.status}`,
274
+ };
275
+ }
276
+ throw new Error(`exec.result status ${parsed.status}`);
277
+ }
278
+ throw new Error('Structured output did not match a known probe or mcode wrapper shape');
279
+ }
280
+
281
+ function updateExecutionCapability(target, result, status, observation) {
282
+ target.status = status;
283
+ target.exitCode = result.exitCode;
284
+ target.observation = observation;
285
+ target.executed = true;
286
+ }
287
+
288
+ function writeEvidence(evidence, exitCode) {
289
+ process.stdout.write(`${JSON.stringify(evidence, null, 2)}\n`);
290
+ process.exitCode = exitCode;
291
+ }
292
+
293
+ function sentinelSet(parsed) {
294
+ return new Set(parsed?.sentinels ?? []);
295
+ }
296
+
297
+ let options;
298
+ try {
299
+ options = parseArguments(process.argv.slice(2));
300
+ } catch (error) {
301
+ process.stdout.write(
302
+ `${JSON.stringify({ schemaVersion: 1, probeStatus: 'blocked', error: error.message }, null, 2)}\n`,
303
+ );
304
+ process.exitCode = 2;
305
+ }
306
+
307
+ if (options) {
308
+ const { mcode, workdir } = options;
309
+ let isolatedHome;
310
+ try {
311
+ isolatedHome = fs.mkdtempSync(path.join(os.tmpdir(), 'mavis-probe-home-'));
312
+ const operatorHome = process.env.HOME || os.homedir();
313
+ const authSeed = seedIsolatedAuth(operatorHome, isolatedHome);
314
+ const redact = createRedactor({ mcode, workdir, isolatedHome });
315
+ const capabilities = createCapabilities(redact, mcode, workdir);
316
+ const evidence = {
317
+ schemaVersion: 1,
318
+ probeStatus: 'completed',
319
+ cli: {
320
+ executable: '<MCODE>',
321
+ version: null,
322
+ },
323
+ os: {
324
+ platform: os.platform(),
325
+ release: os.release(),
326
+ arch: os.arch(),
327
+ },
328
+ workdir: '<WORKDIR>',
329
+ authSeed: {
330
+ seeded: authSeed.seeded,
331
+ entries: authSeed.entries,
332
+ },
333
+ capabilities,
334
+ };
335
+
336
+ fs.mkdirSync(workdir, { recursive: true });
337
+ if (fs.readdirSync(workdir).length > 0) {
338
+ evidence.probeStatus = 'blocked';
339
+ capabilities.freshInit.observation = 'Workdir must be empty before the probe starts.';
340
+ writeEvidence(evidence, 2);
341
+ } else {
342
+ const version = runMcode(mcode, ['--version'], workdir, redact, isolatedHome);
343
+ const versionText = redact(version.stdout).split(/\r?\n/, 1)[0] || null;
344
+ updateExecutionCapability(
345
+ capabilities.cliVersion,
346
+ version,
347
+ version.exitCode === 0 && versionText ? 'confirmed' : 'unknown',
348
+ version.exitCode === 0 && versionText ? versionText : version.observation,
349
+ );
350
+
351
+ if (capabilities.cliVersion.status !== 'confirmed') {
352
+ evidence.probeStatus = 'blocked';
353
+ writeEvidence(evidence, 2);
354
+ } else {
355
+ evidence.cli.version = versionText;
356
+
357
+ const help = runMcode(mcode, ['--help'], workdir, redact, isolatedHome);
358
+ updateExecutionCapability(
359
+ capabilities.cliHelp,
360
+ help,
361
+ help.exitCode === 0 ? 'confirmed' : 'unknown',
362
+ help.observation,
363
+ );
364
+
365
+ const init = runInit(mcode, workdir, redact, isolatedHome);
366
+ updateExecutionCapability(
367
+ capabilities.freshInit,
368
+ init,
369
+ init.exitCode === 0 ? 'confirmed' : 'unknown',
370
+ init.observation,
371
+ );
372
+
373
+ copyProbeInputs(workdir, LIBRARY_INPUTS);
374
+
375
+ const nativeArgs = restoreSpawnArgs(capabilities.nativeProjectRules.command, workdir);
376
+ const nativeResult = runMcode(mcode, nativeArgs, workdir, redact, isolatedHome);
377
+ let nativeOutput = null;
378
+ try {
379
+ nativeOutput = nativeResult.exitCode === 0 ? parseStructuredOutput(nativeResult.stdout) : null;
380
+ } catch (error) {
381
+ nativeResult.observation = redact(error.message);
382
+ }
383
+ const nativeSentinels = sentinelSet(nativeOutput);
384
+ const nativeObservation = redact(nativeOutput?.observation ?? nativeResult.observation);
385
+ updateExecutionCapability(
386
+ capabilities.nativeProjectRules,
387
+ nativeResult,
388
+ nativeSentinels.has('MAVIS_RULE_SENTINEL') ? 'confirmed' : 'unknown',
389
+ nativeSentinels.has('MAVIS_RULE_SENTINEL')
390
+ ? 'Rule sentinel returned without an explicit root AGENTS.md reference.'
391
+ : nativeObservation,
392
+ );
393
+ updateExecutionCapability(
394
+ capabilities.nativeWorkspaceSkills,
395
+ nativeResult,
396
+ nativeSentinels.has('MAVIS_SKILL_SENTINEL') ? 'confirmed' : 'unknown',
397
+ nativeSentinels.has('MAVIS_SKILL_SENTINEL')
398
+ ? 'Skill sentinel returned without an explicit root AGENTS.md reference.'
399
+ : nativeObservation,
400
+ );
401
+ updateExecutionCapability(
402
+ capabilities.nativeWorkspaceAgents,
403
+ nativeResult,
404
+ nativeSentinels.has('MAVIS_AGENT_FILE_SENTINEL') ? 'confirmed' : 'unknown',
405
+ nativeSentinels.has('MAVIS_AGENT_FILE_SENTINEL')
406
+ ? 'Agent sentinel returned without mcode exec --file.'
407
+ : nativeObservation,
408
+ );
409
+
410
+ copyProbeInputs(workdir, ['AGENTS.md']);
411
+
412
+ const rootArgs = restoreSpawnArgs(capabilities.rootAgents.command, workdir);
413
+ const rootResult = runMcode(mcode, rootArgs, workdir, redact, isolatedHome);
414
+ let rootOutput = null;
415
+ try {
416
+ rootOutput = rootResult.exitCode === 0 ? parseStructuredOutput(rootResult.stdout) : null;
417
+ } catch (error) {
418
+ rootResult.observation = redact(error.message);
419
+ }
420
+ const rootSentinels = sentinelSet(rootOutput);
421
+ updateExecutionCapability(
422
+ capabilities.rootAgents,
423
+ rootResult,
424
+ rootSentinels.has('MAVIS_AGENTS_SENTINEL') ? 'confirmed' : 'unknown',
425
+ redact(rootOutput?.observation ?? rootResult.observation),
426
+ );
427
+ updateExecutionCapability(
428
+ capabilities.referencedRule,
429
+ rootResult,
430
+ rootSentinels.has('MAVIS_RULE_SENTINEL') ? 'confirmed' : 'unknown',
431
+ rootSentinels.has('MAVIS_RULE_SENTINEL')
432
+ ? 'Rule sentinel returned through the explicit root AGENTS.md reference.'
433
+ : rootResult.observation,
434
+ );
435
+ updateExecutionCapability(
436
+ capabilities.referencedSkill,
437
+ rootResult,
438
+ rootSentinels.has('MAVIS_SKILL_SENTINEL') ? 'confirmed' : 'unknown',
439
+ rootSentinels.has('MAVIS_SKILL_SENTINEL')
440
+ ? 'Skill sentinel returned through the explicit root AGENTS.md reference.'
441
+ : rootResult.observation,
442
+ );
443
+ updateExecutionCapability(
444
+ capabilities.structuredOutput,
445
+ rootResult,
446
+ rootOutput ? 'confirmed' : 'unknown',
447
+ rootOutput
448
+ ? 'Output parsed as JSON and matched the required probe fields.'
449
+ : rootResult.observation,
450
+ );
451
+
452
+ const roleArgs = restoreSpawnArgs(capabilities.explicitAgentFile.command, workdir);
453
+ const roleResult = runMcode(mcode, roleArgs, workdir, redact, isolatedHome);
454
+ let roleOutput = null;
455
+ try {
456
+ roleOutput = roleResult.exitCode === 0 ? parseStructuredOutput(roleResult.stdout) : null;
457
+ } catch (error) {
458
+ roleResult.observation = redact(error.message);
459
+ }
460
+ updateExecutionCapability(
461
+ capabilities.explicitAgentFile,
462
+ roleResult,
463
+ roleOutput?.sentinels.includes('MAVIS_AGENT_FILE_SENTINEL') ? 'confirmed' : 'unknown',
464
+ redact(roleOutput?.observation ?? roleResult.observation),
465
+ );
466
+
467
+ const hardNoGoObserved =
468
+ capabilities.rootAgents.status !== 'confirmed' ||
469
+ capabilities.explicitAgentFile.status !== 'confirmed' ||
470
+ capabilities.structuredOutput.status !== 'confirmed';
471
+ if (hardNoGoObserved) evidence.probeStatus = 'blocked';
472
+ writeEvidence(evidence, hardNoGoObserved ? 2 : 0);
473
+ }
474
+ }
475
+ } finally {
476
+ if (isolatedHome) {
477
+ fs.rmSync(isolatedHome, { recursive: true, force: true });
478
+ }
479
+ }
480
+ }