vibecheck-ai 2.0.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (456) hide show
  1. package/bin/.generated +25 -0
  2. package/bin/_deprecations.js +463 -0
  3. package/bin/_router.js +46 -0
  4. package/bin/cli-hygiene.js +241 -0
  5. package/bin/dev/run-v2-torture.js +30 -0
  6. package/bin/registry.js +656 -0
  7. package/bin/runners/CLI_REFACTOR_SUMMARY.md +229 -0
  8. package/bin/runners/ENHANCEMENT_GUIDE.md +121 -0
  9. package/bin/runners/REPORT_AUDIT.md +64 -0
  10. package/bin/runners/cli-utils.js +1070 -0
  11. package/bin/runners/context/ai-task-decomposer.js +337 -0
  12. package/bin/runners/context/analyzer.js +513 -0
  13. package/bin/runners/context/api-contracts.js +427 -0
  14. package/bin/runners/context/context-diff.js +342 -0
  15. package/bin/runners/context/context-pruner.js +291 -0
  16. package/bin/runners/context/dependency-graph.js +414 -0
  17. package/bin/runners/context/generators/claude.js +107 -0
  18. package/bin/runners/context/generators/codex.js +108 -0
  19. package/bin/runners/context/generators/copilot.js +119 -0
  20. package/bin/runners/context/generators/cursor-enhanced.js +2525 -0
  21. package/bin/runners/context/generators/cursor.js +514 -0
  22. package/bin/runners/context/generators/mcp.js +169 -0
  23. package/bin/runners/context/generators/windsurf.js +180 -0
  24. package/bin/runners/context/git-context.js +304 -0
  25. package/bin/runners/context/index.js +1110 -0
  26. package/bin/runners/context/insights.js +173 -0
  27. package/bin/runners/context/mcp-server/generate-rules.js +337 -0
  28. package/bin/runners/context/mcp-server/index.js +1176 -0
  29. package/bin/runners/context/mcp-server/package.json +24 -0
  30. package/bin/runners/context/memory.js +200 -0
  31. package/bin/runners/context/monorepo.js +215 -0
  32. package/bin/runners/context/multi-repo-federation.js +404 -0
  33. package/bin/runners/context/patterns.js +253 -0
  34. package/bin/runners/context/proof-context.js +1264 -0
  35. package/bin/runners/context/security-scanner.js +541 -0
  36. package/bin/runners/context/semantic-search.js +350 -0
  37. package/bin/runners/context/shared.js +264 -0
  38. package/bin/runners/context/team-conventions.js +336 -0
  39. package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -0
  40. package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
  41. package/bin/runners/lib/agent-firewall/change-packet/builder.js +488 -0
  42. package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
  43. package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
  44. package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
  45. package/bin/runners/lib/agent-firewall/claims/extractor.js +303 -0
  46. package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
  47. package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
  48. package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
  49. package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
  50. package/bin/runners/lib/agent-firewall/enforcement/gateway.js +1059 -0
  51. package/bin/runners/lib/agent-firewall/enforcement/index.js +98 -0
  52. package/bin/runners/lib/agent-firewall/enforcement/mode.js +318 -0
  53. package/bin/runners/lib/agent-firewall/enforcement/orchestrator.js +484 -0
  54. package/bin/runners/lib/agent-firewall/enforcement/proof-artifact.js +418 -0
  55. package/bin/runners/lib/agent-firewall/enforcement/schemas/change-event.schema.json +173 -0
  56. package/bin/runners/lib/agent-firewall/enforcement/schemas/intent.schema.json +181 -0
  57. package/bin/runners/lib/agent-firewall/enforcement/schemas/verdict.schema.json +222 -0
  58. package/bin/runners/lib/agent-firewall/enforcement/verdict-v2.js +333 -0
  59. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
  60. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
  61. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +127 -0
  62. package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
  63. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +213 -0
  64. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
  65. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
  66. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
  67. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
  68. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
  69. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
  70. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
  71. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
  72. package/bin/runners/lib/agent-firewall/index.js +200 -0
  73. package/bin/runners/lib/agent-firewall/integration/index.js +20 -0
  74. package/bin/runners/lib/agent-firewall/integration/ship-gate.js +437 -0
  75. package/bin/runners/lib/agent-firewall/intent/alignment-engine.js +634 -0
  76. package/bin/runners/lib/agent-firewall/intent/auto-detect.js +426 -0
  77. package/bin/runners/lib/agent-firewall/intent/index.js +102 -0
  78. package/bin/runners/lib/agent-firewall/intent/schema.js +352 -0
  79. package/bin/runners/lib/agent-firewall/intent/store.js +283 -0
  80. package/bin/runners/lib/agent-firewall/interception/fs-interceptor.js +502 -0
  81. package/bin/runners/lib/agent-firewall/interception/index.js +23 -0
  82. package/bin/runners/lib/agent-firewall/interceptor/base.js +308 -0
  83. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
  84. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
  85. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
  86. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
  87. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
  88. package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
  89. package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
  90. package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
  91. package/bin/runners/lib/agent-firewall/logger.js +141 -0
  92. package/bin/runners/lib/agent-firewall/policy/default-policy.json +90 -0
  93. package/bin/runners/lib/agent-firewall/policy/engine.js +103 -0
  94. package/bin/runners/lib/agent-firewall/policy/loader.js +451 -0
  95. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
  96. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
  97. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +79 -0
  98. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +227 -0
  99. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +191 -0
  100. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
  101. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
  102. package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
  103. package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
  104. package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
  105. package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
  106. package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
  107. package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
  108. package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
  109. package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
  110. package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
  111. package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
  112. package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
  113. package/bin/runners/lib/agent-firewall/risk/thresholds.js +322 -0
  114. package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
  115. package/bin/runners/lib/agent-firewall/session/collector.js +451 -0
  116. package/bin/runners/lib/agent-firewall/session/index.js +26 -0
  117. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
  118. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
  119. package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
  120. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
  121. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
  122. package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
  123. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
  124. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
  125. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
  126. package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
  127. package/bin/runners/lib/agent-firewall/truthpack/loader.js +137 -0
  128. package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
  129. package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
  130. package/bin/runners/lib/ai-bridge.js +416 -0
  131. package/bin/runners/lib/analysis-core.js +309 -0
  132. package/bin/runners/lib/analyzers.js +2500 -0
  133. package/bin/runners/lib/api-client.js +269 -0
  134. package/bin/runners/lib/approve-output.js +235 -0
  135. package/bin/runners/lib/artifact-envelope.js +540 -0
  136. package/bin/runners/lib/assets/vibecheck-logo.png +0 -0
  137. package/bin/runners/lib/audit-bridge.js +391 -0
  138. package/bin/runners/lib/auth-shared.js +977 -0
  139. package/bin/runners/lib/auth-truth.js +193 -0
  140. package/bin/runners/lib/auth.js +215 -0
  141. package/bin/runners/lib/authority-badge.js +425 -0
  142. package/bin/runners/lib/backup.js +62 -0
  143. package/bin/runners/lib/billing.js +107 -0
  144. package/bin/runners/lib/checkpoint.js +941 -0
  145. package/bin/runners/lib/claims.js +118 -0
  146. package/bin/runners/lib/classify-output.js +204 -0
  147. package/bin/runners/lib/cleanup/engine.js +571 -0
  148. package/bin/runners/lib/cleanup/index.js +53 -0
  149. package/bin/runners/lib/cleanup/output.js +375 -0
  150. package/bin/runners/lib/cleanup/rules.js +1060 -0
  151. package/bin/runners/lib/cli-output.js +400 -0
  152. package/bin/runners/lib/cli-ui.js +540 -0
  153. package/bin/runners/lib/compliance-bridge-new.js +0 -0
  154. package/bin/runners/lib/compliance-bridge.js +165 -0
  155. package/bin/runners/lib/contracts/auth-contract.js +202 -0
  156. package/bin/runners/lib/contracts/env-contract.js +181 -0
  157. package/bin/runners/lib/contracts/external-contract.js +206 -0
  158. package/bin/runners/lib/contracts/guard.js +168 -0
  159. package/bin/runners/lib/contracts/index.js +89 -0
  160. package/bin/runners/lib/contracts/plan-validator.js +311 -0
  161. package/bin/runners/lib/contracts/route-contract.js +199 -0
  162. package/bin/runners/lib/contracts.js +804 -0
  163. package/bin/runners/lib/default-config.js +127 -0
  164. package/bin/runners/lib/detect.js +89 -0
  165. package/bin/runners/lib/detectors-v2.js +622 -0
  166. package/bin/runners/lib/doctor/autofix.js +254 -0
  167. package/bin/runners/lib/doctor/diagnosis-receipt.js +454 -0
  168. package/bin/runners/lib/doctor/failure-signatures.js +526 -0
  169. package/bin/runners/lib/doctor/fix-script.js +336 -0
  170. package/bin/runners/lib/doctor/index.js +37 -0
  171. package/bin/runners/lib/doctor/modules/build-tools.js +453 -0
  172. package/bin/runners/lib/doctor/modules/dependencies.js +325 -0
  173. package/bin/runners/lib/doctor/modules/index.js +105 -0
  174. package/bin/runners/lib/doctor/modules/network.js +250 -0
  175. package/bin/runners/lib/doctor/modules/os-quirks.js +706 -0
  176. package/bin/runners/lib/doctor/modules/project.js +312 -0
  177. package/bin/runners/lib/doctor/modules/repo-integrity.js +485 -0
  178. package/bin/runners/lib/doctor/modules/runtime.js +224 -0
  179. package/bin/runners/lib/doctor/modules/security.js +350 -0
  180. package/bin/runners/lib/doctor/modules/system.js +213 -0
  181. package/bin/runners/lib/doctor/modules/vibecheck.js +394 -0
  182. package/bin/runners/lib/doctor/reporter.js +262 -0
  183. package/bin/runners/lib/doctor/safe-repair.js +384 -0
  184. package/bin/runners/lib/doctor/service.js +262 -0
  185. package/bin/runners/lib/doctor/types.js +113 -0
  186. package/bin/runners/lib/doctor/ui.js +263 -0
  187. package/bin/runners/lib/doctor-enhanced.js +233 -0
  188. package/bin/runners/lib/doctor-output.js +226 -0
  189. package/bin/runners/lib/doctor-v2.js +608 -0
  190. package/bin/runners/lib/drift.js +425 -0
  191. package/bin/runners/lib/enforcement.js +72 -0
  192. package/bin/runners/lib/engine/ast-cache.js +210 -0
  193. package/bin/runners/lib/engine/auth-extractor.js +211 -0
  194. package/bin/runners/lib/engine/billing-extractor.js +112 -0
  195. package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
  196. package/bin/runners/lib/engine/env-extractor.js +207 -0
  197. package/bin/runners/lib/engine/express-extractor.js +208 -0
  198. package/bin/runners/lib/engine/extractors.js +849 -0
  199. package/bin/runners/lib/engine/index.js +207 -0
  200. package/bin/runners/lib/engine/repo-index.js +514 -0
  201. package/bin/runners/lib/engine/types.js +124 -0
  202. package/bin/runners/lib/engines/accessibility-engine.js +190 -0
  203. package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
  204. package/bin/runners/lib/engines/ast-cache.js +99 -0
  205. package/bin/runners/lib/engines/attack-detector.js +1192 -0
  206. package/bin/runners/lib/engines/code-quality-engine.js +255 -0
  207. package/bin/runners/lib/engines/console-logs-engine.js +115 -0
  208. package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
  209. package/bin/runners/lib/engines/dead-code-engine.js +198 -0
  210. package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
  211. package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
  212. package/bin/runners/lib/engines/file-filter.js +131 -0
  213. package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
  214. package/bin/runners/lib/engines/mock-data-engine.js +272 -0
  215. package/bin/runners/lib/engines/parallel-processor.js +71 -0
  216. package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
  217. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
  218. package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
  219. package/bin/runners/lib/engines/type-aware-engine.js +152 -0
  220. package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
  221. package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
  222. package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
  223. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
  224. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
  225. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
  226. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
  227. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
  228. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
  229. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
  230. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
  231. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
  232. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
  233. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
  234. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
  235. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
  236. package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
  237. package/bin/runners/lib/enterprise-detect.js +603 -0
  238. package/bin/runners/lib/enterprise-init.js +942 -0
  239. package/bin/runners/lib/entitlements-v2.js +265 -0
  240. package/bin/runners/lib/entitlements.generated.js +0 -0
  241. package/bin/runners/lib/entitlements.js +340 -0
  242. package/bin/runners/lib/env-resolver.js +417 -0
  243. package/bin/runners/lib/env-template.js +66 -0
  244. package/bin/runners/lib/env.js +189 -0
  245. package/bin/runners/lib/error-handler.js +368 -0
  246. package/bin/runners/lib/error-messages.js +289 -0
  247. package/bin/runners/lib/evidence-pack.js +684 -0
  248. package/bin/runners/lib/exit-codes.js +275 -0
  249. package/bin/runners/lib/extractors/client-calls.js +990 -0
  250. package/bin/runners/lib/extractors/fastify-route-dump.js +573 -0
  251. package/bin/runners/lib/extractors/fastify-routes.js +426 -0
  252. package/bin/runners/lib/extractors/index.js +363 -0
  253. package/bin/runners/lib/extractors/next-routes.js +524 -0
  254. package/bin/runners/lib/extractors/proof-graph.js +431 -0
  255. package/bin/runners/lib/extractors/route-matcher.js +451 -0
  256. package/bin/runners/lib/extractors/truthpack-v2.js +377 -0
  257. package/bin/runners/lib/extractors/ui-bindings.js +547 -0
  258. package/bin/runners/lib/finding-id.js +69 -0
  259. package/bin/runners/lib/finding-sorter.js +89 -0
  260. package/bin/runners/lib/findings-schema.js +281 -0
  261. package/bin/runners/lib/fingerprint.js +377 -0
  262. package/bin/runners/lib/firewall-prompt.js +50 -0
  263. package/bin/runners/lib/fix-output.js +228 -0
  264. package/bin/runners/lib/global-flags.js +250 -0
  265. package/bin/runners/lib/graph/graph-builder.js +265 -0
  266. package/bin/runners/lib/graph/html-renderer.js +413 -0
  267. package/bin/runners/lib/graph/index.js +32 -0
  268. package/bin/runners/lib/graph/runtime-collector.js +215 -0
  269. package/bin/runners/lib/graph/static-extractor.js +518 -0
  270. package/bin/runners/lib/help-formatter.js +413 -0
  271. package/bin/runners/lib/html-proof-report.js +913 -0
  272. package/bin/runners/lib/html-report.js +650 -0
  273. package/bin/runners/lib/init-wizard.js +601 -0
  274. package/bin/runners/lib/interactive-menu.js +1496 -0
  275. package/bin/runners/lib/json-output.js +76 -0
  276. package/bin/runners/lib/llm.js +75 -0
  277. package/bin/runners/lib/logger.js +38 -0
  278. package/bin/runners/lib/meter.js +61 -0
  279. package/bin/runners/lib/missions/briefing.js +427 -0
  280. package/bin/runners/lib/missions/checkpoint.js +753 -0
  281. package/bin/runners/lib/missions/evidence.js +126 -0
  282. package/bin/runners/lib/missions/hardening.js +851 -0
  283. package/bin/runners/lib/missions/plan.js +648 -0
  284. package/bin/runners/lib/missions/safety-gates.js +645 -0
  285. package/bin/runners/lib/missions/schema.js +478 -0
  286. package/bin/runners/lib/missions/templates.js +317 -0
  287. package/bin/runners/lib/next-action.js +560 -0
  288. package/bin/runners/lib/packs/bundle.js +675 -0
  289. package/bin/runners/lib/packs/evidence-pack.js +671 -0
  290. package/bin/runners/lib/packs/pack-factory.js +837 -0
  291. package/bin/runners/lib/packs/permissions-pack.js +686 -0
  292. package/bin/runners/lib/packs/proof-graph-pack.js +779 -0
  293. package/bin/runners/lib/patch.js +40 -0
  294. package/bin/runners/lib/permissions/auth-model.js +213 -0
  295. package/bin/runners/lib/permissions/idor-prover.js +205 -0
  296. package/bin/runners/lib/permissions/index.js +45 -0
  297. package/bin/runners/lib/permissions/matrix-builder.js +198 -0
  298. package/bin/runners/lib/pkgjson.js +28 -0
  299. package/bin/runners/lib/policy.js +295 -0
  300. package/bin/runners/lib/polish/accessibility.js +62 -0
  301. package/bin/runners/lib/polish/analyzer.js +93 -0
  302. package/bin/runners/lib/polish/backend.js +87 -0
  303. package/bin/runners/lib/polish/configuration.js +83 -0
  304. package/bin/runners/lib/polish/documentation.js +83 -0
  305. package/bin/runners/lib/polish/frontend.js +817 -0
  306. package/bin/runners/lib/polish/index.js +27 -0
  307. package/bin/runners/lib/polish/infrastructure.js +80 -0
  308. package/bin/runners/lib/polish/internationalization.js +85 -0
  309. package/bin/runners/lib/polish/libraries.js +180 -0
  310. package/bin/runners/lib/polish/observability.js +75 -0
  311. package/bin/runners/lib/polish/performance.js +64 -0
  312. package/bin/runners/lib/polish/privacy.js +110 -0
  313. package/bin/runners/lib/polish/resilience.js +92 -0
  314. package/bin/runners/lib/polish/security.js +78 -0
  315. package/bin/runners/lib/polish/seo.js +71 -0
  316. package/bin/runners/lib/polish/styles.js +62 -0
  317. package/bin/runners/lib/polish/utils.js +104 -0
  318. package/bin/runners/lib/preflight.js +142 -0
  319. package/bin/runners/lib/prerequisites.js +149 -0
  320. package/bin/runners/lib/prove-output.js +220 -0
  321. package/bin/runners/lib/reality/correlation-detectors.js +359 -0
  322. package/bin/runners/lib/reality/index.js +318 -0
  323. package/bin/runners/lib/reality/request-hashing.js +416 -0
  324. package/bin/runners/lib/reality/request-mapper.js +453 -0
  325. package/bin/runners/lib/reality/safety-rails.js +463 -0
  326. package/bin/runners/lib/reality/semantic-snapshot.js +408 -0
  327. package/bin/runners/lib/reality/toast-detector.js +393 -0
  328. package/bin/runners/lib/reality-findings.js +84 -0
  329. package/bin/runners/lib/reality-output.js +231 -0
  330. package/bin/runners/lib/receipts.js +179 -0
  331. package/bin/runners/lib/redact.js +29 -0
  332. package/bin/runners/lib/replay/capsule-manager.js +154 -0
  333. package/bin/runners/lib/replay/index.js +263 -0
  334. package/bin/runners/lib/replay/player.js +348 -0
  335. package/bin/runners/lib/replay/recorder.js +331 -0
  336. package/bin/runners/lib/report-engine.js +626 -0
  337. package/bin/runners/lib/report-html.js +1233 -0
  338. package/bin/runners/lib/report-output.js +366 -0
  339. package/bin/runners/lib/report-templates.js +967 -0
  340. package/bin/runners/lib/report.js +135 -0
  341. package/bin/runners/lib/route-detection.js +1209 -0
  342. package/bin/runners/lib/route-truth.js +1322 -0
  343. package/bin/runners/lib/safelist/index.js +96 -0
  344. package/bin/runners/lib/safelist/integration.js +334 -0
  345. package/bin/runners/lib/safelist/matcher.js +696 -0
  346. package/bin/runners/lib/safelist/schema.js +948 -0
  347. package/bin/runners/lib/safelist/store.js +438 -0
  348. package/bin/runners/lib/sandbox/index.js +59 -0
  349. package/bin/runners/lib/sandbox/proof-chain.js +399 -0
  350. package/bin/runners/lib/sandbox/sandbox-runner.js +205 -0
  351. package/bin/runners/lib/sandbox/worktree.js +174 -0
  352. package/bin/runners/lib/scan-cache.js +330 -0
  353. package/bin/runners/lib/scan-output-schema.js +344 -0
  354. package/bin/runners/lib/scan-output.js +631 -0
  355. package/bin/runners/lib/scan-runner.js +135 -0
  356. package/bin/runners/lib/schema-validator.js +350 -0
  357. package/bin/runners/lib/schemas/ajv-validator.js +464 -0
  358. package/bin/runners/lib/schemas/contracts.schema.json +160 -0
  359. package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
  360. package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
  361. package/bin/runners/lib/schemas/finding.schema.json +100 -0
  362. package/bin/runners/lib/schemas/mission-pack.schema.json +206 -0
  363. package/bin/runners/lib/schemas/proof-graph.schema.json +176 -0
  364. package/bin/runners/lib/schemas/reality-report.schema.json +162 -0
  365. package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
  366. package/bin/runners/lib/schemas/run-request.schema.json +108 -0
  367. package/bin/runners/lib/schemas/share-pack.schema.json +180 -0
  368. package/bin/runners/lib/schemas/ship-manifest.schema.json +251 -0
  369. package/bin/runners/lib/schemas/ship-report.schema.json +117 -0
  370. package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -0
  371. package/bin/runners/lib/schemas/validator.js +465 -0
  372. package/bin/runners/lib/schemas/verdict.schema.json +140 -0
  373. package/bin/runners/lib/score-history.js +282 -0
  374. package/bin/runners/lib/security-bridge.js +249 -0
  375. package/bin/runners/lib/server-usage.js +513 -0
  376. package/bin/runners/lib/share-pack.js +239 -0
  377. package/bin/runners/lib/ship-gate.js +832 -0
  378. package/bin/runners/lib/ship-manifest.js +1153 -0
  379. package/bin/runners/lib/ship-output-enterprise.js +239 -0
  380. package/bin/runners/lib/ship-output.js +1128 -0
  381. package/bin/runners/lib/snippets.js +67 -0
  382. package/bin/runners/lib/status-output.js +340 -0
  383. package/bin/runners/lib/terminal-ui.js +356 -0
  384. package/bin/runners/lib/truth.js +1691 -0
  385. package/bin/runners/lib/ui.js +562 -0
  386. package/bin/runners/lib/unified-cli-output.js +947 -0
  387. package/bin/runners/lib/unified-output.js +197 -0
  388. package/bin/runners/lib/upsell.js +410 -0
  389. package/bin/runners/lib/usage.js +153 -0
  390. package/bin/runners/lib/validate-patch.js +156 -0
  391. package/bin/runners/lib/verdict-engine.js +628 -0
  392. package/bin/runners/lib/verification.js +345 -0
  393. package/bin/runners/lib/why-tree.js +650 -0
  394. package/bin/runners/reality/engine.js +917 -0
  395. package/bin/runners/reality/flows.js +122 -0
  396. package/bin/runners/reality/report.js +378 -0
  397. package/bin/runners/reality/session.js +193 -0
  398. package/bin/runners/runAIAgent.js +229 -0
  399. package/bin/runners/runAgent.d.ts +5 -0
  400. package/bin/runners/runAgent.js +161 -0
  401. package/bin/runners/runAllowlist.js +418 -0
  402. package/bin/runners/runApprove.js +320 -0
  403. package/bin/runners/runAudit.js +692 -0
  404. package/bin/runners/runAuth.js +731 -0
  405. package/bin/runners/runCI.js +353 -0
  406. package/bin/runners/runCheckpoint.js +530 -0
  407. package/bin/runners/runClassify.js +928 -0
  408. package/bin/runners/runCleanup.js +343 -0
  409. package/bin/runners/runContext.d.ts +4 -0
  410. package/bin/runners/runContext.js +175 -0
  411. package/bin/runners/runDoctor.js +877 -0
  412. package/bin/runners/runEvidencePack.js +362 -0
  413. package/bin/runners/runFirewall.d.ts +5 -0
  414. package/bin/runners/runFirewall.js +134 -0
  415. package/bin/runners/runFirewallHook.d.ts +5 -0
  416. package/bin/runners/runFirewallHook.js +56 -0
  417. package/bin/runners/runFix.js +1355 -0
  418. package/bin/runners/runForge.js +451 -0
  419. package/bin/runners/runGuard.js +262 -0
  420. package/bin/runners/runInit.js +1927 -0
  421. package/bin/runners/runIntent.js +906 -0
  422. package/bin/runners/runKickoff.js +878 -0
  423. package/bin/runners/runLabs.js +424 -0
  424. package/bin/runners/runLaunch.js +2000 -0
  425. package/bin/runners/runLink.js +785 -0
  426. package/bin/runners/runMcp.js +1875 -0
  427. package/bin/runners/runPacks.js +2089 -0
  428. package/bin/runners/runPolish.d.ts +4 -0
  429. package/bin/runners/runPolish.js +390 -0
  430. package/bin/runners/runPromptFirewall.js +211 -0
  431. package/bin/runners/runProve.js +1411 -0
  432. package/bin/runners/runQuickstart.js +531 -0
  433. package/bin/runners/runReality.js +2260 -0
  434. package/bin/runners/runReport.js +726 -0
  435. package/bin/runners/runRuntime.js +110 -0
  436. package/bin/runners/runSafelist.js +1190 -0
  437. package/bin/runners/runScan.js +688 -0
  438. package/bin/runners/runShield.js +1282 -0
  439. package/bin/runners/runShip.js +1660 -0
  440. package/bin/runners/runTruth.d.ts +5 -0
  441. package/bin/runners/runTruth.js +101 -0
  442. package/bin/runners/runValidate.js +179 -0
  443. package/bin/runners/runWatch.js +478 -0
  444. package/bin/runners/utils.js +360 -0
  445. package/bin/scan.js +617 -0
  446. package/bin/vibecheck.js +1617 -0
  447. package/dist/guardrail/index.d.ts +2405 -0
  448. package/dist/guardrail/index.js +9747 -0
  449. package/dist/guardrail/index.js.map +1 -0
  450. package/dist/scanner/index.d.ts +282 -0
  451. package/dist/scanner/index.js +3395 -0
  452. package/dist/scanner/index.js.map +1 -0
  453. package/package.json +123 -104
  454. package/README.md +0 -491
  455. package/dist/index.js +0 -99711
  456. package/dist/index.js.map +0 -1
