tribunal-kit 9.2.7 → 9.2.8

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 (801) hide show
  1. package/.agent/ARCHITECTURE.md +2 -2
  2. package/.agent/data/skill_certification_ledger.jsonl +40 -0
  3. package/.agent/data/skill_ontology.json +138 -0
  4. package/.agent/history/architecture-model.json +11656 -4996
  5. package/.agent/history/architecture-verification.json +9 -37
  6. package/.agent/routing_index.json +2430 -2069
  7. package/.agent/scripts/adaptive_execution.js +221 -28
  8. package/.agent/scripts/architecture_diff.js +303 -303
  9. package/.agent/scripts/architecture_extractor.js +792 -792
  10. package/.agent/scripts/architecture_health.js +293 -293
  11. package/.agent/scripts/architecture_verifier.js +303 -303
  12. package/.agent/scripts/architecture_visualizer.js +1988 -880
  13. package/.agent/scripts/blast_radius_engine.js +274 -274
  14. package/.agent/scripts/capability_evolution.js +102 -0
  15. package/.agent/scripts/context_broker.js +397 -31
  16. package/.agent/scripts/corpus_certification_orchestrator.js +502 -0
  17. package/.agent/scripts/corpus_validation_engine.js +311 -0
  18. package/.agent/scripts/engineering_memory.js +129 -0
  19. package/.agent/scripts/final_corpus_validation_engine.js +405 -0
  20. package/.agent/scripts/intent_extractor.js +130 -0
  21. package/.agent/scripts/outcome_engine.js +15 -0
  22. package/.agent/scripts/routing_evaluation_engine.js +184 -0
  23. package/.agent/scripts/skill_behavior_classifier.js +90 -0
  24. package/.agent/scripts/skill_behavior_harness.js +105 -0
  25. package/.agent/scripts/skill_certification_engine.js +586 -0
  26. package/.agent/scripts/skill_contract_engine.js +424 -0
  27. package/.agent/scripts/skill_coverage_expansion_engine.js +505 -0
  28. package/.agent/scripts/skill_evidence_acquisition_engine.js +535 -0
  29. package/.agent/scripts/skill_evidence_engine.js +83 -0
  30. package/.agent/scripts/skill_expectation_engine.js +38 -0
  31. package/.agent/scripts/skill_fixture_engine.js +24 -0
  32. package/.agent/scripts/skill_human_validation.js +32 -0
  33. package/.agent/scripts/skill_intelligence.js +89 -160
  34. package/.agent/scripts/skill_observation_engine.js +25 -0
  35. package/.agent/scripts/skill_ontology_engine.js +83 -0
  36. package/.agent/scripts/skill_quality_engine.js +343 -0
  37. package/.agent/scripts/skill_reconstruction_engine.js +164 -0
  38. package/.agent/scripts/skill_remediation_engine.js +326 -0
  39. package/.agent/scripts/skill_scenario_engine.js +108 -0
  40. package/.agent/scripts/skill_test_authoring_engine.js +1011 -0
  41. package/.agent/scripts/validation_engine.js +236 -236
  42. package/.agent/scripts/verification_auditor.js +80 -0
  43. package/.agent/skill_topic_map.json +301 -301
  44. package/.agent/skills/12-principles-of-animation/SKILL.md +9 -0
  45. package/.agent/skills/60fps-animation/SKILL.md +14 -0
  46. package/.agent/skills/accessible-animation/SKILL.md +9 -0
  47. package/.agent/skills/adapt/SKILL.md +8 -0
  48. package/.agent/skills/adr-generation/SKILL.md +9 -0
  49. package/.agent/skills/advanced-rag-pipelines/SKILL.md +9 -0
  50. package/.agent/skills/agent-organizer/SKILL.md +8 -0
  51. package/.agent/skills/agent-syscall-guidelines/SKILL.md +10 -0
  52. package/.agent/skills/agentic-patterns/SKILL.md +9 -0
  53. package/.agent/skills/agentic-workflows-2026/SKILL.md +8 -0
  54. package/.agent/skills/agentshield-security/SKILL.md +16 -0
  55. package/.agent/skills/ai-app-hardening/SKILL.md +7 -0
  56. package/.agent/skills/ai-prompt-injection-defense/SKILL.md +9 -0
  57. package/.agent/skills/animation-on-scroll/SKILL.md +9 -0
  58. package/.agent/skills/animation-systems/SKILL.md +8 -0
  59. package/.agent/skills/antfu-conventions/SKILL.md +9 -0
  60. package/.agent/skills/anti-slop-enforcement/SKILL.md +11 -0
  61. package/.agent/skills/api-patterns/SKILL.md +9 -0
  62. package/.agent/skills/api-security-auditor/SKILL.md +10 -0
  63. package/.agent/skills/app-builder/SKILL.md +8 -0
  64. package/.agent/skills/appflow-wireframe/SKILL.md +9 -0
  65. package/.agent/skills/apple-design/SKILL.md +8 -0
  66. package/.agent/skills/architecture/SKILL.md +8 -0
  67. package/.agent/skills/architecture-drift/SKILL.md +9 -0
  68. package/.agent/skills/architecture-intelligence/SKILL.md +17 -0
  69. package/.agent/skills/audit-and-fix/SKILL.md +8 -0
  70. package/.agent/skills/authentication-best-practices/SKILL.md +10 -0
  71. package/.agent/skills/autonomous-execution/SKILL.md +9 -0
  72. package/.agent/skills/backend-alembic/SKILL.md +16 -0
  73. package/.agent/skills/backend-architecture-auditor/SKILL.md +16 -0
  74. package/.agent/skills/backend-mongodb/SKILL.md +10 -0
  75. package/.agent/skills/backend-mysql/SKILL.md +16 -0
  76. package/.agent/skills/backend-performance-auditor/SKILL.md +10 -0
  77. package/.agent/skills/backend-postgresql/SKILL.md +10 -0
  78. package/.agent/skills/backend-redis/SKILL.md +10 -0
  79. package/.agent/skills/backend-security-expert/SKILL.md +10 -0
  80. package/.agent/skills/backend-sqlalchemy/SKILL.md +10 -0
  81. package/.agent/skills/backend-sqlite/SKILL.md +10 -0
  82. package/.agent/skills/backend-testing-auditor/SKILL.md +15 -0
  83. package/.agent/skills/baseline-ui/SKILL.md +8 -0
  84. package/.agent/skills/bash-linux/SKILL.md +9 -0
  85. package/.agent/skills/behavioral-modes/SKILL.md +9 -0
  86. package/.agent/skills/better-colors/SKILL.md +9 -0
  87. package/.agent/skills/better-typography/SKILL.md +9 -0
  88. package/.agent/skills/better-ui/SKILL.md +8 -0
  89. package/.agent/skills/bolder/SKILL.md +8 -0
  90. package/.agent/skills/brainstorming/SKILL.md +8 -0
  91. package/.agent/skills/browser-audit/SKILL.md +9 -0
  92. package/.agent/skills/browser-native-ai/SKILL.md +8 -0
  93. package/.agent/skills/build-primitive/SKILL.md +8 -0
  94. package/.agent/skills/building-native-ui/SKILL.md +7 -0
  95. package/.agent/skills/cicd-pro/SKILL.md +9 -0
  96. package/.agent/skills/clarify/SKILL.md +8 -0
  97. package/.agent/skills/clean-code/SKILL.md +8 -0
  98. package/.agent/skills/cloud-architect/SKILL.md +8 -0
  99. package/.agent/skills/cobejs/SKILL.md +8 -0
  100. package/.agent/skills/code-review-checklist/SKILL.md +9 -0
  101. package/.agent/skills/codebase-design/SKILL.md +14 -0
  102. package/.agent/skills/colorize/SKILL.md +8 -0
  103. package/.agent/skills/compact-landing/SKILL.md +9 -0
  104. package/.agent/skills/company-logos/SKILL.md +9 -0
  105. package/.agent/skills/config-validator/SKILL.md +9 -0
  106. package/.agent/skills/containerization-pro/SKILL.md +9 -0
  107. package/.agent/skills/context-engineering-pro/SKILL.md +10 -0
  108. package/.agent/skills/create-design-md/SKILL.md +7 -0
  109. package/.agent/skills/critique/SKILL.md +8 -0
  110. package/.agent/skills/csharp-developer/SKILL.md +9 -0
  111. package/.agent/skills/data-validation-schemas/SKILL.md +8 -0
  112. package/.agent/skills/database-design/SKILL.md +8 -0
  113. package/.agent/skills/delight/SKILL.md +8 -0
  114. package/.agent/skills/deployment-procedures/SKILL.md +9 -0
  115. package/.agent/skills/design-lab/SKILL.md +8 -0
  116. package/.agent/skills/devops-engineer/SKILL.md +9 -0
  117. package/.agent/skills/devops-incident-responder/SKILL.md +16 -0
  118. package/.agent/skills/diagnosing-bugs/SKILL.md +9 -0
  119. package/.agent/skills/distill/SKILL.md +8 -0
  120. package/.agent/skills/documentation-templates/SKILL.md +9 -0
  121. package/.agent/skills/domain-modeling/SKILL.md +9 -0
  122. package/.agent/skills/duckdb-analytical-sql/SKILL.md +10 -0
  123. package/.agent/skills/edge-ai-mobile/SKILL.md +8 -0
  124. package/.agent/skills/edge-computing/SKILL.md +9 -0
  125. package/.agent/skills/emil-design-eng/SKILL.md +9 -0
  126. package/.agent/skills/error-resilience/SKILL.md +8 -0
  127. package/.agent/skills/expo-router-v4/SKILL.md +9 -0
  128. package/.agent/skills/extract-design-system/SKILL.md +9 -0
  129. package/.agent/skills/fabel-protocol/SKILL.md +9 -0
  130. package/.agent/skills/failure-mode-analysis/SKILL.md +10 -0
  131. package/.agent/skills/fastapi-pro/SKILL.md +9 -0
  132. package/.agent/skills/fixing-accessibility/SKILL.md +9 -0
  133. package/.agent/skills/fixing-metadata/SKILL.md +9 -0
  134. package/.agent/skills/fixing-motion-performance/SKILL.md +9 -0
  135. package/.agent/skills/framer-motion-expert/SKILL.md +9 -0
  136. package/.agent/skills/frontend-design/SKILL.md +7 -0
  137. package/.agent/skills/frontend-security-expert/SKILL.md +9 -0
  138. package/.agent/skills/game-design-expert/SKILL.md +9 -0
  139. package/.agent/skills/game-engineering-expert/SKILL.md +16 -0
  140. package/.agent/skills/generative-ui-expert/SKILL.md +9 -0
  141. package/.agent/skills/geo-fundamentals/SKILL.md +9 -0
  142. package/.agent/skills/git-pro/SKILL.md +9 -0
  143. package/.agent/skills/github-operations/SKILL.md +9 -0
  144. package/.agent/skills/gpt-taste/SKILL.md +9 -0
  145. package/.agent/skills/graph-engineering/SKILL.md +16 -0
  146. package/.agent/skills/gsap-core/SKILL.md +9 -0
  147. package/.agent/skills/gsap-frameworks/SKILL.md +9 -0
  148. package/.agent/skills/gsap-performance/SKILL.md +9 -0
  149. package/.agent/skills/gsap-plugins/SKILL.md +9 -0
  150. package/.agent/skills/gsap-react/SKILL.md +9 -0
  151. package/.agent/skills/gsap-scrolltrigger/SKILL.md +9 -0
  152. package/.agent/skills/gsap-timeline/SKILL.md +9 -0
  153. package/.agent/skills/gsap-utils/SKILL.md +9 -0
  154. package/.agent/skills/harden/SKILL.md +8 -0
  155. package/.agent/skills/harness-protocol/SKILL.md +9 -0
  156. package/.agent/skills/hf-cli/SKILL.md +11 -0
  157. package/.agent/skills/hf-cloud-aws-context-discovery/SKILL.md +10 -0
  158. package/.agent/skills/hf-cloud-python-env-setup/SKILL.md +10 -0
  159. package/.agent/skills/hf-cloud-sagemaker-deployment-planner/SKILL.md +10 -0
  160. package/.agent/skills/hf-cloud-sagemaker-iam-preflight/SKILL.md +10 -0
  161. package/.agent/skills/hf-cloud-sagemaker-production-defaults/SKILL.md +10 -0
  162. package/.agent/skills/hf-cloud-serving-image-selection/SKILL.md +10 -0
  163. package/.agent/skills/hf-mem/SKILL.md +11 -0
  164. package/.agent/skills/huggingface-best/SKILL.md +9 -0
  165. package/.agent/skills/huggingface-community-evals/SKILL.md +11 -0
  166. package/.agent/skills/huggingface-datasets/SKILL.md +10 -0
  167. package/.agent/skills/huggingface-gradio/SKILL.md +10 -0
  168. package/.agent/skills/huggingface-llm-trainer/SKILL.md +10 -0
  169. package/.agent/skills/huggingface-local-models/SKILL.md +10 -0
  170. package/.agent/skills/huggingface-lora-space-builder/SKILL.md +11 -0
  171. package/.agent/skills/huggingface-paper-publisher/SKILL.md +11 -0
  172. package/.agent/skills/huggingface-papers/SKILL.md +11 -0
  173. package/.agent/skills/huggingface-spaces/SKILL.md +10 -0
  174. package/.agent/skills/huggingface-tool-builder/SKILL.md +11 -0
  175. package/.agent/skills/huggingface-trackio/SKILL.md +11 -0
  176. package/.agent/skills/huggingface-vision-trainer/SKILL.md +11 -0
  177. package/.agent/skills/huggingface-zerogpu/SKILL.md +11 -0
  178. package/.agent/skills/human-gate-negotiation/SKILL.md +11 -0
  179. package/.agent/skills/i18n-localization/SKILL.md +9 -0
  180. package/.agent/skills/impeccable/SKILL.md +8 -0
  181. package/.agent/skills/improve-codebase-architecture/SKILL.md +10 -0
  182. package/.agent/skills/improve-ui/SKILL.md +8 -0
  183. package/.agent/skills/intelligent-routing/SKILL.md +9 -0
  184. package/.agent/skills/knowledge-graph/SKILL.md +9 -0
  185. package/.agent/skills/landing-page/SKILL.md +9 -0
  186. package/.agent/skills/lint-and-validate/SKILL.md +9 -0
  187. package/.agent/skills/llm-engineering/SKILL.md +9 -0
  188. package/.agent/skills/local-first/SKILL.md +10 -0
  189. package/.agent/skills/lottie-animation/SKILL.md +9 -0
  190. package/.agent/skills/marquee-loop/SKILL.md +9 -0
  191. package/.agent/skills/masked-reveal/SKILL.md +9 -0
  192. package/.agent/skills/mcp-builder/SKILL.md +9 -0
  193. package/.agent/skills/micro-interaction/SKILL.md +9 -0
  194. package/.agent/skills/mobile-design/SKILL.md +7 -0
  195. package/.agent/skills/monorepo-management/SKILL.md +9 -0
  196. package/.agent/skills/morphing-icons/SKILL.md +9 -0
  197. package/.agent/skills/motion-engineering/SKILL.md +8 -0
  198. package/.agent/skills/nextjs-react-expert/SKILL.md +10 -0
  199. package/.agent/skills/nodejs-best-practices/SKILL.md +16 -0
  200. package/.agent/skills/observability/SKILL.md +8 -0
  201. package/.agent/skills/opentelemetry-observability/SKILL.md +9 -0
  202. package/.agent/skills/page-transition-animation/SKILL.md +10 -0
  203. package/.agent/skills/parallel-agents/SKILL.md +15 -0
  204. package/.agent/skills/performance-profiling/SKILL.md +9 -0
  205. package/.agent/skills/plan-writing/SKILL.md +8 -0
  206. package/.agent/skills/platform-engineer/SKILL.md +9 -0
  207. package/.agent/skills/platform-engineering-opentofu/SKILL.md +10 -0
  208. package/.agent/skills/playwright-ai-e2e/SKILL.md +9 -0
  209. package/.agent/skills/playwright-best-practices/SKILL.md +16 -0
  210. package/.agent/skills/polish/SKILL.md +8 -0
  211. package/.agent/skills/powershell-windows/SKILL.md +9 -0
  212. package/.agent/skills/pricing-page/SKILL.md +9 -0
  213. package/.agent/skills/product-aware-heuristics/SKILL.md +10 -0
  214. package/.agent/skills/progressive-blur/SKILL.md +9 -0
  215. package/.agent/skills/project-idioms/SKILL.md +8 -0
  216. package/.agent/skills/property-based-testing/SKILL.md +9 -0
  217. package/.agent/skills/python-patterns/SKILL.md +9 -0
  218. package/.agent/skills/python-pro/SKILL.md +9 -0
  219. package/.agent/skills/quieter/SKILL.md +8 -0
  220. package/.agent/skills/react-doctor/SKILL.md +9 -0
  221. package/.agent/skills/react-specialist/SKILL.md +9 -0
  222. package/.agent/skills/readme-builder/SKILL.md +9 -0
  223. package/.agent/skills/realtime-patterns/SKILL.md +9 -0
  224. package/.agent/skills/red-team-tactics/SKILL.md +16 -0
  225. package/.agent/skills/redesign-skill/SKILL.md +9 -0
  226. package/.agent/skills/review-animations/SKILL.md +8 -0
  227. package/.agent/skills/rust-pro/SKILL.md +9 -0
  228. package/.agent/skills/semantic-filesystem-navigation/SKILL.md +11 -0
  229. package/.agent/skills/seo-fundamentals/SKILL.md +9 -0
  230. package/.agent/skills/server-management/SKILL.md +8 -0
  231. package/.agent/skills/session-log-interrogation/SKILL.md +11 -0
  232. package/.agent/skills/shadcn-ui-expert/SKILL.md +9 -0
  233. package/.agent/skills/shape/SKILL.md +8 -0
  234. package/.agent/skills/skill-creator/SKILL.md +9 -0
  235. package/.agent/skills/soft-skill/SKILL.md +9 -0
  236. package/.agent/skills/sounds-on-the-web/SKILL.md +9 -0
  237. package/.agent/skills/sql-pro/SKILL.md +9 -0
  238. package/.agent/skills/subagent-driven-development/SKILL.md +11 -0
  239. package/.agent/skills/supabase-postgres-best-practices/SKILL.md +17 -0
  240. package/.agent/skills/svg-animation/SKILL.md +9 -0
  241. package/.agent/skills/swiftui-expert/SKILL.md +9 -0
  242. package/.agent/skills/swiss-design/SKILL.md +8 -0
  243. package/.agent/skills/system-design-pro/SKILL.md +9 -0
  244. package/.agent/skills/systematic-debugging/SKILL.md +14 -0
  245. package/.agent/skills/tailwind-patterns/SKILL.md +9 -0
  246. package/.agent/skills/taste-skill/SKILL.md +9 -0
  247. package/.agent/skills/tdd-workflow/SKILL.md +9 -0
  248. package/.agent/skills/test-result-analyzer/SKILL.md +9 -0
  249. package/.agent/skills/testing-patterns/SKILL.md +8 -0
  250. package/.agent/skills/thermo-nuclear-code-quality-review/SKILL.md +11 -0
  251. package/.agent/skills/thinking-protocol/SKILL.md +10 -0
  252. package/.agent/skills/to-spring-or-not-to-spring/SKILL.md +9 -0
  253. package/.agent/skills/train-sentence-transformers/SKILL.md +10 -0
  254. package/.agent/skills/transformers-js/SKILL.md +8 -0
  255. package/.agent/skills/transitions-dev/SKILL.md +8 -0
  256. package/.agent/skills/trend-researcher/SKILL.md +9 -0
  257. package/.agent/skills/tribunal-instincts-memory/SKILL.md +11 -0
  258. package/.agent/skills/trl-training/SKILL.md +9 -0
  259. package/.agent/skills/typescript-advanced/SKILL.md +9 -0
  260. package/.agent/skills/typeset/SKILL.md +8 -0
  261. package/.agent/skills/ui-reasoning-engine/SKILL.md +9 -0
  262. package/.agent/skills/ui-skill-packs/SKILL.md +9 -0
  263. package/.agent/skills/ui-skills-root/SKILL.md +9 -0
  264. package/.agent/skills/ui-ux-pro-max/SKILL.md +9 -0
  265. package/.agent/skills/ui-ux-researcher/SKILL.md +8 -0
  266. package/.agent/skills/vector-search-pgvector/SKILL.md +10 -0
  267. package/.agent/skills/verification-before-completion/SKILL.md +9 -0
  268. package/.agent/skills/vue-expert/SKILL.md +9 -0
  269. package/.agent/skills/vulnerability-scanner/SKILL.md +9 -0
  270. package/.agent/skills/web-accessibility-auditor/SKILL.md +16 -0
  271. package/.agent/skills/web-design-guidelines/SKILL.md +9 -0
  272. package/.agent/skills/web-quality-audit/SKILL.md +10 -0
  273. package/.agent/skills/webapp-testing/SKILL.md +8 -0
  274. package/.agent/skills/webgpu-performance/SKILL.md +9 -0
  275. package/.agent/skills/whimsy-injector/SKILL.md +9 -0
  276. package/.agent/skills/workflow-optimizer/SKILL.md +9 -0
  277. package/.agent/skills/zero-trust-passkeys/SKILL.md +10 -0
  278. package/.agent/skills_inventory.json +4257 -4272
  279. package/.agents/skills/12-principles-of-animation/SKILL.md +9 -0
  280. package/.agents/skills/60fps-animation/SKILL.md +14 -0
  281. package/.agents/skills/accessible-animation/SKILL.md +9 -0
  282. package/.agents/skills/adapt/SKILL.md +8 -0
  283. package/.agents/skills/adr-generation/SKILL.md +9 -0
  284. package/.agents/skills/advanced-rag-pipelines/SKILL.md +9 -0
  285. package/.agents/skills/agent-organizer/SKILL.md +8 -0
  286. package/.agents/skills/agent-syscall-guidelines/SKILL.md +10 -0
  287. package/.agents/skills/agentic-patterns/SKILL.md +9 -0
  288. package/.agents/skills/agentic-workflows-2026/SKILL.md +8 -0
  289. package/.agents/skills/agentshield-security/SKILL.md +16 -0
  290. package/.agents/skills/ai-app-hardening/SKILL.md +7 -0
  291. package/.agents/skills/ai-prompt-injection-defense/SKILL.md +9 -0
  292. package/.agents/skills/animation-on-scroll/SKILL.md +9 -0
  293. package/.agents/skills/animation-systems/SKILL.md +8 -0
  294. package/.agents/skills/antfu-conventions/SKILL.md +9 -0
  295. package/.agents/skills/anti-slop-enforcement/SKILL.md +11 -0
  296. package/.agents/skills/api-patterns/SKILL.md +9 -0
  297. package/.agents/skills/api-security-auditor/SKILL.md +10 -0
  298. package/.agents/skills/app-builder/SKILL.md +8 -0
  299. package/.agents/skills/appflow-wireframe/SKILL.md +9 -0
  300. package/.agents/skills/apple-design/SKILL.md +8 -0
  301. package/.agents/skills/architecture/SKILL.md +8 -0
  302. package/.agents/skills/architecture-drift/SKILL.md +9 -0
  303. package/.agents/skills/architecture-intelligence/SKILL.md +17 -0
  304. package/.agents/skills/audit-and-fix/SKILL.md +8 -0
  305. package/.agents/skills/authentication-best-practices/SKILL.md +10 -0
  306. package/.agents/skills/autonomous-execution/SKILL.md +9 -0
  307. package/.agents/skills/backend-alembic/SKILL.md +16 -0
  308. package/.agents/skills/backend-architecture-auditor/SKILL.md +16 -0
  309. package/.agents/skills/backend-mongodb/SKILL.md +10 -0
  310. package/.agents/skills/backend-mysql/SKILL.md +16 -0
  311. package/.agents/skills/backend-performance-auditor/SKILL.md +10 -0
  312. package/.agents/skills/backend-postgresql/SKILL.md +10 -0
  313. package/.agents/skills/backend-redis/SKILL.md +10 -0
  314. package/.agents/skills/backend-security-expert/SKILL.md +10 -0
  315. package/.agents/skills/backend-sqlalchemy/SKILL.md +10 -0
  316. package/.agents/skills/backend-sqlite/SKILL.md +10 -0
  317. package/.agents/skills/backend-testing-auditor/SKILL.md +15 -0
  318. package/.agents/skills/baseline-ui/SKILL.md +8 -0
  319. package/.agents/skills/bash-linux/SKILL.md +9 -0
  320. package/.agents/skills/behavioral-modes/SKILL.md +9 -0
  321. package/.agents/skills/better-colors/SKILL.md +9 -0
  322. package/.agents/skills/better-typography/SKILL.md +9 -0
  323. package/.agents/skills/better-ui/SKILL.md +8 -0
  324. package/.agents/skills/bolder/SKILL.md +8 -0
  325. package/.agents/skills/brainstorming/SKILL.md +8 -0
  326. package/.agents/skills/browser-audit/SKILL.md +9 -0
  327. package/.agents/skills/browser-native-ai/SKILL.md +8 -0
  328. package/.agents/skills/build-primitive/SKILL.md +8 -0
  329. package/.agents/skills/building-native-ui/SKILL.md +7 -0
  330. package/.agents/skills/cicd-pro/SKILL.md +9 -0
  331. package/.agents/skills/clarify/SKILL.md +8 -0
  332. package/.agents/skills/clean-code/SKILL.md +8 -0
  333. package/.agents/skills/cloud-architect/SKILL.md +8 -0
  334. package/.agents/skills/cobejs/SKILL.md +8 -0
  335. package/.agents/skills/code-review-checklist/SKILL.md +9 -0
  336. package/.agents/skills/codebase-design/SKILL.md +14 -0
  337. package/.agents/skills/colorize/SKILL.md +8 -0
  338. package/.agents/skills/compact-landing/SKILL.md +9 -0
  339. package/.agents/skills/company-logos/SKILL.md +9 -0
  340. package/.agents/skills/config-validator/SKILL.md +9 -0
  341. package/.agents/skills/containerization-pro/SKILL.md +9 -0
  342. package/.agents/skills/context-engineering-pro/SKILL.md +10 -0
  343. package/.agents/skills/create-design-md/SKILL.md +7 -0
  344. package/.agents/skills/critique/SKILL.md +8 -0
  345. package/.agents/skills/csharp-developer/SKILL.md +9 -0
  346. package/.agents/skills/data-validation-schemas/SKILL.md +8 -0
  347. package/.agents/skills/database-design/SKILL.md +8 -0
  348. package/.agents/skills/delight/SKILL.md +8 -0
  349. package/.agents/skills/deployment-procedures/SKILL.md +9 -0
  350. package/.agents/skills/design-lab/SKILL.md +8 -0
  351. package/.agents/skills/devops-engineer/SKILL.md +9 -0
  352. package/.agents/skills/devops-incident-responder/SKILL.md +16 -0
  353. package/.agents/skills/diagnosing-bugs/SKILL.md +9 -0
  354. package/.agents/skills/distill/SKILL.md +8 -0
  355. package/.agents/skills/documentation-templates/SKILL.md +9 -0
  356. package/.agents/skills/domain-modeling/SKILL.md +9 -0
  357. package/.agents/skills/duckdb-analytical-sql/SKILL.md +10 -0
  358. package/.agents/skills/edge-ai-mobile/SKILL.md +8 -0
  359. package/.agents/skills/edge-computing/SKILL.md +9 -0
  360. package/.agents/skills/emil-design-eng/SKILL.md +9 -0
  361. package/.agents/skills/error-resilience/SKILL.md +8 -0
  362. package/.agents/skills/expo-router-v4/SKILL.md +9 -0
  363. package/.agents/skills/extract-design-system/SKILL.md +9 -0
  364. package/.agents/skills/fabel-protocol/SKILL.md +9 -0
  365. package/.agents/skills/failure-mode-analysis/SKILL.md +10 -0
  366. package/.agents/skills/fastapi-pro/SKILL.md +9 -0
  367. package/.agents/skills/fixing-accessibility/SKILL.md +9 -0
  368. package/.agents/skills/fixing-metadata/SKILL.md +9 -0
  369. package/.agents/skills/fixing-motion-performance/SKILL.md +9 -0
  370. package/.agents/skills/framer-motion-expert/SKILL.md +9 -0
  371. package/.agents/skills/frontend-design/SKILL.md +7 -0
  372. package/.agents/skills/frontend-security-expert/SKILL.md +9 -0
  373. package/.agents/skills/game-design-expert/SKILL.md +9 -0
  374. package/.agents/skills/game-engineering-expert/SKILL.md +16 -0
  375. package/.agents/skills/generative-ui-expert/SKILL.md +9 -0
  376. package/.agents/skills/geo-fundamentals/SKILL.md +9 -0
  377. package/.agents/skills/git-pro/SKILL.md +9 -0
  378. package/.agents/skills/github-operations/SKILL.md +9 -0
  379. package/.agents/skills/gpt-taste/SKILL.md +9 -0
  380. package/.agents/skills/graph-engineering/SKILL.md +16 -0
  381. package/.agents/skills/gsap-core/SKILL.md +9 -0
  382. package/.agents/skills/gsap-frameworks/SKILL.md +9 -0
  383. package/.agents/skills/gsap-performance/SKILL.md +9 -0
  384. package/.agents/skills/gsap-plugins/SKILL.md +9 -0
  385. package/.agents/skills/gsap-react/SKILL.md +9 -0
  386. package/.agents/skills/gsap-scrolltrigger/SKILL.md +9 -0
  387. package/.agents/skills/gsap-timeline/SKILL.md +9 -0
  388. package/.agents/skills/gsap-utils/SKILL.md +9 -0
  389. package/.agents/skills/harden/SKILL.md +8 -0
  390. package/.agents/skills/harness-protocol/SKILL.md +9 -0
  391. package/.agents/skills/hf-cli/SKILL.md +11 -0
  392. package/.agents/skills/hf-cloud-aws-context-discovery/SKILL.md +10 -0
  393. package/.agents/skills/hf-cloud-python-env-setup/SKILL.md +10 -0
  394. package/.agents/skills/hf-cloud-sagemaker-deployment-planner/SKILL.md +10 -0
  395. package/.agents/skills/hf-cloud-sagemaker-iam-preflight/SKILL.md +10 -0
  396. package/.agents/skills/hf-cloud-sagemaker-production-defaults/SKILL.md +10 -0
  397. package/.agents/skills/hf-cloud-serving-image-selection/SKILL.md +10 -0
  398. package/.agents/skills/hf-mem/SKILL.md +11 -0
  399. package/.agents/skills/huggingface-best/SKILL.md +9 -0
  400. package/.agents/skills/huggingface-community-evals/SKILL.md +11 -0
  401. package/.agents/skills/huggingface-datasets/SKILL.md +10 -0
  402. package/.agents/skills/huggingface-gradio/SKILL.md +10 -0
  403. package/.agents/skills/huggingface-llm-trainer/SKILL.md +10 -0
  404. package/.agents/skills/huggingface-local-models/SKILL.md +10 -0
  405. package/.agents/skills/huggingface-lora-space-builder/SKILL.md +11 -0
  406. package/.agents/skills/huggingface-paper-publisher/SKILL.md +11 -0
  407. package/.agents/skills/huggingface-papers/SKILL.md +11 -0
  408. package/.agents/skills/huggingface-spaces/SKILL.md +10 -0
  409. package/.agents/skills/huggingface-tool-builder/SKILL.md +11 -0
  410. package/.agents/skills/huggingface-trackio/SKILL.md +11 -0
  411. package/.agents/skills/huggingface-vision-trainer/SKILL.md +11 -0
  412. package/.agents/skills/huggingface-zerogpu/SKILL.md +11 -0
  413. package/.agents/skills/human-gate-negotiation/SKILL.md +11 -0
  414. package/.agents/skills/i18n-localization/SKILL.md +9 -0
  415. package/.agents/skills/impeccable/SKILL.md +8 -0
  416. package/.agents/skills/improve-codebase-architecture/SKILL.md +10 -0
  417. package/.agents/skills/improve-ui/SKILL.md +8 -0
  418. package/.agents/skills/intelligent-routing/SKILL.md +9 -0
  419. package/.agents/skills/knowledge-graph/SKILL.md +9 -0
  420. package/.agents/skills/landing-page/SKILL.md +9 -0
  421. package/.agents/skills/lint-and-validate/SKILL.md +9 -0
  422. package/.agents/skills/llm-engineering/SKILL.md +9 -0
  423. package/.agents/skills/local-first/SKILL.md +10 -0
  424. package/.agents/skills/lottie-animation/SKILL.md +9 -0
  425. package/.agents/skills/marquee-loop/SKILL.md +9 -0
  426. package/.agents/skills/masked-reveal/SKILL.md +9 -0
  427. package/.agents/skills/mcp-builder/SKILL.md +9 -0
  428. package/.agents/skills/micro-interaction/SKILL.md +9 -0
  429. package/.agents/skills/mobile-design/SKILL.md +7 -0
  430. package/.agents/skills/monorepo-management/SKILL.md +9 -0
  431. package/.agents/skills/morphing-icons/SKILL.md +9 -0
  432. package/.agents/skills/motion-engineering/SKILL.md +8 -0
  433. package/.agents/skills/nextjs-react-expert/SKILL.md +10 -0
  434. package/.agents/skills/nodejs-best-practices/SKILL.md +16 -0
  435. package/.agents/skills/observability/SKILL.md +8 -0
  436. package/.agents/skills/opentelemetry-observability/SKILL.md +9 -0
  437. package/.agents/skills/page-transition-animation/SKILL.md +10 -0
  438. package/.agents/skills/parallel-agents/SKILL.md +15 -0
  439. package/.agents/skills/performance-profiling/SKILL.md +9 -0
  440. package/.agents/skills/plan-writing/SKILL.md +8 -0
  441. package/.agents/skills/platform-engineer/SKILL.md +9 -0
  442. package/.agents/skills/platform-engineering-opentofu/SKILL.md +10 -0
  443. package/.agents/skills/playwright-ai-e2e/SKILL.md +9 -0
  444. package/.agents/skills/playwright-best-practices/SKILL.md +16 -0
  445. package/.agents/skills/polish/SKILL.md +8 -0
  446. package/.agents/skills/powershell-windows/SKILL.md +9 -0
  447. package/.agents/skills/pricing-page/SKILL.md +9 -0
  448. package/.agents/skills/product-aware-heuristics/SKILL.md +10 -0
  449. package/.agents/skills/progressive-blur/SKILL.md +9 -0
  450. package/.agents/skills/project-idioms/SKILL.md +8 -0
  451. package/.agents/skills/property-based-testing/SKILL.md +9 -0
  452. package/.agents/skills/python-patterns/SKILL.md +9 -0
  453. package/.agents/skills/python-pro/SKILL.md +9 -0
  454. package/.agents/skills/quieter/SKILL.md +8 -0
  455. package/.agents/skills/react-doctor/SKILL.md +9 -0
  456. package/.agents/skills/react-specialist/SKILL.md +9 -0
  457. package/.agents/skills/readme-builder/SKILL.md +9 -0
  458. package/.agents/skills/realtime-patterns/SKILL.md +9 -0
  459. package/.agents/skills/red-team-tactics/SKILL.md +16 -0
  460. package/.agents/skills/redesign-skill/SKILL.md +9 -0
  461. package/.agents/skills/review-animations/SKILL.md +8 -0
  462. package/.agents/skills/rust-pro/SKILL.md +9 -0
  463. package/.agents/skills/semantic-filesystem-navigation/SKILL.md +11 -0
  464. package/.agents/skills/seo-fundamentals/SKILL.md +9 -0
  465. package/.agents/skills/server-management/SKILL.md +8 -0
  466. package/.agents/skills/session-log-interrogation/SKILL.md +11 -0
  467. package/.agents/skills/shadcn-ui-expert/SKILL.md +9 -0
  468. package/.agents/skills/shape/SKILL.md +8 -0
  469. package/.agents/skills/skill-creator/SKILL.md +9 -0
  470. package/.agents/skills/soft-skill/SKILL.md +9 -0
  471. package/.agents/skills/sounds-on-the-web/SKILL.md +9 -0
  472. package/.agents/skills/sql-pro/SKILL.md +9 -0
  473. package/.agents/skills/subagent-driven-development/SKILL.md +11 -0
  474. package/.agents/skills/supabase-postgres-best-practices/SKILL.md +17 -0
  475. package/.agents/skills/svg-animation/SKILL.md +9 -0
  476. package/.agents/skills/swiftui-expert/SKILL.md +9 -0
  477. package/.agents/skills/swiss-design/SKILL.md +8 -0
  478. package/.agents/skills/system-design-pro/SKILL.md +9 -0
  479. package/.agents/skills/systematic-debugging/SKILL.md +14 -0
  480. package/.agents/skills/tailwind-patterns/SKILL.md +9 -0
  481. package/.agents/skills/taste-skill/SKILL.md +9 -0
  482. package/.agents/skills/tdd-workflow/SKILL.md +9 -0
  483. package/.agents/skills/test-result-analyzer/SKILL.md +9 -0
  484. package/.agents/skills/testing-patterns/SKILL.md +8 -0
  485. package/.agents/skills/thermo-nuclear-code-quality-review/SKILL.md +11 -0
  486. package/.agents/skills/thinking-protocol/SKILL.md +10 -0
  487. package/.agents/skills/to-spring-or-not-to-spring/SKILL.md +9 -0
  488. package/.agents/skills/train-sentence-transformers/SKILL.md +10 -0
  489. package/.agents/skills/transformers-js/SKILL.md +8 -0
  490. package/.agents/skills/transitions-dev/SKILL.md +8 -0
  491. package/.agents/skills/trend-researcher/SKILL.md +9 -0
  492. package/.agents/skills/tribunal-instincts-memory/SKILL.md +11 -0
  493. package/.agents/skills/trl-training/SKILL.md +9 -0
  494. package/.agents/skills/typescript-advanced/SKILL.md +9 -0
  495. package/.agents/skills/typeset/SKILL.md +8 -0
  496. package/.agents/skills/ui-reasoning-engine/SKILL.md +9 -0
  497. package/.agents/skills/ui-skill-packs/SKILL.md +9 -0
  498. package/.agents/skills/ui-skills-root/SKILL.md +9 -0
  499. package/.agents/skills/ui-ux-pro-max/SKILL.md +9 -0
  500. package/.agents/skills/ui-ux-researcher/SKILL.md +8 -0
  501. package/.agents/skills/vector-search-pgvector/SKILL.md +10 -0
  502. package/.agents/skills/verification-before-completion/SKILL.md +9 -0
  503. package/.agents/skills/vue-expert/SKILL.md +9 -0
  504. package/.agents/skills/vulnerability-scanner/SKILL.md +9 -0
  505. package/.agents/skills/web-accessibility-auditor/SKILL.md +16 -0
  506. package/.agents/skills/web-design-guidelines/SKILL.md +9 -0
  507. package/.agents/skills/web-quality-audit/SKILL.md +10 -0
  508. package/.agents/skills/webapp-testing/SKILL.md +8 -0
  509. package/.agents/skills/webgpu-performance/SKILL.md +9 -0
  510. package/.agents/skills/whimsy-injector/SKILL.md +9 -0
  511. package/.agents/skills/workflow-optimizer/SKILL.md +9 -0
  512. package/.agents/skills/zero-trust-passkeys/SKILL.md +10 -0
  513. package/README.md +4 -4
  514. package/bin/adapter-install.js +1 -1
  515. package/bin/mcp-server.js +249 -0
  516. package/package.json +12 -8
  517. package/plugins/core-plugin.json +1 -1
  518. package/plugins/gemini/extension.json +1 -1
  519. package/skills/12-principles-of-animation/SKILL.md +9 -0
  520. package/skills/60fps-animation/SKILL.md +14 -0
  521. package/skills/accessible-animation/SKILL.md +9 -0
  522. package/skills/adapt/SKILL.md +8 -0
  523. package/skills/adr-generation/SKILL.md +9 -0
  524. package/skills/advanced-rag-pipelines/SKILL.md +9 -0
  525. package/skills/agent-organizer/SKILL.md +8 -0
  526. package/skills/agent-syscall-guidelines/SKILL.md +10 -0
  527. package/skills/agentic-patterns/SKILL.md +9 -0
  528. package/skills/agentic-workflows-2026/SKILL.md +8 -0
  529. package/skills/agentshield-security/SKILL.md +16 -0
  530. package/skills/ai-app-hardening/SKILL.md +7 -0
  531. package/skills/ai-prompt-injection-defense/SKILL.md +9 -0
  532. package/skills/animation-on-scroll/SKILL.md +9 -0
  533. package/skills/animation-systems/SKILL.md +8 -0
  534. package/skills/antfu-conventions/SKILL.md +9 -0
  535. package/skills/anti-slop-enforcement/SKILL.md +11 -0
  536. package/skills/api-patterns/SKILL.md +9 -0
  537. package/skills/api-security-auditor/SKILL.md +10 -0
  538. package/skills/app-builder/SKILL.md +8 -0
  539. package/skills/appflow-wireframe/SKILL.md +9 -0
  540. package/skills/apple-design/SKILL.md +8 -0
  541. package/skills/architecture/SKILL.md +8 -0
  542. package/skills/architecture-drift/SKILL.md +9 -0
  543. package/skills/architecture-intelligence/SKILL.md +17 -0
  544. package/skills/audit-and-fix/SKILL.md +8 -0
  545. package/skills/authentication-best-practices/SKILL.md +10 -0
  546. package/skills/autonomous-execution/SKILL.md +9 -0
  547. package/skills/backend-alembic/SKILL.md +16 -0
  548. package/skills/backend-architecture-auditor/SKILL.md +16 -0
  549. package/skills/backend-mongodb/SKILL.md +10 -0
  550. package/skills/backend-mysql/SKILL.md +16 -0
  551. package/skills/backend-performance-auditor/SKILL.md +10 -0
  552. package/skills/backend-postgresql/SKILL.md +10 -0
  553. package/skills/backend-redis/SKILL.md +10 -0
  554. package/skills/backend-security-expert/SKILL.md +10 -0
  555. package/skills/backend-sqlalchemy/SKILL.md +10 -0
  556. package/skills/backend-sqlite/SKILL.md +10 -0
  557. package/skills/backend-testing-auditor/SKILL.md +15 -0
  558. package/skills/baseline-ui/SKILL.md +8 -0
  559. package/skills/bash-linux/SKILL.md +9 -0
  560. package/skills/behavioral-modes/SKILL.md +9 -0
  561. package/skills/better-colors/SKILL.md +9 -0
  562. package/skills/better-typography/SKILL.md +9 -0
  563. package/skills/better-ui/SKILL.md +8 -0
  564. package/skills/bolder/SKILL.md +8 -0
  565. package/skills/brainstorming/SKILL.md +8 -0
  566. package/skills/browser-audit/SKILL.md +9 -0
  567. package/skills/browser-native-ai/SKILL.md +8 -0
  568. package/skills/build-primitive/SKILL.md +8 -0
  569. package/skills/building-native-ui/SKILL.md +7 -0
  570. package/skills/cicd-pro/SKILL.md +9 -0
  571. package/skills/clarify/SKILL.md +8 -0
  572. package/skills/clean-code/SKILL.md +8 -0
  573. package/skills/cloud-architect/SKILL.md +8 -0
  574. package/skills/cobejs/SKILL.md +8 -0
  575. package/skills/code-review-checklist/SKILL.md +9 -0
  576. package/skills/codebase-design/SKILL.md +14 -0
  577. package/skills/colorize/SKILL.md +8 -0
  578. package/skills/compact-landing/SKILL.md +9 -0
  579. package/skills/company-logos/SKILL.md +9 -0
  580. package/skills/config-validator/SKILL.md +9 -0
  581. package/skills/containerization-pro/SKILL.md +9 -0
  582. package/skills/context-engineering-pro/SKILL.md +10 -0
  583. package/skills/create-design-md/SKILL.md +7 -0
  584. package/skills/critique/SKILL.md +8 -0
  585. package/skills/csharp-developer/SKILL.md +9 -0
  586. package/skills/data-validation-schemas/SKILL.md +8 -0
  587. package/skills/database-design/SKILL.md +8 -0
  588. package/skills/delight/SKILL.md +8 -0
  589. package/skills/deployment-procedures/SKILL.md +9 -0
  590. package/skills/design-lab/SKILL.md +8 -0
  591. package/skills/devops-engineer/SKILL.md +9 -0
  592. package/skills/devops-incident-responder/SKILL.md +16 -0
  593. package/skills/diagnosing-bugs/SKILL.md +9 -0
  594. package/skills/distill/SKILL.md +8 -0
  595. package/skills/documentation-templates/SKILL.md +9 -0
  596. package/skills/domain-modeling/SKILL.md +9 -0
  597. package/skills/duckdb-analytical-sql/SKILL.md +10 -0
  598. package/skills/edge-ai-mobile/SKILL.md +8 -0
  599. package/skills/edge-computing/SKILL.md +9 -0
  600. package/skills/emil-design-eng/SKILL.md +9 -0
  601. package/skills/error-resilience/SKILL.md +8 -0
  602. package/skills/expo-router-v4/SKILL.md +9 -0
  603. package/skills/extract-design-system/SKILL.md +9 -0
  604. package/skills/fabel-protocol/SKILL.md +9 -0
  605. package/skills/failure-mode-analysis/SKILL.md +10 -0
  606. package/skills/fastapi-pro/SKILL.md +9 -0
  607. package/skills/fixing-accessibility/SKILL.md +9 -0
  608. package/skills/fixing-metadata/SKILL.md +9 -0
  609. package/skills/fixing-motion-performance/SKILL.md +9 -0
  610. package/skills/framer-motion-expert/SKILL.md +9 -0
  611. package/skills/frontend-design/SKILL.md +7 -0
  612. package/skills/frontend-security-expert/SKILL.md +9 -0
  613. package/skills/game-design-expert/SKILL.md +9 -0
  614. package/skills/game-engineering-expert/SKILL.md +16 -0
  615. package/skills/generative-ui-expert/SKILL.md +9 -0
  616. package/skills/geo-fundamentals/SKILL.md +9 -0
  617. package/skills/git-pro/SKILL.md +9 -0
  618. package/skills/github-operations/SKILL.md +9 -0
  619. package/skills/gpt-taste/SKILL.md +9 -0
  620. package/skills/graph-engineering/SKILL.md +16 -0
  621. package/skills/gsap-core/SKILL.md +9 -0
  622. package/skills/gsap-frameworks/SKILL.md +9 -0
  623. package/skills/gsap-performance/SKILL.md +9 -0
  624. package/skills/gsap-plugins/SKILL.md +9 -0
  625. package/skills/gsap-react/SKILL.md +9 -0
  626. package/skills/gsap-scrolltrigger/SKILL.md +9 -0
  627. package/skills/gsap-timeline/SKILL.md +9 -0
  628. package/skills/gsap-utils/SKILL.md +9 -0
  629. package/skills/harden/SKILL.md +8 -0
  630. package/skills/harness-protocol/SKILL.md +9 -0
  631. package/skills/hf-cli/SKILL.md +11 -0
  632. package/skills/hf-cloud-aws-context-discovery/SKILL.md +10 -0
  633. package/skills/hf-cloud-python-env-setup/SKILL.md +10 -0
  634. package/skills/hf-cloud-sagemaker-deployment-planner/SKILL.md +10 -0
  635. package/skills/hf-cloud-sagemaker-iam-preflight/SKILL.md +10 -0
  636. package/skills/hf-cloud-sagemaker-production-defaults/SKILL.md +10 -0
  637. package/skills/hf-cloud-serving-image-selection/SKILL.md +10 -0
  638. package/skills/hf-mem/SKILL.md +11 -0
  639. package/skills/huggingface-best/SKILL.md +9 -0
  640. package/skills/huggingface-community-evals/SKILL.md +11 -0
  641. package/skills/huggingface-datasets/SKILL.md +10 -0
  642. package/skills/huggingface-gradio/SKILL.md +10 -0
  643. package/skills/huggingface-llm-trainer/SKILL.md +10 -0
  644. package/skills/huggingface-local-models/SKILL.md +10 -0
  645. package/skills/huggingface-lora-space-builder/SKILL.md +11 -0
  646. package/skills/huggingface-paper-publisher/SKILL.md +11 -0
  647. package/skills/huggingface-papers/SKILL.md +11 -0
  648. package/skills/huggingface-spaces/SKILL.md +10 -0
  649. package/skills/huggingface-tool-builder/SKILL.md +11 -0
  650. package/skills/huggingface-trackio/SKILL.md +11 -0
  651. package/skills/huggingface-vision-trainer/SKILL.md +11 -0
  652. package/skills/huggingface-zerogpu/SKILL.md +11 -0
  653. package/skills/human-gate-negotiation/SKILL.md +11 -0
  654. package/skills/i18n-localization/SKILL.md +9 -0
  655. package/skills/impeccable/SKILL.md +8 -0
  656. package/skills/improve-codebase-architecture/SKILL.md +10 -0
  657. package/skills/improve-ui/SKILL.md +8 -0
  658. package/skills/intelligent-routing/SKILL.md +9 -0
  659. package/skills/knowledge-graph/SKILL.md +9 -0
  660. package/skills/landing-page/SKILL.md +9 -0
  661. package/skills/lint-and-validate/SKILL.md +9 -0
  662. package/skills/llm-engineering/SKILL.md +9 -0
  663. package/skills/local-first/SKILL.md +10 -0
  664. package/skills/lottie-animation/SKILL.md +9 -0
  665. package/skills/marquee-loop/SKILL.md +9 -0
  666. package/skills/masked-reveal/SKILL.md +9 -0
  667. package/skills/mcp-builder/SKILL.md +9 -0
  668. package/skills/micro-interaction/SKILL.md +9 -0
  669. package/skills/mobile-design/SKILL.md +7 -0
  670. package/skills/monorepo-management/SKILL.md +9 -0
  671. package/skills/morphing-icons/SKILL.md +9 -0
  672. package/skills/motion-engineering/SKILL.md +8 -0
  673. package/skills/nextjs-react-expert/SKILL.md +10 -0
  674. package/skills/nodejs-best-practices/SKILL.md +16 -0
  675. package/skills/observability/SKILL.md +8 -0
  676. package/skills/opentelemetry-observability/SKILL.md +9 -0
  677. package/skills/page-transition-animation/SKILL.md +10 -0
  678. package/skills/parallel-agents/SKILL.md +15 -0
  679. package/skills/performance-profiling/SKILL.md +9 -0
  680. package/skills/plan-writing/SKILL.md +8 -0
  681. package/skills/platform-engineer/SKILL.md +9 -0
  682. package/skills/platform-engineering-opentofu/SKILL.md +10 -0
  683. package/skills/playwright-ai-e2e/SKILL.md +9 -0
  684. package/skills/playwright-best-practices/SKILL.md +16 -0
  685. package/skills/polish/SKILL.md +8 -0
  686. package/skills/powershell-windows/SKILL.md +9 -0
  687. package/skills/pricing-page/SKILL.md +9 -0
  688. package/skills/product-aware-heuristics/SKILL.md +10 -0
  689. package/skills/progressive-blur/SKILL.md +9 -0
  690. package/skills/project-idioms/SKILL.md +8 -0
  691. package/skills/property-based-testing/SKILL.md +9 -0
  692. package/skills/python-patterns/SKILL.md +9 -0
  693. package/skills/python-pro/SKILL.md +9 -0
  694. package/skills/quieter/SKILL.md +8 -0
  695. package/skills/react-doctor/SKILL.md +9 -0
  696. package/skills/react-specialist/SKILL.md +9 -0
  697. package/skills/readme-builder/SKILL.md +9 -0
  698. package/skills/realtime-patterns/SKILL.md +9 -0
  699. package/skills/red-team-tactics/SKILL.md +16 -0
  700. package/skills/redesign-skill/SKILL.md +9 -0
  701. package/skills/review-animations/SKILL.md +8 -0
  702. package/skills/rust-pro/SKILL.md +9 -0
  703. package/skills/semantic-filesystem-navigation/SKILL.md +11 -0
  704. package/skills/seo-fundamentals/SKILL.md +9 -0
  705. package/skills/server-management/SKILL.md +8 -0
  706. package/skills/session-log-interrogation/SKILL.md +11 -0
  707. package/skills/shadcn-ui-expert/SKILL.md +9 -0
  708. package/skills/shape/SKILL.md +8 -0
  709. package/skills/skill-creator/SKILL.md +9 -0
  710. package/skills/soft-skill/SKILL.md +9 -0
  711. package/skills/sounds-on-the-web/SKILL.md +9 -0
  712. package/skills/sql-pro/SKILL.md +9 -0
  713. package/skills/subagent-driven-development/SKILL.md +11 -0
  714. package/skills/supabase-postgres-best-practices/SKILL.md +17 -0
  715. package/skills/svg-animation/SKILL.md +9 -0
  716. package/skills/swiftui-expert/SKILL.md +9 -0
  717. package/skills/swiss-design/SKILL.md +8 -0
  718. package/skills/system-design-pro/SKILL.md +9 -0
  719. package/skills/systematic-debugging/SKILL.md +14 -0
  720. package/skills/tailwind-patterns/SKILL.md +9 -0
  721. package/skills/taste-skill/SKILL.md +9 -0
  722. package/skills/tdd-workflow/SKILL.md +9 -0
  723. package/skills/test-result-analyzer/SKILL.md +9 -0
  724. package/skills/testing-patterns/SKILL.md +8 -0
  725. package/skills/thermo-nuclear-code-quality-review/SKILL.md +11 -0
  726. package/skills/thinking-protocol/SKILL.md +10 -0
  727. package/skills/to-spring-or-not-to-spring/SKILL.md +9 -0
  728. package/skills/train-sentence-transformers/SKILL.md +10 -0
  729. package/skills/transformers-js/SKILL.md +8 -0
  730. package/skills/transitions-dev/SKILL.md +8 -0
  731. package/skills/trend-researcher/SKILL.md +9 -0
  732. package/skills/tribunal-instincts-memory/SKILL.md +11 -0
  733. package/skills/trl-training/SKILL.md +9 -0
  734. package/skills/typescript-advanced/SKILL.md +9 -0
  735. package/skills/typeset/SKILL.md +8 -0
  736. package/skills/ui-reasoning-engine/SKILL.md +9 -0
  737. package/skills/ui-skill-packs/SKILL.md +9 -0
  738. package/skills/ui-skills-root/SKILL.md +9 -0
  739. package/skills/ui-ux-pro-max/SKILL.md +9 -0
  740. package/skills/ui-ux-researcher/SKILL.md +8 -0
  741. package/skills/vector-search-pgvector/SKILL.md +10 -0
  742. package/skills/verification-before-completion/SKILL.md +9 -0
  743. package/skills/vue-expert/SKILL.md +9 -0
  744. package/skills/vulnerability-scanner/SKILL.md +9 -0
  745. package/skills/web-accessibility-auditor/SKILL.md +16 -0
  746. package/skills/web-design-guidelines/SKILL.md +9 -0
  747. package/skills/web-quality-audit/SKILL.md +10 -0
  748. package/skills/webapp-testing/SKILL.md +8 -0
  749. package/skills/webgpu-performance/SKILL.md +9 -0
  750. package/skills/whimsy-injector/SKILL.md +9 -0
  751. package/skills/workflow-optimizer/SKILL.md +9 -0
  752. package/skills/zero-trust-passkeys/SKILL.md +10 -0
  753. package/src/cli.js +18 -0
  754. package/src/commands/init.js +538 -462
  755. package/src/commands/intelligence.js +86 -0
  756. package/src/commands/review.js +235 -1
  757. package/src/commands/system1.js +562 -413
  758. package/src/evaluation/evaluation_runner.js +207 -0
  759. package/src/evaluation/scenario_registry.js +82 -0
  760. package/src/execution/agent_correction_engine.js +76 -0
  761. package/src/execution/controlled_write_service.js +301 -0
  762. package/src/execution/correction_run_engine.js +234 -0
  763. package/src/execution/correction_verifier.js +85 -0
  764. package/src/execution/evidence_aggregator.js +54 -0
  765. package/src/execution/finding_diff_engine.js +59 -0
  766. package/src/execution/index.js +42 -0
  767. package/src/execution/prompt_isolator.js +145 -0
  768. package/src/execution/provider_adapter.js +495 -0
  769. package/src/execution/resolution_certificate.js +53 -0
  770. package/src/execution/resolution_policy.js +70 -0
  771. package/src/execution/review_executor.js +335 -0
  772. package/src/execution/reviewer_registry.js +137 -0
  773. package/src/execution/schemas.js +298 -0
  774. package/src/execution/transaction_manager.js +237 -0
  775. package/src/execution/validation_runner.js +174 -0
  776. package/src/execution/verdict_aggregator.js +181 -0
  777. package/src/execution/write_policy_engine.js +95 -0
  778. package/src/intelligence/adaptive_correction.js +72 -0
  779. package/src/intelligence/adaptive_reviewer_orchestrator.js +123 -0
  780. package/src/intelligence/case_indexer.js +166 -0
  781. package/src/intelligence/case_memory.js +149 -0
  782. package/src/intelligence/case_similarity.js +86 -0
  783. package/src/intelligence/cbr_engine.js +90 -0
  784. package/src/intelligence/evidence_optimization.js +106 -0
  785. package/src/intelligence/failure_intelligence.js +95 -0
  786. package/src/intelligence/governance_drift_detector.js +75 -0
  787. package/src/intelligence/governance_simulator.js +115 -0
  788. package/src/intelligence/human_intelligence.js +46 -0
  789. package/src/intelligence/mcp_tools.js +87 -0
  790. package/src/intelligence/reviewer_performance.js +94 -0
  791. package/src/intelligence/risk_prediction_engine.js +92 -0
  792. package/src/intelligence/token_intelligence.js +73 -0
  793. package/src/tui/banner.js +26 -47
  794. package/src/tui/index.js +4 -0
  795. package/src/tui/panel.js +55 -0
  796. package/src/tui/progress.js +42 -0
  797. package/src/tui/reviewer-grid.js +9 -10
  798. package/src/tui/theme.js +59 -16
  799. package/src/tui/tree.js +57 -29
  800. package/src/tui/wizard.js +22 -18
  801. package/.agent/skills/local-first-architecture/SKILL.md +0 -123
