@su-record/vibe 3.2.13 → 3.2.15

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 (305) hide show
  1. package/CLAUDE.md +15 -14
  2. package/README.en.md +1 -1
  3. package/README.md +1 -1
  4. package/dist/cli/setup/ProjectSetup.d.ts +6 -0
  5. package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
  6. package/dist/cli/setup/ProjectSetup.js +19 -13
  7. package/dist/cli/setup/ProjectSetup.js.map +1 -1
  8. package/dist/infra/lib/codex-proxy.d.ts +126 -0
  9. package/dist/infra/lib/codex-proxy.d.ts.map +1 -1
  10. package/dist/infra/lib/codex-proxy.js +16 -16
  11. package/dist/infra/lib/codex-proxy.js.map +1 -1
  12. package/dist/infra/lib/figma/audit.d.ts.map +1 -1
  13. package/dist/infra/lib/figma/audit.js +0 -2
  14. package/dist/infra/lib/figma/audit.js.map +1 -1
  15. package/dist/infra/lib/figma/extract.d.ts +6 -1
  16. package/dist/infra/lib/figma/extract.d.ts.map +1 -1
  17. package/dist/infra/lib/figma/extract.js +17 -15
  18. package/dist/infra/lib/figma/extract.js.map +1 -1
  19. package/dist/infra/lib/figma/types.d.ts +103 -0
  20. package/dist/infra/lib/figma/types.d.ts.map +1 -1
  21. package/dist/infra/lib/figma/types.js +8 -0
  22. package/dist/infra/lib/figma/types.js.map +1 -1
  23. package/hooks/hooks.json +1 -1
  24. package/hooks/scripts/clone-extract.js +16 -1
  25. package/hooks/scripts/code-check.js +72 -55
  26. package/hooks/scripts/lib/anchor.js +74 -0
  27. package/hooks/scripts/lib/console-allow.js +66 -0
  28. package/hooks/scripts/lib/dispatcher.js +71 -19
  29. package/hooks/scripts/lib/inbox.js +60 -0
  30. package/hooks/scripts/loop-ledger.js +24 -1
  31. package/hooks/scripts/post-edit-dispatcher.js +4 -3
  32. package/hooks/scripts/post-edit.js +2 -2
  33. package/package.json +13 -9
  34. package/skills/vibe/SKILL.md +2 -1
  35. package/skills/vibe.clone/references/verification-loops.md +6 -3
  36. package/skills/vibe.loop/SKILL.md +7 -4
  37. package/skills/vibe.review/SKILL.md +5 -1
  38. package/skills/vibe.run/references/e2e-and-autofix.md +1 -1
  39. package/skills/vibe.run/references/process-steps.md +1 -1
  40. package/vibe/constitution.md +1 -1
  41. package/vibe/rules/loop-contract.md +40 -3
  42. package/vibe/rules/quality/checklist.md +3 -3
  43. package/vibe/templates/constitution-template.md +1 -1
  44. package/dist/__tests__/agent-model-sync.test.d.ts +0 -2
  45. package/dist/__tests__/agent-model-sync.test.d.ts.map +0 -1
  46. package/dist/__tests__/agent-model-sync.test.js +0 -71
  47. package/dist/__tests__/agent-model-sync.test.js.map +0 -1
  48. package/dist/__tests__/architecture.test.d.ts +0 -2
  49. package/dist/__tests__/architecture.test.d.ts.map +0 -1
  50. package/dist/__tests__/architecture.test.js +0 -207
  51. package/dist/__tests__/architecture.test.js.map +0 -1
  52. package/dist/__tests__/skill-namespace.test.d.ts +0 -2
  53. package/dist/__tests__/skill-namespace.test.d.ts.map +0 -1
  54. package/dist/__tests__/skill-namespace.test.js +0 -60
  55. package/dist/__tests__/skill-namespace.test.js.map +0 -1
  56. package/dist/__tests__/stakes-contract.test.d.ts +0 -2
  57. package/dist/__tests__/stakes-contract.test.d.ts.map +0 -1
  58. package/dist/__tests__/stakes-contract.test.js +0 -166
  59. package/dist/__tests__/stakes-contract.test.js.map +0 -1
  60. package/dist/__tests__/stuck-semantics.test.d.ts +0 -2
  61. package/dist/__tests__/stuck-semantics.test.d.ts.map +0 -1
  62. package/dist/__tests__/stuck-semantics.test.js +0 -109
  63. package/dist/__tests__/stuck-semantics.test.js.map +0 -1
  64. package/dist/__tests__/wiring-integrity.test.d.ts +0 -2
  65. package/dist/__tests__/wiring-integrity.test.d.ts.map +0 -1
  66. package/dist/__tests__/wiring-integrity.test.js +0 -160
  67. package/dist/__tests__/wiring-integrity.test.js.map +0 -1
  68. package/dist/cli/commands/info.test.d.ts +0 -2
  69. package/dist/cli/commands/info.test.d.ts.map +0 -1
  70. package/dist/cli/commands/info.test.js +0 -74
  71. package/dist/cli/commands/info.test.js.map +0 -1
  72. package/dist/cli/commands/upgrade.test.d.ts +0 -2
  73. package/dist/cli/commands/upgrade.test.d.ts.map +0 -1
  74. package/dist/cli/commands/upgrade.test.js +0 -99
  75. package/dist/cli/commands/upgrade.test.js.map +0 -1
  76. package/dist/cli/design/design-md-parser.test.d.ts +0 -2
  77. package/dist/cli/design/design-md-parser.test.d.ts.map +0 -1
  78. package/dist/cli/design/design-md-parser.test.js +0 -149
  79. package/dist/cli/design/design-md-parser.test.js.map +0 -1
  80. package/dist/cli/detect.characterization.test.d.ts +0 -7
  81. package/dist/cli/detect.characterization.test.d.ts.map +0 -1
  82. package/dist/cli/detect.characterization.test.js +0 -294
  83. package/dist/cli/detect.characterization.test.js.map +0 -1
  84. package/dist/cli/postinstall/fs-utils.test.d.ts +0 -2
  85. package/dist/cli/postinstall/fs-utils.test.d.ts.map +0 -1
  86. package/dist/cli/postinstall/fs-utils.test.js +0 -259
  87. package/dist/cli/postinstall/fs-utils.test.js.map +0 -1
  88. package/dist/cli/setup/CodexHooks.test.d.ts +0 -2
  89. package/dist/cli/setup/CodexHooks.test.d.ts.map +0 -1
  90. package/dist/cli/setup/CodexHooks.test.js +0 -52
  91. package/dist/cli/setup/CodexHooks.test.js.map +0 -1
  92. package/dist/cli/setup/GlobalInstaller.test.d.ts +0 -2
  93. package/dist/cli/setup/GlobalInstaller.test.d.ts.map +0 -1
  94. package/dist/cli/setup/GlobalInstaller.test.js +0 -16
  95. package/dist/cli/setup/GlobalInstaller.test.js.map +0 -1
  96. package/dist/cli/utils/cli-detector.test.d.ts +0 -2
  97. package/dist/cli/utils/cli-detector.test.d.ts.map +0 -1
  98. package/dist/cli/utils/cli-detector.test.js +0 -52
  99. package/dist/cli/utils/cli-detector.test.js.map +0 -1
  100. package/dist/infra/lib/SkillFrontmatter.test.d.ts +0 -2
  101. package/dist/infra/lib/SkillFrontmatter.test.d.ts.map +0 -1
  102. package/dist/infra/lib/SkillFrontmatter.test.js +0 -60
  103. package/dist/infra/lib/SkillFrontmatter.test.js.map +0 -1
  104. package/dist/infra/lib/__tests__/AutomationLevel.test.d.ts +0 -2
  105. package/dist/infra/lib/__tests__/AutomationLevel.test.d.ts.map +0 -1
  106. package/dist/infra/lib/__tests__/AutomationLevel.test.js +0 -297
  107. package/dist/infra/lib/__tests__/AutomationLevel.test.js.map +0 -1
  108. package/dist/infra/lib/__tests__/ComponentRegistry.test.d.ts +0 -2
  109. package/dist/infra/lib/__tests__/ComponentRegistry.test.d.ts.map +0 -1
  110. package/dist/infra/lib/__tests__/ComponentRegistry.test.js +0 -99
  111. package/dist/infra/lib/__tests__/ComponentRegistry.test.js.map +0 -1
  112. package/dist/infra/lib/__tests__/DecisionTracer.test.d.ts +0 -2
  113. package/dist/infra/lib/__tests__/DecisionTracer.test.d.ts.map +0 -1
  114. package/dist/infra/lib/__tests__/DecisionTracer.test.js +0 -274
  115. package/dist/infra/lib/__tests__/DecisionTracer.test.js.map +0 -1
  116. package/dist/infra/lib/__tests__/InteractiveCheckpoint.test.d.ts +0 -2
  117. package/dist/infra/lib/__tests__/InteractiveCheckpoint.test.d.ts.map +0 -1
  118. package/dist/infra/lib/__tests__/InteractiveCheckpoint.test.js +0 -350
  119. package/dist/infra/lib/__tests__/InteractiveCheckpoint.test.js.map +0 -1
  120. package/dist/infra/lib/__tests__/LoopBreaker.test.d.ts +0 -2
  121. package/dist/infra/lib/__tests__/LoopBreaker.test.d.ts.map +0 -1
  122. package/dist/infra/lib/__tests__/LoopBreaker.test.js +0 -340
  123. package/dist/infra/lib/__tests__/LoopBreaker.test.js.map +0 -1
  124. package/dist/infra/lib/__tests__/VerificationLoop.test.d.ts +0 -2
  125. package/dist/infra/lib/__tests__/VerificationLoop.test.d.ts.map +0 -1
  126. package/dist/infra/lib/__tests__/VerificationLoop.test.js +0 -486
  127. package/dist/infra/lib/__tests__/VerificationLoop.test.js.map +0 -1
  128. package/dist/infra/lib/config/GlobalConfigManager.test.d.ts +0 -2
  129. package/dist/infra/lib/config/GlobalConfigManager.test.d.ts.map +0 -1
  130. package/dist/infra/lib/config/GlobalConfigManager.test.js +0 -9
  131. package/dist/infra/lib/config/GlobalConfigManager.test.js.map +0 -1
  132. package/dist/infra/lib/embedding/__tests__/EmbeddingProvider.test.d.ts +0 -2
  133. package/dist/infra/lib/embedding/__tests__/EmbeddingProvider.test.d.ts.map +0 -1
  134. package/dist/infra/lib/embedding/__tests__/EmbeddingProvider.test.js +0 -43
  135. package/dist/infra/lib/embedding/__tests__/EmbeddingProvider.test.js.map +0 -1
  136. package/dist/infra/lib/embedding/__tests__/VectorStore.test.d.ts +0 -2
  137. package/dist/infra/lib/embedding/__tests__/VectorStore.test.d.ts.map +0 -1
  138. package/dist/infra/lib/embedding/__tests__/VectorStore.test.js +0 -94
  139. package/dist/infra/lib/embedding/__tests__/VectorStore.test.js.map +0 -1
  140. package/dist/infra/lib/embedding/__tests__/cosine.test.d.ts +0 -2
  141. package/dist/infra/lib/embedding/__tests__/cosine.test.d.ts.map +0 -1
  142. package/dist/infra/lib/embedding/__tests__/cosine.test.js +0 -73
  143. package/dist/infra/lib/embedding/__tests__/cosine.test.js.map +0 -1
  144. package/dist/infra/lib/evolution/__tests__/deprecation.test.d.ts +0 -2
  145. package/dist/infra/lib/evolution/__tests__/deprecation.test.d.ts.map +0 -1
  146. package/dist/infra/lib/evolution/__tests__/deprecation.test.js +0 -251
  147. package/dist/infra/lib/evolution/__tests__/deprecation.test.js.map +0 -1
  148. package/dist/infra/lib/evolution/__tests__/eval.test.d.ts +0 -2
  149. package/dist/infra/lib/evolution/__tests__/eval.test.d.ts.map +0 -1
  150. package/dist/infra/lib/evolution/__tests__/eval.test.js +0 -603
  151. package/dist/infra/lib/evolution/__tests__/eval.test.js.map +0 -1
  152. package/dist/infra/lib/evolution/__tests__/generation.test.d.ts +0 -2
  153. package/dist/infra/lib/evolution/__tests__/generation.test.d.ts.map +0 -1
  154. package/dist/infra/lib/evolution/__tests__/generation.test.js +0 -396
  155. package/dist/infra/lib/evolution/__tests__/generation.test.js.map +0 -1
  156. package/dist/infra/lib/evolution/__tests__/insight.test.d.ts +0 -2
  157. package/dist/infra/lib/evolution/__tests__/insight.test.d.ts.map +0 -1
  158. package/dist/infra/lib/evolution/__tests__/insight.test.js +0 -204
  159. package/dist/infra/lib/evolution/__tests__/insight.test.js.map +0 -1
  160. package/dist/infra/lib/evolution/__tests__/integration.test.d.ts +0 -2
  161. package/dist/infra/lib/evolution/__tests__/integration.test.d.ts.map +0 -1
  162. package/dist/infra/lib/evolution/__tests__/integration.test.js +0 -206
  163. package/dist/infra/lib/evolution/__tests__/integration.test.js.map +0 -1
  164. package/dist/infra/lib/evolution/__tests__/lifecycle.test.d.ts +0 -2
  165. package/dist/infra/lib/evolution/__tests__/lifecycle.test.d.ts.map +0 -1
  166. package/dist/infra/lib/evolution/__tests__/lifecycle.test.js +0 -350
  167. package/dist/infra/lib/evolution/__tests__/lifecycle.test.js.map +0 -1
  168. package/dist/infra/lib/evolution/__tests__/parity.test.d.ts +0 -2
  169. package/dist/infra/lib/evolution/__tests__/parity.test.d.ts.map +0 -1
  170. package/dist/infra/lib/evolution/__tests__/parity.test.js +0 -319
  171. package/dist/infra/lib/evolution/__tests__/parity.test.js.map +0 -1
  172. package/dist/infra/lib/llm/auth/AuthProfileManager.test.d.ts +0 -5
  173. package/dist/infra/lib/llm/auth/AuthProfileManager.test.d.ts.map +0 -1
  174. package/dist/infra/lib/llm/auth/AuthProfileManager.test.js +0 -168
  175. package/dist/infra/lib/llm/auth/AuthProfileManager.test.js.map +0 -1
  176. package/dist/infra/lib/llm/auth/TokenRefresher.test.d.ts +0 -2
  177. package/dist/infra/lib/llm/auth/TokenRefresher.test.d.ts.map +0 -1
  178. package/dist/infra/lib/llm/auth/TokenRefresher.test.js +0 -120
  179. package/dist/infra/lib/llm/auth/TokenRefresher.test.js.map +0 -1
  180. package/dist/infra/lib/llm/timeout.test.d.ts +0 -2
  181. package/dist/infra/lib/llm/timeout.test.d.ts.map +0 -1
  182. package/dist/infra/lib/llm/timeout.test.js +0 -50
  183. package/dist/infra/lib/llm/timeout.test.js.map +0 -1
  184. package/dist/infra/lib/llm-availability.test.d.ts +0 -2
  185. package/dist/infra/lib/llm-availability.test.d.ts.map +0 -1
  186. package/dist/infra/lib/llm-availability.test.js +0 -37
  187. package/dist/infra/lib/llm-availability.test.js.map +0 -1
  188. package/dist/infra/lib/memory/KnowledgeGraph.test.d.ts +0 -2
  189. package/dist/infra/lib/memory/KnowledgeGraph.test.d.ts.map +0 -1
  190. package/dist/infra/lib/memory/KnowledgeGraph.test.js +0 -189
  191. package/dist/infra/lib/memory/KnowledgeGraph.test.js.map +0 -1
  192. package/dist/infra/lib/memory/MemorySearch.test.d.ts +0 -2
  193. package/dist/infra/lib/memory/MemorySearch.test.d.ts.map +0 -1
  194. package/dist/infra/lib/memory/MemorySearch.test.js +0 -149
  195. package/dist/infra/lib/memory/MemorySearch.test.js.map +0 -1
  196. package/dist/infra/lib/memory/MemoryStorage.test.d.ts +0 -2
  197. package/dist/infra/lib/memory/MemoryStorage.test.d.ts.map +0 -1
  198. package/dist/infra/lib/memory/MemoryStorage.test.js +0 -198
  199. package/dist/infra/lib/memory/MemoryStorage.test.js.map +0 -1
  200. package/dist/infra/lib/memory/SessionRAGRetriever.test.d.ts +0 -2
  201. package/dist/infra/lib/memory/SessionRAGRetriever.test.d.ts.map +0 -1
  202. package/dist/infra/lib/memory/SessionRAGRetriever.test.js +0 -180
  203. package/dist/infra/lib/memory/SessionRAGRetriever.test.js.map +0 -1
  204. package/dist/infra/lib/memory/SessionRAGStore.test.d.ts +0 -2
  205. package/dist/infra/lib/memory/SessionRAGStore.test.d.ts.map +0 -1
  206. package/dist/infra/lib/memory/SessionRAGStore.test.js +0 -326
  207. package/dist/infra/lib/memory/SessionRAGStore.test.js.map +0 -1
  208. package/dist/infra/lib/memory/__tests__/InMemoryStorage.test.d.ts +0 -2
  209. package/dist/infra/lib/memory/__tests__/InMemoryStorage.test.d.ts.map +0 -1
  210. package/dist/infra/lib/memory/__tests__/InMemoryStorage.test.js +0 -114
  211. package/dist/infra/lib/memory/__tests__/InMemoryStorage.test.js.map +0 -1
  212. package/dist/infra/lib/memory/__tests__/ReflectionStore.test.d.ts +0 -2
  213. package/dist/infra/lib/memory/__tests__/ReflectionStore.test.d.ts.map +0 -1
  214. package/dist/infra/lib/memory/__tests__/ReflectionStore.test.js +0 -196
  215. package/dist/infra/lib/memory/__tests__/ReflectionStore.test.js.map +0 -1
  216. package/dist/infra/lib/memory/index.test.d.ts +0 -2
  217. package/dist/infra/lib/memory/index.test.d.ts.map +0 -1
  218. package/dist/infra/lib/memory/index.test.js +0 -23
  219. package/dist/infra/lib/memory/index.test.js.map +0 -1
  220. package/dist/infra/lib/telemetry/SkillTelemetry.test.d.ts +0 -2
  221. package/dist/infra/lib/telemetry/SkillTelemetry.test.d.ts.map +0 -1
  222. package/dist/infra/lib/telemetry/SkillTelemetry.test.js +0 -124
  223. package/dist/infra/lib/telemetry/SkillTelemetry.test.js.map +0 -1
  224. package/dist/infra/lib/ui-ux/Bm25Engine.test.d.ts +0 -2
  225. package/dist/infra/lib/ui-ux/Bm25Engine.test.d.ts.map +0 -1
  226. package/dist/infra/lib/ui-ux/Bm25Engine.test.js +0 -159
  227. package/dist/infra/lib/ui-ux/Bm25Engine.test.js.map +0 -1
  228. package/dist/infra/lib/ui-ux/CsvDataLoader.test.d.ts +0 -2
  229. package/dist/infra/lib/ui-ux/CsvDataLoader.test.d.ts.map +0 -1
  230. package/dist/infra/lib/ui-ux/CsvDataLoader.test.js +0 -141
  231. package/dist/infra/lib/ui-ux/CsvDataLoader.test.js.map +0 -1
  232. package/dist/infra/lib/ui-ux/DesignSystemGenerator.test.d.ts +0 -2
  233. package/dist/infra/lib/ui-ux/DesignSystemGenerator.test.d.ts.map +0 -1
  234. package/dist/infra/lib/ui-ux/DesignSystemGenerator.test.js +0 -370
  235. package/dist/infra/lib/ui-ux/DesignSystemGenerator.test.js.map +0 -1
  236. package/dist/infra/lib/ui-ux/SearchService.test.d.ts +0 -2
  237. package/dist/infra/lib/ui-ux/SearchService.test.d.ts.map +0 -1
  238. package/dist/infra/lib/ui-ux/SearchService.test.js +0 -215
  239. package/dist/infra/lib/ui-ux/SearchService.test.js.map +0 -1
  240. package/dist/test-helpers/index.d.ts +0 -36
  241. package/dist/test-helpers/index.d.ts.map +0 -1
  242. package/dist/test-helpers/index.js +0 -85
  243. package/dist/test-helpers/index.js.map +0 -1
  244. package/dist/test-helpers/index.test.d.ts +0 -2
  245. package/dist/test-helpers/index.test.d.ts.map +0 -1
  246. package/dist/test-helpers/index.test.js +0 -92
  247. package/dist/test-helpers/index.test.js.map +0 -1
  248. package/dist/tests/curated-release-notes.test.d.ts +0 -2
  249. package/dist/tests/curated-release-notes.test.d.ts.map +0 -1
  250. package/dist/tests/curated-release-notes.test.js +0 -160
  251. package/dist/tests/curated-release-notes.test.js.map +0 -1
  252. package/dist/tools/convention/analyzeComplexity.test.d.ts +0 -2
  253. package/dist/tools/convention/analyzeComplexity.test.d.ts.map +0 -1
  254. package/dist/tools/convention/analyzeComplexity.test.js +0 -207
  255. package/dist/tools/convention/analyzeComplexity.test.js.map +0 -1
  256. package/dist/tools/convention/validateCodeQuality.test.d.ts +0 -2
  257. package/dist/tools/convention/validateCodeQuality.test.d.ts.map +0 -1
  258. package/dist/tools/convention/validateCodeQuality.test.js +0 -230
  259. package/dist/tools/convention/validateCodeQuality.test.js.map +0 -1
  260. package/dist/tools/loop/validateLoopDefinition.test.d.ts +0 -14
  261. package/dist/tools/loop/validateLoopDefinition.test.d.ts.map +0 -1
  262. package/dist/tools/loop/validateLoopDefinition.test.js +0 -229
  263. package/dist/tools/loop/validateLoopDefinition.test.js.map +0 -1
  264. package/dist/tools/spec/executionPacket.test.d.ts +0 -2
  265. package/dist/tools/spec/executionPacket.test.d.ts.map +0 -1
  266. package/dist/tools/spec/executionPacket.test.js +0 -374
  267. package/dist/tools/spec/executionPacket.test.js.map +0 -1
  268. package/dist/tools/spec/prdParser.test.d.ts +0 -6
  269. package/dist/tools/spec/prdParser.test.d.ts.map +0 -1
  270. package/dist/tools/spec/prdParser.test.js +0 -332
  271. package/dist/tools/spec/prdParser.test.js.map +0 -1
  272. package/dist/tools/spec/specGenerator.test.d.ts +0 -2
  273. package/dist/tools/spec/specGenerator.test.d.ts.map +0 -1
  274. package/dist/tools/spec/specGenerator.test.js +0 -130
  275. package/dist/tools/spec/specGenerator.test.js.map +0 -1
  276. package/dist/tools/spec/traceabilityMatrix.path-resolution.test.d.ts +0 -10
  277. package/dist/tools/spec/traceabilityMatrix.path-resolution.test.d.ts.map +0 -1
  278. package/dist/tools/spec/traceabilityMatrix.path-resolution.test.js +0 -120
  279. package/dist/tools/spec/traceabilityMatrix.path-resolution.test.js.map +0 -1
  280. package/dist/tools/spec/traceabilityMatrix.test.d.ts +0 -6
  281. package/dist/tools/spec/traceabilityMatrix.test.d.ts.map +0 -1
  282. package/dist/tools/spec/traceabilityMatrix.test.js +0 -359
  283. package/dist/tools/spec/traceabilityMatrix.test.js.map +0 -1
  284. package/hooks/scripts/__tests__/.vibe/command-log.txt +0 -3
  285. package/hooks/scripts/__tests__/auto-test-debounce.test.js +0 -145
  286. package/hooks/scripts/__tests__/clone-behaviors.test.js +0 -152
  287. package/hooks/scripts/__tests__/clone-merge-responsive.test.js +0 -106
  288. package/hooks/scripts/__tests__/code-check-detectors.test.js +0 -213
  289. package/hooks/scripts/__tests__/code-check-memory-write.test.js +0 -81
  290. package/hooks/scripts/__tests__/codex-hook-adapter.test.js +0 -64
  291. package/hooks/scripts/__tests__/curation-index.test.js +0 -157
  292. package/hooks/scripts/__tests__/dispatcher-inprocess.test.js +0 -99
  293. package/hooks/scripts/__tests__/figma-extract.test.js +0 -338
  294. package/hooks/scripts/__tests__/hook-payload.test.js +0 -29
  295. package/hooks/scripts/__tests__/llm-orchestrate-antigravity.test.js +0 -66
  296. package/hooks/scripts/__tests__/loop-ledger.test.js +0 -321
  297. package/hooks/scripts/__tests__/post-edit-dispatcher.test.js +0 -139
  298. package/hooks/scripts/__tests__/pre-tool-guard.test.js +0 -523
  299. package/hooks/scripts/__tests__/recipe-extractor.test.js +0 -244
  300. package/hooks/scripts/__tests__/run-ledger-verify-required.test.js +0 -151
  301. package/hooks/scripts/__tests__/run-ledger.test.js +0 -481
  302. package/hooks/scripts/__tests__/scope-from-spec.test.js +0 -215
  303. package/hooks/scripts/__tests__/sentinel-guard.test.js +0 -263
  304. package/hooks/scripts/__tests__/step-counter.test.js +0 -459
  305. package/hooks/scripts/__tests__/utils-npm-root.test.js +0 -99
