tribunal-kit 6.0.0 → 7.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 (353) hide show
  1. package/.agent/.manifest.json +78 -0
  2. package/.agent/ARCHITECTURE.md +19 -241
  3. package/.agent/agents/accessibility-reviewer.md +23 -16
  4. package/.agent/agents/ai-code-reviewer.md +25 -21
  5. package/.agent/agents/anti-pattern-reviewer.md +12 -7
  6. package/.agent/agents/api-architect.md +1 -0
  7. package/.agent/agents/backend-specialist.md +23 -22
  8. package/.agent/agents/cloud-engineer.md +1 -0
  9. package/.agent/agents/code-archaeologist.md +1 -0
  10. package/.agent/agents/complexity-reviewer.md +10 -7
  11. package/.agent/agents/database-architect.md +3 -2
  12. package/.agent/agents/db-latency-auditor.md +6 -2
  13. package/.agent/agents/debugger.md +3 -2
  14. package/.agent/agents/dependency-reviewer.md +1 -0
  15. package/.agent/agents/devops-engineer.md +9 -8
  16. package/.agent/agents/documentation-writer.md +6 -5
  17. package/.agent/agents/explorer-agent.md +1 -0
  18. package/.agent/agents/frontend-reviewer.md +21 -17
  19. package/.agent/agents/frontend-specialist.md +23 -20
  20. package/.agent/agents/game-developer.md +1 -0
  21. package/.agent/agents/interaction-reviewer.md +10 -5
  22. package/.agent/agents/logic-reviewer.md +3 -0
  23. package/.agent/agents/minimalist-reviewer.md +6 -0
  24. package/.agent/agents/mobile-developer.md +7 -6
  25. package/.agent/agents/mobile-reviewer.md +14 -13
  26. package/.agent/agents/orchestrator.md +3 -0
  27. package/.agent/agents/penetration-tester.md +1 -0
  28. package/.agent/agents/performance-optimizer.md +6 -5
  29. package/.agent/agents/performance-reviewer.md +6 -6
  30. package/.agent/agents/pipeline-reviewer.md +144 -0
  31. package/.agent/agents/precedence-reviewer.md +1 -0
  32. package/.agent/agents/product-manager.md +1 -0
  33. package/.agent/agents/product-owner.md +1 -0
  34. package/.agent/agents/product-reviewer.md +12 -7
  35. package/.agent/agents/project-planner.md +3 -0
  36. package/.agent/agents/qa-automation-engineer.md +50 -43
  37. package/.agent/agents/resilience-reviewer.md +1 -0
  38. package/.agent/agents/schema-reviewer.md +1 -0
  39. package/.agent/agents/security-auditor.md +24 -24
  40. package/.agent/agents/seo-specialist.md +33 -23
  41. package/.agent/agents/sql-reviewer.md +5 -4
  42. package/.agent/agents/supervisor-agent.md +12 -2
  43. package/.agent/agents/swarm-worker-contracts.md +13 -13
  44. package/.agent/agents/swarm-worker-registry.md +51 -51
  45. package/.agent/agents/system-architect.md +1 -0
  46. package/.agent/agents/test-coverage-reviewer.md +25 -22
  47. package/.agent/agents/test-engineer.md +12 -11
  48. package/.agent/agents/throughput-optimizer.md +45 -40
  49. package/.agent/agents/type-safety-reviewer.md +5 -4
  50. package/.agent/agents/ui-ux-auditor.md +6 -4
  51. package/.agent/agents/ui-visual-auditor.md +3 -0
  52. package/.agent/agents/ux-reviewer.md +11 -6
  53. package/.agent/agents/visual-reviewer.md +11 -6
  54. package/.agent/agents/vitals-reviewer.md +5 -4
  55. package/.agent/history/memory/.memory.idx +3716 -1
  56. package/.agent/history/memory/MEMORY.md +246 -1
  57. package/.agent/mcp_config.json +1 -6
  58. package/.agent/routing_index.json +2034 -263
  59. package/.agent/rules/GEMINI.md +12 -10
  60. package/.agent/rules/GEMINI_PLANNER.md +19 -21
  61. package/.agent/scripts/_colors.js +52 -54
  62. package/.agent/scripts/_utils.js +52 -53
  63. package/.agent/scripts/auto_preview.js +39 -43
  64. package/.agent/scripts/bundle_analyzer.js +47 -60
  65. package/.agent/scripts/case_law_manager.js +200 -294
  66. package/.agent/scripts/checklist.js +73 -94
  67. package/.agent/scripts/cicd_validator.js +305 -0
  68. package/.agent/scripts/compile_router.py +4 -111
  69. package/.agent/scripts/context_broker.js +317 -412
  70. package/.agent/scripts/contract_engine.js +402 -0
  71. package/.agent/scripts/dependency_analyzer.js +112 -124
  72. package/.agent/scripts/graph_builder.js +75 -103
  73. package/.agent/scripts/graph_visualizer.js +10 -12
  74. package/.agent/scripts/graph_zoom.js +38 -55
  75. package/.agent/scripts/guardrail_engine.js +195 -145
  76. package/.agent/scripts/impact_classifier.js +55 -30
  77. package/.agent/scripts/inner_loop_validator.js +108 -159
  78. package/.agent/scripts/integrity_manifest.js +59 -67
  79. package/.agent/scripts/lint_runner.js +65 -75
  80. package/.agent/scripts/marathon_harness.js +131 -208
  81. package/.agent/scripts/migrate_skills_frontmatter.py +4 -63
  82. package/.agent/scripts/minify_context.js +29 -33
  83. package/.agent/scripts/minimal_change_engine.js +95 -87
  84. package/.agent/scripts/mutation_runner.js +46 -62
  85. package/.agent/scripts/pipeline_engine.js +320 -209
  86. package/.agent/scripts/prompt_compiler.js +118 -93
  87. package/.agent/scripts/schema_validator.js +73 -121
  88. package/.agent/scripts/security_scan.js +88 -117
  89. package/.agent/scripts/session_manager.js +52 -69
  90. package/.agent/scripts/signal_detector.js +24 -22
  91. package/.agent/scripts/skill_evolution.js +184 -245
  92. package/.agent/scripts/skill_integrator.js +35 -48
  93. package/.agent/scripts/socratic_gate_policy.js +15 -12
  94. package/.agent/scripts/strengthen_skills.js +29 -33
  95. package/.agent/scripts/swarm_dispatcher.js +120 -151
  96. package/.agent/scripts/test_runner.js +54 -56
  97. package/.agent/scripts/token_budget_broker.js +9 -7
  98. package/.agent/scripts/trace_engine.js +126 -0
  99. package/.agent/scripts/verify_all.js +76 -93
  100. package/.agent/scripts/visual_audit.js +16 -21
  101. package/.agent/skill_topic_map.json +237 -0
  102. package/.agent/skills/12-principles-of-animation/SKILL.md +7 -0
  103. package/.agent/skills/60fps-animation/SKILL.md +7 -0
  104. package/.agent/skills/accessible-animation/SKILL.md +5 -1
  105. package/.agent/skills/adapt/SKILL.md +7 -1
  106. package/.agent/skills/advanced-rag-pipelines/SKILL.md +1 -0
  107. package/.agent/skills/agent-organizer/SKILL.md +1 -0
  108. package/.agent/skills/agentic-patterns/SKILL.md +33 -25
  109. package/.agent/skills/agentic-workflows-2026/SKILL.md +80 -0
  110. package/.agent/skills/ai-app-hardening/SKILL.md +59 -0
  111. package/.agent/skills/ai-prompt-injection-defense/SKILL.md +7 -6
  112. package/.agent/skills/animation-on-scroll/SKILL.md +24 -15
  113. package/.agent/skills/animation-systems/SKILL.md +11 -10
  114. package/.agent/skills/antfu-conventions/SKILL.md +7 -2
  115. package/.agent/skills/api-patterns/SKILL.md +14 -10
  116. package/.agent/skills/api-security-auditor/SKILL.md +15 -14
  117. package/.agent/skills/app-builder/SKILL.md +1 -0
  118. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +2 -2
  119. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +1 -1
  120. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +12 -12
  121. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +3 -3
  122. package/.agent/skills/apple-design/SKILL.md +8 -7
  123. package/.agent/skills/architecture/SKILL.md +3 -2
  124. package/.agent/skills/audit-and-fix/SKILL.md +8 -5
  125. package/.agent/skills/authentication-best-practices/SKILL.md +9 -8
  126. package/.agent/skills/backend-security-expert/SKILL.md +1 -0
  127. package/.agent/skills/baseline-ui/SKILL.md +8 -7
  128. package/.agent/skills/bash-linux/SKILL.md +1 -0
  129. package/.agent/skills/behavioral-modes/SKILL.md +1 -0
  130. package/.agent/skills/better-colors/SKILL.md +11 -7
  131. package/.agent/skills/better-typography/SKILL.md +30 -16
  132. package/.agent/skills/better-ui/SKILL.md +17 -10
  133. package/.agent/skills/bolder/SKILL.md +6 -0
  134. package/.agent/skills/brainstorming/SKILL.md +6 -4
  135. package/.agent/skills/browser-native-ai/SKILL.md +5 -4
  136. package/.agent/skills/build-primitive/SKILL.md +5 -0
  137. package/.agent/skills/building-native-ui/SKILL.md +1 -0
  138. package/.agent/skills/cicd-pro/SKILL.md +2 -1
  139. package/.agent/skills/clarify/SKILL.md +19 -14
  140. package/.agent/skills/clean-code/SKILL.md +16 -15
  141. package/.agent/skills/cloud-architect/SKILL.md +1 -0
  142. package/.agent/skills/cobejs/SKILL.md +7 -9
  143. package/.agent/skills/code-review-checklist/SKILL.md +1 -0
  144. package/.agent/skills/codebase-design/SKILL.md +7 -2
  145. package/.agent/skills/colorize/SKILL.md +8 -3
  146. package/.agent/skills/compact-landing/SKILL.md +8 -3
  147. package/.agent/skills/company-logos/SKILL.md +6 -0
  148. package/.agent/skills/config-validator/SKILL.md +10 -9
  149. package/.agent/skills/containerization-pro/SKILL.md +6 -5
  150. package/.agent/skills/context-engineering-pro/SKILL.md +70 -0
  151. package/.agent/skills/create-design-md/SKILL.md +13 -5
  152. package/.agent/skills/critique/SKILL.md +10 -8
  153. package/.agent/skills/csharp-developer/SKILL.md +1 -0
  154. package/.agent/skills/data-validation-schemas/SKILL.md +28 -23
  155. package/.agent/skills/database-design/SKILL.md +2 -1
  156. package/.agent/skills/delight/SKILL.md +6 -0
  157. package/.agent/skills/deployment-procedures/SKILL.md +2 -1
  158. package/.agent/skills/design-lab/SKILL.md +5 -0
  159. package/.agent/skills/devops-engineer/SKILL.md +3 -2
  160. package/.agent/skills/devops-incident-responder/SKILL.md +2 -1
  161. package/.agent/skills/diagnosing-bugs/SKILL.md +12 -2
  162. package/.agent/skills/distill/SKILL.md +7 -2
  163. package/.agent/skills/documentation-templates/SKILL.md +3 -2
  164. package/.agent/skills/domain-modeling/SKILL.md +12 -4
  165. package/.agent/skills/duckdb-analytical-sql/SKILL.md +59 -0
  166. package/.agent/skills/edge-ai-mobile/SKILL.md +50 -0
  167. package/.agent/skills/edge-computing/SKILL.md +9 -8
  168. package/.agent/skills/emil-design-eng/SKILL.md +43 -27
  169. package/.agent/skills/error-resilience/SKILL.md +34 -16
  170. package/.agent/skills/expo-router-v4/SKILL.md +81 -0
  171. package/.agent/skills/extract-design-system/SKILL.md +12 -11
  172. package/.agent/skills/fabel-protocol/SKILL.md +24 -17
  173. package/.agent/skills/fixing-accessibility/SKILL.md +23 -16
  174. package/.agent/skills/fixing-metadata/SKILL.md +24 -13
  175. package/.agent/skills/fixing-motion-performance/SKILL.md +7 -5
  176. package/.agent/skills/framer-motion-expert/SKILL.md +29 -15
  177. package/.agent/skills/frontend-design/SKILL.md +21 -13
  178. package/.agent/skills/frontend-security-expert/SKILL.md +1 -0
  179. package/.agent/skills/game-design-expert/SKILL.md +1 -0
  180. package/.agent/skills/game-engineering-expert/SKILL.md +1 -0
  181. package/.agent/skills/generative-ui-expert/SKILL.md +3 -2
  182. package/.agent/skills/geo-fundamentals/SKILL.md +2 -1
  183. package/.agent/skills/git-pro/SKILL.md +10 -9
  184. package/.agent/skills/github-operations/SKILL.md +2 -1
  185. package/.agent/skills/gpt-taste/SKILL.md +7 -0
  186. package/.agent/skills/gsap-core/SKILL.md +26 -22
  187. package/.agent/skills/gsap-frameworks/SKILL.md +6 -5
  188. package/.agent/skills/gsap-performance/SKILL.md +4 -3
  189. package/.agent/skills/gsap-plugins/SKILL.md +34 -33
  190. package/.agent/skills/gsap-react/SKILL.md +9 -8
  191. package/.agent/skills/gsap-scrolltrigger/SKILL.md +34 -33
  192. package/.agent/skills/gsap-timeline/SKILL.md +18 -15
  193. package/.agent/skills/gsap-utils/SKILL.md +25 -24
  194. package/.agent/skills/harden/SKILL.md +9 -3
  195. package/.agent/skills/harness-protocol/SKILL.md +1 -0
  196. package/.agent/skills/i18n-localization/SKILL.md +10 -9
  197. package/.agent/skills/impeccable/SKILL.md +5 -0
  198. package/.agent/skills/improve-codebase-architecture/SKILL.md +10 -5
  199. package/.agent/skills/improve-ui/SKILL.md +12 -5
  200. package/.agent/skills/intelligent-routing/SKILL.md +7 -6
  201. package/.agent/skills/knowledge-graph/SKILL.md +1 -0
  202. package/.agent/skills/landing-page/SKILL.md +1 -0
  203. package/.agent/skills/lint-and-validate/SKILL.md +9 -4
  204. package/.agent/skills/llm-engineering/SKILL.md +55 -54
  205. package/.agent/skills/local-first/SKILL.md +20 -19
  206. package/.agent/skills/local-first-architecture/SKILL.md +6 -1
  207. package/.agent/skills/lottie-animation/SKILL.md +7 -3
  208. package/.agent/skills/marquee-loop/SKILL.md +1 -0
  209. package/.agent/skills/masked-reveal/SKILL.md +17 -4
  210. package/.agent/skills/mcp-builder/SKILL.md +13 -10
  211. package/.agent/skills/micro-interaction/SKILL.md +20 -5
  212. package/.agent/skills/mobile-design/SKILL.md +26 -15
  213. package/.agent/skills/monorepo-management/SKILL.md +3 -2
  214. package/.agent/skills/morphing-icons/SKILL.md +16 -6
  215. package/.agent/skills/motion-engineering/SKILL.md +19 -15
  216. package/.agent/skills/nextjs-react-expert/SKILL.md +26 -21
  217. package/.agent/skills/nodejs-best-practices/SKILL.md +89 -76
  218. package/.agent/skills/observability/SKILL.md +45 -44
  219. package/.agent/skills/opentelemetry-observability/SKILL.md +59 -0
  220. package/.agent/skills/page-transition-animation/SKILL.md +6 -3
  221. package/.agent/skills/parallel-agents/SKILL.md +7 -2
  222. package/.agent/skills/performance-profiling/SKILL.md +24 -13
  223. package/.agent/skills/plan-writing/SKILL.md +1 -0
  224. package/.agent/skills/platform-engineer/SKILL.md +3 -2
  225. package/.agent/skills/platform-engineering-opentofu/SKILL.md +68 -0
  226. package/.agent/skills/playwright-ai-e2e/SKILL.md +60 -0
  227. package/.agent/skills/playwright-best-practices/SKILL.md +29 -28
  228. package/.agent/skills/polish/SKILL.md +13 -12
  229. package/.agent/skills/powershell-windows/SKILL.md +1 -0
  230. package/.agent/skills/pricing-page/SKILL.md +8 -3
  231. package/.agent/skills/product-aware-heuristics/SKILL.md +122 -72
  232. package/.agent/skills/progressive-blur/SKILL.md +9 -4
  233. package/.agent/skills/project-idioms/SKILL.md +1 -0
  234. package/.agent/skills/property-based-testing/SKILL.md +58 -0
  235. package/.agent/skills/python-patterns/SKILL.md +1 -0
  236. package/.agent/skills/python-pro/SKILL.md +1 -0
  237. package/.agent/skills/quieter/SKILL.md +6 -0
  238. package/.agent/skills/react-doctor/SKILL.md +6 -0
  239. package/.agent/skills/react-specialist/SKILL.md +32 -28
  240. package/.agent/skills/readme-builder/SKILL.md +1 -0
  241. package/.agent/skills/realtime-patterns/SKILL.md +34 -33
  242. package/.agent/skills/red-team-tactics/SKILL.md +1 -0
  243. package/.agent/skills/redesign-skill/SKILL.md +6 -0
  244. package/.agent/skills/review-animations/SKILL.md +5 -2
  245. package/.agent/skills/review-animations/STANDARDS.md +37 -23
  246. package/.agent/skills/rust-pro/SKILL.md +1 -0
  247. package/.agent/skills/seo-fundamentals/SKILL.md +4 -3
  248. package/.agent/skills/server-management/SKILL.md +1 -0
  249. package/.agent/skills/shadcn-ui-expert/SKILL.md +28 -22
  250. package/.agent/skills/shape/SKILL.md +9 -2
  251. package/.agent/skills/skill-creator/SKILL.md +1 -0
  252. package/.agent/skills/soft-skill/SKILL.md +6 -0
  253. package/.agent/skills/sounds-on-the-web/SKILL.md +1 -0
  254. package/.agent/skills/sql-pro/SKILL.md +1 -0
  255. package/.agent/skills/supabase-postgres-best-practices/SKILL.md +1 -0
  256. package/.agent/skills/svg-animation/SKILL.md +16 -7
  257. package/.agent/skills/swiftui-expert/SKILL.md +1 -0
  258. package/.agent/skills/swiss-design/SKILL.md +5 -0
  259. package/.agent/skills/system-design-pro/SKILL.md +1 -0
  260. package/.agent/skills/systematic-debugging/SKILL.md +1 -0
  261. package/.agent/skills/tailwind-patterns/SKILL.md +25 -11
  262. package/.agent/skills/taste-skill/SKILL.md +6 -0
  263. package/.agent/skills/tdd-workflow/SKILL.md +5 -0
  264. package/.agent/skills/test-result-analyzer/SKILL.md +1 -0
  265. package/.agent/skills/testing-patterns/SKILL.md +123 -115
  266. package/.agent/skills/thermo-nuclear-code-quality-review/SKILL.md +5 -0
  267. package/.agent/skills/thinking-protocol/SKILL.md +3 -0
  268. package/.agent/skills/to-spring-or-not-to-spring/SKILL.md +9 -8
  269. package/.agent/skills/transitions-dev/SKILL.md +19 -6
  270. package/.agent/skills/trend-researcher/SKILL.md +1 -0
  271. package/.agent/skills/typescript-advanced/SKILL.md +23 -18
  272. package/.agent/skills/typeset/SKILL.md +10 -1
  273. package/.agent/skills/ui-reasoning-engine/SKILL.md +67 -48
  274. package/.agent/skills/ui-skill-packs/SKILL.md +6 -1
  275. package/.agent/skills/ui-skills-root/SKILL.md +39 -38
  276. package/.agent/skills/ui-ux-pro-max/SKILL.md +34 -26
  277. package/.agent/skills/ui-ux-researcher/SKILL.md +1 -0
  278. package/.agent/skills/vector-search-pgvector/SKILL.md +78 -0
  279. package/.agent/skills/vue-expert/SKILL.md +22 -19
  280. package/.agent/skills/vulnerability-scanner/SKILL.md +22 -21
  281. package/.agent/skills/web-accessibility-auditor/SKILL.md +2 -1
  282. package/.agent/skills/web-design-guidelines/SKILL.md +16 -10
  283. package/.agent/skills/web-quality-audit/SKILL.md +5 -0
  284. package/.agent/skills/webapp-testing/SKILL.md +14 -13
  285. package/.agent/skills/webgpu-performance/SKILL.md +1 -0
  286. package/.agent/skills/whimsy-injector/SKILL.md +9 -5
  287. package/.agent/skills/workflow-optimizer/SKILL.md +1 -0
  288. package/.agent/skills/zero-trust-passkeys/SKILL.md +90 -0
  289. package/.agent/templates/DESIGN.md +119 -110
  290. package/.agent/templates/design-tokens.json +9 -6
  291. package/.agent/workflows/acf.md +1 -0
  292. package/.agent/workflows/api-tester.md +1 -0
  293. package/.agent/workflows/audit.md +1 -0
  294. package/.agent/workflows/brainstorm.md +1 -0
  295. package/.agent/workflows/changelog.md +1 -0
  296. package/.agent/workflows/contract.md +60 -0
  297. package/.agent/workflows/create.md +1 -0
  298. package/.agent/workflows/debug.md +1 -0
  299. package/.agent/workflows/deploy.md +1 -0
  300. package/.agent/workflows/enhance.md +1 -0
  301. package/.agent/workflows/fix-ci.md +89 -0
  302. package/.agent/workflows/fix.md +1 -0
  303. package/.agent/workflows/generate.md +1 -0
  304. package/.agent/workflows/marathon.md +1 -0
  305. package/.agent/workflows/migrate.md +1 -0
  306. package/.agent/workflows/minimal.md +9 -7
  307. package/.agent/workflows/orchestrate.md +1 -0
  308. package/.agent/workflows/performance-benchmarker.md +1 -0
  309. package/.agent/workflows/pipeline.md +26 -21
  310. package/.agent/workflows/plan.md +1 -0
  311. package/.agent/workflows/preview.md +1 -0
  312. package/.agent/workflows/refactor.md +3 -2
  313. package/.agent/workflows/review-ai.md +4 -3
  314. package/.agent/workflows/review.md +1 -0
  315. package/.agent/workflows/session.md +1 -0
  316. package/.agent/workflows/status.md +1 -0
  317. package/.agent/workflows/strengthen-skills.md +1 -0
  318. package/.agent/workflows/super-prompt.md +1 -0
  319. package/.agent/workflows/swarm.md +15 -3
  320. package/.agent/workflows/test.md +8 -7
  321. package/.agent/workflows/tribunal-backend.md +3 -2
  322. package/.agent/workflows/tribunal-cicd.md +104 -0
  323. package/.agent/workflows/tribunal-database.md +1 -0
  324. package/.agent/workflows/tribunal-frontend.md +8 -6
  325. package/.agent/workflows/tribunal-full.md +15 -14
  326. package/.agent/workflows/tribunal-mobile.md +6 -5
  327. package/.agent/workflows/tribunal-performance.md +1 -0
  328. package/.agent/workflows/tribunal-speed.md +1 -0
  329. package/.agent/workflows/tribunal-ui.md +29 -21
  330. package/.agent/workflows/ui-ux-pro-max.md +19 -15
  331. package/CONTRIBUTING.md +3 -3
  332. package/README.md +160 -88
  333. package/SECURITY.md +11 -11
  334. package/bin/mcp-server.js +512 -233
  335. package/bin/tribunal-kit.js +29 -30
  336. package/bin/wrapper.js +45 -48
  337. package/dist/cli.js +26 -0
  338. package/dist/commands/case.js +2 -0
  339. package/dist/commands/contract.js +440 -0
  340. package/dist/commands/memory.js +3 -2
  341. package/dist/commands/native.js +36 -0
  342. package/dist/commands/status.js +6 -0
  343. package/dist/esm/index.mjs +32 -0
  344. package/dist/index.d.ts +58 -3
  345. package/package.json +20 -16
  346. package/scripts/benchmark.js +62 -86
  347. package/scripts/changelog.js +67 -73
  348. package/scripts/fix-vbc.js +13 -15
  349. package/scripts/fix-vbc.ps1 +2 -118
  350. package/scripts/stress_benchmark.js +358 -0
  351. package/scripts/sync-version.js +71 -41
  352. package/scripts/validate-payload.js +23 -30
  353. package/scripts/visual_audit.js +23 -13
