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,470 @@
1
+ # External Libraries (CDN)
2
+
3
+ Optional CDN libraries for cases where pure CSS/HTML isn't enough. Only include what the diagram actually needs — most diagrams need zero external JS.
4
+
5
+ ## Mermaid.js — Diagramming Engine
6
+
7
+ Use for flowcharts, sequence diagrams, ER diagrams, state machines, mind maps, class diagrams, and any diagram where automatic node positioning and edge routing saves effort. Mermaid handles layout — you handle theming.
8
+
9
+ Do NOT use for dashboards — CSS Grid card layouts with Chart.js look better for those. Data tables use `<table>` elements.
10
+
11
+ **CDN:**
12
+ ```html
13
+ <script type="module">
14
+ import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
15
+
16
+ mermaid.initialize({ startOnLoad: true, /* ... */ });
17
+ </script>
18
+ ```
19
+
20
+ **With ELK layout** (required for `layout: 'elk'` — it's a separate package, not bundled in core):
21
+ ```html
22
+ <script type="module">
23
+ import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
24
+ import elkLayouts from 'https://cdn.jsdelivr.net/npm/@mermaid-js/layout-elk/dist/mermaid-layout-elk.esm.min.mjs';
25
+
26
+ mermaid.registerLayoutLoaders(elkLayouts);
27
+ mermaid.initialize({ startOnLoad: true, layout: 'elk', /* ... */ });
28
+ </script>
29
+ ```
30
+
31
+ Without the ELK import and registration, `layout: 'elk'` silently falls back to dagre. Only import ELK when you actually need it — it adds significant bundle weight. Most simple diagrams render fine with dagre.
32
+
33
+ ### Deep Theming
34
+
35
+ Always use `theme: 'base'` — it's the only theme where all `themeVariables` are fully customizable. The built-in themes (`default`, `dark`, `forest`, `neutral`) ignore most variable overrides.
36
+
37
+ ```html
38
+ <script type="module">
39
+ import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
40
+
41
+ const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
42
+ mermaid.initialize({
43
+ startOnLoad: true,
44
+ theme: 'base',
45
+ look: 'classic',
46
+ themeVariables: {
47
+ // Background and surfaces — teal/slate palette (not violet/indigo!)
48
+ primaryColor: isDark ? '#134e4a' : '#ccfbf1',
49
+ primaryBorderColor: isDark ? '#14b8a6' : '#0d9488',
50
+ primaryTextColor: isDark ? '#f0fdfa' : '#134e4a',
51
+ secondaryColor: isDark ? '#1e293b' : '#f0fdf4',
52
+ secondaryBorderColor: isDark ? '#059669' : '#16a34a',
53
+ secondaryTextColor: isDark ? '#f1f5f9' : '#1e293b',
54
+ tertiaryColor: isDark ? '#27201a' : '#fef3c7',
55
+ tertiaryBorderColor: isDark ? '#d97706' : '#f59e0b',
56
+ tertiaryTextColor: isDark ? '#fef3c7' : '#27201a',
57
+ // Lines and edges
58
+ lineColor: isDark ? '#64748b' : '#94a3b8',
59
+ // Text
60
+ fontSize: '16px',
61
+ fontFamily: 'var(--font-body)',
62
+ // Notes and labels
63
+ noteBkgColor: isDark ? '#1e293b' : '#fefce8',
64
+ noteTextColor: isDark ? '#f1f5f9' : '#1e293b',
65
+ noteBorderColor: isDark ? '#fbbf24' : '#d97706',
66
+ }
67
+ });
68
+ </script>
69
+ ```
70
+
71
+ **FORBIDDEN in Mermaid themeVariables:** `#8b5cf6`, `#7c3aed`, `#a78bfa` (indigo/violet), `#d946ef` (fuchsia). Use teal, slate, amber, emerald, or colors from your page's palette.
72
+
73
+ ### CSS Overrides on Mermaid SVG
74
+
75
+ Mermaid renders SVG. Override its classes for pixel-perfect control that `themeVariables` can't reach:
76
+
77
+ ```css
78
+ /* Container — see css-patterns.md "Mermaid Zoom Controls" for the full zoom pattern */
79
+ .mermaid-wrap {
80
+ position: relative;
81
+ background: var(--surface);
82
+ border: 1px solid var(--border);
83
+ border-radius: 12px;
84
+ padding: 24px;
85
+ overflow: auto;
86
+ }
87
+
88
+ /* CRITICAL: Force node/edge text to follow the page's color scheme.
89
+ Without this, themeVariables.primaryTextColor works for DEFAULT nodes,
90
+ but any classDef that sets color: will hardcode a single value that
91
+ breaks in the opposite color scheme. Fix: never set color: in classDef,
92
+ and always include these CSS overrides. */
93
+ .mermaid .nodeLabel { color: var(--text) !important; }
94
+ .mermaid .edgeLabel { color: var(--text-dim) !important; background-color: var(--bg) !important; }
95
+ .mermaid .edgeLabel rect { fill: var(--bg) !important; }
96
+
97
+ /* Node shapes */
98
+ .mermaid .node rect,
99
+ .mermaid .node circle,
100
+ .mermaid .node polygon {
101
+ stroke-width: 1.5px;
102
+ }
103
+
104
+ /* Edge paths */
105
+ .mermaid .edge-pattern-solid {
106
+ stroke-width: 1.5px;
107
+ }
108
+
109
+ /* Edge labels — smaller than node labels for visual hierarchy */
110
+ .mermaid .edgeLabel {
111
+ font-family: var(--font-mono) !important;
112
+ font-size: 13px !important;
113
+ }
114
+
115
+ /* Node labels — 16px default; drop to 14px for complex diagrams (20+ nodes) */
116
+ .mermaid .nodeLabel {
117
+ font-family: var(--font-body) !important;
118
+ font-size: 16px !important;
119
+ }
120
+
121
+ /* Sequence diagram actors */
122
+ .mermaid .actor {
123
+ stroke-width: 1.5px;
124
+ }
125
+
126
+ /* Sequence diagram messages */
127
+ .mermaid .messageText {
128
+ font-family: var(--font-mono) !important;
129
+ font-size: 12px !important;
130
+ }
131
+
132
+ /* ER diagram entities */
133
+ .mermaid .er.entityBox {
134
+ stroke-width: 1.5px;
135
+ }
136
+
137
+ /* Mind map nodes */
138
+ .mermaid .mindmap-node rect {
139
+ stroke-width: 1.5px;
140
+ }
141
+ ```
142
+
143
+ ### classDef and style Gotchas
144
+
145
+ `classDef` values and per-node `style` directives are static text inside `<pre>` — they can't use CSS variables or JS ternaries. Two rules:
146
+
147
+ 1. **Never set `color:` in classDef or per-node `style` directives.** It hardcodes a text color that breaks in the opposite color scheme. This applies to both `classDef highlight fill:...,color:#2c2a25` and `style I fill:...,color:#2c2a25`. Let the CSS overrides above handle text color via `var(--text)`.
148
+
149
+ 2. **Use semi-transparent fills (8-digit hex) for node backgrounds.** They layer over whatever Mermaid's base theme background is, producing a tint that works in both light and dark modes. Use `20`–`44` alpha for subtle, `55`–`77` for prominent:
150
+
151
+ ```
152
+ classDef highlight fill:#b5761433,stroke:#b57614,stroke-width:2px
153
+ classDef muted fill:#7c6f6411,stroke:#7c6f6444,stroke-width:1px
154
+ ```
155
+
156
+ Avoid opaque light fills like `fill:#fefce8` — they render as bright boxes in dark mode.
157
+
158
+ ### stateDiagram-v2 Label Limitations
159
+
160
+ State diagram transition labels have a strict parser. Avoid:
161
+ - `<br/>` — only works in flowcharts; causes a parse error in state diagrams
162
+ - Parentheses in labels — `cancel()` can confuse the parser
163
+ - Multiple colons — the first `:` is the label delimiter; extra colons in the label text may break parsing
164
+
165
+ If you need multi-line labels or special characters, use a `flowchart` instead of `stateDiagram-v2`. Flowcharts support quoted labels (`|"label with: special chars"|`) and `<br/>` for line breaks.
166
+
167
+ ### Writing Valid Mermaid
168
+
169
+ Most Mermaid failures come from a few recurring issues. Follow these rules to avoid invalid diagrams:
170
+
171
+ **Quote labels with special characters.** Parentheses, colons, commas, brackets, and ampersands break the parser when unquoted. Wrap any label containing special characters in double quotes:
172
+
173
+ ```
174
+ A["handleRequest(ctx)"] --> B["DB: query users"]
175
+ A[handleRequest] --> B[query users]
176
+ ```
177
+
178
+ **Keep IDs simple.** Node IDs should be alphanumeric with no spaces or punctuation. Put the readable name in the label, not the ID:
179
+
180
+ ```
181
+ userSvc["User Service"] --> authSvc["Auth Service"]
182
+ ```
183
+
184
+ **Max 15-20 nodes per diagram.** Beyond that, readability collapses even with ELK layout. Use `subgraph` blocks to group related nodes, or split into multiple diagrams:
185
+
186
+ ```
187
+ subgraph Auth
188
+ login --> validate --> token
189
+ end
190
+ subgraph API
191
+ gateway --> router --> handler
192
+ end
193
+ Auth --> API
194
+ ```
195
+
196
+ **Arrow styles for semantic meaning:**
197
+
198
+ | Arrow | Meaning | Use for |
199
+ |-------|---------|---------|
200
+ | `-->` | Solid | Primary flow |
201
+ | `-.->` | Dotted | Optional, async, or fallback paths |
202
+ | `==>` | Thick | Critical or highlighted path |
203
+ | `--x` | Cross | Rejected or blocked |
204
+ | `-->\|label\|` | Labeled | Decision branches, data descriptions |
205
+
206
+ **Escape pipes in labels.** If a label contains a literal `|`, use `#124;` (HTML entity) or rephrase to avoid it — pipes delimit edge labels in flowcharts.
207
+
208
+ **Sequence diagram messages must be plain text.** Unlike flowchart labels, sequence diagram messages (the text after `:`) cannot be quoted or escaped. Curly braces `{}`, square brackets `[]`, angle brackets `<>`, and `&` will silently break the parser and the entire diagram renders as raw text. Write human-readable descriptions, not code:
209
+
210
+ ```
211
+ %% WRONG — parser chokes on braces, brackets, ampersand
212
+ A->>B: web_search({ queries: [...] })
213
+ B->>B: User removes query 2, keeps 1 & 3
214
+ B->>S: POST /submit { selected: [0, 2] }
215
+
216
+ %% RIGHT — plain English, no special characters
217
+ A->>B: Call web_search with queries
218
+ B->>B: User removes query 2, keeps 1 and 3
219
+ B->>S: POST /submit with selected indices
220
+ ```
221
+
222
+ **Don't mix diagram syntax.** Each diagram type has its own syntax. `-->` works in flowcharts but not in sequence diagrams (`->>` instead). `:::className` works in flowcharts but not in ER diagrams. When in doubt, check the examples below for correct syntax per type.
223
+
224
+ ### Diagram Type Examples
225
+
226
+ **Flowchart with decisions:**
227
+ ```html
228
+ <pre class="mermaid">
229
+ graph TD
230
+ A[Request] --> B{Authenticated?}
231
+ B -->|Yes| C[Load Dashboard]
232
+ B -->|No| D[Login Page]
233
+ D --> E[Submit Credentials]
234
+ E --> B
235
+ C --> F{Role?}
236
+ F -->|Admin| G[Admin Panel]
237
+ F -->|User| H[User Dashboard]
238
+ </pre>
239
+ ```
240
+
241
+ **Sequence diagram:**
242
+ ```html
243
+ <pre class="mermaid">
244
+ sequenceDiagram
245
+ participant C as Client
246
+ participant G as Gateway
247
+ participant S as Service
248
+ participant D as Database
249
+ C->>G: POST /api/data
250
+ G->>G: Validate JWT
251
+ G->>S: Forward request
252
+ S->>D: Query
253
+ D-->>S: Results
254
+ S-->>G: Response
255
+ G-->>C: 200 OK
256
+ </pre>
257
+ ```
258
+
259
+ **ER diagram:**
260
+ ```html
261
+ <pre class="mermaid">
262
+ erDiagram
263
+ USERS ||--o{ ORDERS : places
264
+ ORDERS ||--|{ LINE_ITEMS : contains
265
+ LINE_ITEMS }o--|| PRODUCTS : references
266
+ USERS { string email PK }
267
+ ORDERS { int id PK }
268
+ LINE_ITEMS { int quantity }
269
+ PRODUCTS { string name }
270
+ </pre>
271
+ ```
272
+
273
+ **State diagram:**
274
+ ```html
275
+ <pre class="mermaid">
276
+ stateDiagram-v2
277
+ [*] --> Draft
278
+ Draft --> Review : submit
279
+ Review --> Approved : approve
280
+ Review --> Draft : request_changes
281
+ Approved --> Published : publish
282
+ Published --> Archived : archive
283
+ Archived --> [*]
284
+ </pre>
285
+ ```
286
+
287
+ **Mind map:**
288
+ ```html
289
+ <pre class="mermaid">
290
+ mindmap
291
+ root((Project))
292
+ Frontend
293
+ React
294
+ Next.js
295
+ Tailwind
296
+ Backend
297
+ Node.js
298
+ PostgreSQL
299
+ Redis
300
+ Infrastructure
301
+ AWS
302
+ Docker
303
+ Terraform
304
+ </pre>
305
+ ```
306
+
307
+ ### Dark Mode Handling
308
+
309
+ Mermaid initializes once — it can't reactively switch themes. Read the preference at load time inside your `<script type="module">`:
310
+
311
+ ```javascript
312
+ const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
313
+ // Use isDark to pick light or dark values in themeVariables
314
+ ```
315
+
316
+ The CSS overrides on the container (`.mermaid-wrap`) and page will still respond to `prefers-color-scheme` normally — only the Mermaid SVG internals are static.
317
+
318
+ ## Chart.js — Data Visualizations
319
+
320
+ Use for bar charts, line charts, pie/doughnut charts, radar charts, and other data-driven visualizations in dashboard-type diagrams. Overkill for static numbers — use pure SVG/CSS for simple progress bars and sparklines.
321
+
322
+ ```html
323
+ <script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script>
324
+
325
+ <canvas id="myChart" width="600" height="300"></canvas>
326
+
327
+ <script>
328
+ const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
329
+ const textColor = isDark ? '#8b949e' : '#6b7280';
330
+ const gridColor = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)';
331
+ const fontFamily = getComputedStyle(document.documentElement)
332
+ .getPropertyValue('--font-body').trim() || 'system-ui, sans-serif';
333
+
334
+ new Chart(document.getElementById('myChart'), {
335
+ type: 'bar',
336
+ data: {
337
+ labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
338
+ datasets: [{
339
+ label: 'Feedback Items',
340
+ data: [45, 62, 78, 91, 120],
341
+ backgroundColor: isDark ? 'rgba(129, 140, 248, 0.6)' : 'rgba(79, 70, 229, 0.6)',
342
+ borderColor: isDark ? '#818cf8' : '#4f46e5',
343
+ borderWidth: 1,
344
+ borderRadius: 4,
345
+ }]
346
+ },
347
+ options: {
348
+ responsive: true,
349
+ plugins: {
350
+ legend: { labels: { color: textColor, font: { family: fontFamily } } },
351
+ },
352
+ scales: {
353
+ x: { ticks: { color: textColor, font: { family: fontFamily } }, grid: { color: gridColor } },
354
+ y: { ticks: { color: textColor, font: { family: fontFamily } }, grid: { color: gridColor } },
355
+ }
356
+ }
357
+ });
358
+ </script>
359
+ ```
360
+
361
+ Wrap the canvas in a styled container:
362
+ ```css
363
+ .chart-container {
364
+ background: var(--surface);
365
+ border: 1px solid var(--border);
366
+ border-radius: 10px;
367
+ padding: 20px;
368
+ position: relative;
369
+ }
370
+
371
+ .chart-container canvas {
372
+ max-height: 300px;
373
+ }
374
+ ```
375
+
376
+ ## anime.js — Orchestrated Animations
377
+
378
+ Use when a diagram has 10+ elements and you want a choreographed entrance sequence (staggered reveals, path drawing, count-up numbers). For simpler diagrams, CSS `animation-delay` staggering is sufficient.
379
+
380
+ ```html
381
+ <script src="https://cdn.jsdelivr.net/npm/animejs@3.2.2/lib/anime.min.js"></script>
382
+
383
+ <script>
384
+ const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
385
+
386
+ if (!prefersReduced) {
387
+ anime({
388
+ targets: '.ve-card',
389
+ opacity: [0, 1],
390
+ translateY: [20, 0],
391
+ delay: anime.stagger(80, { start: 200 }),
392
+ easing: 'easeOutCubic',
393
+ duration: 500,
394
+ });
395
+
396
+ anime({
397
+ targets: '.connector path',
398
+ strokeDashoffset: [anime.setDashoffset, 0],
399
+ easing: 'easeInOutCubic',
400
+ duration: 800,
401
+ delay: anime.stagger(150, { start: 600 }),
402
+ });
403
+
404
+ document.querySelectorAll('[data-count]').forEach(el => {
405
+ anime({
406
+ targets: { val: 0 },
407
+ val: parseInt(el.dataset.count),
408
+ round: 1,
409
+ duration: 1200,
410
+ delay: 400,
411
+ easing: 'easeOutExpo',
412
+ update: (anim) => { el.textContent = anim.animations[0].currentValue; }
413
+ });
414
+ });
415
+ }
416
+ </script>
417
+ ```
418
+
419
+ When using anime.js, set initial opacity to 0 in CSS so elements don't flash before the animation:
420
+ ```css
421
+ .ve-card { opacity: 0; }
422
+
423
+ @media (prefers-reduced-motion: reduce) {
424
+ .ve-card { opacity: 1 !important; }
425
+ }
426
+ ```
427
+
428
+ ## Google Fonts — Typography
429
+
430
+ Always load with `display=swap` for fast rendering. Pick a distinctive pairing — body + mono at minimum, optionally a display font for the title.
431
+
432
+ **FORBIDDEN as `--font-body` (AI slop signals):**
433
+ - Inter — the single most overused AI default font
434
+ - Roboto — generic Android/Google default
435
+ - Arial, Helvetica — system defaults with no character
436
+ - system-ui alone without a named font — signals zero design intent
437
+
438
+ ```html
439
+ <link rel="preconnect" href="https://fonts.googleapis.com">
440
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
441
+ <link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Outfit:wght@400;500;600;700&display=swap" rel="stylesheet">
442
+ ```
443
+
444
+ Define as CSS variables for easy reference:
445
+ ```css
446
+ :root {
447
+ --font-body: 'Outfit', system-ui, sans-serif;
448
+ --font-mono: 'Space Mono', 'SF Mono', Consolas, monospace;
449
+ }
450
+ ```
451
+
452
+ **Font pairings** (rotate — never use the same pairing twice in a row):
453
+
454
+ | Body / Headings | Mono / Labels | Feel | Use for |
455
+ |---|---|---|---|
456
+ | DM Sans | Fira Code | Friendly, developer | Blueprint, technical docs |
457
+ | Instrument Serif | JetBrains Mono | Editorial, refined | Plan reviews, decision logs |
458
+ | IBM Plex Sans | IBM Plex Mono | Reliable, readable | Architecture diagrams |
459
+ | Bricolage Grotesque | Fragment Mono | Bold, characterful | Data tables, dashboards |
460
+ | Plus Jakarta Sans | Azeret Mono | Rounded, approachable | Status reports, audits |
461
+ | Outfit | Space Mono | Clean geometric, modern | Flowcharts, pipelines |
462
+ | Sora | IBM Plex Mono | Technical, precise | ER diagrams, schemas |
463
+ | Crimson Pro | Noto Sans Mono | Scholarly, serious | RFC reviews, specs |
464
+ | Fraunces | Source Code Pro | Warm, distinctive | Project recaps |
465
+ | Geist | Geist Mono | Vercel-inspired, sharp | Modern API docs |
466
+ | Red Hat Display | Red Hat Mono | Cohesive family | System overviews |
467
+ | Libre Franklin | Inconsolata | Classic, reliable | Data-dense tables |
468
+ | Playfair Display | Roboto Mono | Elegant contrast | Executive summaries |
469
+
470
+ The first 5 pairings are recommended for most use cases. Vary across consecutive diagrams.
@@ -0,0 +1,212 @@
1
+ # Responsive Section Navigation
2
+
3
+ Navigation pattern for multi-section pages (reviews, recaps, dashboards). Provides a sticky sidebar TOC on desktop and a sticky horizontal scrollable bar on mobile.
4
+
5
+ ## Layout Structure
6
+
7
+ The page uses a two-column CSS Grid: sidebar (TOC) + main content. On mobile it collapses to single-column with the TOC becoming a horizontal bar.
8
+
9
+ ```html
10
+ <body>
11
+ <div class="wrap">
12
+
13
+ <nav class="toc" id="toc">
14
+ <div class="toc-title">Contents</div>
15
+ <a href="#s1">1. First Section</a>
16
+ <a href="#s2">2. Second Section</a>
17
+ <!-- one link per section -->
18
+ </nav>
19
+
20
+ <div class="main">
21
+ <h1>Page Title</h1>
22
+ <p class="subtitle">Subtitle text</p>
23
+
24
+ <div id="s1" class="sec-head ...">1 — First Section</div>
25
+ <!-- section content -->
26
+
27
+ <div id="s2" class="sec-head ...">2 — Second Section</div>
28
+ <!-- section content -->
29
+ </div><!-- /main -->
30
+
31
+ </div><!-- /wrap -->
32
+ </body>
33
+ ```
34
+
35
+ Key structural rules:
36
+ - `<nav class="toc">` is the **first child** of `.wrap`
37
+ - All page content goes inside `<div class="main">`
38
+ - Every section heading gets an `id="s1"`, `id="s2"`, etc.
39
+ - TOC links use `href="#s1"` matching those IDs
40
+ - Keep TOC link text short (truncate long section names)
41
+
42
+ ## CSS
43
+
44
+ ### Wrap (grid layout)
45
+
46
+ ```css
47
+ .wrap {
48
+ max-width: 1400px;
49
+ margin: 0 auto;
50
+ display: grid;
51
+ grid-template-columns: 170px 1fr;
52
+ gap: 0 40px;
53
+ }
54
+ .main { min-width: 0; }
55
+ ```
56
+
57
+ ### TOC — Desktop (sticky sidebar)
58
+
59
+ ```css
60
+ .toc {
61
+ position: sticky;
62
+ top: 24px;
63
+ align-self: start;
64
+ padding: 14px 0;
65
+ grid-row: 1 / -1;
66
+ max-height: calc(100dvh - 48px);
67
+ overflow-y: auto;
68
+ }
69
+ .toc::-webkit-scrollbar { width: 3px; }
70
+ .toc::-webkit-scrollbar-thumb { background: var(--surface-elevated); border-radius: 2px; }
71
+
72
+ .toc-title {
73
+ font-family: var(--font-mono);
74
+ font-size: 9px;
75
+ font-weight: 700;
76
+ text-transform: uppercase;
77
+ letter-spacing: 2px;
78
+ color: var(--text-dim);
79
+ padding: 0 0 10px;
80
+ margin-bottom: 8px;
81
+ border-bottom: 1px solid var(--border);
82
+ }
83
+
84
+ .toc a {
85
+ display: block;
86
+ font-size: 11px;
87
+ color: var(--text-dim);
88
+ text-decoration: none;
89
+ padding: 4px 8px;
90
+ border-radius: 5px;
91
+ border-left: 2px solid transparent;
92
+ transition: all 0.15s;
93
+ line-height: 1.4;
94
+ margin-bottom: 1px;
95
+ }
96
+ .toc a:hover { color: var(--text); background: var(--surface2); }
97
+ .toc a.active { color: var(--text); border-left-color: var(--accent); }
98
+ ```
99
+
100
+ Replace `var(--accent)` with your page's primary accent color variable (e.g., `var(--orange)`, `var(--blue)`).
101
+
102
+ ### TOC — Mobile (sticky horizontal bar)
103
+
104
+ ```css
105
+ @media (max-width: 1000px) {
106
+ .wrap { grid-template-columns: 1fr; padding-top: 0; }
107
+ body { padding-top: 0; }
108
+
109
+ .toc {
110
+ position: sticky;
111
+ top: 0;
112
+ z-index: 200;
113
+ max-height: none;
114
+ display: flex;
115
+ gap: 4px;
116
+ align-items: center;
117
+ overflow-x: auto;
118
+ -webkit-overflow-scrolling: touch;
119
+ background: var(--bg);
120
+ border-bottom: 1px solid var(--border);
121
+ padding: 10px 0;
122
+ margin: 0 -40px;
123
+ padding-left: 40px;
124
+ padding-right: 40px;
125
+ grid-row: auto;
126
+ }
127
+ .toc::-webkit-scrollbar { display: none; }
128
+ .toc-title { display: none; }
129
+
130
+ .toc a {
131
+ white-space: nowrap;
132
+ flex-shrink: 0;
133
+ border-left: none;
134
+ border-bottom: 2px solid transparent;
135
+ border-radius: 4px 4px 0 0;
136
+ padding: 6px 10px;
137
+ font-size: 10px;
138
+ }
139
+ .toc a.active {
140
+ border-left: none;
141
+ border-bottom-color: var(--accent);
142
+ background: var(--surface);
143
+ }
144
+
145
+ .main { padding-top: 20px; }
146
+
147
+ /* Offset scroll target so headings clear the sticky bar */
148
+ .sec-head { scroll-margin-top: 52px; }
149
+ }
150
+ ```
151
+
152
+ Adjust `margin: 0 -40px` and `padding-left/right: 40px` to match your `body` padding so the bar bleeds edge-to-edge.
153
+
154
+ ## JavaScript — Scroll Spy
155
+
156
+ Place before `</body>`, after any Mermaid init:
157
+
158
+ ```html
159
+ <script>
160
+ (function() {
161
+ const toc = document.getElementById('toc');
162
+ const links = toc.querySelectorAll('a');
163
+ const sections = [];
164
+
165
+ links.forEach(link => {
166
+ const id = link.getAttribute('href').slice(1);
167
+ const el = document.getElementById(id);
168
+ if (el) sections.push({ id, el, link });
169
+ });
170
+
171
+ const observer = new IntersectionObserver(entries => {
172
+ entries.forEach(entry => {
173
+ if (entry.isIntersecting) {
174
+ links.forEach(l => l.classList.remove('active'));
175
+ const match = sections.find(s => s.el === entry.target);
176
+ if (match) {
177
+ match.link.classList.add('active');
178
+ // On mobile, auto-scroll the active tab into view
179
+ if (window.innerWidth <= 1000) {
180
+ match.link.scrollIntoView({
181
+ behavior: 'smooth', block: 'nearest', inline: 'center'
182
+ });
183
+ }
184
+ }
185
+ }
186
+ });
187
+ }, { rootMargin: '-10% 0px -80% 0px' });
188
+
189
+ sections.forEach(s => observer.observe(s.el));
190
+
191
+ links.forEach(link => {
192
+ link.addEventListener('click', e => {
193
+ e.preventDefault();
194
+ const id = link.getAttribute('href').slice(1);
195
+ const el = document.getElementById(id);
196
+ if (el) {
197
+ el.scrollIntoView({ behavior: 'smooth', block: 'start' });
198
+ history.replaceState(null, '', '#' + id);
199
+ }
200
+ });
201
+ });
202
+ })();
203
+ </script>
204
+ ```
205
+
206
+ ## Adaptation Notes
207
+
208
+ - The `.toc-title` text, link labels, accent color, and section IDs change per page. Everything else is copy-paste.
209
+ - For pages with fewer than 4 sections, skip the TOC entirely — it adds clutter without value.
210
+ - The `grid-template-columns: 170px 1fr` width works for most TOCs. If section names are longer, go up to `200px`.
211
+ - The `rootMargin: '-10% 0px -80% 0px'` means a section is "active" when its heading enters the top 10-20% of the viewport. This works well with sticky headers.
212
+ - On mobile, the horizontal bar uses `overflow-x: auto` with hidden scrollbar. The active tab auto-scrolls into the center of the bar as the user scrolls the page.