@@ -178,10 +178,11 @@ Phase 4: /vibe.verify → 검증
178
178
  스킬 **이름과 인자**가 계약이고, 그것을 실제 호출로 바꾸는 것은 각 하네스의 몫이다.
179
179
 
180
180
  각 phase 종료 후 JUDGE 단계:
181
- - 게이트 통과 (P1=0 ∧ verifyPassed) → 루프 종료, Phase 5 보고
181
+ - 게이트 통과 (**측정된** P1=0 ∧ verifyPassed) → 루프 종료, Phase 5 보고. 판정된 P1(리뷰어 findings)은 단독으로 게이트를 막지 않는다 — SSOT: `vibe/rules/loop-contract.md` Judge 권한 경계
182
182
  - 게이트 미통과 → RECORD(run-ledger + loop-history.jsonl) 후 다음 ANCHOR로
183
183
  - stuck(연속 2회 동일 findings 해시) → **어느 automationLevel 에서도 루프를 종료한다.** `confirm`이면 사용자 질문, `autonomous`이면 질문 없이 TODO 기록 후 다음 독립 단위로. 미달을 완료로 기록하지 않는다 (SSOT: `vibe/rules/loop-contract.md` stuck 절)
184
184
  - max_iterations(기본 10) 도달 → 잔여를 인박스로 이월