@@ -33,10 +33,10 @@
33
33
  * }
34
34
  */
35
35
 
36
- "use strict";
36
+ 'use strict';
37
37
 
38
- const fs = require("fs");
39
- const path = require("path");
38
+ const fs = require('fs');
39
+ const path = require('path');
40
40
 
41
41
  // ── Resolve security_scan patterns (reuse — do not duplicate) ─────────────
42
42
  const SCRIPT_DIR = __dirname;
@@ -44,7 +44,7 @@ let SECURITY_PATTERNS = [];
44
44
  let SEVERITY_RANK = {};
45
45
 
46
46
  try {
47
- const secScan = require(path.join(SCRIPT_DIR, "security_scan.js"));
47
+ const secScan = require(path.join(SCRIPT_DIR, 'security_scan.js'));
48
48
  SECURITY_PATTERNS = secScan.PATTERNS || [];
49
49
  SEVERITY_RANK = secScan.SEVERITY_RANK || {
50
50
  critical: 0,
@@ -57,23 +57,13 @@ try {
57
57
  SECURITY_PATTERNS = [
58
58
  [
59
59
  /(?:password|passwd)\s*=\s*["'][^"']+["']/i,
60
- "critical",
61
- "Hardcoded Secret",
62
- "Hardcoded password",
63
- ],
64
- [
65
- /\beval\s*\(/,
66
- "high",
67
- "Code Injection",
68
- "eval() is a code injection vector",
69
- ],
70
- [/\.innerHTML\s*=/, "high", "XSS", "Direct innerHTML assignment"],
71
- [
72
- /algorithms\s*:\s*\[\s*["']none["']/,
73
- "critical",
74
- "Auth Bypass",
75
- "JWT 'none' algorithm",
60
+ 'critical',
61
+ 'Hardcoded Secret',
62
+ 'Hardcoded password',
76
63
  ],
64
+ [/\beval\s*\(/, 'high', 'Code Injection', 'eval() is a code injection vector'],
65
+ [/\.innerHTML\s*=/, 'high', 'XSS', 'Direct innerHTML assignment'],
66
+ [/algorithms\s*:\s*\[\s*["']none["']/, 'critical', 'Auth Bypass', "JWT 'none' algorithm"],
77
67
  ];
78
68
  SEVERITY_RANK = { critical: 0, high: 1, medium: 2, low: 3 };
79
69
  }
@@ -83,68 +73,64 @@ try {
83
73
  const SYNTAX_HEURISTICS = [
84
74
  {
85
75
  pattern: /\bconst\s+\w+\s*=\s*require\s*\(\s*["'](?!\.\/|\.\.\/|[a-zA-Z])/,
86
- severity: "medium",
87
- category: "Hallucination Risk",
88
- message: "Suspicious require() path — verify module exists in package.json",
89
- fix: "Check that this package is listed in package.json dependencies",
76
+ severity: 'medium',
77
+ category: 'Hallucination Risk',
78
+ message: 'Suspicious require() path — verify module exists in package.json',
79
+ fix: 'Check that this package is listed in package.json dependencies',
90
80
  },
91
81
  {
92
82
  pattern: /\/\/\s*VERIFY:/,
93
- severity: "low",
94
- category: "Verification Flag",
95
- message:
96
- "Maker Agent flagged this line as uncertainhuman review required",
97
- fix: "The Maker Agent marked this with // VERIFY: — confirm before approving",
83
+ severity: 'low',
84
+ category: 'Verification Flag',
85
+ message: 'Maker Agent flagged this line as uncertain — human review required',
86
+ fix: 'The Maker Agent marked this with // VERIFY:confirm before approving',
98
87
  },
99
88
  {
100
89
  pattern: /:\s*any\b(?!\s*=)/,
101
- severity: "low",
102
- category: "Type Safety",
103
- message: "TypeScript `any` type used without explanation comment",
104
- fix: "Replace :any with a specific type, or add // any: [reason] comment",
90
+ severity: 'low',
91
+ category: 'Type Safety',
92
+ message: 'TypeScript `any` type used without explanation comment',
93
+ fix: 'Replace :any with a specific type, or add // any: [reason] comment',
105
94
  },
106
95
  {
107
96
  pattern: /process\.env\.\w+(?!\s*\?\?|\s*\|\|)/,
108
- severity: "low",
109
- category: "Config Safety",
110
- message:
111
- "process.env access without nullish fallback — may throw at runtime",
97
+ severity: 'low',
98
+ category: 'Config Safety',
99
+ message: 'process.env access without nullish fallback — may throw at runtime',
112
100
  fix: 'Use: process.env.VAR ?? "default" — always guard env var access',
113
101
  },
114
102
  {
115
103
  pattern: /throw\s+["'`]/,
116
- severity: "low",
117
- category: "Error Quality",
118
- message:
119
- "Throwing a string instead of an Error object — stack traces will be lost",
104
+ severity: 'low',
105
+ category: 'Error Quality',
106
+ message: 'Throwing a string instead of an Error object — stack traces will be lost',
120
107
  fix: 'Use: throw new Error("message") instead of throw "message"',
121
108
  },
122
109
  {
123
110
  pattern: /catch\s*\(\s*\w+\s*\)\s*\{?\s*\}/,
124
- severity: "medium",
125
- category: "Error Handling",
126
- message: "Empty catch block swallows errors silently",
127
- fix: "Add at minimum: catch (err) { console.error(err); throw err; }",
111
+ severity: 'medium',
112
+ category: 'Error Handling',
113
+ message: 'Empty catch block swallows errors silently',
114
+ fix: 'Add at minimum: catch (err) { console.error(err); throw err; }',
128
115
  },
129
116
  {
130
117
  pattern: /\.then\(\s*\)\s*\.catch\s*\(|\.catch\s*\(\s*\)/,
131
- severity: "medium",
132
- category: "Error Handling",
133
- message:
134
- "Empty .then() or .catch() handler Promise errors may be silenced",
135
- fix: "Implement proper resolution and rejection handlers",
118
+ severity: 'medium',
119
+ category: 'Error Handling',
120
+ message: 'Empty .then() or .catch() handler — Promise errors may be silenced',
121
+ fix: 'Implement proper resolution and rejection handlers',
136
122
  },
137
123
  {
138
124
  pattern: /window\.|document\.|navigator\./,
139
- severity: "low",
140
- category: "Environment Check",
141
- message: "Browser global access — may fail in SSR/Node environments",
125
+ severity: 'low',
126
+ category: 'Environment Check',
127
+ message: 'Browser global access — may fail in SSR/Node environments',
142
128
  fix: 'Guard with: typeof window !== "undefined" before accessing browser globals',
143
129
  },
144
130
  ];
145
131
 
146
132
  // ── ANSI colors (centralized via _colors.js) ─────────────────────────────
147
- const { GREEN, YELLOW, RED, CYAN, BOLD, DIM, RESET } = require("./_colors");
133
+ const { GREEN, YELLOW, RED, CYAN, BOLD, DIM, RESET } = require('./_colors');
148
134
 
149
135
  // ── Core scanning ─────────────────────────────────────────────────────────
150
136
 
@@ -156,20 +142,16 @@ const { GREEN, YELLOW, RED, CYAN, BOLD, DIM, RESET } = require("./_colors");
156
142
  * @param {string} [lang] - Language hint ('js' | 'ts' | 'py' | 'jsx' | 'tsx')
157
143
  * @returns {Array<{severity, category, line, message, fix, source}>}
158
144
  */
159
- function scanCode(code, _lang = "js") {
145
+ function scanCode(code, _lang = 'js') {
160
146
  const findings = [];
161
- const lines = code.split("\n");
147
+ const lines = code.split('\n');
162
148
 
163
149
  for (let i = 0; i < lines.length; i++) {
164
150
  const stripped = lines[i].trim();
165
151
  const lineNum = i + 1;
166
152
 
167
153
  // Skip pure comments
168
- if (
169
- stripped.startsWith("//") ||
170
- stripped.startsWith("#") ||
171
- stripped.startsWith("*")
172
- ) {
154
+ if (stripped.startsWith('//') || stripped.startsWith('#') || stripped.startsWith('*')) {
173
155
  continue;
174
156
  }
175
157
 
@@ -182,7 +164,7 @@ function scanCode(code, _lang = "js") {
182
164
  line: lineNum,
183
165
  message,
184
166
  fix: buildSecurityFix(category),
185
- source: "security_scan",
167
+ source: 'security_scan',
186
168
  });
187
169
  }
188
170
  }
@@ -196,7 +178,7 @@ function scanCode(code, _lang = "js") {
196
178
  line: lineNum,
197
179
  message: h.message,
198
180
  fix: h.fix,
199
- source: "heuristic",
181
+ source: 'heuristic',
200
182
  });
201
183
  }
202
184
  }
@@ -212,26 +194,18 @@ function scanCode(code, _lang = "js") {
212
194
  */
213
195
  function buildSecurityFix(category) {
214
196
  const fixes = {
215
- "Hardcoded Secret": "Move to environment variable: process.env.SECRET_NAME",
216
- "SQL Injection":
217
- "Use parameterized queries. Never interpolate user input into SQL.",
218
- XSS: "Use textContent instead of innerHTML. Sanitize with DOMPurify if HTML is needed.",
219
- "Code Injection":
220
- "Remove eval()/new Function(). Use a safe alternative or a JSON parser.",
221
- "Command Injection":
222
- "Use execFile() with an args array instead of exec() with a shell string.",
223
- "Weak Crypto":
224
- 'Use crypto.createHash("sha256") or bcrypt for password hashing.',
225
- "Weak Randomness":
226
- "Use crypto.randomBytes(n) or crypto.randomUUID() for security-sensitive values.",
227
- "Auth Bypass":
228
- 'Enforce JWT algorithm explicitly: { algorithms: ["HS256"] }',
229
- "Info Disclosure":
230
- "Remove logging of sensitive values. Use structured logging with redaction.",
197
+ 'Hardcoded Secret': 'Move to environment variable: process.env.SECRET_NAME',
198
+ 'SQL Injection': 'Use parameterized queries. Never interpolate user input into SQL.',
199
+ XSS: 'Use textContent instead of innerHTML. Sanitize with DOMPurify if HTML is needed.',
200
+ 'Code Injection': 'Remove eval()/new Function(). Use a safe alternative or a JSON parser.',
201
+ 'Command Injection': 'Use execFile() with an args array instead of exec() with a shell string.',
202
+ 'Weak Crypto': 'Use crypto.createHash("sha256") or bcrypt for password hashing.',
203
+ 'Weak Randomness':
204
+ 'Use crypto.randomBytes(n) or crypto.randomUUID() for security-sensitive values.',
205
+ 'Auth Bypass': 'Enforce JWT algorithm explicitly: { algorithms: ["HS256"] }',
206
+ 'Info Disclosure': 'Remove logging of sensitive values. Use structured logging with redaction.',
231
207
  };
232
- return (
233
- fixes[category] || "Review and remediate according to OWASP guidelines."
234
- );
208
+ return fixes[category] || 'Review and remediate according to OWASP guidelines.';
235
209
  }
236
210
 
237
211
  /**
@@ -243,15 +217,15 @@ function buildSecurityFix(category) {
243
217
  */
244
218
  function computeVerdict(findings) {
245
219
  // Filter out VERIFY flags from blocking logic — they are informational
246
- const blocking = findings.filter((f) => f.category !== "Verification Flag");
220
+ const blocking = findings.filter(f => f.category !== 'Verification Flag');
247
221
  const maxSeverityRank = blocking.reduce((min, f) => {
248
222
  const rank = SEVERITY_RANK[f.severity] ?? 3;
249
223
  return rank < min ? rank : min;
250
224
  }, 4); // 4 = no findings
251
225
 
252
- if (maxSeverityRank <= 1) return { verdict: "REJECTED", passed: false }; // critical or high
253
- if (maxSeverityRank === 2) return { verdict: "WARNING", passed: true }; // medium
254
- return { verdict: "APPROVED", passed: true };
226
+ if (maxSeverityRank <= 1) return { verdict: 'REJECTED', passed: false }; // critical or high
227
+ if (maxSeverityRank === 2) return { verdict: 'WARNING', passed: true }; // medium
228
+ return { verdict: 'APPROVED', passed: true };
255
229
  }
256
230
 
257
231
  /**
@@ -262,7 +236,7 @@ function computeVerdict(findings) {
262
236
  * @returns {string|null}
263
237
  */
264
238
  function buildSelfHealingInstructions(findings) {
265
- const blocking = findings.filter((f) => {
239
+ const blocking = findings.filter(f => {
266
240
  const rank = SEVERITY_RANK[f.severity] ?? 3;
267
241
  return rank <= 1; // critical + high only
268
242
  });
@@ -270,20 +244,18 @@ function buildSelfHealingInstructions(findings) {
270
244
  if (!blocking.length) return null;
271
245
 
272
246
  const lines = [
273
- "⚠️ Inner-Loop Validator found blocking issues. Auto-correct the following before writing to disk:\n",
247
+ '⚠️ Inner-Loop Validator found blocking issues. Auto-correct the following before writing to disk:\n',
274
248
  ];
275
249
 
276
250
  for (const f of blocking) {
277
251
  lines.push(`[${f.severity.toUpperCase()}] Line ${f.line} — ${f.category}`);
278
252
  lines.push(` Issue: ${f.message}`);
279
253
  lines.push(` Fix: ${f.fix}`);
280
- lines.push("");
254
+ lines.push('');
281
255
  }
282
256
 
283
- lines.push(
284
- "Re-generate the affected lines only. Do not change unaffected code.",
285
- );
286
- return lines.join("\n");
257
+ lines.push('Re-generate the affected lines only. Do not change unaffected code.');
258
+ return lines.join('\n');
287
259
  }
288
260
 
289
261
  // ── Output ────────────────────────────────────────────────────────────────
@@ -291,26 +263,20 @@ function buildSelfHealingInstructions(findings) {
291
263
  function printHumanReport(result) {
292
264
  const { verdict, issues, summary, self_healing_instructions } = result;
293
265
 
294
- const verdictColor =
295
- verdict === "APPROVED" ? GREEN : verdict === "WARNING" ? YELLOW : RED;
296
- const verdictIcon =
297
- verdict === "APPROVED" ? "✅" : verdict === "WARNING" ? "⚠️" : "❌";
298
-
299
- console.error(
300
- `\n${BOLD}${CYAN}━━━ Inner-Loop Validator ━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`,
301
- );
302
- console.error(
303
- ` Verdict: ${verdictColor}${BOLD}${verdictIcon} ${verdict}${RESET}`,
304
- );
266
+ const verdictColor = verdict === 'APPROVED' ? GREEN : verdict === 'WARNING' ? YELLOW : RED;
267
+ const verdictIcon = verdict === 'APPROVED' ? '✅' : verdict === 'WARNING' ? '⚠️' : '❌';
268
+
269
+ console.error(`\n${BOLD}${CYAN}━━━ Inner-Loop Validator ━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
270
+ console.error(` Verdict: ${verdictColor}${BOLD}${verdictIcon} ${verdict}${RESET}`);
305
271
  console.error(` Summary: ${summary}`);
306
272
 
307
273
  if (issues.length) {
308
274
  console.error(`\n ${BOLD}Issues found:${RESET}`);
309
275
  for (const iss of issues) {
310
276
  const color =
311
- iss.severity === "critical" || iss.severity === "high"
277
+ iss.severity === 'critical' || iss.severity === 'high'
312
278
  ? RED
313
- : iss.severity === "medium"
279
+ : iss.severity === 'medium'
314
280
  ? YELLOW
315
281
  : DIM;
316
282
  console.error(
@@ -322,28 +288,22 @@ function printHumanReport(result) {
322
288
  }
323
289
 
324
290
  if (self_healing_instructions) {
325
- console.error(
326
- `\n ${YELLOW}${BOLD}Self-Healing Instructions (for Maker Agent):${RESET}`,
327
- );
291
+ console.error(`\n ${YELLOW}${BOLD}Self-Healing Instructions (for Maker Agent):${RESET}`);
328
292
  console.error(
329
293
  self_healing_instructions
330
- .split("\n")
331
- .map((l) => ` ${l}`)
332
- .join("\n"),
294
+ .split('\n')
295
+ .map(l => ` ${l}`)
296
+ .join('\n'),
333
297
  );
334
298
  }
335
299
 
336
- console.error(
337
- `${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n`,
338
- );
300
+ console.error(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n`);
339
301
  }
340
302
 
341
303
  // ── Built-in test case ────────────────────────────────────────────────────
342
304
 
343
305
  function runTestCase() {
344
- console.error(
345
- `\n${BOLD}${CYAN}━━━ Inner-Loop Validator — Self-Test ━━━━━━━━━━━━━━${RESET}`,
346
- );
306
+ console.error(`\n${BOLD}${CYAN}━━━ Inner-Loop Validator — Self-Test ━━━━━━━━━━━━━━${RESET}`);
347
307
 
348
308
  const badCode = `
349
309
  const password = "supersecret123";
@@ -353,21 +313,17 @@ const token = eval(req.body.expr);
353
313
  const rand = Math.random() * 1000;
354
314
  `;
355
315
 
356
- const result = validate(badCode, "js");
316
+ const result = validate(badCode, 'js');
357
317
  printHumanReport(result);
358
318
 
359
- const hasCritical = result.issues.some(
360
- (i) => i.severity === "critical" || i.severity === "high",
361
- );
362
- if (hasCritical && result.verdict === "REJECTED") {
319
+ const hasCritical = result.issues.some(i => i.severity === 'critical' || i.severity === 'high');
320
+ if (hasCritical && result.verdict === 'REJECTED') {
363
321
  console.error(
364
322
  `${GREEN}✅ Self-test PASSED — validator correctly identified and blocked critical issues${RESET}\n`,
365
323
  );
366
324
  process.exit(0);
367
325
  } else {
368
- console.error(
369
- `${RED}❌ Self-test FAILED — expected REJECTED verdict for bad code${RESET}\n`,
370
- );
326
+ console.error(`${RED}❌ Self-test FAILED — expected REJECTED verdict for bad code${RESET}\n`);
371
327
  process.exit(1);
372
328
  }
373
329
  }
@@ -383,13 +339,13 @@ const rand = Math.random() * 1000;
383
339
  * @param {object} [opts] - Options: { timeout: number }
384
340
  * @returns {{ verdict, passed, issues, summary, self_healing_instructions }}
385
341
  */
386
- function validate(code, lang = "js", _opts = {}) {
387
- if (!code || typeof code !== "string") {
342
+ function validate(code, lang = 'js', _opts = {}) {
343
+ if (!code || typeof code !== 'string') {
388
344
  return {
389
- verdict: "APPROVED",
345
+ verdict: 'APPROVED',
390
346
  passed: true,
391
347
  issues: [],
392
- summary: "No code provided — skipped.",
348
+ summary: 'No code provided — skipped.',
393
349
  self_healing_instructions: null,
394
350
  };
395
351
  }
@@ -397,34 +353,28 @@ function validate(code, lang = "js", _opts = {}) {
397
353
  const issues = scanCode(code, lang);
398
354
 
399
355
  // Sort by severity rank
400
- issues.sort(
401
- (a, b) =>
402
- (SEVERITY_RANK[a.severity] ?? 3) - (SEVERITY_RANK[b.severity] ?? 3),
403
- );
356
+ issues.sort((a, b) => (SEVERITY_RANK[a.severity] ?? 3) - (SEVERITY_RANK[b.severity] ?? 3));
404
357
 
405
358
  const { verdict, passed } = computeVerdict(issues);
406
359
  const healingInstructions = buildSelfHealingInstructions(issues);
407
360
 
408
- const critCount = issues.filter((i) => i.severity === "critical").length;
409
- const highCount = issues.filter((i) => i.severity === "high").length;
410
- const medCount = issues.filter((i) => i.severity === "medium").length;
411
- const lowCount = issues.filter((i) => i.severity === "low").length;
412
- const verifyCount = issues.filter(
413
- (i) => i.category === "Verification Flag",
414
- ).length;
361
+ const critCount = issues.filter(i => i.severity === 'critical').length;
362
+ const highCount = issues.filter(i => i.severity === 'high').length;
363
+ const medCount = issues.filter(i => i.severity === 'medium').length;
364
+ const lowCount = issues.filter(i => i.severity === 'low').length;
365
+ const verifyCount = issues.filter(i => i.category === 'Verification Flag').length;
415
366
 
416
367
  let summary = `${issues.length} issue(s) found`;
417
368
  if (!issues.length) {
418
- summary = "No issues detected — code is clean";
369
+ summary = 'No issues detected — code is clean';
419
370
  } else {
420
371
  const parts = [];
421
372
  if (critCount) parts.push(`${critCount} critical`);
422
373
  if (highCount) parts.push(`${highCount} high`);
423
374
  if (medCount) parts.push(`${medCount} medium`);
424
375
  if (lowCount) parts.push(`${lowCount} low`);
425
- if (verifyCount)
426
- parts.push(`${verifyCount} VERIFY flag(s) need human review`);
427
- summary = parts.join(", ");
376
+ if (verifyCount) parts.push(`${verifyCount} VERIFY flag(s) need human review`);
377
+ summary = parts.join(', ');
428
378
  }
429
379
 
430
380
  return {
@@ -434,7 +384,7 @@ function validate(code, lang = "js", _opts = {}) {
434
384
  summary,
435
385
  self_healing_instructions: healingInstructions,
436
386
  meta: {
437
- lines_scanned: code.split("\n").length,
387
+ lines_scanned: code.split('\n').length,
438
388
  lang,
439
389
  timestamp: new Date().toISOString(),
440
390
  },
@@ -443,6 +393,7 @@ function validate(code, lang = "js", _opts = {}) {
443
393
 
444
394
  module.exports = {
445
395
  validate,
396
+ validateSnippet: validate,
446
397
  scanCode,
447
398
  computeVerdict,
448
399
  buildSelfHealingInstructions,
@@ -453,7 +404,7 @@ module.exports = {
453
404
  if (require.main === module) {
454
405
  const argv = process.argv.slice(2);
455
406
 
456
- if (!argv.length || argv.includes("--help") || argv.includes("-h")) {
407
+ if (!argv.length || argv.includes('--help') || argv.includes('-h')) {
457
408
  console.log(`
458
409
  ${BOLD}inner_loop_validator.js${RESET} — Tribunal Self-Healing CI
459
410
 
@@ -475,19 +426,19 @@ ${BOLD}Verdict:${RESET}
475
426
  }
476
427
 
477
428
  // Built-in self-test
478
- if (argv[0] === "test-case") {
429
+ if (argv[0] === 'test-case') {
479
430
  runTestCase();
480
431
  process.exit(0);
481
432
  }
482
433
 
483
- const jsonOnly = argv.includes("--json-only");
484
- const fileFlagIdx = argv.indexOf("--file");
485
- const snippetIdx = argv.indexOf("--snippet");
486
- const langIdx = argv.indexOf("--lang");
434
+ const jsonOnly = argv.includes('--json-only');
435
+ const fileFlagIdx = argv.indexOf('--file');
436
+ const snippetIdx = argv.indexOf('--snippet');
437
+ const langIdx = argv.indexOf('--lang');
487
438
 
488
- const lang = langIdx !== -1 && argv[langIdx + 1] ? argv[langIdx + 1] : "js";
439
+ const lang = langIdx !== -1 && argv[langIdx + 1] ? argv[langIdx + 1] : 'js';
489
440
 
490
- let code = "";
441
+ let code = '';
491
442
 
492
443
  if (fileFlagIdx !== -1 && argv[fileFlagIdx + 1]) {
493
444
  const filePath = path.resolve(argv[fileFlagIdx + 1]);
@@ -495,16 +446,14 @@ ${BOLD}Verdict:${RESET}
495
446
  console.error(`${RED}✖ File not found: ${filePath}${RESET}`);
496
447
  process.exit(1);
497
448
  }
498
- code = fs.readFileSync(filePath, "utf8");
449
+ code = fs.readFileSync(filePath, 'utf8');
499
450
  } else if (snippetIdx !== -1 && argv[snippetIdx + 1]) {
500
451
  code = argv[snippetIdx + 1];
501
452
  } else if (!process.stdin.isTTY) {
502
453
  // Read from stdin if piped (cross-platform, works on Windows)
503
- code = fs.readFileSync(0, "utf8");
454
+ code = fs.readFileSync(0, 'utf8');
504
455
  } else {
505
- console.error(
506
- `${RED}✖ Provide --snippet "<code>" or --file <path>${RESET}`,
507
- );
456
+ console.error(`${RED}✖ Provide --snippet "<code>" or --file <path>${RESET}`);
508
457
  process.exit(1);
509
458
  }
510
459