buildanything 1.8.0 → 2.0.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 (458) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/.claude-plugin/plugin.json +9 -3
  3. package/CHANGELOG.md +57 -0
  4. package/README.md +2 -2
  5. package/agents/a11y-architect.md +166 -0
  6. package/agents/business-model.md +80 -29
  7. package/agents/code-architect.md +75 -0
  8. package/agents/code-reviewer.md +255 -0
  9. package/agents/code-simplifier.md +64 -0
  10. package/agents/design-brand-guardian.md +293 -53
  11. package/agents/design-critic.md +139 -0
  12. package/agents/design-inclusive-visuals-specialist.md +6 -19
  13. package/agents/design-ui-designer.md +335 -56
  14. package/agents/design-ux-architect.md +403 -55
  15. package/agents/design-ux-researcher.md +264 -49
  16. package/agents/engineering-ai-engineer.md +26 -36
  17. package/agents/engineering-backend-architect.md +185 -36
  18. package/agents/engineering-data-engineer.md +225 -43
  19. package/agents/engineering-devops-automator.md +227 -74
  20. package/agents/engineering-frontend-developer.md +210 -34
  21. package/agents/engineering-mobile-app-builder.md +6 -1
  22. package/agents/engineering-rapid-prototyper.md +30 -9
  23. package/agents/engineering-security-engineer.md +263 -61
  24. package/agents/engineering-senior-developer.md +128 -19
  25. package/agents/engineering-sre.md +84 -0
  26. package/agents/engineering-technical-writer.md +285 -41
  27. package/agents/feature-intel.md +110 -0
  28. package/agents/ios-app-review-guardian.md +19 -2
  29. package/agents/ios-foundation-models-specialist.md +20 -2
  30. package/agents/ios-storekit-specialist.md +9 -2
  31. package/agents/ios-swift-architect.md +28 -1
  32. package/agents/ios-swift-search.md +8 -1
  33. package/agents/ios-swift-ui-design.md +33 -1
  34. package/agents/marketing-app-store-optimizer.md +246 -64
  35. package/agents/planner.md +216 -0
  36. package/agents/pr-test-analyzer.md +63 -0
  37. package/agents/product-feedback-synthesizer.md +8 -2
  38. package/agents/refactor-cleaner.md +102 -0
  39. package/agents/security-reviewer.md +128 -0
  40. package/agents/silent-failure-hunter.md +54 -0
  41. package/agents/swift-build-resolver.md +119 -0
  42. package/agents/swift-reviewer.md +112 -0
  43. package/agents/tech-feasibility.md +21 -1
  44. package/agents/testing-api-tester.md +236 -59
  45. package/agents/testing-evidence-collector.md +26 -1
  46. package/agents/testing-performance-benchmarker.md +21 -1
  47. package/agents/testing-reality-checker.md +6 -1
  48. package/agents/visual-research.md +116 -0
  49. package/bin/adapters/cycle-counter-tool.ts +155 -0
  50. package/bin/adapters/scribe-tool.ts +71 -0
  51. package/bin/adapters/state-save-tool.ts +130 -0
  52. package/bin/adapters/write-lease-tool.ts +127 -0
  53. package/bin/buildanything-runtime.js +15 -0
  54. package/bin/buildanything-runtime.ts +328 -0
  55. package/bin/setup.js +83 -8
  56. package/commands/add-feature.md +2 -0
  57. package/commands/build.md +782 -266
  58. package/commands/fix.md +1 -1
  59. package/commands/self-check.md +121 -0
  60. package/commands/setup.md +50 -9
  61. package/commands/ux-review.md +2 -2
  62. package/commands/verify.md +6 -9
  63. package/docs/migration/agents.yaml +729 -0
  64. package/docs/migration/phase-graph.yaml +1088 -0
  65. package/docs/migration/sdk-host-compat.md +18 -0
  66. package/hooks/compile-writer-owner-cache.ts +171 -0
  67. package/hooks/hooks.json +36 -0
  68. package/hooks/pre-tool-use +19 -0
  69. package/hooks/pre-tool-use.ts +776 -0
  70. package/hooks/record-mode-transitions.ts +178 -0
  71. package/hooks/session-start +71 -1
  72. package/hooks/subagent-start +17 -0
  73. package/hooks/subagent-start.ts +471 -0
  74. package/hooks/subagent-stop +17 -0
  75. package/hooks/subagent-stop.ts +153 -0
  76. package/package.json +24 -4
  77. package/protocols/architecture-schema.md +171 -0
  78. package/protocols/decision-log.md +131 -0
  79. package/protocols/ios-context.md +10 -11
  80. package/protocols/ios-phase-branches.md +208 -33
  81. package/protocols/launch-readiness.md +258 -0
  82. package/protocols/metric-loop.md +62 -2
  83. package/protocols/smoke-test.md +9 -1
  84. package/protocols/state-schema.json +388 -0
  85. package/protocols/state-schema.md +172 -0
  86. package/protocols/verify.md +62 -2
  87. package/protocols/visual-dna.md +185 -0
  88. package/protocols/web-phase-branches.md +222 -72
  89. package/skills/ios/_VENDORED.md +2 -0
  90. package/skills/ios/app-store-connect-metadata/SKILL.md +148 -0
  91. package/skills/ios/asc-privacy-manifest/SKILL.md +350 -0
  92. package/skills/ios/hig-components-content/SKILL.md +86 -0
  93. package/skills/ios/hig-components-content/references/activity-views.md +79 -0
  94. package/skills/ios/hig-components-content/references/charts.md +180 -0
  95. package/skills/ios/hig-components-content/references/collections.md +48 -0
  96. package/skills/ios/hig-components-content/references/color-wells.md +42 -0
  97. package/skills/ios/hig-components-content/references/image-views.md +82 -0
  98. package/skills/ios/hig-components-content/references/image-wells.md +34 -0
  99. package/skills/ios/hig-components-content/references/lockups.md +78 -0
  100. package/skills/ios/hig-components-content/references/web-views.md +36 -0
  101. package/skills/ios/hig-components-controls/SKILL.md +88 -0
  102. package/skills/ios/hig-components-controls/references/combo-boxes.md +40 -0
  103. package/skills/ios/hig-components-controls/references/controls.md +112 -0
  104. package/skills/ios/hig-components-controls/references/gauges.md +74 -0
  105. package/skills/ios/hig-components-controls/references/labels.md +92 -0
  106. package/skills/ios/hig-components-controls/references/pickers.md +128 -0
  107. package/skills/ios/hig-components-controls/references/rating-indicators.md +38 -0
  108. package/skills/ios/hig-components-controls/references/segmented-controls.md +94 -0
  109. package/skills/ios/hig-components-controls/references/sliders.md +92 -0
  110. package/skills/ios/hig-components-controls/references/steppers.md +40 -0
  111. package/skills/ios/hig-components-controls/references/text-fields.md +88 -0
  112. package/skills/ios/hig-components-controls/references/text-views.md +56 -0
  113. package/skills/ios/hig-components-controls/references/toggles.md +127 -0
  114. package/skills/ios/hig-components-controls/references/token-fields.md +48 -0
  115. package/skills/ios/hig-components-controls/references/virtual-keyboards.md +156 -0
  116. package/skills/ios/hig-components-dialogs/SKILL.md +76 -0
  117. package/skills/ios/hig-components-dialogs/references/action-sheets.md +74 -0
  118. package/skills/ios/hig-components-dialogs/references/alerts.md +158 -0
  119. package/skills/ios/hig-components-dialogs/references/digit-entry-views.md +32 -0
  120. package/skills/ios/hig-components-dialogs/references/popovers.md +81 -0
  121. package/skills/ios/hig-components-dialogs/references/sheets.md +157 -0
  122. package/skills/ios/hig-components-layout/SKILL.md +99 -0
  123. package/skills/ios/hig-components-layout/references/boxes.md +48 -0
  124. package/skills/ios/hig-components-layout/references/column-views.md +44 -0
  125. package/skills/ios/hig-components-layout/references/lists-and-tables.md +99 -0
  126. package/skills/ios/hig-components-layout/references/ornaments.md +56 -0
  127. package/skills/ios/hig-components-layout/references/outline-views.md +64 -0
  128. package/skills/ios/hig-components-layout/references/panels.md +75 -0
  129. package/skills/ios/hig-components-layout/references/scroll-views.md +123 -0
  130. package/skills/ios/hig-components-layout/references/sidebars.md +109 -0
  131. package/skills/ios/hig-components-layout/references/split-views.md +110 -0
  132. package/skills/ios/hig-components-layout/references/tab-bars.md +173 -0
  133. package/skills/ios/hig-components-layout/references/tab-views.md +68 -0
  134. package/skills/ios/hig-components-layout/references/windows.md +188 -0
  135. package/skills/ios/hig-components-menus/SKILL.md +81 -0
  136. package/skills/ios/hig-components-menus/references/action-button.md +61 -0
  137. package/skills/ios/hig-components-menus/references/buttons.md +261 -0
  138. package/skills/ios/hig-components-menus/references/context-menus.md +105 -0
  139. package/skills/ios/hig-components-menus/references/disclosure-controls.md +84 -0
  140. package/skills/ios/hig-components-menus/references/dock-menus.md +40 -0
  141. package/skills/ios/hig-components-menus/references/edit-menus.md +88 -0
  142. package/skills/ios/hig-components-menus/references/menus.md +171 -0
  143. package/skills/ios/hig-components-menus/references/pop-up-buttons.md +70 -0
  144. package/skills/ios/hig-components-menus/references/pull-down-buttons.md +77 -0
  145. package/skills/ios/hig-components-menus/references/the-menu-bar.md +303 -0
  146. package/skills/ios/hig-components-menus/references/toolbars.md +256 -0
  147. package/skills/ios/hig-components-search/SKILL.md +68 -0
  148. package/skills/ios/hig-components-search/references/page-controls.md +120 -0
  149. package/skills/ios/hig-components-search/references/path-controls.md +40 -0
  150. package/skills/ios/hig-components-search/references/search-fields.md +189 -0
  151. package/skills/ios/hig-components-status/SKILL.md +80 -0
  152. package/skills/ios/hig-components-status/references/activity-rings.md +105 -0
  153. package/skills/ios/hig-components-status/references/progress-indicators.md +116 -0
  154. package/skills/ios/hig-components-status/references/status-bars.md +38 -0
  155. package/skills/ios/hig-components-system/SKILL.md +88 -0
  156. package/skills/ios/hig-components-system/references/app-clips.md +387 -0
  157. package/skills/ios/hig-components-system/references/app-shortcuts.md +114 -0
  158. package/skills/ios/hig-components-system/references/complications.md +425 -0
  159. package/skills/ios/hig-components-system/references/home-screen-quick-actions.md +42 -0
  160. package/skills/ios/hig-components-system/references/live-activities.md +442 -0
  161. package/skills/ios/hig-components-system/references/notifications.md +153 -0
  162. package/skills/ios/hig-components-system/references/top-shelf.md +135 -0
  163. package/skills/ios/hig-components-system/references/watch-faces.md +40 -0
  164. package/skills/ios/hig-components-system/references/widgets.md +517 -0
  165. package/skills/ios/hig-foundations/SKILL.md +98 -0
  166. package/skills/ios/hig-foundations/references/accessibility.md +291 -0
  167. package/skills/ios/hig-foundations/references/app-icons.md +210 -0
  168. package/skills/ios/hig-foundations/references/branding.md +44 -0
  169. package/skills/ios/hig-foundations/references/color.md +274 -0
  170. package/skills/ios/hig-foundations/references/dark-mode.md +116 -0
  171. package/skills/ios/hig-foundations/references/icons.md +263 -0
  172. package/skills/ios/hig-foundations/references/images.md +176 -0
  173. package/skills/ios/hig-foundations/references/immersive-experiences.md +174 -0
  174. package/skills/ios/hig-foundations/references/inclusion.md +189 -0
  175. package/skills/ios/hig-foundations/references/layout.md +425 -0
  176. package/skills/ios/hig-foundations/references/materials.md +238 -0
  177. package/skills/ios/hig-foundations/references/motion.md +103 -0
  178. package/skills/ios/hig-foundations/references/privacy.md +231 -0
  179. package/skills/ios/hig-foundations/references/right-to-left.md +206 -0
  180. package/skills/ios/hig-foundations/references/sf-symbols.md +310 -0
  181. package/skills/ios/hig-foundations/references/spatial-layout.md +142 -0
  182. package/skills/ios/hig-foundations/references/typography.md +1146 -0
  183. package/skills/ios/hig-foundations/references/writing.md +91 -0
  184. package/skills/ios/hig-inputs/SKILL.md +94 -0
  185. package/skills/ios/hig-inputs/references/apple-pencil-and-scribble.md +148 -0
  186. package/skills/ios/hig-inputs/references/camera-control.md +107 -0
  187. package/skills/ios/hig-inputs/references/digital-crown.md +83 -0
  188. package/skills/ios/hig-inputs/references/eyes.md +120 -0
  189. package/skills/ios/hig-inputs/references/focus-and-selection.md +120 -0
  190. package/skills/ios/hig-inputs/references/game-controls.md +156 -0
  191. package/skills/ios/hig-inputs/references/gestures.md +208 -0
  192. package/skills/ios/hig-inputs/references/gyro-and-accelerometer.md +40 -0
  193. package/skills/ios/hig-inputs/references/keyboards.md +234 -0
  194. package/skills/ios/hig-inputs/references/nearby-interactions.md +70 -0
  195. package/skills/ios/hig-inputs/references/pointing-devices.md +237 -0
  196. package/skills/ios/hig-inputs/references/remotes.md +67 -0
  197. package/skills/ios/hig-inputs/references/spatial-interactions.md +70 -0
  198. package/skills/ios/hig-patterns/SKILL.md +104 -0
  199. package/skills/ios/hig-patterns/references/charting-data.md +81 -0
  200. package/skills/ios/hig-patterns/references/collaboration-and-sharing.md +86 -0
  201. package/skills/ios/hig-patterns/references/drag-and-drop.md +134 -0
  202. package/skills/ios/hig-patterns/references/entering-data.md +69 -0
  203. package/skills/ios/hig-patterns/references/feedback.md +67 -0
  204. package/skills/ios/hig-patterns/references/file-management.md +135 -0
  205. package/skills/ios/hig-patterns/references/going-full-screen.md +79 -0
  206. package/skills/ios/hig-patterns/references/launching.md +81 -0
  207. package/skills/ios/hig-patterns/references/live-viewing-apps.md +79 -0
  208. package/skills/ios/hig-patterns/references/loading.md +59 -0
  209. package/skills/ios/hig-patterns/references/managing-accounts.md +107 -0
  210. package/skills/ios/hig-patterns/references/managing-notifications.md +99 -0
  211. package/skills/ios/hig-patterns/references/modality.md +82 -0
  212. package/skills/ios/hig-patterns/references/multitasking.md +131 -0
  213. package/skills/ios/hig-patterns/references/offering-help.md +117 -0
  214. package/skills/ios/hig-patterns/references/onboarding.md +69 -0
  215. package/skills/ios/hig-patterns/references/playing-audio.md +124 -0
  216. package/skills/ios/hig-patterns/references/playing-haptics.md +280 -0
  217. package/skills/ios/hig-patterns/references/playing-video.md +180 -0
  218. package/skills/ios/hig-patterns/references/printing.md +50 -0
  219. package/skills/ios/hig-patterns/references/ratings-and-reviews.md +48 -0
  220. package/skills/ios/hig-patterns/references/searching.md +70 -0
  221. package/skills/ios/hig-patterns/references/settings.md +84 -0
  222. package/skills/ios/hig-patterns/references/undo-and-redo.md +58 -0
  223. package/skills/ios/hig-patterns/references/workouts.md +76 -0
  224. package/skills/ios/hig-platforms/SKILL.md +84 -0
  225. package/skills/ios/hig-platforms/references/designing-for-games.md +159 -0
  226. package/skills/ios/hig-platforms/references/designing-for-ios.md +66 -0
  227. package/skills/ios/hig-platforms/references/designing-for-ipados.md +64 -0
  228. package/skills/ios/hig-platforms/references/designing-for-macos.md +70 -0
  229. package/skills/ios/hig-platforms/references/designing-for-tvos.md +68 -0
  230. package/skills/ios/hig-platforms/references/designing-for-visionos.md +85 -0
  231. package/skills/ios/hig-platforms/references/designing-for-watchos.md +74 -0
  232. package/skills/ios/hig-project-context/SKILL.md +133 -0
  233. package/skills/ios/hig-technologies/SKILL.md +107 -0
  234. package/skills/ios/hig-technologies/references/airplay.md +125 -0
  235. package/skills/ios/hig-technologies/references/always-on.md +62 -0
  236. package/skills/ios/hig-technologies/references/apple-pay.md +441 -0
  237. package/skills/ios/hig-technologies/references/augmented-reality.md +247 -0
  238. package/skills/ios/hig-technologies/references/carekit.md +224 -0
  239. package/skills/ios/hig-technologies/references/carplay.md +119 -0
  240. package/skills/ios/hig-technologies/references/game-center.md +343 -0
  241. package/skills/ios/hig-technologies/references/generative-ai.md +110 -0
  242. package/skills/ios/hig-technologies/references/healthkit.md +120 -0
  243. package/skills/ios/hig-technologies/references/homekit.md +343 -0
  244. package/skills/ios/hig-technologies/references/icloud.md +52 -0
  245. package/skills/ios/hig-technologies/references/id-verifier.md +73 -0
  246. package/skills/ios/hig-technologies/references/imessage-apps-and-stickers.md +105 -0
  247. package/skills/ios/hig-technologies/references/in-app-purchase.md +263 -0
  248. package/skills/ios/hig-technologies/references/live-photos.md +54 -0
  249. package/skills/ios/hig-technologies/references/mac-catalyst.md +216 -0
  250. package/skills/ios/hig-technologies/references/machine-learning.md +394 -0
  251. package/skills/ios/hig-technologies/references/maps.md +221 -0
  252. package/skills/ios/hig-technologies/references/nfc.md +51 -0
  253. package/skills/ios/hig-technologies/references/photo-editing.md +40 -0
  254. package/skills/ios/hig-technologies/references/researchkit.md +134 -0
  255. package/skills/ios/hig-technologies/references/shareplay.md +142 -0
  256. package/skills/ios/hig-technologies/references/shazamkit.md +47 -0
  257. package/skills/ios/hig-technologies/references/sign-in-with-apple.md +288 -0
  258. package/skills/ios/hig-technologies/references/siri.md +523 -0
  259. package/skills/ios/hig-technologies/references/tap-to-pay-on-iphone.md +208 -0
  260. package/skills/ios/hig-technologies/references/voiceover.md +90 -0
  261. package/skills/ios/hig-technologies/references/wallet.md +420 -0
  262. package/skills/ios/ios-bootstrap/SKILL.md +16 -7
  263. package/skills/ios/swift-actor-persistence/SKILL.md +143 -0
  264. package/skills/ios/swift-concurrency-6-2/SKILL.md +216 -0
  265. package/skills/ios/swift-protocol-di-testing/SKILL.md +190 -0
  266. package/skills/ios/swiftui-design-tokens/SKILL.md +475 -0
  267. package/skills/ios/writing-for-interfaces/SKILL.md +75 -0
  268. package/skills/web/accessibility/SKILL.md +146 -0
  269. package/skills/web/aceternity-ui/SKILL.md +719 -0
  270. package/skills/web/aceternity-ui/metadata.json +10 -0
  271. package/skills/web/api-design/SKILL.md +523 -0
  272. package/skills/web/chart-accessibility/SKILL.md +332 -0
  273. package/skills/web/composition-patterns/AGENTS.md +946 -0
  274. package/skills/web/composition-patterns/README.md +60 -0
  275. package/skills/web/composition-patterns/SKILL.md +89 -0
  276. package/skills/web/composition-patterns/metadata.json +11 -0
  277. package/skills/web/composition-patterns/rules/_sections.md +29 -0
  278. package/skills/web/composition-patterns/rules/_template.md +24 -0
  279. package/skills/web/composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
  280. package/skills/web/composition-patterns/rules/architecture-compound-components.md +112 -0
  281. package/skills/web/composition-patterns/rules/patterns-children-over-render-props.md +87 -0
  282. package/skills/web/composition-patterns/rules/patterns-explicit-variants.md +100 -0
  283. package/skills/web/composition-patterns/rules/react19-no-forwardref.md +42 -0
  284. package/skills/web/composition-patterns/rules/state-context-interface.md +191 -0
  285. package/skills/web/composition-patterns/rules/state-decouple-implementation.md +113 -0
  286. package/skills/web/composition-patterns/rules/state-lift-state.md +125 -0
  287. package/skills/web/cost-aware-llm-pipeline/SKILL.md +183 -0
  288. package/skills/web/database-migrations/SKILL.md +429 -0
  289. package/skills/web/deployment-patterns/SKILL.md +427 -0
  290. package/skills/web/docker-patterns/SKILL.md +364 -0
  291. package/skills/web/e2e-testing/SKILL.md +326 -0
  292. package/skills/web/lighthouse-ci/SKILL.md +361 -0
  293. package/skills/web/mcp-server-patterns/SKILL.md +69 -0
  294. package/skills/web/next-best-practices/SKILL.md +153 -0
  295. package/skills/web/next-best-practices/async-patterns.md +87 -0
  296. package/skills/web/next-best-practices/bundling.md +180 -0
  297. package/skills/web/next-best-practices/data-patterns.md +297 -0
  298. package/skills/web/next-best-practices/debug-tricks.md +105 -0
  299. package/skills/web/next-best-practices/directives.md +73 -0
  300. package/skills/web/next-best-practices/error-handling.md +227 -0
  301. package/skills/web/next-best-practices/file-conventions.md +140 -0
  302. package/skills/web/next-best-practices/font.md +245 -0
  303. package/skills/web/next-best-practices/functions.md +108 -0
  304. package/skills/web/next-best-practices/hydration-error.md +91 -0
  305. package/skills/web/next-best-practices/image.md +173 -0
  306. package/skills/web/next-best-practices/metadata.md +301 -0
  307. package/skills/web/next-best-practices/parallel-routes.md +287 -0
  308. package/skills/web/next-best-practices/route-handlers.md +146 -0
  309. package/skills/web/next-best-practices/rsc-boundaries.md +159 -0
  310. package/skills/web/next-best-practices/runtime-selection.md +39 -0
  311. package/skills/web/next-best-practices/scripts.md +141 -0
  312. package/skills/web/next-best-practices/self-hosting.md +371 -0
  313. package/skills/web/next-best-practices/suspense-boundaries.md +67 -0
  314. package/skills/web/next-cache-components/SKILL.md +411 -0
  315. package/skills/web/postgres-best-practices/SKILL.md +14 -0
  316. package/skills/web/postgres-best-practices/references/schema-design.md +9 -0
  317. package/skills/web/react-best-practices/AGENTS.md +3810 -0
  318. package/skills/web/react-best-practices/README.md +123 -0
  319. package/skills/web/react-best-practices/SKILL.md +149 -0
  320. package/skills/web/react-best-practices/metadata.json +15 -0
  321. package/skills/web/react-best-practices/rules/_sections.md +46 -0
  322. package/skills/web/react-best-practices/rules/_template.md +28 -0
  323. package/skills/web/react-best-practices/rules/advanced-effect-event-deps.md +56 -0
  324. package/skills/web/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  325. package/skills/web/react-best-practices/rules/advanced-init-once.md +42 -0
  326. package/skills/web/react-best-practices/rules/advanced-use-latest.md +39 -0
  327. package/skills/web/react-best-practices/rules/async-api-routes.md +38 -0
  328. package/skills/web/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
  329. package/skills/web/react-best-practices/rules/async-defer-await.md +82 -0
  330. package/skills/web/react-best-practices/rules/async-dependencies.md +51 -0
  331. package/skills/web/react-best-practices/rules/async-parallel.md +28 -0
  332. package/skills/web/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  333. package/skills/web/react-best-practices/rules/bundle-analyzable-paths.md +63 -0
  334. package/skills/web/react-best-practices/rules/bundle-barrel-imports.md +60 -0
  335. package/skills/web/react-best-practices/rules/bundle-conditional.md +31 -0
  336. package/skills/web/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  337. package/skills/web/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  338. package/skills/web/react-best-practices/rules/bundle-preload.md +50 -0
  339. package/skills/web/react-best-practices/rules/client-event-listeners.md +74 -0
  340. package/skills/web/react-best-practices/rules/client-localstorage-schema.md +71 -0
  341. package/skills/web/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  342. package/skills/web/react-best-practices/rules/client-swr-dedup.md +56 -0
  343. package/skills/web/react-best-practices/rules/js-batch-dom-css.md +107 -0
  344. package/skills/web/react-best-practices/rules/js-cache-function-results.md +80 -0
  345. package/skills/web/react-best-practices/rules/js-cache-property-access.md +28 -0
  346. package/skills/web/react-best-practices/rules/js-cache-storage.md +70 -0
  347. package/skills/web/react-best-practices/rules/js-combine-iterations.md +32 -0
  348. package/skills/web/react-best-practices/rules/js-early-exit.md +50 -0
  349. package/skills/web/react-best-practices/rules/js-flatmap-filter.md +60 -0
  350. package/skills/web/react-best-practices/rules/js-hoist-regexp.md +45 -0
  351. package/skills/web/react-best-practices/rules/js-index-maps.md +37 -0
  352. package/skills/web/react-best-practices/rules/js-length-check-first.md +49 -0
  353. package/skills/web/react-best-practices/rules/js-min-max-loop.md +82 -0
  354. package/skills/web/react-best-practices/rules/js-request-idle-callback.md +105 -0
  355. package/skills/web/react-best-practices/rules/js-set-map-lookups.md +24 -0
  356. package/skills/web/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  357. package/skills/web/react-best-practices/rules/rendering-activity.md +26 -0
  358. package/skills/web/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  359. package/skills/web/react-best-practices/rules/rendering-conditional-render.md +40 -0
  360. package/skills/web/react-best-practices/rules/rendering-content-visibility.md +38 -0
  361. package/skills/web/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  362. package/skills/web/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  363. package/skills/web/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  364. package/skills/web/react-best-practices/rules/rendering-resource-hints.md +85 -0
  365. package/skills/web/react-best-practices/rules/rendering-script-defer-async.md +68 -0
  366. package/skills/web/react-best-practices/rules/rendering-svg-precision.md +28 -0
  367. package/skills/web/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  368. package/skills/web/react-best-practices/rules/rerender-defer-reads.md +39 -0
  369. package/skills/web/react-best-practices/rules/rerender-dependencies.md +45 -0
  370. package/skills/web/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  371. package/skills/web/react-best-practices/rules/rerender-derived-state.md +29 -0
  372. package/skills/web/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  373. package/skills/web/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  374. package/skills/web/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  375. package/skills/web/react-best-practices/rules/rerender-memo.md +44 -0
  376. package/skills/web/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  377. package/skills/web/react-best-practices/rules/rerender-no-inline-components.md +82 -0
  378. package/skills/web/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  379. package/skills/web/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  380. package/skills/web/react-best-practices/rules/rerender-transitions.md +40 -0
  381. package/skills/web/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  382. package/skills/web/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  383. package/skills/web/react-best-practices/rules/server-after-nonblocking.md +73 -0
  384. package/skills/web/react-best-practices/rules/server-auth-actions.md +96 -0
  385. package/skills/web/react-best-practices/rules/server-cache-lru.md +41 -0
  386. package/skills/web/react-best-practices/rules/server-cache-react.md +76 -0
  387. package/skills/web/react-best-practices/rules/server-dedup-props.md +65 -0
  388. package/skills/web/react-best-practices/rules/server-hoist-static-io.md +149 -0
  389. package/skills/web/react-best-practices/rules/server-no-shared-module-state.md +50 -0
  390. package/skills/web/react-best-practices/rules/server-parallel-fetching.md +83 -0
  391. package/skills/web/react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
  392. package/skills/web/react-best-practices/rules/server-serialization.md +38 -0
  393. package/skills/web/seo/SKILL.md +154 -0
  394. package/skills/web/web-design-guidelines/SKILL.md +39 -0
  395. package/skills/web/zap-scan-config/SKILL.md +444 -0
  396. package/skills/web/zap-scan-config/assets/.gitkeep +9 -0
  397. package/skills/web/zap-scan-config/assets/github_action.yml +207 -0
  398. package/skills/web/zap-scan-config/assets/gitlab_ci.yml +226 -0
  399. package/skills/web/zap-scan-config/assets/zap_automation.yaml +196 -0
  400. package/skills/web/zap-scan-config/assets/zap_context.xml +192 -0
  401. package/skills/web/zap-scan-config/references/EXAMPLE.md +40 -0
  402. package/skills/web/zap-scan-config/references/api_testing_guide.md +475 -0
  403. package/skills/web/zap-scan-config/references/authentication_guide.md +431 -0
  404. package/skills/web/zap-scan-config/references/false_positive_handling.md +427 -0
  405. package/skills/web/zap-scan-config/references/owasp_mapping.md +255 -0
  406. package/src/lrr/aggregator.ts +80 -0
  407. package/src/orchestrator/hooks/context-header.ts +95 -0
  408. package/src/orchestrator/hooks/token-accounting-emitter.ts +77 -0
  409. package/src/orchestrator/hooks/token-accounting.ts +101 -0
  410. package/src/orchestrator/mcp/cycle-counter.ts +129 -0
  411. package/src/orchestrator/mcp/scribe.ts +283 -0
  412. package/src/orchestrator/mcp/state-save.ts +149 -0
  413. package/src/orchestrator/mcp/write-lease.ts +167 -0
  414. package/src/orchestrator/phase4-shared-context.ts +41 -0
  415. package/src/orchestrator/schemas/backward-edge.ts +46 -0
  416. package/agents/agentic-identity-trust.md +0 -121
  417. package/agents/data-consolidation-agent.md +0 -39
  418. package/agents/design-image-prompt-engineer.md +0 -105
  419. package/agents/design-visual-storyteller.md +0 -147
  420. package/agents/design-whimsy-injector.md +0 -89
  421. package/agents/engineering-autonomous-optimization-architect.md +0 -105
  422. package/agents/market-intel.md +0 -35
  423. package/agents/marketing-instagram-curator.md +0 -111
  424. package/agents/marketing-reddit-community-builder.md +0 -121
  425. package/agents/marketing-social-media-strategist.md +0 -74
  426. package/agents/marketing-tiktok-strategist.md +0 -123
  427. package/agents/marketing-twitter-engager.md +0 -124
  428. package/agents/marketing-wechat-official-account.md +0 -143
  429. package/agents/marketing-xiaohongshu-specialist.md +0 -136
  430. package/agents/marketing-zhihu-strategist.md +0 -160
  431. package/agents/product-behavioral-nudge-engine.md +0 -78
  432. package/agents/project-management-experiment-tracker.md +0 -102
  433. package/agents/report-distribution-agent.md +0 -43
  434. package/agents/risk-analysis.md +0 -45
  435. package/agents/sales-data-extraction-agent.md +0 -46
  436. package/agents/specialized-cultural-intelligence-strategist.md +0 -65
  437. package/agents/specialized-developer-advocate.md +0 -146
  438. package/agents/support-analytics-reporter.md +0 -133
  439. package/agents/support-executive-summary-generator.md +0 -64
  440. package/agents/support-finance-tracker.md +0 -145
  441. package/agents/support-legal-compliance-checker.md +0 -129
  442. package/agents/support-support-responder.md +0 -91
  443. package/agents/testing-accessibility-auditor.md +0 -110
  444. package/agents/testing-test-results-analyzer.md +0 -97
  445. package/agents/testing-tool-evaluator.md +0 -76
  446. package/agents/testing-workflow-optimizer.md +0 -99
  447. package/agents/user-research.md +0 -40
  448. package/protocols/brainstorm.md +0 -99
  449. package/protocols/design.md +0 -269
  450. package/protocols/planning.md +0 -87
  451. package/skills/ios/ios-hig/SKILL.md +0 -41
  452. package/skills/ios/ios-hig/references/accessibility.md +0 -81
  453. package/skills/ios/ios-hig/references/content.md +0 -142
  454. package/skills/ios/ios-hig/references/feedback.md +0 -123
  455. package/skills/ios/ios-hig/references/interaction.md +0 -199
  456. package/skills/ios/ios-hig/references/performance-platform.md +0 -129
  457. package/skills/ios/ios-hig/references/privacy-permissions.md +0 -181
  458. package/skills/ios/ios-hig/references/visual-design.md +0 -84