185
+ - **실행 실패(error)** — 스킬 미설치·도구 부재·파일 없음·명령 비정상 종료는 stuck 이 아니다(해시 비교로 안 잡힌다). 같은 방식으로 재시도하지 않고 루프를 종료한다: `confirm` 이면 원인을 제시하고 조치/건너뛰기/중단을 묻고, `autonomous` 이면 `loop-ledger.js inbox <name> fail "<원인>"` 기록 후 다음 독립 단위로. 실행 실패도 완료로 기록하지 않는다 (SSOT: `vibe/rules/loop-contract.md` 실행 실패 절)
185
186
 
186
187
  ### Phase 5: 종료 보고
187
188
 
@@ -6,7 +6,8 @@
6
6
  ## Phase 4: Compile Gate
7
7
 
8
8
  ```
9
- No round cap. Loop until compile succeeds (or stuck → ask user).
9
+ No round cap. Loop until compile succeeds (or stuck → end loop; automationLevel decides
10
+ whether the user is asked — see Termination below).
10
11
 
11
12
  0. Capture baseline (before Phase 3): record existing tsc + build errors
12
13
  → Phase 4 only fixes NEW errors
@@ -33,7 +34,8 @@ Termination:
33
34
  **⛔ Skipping Phase 5 makes the entire clone "incomplete".**
34
35
 
35
36
  ```
