godpowers 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (444) hide show
  1. package/AGENTS.md +37 -0
  2. package/CHANGELOG.md +639 -0
  3. package/INSPIRATION.md +52 -0
  4. package/LICENSE +21 -0
  5. package/README.md +232 -0
  6. package/SKILL.md +500 -0
  7. package/agents/god-archaeologist.md +139 -0
  8. package/agents/god-architect.md +92 -0
  9. package/agents/god-auditor.md +150 -0
  10. package/agents/god-browser-tester.md +144 -0
  11. package/agents/god-context-writer.md +137 -0
  12. package/agents/god-coordinator.md +138 -0
  13. package/agents/god-debt-assessor.md +132 -0
  14. package/agents/god-debugger.md +77 -0
  15. package/agents/god-deploy-engineer.md +87 -0
  16. package/agents/god-deps-auditor.md +111 -0
  17. package/agents/god-design-reviewer.md +137 -0
  18. package/agents/god-designer.md +171 -0
  19. package/agents/god-docs-writer.md +102 -0
  20. package/agents/god-executor.md +76 -0
  21. package/agents/god-explorer.md +110 -0
  22. package/agents/god-harden-auditor.md +163 -0
  23. package/agents/god-incident-investigator.md +144 -0
  24. package/agents/god-launch-strategist.md +103 -0
  25. package/agents/god-migration-strategist.md +126 -0
  26. package/agents/god-observability-engineer.md +76 -0
  27. package/agents/god-orchestrator.md +728 -0
  28. package/agents/god-org-context-loader.md +124 -0
  29. package/agents/god-planner.md +73 -0
  30. package/agents/god-pm.md +105 -0
  31. package/agents/god-quality-reviewer.md +74 -0
  32. package/agents/god-reconciler.md +230 -0
  33. package/agents/god-reconstructor.md +124 -0
  34. package/agents/god-repo-scaffolder.md +60 -0
  35. package/agents/god-retrospective.md +109 -0
  36. package/agents/god-roadmap-reconciler.md +123 -0
  37. package/agents/god-roadmap-updater.md +89 -0
  38. package/agents/god-roadmapper.md +82 -0
  39. package/agents/god-spec-reviewer.md +70 -0
  40. package/agents/god-spike-runner.md +119 -0
  41. package/agents/god-stack-selector.md +93 -0
  42. package/agents/god-standards-check.md +132 -0
  43. package/agents/god-storyteller.md +116 -0
  44. package/agents/god-updater.md +174 -0
  45. package/bin/install.js +514 -0
  46. package/extensions/data-pack/README.md +33 -0
  47. package/extensions/data-pack/agents/god-dashboard-builder.md +66 -0
  48. package/extensions/data-pack/agents/god-etl-engineer.md +64 -0
  49. package/extensions/data-pack/agents/god-ml-feature-engineer.md +66 -0
  50. package/extensions/data-pack/manifest.yaml +39 -0
  51. package/extensions/data-pack/package.json +42 -0
  52. package/extensions/data-pack/skills/god-dashboard.md +28 -0
  53. package/extensions/data-pack/skills/god-etl.md +28 -0
  54. package/extensions/data-pack/skills/god-ml-feature.md +28 -0
  55. package/extensions/data-pack/workflows/dashboard-arc.yaml +13 -0
  56. package/extensions/data-pack/workflows/etl-arc.yaml +13 -0
  57. package/extensions/data-pack/workflows/ml-feature-arc.yaml +13 -0
  58. package/extensions/launch-pack/README.md +36 -0
  59. package/extensions/launch-pack/agents/god-indie-hackers-strategist.md +128 -0
  60. package/extensions/launch-pack/agents/god-oss-release-strategist.md +125 -0
  61. package/extensions/launch-pack/agents/god-product-hunt-strategist.md +118 -0
  62. package/extensions/launch-pack/agents/god-show-hn-strategist.md +113 -0
  63. package/extensions/launch-pack/manifest.yaml +45 -0
  64. package/extensions/launch-pack/package.json +41 -0
  65. package/extensions/launch-pack/skills/god-indie-hackers.md +39 -0
  66. package/extensions/launch-pack/skills/god-oss-release.md +43 -0
  67. package/extensions/launch-pack/skills/god-product-hunt.md +41 -0
  68. package/extensions/launch-pack/skills/god-show-hn.md +40 -0
  69. package/extensions/launch-pack/workflows/indie-hackers.yaml +13 -0
  70. package/extensions/launch-pack/workflows/oss-release.yaml +13 -0
  71. package/extensions/launch-pack/workflows/product-hunt.yaml +13 -0
  72. package/extensions/launch-pack/workflows/show-hn.yaml +13 -0
  73. package/extensions/security-pack/README.md +48 -0
  74. package/extensions/security-pack/agents/god-hipaa-auditor.md +117 -0
  75. package/extensions/security-pack/agents/god-pci-auditor.md +100 -0
  76. package/extensions/security-pack/agents/god-soc2-auditor.md +107 -0
  77. package/extensions/security-pack/manifest.yaml +39 -0
  78. package/extensions/security-pack/package.json +42 -0
  79. package/extensions/security-pack/skills/god-hipaa-audit.md +41 -0
  80. package/extensions/security-pack/skills/god-pci-audit.md +40 -0
  81. package/extensions/security-pack/skills/god-soc2-audit.md +42 -0
  82. package/extensions/security-pack/workflows/hipaa-arc.yaml +15 -0
  83. package/extensions/security-pack/workflows/pci-arc.yaml +15 -0
  84. package/extensions/security-pack/workflows/soc2-arc.yaml +15 -0
  85. package/hooks/pre-tool-use.sh +40 -0
  86. package/hooks/session-start.sh +74 -0
  87. package/lib/README.md +28 -0
  88. package/lib/agent-browser-driver.js +215 -0
  89. package/lib/agent-cache.js +194 -0
  90. package/lib/agent-validator.js +275 -0
  91. package/lib/artifact-diff.js +168 -0
  92. package/lib/artifact-linter.js +142 -0
  93. package/lib/awesome-design.js +312 -0
  94. package/lib/browser-bridge.js +209 -0
  95. package/lib/budget.js +215 -0
  96. package/lib/checkpoint.js +390 -0
  97. package/lib/code-scanner.js +262 -0
  98. package/lib/context-budget.js +170 -0
  99. package/lib/context-writer.js +348 -0
  100. package/lib/cost-tracker.js +325 -0
  101. package/lib/cross-artifact-impact.js +162 -0
  102. package/lib/cross-repo-linkage.js +150 -0
  103. package/lib/design-detector.js +167 -0
  104. package/lib/design-spec.js +348 -0
  105. package/lib/drift-detector.js +212 -0
  106. package/lib/event-reader.js +174 -0
  107. package/lib/events.js +183 -0
  108. package/lib/extensions.js +257 -0
  109. package/lib/have-nots-validator.js +647 -0
  110. package/lib/impact.js +314 -0
  111. package/lib/impeccable-bridge.js +139 -0
  112. package/lib/intent.js +177 -0
  113. package/lib/linkage.js +232 -0
  114. package/lib/meta-linter.js +263 -0
  115. package/lib/multi-repo-detector.js +182 -0
  116. package/lib/otel-exporter.js +308 -0
  117. package/lib/recipes.js +186 -0
  118. package/lib/reverse-sync.js +332 -0
  119. package/lib/review-required.js +224 -0
  120. package/lib/router.js +278 -0
  121. package/lib/runtime-audit.js +455 -0
  122. package/lib/runtime-test.js +309 -0
  123. package/lib/skillui-bridge.js +216 -0
  124. package/lib/state-lock.js +201 -0
  125. package/lib/state.js +142 -0
  126. package/lib/story-validator.js +301 -0
  127. package/lib/suite-state.js +220 -0
  128. package/lib/workflow-parser.js +109 -0
  129. package/lib/workflow-runner.js +221 -0
  130. package/package.json +63 -0
  131. package/references/HAVE-NOTS.md +573 -0
  132. package/references/building/BUILD-ANTIPATTERNS.md +102 -0
  133. package/references/building/BUILD-VERTICAL-SLICES.md +75 -0
  134. package/references/building/BUILD-WAVES.md +61 -0
  135. package/references/building/README.md +17 -0
  136. package/references/design/COLOR.md +122 -0
  137. package/references/design/DESIGN-ANATOMY.md +121 -0
  138. package/references/design/DESIGN-ANTIPATTERNS.md +108 -0
  139. package/references/design/INTERACTION.md +148 -0
  140. package/references/design/MOTION.md +120 -0
  141. package/references/design/RESPONSIVE.md +157 -0
  142. package/references/design/SPATIAL.md +109 -0
  143. package/references/design/TYPOGRAPHY.md +121 -0
  144. package/references/design/UX-WRITING.md +135 -0
  145. package/references/orchestration/MODE-DETECTION.md +74 -0
  146. package/references/orchestration/README.md +18 -0
  147. package/references/orchestration/SCALE-DETECTION.md +81 -0
  148. package/references/planning/ARCH-ANATOMY.md +143 -0
  149. package/references/planning/ARCH-ANTIPATTERNS.md +52 -0
  150. package/references/planning/PRD-ANATOMY.md +117 -0
  151. package/references/planning/PRD-ANTIPATTERNS.md +138 -0
  152. package/references/planning/README.md +16 -0
  153. package/references/planning/ROADMAP-ANATOMY.md +43 -0
  154. package/references/planning/ROADMAP-ANTIPATTERNS.md +94 -0
  155. package/references/planning/STACK-ANATOMY.md +60 -0
  156. package/references/planning/STACK-ANTIPATTERNS.md +95 -0
  157. package/references/shared/GLOSSARY.md +80 -0
  158. package/references/shared/ORCHESTRATORS.md +76 -0
  159. package/references/shared/README.md +14 -0
  160. package/references/shipping/DEPLOY-ANTIPATTERNS.md +64 -0
  161. package/references/shipping/DEPLOY-PATTERNS.md +110 -0
  162. package/references/shipping/HARDEN-ANTIPATTERNS.md +66 -0
  163. package/references/shipping/HARDEN-OWASP-WORKSHEETS.md +89 -0
  164. package/references/shipping/LAUNCH-ANTIPATTERNS.md +68 -0
  165. package/references/shipping/OBSERVE-ANTIPATTERNS.md +62 -0
  166. package/references/shipping/OBSERVE-SLO-EXAMPLES.md +107 -0
  167. package/references/shipping/README.md +18 -0
  168. package/routing/god-add-backlog.yaml +24 -0
  169. package/routing/god-add-tests.yaml +27 -0
  170. package/routing/god-add-todo.yaml +24 -0
  171. package/routing/god-agent-audit.yaml +24 -0
  172. package/routing/god-arch.yaml +46 -0
  173. package/routing/god-archaeology.yaml +28 -0
  174. package/routing/god-audit.yaml +32 -0
  175. package/routing/god-budget.yaml +24 -0
  176. package/routing/god-build-agent.yaml +24 -0
  177. package/routing/god-build.yaml +46 -0
  178. package/routing/god-cache-clear.yaml +24 -0
  179. package/routing/god-check-todos.yaml +24 -0
  180. package/routing/god-context-scan.yaml +24 -0
  181. package/routing/god-context.yaml +44 -0
  182. package/routing/god-cost.yaml +24 -0
  183. package/routing/god-debug.yaml +28 -0
  184. package/routing/god-deploy.yaml +34 -0
  185. package/routing/god-design-impact.yaml +25 -0
  186. package/routing/god-design.yaml +67 -0
  187. package/routing/god-discuss.yaml +27 -0
  188. package/routing/god-docs.yaml +33 -0
  189. package/routing/god-doctor.yaml +27 -0
  190. package/routing/god-explore.yaml +27 -0
  191. package/routing/god-extension-add.yaml +24 -0
  192. package/routing/god-extension-info.yaml +24 -0
  193. package/routing/god-extension-list.yaml +24 -0
  194. package/routing/god-extension-remove.yaml +24 -0
  195. package/routing/god-extract-learnings.yaml +24 -0
  196. package/routing/god-fast.yaml +27 -0
  197. package/routing/god-feature.yaml +34 -0
  198. package/routing/god-graph.yaml +24 -0
  199. package/routing/god-harden.yaml +41 -0
  200. package/routing/god-help.yaml +27 -0
  201. package/routing/god-hotfix.yaml +34 -0
  202. package/routing/god-hygiene.yaml +28 -0
  203. package/routing/god-init.yaml +37 -0
  204. package/routing/god-intel.yaml +24 -0
  205. package/routing/god-launch.yaml +41 -0
  206. package/routing/god-lifecycle.yaml +27 -0
  207. package/routing/god-link.yaml +24 -0
  208. package/routing/god-lint.yaml +24 -0
  209. package/routing/god-list-assumptions.yaml +27 -0
  210. package/routing/god-locate.yaml +24 -0
  211. package/routing/god-logs.yaml +24 -0
  212. package/routing/god-map-codebase.yaml +24 -0
  213. package/routing/god-metrics.yaml +24 -0
  214. package/routing/god-mode.yaml +31 -0
  215. package/routing/god-next.yaml +27 -0
  216. package/routing/god-note.yaml +24 -0
  217. package/routing/god-observe.yaml +34 -0
  218. package/routing/god-org-context.yaml +28 -0
  219. package/routing/god-party.yaml +24 -0
  220. package/routing/god-pause-work.yaml +27 -0
  221. package/routing/god-plant-seed.yaml +24 -0
  222. package/routing/god-postmortem.yaml +34 -0
  223. package/routing/god-pr-branch.yaml +25 -0
  224. package/routing/god-prd.yaml +49 -0
  225. package/routing/god-quick.yaml +28 -0
  226. package/routing/god-reconcile.yaml +48 -0
  227. package/routing/god-reconstruct.yaml +36 -0
  228. package/routing/god-redo.yaml +27 -0
  229. package/routing/god-refactor.yaml +36 -0
  230. package/routing/god-repair.yaml +27 -0
  231. package/routing/god-repo.yaml +35 -0
  232. package/routing/god-restore.yaml +27 -0
  233. package/routing/god-resume-work.yaml +27 -0
  234. package/routing/god-review-changes.yaml +25 -0
  235. package/routing/god-review.yaml +28 -0
  236. package/routing/god-roadmap-check.yaml +39 -0
  237. package/routing/god-roadmap-update.yaml +37 -0
  238. package/routing/god-roadmap.yaml +42 -0
  239. package/routing/god-rollback.yaml +27 -0
  240. package/routing/god-scan.yaml +24 -0
  241. package/routing/god-set-profile.yaml +24 -0
  242. package/routing/god-settings.yaml +24 -0
  243. package/routing/god-skip.yaml +27 -0
  244. package/routing/god-smite.yaml +29 -0
  245. package/routing/god-spike.yaml +35 -0
  246. package/routing/god-sprint.yaml +25 -0
  247. package/routing/god-stack.yaml +41 -0
  248. package/routing/god-standards.yaml +24 -0
  249. package/routing/god-status.yaml +27 -0
  250. package/routing/god-stories.yaml +24 -0
  251. package/routing/god-story-build.yaml +25 -0
  252. package/routing/god-story-close.yaml +25 -0
  253. package/routing/god-story-verify.yaml +25 -0
  254. package/routing/god-story.yaml +24 -0
  255. package/routing/god-suite-init.yaml +24 -0
  256. package/routing/god-suite-patch.yaml +25 -0
  257. package/routing/god-suite-release.yaml +25 -0
  258. package/routing/god-suite-status.yaml +25 -0
  259. package/routing/god-suite-sync.yaml +25 -0
  260. package/routing/god-sync.yaml +33 -0
  261. package/routing/god-tech-debt.yaml +32 -0
  262. package/routing/god-test-extension.yaml +24 -0
  263. package/routing/god-test-runtime.yaml +25 -0
  264. package/routing/god-thread.yaml +24 -0
  265. package/routing/god-trace.yaml +24 -0
  266. package/routing/god-undo.yaml +27 -0
  267. package/routing/god-update-deps.yaml +39 -0
  268. package/routing/god-upgrade.yaml +33 -0
  269. package/routing/god-version.yaml +24 -0
  270. package/routing/god-workstream.yaml +24 -0
  271. package/routing/god.yaml +24 -0
  272. package/routing/recipes/add-feature-defer-current-milestone.yaml +21 -0
  273. package/routing/recipes/add-feature-future-conditional.yaml +21 -0
  274. package/routing/recipes/add-feature-mid-arc-pause.yaml +33 -0
  275. package/routing/recipes/add-feature-next-milestone.yaml +23 -0
  276. package/routing/recipes/add-feature-parallel.yaml +29 -0
  277. package/routing/recipes/add-feature-prd-update.yaml +21 -0
  278. package/routing/recipes/add-feature-small.yaml +24 -0
  279. package/routing/recipes/add-feature-tiny.yaml +24 -0
  280. package/routing/recipes/bluefield-org-aware.yaml +27 -0
  281. package/routing/recipes/broken-install.yaml +22 -0
  282. package/routing/recipes/brownfield-onboarding.yaml +32 -0
  283. package/routing/recipes/bug-no-urgency.yaml +21 -0
  284. package/routing/recipes/capture-idea.yaml +22 -0
  285. package/routing/recipes/capture-todo.yaml +21 -0
  286. package/routing/recipes/clean-pr.yaml +21 -0
  287. package/routing/recipes/code-cleanup.yaml +23 -0
  288. package/routing/recipes/docs-drift.yaml +21 -0
  289. package/routing/recipes/existing-codebase-onboarding.yaml +32 -0
  290. package/routing/recipes/extract-learnings.yaml +22 -0
  291. package/routing/recipes/greenfield-fast.yaml +25 -0
  292. package/routing/recipes/greenfield-manual.yaml +32 -0
  293. package/routing/recipes/greenfield-with-ideation.yaml +29 -0
  294. package/routing/recipes/incident-postmortem.yaml +24 -0
  295. package/routing/recipes/major-framework-upgrade.yaml +23 -0
  296. package/routing/recipes/monthly-deps.yaml +22 -0
  297. package/routing/recipes/multi-repo-suite.yaml +56 -0
  298. package/routing/recipes/parallel-engineers.yaml +26 -0
  299. package/routing/recipes/pause-handoff.yaml +21 -0
  300. package/routing/recipes/production-broken.yaml +26 -0
  301. package/routing/recipes/rerun-tier.yaml +21 -0
  302. package/routing/recipes/returning-after-break.yaml +31 -0
  303. package/routing/recipes/state-drift.yaml +21 -0
  304. package/routing/recipes/undo-last.yaml +21 -0
  305. package/routing/recipes/weekly-health-check.yaml +24 -0
  306. package/routing/recipes/whats-next.yaml +22 -0
  307. package/routing/recipes/where-am-i.yaml +21 -0
  308. package/schema/events.v1.json +63 -0
  309. package/schema/extension-manifest.v1.json +84 -0
  310. package/schema/intent.v1.yaml.json +116 -0
  311. package/schema/recipe.v1.json +120 -0
  312. package/schema/routing.v1.json +163 -0
  313. package/schema/state.v1.json +146 -0
  314. package/schema/workflow.v1.json +96 -0
  315. package/skills/god-add-backlog.md +40 -0
  316. package/skills/god-add-tests.md +53 -0
  317. package/skills/god-add-todo.md +32 -0
  318. package/skills/god-agent-audit.md +87 -0
  319. package/skills/god-arch.md +81 -0
  320. package/skills/god-archaeology.md +48 -0
  321. package/skills/god-audit.md +65 -0
  322. package/skills/god-budget.md +103 -0
  323. package/skills/god-build-agent.md +91 -0
  324. package/skills/god-build.md +90 -0
  325. package/skills/god-cache-clear.md +75 -0
  326. package/skills/god-check-todos.md +42 -0
  327. package/skills/god-context-scan.md +125 -0
  328. package/skills/god-context.md +147 -0
  329. package/skills/god-cost.md +118 -0
  330. package/skills/god-debug.md +30 -0
  331. package/skills/god-deploy.md +76 -0
  332. package/skills/god-design-impact.md +86 -0
  333. package/skills/god-design.md +275 -0
  334. package/skills/god-discuss.md +46 -0
  335. package/skills/god-docs.md +81 -0
  336. package/skills/god-doctor.md +94 -0
  337. package/skills/god-explore.md +50 -0
  338. package/skills/god-export-otel.md +87 -0
  339. package/skills/god-extension-add.md +79 -0
  340. package/skills/god-extension-info.md +75 -0
  341. package/skills/god-extension-list.md +55 -0
  342. package/skills/god-extension-remove.md +66 -0
  343. package/skills/god-extract-learnings.md +60 -0
  344. package/skills/god-fast.md +47 -0
  345. package/skills/god-feature.md +114 -0
  346. package/skills/god-graph.md +56 -0
  347. package/skills/god-harden.md +106 -0
  348. package/skills/god-help.md +66 -0
  349. package/skills/god-hotfix.md +139 -0
  350. package/skills/god-hygiene.md +104 -0
  351. package/skills/god-init.md +161 -0
  352. package/skills/god-intel.md +36 -0
  353. package/skills/god-launch.md +86 -0
  354. package/skills/god-lifecycle.md +119 -0
  355. package/skills/god-link.md +90 -0
  356. package/skills/god-lint.md +128 -0
  357. package/skills/god-list-assumptions.md +56 -0
  358. package/skills/god-locate.md +97 -0
  359. package/skills/god-logs.md +57 -0
  360. package/skills/god-map-codebase.md +45 -0
  361. package/skills/god-metrics.md +51 -0
  362. package/skills/god-mode.md +159 -0
  363. package/skills/god-next.md +257 -0
  364. package/skills/god-note.md +39 -0
  365. package/skills/god-observe.md +76 -0
  366. package/skills/god-org-context.md +81 -0
  367. package/skills/god-party.md +87 -0
  368. package/skills/god-pause-work.md +64 -0
  369. package/skills/god-plant-seed.md +59 -0
  370. package/skills/god-postmortem.md +103 -0
  371. package/skills/god-pr-branch.md +50 -0
  372. package/skills/god-prd.md +90 -0
  373. package/skills/god-quick.md +50 -0
  374. package/skills/god-reconcile.md +90 -0
  375. package/skills/god-reconstruct.md +72 -0
  376. package/skills/god-redo.md +73 -0
  377. package/skills/god-refactor.md +137 -0
  378. package/skills/god-repair.md +82 -0
  379. package/skills/god-repo.md +49 -0
  380. package/skills/god-restore.md +91 -0
  381. package/skills/god-resume-work.md +42 -0
  382. package/skills/god-review-changes.md +93 -0
  383. package/skills/god-review.md +52 -0
  384. package/skills/god-roadmap-check.md +66 -0
  385. package/skills/god-roadmap-update.md +64 -0
  386. package/skills/god-roadmap.md +77 -0
  387. package/skills/god-rollback.md +88 -0
  388. package/skills/god-scan.md +106 -0
  389. package/skills/god-set-profile.md +58 -0
  390. package/skills/god-settings.md +44 -0
  391. package/skills/god-skip.md +78 -0
  392. package/skills/god-smite.md +86 -0
  393. package/skills/god-spike.md +120 -0
  394. package/skills/god-sprint.md +77 -0
  395. package/skills/god-stack.md +74 -0
  396. package/skills/god-standards.md +62 -0
  397. package/skills/god-status.md +99 -0
  398. package/skills/god-stories.md +60 -0
  399. package/skills/god-story-build.md +76 -0
  400. package/skills/god-story-close.md +82 -0
  401. package/skills/god-story-verify.md +71 -0
  402. package/skills/god-story.md +55 -0
  403. package/skills/god-suite-init.md +75 -0
  404. package/skills/god-suite-patch.md +64 -0
  405. package/skills/god-suite-release.md +58 -0
  406. package/skills/god-suite-status.md +63 -0
  407. package/skills/god-suite-sync.md +49 -0
  408. package/skills/god-sync.md +102 -0
  409. package/skills/god-tech-debt.md +56 -0
  410. package/skills/god-test-extension.md +87 -0
  411. package/skills/god-test-runtime.md +144 -0
  412. package/skills/god-thread.md +39 -0
  413. package/skills/god-trace.md +50 -0
  414. package/skills/god-undo.md +68 -0
  415. package/skills/god-update-deps.md +134 -0
  416. package/skills/god-upgrade.md +139 -0
  417. package/skills/god-version.md +37 -0
  418. package/skills/god-workstream.md +61 -0
  419. package/skills/god.md +207 -0
  420. package/templates/ARCH.md +99 -0
  421. package/templates/DEPS-AUDIT.md +66 -0
  422. package/templates/DESIGN.md +71 -0
  423. package/templates/DOCS-UPDATE-LOG.md +64 -0
  424. package/templates/HARDEN-FINDINGS.md +69 -0
  425. package/templates/MIGRATION.md +86 -0
  426. package/templates/POSTMORTEM.md +88 -0
  427. package/templates/PRD.md +80 -0
  428. package/templates/PROGRESS.md +49 -0
  429. package/templates/ROADMAP.md +47 -0
  430. package/templates/SPIKE.md +72 -0
  431. package/templates/STACK-DECISION.md +61 -0
  432. package/workflows/audit-only.yaml +22 -0
  433. package/workflows/bluefield-arc.yaml +87 -0
  434. package/workflows/brownfield-arc.yaml +44 -0
  435. package/workflows/deps-audit.yaml +56 -0
  436. package/workflows/docs-arc.yaml +22 -0
  437. package/workflows/feature-arc.yaml +59 -0
  438. package/workflows/full-arc.yaml +84 -0
  439. package/workflows/hotfix-arc.yaml +59 -0
  440. package/workflows/hygiene.yaml +43 -0
  441. package/workflows/migration-arc.yaml +73 -0
  442. package/workflows/postmortem.yaml +31 -0
  443. package/workflows/refactor-arc.yaml +59 -0
  444. package/workflows/spike.yaml +23 -0
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Agent Browser Driver
3
+ *
4
+ * Wraps the vercel-labs/agent-browser CLI for use as a browser backend
5
+ * in the runtime verification pipeline. Native Rust binary, headless by
6
+ * default, accessibility-tree-first interaction model.
7
+ *
8
+ * Source: https://github.com/vercel-labs/agent-browser (MIT)
9
+ *
10
+ * The driver presents a uniform interface (goto, click, type, expect,
11
+ * styles, screenshot, close) that runtime-audit and runtime-test consume
12
+ * regardless of which backend is active.
13
+ *
14
+ * Headless contract: agent-browser is headless by default. We never pass
15
+ * any flag that would change that.
16
+ *
17
+ * Public API:
18
+ * openSession(opts) -> Promise<void>
19
+ * newPage() -> Promise<page-handle> // Driver acts as both browser and page
20
+ * goto(url) -> Promise<void>
21
+ * click(selector) -> Promise<void>
22
+ * type(selector, text) -> Promise<void>
23
+ * fill(selector, text) -> Promise<void>
24
+ * isVisible(selector) -> Promise<boolean>
25
+ * getStyles(selector) -> Promise<object>
26
+ * screenshot(filePath, opts) -> Promise<string>
27
+ * evaluate(fn, ...args) -> Promise<any> // limited support via `eval`
28
+ * snapshot() -> Promise<string> // accessibility tree
29
+ * close() -> Promise<void>
30
+ * isInstalled() -> bool
31
+ */
32
+
33
+ const { execSync } = require('child_process');
34
+ const path = require('path');
35
+
36
+ /**
37
+ * Detect agent-browser presence (mirror of bridge.isAgentBrowserInstalled).
38
+ */
39
+ function isInstalled() {
40
+ try {
41
+ execSync('agent-browser --version', {
42
+ stdio: ['ignore', 'pipe', 'pipe'],
43
+ timeout: 5000
44
+ });
45
+ return true;
46
+ } catch (e1) {
47
+ try {
48
+ execSync('npx --no-install agent-browser --version', {
49
+ stdio: ['ignore', 'pipe', 'pipe'],
50
+ timeout: 5000
51
+ });
52
+ return true;
53
+ } catch (e2) {
54
+ return false;
55
+ }
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Run an agent-browser CLI command and return stdout.
61
+ * Throws on non-zero exit. Times out after 30s default.
62
+ */
63
+ function run(args, opts = {}) {
64
+ const cmd = Array.isArray(args) ? args : [args];
65
+ // Quote arguments containing spaces (best-effort)
66
+ const argString = cmd.map(a => {
67
+ const s = String(a);
68
+ if (/\s/.test(s) && !s.startsWith('"')) return `"${s.replace(/"/g, '\\"')}"`;
69
+ return s;
70
+ }).join(' ');
71
+ const fullCmd = `agent-browser ${argString}`;
72
+ return execSync(fullCmd, {
73
+ stdio: ['ignore', 'pipe', 'pipe'],
74
+ timeout: opts.timeout || 30000,
75
+ cwd: opts.cwd || process.cwd(),
76
+ encoding: 'utf8'
77
+ });
78
+ }
79
+
80
+ let activeSession = null;
81
+
82
+ /**
83
+ * Open a session. agent-browser maintains the browser process between commands.
84
+ * We mark the driver as having an active session.
85
+ */
86
+ async function openSession(opts = {}) {
87
+ if (activeSession) return; // already open
88
+ // `agent-browser open` with no args launches without navigation
89
+ try {
90
+ run(['open'], { cwd: opts.cwd });
91
+ activeSession = { startedAt: Date.now(), opts };
92
+ } catch (e) {
93
+ activeSession = null;
94
+ throw new Error(`agent-browser open failed: ${e.message}`);
95
+ }
96
+ }
97
+
98
+ /**
99
+ * The driver itself acts as the page handle (single session model).
100
+ */
101
+ async function newPage() {
102
+ return module.exports;
103
+ }
104
+
105
+ async function goto(url) {
106
+ run(['open', url]);
107
+ }
108
+
109
+ async function click(selector) {
110
+ // If selector starts with @ (snapshot ref), use as-is. Otherwise try as CSS.
111
+ run(['click', selector]);
112
+ }
113
+
114
+ async function type(selector, text) {
115
+ run(['type', selector, text]);
116
+ }
117
+
118
+ async function fill(selector, text) {
119
+ run(['fill', selector, text]);
120
+ }
121
+
122
+ async function isVisible(selector) {
123
+ try {
124
+ const out = run(['is', 'visible', selector]);
125
+ return /true/i.test(out);
126
+ } catch (e) {
127
+ return false;
128
+ }
129
+ }
130
+
131
+ async function getStyles(selector) {
132
+ try {
133
+ const out = run(['get', 'styles', selector]);
134
+ try {
135
+ return JSON.parse(out);
136
+ } catch (parseErr) {
137
+ // CLI returns a key:value lines format on some versions; best-effort parse
138
+ const result = {};
139
+ for (const line of out.split('\n')) {
140
+ const m = line.match(/^([\w-]+):\s*(.+)$/);
141
+ if (m) result[m[1]] = m[2].trim();
142
+ }
143
+ return result;
144
+ }
145
+ } catch (e) {
146
+ return null;
147
+ }
148
+ }
149
+
150
+ async function screenshot(filePath, opts = {}) {
151
+ const args = ['screenshot', filePath];
152
+ if (opts.fullPage) args.push('--full');
153
+ run(args);
154
+ return filePath;
155
+ }
156
+
157
+ async function evaluate(fn, ...args) {
158
+ // CLI mode: serialize JS expression. agent-browser supports `eval <js>`.
159
+ // We can't pass functions directly; only JS expression strings.
160
+ let expr;
161
+ if (typeof fn === 'string') {
162
+ expr = fn;
163
+ } else if (typeof fn === 'function') {
164
+ // Best-effort: stringify the function and immediately invoke
165
+ const fnStr = fn.toString();
166
+ expr = `(${fnStr})(${args.map(a => JSON.stringify(a)).join(', ')})`;
167
+ } else {
168
+ throw new Error('evaluate expects a string or function');
169
+ }
170
+ const out = run(['eval', expr]);
171
+ try {
172
+ return JSON.parse(out);
173
+ } catch (e) {
174
+ return out;
175
+ }
176
+ }
177
+
178
+ async function snapshot() {
179
+ return run(['snapshot']);
180
+ }
181
+
182
+ async function close() {
183
+ try {
184
+ run(['close']);
185
+ } catch (e) {
186
+ // Already closed
187
+ }
188
+ activeSession = null;
189
+ }
190
+
191
+ /**
192
+ * Match the bridge's expected `browser.newPage` and `browser.close`
193
+ * interface so the higher-level audit/test code can treat agent-browser
194
+ * the same as Playwright.
195
+ */
196
+ module.exports = {
197
+ isInstalled,
198
+ openSession,
199
+ newPage,
200
+ goto,
201
+ click,
202
+ type,
203
+ fill,
204
+ isVisible,
205
+ getStyles,
206
+ screenshot,
207
+ evaluate,
208
+ snapshot,
209
+ close,
210
+ // Expose run for testing
211
+ _run: run,
212
+ // Expose session state
213
+ _session: () => activeSession,
214
+ _setSession: (s) => { activeSession = s; }
215
+ };
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Agent Cache - opt-in cache of agent outputs keyed by deterministic
3
+ * input hash. Cache hit = no spawn, no tokens spent.
4
+ *
5
+ * Cache key = sha256(agent_name + agent_version + sorted-inputs JSON +
6
+ * state_hash + project_mode)
7
+ *
8
+ * Storage: .godpowers/cache/<keyPrefix>/<fullKey>.json
9
+ * Each entry: {
10
+ * key, agent, agent_version, model, ts,
11
+ * inputs_hash, state_hash,
12
+ * output: <artifact text or structured result>,
13
+ * tokens: { in, out },
14
+ * ttl_ms,
15
+ * expires
16
+ * }
17
+ *
18
+ * Cache is OPT-IN. The orchestrator only consults it when
19
+ * intent.yaml.budgets.cache === true, or `/god-mode --cache` is set.
20
+ *
21
+ * Invalidation:
22
+ * - TTL expiration (default 24 hours)
23
+ * - state.json hash mismatch (downstream input changed)
24
+ * - agent version mismatch (agent was updated)
25
+ * - manual: /god-cache-clear (all) or by agent name
26
+ *
27
+ * Public API:
28
+ * cacheDir(projectRoot) -> string
29
+ * key(agent, version, inputs, stateHash) -> string
30
+ * get(projectRoot, key) -> entry | null
31
+ * put(projectRoot, key, entry) -> path
32
+ * has(projectRoot, key) -> bool (and not expired)
33
+ * clear(projectRoot, opts) -> { removed: number }
34
+ * stats(projectRoot) -> { count, totalBytes, oldestTs }
35
+ */
36
+
37
+ const fs = require('fs');
38
+ const path = require('path');
39
+ const crypto = require('crypto');
40
+
41
+ const DEFAULT_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
42
+
43
+ function cacheDir(projectRoot) {
44
+ return path.join(projectRoot, '.godpowers', 'cache');
45
+ }
46
+
47
+ /**
48
+ * Deterministically compute a cache key.
49
+ *
50
+ * inputs is normalized: top-level keys sorted, nested objects sorted
51
+ * recursively, undefined dropped. Same inputs => same key.
52
+ */
53
+ function key(agent, agent_version, inputs, stateHash) {
54
+ const stable = sortKeys(inputs || {});
55
+ const payload = JSON.stringify({
56
+ agent: agent || '',
57
+ agent_version: agent_version || '',
58
+ state_hash: stateHash || '',
59
+ inputs: stable
60
+ });
61
+ return crypto.createHash('sha256').update(payload).digest('hex');
62
+ }
63
+
64
+ function sortKeys(obj) {
65
+ if (Array.isArray(obj)) return obj.map(sortKeys);
66
+ if (obj && typeof obj === 'object') {
67
+ const out = {};
68
+ for (const k of Object.keys(obj).sort()) {
69
+ if (obj[k] === undefined) continue;
70
+ out[k] = sortKeys(obj[k]);
71
+ }
72
+ return out;
73
+ }
74
+ return obj;
75
+ }
76
+
77
+ function entryPath(projectRoot, k) {
78
+ // Shard by first 2 chars of key to keep dirs flat
79
+ return path.join(cacheDir(projectRoot), k.slice(0, 2), `${k}.json`);
80
+ }
81
+
82
+ function isExpired(entry, now) {
83
+ if (!entry || !entry.expires) return true;
84
+ return (now || Date.now()) > Date.parse(entry.expires);
85
+ }
86
+
87
+ /**
88
+ * Read a cache entry. Returns null on miss or expired.
89
+ */
90
+ function get(projectRoot, k) {
91
+ const p = entryPath(projectRoot, k);
92
+ if (!fs.existsSync(p)) return null;
93
+ let entry;
94
+ try { entry = JSON.parse(fs.readFileSync(p, 'utf8')); }
95
+ catch (e) { return null; }
96
+ if (isExpired(entry)) return null;
97
+ return entry;
98
+ }
99
+
100
+ function has(projectRoot, k) {
101
+ return get(projectRoot, k) != null;
102
+ }
103
+
104
+ /**
105
+ * Write a cache entry. Returns the file path.
106
+ */
107
+ function put(projectRoot, k, entry) {
108
+ const p = entryPath(projectRoot, k);
109
+ fs.mkdirSync(path.dirname(p), { recursive: true });
110
+ const ttl = entry.ttl_ms || DEFAULT_TTL_MS;
111
+ const full = {
112
+ key: k,
113
+ ts: new Date().toISOString(),
114
+ expires: new Date(Date.now() + ttl).toISOString(),
115
+ ttl_ms: ttl,
116
+ ...entry
117
+ };
118
+ fs.writeFileSync(p, JSON.stringify(full, null, 2));
119
+ return p;
120
+ }
121
+
122
+ /**
123
+ * Clear cache. opts:
124
+ * { all: bool, agent: string, expiredOnly: bool, olderThanMs: number }
125
+ *
126
+ * Returns { removed: <count>, kept: <count> }.
127
+ */
128
+ function clear(projectRoot, opts = {}) {
129
+ const dir = cacheDir(projectRoot);
130
+ if (!fs.existsSync(dir)) return { removed: 0, kept: 0 };
131
+
132
+ let removed = 0;
133
+ let kept = 0;
134
+ const now = Date.now();
135
+ for (const shard of fs.readdirSync(dir)) {
136
+ const shardPath = path.join(dir, shard);
137
+ if (!fs.statSync(shardPath).isDirectory()) continue;
138
+ for (const fname of fs.readdirSync(shardPath)) {
139
+ const fpath = path.join(shardPath, fname);
140
+ let entry;
141
+ try { entry = JSON.parse(fs.readFileSync(fpath, 'utf8')); }
142
+ catch (e) { fs.unlinkSync(fpath); removed++; continue; }
143
+ let shouldRemove = false;
144
+ if (opts.all) shouldRemove = true;
145
+ else if (opts.agent && entry.agent === opts.agent) shouldRemove = true;
146
+ else if (opts.expiredOnly && isExpired(entry, now)) shouldRemove = true;
147
+ else if (opts.olderThanMs && (now - Date.parse(entry.ts)) > opts.olderThanMs) shouldRemove = true;
148
+ if (shouldRemove) { fs.unlinkSync(fpath); removed++; }
149
+ else kept++;
150
+ }
151
+ // Remove empty shard dirs
152
+ if (fs.readdirSync(shardPath).length === 0) fs.rmdirSync(shardPath);
153
+ }
154
+ return { removed, kept };
155
+ }
156
+
157
+ /**
158
+ * Stats: count, total bytes, oldest entry timestamp.
159
+ */
160
+ function stats(projectRoot) {
161
+ const dir = cacheDir(projectRoot);
162
+ if (!fs.existsSync(dir)) return { count: 0, totalBytes: 0, oldestTs: null };
163
+
164
+ let count = 0;
165
+ let totalBytes = 0;
166
+ let oldestTs = null;
167
+ for (const shard of fs.readdirSync(dir)) {
168
+ const shardPath = path.join(dir, shard);
169
+ if (!fs.statSync(shardPath).isDirectory()) continue;
170
+ for (const fname of fs.readdirSync(shardPath)) {
171
+ const fpath = path.join(shardPath, fname);
172
+ const stat = fs.statSync(fpath);
173
+ totalBytes += stat.size;
174
+ count += 1;
175
+ try {
176
+ const entry = JSON.parse(fs.readFileSync(fpath, 'utf8'));
177
+ if (!oldestTs || entry.ts < oldestTs) oldestTs = entry.ts;
178
+ } catch (e) { /* skip */ }
179
+ }
180
+ }
181
+ return { count, totalBytes, oldestTs };
182
+ }
183
+
184
+ module.exports = {
185
+ cacheDir,
186
+ key,
187
+ get,
188
+ put,
189
+ has,
190
+ clear,
191
+ stats,
192
+ isExpired,
193
+ DEFAULT_TTL_MS
194
+ };
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Agent Validator
3
+ *
4
+ * Parses each `agents/*.md` and validates contract structure.
5
+ *
6
+ * Backward-compatible by design: most issues surface as `warning` so
7
+ * existing agents pass on day one. Only structural breakage (broken
8
+ * hand-off targets, dual-ownership of output paths) escalates to
9
+ * `error`.
10
+ *
11
+ * Public API:
12
+ * parseAgentFile(filePath) -> { name, frontmatter, sections, raw }
13
+ * validateAgent(agent, opts) -> [findings]
14
+ * findHandoffTargets(agent) -> [...names]
15
+ * findOutputPaths(agent) -> [...paths]
16
+ * auditAll(projectRoot, opts) -> { results, summary }
17
+ */
18
+
19
+ const fs = require('fs');
20
+ const path = require('path');
21
+
22
+ const REQUIRED_FRONTMATTER = ['name', 'description'];
23
+ const RECOMMENDED_FRONTMATTER = ['tools'];
24
+ const RECOMMENDED_SECTIONS = ['Have-Nots', 'Inputs', 'Outputs', 'Handoff'];
25
+
26
+ /**
27
+ * Parse a single agent .md file. Extract YAML frontmatter and section
28
+ * headings (# / ## / ###).
29
+ */
30
+ function parseAgentFile(filePath) {
31
+ const raw = fs.readFileSync(filePath, 'utf8');
32
+ const result = {
33
+ path: filePath,
34
+ name: path.basename(filePath, '.md'),
35
+ frontmatter: {},
36
+ sections: {}, // heading -> body string
37
+ raw
38
+ };
39
+
40
+ // Frontmatter block: --- ... ---
41
+ if (raw.startsWith('---')) {
42
+ const end = raw.indexOf('\n---', 3);
43
+ if (end > 0) {
44
+ const fmBlock = raw.slice(3, end).trim();
45
+ // Parse simple YAML (key: value, key: |, etc.)
46
+ let currentMultiline = null;
47
+ for (const line of fmBlock.split('\n')) {
48
+ if (currentMultiline) {
49
+ if (line.startsWith(' ') || line.startsWith('\t')) {
50
+ result.frontmatter[currentMultiline] += '\n' + line.trim();
51
+ continue;
52
+ }
53
+ currentMultiline = null;
54
+ }
55
+ const m = line.match(/^([\w-]+):\s*(.*)$/);
56
+ if (m) {
57
+ if (m[2] === '|' || m[2] === '>') {
58
+ currentMultiline = m[1];
59
+ result.frontmatter[m[1]] = '';
60
+ } else {
61
+ result.frontmatter[m[1]] = m[2].trim();
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+
68
+ // Sections: lines starting with # / ## / ###
69
+ const lines = raw.split('\n');
70
+ let currentHeading = null;
71
+ let currentBody = [];
72
+ for (const line of lines) {
73
+ const m = line.match(/^(#{1,4})\s+(.+?)\s*$/);
74
+ if (m) {
75
+ if (currentHeading) {
76
+ result.sections[currentHeading] = currentBody.join('\n').trim();
77
+ }
78
+ currentHeading = m[2].trim();
79
+ currentBody = [];
80
+ } else if (currentHeading) {
81
+ currentBody.push(line);
82
+ }
83
+ }
84
+ if (currentHeading) {
85
+ result.sections[currentHeading] = currentBody.join('\n').trim();
86
+ }
87
+
88
+ return result;
89
+ }
90
+
91
+ /**
92
+ * Validate one parsed agent. Returns findings.
93
+ */
94
+ function validateAgent(agent, opts = {}) {
95
+ const findings = [];
96
+
97
+ // Required frontmatter
98
+ for (const field of REQUIRED_FRONTMATTER) {
99
+ if (!agent.frontmatter[field]) {
100
+ findings.push({
101
+ severity: 'error',
102
+ kind: 'missing-required-frontmatter',
103
+ agent: agent.name,
104
+ message: `Missing required frontmatter field: \`${field}\``
105
+ });
106
+ }
107
+ }
108
+
109
+ // Recommended frontmatter
110
+ for (const field of RECOMMENDED_FRONTMATTER) {
111
+ if (!agent.frontmatter[field]) {
112
+ findings.push({
113
+ severity: 'warning',
114
+ kind: 'missing-recommended-frontmatter',
115
+ agent: agent.name,
116
+ message: `Missing recommended frontmatter field: \`${field}\``
117
+ });
118
+ }
119
+ }
120
+
121
+ // Recommended sections (case-insensitive substring match)
122
+ const sectionTitles = Object.keys(agent.sections).map(s => s.toLowerCase());
123
+ for (const section of RECOMMENDED_SECTIONS) {
124
+ const lower = section.toLowerCase();
125
+ const found = sectionTitles.some(t =>
126
+ t === lower || t.includes(lower) || (lower === 'handoff' && t.includes('hand'))
127
+ );
128
+ if (!found) {
129
+ findings.push({
130
+ severity: 'info',
131
+ kind: 'missing-recommended-section',
132
+ agent: agent.name,
133
+ message: `Missing recommended section: \`## ${section}\``,
134
+ suggestion: `Add a "${section}" section documenting the contract.`
135
+ });
136
+ }
137
+ }
138
+
139
+ return findings;
140
+ }
141
+
142
+ /**
143
+ * Extract claimed hand-off targets (other agents this agent spawns).
144
+ */
145
+ function findHandoffTargets(agent) {
146
+ const targets = new Set();
147
+ // Look for "spawn god-x", "Spawned by:", "spawns: [god-y, god-z]"
148
+ const text = agent.raw;
149
+
150
+ // "Spawned by:" indicates UPSTREAM (who spawns me); skip
151
+ // We want DOWNSTREAM: who do I spawn?
152
+
153
+ const spawnRegex = /spawn(?:s|ed|ing)?\s+(?:a\s+)?(?:fresh\s+)?`?(god-[\w-]+)`?/gi;
154
+ let m;
155
+ while ((m = spawnRegex.exec(text)) !== null) {
156
+ targets.add(m[1]);
157
+ }
158
+ return [...targets];
159
+ }
160
+
161
+ /**
162
+ * Extract output paths the agent claims to write.
163
+ */
164
+ function findOutputPaths(agent) {
165
+ const paths = new Set();
166
+ const text = agent.raw;
167
+
168
+ // .godpowers/*.md or .godpowers/*.json
169
+ const dotPathRegex = /(?:writes?|appends?|updates?)[\s\S]{0,80}?(\.godpowers\/[\w\/.-]+\.(?:md|json|jsonl|yaml))/gi;
170
+ let m;
171
+ while ((m = dotPathRegex.exec(text)) !== null) {
172
+ paths.add(m[1]);
173
+ }
174
+
175
+ // Project-root files (DESIGN.md, PRODUCT.md, AGENTS.md, etc.)
176
+ const rootRegex = /(?:writes?|appends?|updates?)[\s\S]{0,80}?\b([A-Z]+\.md)\b/g;
177
+ while ((m = rootRegex.exec(text)) !== null) {
178
+ paths.add(m[1]);
179
+ }
180
+
181
+ return [...paths];
182
+ }
183
+
184
+ /**
185
+ * Cross-agent validation: dual-ownership of output paths, unresolved
186
+ * hand-off targets.
187
+ */
188
+ function crossValidate(agents, opts = {}) {
189
+ const findings = [];
190
+ const validAgentNames = new Set(agents.map(a => a.name));
191
+ const outputOwners = {}; // path -> [agent.name, ...]
192
+
193
+ for (const agent of agents) {
194
+ // Hand-off targets must exist
195
+ for (const target of findHandoffTargets(agent)) {
196
+ if (!validAgentNames.has(target)) {
197
+ findings.push({
198
+ severity: 'warning',
199
+ kind: 'unresolved-handoff',
200
+ agent: agent.name,
201
+ message: `Agent claims to spawn \`${target}\` but no such agent file exists.`
202
+ });
203
+ }
204
+ }
205
+
206
+ // Track output paths
207
+ for (const out of findOutputPaths(agent)) {
208
+ if (!outputOwners[out]) outputOwners[out] = [];
209
+ if (!outputOwners[out].includes(agent.name)) {
210
+ outputOwners[out].push(agent.name);
211
+ }
212
+ }
213
+ }
214
+
215
+ // Dual-ownership check (warn for paths claimed by 3+ agents; the
216
+ // orchestrator + reconciler + author triumvirate is normal pattern)
217
+ for (const [outPath, owners] of Object.entries(outputOwners)) {
218
+ if (owners.length >= 4) {
219
+ findings.push({
220
+ severity: 'warning',
221
+ kind: 'multi-ownership',
222
+ path: outPath,
223
+ owners,
224
+ message: `Output \`${outPath}\` is claimed by ${owners.length} agents: ${owners.join(', ')}. Verify the boundaries are clean.`
225
+ });
226
+ }
227
+ }
228
+
229
+ return findings;
230
+ }
231
+
232
+ /**
233
+ * Walk agents/ and audit all.
234
+ */
235
+ function auditAll(projectRoot, opts = {}) {
236
+ const agentsDir = path.join(projectRoot, 'agents');
237
+ if (!fs.existsSync(agentsDir)) {
238
+ return { results: [], summary: { errors: 0, warnings: 0, infos: 0 } };
239
+ }
240
+ const files = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md'));
241
+ const agents = files.map(f => parseAgentFile(path.join(agentsDir, f)));
242
+
243
+ const allFindings = [];
244
+ const results = [];
245
+ for (const agent of agents) {
246
+ const f = validateAgent(agent, opts);
247
+ results.push({ agent: agent.name, findings: f });
248
+ allFindings.push(...f);
249
+ }
250
+ // Cross-agent
251
+ const crossFindings = crossValidate(agents, opts);
252
+ allFindings.push(...crossFindings);
253
+
254
+ const summary = {
255
+ errors: allFindings.filter(f => f.severity === 'error').length,
256
+ warnings: allFindings.filter(f => f.severity === 'warning').length,
257
+ infos: allFindings.filter(f => f.severity === 'info').length,
258
+ crossFindings,
259
+ agentCount: agents.length
260
+ };
261
+
262
+ return { results, summary, allFindings };
263
+ }
264
+
265
+ module.exports = {
266
+ parseAgentFile,
267
+ validateAgent,
268
+ findHandoffTargets,
269
+ findOutputPaths,
270
+ crossValidate,
271
+ auditAll,
272
+ REQUIRED_FRONTMATTER,
273
+ RECOMMENDED_FRONTMATTER,
274
+ RECOMMENDED_SECTIONS
275
+ };