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,390 @@
1
+ /**
2
+ * Checkpoint Manager
3
+ *
4
+ * Maintains `.godpowers/CHECKPOINT.md`, a human-readable + agent-readable
5
+ * orientation file. Anyone (new chat session, new AI tool, returning user)
6
+ * can read this single file and know where the project is, what the last
7
+ * action was, and what comes next.
8
+ *
9
+ * Design intent (context-rot protection):
10
+ * - Long sessions cause the AI's mental model to drift from disk.
11
+ * - New sessions in any tool start with zero context.
12
+ * - CHECKPOINT.md is the disk-authoritative "you are here" pin.
13
+ * - It is updated after every significant action by the orchestrator.
14
+ * - Reads are cheap; writes are append-aware (last 20 actions kept).
15
+ *
16
+ * Schema:
17
+ * YAML frontmatter (machine-readable):
18
+ * id: CHECKPOINT-{ISO8601}
19
+ * project: {name}
20
+ * mode: {A|B|C|E}
21
+ * mode-d-suite: {bool}
22
+ * lifecycle: {pre-init|in-arc|steady-state-active|...}
23
+ * current-tier: {tier-N}
24
+ * current-substep: {substep-key}
25
+ * last-action: {action-name}
26
+ * last-actor: {agent or user}
27
+ * last-update: {ISO8601}
28
+ * facts-hash: {sha256 of the held-facts section}
29
+ * Markdown body (human-readable):
30
+ * ## Where you are
31
+ * ## Last 20 actions (most recent first)
32
+ * ## Held facts (top 10 critical decisions)
33
+ * ## Next suggested command
34
+ * ## If you're a new session
35
+ *
36
+ * Public API:
37
+ * path(projectRoot) -> string
38
+ * read(projectRoot) -> { frontmatter, body, facts, actions } | null
39
+ * write(projectRoot, state, opts) -> path
40
+ * recordAction(projectRoot, action) -> updated checkpoint
41
+ * recordFact(projectRoot, fact) -> updated checkpoint
42
+ * diff(projectRoot, aiClaim) -> { drifts, matches } (for /god-context-scan)
43
+ */
44
+
45
+ const fs = require('fs');
46
+ const path = require('path');
47
+ const crypto = require('crypto');
48
+
49
+ const MAX_ACTIONS = 20;
50
+ const MAX_FACTS = 10;
51
+
52
+ function checkpointPath(projectRoot) {
53
+ return path.join(projectRoot, '.godpowers', 'CHECKPOINT.md');
54
+ }
55
+
56
+ function sha256(s) {
57
+ return crypto.createHash('sha256').update(s).digest('hex');
58
+ }
59
+
60
+ function nowIso() {
61
+ return new Date().toISOString();
62
+ }
63
+
64
+ /**
65
+ * Parse a CHECKPOINT.md file. Returns structured form or null if missing.
66
+ */
67
+ function read(projectRoot) {
68
+ const file = checkpointPath(projectRoot);
69
+ if (!fs.existsSync(file)) return null;
70
+ const raw = fs.readFileSync(file, 'utf8');
71
+
72
+ // Frontmatter parse
73
+ let frontmatter = {};
74
+ let body = raw;
75
+ if (raw.startsWith('---')) {
76
+ const end = raw.indexOf('\n---', 3);
77
+ if (end > 0) {
78
+ const fmText = raw.slice(3, end).trim();
79
+ body = raw.slice(end + 4).trim();
80
+ for (const line of fmText.split('\n')) {
81
+ const m = line.match(/^([\w-]+):\s*(.*)$/);
82
+ if (m) {
83
+ let v = m[2].trim();
84
+ if (v === 'true') v = true;
85
+ else if (v === 'false') v = false;
86
+ frontmatter[m[1]] = v;
87
+ }
88
+ }
89
+ }
90
+ }
91
+
92
+ // Section parse for actions and facts
93
+ const actions = parseList(body, 'Last actions');
94
+ const facts = parseList(body, 'Held facts');
95
+
96
+ return { path: file, frontmatter, body, actions, facts };
97
+ }
98
+
99
+ function parseList(body, heading) {
100
+ const re = new RegExp(`##\\s+${heading}[^\\n]*\\n([\\s\\S]*?)(?:\\n##\\s|$)`, 'i');
101
+ const m = body.match(re);
102
+ if (!m) return [];
103
+ return m[1].split('\n')
104
+ .map(l => l.trim())
105
+ .filter(l => l.startsWith('- '))
106
+ .map(l => l.slice(2));
107
+ }
108
+
109
+ /**
110
+ * Write a fresh CHECKPOINT.md. Overwrites prior content.
111
+ *
112
+ * state shape:
113
+ * { project, mode, modeDSuite, lifecycle, currentTier, currentSubstep,
114
+ * lastAction, lastActor, actions: [...], facts: [...], nextCommand,
115
+ * nextReason }
116
+ */
117
+ function write(projectRoot, state) {
118
+ const file = checkpointPath(projectRoot);
119
+ fs.mkdirSync(path.dirname(file), { recursive: true });
120
+
121
+ const ts = nowIso();
122
+ const id = `CHECKPOINT-${ts.replace(/[:.]/g, '-')}`;
123
+ const actions = (state.actions || []).slice(0, MAX_ACTIONS);
124
+ const facts = (state.facts || []).slice(0, MAX_FACTS);
125
+ const factsHash = sha256(JSON.stringify(facts));
126
+
127
+ const fm = [
128
+ '---',
129
+ `id: ${id}`,
130
+ `project: ${state.project || 'unnamed'}`,
131
+ `mode: ${state.mode || '?'}`,
132
+ `mode-d-suite: ${state.modeDSuite ? 'true' : 'false'}`,
133
+ `lifecycle: ${state.lifecycle || 'in-arc'}`,
134
+ `current-tier: ${state.currentTier || 'tier-0'}`,
135
+ `current-substep: ${state.currentSubstep || 'orchestration'}`,
136
+ `last-action: ${state.lastAction || 'unknown'}`,
137
+ `last-actor: ${state.lastActor || 'unknown'}`,
138
+ `last-update: ${ts}`,
139
+ `facts-hash: sha256:${factsHash}`,
140
+ '---',
141
+ ''
142
+ ].join('\n');
143
+
144
+ const body = [
145
+ '# Checkpoint',
146
+ '',
147
+ '> **For a new chat session or new AI tool**: read this file first.',
148
+ '> It is the authoritative "where you are" pin for this Godpowers project.',
149
+ '> Disk state always wins over conversation memory.',
150
+ '',
151
+ '## Where you are',
152
+ '',
153
+ `- Project: **${state.project || 'unnamed'}**`,
154
+ `- Mode: **${state.mode || '?'}**${state.modeDSuite ? ' (in multi-repo suite)' : ''}`,
155
+ `- Lifecycle phase: **${state.lifecycle || 'in-arc'}**`,
156
+ `- Current tier: **${state.currentTier || 'tier-0'}** / **${state.currentSubstep || 'orchestration'}**`,
157
+ `- Last action: \`${state.lastAction || 'unknown'}\` by ${state.lastActor || 'unknown'} at ${ts}`,
158
+ '',
159
+ '## Next suggested command',
160
+ '',
161
+ state.nextCommand
162
+ ? `\`${state.nextCommand}\` - ${state.nextReason || 'no reason given'}`
163
+ : 'Run `/god-next` to see the next command based on disk state.',
164
+ '',
165
+ `## Last actions (most recent first, max ${MAX_ACTIONS})`,
166
+ '',
167
+ actions.length === 0
168
+ ? '_(no actions recorded yet)_'
169
+ : actions.map(a => `- ${a}`).join('\n'),
170
+ '',
171
+ `## Held facts (top ${MAX_FACTS} critical decisions)`,
172
+ '',
173
+ facts.length === 0
174
+ ? '_(no facts recorded yet)_'
175
+ : facts.map(f => `- ${f}`).join('\n'),
176
+ '',
177
+ '## If you are a new session',
178
+ '',
179
+ '1. Read this whole file.',
180
+ '2. Run `/god-locate` for a full orientation including state.json',
181
+ ' diff and recent events.',
182
+ '3. Run `/god-status` to verify disk reality.',
183
+ '4. Run `/god-next` for the next suggested command.',
184
+ '5. If anything in this file feels inconsistent with what you',
185
+ ' know, run `/god-context-scan` to surface drift.',
186
+ '',
187
+ '## Provenance',
188
+ '',
189
+ `- Generated: ${ts}`,
190
+ `- Schema version: 1.0`,
191
+ `- Authoritative state: \`.godpowers/state.json\``,
192
+ `- Authoritative history: \`.godpowers/runs/<id>/events.jsonl\` + \`.godpowers/log\``,
193
+ ''
194
+ ].join('\n');
195
+
196
+ fs.writeFileSync(file, fm + body);
197
+ return file;
198
+ }
199
+
200
+ /**
201
+ * Append a new action to the checkpoint. Trims to MAX_ACTIONS.
202
+ *
203
+ * action shape: { ts, actor, name, details? }
204
+ */
205
+ function recordAction(projectRoot, action) {
206
+ const existing = read(projectRoot);
207
+ const actions = existing ? existing.actions.slice() : [];
208
+ const line = `[${action.ts || nowIso()}] ${action.actor || 'unknown'}: ${action.name}${action.details ? ' - ' + action.details : ''}`;
209
+ actions.unshift(line);
210
+
211
+ const state = existing ? frontmatterToState(existing.frontmatter, existing.facts) : {};
212
+ state.actions = actions;
213
+ state.lastAction = action.name;
214
+ state.lastActor = action.actor;
215
+ return write(projectRoot, state);
216
+ }
217
+
218
+ /**
219
+ * Append a new held fact. Trims to MAX_FACTS (LRU style by reorder).
220
+ */
221
+ function recordFact(projectRoot, fact) {
222
+ const existing = read(projectRoot);
223
+ const facts = existing ? existing.facts.slice() : [];
224
+ // Dedupe
225
+ const f = typeof fact === 'string' ? fact : `${fact.label}: ${fact.value}`;
226
+ const i = facts.indexOf(f);
227
+ if (i >= 0) facts.splice(i, 1);
228
+ facts.unshift(f);
229
+
230
+ const state = existing ? frontmatterToState(existing.frontmatter, facts) : { facts };
231
+ state.facts = facts;
232
+ return write(projectRoot, state);
233
+ }
234
+
235
+ function frontmatterToState(fm, facts) {
236
+ return {
237
+ project: fm.project,
238
+ mode: fm.mode,
239
+ modeDSuite: fm['mode-d-suite'] === true || fm['mode-d-suite'] === 'true',
240
+ lifecycle: fm.lifecycle,
241
+ currentTier: fm['current-tier'],
242
+ currentSubstep: fm['current-substep'],
243
+ lastAction: fm['last-action'],
244
+ lastActor: fm['last-actor'],
245
+ facts: facts || []
246
+ };
247
+ }
248
+
249
+ /**
250
+ * Compare the AI's claim about state with disk.
251
+ *
252
+ * aiClaim shape: { project, mode, lifecycle, currentTier, currentSubstep, lastAction }
253
+ *
254
+ * Returns { drifts: [...], matches: [...] }.
255
+ * Each drift: { field, claimed, actual }.
256
+ */
257
+ function diff(projectRoot, aiClaim) {
258
+ const cp = read(projectRoot);
259
+ if (!cp) return { drifts: [{ field: 'checkpoint', claimed: aiClaim, actual: 'no checkpoint file' }], matches: [] };
260
+
261
+ const drifts = [];
262
+ const matches = [];
263
+ const state = cp.frontmatter;
264
+ for (const [k, claim] of Object.entries(aiClaim || {})) {
265
+ const mapped = {
266
+ project: state.project,
267
+ mode: state.mode,
268
+ modeDSuite: state['mode-d-suite'],
269
+ lifecycle: state.lifecycle,
270
+ currentTier: state['current-tier'],
271
+ currentSubstep: state['current-substep'],
272
+ lastAction: state['last-action']
273
+ }[k];
274
+ if (String(claim) === String(mapped)) {
275
+ matches.push({ field: k, value: claim });
276
+ } else {
277
+ drifts.push({ field: k, claimed: claim, actual: mapped });
278
+ }
279
+ }
280
+ return { drifts, matches };
281
+ }
282
+
283
+ /**
284
+ * Reconstruct the checkpoint from current disk state.
285
+ * Use when the orchestrator finishes a sub-step and wants to refresh
286
+ * the pin in one call instead of fine-grained recordAction calls.
287
+ *
288
+ * Reads .godpowers/state.json and .godpowers/runs/<latest>/events.jsonl
289
+ * to derive: project, mode, lifecycle, current tier/substep, last action,
290
+ * and the most recent action stream.
291
+ *
292
+ * opts:
293
+ * extraFacts: string[] - facts to also record (prepended)
294
+ * nextCommand: string - next suggested command
295
+ * nextReason: string - reason for the suggestion
296
+ *
297
+ * Returns the path to the written checkpoint.
298
+ */
299
+ function syncFromState(projectRoot, opts = {}) {
300
+ // Defer the requires so checkpoint.js stays a leaf module
301
+ const state = require('./state');
302
+ const events = require('./events');
303
+
304
+ const s = state.read(projectRoot);
305
+ if (!s) throw new Error('state.json not initialized');
306
+
307
+ // Find the current tier + sub-step: first one with status in-flight,
308
+ // else last one done, else tier-0/orchestration.
309
+ let currentTier = 'tier-0';
310
+ let currentSubstep = 'orchestration';
311
+ let lastAction = 'init';
312
+ let lastUpdate = null;
313
+ let lastActor = 'unknown';
314
+ if (s.tiers) {
315
+ outer: for (const tierKey of Object.keys(s.tiers).sort()) {
316
+ for (const [substepKey, sub] of Object.entries(s.tiers[tierKey])) {
317
+ if (sub.status === 'in-flight') {
318
+ currentTier = tierKey;
319
+ currentSubstep = substepKey;
320
+ break outer;
321
+ }
322
+ if (sub.status === 'done' && sub.updated) {
323
+ if (!lastUpdate || sub.updated > lastUpdate) {
324
+ lastUpdate = sub.updated;
325
+ currentTier = tierKey;
326
+ currentSubstep = substepKey;
327
+ lastAction = `${tierKey}.${substepKey} done`;
328
+ }
329
+ }
330
+ }
331
+ }
332
+ }
333
+
334
+ // Pull last 20 actions from events tail
335
+ const runs = events.listRuns(projectRoot);
336
+ const actions = [];
337
+ if (runs.length > 0) {
338
+ const latest = runs[runs.length - 1];
339
+ const all = events.readRun(projectRoot, latest);
340
+ // Walk backward; emit lines for human-significant events
341
+ const significant = ['agent.end', 'agent.pause', 'gate.fail', 'gate.pass',
342
+ 'tier.skip', 'state.repair', 'state.rollback',
343
+ 'extension.install', 'error'];
344
+ for (let i = all.length - 1; i >= 0 && actions.length < MAX_ACTIONS; i--) {
345
+ const e = all[i];
346
+ if (!significant.includes(e.name)) continue;
347
+ const tier = (e.attrs && e.attrs.tier) ? `[${e.attrs.tier}] ` : '';
348
+ const agent = (e.attrs && e.attrs.agent) ? e.attrs.agent + ': ' : '';
349
+ actions.push(`[${e.ts}] ${tier}${agent}${e.name}`);
350
+ if (i === all.length - 1) {
351
+ lastAction = e.name;
352
+ lastActor = (e.attrs && e.attrs.agent) || 'system';
353
+ }
354
+ }
355
+ }
356
+
357
+ // Carry forward existing facts; prepend new ones from opts
358
+ const existing = read(projectRoot);
359
+ const facts = (opts.extraFacts || []).concat(
360
+ existing ? existing.facts : []
361
+ ).slice(0, MAX_FACTS);
362
+
363
+ return write(projectRoot, {
364
+ project: s.project && s.project.name,
365
+ mode: s.mode,
366
+ modeDSuite: !!s['mode-d-suite'],
367
+ lifecycle: s['lifecycle-phase'] || 'in-arc',
368
+ currentTier,
369
+ currentSubstep,
370
+ lastAction,
371
+ lastActor,
372
+ actions,
373
+ facts,
374
+ nextCommand: opts.nextCommand,
375
+ nextReason: opts.nextReason
376
+ });
377
+ }
378
+
379
+ module.exports = {
380
+ checkpointPath,
381
+ path: checkpointPath,
382
+ read,
383
+ write,
384
+ recordAction,
385
+ recordFact,
386
+ syncFromState,
387
+ diff,
388
+ MAX_ACTIONS,
389
+ MAX_FACTS
390
+ };
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Code Scanner
3
+ *
4
+ * Scans a codebase for linkage signals between code and artifact IDs.
5
+ *
6
+ * Discovery mechanisms:
7
+ * 1. Comment annotations: // Implements: P-MUST-01, // ADR-007, // Token: {colors.primary}
8
+ * 2. Filename heuristics: src/components/Button.tsx -> D-button-primary; src/auth/ -> C-auth-service
9
+ * 3. Import analysis: importing a STACK dep links to its decision ID
10
+ * 4. Style-system parsing: tokens used in CSS / styled-components / Tailwind
11
+ * 5. Test descriptions: describe('P-MUST-01: user can log in') -> link
12
+ *
13
+ * Returns structured links: [{ artifactId, file, source, line? }]
14
+ *
15
+ * Public API:
16
+ * scan(projectRoot, opts) -> { links, stats }
17
+ * scanFile(filePath, opts) -> [...links from this file]
18
+ * parseAnnotation(line) -> [...] // exposed for testing
19
+ */
20
+
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+
24
+ const linkage = require('./linkage');
25
+
26
+ // ============================================================================
27
+ // Annotation patterns (across languages, comment styles)
28
+ // ============================================================================
29
+
30
+ // Match: `// Implements: P-MUST-01` or `# Implements: P-MUST-01` etc.
31
+ const ANNOTATION_PATTERNS = [
32
+ // Implements: <id>
33
+ /(?:\/\/|\/\*|\*|#|--|<!--)\s*Implements?\s*:\s*([A-Za-z][\w.-]*(?:,\s*[A-Za-z][\w.-]*)*)/i,
34
+ // Fixes: P-MUST-NN or Fixes: incident-001
35
+ /(?:\/\/|\/\*|\*|#|--|<!--)\s*Fixes?\s*:\s*([A-Za-z][\w.-]*)/i,
36
+ // ADR-007 mentioned anywhere in a comment line
37
+ /(?:\/\/|\/\*|\*|#|--|<!--)[^\n]*\b(ADR-\d+)\b/i,
38
+ // Token: {colors.primary}
39
+ /(?:\/\/|\/\*|\*|#|--|<!--)\s*Token\s*:\s*\{([\w.-]+)\}/i,
40
+ // Pattern: ADR-007 or Source: C-auth-service
41
+ /(?:\/\/|\/\*|\*|#|--|<!--)\s*(?:Pattern|Source|Container)\s*:\s*([A-Za-z][\w.-]+)/i,
42
+ // Implements: D-button-primary (design component)
43
+ /(?:\/\/|\/\*|\*|#|--|<!--)\s*Implements?\s*:\s*(D-[\w-]+)/i
44
+ ];
45
+
46
+ const SCAN_EXTENSIONS = new Set([
47
+ '.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs',
48
+ '.py', '.go', '.rb', '.rs', '.java', '.kt', '.swift',
49
+ '.css', '.scss', '.less', '.styl',
50
+ '.html', '.vue', '.svelte', '.astro',
51
+ '.md', '.mdx',
52
+ '.yml', '.yaml',
53
+ '.sh', '.bash'
54
+ ]);
55
+
56
+ const IGNORE_DIRS = new Set([
57
+ 'node_modules', '.git', '.next', 'dist', 'build', 'out',
58
+ '.cache', '.parcel-cache', '.turbo', 'target', '__pycache__',
59
+ '.pytest_cache', '.venv', 'venv', '.tox', '.idea', '.vscode',
60
+ 'coverage', '.nyc_output', '.svelte-kit', '.vercel',
61
+ '.godpowers'
62
+ ]);
63
+
64
+ /**
65
+ * Parse a single line of source for annotations. Returns array of artifact IDs.
66
+ */
67
+ function parseAnnotation(line) {
68
+ const ids = [];
69
+ for (const pattern of ANNOTATION_PATTERNS) {
70
+ const m = line.match(pattern);
71
+ if (m && m[1]) {
72
+ // Comma-separated list support: "P-MUST-01, P-MUST-02"
73
+ const tokens = m[1].split(',').map(t => t.trim()).filter(Boolean);
74
+ ids.push(...tokens);
75
+ }
76
+ }
77
+ return [...new Set(ids)];
78
+ }
79
+
80
+ /**
81
+ * Scan a single file and return all annotation-based links.
82
+ */
83
+ function scanFile(filePath, opts = {}) {
84
+ const links = [];
85
+ if (!fs.existsSync(filePath)) return links;
86
+
87
+ const ext = path.extname(filePath);
88
+ if (!SCAN_EXTENSIONS.has(ext)) return links;
89
+
90
+ const content = fs.readFileSync(filePath, 'utf8');
91
+ const lines = content.split('\n');
92
+ for (let i = 0; i < lines.length; i++) {
93
+ const ids = parseAnnotation(lines[i]);
94
+ for (const id of ids) {
95
+ links.push({
96
+ artifactId: id,
97
+ file: filePath,
98
+ source: 'annotation',
99
+ line: i + 1
100
+ });
101
+ }
102
+ }
103
+ return links;
104
+ }
105
+
106
+ /**
107
+ * Filename heuristic: src/components/Button.tsx -> [D-button]
108
+ */
109
+ function filenameHeuristic(filePath, projectRoot) {
110
+ const links = [];
111
+ const rel = path.relative(projectRoot, filePath);
112
+
113
+ // src/components/Button.tsx -> D-button
114
+ const compMatch = rel.match(/components?\/([\w-]+)\.(tsx?|jsx?|vue|svelte)$/i);
115
+ if (compMatch) {
116
+ const slug = kebab(compMatch[1]);
117
+ links.push({ artifactId: `D-${slug}`, file: filePath, source: 'filename' });
118
+ }
119
+
120
+ // src/auth/foo.ts -> C-auth-service (if matches container slug pattern)
121
+ const containerMatch = rel.match(/^(?:src|lib|app|services?)\/([a-z][\w-]*)/);
122
+ if (containerMatch) {
123
+ const slug = containerMatch[1];
124
+ // Heuristic: only treat as container if the slug looks service-y
125
+ if (/service|server|api|db|auth|core/i.test(slug)) {
126
+ links.push({ artifactId: `C-${slug}`, file: filePath, source: 'filename' });
127
+ }
128
+ }
129
+ return links;
130
+ }
131
+
132
+ /**
133
+ * Style-system: scan CSS/JSX for token references like var(--colors-primary)
134
+ * or Tailwind class fragments that look like our tokens.
135
+ */
136
+ function styleSystemScan(filePath, opts = {}) {
137
+ const links = [];
138
+ const ext = path.extname(filePath);
139
+ if (!['.css', '.scss', '.less', '.styl', '.tsx', '.jsx', '.vue', '.svelte', '.html'].includes(ext)) {
140
+ return links;
141
+ }
142
+ if (!fs.existsSync(filePath)) return links;
143
+ const content = fs.readFileSync(filePath, 'utf8');
144
+
145
+ // CSS variables: var(--colors-primary) or var(--token-name)
146
+ // Tokens like `colors.primary` get translated to CSS vars `--colors-primary`
147
+ const cssVarRegex = /var\(--([a-z][\w-]*)\)/g;
148
+ let m;
149
+ while ((m = cssVarRegex.exec(content)) !== null) {
150
+ const cssName = m[1]; // e.g., "colors-primary"
151
+ // Convert back to token path: colors-primary -> colors.primary (heuristic)
152
+ const tokenPath = cssName.replace(/-/g, '.');
153
+ if (linkage.classifyId(tokenPath) === 'token') {
154
+ links.push({ artifactId: tokenPath, file: filePath, source: 'css-var' });
155
+ }
156
+ }
157
+
158
+ // Direct {token.path} references in styled-components or Tailwind config
159
+ const tokenRefRegex = /\{(colors|typography|spacing|rounded)\.([\w-]+)\}/g;
160
+ while ((m = tokenRefRegex.exec(content)) !== null) {
161
+ const tokenPath = `${m[1]}.${m[2]}`;
162
+ links.push({ artifactId: tokenPath, file: filePath, source: 'token-ref' });
163
+ }
164
+
165
+ return links;
166
+ }
167
+
168
+ /**
169
+ * Top-level scan: walks the project tree, applies all discovery mechanisms.
170
+ */
171
+ function scan(projectRoot, opts = {}) {
172
+ const root = path.resolve(projectRoot);
173
+ const links = [];
174
+ const stats = {
175
+ filesScanned: 0,
176
+ filesWithLinks: 0,
177
+ annotationLinks: 0,
178
+ filenameLinks: 0,
179
+ styleLinks: 0
180
+ };
181
+
182
+ function walk(dir) {
183
+ if (!fs.existsSync(dir)) return;
184
+ let entries;
185
+ try {
186
+ entries = fs.readdirSync(dir, { withFileTypes: true });
187
+ } catch (e) {
188
+ return;
189
+ }
190
+ for (const e of entries) {
191
+ const full = path.join(dir, e.name);
192
+ if (e.isDirectory()) {
193
+ if (IGNORE_DIRS.has(e.name)) continue;
194
+ walk(full);
195
+ } else if (e.isFile()) {
196
+ const ext = path.extname(e.name);
197
+ if (!SCAN_EXTENSIONS.has(ext)) continue;
198
+
199
+ stats.filesScanned++;
200
+ const before = links.length;
201
+
202
+ // 1. Annotation scan
203
+ const annLinks = scanFile(full);
204
+ links.push(...annLinks);
205
+ stats.annotationLinks += annLinks.length;
206
+
207
+ // 2. Filename heuristic
208
+ const fnLinks = filenameHeuristic(full, root);
209
+ links.push(...fnLinks);
210
+ stats.filenameLinks += fnLinks.length;
211
+
212
+ // 3. Style-system scan
213
+ if (opts.skipStyleScan !== true) {
214
+ const styleLinks = styleSystemScan(full);
215
+ links.push(...styleLinks);
216
+ stats.styleLinks += styleLinks.length;
217
+ }
218
+
219
+ if (links.length > before) stats.filesWithLinks++;
220
+ }
221
+ }
222
+ }
223
+
224
+ walk(root);
225
+ return { links, stats };
226
+ }
227
+
228
+ /**
229
+ * Apply scan results to linkage map. Returns counts of additions.
230
+ */
231
+ function applyScan(projectRoot, scanResult, opts = {}) {
232
+ const { links } = scanResult;
233
+ let added = 0;
234
+ for (const l of links) {
235
+ const r = linkage.addLink(projectRoot, l.artifactId, l.file, { source: l.source });
236
+ if (r.added) added++;
237
+ }
238
+ return { totalLinks: links.length, added };
239
+ }
240
+
241
+ // ============================================================================
242
+ // Helpers
243
+ // ============================================================================
244
+
245
+ function kebab(s) {
246
+ return s
247
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
248
+ .replace(/[\s_]+/g, '-')
249
+ .toLowerCase();
250
+ }
251
+
252
+ module.exports = {
253
+ parseAnnotation,
254
+ scanFile,
255
+ filenameHeuristic,
256
+ styleSystemScan,
257
+ scan,
258
+ applyScan,
259
+ ANNOTATION_PATTERNS,
260
+ SCAN_EXTENSIONS,
261
+ IGNORE_DIRS
262
+ };