forge-server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (412) hide show
  1. package/.claude/hooks/worktree-create.sh +64 -0
  2. package/.claude/hooks/worktree-remove.sh +57 -0
  3. package/.claude/settings.local.json +29 -0
  4. package/.forge/knowledge/conventions.yaml +1 -0
  5. package/.forge/knowledge/decisions.yaml +1 -0
  6. package/.forge/knowledge/gotchas.yaml +1 -0
  7. package/.forge/knowledge/patterns.yaml +1 -0
  8. package/.forge/manifest.yaml +6 -0
  9. package/CLAUDE.md +144 -0
  10. package/bin/setup-forge.sh +132 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +553 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/context/codebase.d.ts +57 -0
  16. package/dist/context/codebase.d.ts.map +1 -0
  17. package/dist/context/codebase.js +301 -0
  18. package/dist/context/codebase.js.map +1 -0
  19. package/dist/context/injector.d.ts +147 -0
  20. package/dist/context/injector.d.ts.map +1 -0
  21. package/dist/context/injector.js +533 -0
  22. package/dist/context/injector.js.map +1 -0
  23. package/dist/context/memory.d.ts +32 -0
  24. package/dist/context/memory.d.ts.map +1 -0
  25. package/dist/context/memory.js +140 -0
  26. package/dist/context/memory.js.map +1 -0
  27. package/dist/context/session-index.d.ts +54 -0
  28. package/dist/context/session-index.d.ts.map +1 -0
  29. package/dist/context/session-index.js +265 -0
  30. package/dist/context/session-index.js.map +1 -0
  31. package/dist/context/session.d.ts +42 -0
  32. package/dist/context/session.d.ts.map +1 -0
  33. package/dist/context/session.js +121 -0
  34. package/dist/context/session.js.map +1 -0
  35. package/dist/index.d.ts +3 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +37 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/ingestion/chunker.d.ts +19 -0
  40. package/dist/ingestion/chunker.d.ts.map +1 -0
  41. package/dist/ingestion/chunker.js +189 -0
  42. package/dist/ingestion/chunker.js.map +1 -0
  43. package/dist/ingestion/embedder.d.ts +45 -0
  44. package/dist/ingestion/embedder.d.ts.map +1 -0
  45. package/dist/ingestion/embedder.js +152 -0
  46. package/dist/ingestion/embedder.js.map +1 -0
  47. package/dist/ingestion/git-analyzer.d.ts +77 -0
  48. package/dist/ingestion/git-analyzer.d.ts.map +1 -0
  49. package/dist/ingestion/git-analyzer.js +437 -0
  50. package/dist/ingestion/git-analyzer.js.map +1 -0
  51. package/dist/ingestion/indexer.d.ts +79 -0
  52. package/dist/ingestion/indexer.d.ts.map +1 -0
  53. package/dist/ingestion/indexer.js +766 -0
  54. package/dist/ingestion/indexer.js.map +1 -0
  55. package/dist/ingestion/markdown-chunker.d.ts +19 -0
  56. package/dist/ingestion/markdown-chunker.d.ts.map +1 -0
  57. package/dist/ingestion/markdown-chunker.js +243 -0
  58. package/dist/ingestion/markdown-chunker.js.map +1 -0
  59. package/dist/ingestion/markdown-knowledge.d.ts +21 -0
  60. package/dist/ingestion/markdown-knowledge.d.ts.map +1 -0
  61. package/dist/ingestion/markdown-knowledge.js +129 -0
  62. package/dist/ingestion/markdown-knowledge.js.map +1 -0
  63. package/dist/ingestion/parser.d.ts +20 -0
  64. package/dist/ingestion/parser.d.ts.map +1 -0
  65. package/dist/ingestion/parser.js +429 -0
  66. package/dist/ingestion/parser.js.map +1 -0
  67. package/dist/ingestion/watcher.d.ts +28 -0
  68. package/dist/ingestion/watcher.d.ts.map +1 -0
  69. package/dist/ingestion/watcher.js +147 -0
  70. package/dist/ingestion/watcher.js.map +1 -0
  71. package/dist/knowledge/hydrator.d.ts +37 -0
  72. package/dist/knowledge/hydrator.d.ts.map +1 -0
  73. package/dist/knowledge/hydrator.js +220 -0
  74. package/dist/knowledge/hydrator.js.map +1 -0
  75. package/dist/knowledge/registry.d.ts +129 -0
  76. package/dist/knowledge/registry.d.ts.map +1 -0
  77. package/dist/knowledge/registry.js +361 -0
  78. package/dist/knowledge/registry.js.map +1 -0
  79. package/dist/knowledge/search.d.ts +114 -0
  80. package/dist/knowledge/search.d.ts.map +1 -0
  81. package/dist/knowledge/search.js +428 -0
  82. package/dist/knowledge/search.js.map +1 -0
  83. package/dist/knowledge/store.d.ts +76 -0
  84. package/dist/knowledge/store.d.ts.map +1 -0
  85. package/dist/knowledge/store.js +230 -0
  86. package/dist/knowledge/store.js.map +1 -0
  87. package/dist/learning/confidence.d.ts +30 -0
  88. package/dist/learning/confidence.d.ts.map +1 -0
  89. package/dist/learning/confidence.js +165 -0
  90. package/dist/learning/confidence.js.map +1 -0
  91. package/dist/learning/patterns.d.ts +52 -0
  92. package/dist/learning/patterns.d.ts.map +1 -0
  93. package/dist/learning/patterns.js +290 -0
  94. package/dist/learning/patterns.js.map +1 -0
  95. package/dist/learning/trajectory.d.ts +55 -0
  96. package/dist/learning/trajectory.d.ts.map +1 -0
  97. package/dist/learning/trajectory.js +200 -0
  98. package/dist/learning/trajectory.js.map +1 -0
  99. package/dist/memory/memory-compat.d.ts +100 -0
  100. package/dist/memory/memory-compat.d.ts.map +1 -0
  101. package/dist/memory/memory-compat.js +146 -0
  102. package/dist/memory/memory-compat.js.map +1 -0
  103. package/dist/memory/observation-store.d.ts +57 -0
  104. package/dist/memory/observation-store.d.ts.map +1 -0
  105. package/dist/memory/observation-store.js +154 -0
  106. package/dist/memory/observation-store.js.map +1 -0
  107. package/dist/memory/session-tracker.d.ts +81 -0
  108. package/dist/memory/session-tracker.d.ts.map +1 -0
  109. package/dist/memory/session-tracker.js +262 -0
  110. package/dist/memory/session-tracker.js.map +1 -0
  111. package/dist/pipeline/engine.d.ts +179 -0
  112. package/dist/pipeline/engine.d.ts.map +1 -0
  113. package/dist/pipeline/engine.js +691 -0
  114. package/dist/pipeline/engine.js.map +1 -0
  115. package/dist/pipeline/events.d.ts +54 -0
  116. package/dist/pipeline/events.d.ts.map +1 -0
  117. package/dist/pipeline/events.js +157 -0
  118. package/dist/pipeline/events.js.map +1 -0
  119. package/dist/pipeline/parallel.d.ts +83 -0
  120. package/dist/pipeline/parallel.d.ts.map +1 -0
  121. package/dist/pipeline/parallel.js +277 -0
  122. package/dist/pipeline/parallel.js.map +1 -0
  123. package/dist/pipeline/state-machine.d.ts +65 -0
  124. package/dist/pipeline/state-machine.d.ts.map +1 -0
  125. package/dist/pipeline/state-machine.js +176 -0
  126. package/dist/pipeline/state-machine.js.map +1 -0
  127. package/dist/query/graph-queries.d.ts +84 -0
  128. package/dist/query/graph-queries.d.ts.map +1 -0
  129. package/dist/query/graph-queries.js +216 -0
  130. package/dist/query/graph-queries.js.map +1 -0
  131. package/dist/query/hybrid-search.d.ts +34 -0
  132. package/dist/query/hybrid-search.d.ts.map +1 -0
  133. package/dist/query/hybrid-search.js +263 -0
  134. package/dist/query/hybrid-search.js.map +1 -0
  135. package/dist/query/intent-detector.d.ts +35 -0
  136. package/dist/query/intent-detector.d.ts.map +1 -0
  137. package/dist/query/intent-detector.js +115 -0
  138. package/dist/query/intent-detector.js.map +1 -0
  139. package/dist/query/ranking.d.ts +57 -0
  140. package/dist/query/ranking.d.ts.map +1 -0
  141. package/dist/query/ranking.js +109 -0
  142. package/dist/query/ranking.js.map +1 -0
  143. package/dist/server.d.ts +3 -0
  144. package/dist/server.d.ts.map +1 -0
  145. package/dist/server.js +291 -0
  146. package/dist/server.js.map +1 -0
  147. package/dist/storage/falkordb-store.d.ts +73 -0
  148. package/dist/storage/falkordb-store.d.ts.map +1 -0
  149. package/dist/storage/falkordb-store.js +346 -0
  150. package/dist/storage/falkordb-store.js.map +1 -0
  151. package/dist/storage/file-cache.d.ts +32 -0
  152. package/dist/storage/file-cache.d.ts.map +1 -0
  153. package/dist/storage/file-cache.js +115 -0
  154. package/dist/storage/file-cache.js.map +1 -0
  155. package/dist/storage/interfaces.d.ts +151 -0
  156. package/dist/storage/interfaces.d.ts.map +1 -0
  157. package/dist/storage/interfaces.js +7 -0
  158. package/dist/storage/interfaces.js.map +1 -0
  159. package/dist/storage/qdrant-store.d.ts +110 -0
  160. package/dist/storage/qdrant-store.d.ts.map +1 -0
  161. package/dist/storage/qdrant-store.js +467 -0
  162. package/dist/storage/qdrant-store.js.map +1 -0
  163. package/dist/storage/schema.d.ts +4 -0
  164. package/dist/storage/schema.d.ts.map +1 -0
  165. package/dist/storage/schema.js +136 -0
  166. package/dist/storage/schema.js.map +1 -0
  167. package/dist/storage/sqlite.d.ts +35 -0
  168. package/dist/storage/sqlite.d.ts.map +1 -0
  169. package/dist/storage/sqlite.js +132 -0
  170. package/dist/storage/sqlite.js.map +1 -0
  171. package/dist/tools/collaboration-tools.d.ts +111 -0
  172. package/dist/tools/collaboration-tools.d.ts.map +1 -0
  173. package/dist/tools/collaboration-tools.js +174 -0
  174. package/dist/tools/collaboration-tools.js.map +1 -0
  175. package/dist/tools/context-tools.d.ts +293 -0
  176. package/dist/tools/context-tools.d.ts.map +1 -0
  177. package/dist/tools/context-tools.js +437 -0
  178. package/dist/tools/context-tools.js.map +1 -0
  179. package/dist/tools/graph-tools.d.ts +129 -0
  180. package/dist/tools/graph-tools.d.ts.map +1 -0
  181. package/dist/tools/graph-tools.js +237 -0
  182. package/dist/tools/graph-tools.js.map +1 -0
  183. package/dist/tools/ingestion-tools.d.ts +96 -0
  184. package/dist/tools/ingestion-tools.d.ts.map +1 -0
  185. package/dist/tools/ingestion-tools.js +90 -0
  186. package/dist/tools/ingestion-tools.js.map +1 -0
  187. package/dist/tools/learning-tools.d.ts +168 -0
  188. package/dist/tools/learning-tools.d.ts.map +1 -0
  189. package/dist/tools/learning-tools.js +158 -0
  190. package/dist/tools/learning-tools.js.map +1 -0
  191. package/dist/tools/memory-tools.d.ts +183 -0
  192. package/dist/tools/memory-tools.d.ts.map +1 -0
  193. package/dist/tools/memory-tools.js +197 -0
  194. package/dist/tools/memory-tools.js.map +1 -0
  195. package/dist/tools/phase-tools.d.ts +954 -0
  196. package/dist/tools/phase-tools.d.ts.map +1 -0
  197. package/dist/tools/phase-tools.js +1215 -0
  198. package/dist/tools/phase-tools.js.map +1 -0
  199. package/dist/tools/pipeline-tools.d.ts +140 -0
  200. package/dist/tools/pipeline-tools.d.ts.map +1 -0
  201. package/dist/tools/pipeline-tools.js +162 -0
  202. package/dist/tools/pipeline-tools.js.map +1 -0
  203. package/dist/tools/registration-tools.d.ts +220 -0
  204. package/dist/tools/registration-tools.d.ts.map +1 -0
  205. package/dist/tools/registration-tools.js +391 -0
  206. package/dist/tools/registration-tools.js.map +1 -0
  207. package/dist/util/circuit-breaker.d.ts +75 -0
  208. package/dist/util/circuit-breaker.d.ts.map +1 -0
  209. package/dist/util/circuit-breaker.js +159 -0
  210. package/dist/util/circuit-breaker.js.map +1 -0
  211. package/dist/util/config.d.ts +23 -0
  212. package/dist/util/config.d.ts.map +1 -0
  213. package/dist/util/config.js +164 -0
  214. package/dist/util/config.js.map +1 -0
  215. package/dist/util/logger.d.ts +13 -0
  216. package/dist/util/logger.d.ts.map +1 -0
  217. package/dist/util/logger.js +45 -0
  218. package/dist/util/logger.js.map +1 -0
  219. package/dist/util/token-counter.d.ts +24 -0
  220. package/dist/util/token-counter.d.ts.map +1 -0
  221. package/dist/util/token-counter.js +48 -0
  222. package/dist/util/token-counter.js.map +1 -0
  223. package/dist/util/types.d.ts +525 -0
  224. package/dist/util/types.d.ts.map +1 -0
  225. package/dist/util/types.js +5 -0
  226. package/dist/util/types.js.map +1 -0
  227. package/docker-compose.yml +20 -0
  228. package/docs/plans/2026-02-27-swarm-coordination/architecture.md +203 -0
  229. package/docs/plans/2026-02-27-swarm-coordination/vision.md +57 -0
  230. package/docs/plans/completed/2026-02-26-forge-plugin-bundling/architecture.md +1 -0
  231. package/docs/plans/completed/2026-02-26-forge-plugin-bundling/vision.md +300 -0
  232. package/docs/plans/completed/2026-02-27-forge-swarm-learning/architecture.md +480 -0
  233. package/docs/plans/completed/2026-02-27-forge-swarm-learning/verification-checklist.md +462 -0
  234. package/docs/plans/completed/2026-02-27-git-history-atlassian/git-jira-plan.md +181 -0
  235. package/package.json +39 -0
  236. package/plugin/.claude-plugin/plugin.json +8 -0
  237. package/plugin/.mcp.json +15 -0
  238. package/plugin/README.md +134 -0
  239. package/plugin/agents/architect.md +367 -0
  240. package/plugin/agents/backend-specialist.md +263 -0
  241. package/plugin/agents/brainstormer.md +122 -0
  242. package/plugin/agents/data-specialist.md +266 -0
  243. package/plugin/agents/designer.md +408 -0
  244. package/plugin/agents/frontend-specialist.md +241 -0
  245. package/plugin/agents/inspector.md +406 -0
  246. package/plugin/agents/knowledge-keeper.md +443 -0
  247. package/plugin/agents/platform-engineer.md +326 -0
  248. package/plugin/agents/product-manager.md +268 -0
  249. package/plugin/agents/product-owner.md +438 -0
  250. package/plugin/agents/pulse-checker.md +73 -0
  251. package/plugin/agents/qa-strategist.md +500 -0
  252. package/plugin/agents/self-improver.md +310 -0
  253. package/plugin/agents/strategist.md +360 -0
  254. package/plugin/agents/supervisor.md +380 -0
  255. package/plugin/commands/brainstorm.md +25 -0
  256. package/plugin/commands/forge.md +88 -0
  257. package/plugin/docs/atlassian-integration.md +110 -0
  258. package/plugin/docs/workflow.md +126 -0
  259. package/plugin/skills/agent-development/.skillfish.json +10 -0
  260. package/plugin/skills/agent-development/SKILL.md +415 -0
  261. package/plugin/skills/agent-development/examples/agent-creation-prompt.md +238 -0
  262. package/plugin/skills/agent-development/examples/complete-agent-examples.md +427 -0
  263. package/plugin/skills/agent-development/references/agent-creation-system-prompt.md +207 -0
  264. package/plugin/skills/agent-development/references/system-prompt-design.md +411 -0
  265. package/plugin/skills/agent-development/references/triggering-examples.md +491 -0
  266. package/plugin/skills/agent-development/scripts/validate-agent.sh +217 -0
  267. package/plugin/skills/agent-handoff/SKILL.md +335 -0
  268. package/plugin/skills/anti-stub/SKILL.md +317 -0
  269. package/plugin/skills/brainstorm/SKILL.md +31 -0
  270. package/plugin/skills/debugging/SKILL.md +276 -0
  271. package/plugin/skills/fix/SKILL.md +62 -0
  272. package/plugin/skills/frontend-design/.skillfish.json +10 -0
  273. package/plugin/skills/frontend-design/SKILL.md +42 -0
  274. package/plugin/skills/gotchas/SKILL.md +61 -0
  275. package/plugin/skills/graph-orchestrator/SKILL.md +38 -0
  276. package/plugin/skills/history/SKILL.md +58 -0
  277. package/plugin/skills/impact/SKILL.md +59 -0
  278. package/plugin/skills/implementation-execution/SKILL.md +291 -0
  279. package/plugin/skills/index-repo/SKILL.md +55 -0
  280. package/plugin/skills/interviewing/SKILL.md +225 -0
  281. package/plugin/skills/knowledge-curation/SKILL.md +393 -0
  282. package/plugin/skills/learn/SKILL.md +69 -0
  283. package/plugin/skills/mcp-integration/.skillfish.json +10 -0
  284. package/plugin/skills/mcp-integration/SKILL.md +554 -0
  285. package/plugin/skills/mcp-integration/examples/http-server.json +20 -0
  286. package/plugin/skills/mcp-integration/examples/sse-server.json +19 -0
  287. package/plugin/skills/mcp-integration/examples/stdio-server.json +26 -0
  288. package/plugin/skills/mcp-integration/references/authentication.md +549 -0
  289. package/plugin/skills/mcp-integration/references/server-types.md +536 -0
  290. package/plugin/skills/mcp-integration/references/tool-usage.md +538 -0
  291. package/plugin/skills/nestjs/.skillfish.json +10 -0
  292. package/plugin/skills/nestjs/SKILL.md +669 -0
  293. package/plugin/skills/nestjs/drizzle-reference.md +1894 -0
  294. package/plugin/skills/nestjs/reference.md +1447 -0
  295. package/plugin/skills/nestjs/workflow-optimization.md +229 -0
  296. package/plugin/skills/parallel-dispatch/SKILL.md +308 -0
  297. package/plugin/skills/project-discovery/SKILL.md +304 -0
  298. package/plugin/skills/search/SKILL.md +56 -0
  299. package/plugin/skills/security-audit/SKILL.md +362 -0
  300. package/plugin/skills/skill-development/.skillfish.json +10 -0
  301. package/plugin/skills/skill-development/SKILL.md +637 -0
  302. package/plugin/skills/skill-development/references/skill-creator-original.md +209 -0
  303. package/plugin/skills/tdd/SKILL.md +273 -0
  304. package/plugin/skills/terminal-presentation/SKILL.md +395 -0
  305. package/plugin/skills/test-strategy/SKILL.md +365 -0
  306. package/plugin/skills/verification-protocol/SKILL.md +256 -0
  307. package/plugin/skills/visual-explainer/CHANGELOG.md +97 -0
  308. package/plugin/skills/visual-explainer/LICENSE +21 -0
  309. package/plugin/skills/visual-explainer/README.md +137 -0
  310. package/plugin/skills/visual-explainer/SKILL.md +352 -0
  311. package/plugin/skills/visual-explainer/banner.png +0 -0
  312. package/plugin/skills/visual-explainer/package.json +11 -0
  313. package/plugin/skills/visual-explainer/prompts/diff-review.md +68 -0
  314. package/plugin/skills/visual-explainer/prompts/fact-check.md +63 -0
  315. package/plugin/skills/visual-explainer/prompts/generate-slides.md +18 -0
  316. package/plugin/skills/visual-explainer/prompts/generate-web-diagram.md +10 -0
  317. package/plugin/skills/visual-explainer/prompts/plan-review.md +86 -0
  318. package/plugin/skills/visual-explainer/prompts/project-recap.md +61 -0
  319. package/plugin/skills/visual-explainer/references/css-patterns.md +1188 -0
  320. package/plugin/skills/visual-explainer/references/libraries.md +470 -0
  321. package/plugin/skills/visual-explainer/references/responsive-nav.md +212 -0
  322. package/plugin/skills/visual-explainer/references/slide-patterns.md +1403 -0
  323. package/plugin/skills/visual-explainer/templates/architecture.html +596 -0
  324. package/plugin/skills/visual-explainer/templates/data-table.html +540 -0
  325. package/plugin/skills/visual-explainer/templates/mermaid-flowchart.html +435 -0
  326. package/plugin/skills/visual-explainer/templates/slide-deck.html +913 -0
  327. package/src/cli.ts +655 -0
  328. package/src/context/.gitkeep +0 -0
  329. package/src/context/codebase.ts +393 -0
  330. package/src/context/injector.ts +797 -0
  331. package/src/context/memory.ts +187 -0
  332. package/src/context/session-index.ts +327 -0
  333. package/src/context/session.ts +152 -0
  334. package/src/index.ts +47 -0
  335. package/src/ingestion/.gitkeep +0 -0
  336. package/src/ingestion/chunker.ts +277 -0
  337. package/src/ingestion/embedder.ts +167 -0
  338. package/src/ingestion/git-analyzer.ts +545 -0
  339. package/src/ingestion/indexer.ts +984 -0
  340. package/src/ingestion/markdown-chunker.ts +337 -0
  341. package/src/ingestion/markdown-knowledge.ts +175 -0
  342. package/src/ingestion/parser.ts +475 -0
  343. package/src/ingestion/watcher.ts +182 -0
  344. package/src/knowledge/.gitkeep +0 -0
  345. package/src/knowledge/hydrator.ts +246 -0
  346. package/src/knowledge/registry.ts +463 -0
  347. package/src/knowledge/search.ts +565 -0
  348. package/src/knowledge/store.ts +262 -0
  349. package/src/learning/.gitkeep +0 -0
  350. package/src/learning/confidence.ts +193 -0
  351. package/src/learning/patterns.ts +360 -0
  352. package/src/learning/trajectory.ts +268 -0
  353. package/src/memory/.gitkeep +0 -0
  354. package/src/memory/memory-compat.ts +233 -0
  355. package/src/memory/observation-store.ts +224 -0
  356. package/src/memory/session-tracker.ts +332 -0
  357. package/src/pipeline/.gitkeep +0 -0
  358. package/src/pipeline/engine.ts +1139 -0
  359. package/src/pipeline/events.ts +253 -0
  360. package/src/pipeline/parallel.ts +394 -0
  361. package/src/pipeline/state-machine.ts +199 -0
  362. package/src/query/.gitkeep +0 -0
  363. package/src/query/graph-queries.ts +262 -0
  364. package/src/query/hybrid-search.ts +337 -0
  365. package/src/query/intent-detector.ts +131 -0
  366. package/src/query/ranking.ts +161 -0
  367. package/src/server.ts +352 -0
  368. package/src/storage/.gitkeep +0 -0
  369. package/src/storage/falkordb-store.ts +388 -0
  370. package/src/storage/file-cache.ts +141 -0
  371. package/src/storage/interfaces.ts +201 -0
  372. package/src/storage/qdrant-store.ts +557 -0
  373. package/src/storage/schema.ts +139 -0
  374. package/src/storage/sqlite.ts +168 -0
  375. package/src/tools/.gitkeep +0 -0
  376. package/src/tools/collaboration-tools.ts +208 -0
  377. package/src/tools/context-tools.ts +493 -0
  378. package/src/tools/graph-tools.ts +295 -0
  379. package/src/tools/ingestion-tools.ts +122 -0
  380. package/src/tools/learning-tools.ts +181 -0
  381. package/src/tools/memory-tools.ts +234 -0
  382. package/src/tools/phase-tools.ts +1452 -0
  383. package/src/tools/pipeline-tools.ts +188 -0
  384. package/src/tools/registration-tools.ts +450 -0
  385. package/src/util/.gitkeep +0 -0
  386. package/src/util/circuit-breaker.ts +193 -0
  387. package/src/util/config.ts +177 -0
  388. package/src/util/logger.ts +53 -0
  389. package/src/util/token-counter.ts +52 -0
  390. package/src/util/types.ts +710 -0
  391. package/tests/context/.gitkeep +0 -0
  392. package/tests/integration/.gitkeep +0 -0
  393. package/tests/knowledge/.gitkeep +0 -0
  394. package/tests/learning/.gitkeep +0 -0
  395. package/tests/pipeline/.gitkeep +0 -0
  396. package/tests/tools/.gitkeep +0 -0
  397. package/tsconfig.json +21 -0
  398. package/vitest.config.ts +10 -0
  399. package/vscode-extension/.vscodeignore +7 -0
  400. package/vscode-extension/README.md +43 -0
  401. package/vscode-extension/out/edge-collector.js +274 -0
  402. package/vscode-extension/out/edge-collector.js.map +1 -0
  403. package/vscode-extension/out/extension.js +264 -0
  404. package/vscode-extension/out/extension.js.map +1 -0
  405. package/vscode-extension/out/forge-client.js +318 -0
  406. package/vscode-extension/out/forge-client.js.map +1 -0
  407. package/vscode-extension/package-lock.json +59 -0
  408. package/vscode-extension/package.json +71 -0
  409. package/vscode-extension/src/edge-collector.ts +320 -0
  410. package/vscode-extension/src/extension.ts +269 -0
  411. package/vscode-extension/src/forge-client.ts +364 -0
  412. package/vscode-extension/tsconfig.json +19 -0