@@ -0,0 +1,80 @@
1
+ export type Verdict = 'PASS' | 'CONCERNS' | 'BLOCK';
2
+ export interface ChapterResult {
3
+ chapter: string;
4
+ verdict: Verdict;
5
+ override_blocks_launch: boolean;
6
+ findings: Array<{ severity: string; description: string; related_decision_id?: string }>;
7
+ follow_up_spawned?: boolean;
8
+ follow_up_confirmed?: boolean;
9
+ }
10
+
11
+ export interface AggregateResult {
12
+ combined_verdict: 'PRODUCTION READY' | 'NEEDS WORK' | 'BLOCKED';
13
+ triggered_rule: number;
14
+ chapters: ChapterResult[];
15
+ star_rule_triggered?: boolean;
16
+ star_rule_decision_ids?: string[];
17
+ }
18
+
19
+ export function aggregate(chapters: ChapterResult[]): AggregateResult {
20
+ // Rule 1: ANY override_blocks_launch → BLOCKED
21
+ if (chapters.some(c => c.override_blocks_launch))
22
+ return { combined_verdict: 'BLOCKED', triggered_rule: 1, chapters };
23
+
24
+ // Rule 6: contradictions between chapters on typed fields → BLOCKED
25
+ // Two chapters contradict if they reference the same finding description
26
+ // but assign conflicting verdicts (one PASS, one BLOCK on the same topic).
27
+ const findingsByDesc = new Map<string, Set<Verdict>>();
28
+ for (const ch of chapters) {
29
+ for (const f of ch.findings) {
30
+ const key = f.description.toLowerCase().trim();
31
+ if (!findingsByDesc.has(key)) findingsByDesc.set(key, new Set());
32
+ findingsByDesc.get(key)!.add(ch.verdict);
33
+ }
34
+ }
35
+ for (const [desc, verdicts] of findingsByDesc) {
36
+ if (verdicts.has('PASS') && verdicts.has('BLOCK')) {
37
+ return {
38
+ combined_verdict: 'BLOCKED', triggered_rule: 6, chapters,
39
+ cross_chapter_contradiction: desc,
40
+ } as AggregateResult;
41
+ }
42
+ }
43
+
44
+ // Rule 5: follow_up spawned AND confirmed → treat as BLOCK
45
+ const effectiveChapters = chapters.map(c => ({
46
+ ...c,
47
+ verdict: (c.follow_up_spawned && c.follow_up_confirmed ? 'BLOCK' : c.verdict) as Verdict,
48
+ }));
49
+
50
+ // Rule 2: ALL PASS and 0 follow-ups → PRODUCTION READY
51
+ if (effectiveChapters.every(c => c.verdict === 'PASS') && !chapters.some(c => c.follow_up_spawned))
52
+ return { combined_verdict: 'PRODUCTION READY', triggered_rule: 2, chapters };
53
+
54
+ // Rule 3: ANY BLOCK → NEEDS WORK
55
+ if (effectiveChapters.some(c => c.verdict === 'BLOCK'))
56
+ return { combined_verdict: 'NEEDS WORK', triggered_rule: 3, chapters };
57
+
58
+ // Rule 4: ANY CONCERNS → NEEDS WORK
59
+ if (effectiveChapters.some(c => c.verdict === 'CONCERNS'))
60
+ return { combined_verdict: 'NEEDS WORK', triggered_rule: 4, chapters };
61
+
62
+ return { combined_verdict: 'PRODUCTION READY', triggered_rule: 2, chapters };
63
+ }
64
+
65
+ /** ⭐⭐ Star rule: on BLOCK, find related_decision_id and route back to authoring phase */
66
+ export function applyStarRule(result: AggregateResult): AggregateResult {
67
+ if (result.combined_verdict === 'NEEDS WORK' || result.combined_verdict === 'BLOCKED') {
68
+ const blockFindings = result.chapters
69
+ .filter(c => c.verdict === 'BLOCK')
70
+ .flatMap(c => c.findings.filter(f => f.related_decision_id));
71
+ if (blockFindings.length > 0) {
72
+ return {
73
+ ...result,
74
+ star_rule_triggered: true,
75
+ star_rule_decision_ids: blockFindings.map(f => f.related_decision_id!),
76
+ };
77
+ }
78
+ }
79
+ return { ...result, star_rule_triggered: false };
80
+ }
@@ -0,0 +1,95 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { readFileSync, existsSync } from 'node:fs';
3
+
4
+ export interface ContextHeaderInput {
5
+ projectType: 'web' | 'ios';
6
+ phase: number;
7
+ iosFeatures?: Record<string, boolean>;
8
+ visualDnaPath?: string; // path to visual-dna.md
9
+ }
10
+
11
+ export interface RenderedHeader {
12
+ content: string;
13
+ hash: string;
14
+ }
15
+
16
+ /** Cache: rendered header keyed by phase + input hash for automatic invalidation */
17
+ let cachedHeader: RenderedHeader | null = null;
18
+ let cachedPhase: number | null = null;
19
+ let cachedInputHash: string | null = null;
20
+
21
+ /**
22
+ * Compute a hash of the variable inputs that affect the rendered header.
23
+ * Used to detect mid-phase mutations (e.g., ios_features changing within a phase).
24
+ */
25
+ function inputHash(input: ContextHeaderInput): string {
26
+ const key = JSON.stringify({
27
+ projectType: input.projectType,
28
+ phase: input.phase,
29
+ iosFeatures: input.iosFeatures ?? null,
30
+ visualDnaPath: input.visualDnaPath ?? null,
31
+ });
32
+ return createHash('sha256').update(key).digest('hex').slice(0, 16);
33
+ }
34
+
35
+ /**
36
+ * Render the CONTEXT header for a phase.
37
+ * Called once at phase boundary; result reused for all dispatches in that phase.
38
+ * Automatically invalidates if inputs change within the same phase
39
+ * (e.g., ios_features mutating mid-build per spec pass criteria).
40
+ */
41
+ export function renderContextHeader(input: ContextHeaderInput): RenderedHeader {
42
+ const currentInputHash = inputHash(input);
43
+ // Return cached if same phase AND same inputs
44
+ if (cachedPhase === input.phase && cachedInputHash === currentInputHash && cachedHeader) return cachedHeader;
45
+
46
+ const lines: string[] = ['CONTEXT:'];
47
+ lines.push(` project_type: ${input.projectType}`);
48
+ lines.push(` phase: ${input.phase}`);
49
+
50
+ // DNA: only for web, phase >= 4
51
+ if (input.projectType === 'web' && input.phase >= 4 && input.visualDnaPath) {
52
+ if (existsSync(input.visualDnaPath)) {
53
+ const dna = readFileSync(input.visualDnaPath, 'utf-8');
54
+ const summary = dna.split('\n').slice(0, 5).join('\n').trim();
55
+ lines.push(` dna: ${summary}`);
56
+ }
57
+ }
58
+
59
+ // iOS features: only for ios
60
+ if (input.projectType === 'ios' && input.iosFeatures) {
61
+ const enabled = Object.entries(input.iosFeatures)
62
+ .filter(([, v]) => v)
63
+ .map(([k]) => k);
64
+ if (enabled.length > 0) {
65
+ lines.push(` ios_features: [${enabled.join(', ')}]`);
66
+ }
67
+ }
68
+
69
+ lines.push('');
70
+ lines.push('TASK:');
71
+
72
+ const content = lines.join('\n');
73
+ const hash = createHash('sha256').update(content).digest('hex').slice(0, 16);
74
+
75
+ cachedHeader = { content, hash };
76
+ cachedPhase = input.phase;
77
+ cachedInputHash = currentInputHash;
78
+ return cachedHeader;
79
+ }
80
+
81
+ /**
82
+ * Invalidate the cache (call on phase boundary or state mutation).
83
+ */
84
+ export function invalidateCache(): void {
85
+ cachedHeader = null;
86
+ cachedPhase = null;
87
+ cachedInputHash = null;
88
+ }
89
+
90
+ /**
91
+ * Check if the cache is valid for a given phase.
92
+ */
93
+ export function isCacheValid(phase: number): boolean {
94
+ return cachedPhase === phase && cachedHeader !== null;
95
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Phase-boundary + Task-completion token accounting emitter (task 3.4.2).
3
+ *
4
+ * Subscribes to SDK assistant+result message `usage` fields.
5
+ * At every phase boundary and Task tool call completion, calls
6
+ * recordUsage() to append a cost line to docs/plans/build-log.md.
7
+ *
8
+ * Spec: MIGRATION-PLAN-FINAL.md §4 Stage 3 G3
9
+ * Depends on: src/orchestrator/hooks/token-accounting.ts (task 3.4.1)
10
+ */
11
+
12
+ import { recordUsage, type TokenUsage, type AccountingEntry } from './token-accounting';
13
+
14
+ const DEFAULT_BUILD_LOG = 'docs/plans/build-log.md';
15
+
16
+ export interface SdkUsageMessage {
17
+ input_tokens?: number;
18
+ output_tokens?: number;
19
+ cache_creation_input_tokens?: number;
20
+ cache_read_input_tokens?: number;
21
+ }
22
+
23
+ export interface PhaseContext {
24
+ phase: number;
25
+ step: string;
26
+ buildLogPath?: string;
27
+ }
28
+
29
+ export interface TaskContext extends PhaseContext {
30
+ task: string;
31
+ subagent_type: string;
32
+ }
33
+
34
+ /**
35
+ * Extract TokenUsage from an SDK usage message.
36
+ * SDK field names differ slightly from our internal format.
37
+ */
38
+ export function extractUsage(msg: SdkUsageMessage): TokenUsage {
39
+ return {
40
+ input_tokens: msg.input_tokens ?? 0,
41
+ output_tokens: msg.output_tokens ?? 0,
42
+ cache_read: msg.cache_read_input_tokens ?? 0,
43
+ cache_create: msg.cache_creation_input_tokens ?? 0,
44
+ };
45
+ }
46
+
47
+ /**
48
+ * Emit a cost line at a phase boundary.
49
+ * Called by the orchestrator after each phase completes.
50
+ */
51
+ export function emitPhaseBoundary(
52
+ ctx: PhaseContext,
53
+ usage: SdkUsageMessage,
54
+ ): AccountingEntry {
55
+ return recordUsage(ctx.buildLogPath ?? DEFAULT_BUILD_LOG, {
56
+ phase: ctx.phase,
57
+ step: ctx.step,
58
+ usage: extractUsage(usage),
59
+ });
60
+ }
61
+
62
+ /**
63
+ * Emit a cost line at task completion.
64
+ * Called after each Task tool call returns from a subagent dispatch.
65
+ */
66
+ export function emitTaskCompletion(
67
+ ctx: TaskContext,
68
+ usage: SdkUsageMessage,
69
+ ): AccountingEntry {
70
+ return recordUsage(ctx.buildLogPath ?? DEFAULT_BUILD_LOG, {
71
+ phase: ctx.phase,
72
+ step: ctx.step,
73
+ task: ctx.task,
74
+ subagent_type: ctx.subagent_type,
75
+ usage: extractUsage(usage),
76
+ });
77
+ }
@@ -0,0 +1,101 @@
1
+ import { writeFileSync, existsSync, mkdirSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+
4
+ export interface TokenUsage {
5
+ input_tokens: number;
6
+ output_tokens: number;
7
+ cache_read?: number;
8
+ cache_create?: number;
9
+ }
10
+
11
+ export interface AccountingEntry {
12
+ timestamp: string;
13
+ phase: number;
14
+ step: string;
15
+ task?: string;
16
+ subagent_type?: string;
17
+ usage: TokenUsage;
18
+ cost_usd: number;
19
+ cumulative_usd: number;
20
+ }
21
+
22
+ /** Running cumulative cost across the build */
23
+ let cumulativeCost = 0;
24
+
25
+ /** Pricing per million tokens (sonnet defaults) */
26
+ const PRICING = {
27
+ input: 3.0,
28
+ output: 15.0,
29
+ cache_read: 0.30,
30
+ cache_create: 3.75,
31
+ };
32
+
33
+ /**
34
+ * Calculate cost from token usage.
35
+ */
36
+ export function calculateCost(usage: TokenUsage): number {
37
+ const inputCost = (usage.input_tokens / 1_000_000) * PRICING.input;
38
+ const outputCost = (usage.output_tokens / 1_000_000) * PRICING.output;
39
+ const cacheReadCost = ((usage.cache_read ?? 0) / 1_000_000) * PRICING.cache_read;
40
+ const cacheCreateCost = ((usage.cache_create ?? 0) / 1_000_000) * PRICING.cache_create;
41
+ return Math.round((inputCost + outputCost + cacheReadCost + cacheCreateCost) * 10000) / 10000;
42
+ }
43
+
44
+ /**
45
+ * Record a token usage entry and append to build-log.md.
46
+ */
47
+ export function recordUsage(
48
+ buildLogPath: string,
49
+ entry: Omit<AccountingEntry, 'cost_usd' | 'cumulative_usd' | 'timestamp'>,
50
+ ): AccountingEntry {
51
+ const cost = calculateCost(entry.usage);
52
+ cumulativeCost += cost;
53
+
54
+ const record: AccountingEntry = {
55
+ timestamp: new Date().toISOString(),
56
+ ...entry,
57
+ cost_usd: cost,
58
+ cumulative_usd: Math.round(cumulativeCost * 10000) / 10000,
59
+ };
60
+
61
+ const line = formatLogLine(record);
62
+ const dir = dirname(buildLogPath);
63
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
64
+ writeFileSync(buildLogPath, line + '\n', { flag: 'a' });
65
+
66
+ return record;
67
+ }
68
+
69
+ /**
70
+ * Format an accounting entry as a build-log line.
71
+ */
72
+ export function formatLogLine(entry: AccountingEntry): string {
73
+ const meta = [`phase=${entry.phase}`, `step=${entry.step}`];
74
+ if (entry.task) meta.push(`task=${entry.task}`);
75
+ if (entry.subagent_type) meta.push(`subagent_type=${entry.subagent_type}`);
76
+
77
+ const tokens = [
78
+ `input_tokens=${entry.usage.input_tokens}`,
79
+ `output_tokens=${entry.usage.output_tokens}`,
80
+ ];
81
+ if (entry.usage.cache_read) tokens.push(`cache_read=${entry.usage.cache_read}`);
82
+ if (entry.usage.cache_create) tokens.push(`cache_create=${entry.usage.cache_create}`);
83
+ tokens.push(`cost_usd=${entry.cost_usd}`);
84
+ tokens.push(`cumulative_usd=${entry.cumulative_usd}`);
85
+
86
+ return `[${entry.timestamp}] ${meta.join(' ')}\n${tokens.join(' ')}`;
87
+ }
88
+
89
+ /**
90
+ * Get current cumulative cost.
91
+ */
92
+ export function getCumulativeCost(): number {
93
+ return cumulativeCost;
94
+ }
95
+
96
+ /**
97
+ * Reset cumulative cost (for testing).
98
+ */
99
+ export function reset(): void {
100
+ cumulativeCost = 0;
101
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * cycle_counter_check MCP handler (Stage 4, A6 semantic).
3
+ *
4
+ * Authoritative semantic: escalation fires when NEW counter value > max_cycles.
5
+ * max_cycles = 2 → first two attempts allow, third escalates.
6
+ *
7
+ * Dual counter: per-decision AND per-target-phase. Escalation when EITHER exceeds cap.
8
+ */
9
+
10
+ import type { InFlightBackwardEdge, BackwardRoutingCounters } from '../schemas/backward-edge';
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // Types
14
+ // ---------------------------------------------------------------------------
15
+
16
+ export interface CycleCheckInput {
17
+ decision_id: string;
18
+ target_phase: string;
19
+ }
20
+
21
+ export interface CycleCheckResult {
22
+ action: 'allow' | 'escalate_to_user';
23
+ decision_count: number;
24
+ phase_count: number;
25
+ }
26
+
27
+ export interface CounterState extends BackwardRoutingCounters {}
28
+
29
+ const DEFAULT_MAX_CYCLES = 2;
30
+
31
+ // ---------------------------------------------------------------------------
32
+ // Core handler (tasks 4.2.1, 4.2.2, 4.2.3)
33
+ // ---------------------------------------------------------------------------
34
+
35
+ /**
36
+ * Check and increment the cycle counter for a backward-routing edge.
37
+ * Returns allow for the first max_cycles attempts, escalate_to_user after.
38
+ *
39
+ * Mutates the state object in place — caller must persist via a single
40
+ * atomic state_save combining counter increment + in_flight_backward_edge
41
+ * write (A3 crash-seam protocol).
42
+ */
43
+ export function cycleCounterCheck(
44
+ state: CounterState,
45
+ input: CycleCheckInput,
46
+ maxCycles: number = DEFAULT_MAX_CYCLES,
47
+ ): CycleCheckResult {
48
+ if (!input.decision_id) throw new Error('decision_id is required');
49
+ if (!input.target_phase) throw new Error('target_phase is required');
50
+
51
+ // Initialize counters if missing
52
+ state.backward_routing_count ??= {};
53
+ state.backward_routing_count_by_target_phase ??= {};
54
+
55
+ // Atomically increment both counters
56
+ const decisionCount = (state.backward_routing_count[input.decision_id] ?? 0) + 1;
57
+ const phaseCount = (state.backward_routing_count_by_target_phase[input.target_phase] ?? 0) + 1;
58
+
59
+ state.backward_routing_count[input.decision_id] = decisionCount;
60
+ state.backward_routing_count_by_target_phase[input.target_phase] = phaseCount;
61
+
62
+ // Write in_flight_backward_edge (A3 crash-seam) — single atomic state_save
63
+ state.in_flight_backward_edge = {
64
+ decision_id: input.decision_id,
65
+ target_phase: input.target_phase,
66
+ counter_value: decisionCount,
67
+ started_at: new Date().toISOString(),
68
+ };
69
+
70
+ // Escalation: EITHER counter exceeds cap → escalate
71
+ const action: CycleCheckResult['action'] =
72
+ (decisionCount > maxCycles || phaseCount > maxCycles)
73
+ ? 'escalate_to_user'
74
+ : 'allow';
75
+
76
+ return { action, decision_count: decisionCount, phase_count: phaseCount };
77
+ }
78
+
79
+ // ---------------------------------------------------------------------------
80
+ // Edge lifecycle helpers
81
+ // ---------------------------------------------------------------------------
82
+
83
+ /**
84
+ * Clear the in-flight backward edge (called by target phase on re-entry).
85
+ * Caller must persist via state_save.
86
+ */
87
+ export function clearInFlightEdge(state: CounterState): void {
88
+ delete state.in_flight_backward_edge;
89
+ }
90
+
91
+ /**
92
+ * Handle stale edge on --resume (A3 crash recovery).
93
+ * If edge is older than threshold, decrement both counters and clear the edge.
94
+ * Returns true if a stale edge was cleaned up.
95
+ */
96
+ export function handleStaleEdge(state: CounterState, thresholdMs: number = 60_000): boolean {
97
+ const edge = state.in_flight_backward_edge;
98
+ if (!edge) return false;
99
+
100
+ const age = Date.now() - new Date(edge.started_at).getTime();
101
+ if (age <= thresholdMs) return false; // edge is fresh, standard resume
102
+
103
+ // Edge never completed — decrement per-decision counter
104
+ const decCurrent = state.backward_routing_count[edge.decision_id] ?? 0;
105
+ if (decCurrent > 0) {
106
+ state.backward_routing_count[edge.decision_id] = decCurrent - 1;
107
+ }
108
+
109
+ // Decrement per-target-phase counter
110
+ const phaseCurrent = state.backward_routing_count_by_target_phase[edge.target_phase] ?? 0;
111
+ if (phaseCurrent > 0) {
112
+ state.backward_routing_count_by_target_phase[edge.target_phase] = phaseCurrent - 1;
113
+ }
114
+
115
+ delete state.in_flight_backward_edge;
116
+ return true; // stale edge handled
117
+ }
118
+
119
+ // ---------------------------------------------------------------------------
120
+ // Test helpers
121
+ // ---------------------------------------------------------------------------
122
+
123
+ /** Create a fresh empty CounterState. For testing only. */
124
+ export function createEmptyState(): CounterState {
125
+ return {
126
+ backward_routing_count: {},
127
+ backward_routing_count_by_target_phase: {},
128
+ };
129
+ }