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,201 @@
1
+ /**
2
+ * State Lock - cooperative advisory locking for state.json mutations.
3
+ *
4
+ * Contract (from ARCHITECTURE.md "Concurrency contract"):
5
+ * - Reads are lock-free.
6
+ * - Writes acquire a lock before mutating, release on completion.
7
+ * - Lock has a `scope` (e.g. `tier-1.arch`, `linkage`, `all`).
8
+ * Concurrent writers with non-overlapping scopes may run.
9
+ * - Stale locks (past `expires`) are reclaimable by any actor;
10
+ * reclaim emits state.repair with previous holder recorded.
11
+ *
12
+ * The lock lives in state.json under the `lock` key. Acquiring writes
13
+ * { holder, acquired, expires, scope }. Releasing sets lock to null.
14
+ *
15
+ * Scope conflict rules:
16
+ * - 'all' conflicts with everything.
17
+ * - 'tier-N.substep' conflicts with another 'tier-N.substep' on same
18
+ * substep AND with 'all'. Does NOT conflict with 'tier-M.substep'
19
+ * where M != N.
20
+ * - 'linkage' conflicts with 'linkage' and 'all'.
21
+ * - Any custom scope: exact-match conflict only (plus 'all').
22
+ *
23
+ * Public API:
24
+ * acquire(projectRoot, opts) -> { acquired: true, lock } | { acquired: false, reason, holder }
25
+ * release(projectRoot, holder) -> { released: bool }
26
+ * peek(projectRoot) -> lock | null
27
+ * isStale(lock, nowMs?) -> bool
28
+ * reclaim(projectRoot, holder) -> { reclaimed: bool, previousHolder? }
29
+ * scopesConflict(a, b) -> bool
30
+ */
31
+
32
+ const fs = require('fs');
33
+ const path = require('path');
34
+
35
+ const state = require('./state');
36
+
37
+ const DEFAULT_TTL_MS = 5 * 60 * 1000; // 5 minutes
38
+
39
+ function nowIso(offsetMs) {
40
+ const d = offsetMs ? new Date(Date.now() + offsetMs) : new Date();
41
+ return d.toISOString();
42
+ }
43
+
44
+ function peek(projectRoot) {
45
+ const s = state.read(projectRoot);
46
+ return s ? (s.lock || null) : null;
47
+ }
48
+
49
+ /**
50
+ * Return true if the lock is past its `expires` time (or null/malformed).
51
+ */
52
+ function isStale(lock, nowMs) {
53
+ if (!lock || !lock.expires) return true;
54
+ const t = (nowMs != null ? nowMs : Date.now());
55
+ const exp = Date.parse(lock.expires);
56
+ return Number.isFinite(exp) ? t > exp : true;
57
+ }
58
+
59
+ /**
60
+ * Determine whether two scopes conflict.
61
+ */
62
+ function scopesConflict(a, b) {
63
+ if (!a || !b) return false;
64
+ if (a === 'all' || b === 'all') return true;
65
+ return a === b;
66
+ }
67
+
68
+ /**
69
+ * Try to acquire a lock.
70
+ *
71
+ * opts: { holder (required), scope (default 'all'), ttlMs (default 5min), force }
72
+ *
73
+ * Returns { acquired: true, lock } on success.
74
+ * Returns { acquired: false, reason, holder, scope } on conflict.
75
+ *
76
+ * Reentrant: same holder can re-acquire. If the existing lock is stale,
77
+ * it is silently reclaimed.
78
+ */
79
+ function acquire(projectRoot, opts = {}) {
80
+ if (!opts.holder) throw new Error('holder is required');
81
+ const scope = opts.scope || 'all';
82
+ const ttlMs = opts.ttlMs || DEFAULT_TTL_MS;
83
+
84
+ const s = state.read(projectRoot);
85
+ if (!s) throw new Error('state.json not initialized');
86
+
87
+ const existing = s.lock || null;
88
+
89
+ if (existing && !isStale(existing) && !opts.force) {
90
+ // Reentrant: same holder + compatible scope -> refresh expiration
91
+ if (existing.holder === opts.holder &&
92
+ (existing.scope === scope || existing.scope === 'all' || scope === 'all')) {
93
+ existing.expires = nowIso(ttlMs);
94
+ s.lock = existing;
95
+ state.write(projectRoot, s);
96
+ return { acquired: true, lock: existing, reentrant: true };
97
+ }
98
+ if (scopesConflict(existing.scope || 'all', scope)) {
99
+ return {
100
+ acquired: false,
101
+ reason: 'held',
102
+ holder: existing.holder,
103
+ scope: existing.scope,
104
+ expires: existing.expires
105
+ };
106
+ }
107
+ // Compatible scopes: layered lock. We support a simple single-lock
108
+ // slot for now, so reject and tell the caller. Multi-lock support
109
+ // can be added when there's a real second writer.
110
+ return {
111
+ acquired: false,
112
+ reason: 'scope-coexistence-not-supported',
113
+ holder: existing.holder,
114
+ scope: existing.scope
115
+ };
116
+ }
117
+
118
+ // existing is null OR stale OR force -> take it
119
+ const lock = {
120
+ holder: opts.holder,
121
+ acquired: nowIso(),
122
+ expires: nowIso(ttlMs),
123
+ scope
124
+ };
125
+ const reclaimedFrom = existing && isStale(existing) ? existing.holder : null;
126
+ s.lock = lock;
127
+ state.write(projectRoot, s);
128
+ return {
129
+ acquired: true,
130
+ lock,
131
+ reclaimed: reclaimedFrom != null,
132
+ reclaimedFrom
133
+ };
134
+ }
135
+
136
+ /**
137
+ * Release a held lock. Only the current holder can release.
138
+ *
139
+ * Returns { released: true } on success, { released: false, reason } otherwise.
140
+ */
141
+ function release(projectRoot, holder) {
142
+ if (!holder) throw new Error('holder is required');
143
+ const s = state.read(projectRoot);
144
+ if (!s) return { released: false, reason: 'no-state' };
145
+ const lock = s.lock;
146
+ if (!lock) return { released: false, reason: 'no-lock' };
147
+ if (lock.holder !== holder) {
148
+ return { released: false, reason: 'wrong-holder', heldBy: lock.holder };
149
+ }
150
+ s.lock = null;
151
+ state.write(projectRoot, s);
152
+ return { released: true, releasedAt: nowIso() };
153
+ }
154
+
155
+ /**
156
+ * Force-reclaim a stale lock. Used by /god-repair.
157
+ * Returns { reclaimed, previousHolder? }.
158
+ */
159
+ function reclaim(projectRoot, holder) {
160
+ const s = state.read(projectRoot);
161
+ if (!s) return { reclaimed: false, reason: 'no-state' };
162
+ const lock = s.lock;
163
+ if (!lock) return { reclaimed: false, reason: 'no-lock' };
164
+ if (!isStale(lock)) {
165
+ return { reclaimed: false, reason: 'lock-not-stale', expires: lock.expires };
166
+ }
167
+ const prev = lock.holder;
168
+ s.lock = null;
169
+ state.write(projectRoot, s);
170
+ return { reclaimed: true, previousHolder: prev };
171
+ }
172
+
173
+ /**
174
+ * Convenience wrapper: run an async function under a lock.
175
+ * Acquires, runs, releases.
176
+ */
177
+ async function withLock(projectRoot, opts, fn) {
178
+ const r = acquire(projectRoot, opts);
179
+ if (!r.acquired) {
180
+ const err = new Error(`lock unavailable: held by ${r.holder} (scope=${r.scope})`);
181
+ err.code = 'LOCK_UNAVAILABLE';
182
+ err.detail = r;
183
+ throw err;
184
+ }
185
+ try {
186
+ return await fn(r.lock);
187
+ } finally {
188
+ release(projectRoot, opts.holder);
189
+ }
190
+ }
191
+
192
+ module.exports = {
193
+ acquire,
194
+ release,
195
+ peek,
196
+ isStale,
197
+ reclaim,
198
+ withLock,
199
+ scopesConflict,
200
+ DEFAULT_TTL_MS
201
+ };
package/lib/state.js ADDED
@@ -0,0 +1,142 @@
1
+ /**
2
+ * State Manager
3
+ *
4
+ * Read/write .godpowers/state.json with schema validation.
5
+ * Source of truth for tier statuses and artifact hashes.
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const crypto = require('crypto');
11
+
12
+ const STATE_VERSION = '1.0.0';
13
+
14
+ function statePath(projectRoot) {
15
+ return path.join(projectRoot, '.godpowers', 'state.json');
16
+ }
17
+
18
+ /**
19
+ * Read state.json from a project. Returns null if not initialized.
20
+ */
21
+ function read(projectRoot) {
22
+ const file = statePath(projectRoot);
23
+ if (!fs.existsSync(file)) return null;
24
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
25
+ }
26
+
27
+ /**
28
+ * Write state.json to a project. Validates basic structure.
29
+ */
30
+ function write(projectRoot, state) {
31
+ if (!state || typeof state !== 'object') {
32
+ throw new Error('state must be an object');
33
+ }
34
+ if (!state.version) state.version = STATE_VERSION;
35
+ if (!state.$schema) state.$schema = 'https://godpowers.dev/schema/state.v1.json';
36
+ if (!state.project || !state.project.name) {
37
+ throw new Error('state.project.name is required');
38
+ }
39
+ if (!state.tiers) state.tiers = {};
40
+
41
+ const file = statePath(projectRoot);
42
+ fs.mkdirSync(path.dirname(file), { recursive: true });
43
+ fs.writeFileSync(file, JSON.stringify(state, null, 2) + '\n');
44
+ return state;
45
+ }
46
+
47
+ /**
48
+ * Initialize a new state.json for a project.
49
+ */
50
+ function init(projectRoot, projectName, opts = {}) {
51
+ const state = {
52
+ $schema: 'https://godpowers.dev/schema/state.v1.json',
53
+ version: STATE_VERSION,
54
+ project: {
55
+ name: projectName,
56
+ started: new Date().toISOString()
57
+ },
58
+ 'active-workstream': 'main',
59
+ tiers: {
60
+ 'tier-0': { orchestration: { status: 'in-flight', updated: new Date().toISOString() } },
61
+ 'tier-1': {
62
+ prd: { status: 'pending' },
63
+ arch: { status: 'pending' },
64
+ roadmap: { status: 'pending' },
65
+ stack: { status: 'pending' },
66
+ design: { status: 'pending' }, // conditional: not-required for backend-only
67
+ product: { status: 'pending' } // populated only when impeccable installed
68
+ },
69
+ 'tier-2': {
70
+ repo: { status: 'pending' },
71
+ build: { status: 'pending' }
72
+ },
73
+ 'tier-3': {
74
+ deploy: { status: 'pending' },
75
+ observe: { status: 'pending' },
76
+ launch: { status: 'pending' },
77
+ harden: { status: 'pending' }
78
+ }
79
+ },
80
+ 'lifecycle-phase': 'in-arc',
81
+ linkage: {
82
+ 'coverage-pct': 0,
83
+ 'orphan-count': 0,
84
+ 'drift-count': 0,
85
+ 'review-required-items': 0
86
+ },
87
+ 'yolo-decisions': [],
88
+ ...opts
89
+ };
90
+ return write(projectRoot, state);
91
+ }
92
+
93
+ /**
94
+ * Update a single sub-step's status.
95
+ */
96
+ function updateSubStep(projectRoot, tierKey, subStepKey, updates) {
97
+ const state = read(projectRoot);
98
+ if (!state) throw new Error('state.json not found');
99
+ if (!state.tiers[tierKey]) throw new Error(`Tier not found: ${tierKey}`);
100
+ state.tiers[tierKey][subStepKey] = {
101
+ ...(state.tiers[tierKey][subStepKey] || {}),
102
+ ...updates,
103
+ updated: new Date().toISOString()
104
+ };
105
+ write(projectRoot, state);
106
+ return state.tiers[tierKey][subStepKey];
107
+ }
108
+
109
+ /**
110
+ * Hash a file. Used for artifact-hash tracking.
111
+ */
112
+ function hashFile(filePath) {
113
+ if (!fs.existsSync(filePath)) return null;
114
+ const content = fs.readFileSync(filePath);
115
+ const hash = crypto.createHash('sha256').update(content).digest('hex');
116
+ return `sha256:${hash}`;
117
+ }
118
+
119
+ /**
120
+ * Detect drift: for each sub-step with an artifact, rehash and compare.
121
+ * Returns a list of drift entries.
122
+ */
123
+ function detectDrift(projectRoot) {
124
+ const state = read(projectRoot);
125
+ if (!state) return [];
126
+ const drift = [];
127
+ for (const [tierKey, tier] of Object.entries(state.tiers)) {
128
+ for (const [subStepKey, subStep] of Object.entries(tier)) {
129
+ if (!subStep.artifact || !subStep['artifact-hash']) continue;
130
+ const fullPath = path.join(projectRoot, '.godpowers', subStep.artifact);
131
+ const currentHash = hashFile(fullPath);
132
+ if (currentHash === null) {
133
+ drift.push({ tierKey, subStepKey, kind: 'missing', recorded: subStep['artifact-hash'] });
134
+ } else if (currentHash !== subStep['artifact-hash']) {
135
+ drift.push({ tierKey, subStepKey, kind: 'modified', recorded: subStep['artifact-hash'], current: currentHash });
136
+ }
137
+ }
138
+ }
139
+ return drift;
140
+ }
141
+
142
+ module.exports = { read, write, init, updateSubStep, hashFile, detectDrift, statePath };
@@ -0,0 +1,301 @@
1
+ /**
2
+ * Story Validator
3
+ *
4
+ * Parses and validates STORY.md files (story-file workflow).
5
+ * Backward-compatible: doesn't replace /god-feature; complements it
6
+ * with finer-grained slices.
7
+ *
8
+ * STORY.md schema:
9
+ * ---
10
+ * id: STORY-{slug}-NNN
11
+ * title: "Short noun phrase"
12
+ * status: pending | in-progress | blocked | done
13
+ * owner: name
14
+ * deps: [STORY-other-001]
15
+ * created: ISO date
16
+ * ---
17
+ *
18
+ * ## User Story
19
+ * As a [persona], I want [capability] so that [outcome].
20
+ *
21
+ * ## Acceptance Criteria
22
+ * - [DECISION] User can do X. Acceptance: clicks Y, sees Z.
23
+ *
24
+ * ## Slice Plan
25
+ * 1. Step 1
26
+ * 2. Step 2
27
+ *
28
+ * ## Notes
29
+ *
30
+ * Public API:
31
+ * parseStory(filePath) -> { id, title, status, owner, deps, body, sections, errors }
32
+ * validateStory(story) -> findings
33
+ * findStoryFiles(projectRoot) -> [paths]
34
+ * listStories(projectRoot) -> [{ id, status, ... }]
35
+ * listByStatus(projectRoot, status) -> [...]
36
+ * isValidId(id) -> bool
37
+ */
38
+
39
+ const fs = require('fs');
40
+ const path = require('path');
41
+
42
+ const VALID_STATUSES = ['pending', 'in-progress', 'blocked', 'done'];
43
+ const ID_PATTERN = /^STORY-[\w-]+-\d+$/;
44
+ const USER_STORY_PATTERN = /as\s+a[n]?\s+.+,\s+i\s+want\s+.+\s+so\s+that\s+/i;
45
+
46
+ function isValidId(id) {
47
+ return ID_PATTERN.test(id);
48
+ }
49
+
50
+ function storiesDir(projectRoot) {
51
+ return path.join(projectRoot, '.godpowers', 'stories');
52
+ }
53
+
54
+ /**
55
+ * Find all STORY-*.md files under .godpowers/stories/.
56
+ */
57
+ function findStoryFiles(projectRoot) {
58
+ const dir = storiesDir(projectRoot);
59
+ const found = [];
60
+ if (!fs.existsSync(dir)) return found;
61
+
62
+ function walk(d) {
63
+ let entries;
64
+ try { entries = fs.readdirSync(d, { withFileTypes: true }); }
65
+ catch (e) { return; }
66
+ for (const e of entries) {
67
+ const full = path.join(d, e.name);
68
+ if (e.isDirectory()) walk(full);
69
+ else if (e.isFile() && /^STORY-/.test(e.name) && e.name.endsWith('.md')) {
70
+ found.push(full);
71
+ }
72
+ }
73
+ }
74
+ walk(dir);
75
+ return found;
76
+ }
77
+
78
+ /**
79
+ * Parse a STORY.md. Returns object with frontmatter, parsed sections, errors.
80
+ */
81
+ function parseStory(filePath) {
82
+ const errors = [];
83
+ if (!fs.existsSync(filePath)) {
84
+ return { errors: ['file-not-found'] };
85
+ }
86
+ const raw = fs.readFileSync(filePath, 'utf8');
87
+ if (!raw.startsWith('---')) {
88
+ return { errors: ['missing-frontmatter'], raw };
89
+ }
90
+ const fmEnd = raw.indexOf('\n---', 3);
91
+ if (fmEnd === -1) {
92
+ return { errors: ['unclosed-frontmatter'], raw };
93
+ }
94
+ const fmText = raw.slice(3, fmEnd).trim();
95
+ const body = raw.slice(fmEnd + 4).trim();
96
+
97
+ const fm = {};
98
+ for (const line of fmText.split('\n')) {
99
+ const m = line.match(/^([\w-]+):\s*(.*)$/);
100
+ if (m) {
101
+ let value = m[2].trim();
102
+ // Parse arrays: [a, b] or ["a", "b"]
103
+ if (value.startsWith('[') && value.endsWith(']')) {
104
+ value = value.slice(1, -1).split(',').map(s => {
105
+ let t = s.trim();
106
+ // Strip surrounding quotes if present
107
+ if ((t.startsWith('"') && t.endsWith('"')) ||
108
+ (t.startsWith("'") && t.endsWith("'"))) {
109
+ t = t.slice(1, -1);
110
+ }
111
+ return t;
112
+ }).filter(Boolean);
113
+ } else if (value.startsWith('"') && value.endsWith('"')) {
114
+ value = value.slice(1, -1);
115
+ }
116
+ fm[m[1]] = value;
117
+ }
118
+ }
119
+
120
+ // Parse sections
121
+ const sections = {};
122
+ let currentHeading = null;
123
+ let currentLines = [];
124
+ for (const line of body.split('\n')) {
125
+ const m = line.match(/^##\s+(.+?)\s*$/);
126
+ if (m) {
127
+ if (currentHeading) {
128
+ sections[currentHeading] = currentLines.join('\n').trim();
129
+ }
130
+ currentHeading = m[1].trim();
131
+ currentLines = [];
132
+ } else if (currentHeading) {
133
+ currentLines.push(line);
134
+ }
135
+ }
136
+ if (currentHeading) {
137
+ sections[currentHeading] = currentLines.join('\n').trim();
138
+ }
139
+
140
+ return {
141
+ path: filePath,
142
+ id: fm.id,
143
+ title: fm.title,
144
+ status: fm.status,
145
+ owner: fm.owner,
146
+ deps: Array.isArray(fm.deps) ? fm.deps : (fm.deps ? [fm.deps] : []),
147
+ created: fm.created,
148
+ frontmatter: fm,
149
+ body,
150
+ sections,
151
+ errors
152
+ };
153
+ }
154
+
155
+ /**
156
+ * Validate a parsed story. Returns findings.
157
+ */
158
+ function validateStory(story) {
159
+ const findings = [];
160
+
161
+ if (story.errors && story.errors.length > 0) {
162
+ for (const e of story.errors) {
163
+ findings.push({ severity: 'error', kind: e, message: e });
164
+ }
165
+ return findings;
166
+ }
167
+
168
+ if (!story.id) {
169
+ findings.push({ severity: 'error', kind: 'missing-id', message: 'STORY missing `id` in frontmatter' });
170
+ } else if (!isValidId(story.id)) {
171
+ findings.push({
172
+ severity: 'error',
173
+ kind: 'invalid-id-format',
174
+ message: `STORY id "${story.id}" does not match STORY-{slug}-NNN pattern`
175
+ });
176
+ }
177
+ if (!story.title) {
178
+ findings.push({ severity: 'error', kind: 'missing-title', message: 'STORY missing `title`' });
179
+ }
180
+ if (!story.status) {
181
+ findings.push({ severity: 'error', kind: 'missing-status', message: 'STORY missing `status`' });
182
+ } else if (!VALID_STATUSES.includes(story.status)) {
183
+ findings.push({
184
+ severity: 'error',
185
+ kind: 'invalid-status',
186
+ message: `Status "${story.status}" not one of ${VALID_STATUSES.join(', ')}`
187
+ });
188
+ }
189
+ if (!story.owner) {
190
+ findings.push({ severity: 'warning', kind: 'missing-owner', message: 'STORY missing `owner` field' });
191
+ }
192
+
193
+ // User Story section format
194
+ if (!story.sections || !story.sections['User Story']) {
195
+ findings.push({
196
+ severity: 'warning',
197
+ kind: 'missing-user-story',
198
+ message: 'STORY missing `## User Story` section'
199
+ });
200
+ } else {
201
+ const us = story.sections['User Story'];
202
+ if (!USER_STORY_PATTERN.test(us)) {
203
+ findings.push({
204
+ severity: 'warning',
205
+ kind: 'user-story-format',
206
+ message: 'User Story does not match "As a X, I want Y so that Z" format'
207
+ });
208
+ }
209
+ }
210
+
211
+ // Acceptance Criteria
212
+ if (!story.sections || !story.sections['Acceptance Criteria']) {
213
+ findings.push({
214
+ severity: 'warning',
215
+ kind: 'missing-acceptance',
216
+ message: 'STORY missing `## Acceptance Criteria` section'
217
+ });
218
+ }
219
+
220
+ return findings;
221
+ }
222
+
223
+ /**
224
+ * List all stories with summary fields.
225
+ */
226
+ function listStories(projectRoot) {
227
+ const files = findStoryFiles(projectRoot);
228
+ return files.map(f => {
229
+ const story = parseStory(f);
230
+ return {
231
+ id: story.id,
232
+ title: story.title,
233
+ status: story.status,
234
+ owner: story.owner,
235
+ deps: story.deps || [],
236
+ path: f
237
+ };
238
+ });
239
+ }
240
+
241
+ function listByStatus(projectRoot, status) {
242
+ return listStories(projectRoot).filter(s => s.status === status);
243
+ }
244
+
245
+ /**
246
+ * Detect dep cycles.
247
+ */
248
+ function detectDepCycles(projectRoot) {
249
+ const stories = listStories(projectRoot);
250
+ const byId = {};
251
+ for (const s of stories) byId[s.id] = s;
252
+ const visited = new Set();
253
+ const stack = new Set();
254
+ const cycles = [];
255
+ function dfs(id, path) {
256
+ if (stack.has(id)) {
257
+ cycles.push([...path, id]);
258
+ return;
259
+ }
260
+ if (visited.has(id)) return;
261
+ visited.add(id);
262
+ stack.add(id);
263
+ const s = byId[id];
264
+ if (s && s.deps) {
265
+ for (const dep of s.deps) {
266
+ if (byId[dep]) dfs(dep, [...path, id]);
267
+ }
268
+ }
269
+ stack.delete(id);
270
+ }
271
+ for (const s of stories) dfs(s.id, []);
272
+ return cycles;
273
+ }
274
+
275
+ /**
276
+ * Update story status (writes back to file).
277
+ */
278
+ function setStatus(filePath, newStatus) {
279
+ if (!VALID_STATUSES.includes(newStatus)) {
280
+ throw new Error(`invalid status: ${newStatus}`);
281
+ }
282
+ const raw = fs.readFileSync(filePath, 'utf8');
283
+ const updated = raw.replace(/^status:\s*\w+/m, `status: ${newStatus}`);
284
+ fs.writeFileSync(filePath, updated);
285
+ return { path: filePath, newStatus };
286
+ }
287
+
288
+ module.exports = {
289
+ parseStory,
290
+ validateStory,
291
+ findStoryFiles,
292
+ listStories,
293
+ listByStatus,
294
+ detectDepCycles,
295
+ setStatus,
296
+ isValidId,
297
+ storiesDir,
298
+ VALID_STATUSES,
299
+ ID_PATTERN,
300
+ USER_STORY_PATTERN
301
+ };