36
- No round cap. Loop until P1=0 (or stuck → ask user).
37
+ No round cap. Loop until P1=0 (or stuck → end loop; automationLevel decides whether the
38
+ user is asked — see Termination below).
37
39
  Infrastructure: src/infra/lib/browser/ (Puppeteer + CDP) — same as figma Phase 6.
38
40
 
39
41
  1. Render scaffolded page in dev server at matching viewport
@@ -52,7 +54,8 @@ Narrowing scope:
52
54
  Termination:
53
55
  ✅ P1=0 AND no new findings → complete
54
56
  ⚠️ Stuck: same findings → ask user (resolve / proceed / abort)
55
- automationLevel: autonomous → on stuck, record TODO without prompting and complete
57
+ automationLevel: autonomous → on stuck, record TODO without prompting and end the loop
58
+ as `stuck` — never record unresolved P1 as complete (SSOT: vibe/rules/loop-contract.md)
56
59
 
57
60
  Responsive: after MO verification → change viewport → repeat against PC screenshot
58
61
  Post-merge (Phase 3C): re-run at BOTH viewports (375×812 vs mo/screenshot.png,
@@ -69,6 +69,9 @@ node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/tools/index
69
69
  `status: paused` 루프는 즉시 종료. 실행 순서는 **전부 의무**이며 생략 불가:
70
70
 
71
71
  ```
72
+ 0. ANCHOR node "$HOOKS_DIR/loop-ledger.js" anchor [feature]
73
+ → missing[] 이 비어 있지 않으면 없는 아티팩트를 기억으로 메우지 않는다.
74
+ 재고정 실패를 인박스에 남기고 종료한다.
72
75
  1. 검증 validateLoopDefinition 통과 확인 (위 design 3의 명령) — 실패 시 인박스에 기록 후 종료
73
76
  2. 시작 기록 node "$HOOKS_DIR/loop-ledger.js" start <name>
74
77
  3. DISCOVER 정의의 discover 지시 실행 → 일거리 목록 산출
@@ -84,10 +87,10 @@ node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/tools/index
84
87
  · tests: 정의의 test_command 실행 → exit 0 만 성공
85
88
  · none: 판정 생략(보고만). "코드를 보니 잘 된 것 같다"는 판정이 아니다.
86
89
  7. 종료 기록 node "$HOOKS_DIR/loop-ledger.js" end <name> <ok|fail|stuck> "<한 줄 요약>"
87
- 8. 인박스 $INBOX 상단에 결과 블록 prepend:
88
- ## <name> <ISO 시각> <ok|fail|stuck>
89
- - 발견: N건 / 처리: M건 / 검증: <기준과 결과>
90
- - 리뷰 필요: <항목들 없으면 "없음">
90
+ 8. 인박스 node "$HOOKS_DIR/loop-ledger.js" inbox <name> <ok|fail|stuck> \
91
+ "발견: N건 / 처리: M건 / 검증: <기준과 결과>" \
92
+ "리뷰 필요: <항목들 없으면 없음>"
93
+ 블록 형식과 최신순 정렬은 명령이 보장한다. 손으로 마크다운을 쓰지 않는다.
91
94
  ```
92
95
 
93
96
  **금지**: `git push`, `gh pr merge`, `npm publish`, 버전 범프, 릴리즈 — 루프는 커밋까지만 가며(auto-commit verify 게이트 통과 시), 그 이상은 인박스를 본 사람이 한다.
@@ -79,7 +79,11 @@ user-invocable: true
79
79
 
80
80
  - **P1 = 0 means MERGE READY** — mergeable even with remaining P2/P3
81
81
  - **P1 = 0 after auto-fix means DONE** — record P2 auto-fix failures as TODO and stop
82
- - **Final P1 list unchanged after Review Debate → DONE** — no new findings = converged
82
+ - **P1 = 0 AND final P1 list unchanged after Review Debate → DONE** — converged
83
+ - **P1 > 0 AND final P1 list unchanged → STUCK, not DONE** — 같은 발견이 2회 연속이면
84
+ 루프는 종료하되 **완료로 기록하지 않는다**. `confirm` 이면 사용자에게 묻고, `autonomous`
85
+ 이면 TODO 로 남긴다 (SSOT: `vibe/rules/loop-contract.md` stuck 절). "목록이 안 바뀌었으니
86
+ 수렴했다" 는 남은 P1 을 완료로 포장하는 것이다
83
87
 
84
88
  ### Anti-Patterns (FORBIDDEN)
85
89
 
@@ -34,7 +34,7 @@ Scenario verification failed
34
34
 
35
35
  **Stakes 프로파일 (SSOT: `vibe/rules/loop-contract.md` Stakes 표):**
36
36
  - `demo`/`prototype` → max_iterations 1, 리뷰 1패스, **검증 스크립트 신규 생성 금지** — 검증은 기존 테스트 러너·브라우저 게이트만 사용한다. 새 verify_*.py / 검증 전용 스크립트 파일을 만들지 않는다.
37
- - JUDGE 검증 산출물 절제 (모든 stakes): 이번 feature 신규 검증 코드 바이트 합이 신규 구현 코드 바이트 합을 초과하면 (`git diff --numstat` 기준) P2 경고를 run-ledger 기록한다. advisory — 게이트 통과 여부는 불변.
37
+ - JUDGE 검증 산출물 절제 (모든 stakes): 이번 feature 신규 검증 코드 수가 신규 구현 코드 수를 초과하면 (`git diff --numstat` 기준) **최종 보고에 P2 경고 1줄**을 적는다. run-ledger 에는 적재하지 않는다 (경고 필드 없음). advisory — 게이트 통과 여부는 불변.
38
38
 
39
39
  ---
40
40
 
@@ -173,7 +173,7 @@ node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/tools/index
173
173
 
174
174
  > Default SPEC path is `.vibe/specs/<feature>.md`. `status === 'empty'` must be treated as failed/not-applicable — never as 100% pass.
175
175
 
176
- JUDGE: `coveragePercent === 100` → 루프 종료. stuck(연속 2회 동일 커버리지) → automationLevel confirm이면 사용자 질문; autonomous이면 TODO + done.
176
+ JUDGE: `coveragePercent === 100` → 루프 종료. stuck(연속 2회 동일 발견 해시 — `loop-ledger.js check-stuck`; 커버리지 수치가 아니라 발견으로 판정한다) → **어느 automationLevel 에서도 루프를 종료한다**; confirm이면 사용자 질문, autonomous이면 TODO 기록 후 다음 독립 단위로. 미달 커버리지를 완료로 기록하지 않는다 (SSOT: `vibe/rules/loop-contract.md`).
177
177
 
178
178
  ---
179
179
 
@@ -81,7 +81,7 @@ All reference documents are stored globally and specified in `.vibe/config.json`
81
81
  - **DRY**: Don't Repeat Yourself
82
82
  - **SRP**: Single Responsibility Principle
83
83
  - **YAGNI**: You Aren't Gonna Need It
84
- - **Functions ≤30 lines** (recommended), ≤50 lines (allowed)
84
+ - **Functions ≤50 lines** (SSOT: `CLAUDE.md` Complexity Limits)
85
85
  - **Cyclomatic Complexity ≤10**
86
86
  - **Cognitive Complexity ≤15**
87
87
 
@@ -21,15 +21,35 @@
21
21
  Model Judge(advisory-only): 발견을 제안하지만 완료 권한 없음
22
22
  Human Taste(release-only): UX·브랜드·제품 감각을 판단하지만 루프 완료 권한 없음
23
23
  RECORD run-ledger + `.vibe/runs/{run-id}/evidence.json` + loop-history.jsonl
24
- → 종료(EXIT): 게이트 전부 통과 │ stuck │ max_iterations │ 예산 상한
24
+ → 종료(EXIT): 게이트 전부 통과 │ stuck │ max_iterations │ 예산 상한 │ 실행 실패(error)
25
25
  ```
26
26
 
27
27
  ### ANCHOR가 컨텍스트 오염 방어인 이유
28
28
  루프 상태는 컨텍스트가 아니라 디스크에 산다. 매 회전이 아티팩트에서 다시 시작하므로 컨텍스트가 오염되거나 compact로 소실돼도 루프는 깨지지 않으며, 회전마다 fresh 컨텍스트(서브에이전트)로 돌려도 된다.
29
29
 
30
+ **재고정은 명령으로 한다** — 모델의 기억이 아니라 디스크가 답한다:
31
+
32
+ ```bash
33
+ node "$HOOKS_DIR/loop-ledger.js" anchor [feature]
34
+ # → { feature, spec, scope, ledger, latestInbox, missing[] }
35
+ ```
36
+
37
+ `missing` 이 비어 있지 않으면 그 회전은 재고정에 실패한 것이다 — 없는 아티팩트를 기억으로 메우지 않는다. JUDGE·RECORD·stuck 이 전부 명령으로 판정되는데 ANCHOR만 산문 지시로 남아 있으면, 정작 오염 방어의 근거가 되는 단계가 가장 약해진다.
38
+
30
39
  ### Judge 권한 경계
31
40
  종료 권한은 테스트 exit code·run-ledger·RTM 같은 **결정론적 Judge**에만 있다. Model Judge는 누락·모순·위험을 발견하는 보조 수단이며, 발견을 테스트나 관측 가능한 기준으로 내리기 전에는 차단 근거가 아니다. Human Taste는 공개·배포 시점의 사람 판단으로 남고 루프의 완료 상태를 변경하지 않는다.
32
41
 
42
+ #### P1 은 출처가 둘이다 — exit 기준은 이를 구분한다
43
+
44
+ "P1" 이 가리키는 것이 두 가지이고, 위 권한 경계는 그중 하나에만 적용된다.
45
+
46
+ | 출처 | 예 | 성격 | exit 게이트 |
47
+ |---|---|---|---|
48
+ | **측정된 P1** | clone Phase 5 `pixelmatch diffRatio > 0.05`, computed CSS delta > 2px, contract drift, 테스트 실패 | 결정론 | **차단한다** — 게이트 통과 = 측정 P1 0 |
49
+ | **판정된 P1** | `vibe.review` 리뷰어 findings | Model Judge | **단독으로 차단하지 않는다** — 테스트·관측 기준으로 내려야 게이트가 된다 |
50
+
51
+ 판정된 P1 이 남았는데 내릴 기준이 없으면, 그것은 게이트 실패가 아니라 **인박스로 가는 리뷰 항목**이다. 동일한 판정 P1 이 2회 연속 반복되면 stuck 이며 — 완료가 아니다 (아래 stuck 절).
52
+
33
53
  ### stuck (결정론)
34
54
  연속 2회 회전의 발견(discover/findings) 해시가 동일 → **그 루프는 종료한다** (`loop-ledger.js check-stuck`이 판정·기록). "다시 해보면 될 것 같다"는 모델 판단으로 무시 금지.
35
55
 
@@ -42,12 +62,25 @@
42
62
 
43
63
  > `autonomous` 의 "계속" 은 **stuck 난 루프를 더 돌린다는 뜻이 아니다** — 2회 연속 동일 발견은 정의상 재시도가 무의미하다. 같은 목표를 붙잡지 않고 다음 단위로 넘어간다는 뜻이며, 미달은 TODO/인박스에 남는다. 미달 상태를 **완료로 기록하지 않는다.**
44
64
 
65
+ ### 실행 실패 (error) — stuck 과 다른 종료 사유
66
+
67
+ stuck 은 **같은 발견이 반복되는** 상태다. 스킬이 로드되지 않거나, 도구가 없거나, 파일이 없거나, 명령이 비정상 종료하는 것은 stuck 이 아니라 **실행 실패**이며 해시 비교로는 잡히지 않는다. 재시도 대상도 아니다 — 환경이 바뀌지 않는 한 결과가 같다.
68
+
69
+ | | 루프 | 사람에게 질문 | 그 다음 |
70
+ |---|---|---|---|
71
+ | `confirm` | 종료 | **한다** (원인 제시 + 조치 요청 / 건너뛰기 / 중단) | 사용자 응답에 따름 |
72
+ | `autonomous` | 종료 | 하지 않음 | 인박스에 원인 기록 후 **다음 독립 단위로** |
73
+
74
+ - 실패한 단계를 **같은 방식으로 재시도하지 않는다.** 재시도가 의미 있으려면 무엇이 달라지는지 말할 수 있어야 한다 (`vibe.review` 의 escalation ladder 가 그 예 — 재시도 1회 → 다른 하네스 1회 → TODO).
75
+ - 실행 실패도 **완료가 아니다.** stuck 과 동일하게, 미달 상태를 완료로 기록하지 않는다.
76
+ - 원인은 인박스에 남긴다: `loop-ledger.js inbox <name> fail "<원인 한 줄>"`.
77
+
45
78
  ## 파라미터 (기본값)
46
79
 
47
80
  | 파라미터 | 기본 | 의미 |
48
81
  |---|---|---|
49
82
  | `max_iterations` | 10 | 회전 상한. 도달 시 잔여를 인박스로 이월 |
50
- | `exit` | 게이트 통과 (P1=0 ∧ verifyPassed) | 종료 기준. coverage 100% 등으로 상향 가능 |
83
+ | `exit` | 게이트 통과 (**측정된** P1=0 ∧ verifyPassed) | 종료 기준. coverage 100% 등으로 상향 가능. 판정된 P1 은 위 Judge 권한 경계 표를 따른다 |
51
84
  | `--interactive` | off | 단계별 확인 모드 (회전마다 사람 승인 — 과거의 기본값) |
52
85
  | `--max-iter N` | — | 회전 상한 명시 (N=1이면 1회 시도) |
53
86
  | `automationLevel` | `confirm` | `confirm`(SPEC·stuck에서 질문) / `autonomous`(질문 없이 TODO 기록 후 다음 단위로, 비대화형) — `.vibe/config.json`. **어느 값에서도 stuck 은 루프를 종료한다** (위 stuck 절) |
@@ -69,7 +102,11 @@
69
102
 
70
103
  ### JUDGE 검증 산출물 절제 (모든 stakes 공통)
71
104
 
72
- JUDGE는 이번 feature의 **신규 생성 파일** 기준으로 검증 코드 총량(테스트·검증 스크립트)과 구현 코드 총량을 `git diff --numstat` 비교한다. 검증 코드 바이트 합 > 구현 코드 바이트 합이면 **P2 경고**를 run-ledger 에 기록한다 (restraint 원칙의 프로세스 적용). 경고는 advisory — 게이트 통과 여부를 바꾸지 않는다.
105
+ 검증은 실패 비용보다 싸야 한다 검증 코드가 구현 코드보다 커지면 루프는 남는 장사가 아니다.
106
+
107
+ JUDGE는 이번 feature의 **신규 생성 파일** 기준으로 검증 코드 총량(테스트·검증 스크립트)과 구현 코드 총량을 `git diff --numstat` 로 비교하고, 검증 코드 줄 수가 구현 코드 줄 수를 넘으면 **최종 보고에 P2 경고 1줄**을 적는다 (restraint 원칙의 프로세스 적용).
108
+
109
+ > ⚠️ 이 경고는 **보고용이며 어디에도 적재되지 않는다.** run-ledger 스키마(`runId`·`runStarted`·`runFeature`·`verifyPassed`·`verifyAt`·`stopWarned`·`verifyRequired`·`verifyRequiredReason`)에는 경고 필드가 없다 — 기록을 지시하면 갈 곳 없는 지시가 된다. 게이트 통과 여부를 바꾸지 않는다.
73
110
 
74
111
  ## 금지 (루프 권한 경계)
75
112
 
@@ -28,7 +28,7 @@ const typeSafety = {
28
28
  ```typescript
29
29
  const codeStructure = {
30
30
  singleResponsibility: true, // ✅ Single Responsibility Principle
31
- functionUnder30Lines: true, // ✅ Functions ≤30 lines (recommended), 50 allowed
31
+ functionUnder50Lines: true, // ✅ Functions ≤50 lines
32
32
  maxNesting3Levels: true, // ✅ Max nesting 3 levels
33
33
  cyclomaticComplexity: 10, // ✅ Cyclomatic complexity ≤ 10
34
34
  cognitiveComplexity: 15, // ✅ Cognitive complexity ≤ 15
@@ -171,7 +171,7 @@ const bundleOptimization = {
171
171
 
172
172
  ```text
173
173
  [ ] Follow Single Responsibility Principle
174
- [ ] Keep function length ≤30 lines (max 50)
174
+ [ ] Keep function length ≤50 lines
175
175
  [ ] Nesting depth ≤3 levels
176
176
  [ ] Extract magic numbers to constants
177
177
  [ ] Ensure type safety
@@ -266,7 +266,7 @@ npm run format:check
266
266
  ```text
267
267
  ✅ Only modified requested scope?
268
268
  ✅ No any types?
269
- ✅ Functions ≤30 lines? (max 50)
269
+ ✅ Functions ≤50 lines?
270
270
  ✅ Nesting ≤3 levels?
271
271
  ✅ Error handling implemented?
272
272
  ✅ Magic numbers extracted to constants?
@@ -99,7 +99,7 @@ All reference documents are stored globally and specified in `.vibe/config.json`
99
99
  - **DRY**: Don't Repeat Yourself
100
100
  - **SRP**: Single Responsibility Principle
101
101
  - **YAGNI**: You Aren't Gonna Need It
102
- - **Functions ≤30 lines** (recommended), ≤50 lines (allowed)
102
+ - **Functions ≤50 lines** (SSOT: `CLAUDE.md` Complexity Limits)
103
103
  - **Cyclomatic Complexity ≤10**
104
104
  - **Cognitive Complexity ≤15**
105
105
 
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=agent-model-sync.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"agent-model-sync.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/agent-model-sync.test.ts"],"names":[],"mappings":""}
@@ -1,71 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import { globSync } from 'glob';
5
- /**
6
- * 모델 할당 SSOT 가드 — agents/(**)/*.md 의 `## Model` 섹션이
7
- * src/cli/postinstall/constants.ts > CLAUDE_MODEL_MAPPING 과 일치하는지 검증한다.
8
- *
9
- * 이 매핑이 유일 SSOT 다(postinstall 이 이 값을 설치 시 frontmatter `model:` 로 주입).
10
- * 문서 본문에 손으로 박은 모델명이 드리프트하면 CI 에서 여기서 실패한다.
11
- * 자동 정렬: `npm run sync:agent-models`.
12
- *
13
- * NOTE: 재작성 로직은 scripts/sync-agent-models.ts 에 있지만, tsconfig rootDir=src
14
- * 때문에 여기서 import 하지 않고 불변식을 순수 fs 로 독립 검증한다(동일 SSOT 참조).
15
- */
16
- const ROOT = path.resolve(__dirname, '..', '..');
17
- const AGENTS_DIR = path.join(ROOT, 'agents');
18
- const CONSTANTS_FILE = path.join(ROOT, 'src', 'cli', 'postinstall', 'constants.ts');
19
- const DISPLAY = {
20
- haiku: 'Haiku',
21
- sonnet: 'Sonnet',
22
- opus: 'Opus',
23
- inherit: 'Inherit',
24
- };
25
- function loadModelMapping() {
26
- const content = fs.readFileSync(CONSTANTS_FILE, 'utf-8');
27
- const block = content.match(/CLAUDE_MODEL_MAPPING[^{]*\{([\s\S]*?)\n\};/);
28
- if (!block)
29
- throw new Error('CLAUDE_MODEL_MAPPING not found in constants.ts');
30
- const map = {};
31
- for (const m of block[1].matchAll(/'([\w-]+)':\s*'([\w-]+)'/g))
32
- map[m[1]] = m[2];
33
- return map;
34
- }
35
- /** `## Model` 섹션의 첫 모델 라인 (`**Model** ...`) 을 반환 */
36
- function firstModelLine(content) {
37
- const lines = content.split('\n');
38
- const h = lines.findIndex((l) => /^##\s+Model\s*$/.test(l));
39
- if (h === -1)
40
- return null;
41
- for (let i = h + 1; i < lines.length && !/^##\s/.test(lines[i]); i++) {
42
- if (/^\s*\*\*(Haiku|Sonnet|Opus|Inherit)/.test(lines[i]))
43
- return lines[i].trim();
44
- }
45
- return null;
46
- }
47
- describe('agent model SSOT (CLAUDE_MODEL_MAPPING)', () => {
48
- const map = loadModelMapping();
49
- const files = globSync('**/*.md', { cwd: AGENTS_DIR }).sort();
50
- it('discovers agent files', () => {
51
- expect(files.length).toBeGreaterThan(0);
52
- });
53
- for (const rel of files) {
54
- const name = path.basename(rel, '.md');
55
- it(`${rel} has a CLAUDE_MODEL_MAPPING entry`, () => {
56
- expect(map[name], `no model mapping for "${name}"`).toBeDefined();
57
- });
58
- it(`${rel} '## Model' matches the mapped tier (no drift, no version)`, () => {
59
- const tier = map[name];
60
- if (!tier)
61
- return; // covered by the entry test above
62
- const content = fs.readFileSync(path.join(AGENTS_DIR, rel), 'utf-8');
63
- const line = firstModelLine(content);
64
- expect(line, `missing '## Model' section in ${rel}`).not.toBeNull();
65
- // 매핑 tier 와 표기가 일치해야 하고, 버전 숫자(예: "Haiku 4.5")가 없어야 한다.
66
- expect(line).toMatch(new RegExp(`^\\*\\*${DISPLAY[tier]}\\*\\*`));
67
- expect(line, `version-pinned model name in ${rel}`).not.toMatch(/\*\*(Haiku|Sonnet|Opus)\s+[\d.]/);
68
- });
69
- }
70
- });
71
- //# sourceMappingURL=agent-model-sync.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"agent-model-sync.test.js","sourceRoot":"","sources":["../../src/__tests__/agent-model-sync.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=architecture.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"architecture.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/architecture.test.ts"],"names":[],"mappings":""}
@@ -1,207 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import { globSync } from 'glob';
5
- const SRC_DIR = path.resolve(__dirname, '..');
6
- /** Extract all static and dynamic import paths from a TypeScript source file */
7
- function extractImports(filePath) {
8
- const content = fs.readFileSync(filePath, 'utf-8');
9
- const results = [];
10
- const staticRegex = /(?:import|export)\s+(?:(?:type\s+)?(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)(?:\s*,\s*(?:\{[^}]*\}|\*\s+as\s+\w+|\w+))*\s+from\s+)?['"]([^'"]+)['"]/g;
11
- const dynamicRegex = /import\(\s*['"]([^'"]+)['"]\s*\)/g;
12
- let match;
13
- while ((match = staticRegex.exec(content)) !== null) {
14
- results.push(match[1]);
15
- }
16
- while ((match = dynamicRegex.exec(content)) !== null) {
17
- results.push(match[1]);
18
- }
19
- return results.filter((p) => p.startsWith('.') || p.startsWith('/'));
20
- }
21
- /**
22
- * Check whether every import of a given path in a file is type-only.
23
- * Returns true only if all matching import statements use `import type`.
24
- */
25
- function importsAreTypeOnly(filePath, importPath) {
26
- const content = fs.readFileSync(filePath, 'utf-8');
27
- const lines = content.split('\n');
28
- for (const line of lines) {
29
- if (!line.includes(importPath))
30
- continue;
31
- // Must match an import statement containing this path
32
- if (!/(?:import|export)/.test(line))
33
- continue;
34
- // If the line is NOT a type-only import, return false
35
- if (/^\s*import\s+(?!type[\s{])/.test(line)) {
36
- return false;
37
- }
38
- }
39
- return true;
40
- }
41
- /** Resolve a relative import path to a layer category */
42
- function categorizeImport(fromFile, importPath) {
43
- const fromDir = path.dirname(fromFile);
44
- // Strip .js extension for resolution
45
- const cleanImport = importPath.replace(/\.js$/, '');
46
- const resolved = path.resolve(fromDir, cleanImport);
47
- const relative = path.relative(SRC_DIR, resolved).replace(/\\/g, '/');
48
- if (relative.startsWith('cli/'))
49
- return 'cli';
50
- if (relative.startsWith('tools/'))
51
- return 'tools';
52
- if (relative.startsWith('infra/orchestrator/') || relative.startsWith('infra/lib/orchestrator'))
53
- return 'infra/orchestrator';
54
- if (relative.startsWith('infra/lib/') || relative.startsWith('infra/'))
55
- return 'infra/lib';
56
- if (relative.startsWith('test-helpers/'))
57
- return 'test-helpers';
58
- return null;
59
- }
60
- /** Collect all non-test .ts files in a layer directory (if it exists) */
61
- function filesInLayer(layerRelPath) {
62
- const layerDir = path.join(SRC_DIR, layerRelPath);
63
- if (!fs.existsSync(layerDir))
64
- return [];
65
- return globSync('**/*.ts', { cwd: layerDir, absolute: true }).filter((f) => !f.includes('__tests__') && !f.endsWith('.test.ts') && !f.endsWith('.spec.ts'));
66
- }
67
- /** Build a layer-level dependency graph from all source files */
68
- function buildLayerGraph() {
69
- const layers = ['cli', 'tools', 'infra/lib', 'infra/orchestrator', 'test-helpers'];
70
- const graph = new Map();
71
- for (const layer of layers) {
72
- graph.set(layer, new Set());
73
- }
74
- const layerDirMap = {
75
- 'cli': 'cli',
76
- 'tools': 'tools',
77
- 'infra/lib': 'infra/lib',
78
- 'infra/orchestrator': 'infra/orchestrator',
79
- 'test-helpers': 'test-helpers',
80
- };
81
- for (const [layer, relDir] of Object.entries(layerDirMap)) {
82
- const files = filesInLayer(relDir);
83
- for (const file of files) {
84
- const imports = extractImports(file);
85
- for (const imp of imports) {
86
- const target = categorizeImport(file, imp);
87
- if (target === null || target === layer)
88
- continue;
89
- // infra/lib may use type-only imports from cli/types — skip that edge
90
- if (layer === 'infra/lib' && target === 'cli') {
91
- const resolved = path.resolve(path.dirname(file), imp.replace(/\.js$/, ''));
92
- const relative = path.relative(SRC_DIR, resolved).replace(/\\/g, '/');
93
- if (relative.startsWith('cli/types') && importsAreTypeOnly(file, imp)) {
94
- continue;
95
- }
96
- }
97
- graph.get(layer).add(target);
98
- }
99
- }
100
- }
101
- return graph;
102
- }
103
- /** Detect cycles in a directed graph using DFS; returns cycle path or null */
104
- function findCycle(graph) {
105
- const visited = new Set();
106
- const stack = new Set();
107
- const stackArr = [];
108
- function dfs(node) {
109
- visited.add(node);
110
- stack.add(node);
111
- stackArr.push(node);
112
- for (const neighbor of graph.get(node) ?? []) {
113
- if (!visited.has(neighbor)) {
114
- const cycle = dfs(neighbor);
115
- if (cycle)
116
- return cycle;
117
- }
118
- else if (stack.has(neighbor)) {
119
- const cycleStart = stackArr.indexOf(neighbor);
120
- return [...stackArr.slice(cycleStart), neighbor];
121
- }
122
- }
123
- stack.delete(node);
124
- stackArr.pop();
125
- return null;
126
- }
127
- for (const node of graph.keys()) {
128
- if (!visited.has(node)) {
129
- const cycle = dfs(node);
130
- if (cycle)
131
- return cycle;
132
- }
133
- }
134
- return null;
135
- }
136
- // ---------------------------------------------------------------------------
137
- // Helpers for violation collection
138
- // ---------------------------------------------------------------------------
139
- function collectViolations(layerRelPath, forbiddenLayer) {
140
- const violations = [];
141
- const files = filesInLayer(layerRelPath);
142
- for (const file of files) {
143
- const imports = extractImports(file);
144
- for (const imp of imports) {
145
- const target = categorizeImport(file, imp);
146
- if (target === forbiddenLayer) {
147
- violations.push(`${path.relative(SRC_DIR, file)} → ${imp}`);
148
- }
149
- }
150
- }
151
- return violations;
152
- }
153
- function collectViolationsExceptTypeOnly(layerRelPath, forbiddenLayer, allowedTypesPath) {
154
- const violations = [];
155
- const files = filesInLayer(layerRelPath);
156
- for (const file of files) {
157
- const imports = extractImports(file);
158
- for (const imp of imports) {
159
- const target = categorizeImport(file, imp);
160
- if (target !== forbiddenLayer)
161
- continue;
162
- // Allow type-only imports from cli/types
163
- const resolved = path.resolve(path.dirname(file), imp.replace(/\.js$/, ''));
164
- const relative = path.relative(SRC_DIR, resolved).replace(/\\/g, '/');
165
- if (relative.startsWith(allowedTypesPath) && importsAreTypeOnly(file, imp)) {
166
- continue;
167
- }
168
- violations.push(`${path.relative(SRC_DIR, file)} → ${imp}`);
169
- }
170
- }
171
- return violations;
172
- }
173
- // ---------------------------------------------------------------------------
174
- // Tests
175
- // ---------------------------------------------------------------------------
176
- describe('Architecture boundary tests', () => {
177
- it('tools/ never imports from cli/', () => {
178
- const violations = collectViolations('tools', 'cli');
179
- expect(violations, `Forbidden imports found:\n${violations.join('\n')}`).toHaveLength(0);
180
- });
181
- it('tools/ never imports from infra/orchestrator/', () => {
182
- const violations = collectViolations('tools', 'infra/orchestrator');
183
- expect(violations, `Forbidden imports found:\n${violations.join('\n')}`).toHaveLength(0);
184
- });
185
- it('infra/lib/ never imports from cli/ (except type-only from cli/types)', () => {
186
- const violations = collectViolationsExceptTypeOnly('infra/lib', 'cli', 'cli/types');
187
- expect(violations, `Forbidden imports found:\n${violations.join('\n')}`).toHaveLength(0);
188
- });
189
- it('infra/lib/ never imports from tools/', () => {
190
- const violations = collectViolations('infra/lib', 'tools');
191
- expect(violations, `Forbidden imports found:\n${violations.join('\n')}`).toHaveLength(0);
192
- });
193
- it('infra/orchestrator/ never imports from cli/', () => {
194
- const violations = collectViolations('infra/orchestrator', 'cli');
195
- expect(violations, `Forbidden imports found:\n${violations.join('\n')}`).toHaveLength(0);
196
- });
197
- it('infra/orchestrator/ never imports from tools/', () => {
198
- const violations = collectViolations('infra/orchestrator', 'tools');
199
- expect(violations, `Forbidden imports found:\n${violations.join('\n')}`).toHaveLength(0);
200
- });
201
- it('no circular module dependencies between layers', () => {
202
- const graph = buildLayerGraph();
203
- const cycle = findCycle(graph);
204
- expect(cycle, `Circular dependency detected: ${cycle?.join(' → ')}`).toBeNull();
205
- });
206
- });
207
- //# sourceMappingURL=architecture.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"architecture.test.js","sourceRoot":"","sources":["../../src/__tests__/architecture.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=skill-namespace.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skill-namespace.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/skill-namespace.test.ts"],"names":[],"mappings":""}
@@ -1,60 +0,0 @@
1
- import { existsSync, readdirSync, readFileSync } from 'node:fs';
2
- import { resolve } from 'node:path';
3
- import { describe, expect, it } from 'vitest';
4
- import { CAPABILITY_SKILLS, GLOBAL_SKILLS, GLOBAL_SKILLS_OPTIONAL, STACK_TO_SKILLS, } from '../cli/postinstall/constants.js';
5
- const SKILLS_DIR = resolve('skills');
6
- const MAX_SKILL_NAME_LENGTH = 32;
7
- function skillNames() {
8
- return readdirSync(SKILLS_DIR, { withFileTypes: true })
9
- .filter((entry) => entry.isDirectory() && existsSync(resolve(SKILLS_DIR, entry.name, 'SKILL.md')))
10
- .map((entry) => {
11
- const content = readFileSync(resolve(SKILLS_DIR, entry.name, 'SKILL.md'), 'utf8');
12
- const name = /^name:\s*(.+)$/m.exec(content)?.[1]?.trim() ?? '';
13
- return { directory: entry.name, name };
14
- });
15
- }
16
- function mappedSkills() {
17
- const stackSkills = Object.values(STACK_TO_SKILLS).flat();
18
- const capabilitySkills = Object.values(CAPABILITY_SKILLS).flat();
19
- return [...GLOBAL_SKILLS, ...GLOBAL_SKILLS_OPTIONAL, ...stackSkills, ...capabilitySkills];
20
- }
21
- describe('skill namespace contract', () => {
22
- it('REQ-skill-namespace-001 namespaces every exposed skill within the length limit', () => {
23
- const exposed = mappedSkills();
24
- expect(exposed.every((name) => name === 'vibe' || name.startsWith('vibe.'))).toBe(true);
25
- expect(exposed.every((name) => name.length <= MAX_SKILL_NAME_LENGTH)).toBe(true);
26
- });
27
- it('keeps directory names and frontmatter names unique and identical', () => {
28
- const skills = skillNames();
29
- const names = skills.map(({ name }) => name);
30
- expect(skills.every(({ directory, name }) => directory === name)).toBe(true);
31
- expect(new Set(names).size).toBe(names.length);
32
- });
33
- it('REQ-skill-namespace-003 namespaces every Vibe-owned install mapping', () => {
34
- expect(mappedSkills().every((name) => name === 'vibe' || name.startsWith('vibe.'))).toBe(true);
35
- });
36
- it('REQ-skill-namespace-002 exposes one public skill for every former wrapper pair', () => {
37
- const names = skillNames().map(({ name }) => name);
38
- const expected = ['spec', 'test', 'contract', 'regress', 'figma', 'clone', 'docs'];
39
- expect(names.some((name) => name.startsWith('vibe.core.'))).toBe(false);
40
- expect(expected.every((name) => names.includes(`vibe.${name}`))).toBe(true);
41
- });
42
- it('bundles internal core behavior without separate discovery entries', () => {
43
- const names = skillNames().map(({ name }) => name);
44
- const run = readFileSync(resolve('skills/vibe.run/SKILL.md'), 'utf8');
45
- expect(['arch-guard', 'exec-plan', 'restraint'].every((name) => !names.includes(name))).toBe(true);
46
- expect(run).toContain('## Bundled internal: arch-guard');
47
- expect(run).toContain('## Bundled internal: exec-plan');
48
- expect(run).toContain('## Bundled internal: restraint');
49
- });
50
- it('REQ-skill-namespace-005 preserves dots in Load skill references', () => {
51
- const validator = readFileSync(resolve('scripts/validate-skill-invocation.ts'), 'utf8');
52
- expect(validator).toContain('[\\w.:-]*');
53
- });
54
- it('routes every owned skill in the generated catalog', () => {
55
- const catalog = readFileSync(resolve('SKILL-CATALOG.md'), 'utf8');
56
- expect(catalog).toContain('`vibe.spec` (global)');
57
- expect(catalog).not.toMatch(/`vibe(?:\.[^`]+)?` \(unrouted\)/);
58
- });
59
- });
60
- //# sourceMappingURL=skill-namespace.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skill-namespace.test.js","sourceRoot":"","sources":["../../src/__tests__/skill-namespace.test.ts"],"names":[],"mappings":"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"}