@@ -0,0 +1,604 @@
1
+ /**
2
+ * Lawbook Invariant Evaluator
3
+ *
4
+ * Evaluates change proposals against organizational invariant rules.
5
+ * Returns violations with severity and remediation suggestions.
6
+ *
7
+ * Codename: Lawbook
8
+ */
9
+
10
+ "use strict";
11
+
12
+ const fs = require("fs");
13
+ const path = require("path");
14
+ const { minimatch } = require("minimatch");
15
+
16
+ const {
17
+ INVARIANT_TYPES,
18
+ INVARIANT_SEVERITY,
19
+ validateInvariant,
20
+ } = require("./schema.js");
21
+ const { lawbookLogger: log, getErrorMessage } = require("../logger.js");
22
+
23
+ /**
24
+ * @typedef {Object} Violation
25
+ * @property {string} invariantId - Invariant that was violated
26
+ * @property {string} rule - Rule type
27
+ * @property {string} severity - Violation severity
28
+ * @property {string} file - File where violation occurred
29
+ * @property {number} line - Line number (if applicable)
30
+ * @property {string} message - Human-readable message
31
+ * @property {string} evidence - Evidence of the violation
32
+ * @property {Object} suggestion - Suggested fix
33
+ */
34
+
35
+ /**
36
+ * @typedef {Object} EvaluationResult
37
+ * @property {boolean} passed - Did evaluation pass (no blocking violations)
38
+ * @property {Violation[]} violations - All violations found
39
+ * @property {Object} summary - Summary by severity
40
+ */
41
+
42
+ /**
43
+ * Invariant Evaluator class
44
+ */
45
+ class InvariantEvaluator {
46
+ constructor(options = {}) {
47
+ this.invariants = [];
48
+ this.envRegistry = null;
49
+ this.projectRoot = options.projectRoot || process.cwd();
50
+ this.strictMode = options.strictMode || false;
51
+ }
52
+
53
+ /**
54
+ * Load invariants from a lawbook
55
+ * @param {Object} lawbook - Parsed lawbook
56
+ */
57
+ loadLawbook(lawbook) {
58
+ if (!lawbook || !lawbook.invariants) return;
59
+
60
+ for (const invariant of lawbook.invariants) {
61
+ const validation = validateInvariant(invariant);
62
+ if (validation.valid) {
63
+ this.invariants.push(invariant);
64
+ } else if (this.strictMode) {
65
+ throw new Error(`Invalid invariant ${invariant.id}: ${validation.errors.map(e => e.message).join(", ")}`);
66
+ }
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Load environment variable registry for env-must-be-registered rules
72
+ * @param {string} registryPath - Path to registry file
73
+ */
74
+ loadEnvRegistry(registryPath) {
75
+ try {
76
+ const fullPath = path.resolve(this.projectRoot, registryPath);
77
+ const content = fs.readFileSync(fullPath, "utf-8");
78
+
79
+ // Parse .env.example style file
80
+ const registry = new Set();
81
+ for (const line of content.split("\n")) {
82
+ const trimmed = line.trim();
83
+ if (!trimmed || trimmed.startsWith("#")) continue;
84
+
85
+ const match = trimmed.match(/^([A-Z_][A-Z0-9_]*)=/);
86
+ if (match) {
87
+ registry.add(match[1]);
88
+ }
89
+ }
90
+
91
+ this.envRegistry = registry;
92
+ } catch (error) {
93
+ log.warn(`Failed to load env registry: ${getErrorMessage(error)}`);
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Evaluate a change proposal against all invariants
99
+ * @param {Object} proposal - Change proposal
100
+ * @returns {EvaluationResult} Evaluation result
101
+ */
102
+ evaluate(proposal) {
103
+ const violations = [];
104
+
105
+ for (const invariant of this.invariants) {
106
+ const invariantViolations = this.evaluateInvariant(invariant, proposal);
107
+ violations.push(...invariantViolations);
108
+ }
109
+
110
+ // Calculate summary
111
+ const summary = {
112
+ total: violations.length,
113
+ block: violations.filter(v => v.severity === INVARIANT_SEVERITY.BLOCK).length,
114
+ error: violations.filter(v => v.severity === INVARIANT_SEVERITY.ERROR).length,
115
+ warning: violations.filter(v => v.severity === INVARIANT_SEVERITY.WARNING).length,
116
+ info: violations.filter(v => v.severity === INVARIANT_SEVERITY.INFO).length,
117
+ };
118
+
119
+ return {
120
+ passed: summary.block === 0 && summary.error === 0,
121
+ violations,
122
+ summary,
123
+ };
124
+ }
125
+
126
+ /**
127
+ * Evaluate a single invariant against a proposal
128
+ * @param {Object} invariant - Invariant to check
129
+ * @param {Object} proposal - Change proposal
130
+ * @returns {Violation[]} Violations found
131
+ */
132
+ evaluateInvariant(invariant, proposal) {
133
+ switch (invariant.rule) {
134
+ case INVARIANT_TYPES.NO_MODIFY:
135
+ return this.evaluateNoModify(invariant, proposal);
136
+
137
+ case INVARIANT_TYPES.NO_DELETE:
138
+ return this.evaluateNoDelete(invariant, proposal);
139
+
140
+ case INVARIANT_TYPES.NO_CREATE:
141
+ return this.evaluateNoCreate(invariant, proposal);
142
+
143
+ case INVARIANT_TYPES.NEVER:
144
+ return this.evaluateNever(invariant, proposal);
145
+
146
+ case INVARIANT_TYPES.ALWAYS:
147
+ return this.evaluateAlways(invariant, proposal);
148
+
149
+ case INVARIANT_TYPES.ALL_THROUGH:
150
+ return this.evaluateAllThrough(invariant, proposal);
151
+
152
+ case INVARIANT_TYPES.NO_DIRECT:
153
+ return this.evaluateNoDirect(invariant, proposal);
154
+
155
+ case INVARIANT_TYPES.ENV_MUST_BE_REGISTERED:
156
+ return this.evaluateEnvMustBeRegistered(invariant, proposal);
157
+
158
+ case INVARIANT_TYPES.REQUIRE_APPROVAL:
159
+ return this.evaluateRequireApproval(invariant, proposal);
160
+
161
+ default:
162
+ return [];
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Check if a file matches an invariant's scope
168
+ * @param {string} filePath - File path to check
169
+ * @param {Object} invariant - Invariant with scope
170
+ * @returns {boolean} Does file match scope
171
+ */
172
+ matchesScope(filePath, invariant) {
173
+ if (!invariant.scope) return true;
174
+
175
+ const relativePath = path.relative(this.projectRoot, filePath).replace(/\\/g, "/");
176
+
177
+ // Check if matches scope
178
+ const matchesInclude = minimatch(relativePath, invariant.scope, { dot: true });
179
+
180
+ // Check if excluded
181
+ if (matchesInclude && invariant.exclude) {
182
+ const excludes = Array.isArray(invariant.exclude) ? invariant.exclude : [invariant.exclude];
183
+ for (const exclude of excludes) {
184
+ if (minimatch(relativePath, exclude, { dot: true })) {
185
+ return false;
186
+ }
187
+ }
188
+ }
189
+
190
+ return matchesInclude;
191
+ }
192
+
193
+ /**
194
+ * Create a violation object
195
+ * @param {Object} invariant - Violated invariant
196
+ * @param {Object} details - Violation details
197
+ * @returns {Violation} Violation object
198
+ */
199
+ createViolation(invariant, details) {
200
+ return {
201
+ invariantId: invariant.id,
202
+ rule: invariant.rule,
203
+ severity: invariant.severity || INVARIANT_SEVERITY.ERROR,
204
+ file: details.file || null,
205
+ line: details.line || null,
206
+ message: details.message || invariant.message || invariant.description,
207
+ evidence: details.evidence || null,
208
+ suggestion: details.suggestion || null,
209
+ };
210
+ }
211
+
212
+ // ═══════════════════════════════════════════════════════════════════════════════
213
+ // RULE EVALUATORS
214
+ // ═══════════════════════════════════════════════════════════════════════════════
215
+
216
+ /**
217
+ * Evaluate no-modify rule
218
+ */
219
+ evaluateNoModify(invariant, proposal) {
220
+ const violations = [];
221
+
222
+ for (const op of proposal.operations || []) {
223
+ if (op.type === "modify" || op.type === "update") {
224
+ const filePath = op.path || op.file;
225
+ if (filePath && this.matchesScope(filePath, invariant)) {
226
+ violations.push(this.createViolation(invariant, {
227
+ file: filePath,
228
+ message: `File is protected by '${invariant.id}' - modifications not allowed`,
229
+ evidence: `Attempted to modify: ${filePath}`,
230
+ suggestion: {
231
+ action: "remove_operation",
232
+ reason: invariant.description || "This file/path is protected",
233
+ incident: invariant.incident,
234
+ },
235
+ }));
236
+ }
237
+ }
238
+ }
239
+
240
+ return violations;
241
+ }
242
+
243
+ /**
244
+ * Evaluate no-delete rule
245
+ */
246
+ evaluateNoDelete(invariant, proposal) {
247
+ const violations = [];
248
+
249
+ for (const op of proposal.operations || []) {
250
+ if (op.type === "delete" || op.type === "remove") {
251
+ const filePath = op.path || op.file;
252
+ if (filePath && this.matchesScope(filePath, invariant)) {
253
+ violations.push(this.createViolation(invariant, {
254
+ file: filePath,
255
+ message: `File is protected by '${invariant.id}' - deletion not allowed`,
256
+ evidence: `Attempted to delete: ${filePath}`,
257
+ suggestion: {
258
+ action: "remove_operation",
259
+ reason: invariant.description || "This file/path cannot be deleted",
260
+ },
261
+ }));
262
+ }
263
+ }
264
+ }
265
+
266
+ return violations;
267
+ }
268
+
269
+ /**
270
+ * Evaluate no-create rule
271
+ */
272
+ evaluateNoCreate(invariant, proposal) {
273
+ const violations = [];
274
+
275
+ for (const op of proposal.operations || []) {
276
+ if (op.type === "create" || op.type === "add") {
277
+ const filePath = op.path || op.file;
278
+ if (filePath && this.matchesScope(filePath, invariant)) {
279
+ violations.push(this.createViolation(invariant, {
280
+ file: filePath,
281
+ message: `Creating files matching '${invariant.scope}' is not allowed`,
282
+ evidence: `Attempted to create: ${filePath}`,
283
+ suggestion: {
284
+ action: "remove_operation",
285
+ reason: invariant.description || "This pattern is forbidden",
286
+ },
287
+ }));
288
+ }
289
+ }
290
+ }
291
+
292
+ return violations;
293
+ }
294
+
295
+ /**
296
+ * Evaluate never rule (pattern must not appear)
297
+ */
298
+ evaluateNever(invariant, proposal) {
299
+ const violations = [];
300
+ const pattern = new RegExp(invariant.pattern, "gm");
301
+
302
+ for (const op of proposal.operations || []) {
303
+ const filePath = op.path || op.file;
304
+ if (!filePath || !this.matchesScope(filePath, invariant)) continue;
305
+
306
+ const content = op.content || op.newContent;
307
+ if (!content) continue;
308
+
309
+ const lines = content.split("\n");
310
+ for (let i = 0; i < lines.length; i++) {
311
+ const line = lines[i];
312
+ const matches = line.match(pattern);
313
+
314
+ if (matches) {
315
+ violations.push(this.createViolation(invariant, {
316
+ file: filePath,
317
+ line: i + 1,
318
+ message: `Pattern '${invariant.pattern}' is forbidden by '${invariant.id}'`,
319
+ evidence: line.trim(),
320
+ suggestion: {
321
+ action: "remove_pattern",
322
+ pattern: invariant.pattern,
323
+ reason: invariant.description,
324
+ },
325
+ }));
326
+ }
327
+ }
328
+ }
329
+
330
+ return violations;
331
+ }
332
+
333
+ /**
334
+ * Evaluate always rule (pattern must be present)
335
+ */
336
+ evaluateAlways(invariant, proposal) {
337
+ const violations = [];
338
+ const pattern = new RegExp(invariant.pattern);
339
+
340
+ for (const op of proposal.operations || []) {
341
+ const filePath = op.path || op.file;
342
+ if (!filePath || !this.matchesScope(filePath, invariant)) continue;
343
+
344
+ // Only check newly created or modified files
345
+ if (op.type !== "create" && op.type !== "modify") continue;
346
+
347
+ const content = op.content || op.newContent;
348
+ if (!content) continue;
349
+
350
+ if (!pattern.test(content)) {
351
+ violations.push(this.createViolation(invariant, {
352
+ file: filePath,
353
+ message: `Required pattern '${invariant.pattern}' is missing (required by '${invariant.id}')`,
354
+ evidence: `Pattern not found in file`,
355
+ suggestion: {
356
+ action: "add_pattern",
357
+ pattern: invariant.pattern,
358
+ reason: invariant.description,
359
+ },
360
+ }));
361
+ }
362
+ }
363
+
364
+ return violations;
365
+ }
366
+
367
+ /**
368
+ * Evaluate all-through rule (all X must go through Y)
369
+ */
370
+ evaluateAllThrough(invariant, proposal) {
371
+ const violations = [];
372
+
373
+ if (!invariant.violations || !invariant.target) return violations;
374
+
375
+ for (const op of proposal.operations || []) {
376
+ const filePath = op.path || op.file;
377
+ if (!filePath) continue;
378
+
379
+ // Skip the target file itself
380
+ const relativePath = path.relative(this.projectRoot, filePath).replace(/\\/g, "/");
381
+ if (relativePath === invariant.target || minimatch(relativePath, invariant.target, { dot: true })) {
382
+ continue;
383
+ }
384
+
385
+ const content = op.content || op.newContent;
386
+ if (!content) continue;
387
+
388
+ // Check each violation pattern
389
+ for (const violationDef of invariant.violations) {
390
+ // Skip if file is excluded
391
+ if (violationDef.exclude) {
392
+ const excludes = Array.isArray(violationDef.exclude) ? violationDef.exclude : [violationDef.exclude];
393
+ let excluded = false;
394
+ for (const exclude of excludes) {
395
+ if (minimatch(relativePath, exclude, { dot: true })) {
396
+ excluded = true;
397
+ break;
398
+ }
399
+ }
400
+ if (excluded) continue;
401
+ }
402
+
403
+ const pattern = new RegExp(violationDef.pattern, "gm");
404
+ const lines = content.split("\n");
405
+
406
+ for (let i = 0; i < lines.length; i++) {
407
+ if (pattern.test(lines[i])) {
408
+ violations.push(this.createViolation(invariant, {
409
+ file: filePath,
410
+ line: i + 1,
411
+ message: violationDef.message || `Must use ${invariant.target} instead of direct access`,
412
+ evidence: lines[i].trim(),
413
+ suggestion: {
414
+ action: "use_approved_path",
415
+ target: invariant.target,
416
+ reason: invariant.description,
417
+ },
418
+ }));
419
+ }
420
+ }
421
+ }
422
+ }
423
+
424
+ return violations;
425
+ }
426
+
427
+ /**
428
+ * Evaluate no-direct rule (must use approved pattern)
429
+ */
430
+ evaluateNoDirect(invariant, proposal) {
431
+ const violations = [];
432
+ const pattern = new RegExp(invariant.pattern, "gm");
433
+
434
+ for (const op of proposal.operations || []) {
435
+ const filePath = op.path || op.file;
436
+ if (!filePath || !this.matchesScope(filePath, invariant)) continue;
437
+
438
+ const content = op.content || op.newContent;
439
+ if (!content) continue;
440
+
441
+ const lines = content.split("\n");
442
+ for (let i = 0; i < lines.length; i++) {
443
+ if (pattern.test(lines[i])) {
444
+ violations.push(this.createViolation(invariant, {
445
+ file: filePath,
446
+ line: i + 1,
447
+ message: `Direct access to '${invariant.pattern}' is forbidden`,
448
+ evidence: lines[i].trim(),
449
+ suggestion: {
450
+ action: "use_abstraction",
451
+ reason: invariant.description,
452
+ },
453
+ }));
454
+ }
455
+ }
456
+ }
457
+
458
+ return violations;
459
+ }
460
+
461
+ /**
462
+ * Evaluate env-must-be-registered rule
463
+ */
464
+ evaluateEnvMustBeRegistered(invariant, proposal) {
465
+ const violations = [];
466
+
467
+ // Load registry if not loaded
468
+ if (!this.envRegistry && invariant.registry) {
469
+ this.loadEnvRegistry(invariant.registry);
470
+ }
471
+
472
+ if (!this.envRegistry) return violations;
473
+
474
+ // Pattern to find env var usage
475
+ const envPattern = /process\.env\.([A-Z_][A-Z0-9_]*)|import\.meta\.env\.([A-Z_][A-Z0-9_]*)/g;
476
+
477
+ for (const op of proposal.operations || []) {
478
+ const filePath = op.path || op.file;
479
+ if (!filePath || !this.matchesScope(filePath, invariant)) continue;
480
+
481
+ const content = op.content || op.newContent;
482
+ if (!content) continue;
483
+
484
+ let match;
485
+ const lines = content.split("\n");
486
+
487
+ for (let i = 0; i < lines.length; i++) {
488
+ while ((match = envPattern.exec(lines[i])) !== null) {
489
+ const envVar = match[1] || match[2];
490
+
491
+ if (!this.envRegistry.has(envVar)) {
492
+ violations.push(this.createViolation(invariant, {
493
+ file: filePath,
494
+ line: i + 1,
495
+ message: `Environment variable '${envVar}' is not registered in ${invariant.registry}`,
496
+ evidence: lines[i].trim(),
497
+ suggestion: {
498
+ action: "register_env_var",
499
+ variable: envVar,
500
+ registry: invariant.registry,
501
+ },
502
+ }));
503
+ }
504
+ }
505
+ }
506
+ }
507
+
508
+ return violations;
509
+ }
510
+
511
+ /**
512
+ * Evaluate require-approval rule
513
+ */
514
+ evaluateRequireApproval(invariant, proposal) {
515
+ const violations = [];
516
+
517
+ for (const op of proposal.operations || []) {
518
+ const filePath = op.path || op.file;
519
+ if (!filePath || !this.matchesScope(filePath, invariant)) continue;
520
+
521
+ // Check if proposal has required approval
522
+ const hasApproval = proposal.approvals?.some(a =>
523
+ a.invariantId === invariant.id && a.approved
524
+ );
525
+
526
+ if (!hasApproval) {
527
+ violations.push(this.createViolation(invariant, {
528
+ file: filePath,
529
+ message: `Changes to '${filePath}' require approval`,
530
+ evidence: `Operation type: ${op.type}`,
531
+ suggestion: {
532
+ action: "request_approval",
533
+ owner: invariant.owner,
534
+ reason: invariant.description,
535
+ },
536
+ }));
537
+ }
538
+ }
539
+
540
+ return violations;
541
+ }
542
+
543
+ /**
544
+ * Get all invariants
545
+ * @returns {Object[]} All loaded invariants
546
+ */
547
+ getInvariants() {
548
+ return [...this.invariants];
549
+ }
550
+
551
+ /**
552
+ * Get invariant by ID
553
+ * @param {string} id - Invariant ID
554
+ * @returns {Object|null} Invariant or null
555
+ */
556
+ getInvariant(id) {
557
+ return this.invariants.find(i => i.id === id) || null;
558
+ }
559
+
560
+ /**
561
+ * Add a single invariant
562
+ * @param {Object} invariant - Invariant to add
563
+ */
564
+ addInvariant(invariant) {
565
+ const validation = validateInvariant(invariant);
566
+ if (!validation.valid) {
567
+ throw new Error(`Invalid invariant: ${validation.errors.map(e => e.message).join(", ")}`);
568
+ }
569
+ this.invariants.push(invariant);
570
+ }
571
+
572
+ /**
573
+ * Remove an invariant
574
+ * @param {string} id - Invariant ID to remove
575
+ * @returns {boolean} Success
576
+ */
577
+ removeInvariant(id) {
578
+ const index = this.invariants.findIndex(i => i.id === id);
579
+ if (index !== -1) {
580
+ this.invariants.splice(index, 1);
581
+ return true;
582
+ }
583
+ return false;
584
+ }
585
+
586
+ /**
587
+ * Clear all invariants
588
+ */
589
+ clear() {
590
+ this.invariants = [];
591
+ this.envRegistry = null;
592
+ }
593
+ }
594
+
595
+ /**
596
+ * Create an evaluator instance
597
+ * @param {Object} options - Options
598
+ * @returns {InvariantEvaluator} Evaluator instance
599
+ */
600
+ function createEvaluator(options = {}) {
601
+ return new InvariantEvaluator(options);
602
+ }
603
+
604
+ module.exports = { InvariantEvaluator, createEvaluator };