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
@@ -26,20 +26,32 @@
26
26
  * const { planPhase, buildPhase, validatePhase, fullPipeline } = require('./pipeline_engine');
27
27
  */
28
28
 
29
- "use strict";
29
+ 'use strict';
30
30
 
31
- const fs = require("fs");
32
- const path = require("path");
31
+ const fs = require('fs');
32
+ const path = require('path');
33
33
 
34
34
  // ── Shared Utilities ────────────────────────────────────────────────────────
35
- const { GREEN, YELLOW, CYAN, RED, BLUE, BOLD, DIM, RESET, banner, sectionHeader, timer } = require("./_colors");
36
- const { findAgentDir, parseArgs, loadJson } = require("./_utils");
35
+ const {
36
+ GREEN,
37
+ YELLOW,
38
+ CYAN,
39
+ RED,
40
+ BLUE,
41
+ BOLD,
42
+ DIM,
43
+ RESET,
44
+ banner,
45
+ sectionHeader,
46
+ timer,
47
+ } = require('./_colors');
48
+ const { findAgentDir, parseArgs, loadJson } = require('./_utils');
37
49
 
38
50
  // ── Lazy-load sibling scripts (avoid circular deps) ─────────────────────────
39
51
  let _contextBroker = null;
40
52
  function getContextBroker() {
41
53
  if (!_contextBroker) {
42
- _contextBroker = require(path.join(__dirname, "context_broker.js"));
54
+ _contextBroker = require(path.join(__dirname, 'context_broker.js'));
43
55
  }
44
56
  return _contextBroker;
45
57
  }
