@polderlabs/bizar 3.23.1 → 4.2.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 (361) hide show
  1. package/README.md +83 -16
  2. package/bizar-dash/.bizar/activity.log +3 -0
  3. package/bizar-dash/.bizar/graph/.graphify_analysis.json +1540 -0
  4. package/bizar-dash/.bizar/graph/.graphify_labels.json +1 -0
  5. package/bizar-dash/.bizar/graph/GRAPH_REPORT.md +404 -0
  6. package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/0661b816358db84dfdb7f10443db8a61152fd20b3fee950caf8fbf32920a1790.json +1 -0
  7. package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/16da06d774142a6e5d74829ad982531286a6193ef798de8f593db029e123ec32.json +1 -0
  8. package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/27e5697c01254c69c64c5a33896669073b40afb5ba88375102ae77fa5404136d.json +1 -0
  9. package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/532997898027254aa4c0932243dc71d2f55888181232b65974961934997dc85b.json +1 -0
  10. package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/84e3451a64c7f99f0cd6a88b0748d7426780486f53ab4935b7476b28c08f8293.json +1 -0
  11. package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/88e5ea5f3e78fa69353fe9e6a8d1a05391d54605e25600cb125531eb5a6432ff.json +1 -0
  12. package/bizar-dash/.bizar/graph/cache/stat-index.json +1 -0
  13. package/bizar-dash/.bizar/graph/graph.html +307 -0
  14. package/bizar-dash/.bizar/graph/graph.json +40267 -0
  15. package/bizar-dash/.bizar/graph/manifest.json +762 -0
  16. package/bizar-dash/.graphifyignore +40 -0
  17. package/bizar-dash/.obsidian/README.md +14 -0
  18. package/bizar-dash/.obsidian/daily/2026-06-25.md +9 -0
  19. package/bizar-dash/.obsidian/vault.json +7 -0
  20. package/bizar-dash/.od-skills/web-prototype-e1429c1737/SKILL.md +103 -0
  21. package/bizar-dash/.od-skills/web-prototype-e1429c1737/assets/template.html +338 -0
  22. package/bizar-dash/.od-skills/web-prototype-e1429c1737/example.html +81 -0
  23. package/bizar-dash/.od-skills/web-prototype-e1429c1737/open-design.json +172 -0
  24. package/bizar-dash/.od-skills/web-prototype-e1429c1737/references/checklist.md +44 -0
  25. package/bizar-dash/.od-skills/web-prototype-e1429c1737/references/layouts.md +247 -0
  26. package/bizar-dash/CHANGELOG.md +474 -0
  27. package/bizar-dash/DESIGN.md +136 -0
  28. package/bizar-dash/dist/assets/main-B3RgW6FS.js +331 -0
  29. package/bizar-dash/dist/assets/main-B3RgW6FS.js.map +1 -0
  30. package/bizar-dash/dist/assets/main-DlJ8wgLR.css +1 -0
  31. package/bizar-dash/dist/assets/mobile-CsZQAswA.css +1 -0
  32. package/bizar-dash/dist/assets/mobile-DbxIw8BG.js +2 -0
  33. package/bizar-dash/dist/assets/mobile-DbxIw8BG.js.map +1 -0
  34. package/bizar-dash/dist/assets/mobile-Dvq2d53Y.js +354 -0
  35. package/bizar-dash/dist/assets/mobile-Dvq2d53Y.js.map +1 -0
  36. package/bizar-dash/dist/index.html +40 -0
  37. package/bizar-dash/dist/mobile.html +22 -0
  38. package/bizar-dash/plans/debug-plan/comments.json +1 -0
  39. package/bizar-dash/plans/debug-plan/meta.json +10 -0
  40. package/bizar-dash/plans/debug-plan/plan.json +174 -0
  41. package/bizar-dash/scripts/smoke-bg-retry.mjs +246 -0
  42. package/bizar-dash/src/cli/dashboard-ports.mjs +488 -0
  43. package/bizar-dash/src/cli.mjs +522 -0
  44. package/bizar-dash/src/server/activity-log.mjs +174 -0
  45. package/bizar-dash/src/server/agents-store.mjs +465 -0
  46. package/bizar-dash/src/server/api.mjs +138 -0
  47. package/bizar-dash/src/server/artifact-template.html +810 -0
  48. package/bizar-dash/src/server/artifacts-store.mjs +733 -0
  49. package/bizar-dash/src/server/auth.mjs +381 -0
  50. package/bizar-dash/src/server/background-store.mjs +447 -0
  51. package/bizar-dash/src/server/bg-poller.mjs +305 -0
  52. package/bizar-dash/src/server/bg-retry.mjs +574 -0
  53. package/bizar-dash/src/server/browser.mjs +40 -0
  54. package/bizar-dash/src/server/diagnostics-store.mjs +148 -0
  55. package/bizar-dash/src/server/dialog-poller.mjs +105 -0
  56. package/bizar-dash/src/server/dialog-store.mjs +177 -0
  57. package/bizar-dash/src/server/glyphs/mdx-compiler.mjs +583 -0
  58. package/bizar-dash/src/server/lib/path-safe.mjs +283 -0
  59. package/bizar-dash/src/server/memory-git.mjs +329 -0
  60. package/bizar-dash/src/server/memory-lightrag.mjs +767 -0
  61. package/bizar-dash/src/server/memory-schema.mjs +145 -0
  62. package/bizar-dash/src/server/memory-secrets.mjs +84 -0
  63. package/bizar-dash/src/server/memory-store.mjs +471 -0
  64. package/bizar-dash/src/server/mod-security.mjs +398 -0
  65. package/bizar-dash/src/server/mods-loader.mjs +1067 -0
  66. package/bizar-dash/src/server/notifications-store.mjs +243 -0
  67. package/bizar-dash/src/server/obsidian-store.mjs +318 -0
  68. package/bizar-dash/src/server/opencode-runner.mjs +279 -0
  69. package/bizar-dash/src/server/pair-store.mjs +138 -0
  70. package/bizar-dash/src/server/projects-store.mjs +364 -0
  71. package/bizar-dash/src/server/providers-store.mjs +789 -0
  72. package/bizar-dash/src/server/routes/_shared.mjs +415 -0
  73. package/bizar-dash/src/server/routes/activity.mjs +110 -0
  74. package/bizar-dash/src/server/routes/agents.mjs +134 -0
  75. package/bizar-dash/src/server/routes/artifacts.mjs +279 -0
  76. package/bizar-dash/src/server/routes/auth.mjs +69 -0
  77. package/bizar-dash/src/server/routes/background.mjs +165 -0
  78. package/bizar-dash/src/server/routes/chat.mjs +485 -0
  79. package/bizar-dash/src/server/routes/config.mjs +129 -0
  80. package/bizar-dash/src/server/routes/diagnostics.mjs +50 -0
  81. package/bizar-dash/src/server/routes/dialogs.mjs +86 -0
  82. package/bizar-dash/src/server/routes/fs.mjs +429 -0
  83. package/bizar-dash/src/server/routes/history.mjs +78 -0
  84. package/bizar-dash/src/server/routes/memory.mjs +658 -0
  85. package/bizar-dash/src/server/routes/misc.mjs +89 -0
  86. package/bizar-dash/src/server/routes/mods.mjs +359 -0
  87. package/bizar-dash/src/server/routes/notifications.mjs +54 -0
  88. package/bizar-dash/src/server/routes/obsidian.mjs +239 -0
  89. package/bizar-dash/src/server/routes/opencode-sessions.mjs +55 -0
  90. package/bizar-dash/src/server/routes/overview.mjs +91 -0
  91. package/bizar-dash/src/server/routes/pair.mjs +67 -0
  92. package/bizar-dash/src/server/routes/projects.mjs +175 -0
  93. package/bizar-dash/src/server/routes/providers.mjs +47 -0
  94. package/bizar-dash/src/server/routes/schedules.mjs +104 -0
  95. package/bizar-dash/src/server/routes/settings.mjs +51 -0
  96. package/bizar-dash/src/server/routes/skills.mjs +76 -0
  97. package/bizar-dash/src/server/routes/tasks.mjs +468 -0
  98. package/bizar-dash/src/server/routes/themes.mjs +51 -0
  99. package/bizar-dash/src/server/routes-v2/auth.mjs +59 -0
  100. package/bizar-dash/src/server/routes-v2/events.mjs +107 -0
  101. package/bizar-dash/src/server/routes-v2/health.mjs +21 -0
  102. package/bizar-dash/src/server/routes-v2/index.mjs +90 -0
  103. package/bizar-dash/src/server/routes-v2/sessions.mjs +111 -0
  104. package/bizar-dash/src/server/schedules-runner.mjs +369 -0
  105. package/bizar-dash/src/server/schedules-store.mjs +268 -0
  106. package/bizar-dash/src/server/search-store.mjs +220 -0
  107. package/bizar-dash/src/server/serve-info.mjs +684 -0
  108. package/bizar-dash/src/server/server.mjs +796 -0
  109. package/bizar-dash/src/server/settings-store.mjs +45 -0
  110. package/bizar-dash/src/server/skills-store.mjs +300 -0
  111. package/bizar-dash/src/server/state.mjs +437 -0
  112. package/bizar-dash/src/server/tailscale-store.mjs +113 -0
  113. package/bizar-dash/src/server/task-delegator.mjs +824 -0
  114. package/bizar-dash/src/server/tasks-store.mjs +508 -0
  115. package/bizar-dash/src/server/tui.mjs +923 -0
  116. package/bizar-dash/src/server/update-store.mjs +168 -0
  117. package/bizar-dash/src/server/v2-auth-file.mjs +99 -0
  118. package/bizar-dash/src/server/v2-event-bus.mjs +128 -0
  119. package/bizar-dash/src/server/watcher.mjs +81 -0
  120. package/bizar-dash/src/server/yaml.mjs +238 -0
  121. package/bizar-dash/src/web/App.tsx +718 -0
  122. package/bizar-dash/src/web/MobileApp.tsx +408 -0
  123. package/bizar-dash/src/web/components/ArtifactCreateDialog.tsx +95 -0
  124. package/bizar-dash/src/web/components/ArtifactListDialog.tsx +55 -0
  125. package/bizar-dash/src/web/components/ArtifactViewer.tsx +143 -0
  126. package/bizar-dash/src/web/components/AuditDialog.tsx +79 -0
  127. package/bizar-dash/src/web/components/BgStatusBadge.tsx +32 -0
  128. package/bizar-dash/src/web/components/Button.tsx +56 -0
  129. package/bizar-dash/src/web/components/CanvasContextMenu.tsx +68 -0
  130. package/bizar-dash/src/web/components/Card.tsx +40 -0
  131. package/bizar-dash/src/web/components/CollapsibleSection.tsx +72 -0
  132. package/bizar-dash/src/web/components/CommandDialog.tsx +66 -0
  133. package/bizar-dash/src/web/components/EmptyState.tsx +30 -0
  134. package/bizar-dash/src/web/components/FileBrowser.tsx +633 -0
  135. package/bizar-dash/src/web/components/HelpDialog.tsx +55 -0
  136. package/bizar-dash/src/web/components/KillConfirmDialog.tsx +88 -0
  137. package/bizar-dash/src/web/components/Modal.tsx +215 -0
  138. package/bizar-dash/src/web/components/Notifications.tsx +241 -0
  139. package/bizar-dash/src/web/components/SearchModal.tsx +224 -0
  140. package/bizar-dash/src/web/components/Sidebar.tsx +66 -0
  141. package/bizar-dash/src/web/components/Spinner.tsx +19 -0
  142. package/bizar-dash/src/web/components/StatusBadge.tsx +25 -0
  143. package/bizar-dash/src/web/components/Tag.tsx +28 -0
  144. package/bizar-dash/src/web/components/Toast.tsx +150 -0
  145. package/bizar-dash/src/web/components/Topbar.tsx +368 -0
  146. package/bizar-dash/src/web/components/VisualPlanDialog.tsx +58 -0
  147. package/bizar-dash/src/web/components/chat/AgentChip.tsx +68 -0
  148. package/bizar-dash/src/web/components/chat/ChatBubble.tsx +60 -0
  149. package/bizar-dash/src/web/components/chat/ChatThread.tsx +88 -0
  150. package/bizar-dash/src/web/components/chat/ChatTopBar.tsx +50 -0
  151. package/bizar-dash/src/web/components/chat/Composer.tsx +164 -0
  152. package/bizar-dash/src/web/components/chat/ConfirmModal.tsx +54 -0
  153. package/bizar-dash/src/web/components/chat/EmptyState.tsx +21 -0
  154. package/bizar-dash/src/web/components/chat/FirstRunGreeting.tsx +18 -0
  155. package/bizar-dash/src/web/components/chat/FloatingComposer.tsx +32 -0
  156. package/bizar-dash/src/web/components/chat/InfoPanel.tsx +119 -0
  157. package/bizar-dash/src/web/components/chat/LoadingSkeleton.tsx +19 -0
  158. package/bizar-dash/src/web/components/chat/MessageBubble.tsx +60 -0
  159. package/bizar-dash/src/web/components/chat/SessionList.tsx +153 -0
  160. package/bizar-dash/src/web/components/chat/StreamingIndicator.tsx +9 -0
  161. package/bizar-dash/src/web/components/chat/SuggestionCards.tsx +55 -0
  162. package/bizar-dash/src/web/components/chat/WelcomeScreen.tsx +36 -0
  163. package/bizar-dash/src/web/components/chat/index.ts +20 -0
  164. package/bizar-dash/src/web/components/chat/useAutoGrowTextarea.ts +18 -0
  165. package/bizar-dash/src/web/components/chat/useChat.ts +219 -0
  166. package/bizar-dash/src/web/components/chat/useSlashCommands.ts +47 -0
  167. package/bizar-dash/src/web/index.html +37 -0
  168. package/bizar-dash/src/web/lib/api.ts +193 -0
  169. package/bizar-dash/src/web/lib/markdown.tsx +59 -0
  170. package/bizar-dash/src/web/lib/types.ts +668 -0
  171. package/bizar-dash/src/web/lib/utils.ts +114 -0
  172. package/bizar-dash/src/web/lib/ws.ts +176 -0
  173. package/bizar-dash/src/web/main.tsx +34 -0
  174. package/bizar-dash/src/web/mobile/MobileApp.tsx +278 -0
  175. package/bizar-dash/src/web/mobile/MobileBottomNav.tsx +38 -0
  176. package/bizar-dash/src/web/mobile/MobileTopbar.tsx +115 -0
  177. package/bizar-dash/src/web/mobile/components/MobileBottomSheet.tsx +182 -0
  178. package/bizar-dash/src/web/mobile/components/MobileListItem.tsx +64 -0
  179. package/bizar-dash/src/web/mobile/components/MobileModal.tsx +123 -0
  180. package/bizar-dash/src/web/mobile/views/MobileActivity.tsx +273 -0
  181. package/bizar-dash/src/web/mobile/views/MobileAgents.tsx +374 -0
  182. package/bizar-dash/src/web/mobile/views/MobileArtifactCanvas.tsx +439 -0
  183. package/bizar-dash/src/web/mobile/views/MobileArtifacts.tsx +143 -0
  184. package/bizar-dash/src/web/mobile/views/MobileChat.tsx +180 -0
  185. package/bizar-dash/src/web/mobile/views/MobileConfig.tsx +175 -0
  186. package/bizar-dash/src/web/mobile/views/MobileHistory.tsx +191 -0
  187. package/bizar-dash/src/web/mobile/views/MobileMods.tsx +149 -0
  188. package/bizar-dash/src/web/mobile/views/MobileMore.tsx +121 -0
  189. package/bizar-dash/src/web/mobile/views/MobileNotifications.tsx +137 -0
  190. package/bizar-dash/src/web/mobile/views/MobilePlans.tsx +26 -0
  191. package/bizar-dash/src/web/mobile/views/MobileSchedules.tsx +685 -0
  192. package/bizar-dash/src/web/mobile/views/MobileSearchModal.tsx +172 -0
  193. package/bizar-dash/src/web/mobile/views/MobileSettings.tsx +388 -0
  194. package/bizar-dash/src/web/mobile/views/MobileSkills.tsx +153 -0
  195. package/bizar-dash/src/web/mobile/views/MobileTasks.tsx +564 -0
  196. package/bizar-dash/src/web/mobile.html +20 -0
  197. package/bizar-dash/src/web/mobile.tsx +13 -0
  198. package/bizar-dash/src/web/styles/chat.css +198 -0
  199. package/bizar-dash/src/web/styles/glyphs.css +960 -0
  200. package/bizar-dash/src/web/styles/main.css +8855 -0
  201. package/bizar-dash/src/web/styles/mobile-chat.css +5 -0
  202. package/bizar-dash/src/web/styles/mobile.css +1960 -0
  203. package/bizar-dash/src/web/views/Activity.tsx +1203 -0
  204. package/bizar-dash/src/web/views/Agents.tsx +701 -0
  205. package/bizar-dash/src/web/views/Artifacts.tsx +1480 -0
  206. package/bizar-dash/src/web/views/BackgroundAgents.tsx +450 -0
  207. package/bizar-dash/src/web/views/Chat.tsx +190 -0
  208. package/bizar-dash/src/web/views/Config.tsx +2063 -0
  209. package/bizar-dash/src/web/views/History.tsx +335 -0
  210. package/bizar-dash/src/web/views/ModView.tsx +207 -0
  211. package/bizar-dash/src/web/views/Mods.tsx +693 -0
  212. package/bizar-dash/src/web/views/Overview.tsx +812 -0
  213. package/bizar-dash/src/web/views/Providers.tsx +302 -0
  214. package/bizar-dash/src/web/views/Schedules.tsx +802 -0
  215. package/bizar-dash/src/web/views/Settings.tsx +1787 -0
  216. package/bizar-dash/src/web/views/Skills.tsx +431 -0
  217. package/bizar-dash/src/web/views/Tasks.tsx +1523 -0
  218. package/bizar-dash/src/web/views/glyphs/GlyphRenderer.tsx +613 -0
  219. package/bizar-dash/src/web/views/glyphs/components.tsx +1098 -0
  220. package/bizar-dash/templates/mod/FORMAT.md +76 -0
  221. package/bizar-dash/templates/mod/hello-mod/README.md +19 -0
  222. package/bizar-dash/templates/mod/hello-mod/agents/greeter.md +8 -0
  223. package/bizar-dash/templates/mod/hello-mod/commands/hello.md +6 -0
  224. package/bizar-dash/templates/mod/hello-mod/mod.json +20 -0
  225. package/bizar-dash/templates/mod/hello-mod/routes/ping.mjs +9 -0
  226. package/bizar-dash/templates/mod/hello-mod/views/HelloView.tsx +10 -0
  227. package/bizar-dash/tests/dashboard-ports.test.mjs +138 -0
  228. package/bizar-dash/tests/graphify-mod-spawn.node.test.mjs +90 -0
  229. package/bizar-dash/tests/memory-cli.test.mjs +542 -0
  230. package/bizar-dash/tests/memory-config.test.mjs +422 -0
  231. package/bizar-dash/tests/memory-git.test.mjs +246 -0
  232. package/bizar-dash/tests/memory-lightrag.test.mjs +153 -0
  233. package/bizar-dash/tests/memory-protocol-drift.test.mjs +45 -0
  234. package/bizar-dash/tests/memory-schema.test.mjs +198 -0
  235. package/bizar-dash/tests/memory-secrets.test.mjs +121 -0
  236. package/bizar-dash/tests/memory-store.test.mjs +390 -0
  237. package/bizar-dash/tests/memory-sync.test.mjs +141 -0
  238. package/bizar-dash/tests/mod-instructions.node.test.mjs +188 -0
  239. package/bizar-dash/tests/mod-security.test.mjs +273 -0
  240. package/bizar-dash/tests/mod-upgrade.node.test.mjs +357 -0
  241. package/bizar-dash/tests/no-agent-browser.node.test.mjs +98 -0
  242. package/bizar-dash/tests/obsidian-back-compat.test.mjs +199 -0
  243. package/bizar-dash/tests/opencode-runner.test.mjs +172 -0
  244. package/bizar-dash/tests/path-safe.test.mjs +108 -0
  245. package/bizar-dash/tests/providers-store-backup-keys.node.test.mjs +333 -0
  246. package/bizar-dash/tests/smoke-v2.mjs +212 -0
  247. package/bizar-dash/tests/strip-thinking.test.mjs +175 -0
  248. package/bizar-dash/tests/submit-feedback.test.mjs +353 -0
  249. package/bizar-dash/tests/tmux-wrap.test.mjs +145 -0
  250. package/bizar-dash/tests/yaml.test.mjs +128 -0
  251. package/bizar-dash/tsconfig.json +23 -0
  252. package/bizar-dash/vite.config.ts +27 -0
  253. package/cli/atomic.mjs +73 -0
  254. package/cli/banner.mjs +1 -1
  255. package/cli/bin.mjs +44 -47
  256. package/cli/bootstrap.mjs +1 -1
  257. package/cli/copy.mjs +25 -16
  258. package/cli/dev-link.mjs +17 -1
  259. package/cli/doctor.mjs +4 -4
  260. package/cli/doctor.test.mjs +2 -2
  261. package/cli/init.mjs +135 -1
  262. package/cli/install.mjs +31 -39
  263. package/cli/memory-constants.mjs +59 -0
  264. package/cli/memory.mjs +1436 -0
  265. package/cli/service.mjs +5 -6
  266. package/cli/utils.mjs +6 -3
  267. package/config/AGENTS.md +7 -7
  268. package/config/agents/_shared/AGENT_BASELINE.md +59 -61
  269. package/config/opencode.json +13 -38
  270. package/config/skills/memory-protocol/SKILL.md +105 -0
  271. package/config/skills/obsidian/SKILL.md +270 -65
  272. package/install.sh +59 -19
  273. package/package.json +49 -14
  274. package/packages/sdk/LICENSE +21 -0
  275. package/packages/sdk/README.md +80 -0
  276. package/packages/sdk/src/client.ts +183 -0
  277. package/packages/sdk/src/errors.ts +120 -0
  278. package/packages/sdk/src/events.ts +153 -0
  279. package/packages/sdk/src/index.ts +63 -0
  280. package/packages/sdk/src/types.ts +176 -0
  281. package/packages/sdk/src/version.ts +4 -0
  282. package/packages/sdk/tests/client.test.ts +217 -0
  283. package/packages/sdk/tests/errors.test.ts +108 -0
  284. package/packages/sdk/tests/events.test.ts +139 -0
  285. package/packages/sdk/tests/fixtures/fetch-mock.ts +152 -0
  286. package/packages/sdk/tests/fixtures/sse-mock.ts +30 -0
  287. package/packages/sdk/tsconfig.json +25 -0
  288. package/packages/sdk/vitest.config.ts +9 -0
  289. package/plugins/bizar/LICENSE +21 -0
  290. package/plugins/bizar/README.md +448 -0
  291. package/plugins/bizar/dist/index.js +29901 -0
  292. package/plugins/bizar/index.ts +1491 -0
  293. package/plugins/bizar/scripts/check-forbidden-imports.sh +33 -0
  294. package/plugins/bizar/src/background-state.ts +551 -0
  295. package/plugins/bizar/src/background.ts +1250 -0
  296. package/plugins/bizar/src/commands-impl.ts +464 -0
  297. package/plugins/bizar/src/commands.ts +1168 -0
  298. package/plugins/bizar/src/dashboard-client.ts +233 -0
  299. package/plugins/bizar/src/event-stream.ts +606 -0
  300. package/plugins/bizar/src/fingerprint.ts +120 -0
  301. package/plugins/bizar/src/handoff.ts +79 -0
  302. package/plugins/bizar/src/http-client.ts +467 -0
  303. package/plugins/bizar/src/key-rotation.ts +218 -0
  304. package/plugins/bizar/src/logger.ts +144 -0
  305. package/plugins/bizar/src/loop.ts +176 -0
  306. package/plugins/bizar/src/opencode-runner.ts +390 -0
  307. package/plugins/bizar/src/options.ts +421 -0
  308. package/plugins/bizar/src/plan-fs.ts +323 -0
  309. package/plugins/bizar/src/reasoning-clean.ts +454 -0
  310. package/plugins/bizar/src/report.ts +178 -0
  311. package/plugins/bizar/src/research-prompt.ts +35 -0
  312. package/plugins/bizar/src/serve-info.ts +228 -0
  313. package/plugins/bizar/src/serve.ts +496 -0
  314. package/plugins/bizar/src/settings.ts +349 -0
  315. package/plugins/bizar/src/state.ts +298 -0
  316. package/plugins/bizar/src/tools/bg-collect.ts +104 -0
  317. package/plugins/bizar/src/tools/bg-get-comments.ts +239 -0
  318. package/plugins/bizar/src/tools/bg-kill.ts +87 -0
  319. package/plugins/bizar/src/tools/bg-spawn.ts +401 -0
  320. package/plugins/bizar/src/tools/bg-status.ts +99 -0
  321. package/plugins/bizar/src/tools/open-kb.ts +191 -0
  322. package/plugins/bizar/src/tools/plan-action.ts +767 -0
  323. package/plugins/bizar/src/tools/read-glyph-feedback.ts +170 -0
  324. package/plugins/bizar/src/tools/wait-for-feedback.ts +402 -0
  325. package/plugins/bizar/tests/attach-handler-bug.test.ts +169 -0
  326. package/plugins/bizar/tests/background-state.test.ts +277 -0
  327. package/plugins/bizar/tests/background.test.ts +402 -0
  328. package/plugins/bizar/tests/block.test.ts +195 -0
  329. package/plugins/bizar/tests/canonical-key-order.test.ts +75 -0
  330. package/plugins/bizar/tests/commands-impl.test.ts +442 -0
  331. package/plugins/bizar/tests/commands.test.ts +584 -0
  332. package/plugins/bizar/tests/config.test.ts +122 -0
  333. package/plugins/bizar/tests/dashboard-client.test.ts +159 -0
  334. package/plugins/bizar/tests/dispose.test.ts +336 -0
  335. package/plugins/bizar/tests/event-stream.test.ts +409 -0
  336. package/plugins/bizar/tests/event.test.ts +262 -0
  337. package/plugins/bizar/tests/fingerprint.test.ts +162 -0
  338. package/plugins/bizar/tests/http-client.test.ts +404 -0
  339. package/plugins/bizar/tests/init-helpers.test.ts +203 -0
  340. package/plugins/bizar/tests/integration/slash-command.test.ts +348 -0
  341. package/plugins/bizar/tests/integration/tool-routing.test.ts +314 -0
  342. package/plugins/bizar/tests/key-rotation.test.ts +396 -0
  343. package/plugins/bizar/tests/loop.test.ts +397 -0
  344. package/plugins/bizar/tests/options.test.ts +276 -0
  345. package/plugins/bizar/tests/reasoning-clean.test.ts +422 -0
  346. package/plugins/bizar/tests/serve.test.ts +339 -0
  347. package/plugins/bizar/tests/settings.test.ts +351 -0
  348. package/plugins/bizar/tests/stall-think.test.ts +750 -0
  349. package/plugins/bizar/tests/state.test.ts +276 -0
  350. package/plugins/bizar/tests/tools/bg-collect.test.ts +337 -0
  351. package/plugins/bizar/tests/tools/bg-get-comments.test.ts +485 -0
  352. package/plugins/bizar/tests/tools/bg-kill.test.ts +235 -0
  353. package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +147 -0
  354. package/plugins/bizar/tests/tools/bg-spawn.test.ts +311 -0
  355. package/plugins/bizar/tests/tools/bg-status.test.ts +217 -0
  356. package/plugins/bizar/tests/tools/opencode-runner.test.ts +115 -0
  357. package/plugins/bizar/tests/tools/plan-action.test.ts +599 -0
  358. package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +253 -0
  359. package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +390 -0
  360. package/plugins/bizar/tests/update-deadlock.test.ts +145 -0
  361. package/plugins/bizar/tsconfig.json +29 -0