@@ -0,0 +1,1188 @@
1
+ # CSS Patterns for Diagrams
2
+
3
+ Reusable patterns for layout, connectors, theming, and visual effects in self-contained HTML diagrams.
4
+
5
+ ## Theme Setup
6
+
7
+ Always define both light and dark palettes via custom properties. Start with whichever fits the chosen aesthetic, ensure both work.
8
+
9
+ ```css
10
+ :root {
11
+ --font-body: 'Outfit', system-ui, sans-serif;
12
+ --font-mono: 'Space Mono', 'SF Mono', Consolas, monospace;
13
+
14
+ --bg: #f8f9fa;
15
+ --surface: #ffffff;
16
+ --surface-elevated: #ffffff;
17
+ --border: rgba(0, 0, 0, 0.08);
18
+ --border-bright: rgba(0, 0, 0, 0.15);
19
+ --text: #1a1a2e;
20
+ --text-dim: #6b7280;
21
+ --accent: #0891b2;
22
+ --accent-dim: rgba(8, 145, 178, 0.1);
23
+ /* Semantic accents for diagram elements */
24
+ --node-a: #0891b2;
25
+ --node-a-dim: rgba(8, 145, 178, 0.1);
26
+ --node-b: #059669;
27
+ --node-b-dim: rgba(5, 150, 105, 0.1);
28
+ --node-c: #d97706;
29
+ --node-c-dim: rgba(217, 119, 6, 0.1);
30
+ }
31
+
32
+ @media (prefers-color-scheme: dark) {
33
+ :root {
34
+ --bg: #0d1117;
35
+ --surface: #161b22;
36
+ --surface-elevated: #1c2333;
37
+ --border: rgba(255, 255, 255, 0.06);
38
+ --border-bright: rgba(255, 255, 255, 0.12);
39
+ --text: #e6edf3;
40
+ --text-dim: #8b949e;
41
+ --accent: #22d3ee;
42
+ --accent-dim: rgba(34, 211, 238, 0.12);
43
+ --node-a: #22d3ee;
44
+ --node-a-dim: rgba(34, 211, 238, 0.12);
45
+ --node-b: #34d399;
46
+ --node-b-dim: rgba(52, 211, 153, 0.12);
47
+ --node-c: #fbbf24;
48
+ --node-c-dim: rgba(251, 191, 36, 0.12);
49
+ }
50
+ }
51
+ ```
52
+
53
+ ## Background Atmosphere
54
+
55
+ Flat backgrounds feel dead. Use subtle gradients or patterns.
56
+
57
+ ```css
58
+ /* Radial glow behind focal area */
59
+ body {
60
+ background: var(--bg);
61
+ background-image: radial-gradient(ellipse at 50% 0%, var(--accent-dim) 0%, transparent 60%);
62
+ }
63
+
64
+ /* Faint dot grid */
65
+ body {
66
+ background-color: var(--bg);
67
+ background-image: radial-gradient(circle, var(--border) 1px, transparent 1px);
68
+ background-size: 24px 24px;
69
+ }
70
+
71
+ /* Diagonal subtle lines */
72
+ body {
73
+ background-color: var(--bg);
74
+ background-image: repeating-linear-gradient(
75
+ -45deg, transparent, transparent 40px,
76
+ var(--border) 40px, var(--border) 41px
77
+ );
78
+ }
79
+
80
+ /* Gradient mesh (pick 2-3 positioned radials) */
81
+ body {
82
+ background: var(--bg);
83
+ background-image:
84
+ radial-gradient(at 20% 20%, var(--node-a-dim) 0%, transparent 50%),
85
+ radial-gradient(at 80% 60%, var(--node-b-dim) 0%, transparent 50%);
86
+ }
87
+ ```
88
+
89
+ ## Section / Card Components
90
+
91
+ The fundamental building block. A colored card representing a system component, pipeline step, or data entity.
92
+
93
+ **IMPORTANT: Never use `.node` as a CSS class name.** Mermaid.js internally uses `.node` on its SVG `<g>` elements with `transform: translate(x, y)` for positioning. Any page-level `.node` styles (hover transforms, box-shadows, transitions) will leak into Mermaid diagrams and break their layout. Use `.ve-card` instead (namespaced to avoid collisions with CSS frameworks like Bootstrap/Tailwind that also use `.card`).
94
+
95
+ ```css
96
+ .ve-card {
97
+ background: var(--surface);
98
+ border: 1px solid var(--border);
99
+ border-radius: 10px;
100
+ padding: 16px 20px;
101
+ position: relative;
102
+ }
103
+
104
+ /* Colored accent border (left or top) */
105
+ .ve-card--accent-a {
106
+ border-left: 3px solid var(--node-a);
107
+ }
108
+
109
+ /* --- Depth tiers: vary card depth to signal importance --- */
110
+
111
+ /* Elevated: KPIs, key sections, anything that should pop */
112
+ .ve-card--elevated {
113
+ background: var(--surface-elevated);
114
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04);
115
+ }
116
+
117
+ /* Recessed: code blocks, secondary content, detail panels */
118
+ .ve-card--recessed {
119
+ background: color-mix(in srgb, var(--bg) 70%, var(--surface) 30%);
120
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.06);
121
+ border-color: var(--border);
122
+ }
123
+
124
+ /* Hero: executive summaries, focal elements — demands attention */
125
+ .ve-card--hero {
126
+ background: color-mix(in srgb, var(--surface) 92%, var(--accent) 8%);
127
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08), 0 1px 3px rgba(0, 0, 0, 0.04);
128
+ border-color: color-mix(in srgb, var(--border) 50%, var(--accent) 50%);
129
+ }
130
+
131
+ /* Glass: special-occasion overlay effect (use sparingly) */
132
+ .ve-card--glass {
133
+ background: color-mix(in srgb, var(--surface) 60%, transparent 40%);
134
+ backdrop-filter: blur(12px);
135
+ -webkit-backdrop-filter: blur(12px);
136
+ border-color: rgba(255, 255, 255, 0.1);
137
+ }
138
+
139
+ /* Section label (monospace, uppercase, small) */
140
+ .ve-card__label {
141
+ font-family: var(--font-mono);
142
+ font-size: 10px;
143
+ font-weight: 600;
144
+ text-transform: uppercase;
145
+ letter-spacing: 1.5px;
146
+ color: var(--node-a);
147
+ margin-bottom: 10px;
148
+ display: flex;
149
+ align-items: center;
150
+ gap: 8px;
151
+ }
152
+
153
+ /* Colored dot indicator */
154
+ .ve-card__label::before {
155
+ content: '';
156
+ width: 8px;
157
+ height: 8px;
158
+ border-radius: 50%;
159
+ background: currentColor;
160
+ }
161
+ ```
162
+
163
+ ## Overflow Protection
164
+
165
+ Grid and flex children default to `min-width: auto`, which prevents them from shrinking below their content width. Long text, inline code badges, and non-wrapping elements will blow out containers.
166
+
167
+ ### Global rules
168
+
169
+ ```css
170
+ /* Every grid/flex child must be able to shrink */
171
+ .grid > *, .flex > *,
172
+ [style*="display: grid"] > *,
173
+ [style*="display: flex"] > * {
174
+ min-width: 0;
175
+ }
176
+
177
+ /* Long text wraps instead of overflowing */
178
+ body {
179
+ overflow-wrap: break-word;
180
+ }
181
+ ```
182
+
183
+ ### Side-by-side comparison panels
184
+
185
+ ```css
186
+ .comparison {
187
+ display: grid;
188
+ grid-template-columns: 1fr 1fr;
189
+ gap: 16px;
190
+ }
191
+
192
+ .comparison > * {
193
+ min-width: 0;
194
+ overflow-wrap: break-word;
195
+ }
196
+
197
+ @media (max-width: 768px) {
198
+ .comparison { grid-template-columns: 1fr; }
199
+ }
200
+ ```
201
+
202
+ ### Never use `display: flex` on `<li>` for marker characters
203
+
204
+ Using `display: flex` on a list item to position a `::before` marker creates an anonymous flex item for the remaining text content. That anonymous flex item gets `min-width: auto` and you **cannot** set `min-width: 0` on anonymous boxes. Lines with many inline `<code>` badges will overflow their container with no CSS fix possible.
205
+
206
+ Use absolute positioning for markers instead:
207
+
208
+ ```css
209
+ /* WRONG — causes overflow with inline code badges */
210
+ li {
211
+ display: flex;
212
+ align-items: baseline;
213
+ gap: 6px;
214
+ }
215
+ li::before {
216
+ content: '›';
217
+ flex-shrink: 0;
218
+ }
219
+
220
+ /* RIGHT — text wraps normally */
221
+ li {
222
+ padding-left: 14px;
223
+ position: relative;
224
+ }
225
+ li::before {
226
+ content: '›';
227
+ position: absolute;
228
+ left: 0;
229
+ }
230
+ ```
231
+
232
+ ## Mermaid Zoom Controls
233
+
234
+ Mermaid diagrams are often too small to read comfortably, especially complex flowcharts and sequence diagrams. Add zoom controls to every `.mermaid-wrap` container.
235
+
236
+ **Centering fix.** Mermaid SVGs render at a fixed size and default to the top-left of their container, leaving dead space in larger containers. Always add `display: flex; align-items: center; justify-content: center;` to `.mermaid-wrap` so the SVG centers regardless of container size. Use `transform-origin: center center` so zoom radiates from the middle.
237
+
238
+ **Small diagrams in slides.** If a diagram has fewer than ~7 nodes with no branching, it will render tiny in a full-viewport slide container. For simple linear flows (A → B → C → D), use CSS pipeline cards instead of Mermaid — see `slide-patterns.md` "CSS Pipeline Slide." Reserve Mermaid for complex graphs where automatic edge routing is actually needed.
239
+
240
+ ### CSS
241
+
242
+ ```css
243
+ .mermaid-wrap {
244
+ position: relative;
245
+ background: var(--surface);
246
+ border: 1px solid var(--border);
247
+ border-radius: 12px;
248
+ padding: 32px 24px;
249
+ overflow: auto;
250
+ display: flex;
251
+ align-items: center;
252
+ justify-content: center;
253
+ scrollbar-width: thin;
254
+ scrollbar-color: var(--border) transparent;
255
+ }
256
+ .mermaid-wrap::-webkit-scrollbar { width: 6px; height: 6px; }
257
+ .mermaid-wrap::-webkit-scrollbar-track { background: transparent; }
258
+ .mermaid-wrap::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
259
+ .mermaid-wrap::-webkit-scrollbar-thumb:hover { background: var(--text-dim); }
260
+
261
+ .mermaid-wrap .mermaid {
262
+ transition: transform 0.2s ease;
263
+ transform-origin: center center;
264
+ }
265
+
266
+ .zoom-controls {
267
+ position: absolute;
268
+ top: 8px;
269
+ right: 8px;
270
+ display: flex;
271
+ gap: 2px;
272
+ z-index: 10;
273
+ background: var(--surface);
274
+ border: 1px solid var(--border);
275
+ border-radius: 6px;
276
+ padding: 2px;
277
+ }
278
+
279
+ .zoom-controls button {
280
+ width: 28px;
281
+ height: 28px;
282
+ border: none;
283
+ background: transparent;
284
+ color: var(--text-dim);
285
+ font-family: var(--font-mono);
286
+ font-size: 14px;
287
+ cursor: pointer;
288
+ border-radius: 4px;
289
+ display: flex;
290
+ align-items: center;
291
+ justify-content: center;
292
+ transition: background 0.15s ease, color 0.15s ease;
293
+ }
294
+
295
+ .zoom-controls button:hover {
296
+ background: var(--border);
297
+ color: var(--text);
298
+ }
299
+
300
+ .mermaid-wrap.is-zoomed { cursor: grab; }
301
+ .mermaid-wrap.is-panning { cursor: grabbing; user-select: none; }
302
+
303
+ @media (prefers-reduced-motion: reduce) {
304
+ .mermaid-wrap .mermaid { transition: none; }
305
+ }
306
+ ```
307
+
308
+ ### HTML
309
+
310
+ ```html
311
+ <div class="mermaid-wrap">
312
+ <div class="zoom-controls">
313
+ <button onclick="zoomDiagram(this, 1.2)" title="Zoom in">+</button>
314
+ <button onclick="zoomDiagram(this, 0.8)" title="Zoom out">&minus;</button>
315
+ <button onclick="resetZoom(this)" title="Reset zoom">&#8634;</button>
316
+ </div>
317
+ <pre class="mermaid">
318
+ graph TD
319
+ A --> B
320
+ </pre>
321
+ </div>
322
+ ```
323
+
324
+ ### JavaScript
325
+
326
+ Add once at the end of the page. Handles button clicks and scroll-to-zoom on all `.mermaid-wrap` containers:
327
+
328
+ ```javascript
329
+ function updateZoomState(wrap) {
330
+ var target = wrap.querySelector('.mermaid');
331
+ var zoom = parseFloat(target.dataset.zoom || '1');
332
+ wrap.classList.toggle('is-zoomed', zoom > 1);
333
+ }
334
+
335
+ function zoomDiagram(btn, factor) {
336
+ var wrap = btn.closest('.mermaid-wrap');
337
+ var target = wrap.querySelector('.mermaid');
338
+ var current = parseFloat(target.dataset.zoom || '1');
339
+ var next = Math.min(Math.max(current * factor, 0.3), 5);
340
+ target.dataset.zoom = next;
341
+ target.style.transform = 'scale(' + next + ')';
342
+ updateZoomState(wrap);
343
+ }
344
+
345
+ function resetZoom(btn) {
346
+ var wrap = btn.closest('.mermaid-wrap');
347
+ var target = wrap.querySelector('.mermaid');
348
+ target.dataset.zoom = '1';
349
+ target.style.transform = 'scale(1)';
350
+ updateZoomState(wrap);
351
+ }
352
+
353
+ document.querySelectorAll('.mermaid-wrap').forEach(function(wrap) {
354
+ // Ctrl/Cmd + scroll to zoom
355
+ wrap.addEventListener('wheel', function(e) {
356
+ if (!e.ctrlKey && !e.metaKey) return;
357
+ e.preventDefault();
358
+ var target = wrap.querySelector('.mermaid');
359
+ var current = parseFloat(target.dataset.zoom || '1');
360
+ var factor = e.deltaY < 0 ? 1.1 : 0.9;
361
+ var next = Math.min(Math.max(current * factor, 0.3), 5);
362
+ target.dataset.zoom = next;
363
+ target.style.transform = 'scale(' + next + ')';
364
+ updateZoomState(wrap);
365
+ }, { passive: false });
366
+
367
+ // Click-and-drag to pan when zoomed
368
+ var startX, startY, scrollL, scrollT;
369
+ wrap.addEventListener('mousedown', function(e) {
370
+ if (e.target.closest('.zoom-controls')) return;
371
+ var target = wrap.querySelector('.mermaid');
372
+ if (parseFloat(target.dataset.zoom || '1') <= 1) return;
373
+ wrap.classList.add('is-panning');
374
+ startX = e.clientX;
375
+ startY = e.clientY;
376
+ scrollL = wrap.scrollLeft;
377
+ scrollT = wrap.scrollTop;
378
+ });
379
+ window.addEventListener('mousemove', function(e) {
380
+ if (!wrap.classList.contains('is-panning')) return;
381
+ wrap.scrollLeft = scrollL - (e.clientX - startX);
382
+ wrap.scrollTop = scrollT - (e.clientY - startY);
383
+ });
384
+ window.addEventListener('mouseup', function() {
385
+ wrap.classList.remove('is-panning');
386
+ });
387
+ });
388
+ ```
389
+
390
+ Scroll-to-zoom requires Ctrl/Cmd+scroll to avoid hijacking normal page scroll. Click-and-drag panning activates only when zoomed in (zoom > 1). Cursor changes to `grab`/`grabbing` to signal the behavior. The zoom range is capped at 0.3x–5x.
391
+
392
+ ## Grid Layouts
393
+
394
+ ### Architecture Diagram (2-column with sidebar)
395
+ ```css
396
+ .arch-grid {
397
+ display: grid;
398
+ grid-template-columns: 260px 1fr;
399
+ grid-template-rows: auto;
400
+ gap: 20px;
401
+ max-width: 1100px;
402
+ margin: 0 auto;
403
+ }
404
+
405
+ .arch-grid__sidebar { grid-column: 1; }
406
+ .arch-grid__main { grid-column: 2; }
407
+ .arch-grid__full { grid-column: 1 / -1; }
408
+ ```
409
+
410
+ ### Pipeline (horizontal steps)
411
+ ```css
412
+ .pipeline {
413
+ display: flex;
414
+ align-items: stretch;
415
+ gap: 0;
416
+ overflow-x: auto;
417
+ padding-bottom: 8px;
418
+ }
419
+
420
+ .pipeline__step {
421
+ min-width: 130px;
422
+ flex-shrink: 0;
423
+ }
424
+
425
+ .pipeline__arrow {
426
+ display: flex;
427
+ align-items: center;
428
+ padding: 0 4px;
429
+ color: var(--border-bright);
430
+ font-size: 18px;
431
+ flex-shrink: 0;
432
+ }
433
+
434
+ /* Parallel branch within a pipeline */
435
+ .pipeline__parallel {
436
+ display: flex;
437
+ flex-direction: column;
438
+ gap: 6px;
439
+ }
440
+ ```
441
+
442
+ ### Card Grid (dashboard / metrics)
443
+ ```css
444
+ .card-grid {
445
+ display: grid;
446
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
447
+ gap: 16px;
448
+ }
449
+ ```
450
+
451
+ ### Data Tables
452
+
453
+ Use real `<table>` elements for tabular data. Wrap in a scrollable container for wide tables.
454
+
455
+ ```css
456
+ /* Scrollable wrapper for wide tables */
457
+ .table-wrap {
458
+ background: var(--surface);
459
+ border: 1px solid var(--border);
460
+ border-radius: 12px;
461
+ overflow: hidden;
462
+ }
463
+
464
+ .table-scroll {
465
+ overflow-x: auto;
466
+ -webkit-overflow-scrolling: touch;
467
+ }
468
+
469
+ /* Base table */
470
+ .data-table {
471
+ width: 100%;
472
+ border-collapse: collapse;
473
+ font-size: 13px;
474
+ line-height: 1.5;
475
+ }
476
+
477
+ /* Header */
478
+ .data-table thead {
479
+ position: sticky;
480
+ top: 0;
481
+ z-index: 2;
482
+ }
483
+
484
+ .data-table th {
485
+ background: var(--surface-elevated, var(--surface2, var(--surface)));
486
+ font-family: var(--font-mono);
487
+ font-size: 11px;
488
+ font-weight: 600;
489
+ text-transform: uppercase;
490
+ letter-spacing: 1px;
491
+ color: var(--text-dim);
492
+ text-align: left;
493
+ padding: 12px 16px;
494
+ border-bottom: 2px solid var(--border-bright);
495
+ white-space: nowrap;
496
+ }
497
+
498
+ /* Cells */
499
+ .data-table td {
500
+ padding: 12px 16px;
501
+ border-bottom: 1px solid var(--border);
502
+ vertical-align: top;
503
+ color: var(--text);
504
+ }
505
+
506
+ /* Let text-heavy columns wrap naturally */
507
+ .data-table .wide {
508
+ min-width: 200px;
509
+ max-width: 500px;
510
+ }
511
+
512
+ /* Right-align numeric columns */
513
+ .data-table td.num,
514
+ .data-table th.num {
515
+ text-align: right;
516
+ font-variant-numeric: tabular-nums;
517
+ font-family: var(--font-mono);
518
+ }
519
+
520
+ /* Alternating rows */
521
+ .data-table tbody tr:nth-child(even) {
522
+ background: var(--accent-dim);
523
+ }
524
+
525
+ /* Row hover */
526
+ .data-table tbody tr {
527
+ transition: background 0.15s ease;
528
+ }
529
+
530
+ .data-table tbody tr:hover {
531
+ background: var(--border);
532
+ }
533
+
534
+ /* Last row: no bottom border (container handles it) */
535
+ .data-table tbody tr:last-child td {
536
+ border-bottom: none;
537
+ }
538
+
539
+ /* Code inside cells */
540
+ .data-table code {
541
+ font-family: var(--font-mono);
542
+ font-size: 11px;
543
+ background: var(--accent-dim);
544
+ color: var(--accent);
545
+ padding: 1px 5px;
546
+ border-radius: 3px;
547
+ }
548
+
549
+ /* Secondary detail text */
550
+ .data-table small {
551
+ display: block;
552
+ color: var(--text-dim);
553
+ font-size: 11px;
554
+ margin-top: 2px;
555
+ }
556
+ ```
557
+
558
+ #### Status Indicators
559
+
560
+ Styled spans for match/gap/warning states. Never use emoji.
561
+
562
+ ```css
563
+ .status {
564
+ display: inline-flex;
565
+ align-items: center;
566
+ gap: 6px;
567
+ font-family: var(--font-mono);
568
+ font-size: 11px;
569
+ font-weight: 500;
570
+ padding: 3px 10px;
571
+ border-radius: 6px;
572
+ white-space: nowrap;
573
+ }
574
+
575
+ .status--match {
576
+ background: var(--green-dim, rgba(5, 150, 105, 0.1));
577
+ color: var(--green, #059669);
578
+ }
579
+
580
+ .status--gap {
581
+ background: var(--red-dim, rgba(239, 68, 68, 0.1));
582
+ color: var(--red, #ef4444);
583
+ }
584
+
585
+ .status--warn {
586
+ background: var(--orange-dim, rgba(217, 119, 6, 0.1));
587
+ color: var(--orange, #d97706);
588
+ }
589
+
590
+ .status--info {
591
+ background: var(--accent-dim);
592
+ color: var(--accent);
593
+ }
594
+
595
+ /* Dot variant (compact, no text) */
596
+ .status-dot {
597
+ width: 8px;
598
+ height: 8px;
599
+ border-radius: 50%;
600
+ display: inline-block;
601
+ }
602
+
603
+ .status-dot--match { background: var(--green, #059669); }
604
+ .status-dot--gap { background: var(--red, #ef4444); }
605
+ .status-dot--warn { background: var(--orange, #d97706); }
606
+ ```
607
+
608
+ Usage in table cells:
609
+ ```html
610
+ <td><span class="status status--match">Match</span></td>
611
+ <td><span class="status status--gap">Gap</span></td>
612
+ <td><span class="status status--warn">Partial</span></td>
613
+ ```
614
+
615
+ #### Table Summary Row
616
+
617
+ For totals, counts, or aggregate status at the bottom:
618
+
619
+ ```css
620
+ .data-table tfoot td {
621
+ background: var(--surface-elevated, var(--surface2, var(--surface)));
622
+ font-weight: 600;
623
+ font-size: 12px;
624
+ border-top: 2px solid var(--border-bright);
625
+ border-bottom: none;
626
+ padding: 12px 16px;
627
+ }
628
+ ```
629
+
630
+ #### Sticky First Column (for very wide tables)
631
+
632
+ ```css
633
+ .data-table th:first-child,
634
+ .data-table td:first-child {
635
+ position: sticky;
636
+ left: 0;
637
+ z-index: 1;
638
+ background: var(--surface);
639
+ }
640
+
641
+ .data-table tbody tr:nth-child(even) td:first-child {
642
+ background: color-mix(in srgb, var(--surface) 95%, var(--accent) 5%);
643
+ }
644
+ ```
645
+
646
+ ## Connectors
647
+
648
+ ### CSS Arrow (vertical, between stacked sections)
649
+ ```css
650
+ .flow-arrow {
651
+ display: flex;
652
+ justify-content: center;
653
+ align-items: center;
654
+ gap: 8px;
655
+ color: var(--text-dim);
656
+ font-family: var(--font-mono);
657
+ font-size: 12px;
658
+ padding: 6px 0;
659
+ }
660
+
661
+ /* Down arrow via SVG icon */
662
+ .flow-arrow svg {
663
+ width: 20px;
664
+ height: 20px;
665
+ fill: none;
666
+ stroke: var(--border-bright);
667
+ stroke-width: 2;
668
+ stroke-linecap: round;
669
+ stroke-linejoin: round;
670
+ }
671
+ ```
672
+
673
+ Down arrow SVG (reuse inline):
674
+ ```html
675
+ <svg viewBox="0 0 20 20"><path d="M10 4 L10 16 M6 12 L10 16 L14 12"/></svg>
676
+ ```
677
+
678
+ ### CSS Arrow (horizontal, between inline steps)
679
+ Use `::after` or a literal arrow character:
680
+ ```css
681
+ .h-arrow::after {
682
+ content: '→';
683
+ color: var(--border-bright);
684
+ font-size: 18px;
685
+ padding: 0 4px;
686
+ }
687
+ ```
688
+
689
+ ### SVG Curved Connector (between arbitrary nodes)
690
+ For connections that aren't simple vertical/horizontal, use an absolutely positioned SVG overlay:
691
+ ```html
692
+ <svg class="connectors" style="position:absolute;inset:0;width:100%;height:100%;pointer-events:none;">
693
+ <path d="M 150,100 C 150,200 350,100 350,200" fill="none" stroke="var(--accent)" stroke-width="1.5" stroke-dasharray="4 3"/>
694
+ <!-- Arrowhead -->
695
+ <polygon points="348,195 352,205 356,195" fill="var(--accent)"/>
696
+ </svg>
697
+ ```
698
+
699
+ Position the parent container as `position: relative` to scope the SVG overlay.
700
+
701
+ ## Animations
702
+
703
+ ### Staggered Fade-In on Load
704
+
705
+ Define the keyframe once, then stagger via a `--i` CSS variable set per element. This approach works regardless of DOM nesting or interleaved non-animated elements (unlike `nth-child` which breaks when siblings aren't all the same type).
706
+
707
+ ```css
708
+ @keyframes fadeUp {
709
+ from { opacity: 0; transform: translateY(12px); }
710
+ to { opacity: 1; transform: translateY(0); }
711
+ }
712
+
713
+ .ve-card {
714
+ animation: fadeUp 0.4s ease-out both;
715
+ animation-delay: calc(var(--i, 0) * 0.05s);
716
+ }
717
+ ```
718
+
719
+ Set `--i` per element in the HTML to control stagger order:
720
+
721
+ ```html
722
+ <div class="ve-card" style="--i: 0">First</div>
723
+ <div class="connector">...</div>
724
+ <div class="ve-card" style="--i: 1">Second</div>
725
+ <div class="connector">...</div>
726
+ <div class="ve-card" style="--i: 2">Third</div>
727
+ ```
728
+
729
+ ### Hover Lift
730
+ ```css
731
+ .ve-card {
732
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
733
+ }
734
+
735
+ .ve-card:hover {
736
+ transform: translateY(-2px);
737
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
738
+ }
739
+ ```
740
+
741
+ ### Scale-Fade (for KPI cards, badges, status indicators)
742
+
743
+ ```css
744
+ @keyframes fadeScale {
745
+ from { opacity: 0; transform: scale(0.92); }
746
+ to { opacity: 1; transform: scale(1); }
747
+ }
748
+
749
+ .kpi-card {
750
+ animation: fadeScale 0.35s ease-out both;
751
+ animation-delay: calc(var(--i, 0) * 0.06s);
752
+ }
753
+ ```
754
+
755
+ ### SVG Draw-In (for connectors, progress rings, path elements)
756
+
757
+ ```css
758
+ @keyframes drawIn {
759
+ from { stroke-dashoffset: var(--path-length); }
760
+ to { stroke-dashoffset: 0; }
761
+ }
762
+
763
+ /* Set --path-length to the path's getTotalLength() value */
764
+ .connector path {
765
+ stroke-dasharray: var(--path-length);
766
+ animation: drawIn 0.8s ease-in-out both;
767
+ animation-delay: calc(var(--i, 0) * 0.1s);
768
+ }
769
+ ```
770
+
771
+ ### CSS Counter (for hero numbers without JS)
772
+
773
+ Uses `@property` to animate a custom property as an integer, then display it via `counter()`. No JS required. Falls back to showing the final value immediately in browsers without `@property` support.
774
+
775
+ ```css
776
+ @property --count {
777
+ syntax: '<integer>';
778
+ initial-value: 0;
779
+ inherits: false;
780
+ }
781
+
782
+ @keyframes countUp {
783
+ to { --count: var(--target); }
784
+ }
785
+
786
+ .kpi-card__value--animated {
787
+ --target: 247;
788
+ counter-reset: val var(--count);
789
+ animation: countUp 1.2s ease-out forwards;
790
+ }
791
+
792
+ .kpi-card__value--animated::after {
793
+ content: counter(val);
794
+ }
795
+ ```
796
+
797
+ ### Choreography
798
+
799
+ Don't use the same animation for everything. Mix types by element role, with easing stagger (fast-then-slow, not linear):
800
+
801
+ - **Cards**: `fadeUp` — the default entrance, reliable and subtle
802
+ - **KPI / badges**: `fadeScale` — scale draws the eye to important numbers
803
+ - **SVG connectors**: `drawIn` — reveals flow direction, pairs with card stagger
804
+ - **Hero numbers**: `countUp` — counting motion signals "this number matters"
805
+ - **Stagger timing**: `calc(var(--i) * 0.06s)` with lower `--i` values on important elements so they appear first
806
+
807
+ ### Respect Reduced Motion
808
+ ```css
809
+ @media (prefers-reduced-motion: reduce) {
810
+ *, *::before, *::after {
811
+ animation-duration: 0.01ms !important;
812
+ animation-iteration-count: 1 !important;
813
+ transition-duration: 0.01ms !important;
814
+ }
815
+ }
816
+ ```
817
+
818
+ ## Sparklines and Simple Charts (Pure SVG)
819
+
820
+ For simple inline visualizations without a library:
821
+
822
+ ```html
823
+ <!-- Sparkline -->
824
+ <svg viewBox="0 0 100 30" style="width:100px;height:30px;">
825
+ <polyline points="0,25 15,20 30,22 45,10 60,15 75,5 90,12 100,8"
826
+ fill="none" stroke="var(--accent)" stroke-width="1.5" stroke-linecap="round"/>
827
+ </svg>
828
+
829
+ <!-- Progress bar -->
830
+ <div style="height:6px;background:var(--border);border-radius:3px;overflow:hidden;">
831
+ <div style="height:100%;width:72%;background:var(--accent);border-radius:3px;"></div>
832
+ </div>
833
+ ```
834
+
835
+ ## Responsive Breakpoint
836
+
837
+ Include a single breakpoint for narrow viewports:
838
+
839
+ ```css
840
+ @media (max-width: 768px) {
841
+ .arch-grid { grid-template-columns: 1fr; }
842
+ .pipeline { flex-wrap: wrap; gap: 8px; }
843
+ .pipeline__arrow { display: none; }
844
+ body { padding: 16px; }
845
+ }
846
+ ```
847
+
848
+ ## Badges and Tags
849
+
850
+ Small inline labels for categorizing elements:
851
+
852
+ ```css
853
+ .tag {
854
+ font-family: var(--font-mono);
855
+ font-size: 10px;
856
+ font-weight: 500;
857
+ padding: 2px 7px;
858
+ border-radius: 4px;
859
+ background: var(--node-a-dim);
860
+ color: var(--node-a);
861
+ }
862
+ ```
863
+
864
+ ## Lists Inside Nodes
865
+
866
+ For tool listings, feature lists, table columns:
867
+
868
+ ```css
869
+ .node-list {
870
+ list-style: none;
871
+ padding: 0;
872
+ margin: 0;
873
+ font-size: 12px;
874
+ line-height: 1.8;
875
+ }
876
+
877
+ .node-list li {
878
+ padding-left: 14px;
879
+ position: relative;
880
+ }
881
+
882
+ .node-list li::before {
883
+ content: '›';
884
+ color: var(--text-dim);
885
+ font-weight: 600;
886
+ position: absolute;
887
+ left: 0;
888
+ }
889
+
890
+ .node-list code {
891
+ font-family: var(--font-mono);
892
+ font-size: 11px;
893
+ background: var(--accent-dim);
894
+ color: var(--accent);
895
+ padding: 1px 5px;
896
+ border-radius: 3px;
897
+ }
898
+ ```
899
+
900
+ ## KPI / Metric Cards
901
+
902
+ Large hero number with trend indicator and label. For dashboards, review summaries, and impact sections.
903
+
904
+ ```css
905
+ .kpi-row {
906
+ display: grid;
907
+ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
908
+ gap: 16px;
909
+ }
910
+
911
+ .kpi-card {
912
+ background: var(--surface-elevated);
913
+ border: 1px solid var(--border);
914
+ border-radius: 10px;
915
+ padding: 20px;
916
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
917
+ }
918
+
919
+ .kpi-card__value {
920
+ font-size: 36px;
921
+ font-weight: 700;
922
+ letter-spacing: -1px;
923
+ line-height: 1.1;
924
+ font-variant-numeric: tabular-nums;
925
+ }
926
+
927
+ .kpi-card__label {
928
+ font-family: var(--font-mono);
929
+ font-size: 10px;
930
+ font-weight: 600;
931
+ text-transform: uppercase;
932
+ letter-spacing: 1.5px;
933
+ color: var(--text-dim);
934
+ margin-top: 6px;
935
+ }
936
+
937
+ .kpi-card__trend {
938
+ font-family: var(--font-mono);
939
+ font-size: 12px;
940
+ margin-top: 4px;
941
+ }
942
+
943
+ .kpi-card__trend--up { color: var(--node-b, #059669); }
944
+ .kpi-card__trend--down { color: var(--red, #ef4444); }
945
+ ```
946
+
947
+ ```html
948
+ <div class="kpi-row">
949
+ <div class="kpi-card">
950
+ <div class="kpi-card__value">247</div>
951
+ <div class="kpi-card__label">Lines Added</div>
952
+ <div class="kpi-card__trend kpi-card__trend--up">+34%</div>
953
+ </div>
954
+ <!-- ... more cards -->
955
+ </div>
956
+ ```
957
+
958
+ ## Before / After Panels
959
+
960
+ Two-column comparison with diff-colored headers. For review pages, migration docs, and feature comparisons.
961
+
962
+ ```css
963
+ .diff-panels {
964
+ display: grid;
965
+ grid-template-columns: 1fr 1fr;
966
+ gap: 0;
967
+ border: 1px solid var(--border);
968
+ border-radius: 10px;
969
+ overflow: hidden;
970
+ }
971
+
972
+ .diff-panels > * { min-width: 0; overflow-wrap: break-word; }
973
+
974
+ .diff-panel__header {
975
+ font-family: var(--font-mono);
976
+ font-size: 11px;
977
+ font-weight: 600;
978
+ text-transform: uppercase;
979
+ letter-spacing: 1px;
980
+ padding: 10px 16px;
981
+ }
982
+
983
+ .diff-panel__header--before {
984
+ background: var(--red-dim, rgba(239, 68, 68, 0.08));
985
+ color: var(--red, #ef4444);
986
+ border-bottom: 2px solid var(--red, #ef4444);
987
+ }
988
+
989
+ .diff-panel__header--after {
990
+ background: var(--green-dim, rgba(5, 150, 105, 0.08));
991
+ color: var(--green, #059669);
992
+ border-bottom: 2px solid var(--green, #059669);
993
+ }
994
+
995
+ .diff-panel__body {
996
+ padding: 16px;
997
+ background: var(--surface);
998
+ font-size: 13px;
999
+ line-height: 1.6;
1000
+ }
1001
+
1002
+ /* Highlight changed items within a panel */
1003
+ .diff-changed {
1004
+ background: var(--accent-dim);
1005
+ border-radius: 3px;
1006
+ padding: 0 3px;
1007
+ }
1008
+
1009
+ @media (max-width: 768px) {
1010
+ .diff-panels { grid-template-columns: 1fr; }
1011
+ }
1012
+ ```
1013
+
1014
+ ```html
1015
+ <div class="diff-panels">
1016
+ <div class="diff-panel__header diff-panel__header--before">Before</div>
1017
+ <div class="diff-panel__header diff-panel__header--after">After</div>
1018
+ <div class="diff-panel__body">Previous implementation...</div>
1019
+ <div class="diff-panel__body">New implementation...</div>
1020
+ </div>
1021
+ ```
1022
+
1023
+ ## Collapsible Sections
1024
+
1025
+ Native `<details>/<summary>` with styled disclosure. Zero JS, accessible. For lower-priority content: file maps, decision logs, reference sections.
1026
+
1027
+ ```css
1028
+ details.collapsible {
1029
+ border: 1px solid var(--border);
1030
+ border-radius: 10px;
1031
+ overflow: hidden;
1032
+ }
1033
+
1034
+ details.collapsible summary {
1035
+ padding: 14px 20px;
1036
+ background: var(--surface);
1037
+ font-family: var(--font-mono);
1038
+ font-size: 12px;
1039
+ font-weight: 600;
1040
+ cursor: pointer;
1041
+ list-style: none;
1042
+ display: flex;
1043
+ align-items: center;
1044
+ gap: 8px;
1045
+ color: var(--text);
1046
+ transition: background 0.15s ease;
1047
+ }
1048
+
1049
+ details.collapsible summary:hover {
1050
+ background: var(--surface-elevated, var(--surface));
1051
+ }
1052
+
1053
+ details.collapsible summary::-webkit-details-marker { display: none; }
1054
+
1055
+ /* Chevron indicator */
1056
+ details.collapsible summary::before {
1057
+ content: '▸';
1058
+ font-size: 11px;
1059
+ color: var(--text-dim);
1060
+ transition: transform 0.15s ease;
1061
+ }
1062
+
1063
+ details.collapsible[open] summary::before {
1064
+ transform: rotate(90deg);
1065
+ }
1066
+
1067
+ details.collapsible .collapsible__body {
1068
+ padding: 16px 20px;
1069
+ border-top: 1px solid var(--border);
1070
+ font-size: 13px;
1071
+ line-height: 1.6;
1072
+ }
1073
+ ```
1074
+
1075
+ ```html
1076
+ <details class="collapsible">
1077
+ <summary>File Map (14 files changed)</summary>
1078
+ <div class="collapsible__body">
1079
+ <!-- content here -->
1080
+ </div>
1081
+ </details>
1082
+ ```
1083
+
1084
+ ## Generated Images
1085
+
1086
+ For AI-generated illustrations embedded as base64 data URIs via `surf gemini --generate-image`. Use sparingly — hero banners, conceptual illustrations, educational diagrams, decorative accents.
1087
+
1088
+ ### Hero Banner
1089
+
1090
+ Full-width image cropped to a fixed height with a gradient fade into the page background. Place at the top of the page before the title, or between the title and the first content section.
1091
+
1092
+ ```css
1093
+ .hero-img-wrap {
1094
+ position: relative;
1095
+ border-radius: 12px;
1096
+ overflow: hidden;
1097
+ margin-bottom: 24px;
1098
+ }
1099
+
1100
+ .hero-img-wrap img {
1101
+ width: 100%;
1102
+ height: 240px;
1103
+ object-fit: cover;
1104
+ display: block;
1105
+ }
1106
+
1107
+ /* Gradient fade into page background */
1108
+ .hero-img-wrap::after {
1109
+ content: '';
1110
+ position: absolute;
1111
+ bottom: 0;
1112
+ left: 0;
1113
+ right: 0;
1114
+ height: 50%;
1115
+ background: linear-gradient(to top, var(--bg), transparent);
1116
+ pointer-events: none;
1117
+ }
1118
+ ```
1119
+
1120
+ ```html
1121
+ <div class="hero-img-wrap">
1122
+ <img src="data:image/png;base64,..." alt="Descriptive alt text">
1123
+ </div>
1124
+ ```
1125
+
1126
+ Generate with `--aspect-ratio 16:9` for hero banners.
1127
+
1128
+ ### Inline Illustration
1129
+
1130
+ Centered image with border, shadow, and optional caption. Use within content sections for conceptual or educational illustrations.
1131
+
1132
+ ```css
1133
+ .illus {
1134
+ text-align: center;
1135
+ margin: 24px 0;
1136
+ }
1137
+
1138
+ .illus img {
1139
+ max-width: 480px;
1140
+ width: 100%;
1141
+ border-radius: 10px;
1142
+ border: 1px solid var(--border);
1143
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
1144
+ }
1145
+
1146
+ .illus figcaption {
1147
+ font-family: var(--font-mono);
1148
+ font-size: 11px;
1149
+ color: var(--text-dim);
1150
+ margin-top: 8px;
1151
+ }
1152
+ ```
1153
+
1154
+ ```html
1155
+ <figure class="illus">
1156
+ <img src="data:image/png;base64,..." alt="Descriptive alt text">
1157
+ <figcaption>How the message queue routes events between services</figcaption>
1158
+ </figure>
1159
+ ```
1160
+
1161
+ Generate with `--aspect-ratio 1:1` or `--aspect-ratio 4:3` for inline illustrations.
1162
+
1163
+ ### Side Accent
1164
+
1165
+ Small image floated beside a section. Use when the illustration supports but doesn't dominate the content.
1166
+
1167
+ ```css
1168
+ .accent-img {
1169
+ float: right;
1170
+ max-width: 200px;
1171
+ margin: 0 0 16px 24px;
1172
+ border-radius: 10px;
1173
+ border: 1px solid var(--border);
1174
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
1175
+ }
1176
+
1177
+ @media (max-width: 768px) {
1178
+ .accent-img {
1179
+ float: none;
1180
+ max-width: 100%;
1181
+ margin: 0 0 16px 0;
1182
+ }
1183
+ }
1184
+ ```
1185
+
1186
+ ```html
1187
+ <img class="accent-img" src="data:image/png;base64,..." alt="Descriptive alt text">
1188
+ ```