@@ -48,7 +60,7 @@ let _innerLoopValidator = null;
48
60
  function getInnerLoopValidator() {
49
61
  if (!_innerLoopValidator) {
50
62
  try {
51
- _innerLoopValidator = require(path.join(__dirname, "inner_loop_validator.js"));
63
+ _innerLoopValidator = require(path.join(__dirname, 'inner_loop_validator.js'));
52
64
  } catch {
53
65
  _innerLoopValidator = null;
54
66
  }
@@ -60,7 +72,7 @@ let _guardrailEngine = null;
60
72
  function _getGuardrailEngine() {
61
73
  if (!_guardrailEngine) {
62
74
  try {
63
- _guardrailEngine = require(path.join(__dirname, "guardrail_engine.js"));
75
+ _guardrailEngine = require(path.join(__dirname, 'guardrail_engine.js'));
64
76
  } catch {
65
77
  _guardrailEngine = null;
66
78
  }
@@ -72,7 +84,7 @@ let _minimalChangeEngine = null;
72
84
  function getMinimalChangeEngine() {
73
85
  if (!_minimalChangeEngine) {
74
86
  try {
75
- _minimalChangeEngine = require(path.join(__dirname, "minimal_change_engine.js"));
87
+ _minimalChangeEngine = require(path.join(__dirname, 'minimal_change_engine.js'));
76
88
  } catch {
77
89
  _minimalChangeEngine = null;
78
90
  }
@@ -80,42 +92,83 @@ function getMinimalChangeEngine() {
80
92
  return _minimalChangeEngine;
81
93
  }
82
94
 
83
-
84
95
  // ── Task Classification ─────────────────────────────────────────────────────
85
96
  // Lightweight intent detection — no LLM call needed.
86
97
 
87
98
  const TASK_TYPES = {
88
99
  frontend_component: {
89
- keywords: ["component", "page", "layout", "ui", "form", "modal", "dialog", "card", "hero", "nav", "sidebar", "dashboard", "landing"],
90
- stack_hint: ["react", "vue", "svelte", "html", "css"],
100
+ keywords: [
101
+ 'component',
102
+ 'page',
103
+ 'layout',
104
+ 'ui',
105
+ 'form',
106
+ 'modal',
107
+ 'dialog',
108
+ 'card',
109
+ 'hero',
110
+ 'nav',
111
+ 'sidebar',
112
+ 'dashboard',
113
+ 'landing',
114
+ ],
115
+ stack_hint: ['react', 'vue', 'svelte', 'html', 'css'],
91
116
  },
92
117
  frontend_page: {
93
- keywords: ["page", "landing", "dashboard", "home", "about", "pricing", "settings"],
94
- stack_hint: ["react", "next", "vue", "nuxt"],
118
+ keywords: ['page', 'landing', 'dashboard', 'home', 'about', 'pricing', 'settings'],
119
+ stack_hint: ['react', 'next', 'vue', 'nuxt'],
95
120
  },
96
121
  api_endpoint: {
97
- keywords: ["api", "endpoint", "route", "handler", "middleware", "controller", "rest", "graphql"],
98
- stack_hint: ["express", "fastapi", "hono", "node"],
122
+ keywords: [
123
+ 'api',
124
+ 'endpoint',
125
+ 'route',
126
+ 'handler',
127
+ 'middleware',
128
+ 'controller',
129
+ 'rest',
130
+ 'graphql',
131
+ ],
132
+ stack_hint: ['express', 'fastapi', 'hono', 'node'],
99
133
  },
100
134
  database_query: {
101
- keywords: ["query", "sql", "migration", "schema", "prisma", "drizzle", "orm", "table", "index"],
102
- stack_hint: ["prisma", "drizzle", "postgres", "mysql", "sql"],
135
+ keywords: ['query', 'sql', 'migration', 'schema', 'prisma', 'drizzle', 'orm', 'table', 'index'],
136
+ stack_hint: ['prisma', 'drizzle', 'postgres', 'mysql', 'sql'],
103
137
  },
104
138
  auth_flow: {
105
- keywords: ["auth", "login", "signup", "jwt", "oauth", "session", "password", "rbac", "permission"],
106
- stack_hint: ["jwt", "oauth", "next-auth"],
139
+ keywords: [
140
+ 'auth',
141
+ 'login',
142
+ 'signup',
143
+ 'jwt',
144
+ 'oauth',
145
+ 'session',
146
+ 'password',
147
+ 'rbac',
148
+ 'permission',
149
+ ],
150
+ stack_hint: ['jwt', 'oauth', 'next-auth'],
107
151
  },
108
152
  test_suite: {
109
- keywords: ["test", "spec", "jest", "vitest", "playwright", "e2e", "unit", "mock"],
110
- stack_hint: ["jest", "vitest", "playwright"],
153
+ keywords: ['test', 'spec', 'jest', 'vitest', 'playwright', 'e2e', 'unit', 'mock'],
154
+ stack_hint: ['jest', 'vitest', 'playwright'],
111
155
  },
112
156
  refactor: {
113
- keywords: ["refactor", "clean", "extract", "rename", "move", "split", "merge", "deduplicate"],
157
+ keywords: ['refactor', 'clean', 'extract', 'rename', 'move', 'split', 'merge', 'deduplicate'],
114
158
  stack_hint: [],
115
159
  },
116
160
  animation: {
117
- keywords: ["animation", "motion", "gsap", "framer", "transition", "scroll", "parallax", "hover"],
118
- stack_hint: ["gsap", "framer-motion", "css"],
161
+ keywords: [
162
+ 'animation',
163
+ 'motion',
164
+ 'gsap',
165
+ 'framer',
166
+ 'transition',
167
+ 'scroll',
168
+ 'parallax',
169
+ 'hover',
170
+ ],
171
+ stack_hint: ['gsap', 'framer-motion', 'css'],
119
172
  },
120
173
  general: {
121
174
  keywords: [],
@@ -125,18 +178,17 @@ const TASK_TYPES = {
125
178
 
126
179
  // Stack detection keywords
127
180
  const STACK_KEYWORDS = {
128
- react: ["react", "jsx", "tsx", "useState", "useEffect", "component"],
129
- nextjs: ["next", "nextjs", "server component", "server action", "app router"],
130
- vue: ["vue", "nuxt", "composition api", "ref(", "computed("],
131
- typescript: ["typescript", "ts", "interface", "type ", "generic"],
132
- python: ["python", "fastapi", "django", "flask", "pydantic"],
133
- node: ["node", "express", "hono", "koa"],
134
- css: ["css", "tailwind", "style", "responsive", "dark mode"],
135
- sql: ["sql", "postgres", "mysql", "prisma", "drizzle", "query"],
136
- rust: ["rust", "cargo", "tokio", "axum"],
181
+ react: ['react', 'jsx', 'tsx', 'useState', 'useEffect', 'component'],
182
+ nextjs: ['next', 'nextjs', 'server component', 'server action', 'app router'],
183
+ vue: ['vue', 'nuxt', 'composition api', 'ref(', 'computed('],
184
+ typescript: ['typescript', 'ts', 'interface', 'type ', 'generic'],
185
+ python: ['python', 'fastapi', 'django', 'flask', 'pydantic'],
186
+ node: ['node', 'express', 'hono', 'koa'],
187
+ css: ['css', 'tailwind', 'style', 'responsive', 'dark mode'],
188
+ sql: ['sql', 'postgres', 'mysql', 'prisma', 'drizzle', 'query'],
189
+ rust: ['rust', 'cargo', 'tokio', 'axum'],
137
190
  };
138
191
 
139
-
140
192
  // ══════════════════════════════════════════════════════════════════════════════
141
193
  // PASS 1 — PLANNER
142
194
  // Classify the task, detect stack, select minimal skills, emit structured spec.
@@ -152,11 +204,22 @@ const STACK_KEYWORDS = {
152
204
  * @returns {object} Structured spec JSON
153
205
  */
154
206
  function planPhase(task, files = [], agentDir = null) {
207
+ let taskStr = task;
208
+ let fileList = files;
209
+
210
+ if (typeof task === 'object' && task !== null) {
211
+ taskStr = task.task || task.spec || '';
212
+ if (task.files) fileList = task.files;
213
+ if (task.file) fileList = [task.file];
214
+ if (task.agentDir) agentDir = task.agentDir;
215
+ }
216
+ if (typeof taskStr !== 'string') taskStr = String(taskStr || '');
155
217
  const resolvedAgentDir = agentDir || findAgentDir();
156
- const taskLower = task.toLowerCase();
218
+ const taskLower = taskStr.toLowerCase();
219
+ files = Array.isArray(fileList) ? fileList : [fileList];
157
220
 
158
221
  // 1. Classify task type
159
- let bestType = "general";
222
+ let bestType = 'general';
160
223
  let bestScore = 0;
161
224
  for (const [type, config] of Object.entries(TASK_TYPES)) {
162
225
  let score = 0;
@@ -182,11 +245,15 @@ function planPhase(task, files = [], agentDir = null) {
182
245
 
183
246
  // Infer stack from file extensions
184
247
  const extToStack = {
185
- ".tsx": "react", ".jsx": "react",
186
- ".ts": "typescript", ".js": "node",
187
- ".vue": "vue", ".py": "python",
188
- ".rs": "rust", ".sql": "sql",
189
- ".css": "css",
248
+ '.tsx': 'react',
249
+ '.jsx': 'react',
250
+ '.ts': 'typescript',
251
+ '.js': 'node',
252
+ '.vue': 'vue',
253
+ '.py': 'python',
254
+ '.rs': 'rust',
255
+ '.sql': 'sql',
256
+ '.css': 'css',
190
257
  };
191
258
  for (const f of files) {
192
259
  const ext = path.extname(f).toLowerCase();
@@ -201,8 +268,8 @@ function planPhase(task, files = [], agentDir = null) {
201
268
  const selection = broker.selectSkills(
202
269
  task,
203
270
  files,
204
- "small", // Use small-model tier for aggressive pruning
205
- broker.loadSkills(resolvedAgentDir)
271
+ 'small', // Use small-model tier for aggressive pruning
272
+ broker.loadSkills(resolvedAgentDir),
206
273
  );
207
274
 
208
275
  // Take only top 3 essential skills for Pass 2
@@ -213,22 +280,30 @@ function planPhase(task, files = [], agentDir = null) {
213
280
 
214
281
  // 4. Extract constraints from task text
215
282
  const constraints = {};
216
- if (taskLower.includes("accessible") || taskLower.includes("a11y") || taskLower.includes("aria")) {
283
+ if (
284
+ taskLower.includes('accessible') ||
285
+ taskLower.includes('a11y') ||
286
+ taskLower.includes('aria')
287
+ ) {
217
288
  constraints.accessibility = true;
218
289
  }
219
- if (taskLower.includes("responsive") || taskLower.includes("mobile")) {
290
+ if (taskLower.includes('responsive') || taskLower.includes('mobile')) {
220
291
  constraints.responsive = true;
221
292
  }
222
- if (taskLower.includes("dark mode") || taskLower.includes("theme")) {
293
+ if (taskLower.includes('dark mode') || taskLower.includes('theme')) {
223
294
  constraints.dark_mode = true;
224
295
  }
225
- if (taskLower.includes("animation") || taskLower.includes("motion") || taskLower.includes("gsap")) {
296
+ if (
297
+ taskLower.includes('animation') ||
298
+ taskLower.includes('motion') ||
299
+ taskLower.includes('gsap')
300
+ ) {
226
301
  constraints.animation = true;
227
302
  }
228
- if (taskLower.includes("test") || taskLower.includes("spec")) {
303
+ if (taskLower.includes('test') || taskLower.includes('spec')) {
229
304
  constraints.tests_required = true;
230
305
  }
231
- if (taskLower.includes("typescript") || taskLower.includes("type-safe")) {
306
+ if (taskLower.includes('typescript') || taskLower.includes('type-safe')) {
232
307
  constraints.type_safe = true;
233
308
  }
234
309
 
@@ -240,15 +315,24 @@ function planPhase(task, files = [], agentDir = null) {
240
315
  let socraticGatePolicy = null;
241
316
  let tokenBudget = null;
242
317
  try {
243
- const { classifyImpact } = require("./impact_classifier.js");
244
- const { evaluateSocraticGate } = require("./socratic_gate_policy.js");
245
- const { getTokenBudget } = require("./token_budget_broker.js");
318
+ const { classifyImpact } = require('./impact_classifier.js');
319
+ const { evaluateSocraticGate } = require('./socratic_gate_policy.js');
320
+ const { getTokenBudget } = require('./token_budget_broker.js');
246
321
  impactClassification = classifyImpact({ files, task });
247
- socraticGatePolicy = evaluateSocraticGate({ tier: impactClassification.tier, ambiguityScore: 0.2 });
322
+ socraticGatePolicy = evaluateSocraticGate({
323
+ tier: impactClassification.tier,
324
+ ambiguityScore: 0.2,
325
+ });
248
326
  tokenBudget = getTokenBudget(impactClassification.tier);
249
327
  } catch {
250
- impactClassification = { tier: 1, score: 0.2, maxReviewers: 1, requireGate: false, fastPass: false };
251
- socraticGatePolicy = { shouldBlock: false, reason: "Fallback evaluation" };
328
+ impactClassification = {
329
+ tier: 1,
330
+ score: 0.2,
331
+ maxReviewers: 1,
332
+ requireGate: false,
333
+ fastPass: false,
334
+ };
335
+ socraticGatePolicy = { shouldBlock: false, reason: 'Fallback evaluation' };
252
336
  tokenBudget = { tier: 1, maxTokens: 2000, maxReviewers: 1 };
253
337
  }
254
338
 
@@ -289,7 +373,6 @@ function planPhase(task, files = [], agentDir = null) {
289
373
  };
290
374
  }
291
375
 
292
-
293
376
  // ══════════════════════════════════════════════════════════════════════════════
294
377
  // PASS 2 — BUILDER
295
378
  // Assemble a minimal, focused prompt for code generation.
@@ -315,37 +398,37 @@ function buildPhase(spec, agentDir = null, opts = {}) {
315
398
  const skillsLoaded = [];
316
399
 
317
400
  // ── Section 1: Task Specification (compact) ────────────────────────────────
318
- lines.push("# Code Generation Task");
319
- lines.push("");
401
+ lines.push('# Code Generation Task');
402
+ lines.push('');
320
403
  lines.push(`Type: ${spec.task_type}`);
321
- lines.push(`Stack: ${spec.stack.join(", ") || "detect from context"}`);
404
+ lines.push(`Stack: ${spec.stack.join(', ') || 'detect from context'}`);
322
405
  if (spec.target_file) {
323
406
  lines.push(`Target: ${spec.target_file}`);
324
407
  }
325
- lines.push("");
326
- lines.push("## Requirements");
327
- lines.push("");
408
+ lines.push('');
409
+ lines.push('## Requirements');
410
+ lines.push('');
328
411
  lines.push(spec.spec);
329
- lines.push("");
412
+ lines.push('');
330
413
 
331
414
  // Constraints
332
415
  const constraintEntries = Object.entries(spec.constraints || {});
333
416
  if (constraintEntries.length > 0) {
334
- lines.push("## Constraints");
335
- lines.push("");
417
+ lines.push('## Constraints');
418
+ lines.push('');
336
419
  for (const [key, val] of constraintEntries) {
337
- lines.push(`- ${key.replace(/_/g, " ")}: ${val}`);
420
+ lines.push(`- ${key.replace(/_/g, ' ')}: ${val}`);
338
421
  }
339
- lines.push("");
422
+ lines.push('');
340
423
  }
341
424
 
342
425
  // ── Section 2: Essential Skill Key-Rules (max 3 skills) ────────────────────
343
426
  const skillNames = (spec.essential_skills || []).map(s => s.name);
344
427
  if (skillNames.length > 0) {
345
- lines.push("## Design & Implementation Guidelines");
346
- lines.push("");
347
- lines.push("Follow these rules strictly:");
348
- lines.push("");
428
+ lines.push('## Design & Implementation Guidelines');
429
+ lines.push('');
430
+ lines.push('Follow these rules strictly:');
431
+ lines.push('');
349
432
 
350
433
  for (const skillName of skillNames.slice(0, 3)) {
351
434
  const skill = allSkills.find(s => s.name === skillName);
@@ -353,39 +436,39 @@ function buildPhase(spec, agentDir = null, opts = {}) {
353
436
 
354
437
  skillsLoaded.push(skillName);
355
438
  lines.push(`### ${skillName}`);
356
- lines.push("");
439
+ lines.push('');
357
440
  // Use condensed key-rules only — not full SKILL.md
358
- lines.push(skill.keyRules || "");
359
- lines.push("");
441
+ lines.push(skill.keyRules || '');
442
+ lines.push('');
360
443
  }
361
444
  }
362
445
 
363
446
  // ── Section 3: Target File Context (if modifying existing code) ────────────
364
447
  if (opts.targetFileContent) {
365
- lines.push("## Current File Content");
366
- lines.push("");
367
- lines.push("```");
448
+ lines.push('## Current File Content');
449
+ lines.push('');
450
+ lines.push('```');
368
451
  // Truncate to ~200 lines to stay within budget
369
- const fileLines = opts.targetFileContent.split("\n");
452
+ const fileLines = opts.targetFileContent.split('\n');
370
453
  if (fileLines.length > 200) {
371
- lines.push(fileLines.slice(0, 200).join("\n"));
454
+ lines.push(fileLines.slice(0, 200).join('\n'));
372
455
  lines.push(`\n... (${fileLines.length - 200} more lines truncated)`);
373
456
  } else {
374
457
  lines.push(opts.targetFileContent);
375
458
  }
376
- lines.push("```");
377
- lines.push("");
459
+ lines.push('```');
460
+ lines.push('');
378
461
  }
379
462
 
380
463
  // ── Section 4: Output Format Instruction ───────────────────────────────────
381
- lines.push("## Output Instructions");
382
- lines.push("");
383
- lines.push("Generate ONLY the code. No explanations, no preamble, no markdown fences.");
384
- lines.push("Use self-documenting names. Add error handling on async functions.");
385
- lines.push("Mark any uncertain API calls with // VERIFY: [reason].");
386
- lines.push("");
464
+ lines.push('## Output Instructions');
465
+ lines.push('');
466
+ lines.push('Generate ONLY the code. No explanations, no preamble, no markdown fences.');
467
+ lines.push('Use self-documenting names. Add error handling on async functions.');
468
+ lines.push('Mark any uncertain API calls with // VERIFY: [reason].');
469
+ lines.push('');
387
470
 
388
- const prompt = lines.join("\n");
471
+ const prompt = lines.join('\n');
389
472
 
390
473
  // Rough token estimate: ~4 chars per token for English text
391
474
  const tokenEstimate = Math.ceil(prompt.length / 4);
@@ -393,7 +476,6 @@ function buildPhase(spec, agentDir = null, opts = {}) {
393
476
  return { prompt, tokenEstimate, skillsLoaded };
394
477
  }
395
478
 
396
-
397
479
  // ══════════════════════════════════════════════════════════════════════════════
398
480
  // PASS 3 — VALIDATOR
399
481
  // Run deterministic checks on generated code (zero LLM calls).
@@ -412,21 +494,21 @@ function buildPhase(spec, agentDir = null, opts = {}) {
412
494
  */
413
495
  function validatePhase(code, spec, opts = {}) {
414
496
  const issues = [];
415
- let verdict = "APPROVED";
497
+ let verdict = 'APPROVED';
416
498
 
417
499
  // ── Inner Loop Validator (security patterns + syntax) ──────────────────────
418
500
  const innerLoop = getInnerLoopValidator();
419
- if (innerLoop && typeof innerLoop.validateSnippet === "function") {
501
+ if (innerLoop && typeof innerLoop.validateSnippet === 'function') {
420
502
  try {
421
503
  const ilResult = innerLoop.validateSnippet(code, opts.lang || detectLang(spec));
422
504
  if (ilResult && ilResult.issues) {
423
505
  for (const issue of ilResult.issues) {
424
506
  issues.push({
425
- source: "inner_loop_validator",
426
- severity: issue.severity || "medium",
427
- category: issue.category || "unknown",
507
+ source: 'inner_loop_validator',
508
+ severity: issue.severity || 'medium',
509
+ category: issue.category || 'unknown',
428
510
  line: issue.line || null,
429
- message: issue.message || "Unnamed issue",
511
+ message: issue.message || 'Unnamed issue',
430
512
  fix: issue.fix || null,
431
513
  });
432
514
  }
@@ -441,37 +523,38 @@ function validatePhase(code, spec, opts = {}) {
441
523
  issues.push(...manualIssues);
442
524
 
443
525
  // ── Classify verdict ───────────────────────────────────────────────────────
444
- const criticalCount = issues.filter(i => i.severity === "critical").length;
445
- const highCount = issues.filter(i => i.severity === "high").length;
526
+ const criticalCount = issues.filter(i => i.severity === 'critical').length;
527
+ const highCount = issues.filter(i => i.severity === 'high').length;
446
528
 
447
529
  if (criticalCount > 0) {
448
- verdict = "REJECTED";
530
+ verdict = 'REJECTED';
449
531
  } else if (highCount > 0) {
450
- verdict = "WARNING";
532
+ verdict = 'WARNING';
451
533
  } else {
452
- verdict = "APPROVED";
534
+ verdict = 'APPROVED';
453
535
  }
454
536
 
455
537
  // ── Build self-healing feedback for retry ──────────────────────────────────
456
538
  let feedback = null;
457
- if (verdict !== "APPROVED" && issues.length > 0) {
458
- const feedbackLines = ["The following issues were found in the generated code:"];
539
+ if (verdict !== 'APPROVED' && issues.length > 0) {
540
+ const feedbackLines = ['The following issues were found in the generated code:'];
459
541
  for (const issue of issues.slice(0, 5)) {
460
542
  feedbackLines.push(`- [${issue.severity.toUpperCase()}] ${issue.message}`);
461
543
  if (issue.fix) feedbackLines.push(` Fix: ${issue.fix}`);
462
544
  }
463
- feedbackLines.push("");
464
- feedbackLines.push("Please regenerate the code addressing these issues.");
465
- feedback = feedbackLines.join("\n");
545
+ feedbackLines.push('');
546
+ feedbackLines.push('Please regenerate the code addressing these issues.');
547
+ feedback = feedbackLines.join('\n');
466
548
  }
467
549
 
468
- const summary = verdict === "APPROVED"
469
- ? `✅ Code passed validation (${issues.length} issues found, none blocking)`
470
- : `${verdict === "REJECTED" ? "❌" : "⚠️"} Code ${verdict.toLowerCase()}: ${criticalCount} critical, ${highCount} high severity issues`;
550
+ const summary =
551
+ verdict === 'APPROVED'
552
+ ? `✅ Code passed validation (${issues.length} issues found, none blocking)`
553
+ : `${verdict === 'REJECTED' ? '❌' : '⚠️'} Code ${verdict.toLowerCase()}: ${criticalCount} critical, ${highCount} high severity issues`;
471
554
 
472
555
  return {
473
556
  verdict,
474
- passed: verdict === "APPROVED",
557
+ passed: verdict === 'APPROVED',
475
558
  issues,
476
559
  summary,
477
560
  feedback,
@@ -482,14 +565,21 @@ function validatePhase(code, spec, opts = {}) {
482
565
  * Detect language from spec for validation context.
483
566
  */
484
567
  function detectLang(spec) {
485
- if (!spec || !spec.target_file) return "js";
568
+ if (!spec || !spec.target_file) return 'js';
486
569
  const ext = path.extname(spec.target_file).toLowerCase();
487
570
  const map = {
488
- ".ts": "ts", ".tsx": "tsx", ".js": "js", ".jsx": "jsx",
489
- ".py": "py", ".rs": "rs", ".sql": "sql", ".vue": "vue",
490
- ".css": "css", ".html": "html",
571
+ '.ts': 'ts',
572
+ '.tsx': 'tsx',
573
+ '.js': 'js',
574
+ '.jsx': 'jsx',
575
+ '.py': 'py',
576
+ '.rs': 'rs',
577
+ '.sql': 'sql',
578
+ '.vue': 'vue',
579
+ '.css': 'css',
580
+ '.html': 'html',
491
581
  };
492
- return map[ext] || "js";
582
+ return map[ext] || 'js';
493
583
  }
494
584
 
495
585
  /**
@@ -498,54 +588,56 @@ function detectLang(spec) {
498
588
  */
499
589
  function runManualChecks(code, spec) {
500
590
  const issues = [];
501
- const lines = code.split("\n");
591
+ const lines = code.split('\n');
502
592
 
503
593
  // Check 1: eval() usage
504
594
  if (/\beval\s*\(/.test(code)) {
505
595
  issues.push({
506
- source: "pipeline_validator",
507
- severity: "critical",
508
- category: "Code Injection",
596
+ source: 'pipeline_validator',
597
+ severity: 'critical',
598
+ category: 'Code Injection',
509
599
  line: findLineNumber(lines, /\beval\s*\(/),
510
- message: "eval() is a code injection vector — never use in production",
511
- fix: "Use JSON.parse(), new Function(), or a proper parser instead",
600
+ message: 'eval() is a code injection vector — never use in production',
601
+ fix: 'Use JSON.parse(), new Function(), or a proper parser instead',
512
602
  });
513
603
  }
514
604
 
515
605
  // Check 2: Hardcoded secrets
516
606
  if (/(?:password|secret|api[_-]?key)\s*[:=]\s*["'][^"']{4,}["']/i.test(code)) {
517
607
  issues.push({
518
- source: "pipeline_validator",
519
- severity: "critical",
520
- category: "Hardcoded Secret",
608
+ source: 'pipeline_validator',
609
+ severity: 'critical',
610
+ category: 'Hardcoded Secret',
521
611
  line: findLineNumber(lines, /(?:password|secret|api[_-]?key)\s*[:=]\s*["']/i),
522
- message: "Hardcoded secret detected — use environment variables",
523
- fix: "Replace with process.env.SECRET_NAME or equivalent",
612
+ message: 'Hardcoded secret detected — use environment variables',
613
+ fix: 'Replace with process.env.SECRET_NAME or equivalent',
524
614
  });
525
615
  }
526
616
 
527
617
  // Check 3: innerHTML XSS
528
- if (/\.innerHTML\s*=/.test(code) && !code.includes("DOMPurify")) {
618
+ if (/\.innerHTML\s*=/.test(code) && !code.includes('DOMPurify')) {
529
619
  issues.push({
530
- source: "pipeline_validator",
531
- severity: "high",
532
- category: "XSS",
620
+ source: 'pipeline_validator',
621
+ severity: 'high',
622
+ category: 'XSS',
533
623
  line: findLineNumber(lines, /\.innerHTML\s*=/),
534
- message: "Direct innerHTML assignment without sanitization",
624
+ message: 'Direct innerHTML assignment without sanitization',
535
625
  fix: "Use textContent, DOMPurify.sanitize(), or React's JSX instead",
536
626
  });
537
627
  }
538
628
 
539
629
  // Check 4: SQL injection (string interpolation in queries)
540
- if (/\$\{.*\}.*(?:SELECT|INSERT|UPDATE|DELETE|WHERE)/i.test(code) ||
541
- /['"].*\+.*(?:SELECT|INSERT|UPDATE|DELETE|WHERE)/i.test(code)) {
630
+ if (
631
+ /\$\{.*\}.*(?:SELECT|INSERT|UPDATE|DELETE|WHERE)/i.test(code) ||
632
+ /['"].*\+.*(?:SELECT|INSERT|UPDATE|DELETE|WHERE)/i.test(code)
633
+ ) {
542
634
  issues.push({
543
- source: "pipeline_validator",
544
- severity: "critical",
545
- category: "SQL Injection",
635
+ source: 'pipeline_validator',
636
+ severity: 'critical',
637
+ category: 'SQL Injection',
546
638
  line: null,
547
- message: "Possible SQL injection — string interpolation in SQL query",
548
- fix: "Use parameterized queries ($1, ?) or an ORM",
639
+ message: 'Possible SQL injection — string interpolation in SQL query',
640
+ fix: 'Use parameterized queries ($1, ?) or an ORM',
549
641
  });
550
642
  }
551
643
 
@@ -553,36 +645,36 @@ function runManualChecks(code, spec) {
553
645
  const consoleCount = (code.match(/console\.(log|debug|info)\(/g) || []).length;
554
646
  if (consoleCount > 3) {
555
647
  issues.push({
556
- source: "pipeline_validator",
557
- severity: "low",
558
- category: "Code Quality",
648
+ source: 'pipeline_validator',
649
+ severity: 'low',
650
+ category: 'Code Quality',
559
651
  line: null,
560
652
  message: `${consoleCount} console.log statements found — remove before production`,
561
- fix: "Use a proper logger (winston, pino) or remove debug logs",
653
+ fix: 'Use a proper logger (winston, pino) or remove debug logs',
562
654
  });
563
655
  }
564
656
 
565
657
  // Check 6: Empty catch blocks
566
658
  if (/catch\s*\([^)]*\)\s*\{[\s\n]*\}/.test(code)) {
567
659
  issues.push({
568
- source: "pipeline_validator",
569
- severity: "medium",
570
- category: "Error Handling",
660
+ source: 'pipeline_validator',
661
+ severity: 'medium',
662
+ category: 'Error Handling',
571
663
  line: findLineNumber(lines, /catch\s*\([^)]*\)\s*\{[\s\n]*\}/),
572
- message: "Empty catch block swallows errors silently",
573
- fix: "At minimum, log the error: catch(err) { console.error(err); }",
664
+ message: 'Empty catch block swallows errors silently',
665
+ fix: 'At minimum, log the error: catch(err) { console.error(err); }',
574
666
  });
575
667
  }
576
668
 
577
669
  // Check 7: TypeScript `any` usage (if TS file)
578
670
  const lang = detectLang(spec);
579
- if ((lang === "ts" || lang === "tsx") && /:\s*any\b/.test(code)) {
671
+ if ((lang === 'ts' || lang === 'tsx') && /:\s*any\b/.test(code)) {
580
672
  const anyCount = (code.match(/:\s*any\b/g) || []).length;
581
673
  if (anyCount > 2) {
582
674
  issues.push({
583
- source: "pipeline_validator",
584
- severity: "medium",
585
- category: "Type Safety",
675
+ source: 'pipeline_validator',
676
+ severity: 'medium',
677
+ category: 'Type Safety',
586
678
  line: null,
587
679
  message: `${anyCount} uses of 'any' type — reduces type safety`,
588
680
  fix: "Replace with specific types or use 'unknown' with type guards",
@@ -603,7 +695,6 @@ function findLineNumber(lines, pattern) {
603
695
  return null;
604
696
  }
605
697
 
606
-
607
698
  // ══════════════════════════════════════════════════════════════════════════════
608
699
  // FULL PIPELINE — Orchestrate all 3 passes
609
700
  // ══════════════════════════════════════════════════════════════════════════════
@@ -632,7 +723,7 @@ function fullPipeline(task, files = [], opts = {}) {
632
723
 
633
724
  // Pass 3: Return validator as a callable
634
725
  // The caller invokes validate(code) after the LLM generates the code
635
- const validate = (code) => validatePhase(code, spec, { lang: detectLang(spec) });
726
+ const validate = code => validatePhase(code, spec, { lang: detectLang(spec) });
636
727
 
637
728
  return {
638
729
  spec,
@@ -643,7 +734,6 @@ function fullPipeline(task, files = [], opts = {}) {
643
734
  };
644
735
  }
645
736
 
646
-
647
737
  // ══════════════════════════════════════════════════════════════════════════════
648
738
  // PUBLIC API
649
739
  // ══════════════════════════════════════════════════════════════════════════════
@@ -658,23 +748,22 @@ module.exports = {
658
748
  STACK_KEYWORDS,
659
749
  };
660
750
 
661
-
662
751
  // ══════════════════════════════════════════════════════════════════════════════
663
752
  // CLI ENTRY POINT
664
753
  // ══════════════════════════════════════════════════════════════════════════════
665
754
 
666
755
  if (require.main === module) {
667
756
  const { flags, positional } = parseArgs(process.argv.slice(2), {
668
- task: { type: "string", default: null },
669
- file: { type: "string", default: null },
670
- phase: { type: "string", default: "full" },
671
- output: { type: "string", default: "report" },
672
- spec: { type: "string", default: null },
673
- code: { type: "string", default: null },
674
- "dry-run": { type: "boolean", default: false },
757
+ task: { type: 'string', default: null },
758
+ file: { type: 'string', default: null },
759
+ phase: { type: 'string', default: 'full' },
760
+ output: { type: 'string', default: 'report' },
761
+ spec: { type: 'string', default: null },
762
+ code: { type: 'string', default: null },
763
+ 'dry-run': { type: 'boolean', default: false },
675
764
  });
676
765
 
677
- if (flags.help || (!flags.task && positional[0] !== "demo")) {
766
+ if (flags.help || (!flags.task && positional[0] !== 'demo')) {
678
767
  console.log(`
679
768
  ${BOLD}pipeline_engine.js${RESET} — Tribunal Hybrid Pipeline Engine
680
769
 
@@ -708,15 +797,15 @@ ${BOLD}Examples:${RESET}
708
797
  const agentDir = findAgentDir();
709
798
 
710
799
  // ── Demo Mode ──────────────────────────────────────────────────────────────
711
- if (positional[0] === "demo") {
800
+ if (positional[0] === 'demo') {
712
801
  const scenarios = [
713
- { task: "Build a React dashboard with charts and dark mode", file: "Dashboard.tsx" },
714
- { task: "Create an Express JWT authentication middleware", file: "auth.ts" },
715
- { task: "Write a Prisma query for paginated user search", file: "users.ts" },
716
- { task: "Design a premium SaaS landing page with scroll animations", file: "Hero.tsx" },
802
+ { task: 'Build a React dashboard with charts and dark mode', file: 'Dashboard.tsx' },
803
+ { task: 'Create an Express JWT authentication middleware', file: 'auth.ts' },
804
+ { task: 'Write a Prisma query for paginated user search', file: 'users.ts' },
805
+ { task: 'Design a premium SaaS landing page with scroll animations', file: 'Hero.tsx' },
717
806
  ];
718
807
 
719
- console.log(banner("Pipeline Engine — Demo Mode"));
808
+ console.log(banner('Pipeline Engine — Demo Mode'));
720
809
 
721
810
  for (const scenario of scenarios) {
722
811
  const t = timer();
@@ -725,59 +814,71 @@ ${BOLD}Examples:${RESET}
725
814
 
726
815
  console.log(`\n ${BOLD}Task:${RESET} "${scenario.task}"`);
727
816
  console.log(` ${DIM}Type:${RESET} ${result.spec.task_type}`);
728
- console.log(` ${DIM}Stack:${RESET} ${result.spec.stack.join(", ")}`);
729
- console.log(` ${GREEN}Skills:${RESET} ${result.skillsLoaded.join(", ") || "(none matched)"}`);
817
+ console.log(` ${DIM}Stack:${RESET} ${result.spec.stack.join(', ')}`);
818
+ console.log(
819
+ ` ${GREEN}Skills:${RESET} ${result.skillsLoaded.join(', ') || '(none matched)'}`,
820
+ );
730
821
  console.log(` ${CYAN}Tokens:${RESET} ~${result.tokenEstimate} (vs ~12,000 monolithic)`);
731
822
  console.log(` ${DIM}Time:${RESET} ${elapsed}ms`);
732
823
  }
733
824
 
734
- console.log(`\n${CYAN}${"".repeat(56)}${RESET}\n`);
825
+ console.log(`\n${CYAN}${''.repeat(56)}${RESET}\n`);
735
826
  process.exit(0);
736
827
  }
737
828
 
738
829
  // ── Phase Execution ────────────────────────────────────────────────────────
739
830
  const files = flags.file ? [flags.file] : [];
740
831
 
741
- if (flags.phase === "plan" || flags.phase === "full") {
832
+ if (flags.phase === 'plan' || flags.phase === 'full') {
742
833
  const t = timer();
743
834
  const spec = planPhase(flags.task, files, agentDir);
744
835
  const elapsed = t().toFixed(1);
745
836
 
746
- if (flags.output === "json") {
837
+ if (flags.output === 'json') {
747
838
  console.log(JSON.stringify(spec, null, 2));
748
839
  } else {
749
- console.log(banner("Pipeline — Pass 1: Planner"));
840
+ console.log(banner('Pipeline — Pass 1: Planner'));
750
841
  console.log(` ${BOLD}Task Type:${RESET} ${spec.task_type}`);
751
- console.log(` ${BOLD}Stack:${RESET} ${spec.stack.join(", ") || "(auto-detect)"}`);
752
- console.log(` ${BOLD}Skills:${RESET} ${spec.essential_skills.map(s => s.name).join(", ")}`);
842
+ console.log(` ${BOLD}Stack:${RESET} ${spec.stack.join(', ') || '(auto-detect)'}`);
843
+ console.log(
844
+ ` ${BOLD}Skills:${RESET} ${spec.essential_skills.map(s => s.name).join(', ')}`,
845
+ );
753
846
  if (Object.keys(spec.constraints).length > 0) {
754
- console.log(` ${BOLD}Constraints:${RESET} ${Object.keys(spec.constraints).join(", ")}`);
847
+ console.log(` ${BOLD}Constraints:${RESET} ${Object.keys(spec.constraints).join(', ')}`);
755
848
  }
756
849
  console.log(` ${DIM}Time: ${elapsed}ms${RESET}`);
757
850
  }
758
851
 
759
- if (flags.phase === "full" && !flags["dry-run"]) {
852
+ if (flags.phase === 'full' && !flags['dry-run']) {
760
853
  const builderResult = buildPhase(spec, agentDir);
761
854
 
762
- if (flags.output === "json") {
763
- console.log(JSON.stringify({
764
- spec,
765
- tokenEstimate: builderResult.tokenEstimate,
766
- skillsLoaded: builderResult.skillsLoaded,
767
- }, null, 2));
768
- } else if (flags.output === "prompt") {
855
+ if (flags.output === 'json') {
856
+ console.log(
857
+ JSON.stringify(
858
+ {
859
+ spec,
860
+ tokenEstimate: builderResult.tokenEstimate,
861
+ skillsLoaded: builderResult.skillsLoaded,
862
+ },
863
+ null,
864
+ 2,
865
+ ),
866
+ );
867
+ } else if (flags.output === 'prompt') {
769
868
  console.log(builderResult.prompt);
770
869
  } else {
771
- console.log(sectionHeader("Pass 2: Builder Prompt", 2));
870
+ console.log(sectionHeader('Pass 2: Builder Prompt', 2));
772
871
  console.log(` ${BOLD}Token Estimate:${RESET} ~${builderResult.tokenEstimate}`);
773
- console.log(` ${BOLD}Skills Loaded:${RESET} ${builderResult.skillsLoaded.join(", ")}`);
774
- console.log(` ${GREEN}Savings:${RESET} ~${Math.round((1 - builderResult.tokenEstimate / 14000) * 100)}% vs monolithic prompt`);
872
+ console.log(` ${BOLD}Skills Loaded:${RESET} ${builderResult.skillsLoaded.join(', ')}`);
873
+ console.log(
874
+ ` ${GREEN}Savings:${RESET} ~${Math.round((1 - builderResult.tokenEstimate / 14000) * 100)}% vs monolithic prompt`,
875
+ );
775
876
  console.log(`\n ${DIM}Use --output prompt to see the full builder prompt${RESET}`);
776
877
  }
777
878
  }
778
879
  }
779
880
 
780
- if (flags.phase === "build") {
881
+ if (flags.phase === 'build') {
781
882
  let spec;
782
883
  if (flags.spec) {
783
884
  spec = loadJson(flags.spec);
@@ -794,26 +895,32 @@ ${BOLD}Examples:${RESET}
794
895
 
795
896
  const result = buildPhase(spec, agentDir);
796
897
 
797
- if (flags.output === "prompt") {
898
+ if (flags.output === 'prompt') {
798
899
  console.log(result.prompt);
799
- } else if (flags.output === "json") {
800
- console.log(JSON.stringify({
801
- tokenEstimate: result.tokenEstimate,
802
- skillsLoaded: result.skillsLoaded,
803
- }, null, 2));
900
+ } else if (flags.output === 'json') {
901
+ console.log(
902
+ JSON.stringify(
903
+ {
904
+ tokenEstimate: result.tokenEstimate,
905
+ skillsLoaded: result.skillsLoaded,
906
+ },
907
+ null,
908
+ 2,
909
+ ),
910
+ );
804
911
  } else {
805
- console.log(banner("Pipeline — Pass 2: Builder"));
912
+ console.log(banner('Pipeline — Pass 2: Builder'));
806
913
  console.log(` Token Estimate: ~${result.tokenEstimate}`);
807
- console.log(` Skills Loaded: ${result.skillsLoaded.join(", ")}`);
914
+ console.log(` Skills Loaded: ${result.skillsLoaded.join(', ')}`);
808
915
  console.log(`\n Use --output prompt to see the full builder prompt`);
809
916
  }
810
917
  }
811
918
 
812
- if (flags.phase === "validate") {
919
+ if (flags.phase === 'validate') {
813
920
  let codeContent;
814
921
  if (flags.code) {
815
922
  try {
816
- codeContent = fs.readFileSync(flags.code, "utf8");
923
+ codeContent = fs.readFileSync(flags.code, 'utf8');
817
924
  } catch (_err) {
818
925
  console.error(`${RED}✖ Could not read code file: ${flags.code}${RESET}`);
819
926
  process.exit(1);
@@ -826,28 +933,32 @@ ${BOLD}Examples:${RESET}
826
933
  const spec = flags.task ? planPhase(flags.task, files, agentDir) : { target_file: flags.code };
827
934
  const result = validatePhase(codeContent, spec);
828
935
 
829
- if (flags.output === "json") {
936
+ if (flags.output === 'json') {
830
937
  console.log(JSON.stringify(result, null, 2));
831
938
  } else {
832
- console.log(banner("Pipeline — Pass 3: Validator"));
833
- const icon = result.verdict === "APPROVED" ? `${GREEN}✅` :
834
- result.verdict === "WARNING" ? `${YELLOW}⚠️` : `${RED}❌`;
939
+ console.log(banner('Pipeline — Pass 3: Validator'));
940
+ const icon =
941
+ result.verdict === 'APPROVED'
942
+ ? `${GREEN}✅`
943
+ : result.verdict === 'WARNING'
944
+ ? `${YELLOW}⚠️`
945
+ : `${RED}❌`;
835
946
  console.log(` ${BOLD}Verdict:${RESET} ${icon} ${result.verdict}${RESET}`);
836
947
  console.log(` ${BOLD}Issues:${RESET} ${result.issues.length}`);
837
948
 
838
949
  if (result.issues.length > 0) {
839
- console.log("");
950
+ console.log('');
840
951
  for (const issue of result.issues) {
841
- const sev = issue.severity === "critical" ? RED :
842
- issue.severity === "high" ? YELLOW : DIM;
843
- const loc = issue.line ? ` (line ${issue.line})` : "";
952
+ const sev =
953
+ issue.severity === 'critical' ? RED : issue.severity === 'high' ? YELLOW : DIM;
954
+ const loc = issue.line ? ` (line ${issue.line})` : '';
844
955
  console.log(` ${sev}[${issue.severity.toUpperCase()}]${RESET} ${issue.message}${loc}`);
845
956
  }
846
957
  }
847
958
 
848
959
  if (result.feedback) {
849
960
  console.log(`\n ${BLUE}Self-Healing Feedback:${RESET}`);
850
- console.log(` ${DIM}${result.feedback.split("\n").join("\n ")}${RESET}`);
961
+ console.log(` ${DIM}${result.feedback.split('\n').join('\n ')}${RESET}`);
851
962
  }
852
963
  }
853
964