@@ -0,0 +1,40 @@
1
+ # Auto-generated by the graphify mod (no LLM API key detected).
2
+ # Code-only mode: restricts extraction to source files (processed locally
3
+ # via tree-sitter — no API key needed). Delete this file and re-run once
4
+ # you've set one of: GEMINI_API_KEY, GOOGLE_API_KEY, MOONSHOT_API_KEY,
5
+ # ANTHROPIC_API_KEY, OPENAI_API_KEY, DEEPSEEK_API_KEY, AZURE_OPENAI_API_KEY.
6
+
7
+ # Heavy / vendored dirs to skip entirely
8
+ node_modules/
9
+ .git/
10
+ .bizar/
11
+ .agents/
12
+ dist/
13
+ build/
14
+ coverage/
15
+
16
+ # Agent system prompts — Markdown with YAML frontmatter, not project docs.
17
+ config/agents/
18
+
19
+ # Non-code file types — graphify would need an LLM for these
20
+ *.md
21
+ *.markdown
22
+ *.rst
23
+ *.txt
24
+ *.pdf
25
+ *.docx
26
+ *.html
27
+ *.htm
28
+
29
+ # Image / binary assets
30
+ *.png
31
+ *.jpg
32
+ *.jpeg
33
+ *.gif
34
+ *.svg
35
+ *.webp
36
+ *.ico
37
+ *.mp4
38
+ *.mp3
39
+ *.wav
40
+ *.pdf
@@ -0,0 +1,14 @@
1
+ # bizar-dash — Obsidian Vault
2
+
3
+ Long-term memory for this project's AI agents.
4
+
5
+ ## Structure
6
+
7
+ - `daily/` — daily journal entries (one file per day)
8
+ - `decisions/` — architecture / design decisions
9
+ - `patterns/` — code patterns learned
10
+ - `api/` — API contracts discovered
11
+ - `tasks/` — per-task learnings
12
+
13
+ All notes are plain markdown with YAML frontmatter.
14
+ Agents maintain this vault automatically.
@@ -0,0 +1,9 @@
1
+ ---
2
+ id: daily-2026-06-25
3
+ title: Today
4
+ tags:
5
+ created: "2026-06-26T02:02:33.893Z"
6
+ updated: "2026-06-26T02:02:33.893Z"
7
+ ---
8
+
9
+ # Started v3.19.0
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "bizar-dash",
3
+ "version": "1.0.0",
4
+ "format": "obsidian-vault",
5
+ "createdAt": "2026-06-26T02:02:33.872Z",
6
+ "managedBy": "bizar-dash"
7
+ }
@@ -0,0 +1,103 @@
1
+ ---
2
+ name: web-prototype
3
+ description: |
4
+ General-purpose desktop web prototype. Single self-contained HTML file built
5
+ by copying the seed `assets/template.html` and pasting section layouts from
6
+ `references/layouts.md`. Default for any landing / marketing / docs / SaaS
7
+ page when no more specific skill matches.
8
+ triggers:
9
+ - "prototype"
10
+ - "mockup"
11
+ - "landing"
12
+ - "single page"
13
+ - "marketing page"
14
+ - "homepage"
15
+ od:
16
+ mode: prototype
17
+ platform: desktop
18
+ scenario: design
19
+ preview:
20
+ type: html
21
+ entry: index.html
22
+ design_system:
23
+ requires: true
24
+ sections: [color, typography, layout, components]
25
+ ---
26
+
27
+ # Web Prototype Skill
28
+
29
+ Produce a single, self-contained HTML prototype using the bundled seed and layout library — **not** by writing CSS from scratch. The seed already encodes good defaults (typography, spacing, accent budget). Your job is to compose it.
30
+
31
+ ## Resource map
32
+
33
+ ```
34
+ web-prototype/
35
+ ├── SKILL.md ← you're reading this
36
+ ├── assets/
37
+ │ └── template.html ← seed: tokens + class system + chrome (READ FIRST)
38
+ └── references/
39
+ ├── layouts.md ← 8 paste-ready section skeletons
40
+ └── checklist.md ← P0/P1/P2 self-review
41
+ ```
42
+
43
+ ## Workflow
44
+
45
+ ### Step 0 — Pre-flight (do this once before writing anything)
46
+
47
+ 1. **Read `assets/template.html` end-to-end** — at minimum through the `<style>` block. The class inventory at the top of `references/layouts.md` lists every class that must be defined there; if one is missing, add it to `<style>` rather than re-defining it inline on every section.
48
+ 2. **Read `references/layouts.md`** so you know which section skeletons exist. Don't write a section type that isn't covered — pick the closest layout and adapt.
49
+ 3. **Read the active DESIGN.md** (already injected into your system prompt). Map its colors to the six `:root` variables in the seed; don't introduce new tokens.
50
+
51
+ ### Step 1 — Prepare the artifact from the seed
52
+
53
+ Choose one kebab-case artifact slug before composing the page. Use `assets/template.html` as the seed for the final artifact HTML.
54
+
55
+ Do not write a project-root HTML draft with file-write before emitting the final `<artifact>`. The live-artifact output is the canonical HTML file for this generation turn; an extra `index.html`, `cast.html`, or brief-derived draft can be stranded beside it as an orphan.
56
+
57
+ Replace the six `:root` variables with the active design system's tokens. Replace the page `<title>` and the topnav brand.
58
+
59
+ ### Step 2 — Plan the section list
60
+
61
+ **Pick layouts before writing copy.** Default rhythms (from `layouts.md`):
62
+
63
+ | Page kind | Default rhythm |
64
+ |---|---|
65
+ | Landing | 1 hero → 3 features → 4 stats *or* 5 quote → custom split → 6 cta |
66
+ | Marketing / editorial | 1 hero-center → 7 log list → 6 cta |
67
+ | Pricing | 1 hero-center → 8 comparison table → 6 cta |
68
+ | Docs index | 1 hero-center → 7 log list (sections of docs) → 6 cta |
69
+
70
+ State the chosen list in one sentence to the user *before* writing — they can redirect cheaply now and not after 200 lines of HTML.
71
+
72
+ ### Step 3 — Paste and fill
73
+
74
+ For each chosen layout, copy the `<section>` block from `layouts.md` into `<main id="content">` of the artifact HTML. Replace bracketed `[REPLACE]` strings with real, specific copy from the user's brief. **No filler** — if a slot is empty, the section is the wrong choice; pick a different layout.
75
+
76
+ ### Step 4 — Self-check
77
+
78
+ Run through `references/checklist.md` top to bottom. Every P0 item must pass before you move on. P1 items should pass; P2 are bonus.
79
+
80
+ ### Step 5 — Emit the artifact
81
+
82
+ Wrap the completed HTML in `<artifact>` tags using the artifact slug as the `identifier`. One sentence before describing what's there. Stop after `</artifact>`.
83
+
84
+ ## Hard rules (the seed protects most of these — don't fight it)
85
+
86
+ - **Single accent, used at most twice per screen.** Eyebrow + primary CTA is the default budget.
87
+ - **Display font is serif** (Iowan Old Style / Charter / Georgia in the seed). Sans for body. Mono for numerics, captions, eyebrows.
88
+ - **Image placeholders, not external URLs.** Use the `.ph-img` class — never link to a stock photo CDN.
89
+ - **Mobile reflow already works** via the seed's media query at 920px. Don't break it by adding fixed widths.
90
+ - **`data-od-id` on every `<section>`** so comment mode can target it.
91
+
92
+ ## Output contract
93
+
94
+ ```
95
+ <artifact identifier="kebab-case-slug" type="text/html" title="Human Title">
96
+ <!doctype html>
97
+ <html>...</html>
98
+ </artifact>
99
+ ```
100
+
101
+ Open Design derives the canonical HTML artifact from this identifier. Do not also write another root HTML file for the same generation turn.
102
+
103
+ One sentence before the artifact. Nothing after.
@@ -0,0 +1,338 @@
1
+ <!doctype html>
2
+ <!--
3
+ OD web-prototype seed.
4
+
5
+ Copy this file to <project>/index.html, then fill `<main id="content">` by
6
+ pasting blocks from `references/layouts.md`. Every class referenced in
7
+ layouts.md is defined here — DO NOT remove unused ones unless you also
8
+ remove their callers, and DO NOT invent new global classes (use inline
9
+ style="…" for one-off tweaks).
10
+
11
+ Theme tokens at the top of `<style>` are the *only* place to set palette
12
+ and type. They map cleanly onto a DESIGN.md — when an active design system
13
+ is injected, swap these six variables and everything reflows.
14
+ -->
15
+ <html lang="en">
16
+ <head>
17
+ <meta charset="utf-8" />
18
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
19
+ <title>[REPLACE] Page title · brand</title>
20
+ <style>
21
+ /* ─── tokens ─────────────────────────────────────────────────────────
22
+ Six variables. Bind them to the active DESIGN.md and stop.
23
+ Do not introduce raw hex anywhere else in this file. */
24
+ :root {
25
+ --bg: #fafaf7; /* page background — never #fff */
26
+ --surface: #ffffff; /* cards, modals, raised areas */
27
+ --fg: #1a1916; /* primary text — never #000 */
28
+ --muted: #6b6964; /* secondary text, captions */
29
+ --border: #e8e5df; /* hairlines, dividers */
30
+ --accent: #c96442; /* one accent — used at most 2× per screen */
31
+
32
+ /* derived — do not change */
33
+ --accent-soft: color-mix(in oklch, var(--accent) 14%, transparent);
34
+ --fg-soft: color-mix(in oklch, var(--fg) 6%, transparent);
35
+
36
+ /* type — display = serif (default), body = sans, mono for numerics */
37
+ --font-display: 'Iowan Old Style', 'Charter', Georgia, 'Times New Roman', serif;
38
+ --font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
39
+ --font-mono: ui-monospace, 'JetBrains Mono', 'SF Mono', Menlo, monospace;
40
+
41
+ /* scale — clamp() so it works at 1280, 1440, 1920 without media queries */
42
+ --fs-h1: clamp(44px, 6vw, 76px);
43
+ --fs-h2: clamp(32px, 4vw, 48px);
44
+ --fs-h3: 22px;
45
+ --fs-lead: 19px;
46
+ --fs-body: 16px;
47
+ --fs-meta: 13px;
48
+
49
+ /* spacing — 8-point grid */
50
+ --gap-xs: 8px;
51
+ --gap-sm: 12px;
52
+ --gap-md: 20px;
53
+ --gap-lg: 32px;
54
+ --gap-xl: 56px;
55
+ --gap-2xl: 96px;
56
+ --container: 1120px;
57
+ --gutter: 32px;
58
+
59
+ --radius: 10px;
60
+ --radius-lg: 16px;
61
+ }
62
+
63
+ /* ─── reset & base ──────────────────────────────────────────────── */
64
+ *, *::before, *::after { box-sizing: border-box; }
65
+ html { -webkit-text-size-adjust: 100%; }
66
+ body {
67
+ margin: 0;
68
+ background: var(--bg);
69
+ color: var(--fg);
70
+ font-family: var(--font-body);
71
+ font-size: var(--fs-body);
72
+ line-height: 1.55;
73
+ text-rendering: optimizeLegibility;
74
+ -webkit-font-smoothing: antialiased;
75
+ }
76
+ img, svg { display: block; max-width: 100%; }
77
+ a { color: inherit; text-decoration: none; }
78
+ button { font: inherit; cursor: pointer; }
79
+ p { text-wrap: pretty; }
80
+ h1, h2, h3, h4 { text-wrap: balance; }
81
+
82
+ /* ─── layout primitives ─────────────────────────────────────────── */
83
+ .container {
84
+ max-width: var(--container);
85
+ margin-inline: auto;
86
+ padding-inline: var(--gutter);
87
+ }
88
+ .section {
89
+ padding-block: clamp(48px, 8vw, var(--gap-2xl));
90
+ }
91
+ .section + .section { border-top: 1px solid var(--border); }
92
+ .stack { display: flex; flex-direction: column; }
93
+ .stack > * + * { margin-top: var(--gap-md); }
94
+ .row { display: flex; align-items: center; gap: var(--gap-md); }
95
+ .row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--gap-md); }
96
+ .grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--gap-lg); }
97
+ .grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap-lg); }
98
+ .grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gap-md); }
99
+ .grid-2-1 { display: grid; grid-template-columns: 2fr 1fr; gap: var(--gap-xl); align-items: start; }
100
+ .grid-1-2 { display: grid; grid-template-columns: 1fr 2fr; gap: var(--gap-xl); align-items: start; }
101
+ @media (max-width: 920px) {
102
+ .grid-2, .grid-3, .grid-4, .grid-2-1, .grid-1-2 { grid-template-columns: 1fr; }
103
+ }
104
+
105
+ /* ─── type ──────────────────────────────────────────────────────── */
106
+ .h1, h1 { font-family: var(--font-display); font-size: var(--fs-h1); line-height: 1.04; letter-spacing: -0.02em; margin: 0; }
107
+ .h2, h2 { font-family: var(--font-display); font-size: var(--fs-h2); line-height: 1.1; letter-spacing: -0.015em; margin: 0; }
108
+ .h3, h3 { font-size: var(--fs-h3); font-weight: 600; line-height: 1.3; letter-spacing: -0.005em; margin: 0; }
109
+ .lead { font-size: var(--fs-lead); line-height: 1.55; color: var(--muted); max-width: 60ch; margin: 0; }
110
+ .eyebrow {
111
+ font-family: var(--font-mono);
112
+ font-size: 12px;
113
+ letter-spacing: 0.08em;
114
+ text-transform: uppercase;
115
+ color: var(--accent);
116
+ margin: 0 0 var(--gap-md);
117
+ }
118
+ .meta { font-family: var(--font-mono); font-size: var(--fs-meta); color: var(--muted); }
119
+ .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
120
+
121
+ /* ─── chrome: nav + footer ──────────────────────────────────────── */
122
+ .topnav {
123
+ position: sticky; top: 0; z-index: 10;
124
+ background: color-mix(in oklch, var(--bg) 92%, transparent);
125
+ backdrop-filter: blur(12px);
126
+ border-bottom: 1px solid var(--border);
127
+ }
128
+ .topnav-inner { display: flex; align-items: center; justify-content: space-between; padding-block: 14px; }
129
+ .topnav .logo { font-family: var(--font-display); font-size: 19px; font-weight: 600; letter-spacing: -0.01em; }
130
+ .topnav nav { display: flex; gap: var(--gap-lg); }
131
+ .topnav nav a { font-size: 14px; color: var(--muted); }
132
+ .topnav nav a:hover { color: var(--fg); }
133
+ .pagefoot { padding-block: var(--gap-xl); color: var(--muted); font-size: 13px; border-top: 1px solid var(--border); }
134
+ .pagefoot .row-between { flex-wrap: wrap; gap: var(--gap-md); }
135
+
136
+ /* ─── buttons ───────────────────────────────────────────────────── */
137
+ .btn {
138
+ display: inline-flex; align-items: center; gap: 8px;
139
+ padding: 11px 20px;
140
+ border-radius: var(--radius);
141
+ border: 1px solid transparent;
142
+ font-size: 15px;
143
+ font-weight: 500;
144
+ letter-spacing: -0.005em;
145
+ transition: transform 0.05s ease, background 0.15s ease, border-color 0.15s ease;
146
+ }
147
+ .btn:active { transform: translateY(1px); }
148
+ .btn-primary { background: var(--accent); color: var(--surface); border-color: var(--accent); }
149
+ .btn-primary:hover { background: color-mix(in oklch, var(--accent) 88%, black); }
150
+ .btn-secondary { background: transparent; color: var(--fg); border-color: var(--border); }
151
+ .btn-secondary:hover { border-color: var(--fg); }
152
+ .btn-ghost { background: transparent; color: var(--fg); border-color: transparent; padding-inline: 8px; }
153
+ .btn-ghost:hover { color: var(--accent); }
154
+ .btn-arrow::after { content: '→'; transition: transform 0.15s ease; }
155
+ .btn-arrow:hover::after { transform: translateX(2px); }
156
+
157
+ /* ─── card / surface ────────────────────────────────────────────── */
158
+ .card {
159
+ background: var(--surface);
160
+ border: 1px solid var(--border);
161
+ border-radius: var(--radius-lg);
162
+ padding: 28px;
163
+ }
164
+ .card-flat { background: transparent; border: 0; padding: 0; }
165
+ .card-rule { background: transparent; border: 0; border-top: 1px solid var(--fg); padding: 24px 0 0; border-radius: 0; }
166
+
167
+ /* ─── feature cell (icon + h3 + p) ──────────────────────────────── */
168
+ .feature .feature-mark {
169
+ width: 36px; height: 36px;
170
+ display: grid; place-items: center;
171
+ border: 1px solid var(--border);
172
+ border-radius: 10px;
173
+ color: var(--accent);
174
+ margin-bottom: var(--gap-md);
175
+ }
176
+ .feature .feature-mark svg { width: 18px; height: 18px; }
177
+ .feature h3 { margin-bottom: 6px; }
178
+ .feature p { margin: 0; color: var(--muted); font-size: 15px; }
179
+
180
+ /* ─── stat (big number + label) ─────────────────────────────────── */
181
+ .stat .stat-num {
182
+ font-family: var(--font-display);
183
+ font-size: clamp(56px, 8vw, 96px);
184
+ line-height: 0.95;
185
+ letter-spacing: -0.04em;
186
+ color: var(--accent);
187
+ font-weight: 600;
188
+ }
189
+ .stat .stat-label { color: var(--muted); font-size: 14px; margin-top: 8px; max-width: 24ch; }
190
+ .stat .stat-unit { font-size: 0.5em; opacity: 0.7; margin-left: 2px; }
191
+
192
+ /* ─── quote / testimonial ───────────────────────────────────────── */
193
+ .quote {
194
+ font-family: var(--font-display);
195
+ font-size: clamp(24px, 2.6vw, 32px);
196
+ line-height: 1.32;
197
+ letter-spacing: -0.01em;
198
+ max-width: 28ch;
199
+ }
200
+ .quote-author { color: var(--muted); font-size: 14px; margin-top: var(--gap-md); }
201
+ .quote-mark {
202
+ font-family: var(--font-display);
203
+ font-size: 140px; line-height: 0.7;
204
+ color: var(--accent); opacity: 0.18;
205
+ margin-bottom: -28px;
206
+ }
207
+
208
+ /* ─── pill / badge / tag ────────────────────────────────────────── */
209
+ .pill {
210
+ display: inline-flex; align-items: center; gap: 6px;
211
+ padding: 4px 10px;
212
+ background: var(--accent-soft);
213
+ color: var(--accent);
214
+ border-radius: 999px;
215
+ font-family: var(--font-mono);
216
+ font-size: 11px;
217
+ letter-spacing: 0.04em;
218
+ text-transform: uppercase;
219
+ }
220
+ .tag {
221
+ display: inline-flex; align-items: center;
222
+ padding: 4px 10px;
223
+ background: transparent;
224
+ color: var(--muted);
225
+ border: 1px solid var(--border);
226
+ border-radius: 999px;
227
+ font-size: 12px;
228
+ }
229
+
230
+ /* ─── form field ────────────────────────────────────────────────── */
231
+ .field { display: flex; flex-direction: column; gap: 6px; }
232
+ .field label { font-size: 13px; color: var(--muted); }
233
+ .input, .textarea {
234
+ width: 100%;
235
+ padding: 11px 14px;
236
+ border: 1px solid var(--border);
237
+ border-radius: var(--radius);
238
+ background: var(--surface);
239
+ color: var(--fg);
240
+ font: inherit;
241
+ font-size: 15px;
242
+ }
243
+ .input:focus, .textarea:focus {
244
+ outline: 2px solid var(--accent-soft);
245
+ border-color: var(--accent);
246
+ }
247
+ .textarea { min-height: 96px; resize: vertical; line-height: 1.55; }
248
+
249
+ /* ─── table (data-style, no chrome) ─────────────────────────────── */
250
+ .ds-table { width: 100%; border-collapse: collapse; font-size: 14px; }
251
+ .ds-table th, .ds-table td { padding: 12px 14px; text-align: left; border-bottom: 1px solid var(--border); }
252
+ .ds-table th { color: var(--muted); font-weight: 500; font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase; }
253
+ .ds-table tbody tr:hover { background: var(--fg-soft); }
254
+ .ds-table .num-col { font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; }
255
+
256
+ /* ─── image placeholder (DS-tinted block, never broken <img>) ──── */
257
+ .ph-img {
258
+ background:
259
+ linear-gradient(135deg, var(--accent-soft), var(--fg-soft)),
260
+ var(--surface);
261
+ border: 1px solid var(--border);
262
+ border-radius: var(--radius-lg);
263
+ aspect-ratio: 16 / 10;
264
+ display: grid; place-items: center;
265
+ color: var(--muted);
266
+ font-family: var(--font-mono);
267
+ font-size: 12px;
268
+ letter-spacing: 0.04em;
269
+ }
270
+ .ph-img.square { aspect-ratio: 1 / 1; }
271
+ .ph-img.portrait { aspect-ratio: 3 / 4; }
272
+ .ph-img.wide { aspect-ratio: 16 / 9; }
273
+
274
+ /* ─── divider ───────────────────────────────────────────────────── */
275
+ .rule { border: 0; border-top: 1px solid var(--border); margin: 0; }
276
+ .rule-strong { border: 0; border-top: 1px solid var(--fg); margin: 0; }
277
+
278
+ /* ─── hero variants used by layouts.md ──────────────────────────── */
279
+ .hero { padding-block: clamp(80px, 12vw, 160px); }
280
+ .hero-center { text-align: center; max-width: 32ch; margin-inline: auto; }
281
+ .hero h1 { margin-bottom: var(--gap-md); }
282
+ .hero .lead { margin-bottom: var(--gap-lg); }
283
+ .hero-cta { display: inline-flex; gap: var(--gap-sm); flex-wrap: wrap; }
284
+ .hero-center .hero-cta { justify-content: center; }
285
+ .hero-split { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap-2xl); align-items: center; }
286
+ @media (max-width: 920px) { .hero-split { grid-template-columns: 1fr; } }
287
+
288
+ /* ─── log row (newsletter, blog list, changelog) ────────────────── */
289
+ .log-row { display: grid; grid-template-columns: 120px 1fr 100px; gap: var(--gap-lg); padding: 22px 0; border-top: 1px solid var(--border); align-items: baseline; }
290
+ .log-row .meta { color: var(--muted); }
291
+ .log-row h3 { font-size: 19px; }
292
+ .log-row .pull { text-align: right; }
293
+ </style>
294
+ </head>
295
+ <body>
296
+ <header class="topnav" data-od-id="topnav">
297
+ <div class="container topnav-inner">
298
+ <span class="logo">[REPLACE] Brand</span>
299
+ <nav>
300
+ <a href="#">[REPLACE] Link 1</a>
301
+ <a href="#">[REPLACE] Link 2</a>
302
+ <a href="#">[REPLACE] Link 3</a>
303
+ </nav>
304
+ <button class="btn btn-primary">[REPLACE] CTA</button>
305
+ </div>
306
+ </header>
307
+
308
+ <main id="content">
309
+ <!--
310
+ ┌─────────────────────────────────────────────────────────────────┐
311
+ │ PASTE LAYOUTS FROM references/layouts.md HERE. │
312
+ │ ► Each layout block is a self-contained `<section>` — │
313
+ │ drop in 3–6 of them per page. │
314
+ │ ► Always lead with one hero (Layout 1 or 2). │
315
+ │ ► End with a CTA strip + footer (Layout 6 / footer below). │
316
+ └─────────────────────────────────────────────────────────────────┘
317
+ -->
318
+ <section class="section hero" data-od-id="hero">
319
+ <div class="container hero-center">
320
+ <p class="eyebrow">[REPLACE] Eyebrow</p>
321
+ <h1>[REPLACE] One sharp sentence about what this is.</h1>
322
+ <p class="lead">[REPLACE] One subhead sentence — concrete value, not a tagline.</p>
323
+ <div class="hero-cta">
324
+ <button class="btn btn-primary">[REPLACE] Primary CTA</button>
325
+ <button class="btn btn-secondary">[REPLACE] Secondary</button>
326
+ </div>
327
+ </div>
328
+ </section>
329
+ </main>
330
+
331
+ <footer class="pagefoot" data-od-id="footer">
332
+ <div class="container row-between">
333
+ <span>© [REPLACE] Brand · [REPLACE] Year</span>
334
+ <span class="meta">[REPLACE] tagline · contact@example.com</span>
335
+ </div>
336
+ </footer>
337
+ </body>
338
+ </html>
@@ -0,0 +1,81 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Tomato — focused work timer</title>
7
+ <style>
8
+ :root {
9
+ --bg: #fafaf9; --fg: #1c1b1a; --muted: #6b6964; --border: #e6e4e0;
10
+ --accent: #c96442; --surface: #ffffff;
11
+ }
12
+ * { box-sizing: border-box; }
13
+ body { margin: 0; background: var(--bg); color: var(--fg); font: 16px/1.55 -apple-system, system-ui, sans-serif; }
14
+ header, main, footer { max-width: 1080px; margin: 0 auto; padding: 0 32px; }
15
+ header { display: flex; justify-content: space-between; align-items: center; padding-top: 20px; }
16
+ .logo { font-weight: 600; font-size: 17px; letter-spacing: -0.01em; }
17
+ nav a { color: var(--fg); text-decoration: none; margin-left: 24px; font-size: 14px; }
18
+ nav a:hover { color: var(--accent); }
19
+ .hero { padding: 96px 0 80px; text-align: center; }
20
+ .hero h1 { font-size: clamp(44px, 6vw, 76px); line-height: 1.05; letter-spacing: -0.02em; margin: 0 0 20px; max-width: 18ch; margin-inline: auto; }
21
+ .hero p { color: var(--muted); font-size: 19px; max-width: 52ch; margin: 0 auto 32px; }
22
+ .cta { display: inline-flex; gap: 12px; }
23
+ button { font: inherit; cursor: pointer; padding: 12px 22px; border-radius: 8px; }
24
+ .btn-primary { background: var(--accent); color: white; border: 1px solid var(--accent); font-weight: 500; }
25
+ .btn-secondary { background: transparent; color: var(--fg); border: 1px solid var(--border); }
26
+ .features { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; padding: 56px 0 96px; }
27
+ @media (max-width: 720px) { .features { grid-template-columns: 1fr; } }
28
+ .feature { padding: 28px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; }
29
+ .feature .icon { width: 36px; height: 36px; border-radius: 8px; background: var(--accent); margin-bottom: 16px; opacity: 0.12; }
30
+ .feature h3 { margin: 0 0 8px; font-size: 17px; letter-spacing: -0.01em; }
31
+ .feature p { margin: 0; color: var(--muted); font-size: 14px; }
32
+ .closing { padding: 64px 0 96px; text-align: center; border-top: 1px solid var(--border); }
33
+ .closing h2 { font-size: 32px; margin: 0 0 12px; letter-spacing: -0.01em; }
34
+ .closing p { color: var(--muted); margin: 0 0 28px; }
35
+ footer { padding: 32px; color: var(--muted); font-size: 13px; text-align: center; }
36
+ </style>
37
+ </head>
38
+ <body>
39
+ <header data-od-id="topnav">
40
+ <span class="logo">🍅 Tomato</span>
41
+ <nav>
42
+ <a href="#features">Features</a>
43
+ <a href="#pricing">Pricing</a>
44
+ <a href="#login">Sign in</a>
45
+ </nav>
46
+ </header>
47
+ <main>
48
+ <section class="hero" data-od-id="hero">
49
+ <h1>Twenty-five minutes at a time.</h1>
50
+ <p>The pomodoro timer that actually keeps your hands off Slack. Block notifications, log every cycle, ship more before lunch.</p>
51
+ <div class="cta">
52
+ <button class="btn-primary">Start a session</button>
53
+ <button class="btn-secondary">See how it works</button>
54
+ </div>
55
+ </section>
56
+ <section class="features" id="features">
57
+ <div class="feature" data-od-id="feature-block">
58
+ <div class="icon"></div>
59
+ <h3>Block on, not off</h3>
60
+ <p>Slack and email go quiet for 25 minutes. They come back loud at the break, with a digest.</p>
61
+ </div>
62
+ <div class="feature" data-od-id="feature-stats">
63
+ <div class="icon"></div>
64
+ <h3>Stats that don't lie</h3>
65
+ <p>Weekly review tells you which days you actually shipped versus which you only seemed busy.</p>
66
+ </div>
67
+ <div class="feature" data-od-id="feature-team">
68
+ <div class="icon"></div>
69
+ <h3>Team-friendly silences</h3>
70
+ <p>Your status auto-updates so teammates know when to ask, when to wait, and when you're done.</p>
71
+ </div>
72
+ </section>
73
+ <section class="closing" data-od-id="closing">
74
+ <h2>Stop measuring meetings. Start measuring focus.</h2>
75
+ <p>Free for solo. $4/mo per teammate after that.</p>
76
+ <button class="btn-primary">Try Tomato free</button>
77
+ </section>
78
+ </main>
79
+ <footer>© Tomato Labs · Made for people who'd rather be making.</footer>
80
+ </body>
81
+ </html>