@@ -1,880 +1,1988 @@
1
- #!/usr/bin/env node
2
- /**
3
- * architecture_visualizer.js — Tribunal Architecture Intelligence Explorer
4
- * ═════════════════════════════════════════════════════════════════════════════
5
- * Generates an ultra-premium, zero-dependency, self-contained standalone HTML
6
- * interactive architecture explorer with 5 dynamic projections:
7
- *
8
- * 1. System Topology (Services, Endpoints, Datastores, Queues)
9
- * 2. Security Trust Zones (Public Untrusted, DMZ, Authenticated, Datastore)
10
- * 3. Failure Architecture (Timeouts, Retries, Fallbacks, Circuit Breakers)
11
- * 4. Data Lineage & Persistence
12
- * 5. Interactive Blast Radius Simulator (Real-time downstream impact on click)
13
- *
14
- * Features:
15
- * - Offline zero-CDN execution
16
- * - Dark aesthetic with vibrant HSL design tokens
17
- * - Pan, zoom, search, node filtering, and focus isolation
18
- * - Live Evidence Drawer with verified source files, line numbers, and L1-L5 badges
19
- *
20
- * Zero external dependencies.
21
- */
22
-
23
- 'use strict';
24
-
25
- const fs = require('fs');
26
- const path = require('path');
27
- const { GREEN, CYAN, RED, DIM, RESET, BOX, banner, timer, formatMs } = require('./_colors');
28
-
29
- class ArchitectureVisualizer {
30
- constructor(model, verification = null) {
31
- this.model = model;
32
- this.verification = verification;
33
- }
34
-
35
- generateHtml() {
36
- const rawDataJson = JSON.stringify({
37
- model: this.model,
38
- verification: this.verification,
39
- }).replace(/</g, '\\u003c');
40
-
41
- return `<!DOCTYPE html>
42
- <html lang="en">
43
- <head>
44
- <meta charset="UTF-8">
45
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
46
- <title>Tribunal Architecture Intelligence Explorer</title>
47
- <style>
48
- :root {
49
- --bg: #09090b;
50
- --bg-panel: rgba(18, 18, 24, 0.85);
51
- --bg-card: #14141e;
52
- --border: #272738;
53
- --border-bright: #3f3f5a;
54
- --text: #f4f4f6;
55
- --text-dim: #9494a8;
56
- --accent-cyan: #06b6d4;
57
- --accent-blue: #3b82f6;
58
- --accent-green: #10b981;
59
- --accent-amber: #f59e0b;
60
- --accent-rose: #f43f5e;
61
- --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
62
- --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
63
- }
64
-
65
- * { box-sizing: border-box; margin: 0; padding: 0; }
66
- body {
67
- background: var(--bg);
68
- color: var(--text);
69
- font-family: var(--font-sans);
70
- height: 100vh;
71
- overflow: hidden;
72
- display: flex;
73
- flex-direction: column;
74
- }
75
-
76
- /* Top Navigation Bar */
77
- header {
78
- height: 56px;
79
- background: var(--bg-panel);
80
- backdrop-filter: blur(12px);
81
- border-bottom: 1px solid var(--border);
82
- display: flex;
83
- align-items: center;
84
- justify-content: space-between;
85
- padding: 0 20px;
86
- z-index: 50;
87
- flex-shrink: 0;
88
- }
89
-
90
- .brand {
91
- display: flex;
92
- align-items: center;
93
- gap: 10px;
94
- font-weight: 700;
95
- font-size: 15px;
96
- letter-spacing: -0.01em;
97
- }
98
- .brand-badge {
99
- background: linear-gradient(135deg, #06b6d4, #3b82f6);
100
- color: #000;
101
- font-size: 10px;
102
- font-weight: 800;
103
- padding: 2px 7px;
104
- border-radius: 4px;
105
- text-transform: uppercase;
106
- }
107
-
108
- /* Projection Tabs */
109
- .projection-tabs {
110
- display: flex;
111
- gap: 4px;
112
- background: rgba(0, 0, 0, 0.4);
113
- padding: 3px;
114
- border-radius: 8px;
115
- border: 1px solid var(--border);
116
- }
117
- .tab-btn {
118
- background: transparent;
119
- border: none;
120
- color: var(--text-dim);
121
- padding: 6px 14px;
122
- border-radius: 6px;
123
- font-size: 12px;
124
- font-weight: 600;
125
- cursor: pointer;
126
- transition: all 0.15s ease;
127
- }
128
- .tab-btn:hover { color: var(--text); }
129
- .tab-btn.active {
130
- background: var(--border-bright);
131
- color: #fff;
132
- box-shadow: 0 1px 3px rgba(0,0,0,0.3);
133
- }
134
-
135
- .header-actions {
136
- display: flex;
137
- align-items: center;
138
- gap: 12px;
139
- }
140
- .search-box {
141
- position: relative;
142
- }
143
- .search-box input {
144
- background: #14141e;
145
- border: 1px solid var(--border);
146
- border-radius: 6px;
147
- color: var(--text);
148
- font-size: 12px;
149
- padding: 6px 12px 6px 28px;
150
- outline: none;
151
- width: 220px;
152
- transition: border-color 0.15s ease;
153
- }
154
- .search-box input:focus { border-color: var(--accent-cyan); }
155
- .search-icon {
156
- position: absolute;
157
- left: 9px;
158
- top: 7px;
159
- color: var(--text-dim);
160
- font-size: 12px;
161
- }
162
-
163
- /* Main Canvas Area */
164
- .viewport {
165
- flex: 1;
166
- position: relative;
167
- overflow: hidden;
168
- cursor: grab;
169
- user-select: none;
170
- }
171
- .viewport:active { cursor: grabbing; }
172
-
173
- svg#arch-canvas {
174
- width: 100%;
175
- height: 100%;
176
- display: block;
177
- }
178
-
179
- /* Floating Controls */
180
- .canvas-controls {
181
- position: absolute;
182
- bottom: 20px;
183
- left: 20px;
184
- display: flex;
185
- gap: 6px;
186
- background: var(--bg-panel);
187
- backdrop-filter: blur(8px);
188
- padding: 4px;
189
- border-radius: 8px;
190
- border: 1px solid var(--border);
191
- z-index: 40;
192
- }
193
- .ctrl-btn {
194
- background: transparent;
195
- border: 1px solid transparent;
196
- color: var(--text);
197
- width: 32px;
198
- height: 32px;
199
- border-radius: 6px;
200
- display: flex;
201
- align-items: center;
202
- justify-content: center;
203
- cursor: pointer;
204
- font-size: 14px;
205
- transition: background 0.1s ease;
206
- }
207
- .ctrl-btn:hover { background: var(--border); }
208
-
209
- /* Legend Overlay */
210
- .legend-card {
211
- position: absolute;
212
- bottom: 20px;
213
- right: 20px;
214
- background: var(--bg-panel);
215
- backdrop-filter: blur(8px);
216
- padding: 12px 16px;
217
- border-radius: 8px;
218
- border: 1px solid var(--border);
219
- font-size: 11px;
220
- z-index: 40;
221
- max-width: 280px;
222
- }
223
- .legend-title {
224
- font-weight: 700;
225
- margin-bottom: 8px;
226
- text-transform: uppercase;
227
- letter-spacing: 0.05em;
228
- color: var(--text-dim);
229
- }
230
- .legend-item {
231
- display: flex;
232
- align-items: center;
233
- gap: 8px;
234
- margin-bottom: 4px;
235
- }
236
- .legend-dot {
237
- width: 10px;
238
- height: 10px;
239
- border-radius: 3px;
240
- }
241
-
242
- /* Slide-over Evidence Drawer */
243
- #evidence-drawer {
244
- position: absolute;
245
- top: 56px;
246
- right: 0;
247
- bottom: 0;
248
- width: 440px;
249
- background: var(--bg-panel);
250
- backdrop-filter: blur(16px);
251
- border-left: 1px solid var(--border);
252
- padding: 24px;
253
- overflow-y: auto;
254
- transform: translateX(100%);
255
- transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);
256
- z-index: 60;
257
- }
258
- #evidence-drawer.open { transform: translateX(0); }
259
-
260
- .drawer-close {
261
- position: absolute;
262
- top: 16px;
263
- right: 16px;
264
- background: transparent;
265
- border: none;
266
- color: var(--text-dim);
267
- font-size: 18px;
268
- cursor: pointer;
269
- }
270
- .drawer-close:hover { color: var(--text); }
271
-
272
- .drawer-title { font-size: 18px; font-weight: 700; margin-bottom: 4px; }
273
- .drawer-subtitle { font-size: 12px; color: var(--text-dim); margin-bottom: 16px; font-family: var(--font-mono); }
274
-
275
- .stat-pill-group {
276
- display: flex;
277
- gap: 8px;
278
- flex-wrap: wrap;
279
- margin-bottom: 20px;
280
- }
281
- .stat-pill {
282
- background: var(--bg-card);
283
- border: 1px solid var(--border);
284
- padding: 6px 12px;
285
- border-radius: 6px;
286
- font-size: 11px;
287
- }
288
- .stat-pill strong { color: var(--accent-cyan); }
289
-
290
- .section-title {
291
- font-size: 12px;
292
- font-weight: 700;
293
- text-transform: uppercase;
294
- letter-spacing: 0.05em;
295
- color: var(--text-dim);
296
- margin: 16px 0 8px 0;
297
- }
298
-
299
- .evidence-block {
300
- background: #0d0d14;
301
- border: 1px solid var(--border);
302
- border-radius: 6px;
303
- padding: 12px;
304
- margin-bottom: 8px;
305
- font-family: var(--font-mono);
306
- font-size: 11px;
307
- }
308
- .evidence-loc { color: var(--accent-cyan); font-weight: 600; margin-bottom: 4px; }
309
- .evidence-snippet {
310
- color: #cbd5e1;
311
- white-space: pre-wrap;
312
- word-break: break-all;
313
- background: rgba(0,0,0,0.3);
314
- padding: 6px;
315
- border-radius: 4px;
316
- margin-top: 6px;
317
- }
318
- .confidence-badge {
319
- display: inline-block;
320
- padding: 2px 6px;
321
- border-radius: 4px;
322
- font-size: 9px;
323
- font-weight: 800;
324
- text-transform: uppercase;
325
- }
326
- .conf-L1 { background: #065f46; color: #34d399; }
327
- .conf-L2 { background: #1e3a8a; color: #60a5fa; }
328
- .conf-L3 { background: #78350f; color: #fbbf24; }
329
- .conf-L5 { background: #881337; color: #f43f5e; }
330
-
331
- /* SVG Graphical Node Styling */
332
- .node-group { cursor: pointer; transition: opacity 0.2s; }
333
- .node-box {
334
- stroke-width: 1.5px;
335
- rx: 8px;
336
- transition: all 0.2s ease;
337
- }
338
- .node-group:hover .node-box {
339
- stroke-width: 2.5px;
340
- filter: drop-shadow(0 0 8px rgba(6, 182, 212, 0.4));
341
- }
342
- .node-text-title {
343
- font-family: var(--font-sans);
344
- font-weight: 700;
345
- fill: #ffffff;
346
- font-size: 12px;
347
- pointer-events: none;
348
- }
349
- .node-text-sub {
350
- font-family: var(--font-sans);
351
- font-size: 10px;
352
- fill: #9494a8;
353
- pointer-events: none;
354
- }
355
- .edge-path {
356
- fill: none;
357
- stroke-width: 1.5px;
358
- transition: stroke 0.2s, stroke-width 0.2s;
359
- }
360
- .edge-marker { fill: #475569; }
361
-
362
- /* Dimming & Highlight states */
363
- .dimmed { opacity: 0.15; }
364
- .highlighted { opacity: 1 !important; }
365
- .highlighted-edge { stroke: #06b6d4 !important; stroke-width: 2.5px !important; }
366
- .blast-ring-1 { stroke: #f43f5e !important; stroke-width: 3px !important; }
367
- .blast-ring-2 { stroke: #f59e0b !important; stroke-width: 2.5px !important; }
368
- .blast-ring-3 { stroke: #3b82f6 !important; stroke-width: 2px !important; }
369
- </style>
370
- </head>
371
- <body>
372
-
373
- <header>
374
- <div class="brand">
375
- <span>⚖️ Tribunal Architecture Intelligence</span>
376
- <span class="brand-badge">TAI Fact Graph</span>
377
- </div>
378
-
379
- <div class="projection-tabs">
380
- <button class="tab-btn active" data-projection="topology">Topology</button>
381
- <button class="tab-btn" data-projection="security">Security Zones</button>
382
- <button class="tab-btn" data-projection="failure">Failure Modes</button>
383
- <button class="tab-btn" data-projection="blast">Blast Radius Simulator</button>
384
- </div>
385
-
386
- <div class="header-actions">
387
- <div class="search-box">
388
- <span class="search-icon">🔍</span>
389
- <input type="text" id="node-search" placeholder="Search architecture...">
390
- </div>
391
- </div>
392
- </header>
393
-
394
- <main class="viewport" id="viewport">
395
- <svg id="arch-canvas">
396
- <defs>
397
- <marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
398
- <path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#64748b" />
399
- </marker>
400
- <marker id="arrow-active" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
401
- <path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#06b6d4" />
402
- </marker>
403
- <marker id="arrow-warn" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
404
- <path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#f59e0b" />
405
- </marker>
406
- </defs>
407
- <g id="world-layer">
408
- <g id="zones-layer"></g>
409
- <g id="edges-layer"></g>
410
- <g id="nodes-layer"></g>
411
- </g>
412
- </svg>
413
-
414
- <div class="canvas-controls">
415
- <button class="ctrl-btn" id="btn-zoom-in" title="Zoom In">+</button>
416
- <button class="ctrl-btn" id="btn-zoom-out" title="Zoom Out">−</button>
417
- <button class="ctrl-btn" id="btn-zoom-reset" title="Fit Screen">⛶</button>
418
- </div>
419
-
420
- <div class="legend-card" id="legend">
421
- <div class="legend-title" id="legend-title">System Topology</div>
422
- <div id="legend-items"></div>
423
- </div>
424
- </main>
425
-
426
- <aside id="evidence-drawer">
427
- <button class="drawer-close" id="drawer-close">✕</button>
428
- <div id="drawer-content"></div>
429
- </aside>
430
-
431
- <script id="tribunal-architecture-data" type="application/json">
432
- ${rawDataJson}
433
- </script>
434
-
435
- <script>
436
- (function () {
437
- const rawData = JSON.parse(document.getElementById('tribunal-architecture-data').textContent);
438
- const model = rawData.model;
439
- const entities = model.entities || [];
440
- const relationships = model.relationships || [];
441
- const trustBoundaries = model.trustBoundaries || [];
442
-
443
- let currentProjection = 'topology';
444
- let selectedNodeId = null;
445
-
446
- // Transform & Pan/Zoom State
447
- let transform = { x: 80, y: 80, k: 0.75 };
448
- let isPanning = false;
449
- let startPoint = { x: 0, y: 0 };
450
-
451
- const viewport = document.getElementById('viewport');
452
- const world = document.getElementById('world-layer');
453
- const nodesLayer = document.getElementById('nodes-layer');
454
- const edgesLayer = document.getElementById('edges-layer');
455
- const zonesLayer = document.getElementById('zones-layer');
456
- const drawer = document.getElementById('evidence-drawer');
457
- const drawerContent = document.getElementById('drawer-content');
458
- const drawerClose = document.getElementById('drawer-close');
459
-
460
- // ── Build Spatial Layout with Semantic Column Zoning ──────────────────
461
- const NODE_W = 160;
462
- const NODE_H = 60;
463
- const GAP_X = 240;
464
- const GAP_Y = 90;
465
-
466
- const columnMap = {
467
- endpoint: 0,
468
- module: 1,
469
- event_bus: 2,
470
- queue: 2,
471
- cache: 2,
472
- datastore: 3,
473
- external_api: 3,
474
- identity_provider: 0,
475
- test_suite: 1,
476
- };
477
-
478
- const columns = [[], [], [], []];
479
- entities.forEach(e => {
480
- const col = columnMap[e.kind] ?? 1;
481
- columns[col].push(e);
482
- });
483
-
484
- const nodeCoords = new Map();
485
- columns.forEach((colEntities, colIdx) => {
486
- colEntities.forEach((entity, rowIdx) => {
487
- nodeCoords.set(entity.id, {
488
- x: colIdx * (NODE_W + GAP_X) + 100,
489
- y: rowIdx * (NODE_H + GAP_Y) + 100,
490
- w: NODE_W,
491
- h: NODE_H,
492
- entity
493
- });
494
- });
495
- });
496
-
497
- // ── Render Graph ──────────────────────────────────────────────────────
498
- function updateCanvasTransform() {
499
- world.setAttribute('transform', \`translate(\${transform.x}, \${transform.y}) scale(\${transform.k})\`);
500
- }
501
-
502
- function renderEdges() {
503
- edgesLayer.innerHTML = '';
504
- relationships.forEach(rel => {
505
- const src = nodeCoords.get(rel.sourceId);
506
- const tgt = nodeCoords.get(rel.targetId);
507
- if (!src || !tgt) return;
508
-
509
- const x1 = src.x + src.w;
510
- const y1 = src.y + src.h / 2;
511
- const x2 = tgt.x;
512
- const y2 = tgt.y + tgt.h / 2;
513
-
514
- const dx = (x2 - x1) / 2;
515
- const d = \`M \${x1} \${y1} C \${x1 + dx} \${y1}, \${x2 - dx} \${y2}, \${x2} \${y2}\`;
516
-
517
- const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
518
- path.setAttribute('d', d);
519
- path.setAttribute('class', 'edge-path');
520
- path.setAttribute('data-id', rel.id);
521
- path.setAttribute('data-source', rel.sourceId);
522
- path.setAttribute('data-target', rel.targetId);
523
-
524
- let strokeColor = '#334155';
525
- let marker = 'url(#arrow)';
526
-
527
- if (currentProjection === 'failure' && rel.failureMode && !rel.failureMode.hasTimeout) {
528
- strokeColor = '#f59e0b';
529
- marker = 'url(#arrow-warn)';
530
- }
531
-
532
- path.setAttribute('stroke', strokeColor);
533
- path.setAttribute('marker-end', marker);
534
- edgesLayer.appendChild(path);
535
- });
536
- }
537
-
538
- function renderNodes() {
539
- nodesLayer.innerHTML = '';
540
- entities.forEach(entity => {
541
- const coord = nodeCoords.get(entity.id);
542
- if (!coord) return;
543
-
544
- const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
545
- g.setAttribute('class', 'node-group');
546
- g.setAttribute('data-id', entity.id);
547
- g.setAttribute('transform', \`translate(\${coord.x}, \${coord.y})\`);
548
-
549
- // Color tokens by projection
550
- let stroke = '#272738';
551
- let fill = '#14141e';
552
-
553
- if (currentProjection === 'topology') {
554
- if (entity.kind === 'endpoint') stroke = '#06b6d4';
555
- else if (entity.kind === 'datastore' || entity.kind === 'cache') stroke = '#3b82f6';
556
- else if (entity.kind === 'queue' || entity.kind === 'event_bus') stroke = '#a855f7';
557
- else if (entity.kind === 'external_api') stroke = '#f43f5e';
558
- else stroke = '#475569';
559
- } else if (currentProjection === 'security') {
560
- if (entity.trustZone === 'public_untrusted') stroke = '#f43f5e';
561
- else if (entity.trustZone === 'dmz_gateway') stroke = '#f59e0b';
562
- else if (entity.trustZone === 'internal_service') stroke = '#10b981';
563
- else if (entity.trustZone === 'isolated_datastore') stroke = '#3b82f6';
564
- else stroke = '#64748b';
565
- } else if (currentProjection === 'failure') {
566
- if (entity.kind === 'external_api') stroke = '#f59e0b';
567
- else stroke = '#334155';
568
- }
569
-
570
- const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
571
- rect.setAttribute('width', coord.w);
572
- rect.setAttribute('height', coord.h);
573
- rect.setAttribute('class', 'node-box');
574
- rect.setAttribute('fill', fill);
575
- rect.setAttribute('stroke', stroke);
576
-
577
- const title = document.createElementNS('http://www.w3.org/2000/svg', 'text');
578
- title.setAttribute('x', 12);
579
- title.setAttribute('y', 26);
580
- title.setAttribute('class', 'node-text-title');
581
- const cleanName = entity.name.length > 18 ? entity.name.slice(0, 16) + '...' : entity.name;
582
- title.textContent = cleanName;
583
-
584
- const sub = document.createElementNS('http://www.w3.org/2000/svg', 'text');
585
- sub.setAttribute('x', 12);
586
- sub.setAttribute('y', 44);
587
- sub.setAttribute('class', 'node-text-sub');
588
- sub.textContent = entity.kind.replace('_', ' ').toUpperCase();
589
-
590
- g.appendChild(rect);
591
- g.appendChild(title);
592
- g.appendChild(sub);
593
-
594
- g.addEventListener('click', (ev) => {
595
- ev.stopPropagation();
596
- onNodeClick(entity.id);
597
- });
598
-
599
- nodesLayer.appendChild(g);
600
- });
601
- }
602
-
603
- function updateLegend() {
604
- const titleEl = document.getElementById('legend-title');
605
- const itemsEl = document.getElementById('legend-items');
606
-
607
- const legends = {
608
- topology: {
609
- title: 'System Topology',
610
- items: [
611
- { color: '#06b6d4', label: 'HTTP API Endpoint' },
612
- { color: '#475569', label: 'Internal Module' },
613
- { color: '#3b82f6', label: 'Datastore / Cache' },
614
- { color: '#a855f7', label: 'Queue / Event Channel' },
615
- { color: '#f43f5e', label: 'External Service' },
616
- ]
617
- },
618
- security: {
619
- title: 'Security Trust Zones',
620
- items: [
621
- { color: '#f43f5e', label: 'Public Untrusted' },
622
- { color: '#f59e0b', label: 'DMZ Gateway / Auth' },
623
- { color: '#10b981', label: 'Authenticated Service' },
624
- { color: '#3b82f6', label: 'Isolated Datastore' },
625
- ]
626
- },
627
- failure: {
628
- title: 'Failure Architecture',
629
- items: [
630
- { color: '#f59e0b', label: 'External (No Timeout)' },
631
- { color: '#10b981', label: 'Resilient RPC' },
632
- ]
633
- },
634
- blast: {
635
- title: 'Blast Radius Simulator',
636
- items: [
637
- { color: '#f43f5e', label: 'Ring 1 (Direct Impact)' },
638
- { color: '#f59e0b', label: 'Ring 2 (Transitive Depth 2)' },
639
- { color: '#3b82f6', label: 'Ring 3+ (Deep Transitive)' },
640
- ]
641
- }
642
- };
643
-
644
- const cur = legends[currentProjection] || legends.topology;
645
- titleEl.textContent = cur.title;
646
- itemsEl.innerHTML = cur.items.map(it => \`
647
- <div class="legend-item">
648
- <div class="legend-dot" style="background: \${it.color}"></div>
649
- <span>\${it.label}</span>
650
- </div>
651
- \`).join('');
652
- }
653
-
654
- // ── Interactive Selection & Blast Simulation ─────────────────────────
655
- function onNodeClick(id) {
656
- selectedNodeId = id;
657
- const entity = entities.find(e => e.id === id);
658
- if (!entity) return;
659
-
660
- // Reset styling
661
- document.querySelectorAll('.node-group').forEach(el => el.classList.remove('dimmed', 'highlighted'));
662
- document.querySelectorAll('.edge-path').forEach(el => {
663
- el.classList.remove('dimmed', 'highlighted-edge', 'blast-ring-1', 'blast-ring-2', 'blast-ring-3');
664
- });
665
-
666
- if (currentProjection === 'blast') {
667
- // Live Blast Simulation
668
- const ring1 = new Set();
669
- const ring2 = new Set();
670
- const ring3 = new Set();
671
-
672
- relationships.forEach(r => {
673
- if (r.targetId === id) ring1.add(r.sourceId);
674
- });
675
- relationships.forEach(r => {
676
- if (ring1.has(r.targetId) && r.sourceId !== id) ring2.add(r.sourceId);
677
- });
678
- relationships.forEach(r => {
679
- if (ring2.has(r.targetId) && !ring1.has(r.sourceId) && r.sourceId !== id) ring3.add(r.sourceId);
680
- });
681
-
682
- document.querySelectorAll('.node-group').forEach(el => {
683
- const elId = el.getAttribute('data-id');
684
- if (elId === id) el.classList.add('highlighted');
685
- else if (ring1.has(elId) || ring2.has(elId) || ring3.has(elId)) el.classList.add('highlighted');
686
- else el.classList.add('dimmed');
687
- });
688
-
689
- document.querySelectorAll('.edge-path').forEach(el => {
690
- const tgt = el.getAttribute('data-target');
691
- if (tgt === id) el.classList.add('blast-ring-1');
692
- else if (ring1.has(tgt)) el.classList.add('blast-ring-2');
693
- else if (ring2.has(tgt)) el.classList.add('blast-ring-3');
694
- else el.classList.add('dimmed');
695
- });
696
- } else {
697
- // Standard connected focus
698
- const connectedNodes = new Set([id]);
699
- relationships.forEach(r => {
700
- if (r.sourceId === id) connectedNodes.add(r.targetId);
701
- if (r.targetId === id) connectedNodes.add(r.sourceId);
702
- });
703
-
704
- document.querySelectorAll('.node-group').forEach(el => {
705
- const elId = el.getAttribute('data-id');
706
- if (connectedNodes.has(elId)) el.classList.add('highlighted');
707
- else el.classList.add('dimmed');
708
- });
709
-
710
- document.querySelectorAll('.edge-path').forEach(el => {
711
- const s = el.getAttribute('data-source');
712
- const t = el.getAttribute('data-target');
713
- if (s === id || t === id) el.classList.add('highlighted-edge');
714
- else el.classList.add('dimmed');
715
- });
716
- }
717
-
718
- openDrawer(entity);
719
- }
720
-
721
- function openDrawer(entity) {
722
- drawer.classList.add('open');
723
- const sources = entity.sources || [];
724
-
725
- drawerContent.innerHTML = \`
726
- <h2 class="drawer-title">\${entity.name}</h2>
727
- <div class="drawer-subtitle">\${entity.id}</div>
728
-
729
- <div class="stat-pill-group">
730
- <div class="stat-pill">Kind: <strong>\${entity.kind}</strong></div>
731
- <div class="stat-pill">Zone: <strong>\${entity.trustZone || 'none'}</strong></div>
732
- <div class="stat-pill">Risk: <strong>\${entity.blastRadius?.riskScore || 0.1}</strong></div>
733
- <div class="stat-pill">Confidence: <span class="confidence-badge conf-\${entity.confidence || 'L1'}">\${entity.confidence || 'L1'} FACT</span></div>
734
- </div>
735
-
736
- <div class="section-title">Verified Source Code Evidence</div>
737
- \${sources.map(s => \`
738
- <div class="evidence-block">
739
- <div class="evidence-loc">\${s.file}:\${s.startLine}\${s.endLine ? '-' + s.endLine : ''}</div>
740
- <div>Hash: <code>\${s.contentHash || 'verified'}</code></div>
741
- \${s.snippet ? \`<div class="evidence-snippet">\${s.snippet}</div>\` : ''}
742
- </div>
743
- \`).join('')}
744
-
745
- <div class="section-title">Architectural Role & Description</div>
746
- <p style="font-size: 13px; line-height: 1.5; color: #cbd5e1; margin-bottom: 16px;">
747
- \${entity.role || 'Internal architectural component extracted deterministically from codebase AST.'}
748
- </p>
749
- \`;
750
- }
751
-
752
- drawerClose.addEventListener('click', () => {
753
- drawer.classList.remove('open');
754
- document.querySelectorAll('.node-group').forEach(el => el.classList.remove('dimmed', 'highlighted'));
755
- document.querySelectorAll('.edge-path').forEach(el => {
756
- el.classList.remove('dimmed', 'highlighted-edge', 'blast-ring-1', 'blast-ring-2', 'blast-ring-3');
757
- });
758
- });
759
-
760
- // ── Event Handlers: Pan / Zoom / Tabs ────────────────────────────────
761
- viewport.addEventListener('mousedown', (e) => {
762
- if (e.target.closest('.node-group')) return;
763
- isPanning = true;
764
- startPoint = { x: e.clientX - transform.x, y: e.clientY - transform.y };
765
- });
766
- window.addEventListener('mousemove', (e) => {
767
- if (!isPanning) return;
768
- transform.x = e.clientX - startPoint.x;
769
- transform.y = e.clientY - startPoint.y;
770
- updateCanvasTransform();
771
- });
772
- window.addEventListener('mouseup', () => { isPanning = false; });
773
-
774
- viewport.addEventListener('wheel', (e) => {
775
- e.preventDefault();
776
- const factor = e.deltaY > 0 ? 0.9 : 1.1;
777
- transform.k = Math.max(0.2, Math.min(3.0, transform.k * factor));
778
- updateCanvasTransform();
779
- });
780
-
781
- document.getElementById('btn-zoom-in').addEventListener('click', () => {
782
- transform.k = Math.min(3.0, transform.k * 1.2);
783
- updateCanvasTransform();
784
- });
785
- document.getElementById('btn-zoom-out').addEventListener('click', () => {
786
- transform.k = Math.max(0.2, transform.k / 1.2);
787
- updateCanvasTransform();
788
- });
789
- document.getElementById('btn-zoom-reset').addEventListener('click', () => {
790
- transform = { x: 80, y: 80, k: 0.75 };
791
- updateCanvasTransform();
792
- });
793
-
794
- document.querySelectorAll('.tab-btn').forEach(btn => {
795
- btn.addEventListener('click', () => {
796
- document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
797
- btn.classList.add('active');
798
- currentProjection = btn.getAttribute('data-projection');
799
- updateLegend();
800
- renderNodes();
801
- renderEdges();
802
- if (selectedNodeId) onNodeClick(selectedNodeId);
803
- });
804
- });
805
-
806
- // Search Handler
807
- document.getElementById('node-search').addEventListener('input', (e) => {
808
- const query = e.target.value.toLowerCase().trim();
809
- if (!query) {
810
- document.querySelectorAll('.node-group').forEach(el => el.classList.remove('dimmed', 'highlighted'));
811
- return;
812
- }
813
- document.querySelectorAll('.node-group').forEach(el => {
814
- const id = el.getAttribute('data-id').toLowerCase();
815
- const ent = entities.find(x => x.id.toLowerCase() === id);
816
- if (id.includes(query) || (ent && ent.name.toLowerCase().includes(query))) {
817
- el.classList.add('highlighted');
818
- el.classList.remove('dimmed');
819
- } else {
820
- el.classList.add('dimmed');
821
- el.classList.remove('highlighted');
822
- }
823
- });
824
- });
825
-
826
- // Initial Mount
827
- updateCanvasTransform();
828
- updateLegend();
829
- renderNodes();
830
- renderEdges();
831
- })();
832
- </script>
833
- </body>
834
- </html>`;
835
- }
836
-
837
- saveHtml(outputPath) {
838
- const dest =
839
- outputPath || path.join(process.cwd(), '.agent', 'history', 'architecture-intelligence.html');
840
- fs.mkdirSync(path.dirname(dest), { recursive: true });
841
- const html = this.generateHtml();
842
- fs.writeFileSync(dest, html, 'utf8');
843
- return dest;
844
- }
845
- }
846
-
847
- // ── Standalone CLI ────────────────────────────────────────────────────────────
848
- if (require.main === module) {
849
- const t = timer();
850
- const repoRoot = process.cwd();
851
- const modelFile = path.join(repoRoot, '.agent', 'history', 'architecture-model.json');
852
- const verifFile = path.join(repoRoot, '.agent', 'history', 'architecture-verification.json');
853
-
854
- console.log(banner('Tribunal Architecture Intelligence Visualizer'));
855
-
856
- if (!fs.existsSync(modelFile)) {
857
- console.error(
858
- ` ${RED}✖ architecture-model.json not found.${RESET} Run architecture_extractor.js first.`,
859
- );
860
- process.exit(1);
861
- }
862
-
863
- const model = JSON.parse(fs.readFileSync(modelFile, 'utf8'));
864
- const verification = fs.existsSync(verifFile)
865
- ? JSON.parse(fs.readFileSync(verifFile, 'utf8'))
866
- : null;
867
-
868
- const visualizer = new ArchitectureVisualizer(model, verification);
869
- const outPath = visualizer.saveHtml();
870
-
871
- console.log(` ${GREEN}${BOX.check} Interactive Architecture Explorer Generated!${RESET}`);
872
- console.log(` ${DIM}File:${RESET} ${CYAN}${outPath}${RESET} (${formatMs(t())})`);
873
- console.log(
874
- ` ${DIM}Projections Enabled:${RESET} Topology, Security Zones, Failure Modes, Blast Simulator\n`,
875
- );
876
- }
877
-
878
- module.exports = {
879
- ArchitectureVisualizer,
880
- };
1
+ #!/usr/bin/env node
2
+ /**
3
+ * architecture_visualizer.js — Tribunal Architecture Intelligence Explorer
4
+ * ═════════════════════════════════════════════════════════════════════════════
5
+ * The Evidence Console: Ultra-premium, zero-dependency, self-contained standalone
6
+ * interactive architecture explorer inspired by Archify's precision engineering
7
+ * aesthetics and enhanced with Tribunal's zero-trust verification engine.
8
+ *
9
+ * Core Capabilities:
10
+ * - 4 Visual Presets:
11
+ * • Obsidian Console (Classic Dark Precision)
12
+ * • Signal Flow (Live animated pulses & atmospheric depth)
13
+ * • Cyber Blueprint (Technical drafting grid, 0.2rem sharp geometry)
14
+ * • Editorial Monolith (Swiss bone parchment, high-contrast typography)
15
+ * - Dark / Light Theme Parity with instant zero-flash theme persistence (T key)
16
+ * - Multi-Projection Architecture:
17
+ * 1. System Topology (Endpoints, Modules, Datastores, Queues, External APIs)
18
+ * 2. Security Trust Zones (Public Untrusted, DMZ Gateway, Authenticated, Isolated)
19
+ * 3. Failure Architecture (Timeouts, Resilient RPCs, Circuit Breakers)
20
+ * 4. Blast Radius Simulator (Live concentric impact rings on click)
21
+ * - Semantic Passport (Slide-over proof drawer):
22
+ * • Ground-truth L1-L5 confidence rating
23
+ * • Authored Reachability Engine (Upstream in Violet, Downstream in Green)
24
+ * • Reachability Receipt (Nodes · Links · Maximum Hops)
25
+ * • Verified Source Beacons (SRC n) with exact line numbers & code snippets
26
+ * - Export Hub (E key):
27
+ * • Lossless SVG Export
28
+ * • High-Resolution PNG & WebP Export
29
+ * • Copy PNG to Clipboard
30
+ * • 1200×630 Reach & Blast Share Card PNG Export (Archify-grade)
31
+ * - Live Motion Governor (M key) & Fullscreen Presentation Mode (F key)
32
+ * - Node Finder with instant autocomplete and camera fly-to centering (/ key)
33
+ * - Pure zero-dependency standalone execution (offline capable, no CDN required).
34
+ * ═════════════════════════════════════════════════════════════════════════════
35
+ */
36
+
37
+ 'use strict';
38
+
39
+ const fs = require('fs');
40
+ const path = require('path');
41
+ const { GREEN, CYAN, RED, DIM, RESET, BOX, banner, timer, formatMs } = require('./_colors');
42
+
43
+ class ArchitectureVisualizer {
44
+ constructor(model, verification = null) {
45
+ this.model = model;
46
+ this.verification = verification;
47
+ }
48
+
49
+ generateHtml() {
50
+ const rawDataJson = JSON.stringify({
51
+ model: this.model,
52
+ verification: this.verification,
53
+ }).replace(/</g, '\\u003c');
54
+
55
+ return `<!DOCTYPE html>
56
+ <html lang="en" data-theme="dark" data-preset="signal-flow">
57
+ <head>
58
+ <meta charset="UTF-8">
59
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
60
+ <title>Tribunal Architecture Intelligence — Evidence Console</title>
61
+ <link rel="preconnect" href="https://fonts.googleapis.com">
62
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
63
+ <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700;800&display=swap" rel="stylesheet">
64
+ <script>
65
+ (function () {
66
+ try {
67
+ var theme = localStorage.getItem('tribunal-arch-theme') || (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark');
68
+ var preset = localStorage.getItem('tribunal-arch-preset') || 'signal-flow';
69
+ document.documentElement.setAttribute('data-theme', theme);
70
+ document.documentElement.setAttribute('data-preset', preset);
71
+ } catch (_) {}
72
+ })();
73
+ </script>
74
+ <style>
75
+ /* ══════════════════════════════════════════════════════════════════════
76
+ 1. CORE DESIGN TOKENS & ARCHIFY "EVIDENCE CONSOLE" PALETTE
77
+ ══════════════════════════════════════════════════════════════════════ */
78
+ :root {
79
+ /* Shared Semantic Signals (Fixed Vocabulary) */
80
+ --frontend: #22d3ee; /* Verified Cyan: focus, routes, navigation */
81
+ --backend: #34d399; /* Proof Green: services, verification, downstream */
82
+ --database: #a78bfa; /* Repository Violet: datastores, upstream */
83
+ --cloud: #fbbf24; /* Cloud Amber: DMZ, gateways, external caches */
84
+ --security: #fb7185; /* Boundary Rose: public untrusted, security, blast ring 1 */
85
+ --messagebus: #fb923c; /* Transit Orange: queues, brokers, events */
86
+ --external: #94a3b8; /* External Slate: 3rd party SaaS */
87
+
88
+ /* Typography */
89
+ --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
90
+ --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
91
+
92
+ /* Motion */
93
+ --ease-spring: cubic-bezier(0.16, 1, 0.3, 1);
94
+ --transition-fast: 150ms var(--ease-spring);
95
+ --transition-normal: 220ms var(--ease-spring);
96
+ }
97
+
98
+ /* ── Preset 1: Obsidian Console (Classic Dark) ─────────────────────── */
99
+ html[data-theme="dark"][data-preset="classic"] {
100
+ --canvas: #020617;
101
+ --mask: #0f172a;
102
+ --panel: rgba(15, 23, 42, 0.90);
103
+ --card: #131d34;
104
+ --border: #1e293b;
105
+ --border-bright: #334155;
106
+ --ink: #ffffff;
107
+ --muted: #94a3b8;
108
+ --dim: #475569;
109
+ --grid-line: rgba(255, 255, 255, 0.03);
110
+ --radius-control: 6px;
111
+ --radius-panel: 12px;
112
+ --node-radius: 8px;
113
+ --canvas-shadow: none;
114
+ }
115
+
116
+ /* ── Preset 2: Signal Flow (Dynamic Atmosphere) ────────────────────── */
117
+ html[data-theme="dark"][data-preset="signal-flow"] {
118
+ --canvas: #030712;
119
+ --mask: #0b1120;
120
+ --panel: rgba(11, 17, 32, 0.88);
121
+ --card: #111a2e;
122
+ --border: #1f293d;
123
+ --border-bright: #38bdf8;
124
+ --ink: #f8fafc;
125
+ --muted: #94a3b8;
126
+ --dim: #4b5563;
127
+ --grid-line: rgba(56, 189, 248, 0.04);
128
+ --radius-control: 8px;
129
+ --radius-panel: 14px;
130
+ --node-radius: 10px;
131
+ --canvas-shadow: 0 28px 80px rgba(0, 0, 0, 0.55);
132
+ }
133
+
134
+ /* ── Preset 3: Cyber Blueprint (Technical Drafting Wireframe) ──────── */
135
+ html[data-theme="dark"][data-preset="blueprint"] {
136
+ --canvas: #040d1a;
137
+ --mask: #071529;
138
+ --panel: rgba(7, 21, 41, 0.94);
139
+ --card: #0a1e38;
140
+ --border: #15345b;
141
+ --border-bright: #22d3ee;
142
+ --ink: #e0f2fe;
143
+ --muted: #7dd3fc;
144
+ --dim: #38bdf8;
145
+ --grid-line: rgba(34, 211, 238, 0.08);
146
+ --radius-control: 3px;
147
+ --radius-panel: 4px;
148
+ --node-radius: 3px;
149
+ --canvas-shadow: none;
150
+ }
151
+
152
+ /* ── Preset 4: Editorial Monolith (Swiss Publication Warmth) ────────── */
153
+ html[data-preset="editorial"] {
154
+ --canvas: #f5f2eb;
155
+ --mask: #ebe7de;
156
+ --panel: rgba(235, 231, 222, 0.95);
157
+ --card: #ffffff;
158
+ --border: #d4d8e0;
159
+ --border-bright: #8a92a3;
160
+ --ink: #060709;
161
+ --muted: #4b5563;
162
+ --dim: #8a92a3;
163
+ --grid-line: rgba(0, 0, 0, 0.04);
164
+ --radius-control: 4px;
165
+ --radius-panel: 6px;
166
+ --node-radius: 4px;
167
+ --canvas-shadow: 0 16px 40px rgba(0, 0, 0, 0.08);
168
+ }
169
+
170
+ /* ── Light Mode Base (Parity with Dark) ────────────────────────────── */
171
+ html[data-theme="light"]:not([data-preset="editorial"]) {
172
+ --canvas: #f8fafc;
173
+ --mask: #ffffff;
174
+ --panel: rgba(255, 255, 255, 0.92);
175
+ --card: #f1f5f9;
176
+ --border: #e2e8f0;
177
+ --border-bright: #94a3b8;
178
+ --ink: #0f172a;
179
+ --muted: #475569;
180
+ --dim: #94a3b8;
181
+ --grid-line: rgba(0, 0, 0, 0.04);
182
+ --radius-control: 6px;
183
+ --radius-panel: 12px;
184
+ --node-radius: 8px;
185
+ --canvas-shadow: 0 20px 50px rgba(0, 0, 0, 0.06);
186
+ }
187
+
188
+ /* ══════════════════════════════════════════════════════════════════════
189
+ 2. GLOBAL RESET & BASE STYLING
190
+ ══════════════════════════════════════════════════════════════════════ */
191
+ * { box-sizing: border-box; margin: 0; padding: 0; }
192
+ body {
193
+ background: var(--canvas);
194
+ color: var(--ink);
195
+ font-family: var(--font-mono);
196
+ height: 100vh;
197
+ overflow: hidden;
198
+ display: flex;
199
+ flex-direction: column;
200
+ user-select: none;
201
+ -webkit-font-smoothing: antialiased;
202
+ }
203
+
204
+ /* Grid canvas atmosphere */
205
+ .viewport {
206
+ flex: 1;
207
+ position: relative;
208
+ overflow: hidden;
209
+ cursor: grab;
210
+ background-image:
211
+ radial-gradient(var(--grid-line) 1.2px, transparent 1.2px),
212
+ radial-gradient(var(--grid-line) 1.2px, var(--canvas) 1.2px);
213
+ background-size: 28px 28px;
214
+ background-position: 0 0, 14px 14px;
215
+ }
216
+ .viewport:active { cursor: grabbing; }
217
+
218
+ /* ══════════════════════════════════════════════════════════════════════
219
+ 3. TOP NAVIGATION / TOOLBAR CHROME
220
+ ══════════════════════════════════════════════════════════════════════ */
221
+ header.toolbar {
222
+ height: 52px;
223
+ background: var(--panel);
224
+ backdrop-filter: blur(14px);
225
+ border-bottom: 1px solid var(--border);
226
+ display: flex;
227
+ align-items: center;
228
+ justify-content: space-between;
229
+ padding: 0 16px;
230
+ z-index: 50;
231
+ flex-shrink: 0;
232
+ gap: 12px;
233
+ }
234
+
235
+ .brand-group {
236
+ display: flex;
237
+ align-items: center;
238
+ gap: 10px;
239
+ }
240
+ .brand-icon {
241
+ font-size: 16px;
242
+ filter: drop-shadow(0 0 6px rgba(34, 211, 238, 0.4));
243
+ }
244
+ .brand-name {
245
+ font-size: 13px;
246
+ font-weight: 700;
247
+ letter-spacing: -0.01em;
248
+ color: var(--ink);
249
+ display: flex;
250
+ align-items: center;
251
+ gap: 8px;
252
+ }
253
+ .brand-badge {
254
+ font-size: 9px;
255
+ font-weight: 800;
256
+ text-transform: uppercase;
257
+ letter-spacing: 0.08em;
258
+ background: var(--border);
259
+ color: var(--frontend);
260
+ border: 1px solid var(--border-bright);
261
+ padding: 2px 6px;
262
+ border-radius: var(--radius-control);
263
+ }
264
+
265
+ /* Projection Segmented Switcher */
266
+ .projection-switcher {
267
+ display: flex;
268
+ gap: 2px;
269
+ background: var(--mask);
270
+ padding: 3px;
271
+ border-radius: var(--radius-control);
272
+ border: 1px solid var(--border);
273
+ }
274
+ .proj-btn {
275
+ background: transparent;
276
+ border: none;
277
+ color: var(--muted);
278
+ padding: 5px 12px;
279
+ border-radius: calc(var(--radius-control) - 2px);
280
+ font-family: var(--font-mono);
281
+ font-size: 11px;
282
+ font-weight: 600;
283
+ cursor: pointer;
284
+ display: flex;
285
+ align-items: center;
286
+ gap: 6px;
287
+ transition: all var(--transition-fast);
288
+ }
289
+ .proj-btn:hover { color: var(--ink); background: rgba(255, 255, 255, 0.04); }
290
+ .proj-btn.active {
291
+ background: var(--card);
292
+ color: var(--ink);
293
+ border: 1px solid var(--border-bright);
294
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
295
+ }
296
+
297
+ /* Actions Right Cluster */
298
+ .toolbar-actions {
299
+ display: flex;
300
+ align-items: center;
301
+ gap: 8px;
302
+ }
303
+
304
+ /* Search Box */
305
+ .search-wrap {
306
+ position: relative;
307
+ }
308
+ .search-wrap input {
309
+ background: var(--mask);
310
+ border: 1px solid var(--border);
311
+ border-radius: var(--radius-control);
312
+ color: var(--ink);
313
+ font-family: var(--font-mono);
314
+ font-size: 11px;
315
+ padding: 6px 10px 6px 28px;
316
+ outline: none;
317
+ width: 190px;
318
+ transition: all var(--transition-fast);
319
+ }
320
+ .search-wrap input:focus {
321
+ width: 240px;
322
+ border-color: var(--frontend);
323
+ box-shadow: 0 0 0 2px rgba(34, 211, 238, 0.15);
324
+ }
325
+ .search-icon {
326
+ position: absolute;
327
+ left: 9px;
328
+ top: 7px;
329
+ color: var(--dim);
330
+ font-size: 11px;
331
+ pointer-events: none;
332
+ }
333
+ .search-kbd {
334
+ position: absolute;
335
+ right: 7px;
336
+ top: 6px;
337
+ background: var(--card);
338
+ border: 1px solid var(--border);
339
+ color: var(--dim);
340
+ font-size: 9px;
341
+ padding: 1px 4px;
342
+ border-radius: 3px;
343
+ pointer-events: none;
344
+ }
345
+
346
+ /* Autocomplete dropdown */
347
+ .search-dropdown {
348
+ position: absolute;
349
+ top: 36px;
350
+ left: 0;
351
+ right: 0;
352
+ background: var(--panel);
353
+ border: 1px solid var(--border-bright);
354
+ border-radius: var(--radius-control);
355
+ backdrop-filter: blur(16px);
356
+ box-shadow: 0 12px 30px rgba(0, 0, 0, 0.4);
357
+ max-height: 280px;
358
+ overflow-y: auto;
359
+ z-index: 100;
360
+ display: none;
361
+ }
362
+ .search-dropdown.open { display: block; }
363
+ .search-item {
364
+ padding: 8px 12px;
365
+ cursor: pointer;
366
+ display: flex;
367
+ justify-content: space-between;
368
+ align-items: center;
369
+ border-bottom: 1px solid var(--border);
370
+ font-size: 11px;
371
+ }
372
+ .search-item:hover, .search-item.highlighted {
373
+ background: rgba(34, 211, 238, 0.1);
374
+ color: var(--frontend);
375
+ }
376
+
377
+ /* Action Buttons (Presets, Motion, Theme, Present, Export) */
378
+ .btn-action {
379
+ background: var(--mask);
380
+ border: 1px solid var(--border);
381
+ color: var(--ink);
382
+ font-family: var(--font-mono);
383
+ font-size: 11px;
384
+ font-weight: 600;
385
+ padding: 6px 10px;
386
+ border-radius: var(--radius-control);
387
+ display: flex;
388
+ align-items: center;
389
+ gap: 6px;
390
+ cursor: pointer;
391
+ transition: all var(--transition-fast);
392
+ position: relative;
393
+ }
394
+ .btn-action:hover {
395
+ background: var(--card);
396
+ border-color: var(--border-bright);
397
+ }
398
+ .btn-action:active { transform: scale(0.97); }
399
+
400
+ /* Dropdown Menus */
401
+ .dropdown-wrap {
402
+ position: relative;
403
+ }
404
+ .dropdown-menu {
405
+ position: absolute;
406
+ top: calc(100% + 6px);
407
+ right: 0;
408
+ background: var(--panel);
409
+ border: 1px solid var(--border-bright);
410
+ border-radius: var(--radius-control);
411
+ backdrop-filter: blur(16px);
412
+ box-shadow: 0 14px 36px rgba(0, 0, 0, 0.4);
413
+ width: 220px;
414
+ padding: 6px;
415
+ z-index: 90;
416
+ display: none;
417
+ }
418
+ .dropdown-menu.open { display: block; }
419
+ .dropdown-header {
420
+ font-size: 9px;
421
+ font-weight: 800;
422
+ text-transform: uppercase;
423
+ letter-spacing: 0.08em;
424
+ color: var(--dim);
425
+ padding: 6px 8px 4px 8px;
426
+ }
427
+ .dropdown-item {
428
+ padding: 7px 10px;
429
+ border-radius: calc(var(--radius-control) - 2px);
430
+ cursor: pointer;
431
+ display: flex;
432
+ align-items: center;
433
+ justify-content: space-between;
434
+ color: var(--ink);
435
+ font-size: 11px;
436
+ transition: background var(--transition-fast);
437
+ }
438
+ .dropdown-item:hover {
439
+ background: rgba(34, 211, 238, 0.12);
440
+ color: var(--frontend);
441
+ }
442
+ .dropdown-item.active {
443
+ color: var(--frontend);
444
+ font-weight: 700;
445
+ }
446
+ .dropdown-hint {
447
+ font-size: 9px;
448
+ color: var(--dim);
449
+ }
450
+
451
+ /* ══════════════════════════════════════════════════════════════════════
452
+ 4. SVG GRAPH RENDERING & CONNECTION PULSES
453
+ ══════════════════════════════════════════════════════════════════════ */
454
+ svg#arch-canvas {
455
+ width: 100%;
456
+ height: 100%;
457
+ display: block;
458
+ }
459
+
460
+ /* Node Groups */
461
+ .node-group {
462
+ cursor: pointer;
463
+ transition: opacity var(--transition-fast), transform var(--transition-fast);
464
+ }
465
+ .node-card {
466
+ stroke-width: 1px;
467
+ transition: stroke var(--transition-fast), filter var(--transition-fast), stroke-width var(--transition-fast);
468
+ }
469
+ .node-group:hover .node-card {
470
+ stroke-width: 2px;
471
+ filter: drop-shadow(0 0 10px rgba(34, 211, 238, 0.35));
472
+ }
473
+
474
+ .node-title {
475
+ font-family: var(--font-mono);
476
+ font-weight: 700;
477
+ font-size: 11.5px;
478
+ fill: var(--ink);
479
+ pointer-events: none;
480
+ }
481
+ .node-kind {
482
+ font-family: var(--font-mono);
483
+ font-size: 9px;
484
+ font-weight: 600;
485
+ fill: var(--dim);
486
+ letter-spacing: 0.05em;
487
+ text-transform: uppercase;
488
+ pointer-events: none;
489
+ }
490
+ .node-conf-tag {
491
+ font-family: var(--font-mono);
492
+ font-size: 8px;
493
+ font-weight: 800;
494
+ pointer-events: none;
495
+ }
496
+
497
+ /* Edges & Signal Pulses */
498
+ .edge-bg {
499
+ fill: none;
500
+ stroke-width: 1.5px;
501
+ transition: stroke var(--transition-fast), stroke-width var(--transition-fast), opacity var(--transition-fast);
502
+ }
503
+ .edge-pulse {
504
+ fill: none;
505
+ stroke-width: 2px;
506
+ stroke-dasharray: 6, 14;
507
+ animation: signalFlowAnim 1.6s linear infinite;
508
+ pointer-events: none;
509
+ display: none;
510
+ }
511
+ html[data-preset="signal-flow"] .edge-pulse {
512
+ display: block;
513
+ }
514
+ @keyframes signalFlowAnim {
515
+ from { stroke-dashoffset: 40; }
516
+ to { stroke-dashoffset: 0; }
517
+ }
518
+
519
+ /* Focus & Dimming states */
520
+ .dimmed { opacity: 0.12 !important; }
521
+ .highlighted { opacity: 1 !important; }
522
+ .highlighted-node .node-card {
523
+ stroke-width: 2.5px !important;
524
+ filter: drop-shadow(0 0 14px rgba(34, 211, 238, 0.5)) !important;
525
+ }
526
+
527
+ /* Reachability & Blast Highlights */
528
+ .reach-upstream .node-card { stroke: var(--database) !important; stroke-width: 2.5px !important; }
529
+ .reach-upstream-edge { stroke: var(--database) !important; stroke-width: 2.5px !important; }
530
+ .reach-downstream .node-card { stroke: var(--backend) !important; stroke-width: 2.5px !important; }
531
+ .reach-downstream-edge { stroke: var(--backend) !important; stroke-width: 2.5px !important; }
532
+
533
+ .blast-ring-1 .node-card { stroke: var(--security) !important; stroke-width: 3px !important; }
534
+ .blast-ring-1-edge { stroke: var(--security) !important; stroke-width: 3px !important; }
535
+ .blast-ring-2 .node-card { stroke: var(--cloud) !important; stroke-width: 2.5px !important; }
536
+ .blast-ring-2-edge { stroke: var(--cloud) !important; stroke-width: 2.5px !important; }
537
+ .blast-ring-3 .node-card { stroke: var(--frontend) !important; stroke-width: 2px !important; }
538
+ .blast-ring-3-edge { stroke: var(--frontend) !important; stroke-width: 2px !important; }
539
+
540
+ /* ══════════════════════════════════════════════════════════════════════
541
+ 5. FLOATING HUD CONTROLS & STATUS BAR
542
+ ══════════════════════════════════════════════════════════════════════ */
543
+ .canvas-hud-bottom {
544
+ position: absolute;
545
+ bottom: 16px;
546
+ left: 16px;
547
+ display: flex;
548
+ gap: 6px;
549
+ background: var(--panel);
550
+ backdrop-filter: blur(12px);
551
+ padding: 4px;
552
+ border-radius: var(--radius-control);
553
+ border: 1px solid var(--border);
554
+ z-index: 40;
555
+ }
556
+ .hud-btn {
557
+ background: transparent;
558
+ border: 1px solid transparent;
559
+ color: var(--ink);
560
+ font-family: var(--font-mono);
561
+ font-size: 13px;
562
+ font-weight: 700;
563
+ width: 32px;
564
+ height: 32px;
565
+ border-radius: calc(var(--radius-control) - 2px);
566
+ display: flex;
567
+ align-items: center;
568
+ justify-content: center;
569
+ cursor: pointer;
570
+ transition: background var(--transition-fast);
571
+ }
572
+ .hud-btn:hover { background: var(--card); border-color: var(--border-bright); }
573
+
574
+ /* Telemetry / Legend Overlay */
575
+ .telemetry-card {
576
+ position: absolute;
577
+ bottom: 16px;
578
+ right: 16px;
579
+ background: var(--panel);
580
+ backdrop-filter: blur(12px);
581
+ padding: 10px 14px;
582
+ border-radius: var(--radius-control);
583
+ border: 1px solid var(--border);
584
+ font-size: 10.5px;
585
+ z-index: 40;
586
+ max-width: 260px;
587
+ }
588
+ .telemetry-title {
589
+ font-weight: 700;
590
+ text-transform: uppercase;
591
+ letter-spacing: 0.08em;
592
+ color: var(--dim);
593
+ margin-bottom: 6px;
594
+ display: flex;
595
+ justify-content: space-between;
596
+ align-items: center;
597
+ }
598
+ .telemetry-item {
599
+ display: flex;
600
+ align-items: center;
601
+ gap: 8px;
602
+ margin-bottom: 4px;
603
+ }
604
+ .telemetry-dot {
605
+ width: 8px;
606
+ height: 8px;
607
+ border-radius: 2px;
608
+ flex-shrink: 0;
609
+ }
610
+
611
+ /* ══════════════════════════════════════════════════════════════════════
612
+ 6. SEMANTIC PASSPORT (PROOF CONSOLE DRAWER)
613
+ ══════════════════════════════════════════════════════════════════════ */
614
+ #semantic-passport {
615
+ position: absolute;
616
+ top: 52px;
617
+ right: 0;
618
+ bottom: 0;
619
+ width: 440px;
620
+ background: var(--panel);
621
+ backdrop-filter: blur(20px);
622
+ border-left: 1px solid var(--border);
623
+ padding: 20px;
624
+ overflow-y: auto;
625
+ transform: translateX(100%);
626
+ transition: transform var(--transition-normal);
627
+ z-index: 60;
628
+ display: flex;
629
+ flex-direction: column;
630
+ gap: 16px;
631
+ }
632
+ #semantic-passport.open { transform: translateX(0); }
633
+
634
+ .passport-header {
635
+ display: flex;
636
+ justify-content: space-between;
637
+ align-items: flex-start;
638
+ border-bottom: 1px solid var(--border);
639
+ padding-bottom: 12px;
640
+ }
641
+ .passport-title {
642
+ font-size: 15px;
643
+ font-weight: 800;
644
+ letter-spacing: -0.01em;
645
+ color: var(--ink);
646
+ }
647
+ .passport-id {
648
+ font-size: 10px;
649
+ color: var(--dim);
650
+ margin-top: 2px;
651
+ }
652
+ .passport-close {
653
+ background: transparent;
654
+ border: none;
655
+ color: var(--dim);
656
+ font-size: 16px;
657
+ cursor: pointer;
658
+ padding: 4px;
659
+ }
660
+ .passport-close:hover { color: var(--ink); }
661
+
662
+ /* Reachability Action Buttons */
663
+ .reach-actions {
664
+ display: flex;
665
+ gap: 6px;
666
+ }
667
+ .btn-reach {
668
+ flex: 1;
669
+ padding: 7px 10px;
670
+ font-family: var(--font-mono);
671
+ font-size: 10px;
672
+ font-weight: 700;
673
+ text-transform: uppercase;
674
+ letter-spacing: 0.05em;
675
+ border-radius: var(--radius-control);
676
+ border: 1px solid var(--border);
677
+ background: var(--mask);
678
+ color: var(--ink);
679
+ cursor: pointer;
680
+ display: flex;
681
+ align-items: center;
682
+ justify-content: center;
683
+ gap: 6px;
684
+ transition: all var(--transition-fast);
685
+ }
686
+ .btn-reach.upstream:hover, .btn-reach.upstream.active {
687
+ background: rgba(167, 139, 250, 0.15);
688
+ border-color: var(--database);
689
+ color: var(--database);
690
+ }
691
+ .btn-reach.downstream:hover, .btn-reach.downstream.active {
692
+ background: rgba(52, 211, 153, 0.15);
693
+ border-color: var(--backend);
694
+ color: var(--backend);
695
+ }
696
+ .btn-reach.reset:hover {
697
+ background: var(--card);
698
+ }
699
+
700
+ /* Receipt Badge */
701
+ .receipt-badge {
702
+ background: var(--mask);
703
+ border: 1px solid var(--border);
704
+ border-radius: var(--radius-control);
705
+ padding: 6px 10px;
706
+ font-size: 10px;
707
+ color: var(--muted);
708
+ display: flex;
709
+ align-items: center;
710
+ justify-content: space-between;
711
+ }
712
+ .receipt-highlight {
713
+ font-weight: 700;
714
+ color: var(--frontend);
715
+ }
716
+
717
+ /* Meta Badges Grid */
718
+ .meta-grid {
719
+ display: grid;
720
+ grid-template-columns: repeat(2, 1fr);
721
+ gap: 8px;
722
+ }
723
+ .meta-box {
724
+ background: var(--mask);
725
+ border: 1px solid var(--border);
726
+ border-radius: var(--radius-control);
727
+ padding: 8px 10px;
728
+ }
729
+ .meta-label {
730
+ font-size: 9px;
731
+ text-transform: uppercase;
732
+ letter-spacing: 0.08em;
733
+ color: var(--dim);
734
+ }
735
+ .meta-val {
736
+ font-size: 11px;
737
+ font-weight: 700;
738
+ margin-top: 2px;
739
+ color: var(--ink);
740
+ }
741
+
742
+ /* Verified Source Code Evidence */
743
+ .section-head {
744
+ font-size: 10px;
745
+ font-weight: 800;
746
+ text-transform: uppercase;
747
+ letter-spacing: 0.08em;
748
+ color: var(--dim);
749
+ display: flex;
750
+ align-items: center;
751
+ justify-content: space-between;
752
+ }
753
+ .evidence-card {
754
+ background: var(--mask);
755
+ border: 1px solid var(--border);
756
+ border-radius: var(--radius-control);
757
+ padding: 10px;
758
+ font-size: 10.5px;
759
+ }
760
+ .evidence-path {
761
+ color: var(--frontend);
762
+ font-weight: 700;
763
+ display: flex;
764
+ align-items: center;
765
+ gap: 6px;
766
+ margin-bottom: 4px;
767
+ }
768
+ .evidence-snippet {
769
+ background: rgba(0, 0, 0, 0.35);
770
+ border: 1px solid var(--border);
771
+ border-radius: 4px;
772
+ padding: 6px 8px;
773
+ color: #cbd5e1;
774
+ white-space: pre-wrap;
775
+ word-break: break-all;
776
+ font-size: 10px;
777
+ line-height: 1.45;
778
+ margin-top: 6px;
779
+ }
780
+
781
+ /* Blast Risk Gauge */
782
+ .risk-gauge-wrap {
783
+ display: flex;
784
+ align-items: center;
785
+ gap: 8px;
786
+ margin-top: 4px;
787
+ }
788
+ .risk-pill {
789
+ font-size: 9px;
790
+ font-weight: 800;
791
+ padding: 2px 7px;
792
+ border-radius: 3px;
793
+ text-transform: uppercase;
794
+ }
795
+ .risk-LOW { background: #064e3b; color: #34d399; }
796
+ .risk-MEDIUM { background: #78350f; color: #fbbf24; }
797
+ .risk-HIGH { background: #7c2d12; color: #fb923c; }
798
+ .risk-CRITICAL { background: #881337; color: #f43f5e; }
799
+
800
+ /* Presentation mode */
801
+ body.presentation-mode header.toolbar { display: none; }
802
+ body.presentation-mode #semantic-passport { top: 0; }
803
+ </style>
804
+ </head>
805
+ <body>
806
+
807
+ <!-- ══════════════════════════════════════════════════════════════════════
808
+ TOOLBAR / CONTROL CHROME
809
+ ══════════════════════════════════════════════════════════════════════ -->
810
+ <header class="toolbar" role="toolbar" aria-label="Architecture Intelligence Controls">
811
+ <div class="brand-group">
812
+ <span class="brand-icon">⚖️</span>
813
+ <div class="brand-name">
814
+ <span>Tribunal Architecture</span>
815
+ <span class="brand-badge">Evidence Console</span>
816
+ </div>
817
+ </div>
818
+
819
+ <!-- Multi-Projection Switcher -->
820
+ <div class="projection-switcher" role="radiogroup" aria-label="Projections">
821
+ <button class="proj-btn active" data-projection="topology" title="System Topology: Services, Routes, Datastores">
822
+ <span>Topology</span>
823
+ </button>
824
+ <button class="proj-btn" data-projection="security" title="Security Trust Zones: Public, DMZ, Isolated">
825
+ <span>Security</span>
826
+ </button>
827
+ <button class="proj-btn" data-projection="failure" title="Failure Modes: Timeouts, Resilient RPCs">
828
+ <span>Failure</span>
829
+ </button>
830
+ <button class="proj-btn" data-projection="blast" title="Blast Radius Simulator: Concentric Impact">
831
+ <span>Blast Simulator</span>
832
+ </button>
833
+ </div>
834
+
835
+ <!-- Actions Cluster -->
836
+ <div class="toolbar-actions">
837
+ <!-- Search Autocomplete -->
838
+ <div class="search-wrap">
839
+ <span class="search-icon">🔍</span>
840
+ <input type="text" id="node-search" placeholder="Search architecture..." autocomplete="off">
841
+ <span class="search-kbd">/</span>
842
+ <div class="search-dropdown" id="search-dropdown"></div>
843
+ </div>
844
+
845
+ <!-- Preset Style Dropdown -->
846
+ <div class="dropdown-wrap">
847
+ <button class="btn-action" id="btn-preset-toggle" title="Cycle or select visual preset (Shortcut: S)">
848
+ <span>🎨</span>
849
+ <span id="preset-label">Signal Flow</span>
850
+ <span style="font-size: 8px;">▼</span>
851
+ </button>
852
+ <div class="dropdown-menu" id="preset-menu">
853
+ <div class="dropdown-header">Visual Style Preset (S)</div>
854
+ <div class="dropdown-item" data-val="classic">
855
+ <span>Obsidian Console</span>
856
+ <span class="dropdown-hint">Classic</span>
857
+ </div>
858
+ <div class="dropdown-item active" data-val="signal-flow">
859
+ <span>Signal Flow</span>
860
+ <span class="dropdown-hint">Active Pulses</span>
861
+ </div>
862
+ <div class="dropdown-item" data-val="blueprint">
863
+ <span>Cyber Blueprint</span>
864
+ <span class="dropdown-hint">Drafting</span>
865
+ </div>
866
+ <div class="dropdown-item" data-val="editorial">
867
+ <span>Editorial Monolith</span>
868
+ <span class="dropdown-hint">Swiss</span>
869
+ </div>
870
+ </div>
871
+ </div>
872
+
873
+ <!-- Motion Governor -->
874
+ <button class="btn-action" id="btn-motion" title="Toggle active signal animations (Shortcut: M)">
875
+ <span id="motion-dot" style="display:inline-block; width:6px; height:6px; border-radius:50%; background:#22d3ee;"></span>
876
+ <span id="motion-label">Motion</span>
877
+ </button>
878
+
879
+ <!-- Theme Switcher -->
880
+ <button class="btn-action" id="btn-theme" title="Toggle Dark / Light theme (Shortcut: T)">
881
+ <span id="theme-icon">🌙</span>
882
+ </button>
883
+
884
+ <!-- Fullscreen Present -->
885
+ <button class="btn-action" id="btn-present" title="Presentation stage mode (Shortcut: F)">
886
+ <span>⛶</span>
887
+ </button>
888
+
889
+ <!-- Export Hub Dropdown -->
890
+ <div class="dropdown-wrap">
891
+ <button class="btn-action" id="btn-export-toggle" style="background: rgba(34, 211, 238, 0.1); border-color: var(--frontend); color: var(--frontend);" title="Export diagrams & share cards (Shortcut: E)">
892
+ <span>⤓</span>
893
+ <span>Export</span>
894
+ <span style="font-size: 8px;">▼</span>
895
+ </button>
896
+ <div class="dropdown-menu" id="export-menu">
897
+ <div class="dropdown-header">Share & PR Artifacts</div>
898
+ <div class="dropdown-item" id="act-share-card">
899
+ <span>Reach Share Card</span>
900
+ <span class="dropdown-hint">1200×630 PNG</span>
901
+ </div>
902
+ <div class="dropdown-item" id="act-copy-png">
903
+ <span>Copy to Clipboard</span>
904
+ <span class="dropdown-hint">PNG</span>
905
+ </div>
906
+ <div class="dropdown-header">Vector & Image</div>
907
+ <div class="dropdown-item" id="act-download-svg">
908
+ <span>Lossless SVG</span>
909
+ <span class="dropdown-hint">Vector</span>
910
+ </div>
911
+ <div class="dropdown-item" id="act-download-png">
912
+ <span>High-Res PNG</span>
913
+ <span class="dropdown-hint">Raster</span>
914
+ </div>
915
+ <div class="dropdown-item" id="act-download-webp">
916
+ <span>Modern WebP</span>
917
+ <span class="dropdown-hint">Compact</span>
918
+ </div>
919
+ </div>
920
+ </div>
921
+ </div>
922
+ </header>
923
+
924
+ <!-- ══════════════════════════════════════════════════════════════════════
925
+ MAIN INTERACTIVE CANVAS VIEWPORT
926
+ ══════════════════════════════════════════════════════════════════════ -->
927
+ <main class="viewport" id="viewport">
928
+ <svg id="arch-canvas">
929
+ <defs>
930
+ <!-- Arrowhead markers with semantic colors -->
931
+ <marker id="arrow-default" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
932
+ <path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#475569" />
933
+ </marker>
934
+ <marker id="arrow-cyan" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
935
+ <path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#22d3ee" />
936
+ </marker>
937
+ <marker id="arrow-green" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
938
+ <path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#34d399" />
939
+ </marker>
940
+ <marker id="arrow-violet" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
941
+ <path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#a78bfa" />
942
+ </marker>
943
+ <marker id="arrow-warn" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
944
+ <path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#fbbf24" />
945
+ </marker>
946
+ <marker id="arrow-rose" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
947
+ <path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#fb7185" />
948
+ </marker>
949
+ </defs>
950
+ <g id="world-layer">
951
+ <g id="zones-layer"></g>
952
+ <g id="edges-layer"></g>
953
+ <g id="nodes-layer"></g>
954
+ </g>
955
+ </svg>
956
+
957
+ <!-- Canvas Navigation HUD -->
958
+ <div class="canvas-hud-bottom">
959
+ <button class="hud-btn" id="btn-zoom-in" title="Zoom In (+)">+</button>
960
+ <button class="hud-btn" id="btn-zoom-out" title="Zoom Out (−)">−</button>
961
+ <button class="hud-btn" id="btn-zoom-reset" title="Fit to Screen (0)">⛶</button>
962
+ </div>
963
+
964
+ <!-- Active Legend & Telemetry HUD -->
965
+ <div class="telemetry-card" id="telemetry-card">
966
+ <div class="telemetry-title">
967
+ <span id="telemetry-mode-label">System Topology</span>
968
+ <span id="telemetry-node-count" style="color:var(--frontend);">0 NODES</span>
969
+ </div>
970
+ <div id="telemetry-items"></div>
971
+ </div>
972
+ </main>
973
+
974
+ <!-- ══════════════════════════════════════════════════════════════════════
975
+ SEMANTIC PASSPORT (PROVENANCE & EVIDENCE CONSOLE)
976
+ ══════════════════════════════════════════════════════════════════════ -->
977
+ <aside id="semantic-passport">
978
+ <div class="passport-header">
979
+ <div>
980
+ <div class="passport-title" id="pass-title">Component Name</div>
981
+ <div class="passport-id" id="pass-id">component.id</div>
982
+ </div>
983
+ <button class="passport-close" id="pass-close" title="Close Passport (Esc)">✕</button>
984
+ </div>
985
+
986
+ <!-- Reachability Engine Controls -->
987
+ <div>
988
+ <div class="section-head" style="margin-bottom: 6px;">
989
+ <span>Authored Reachability</span>
990
+ <span style="font-size:8px; color:var(--dim);">SUBGRAPH ENGINE</span>
991
+ </div>
992
+ <div class="reach-actions">
993
+ <button class="btn-reach upstream" id="btn-reach-upstream" title="Trace incoming upstream dependencies">
994
+ <span>▲</span>
995
+ <span>Upstream</span>
996
+ </button>
997
+ <button class="btn-reach downstream" id="btn-reach-downstream" title="Trace outgoing downstream dependencies">
998
+ <span>▼</span>
999
+ <span>Downstream</span>
1000
+ </button>
1001
+ <button class="btn-reach reset" id="btn-reach-reset" title="Clear subgraph highlight">
1002
+ <span>Reset</span>
1003
+ </button>
1004
+ </div>
1005
+ </div>
1006
+
1007
+ <!-- Receipt Badge -->
1008
+ <div class="receipt-badge" id="pass-receipt">
1009
+ <span>Reach Receipt:</span>
1010
+ <span class="receipt-highlight" id="pass-receipt-val">Full Topology Active</span>
1011
+ </div>
1012
+
1013
+ <!-- Metadata Grid -->
1014
+ <div class="meta-grid">
1015
+ <div class="meta-box">
1016
+ <div class="meta-label">Kind</div>
1017
+ <div class="meta-val" id="pass-kind">MODULE</div>
1018
+ </div>
1019
+ <div class="meta-box">
1020
+ <div class="meta-label">Trust Zone</div>
1021
+ <div class="meta-val" id="pass-zone">INTERNAL</div>
1022
+ </div>
1023
+ <div class="meta-box">
1024
+ <div class="meta-label">Confidence</div>
1025
+ <div class="meta-val" id="pass-confidence" style="color:var(--backend);">L1 FACT</div>
1026
+ </div>
1027
+ <div class="meta-box">
1028
+ <div class="meta-label">Risk Tier</div>
1029
+ <div class="meta-val" id="pass-risk">LOW (0.1)</div>
1030
+ </div>
1031
+ </div>
1032
+
1033
+ <!-- Blast Radius & Transitive Impact -->
1034
+ <div>
1035
+ <div class="section-head" style="margin-bottom: 6px;">
1036
+ <span>Blast Simulation Metric</span>
1037
+ <span id="pass-blast-tier" class="risk-pill risk-LOW">LOW</span>
1038
+ </div>
1039
+ <div class="meta-box">
1040
+ <div style="font-size:10px; color:var(--muted); line-height:1.4;" id="pass-blast-desc">
1041
+ Direct dependents: 0 · Transitive depth: 0
1042
+ </div>
1043
+ </div>
1044
+ </div>
1045
+
1046
+ <!-- Verified Code Evidence -->
1047
+ <div>
1048
+ <div class="section-head" style="margin-bottom: 6px;">
1049
+ <span>Verified Ground Truth Evidence</span>
1050
+ <span style="color:var(--backend); font-size:8px;">AST VERIFIED</span>
1051
+ </div>
1052
+ <div id="pass-evidence-list" style="display:flex; flex-direction:column; gap:8px;"></div>
1053
+ </div>
1054
+
1055
+ <!-- Architectural Role -->
1056
+ <div>
1057
+ <div class="section-head" style="margin-bottom: 6px;">Architectural Purpose</div>
1058
+ <p style="font-size: 11px; line-height: 1.55; color: var(--muted);" id="pass-role"></p>
1059
+ </div>
1060
+ </aside>
1061
+
1062
+ <!-- Offscreen canvas for Reach Share Card & PNG rasterization -->
1063
+ <canvas id="export-canvas" width="1200" height="630" style="display:none;"></canvas>
1064
+
1065
+ <!-- Embedded Architecture Payload -->
1066
+ <script id="tribunal-architecture-data" type="application/json">
1067
+ ${rawDataJson}
1068
+ </script>
1069
+
1070
+ <!-- ══════════════════════════════════════════════════════════════════════
1071
+ 7. CLIENT-SIDE INTERACTIVITY & RENDERING ENGINE
1072
+ ══════════════════════════════════════════════════════════════════════ -->
1073
+ <script>
1074
+ (function () {
1075
+ const rawData = JSON.parse(document.getElementById('tribunal-architecture-data').textContent);
1076
+ const model = rawData.model || {};
1077
+ const entities = model.entities || [];
1078
+ const relationships = model.relationships || [];
1079
+ const trustBoundaries = model.trustBoundaries || [];
1080
+
1081
+ let currentProjection = 'topology';
1082
+ let selectedNodeId = null;
1083
+ let reachMode = null; // 'upstream' | 'downstream' | null
1084
+ let motionEnabled = true;
1085
+
1086
+ // Transform state
1087
+ let transform = { x: 70, y: 70, k: 0.78 };
1088
+ let isPanning = false;
1089
+ let startPoint = { x: 0, y: 0 };
1090
+
1091
+ // DOM Elements
1092
+ const viewport = document.getElementById('viewport');
1093
+ const world = document.getElementById('world-layer');
1094
+ const nodesLayer = document.getElementById('nodes-layer');
1095
+ const edgesLayer = document.getElementById('edges-layer');
1096
+ const zonesLayer = document.getElementById('zones-layer');
1097
+ const passport = document.getElementById('semantic-passport');
1098
+ const searchInput = document.getElementById('node-search');
1099
+ const searchDropdown = document.getElementById('search-dropdown');
1100
+ const telemetryItems = document.getElementById('telemetry-items');
1101
+ const telemetryTitle = document.getElementById('telemetry-mode-label');
1102
+ const telemetryNodeCount = document.getElementById('telemetry-node-count');
1103
+
1104
+ // ── Spatial Auto-Layout Engine ───────────────────────────────────────
1105
+ const NODE_W = 180;
1106
+ const NODE_H = 68;
1107
+ const GAP_X = 220;
1108
+ const GAP_Y = 88;
1109
+
1110
+ const columnMap = {
1111
+ endpoint: 0,
1112
+ identity_provider: 0,
1113
+ module: 1,
1114
+ test_suite: 1,
1115
+ event_bus: 2,
1116
+ queue: 2,
1117
+ cache: 2,
1118
+ datastore: 3,
1119
+ external_api: 3,
1120
+ };
1121
+
1122
+ const columns = [[], [], [], []];
1123
+ entities.forEach(e => {
1124
+ const col = columnMap[e.kind] ?? 1;
1125
+ columns[col].push(e);
1126
+ });
1127
+
1128
+ const nodeCoords = new Map();
1129
+ columns.forEach((colEntities, colIdx) => {
1130
+ colEntities.forEach((entity, rowIdx) => {
1131
+ nodeCoords.set(entity.id, {
1132
+ x: colIdx * (NODE_W + GAP_X) + 80,
1133
+ y: rowIdx * (NODE_H + GAP_Y) + 80,
1134
+ w: NODE_W,
1135
+ h: NODE_H,
1136
+ entity
1137
+ });
1138
+ });
1139
+ });
1140
+
1141
+ function updateCanvasTransform() {
1142
+ world.setAttribute('transform', 'translate(' + transform.x + ', ' + transform.y + ') scale(' + transform.k + ')');
1143
+ }
1144
+
1145
+ // ── Edges & Live Signal Rendering ────────────────────────────────────
1146
+ function renderEdges() {
1147
+ edgesLayer.innerHTML = '';
1148
+ relationships.forEach(rel => {
1149
+ const src = nodeCoords.get(rel.sourceId);
1150
+ const tgt = nodeCoords.get(rel.targetId);
1151
+ if (!src || !tgt) return;
1152
+
1153
+ const x1 = src.x + src.w;
1154
+ const y1 = src.y + src.h / 2;
1155
+ const x2 = tgt.x;
1156
+ const y2 = tgt.y + tgt.h / 2;
1157
+
1158
+ const dx = (x2 - x1) / 2;
1159
+ const d = 'M ' + x1 + ' ' + y1 + ' C ' + (x1 + dx) + ' ' + y1 + ', ' + (x2 - dx) + ' ' + y2 + ', ' + x2 + ' ' + y2;
1160
+
1161
+ // Background base edge
1162
+ const pathBg = document.createElementNS('http://www.w3.org/2000/svg', 'path');
1163
+ pathBg.setAttribute('d', d);
1164
+ pathBg.setAttribute('class', 'edge-bg');
1165
+ pathBg.setAttribute('data-id', rel.id || (rel.sourceId + '->' + rel.targetId));
1166
+ pathBg.setAttribute('data-source', rel.sourceId);
1167
+ pathBg.setAttribute('data-target', rel.targetId);
1168
+
1169
+ let strokeColor = '#334155';
1170
+ let marker = 'url(#arrow-default)';
1171
+
1172
+ if (currentProjection === 'failure' && rel.failureMode && !rel.failureMode.hasTimeout) {
1173
+ strokeColor = '#fbbf24';
1174
+ marker = 'url(#arrow-warn)';
1175
+ }
1176
+
1177
+ pathBg.setAttribute('stroke', strokeColor);
1178
+ pathBg.setAttribute('marker-end', marker);
1179
+ edgesLayer.appendChild(pathBg);
1180
+
1181
+ // Foreground signal pulse path (for Signal Flow preset)
1182
+ const pathPulse = document.createElementNS('http://www.w3.org/2000/svg', 'path');
1183
+ pathPulse.setAttribute('d', d);
1184
+ pathPulse.setAttribute('class', 'edge-pulse');
1185
+ pathPulse.setAttribute('stroke', '#22d3ee');
1186
+ pathPulse.setAttribute('data-source', rel.sourceId);
1187
+ pathPulse.setAttribute('data-target', rel.targetId);
1188
+ edgesLayer.appendChild(pathPulse);
1189
+ });
1190
+ }
1191
+
1192
+ // ── Nodes Rendering ──────────────────────────────────────────────────
1193
+ function renderNodes() {
1194
+ nodesLayer.innerHTML = '';
1195
+ entities.forEach(entity => {
1196
+ const coord = nodeCoords.get(entity.id);
1197
+ if (!coord) return;
1198
+
1199
+ const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
1200
+ g.setAttribute('class', 'node-group');
1201
+ g.setAttribute('data-id', entity.id);
1202
+ g.setAttribute('transform', 'translate(' + coord.x + ', ' + coord.y + ')');
1203
+
1204
+ // Semantic color accent
1205
+ let accent = '#475569';
1206
+ let icon = '📦';
1207
+ if (entity.kind === 'endpoint') { accent = '#22d3ee'; icon = '⚡'; }
1208
+ else if (entity.kind === 'datastore' || entity.kind === 'cache') { accent = '#a78bfa'; icon = '💾'; }
1209
+ else if (entity.kind === 'queue' || entity.kind === 'event_bus') { accent = '#fb923c'; icon = '📨'; }
1210
+ else if (entity.kind === 'external_api') { accent = '#fb7185'; icon = '🌐'; }
1211
+ else if (entity.kind === 'module') { accent = '#34d399'; icon = '⚙️'; }
1212
+
1213
+ if (currentProjection === 'security') {
1214
+ if (entity.trustZone === 'public_untrusted') accent = '#fb7185';
1215
+ else if (entity.trustZone === 'dmz_gateway') accent = '#fbbf24';
1216
+ else if (entity.trustZone === 'internal_service') accent = '#34d399';
1217
+ else if (entity.trustZone === 'isolated_datastore') accent = '#a78bfa';
1218
+ }
1219
+
1220
+ // Card Background
1221
+ const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
1222
+ rect.setAttribute('width', coord.w);
1223
+ rect.setAttribute('height', coord.h);
1224
+ rect.setAttribute('rx', 'var(--node-radius, 8px)');
1225
+ rect.setAttribute('class', 'node-card');
1226
+ rect.setAttribute('fill', 'var(--card)');
1227
+ rect.setAttribute('stroke', accent);
1228
+
1229
+ // Top Accent Line
1230
+ const accentLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
1231
+ accentLine.setAttribute('x1', '0');
1232
+ accentLine.setAttribute('y1', '0');
1233
+ accentLine.setAttribute('x2', coord.w);
1234
+ accentLine.setAttribute('y2', '0');
1235
+ accentLine.setAttribute('stroke', accent);
1236
+ accentLine.setAttribute('stroke-width', '3');
1237
+ accentLine.setAttribute('stroke-linecap', 'round');
1238
+
1239
+ // Title
1240
+ const title = document.createElementNS('http://www.w3.org/2000/svg', 'text');
1241
+ title.setAttribute('x', 14);
1242
+ title.setAttribute('y', 28);
1243
+ title.setAttribute('class', 'node-title');
1244
+ const cleanName = entity.name.length > 17 ? entity.name.slice(0, 15) + '…' : entity.name;
1245
+ title.textContent = icon + ' ' + cleanName;
1246
+
1247
+ // Kind & Confidence Tag
1248
+ const kindText = document.createElementNS('http://www.w3.org/2000/svg', 'text');
1249
+ kindText.setAttribute('x', 14);
1250
+ kindText.setAttribute('y', 48);
1251
+ kindText.setAttribute('class', 'node-kind');
1252
+ kindText.textContent = (entity.kind || 'MODULE').replace('_', ' ');
1253
+
1254
+ const confBadge = document.createElementNS('http://www.w3.org/2000/svg', 'text');
1255
+ confBadge.setAttribute('x', coord.w - 14);
1256
+ confBadge.setAttribute('y', 48);
1257
+ confBadge.setAttribute('text-anchor', 'end');
1258
+ confBadge.setAttribute('class', 'node-conf-tag');
1259
+ confBadge.setAttribute('fill', entity.confidence === 'L1' ? '#34d399' : '#fbbf24');
1260
+ confBadge.textContent = entity.confidence || 'L1';
1261
+
1262
+ g.appendChild(rect);
1263
+ g.appendChild(accentLine);
1264
+ g.appendChild(title);
1265
+ g.appendChild(kindText);
1266
+ g.appendChild(confBadge);
1267
+
1268
+ g.addEventListener('click', (ev) => {
1269
+ ev.stopPropagation();
1270
+ onNodeClick(entity.id);
1271
+ });
1272
+
1273
+ nodesLayer.appendChild(g);
1274
+ });
1275
+ }
1276
+
1277
+ // ── Legend & Telemetry Update ────────────────────────────────────────
1278
+ function updateTelemetry() {
1279
+ telemetryNodeCount.textContent = entities.length + ' NODES';
1280
+
1281
+ const configs = {
1282
+ topology: {
1283
+ title: 'System Topology',
1284
+ items: [
1285
+ { color: '#22d3ee', label: 'HTTP API Endpoint' },
1286
+ { color: '#34d399', label: 'Internal Module' },
1287
+ { color: '#a78bfa', label: 'Datastore / Cache' },
1288
+ { color: '#fb923c', label: 'Queue / Event Channel' },
1289
+ { color: '#fb7185', label: 'External SaaS' },
1290
+ ]
1291
+ },
1292
+ security: {
1293
+ title: 'Security Trust Zones',
1294
+ items: [
1295
+ { color: '#fb7185', label: 'Public Untrusted' },
1296
+ { color: '#fbbf24', label: 'DMZ Gateway / Auth' },
1297
+ { color: '#34d399', label: 'Authenticated Service' },
1298
+ { color: '#a78bfa', label: 'Isolated Datastore' },
1299
+ ]
1300
+ },
1301
+ failure: {
1302
+ title: 'Failure Architecture',
1303
+ items: [
1304
+ { color: '#fbbf24', label: 'External (No Timeout)' },
1305
+ { color: '#34d399', label: 'Resilient RPC / Protected' },
1306
+ ]
1307
+ },
1308
+ blast: {
1309
+ title: 'Blast Radius Simulator',
1310
+ items: [
1311
+ { color: '#fb7185', label: 'Ring 1 (Direct Impact)' },
1312
+ { color: '#fbbf24', label: 'Ring 2 (Transitive Ring)' },
1313
+ { color: '#22d3ee', label: 'Ring 3 (Edge Services)' },
1314
+ ]
1315
+ }
1316
+ };
1317
+
1318
+ const active = configs[currentProjection] || configs.topology;
1319
+ telemetryTitle.textContent = active.title;
1320
+ telemetryItems.innerHTML = active.items.map(it =>
1321
+ '<div class="telemetry-item"><div class="telemetry-dot" style="background:' + it.color + '"></div><span>' + it.label + '</span></div>'
1322
+ ).join('');
1323
+ }
1324
+
1325
+ // ── Reachability & Selection Engine ──────────────────────────────────
1326
+ function computeReachability(originId, direction) {
1327
+ const visitedNodes = new Set([originId]);
1328
+ const matchedEdges = new Set();
1329
+ let currentLevel = [originId];
1330
+ let hops = 0;
1331
+
1332
+ while (currentLevel.length > 0) {
1333
+ const nextLevel = [];
1334
+ hops++;
1335
+ currentLevel.forEach(currId => {
1336
+ relationships.forEach(rel => {
1337
+ if (direction === 'upstream' && rel.targetId === currId) {
1338
+ matchedEdges.add(rel);
1339
+ if (!visitedNodes.has(rel.sourceId)) {
1340
+ visitedNodes.add(rel.sourceId);
1341
+ nextLevel.push(rel.sourceId);
1342
+ }
1343
+ } else if (direction === 'downstream' && rel.sourceId === currId) {
1344
+ matchedEdges.add(rel);
1345
+ if (!visitedNodes.has(rel.targetId)) {
1346
+ visitedNodes.add(rel.targetId);
1347
+ nextLevel.push(rel.targetId);
1348
+ }
1349
+ }
1350
+ });
1351
+ });
1352
+ currentLevel = nextLevel;
1353
+ }
1354
+
1355
+ return {
1356
+ nodes: visitedNodes,
1357
+ edges: matchedEdges,
1358
+ hops: Math.max(0, hops - 1)
1359
+ };
1360
+ }
1361
+
1362
+ function clearHighlights() {
1363
+ reachMode = null;
1364
+ document.querySelectorAll('.node-group').forEach(el => {
1365
+ el.classList.remove('dimmed', 'highlighted', 'highlighted-node', 'reach-upstream', 'reach-downstream', 'blast-ring-1', 'blast-ring-2', 'blast-ring-3');
1366
+ });
1367
+ document.querySelectorAll('.edge-bg, .edge-pulse').forEach(el => {
1368
+ el.classList.remove('dimmed', 'highlighted-edge', 'reach-upstream-edge', 'reach-downstream-edge', 'blast-ring-1-edge', 'blast-ring-2-edge', 'blast-ring-3-edge');
1369
+ });
1370
+ document.getElementById('btn-reach-upstream').classList.remove('active');
1371
+ document.getElementById('btn-reach-downstream').classList.remove('active');
1372
+ document.getElementById('pass-receipt-val').textContent = 'Full Topology Active';
1373
+ }
1374
+
1375
+ function onNodeClick(id) {
1376
+ selectedNodeId = id;
1377
+ const entity = entities.find(e => e.id === id);
1378
+ if (!entity) return;
1379
+
1380
+ clearHighlights();
1381
+
1382
+ if (currentProjection === 'blast') {
1383
+ // Live Blast Simulation
1384
+ const ring1 = new Set();
1385
+ const ring2 = new Set();
1386
+ const ring3 = new Set();
1387
+
1388
+ relationships.forEach(r => { if (r.targetId === id) ring1.add(r.sourceId); });
1389
+ relationships.forEach(r => { if (ring1.has(r.targetId) && r.sourceId !== id) ring2.add(r.sourceId); });
1390
+ relationships.forEach(r => { if (ring2.has(r.targetId) && !ring1.has(r.sourceId) && r.sourceId !== id) ring3.add(r.sourceId); });
1391
+
1392
+ document.querySelectorAll('.node-group').forEach(el => {
1393
+ const elId = el.getAttribute('data-id');
1394
+ if (elId === id) { el.classList.add('highlighted', 'highlighted-node'); }
1395
+ else if (ring1.has(elId)) { el.classList.add('highlighted', 'blast-ring-1'); }
1396
+ else if (ring2.has(elId)) { el.classList.add('highlighted', 'blast-ring-2'); }
1397
+ else if (ring3.has(elId)) { el.classList.add('highlighted', 'blast-ring-3'); }
1398
+ else { el.classList.add('dimmed'); }
1399
+ });
1400
+
1401
+ document.querySelectorAll('.edge-bg').forEach(el => {
1402
+ const tgt = el.getAttribute('data-target');
1403
+ if (tgt === id) { el.classList.add('blast-ring-1-edge'); }
1404
+ else if (ring1.has(tgt)) { el.classList.add('blast-ring-2-edge'); }
1405
+ else if (ring2.has(tgt)) { el.classList.add('blast-ring-3-edge'); }
1406
+ else { el.classList.add('dimmed'); }
1407
+ });
1408
+
1409
+ document.getElementById('pass-receipt-val').textContent = 'Blast: ' + (ring1.size + ring2.size + ring3.size) + ' Impacted Nodes';
1410
+ } else {
1411
+ // Standard Focus
1412
+ const connected = new Set([id]);
1413
+ relationships.forEach(r => {
1414
+ if (r.sourceId === id) connected.add(r.targetId);
1415
+ if (r.targetId === id) connected.add(r.sourceId);
1416
+ });
1417
+
1418
+ document.querySelectorAll('.node-group').forEach(el => {
1419
+ const elId = el.getAttribute('data-id');
1420
+ if (connected.has(elId)) {
1421
+ el.classList.add('highlighted');
1422
+ if (elId === id) el.classList.add('highlighted-node');
1423
+ } else {
1424
+ el.classList.add('dimmed');
1425
+ }
1426
+ });
1427
+
1428
+ document.querySelectorAll('.edge-bg, .edge-pulse').forEach(el => {
1429
+ const s = el.getAttribute('data-source');
1430
+ const t = el.getAttribute('data-target');
1431
+ if (s === id || t === id) { el.classList.add('highlighted'); }
1432
+ else { el.classList.add('dimmed'); }
1433
+ });
1434
+
1435
+ document.getElementById('pass-receipt-val').textContent = 'Connected: ' + connected.size + ' Nodes';
1436
+ }
1437
+
1438
+ populatePassport(entity);
1439
+ }
1440
+
1441
+ function populatePassport(entity) {
1442
+ passport.classList.add('open');
1443
+ document.getElementById('pass-title').textContent = entity.name;
1444
+ document.getElementById('pass-id').textContent = entity.id;
1445
+ document.getElementById('pass-kind').textContent = (entity.kind || 'MODULE').toUpperCase();
1446
+ document.getElementById('pass-zone').textContent = (entity.trustZone || 'INTERNAL').toUpperCase();
1447
+ document.getElementById('pass-confidence').textContent = (entity.confidence || 'L1') + ' FACT';
1448
+
1449
+ const riskScore = entity.blastRadius?.riskScore || 0.1;
1450
+ const tier = riskScore > 0.7 ? 'CRITICAL' : riskScore > 0.4 ? 'HIGH' : riskScore > 0.2 ? 'MEDIUM' : 'LOW';
1451
+ document.getElementById('pass-risk').textContent = tier + ' (' + riskScore.toFixed(2) + ')';
1452
+ const blastPill = document.getElementById('pass-blast-tier');
1453
+ blastPill.textContent = tier;
1454
+ blastPill.className = 'risk-pill risk-' + tier;
1455
+
1456
+ const directDep = relationships.filter(r => r.targetId === entity.id).length;
1457
+ document.getElementById('pass-blast-desc').textContent = 'Direct callers: ' + directDep + ' · Blast risk score: ' + riskScore.toFixed(2);
1458
+ document.getElementById('pass-role').textContent = entity.role || 'Component extracted deterministically from codebase AST with zero-trust provenance.';
1459
+
1460
+ const evList = document.getElementById('pass-evidence-list');
1461
+ const sources = entity.sources || [];
1462
+ if (sources.length === 0) {
1463
+ evList.innerHTML = '<div style="font-size:10px; color:var(--dim);">No file sources recorded.</div>';
1464
+ } else {
1465
+ evList.innerHTML = sources.map(s =>
1466
+ '<div class="evidence-card">' +
1467
+ '<div class="evidence-path"><span>📄</span> ' + s.file + (s.startLine ? ':' + s.startLine + (s.endLine ? '-' + s.endLine : '') : '') + '</div>' +
1468
+ (s.contentHash ? '<div style="color:var(--dim); font-size:9px;">Hash: <code>' + s.contentHash.slice(0, 16) + '…</code></div>' : '') +
1469
+ (s.snippet ? '<div class="evidence-snippet">' + s.snippet.replace(/</g, '&lt;').replace(/>/g, '&gt;') + '</div>' : '') +
1470
+ '</div>'
1471
+ ).join('');
1472
+ }
1473
+ }
1474
+
1475
+ // ── Authored Reachability Actions ────────────────────────────────────
1476
+ document.getElementById('btn-reach-upstream').addEventListener('click', () => {
1477
+ if (!selectedNodeId) return;
1478
+ clearHighlights();
1479
+ reachMode = 'upstream';
1480
+ document.getElementById('btn-reach-upstream').classList.add('active');
1481
+
1482
+ const reach = computeReachability(selectedNodeId, 'upstream');
1483
+ document.querySelectorAll('.node-group').forEach(el => {
1484
+ const elId = el.getAttribute('data-id');
1485
+ if (reach.nodes.has(elId)) {
1486
+ el.classList.add('highlighted', 'reach-upstream');
1487
+ if (elId === selectedNodeId) el.classList.add('highlighted-node');
1488
+ } else {
1489
+ el.classList.add('dimmed');
1490
+ }
1491
+ });
1492
+
1493
+ document.querySelectorAll('.edge-bg').forEach(el => {
1494
+ const s = el.getAttribute('data-source');
1495
+ const t = el.getAttribute('data-target');
1496
+ let matched = false;
1497
+ reach.edges.forEach(rel => {
1498
+ if (rel.sourceId === s && rel.targetId === t) matched = true;
1499
+ });
1500
+ if (matched) { el.classList.add('reach-upstream-edge'); el.setAttribute('marker-end', 'url(#arrow-violet)'); }
1501
+ else { el.classList.add('dimmed'); }
1502
+ });
1503
+
1504
+ document.getElementById('pass-receipt-val').textContent = 'Upstream: ' + reach.nodes.size + ' Nodes · ' + reach.edges.size + ' Links · max ' + reach.hops + ' hops';
1505
+ });
1506
+
1507
+ document.getElementById('btn-reach-downstream').addEventListener('click', () => {
1508
+ if (!selectedNodeId) return;
1509
+ clearHighlights();
1510
+ reachMode = 'downstream';
1511
+ document.getElementById('btn-reach-downstream').classList.add('active');
1512
+
1513
+ const reach = computeReachability(selectedNodeId, 'downstream');
1514
+ document.querySelectorAll('.node-group').forEach(el => {
1515
+ const elId = el.getAttribute('data-id');
1516
+ if (reach.nodes.has(elId)) {
1517
+ el.classList.add('highlighted', 'reach-downstream');
1518
+ if (elId === selectedNodeId) el.classList.add('highlighted-node');
1519
+ } else {
1520
+ el.classList.add('dimmed');
1521
+ }
1522
+ });
1523
+
1524
+ document.querySelectorAll('.edge-bg').forEach(el => {
1525
+ const s = el.getAttribute('data-source');
1526
+ const t = el.getAttribute('data-target');
1527
+ let matched = false;
1528
+ reach.edges.forEach(rel => {
1529
+ if (rel.sourceId === s && rel.targetId === t) matched = true;
1530
+ });
1531
+ if (matched) { el.classList.add('reach-downstream-edge'); el.setAttribute('marker-end', 'url(#arrow-green)'); }
1532
+ else { el.classList.add('dimmed'); }
1533
+ });
1534
+
1535
+ document.getElementById('pass-receipt-val').textContent = 'Downstream: ' + reach.nodes.size + ' Nodes · ' + reach.edges.size + ' Links · max ' + reach.hops + ' hops';
1536
+ });
1537
+
1538
+ document.getElementById('btn-reach-reset').addEventListener('click', () => {
1539
+ if (selectedNodeId) onNodeClick(selectedNodeId);
1540
+ else clearHighlights();
1541
+ });
1542
+
1543
+ document.getElementById('pass-close').addEventListener('click', () => {
1544
+ passport.classList.remove('open');
1545
+ clearHighlights();
1546
+ selectedNodeId = null;
1547
+ });
1548
+
1549
+ // ── Pan, Zoom & Camera Navigation ────────────────────────────────────
1550
+ viewport.addEventListener('mousedown', (e) => {
1551
+ if (e.target.closest('.node-group')) return;
1552
+ isPanning = true;
1553
+ startPoint = { x: e.clientX - transform.x, y: e.clientY - transform.y };
1554
+ });
1555
+ window.addEventListener('mousemove', (e) => {
1556
+ if (!isPanning) return;
1557
+ transform.x = e.clientX - startPoint.x;
1558
+ transform.y = e.clientY - startPoint.y;
1559
+ updateCanvasTransform();
1560
+ });
1561
+ window.addEventListener('mouseup', () => { isPanning = false; });
1562
+
1563
+ viewport.addEventListener('wheel', (e) => {
1564
+ e.preventDefault();
1565
+ const factor = e.deltaY > 0 ? 0.9 : 1.1;
1566
+ transform.k = Math.max(0.15, Math.min(3.5, transform.k * factor));
1567
+ updateCanvasTransform();
1568
+ });
1569
+
1570
+ document.getElementById('btn-zoom-in').addEventListener('click', () => {
1571
+ transform.k = Math.min(3.5, transform.k * 1.25);
1572
+ updateCanvasTransform();
1573
+ });
1574
+ document.getElementById('btn-zoom-out').addEventListener('click', () => {
1575
+ transform.k = Math.max(0.15, transform.k / 1.25);
1576
+ updateCanvasTransform();
1577
+ });
1578
+ document.getElementById('btn-zoom-reset').addEventListener('click', () => {
1579
+ transform = { x: 70, y: 70, k: 0.78 };
1580
+ updateCanvasTransform();
1581
+ });
1582
+
1583
+ // ── Fly-to Camera Centering on Entity ────────────────────────────────
1584
+ function flyToNode(id) {
1585
+ const coord = nodeCoords.get(id);
1586
+ if (!coord) return;
1587
+ const vRect = viewport.getBoundingClientRect();
1588
+ const targetX = vRect.width / 2 - (coord.x + coord.w / 2) * transform.k;
1589
+ const targetY = vRect.height / 2 - (coord.y + coord.h / 2) * transform.k;
1590
+ transform.x = targetX;
1591
+ transform.y = targetY;
1592
+ updateCanvasTransform();
1593
+ onNodeClick(id);
1594
+ }
1595
+
1596
+ // ── Search & Instant Autocomplete ────────────────────────────────────
1597
+ searchInput.addEventListener('input', (e) => {
1598
+ const q = e.target.value.toLowerCase().trim();
1599
+ if (!q) {
1600
+ searchDropdown.classList.remove('open');
1601
+ clearHighlights();
1602
+ return;
1603
+ }
1604
+
1605
+ const matches = entities.filter(ent =>
1606
+ ent.id.toLowerCase().includes(q) || ent.name.toLowerCase().includes(q) || (ent.kind && ent.kind.toLowerCase().includes(q))
1607
+ );
1608
+
1609
+ if (matches.length > 0) {
1610
+ searchDropdown.innerHTML = matches.slice(0, 8).map(m =>
1611
+ '<div class="search-item" data-id="' + m.id + '">' +
1612
+ '<strong>' + m.name + '</strong>' +
1613
+ '<span class="dropdown-hint">' + m.kind.toUpperCase() + '</span>' +
1614
+ '</div>'
1615
+ ).join('');
1616
+ searchDropdown.classList.add('open');
1617
+ } else {
1618
+ searchDropdown.innerHTML = '<div style="padding:8px 12px; font-size:10px; color:var(--dim);">No components match</div>';
1619
+ searchDropdown.classList.add('open');
1620
+ }
1621
+
1622
+ // Live visual highlight matching nodes
1623
+ document.querySelectorAll('.node-group').forEach(el => {
1624
+ const id = el.getAttribute('data-id');
1625
+ const isMatch = matches.some(m => m.id === id);
1626
+ if (isMatch) { el.classList.add('highlighted'); el.classList.remove('dimmed'); }
1627
+ else { el.classList.add('dimmed'); el.classList.remove('highlighted'); }
1628
+ });
1629
+ });
1630
+
1631
+ searchDropdown.addEventListener('click', (e) => {
1632
+ const item = e.target.closest('.search-item');
1633
+ if (!item) return;
1634
+ const id = item.getAttribute('data-id');
1635
+ searchDropdown.classList.remove('open');
1636
+ searchInput.value = '';
1637
+ flyToNode(id);
1638
+ });
1639
+
1640
+ // ── Projection Switching ─────────────────────────────────────────────
1641
+ document.querySelectorAll('.proj-btn').forEach(btn => {
1642
+ btn.addEventListener('click', () => {
1643
+ document.querySelectorAll('.proj-btn').forEach(b => b.classList.remove('active'));
1644
+ btn.classList.add('active');
1645
+ currentProjection = btn.getAttribute('data-projection');
1646
+ updateTelemetry();
1647
+ renderNodes();
1648
+ renderEdges();
1649
+ if (selectedNodeId) onNodeClick(selectedNodeId);
1650
+ });
1651
+ });
1652
+
1653
+ // ── Presets Menu & Switcher ──────────────────────────────────────────
1654
+ const presetBtn = document.getElementById('btn-preset-toggle');
1655
+ const presetMenu = document.getElementById('preset-menu');
1656
+ const presetLabel = document.getElementById('preset-label');
1657
+
1658
+ presetBtn.addEventListener('click', (e) => {
1659
+ e.stopPropagation();
1660
+ exportMenu.classList.remove('open');
1661
+ presetMenu.classList.toggle('open');
1662
+ });
1663
+
1664
+ presetMenu.addEventListener('click', (e) => {
1665
+ const item = e.target.closest('.dropdown-item');
1666
+ if (!item) return;
1667
+ const val = item.getAttribute('data-val');
1668
+ setPreset(val);
1669
+ presetMenu.classList.remove('open');
1670
+ });
1671
+
1672
+ function setPreset(val) {
1673
+ document.documentElement.setAttribute('data-preset', val);
1674
+ localStorage.setItem('tribunal-arch-preset', val);
1675
+ document.querySelectorAll('#preset-menu .dropdown-item').forEach(it => {
1676
+ it.classList.toggle('active', it.getAttribute('data-val') === val);
1677
+ });
1678
+ const labels = {
1679
+ classic: 'Obsidian',
1680
+ 'signal-flow': 'Signal Flow',
1681
+ blueprint: 'Blueprint',
1682
+ editorial: 'Editorial'
1683
+ };
1684
+ presetLabel.textContent = labels[val] || val;
1685
+ }
1686
+
1687
+ function cyclePreset() {
1688
+ const presets = ['classic', 'signal-flow', 'blueprint', 'editorial'];
1689
+ const current = document.documentElement.getAttribute('data-preset') || 'signal-flow';
1690
+ const next = presets[(presets.indexOf(current) + 1) % presets.length];
1691
+ setPreset(next);
1692
+ }
1693
+
1694
+ // ── Theme Toggle ─────────────────────────────────────────────────────
1695
+ const themeBtn = document.getElementById('btn-theme');
1696
+ const themeIcon = document.getElementById('theme-icon');
1697
+
1698
+ function toggleTheme() {
1699
+ const current = document.documentElement.getAttribute('data-theme') || 'dark';
1700
+ const next = current === 'dark' ? 'light' : 'dark';
1701
+ document.documentElement.setAttribute('data-theme', next);
1702
+ localStorage.setItem('tribunal-arch-theme', next);
1703
+ themeIcon.textContent = next === 'dark' ? '🌙' : '☀️';
1704
+ }
1705
+ themeBtn.addEventListener('click', toggleTheme);
1706
+
1707
+ // ── Motion Governor ──────────────────────────────────────────────────
1708
+ const motionBtn = document.getElementById('btn-motion');
1709
+ const motionDot = document.getElementById('motion-dot');
1710
+ const motionLabel = document.getElementById('motion-label');
1711
+
1712
+ function toggleMotion() {
1713
+ motionEnabled = !motionEnabled;
1714
+ if (motionEnabled) {
1715
+ motionDot.style.background = '#22d3ee';
1716
+ motionLabel.textContent = 'Motion';
1717
+ document.querySelectorAll('.edge-pulse').forEach(el => el.style.animationPlayState = 'running');
1718
+ } else {
1719
+ motionDot.style.background = '#64748b';
1720
+ motionLabel.textContent = 'Paused';
1721
+ document.querySelectorAll('.edge-pulse').forEach(el => el.style.animationPlayState = 'paused');
1722
+ }
1723
+ }
1724
+ motionBtn.addEventListener('click', toggleMotion);
1725
+
1726
+ // ── Presentation Mode ────────────────────────────────────────────────
1727
+ document.getElementById('btn-present').addEventListener('click', () => {
1728
+ document.body.classList.toggle('presentation-mode');
1729
+ });
1730
+
1731
+ // ── Export Menu & Handlers ───────────────────────────────────────────
1732
+ const exportBtn = document.getElementById('btn-export-toggle');
1733
+ const exportMenu = document.getElementById('export-menu');
1734
+
1735
+ exportBtn.addEventListener('click', (e) => {
1736
+ e.stopPropagation();
1737
+ presetMenu.classList.remove('open');
1738
+ exportMenu.classList.toggle('open');
1739
+ });
1740
+
1741
+ window.addEventListener('click', () => {
1742
+ presetMenu.classList.remove('open');
1743
+ exportMenu.classList.remove('open');
1744
+ searchDropdown.classList.remove('open');
1745
+ });
1746
+
1747
+ // 1. Lossless SVG Download
1748
+ document.getElementById('act-download-svg').addEventListener('click', () => {
1749
+ const svgEl = document.getElementById('arch-canvas');
1750
+ const serializer = new XMLSerializer();
1751
+ let source = serializer.serializeToString(svgEl);
1752
+ source = '<?xml version="1.0" standalone="no"?>\\r\\n' + source;
1753
+ const blob = new Blob([source], { type: 'image/svg+xml;charset=utf-8' });
1754
+ const url = URL.createObjectURL(blob);
1755
+ const a = document.createElement('a');
1756
+ a.href = url;
1757
+ a.download = (model.engine || 'architecture') + '-diagram.svg';
1758
+ a.click();
1759
+ URL.revokeObjectURL(url);
1760
+ });
1761
+
1762
+ // Helper: Render SVG to offscreen canvas
1763
+ function rasterizeToCanvas(targetCanvas, width, height, callback) {
1764
+ const svgEl = document.getElementById('arch-canvas');
1765
+ const serializer = new XMLSerializer();
1766
+ const svgString = serializer.serializeToString(svgEl);
1767
+ const img = new Image();
1768
+ const svgBlob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });
1769
+ const url = URL.createObjectURL(svgBlob);
1770
+
1771
+ img.onload = function () {
1772
+ const ctx = targetCanvas.getContext('2d');
1773
+ targetCanvas.width = width;
1774
+ targetCanvas.height = height;
1775
+
1776
+ // Background fill matching theme
1777
+ const theme = document.documentElement.getAttribute('data-theme') || 'dark';
1778
+ ctx.fillStyle = theme === 'light' ? '#f8fafc' : '#030712';
1779
+ ctx.fillRect(0, 0, width, height);
1780
+
1781
+ ctx.drawImage(img, 0, 0, width, height);
1782
+ URL.revokeObjectURL(url);
1783
+ callback(targetCanvas);
1784
+ };
1785
+ img.src = url;
1786
+ }
1787
+
1788
+ // 2. High-Res PNG Download
1789
+ document.getElementById('act-download-png').addEventListener('click', () => {
1790
+ const canvas = document.getElementById('export-canvas');
1791
+ rasterizeToCanvas(canvas, 1920, 1080, (c) => {
1792
+ const a = document.createElement('a');
1793
+ a.download = (model.engine || 'architecture') + '-1080p.png';
1794
+ a.href = c.toDataURL('image/png');
1795
+ a.click();
1796
+ });
1797
+ });
1798
+
1799
+ // 3. WebP Download
1800
+ document.getElementById('act-download-webp').addEventListener('click', () => {
1801
+ const canvas = document.getElementById('export-canvas');
1802
+ rasterizeToCanvas(canvas, 1920, 1080, (c) => {
1803
+ const a = document.createElement('a');
1804
+ a.download = (model.engine || 'architecture') + '-1080p.webp';
1805
+ a.href = c.toDataURL('image/webp', 0.92);
1806
+ a.click();
1807
+ });
1808
+ });
1809
+
1810
+ // 4. Copy PNG to Clipboard
1811
+ document.getElementById('act-copy-png').addEventListener('click', () => {
1812
+ const canvas = document.getElementById('export-canvas');
1813
+ rasterizeToCanvas(canvas, 1600, 900, (c) => {
1814
+ c.toBlob(blob => {
1815
+ if (navigator.clipboard && window.ClipboardItem) {
1816
+ navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })])
1817
+ .then(() => alert('Architecture diagram copied to clipboard as PNG!'))
1818
+ .catch(err => console.error(err));
1819
+ }
1820
+ });
1821
+ });
1822
+ });
1823
+
1824
+ // 5. Archify-Grade Reach / Blast Share Card (1200×630 PNG)
1825
+ document.getElementById('act-share-card').addEventListener('click', () => {
1826
+ const canvas = document.getElementById('export-canvas');
1827
+ const ctx = canvas.getContext('2d');
1828
+ canvas.width = 1200;
1829
+ canvas.height = 630;
1830
+
1831
+ // Draw Premium Midnight Card Base
1832
+ ctx.fillStyle = '#020617';
1833
+ ctx.fillRect(0, 0, 1200, 630);
1834
+
1835
+ // Radial ambient accent
1836
+ const grad = ctx.createRadialGradient(600, 315, 50, 600, 315, 600);
1837
+ grad.addColorStop(0, 'rgba(34, 211, 238, 0.08)');
1838
+ grad.addColorStop(1, 'rgba(2, 6, 23, 0)');
1839
+ ctx.fillStyle = grad;
1840
+ ctx.fillRect(0, 0, 1200, 630);
1841
+
1842
+ // Outer Structural 1px Border
1843
+ ctx.strokeStyle = '#1e293b';
1844
+ ctx.lineWidth = 2;
1845
+ ctx.strokeRect(16, 16, 1168, 598);
1846
+
1847
+ // Header Lockup
1848
+ ctx.fillStyle = '#22d3ee';
1849
+ ctx.font = 'bold 12px "JetBrains Mono", monospace';
1850
+ ctx.fillText('⚖️ TRIBUNAL ARCHITECTURE INTELLIGENCE // EVIDENCE CONSOLE', 40, 56);
1851
+
1852
+ // Title
1853
+ const targetEntity = entities.find(e => e.id === selectedNodeId);
1854
+ const targetTitle = targetEntity ? targetEntity.name : 'System Architecture Overview';
1855
+ ctx.fillStyle = '#ffffff';
1856
+ ctx.font = 'bold 24px "JetBrains Mono", monospace';
1857
+ ctx.fillText(targetTitle, 40, 92);
1858
+
1859
+ // Telemetry Subtitle Receipt
1860
+ const receiptText = document.getElementById('pass-receipt-val').textContent || 'Full System Topology';
1861
+ ctx.fillStyle = '#94a3b8';
1862
+ ctx.font = '13px "JetBrains Mono", monospace';
1863
+ ctx.fillText('RECEIPT: ' + receiptText.toUpperCase() + ' · TIMESTAMP: ' + new Date().toISOString().slice(0, 10), 40, 118);
1864
+
1865
+ // Draw Diagram Preview into Card Center
1866
+ const svgEl = document.getElementById('arch-canvas');
1867
+ const serializer = new XMLSerializer();
1868
+ const svgString = serializer.serializeToString(svgEl);
1869
+ const img = new Image();
1870
+ const svgBlob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });
1871
+ const url = URL.createObjectURL(svgBlob);
1872
+
1873
+ img.onload = function () {
1874
+ // Draw thumbnail into box (40, 140, 1120, 430)
1875
+ ctx.drawImage(img, 40, 140, 1120, 420);
1876
+ URL.revokeObjectURL(url);
1877
+
1878
+ // Card Footer Watermark
1879
+ ctx.fillStyle = '#475569';
1880
+ ctx.font = '10px "JetBrains Mono", monospace';
1881
+ ctx.fillText('VERIFIED VIA AST EXTRACTION · L1-L5 PROVENANCE GUARANTEED · TRIBUNAL-KIT', 40, 590);
1882
+
1883
+ const a = document.createElement('a');
1884
+ a.download = (targetEntity ? targetEntity.name.replace(/[^a-z0-9]/gi, '_') : 'arch') + '-share-card.png';
1885
+ a.href = canvas.toDataURL('image/png');
1886
+ a.click();
1887
+ };
1888
+ img.src = url;
1889
+ });
1890
+
1891
+ // ── Keyboard Shortcuts ───────────────────────────────────────────────
1892
+ window.addEventListener('keydown', (e) => {
1893
+ if (e.target.tagName === 'INPUT') {
1894
+ if (e.key === 'Escape') searchInput.blur();
1895
+ return;
1896
+ }
1897
+ if (e.key === '/') {
1898
+ e.preventDefault();
1899
+ searchInput.focus();
1900
+ } else if (e.key === 's' || e.key === 'S') {
1901
+ e.preventDefault();
1902
+ cyclePreset();
1903
+ } else if (e.key === 't' || e.key === 'T') {
1904
+ e.preventDefault();
1905
+ toggleTheme();
1906
+ } else if (e.key === 'm' || e.key === 'M') {
1907
+ e.preventDefault();
1908
+ toggleMotion();
1909
+ } else if (e.key === 'f' || e.key === 'F') {
1910
+ e.preventDefault();
1911
+ document.body.classList.toggle('presentation-mode');
1912
+ } else if (e.key === 'e' || e.key === 'E') {
1913
+ e.preventDefault();
1914
+ exportMenu.classList.toggle('open');
1915
+ } else if (e.key === 'Escape') {
1916
+ passport.classList.remove('open');
1917
+ searchDropdown.classList.remove('open');
1918
+ clearHighlights();
1919
+ selectedNodeId = null;
1920
+ } else if (e.key === '0') {
1921
+ transform = { x: 70, y: 70, k: 0.78 };
1922
+ updateCanvasTransform();
1923
+ }
1924
+ });
1925
+
1926
+ // ── Initial Mount ────────────────────────────────────────────────────
1927
+ updateCanvasTransform();
1928
+ updateTelemetry();
1929
+ renderNodes();
1930
+ renderEdges();
1931
+ })();
1932
+ </script>
1933
+ </body>
1934
+ </html>`;
1935
+ }
1936
+
1937
+ saveHtml(outputPath) {
1938
+ const dest =
1939
+ outputPath || path.join(process.cwd(), '.agent', 'history', 'architecture-intelligence.html');
1940
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
1941
+ const html = this.generateHtml();
1942
+ fs.writeFileSync(dest, html, 'utf8');
1943
+ return dest;
1944
+ }
1945
+ }
1946
+
1947
+ // ── Standalone CLI ────────────────────────────────────────────────────────────
1948
+ if (require.main === module) {
1949
+ const t = timer();
1950
+ const repoRoot = process.cwd();
1951
+ const modelFile = path.join(repoRoot, '.agent', 'history', 'architecture-model.json');
1952
+ const verifFile = path.join(repoRoot, '.agent', 'history', 'architecture-verification.json');
1953
+
1954
+ console.log(banner('Tribunal Architecture Intelligence Visualizer (The Evidence Console)'));
1955
+
1956
+ if (!fs.existsSync(modelFile)) {
1957
+ console.error(
1958
+ ` ${RED}✖ architecture-model.json not found.${RESET} Run architecture_extractor.js first.`,
1959
+ );
1960
+ process.exit(1);
1961
+ }
1962
+
1963
+ const model = JSON.parse(fs.readFileSync(modelFile, 'utf8'));
1964
+ const verification = fs.existsSync(verifFile)
1965
+ ? JSON.parse(fs.readFileSync(verifFile, 'utf8'))
1966
+ : null;
1967
+
1968
+ const visualizer = new ArchitectureVisualizer(model, verification);
1969
+ const outPath = visualizer.saveHtml();
1970
+
1971
+ console.log(
1972
+ ` ${GREEN}${BOX.check} Interactive Architecture Explorer (Evidence Console) Generated!${RESET}`,
1973
+ );
1974
+ console.log(` ${DIM}File:${RESET} ${CYAN}${outPath}${RESET} (${formatMs(t())})`);
1975
+ console.log(
1976
+ ` ${DIM}Presets Enabled:${RESET} Obsidian Console, Signal Flow, Cyber Blueprint, Editorial Monolith`,
1977
+ );
1978
+ console.log(
1979
+ ` ${DIM}Projections Enabled:${RESET} Topology, Security Zones, Failure Modes, Blast Simulator`,
1980
+ );
1981
+ console.log(
1982
+ ` ${DIM}Features:${RESET} Semantic Passport, Reachability Subgraphs, 1200x630 Share Card Export\n`,
1983
+ );
1984
+ }
1985
+
1986
+ module.exports = {
1987
+ ArchitectureVisualizer,
1988
+ };