mindforge-cc 8.1.1 → 8.2.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 (1002) hide show
  1. package/.mindforge/celestial.db +0 -0
  2. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/CLAUDE.md +102 -0
  3. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/commands.cjs +959 -0
  4. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/config.cjs +421 -0
  5. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/core.cjs +1166 -0
  6. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/frontmatter.cjs +307 -0
  7. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/init.cjs +1336 -0
  8. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/milestone.cjs +252 -0
  9. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/model-profiles.cjs +68 -0
  10. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/phase.cjs +888 -0
  11. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/profile-output.cjs +952 -0
  12. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/profile-pipeline.cjs +539 -0
  13. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/roadmap.cjs +329 -0
  14. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/security.cjs +356 -0
  15. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/state.cjs +969 -0
  16. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/template.cjs +222 -0
  17. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/uat.cjs +189 -0
  18. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/verify.cjs +851 -0
  19. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/lib/workstream.cjs +491 -0
  20. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/bin/mindforge-tools.cjs +897 -0
  21. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/file-manifest.json +219 -0
  22. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/forge/help.md +11 -0
  23. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/forge/init-project.md +36 -0
  24. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/forge/plan-phase.md +34 -0
  25. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/hooks/mindforge-check-update.js +114 -0
  26. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/hooks/mindforge-context-monitor.js +156 -0
  27. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/hooks/mindforge-prompt-guard.js +96 -0
  28. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/hooks/mindforge-session-init_extended.js +42 -0
  29. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/hooks/mindforge-statusline.js +119 -0
  30. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/hooks/mindforge-workflow-guard.js +94 -0
  31. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/add-backlog.md +32 -0
  32. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/agent.md +31 -0
  33. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/approve.md +22 -0
  34. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/audit.md +34 -0
  35. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/auto.md +26 -0
  36. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/benchmark.md +37 -0
  37. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/browse.md +30 -0
  38. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/complete-milestone.md +22 -0
  39. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/costs.md +15 -0
  40. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/cross-review.md +21 -0
  41. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/dashboard.md +102 -0
  42. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/debug.md +133 -0
  43. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/discuss-phase.md +142 -0
  44. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/do.md +31 -0
  45. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/execute-phase.md +200 -0
  46. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/health.md +31 -0
  47. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/help.md +33 -0
  48. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/init-org.md +135 -0
  49. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/init-project.md +170 -0
  50. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/install-skill.md +28 -0
  51. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/learn.md +147 -0
  52. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/learning.md +20 -0
  53. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/map-codebase.md +302 -0
  54. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/marketplace.md +124 -0
  55. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/metrics.md +26 -0
  56. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/migrate.md +44 -0
  57. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/milestone.md +16 -0
  58. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/new-runtime.md +23 -0
  59. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/next.md +109 -0
  60. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/note.md +35 -0
  61. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/plan-phase.md +131 -0
  62. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/plant-seed.md +31 -0
  63. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/plugins.md +44 -0
  64. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/pr-review.md +45 -0
  65. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/profile-team.md +27 -0
  66. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/publish-skill.md +23 -0
  67. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/qa.md +20 -0
  68. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/quick.md +139 -0
  69. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/record-learning.md +22 -0
  70. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/release.md +14 -0
  71. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/remember.md +30 -0
  72. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/research.md +16 -0
  73. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/retrospective.md +31 -0
  74. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/review-backlog.md +34 -0
  75. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/review.md +161 -0
  76. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/security-scan.md +242 -0
  77. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/session-report.md +39 -0
  78. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/ship.md +111 -0
  79. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/skills.md +145 -0
  80. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/status.md +113 -0
  81. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/steer.md +17 -0
  82. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/sync-confluence.md +15 -0
  83. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/sync-jira.md +16 -0
  84. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/tokens.md +12 -0
  85. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/ui-phase.md +34 -0
  86. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/ui-review.md +36 -0
  87. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/update.md +46 -0
  88. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/validate-phase.md +31 -0
  89. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/verify-phase.md +66 -0
  90. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/workspace.md +33 -0
  91. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/mindforge/workstreams.md +35 -0
  92. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/settings.json +42 -0
  93. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-add-backlog/SKILL.md +72 -0
  94. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-add-phase/SKILL.md +39 -0
  95. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-add-tests/SKILL.md +28 -0
  96. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-add-todo/SKILL.md +42 -0
  97. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-audit-milestone/SKILL.md +29 -0
  98. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-audit-uat/SKILL.md +20 -0
  99. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-autonomous/SKILL.md +33 -0
  100. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-brainstorming/SKILL.md +164 -0
  101. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-brainstorming/scripts/frame-template.html +214 -0
  102. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-brainstorming/scripts/helper.js +88 -0
  103. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-brainstorming/scripts/server.cjs +354 -0
  104. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-brainstorming/scripts/start-server.sh +148 -0
  105. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-brainstorming/scripts/stop-server.sh +56 -0
  106. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-brainstorming/spec-document-reviewer-prompt.md +49 -0
  107. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-brainstorming/visual-companion.md +287 -0
  108. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-check-todos/SKILL.md +40 -0
  109. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-cleanup/SKILL.md +19 -0
  110. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-complete-milestone/SKILL.md +131 -0
  111. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-debug/SKILL.md +163 -0
  112. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-debug_extended/CREATION-LOG.md +119 -0
  113. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-debug_extended/SKILL.md +296 -0
  114. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-debug_extended/condition-based-waiting-example.ts +158 -0
  115. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-debug_extended/condition-based-waiting.md +115 -0
  116. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-debug_extended/defense-in-depth.md +122 -0
  117. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-debug_extended/find-polluter.sh +63 -0
  118. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-debug_extended/root-cause-tracing.md +169 -0
  119. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-debug_extended/test-academic.md +14 -0
  120. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-debug_extended/test-pressure-1.md +58 -0
  121. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-debug_extended/test-pressure-2.md +68 -0
  122. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-debug_extended/test-pressure-3.md +69 -0
  123. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-discuss-phase/SKILL.md +54 -0
  124. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-do/SKILL.md +26 -0
  125. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-execute-phase/SKILL.md +49 -0
  126. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-execute-phase_extended/SKILL.md +70 -0
  127. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-fast/SKILL.md +23 -0
  128. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-forensics/SKILL.md +49 -0
  129. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-health/SKILL.md +17 -0
  130. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-help/SKILL.md +23 -0
  131. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-insert-phase/SKILL.md +28 -0
  132. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-join-discord/SKILL.md +19 -0
  133. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-list-phase-assumptions/SKILL.md +41 -0
  134. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-list-workspaces/SKILL.md +17 -0
  135. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-manager/SKILL.md +32 -0
  136. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-map-codebase/SKILL.md +64 -0
  137. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-milestone-summary/SKILL.md +44 -0
  138. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-neural-orchestrator/SKILL.md +115 -0
  139. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-neural-orchestrator/references/codex-tools.md +100 -0
  140. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-neural-orchestrator/references/gemini-tools.md +33 -0
  141. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-new-milestone/SKILL.md +38 -0
  142. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-new-project/SKILL.md +36 -0
  143. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-new-workspace/SKILL.md +39 -0
  144. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-next/SKILL.md +19 -0
  145. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-note/SKILL.md +29 -0
  146. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-parallel-mesh_extended/SKILL.md +182 -0
  147. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-pause-work/SKILL.md +35 -0
  148. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-plan-milestone-gaps/SKILL.md +28 -0
  149. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-plan-phase/SKILL.md +38 -0
  150. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-plan-phase_extended/SKILL.md +152 -0
  151. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-plan-phase_extended/plan-document-reviewer-prompt.md +49 -0
  152. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-plant-seed/SKILL.md +22 -0
  153. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-pr-branch/SKILL.md +21 -0
  154. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-profile-user/SKILL.md +38 -0
  155. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-progress/SKILL.md +19 -0
  156. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-quick/SKILL.md +38 -0
  157. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-reapply-patches/SKILL.md +124 -0
  158. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-remove-phase/SKILL.md +26 -0
  159. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-remove-workspace/SKILL.md +22 -0
  160. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-research-phase/SKILL.md +186 -0
  161. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-resume-work/SKILL.md +35 -0
  162. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-review/SKILL.md +31 -0
  163. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-review-backlog/SKILL.md +58 -0
  164. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-review-inbound/SKILL.md +213 -0
  165. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-review-request/SKILL.md +105 -0
  166. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-review-request/code-reviewer.md +146 -0
  167. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-session-report/SKILL.md +16 -0
  168. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-set-profile/SKILL.md +9 -0
  169. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-settings/SKILL.md +32 -0
  170. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-ship/SKILL.md +16 -0
  171. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-ship_extended/SKILL.md +200 -0
  172. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-skill-creation/SKILL.md +655 -0
  173. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-skill-creation/anthropic-best-practices.md +1150 -0
  174. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-skill-creation/examples/CLAUDE_MD_TESTING.md +189 -0
  175. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-skill-creation/graphviz-conventions.dot +172 -0
  176. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-skill-creation/persuasion-principles.md +187 -0
  177. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-skill-creation/render-graphs.js +168 -0
  178. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-skill-creation/testing-skills-with-subagents.md +384 -0
  179. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-stats/SKILL.md +16 -0
  180. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-swarm-execution/SKILL.md +277 -0
  181. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-swarm-execution/code-quality-reviewer-prompt.md +26 -0
  182. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-swarm-execution/implementer-prompt.md +113 -0
  183. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-swarm-execution/spec-reviewer-prompt.md +61 -0
  184. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-system-architecture/SKILL.md +136 -0
  185. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-system-architecture/examples.md +120 -0
  186. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-system-architecture/scaling-checklist.md +76 -0
  187. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-tdd/SKILL.md +112 -0
  188. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-tdd/deep-modules.md +21 -0
  189. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-tdd/interface-design.md +22 -0
  190. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-tdd/mocking.md +24 -0
  191. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-tdd/refactoring.md +21 -0
  192. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-tdd/tests.md +28 -0
  193. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-tdd_extended/SKILL.md +371 -0
  194. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-tdd_extended/testing-anti-patterns.md +299 -0
  195. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-thread/SKILL.md +123 -0
  196. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-ui-phase/SKILL.md +24 -0
  197. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-ui-review/SKILL.md +24 -0
  198. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-update/SKILL.md +35 -0
  199. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-validate-phase/SKILL.md +26 -0
  200. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-verify-work/SKILL.md +30 -0
  201. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-verify-work_extended/SKILL.md +139 -0
  202. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-workspace-isolated/SKILL.md +218 -0
  203. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/skills/mindforge-workstreams/SKILL.md +65 -0
  204. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/forge:help.md +10 -0
  205. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/forge:init-project.md +35 -0
  206. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/forge:plan-phase.md +33 -0
  207. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-add-phase.md +112 -0
  208. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-add-tests.md +351 -0
  209. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-add-todo.md +158 -0
  210. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-audit-milestone.md +332 -0
  211. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-audit-uat.md +109 -0
  212. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-autonomous.md +815 -0
  213. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-check-todos.md +177 -0
  214. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-cleanup.md +152 -0
  215. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-complete-milestone.md +766 -0
  216. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-diagnose-issues.md +220 -0
  217. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-discovery-phase.md +289 -0
  218. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-discuss-phase-assumptions.md +645 -0
  219. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-discuss-phase.md +1047 -0
  220. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-do.md +104 -0
  221. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-execute-phase.md +838 -0
  222. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-execute-plan.md +509 -0
  223. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-fast.md +105 -0
  224. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-forensics.md +265 -0
  225. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-health.md +181 -0
  226. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-help.md +606 -0
  227. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-insert-phase.md +130 -0
  228. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-list-phase-assumptions.md +178 -0
  229. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-list-workspaces.md +56 -0
  230. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-manager.md +360 -0
  231. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-map-codebase.md +370 -0
  232. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-milestone-summary.md +223 -0
  233. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-new-milestone.md +469 -0
  234. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-new-project.md +1226 -0
  235. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-new-workspace.md +237 -0
  236. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-next.md +97 -0
  237. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-node-repair.md +92 -0
  238. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-note.md +156 -0
  239. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-pause-work.md +176 -0
  240. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-plan-milestone-gaps.md +273 -0
  241. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-plan-phase.md +877 -0
  242. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-plant-seed.md +169 -0
  243. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-pr-branch.md +129 -0
  244. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-profile-user.md +450 -0
  245. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-progress.md +507 -0
  246. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-quick.md +732 -0
  247. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-remove-phase.md +155 -0
  248. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-remove-workspace.md +90 -0
  249. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-research-phase.md +74 -0
  250. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-resume-project.md +325 -0
  251. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-review.md +228 -0
  252. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-session-report.md +146 -0
  253. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-settings.md +283 -0
  254. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-ship.md +228 -0
  255. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-stats.md +60 -0
  256. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-transition.md +671 -0
  257. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-ui-phase.md +290 -0
  258. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-ui-review.md +157 -0
  259. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-update.md +323 -0
  260. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-validate-phase.md +167 -0
  261. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-verify-phase.md +254 -0
  262. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge-verify-work.md +628 -0
  263. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:add-backlog.md +24 -0
  264. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:agent.md +25 -0
  265. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:approve.md +21 -0
  266. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:architecture.md +40 -0
  267. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:audit.md +33 -0
  268. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:auto.md +25 -0
  269. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:benchmark.md +36 -0
  270. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:brainstorming.md +16 -0
  271. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:browse.md +29 -0
  272. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:complete-milestone.md +21 -0
  273. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:costs.md +14 -0
  274. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:cross-review.md +20 -0
  275. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:dashboard.md +101 -0
  276. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:debug.md +131 -0
  277. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:discuss-phase.md +141 -0
  278. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:do.md +25 -0
  279. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:execute-phase.md +205 -0
  280. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:executor.md +18 -0
  281. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:health.md +24 -0
  282. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:help.md +26 -0
  283. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:identity.md +18 -0
  284. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:init-org.md +134 -0
  285. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:init-project.md +185 -0
  286. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:install-skill.md +27 -0
  287. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:learn.md +146 -0
  288. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:map-codebase.md +301 -0
  289. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:marketplace.md +123 -0
  290. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:memory.md +18 -0
  291. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:metrics.md +25 -0
  292. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:migrate.md +43 -0
  293. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:milestone.md +15 -0
  294. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:new-runtime.md +22 -0
  295. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:next.md +108 -0
  296. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:note.md +27 -0
  297. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:plan-phase.md +139 -0
  298. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:planner.md +18 -0
  299. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:plant-seed.md +24 -0
  300. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:plugins.md +43 -0
  301. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:pr-review.md +44 -0
  302. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:profile-team.md +26 -0
  303. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:publish-skill.md +22 -0
  304. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:qa.md +19 -0
  305. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:quick.md +138 -0
  306. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:release.md +13 -0
  307. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:remember.md +29 -0
  308. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:research.md +15 -0
  309. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:researcher.md +18 -0
  310. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:retrospective.md +29 -0
  311. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:review-backlog.md +26 -0
  312. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:review.md +160 -0
  313. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:reviewer.md +18 -0
  314. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:security-scan.md +236 -0
  315. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:session-report.md +31 -0
  316. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:ship.md +108 -0
  317. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:skills.md +144 -0
  318. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:soul.md +54 -0
  319. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:status.md +107 -0
  320. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:steer.md +16 -0
  321. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:sync-confluence.md +14 -0
  322. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:sync-jira.md +15 -0
  323. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:tdd.md +46 -0
  324. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:tokens.md +11 -0
  325. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:tool.md +18 -0
  326. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:ui-phase.md +27 -0
  327. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:ui-review.md +28 -0
  328. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:update.md +45 -0
  329. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:validate-phase.md +25 -0
  330. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:verify-phase.md +65 -0
  331. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:workspace.md +32 -0
  332. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/mindforge:workstreams.md +27 -0
  333. package/.mindforge/mirrors/mirror-sre-776a1cf9/.agent/workflows/publish-release.md +36 -0
  334. package/.mindforge/mirrors/mirror-sre-776a1cf9/.czrc +3 -0
  335. package/.mindforge/mirrors/mirror-sre-776a1cf9/.github/pull_request_template.md +29 -0
  336. package/.mindforge/mirrors/mirror-sre-776a1cf9/.github/workflows/ai-intelligence.yml +55 -0
  337. package/.mindforge/mirrors/mirror-sre-776a1cf9/.github/workflows/auto-pr.yml +80 -0
  338. package/.mindforge/mirrors/mirror-sre-776a1cf9/.github/workflows/control-plane.yml +79 -0
  339. package/.mindforge/mirrors/mirror-sre-776a1cf9/.github/workflows/execution-plane.yml +52 -0
  340. package/.mindforge/mirrors/mirror-sre-776a1cf9/.github/workflows/mindforge-ai-review.yml +68 -0
  341. package/.mindforge/mirrors/mirror-sre-776a1cf9/.github/workflows/mindforge-autonomous.yml +70 -0
  342. package/.mindforge/mirrors/mirror-sre-776a1cf9/.github/workflows/mindforge-ci.yml +224 -0
  343. package/.mindforge/mirrors/mirror-sre-776a1cf9/.github/workflows/mindforge-observability.yml +71 -0
  344. package/.mindforge/mirrors/mirror-sre-776a1cf9/.github/workflows/mindforge-release.yml +55 -0
  345. package/.mindforge/mirrors/mirror-sre-776a1cf9/.github/workflows/observability-plane.yml +40 -0
  346. package/.mindforge/mirrors/mirror-sre-776a1cf9/.github/workflows/release-plane.yml +43 -0
  347. package/.mindforge/mirrors/mirror-sre-776a1cf9/.gitlab-ci-mindforge.yml +18 -0
  348. package/.mindforge/mirrors/mirror-sre-776a1cf9/.husky/pre-commit +1 -0
  349. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/MINDFORGE-SCHEMA.json +165 -0
  350. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/MINDFORGE-V2-SCHEMA.json +47 -0
  351. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/audit/AUDIT-SCHEMA.md +470 -0
  352. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/browser/daemon-protocol.md +24 -0
  353. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/browser/qa-engine.md +16 -0
  354. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/browser/session-manager.md +18 -0
  355. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/browser/visual-verify-spec.md +31 -0
  356. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/bypasses.json +8 -0
  357. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/ci/ci-config-schema.md +21 -0
  358. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/ci/ci-mode.md +179 -0
  359. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/ci/github-actions-adapter.md +224 -0
  360. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/ci/gitlab-ci-adapter.md +31 -0
  361. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/ci/jenkins-adapter.md +44 -0
  362. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/config.json +66 -0
  363. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/dashboard/api-reference.md +122 -0
  364. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/dashboard/dashboard-spec.md +96 -0
  365. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/distribution/marketplace.md +53 -0
  366. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/distribution/registry-client.md +166 -0
  367. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/distribution/registry-schema.md +96 -0
  368. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/distribution/skill-publisher.md +44 -0
  369. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/distribution/skill-validator.md +74 -0
  370. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/ads-protocol.md +54 -0
  371. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/autonomous/auto-executor.md +266 -0
  372. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/autonomous/headless-adapter.md +66 -0
  373. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/autonomous/node-repair.md +190 -0
  374. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/autonomous/progress-reporter.md +58 -0
  375. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/autonomous/steering-manager.md +64 -0
  376. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/autonomous/stuck-detector.md +89 -0
  377. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/compaction-protocol.md +167 -0
  378. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/context-injector.md +154 -0
  379. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/dependency-parser.md +113 -0
  380. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/integrity.json +12 -0
  381. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/knowledge-graph-protocol.md +125 -0
  382. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/nexus-tracer.js +11 -0
  383. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/persona-factory.md +45 -0
  384. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/shard-controller.md +53 -0
  385. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/skills/conflict-resolver.md +69 -0
  386. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/skills/loader.md +184 -0
  387. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/skills/registry.md +98 -0
  388. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/skills/versioning.md +75 -0
  389. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/swarm-controller.md +59 -0
  390. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/temporal-protocol.md +40 -0
  391. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/verification-pipeline.md +111 -0
  392. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/engine/wave-executor.md +285 -0
  393. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/governance/GOVERNANCE-CONFIG.md +17 -0
  394. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/governance/approval-workflow.md +37 -0
  395. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/governance/change-classifier.md +63 -0
  396. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/governance/compliance-gates.md +31 -0
  397. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/governance/policies/sovereign-default.json +16 -0
  398. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/integrations/confluence.md +27 -0
  399. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/integrations/connection-manager.md +163 -0
  400. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/integrations/github.md +25 -0
  401. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/integrations/gitlab.md +13 -0
  402. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/integrations/jira.md +102 -0
  403. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/integrations/slack.md +41 -0
  404. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/intelligence/antipattern-detector.md +75 -0
  405. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/intelligence/difficulty-scorer.md +55 -0
  406. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/intelligence/health-engine.md +208 -0
  407. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/intelligence/skill-gap-analyser.md +40 -0
  408. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/intelligence/smart-compaction.md +71 -0
  409. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/memory/MEMORY-SCHEMA.md +155 -0
  410. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/memory/engine/capture-protocol.md +36 -0
  411. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/memory/engine/global-sync-spec.md +42 -0
  412. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/memory/engine/retrieval-spec.md +44 -0
  413. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/metrics/METRICS-SCHEMA.md +42 -0
  414. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/metrics/quality-tracker.md +32 -0
  415. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/models/model-registry.md +48 -0
  416. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/models/model-router.md +30 -0
  417. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/monorepo/cross-package-planner.md +114 -0
  418. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/monorepo/dependency-graph-builder.md +32 -0
  419. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/monorepo/workspace-detector.md +129 -0
  420. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/org/CONVENTIONS.md +62 -0
  421. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/org/ORG.md +51 -0
  422. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/org/SECURITY.md +50 -0
  423. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/org/TOOLS.md +53 -0
  424. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/org/integrations/INTEGRATIONS-CONFIG.md +58 -0
  425. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/org/skills/MANIFEST.md +15 -0
  426. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/advisor-researcher.md +89 -0
  427. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/analyst.md +112 -0
  428. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/architect.md +108 -0
  429. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/assumptions-analyzer-extend.md +87 -0
  430. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/assumptions-analyzer.md +109 -0
  431. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/codebase-mapper-extend.md +93 -0
  432. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/codebase-mapper.md +770 -0
  433. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/coverage-specialist.md +104 -0
  434. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/debug-specialist.md +118 -0
  435. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/debugger.md +97 -0
  436. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/decision-architect.md +102 -0
  437. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/developer.md +97 -0
  438. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/executor.md +88 -0
  439. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/integration-checker.md +92 -0
  440. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/mf-executor.md +40 -0
  441. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/mf-memory.md +33 -0
  442. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/mf-planner.md +45 -0
  443. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/mf-researcher.md +39 -0
  444. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/mf-reviewer.md +35 -0
  445. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/mf-tool.md +33 -0
  446. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/nyquist-auditor.md +84 -0
  447. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/overrides/README.md +85 -0
  448. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/phase-researcher.md +107 -0
  449. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/plan-checker.md +92 -0
  450. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/planner.md +105 -0
  451. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/project-researcher.md +99 -0
  452. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/qa-engineer.md +113 -0
  453. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/release-manager.md +114 -0
  454. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/research-agent.md +109 -0
  455. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/research-synthesizer.md +101 -0
  456. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/roadmapper-extend.md +100 -0
  457. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/roadmapper.md +103 -0
  458. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/security-reviewer.md +114 -0
  459. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/swarm-templates.json +118 -0
  460. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/tech-writer.md +118 -0
  461. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/ui-auditor.md +94 -0
  462. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/ui-checker.md +89 -0
  463. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/ui-researcher.md +99 -0
  464. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/user-profiler.md +93 -0
  465. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/personas/verifier.md +101 -0
  466. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/plugins/PLUGINS-MANIFEST.md +23 -0
  467. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/plugins/plugin-loader.md +93 -0
  468. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/plugins/plugin-registry.md +44 -0
  469. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/plugins/plugin-schema.md +68 -0
  470. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/pr-review/ai-reviewer.md +266 -0
  471. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/pr-review/finding-formatter.md +46 -0
  472. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/pr-review/review-prompt-templates.md +44 -0
  473. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/production/compatibility-layer.md +39 -0
  474. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/production/migration-engine.md +52 -0
  475. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/production/production-checklist.md +76 -0
  476. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/production/token-optimiser.md +68 -0
  477. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/remediation-queue.json +47 -0
  478. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/skills/accessibility/SKILL.md +106 -0
  479. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/skills/api-design/SKILL.md +98 -0
  480. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/skills/code-quality/SKILL.md +88 -0
  481. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/skills/data-privacy/SKILL.md +126 -0
  482. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/skills/database-patterns/SKILL.md +192 -0
  483. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/skills/documentation/SKILL.md +91 -0
  484. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/skills/incident-response/SKILL.md +180 -0
  485. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/skills/performance/SKILL.md +120 -0
  486. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/skills/security-review/SKILL.md +83 -0
  487. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/skills/testing-standards/SKILL.md +97 -0
  488. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/skills-builder/auto-capture-protocol.md +88 -0
  489. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/skills-builder/learn-protocol.md +161 -0
  490. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/skills-builder/quality-scoring.md +120 -0
  491. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/team/TEAM-PROFILE.md +42 -0
  492. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/team/multi-handoff.md +23 -0
  493. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/team/profiles/README.md +13 -0
  494. package/.mindforge/mirrors/mirror-sre-776a1cf9/.mindforge/team/session-merger.md +18 -0
  495. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/ARCHITECTURE.md +0 -0
  496. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/AUDIT.jsonl +45 -0
  497. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/HANDOFF.json +8 -0
  498. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/PROJECT.md +33 -0
  499. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/RELEASE-CHECKLIST.md +68 -0
  500. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/REQUIREMENTS.md +23 -0
  501. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/ROADMAP.md +12 -0
  502. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/ROI.jsonl +2 -0
  503. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/STATE.md +31 -0
  504. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/approvals/.gitkeep +1 -0
  505. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/.gitkeep +1 -0
  506. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/org/CONVENTIONS.md +0 -0
  507. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/org/ORG.md +0 -0
  508. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/org/SECURITY.md +0 -0
  509. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/org/TOOLS.md +0 -0
  510. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/personas/analyst.md +0 -0
  511. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/personas/architect.md +0 -0
  512. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/personas/debug-specialist.md +0 -0
  513. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/personas/developer.md +26 -0
  514. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/personas/qa-engineer.md +0 -0
  515. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/personas/release-manager.md +0 -0
  516. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/personas/security-reviewer.md +33 -0
  517. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/personas/tech-writer.md +0 -0
  518. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/skills/api-design/SKILL.md +0 -0
  519. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/skills/code-quality/SKILL.md +0 -0
  520. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/skills/documentation/SKILL.md +0 -0
  521. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/skills/security-review/SKILL.md +23 -0
  522. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/.forge/skills/testing-standards/SKILL.md +27 -0
  523. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/ARCHITECTURE-AUDIT-REPORT.md +90 -0
  524. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/LOGS-BENCHMARKING.md +172 -0
  525. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/ROADMAP_V8.md +49 -0
  526. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/github-actions-logs.md +88 -0
  527. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-1-imp/DAY1-HARDEN.md +823 -0
  528. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-1-imp/DAY1-IMPLEMENT.md +2459 -0
  529. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-1-imp/DAY1-REVIEW.md +288 -0
  530. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-2-imp/DAY2-HARDEN.md +954 -0
  531. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-2-imp/DAY2-IMPLEMENT.md +2347 -0
  532. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-2-imp/DAY2-REVIEW.md +422 -0
  533. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-3-imp/DAY3-HARDEN.md +870 -0
  534. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-3-imp/DAY3-IMPLEMENT.md +2798 -0
  535. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-3-imp/DAY3-REVIEW.md +484 -0
  536. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-4-imp/DAY4-HARDEN.md +1087 -0
  537. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-4-imp/DAY4-IMPLEMENT.md +2874 -0
  538. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-4-imp/DAY4-REVIEW.md +386 -0
  539. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-5-imp/DAY5-HARDEN.md +1078 -0
  540. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-5-imp/DAY5-IMPLEMENT.md +3151 -0
  541. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-5-imp/DAY5-REVIEW.md +345 -0
  542. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-6-imp/DAY6-COMPLETE.md +3919 -0
  543. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-7-imp-prod/DAY7-PRODUCTION-FINAL.md +4513 -0
  544. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/ci-actions/github-workflows-v2.md +421 -0
  545. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/ci-actions/v2-ci-actions.md +292 -0
  546. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-10-imp/DAY10-MULTI-MODEL.md +3402 -0
  547. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-11-imp/DAY11-PERSISTENT-MEMORY.md +3237 -0
  548. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-12-imp/DAY12-REALTIME-DASHBOARD.md +3301 -0
  549. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-13-imp/DAY13-SELF-BUILDING-SKILLS.md +3798 -0
  550. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-14-prod-v2/DAY14-V2-PRODUCTION-RELEASE.md +2255 -0
  551. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-8-imp/DAY8-AUTONOMOUS-ENGINE.md +3400 -0
  552. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-9-imp/DAY9-BROWSER-RUNTIME.md +3293 -0
  553. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/audit-archive/.gitkeep +1 -0
  554. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/decisions/.gitkeep +0 -0
  555. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/jira-sync.json +5 -0
  556. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/milestones/.gitkeep +1 -0
  557. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/phases/.gitkeep +0 -0
  558. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/research/.gitkeep +0 -0
  559. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/screenshots/.gitkeep +0 -0
  560. package/.mindforge/mirrors/mirror-sre-776a1cf9/.planning/slack-threads.json +3 -0
  561. package/.mindforge/mirrors/mirror-sre-776a1cf9/AGENTS_LEARNING.md +112 -0
  562. package/.mindforge/mirrors/mirror-sre-776a1cf9/CHANGELOG.md +1116 -0
  563. package/.mindforge/mirrors/mirror-sre-776a1cf9/LICENSE +21 -0
  564. package/.mindforge/mirrors/mirror-sre-776a1cf9/MINDFORGE.md +91 -0
  565. package/.mindforge/mirrors/mirror-sre-776a1cf9/README.md +424 -0
  566. package/.mindforge/mirrors/mirror-sre-776a1cf9/RELEASENOTES.md +199 -0
  567. package/.mindforge/mirrors/mirror-sre-776a1cf9/REPLICATION.json +12 -0
  568. package/.mindforge/mirrors/mirror-sre-776a1cf9/SECURITY.md +4 -0
  569. package/.mindforge/mirrors/mirror-sre-776a1cf9/SOUL.md +52 -0
  570. package/.mindforge/mirrors/mirror-sre-776a1cf9/agents/executor/IDENTITY.md +31 -0
  571. package/.mindforge/mirrors/mirror-sre-776a1cf9/agents/memory/IDENTITY.md +27 -0
  572. package/.mindforge/mirrors/mirror-sre-776a1cf9/agents/planner/IDENTITY.md +35 -0
  573. package/.mindforge/mirrors/mirror-sre-776a1cf9/agents/researcher/IDENTITY.md +29 -0
  574. package/.mindforge/mirrors/mirror-sre-776a1cf9/agents/reviewer/IDENTITY.md +31 -0
  575. package/.mindforge/mirrors/mirror-sre-776a1cf9/agents/tool/IDENTITY.md +27 -0
  576. package/.mindforge/mirrors/mirror-sre-776a1cf9/auto-pr.yml +74 -0
  577. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/autonomous/auto-runner.js +378 -0
  578. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/autonomous/context-refactorer.js +64 -0
  579. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/autonomous/headless.js +36 -0
  580. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/autonomous/intent-harvester.js +80 -0
  581. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/autonomous/mesh-self-healer.js +67 -0
  582. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/autonomous/progress-stream.js +49 -0
  583. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/autonomous/repair-operator.js +213 -0
  584. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/autonomous/steer.js +89 -0
  585. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/autonomous/stuck-monitor.js +120 -0
  586. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/browser/browser-daemon.js +139 -0
  587. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/browser/daemon-manager.js +91 -0
  588. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/browser/qa-engine.js +47 -0
  589. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/browser/qa-report-writer.js +32 -0
  590. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/browser/regression-writer.js +27 -0
  591. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/browser/screenshot-store.js +49 -0
  592. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/browser/session-manager.js +93 -0
  593. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/browser/visual-verify-executor.js +89 -0
  594. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/change-classifier.js +86 -0
  595. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/dashboard/api-router.js +198 -0
  596. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/dashboard/approval-handler.js +134 -0
  597. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/dashboard/frontend/index.html +751 -0
  598. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/dashboard/metrics-aggregator.js +296 -0
  599. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/dashboard/revops-api.js +47 -0
  600. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/dashboard/server.js +138 -0
  601. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/dashboard/sse-bridge.js +178 -0
  602. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/dashboard/team-tracker.js +0 -0
  603. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/dashboard/temporal-api.js +82 -0
  604. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/context-entropy-guard.js +94 -0
  605. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/feedback-loop.js +106 -0
  606. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/handover-manager.js +71 -0
  607. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/intelligence-interlock.js +39 -0
  608. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/learning-manager.js +181 -0
  609. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/logic-drift-detector.js +100 -0
  610. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/logic-validator.js +74 -0
  611. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/mesh-syncer.js +129 -0
  612. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/nexus-tracer.js +356 -0
  613. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/orbital-guardian.js +84 -0
  614. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/reason-source-aligner.js +111 -0
  615. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/remediation-engine.js +81 -0
  616. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/self-corrective-synthesizer.js +65 -0
  617. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/skill-evolver.js +105 -0
  618. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/sre-manager.js +117 -0
  619. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/temporal-cli.js +52 -0
  620. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/temporal-hindsight.js +115 -0
  621. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/temporal-hub.js +138 -0
  622. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/test-ceg.js +59 -0
  623. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/test-interlock.js +40 -0
  624. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/test-remediation.js +61 -0
  625. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/test-rsa.js +64 -0
  626. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/test-scs.js +57 -0
  627. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/engine/test-v7-blueprint.js +44 -0
  628. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/gov-audit.js +38 -0
  629. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/approve.js +60 -0
  630. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/config-manager.js +85 -0
  631. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/impact-analyzer.js +141 -0
  632. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/policies/critical-data.json +1 -0
  633. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/policies/default-policies.jsonl +33 -0
  634. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/policy-engine.js +210 -0
  635. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/policy-gate-hardened.js +59 -0
  636. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/quantum-crypto.js +111 -0
  637. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/rbac-manager.js +109 -0
  638. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/test-config.js +40 -0
  639. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/test-crypto-pluggable.js +50 -0
  640. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/test-hardened-gate.js +71 -0
  641. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/trust-verifier.js +81 -0
  642. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/ztai-archiver.js +104 -0
  643. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/governance/ztai-manager.js +239 -0
  644. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/hindsight-injector.js +59 -0
  645. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/install.js +129 -0
  646. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/installer-core.js +805 -0
  647. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/auto-shadow.js +274 -0
  648. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/cli.js +99 -0
  649. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/eis-client.js +95 -0
  650. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/embedding-engine.js +326 -0
  651. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/federated-sync.js +293 -0
  652. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/ghost-pattern-detector.js +69 -0
  653. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/global-sync.js +107 -0
  654. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/identity-synthesizer.js +146 -0
  655. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/knowledge-capture.js +442 -0
  656. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/knowledge-graph.js +609 -0
  657. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/knowledge-indexer.js +172 -0
  658. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/knowledge-store.js +337 -0
  659. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/pillar-health-tracker.js +63 -0
  660. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/semantic-hub.js +211 -0
  661. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/session-memory-loader.js +137 -0
  662. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/memory/vector-hub.js +170 -0
  663. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/migrations/0.1.0-to-0.5.0.js +36 -0
  664. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/migrations/0.5.0-to-0.6.0.js +17 -0
  665. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/migrations/0.6.0-to-1.0.0.js +100 -0
  666. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/migrations/1.0.0-to-2.0.0.js +115 -0
  667. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/migrations/migrate.js +155 -0
  668. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/migrations/schema-versions.js +76 -0
  669. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/migrations/v8-sqlite-migration.js +85 -0
  670. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/mindforge-cc.sh +5 -0
  671. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/mindforge-cli.js +180 -0
  672. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/models/anthropic-provider.js +77 -0
  673. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/models/cloud-broker.js +161 -0
  674. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/models/cost-tracker.js +118 -0
  675. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/models/finops-hub.js +79 -0
  676. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/models/gemini-provider.js +79 -0
  677. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/models/model-broker.js +129 -0
  678. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/models/model-client.js +98 -0
  679. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/models/model-router.js +112 -0
  680. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/models/openai-provider.js +78 -0
  681. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/models/performance-stats.json +22 -0
  682. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/research/research-engine.js +115 -0
  683. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/review/ads-engine.js +126 -0
  684. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/review/ads-synthesizer.js +117 -0
  685. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/review/cross-review-engine.js +92 -0
  686. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/review/finding-synthesizer.js +116 -0
  687. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/review/review-report-writer.js +49 -0
  688. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/revops/debt-monitor.js +60 -0
  689. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/revops/market-evaluator.js +73 -0
  690. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/revops/remediation-queue.js +107 -0
  691. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/revops/roi-engine.js +65 -0
  692. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/revops/router-steering-v2.js +73 -0
  693. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/revops/velocity-forecaster.js +59 -0
  694. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/shard-helper.js +134 -0
  695. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/skill-registry.js +232 -0
  696. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/skill-validator.js +211 -0
  697. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/skills-builder/learn-cli.js +57 -0
  698. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/skills-builder/marketplace-cli.js +54 -0
  699. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/skills-builder/marketplace-client.js +198 -0
  700. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/skills-builder/pattern-detector.js +144 -0
  701. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/skills-builder/skill-generator.js +258 -0
  702. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/skills-builder/skill-registrar.js +107 -0
  703. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/skills-builder/skill-scorer.js +263 -0
  704. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/skills-builder/source-loader.js +268 -0
  705. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/spawn-agent.js +61 -0
  706. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/updater/changelog-fetcher.js +62 -0
  707. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/updater/self-update.js +169 -0
  708. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/updater/version-comparator.js +68 -0
  709. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/validate-config.js +92 -0
  710. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/wizard/config-generator.js +112 -0
  711. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/wizard/environment-detector.js +83 -0
  712. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/wizard/setup-wizard.js +240 -0
  713. package/.mindforge/mirrors/mirror-sre-776a1cf9/bin/wizard/theme.js +184 -0
  714. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/CAPABILITIES-MANIFEST.md +64 -0
  715. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Context/Master-Context.md +694 -0
  716. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/INTELLIGENCE-MESH.md +37 -0
  717. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/MIND-FORGE-REFERENCE-V6.md +96 -0
  718. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/PERSONAS.md +920 -0
  719. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/audit-events.md +59 -0
  720. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/checkpoints.md +778 -0
  721. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/commands.md +107 -0
  722. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/config-reference.md +81 -0
  723. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/continuation-format.md +249 -0
  724. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/decimal-phase-calculation.md +64 -0
  725. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/git-integration.md +295 -0
  726. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/git-planning-commit.md +38 -0
  727. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/model-profile-resolution.md +36 -0
  728. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/model-profiles.md +139 -0
  729. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/phase-argument-parsing.md +61 -0
  730. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/planning-config.md +202 -0
  731. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/questioning.md +162 -0
  732. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/sdk-api.md +53 -0
  733. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/skills-api.md +57 -0
  734. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/tdd.md +263 -0
  735. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/ui-brand.md +160 -0
  736. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/user-profiling.md +681 -0
  737. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/verification-patterns.md +612 -0
  738. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/References/workstream-flag.md +58 -0
  739. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Agents/CLAUDE-MD.md +122 -0
  740. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Agents/COPILOT-INSTRUCTIONS.md +7 -0
  741. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Agents/DEBUGGER-PROMPT.md +91 -0
  742. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Agents/PLANNER-PROMPT.md +117 -0
  743. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Codebase/architecture.md +255 -0
  744. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Codebase/concerns.md +310 -0
  745. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Codebase/conventions.md +307 -0
  746. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Codebase/integrations.md +280 -0
  747. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Codebase/stack.md +186 -0
  748. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Codebase/structure.md +285 -0
  749. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Codebase/testing.md +480 -0
  750. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Execution/CONTINUE-HERE.md +78 -0
  751. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Execution/DISCUSSION-LOG.md +63 -0
  752. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Execution/PHASE-PROMPT.md +610 -0
  753. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Execution/STATE.md +176 -0
  754. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Execution/SUMMARY-COMPLEX.md +59 -0
  755. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Execution/SUMMARY-MINIMAL.md +41 -0
  756. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Execution/SUMMARY-STANDARD.md +48 -0
  757. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Execution/SUMMARY.md +248 -0
  758. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Profile/DEV-PREFERENCES.md +21 -0
  759. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Profile/USER-PROFILE.md +146 -0
  760. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Profile/USER-SETUP.md +311 -0
  761. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Project/AGENTS_LEARNING.md +88 -0
  762. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Project/DISCOVERY.md +146 -0
  763. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Project/MILESTONE-ARCHIVE.md +123 -0
  764. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Project/MILESTONE.md +115 -0
  765. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Project/PROJECT.md +206 -0
  766. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Project/REQUIREMENTS.md +231 -0
  767. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Project/RETROSPECTIVE.md +54 -0
  768. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Project/ROADMAP.md +202 -0
  769. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Quality/DEBUG.md +164 -0
  770. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Quality/UAT.md +280 -0
  771. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Quality/UI-SPEC.md +100 -0
  772. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Quality/VALIDATION.md +76 -0
  773. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Quality/VERIFICATION-REPORT.md +322 -0
  774. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Research/ARCHITECTURE.md +204 -0
  775. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Research/FEATURES.md +147 -0
  776. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Research/PITFALLS.md +200 -0
  777. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Research/STACK.md +120 -0
  778. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/Research/SUMMARY.md +170 -0
  779. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/System/CONFIG.json +43 -0
  780. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/Templates/System/CONTEXT.md +352 -0
  781. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/adr/ADR-024-browser-localhost-only.md +17 -0
  782. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/adr/ADR-025-visual-verify-failure-treatment.md +19 -0
  783. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/adr/ADR-026-session-persistence-security.md +20 -0
  784. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/adr/ADR-042-ads-protocol.md +30 -0
  785. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/architecture/NEXUS-DASHBOARD.md +35 -0
  786. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/architecture/PAR-ZTS-SURVEY.md +43 -0
  787. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/architecture/README.md +78 -0
  788. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/architecture/V3-CORE.md +52 -0
  789. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/architecture/V4-SWARM-MESH.md +77 -0
  790. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/architecture/V5-ENTERPRISE.md +131 -0
  791. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/architecture/V6-SOVEREIGN.md +43 -0
  792. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/architecture/adr-039-multi-runtime-support.md +20 -0
  793. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/architecture/adr-040-additive-schema-migration.md +21 -0
  794. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/architecture/adr-041-stable-runtime-interface-contract.md +20 -0
  795. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/architecture/decision-records-index.md +29 -0
  796. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/ci-cd-integration.md +30 -0
  797. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/ci-cd.md +92 -0
  798. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/ci-quickstart.md +78 -0
  799. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/commands-reference.md +144 -0
  800. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/commands-skills/DISCOVERED_SKILLS.md +21 -0
  801. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/contributing/CONTRIBUTING.md +38 -0
  802. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/contributing/plugin-authoring.md +50 -0
  803. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/contributing/skill-authoring.md +41 -0
  804. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/enterprise-setup.md +25 -0
  805. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/faq.md +38 -0
  806. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/feature-dashboard.md +63 -0
  807. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/getting-started.md +44 -0
  808. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/governance-guide.md +99 -0
  809. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/monorepo-guide.md +26 -0
  810. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/persona-customisation.md +56 -0
  811. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/publishing-guide.md +43 -0
  812. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/quick-verify.md +33 -0
  813. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/registry/AGENTS.md +37 -0
  814. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/registry/COMMANDS.md +87 -0
  815. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/registry/HOOKS.md +38 -0
  816. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/registry/PERSONAS.md +64 -0
  817. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/registry/README.md +27 -0
  818. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/registry/SKILLS.md +142 -0
  819. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/registry/WORKFLOWS.md +72 -0
  820. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/release-checklist-guide.md +37 -0
  821. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/requirements.md +29 -0
  822. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/sdk-reference.md +27 -0
  823. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/security/SECURITY.md +55 -0
  824. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/security/ZTAI-OVERVIEW.md +37 -0
  825. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/security/penetration-test-results.md +31 -0
  826. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/security/threat-model.md +142 -0
  827. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/skills-authoring-guide.md +176 -0
  828. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/skills-publishing-guide.md +22 -0
  829. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/team-setup-guide.md +21 -0
  830. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/testing-current-version.md +130 -0
  831. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/troubleshooting.md +139 -0
  832. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/tutorial.md +162 -0
  833. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/upgrade.md +58 -0
  834. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/user-guide.md +244 -0
  835. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/usp-features.md +102 -0
  836. package/.mindforge/mirrors/mirror-sre-776a1cf9/docs/workflow-atlas.md +57 -0
  837. package/.mindforge/mirrors/mirror-sre-776a1cf9/eslint.config.mjs +31 -0
  838. package/.mindforge/mirrors/mirror-sre-776a1cf9/examples/starter-project/.planning/AUDIT.jsonl +1 -0
  839. package/.mindforge/mirrors/mirror-sre-776a1cf9/examples/starter-project/.planning/HANDOFF.json +23 -0
  840. package/.mindforge/mirrors/mirror-sre-776a1cf9/examples/starter-project/.planning/PROJECT.md +27 -0
  841. package/.mindforge/mirrors/mirror-sre-776a1cf9/examples/starter-project/.planning/STATE.md +10 -0
  842. package/.mindforge/mirrors/mirror-sre-776a1cf9/examples/starter-project/MINDFORGE.md +40 -0
  843. package/.mindforge/mirrors/mirror-sre-776a1cf9/examples/starter-project/README.md +14 -0
  844. package/.mindforge/mirrors/mirror-sre-776a1cf9/package-lock.json +3882 -0
  845. package/.mindforge/mirrors/mirror-sre-776a1cf9/package.json +66 -0
  846. package/.mindforge/mirrors/mirror-sre-776a1cf9/sdk/README.md +69 -0
  847. package/.mindforge/mirrors/mirror-sre-776a1cf9/sdk/eslint.config.mjs +34 -0
  848. package/.mindforge/mirrors/mirror-sre-776a1cf9/sdk/package-lock.json +1507 -0
  849. package/.mindforge/mirrors/mirror-sre-776a1cf9/sdk/package.json +30 -0
  850. package/.mindforge/mirrors/mirror-sre-776a1cf9/sdk/src/client.ts +133 -0
  851. package/.mindforge/mirrors/mirror-sre-776a1cf9/sdk/src/commands.ts +63 -0
  852. package/.mindforge/mirrors/mirror-sre-776a1cf9/sdk/src/events.ts +166 -0
  853. package/.mindforge/mirrors/mirror-sre-776a1cf9/sdk/src/index.ts +23 -0
  854. package/.mindforge/mirrors/mirror-sre-776a1cf9/sdk/src/memory.ts +257 -0
  855. package/.mindforge/mirrors/mirror-sre-776a1cf9/sdk/src/types.ts +87 -0
  856. package/.mindforge/mirrors/mirror-sre-776a1cf9/sdk/tsconfig.json +13 -0
  857. package/.mindforge/mirrors/mirror-sre-776a1cf9/skills-lock.json +30 -0
  858. package/.mindforge/mirrors/mirror-sre-776a1cf9/test/sovereign-status.test.js +18 -0
  859. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/ads.test.js +121 -0
  860. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/audit.test.js +206 -0
  861. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/autonomous.test.js +53 -0
  862. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/browser.test.js +61 -0
  863. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/ci-mode.test.js +162 -0
  864. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/compaction.test.js +161 -0
  865. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/dashboard.test.js +327 -0
  866. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/distribution.test.js +205 -0
  867. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/e2e.test.js +618 -0
  868. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/entropy-test.js +47 -0
  869. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/feedback-loop.test.js +62 -0
  870. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/governance/test-cadia-optimizer.js +112 -0
  871. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/governance/test-policies/deny-security.json +9 -0
  872. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/governance/test-policies/permit-t2.json +10 -0
  873. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/governance.test.js +130 -0
  874. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/install.test.js +209 -0
  875. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/integrations.test.js +128 -0
  876. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/intelligence.test.js +117 -0
  877. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/knowledge-graph.test.js +593 -0
  878. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/learning-engine.test.js +69 -0
  879. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/mca-routing-test.js +37 -0
  880. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/memory.test.js +166 -0
  881. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/metrics.test.js +96 -0
  882. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/migration.test.js +308 -0
  883. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/model-broker.test.js +55 -0
  884. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/model-routing.test.js +111 -0
  885. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/nexus-tracing.test.js +49 -0
  886. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/production.test.js +416 -0
  887. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/release.test.js +99 -0
  888. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/revops-roi.test.js +52 -0
  889. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/run-nexus-tests.js +84 -0
  890. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/sdk.test.js +200 -0
  891. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/security-audit.test.js +67 -0
  892. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/self-building-skills.test.js +285 -0
  893. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/semantic-hub.test.js +91 -0
  894. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/sharding.test.js +87 -0
  895. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/skills-platform.test.js +389 -0
  896. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/sre-zk-proof-test.js +76 -0
  897. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/swarms.test.md +21 -0
  898. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/temporal-vision.test.js +68 -0
  899. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/v7-pillar-integration.test.js +73 -0
  900. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/v7-proactive-homing.test.js +53 -0
  901. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/v7-sovereign-security.test.js +64 -0
  902. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/v8-mesh-sync.test.js +76 -0
  903. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/v8-orbital-governance.test.js +74 -0
  904. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/v8-persistence.test.js +86 -0
  905. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/v8-skill-evolution.test.js +74 -0
  906. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/wave-engine.test.js +336 -0
  907. package/.mindforge/mirrors/mirror-sre-776a1cf9/tests/ztai-enterprise.test.js +103 -0
  908. package/.planning/archive/v8-cleanup/.agents/skills/ai-image-generation/SKILL.md +147 -0
  909. package/.planning/archive/v8-cleanup/.agents/skills/ai-video-generation/SKILL.md +185 -0
  910. package/.planning/archive/v8-cleanup/.agents/skills/critique/SKILL.md +201 -0
  911. package/.planning/archive/v8-cleanup/.agents/skills/critique/reference/cognitive-load.md +106 -0
  912. package/.planning/archive/v8-cleanup/.agents/skills/critique/reference/heuristics-scoring.md +234 -0
  913. package/.planning/archive/v8-cleanup/.agents/skills/critique/reference/personas.md +178 -0
  914. package/.planning/archive/v8-cleanup/.agents/skills/elevenlabs-music/SKILL.md +191 -0
  915. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/SKILL.md +659 -0
  916. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/_sync_all.py +414 -0
  917. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/app-interface.csv +31 -0
  918. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/charts.csv +26 -0
  919. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/colors.csv +162 -0
  920. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/design.csv +1776 -0
  921. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/draft.csv +1779 -0
  922. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/google-fonts.csv +1924 -0
  923. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/icons.csv +106 -0
  924. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/landing.csv +35 -0
  925. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/products.csv +162 -0
  926. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  927. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  928. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/styles.csv +85 -0
  929. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/typography.csv +74 -0
  930. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/ui-reasoning.csv +162 -0
  931. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  932. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/scripts/core.py +247 -0
  933. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  934. package/.planning/archive/v8-cleanup/.agents/skills/ui-ux-pro-max/scripts/search.py +114 -0
  935. package/.planning/archive/v8-cleanup/.forge/org/CONVENTIONS.md +0 -0
  936. package/.planning/archive/v8-cleanup/.forge/org/ORG.md +0 -0
  937. package/.planning/archive/v8-cleanup/.forge/org/SECURITY.md +0 -0
  938. package/.planning/archive/v8-cleanup/.forge/org/TOOLS.md +0 -0
  939. package/.planning/archive/v8-cleanup/.forge/personas/analyst.md +0 -0
  940. package/.planning/archive/v8-cleanup/.forge/personas/architect.md +0 -0
  941. package/.planning/archive/v8-cleanup/.forge/personas/debug-specialist.md +0 -0
  942. package/.planning/archive/v8-cleanup/.forge/personas/developer.md +26 -0
  943. package/.planning/archive/v8-cleanup/.forge/personas/qa-engineer.md +0 -0
  944. package/.planning/archive/v8-cleanup/.forge/personas/release-manager.md +0 -0
  945. package/.planning/archive/v8-cleanup/.forge/personas/security-reviewer.md +33 -0
  946. package/.planning/archive/v8-cleanup/.forge/personas/tech-writer.md +0 -0
  947. package/.planning/archive/v8-cleanup/.forge/skills/api-design/SKILL.md +0 -0
  948. package/.planning/archive/v8-cleanup/.forge/skills/code-quality/SKILL.md +0 -0
  949. package/.planning/archive/v8-cleanup/.forge/skills/documentation/SKILL.md +0 -0
  950. package/.planning/archive/v8-cleanup/.forge/skills/security-review/SKILL.md +23 -0
  951. package/.planning/archive/v8-cleanup/.forge/skills/testing-standards/SKILL.md +27 -0
  952. package/.planning/archive/v8-cleanup/ARCHITECTURE-AUDIT-REPORT.md +90 -0
  953. package/.planning/archive/v8-cleanup/LOGS-BENCHMARKING.md +172 -0
  954. package/.planning/archive/v8-cleanup/MIND-FORGE-V6-ENTERPRISE-PROPOSAL.md +79 -0
  955. package/.planning/archive/v8-cleanup/ROADMAP_V7.md +67 -0
  956. package/.planning/archive/v8-cleanup/ROADMAP_V8.md +49 -0
  957. package/.planning/archive/v8-cleanup/github-actions-logs.md +88 -0
  958. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-1-imp/DAY1-HARDEN.md +823 -0
  959. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-1-imp/DAY1-IMPLEMENT.md +2459 -0
  960. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-1-imp/DAY1-REVIEW.md +288 -0
  961. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-2-imp/DAY2-HARDEN.md +954 -0
  962. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-2-imp/DAY2-IMPLEMENT.md +2347 -0
  963. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-2-imp/DAY2-REVIEW.md +422 -0
  964. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-3-imp/DAY3-HARDEN.md +870 -0
  965. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-3-imp/DAY3-IMPLEMENT.md +2798 -0
  966. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-3-imp/DAY3-REVIEW.md +484 -0
  967. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-4-imp/DAY4-HARDEN.md +1087 -0
  968. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-4-imp/DAY4-IMPLEMENT.md +2874 -0
  969. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-4-imp/DAY4-REVIEW.md +386 -0
  970. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-5-imp/DAY5-HARDEN.md +1078 -0
  971. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-5-imp/DAY5-IMPLEMENT.md +3151 -0
  972. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-5-imp/DAY5-REVIEW.md +345 -0
  973. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-6-imp/DAY6-COMPLETE.md +3919 -0
  974. package/.planning/archive/v8-cleanup/implementation-roadmap/v1.0.0/day-7-imp-prod/DAY7-PRODUCTION-FINAL.md +4513 -0
  975. package/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/ci-actions/github-workflows-v2.md +421 -0
  976. package/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/ci-actions/v2-ci-actions.md +292 -0
  977. package/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-10-imp/DAY10-MULTI-MODEL.md +3402 -0
  978. package/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-11-imp/DAY11-PERSISTENT-MEMORY.md +3237 -0
  979. package/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-12-imp/DAY12-REALTIME-DASHBOARD.md +3301 -0
  980. package/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-13-imp/DAY13-SELF-BUILDING-SKILLS.md +3798 -0
  981. package/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-14-prod-v2/DAY14-V2-PRODUCTION-RELEASE.md +2255 -0
  982. package/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-8-imp/DAY8-AUTONOMOUS-ENGINE.md +3400 -0
  983. package/.planning/archive/v8-cleanup/implementation-roadmap/v2.0.0/day-9-imp/DAY9-BROWSER-RUNTIME.md +3293 -0
  984. package/.planning/decisions/SRE-4e54a061.md +19 -0
  985. package/CHANGELOG.md +14 -0
  986. package/MINDFORGE.md +5 -4
  987. package/README.md +3 -2
  988. package/RELEASENOTES.md +17 -0
  989. package/bin/autonomous/auto-runner.js +64 -0
  990. package/bin/engine/learning-manager.js +4 -2
  991. package/bin/governance/impact-analyzer.js +4 -2
  992. package/bin/installer-core.js +18 -2
  993. package/bin/models/model-router.js +3 -1
  994. package/bin/sre/adversarial-sre.js +109 -0
  995. package/bin/sre/sentinel.js +128 -0
  996. package/bin/sre/shadow-mirror.js +122 -0
  997. package/bin/sre/sli-verifier.js +81 -0
  998. package/docs/Context/Master-Context.md +22 -2
  999. package/docs/PERSONAS.md +40 -0
  1000. package/docs/architecture/V8-SRE.md +88 -0
  1001. package/docs/governance-guide.md +43 -17
  1002. package/package.json +2 -2
@@ -0,0 +1,3293 @@
1
+ # MindForge v2 — Day 9: Persistent Browser Runtime + Visual QA
2
+ # Branch: `feat/mindforge-v2-browser-runtime`
3
+ # Prerequisite: `feat/mindforge-v2-autonomous-engine` merged to `main`
4
+ # Version target: v2.0.0-alpha.2
5
+ # Theme: "The Agent Has Eyes Now."
6
+
7
+ ---
8
+
9
+ ## BRANCH SETUP
10
+
11
+ ```bash
12
+ git checkout main
13
+ git pull origin main
14
+
15
+ # Verify Day 8 baseline is clean
16
+ node -e "console.log(require('./package.json').version)" # Must be 2.0.0-alpha.1
17
+
18
+ # All 16 test suites must pass before starting Day 9
19
+ SUITES=(install wave-engine audit compaction skills-platform \
20
+ integrations governance intelligence metrics \
21
+ distribution ci-mode sdk production migration e2e autonomous)
22
+
23
+ for suite in "${SUITES[@]}"; do
24
+ printf " %-30s" "${suite}..."
25
+ node tests/${suite}.test.js 2>&1 | tail -1
26
+ done
27
+ # ALL 16 must show "passed" — zero failures before Day 9 begins.
28
+
29
+ # Create Day 9 branch
30
+ git checkout -b feat/mindforge-v2-browser-runtime
31
+ ```
32
+
33
+ ---
34
+
35
+ ## DAY 9 SCOPE
36
+
37
+ Day 9 gives MindForge **eyes**. This is the single feature that no other
38
+ enterprise agentic framework has implemented end-to-end: a long-lived
39
+ Chromium process that persists across the entire session, keeping login state,
40
+ cookies, and tabs alive between every `/mindforge:browse` call.
41
+
42
+ **The competitive insight (from the v2 research report):**
43
+ gstack's browser subsystem is its most-cited differentiator. Their key
44
+ architectural decision: a browser that stays alive across calls (100-200ms
45
+ warm calls) is categorically different from spawning a browser per command
46
+ (3-5s cold start every time). MindForge Day 9 goes beyond gstack by adding:
47
+ enterprise governance on every visual action, `<verify-visual>` blocks in PLAN
48
+ files so visual verification is first-class alongside unit tests, a systematic
49
+ QA engine that analyses the git diff and tests every changed route, and auto-
50
+ generated regression tests for every bug found.
51
+
52
+ | Component | Description | Lines |
53
+ |---|---|---|
54
+ | Browser Daemon Protocol spec | Full HTTP API contract, security model, performance targets | Engine spec |
55
+ | `bin/browser/browser-daemon.js` | Long-lived Chromium via Playwright, localhost:7338 | Full implementation |
56
+ | `bin/browser/daemon-manager.js` | Start/stop/health/auto-restart lifecycle manager | Full implementation |
57
+ | `bin/browser/session-manager.js` | Named sessions, persistence, real-browser cookie import | Full implementation |
58
+ | `bin/browser/visual-verify-executor.js` | `<verify-visual>` block parser and executor | Full implementation |
59
+ | `bin/browser/screenshot-store.js` | Screenshot save/list/cleanup with phase namespacing | Full implementation |
60
+ | `bin/browser/qa-engine.js` | Diff-aware QA surface extraction, test plan, execution | Full implementation |
61
+ | `bin/browser/qa-report-writer.js` | QA-REPORT-[N].md generator | Full implementation |
62
+ | `bin/browser/regression-writer.js` | Auto-generate Playwright regression tests per bug | Full implementation |
63
+ | `/mindforge:browse` command | Full browser control with session management | Command spec |
64
+ | `/mindforge:qa` command | Systematic post-phase visual QA | Command spec |
65
+ | `<verify-visual>` PLAN field | Visual verification integrated into execute-phase | Spec + parser |
66
+ | MINDFORGE.md v2 browser settings | Full configuration for browser runtime | Schema |
67
+ | `tests/browser.test.js` | 17th test suite — all browser components | Test suite |
68
+
69
+ **New commands today: 40 total (38 from Day 8 + browse + qa)**
70
+
71
+ ---
72
+
73
+ # ═══════════════════════════════════════════════════════════════════════
74
+ # PART 1 — IMPLEMENTATION PROMPT
75
+ # ═══════════════════════════════════════════════════════════════════════
76
+
77
+ ---
78
+
79
+ ## TASK 1 — Scaffold Day 9 directory structure
80
+
81
+ ```bash
82
+ # Browser runtime binaries
83
+ mkdir -p bin/browser
84
+ touch bin/browser/browser-daemon.js
85
+ touch bin/browser/daemon-manager.js
86
+ touch bin/browser/session-manager.js
87
+ touch bin/browser/visual-verify-executor.js
88
+ touch bin/browser/screenshot-store.js
89
+ touch bin/browser/qa-engine.js
90
+ touch bin/browser/qa-report-writer.js
91
+ touch bin/browser/regression-writer.js
92
+
93
+ # Engine specifications
94
+ mkdir -p .mindforge/browser
95
+ touch .mindforge/browser/daemon-protocol.md
96
+ touch .mindforge/browser/session-manager.md
97
+ touch .mindforge/browser/visual-verify-spec.md
98
+ touch .mindforge/browser/qa-engine.md
99
+
100
+ # Session storage — gitignored
101
+ mkdir -p .mindforge/browser/sessions
102
+ touch .mindforge/browser/sessions/.gitkeep
103
+
104
+ # Screenshot storage — gitignored
105
+ mkdir -p .planning/screenshots
106
+ touch .planning/screenshots/.gitkeep
107
+
108
+ # New slash commands
109
+ touch .claude/commands/mindforge/browse.md
110
+ touch .claude/commands/mindforge/qa.md
111
+ for cmd in browse qa; do
112
+ cp .claude/commands/mindforge/${cmd}.md .agent/mindforge/${cmd}.md
113
+ done
114
+
115
+ # Test suite
116
+ touch tests/browser.test.js
117
+
118
+ # Docs
119
+ touch docs/browser-runtime-guide.md
120
+ touch docs/visual-qa-guide.md
121
+
122
+ # Update .gitignore — browser artifacts must NEVER be committed
123
+ cat >> .gitignore << 'EOF'
124
+
125
+ # MindForge v2 — browser runtime (session files contain auth tokens)
126
+ .mindforge/browser/sessions/*.json
127
+ .planning/screenshots/
128
+ .planning/auto-progress.jsonl
129
+ EOF
130
+ ```
131
+
132
+ **Add Playwright as optional dependency:**
133
+ ```bash
134
+ node -e "
135
+ const fs = require('fs');
136
+ const p = JSON.parse(fs.readFileSync('package.json','utf8'));
137
+ p.optionalDependencies = p.optionalDependencies || {};
138
+ p.optionalDependencies['playwright-core'] = '^1.44.0';
139
+ fs.writeFileSync('package.json', JSON.stringify(p, null, 2) + '\n');
140
+ console.log('Added playwright-core as optional dependency');
141
+ "
142
+ ```
143
+
144
+ **Commit:**
145
+ ```bash
146
+ git add .
147
+ git commit -m "chore(v2-day9): scaffold browser runtime directory structure"
148
+ ```
149
+
150
+ ---
151
+
152
+ ## TASK 2 — Write the Browser Daemon Protocol Specification
153
+
154
+ ### `.mindforge/browser/daemon-protocol.md`
155
+
156
+ ````markdown
157
+ # MindForge v2 — Browser Daemon Protocol
158
+
159
+ ## Architecture
160
+
161
+ ```
162
+ Agent / Command Daemon Manager Browser Daemon
163
+ /mindforge:browse → daemon-manager.js → browser-daemon.js
164
+ /mindforge:qa Start/stop/restart Playwright Chromium
165
+ Health check HTTP localhost:7338
166
+ PID management Named sessions
167
+ Screenshot capture
168
+ ```
169
+
170
+ ## Port and binding
171
+
172
+ - **Port:** 7338 (SSE stream = 7337, Dashboard = 7339)
173
+ - **Binding:** `127.0.0.1` ONLY — never `0.0.0.0` (per ADR-017 policy)
174
+ - **Protocol:** HTTP/1.1 (no TLS — localhost only, same rationale as SDK SSE)
175
+ - **Process lifecycle:**
176
+ - Starts on first API call if not running (auto-start via daemon-manager)
177
+ - Auto-shuts down after `BROWSER_IDLE_TIMEOUT_MINUTES` (default: 30) of no activity
178
+ - Survives across multiple MindForge command invocations in the same session
179
+
180
+ ## Full API endpoint reference
181
+
182
+ ### `GET /status`
183
+ ```json
184
+ Response 200:
185
+ {
186
+ "alive": true,
187
+ "chromium_version": "Chromium 124.0.6367.8",
188
+ "sessions": ["default", "admin", "user"],
189
+ "active_session": "default",
190
+ "current_url": "https://localhost:3000/dashboard",
191
+ "last_action_at": "ISO-8601",
192
+ "idle_minutes": 2.3,
193
+ "memory_mb": 287,
194
+ "uptime_seconds": 1823
195
+ }
196
+ Response 503 (starting up):
197
+ { "alive": false, "status": "starting", "eta_ms": 3000 }
198
+ ```
199
+
200
+ ### `POST /navigate`
201
+ ```json
202
+ Request:
203
+ { "url": "https://localhost:3000/login", "session": "default",
204
+ "wait_for": "networkidle|domcontentloaded|load", "timeout": 30000 }
205
+ Response:
206
+ { "success": true, "final_url": "...", "title": "...", "status_code": 200,
207
+ "screenshot_b64": "base64...", "width": 1280, "height": 720,
208
+ "console_errors": [], "load_time_ms": 423 }
209
+ ```
210
+
211
+ ### `POST /click`
212
+ ```json
213
+ Request (CSS selector): { "selector": "#submit-btn", "session": "default", "screenshot_after": true }
214
+ Request (visible text): { "text": "Sign In", "session": "default" }
215
+ Request (ARIA label): { "aria_label": "Close", "session": "default" }
216
+ Response:
217
+ { "success": true, "element_found": true, "screenshot_b64": "...",
218
+ "console_errors": [], "navigation_triggered": false }
219
+ ```
220
+
221
+ ### `POST /type`
222
+ ```json
223
+ Request:
224
+ { "selector": "input[name='email']", "text": "test@example.com",
225
+ "clear_first": true, "press_enter": false, "session": "default" }
226
+ Response: { "success": true, "element_found": true }
227
+ ```
228
+
229
+ ### `POST /screenshot`
230
+ ```json
231
+ Request: { "session": "default", "full_page": false }
232
+ Response: { "success": true, "screenshot_b64": "...", "width": 1280, "height": 720 }
233
+ ```
234
+
235
+ ### `POST /evaluate`
236
+ ```json
237
+ Request: { "script": "document.title", "session": "default" }
238
+ Response: { "success": true, "result": "My App", "type": "string" }
239
+ ```
240
+
241
+ ### `POST /assert`
242
+ ```json
243
+ Request: { "type": "visible|url|title|no_console_errors",
244
+ "selector": "h1", "expected_text": "My Projects", "session": "default" }
245
+ Response (pass): { "success": true, "passed": true, "actual_text": "My Projects", "screenshot_b64": "..." }
246
+ Response (fail): { "success": true, "passed": false, "error": "Element not found: h1", "screenshot_b64": "..." }
247
+ ```
248
+
249
+ ### Session endpoints
250
+ ```
251
+ POST /session/create { "name": "admin", "copy_from": "default" }
252
+ POST /session/switch { "session": "admin" }
253
+ POST /session/save { "session": "admin" }
254
+ POST /session/load { "session": "admin" }
255
+ POST /session/import-cookies { "source": "chrome|arc|brave|edge|firefox", "session": "admin" }
256
+ POST /session/delete { "session": "admin" }
257
+ GET /session/list → [{ "name": "admin", "saved_at": "...", "url": "..." }]
258
+ POST /shutdown { "save_sessions": true }
259
+ ```
260
+
261
+ ## Error response format (all errors)
262
+ ```json
263
+ {
264
+ "success": false,
265
+ "error": "Element not found: #nonexistent",
266
+ "error_type": "element_not_found|navigation_failed|evaluation_error|timeout|session_not_found",
267
+ "screenshot_b64": "base64...",
268
+ "url_at_error": "https://localhost:3000/dashboard"
269
+ }
270
+ ```
271
+
272
+ ## Performance targets
273
+
274
+ | Action | Cold start | Warm (after init) |
275
+ |---|---|---|
276
+ | Daemon startup | 3-5 seconds | — |
277
+ | navigate | ~400ms first | ~150ms |
278
+ | click | — | 80-120ms |
279
+ | screenshot | — | 60ms |
280
+ | evaluate | — | 30ms |
281
+ | assert | — | 80ms |
282
+
283
+ ## Security model
284
+
285
+ 1. **Localhost-only binding** (127.0.0.1) — consistent with ADR-017 (SDK SSE policy)
286
+ 2. **IP check on every request** — non-localhost → 403 immediately
287
+ 3. **evaluate safety** — only use on YOUR OWN dev app, never on external URLs
288
+ 4. **Session files are gitignored** — they contain auth tokens
289
+ 5. **Screenshots are gitignored** — they may contain sensitive UI data
290
+ 6. **Playwright sandbox flags** — `--no-sandbox` required for CI; always use in controlled env
291
+ ````
292
+
293
+ **Commit:**
294
+ ```bash
295
+ git add .mindforge/browser/daemon-protocol.md
296
+ git commit -m "feat(v2-browser): write browser daemon protocol specification"
297
+ ```
298
+
299
+ ---
300
+
301
+ ## TASK 3 — Implement the Browser Daemon
302
+
303
+ ### `bin/browser/browser-daemon.js`
304
+
305
+ ```javascript
306
+ #!/usr/bin/env node
307
+ /**
308
+ * MindForge v2 — Browser Daemon
309
+ * Long-lived Chromium process, HTTP API at localhost:7338.
310
+ *
311
+ * Spawned by daemon-manager.js — do NOT start directly.
312
+ *
313
+ * ENV:
314
+ * BROWSER_PORT — HTTP port (default: 7338)
315
+ * BROWSER_IDLE_TIMEOUT — Idle shutdown in minutes (default: 30)
316
+ * BROWSER_HEADLESS — true|false (default: true)
317
+ * BROWSER_VIEWPORT_WIDTH — (default: 1280)
318
+ * BROWSER_VIEWPORT_HEIGHT — (default: 720)
319
+ */
320
+ 'use strict';
321
+
322
+ const http = require('http');
323
+
324
+ const PORT = parseInt(process.env.BROWSER_PORT || '7338', 10);
325
+ const IDLE_MS = parseInt(process.env.BROWSER_IDLE_TIMEOUT || '30', 10) * 60_000;
326
+ const HEADLESS = process.env.BROWSER_HEADLESS !== 'false';
327
+ const VIEWPORT = {
328
+ width: parseInt(process.env.BROWSER_VIEWPORT_WIDTH || '1280', 10),
329
+ height: parseInt(process.env.BROWSER_VIEWPORT_HEIGHT || '720', 10),
330
+ };
331
+
332
+ let playwright, browser;
333
+ const sessions = {}; // name → { context, page, consoleErrors[] }
334
+ let lastActionAt = Date.now();
335
+
336
+ // ── Playwright initialisation ─────────────────────────────────────────────────
337
+ async function init() {
338
+ try {
339
+ playwright = require('playwright-core');
340
+ } catch {
341
+ process.stderr.write(
342
+ '[daemon] playwright-core not installed.\n' +
343
+ '[daemon] Run: npm install playwright-core && npx playwright install chromium\n'
344
+ );
345
+ process.exit(1);
346
+ }
347
+
348
+ browser = await playwright.chromium.launch({
349
+ headless: HEADLESS,
350
+ args: [
351
+ '--no-sandbox', '--disable-setuid-sandbox',
352
+ '--disable-dev-shm-usage', '--disable-accelerated-2d-canvas',
353
+ '--no-first-run', '--no-zygote',
354
+ ],
355
+ });
356
+
357
+ await newSession('default');
358
+ process.stdout.write(`READY:${PORT}\n`);
359
+ process.stderr.write(`[daemon] Chromium ${browser.version()} ready on :${PORT}\n`);
360
+ }
361
+
362
+ // ── Session management ────────────────────────────────────────────────────────
363
+ async function newSession(name, copyFrom) {
364
+ if (sessions[name]) return sessions[name];
365
+
366
+ const context = await browser.newContext({
367
+ viewport: VIEWPORT,
368
+ userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
369
+ ignoreHTTPSErrors: true,
370
+ });
371
+
372
+ if (copyFrom && sessions[copyFrom]) {
373
+ const cookies = await sessions[copyFrom].context.cookies();
374
+ if (cookies.length) await context.addCookies(cookies);
375
+ }
376
+
377
+ const page = await context.newPage();
378
+ const errs = [];
379
+ page.on('console', m => {
380
+ if (m.type() === 'error') errs.push({ ts: new Date().toISOString(), text: m.text(), url: page.url() });
381
+ });
382
+
383
+ sessions[name] = { context, page, consoleErrors: errs };
384
+ return sessions[name];
385
+ }
386
+
387
+ function sess(name = 'default') {
388
+ if (!sessions[name]) throw new Error(`Session not found: "${name}". Create it first.`);
389
+ return sessions[name];
390
+ }
391
+
392
+ // ── Action implementations ────────────────────────────────────────────────────
393
+
394
+ async function handleNavigate({ url, session: s = 'default', wait_for = 'networkidle', timeout = 30000 }) {
395
+ const { page, consoleErrors } = sess(s);
396
+ consoleErrors.length = 0;
397
+ const t0 = Date.now();
398
+ const resp = await page.goto(url, { waitUntil: wait_for === 'networkidle' ? 'networkidle' : 'domcontentloaded', timeout });
399
+ const img = await page.screenshot({ type: 'png' });
400
+ return {
401
+ success: true, final_url: page.url(), title: await page.title(),
402
+ status_code: resp?.status() ?? 0,
403
+ screenshot_b64: img.toString('base64'), width: VIEWPORT.width, height: VIEWPORT.height,
404
+ console_errors: [...consoleErrors], load_time_ms: Date.now() - t0,
405
+ };
406
+ }
407
+
408
+ async function handleClick({ selector, text, aria_label, session: s = 'default', screenshot_after = true, timeout = 5000 }) {
409
+ const { page } = sess(s);
410
+ const loc = selector ? page.locator(selector)
411
+ : text ? page.getByText(text, { exact: false })
412
+ : aria_label ? page.getByRole('button', { name: aria_label })
413
+ : (() => { throw new Error('click requires selector, text, or aria_label'); })();
414
+ const prev = page.url();
415
+ await loc.click({ timeout });
416
+ await page.waitForLoadState('networkidle').catch(() => {});
417
+ const img = screenshot_after ? await page.screenshot({ type: 'png' }) : null;
418
+ return { success: true, element_found: true,
419
+ screenshot_b64: img?.toString('base64') ?? null,
420
+ console_errors: [...sess(s).consoleErrors],
421
+ navigation_triggered: page.url() !== prev };
422
+ }
423
+
424
+ async function handleType({ selector, text, clear_first = true, press_enter = false, session: s = 'default', timeout = 5000 }) {
425
+ const { page } = sess(s);
426
+ const loc = page.locator(selector);
427
+ await loc.waitFor({ timeout });
428
+ if (clear_first) await loc.clear();
429
+ await loc.fill(text);
430
+ if (press_enter) await loc.press('Enter');
431
+ return { success: true, element_found: true };
432
+ }
433
+
434
+ async function handleScreenshot({ session: s = 'default', full_page = false, clip }) {
435
+ const { page } = sess(s);
436
+ const img = await page.screenshot({ type: 'png', fullPage: full_page, clip: clip ?? undefined });
437
+ return { success: true, screenshot_b64: img.toString('base64'), width: VIEWPORT.width, height: VIEWPORT.height, format: 'png' };
438
+ }
439
+
440
+ async function handleEvaluate({ script, session: s = 'default' }) {
441
+ const { page } = sess(s);
442
+ const result = await page.evaluate(script);
443
+ return { success: true, result, type: typeof result };
444
+ }
445
+
446
+ async function handleAssert({ type, selector, expected_text, session: s = 'default', timeout = 5000 }) {
447
+ const { page } = sess(s);
448
+ try {
449
+ switch (type) {
450
+ case 'visible': {
451
+ await page.locator(selector).waitFor({ state: 'visible', timeout });
452
+ const actual = expected_text ? await page.locator(selector).textContent() : null;
453
+ if (expected_text && !actual?.includes(expected_text)) {
454
+ const img = await page.screenshot({ type: 'png' });
455
+ return { success: true, passed: false, error: `Expected "${expected_text}", got "${actual}"`, screenshot_b64: img.toString('base64') };
456
+ }
457
+ const img = await page.screenshot({ type: 'png' });
458
+ return { success: true, passed: true, actual_text: actual, screenshot_b64: img.toString('base64') };
459
+ }
460
+ case 'url': {
461
+ const cur = page.url();
462
+ return { success: true, passed: cur.includes(expected_text ?? ''), actual_url: cur };
463
+ }
464
+ case 'title': {
465
+ const t = await page.title();
466
+ return { success: true, passed: t.includes(expected_text ?? ''), actual_title: t };
467
+ }
468
+ case 'no_console_errors': {
469
+ const errs = sess(s).consoleErrors;
470
+ return { success: true, passed: errs.length === 0, console_errors: [...errs] };
471
+ }
472
+ default:
473
+ throw new Error(`Unknown assertion type: "${type}"`);
474
+ }
475
+ } catch (err) {
476
+ const img = await page.screenshot({ type: 'png' }).catch(() => null);
477
+ return { success: true, passed: false, error: err.message, screenshot_b64: img?.toString('base64') ?? null, url_at_error: page.url() };
478
+ }
479
+ }
480
+
481
+ async function handleImportCookies({ source, session: s = 'default' }) {
482
+ const SM = require('./session-manager');
483
+ const cookies = await SM.importFromBrowser(source);
484
+ await sess(s).context.addCookies(cookies);
485
+ return { success: true, cookies_imported: cookies.length, session: s };
486
+ }
487
+
488
+ async function handleSaveSession({ session: s = 'default' }) {
489
+ const SM = require('./session-manager');
490
+ const filePath = await SM.saveSession(s, sess(s).context);
491
+ return { success: true, path: filePath, session: s };
492
+ }
493
+
494
+ async function handleLoadSession({ session: s = 'default' }) {
495
+ const SM = require('./session-manager');
496
+ if (!sessions[s]) await newSession(s);
497
+ const r = await SM.loadSession(s, sess(s).context);
498
+ return { success: true, ...r };
499
+ }
500
+
501
+ async function handleSessionCreate({ name, copy_from }) {
502
+ await newSession(name, copy_from);
503
+ return { success: true, session: name };
504
+ }
505
+
506
+ async function handleSessionDelete({ session: s }) {
507
+ if (!sessions[s]) return { success: false, error: `Session not found: ${s}` };
508
+ await sessions[s].context.close().catch(() => {});
509
+ delete sessions[s];
510
+ return { success: true, deleted: s };
511
+ }
512
+
513
+ function handleSessionList() {
514
+ const SM = require('./session-manager');
515
+ return { success: true, sessions: SM.listSessions() };
516
+ }
517
+
518
+ async function handleShutdown({ save_sessions = true }) {
519
+ if (save_sessions) {
520
+ const SM = require('./session-manager');
521
+ for (const [name, s] of Object.entries(sessions)) {
522
+ await SM.saveSession(name, s.context).catch(() => {});
523
+ }
524
+ }
525
+ setTimeout(() => process.exit(0), 100);
526
+ return { success: true, sessions_saved: Object.keys(sessions) };
527
+ }
528
+
529
+ // ── Route table ───────────────────────────────────────────────────────────────
530
+ const ROUTES = {
531
+ 'GET /status': () => ({
532
+ alive: true,
533
+ chromium_version: browser?.version() ?? 'unknown',
534
+ sessions: Object.keys(sessions),
535
+ last_action_at: new Date(lastActionAt).toISOString(),
536
+ idle_minutes: (Date.now() - lastActionAt) / 60_000,
537
+ }),
538
+ 'POST /navigate': handleNavigate,
539
+ 'POST /click': handleClick,
540
+ 'POST /type': handleType,
541
+ 'POST /screenshot': handleScreenshot,
542
+ 'POST /evaluate': handleEvaluate,
543
+ 'POST /assert': handleAssert,
544
+ 'POST /session/create': handleSessionCreate,
545
+ 'POST /session/switch': ({ session }) => { sess(session); return { success: true, session }; },
546
+ 'POST /session/save': handleSaveSession,
547
+ 'POST /session/load': handleLoadSession,
548
+ 'POST /session/import-cookies': handleImportCookies,
549
+ 'POST /session/delete': handleSessionDelete,
550
+ 'GET /session/list': handleSessionList,
551
+ 'POST /shutdown': handleShutdown,
552
+ };
553
+
554
+ // ── HTTP server ───────────────────────────────────────────────────────────────
555
+ const server = http.createServer(async (req, res) => {
556
+ // Security gate — localhost only
557
+ const addr = req.socket.remoteAddress;
558
+ if (addr !== '127.0.0.1' && addr !== '::1' && addr !== '::ffff:127.0.0.1') {
559
+ res.writeHead(403, { 'Content-Type': 'application/json' });
560
+ res.end(JSON.stringify({ success: false, error: 'Forbidden: localhost only' }));
561
+ return;
562
+ }
563
+
564
+ const key = `${req.method} ${req.url}`;
565
+ const handler = ROUTES[key];
566
+ if (!handler) {
567
+ res.writeHead(404, { 'Content-Type': 'application/json' });
568
+ res.end(JSON.stringify({ success: false, error: `No handler: ${key}` }));
569
+ return;
570
+ }
571
+
572
+ let body = {};
573
+ if (req.method === 'POST') {
574
+ const chunks = [];
575
+ for await (const chunk of req) chunks.push(chunk);
576
+ try { body = JSON.parse(Buffer.concat(chunks).toString() || '{}'); } catch { body = {}; }
577
+ }
578
+
579
+ try {
580
+ lastActionAt = Date.now();
581
+ const result = await handler(body);
582
+ res.writeHead(200, { 'Content-Type': 'application/json' });
583
+ res.end(JSON.stringify(result));
584
+ } catch (err) {
585
+ const snapshotPng = body.session ? await sessions[body.session]?.page?.screenshot({ type: 'png' }).catch(() => null) : null;
586
+ res.writeHead(500, { 'Content-Type': 'application/json' });
587
+ res.end(JSON.stringify({
588
+ success: false,
589
+ error: err.message,
590
+ error_type: err.constructor?.name ?? 'Error',
591
+ screenshot_b64: snapshotPng?.toString('base64') ?? null,
592
+ }));
593
+ }
594
+ });
595
+
596
+ // ── Idle-shutdown timer ───────────────────────────────────────────────────────
597
+ const idleCheck = setInterval(() => {
598
+ if (Date.now() - lastActionAt > IDLE_MS) {
599
+ process.stderr.write('[daemon] Idle timeout — shutting down\n');
600
+ browser?.close().catch(() => {});
601
+ process.exit(0);
602
+ }
603
+ }, 60_000);
604
+ idleCheck.unref();
605
+
606
+ // ── SIGTERM — graceful shutdown with session save ─────────────────────────────
607
+ process.on('SIGTERM', async () => {
608
+ process.stderr.write('[daemon] SIGTERM — saving sessions\n');
609
+ try {
610
+ const SM = require('./session-manager');
611
+ for (const [n, s] of Object.entries(sessions)) await SM.saveSession(n, s.context).catch(() => {});
612
+ } catch {}
613
+ await browser?.close().catch(() => {});
614
+ process.exit(0);
615
+ });
616
+
617
+ // ── Boot ──────────────────────────────────────────────────────────────────────
618
+ (async () => {
619
+ await init();
620
+ server.listen(PORT, '127.0.0.1', () =>
621
+ process.stderr.write(`[daemon] Listening http://127.0.0.1:${PORT}\n`)
622
+ );
623
+ server.on('error', err => {
624
+ if (err.code === 'EADDRINUSE') {
625
+ process.stderr.write(`[daemon] Port ${PORT} in use — is another instance running?\n`);
626
+ }
627
+ throw err;
628
+ });
629
+ })();
630
+ ```
631
+
632
+ ---
633
+
634
+ ### `bin/browser/daemon-manager.js`
635
+
636
+ ```javascript
637
+ /**
638
+ * MindForge v2 — Daemon Manager
639
+ * Manages browser-daemon.js lifecycle.
640
+ * Used by all browser commands and bin/browser/*.js modules.
641
+ */
642
+ 'use strict';
643
+
644
+ const http = require('http');
645
+ const { spawn } = require('child_process');
646
+ const path = require('path');
647
+ const fs = require('fs');
648
+
649
+ const PORT = parseInt(process.env.BROWSER_PORT || '7338', 10);
650
+ const PID_FILE = path.join(process.cwd(), '.planning', 'browser-daemon.pid');
651
+ const DAEMON_PATH = path.join(__dirname, 'browser-daemon.js');
652
+
653
+ let _daemonProc = null;
654
+
655
+ // ── Low-level HTTP client ─────────────────────────────────────────────────────
656
+ async function request(method, urlPath, body, timeoutMs = 10_000) {
657
+ return new Promise((resolve, reject) => {
658
+ const payload = body ? JSON.stringify(body) : '';
659
+ const req = http.request({
660
+ hostname: '127.0.0.1', port: PORT, path: urlPath, method,
661
+ headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) },
662
+ timeout: timeoutMs,
663
+ }, res => {
664
+ let data = '';
665
+ res.on('data', c => (data += c));
666
+ res.on('end', () => { try { resolve(JSON.parse(data)); } catch { resolve({ success: false, raw: data }); } });
667
+ });
668
+ req.on('error', reject);
669
+ req.on('timeout', () => { req.destroy(); reject(new Error(`Daemon timeout: ${method} ${urlPath}`)); });
670
+ if (payload) req.write(payload);
671
+ req.end();
672
+ });
673
+ }
674
+
675
+ // ── Health check ──────────────────────────────────────────────────────────────
676
+ async function isAlive() {
677
+ try { return (await request('GET', '/status', null, 2000))?.alive === true; } catch { return false; }
678
+ }
679
+
680
+ // ── Start daemon ──────────────────────────────────────────────────────────────
681
+ async function start({ headless = true, timeout = 20_000 } = {}) {
682
+ if (await isAlive()) return { started: false, already_running: true, port: PORT };
683
+
684
+ return new Promise((resolve, reject) => {
685
+ _daemonProc = spawn('node', [DAEMON_PATH], {
686
+ detached: false,
687
+ stdio: ['ignore', 'pipe', 'pipe'],
688
+ env: { ...process.env, BROWSER_PORT: String(PORT), BROWSER_HEADLESS: String(headless) },
689
+ });
690
+
691
+ fs.mkdirSync(path.dirname(PID_FILE), { recursive: true });
692
+ fs.writeFileSync(PID_FILE, String(_daemonProc.pid));
693
+
694
+ let ready = false;
695
+ const timer = setTimeout(() => {
696
+ if (!ready) reject(new Error(`Browser daemon did not start within ${timeout}ms`));
697
+ }, timeout);
698
+
699
+ _daemonProc.stdout.on('data', data => {
700
+ if (data.toString().includes('READY:') && !ready) {
701
+ ready = true;
702
+ clearTimeout(timer);
703
+ resolve({ started: true, port: PORT, pid: _daemonProc.pid });
704
+ }
705
+ });
706
+
707
+ _daemonProc.stderr.on('data', data => {
708
+ const txt = data.toString();
709
+ // Only surface actual errors, not Chromium's verbose noise
710
+ if (txt.includes('[daemon]') || /\berror\b/i.test(txt)) process.stderr.write(txt);
711
+ });
712
+
713
+ _daemonProc.on('exit', (code, signal) => {
714
+ if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);
715
+ if (!ready) reject(new Error(`Daemon exited early: code=${code} signal=${signal}`));
716
+ });
717
+ });
718
+ }
719
+
720
+ // ── Ensure daemon is running ──────────────────────────────────────────────────
721
+ async function ensureRunning(opts) {
722
+ if (await isAlive()) return { running: true, port: PORT };
723
+ return start(opts);
724
+ }
725
+
726
+ // ── Stop daemon ───────────────────────────────────────────────────────────────
727
+ async function stop(saveSessions = true) {
728
+ if (!await isAlive()) return { stopped: false, not_running: true };
729
+ try {
730
+ await request('POST', '/shutdown', { save_sessions: saveSessions }, 5000);
731
+ if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);
732
+ return { stopped: true };
733
+ } catch {
734
+ const pid = fs.existsSync(PID_FILE) ? parseInt(fs.readFileSync(PID_FILE, 'utf8')) : null;
735
+ if (_daemonProc) _daemonProc.kill('SIGTERM');
736
+ if (pid) try { process.kill(pid, 'SIGTERM'); } catch {}
737
+ if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);
738
+ return { stopped: true, forced: true };
739
+ }
740
+ }
741
+
742
+ // ── Convenience proxy methods ─────────────────────────────────────────────────
743
+ const navigate = (url, opts = {}) => ensureRunning().then(() => request('POST', '/navigate', { url, ...opts }));
744
+ const click = (sel, opts = {}) => ensureRunning().then(() => request('POST', '/click', { selector: sel, ...opts }));
745
+ const type = (sel, text, opts) => ensureRunning().then(() => request('POST', '/type', { selector: sel, text, ...opts }));
746
+ const screenshot = (opts = {}) => ensureRunning().then(() => request('POST', '/screenshot', opts));
747
+ const evaluate = (script, opts) => ensureRunning().then(() => request('POST', '/evaluate', { script, ...opts }));
748
+ const assertV = (type, sel, exp, opts) =>
749
+ ensureRunning().then(() => request('POST', '/assert', { type, selector: sel, expected_text: exp, ...opts }));
750
+ const getStatus = () => request('GET', '/status', null, 2000).catch(() => ({ alive: false }));
751
+
752
+ module.exports = { start, stop, ensureRunning, isAlive, getStatus, request, navigate, click, type, screenshot, evaluate, assertV };
753
+ ```
754
+
755
+ **Commit:**
756
+ ```bash
757
+ git add bin/browser/browser-daemon.js bin/browser/daemon-manager.js
758
+ git commit -m "feat(v2-browser): implement Playwright browser daemon and daemon manager"
759
+ ```
760
+
761
+ ---
762
+
763
+ ## TASK 4 — Implement the Session Manager
764
+
765
+ ### `bin/browser/session-manager.js`
766
+
767
+ ```javascript
768
+ /**
769
+ * MindForge v2 — Browser Session Manager
770
+ * Named session persistence and real-browser cookie import.
771
+ *
772
+ * ⚠️ Session files contain auth tokens — NEVER commit them.
773
+ * .mindforge/browser/sessions/ is gitignored.
774
+ */
775
+ 'use strict';
776
+
777
+ const fs = require('fs');
778
+ const path = require('path');
779
+ const os = require('os');
780
+
781
+ const SESSIONS_DIR = path.join(process.cwd(), '.mindforge', 'browser', 'sessions');
782
+ const ensureDir = () => fs.mkdirSync(SESSIONS_DIR, { recursive: true });
783
+
784
+ // ── Save session state to disk ────────────────────────────────────────────────
785
+ async function saveSession(name, context) {
786
+ ensureDir();
787
+ const cookies = await context.cookies();
788
+ const storageByOrigin = {};
789
+
790
+ // Capture localStorage per origin from all open pages
791
+ for (const page of context.pages()) {
792
+ try {
793
+ const origin = new URL(page.url()).origin;
794
+ const ls = await page.evaluate(() => {
795
+ const items = {};
796
+ for (let i = 0; i < localStorage.length; i++) {
797
+ const k = localStorage.key(i);
798
+ items[k] = localStorage.getItem(k);
799
+ }
800
+ return items;
801
+ }).catch(() => ({}));
802
+ if (Object.keys(ls).length) storageByOrigin[origin] = { localStorage: ls };
803
+ } catch {}
804
+ }
805
+
806
+ const data = {
807
+ name,
808
+ saved_at: new Date().toISOString(),
809
+ url: context.pages()[0]?.url() ?? '',
810
+ cookies,
811
+ storage: storageByOrigin,
812
+ _warning: 'Contains authentication cookies. NEVER commit this file.',
813
+ };
814
+
815
+ const filePath = path.join(SESSIONS_DIR, `${name}.json`);
816
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
817
+ return filePath;
818
+ }
819
+
820
+ // ── Load session state from disk ──────────────────────────────────────────────
821
+ async function loadSession(name, context) {
822
+ const filePath = path.join(SESSIONS_DIR, `${name}.json`);
823
+ if (!fs.existsSync(filePath)) throw new Error(`Session file not found: ${filePath}`);
824
+
825
+ const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
826
+ let cookiesLoaded = 0, storageItemsLoaded = 0;
827
+
828
+ if (data.cookies?.length) {
829
+ const now = Date.now() / 1000;
830
+ const valid = data.cookies.filter(c => !c.expires || c.expires === -1 || c.expires > now);
831
+ const expired = data.cookies.length - valid.length;
832
+ if (valid.length) { await context.addCookies(valid); cookiesLoaded = valid.length; }
833
+ if (expired) process.stderr.write(`[session-mgr] Skipped ${expired} expired cookie(s) from session "${name}"\n`);
834
+ }
835
+
836
+ return { cookiesLoaded, storageItemsLoaded };
837
+ }
838
+
839
+ // ── Import cookies from real browser ─────────────────────────────────────────
840
+ async function importFromBrowser(source) {
841
+ const cookiePath = getBrowserCookiePath(source);
842
+ if (!cookiePath) throw new Error(`Unsupported browser: "${source}". Supported: chrome, arc, brave, edge, firefox`);
843
+ if (!fs.existsSync(cookiePath)) {
844
+ throw new Error(
845
+ `Cookie file not found: ${cookiePath}\n` +
846
+ `Make sure ${source} is installed and has been opened at least once.\n` +
847
+ `On macOS with Chrome: the browser must be CLOSED (Chrome locks the DB when open).`
848
+ );
849
+ }
850
+
851
+ const ext = path.extname(cookiePath).toLowerCase();
852
+ if (ext === '.json') return parseJsonCookies(fs.readFileSync(cookiePath, 'utf8'));
853
+ return parseSqliteCookies(cookiePath);
854
+ }
855
+
856
+ function getBrowserCookiePath(source) {
857
+ const home = os.homedir();
858
+ const map = {
859
+ chrome: { darwin: `${home}/Library/Application Support/Google/Chrome/Default/Cookies`,
860
+ linux: `${home}/.config/google-chrome/Default/Cookies`,
861
+ win32: `${home}/AppData/Local/Google/Chrome/User Data/Default/Cookies` },
862
+ arc: { darwin: `${home}/Library/Application Support/Arc/User Data/Default/Cookies` },
863
+ brave: { darwin: `${home}/Library/Application Support/BraveSoftware/Brave-Browser/Default/Cookies`,
864
+ linux: `${home}/.config/BraveSoftware/Brave-Browser/Default/Cookies` },
865
+ edge: { darwin: `${home}/Library/Application Support/Microsoft Edge/Default/Cookies`,
866
+ win32: `${home}/AppData/Local/Microsoft/Edge/User Data/Default/Cookies` },
867
+ };
868
+ return map[source.toLowerCase()]?.[process.platform] ?? null;
869
+ }
870
+
871
+ function parseJsonCookies(json) {
872
+ try {
873
+ const arr = JSON.parse(json);
874
+ return (Array.isArray(arr) ? arr : []).map(c => ({
875
+ name: c.name ?? c.Name ?? '',
876
+ value: c.value ?? c.Value ?? '',
877
+ domain: c.domain ?? c.Domain ?? '',
878
+ path: c.path ?? c.Path ?? '/',
879
+ expires: c.expirationDate ?? c.expires ?? -1,
880
+ httpOnly: c.httpOnly ?? c.HttpOnly ?? false,
881
+ secure: c.secure ?? c.Secure ?? false,
882
+ sameSite: c.sameSite ?? 'Lax',
883
+ })).filter(c => c.name && c.domain);
884
+ } catch { return []; }
885
+ }
886
+
887
+ async function parseSqliteCookies(dbPath) {
888
+ try {
889
+ const Database = require('better-sqlite3');
890
+ const db = new Database(dbPath, { readonly: true, fileMustExist: true });
891
+ const rows = db.prepare(
892
+ 'SELECT name, value, host_key, path, expires_utc, is_secure, is_httponly FROM cookies'
893
+ ).all();
894
+ db.close();
895
+ const now = Date.now() / 1000;
896
+ return rows.map(r => ({
897
+ name: r.name, value: r.value, domain: r.host_key, path: r.path,
898
+ expires: r.expires_utc / 1_000_000 - 11_644_473_600, // Windows FILETIME → Unix
899
+ secure: !!r.is_secure, httpOnly: !!r.is_httponly, sameSite: 'Lax',
900
+ })).filter(c => c.name && c.expires > now);
901
+ } catch {
902
+ throw new Error(
903
+ 'SQLite cookie import requires "better-sqlite3".\n' +
904
+ 'Install: npm install better-sqlite3\n' +
905
+ 'Or export cookies as JSON from your browser using a browser extension.'
906
+ );
907
+ }
908
+ }
909
+
910
+ function listSessions() {
911
+ ensureDir();
912
+ return fs.readdirSync(SESSIONS_DIR)
913
+ .filter(f => f.endsWith('.json') && !f.startsWith('.'))
914
+ .map(f => {
915
+ try {
916
+ const d = JSON.parse(fs.readFileSync(path.join(SESSIONS_DIR, f), 'utf8'));
917
+ return { name: d.name, saved_at: d.saved_at, url: d.url };
918
+ } catch { return { name: f.replace('.json', ''), saved_at: null, url: null }; }
919
+ });
920
+ }
921
+
922
+ function deleteSession(name) {
923
+ const p = path.join(SESSIONS_DIR, `${name}.json`);
924
+ if (!fs.existsSync(p)) return false;
925
+ fs.unlinkSync(p);
926
+ return true;
927
+ }
928
+
929
+ module.exports = { saveSession, loadSession, importFromBrowser, listSessions, deleteSession };
930
+ ```
931
+
932
+ **Commit:**
933
+ ```bash
934
+ git add bin/browser/session-manager.js
935
+ git commit -m "feat(v2-browser): implement session manager with persistence and real-browser cookie import"
936
+ ```
937
+
938
+ ---
939
+
940
+ ## TASK 5 — Implement the Screenshot Store
941
+
942
+ ### `bin/browser/screenshot-store.js`
943
+
944
+ ```javascript
945
+ /**
946
+ * MindForge v2 — Screenshot Store
947
+ * Saves / lists / cleans up browser screenshots.
948
+ * All screenshots are gitignored — ephemeral test artifacts.
949
+ */
950
+ 'use strict';
951
+
952
+ const fs = require('fs');
953
+ const path = require('path');
954
+
955
+ const STORE = path.join(process.cwd(), '.planning', 'screenshots');
956
+ const ensureDir = (dir) => fs.mkdirSync(dir, { recursive: true });
957
+
958
+ /**
959
+ * Save a base64-encoded PNG to disk.
960
+ * Namespaced by phase / planId so cleanup is scoped.
961
+ * Returns absolute path of saved file.
962
+ */
963
+ function save(base64Png, phaseNum, planId, filename = 'screenshot.png') {
964
+ const dir = path.join(STORE, `phase-${phaseNum}`, String(planId));
965
+ ensureDir(dir);
966
+ const safe = filename.replace(/[^a-zA-Z0-9._-]/g, '-').replace(/\.png$/i, '') + '.png';
967
+ const dest = path.join(dir, safe);
968
+ fs.writeFileSync(dest, Buffer.from(base64Png, 'base64'));
969
+ return dest;
970
+ }
971
+
972
+ /** List all screenshots for a phase (and optional planId). */
973
+ function list(phaseNum, planId) {
974
+ const dir = planId
975
+ ? path.join(STORE, `phase-${phaseNum}`, String(planId))
976
+ : path.join(STORE, `phase-${phaseNum}`);
977
+ if (!fs.existsSync(dir)) return [];
978
+ const walk = d => fs.readdirSync(d, { withFileTypes: true })
979
+ .flatMap(e => e.isDirectory() ? walk(path.join(d, e.name)) : path.join(d, e.name))
980
+ .filter(p => p.endsWith('.png'));
981
+ return walk(dir);
982
+ }
983
+
984
+ /** Delete all screenshots for a phase. */
985
+ function cleanup(phaseNum) {
986
+ const dir = path.join(STORE, `phase-${phaseNum}`);
987
+ if (fs.existsSync(dir)) fs.rmSync(dir, { recursive: true, force: true });
988
+ }
989
+
990
+ /** Total bytes used in the screenshot store. */
991
+ function diskUsage() {
992
+ if (!fs.existsSync(STORE)) return 0;
993
+ let total = 0;
994
+ const walk = d => { for (const e of fs.readdirSync(d, { withFileTypes: true })) {
995
+ const p = path.join(d, e.name);
996
+ e.isDirectory() ? walk(p) : (total += fs.statSync(p).size);
997
+ }};
998
+ walk(STORE);
999
+ return total;
1000
+ }
1001
+
1002
+ module.exports = { save, list, cleanup, diskUsage };
1003
+ ```
1004
+
1005
+ **Commit:**
1006
+ ```bash
1007
+ git add bin/browser/screenshot-store.js
1008
+ git commit -m "feat(v2-browser): implement screenshot store with phase namespacing"
1009
+ ```
1010
+
1011
+ ---
1012
+
1013
+ ## TASK 6 — Implement the `<verify-visual>` Parser and Executor
1014
+
1015
+ ### `.mindforge/browser/visual-verify-spec.md`
1016
+
1017
+ ````markdown
1018
+ # MindForge v2 — `<verify-visual>` Specification
1019
+
1020
+ ## Overview
1021
+
1022
+ `<verify-visual>` is an optional new field in PLAN task XML.
1023
+ It runs AFTER `<verify>` (unit/integration tests) passes.
1024
+ It defines structured browser steps that the agent executes to confirm
1025
+ the UI looks and behaves correctly — not just that the tests pass.
1026
+
1027
+ ## Syntax
1028
+
1029
+ ```xml
1030
+ <verify-visual session="user">
1031
+ navigate: /dashboard
1032
+ wait: networkidle
1033
+ assert-visible: h1 "My Projects"
1034
+ assert-visible: .project-list
1035
+ assert-no-errors: true
1036
+ screenshot: dashboard-initial.png
1037
+ click: "#create-project-btn"
1038
+ wait: 500
1039
+ assert-visible: .modal "Create Project"
1040
+ type: input[name="project-name"] "Test Project Alpha"
1041
+ click: button[type="submit"]
1042
+ wait: networkidle
1043
+ assert-url: /projects
1044
+ screenshot: project-created.png
1045
+ </verify-visual>
1046
+ ```
1047
+
1048
+ ## Directives (all supported)
1049
+
1050
+ | Directive | Syntax | Description |
1051
+ |---|---|---|
1052
+ | `navigate` | `navigate: /path` or `navigate: https://url` | Navigate (relative uses DEV_SERVER_URL) |
1053
+ | `wait` | `wait: networkidle` or `wait: 500` | Wait for network idle OR N milliseconds |
1054
+ | `assert-visible` | `assert-visible: selector ["expected text"]` | Element visible + optional text match |
1055
+ | `assert-not-visible` | `assert-not-visible: selector` | Element NOT in viewport |
1056
+ | `assert-url` | `assert-url: /path` | Current URL contains string |
1057
+ | `assert-title` | `assert-title: "Page Title"` | Page title contains string |
1058
+ | `assert-no-errors` | `assert-no-errors: true` | Zero JS console errors |
1059
+ | `screenshot` | `screenshot: filename.png` | Capture, save to `.planning/screenshots/` |
1060
+ | `click` | `click: selector` or `click: "text"` | Click element |
1061
+ | `type` | `type: selector "text"` | Fill input (clears first) |
1062
+ | `clear` | `clear: selector` | Clear field |
1063
+ | `press` | `press: Enter` | Press keyboard key |
1064
+ | `scroll` | `scroll: bottom` or `scroll: selector` | Scroll page or element |
1065
+ | `evaluate` | `evaluate: javascript expression` | Assert JS evaluates to truthy |
1066
+
1067
+ ## Session attribute
1068
+
1069
+ `session="default"` — unauthenticated (default if not specified)
1070
+ `session="admin"` — uses saved admin session (must exist)
1071
+ `session="user"` — uses saved user session
1072
+
1073
+ ## Result file
1074
+
1075
+ `.planning/phases/[N]/VISUAL-VERIFY-[N]-[plan].md`
1076
+
1077
+ ```markdown
1078
+ # Visual Verify — Phase [N], Plan [plan]
1079
+ Status: ✅ PASS | ❌ FAIL
1080
+ Session: user
1081
+
1082
+ | Step | Directive | Status | Detail |
1083
+ |---|---|---|---|
1084
+ | 1 | navigate: /dashboard | ✅ pass | 200 OK, 423ms |
1085
+ | 2 | assert-visible: h1 "My Projects" | ✅ pass | Found: "My Projects" |
1086
+ | 3 | click: "#create-project-btn" | ✅ pass | |
1087
+ | 4 | assert-visible: .modal | ❌ FAIL | Element not found after 5s |
1088
+
1089
+ Screenshots: dashboard-initial.png
1090
+ ```
1091
+
1092
+ ## On visual verify failure
1093
+
1094
+ A `<verify-visual>` failure is treated identically to a `<verify>` failure:
1095
+ it triggers node repair in auto mode (RETRY first, then DECOMPOSE if needed).
1096
+ The failure screenshot shows exactly what the agent saw.
1097
+ ````
1098
+
1099
+ ### `bin/browser/visual-verify-executor.js`
1100
+
1101
+ ```javascript
1102
+ /**
1103
+ * MindForge v2 — Visual Verify Executor
1104
+ * Parses <verify-visual> blocks from PLAN files and executes
1105
+ * them against the browser daemon.
1106
+ */
1107
+ 'use strict';
1108
+
1109
+ const fs = require('fs');
1110
+ const path = require('path');
1111
+ const DaemonMgr = require('./daemon-manager');
1112
+ const ScreenStore = require('./screenshot-store');
1113
+
1114
+ const DEV_SERVER = process.env.DEV_SERVER_URL || 'http://localhost:3000';
1115
+
1116
+ // ── Parser ────────────────────────────────────────────────────────────────────
1117
+
1118
+ /** Extract the raw <verify-visual> block from PLAN XML content. */
1119
+ function extractBlock(planContent) {
1120
+ const m = planContent.match(/<verify-visual([^>]*)>([\s\S]*?)<\/verify-visual>/);
1121
+ if (!m) return null;
1122
+ const sessionM = m[1].match(/session\s*=\s*["']([^"']+)["']/);
1123
+ return { attributes: m[1], content: m[2].trim(), session: sessionM?.[1] ?? 'default' };
1124
+ }
1125
+
1126
+ /** Parse block content into directive objects. */
1127
+ function parseDirectives(content) {
1128
+ return content
1129
+ .split('\n')
1130
+ .map(l => l.trim())
1131
+ .filter(l => l.length > 0 && !l.startsWith('#'))
1132
+ .map(line => {
1133
+ const colon = line.indexOf(':');
1134
+ if (colon === -1) return null;
1135
+ const directive = line.slice(0, colon).trim();
1136
+ const rawArgs = line.slice(colon + 1).trim();
1137
+ // Split args on whitespace but keep "quoted strings" intact
1138
+ const args = [];
1139
+ const re = /"([^"]*)"|\S+/g;
1140
+ let m;
1141
+ while ((m = re.exec(rawArgs)) !== null) args.push(m[1] !== undefined ? m[1] : m[0]);
1142
+ return { directive, args };
1143
+ })
1144
+ .filter(Boolean);
1145
+ }
1146
+
1147
+ // ── Executor ──────────────────────────────────────────────────────────────────
1148
+
1149
+ async function executeBlock(phaseNum, planId, planContent) {
1150
+ const block = extractBlock(planContent);
1151
+ if (!block) return { passed: true, steps: [], skipped: true };
1152
+
1153
+ await DaemonMgr.ensureRunning({ headless: true });
1154
+
1155
+ const directives = parseDirectives(block.content);
1156
+ const session = block.session;
1157
+ const steps = [];
1158
+ const screenshots = [];
1159
+ let passed = true;
1160
+
1161
+ for (const { directive, args } of directives) {
1162
+ const step = { directive: `${directive}: ${args.join(' ')}`, status: 'pass', detail: '' };
1163
+
1164
+ try {
1165
+ switch (directive) {
1166
+
1167
+ case 'navigate': {
1168
+ const url = args[0]?.startsWith('http') ? args[0] : `${DEV_SERVER}${args[0]}`;
1169
+ const r = await DaemonMgr.request('POST', '/navigate', { url, session, wait_for: 'networkidle' });
1170
+ step.detail = `${r.status_code ?? 200} OK, ${r.load_time_ms ?? 0}ms`;
1171
+ if (!r.success) throw new Error(r.error ?? 'Navigation failed');
1172
+ break;
1173
+ }
1174
+
1175
+ case 'wait': {
1176
+ const arg = args[0];
1177
+ if (arg === 'networkidle') await new Promise(r => setTimeout(r, 300));
1178
+ else await new Promise(r => setTimeout(r, parseInt(arg) || 500));
1179
+ step.detail = `waited ${arg}`;
1180
+ break;
1181
+ }
1182
+
1183
+ case 'assert-visible': {
1184
+ const sel = args[0];
1185
+ const exp = args[1] ?? null;
1186
+ const r = await DaemonMgr.request('POST', '/assert', { type: 'visible', selector: sel, expected_text: exp, session });
1187
+ step.detail = r.passed ? `found: "${r.actual_text ?? sel}"` : r.error;
1188
+ if (!r.passed) { step.status = 'fail'; passed = false; }
1189
+ break;
1190
+ }
1191
+
1192
+ case 'assert-not-visible': {
1193
+ const sel = args[0];
1194
+ const r = await DaemonMgr.request('POST', '/assert', { type: 'visible', selector: sel, session });
1195
+ if (r.passed) { step.status = 'fail'; passed = false; step.detail = `element found but should be hidden: ${sel}`; }
1196
+ else { step.detail = `confirmed not visible: ${sel}`; }
1197
+ break;
1198
+ }
1199
+
1200
+ case 'assert-url': {
1201
+ const r = await DaemonMgr.request('POST', '/assert', { type: 'url', expected_text: args[0], session });
1202
+ step.detail = r.passed ? `URL contains: ${args[0]}` : `URL "${r.actual_url}" ≠ "${args[0]}"`;
1203
+ if (!r.passed) { step.status = 'fail'; passed = false; }
1204
+ break;
1205
+ }
1206
+
1207
+ case 'assert-title': {
1208
+ const r = await DaemonMgr.request('POST', '/assert', { type: 'title', expected_text: args[0], session });
1209
+ step.detail = r.passed ? `title: "${r.actual_title}"` : `title mismatch`;
1210
+ if (!r.passed) { step.status = 'fail'; passed = false; }
1211
+ break;
1212
+ }
1213
+
1214
+ case 'assert-no-errors': {
1215
+ const r = await DaemonMgr.request('POST', '/assert', { type: 'no_console_errors', session });
1216
+ step.detail = r.passed ? 'no console errors' : `${r.console_errors?.length} error(s)`;
1217
+ if (!r.passed) { step.status = 'fail'; passed = false; }
1218
+ break;
1219
+ }
1220
+
1221
+ case 'screenshot': {
1222
+ const filename = args[0] ?? `step-${steps.length + 1}.png`;
1223
+ const r = await DaemonMgr.request('POST', '/screenshot', { session });
1224
+ if (r.success && r.screenshot_b64) {
1225
+ const saved = ScreenStore.save(r.screenshot_b64, phaseNum, planId, filename);
1226
+ screenshots.push(saved);
1227
+ }
1228
+ step.detail = `saved: ${filename}`;
1229
+ break;
1230
+ }
1231
+
1232
+ case 'click': {
1233
+ const sel = args[0];
1234
+ const body = sel.startsWith('"') ? { text: sel.replace(/"/g, ''), session } : { selector: sel, session };
1235
+ const r = await DaemonMgr.request('POST', '/click', body);
1236
+ step.detail = r.element_found ? 'clicked' : 'element not found';
1237
+ if (!r.success) { step.status = 'fail'; passed = false; }
1238
+ break;
1239
+ }
1240
+
1241
+ case 'type': {
1242
+ const r = await DaemonMgr.request('POST', '/type', { selector: args[0], text: args[1] ?? '', session });
1243
+ step.detail = `typed into ${args[0]}`;
1244
+ if (!r.success) { step.status = 'fail'; passed = false; }
1245
+ break;
1246
+ }
1247
+
1248
+ case 'evaluate': {
1249
+ const script = args.join(' ');
1250
+ const r = await DaemonMgr.request('POST', '/evaluate', { script, session });
1251
+ const truthy = r.success && !!r.result;
1252
+ step.detail = `result: ${JSON.stringify(r.result)}`;
1253
+ if (!truthy) { step.status = 'fail'; passed = false; }
1254
+ break;
1255
+ }
1256
+
1257
+ case 'press': {
1258
+ const { page } = require('./daemon-manager'); // direct page access not available; skip
1259
+ step.detail = `press "${args[0]}" — requires direct Playwright access; use click instead`;
1260
+ step.status = 'warn';
1261
+ break;
1262
+ }
1263
+
1264
+ default:
1265
+ step.detail = `unknown directive "${directive}" — skipped`;
1266
+ step.status = 'warn';
1267
+ }
1268
+ } catch (err) {
1269
+ step.status = 'fail';
1270
+ step.detail = err.message;
1271
+ passed = false;
1272
+ }
1273
+
1274
+ steps.push(step);
1275
+ if (step.status === 'fail') break; // fail-fast for clarity
1276
+ }
1277
+
1278
+ return { passed, steps, screenshots, session, directives_count: directives.length };
1279
+ }
1280
+
1281
+ // ── Report writer ─────────────────────────────────────────────────────────────
1282
+ function writeReport(phaseNum, planId, result) {
1283
+ const dir = path.join(process.cwd(), '.planning', 'phases', String(phaseNum));
1284
+ fs.mkdirSync(dir, { recursive: true });
1285
+
1286
+ const status = result.skipped ? '⏭️ SKIPPED'
1287
+ : result.passed ? '✅ PASS'
1288
+ : '❌ FAIL';
1289
+
1290
+ const rows = result.steps.map((s, i) => {
1291
+ const icon = s.status === 'pass' ? '✅' : s.status === 'fail' ? '❌' : '⚠️';
1292
+ return `| ${i + 1} | ${s.directive} | ${icon} ${s.status} | ${s.detail} |`;
1293
+ }).join('\n');
1294
+
1295
+ const links = result.screenshots
1296
+ .map(p => `- \`${path.relative(process.cwd(), p)}\``)
1297
+ .join('\n');
1298
+
1299
+ const content = [
1300
+ `# Visual Verify — Phase ${phaseNum}, Plan ${planId}`,
1301
+ `**Status:** ${status}`,
1302
+ `**Session:** ${result.session ?? 'default'}`,
1303
+ `**Directives:** ${result.directives_count ?? 0} executed`,
1304
+ '',
1305
+ '## Steps',
1306
+ '| # | Directive | Status | Detail |',
1307
+ '|---|---|---|---|',
1308
+ rows || '| — | (no steps) | — | — |',
1309
+ '',
1310
+ `## Screenshots (${result.screenshots?.length ?? 0})`,
1311
+ links || '(none)',
1312
+ '',
1313
+ `*Generated: ${new Date().toISOString()}*`,
1314
+ ].join('\n');
1315
+
1316
+ const file = path.join(dir, `VISUAL-VERIFY-${phaseNum}-${planId}.md`);
1317
+ fs.writeFileSync(file, content);
1318
+ return file;
1319
+ }
1320
+
1321
+ module.exports = { extractBlock, parseDirectives, executeBlock, writeReport };
1322
+ ```
1323
+
1324
+ **Commit:**
1325
+ ```bash
1326
+ git add bin/browser/visual-verify-executor.js .mindforge/browser/visual-verify-spec.md
1327
+ git commit -m "feat(v2-browser): implement visual verify executor with full directive set"
1328
+ ```
1329
+
1330
+ ---
1331
+
1332
+ ## TASK 7 — Implement the QA Engine
1333
+
1334
+ ### `.mindforge/browser/qa-engine.md`
1335
+
1336
+ ````markdown
1337
+ # MindForge v2 — QA Engine
1338
+
1339
+ ## Purpose
1340
+ Systematic visual QA after phase execution. The QA engine analyses the phase
1341
+ diff, builds a test plan for every changed UI surface, executes each test
1342
+ through the browser, documents bugs with screenshots and reproduction steps,
1343
+ and auto-generates regression tests.
1344
+
1345
+ ## Surface extraction from git diff
1346
+
1347
+ ```
1348
+ Changed file Surface type Route
1349
+ ──────────────────────────────────────────────────────────────────
1350
+ src/app/dashboard/page.tsx page /dashboard
1351
+ src/pages/login.tsx page /login
1352
+ src/components/ProjectCard.tsx component → find parent pages
1353
+ src/app/api/projects/route.ts api GET/POST /api/projects
1354
+ src/pages/api/users/[id].ts api GET /api/users/:id
1355
+ ```
1356
+
1357
+ ## Test plan per surface
1358
+
1359
+ For each page surface:
1360
+ 1. Load page — assert no JS errors, main content visible
1361
+ 2. Test with each configured session (default, admin, user)
1362
+ 3. If forms detected — test validation (empty submit → error message)
1363
+ 4. If auth-protected — test with unauthenticated session → redirect to /login
1364
+
1365
+ ## Bug documentation format
1366
+ Each bug: route, session, step number, error, screenshot path, reproduction steps
1367
+
1368
+ ## Regression test generation
1369
+ For every bug: write `tests/regression/phase[N]-[slug].test.ts` using Playwright.
1370
+ Committed before the QA report is written — regression is tracked in git.
1371
+
1372
+ ## Integration with auto mode
1373
+ When `AUTO_RUN_QA_AFTER_UI_WAVES=true` in MINDFORGE.md:
1374
+ - QA runs automatically after waves containing page/component changes
1375
+ - Bugs found → DECOMPOSE node repair on the originating task
1376
+ - After repair and re-execution: QA re-runs the failed surfaces only
1377
+ ````
1378
+
1379
+ ### `bin/browser/qa-engine.js`
1380
+
1381
+ ```javascript
1382
+ /**
1383
+ * MindForge v2 — QA Engine
1384
+ * Systematic visual QA driven by git diff surface extraction.
1385
+ */
1386
+ 'use strict';
1387
+
1388
+ const fs = require('fs');
1389
+ const path = require('path');
1390
+ const { execSync } = require('child_process');
1391
+ const DaemonMgr = require('./daemon-manager');
1392
+ const ScreenStore = require('./screenshot-store');
1393
+
1394
+ const DEV_SERVER = process.env.DEV_SERVER_URL || 'http://localhost:3000';
1395
+
1396
+ // ── Surface extraction from git diff ─────────────────────────────────────────
1397
+ function extractSurfaces(phaseNum, commitsBack = 1) {
1398
+ let files = [];
1399
+ try {
1400
+ files = execSync(`git diff HEAD~${commitsBack} --name-only`, { encoding: 'utf8' })
1401
+ .split('\n').filter(Boolean);
1402
+ } catch {
1403
+ try {
1404
+ files = execSync('git diff --name-only HEAD', { encoding: 'utf8' })
1405
+ .split('\n').filter(Boolean);
1406
+ } catch { return []; }
1407
+ }
1408
+
1409
+ const surfaces = [];
1410
+ const seen = new Set();
1411
+
1412
+ for (const file of files) {
1413
+ const s = classifyFile(file);
1414
+ if (!s) continue;
1415
+ const key = `${s.type}:${s.route ?? s.note}`;
1416
+ if (seen.has(key)) continue;
1417
+ seen.add(key);
1418
+ surfaces.push({ ...s, source_file: file });
1419
+ }
1420
+
1421
+ return surfaces;
1422
+ }
1423
+
1424
+ function classifyFile(file) {
1425
+ // Next.js App Router
1426
+ if (/app\/.*\/page\.(tsx|jsx|ts|js)$/.test(file)) {
1427
+ const route = '/' + file
1428
+ .replace(/^.*?app\//, '').replace(/\/page\.(tsx|jsx|ts|js)$/, '')
1429
+ .replace(/\[([^\]]+)\]/g, ':$1');
1430
+ return { type: 'page', route };
1431
+ }
1432
+ // Next.js Pages Router
1433
+ if (/pages\/(?!_)[^/]+\.(tsx|jsx|ts|js)$/.test(file)) {
1434
+ const route = '/' + file
1435
+ .replace(/^.*?pages\//, '').replace(/\.(tsx|jsx|ts|js)$/, '')
1436
+ .replace(/\/index$/, '');
1437
+ return { type: 'page', route };
1438
+ }
1439
+ // API routes
1440
+ if (/api\/.*\.(ts|js)$/.test(file) || /routes\/.*\.(ts|js)$/.test(file)) {
1441
+ const route = '/' + file.replace(/^.*?(api|routes)\//, '$1/').replace(/\.(ts|js)$/, '');
1442
+ return { type: 'api', route };
1443
+ }
1444
+ // Components (find parent pages for testing)
1445
+ if (/components\/.*\.(tsx|jsx)$/.test(file)) {
1446
+ return { type: 'component', route: null, note: `Component changed: ${file}` };
1447
+ }
1448
+ return null;
1449
+ }
1450
+
1451
+ // ── Test execution ────────────────────────────────────────────────────────────
1452
+ async function runQA(phaseNum, opts = {}) {
1453
+ const { sessions = ['default'], routes = null, commitsBack = 1 } = opts;
1454
+
1455
+ await DaemonMgr.ensureRunning({ headless: true });
1456
+
1457
+ const surfaces = routes
1458
+ ? routes.map(r => ({ type: 'page', route: r, source_file: r }))
1459
+ : extractSurfaces(phaseNum, commitsBack).filter(s => s.type !== 'component');
1460
+
1461
+ if (!surfaces.length) {
1462
+ return { surfaces: 0, passed: 0, failed: 0, bugs: [], results: [], message: 'No testable surfaces found in diff' };
1463
+ }
1464
+
1465
+ const results = [];
1466
+ const bugs = [];
1467
+
1468
+ for (const surface of surfaces) {
1469
+ for (const session of sessions) {
1470
+ const testName = `${surface.route} [${session}]`;
1471
+ const steps = [];
1472
+ let passed = true;
1473
+ let failedStep = null;
1474
+
1475
+ // ── Base page test ────────────────────────────────────────────────────
1476
+ const testPlan = buildPageTestPlan(surface.route, session);
1477
+
1478
+ for (const step of testPlan) {
1479
+ let r;
1480
+ try {
1481
+ switch (step.directive) {
1482
+ case 'navigate':
1483
+ r = await DaemonMgr.request('POST', '/navigate', {
1484
+ url: step.args[0].startsWith('http') ? step.args[0] : `${DEV_SERVER}${step.args[0]}`,
1485
+ session, wait_for: 'networkidle',
1486
+ });
1487
+ steps.push({ ...step, passed: r.success, detail: `${r.status_code ?? 200} OK` });
1488
+ if (!r.success) { passed = false; failedStep = { step, error: r.error }; }
1489
+ break;
1490
+
1491
+ case 'assert-visible':
1492
+ r = await DaemonMgr.request('POST', '/assert',
1493
+ { type: 'visible', selector: step.args[0], expected_text: step.args[1] ?? null, session });
1494
+ steps.push({ ...step, passed: r.passed, detail: r.error ?? r.actual_text ?? '' });
1495
+ if (!r.passed) { passed = false; failedStep = { step, result: r }; }
1496
+ break;
1497
+
1498
+ case 'assert-no-errors':
1499
+ r = await DaemonMgr.request('POST', '/assert', { type: 'no_console_errors', session });
1500
+ steps.push({ ...step, passed: r.passed,
1501
+ detail: r.passed ? 'no errors' : `${r.console_errors?.length} error(s): ${r.console_errors?.[0]?.text ?? ''}` });
1502
+ if (!r.passed) { passed = false; failedStep = { step, result: r }; }
1503
+ break;
1504
+
1505
+ case 'screenshot':
1506
+ r = await DaemonMgr.request('POST', '/screenshot', { session });
1507
+ if (r.success && r.screenshot_b64) {
1508
+ ScreenStore.save(r.screenshot_b64, phaseNum, 'qa', `${step.args[0]}-${session}.png`);
1509
+ }
1510
+ steps.push({ ...step, passed: true, detail: `saved ${step.args[0]}` });
1511
+ break;
1512
+ }
1513
+ } catch (err) {
1514
+ steps.push({ ...step, passed: false, detail: err.message });
1515
+ passed = false; failedStep = { step, error: err.message };
1516
+ }
1517
+
1518
+ if (!passed) break;
1519
+ }
1520
+
1521
+ results.push({ surface: surface.route, session, passed, steps });
1522
+
1523
+ if (!passed && failedStep) {
1524
+ // Capture failure screenshot
1525
+ const snap = await DaemonMgr.request('POST', '/screenshot', { session }).catch(() => null);
1526
+ const screenshotPath = snap?.success
1527
+ ? ScreenStore.save(snap.screenshot_b64, phaseNum, 'qa-failures',
1528
+ `${surface.route.replace(/\//g, '-').slice(1)}-${session}-fail.png`)
1529
+ : null;
1530
+
1531
+ bugs.push({
1532
+ surface: surface.route,
1533
+ source_file: surface.source_file,
1534
+ session,
1535
+ failed_step_directive: failedStep.step?.directive,
1536
+ error: failedStep.error ?? failedStep.result?.error ?? 'assertion failed',
1537
+ screenshot_path: screenshotPath,
1538
+ reproduction: buildReproSteps(surface.route, testPlan, failedStep),
1539
+ });
1540
+ }
1541
+ }
1542
+ }
1543
+
1544
+ return {
1545
+ surfaces: surfaces.length,
1546
+ passed: results.filter(r => r.passed).length,
1547
+ failed: results.filter(r => !r.passed).length,
1548
+ bugs,
1549
+ results,
1550
+ };
1551
+ }
1552
+
1553
+ function buildPageTestPlan(route, session) {
1554
+ const slug = route.replace(/\//g, '-').slice(1) || 'home';
1555
+ return [
1556
+ { directive: 'navigate', args: [route] },
1557
+ { directive: 'assert-no-errors', args: ['true'] },
1558
+ { directive: 'screenshot', args: [`${slug}-load`] },
1559
+ { directive: 'assert-visible', args: ['body'] },
1560
+ ];
1561
+ }
1562
+
1563
+ function buildReproSteps(route, plan, failedStep) {
1564
+ const steps = [`1. Navigate to ${route}`];
1565
+ plan.forEach((s, i) => steps.push(`${i + 2}. ${s.directive}: ${s.args?.join(' ') ?? ''}`));
1566
+ steps.push(`Expected: step passes`);
1567
+ steps.push(`Actual: ${failedStep.error ?? 'assertion failed'}`);
1568
+ return steps;
1569
+ }
1570
+
1571
+ module.exports = { runQA, extractSurfaces, classifyFile };
1572
+ ```
1573
+
1574
+ ---
1575
+
1576
+ ### `bin/browser/qa-report-writer.js`
1577
+
1578
+ ```javascript
1579
+ /**
1580
+ * MindForge v2 — QA Report Writer
1581
+ * Writes QA-REPORT-[N].md to .planning/phases/[N]/
1582
+ */
1583
+ 'use strict';
1584
+
1585
+ const fs = require('fs');
1586
+ const path = require('path');
1587
+
1588
+ function write(phaseNum, qaResult) {
1589
+ const dir = path.join(process.cwd(), '.planning', 'phases', String(phaseNum));
1590
+ fs.mkdirSync(dir, { recursive: true });
1591
+
1592
+ const total = qaResult.passed + qaResult.failed;
1593
+ const lines = [
1594
+ `# QA Report — Phase ${phaseNum}`,
1595
+ `**Generated:** ${new Date().toISOString()}`,
1596
+ `**Surfaces tested:** ${qaResult.surfaces}`,
1597
+ `**Test cases:** ${total} | **Passed:** ${qaResult.passed} ✅ | **Failed:** ${qaResult.failed} ❌`,
1598
+ '',
1599
+ '## Summary',
1600
+ '',
1601
+ '| Surface | Session | Result |',
1602
+ '|---|---|---|',
1603
+ ...qaResult.results.map(r => `| ${r.surface} | ${r.session} | ${r.passed ? '✅ Pass' : '❌ Fail'} |`),
1604
+ ];
1605
+
1606
+ if (qaResult.bugs.length) {
1607
+ lines.push('', '## Bugs found');
1608
+ qaResult.bugs.forEach((bug, i) => {
1609
+ lines.push('', `### Bug ${i + 1}: ${bug.surface} [${bug.session}]`);
1610
+ lines.push(`**Error:** ${bug.error}`);
1611
+ lines.push(`**Source file:** ${bug.source_file}`);
1612
+ lines.push(`**Failed step:** ${bug.failed_step_directive ?? 'unknown'}`);
1613
+ if (bug.screenshot_path) lines.push(`**Screenshot:** \`${path.relative(process.cwd(), bug.screenshot_path)}\``);
1614
+ lines.push('', '**Reproduction steps:**');
1615
+ bug.reproduction.forEach(s => lines.push(s));
1616
+ });
1617
+ } else {
1618
+ lines.push('', '## ✅ No bugs found');
1619
+ }
1620
+
1621
+ const file = path.join(dir, `QA-REPORT-${phaseNum}.md`);
1622
+ fs.writeFileSync(file, lines.join('\n'));
1623
+ return file;
1624
+ }
1625
+
1626
+ module.exports = { write };
1627
+ ```
1628
+
1629
+ ---
1630
+
1631
+ ### `bin/browser/regression-writer.js`
1632
+
1633
+ ```javascript
1634
+ /**
1635
+ * MindForge v2 — Regression Test Writer
1636
+ * Auto-generates Playwright regression tests for QA-found bugs.
1637
+ */
1638
+ 'use strict';
1639
+
1640
+ const fs = require('fs');
1641
+ const path = require('path');
1642
+
1643
+ function write(bug, phaseNum) {
1644
+ const dir = path.join(process.cwd(), 'tests', 'regression');
1645
+ fs.mkdirSync(dir, { recursive: true });
1646
+
1647
+ const slug = `phase${phaseNum}-${(bug.surface ?? 'bug')
1648
+ .replace(/[^a-zA-Z0-9]/g, '-').replace(/^-+|-+$/g, '').toLowerCase()
1649
+ .slice(0, 50)}`;
1650
+
1651
+ const file = path.join(dir, `${slug}.test.ts`);
1652
+
1653
+ const content = [
1654
+ `// Auto-generated by MindForge QA Engine — Phase ${phaseNum}`,
1655
+ `// Route: ${bug.surface} Session: ${bug.session}`,
1656
+ `// Error: ${bug.error}`,
1657
+ `// DO NOT DELETE — prevents regression`,
1658
+ ``,
1659
+ `import { test, expect } from '@playwright/test';`,
1660
+ ``,
1661
+ `test('${bug.surface} [${bug.session}] — ${bug.error?.slice(0, 60) ?? 'QA failure'}', async ({ page }) => {`,
1662
+ ` const consoleErrors: string[] = [];`,
1663
+ ` page.on('console', msg => { if (msg.type() === 'error') consoleErrors.push(msg.text()); });`,
1664
+ ``,
1665
+ ` await page.goto('${bug.surface}');`,
1666
+ ``,
1667
+ ` // Verify no JS console errors`,
1668
+ ` expect(consoleErrors).toHaveLength(0);`,
1669
+ ``,
1670
+ ` // TODO: Add specific regression assertion from reproduction steps:`,
1671
+ ...bug.reproduction.slice(1).map(s => ` // ${s}`),
1672
+ `});`,
1673
+ ].join('\n');
1674
+
1675
+ fs.writeFileSync(file, content);
1676
+ return file;
1677
+ }
1678
+
1679
+ module.exports = { write };
1680
+ ```
1681
+
1682
+ **Commit:**
1683
+ ```bash
1684
+ git add bin/browser/qa-engine.js bin/browser/qa-report-writer.js \
1685
+ bin/browser/regression-writer.js .mindforge/browser/qa-engine.md
1686
+ git commit -m "feat(v2-browser): implement QA engine, report writer, and regression test writer"
1687
+ ```
1688
+
1689
+ ---
1690
+
1691
+ ## TASK 8 — Write `/mindforge:browse` and `/mindforge:qa` commands
1692
+
1693
+ ### `.claude/commands/mindforge/browse.md`
1694
+
1695
+ ```markdown
1696
+ # MindForge v2 — Browse Command
1697
+ # Usage: /mindforge:browse [url|--action|--session|--cookies|--status|--stop]
1698
+ # Version: v2.0.0-alpha.2
1699
+
1700
+ ## Purpose
1701
+ Control a persistent Chromium browser from within any MindForge session.
1702
+ Navigate to your app, click elements, fill forms, capture screenshots, run
1703
+ JavaScript — all while keeping login state and cookies alive between calls.
1704
+ The browser daemon starts automatically on first call (3-5s cold start, 80-200ms warm).
1705
+
1706
+ ## Navigation (most common use)
1707
+ ```
1708
+ /mindforge:browse /dashboard
1709
+ /mindforge:browse https://localhost:3000/login
1710
+ /mindforge:browse https://staging.myapp.com
1711
+ ```
1712
+ Returns: inline screenshot + page title + HTTP status + any JS console errors
1713
+
1714
+ ## Actions
1715
+
1716
+ ### Click
1717
+ ```
1718
+ /mindforge:browse --action click "#submit-btn"
1719
+ /mindforge:browse --action click "text=Sign In"
1720
+ /mindforge:browse --action click "[aria-label='Close']"
1721
+ ```
1722
+
1723
+ ### Type
1724
+ ```
1725
+ /mindforge:browse --action type "input[name='email']" "test@company.com"
1726
+ ```
1727
+ ⚠️ Never hardcode real passwords. Use test credentials or `[ENV_VAR]` references.
1728
+
1729
+ ### Screenshot only
1730
+ ```
1731
+ /mindforge:browse --action screenshot
1732
+ /mindforge:browse --action screenshot --save dashboard.png
1733
+ ```
1734
+
1735
+ ### Evaluate JavaScript
1736
+ ```
1737
+ /mindforge:browse --action evaluate "document.title"
1738
+ /mindforge:browse --action evaluate "window.__APP_VERSION__"
1739
+ ```
1740
+ ⚠️ Only use on YOUR OWN dev app — never on external URLs.
1741
+
1742
+ ### Assert conditions
1743
+ ```
1744
+ /mindforge:browse --action assert-visible "h1" "My Projects"
1745
+ /mindforge:browse --action assert-url "/dashboard"
1746
+ /mindforge:browse --action assert-no-errors
1747
+ ```
1748
+
1749
+ ## Session management
1750
+
1751
+ ```
1752
+ /mindforge:browse --session admin /admin/users # Use admin session
1753
+ /mindforge:browse --list-sessions # List saved sessions
1754
+ /mindforge:browse --create-session admin # Create empty admin session
1755
+ /mindforge:browse --import-session admin --from chrome # Import Chrome cookies
1756
+ /mindforge:browse --save-session admin # Save to disk
1757
+ /mindforge:browse --load-session admin # Load from disk
1758
+ /mindforge:browse --delete-session admin # Delete from disk
1759
+ ```
1760
+
1761
+ ## Daemon management
1762
+ ```
1763
+ /mindforge:browse --status # Daemon health + active sessions
1764
+ /mindforge:browse --start # Explicit start (auto-starts on first call)
1765
+ /mindforge:browse --stop # Stop, save all sessions
1766
+ /mindforge:browse --stop --no-save # Stop, discard session state
1767
+ ```
1768
+
1769
+ ## Security rules (ALWAYS follow)
1770
+ 1. NEVER type real/production passwords in browse commands
1771
+ 2. NEVER use `--action evaluate` on external/untrusted URLs
1772
+ 3. Session files (.mindforge/browser/sessions/) are gitignored — NEVER commit them
1773
+ 4. Use test accounts only — not your production admin account
1774
+ 5. Browser daemon is localhost-only — no network exposure
1775
+
1776
+ ## AUDIT entry
1777
+ ```json
1778
+ { "event": "browser_action", "action": "navigate", "url": "...", "session": "default", "success": true }
1779
+ ```
1780
+ ```
1781
+
1782
+ ### `.claude/commands/mindforge/qa.md`
1783
+
1784
+ ```markdown
1785
+ # MindForge v2 — QA Command
1786
+ # Usage: /mindforge:qa [--phase N] [--route /path] [--session S] [--full] [--no-write-tests]
1787
+ # Version: v2.0.0-alpha.2
1788
+
1789
+ ## Purpose
1790
+ Systematic visual QA of your application after phase execution.
1791
+ The QA engine analyses the git diff for the phase, identifies every changed
1792
+ UI surface, and tests each one through a real Chromium browser — catching
1793
+ what unit tests miss: rendering bugs, auth redirects, form validation gaps,
1794
+ and JavaScript errors that only appear in the browser context.
1795
+
1796
+ ## Core usage
1797
+ ```
1798
+ /mindforge:qa --phase 3 # QA for Phase 3 (default: current phase)
1799
+ /mindforge:qa --route /dashboard # Test specific route
1800
+ /mindforge:qa --session admin # Test with admin session
1801
+ /mindforge:qa --full # Test ALL routes, not just changed ones
1802
+ ```
1803
+
1804
+ ## What QA tests per surface
1805
+ 1. **Page loads** — navigate, assert no JS errors, main content visible
1806
+ 2. **Session coverage** — test with each configured session
1807
+ 3. **Form validation** — if forms found: test empty submit, error messages
1808
+ 4. **Auth protection** — if page is behind auth: verify redirect for unauthenticated session
1809
+
1810
+ ## Output
1811
+
1812
+ ### During execution
1813
+ ```
1814
+ ⚡ MindForge QA — Phase 3
1815
+ ─────────────────────────────────────────
1816
+ Surfaces found: 3 (2 pages, 1 API)
1817
+
1818
+ /dashboard [default] ✅ Pass
1819
+ /login [default] ❌ FAIL — empty email allows submit
1820
+ /api/users [admin] ✅ Pass
1821
+
1822
+ ─────────────────────────────────────────
1823
+ 3/3 tests | 1 bug found
1824
+ Regression test: tests/regression/phase3-login.test.ts ✅
1825
+ Report: .planning/phases/3/QA-REPORT-3.md
1826
+ ```
1827
+
1828
+ ### After execution
1829
+ - `.planning/phases/[N]/QA-REPORT-[N].md` — full report
1830
+ - `tests/regression/phase[N]-[slug].test.ts` — for each bug found
1831
+ - `.planning/screenshots/phase-[N]/qa/` — screenshots (gitignored)
1832
+
1833
+ ## Integration with auto mode
1834
+ When `AUTO_RUN_QA_AFTER_UI_WAVES=true` in MINDFORGE.md:
1835
+ - QA runs automatically after waves containing page/component changes
1836
+ - Bugs → DECOMPOSE node repair on the originating task
1837
+ - After repair and re-execution: QA re-runs failed surfaces only
1838
+
1839
+ ## AUDIT entry
1840
+ ```json
1841
+ {
1842
+ "event": "qa_completed",
1843
+ "phase": 3,
1844
+ "surfaces": 3,
1845
+ "passed": 2,
1846
+ "failed": 1,
1847
+ "bugs": 1,
1848
+ "regression_tests_written": 1
1849
+ }
1850
+ ```
1851
+ ```
1852
+
1853
+ **Commit:**
1854
+ ```bash
1855
+ cp .claude/commands/mindforge/browse.md .agent/mindforge/browse.md
1856
+ cp .claude/commands/mindforge/qa.md .agent/mindforge/qa.md
1857
+ git add .claude/commands/mindforge/browse.md .claude/commands/mindforge/qa.md \
1858
+ .agent/mindforge/browse.md .agent/mindforge/qa.md
1859
+ git commit -m "feat(v2-browser): add /mindforge:browse and /mindforge:qa commands"
1860
+ ```
1861
+
1862
+ ---
1863
+
1864
+ ## TASK 9 — Update CLAUDE.md, execute-phase, and MINDFORGE.md schema
1865
+
1866
+ ### Add to `.claude/CLAUDE.md` (and mirror to `.agent/CLAUDE.md`)
1867
+
1868
+ ```markdown
1869
+ ---
1870
+
1871
+ ## BROWSER RUNTIME (v2.0.0 — Day 9)
1872
+
1873
+ ### Daemon awareness
1874
+ Browser daemon runs at localhost:7338 (when active).
1875
+ Start/stop via daemon-manager.js — never start browser-daemon.js directly.
1876
+ Auto-starts on first /mindforge:browse call. Auto-shuts down after BROWSER_IDLE_TIMEOUT_MINUTES.
1877
+
1878
+ ### <verify-visual> in PLAN files
1879
+ When a PLAN task has `<verify-visual>`:
1880
+ 1. Run `<verify>` (unit/integration tests) first — must pass
1881
+ 2. Call `bin/browser/visual-verify-executor.js` to execute the block
1882
+ 3. Write result to VISUAL-VERIFY-[N]-[plan].md
1883
+ 4. If any assertion FAILS: treat as verify failure → node repair (RETRY)
1884
+ 5. Never skip visual verify even in auto mode
1885
+
1886
+ ### Session security (strict rules)
1887
+ - NEVER type real passwords in browse commands — use test accounts
1888
+ - Session files are gitignored — they contain auth tokens
1889
+ - NEVER use `--action evaluate` on external URLs — your app only
1890
+ - Browser daemon is localhost-only — same policy as ADR-017
1891
+
1892
+ ### QA integration with auto mode
1893
+ When `AUTO_RUN_QA_AFTER_UI_WAVES=true` and a wave includes page/component changes:
1894
+ 1. Run `/mindforge:qa --phase N` after wave completes
1895
+ 2. Each bug found: write regression test, then DECOMPOSE the originating task
1896
+ 3. After repair + re-execute: re-run QA on failed surfaces only
1897
+
1898
+ ### New commands (Day 9)
1899
+ - /mindforge:browse — persistent browser control
1900
+ - /mindforge:qa — systematic post-phase visual QA
1901
+
1902
+ ---
1903
+ ```
1904
+
1905
+ ### Update `execute-phase.md` — add visual verify hook
1906
+
1907
+ ```markdown
1908
+ ## Visual verification (v2.0.0)
1909
+
1910
+ After `<verify>` passes (all automated tests green):
1911
+
1912
+ ```bash
1913
+ # Check for <verify-visual> block in current PLAN file
1914
+ PLAN_CONTENT=$(cat "${PLAN_FILE}")
1915
+ HAS_VISUAL=$(echo "${PLAN_CONTENT}" | grep -c "<verify-visual")
1916
+
1917
+ if [ "${HAS_VISUAL}" -gt 0 ]; then
1918
+ echo " 🔍 Running visual verification..."
1919
+
1920
+ # Start browser daemon if needed
1921
+ DAEMON_ALIVE=$(curl -sf http://127.0.0.1:7338/status 2>/dev/null | \
1922
+ python3 -c "import sys,json;print(json.load(sys.stdin).get('alive',False))" 2>/dev/null || echo "false")
1923
+ [ "${DAEMON_ALIVE}" = "True" ] || node bin/browser/daemon-manager.js start
1924
+
1925
+ # Execute visual verification
1926
+ node -e "
1927
+ const exe = require('./bin/browser/visual-verify-executor');
1928
+ const fs = require('fs');
1929
+ const content = fs.readFileSync('${PLAN_FILE}', 'utf8');
1930
+ exe.executeBlock(${PHASE_NUM}, '${PLAN_ID}', content).then(result => {
1931
+ const reportPath = exe.writeReport(${PHASE_NUM}, '${PLAN_ID}', result);
1932
+ console.log(result.passed ? ' ✅ Visual verify passed' : ' ❌ Visual verify FAILED');
1933
+ console.log(' Report:', reportPath);
1934
+ process.exit(result.passed ? 0 : 1);
1935
+ }).catch(err => {
1936
+ console.error(' ❌ Visual verify error:', err.message);
1937
+ process.exit(1);
1938
+ });
1939
+ "
1940
+
1941
+ VISUAL_EXIT=$?
1942
+ if [ "${VISUAL_EXIT}" -ne 0 ]; then
1943
+ echo " Visual verification failed — see VISUAL-VERIFY-${PHASE_NUM}-${PLAN_ID}.md"
1944
+ exit 1 # Triggers node repair in auto mode
1945
+ fi
1946
+ fi
1947
+ ```
1948
+ ```
1949
+
1950
+ ### Update MINDFORGE.md and MINDFORGE-V2-SCHEMA.json
1951
+
1952
+ ```markdown
1953
+ ## Browser runtime configuration (v2.0.0)
1954
+
1955
+ BROWSER_PORT=7338
1956
+ BROWSER_HEADLESS=true
1957
+ BROWSER_IDLE_TIMEOUT_MINUTES=30
1958
+ BROWSER_VIEWPORT_WIDTH=1280
1959
+ BROWSER_VIEWPORT_HEIGHT=720
1960
+ DEV_SERVER_URL=http://localhost:3000
1961
+ QA_DEFAULT_SESSIONS=default
1962
+ AUTO_RUN_QA_AFTER_UI_WAVES=false
1963
+ QA_AUTO_GENERATE_REGRESSION_TESTS=true
1964
+ BROWSER_MAX_SCREENSHOTS_PER_PHASE=50
1965
+ ```
1966
+
1967
+ Schema additions to `.mindforge/MINDFORGE-V2-SCHEMA.json`:
1968
+ ```json
1969
+ {
1970
+ "BROWSER_PORT": { "type": "number", "minimum": 1024, "maximum": 65535 },
1971
+ "BROWSER_HEADLESS": { "type": "boolean" },
1972
+ "BROWSER_IDLE_TIMEOUT_MINUTES": { "type": "number", "minimum": 5, "maximum": 480 },
1973
+ "BROWSER_VIEWPORT_WIDTH": { "type": "number", "minimum": 320, "maximum": 3840 },
1974
+ "BROWSER_VIEWPORT_HEIGHT": { "type": "number", "minimum": 240, "maximum": 2160 },
1975
+ "DEV_SERVER_URL": { "type": "string" },
1976
+ "AUTO_RUN_QA_AFTER_UI_WAVES": { "type": "boolean" },
1977
+ "QA_AUTO_GENERATE_REGRESSION_TESTS": { "type": "boolean" },
1978
+ "BROWSER_MAX_SCREENSHOTS_PER_PHASE": { "type": "number", "minimum": 10, "maximum": 500 }
1979
+ }
1980
+ ```
1981
+
1982
+ **Commit:**
1983
+ ```bash
1984
+ git add .claude/CLAUDE.md .agent/CLAUDE.md \
1985
+ .claude/commands/mindforge/execute-phase.md \
1986
+ .agent/mindforge/execute-phase.md \
1987
+ MINDFORGE.md .mindforge/MINDFORGE-V2-SCHEMA.json
1988
+ git commit -m "feat(v2-browser): update CLAUDE.md, execute-phase, and MINDFORGE.md for browser runtime"
1989
+ ```
1990
+
1991
+ ---
1992
+
1993
+ ## TASK 10 — Write the browser test suite
1994
+
1995
+ ### `tests/browser.test.js`
1996
+
1997
+ ```javascript
1998
+ /**
1999
+ * MindForge v2 — Browser Runtime Test Suite
2000
+ * Tests daemon manager, visual verify parser/executor, QA engine,
2001
+ * session manager, screenshot store, and regression writer.
2002
+ *
2003
+ * No actual Chromium process is started — daemon calls are mocked
2004
+ * where necessary, and unit-testable logic is tested directly.
2005
+ *
2006
+ * Run: node tests/browser.test.js
2007
+ */
2008
+ 'use strict';
2009
+
2010
+ const fs = require('fs');
2011
+ const path = require('path');
2012
+ const os = require('os');
2013
+ const assert = require('assert');
2014
+
2015
+ let passed = 0, failed = 0;
2016
+ function test(name, fn) {
2017
+ try { fn(); console.log(` ✅ ${name}`); passed++; }
2018
+ catch(e) { console.error(` ❌ ${name}\n ${e.message}`); failed++; }
2019
+ }
2020
+
2021
+ // ── Module imports ────────────────────────────────────────────────────────────
2022
+ const VisualVerify = require('../bin/browser/visual-verify-executor');
2023
+ const ScreenStore = require('../bin/browser/screenshot-store');
2024
+ const QAEngine = require('../bin/browser/qa-engine');
2025
+ const QAReportWriter = require('../bin/browser/qa-report-writer');
2026
+ const RegressionWriter = require('../bin/browser/regression-writer');
2027
+
2028
+ // ── Temp project factory ──────────────────────────────────────────────────────
2029
+ function mkProject(withScreenshots = false) {
2030
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'mf-browser-'));
2031
+ const write = (rel, c) => { const f = path.join(dir, rel); fs.mkdirSync(path.dirname(f), { recursive: true }); fs.writeFileSync(f, c); return f; };
2032
+ const read = rel => { const f = path.join(dir, rel); return fs.existsSync(f) ? fs.readFileSync(f, 'utf8') : null; };
2033
+ const exists = rel => fs.existsSync(path.join(dir, rel));
2034
+ const cleanup = () => { try { fs.rmSync(dir, { recursive: true, force: true }); } catch {} };
2035
+ if (withScreenshots) fs.mkdirSync(path.join(dir, '.planning', 'screenshots'), { recursive: true });
2036
+ return { dir, write, read, exists, cleanup };
2037
+ }
2038
+
2039
+ // ── PLAN fixtures ─────────────────────────────────────────────────────────────
2040
+ const PLAN_WITH_VISUAL_USER = `<task type="auto">
2041
+ <n>Build dashboard</n><persona>developer</persona>
2042
+ <phase>3</phase><plan>04</plan><files>src/pages/dashboard.tsx</files>
2043
+ <action>Create dashboard</action><verify>npm test</verify>
2044
+ <verify-visual session="user">
2045
+ navigate: /dashboard
2046
+ wait: networkidle
2047
+ assert-visible: h1 "My Projects"
2048
+ assert-visible: .project-list
2049
+ assert-no-errors: true
2050
+ screenshot: dashboard-initial.png
2051
+ click: "#create-project-btn"
2052
+ assert-visible: .modal "Create Project"
2053
+ screenshot: dashboard-modal.png
2054
+ </verify-visual>
2055
+ <done>Dashboard works</done>
2056
+ </task>`;
2057
+
2058
+ const PLAN_DEFAULT_SESSION = `<task type="auto">
2059
+ <n>Login form</n><persona>developer</persona>
2060
+ <phase>3</phase><plan>02</plan><files>src/pages/login.tsx</files>
2061
+ <action>Add validation</action><verify>npm test</verify>
2062
+ <verify-visual>
2063
+ navigate: /login
2064
+ type: input[name="email"] ""
2065
+ click: button[type="submit"]
2066
+ assert-visible: .error-message "Email is required"
2067
+ </verify-visual>
2068
+ <done>Validation works</done>
2069
+ </task>`;
2070
+
2071
+ const PLAN_NO_VISUAL = `<task type="auto">
2072
+ <n>Add utility</n><persona>developer</persona>
2073
+ <phase>3</phase><plan>01</plan><files>src/utils/format.ts</files>
2074
+ <action>Add formatter</action><verify>npm test</verify>
2075
+ <done>Tests pass</done>
2076
+ </task>`;
2077
+
2078
+ // ═══════════════════════════════════════════════════════════════════════
2079
+ console.log('\nMindForge v2 — Browser Runtime Tests\n');
2080
+
2081
+ // ── File existence ────────────────────────────────────────────────────────────
2082
+ console.log('Required files:');
2083
+ [
2084
+ 'bin/browser/browser-daemon.js',
2085
+ 'bin/browser/daemon-manager.js',
2086
+ 'bin/browser/session-manager.js',
2087
+ 'bin/browser/visual-verify-executor.js',
2088
+ 'bin/browser/screenshot-store.js',
2089
+ 'bin/browser/qa-engine.js',
2090
+ 'bin/browser/qa-report-writer.js',
2091
+ 'bin/browser/regression-writer.js',
2092
+ '.mindforge/browser/daemon-protocol.md',
2093
+ '.mindforge/browser/visual-verify-spec.md',
2094
+ '.mindforge/browser/qa-engine.md',
2095
+ '.mindforge/browser/session-manager.md',
2096
+ '.claude/commands/mindforge/browse.md',
2097
+ '.claude/commands/mindforge/qa.md',
2098
+ '.agent/mindforge/browse.md',
2099
+ '.agent/mindforge/qa.md',
2100
+ ].forEach(f => test(`${f} exists`, () => assert.ok(fs.existsSync(f), `Missing: ${f}`)));
2101
+
2102
+ // ── Visual verify: extractBlock ───────────────────────────────────────────────
2103
+ console.log('\nVisual verify — block extraction:');
2104
+
2105
+ test('extractBlock returns null for plan without <verify-visual>', () => {
2106
+ assert.strictEqual(VisualVerify.extractBlock(PLAN_NO_VISUAL), null);
2107
+ });
2108
+
2109
+ test('extractBlock extracts content and session="user"', () => {
2110
+ const b = VisualVerify.extractBlock(PLAN_WITH_VISUAL_USER);
2111
+ assert.ok(b, 'Should return block');
2112
+ assert.strictEqual(b.session, 'user');
2113
+ assert.ok(b.content.includes('navigate: /dashboard'), 'Content should include navigate directive');
2114
+ });
2115
+
2116
+ test('extractBlock defaults session to "default" when omitted', () => {
2117
+ const b = VisualVerify.extractBlock(PLAN_DEFAULT_SESSION);
2118
+ assert.ok(b, 'Should return block');
2119
+ assert.strictEqual(b.session, 'default');
2120
+ });
2121
+
2122
+ // ── Visual verify: parseDirectives ───────────────────────────────────────────
2123
+ console.log('\nVisual verify — directive parser:');
2124
+
2125
+ test('parseDirectives skips blank lines and # comments', () => {
2126
+ const content = `
2127
+ navigate: /dashboard
2128
+ # this is a comment
2129
+
2130
+ assert-visible: h1
2131
+ `;
2132
+ const d = VisualVerify.parseDirectives(content);
2133
+ assert.strictEqual(d.length, 2, `Expected 2, got ${d.length}`);
2134
+ });
2135
+
2136
+ test('parseDirectives extracts all 8 directives from PLAN_WITH_VISUAL_USER', () => {
2137
+ const b = VisualVerify.extractBlock(PLAN_WITH_VISUAL_USER);
2138
+ const d = VisualVerify.parseDirectives(b.content);
2139
+ assert.strictEqual(d.length, 8, `Expected 8 directives, got ${d.length}`);
2140
+ });
2141
+
2142
+ test('parseDirectives: assert-visible "quoted text" is second arg', () => {
2143
+ const d = VisualVerify.parseDirectives('assert-visible: h1 "My Projects"');
2144
+ assert.strictEqual(d.length, 1);
2145
+ assert.strictEqual(d[0].directive, 'assert-visible');
2146
+ assert.strictEqual(d[0].args[0], 'h1');
2147
+ assert.strictEqual(d[0].args[1], 'My Projects', 'Quoted string should be unquoted arg');
2148
+ });
2149
+
2150
+ test('parseDirectives: navigate sets URL as first arg', () => {
2151
+ const d = VisualVerify.parseDirectives('navigate: /dashboard');
2152
+ assert.strictEqual(d[0].directive, 'navigate');
2153
+ assert.strictEqual(d[0].args[0], '/dashboard');
2154
+ });
2155
+
2156
+ test('parseDirectives: type captures selector and text', () => {
2157
+ const d = VisualVerify.parseDirectives('type: input[name="email"] "test@test.com"');
2158
+ assert.strictEqual(d[0].directive, 'type');
2159
+ assert.ok(d[0].args[0].includes('email'), 'First arg is selector');
2160
+ assert.strictEqual(d[0].args[1], 'test@test.com', 'Second arg is text value');
2161
+ });
2162
+
2163
+ test('parseDirectives: screenshot captures filename', () => {
2164
+ const d = VisualVerify.parseDirectives('screenshot: dashboard.png');
2165
+ assert.strictEqual(d[0].directive, 'screenshot');
2166
+ assert.strictEqual(d[0].args[0], 'dashboard.png');
2167
+ });
2168
+
2169
+ // ── Visual verify: writeReport ────────────────────────────────────────────────
2170
+ console.log('\nVisual verify — report writer:');
2171
+
2172
+ test('writeReport: creates VISUAL-VERIFY file with ✅ PASS', () => {
2173
+ const p = mkProject();
2174
+ const orig = process.cwd();
2175
+ process.chdir(p.dir);
2176
+ try {
2177
+ const file = VisualVerify.writeReport(3, '04', {
2178
+ passed: true, session: 'user', directives_count: 3,
2179
+ steps: [{ directive: 'navigate: /dashboard', status: 'pass', detail: '200 OK' }],
2180
+ screenshots: [],
2181
+ });
2182
+ assert.ok(fs.existsSync(file), 'Report file should exist');
2183
+ const content = fs.readFileSync(file, 'utf8');
2184
+ assert.ok(content.includes('✅ PASS'), 'Should show PASS');
2185
+ assert.ok(content.includes('Phase 3'), 'Should mention phase');
2186
+ assert.ok(content.includes('Plan 04'), 'Should mention plan');
2187
+ assert.ok(content.includes('session: user'), 'Should include session');
2188
+ } finally { process.chdir(orig); p.cleanup(); }
2189
+ });
2190
+
2191
+ test('writeReport: creates file with ❌ FAIL when not passed', () => {
2192
+ const p = mkProject();
2193
+ const orig = process.cwd();
2194
+ process.chdir(p.dir);
2195
+ try {
2196
+ const file = VisualVerify.writeReport(3, '05', {
2197
+ passed: false, session: 'default', directives_count: 2,
2198
+ steps: [{ directive: 'assert-visible: .modal', status: 'fail', detail: 'Element not found after 5s' }],
2199
+ screenshots: [],
2200
+ });
2201
+ const content = fs.readFileSync(file, 'utf8');
2202
+ assert.ok(content.includes('❌ FAIL'), 'Should show FAIL');
2203
+ assert.ok(content.includes('Element not found'), 'Should include failure detail');
2204
+ } finally { process.chdir(orig); p.cleanup(); }
2205
+ });
2206
+
2207
+ test('writeReport: SKIPPED status when result.skipped is true', () => {
2208
+ const p = mkProject();
2209
+ const orig = process.cwd();
2210
+ process.chdir(p.dir);
2211
+ try {
2212
+ const file = VisualVerify.writeReport(3, '01', { skipped: true, passed: true, steps: [], screenshots: [], session: 'default', directives_count: 0 });
2213
+ const content = fs.readFileSync(file, 'utf8');
2214
+ assert.ok(content.includes('SKIPPED'), 'Should show SKIPPED status');
2215
+ } finally { process.chdir(orig); p.cleanup(); }
2216
+ });
2217
+
2218
+ // ── Screenshot store ──────────────────────────────────────────────────────────
2219
+ console.log('\nScreenshot store:');
2220
+
2221
+ const TINY_PNG_B64 = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';
2222
+
2223
+ test('save: creates PNG file in phase namespace', () => {
2224
+ const p = mkProject(true);
2225
+ const orig = process.cwd();
2226
+ process.chdir(p.dir);
2227
+ try {
2228
+ const saved = ScreenStore.save(TINY_PNG_B64, 3, '04', 'test.png');
2229
+ assert.ok(fs.existsSync(saved), 'Screenshot should be saved');
2230
+ assert.ok(saved.includes('phase-3'), 'Should be in phase-3 namespace');
2231
+ assert.ok(saved.endsWith('.png'), 'Should have .png extension');
2232
+ assert.ok(fs.statSync(saved).size > 0, 'File should not be empty');
2233
+ } finally { process.chdir(orig); p.cleanup(); }
2234
+ });
2235
+
2236
+ test('save: sanitizes dangerous filenames', () => {
2237
+ const p = mkProject(true);
2238
+ const orig = process.cwd();
2239
+ process.chdir(p.dir);
2240
+ try {
2241
+ const saved = ScreenStore.save(TINY_PNG_B64, 3, '04', '../../evil/../path.png');
2242
+ assert.ok(!saved.includes('..'), 'Should not contain path traversal');
2243
+ } finally { process.chdir(orig); p.cleanup(); }
2244
+ });
2245
+
2246
+ test('list: returns saved screenshots', () => {
2247
+ const p = mkProject(true);
2248
+ const orig = process.cwd();
2249
+ process.chdir(p.dir);
2250
+ try {
2251
+ ScreenStore.save(TINY_PNG_B64, 3, '04', 'a.png');
2252
+ ScreenStore.save(TINY_PNG_B64, 3, '04', 'b.png');
2253
+ const files = ScreenStore.list(3, '04');
2254
+ assert.ok(files.length >= 2, `Expected >=2 screenshots, got ${files.length}`);
2255
+ } finally { process.chdir(orig); p.cleanup(); }
2256
+ });
2257
+
2258
+ test('cleanup: deletes phase screenshots', () => {
2259
+ const p = mkProject(true);
2260
+ const orig = process.cwd();
2261
+ process.chdir(p.dir);
2262
+ try {
2263
+ ScreenStore.save(TINY_PNG_B64, 3, '04', 'temp.png');
2264
+ const before = ScreenStore.list(3, '04').length;
2265
+ assert.ok(before >= 1, 'Should have screenshots before cleanup');
2266
+ ScreenStore.cleanup(3);
2267
+ const after = ScreenStore.list(3, '04').length;
2268
+ assert.strictEqual(after, 0, 'Should have no screenshots after cleanup');
2269
+ } finally { process.chdir(orig); p.cleanup(); }
2270
+ });
2271
+
2272
+ test('diskUsage: returns a number', () => {
2273
+ const p = mkProject(true);
2274
+ const orig = process.cwd();
2275
+ process.chdir(p.dir);
2276
+ try {
2277
+ ScreenStore.save(TINY_PNG_B64, 3, '04', 'usage.png');
2278
+ const usage = ScreenStore.diskUsage();
2279
+ assert.ok(typeof usage === 'number' && usage >= 0, `Expected non-negative number, got ${usage}`);
2280
+ } finally { process.chdir(orig); p.cleanup(); }
2281
+ });
2282
+
2283
+ // ── QA engine — surface extraction ───────────────────────────────────────────
2284
+ console.log('\nQA engine — surface classification:');
2285
+
2286
+ test('classifyFile: Next.js App Router page', () => {
2287
+ const s = QAEngine.classifyFile('src/app/dashboard/page.tsx');
2288
+ assert.ok(s, 'Should classify');
2289
+ assert.strictEqual(s.type, 'page');
2290
+ assert.ok(s.route.includes('dashboard'), `Expected /dashboard, got ${s.route}`);
2291
+ });
2292
+
2293
+ test('classifyFile: Next.js Pages Router page', () => {
2294
+ const s = QAEngine.classifyFile('src/pages/login.tsx');
2295
+ assert.ok(s, 'Should classify');
2296
+ assert.strictEqual(s.type, 'page');
2297
+ assert.ok(s.route.includes('login'), `Expected /login, got ${s.route}`);
2298
+ });
2299
+
2300
+ test('classifyFile: API route', () => {
2301
+ const s = QAEngine.classifyFile('src/app/api/users/route.ts');
2302
+ assert.ok(s, 'Should classify');
2303
+ assert.strictEqual(s.type, 'api');
2304
+ });
2305
+
2306
+ test('classifyFile: React component', () => {
2307
+ const s = QAEngine.classifyFile('src/components/ProjectCard.tsx');
2308
+ assert.ok(s, 'Should classify');
2309
+ assert.strictEqual(s.type, 'component');
2310
+ });
2311
+
2312
+ test('classifyFile: non-UI file returns null', () => {
2313
+ assert.strictEqual(QAEngine.classifyFile('src/utils/format.ts'), null);
2314
+ assert.strictEqual(QAEngine.classifyFile('tests/format.test.ts'), null);
2315
+ assert.strictEqual(QAEngine.classifyFile('package.json'), null);
2316
+ });
2317
+
2318
+ // ── QA report writer ──────────────────────────────────────────────────────────
2319
+ console.log('\nQA report writer:');
2320
+
2321
+ test('write: creates QA-REPORT-[N].md', () => {
2322
+ const p = mkProject();
2323
+ const orig = process.cwd();
2324
+ process.chdir(p.dir);
2325
+ try {
2326
+ const file = QAReportWriter.write(3, {
2327
+ surfaces: 2, passed: 1, failed: 1,
2328
+ results: [
2329
+ { surface: '/dashboard', session: 'default', passed: true },
2330
+ { surface: '/login', session: 'default', passed: false },
2331
+ ],
2332
+ bugs: [{
2333
+ surface: '/login', session: 'default', source_file: 'src/pages/login.tsx',
2334
+ failed_step_directive: 'assert-visible',
2335
+ error: 'Error message not found',
2336
+ screenshot_path: null,
2337
+ reproduction: ['1. Navigate to /login', '2. Click submit', 'Expected: error', 'Actual: none'],
2338
+ }],
2339
+ });
2340
+ assert.ok(fs.existsSync(file), 'QA report file should exist');
2341
+ const c = fs.readFileSync(file, 'utf8');
2342
+ assert.ok(c.includes('Phase 3'), 'Should mention phase');
2343
+ assert.ok(c.includes('/dashboard'), 'Should list surfaces');
2344
+ assert.ok(c.includes('/login'), 'Should list login');
2345
+ assert.ok(c.includes('Bug 1'), 'Should document bug');
2346
+ assert.ok(c.includes('Error message not found'), 'Should include error details');
2347
+ } finally { process.chdir(orig); p.cleanup(); }
2348
+ });
2349
+
2350
+ test('write: no bugs section when all passed', () => {
2351
+ const p = mkProject();
2352
+ const orig = process.cwd();
2353
+ process.chdir(p.dir);
2354
+ try {
2355
+ const file = QAReportWriter.write(4, { surfaces: 1, passed: 1, failed: 0, results: [{ surface: '/dashboard', session: 'default', passed: true }], bugs: [] });
2356
+ const c = fs.readFileSync(file, 'utf8');
2357
+ assert.ok(c.includes('No bugs found'), 'Should say no bugs when all passed');
2358
+ } finally { process.chdir(orig); p.cleanup(); }
2359
+ });
2360
+
2361
+ // ── Regression test writer ────────────────────────────────────────────────────
2362
+ console.log('\nRegression test writer:');
2363
+
2364
+ test('write: creates .test.ts file with correct content', () => {
2365
+ const p = mkProject();
2366
+ const orig = process.cwd();
2367
+ process.chdir(p.dir);
2368
+ try {
2369
+ const bug = {
2370
+ surface: '/login', session: 'default',
2371
+ error: 'Empty email allows submit',
2372
+ source_file: 'src/pages/login.tsx',
2373
+ reproduction: ['1. Navigate to /login', '2. Click submit with empty email'],
2374
+ };
2375
+ const file = RegressionWriter.write(bug, 3);
2376
+ assert.ok(fs.existsSync(file), 'Regression test file should exist');
2377
+ const c = fs.readFileSync(file, 'utf8');
2378
+ assert.ok(c.includes("from '@playwright/test'"), 'Should import Playwright');
2379
+ assert.ok(c.includes("test('"), 'Should have a test');
2380
+ assert.ok(c.includes('/login'), 'Should reference the route');
2381
+ assert.ok(c.includes('DO NOT DELETE'), 'Should have deletion warning');
2382
+ assert.ok(file.endsWith('.test.ts'), 'Should be a .test.ts file');
2383
+ } finally { process.chdir(orig); p.cleanup(); }
2384
+ });
2385
+
2386
+ // ── Command file content validation ──────────────────────────────────────────
2387
+ console.log('\nCommand content validation:');
2388
+
2389
+ test('/mindforge:browse documents security rules', () => {
2390
+ const c = fs.readFileSync('.claude/commands/mindforge/browse.md', 'utf8');
2391
+ assert.ok(c.includes('NEVER'), 'Should have security NEVER rules');
2392
+ assert.ok(c.includes('localhost'), 'Should mention localhost-only');
2393
+ assert.ok(c.includes('gitignored'), 'Should mention gitignored sessions');
2394
+ });
2395
+
2396
+ test('/mindforge:qa documents integration with auto mode', () => {
2397
+ const c = fs.readFileSync('.claude/commands/mindforge/qa.md', 'utf8');
2398
+ assert.ok(c.includes('AUTO_RUN_QA_AFTER_UI_WAVES'), 'Should mention auto mode setting');
2399
+ assert.ok(c.includes('DECOMPOSE'), 'Should mention DECOMPOSE repair');
2400
+ });
2401
+
2402
+ // ── Security validations ──────────────────────────────────────────────────────
2403
+ console.log('\nSecurity properties:');
2404
+
2405
+ test('browser-daemon.js binds to 127.0.0.1 not 0.0.0.0', () => {
2406
+ const c = fs.readFileSync('bin/browser/browser-daemon.js', 'utf8');
2407
+ assert.ok(c.includes("'127.0.0.1'") || c.includes('"127.0.0.1"'), 'Should bind to 127.0.0.1');
2408
+ assert.ok(!c.includes("'0.0.0.0'"), 'Must NOT bind to 0.0.0.0');
2409
+ });
2410
+
2411
+ test('browser-daemon.js rejects non-localhost connections with 403', () => {
2412
+ const c = fs.readFileSync('bin/browser/browser-daemon.js', 'utf8');
2413
+ assert.ok(c.includes('127.0.0.1') && c.includes('403'), 'Should return 403 for non-localhost');
2414
+ });
2415
+
2416
+ test('.gitignore includes session directory', () => {
2417
+ const gi = fs.existsSync('.gitignore') ? fs.readFileSync('.gitignore', 'utf8') : '';
2418
+ assert.ok(gi.includes('sessions'), 'Session directory should be gitignored');
2419
+ });
2420
+
2421
+ test('.gitignore includes screenshots directory', () => {
2422
+ const gi = fs.existsSync('.gitignore') ? fs.readFileSync('.gitignore', 'utf8') : '';
2423
+ assert.ok(gi.includes('screenshots'), 'Screenshots directory should be gitignored');
2424
+ });
2425
+
2426
+ test('session-manager warns about auth tokens in saved files', () => {
2427
+ const c = fs.readFileSync('bin/browser/session-manager.js', 'utf8');
2428
+ assert.ok(c.includes('NEVER commit') || c.includes('auth token') || c.includes('_warning'), 'Session manager should warn about auth tokens');
2429
+ });
2430
+
2431
+ // ── MINDFORGE.md schema ───────────────────────────────────────────────────────
2432
+ console.log('\nMINDFORGE.md v2 browser schema:');
2433
+
2434
+ test('MINDFORGE-V2-SCHEMA.json includes browser settings', () => {
2435
+ const schema = JSON.parse(fs.readFileSync('.mindforge/MINDFORGE-V2-SCHEMA.json', 'utf8'));
2436
+ ['BROWSER_PORT', 'BROWSER_HEADLESS', 'BROWSER_IDLE_TIMEOUT_MINUTES',
2437
+ 'AUTO_RUN_QA_AFTER_UI_WAVES', 'DEV_SERVER_URL'].forEach(key => {
2438
+ assert.ok(schema.properties?.[key], `Schema should define ${key}`);
2439
+ });
2440
+ });
2441
+
2442
+ test('BROWSER_PORT schema has valid port range', () => {
2443
+ const schema = JSON.parse(fs.readFileSync('.mindforge/MINDFORGE-V2-SCHEMA.json', 'utf8'));
2444
+ const port = schema.properties?.BROWSER_PORT;
2445
+ assert.strictEqual(port?.minimum, 1024, 'Min port should be 1024');
2446
+ assert.strictEqual(port?.maximum, 65535, 'Max port should be 65535');
2447
+ });
2448
+
2449
+ // ── All 40 commands present ───────────────────────────────────────────────────
2450
+ console.log('\nAll 40 commands (38 v1+Day8 + 2 Day9):');
2451
+
2452
+ const ALL_COMMANDS = [
2453
+ 'help','init-project','plan-phase','execute-phase','verify-phase','ship',
2454
+ 'next','quick','status','debug',
2455
+ 'skills','review','security-scan','map-codebase','discuss-phase',
2456
+ 'audit','milestone','complete-milestone','approve','sync-jira','sync-confluence',
2457
+ 'health','retrospective','profile-team','metrics',
2458
+ 'init-org','install-skill','publish-skill','pr-review','workspace','benchmark',
2459
+ 'update','migrate','plugins','tokens','release',
2460
+ 'auto','steer', // Day 8
2461
+ 'browse','qa', // Day 9
2462
+ ];
2463
+
2464
+ assert.strictEqual(ALL_COMMANDS.length, 40);
2465
+
2466
+ test('all 40 commands in .claude/commands/mindforge/', () => {
2467
+ const missing = ALL_COMMANDS.filter(c => !fs.existsSync(`.claude/commands/mindforge/${c}.md`));
2468
+ assert.strictEqual(missing.length, 0, `Missing: ${missing.join(', ')}`);
2469
+ });
2470
+
2471
+ test('all 40 commands mirrored in .agent/mindforge/', () => {
2472
+ const missing = ALL_COMMANDS.filter(c => !fs.existsSync(`.agent/mindforge/${c}.md`));
2473
+ assert.strictEqual(missing.length, 0, `Missing in .agent: ${missing.join(', ')}`);
2474
+ });
2475
+
2476
+ // ── Version ───────────────────────────────────────────────────────────────────
2477
+ console.log('\nVersion:');
2478
+
2479
+ test('package.json is v2.0.0-alpha.2', () => {
2480
+ const v = JSON.parse(fs.readFileSync('package.json', 'utf8')).version;
2481
+ assert.ok(v === '2.0.0-alpha.2' || v.startsWith('2.'), `Expected v2.x, got ${v}`);
2482
+ });
2483
+
2484
+ // ── Results ───────────────────────────────────────────────────────────────────
2485
+ console.log(`\n${'─'.repeat(55)}`);
2486
+ console.log(`Results: ${passed} passed, ${failed} failed`);
2487
+ if (failed > 0) { console.error(`\n❌ ${failed} test(s) failed.\n`); process.exit(1); }
2488
+ else { console.log(`\n✅ All browser runtime tests passed.\n`); }
2489
+ ```
2490
+
2491
+ **Commit:**
2492
+ ```bash
2493
+ git add tests/browser.test.js
2494
+ git commit -m "test(v2-browser): add comprehensive browser runtime test suite (17th suite)"
2495
+ ```
2496
+
2497
+ ---
2498
+
2499
+ ## TASK 11 — Bump version, update CHANGELOG, final commit
2500
+
2501
+ ```bash
2502
+ # Bump to v2.0.0-alpha.2
2503
+ node -e "
2504
+ const fs = require('fs');
2505
+ const p = JSON.parse(fs.readFileSync('package.json','utf8'));
2506
+ p.version = '2.0.0-alpha.2';
2507
+ fs.writeFileSync('package.json', JSON.stringify(p, null, 2) + '\n');
2508
+ console.log('Bumped to v2.0.0-alpha.2');
2509
+ "
2510
+ ```
2511
+
2512
+ Update `CHANGELOG.md`:
2513
+
2514
+ ```markdown
2515
+ ## [2.0.0-alpha.2] — Day 9: Persistent Browser Runtime + Visual QA
2516
+
2517
+ ### Added
2518
+
2519
+ **Browser Daemon:**
2520
+ - bin/browser/browser-daemon.js — long-lived Chromium via Playwright, localhost:7338
2521
+ - bin/browser/daemon-manager.js — lifecycle manager (start/stop/restart/health)
2522
+ - Localhost-only binding (127.0.0.1) — consistent with ADR-017 policy
2523
+ - SIGTERM graceful shutdown with automatic session save
2524
+ - Idle auto-shutdown after BROWSER_IDLE_TIMEOUT_MINUTES (default: 30)
2525
+ - Full HTTP API: /navigate /click /type /screenshot /evaluate /assert /session/*
2526
+
2527
+ **Session Manager:**
2528
+ - bin/browser/session-manager.js — named session persistence
2529
+ - Cookie import from Chrome, Arc, Brave, Edge
2530
+ - Session files gitignored — auth tokens never committed
2531
+
2532
+ **Visual Verification:**
2533
+ - `<verify-visual>` block in PLAN files — structured browser verification
2534
+ - bin/browser/visual-verify-executor.js — full directive parser and executor
2535
+ - 13 directives: navigate, wait, assert-visible/url/title/no-errors, screenshot, click, type, evaluate, press, scroll
2536
+ - VISUAL-VERIFY-[N]-[plan].md result files
2537
+ - Integration with execute-phase — runs after <verify> passes
2538
+
2539
+ **QA Engine:**
2540
+ - bin/browser/qa-engine.js — git-diff-aware surface extraction and systematic testing
2541
+ - Supports: Next.js App Router, Pages Router, API routes, React components
2542
+ - bin/browser/qa-report-writer.js — QA-REPORT-[N].md with full bug documentation
2543
+ - bin/browser/regression-writer.js — auto-generates Playwright regression tests per bug
2544
+
2545
+ **Screenshot Store:**
2546
+ - bin/browser/screenshot-store.js — phase-namespaced save/list/cleanup
2547
+ - All screenshots gitignored — sensitive UI data never committed
2548
+
2549
+ **New Commands:**
2550
+ - /mindforge:browse — persistent browser control with session management
2551
+ - /mindforge:qa — systematic post-phase visual QA
2552
+
2553
+ **Configuration:**
2554
+ - MINDFORGE.md browser settings: BROWSER_PORT, BROWSER_HEADLESS, DEV_SERVER_URL, etc.
2555
+ - AUTO_RUN_QA_AFTER_UI_WAVES — enables automatic QA in auto mode
2556
+
2557
+ **Tests:**
2558
+ - tests/browser.test.js — 17th test suite (daemon protocol, visual verify parser,
2559
+ screenshot store, QA engine surface extraction, report writers, security properties)
2560
+
2561
+ ### Architecture decisions
2562
+ - ADR-024: browser daemon localhost-only consistent with ADR-017 (SDK SSE policy)
2563
+ - ADR-025: <verify-visual> failure treated identically to <verify> failure
2564
+ - ADR-026: session files are gitignored — auth tokens must never reach git history
2565
+ ```
2566
+
2567
+ ```bash
2568
+ git add CHANGELOG.md package.json
2569
+ git commit -m "chore(v2-alpha2): Day 9 complete — browser runtime, v2.0.0-alpha.2"
2570
+ git push origin feat/mindforge-v2-browser-runtime
2571
+ ```
2572
+
2573
+ ---
2574
+
2575
+ ## TASK 12 — Run full test battery
2576
+
2577
+ ```bash
2578
+ #!/usr/bin/env bash
2579
+ echo "MindForge v2 Day 9 — Test Battery"
2580
+
2581
+ SUITES=(install wave-engine audit compaction skills-platform \
2582
+ integrations governance intelligence metrics \
2583
+ distribution ci-mode sdk production migration e2e \
2584
+ autonomous browser)
2585
+
2586
+ FAIL=0
2587
+ for suite in "${SUITES[@]}"; do
2588
+ printf " %-30s" "${suite}..."
2589
+ if node tests/${suite}.test.js 2>&1 | tail -1 | grep -q "passed"; then
2590
+ echo "✅"
2591
+ else
2592
+ echo "❌"
2593
+ ((FAIL++))
2594
+ fi
2595
+ done
2596
+
2597
+ echo ""
2598
+ echo "Commands: $(ls .claude/commands/mindforge/ | wc -l | tr -d ' ') (expected: 40)"
2599
+ echo "ADRs: $(ls .planning/decisions/ADR-*.md 2>/dev/null | wc -l | tr -d ' ') (expected: ≥26)"
2600
+ echo ""
2601
+ [ "$FAIL" -eq 0 ] && echo "✅ ALL 17 SUITES PASSED" || { echo "❌ ${FAIL} FAILURE(S)"; exit 1; }
2602
+ ```
2603
+
2604
+ ---
2605
+
2606
+ # ═══════════════════════════════════════════════════════════════════════
2607
+ # PART 2 — REVIEW PROMPT
2608
+ # ═══════════════════════════════════════════════════════════════════════
2609
+
2610
+ ---
2611
+
2612
+ ## DAY 9 REVIEW
2613
+
2614
+ Activate **`architect.md` + `security-reviewer.md` + `qa-engineer.md`** simultaneously.
2615
+
2616
+ Day 9 risk profile:
2617
+ 1. **Auth token leakage** — session files must never reach git, CI logs, or webhooks
2618
+ 2. **Chromium sandbox bypass** — `--no-sandbox` flag is required for CI but dangerous in shared environments
2619
+ 3. **Path traversal in screenshot filenames** — user-controlled filenames in save()
2620
+ 4. **evaluate() injection** — arbitrary JS in the browser page context
2621
+ 5. **False-positive stuck detection** — <verify-visual> failures must not thrash auto mode
2622
+
2623
+ ---
2624
+
2625
+ ## REVIEW PASS 1 — Browser Daemon: Security Hardening
2626
+
2627
+ Read `browser-daemon.js` completely.
2628
+
2629
+ - [ ] **`--no-sandbox` in all environments.** The daemon always passes `--no-sandbox` to Chromium. In a developer's local machine (macOS/Linux), this is unnecessary and reduces security — `--no-sandbox` disables the Chromium sandbox which is a meaningful security boundary. Fix: "Only add `--no-sandbox` and `--disable-setuid-sandbox` when `CI=true` or `BROWSER_HEADLESS=true` AND running as root (which is common in Docker CI). On macOS/Linux as a non-root user, the sandbox works fine and should be enabled."
2630
+
2631
+ - [ ] **evaluate() runs arbitrary JS.** The `/evaluate` endpoint runs `page.evaluate(script)` where `script` comes directly from the HTTP request body. Since the daemon is localhost-only, the threat is mainly accidental misuse (evaluating on an external page) and malformed scripts causing unhandled errors. Add: "Validate that the current page URL starts with DEV_SERVER_URL before executing eval scripts. If not a known dev URL: return `{ success: false, error: 'evaluate() is only permitted on DEV_SERVER_URL origins' }`."
2632
+
2633
+ - [ ] **Session save race condition.** `SIGTERM` handler calls `saveSession()` for all sessions, but `saveSession()` uses `await context.cookies()` — what if the context is already closing? Add try-catch per session: "If `saveSession()` throws for a specific session during SIGTERM: log the error and continue to the next session. Never let one failed session save block the others."
2634
+
2635
+ - [ ] **Idle shutdown timer fires even when a request is in progress.** The idle timer checks `Date.now() - lastActionAt > IDLE_MS` every 60 seconds. But `lastActionAt` is only updated at the START of request handling. A slow request (e.g., navigating a slow page) takes 25 seconds — `lastActionAt` is updated at the start, so the idle timer won't fire mid-request. But a crash during a long request could leave `lastActionAt` stale. This is acceptable — document it: "Idle timer fires at most 60 seconds after the last request completion. A crash during a long request may cause the timer to fire earlier than expected."
2636
+
2637
+ ---
2638
+
2639
+ ## REVIEW PASS 2 — Screenshot Store: Path Traversal
2640
+
2641
+ Read `screenshot-store.js` completely.
2642
+
2643
+ - [ ] **Path traversal in `save()`.** The current `save()` sanitizes the filename with `.replace(/[^a-zA-Z0-9._-]/g, '-')`. But this only sanitizes the filename, not the planId parameter. If `planId` contains `../../../etc`, the screenshot would be saved outside the screenshots directory. Fix: "Also sanitize `planId` and `phaseNum` parameters. `planId`: allow only `[a-zA-Z0-9_-]`. `phaseNum`: coerce to integer. Verify the final resolved path starts with `STORE` using `path.resolve()`."
2644
+
2645
+ - [ ] **No disk quota enforcement.** The store has `diskUsage()` and `BROWSER_MAX_SCREENSHOTS_PER_PHASE` is in MINDFORGE.md, but `save()` doesn't check or enforce the limit. In a long auto-mode run with many visual verifies, screenshots could consume gigabytes. Fix: "In `save()`: after writing, check if `list(phaseNum).length > BROWSER_MAX_SCREENSHOTS_PER_PHASE`. If exceeded: delete the oldest N screenshots from the phase. Log: 'Screenshot limit reached for phase N — deleted M oldest'."
2646
+
2647
+ ---
2648
+
2649
+ ## REVIEW PASS 3 — Visual Verify Executor: Edge Cases
2650
+
2651
+ Read `visual-verify-executor.js` completely.
2652
+
2653
+ - [ ] **`press` directive is unimplemented.** The handler has `step.status = 'warn'` but the comment says "requires direct Playwright access; use click instead." This means `press: Enter` in a PLAN file silently passes as a warning. If a developer adds `press: Enter` expecting form submission, the form won't submit and the next assertion will fail with a confusing error. Fix: "Implement press via: `POST /evaluate` with `page.keyboard.press(args[0])` — or add a `/press` endpoint to the daemon. The `press` directive is commonly needed for `Enter` (form submit) and `Tab` (focus change)."
2654
+
2655
+ - [ ] **DEV_SERVER_URL used for relative URL resolution but not validated.** The executor resolves `/dashboard` to `${DEV_SERVER}${path}`. If `DEV_SERVER_URL` is not set and the default `http://localhost:3000` is wrong for the project, visual verify will silently navigate to the wrong URL and tests will fail with confusing "element not found" errors. Add: "At executor startup: check if `DEV_SERVER_URL` is reachable (single HEAD request with 2s timeout). If not: warn: 'DEV_SERVER_URL (http://localhost:3000) appears unreachable. Is your dev server running? Set DEV_SERVER_URL in MINDFORGE.md if using a different port.'"
2656
+
2657
+ - [ ] **`click` directive: selector vs text heuristic is fragile.** Current code: `const sel = args[0]; const body = sel.startsWith('"') ? { text: ... } : { selector: sel }`. But `"#create-project-btn"` with quotes would be treated as a text click, not a selector click. The quotes are already stripped by `parseDirectives`. Fix the heuristic: "Text click when the selector arg contains no CSS characters (`#`, `.`, `[`, `:`). Otherwise it's a CSS selector."
2658
+
2659
+ ---
2660
+
2661
+ ## REVIEW PASS 4 — QA Engine: Reliability
2662
+
2663
+ Read `qa-engine.js` completely.
2664
+
2665
+ - [ ] **`extractSurfaces` shell command injection.** `commitsBack` comes from function args (user-controlled). The exec call: `execSync(\`git diff HEAD~${commitsBack} --name-only\`)` — if `commitsBack` is `"; rm -rf /"` this is command injection. Fix: "Validate `commitsBack` is a positive integer before using in shell command. `const safeN = Math.max(1, Math.floor(Math.abs(Number(commitsBack) || 1)));`"
2666
+
2667
+ - [ ] **QA skips component files but doesn't find their parent pages.** When a component like `src/components/ProjectCard.tsx` changes, `classifyFile` returns `{ type: 'component' }` and the QA engine skips it. But the component could have broken the pages that use it. The spec says "find parent pages" — but the implementation just skips components. Fix: "For component surfaces: scan `src/pages/` and `src/app/` for files that import the component. Add those pages as derived surfaces with `derived_from: component_path`."
2668
+
2669
+ - [ ] **Dev server unreachable produces cascading failures.** If the dev server is not running, every `navigate` call fails. The QA report would show every surface as failed — which is misleading (the issue is the dev server, not the code). Add: "Before the QA loop: do a single `navigate('/')` health check. If it fails: return `{ error: 'Dev server unreachable at DEV_SERVER_URL', surfaces: 0 }` without running any tests."
2670
+
2671
+ ---
2672
+
2673
+ ## REVIEW PASS 5 — Session Manager: Cookie Expiry
2674
+
2675
+ Read `session-manager.js` completely.
2676
+
2677
+ - [ ] **`parseSqliteCookies` Windows epoch conversion.** The conversion `r.expires_utc / 1_000_000 - 11_644_473_600` converts Chrome's Windows FILETIME to Unix timestamp. But Chrome stores `expires_utc` in microseconds since 1601-01-01 (Windows epoch). The formula is correct, BUT: if `expires_utc` is 0 (session cookie — no expiry), the formula produces a negative number, which would be filtered out by `> now`. Session cookies should be treated as valid (non-expiring). Fix: "If `r.expires_utc === 0`: set `expires: -1` (Playwright's 'never expires' sentinel) instead of computing the conversion."
2678
+
2679
+ - [ ] **`importFromBrowser` error message suggests closing Chrome.** But on macOS, Chrome uses OS-level file locking inconsistently — sometimes the cookie file IS readable while Chrome is open. The error is premature. Fix: "First attempt to read the file. If it fails with EBUSY or similar: THEN suggest closing the browser. Do not pre-emptively tell users to close their browser."
2680
+
2681
+ ---
2682
+
2683
+ ## REVIEW PASS 6 — Test Suite Quality
2684
+
2685
+ Read `tests/browser.test.js` completely.
2686
+
2687
+ - [ ] **Screenshot store path traversal test is weak.** The test checks `!saved.includes('..')` but a sophisticated path traversal could use URL encoding or other tricks. The test should also verify the resolved path is WITHIN the expected directory. Fix: "Use `path.resolve()` to resolve the returned path and verify it starts with the expected screenshots directory: `assert.ok(path.resolve(saved).startsWith(path.resolve(STORE)))`."
2688
+
2689
+ - [ ] **`click` heuristic change not covered.** Review Pass 3 identified a bug in the click heuristic (CSS characters determine click type, not quote presence). The test suite has no test for this. Add: "Test that `click: .project-list` is treated as a CSS selector, `click: "Create Project"` as text click, and `click: #btn` as a CSS selector (not text)."
2690
+
2691
+ - [ ] **Missing test: QA dev server health check.** Review Pass 4 identified that QA should health-check the dev server before running. Add a test that verifies `runQA` returns an error object (not crashes) when the daemon is not running and cannot navigate.
2692
+
2693
+ ---
2694
+
2695
+ ## REVIEW SUMMARY TABLE
2696
+
2697
+ ```
2698
+ ## Day 9 Review Summary
2699
+
2700
+ | Category | BLOCKING | MAJOR | MINOR | SUGGESTION |
2701
+ |--------------------|----------|-------|-------|------------|
2702
+ | Browser Daemon | | | | |
2703
+ | Screenshot Store | | | | |
2704
+ | Visual Verify | | | | |
2705
+ | QA Engine | | | | |
2706
+ | Session Manager | | | | |
2707
+ | Test Suite | | | | |
2708
+ | **TOTAL** | | | | |
2709
+
2710
+ ## Verdict
2711
+ [ ] ✅ APPROVED — Proceed to HARDEN section
2712
+ [ ] ⚠️ APPROVED WITH CONDITIONS
2713
+ [ ] ❌ NOT APPROVED
2714
+ ```
2715
+
2716
+ ---
2717
+
2718
+ # ═══════════════════════════════════════════════════════════════════════
2719
+ # PART 3 — HARDENING PROMPT
2720
+ # ═══════════════════════════════════════════════════════════════════════
2721
+
2722
+ ---
2723
+
2724
+ ## DAY 9 HARDENING
2725
+
2726
+ Activate **`security-reviewer.md` + `qa-engineer.md`** simultaneously.
2727
+
2728
+ Confirm all test suites pass before hardening:
2729
+ ```bash
2730
+ for suite in install wave-engine audit compaction skills-platform \
2731
+ integrations governance intelligence metrics \
2732
+ distribution ci-mode sdk production migration e2e \
2733
+ autonomous browser; do
2734
+ printf " %-30s" "${suite}..."
2735
+ node tests/${suite}.test.js 2>&1 | tail -1
2736
+ done
2737
+ ```
2738
+
2739
+ ---
2740
+
2741
+ ## HARDEN 1 — Conditional Chromium sandbox flags
2742
+
2743
+ Update `browser-daemon.js` `init()` function:
2744
+
2745
+ ```javascript
2746
+ // Replace hardcoded --no-sandbox with environment-aware flags
2747
+ function getChromiumArgs() {
2748
+ const base = ['--no-first-run', '--no-zygote', '--disable-accelerated-2d-canvas'];
2749
+
2750
+ // Disable sandbox ONLY when:
2751
+ // - Running as root (common in Docker/CI)
2752
+ // - OR explicitly in CI environment
2753
+ // - OR BROWSER_NO_SANDBOX=true is set
2754
+ const isRoot = process.getuid && process.getuid() === 0;
2755
+ const isCI = process.env.CI === 'true';
2756
+ const forceNoSandbox = process.env.BROWSER_NO_SANDBOX === 'true';
2757
+
2758
+ if (isRoot || isCI || forceNoSandbox) {
2759
+ base.unshift('--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage');
2760
+ process.stderr.write('[daemon] ⚠️ Running without Chromium sandbox (CI/root mode)\n');
2761
+ } else {
2762
+ process.stderr.write('[daemon] ✅ Chromium sandbox enabled (local dev mode)\n');
2763
+ }
2764
+
2765
+ return base;
2766
+ }
2767
+
2768
+ // In init():
2769
+ browser = await playwright.chromium.launch({ headless: HEADLESS, args: getChromiumArgs() });
2770
+ ```
2771
+
2772
+ Add to MINDFORGE-V2-SCHEMA.json:
2773
+ ```json
2774
+ "BROWSER_NO_SANDBOX": { "type": "boolean",
2775
+ "description": "Disable Chromium sandbox (set true for CI/Docker, false for local dev)" }
2776
+ ```
2777
+
2778
+ **Commit:**
2779
+ ```bash
2780
+ git add bin/browser/browser-daemon.js .mindforge/MINDFORGE-V2-SCHEMA.json
2781
+ git commit -m "harden(v2-browser): conditional Chromium sandbox — enable locally, disable in CI/root"
2782
+ ```
2783
+
2784
+ ---
2785
+
2786
+ ## HARDEN 2 — Fix screenshot path traversal
2787
+
2788
+ Update `bin/browser/screenshot-store.js`:
2789
+
2790
+ ```javascript
2791
+ 'use strict';
2792
+ const fs = require('fs');
2793
+ const path = require('path');
2794
+
2795
+ const STORE = path.join(process.cwd(), '.planning', 'screenshots');
2796
+ const MAX_SCREENSHOTS = parseInt(process.env.BROWSER_MAX_SCREENSHOTS_PER_PHASE || '50', 10);
2797
+
2798
+ const ensureDir = d => fs.mkdirSync(d, { recursive: true });
2799
+
2800
+ function save(base64Png, phaseNum, planId, filename = 'screenshot.png') {
2801
+ // ── INPUT VALIDATION: prevent path traversal ─────────────────────────────
2802
+ const safePhase = Math.floor(Math.abs(Number(phaseNum) || 0));
2803
+ const safePlan = String(planId).replace(/[^a-zA-Z0-9_-]/g, '-').slice(0, 64);
2804
+ const safeName = String(filename || 'screenshot.png')
2805
+ .replace(/[^a-zA-Z0-9._-]/g, '-')
2806
+ .replace(/\.png$/i, '')
2807
+ .slice(0, 128) + '.png';
2808
+
2809
+ const dir = path.join(STORE, `phase-${safePhase}`, safePlan);
2810
+ const dest = path.join(dir, safeName);
2811
+
2812
+ // ── PATH TRAVERSAL GUARD: resolved path must stay inside STORE ───────────
2813
+ const resolvedStore = path.resolve(STORE);
2814
+ const resolvedDest = path.resolve(dest);
2815
+ if (!resolvedDest.startsWith(resolvedStore + path.sep) &&
2816
+ !resolvedDest.startsWith(resolvedStore)) {
2817
+ throw new Error(`Path traversal rejected: ${dest} is outside screenshot store`);
2818
+ }
2819
+
2820
+ ensureDir(dir);
2821
+ fs.writeFileSync(dest, Buffer.from(base64Png, 'base64'));
2822
+
2823
+ // ── QUOTA ENFORCEMENT: delete oldest if over limit ────────────────────────
2824
+ const phaseDir = path.join(STORE, `phase-${safePhase}`);
2825
+ const allShots = listAll(phaseDir);
2826
+ if (allShots.length > MAX_SCREENSHOTS) {
2827
+ const oldest = allShots
2828
+ .map(f => ({ f, mt: fs.statSync(f).mtimeMs }))
2829
+ .sort((a, b) => a.mt - b.mt)
2830
+ .slice(0, allShots.length - MAX_SCREENSHOTS);
2831
+ oldest.forEach(({ f }) => { try { fs.unlinkSync(f); } catch {} });
2832
+ process.stderr.write(`[screenshot-store] Quota: deleted ${oldest.length} oldest screenshots for phase ${safePhase}\n`);
2833
+ }
2834
+
2835
+ return dest;
2836
+ }
2837
+
2838
+ function listAll(dir) {
2839
+ if (!fs.existsSync(dir)) return [];
2840
+ const walk = d => fs.readdirSync(d, { withFileTypes: true })
2841
+ .flatMap(e => e.isDirectory() ? walk(path.join(d, e.name)) : path.join(d, e.name))
2842
+ .filter(p => p.endsWith('.png'));
2843
+ return walk(dir);
2844
+ }
2845
+
2846
+ function list(phaseNum, planId) {
2847
+ const safePhase = Math.floor(Math.abs(Number(phaseNum) || 0));
2848
+ const dir = planId
2849
+ ? path.join(STORE, `phase-${safePhase}`, String(planId).replace(/[^a-zA-Z0-9_-]/g, '-'))
2850
+ : path.join(STORE, `phase-${safePhase}`);
2851
+ return listAll(dir);
2852
+ }
2853
+
2854
+ function cleanup(phaseNum) {
2855
+ const safePhase = Math.floor(Math.abs(Number(phaseNum) || 0));
2856
+ const dir = path.join(STORE, `phase-${safePhase}`);
2857
+ if (fs.existsSync(dir)) fs.rmSync(dir, { recursive: true, force: true });
2858
+ }
2859
+
2860
+ function diskUsage() {
2861
+ if (!fs.existsSync(STORE)) return 0;
2862
+ let total = 0;
2863
+ const walk = d => { for (const e of fs.readdirSync(d, { withFileTypes: true })) {
2864
+ const p = path.join(d, e.name);
2865
+ e.isDirectory() ? walk(p) : (total += fs.statSync(p).size);
2866
+ }};
2867
+ walk(STORE);
2868
+ return total;
2869
+ }
2870
+
2871
+ module.exports = { save, list, cleanup, diskUsage };
2872
+ ```
2873
+
2874
+ **Commit:**
2875
+ ```bash
2876
+ git add bin/browser/screenshot-store.js
2877
+ git commit -m "harden(v2-browser): fix screenshot path traversal with path.resolve guard + quota enforcement"
2878
+ ```
2879
+
2880
+ ---
2881
+
2882
+ ## HARDEN 3 — Fix QA command injection and add dev server health check
2883
+
2884
+ Update `bin/browser/qa-engine.js`:
2885
+
2886
+ ```javascript
2887
+ // At top of extractSurfaces function — replace commitsBack usage:
2888
+ function extractSurfaces(phaseNum, commitsBack = 1) {
2889
+ // ── INPUT VALIDATION: prevent shell injection ─────────────────────────────
2890
+ const safeN = Math.max(1, Math.min(100, Math.floor(Math.abs(Number(commitsBack) || 1))));
2891
+ let files = [];
2892
+ // ... rest of function uses safeN instead of commitsBack ...
2893
+
2894
+ // Add dev server health check at top of runQA:
2895
+ async function runQA(phaseNum, opts = {}) {
2896
+ const { sessions = ['default'], routes = null, commitsBack = 1 } = opts;
2897
+
2898
+ await DaemonMgr.ensureRunning({ headless: true });
2899
+
2900
+ // ── Dev server health check ───────────────────────────────────────────────
2901
+ const healthCheck = await DaemonMgr.request('POST', '/navigate',
2902
+ { url: DEV_SERVER, session: 'default', wait_for: 'domcontentloaded' }
2903
+ ).catch(() => ({ success: false, error: 'Connection refused' }));
2904
+
2905
+ if (!healthCheck.success) {
2906
+ process.stderr.write(`[qa-engine] ⚠️ Dev server unreachable at ${DEV_SERVER}\n`);
2907
+ process.stderr.write(`[qa-engine] Is your dev server running? Start it first.\n`);
2908
+ return {
2909
+ surfaces: 0, passed: 0, failed: 0, bugs: [], results: [],
2910
+ error: `Dev server unreachable at ${DEV_SERVER}. Start your dev server and retry.`,
2911
+ };
2912
+ }
2913
+
2914
+ // ... rest of function unchanged ...
2915
+ ```
2916
+
2917
+ Also implement parent page discovery for components:
2918
+
2919
+ ```javascript
2920
+ // Add to qa-engine.js — called after classifyFile returns a component:
2921
+ function findParentPages(componentFile) {
2922
+ const parents = [];
2923
+ const pagesRoots = ['src/app', 'src/pages'];
2924
+
2925
+ for (const root of pagesRoots) {
2926
+ if (!fs.existsSync(root)) continue;
2927
+ const walk = (dir) => {
2928
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
2929
+ const full = path.join(dir, entry.name);
2930
+ if (entry.isDirectory()) { walk(full); continue; }
2931
+ if (!/\.(tsx|jsx|ts|js)$/.test(entry.name)) continue;
2932
+ try {
2933
+ const content = fs.readFileSync(full, 'utf8');
2934
+ if (content.includes(path.basename(componentFile, path.extname(componentFile)))) {
2935
+ const surface = classifyFile(full.replace(process.cwd() + '/', ''));
2936
+ if (surface?.type === 'page') parents.push({ ...surface, source_file: full, derived_from: componentFile });
2937
+ }
2938
+ } catch {}
2939
+ }
2940
+ };
2941
+ walk(root);
2942
+ }
2943
+ return parents;
2944
+ }
2945
+ ```
2946
+
2947
+ **Commit:**
2948
+ ```bash
2949
+ git add bin/browser/qa-engine.js
2950
+ git commit -m "harden(v2-browser): fix QA shell injection, add dev server health check, component parent discovery"
2951
+ ```
2952
+
2953
+ ---
2954
+
2955
+ ## HARDEN 4 — Fix `press` directive and click heuristic
2956
+
2957
+ Update `bin/browser/visual-verify-executor.js`:
2958
+
2959
+ ```javascript
2960
+ // Replace 'press' case in executeBlock switch:
2961
+ case 'press': {
2962
+ const key = args[0] || 'Enter';
2963
+ // Implement via evaluate — page.keyboard is accessible in evaluate context
2964
+ const r = await DaemonMgr.request('POST', '/evaluate', {
2965
+ script: `document.activeElement.dispatchEvent(new KeyboardEvent('keydown', {key:'${key}',bubbles:true}))`,
2966
+ session,
2967
+ });
2968
+ step.detail = `pressed ${key}`;
2969
+ // Also try pressing Enter on the focused element via Playwright hint
2970
+ break;
2971
+ }
2972
+
2973
+ // Fix click directive heuristic — replace existing 'click' case:
2974
+ case 'click': {
2975
+ const raw = args[0] || '';
2976
+ // Use CSS characters to determine if it's a selector or text
2977
+ const isCSSSelector = /^[#\.\[\:\*\~\>\+]/.test(raw) || raw.includes('[') || raw.includes('=');
2978
+ const body = isCSSSelector
2979
+ ? { selector: raw, session }
2980
+ : { text: raw.replace(/^["']|["']$/g, ''), session }; // Strip quotes from text
2981
+ const r = await DaemonMgr.request('POST', '/click', body);
2982
+ step.detail = r.element_found ? 'clicked' : 'element not found';
2983
+ if (!r.success || !r.element_found) { step.status = 'fail'; passed = false; }
2984
+ break;
2985
+ }
2986
+ ```
2987
+
2988
+ **Commit:**
2989
+ ```bash
2990
+ git add bin/browser/visual-verify-executor.js
2991
+ git commit -m "harden(v2-browser): implement press directive, fix click CSS-vs-text heuristic"
2992
+ ```
2993
+
2994
+ ---
2995
+
2996
+ ## HARDEN 5 — Fix SQLite session cookie Windows epoch for session cookies
2997
+
2998
+ Update `bin/browser/session-manager.js`:
2999
+
3000
+ ```javascript
3001
+ // In parseSqliteCookies — replace expires calculation:
3002
+ return rows.map(r => ({
3003
+ name: r.name, value: r.value, domain: r.host_key, path: r.path,
3004
+ // Session cookies have expires_utc = 0 — map to -1 (Playwright: never expires)
3005
+ expires: r.expires_utc === 0
3006
+ ? -1
3007
+ : r.expires_utc / 1_000_000 - 11_644_473_600,
3008
+ secure: !!r.is_secure, httpOnly: !!r.is_httponly, sameSite: 'Lax',
3009
+ }))
3010
+ // Filter: keep session cookies (expires = -1) AND non-expired time-bound cookies
3011
+ .filter(c => c.name && (c.expires === -1 || c.expires > Date.now() / 1000));
3012
+ ```
3013
+
3014
+ **Commit:**
3015
+ ```bash
3016
+ git add bin/browser/session-manager.js
3017
+ git commit -m "harden(v2-browser): fix session cookie Windows epoch — map expires_utc=0 to -1"
3018
+ ```
3019
+
3020
+ ---
3021
+
3022
+ ## HARDEN 6 — Strengthen test coverage for hardened paths
3023
+
3024
+ Add to `tests/browser.test.js`:
3025
+
3026
+ ```javascript
3027
+ // ── Hardening tests ───────────────────────────────────────────────────────────
3028
+ console.log('\nHardening tests:');
3029
+
3030
+ test('screenshot save: path traversal with planId is rejected', () => {
3031
+ const p = mkProject(true);
3032
+ const orig = process.cwd();
3033
+ process.chdir(p.dir);
3034
+ try {
3035
+ assert.throws(
3036
+ () => ScreenStore.save(TINY_PNG_B64, 3, '../../evil', 'bad.png'),
3037
+ /traversal/i,
3038
+ 'Should throw on path traversal in planId'
3039
+ );
3040
+ } finally { process.chdir(orig); p.cleanup(); }
3041
+ });
3042
+
3043
+ test('screenshot save: path traversal in filename is rejected', () => {
3044
+ const p = mkProject(true);
3045
+ const orig = process.cwd();
3046
+ process.chdir(p.dir);
3047
+ try {
3048
+ // This should NOT throw — filename is sanitized, not rejected
3049
+ // But the saved path must stay inside STORE
3050
+ const saved = ScreenStore.save(TINY_PNG_B64, 3, '04', '../../evil.png');
3051
+ const resolvedStore = require('path').resolve(p.dir, '.planning', 'screenshots');
3052
+ const resolvedSaved = require('path').resolve(saved);
3053
+ assert.ok(resolvedSaved.startsWith(resolvedStore), 'Saved path must be inside screenshot store');
3054
+ } finally { process.chdir(orig); p.cleanup(); }
3055
+ });
3056
+
3057
+ test('Chromium args: no-sandbox only when CI=true or root', () => {
3058
+ const c = fs.readFileSync('bin/browser/browser-daemon.js', 'utf8');
3059
+ assert.ok(
3060
+ c.includes('isCI') || c.includes('CI=') || c.includes('process.env.CI'),
3061
+ 'Sandbox flag should be conditional on CI environment'
3062
+ );
3063
+ assert.ok(
3064
+ !c.includes("'--no-sandbox'") || c.includes('if') || c.includes('getChromiumArgs'),
3065
+ '--no-sandbox should not be unconditional'
3066
+ );
3067
+ });
3068
+
3069
+ test('visual verify click heuristic: CSS selector detected by # prefix', () => {
3070
+ const d = VisualVerify.parseDirectives('click: #submit-btn');
3071
+ assert.strictEqual(d[0].directive, 'click');
3072
+ assert.strictEqual(d[0].args[0], '#submit-btn', 'CSS selector preserved as-is');
3073
+ });
3074
+
3075
+ test('visual verify click heuristic: text click detected when no CSS chars', () => {
3076
+ const d = VisualVerify.parseDirectives('click: "Sign In"');
3077
+ assert.strictEqual(d[0].directive, 'click');
3078
+ // Text args have quotes stripped by parseDirectives
3079
+ assert.strictEqual(d[0].args[0], 'Sign In', 'Text has quotes stripped');
3080
+ });
3081
+
3082
+ test('QA report: no bugs section says "No bugs found"', () => {
3083
+ const p = mkProject();
3084
+ const orig = process.cwd();
3085
+ process.chdir(p.dir);
3086
+ try {
3087
+ const file = QAReportWriter.write(5, { surfaces: 1, passed: 1, failed: 0, results: [{ surface: '/home', session: 'default', passed: true }], bugs: [] });
3088
+ const c = fs.readFileSync(file, 'utf8');
3089
+ assert.ok(c.includes('No bugs found'), 'Should say "No bugs found"');
3090
+ } finally { process.chdir(orig); p.cleanup(); }
3091
+ });
3092
+ ```
3093
+
3094
+ **Commit:**
3095
+ ```bash
3096
+ git add tests/browser.test.js
3097
+ git commit -m "test(v2-browser): add hardening tests for path traversal, sandbox flags, click heuristic"
3098
+ ```
3099
+
3100
+ ---
3101
+
3102
+ ## HARDEN 7 — Write 3 ADRs for Day 9 decisions
3103
+
3104
+ ### `.planning/decisions/ADR-024-browser-daemon-localhost-only.md`
3105
+
3106
+ ```markdown
3107
+ # ADR-024: Browser daemon binds to localhost only (127.0.0.1)
3108
+
3109
+ **Status:** Accepted | **Date:** v2.0.0 | **Day:** 9
3110
+
3111
+ ## Context
3112
+ The browser daemon (port 7338) exposes session data, screenshots, and
3113
+ JavaScript evaluation capabilities. Should it bind to all interfaces?
3114
+
3115
+ ## Decision
3116
+ Bind to 127.0.0.1 only. Consistent with ADR-017 (SDK SSE server).
3117
+
3118
+ ## Rationale
3119
+ Sessions contain auth tokens. Cookies can include JWTs and session IDs.
3120
+ Exposing these on a network interface in a shared dev environment would
3121
+ allow any other machine (or container on the same host network) to access
3122
+ them. The use case (developer testing their own app) never requires remote access.
3123
+ For remote monitoring: use SSH tunneling.
3124
+
3125
+ ## Consequences
3126
+ Same as ADR-017: remote access requires explicit SSH tunnel.
3127
+ CI environments (Docker, GitHub Actions) run locally — no issue.
3128
+ ```
3129
+
3130
+ ### `.planning/decisions/ADR-025-verify-visual-failure-is-verify-failure.md`
3131
+
3132
+ ```markdown
3133
+ # ADR-025: <verify-visual> failure is treated identically to <verify> failure
3134
+
3135
+ **Status:** Accepted | **Date:** v2.0.0 | **Day:** 9
3136
+
3137
+ ## Context
3138
+ When <verify-visual> assertions fail after <verify> passes, what should happen?
3139
+
3140
+ ## Decision
3141
+ <verify-visual> failure triggers node repair (RETRY → DECOMPOSE → PRUNE → ESCALATE)
3142
+ identically to a <verify> (unit test) failure.
3143
+
3144
+ ## Rationale
3145
+ If the UI doesn't look correct, the task is not done — regardless of whether
3146
+ unit tests pass. A login form that passes tests but allows empty email submission
3147
+ is a real bug. Node repair handles it the same way.
3148
+
3149
+ The screenshot attached to the visual verify failure gives the retry agent
3150
+ much better information than a test failure message — it can see exactly what
3151
+ the browser showed when the assertion failed.
3152
+
3153
+ ## Consequences
3154
+ Auto mode will attempt to self-repair visual verification failures.
3155
+ Engineers should use <verify-visual> for meaningful assertions (not cosmetic preferences)
3156
+ to avoid excessive node repairs on subjective UI details.
3157
+ ```
3158
+
3159
+ ### `.planning/decisions/ADR-026-session-files-gitignored.md`
3160
+
3161
+ ```markdown
3162
+ # ADR-026: Browser session files are gitignored — auth tokens must never reach git
3163
+
3164
+ **Status:** Accepted | **Date:** v2.0.0 | **Day:** 9
3165
+
3166
+ ## Context
3167
+ Browser sessions contain cookies (including auth tokens, session IDs, JWTs).
3168
+ Should they be committed to git for reproducibility?
3169
+
3170
+ ## Decision
3171
+ Session files are gitignored. They are never committed to any branch.
3172
+ Screenshots are also gitignored.
3173
+
3174
+ ## Rationale
3175
+ Auth tokens in git are a security incident requiring token rotation and history rewrite.
3176
+ The benefit of committing sessions (reproducibility) is outweighed by:
3177
+ 1. Sessions expire anyway — they are not long-lived test fixtures
3178
+ 2. Session files contain credentials for developer accounts
3179
+ 3. Git history is effectively permanent — a leaked token stays in history
3180
+
3181
+ For CI: use programmatic session creation (Method 3 from session-manager.md)
3182
+ with credentials stored in CI secrets, not in committed files.
3183
+
3184
+ ## Consequences
3185
+ Each developer creates their own sessions locally.
3186
+ CI uses programmatic login with test credentials from CI secrets.
3187
+ Session state cannot be shared via git — this is by design.
3188
+ ```
3189
+
3190
+ **Commit:**
3191
+ ```bash
3192
+ git add .planning/decisions/ADR-024*.md \
3193
+ .planning/decisions/ADR-025*.md \
3194
+ .planning/decisions/ADR-026*.md
3195
+ git commit -m "docs(adr): add ADR-024 localhost binding, ADR-025 visual verify failure, ADR-026 sessions gitignored"
3196
+ ```
3197
+
3198
+ ---
3199
+
3200
+ ## HARDEN 8 — Final pre-merge verification
3201
+
3202
+ ```bash
3203
+ #!/usr/bin/env bash
3204
+ echo "MindForge v2 Day 9 — Pre-Merge Verification"
3205
+ echo "══════════════════════════════════════════════"
3206
+ PASS=true
3207
+
3208
+ # 1. Version
3209
+ V=$(node -e "console.log(require('./package.json').version)")
3210
+ [[ "${V}" == "2.0.0-alpha.2" ]] && echo " Version: ${V} ✅" || { echo " ❌ Version: ${V}"; PASS=false; }
3211
+
3212
+ # 2. All 17 test suites
3213
+ echo ""
3214
+ echo " Test suites:"
3215
+ FAIL=0
3216
+ for suite in install wave-engine audit compaction skills-platform \
3217
+ integrations governance intelligence metrics \
3218
+ distribution ci-mode sdk production migration e2e \
3219
+ autonomous browser; do
3220
+ printf " %-30s" "${suite}..."
3221
+ if node tests/${suite}.test.js 2>&1 | tail -1 | grep -q "passed"; then
3222
+ echo "✅"
3223
+ else
3224
+ echo "❌"; ((FAIL++)); PASS=false
3225
+ fi
3226
+ done
3227
+ echo " Failed: ${FAIL}"
3228
+
3229
+ # 3. Command count
3230
+ CMDS=$(ls .claude/commands/mindforge/ | wc -l | tr -d ' ')
3231
+ [ "$CMDS" -ge 40 ] && echo " Commands: ${CMDS} ✅" || { echo " ❌ Commands: ${CMDS} < 40"; PASS=false; }
3232
+
3233
+ # 4. ADRs
3234
+ ADRS=$(ls .planning/decisions/ADR-*.md 2>/dev/null | wc -l | tr -d ' ')
3235
+ [ "$ADRS" -ge 26 ] && echo " ADRs: ${ADRS} ✅" || { echo " ❌ ADRs: ${ADRS} < 26"; PASS=false; }
3236
+
3237
+ # 5. gitignore
3238
+ grep -q "sessions" .gitignore && grep -q "screenshots" .gitignore \
3239
+ && echo " .gitignore: sessions + screenshots ✅" \
3240
+ || { echo " ❌ .gitignore missing browser entries"; PASS=false; }
3241
+
3242
+ # 6. No secrets
3243
+ SECRETS=$(grep -rE "(password|api_key|token)\s*=\s*['\"][^'\"]{8,}" \
3244
+ --include="*.md" --include="*.js" --include="*.json" \
3245
+ --exclude-dir=node_modules --exclude-dir=.git . 2>/dev/null | \
3246
+ grep -v "placeholder\|example\|your-\|TEST_ONLY" || true)
3247
+ [ -z "$SECRETS" ] && echo " Secrets: clean ✅" || { echo " ❌ Credentials detected"; PASS=false; }
3248
+
3249
+ echo ""
3250
+ if $PASS; then
3251
+ echo "✅ ALL CHECKS PASSED — Day 9 complete"
3252
+ echo ""
3253
+ echo " v2.0.0-alpha.2 is ready for PR."
3254
+ echo " Next: Day 10 — Multi-Model Intelligence Layer"
3255
+ else
3256
+ echo "❌ FAILURES — fix before merging"
3257
+ exit 1
3258
+ fi
3259
+ ```
3260
+
3261
+ **Final commits:**
3262
+ ```bash
3263
+ git add .
3264
+ git commit -m "harden(v2-day9): complete all hardening — path traversal, sandbox, click heuristic, ADRs"
3265
+ git push origin feat/mindforge-v2-browser-runtime
3266
+ ```
3267
+
3268
+ ---
3269
+
3270
+ ## DAY 9 COMPLETE
3271
+
3272
+ | Component | Status |
3273
+ |---|---|
3274
+ | Browser daemon (Playwright, port 7338, localhost-only) | ✅ |
3275
+ | Daemon manager (lifecycle, auto-start, PID file) | ✅ |
3276
+ | Session manager (persistence, cookie import, expiry) | ✅ |
3277
+ | `<verify-visual>` parser (13 directives, session attr) | ✅ |
3278
+ | Visual verify executor (fail-fast, screenshot capture) | ✅ |
3279
+ | Screenshot store (phase namespaced, path traversal guard) | ✅ |
3280
+ | QA engine (git-diff surfaces, component parent discovery) | ✅ |
3281
+ | QA report writer (QA-REPORT-[N].md) | ✅ |
3282
+ | Regression test writer (Playwright .test.ts per bug) | ✅ |
3283
+ | `/mindforge:browse` command (40th) | ✅ |
3284
+ | `/mindforge:qa` command (40th) | ✅ |
3285
+ | execute-phase: `<verify-visual>` hook | ✅ |
3286
+ | MINDFORGE.md browser settings + schema | ✅ |
3287
+ | `tests/browser.test.js` (17th suite) | ✅ |
3288
+ | ADR-024, ADR-025, ADR-026 | ✅ |
3289
+ | CHANGELOG v2.0.0-alpha.2 | ✅ |
3290
+
3291
+ **MindForge v2.0.0-alpha.2: 40 commands · 17 test suites · 26 ADRs**
3292
+ **Branch:** `feat/mindforge-v2-browser-runtime`
3293
+ **Day 9 complete. Open PR → merge → start Day 10 (Multi-Model Intelligence)**