@polderlabs/bizar 3.23.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -2
- package/bizar-dash/.bizar/activity.log +3 -0
- package/bizar-dash/.bizar/graph/.graphify_analysis.json +1540 -0
- package/bizar-dash/.bizar/graph/.graphify_labels.json +1 -0
- package/bizar-dash/.bizar/graph/GRAPH_REPORT.md +404 -0
- package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/0661b816358db84dfdb7f10443db8a61152fd20b3fee950caf8fbf32920a1790.json +1 -0
- package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/16da06d774142a6e5d74829ad982531286a6193ef798de8f593db029e123ec32.json +1 -0
- package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/27e5697c01254c69c64c5a33896669073b40afb5ba88375102ae77fa5404136d.json +1 -0
- package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/532997898027254aa4c0932243dc71d2f55888181232b65974961934997dc85b.json +1 -0
- package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/84e3451a64c7f99f0cd6a88b0748d7426780486f53ab4935b7476b28c08f8293.json +1 -0
- package/bizar-dash/.bizar/graph/cache/ast/v0.8.46/88e5ea5f3e78fa69353fe9e6a8d1a05391d54605e25600cb125531eb5a6432ff.json +1 -0
- package/bizar-dash/.bizar/graph/cache/stat-index.json +1 -0
- package/bizar-dash/.bizar/graph/graph.html +307 -0
- package/bizar-dash/.bizar/graph/graph.json +40267 -0
- package/bizar-dash/.bizar/graph/manifest.json +762 -0
- package/bizar-dash/.graphifyignore +40 -0
- package/bizar-dash/.obsidian/README.md +14 -0
- package/bizar-dash/.obsidian/daily/2026-06-25.md +9 -0
- package/bizar-dash/.obsidian/vault.json +7 -0
- package/bizar-dash/.od-skills/web-prototype-e1429c1737/SKILL.md +103 -0
- package/bizar-dash/.od-skills/web-prototype-e1429c1737/assets/template.html +338 -0
- package/bizar-dash/.od-skills/web-prototype-e1429c1737/example.html +81 -0
- package/bizar-dash/.od-skills/web-prototype-e1429c1737/open-design.json +172 -0
- package/bizar-dash/.od-skills/web-prototype-e1429c1737/references/checklist.md +44 -0
- package/bizar-dash/.od-skills/web-prototype-e1429c1737/references/layouts.md +247 -0
- package/bizar-dash/CHANGELOG.md +474 -0
- package/bizar-dash/DESIGN.md +136 -0
- package/bizar-dash/dist/assets/main-B3RgW6FS.js +331 -0
- package/bizar-dash/dist/assets/main-B3RgW6FS.js.map +1 -0
- package/bizar-dash/dist/assets/main-DlJ8wgLR.css +1 -0
- package/bizar-dash/dist/assets/mobile-CsZQAswA.css +1 -0
- package/bizar-dash/dist/assets/mobile-DbxIw8BG.js +2 -0
- package/bizar-dash/dist/assets/mobile-DbxIw8BG.js.map +1 -0
- package/bizar-dash/dist/assets/mobile-Dvq2d53Y.js +354 -0
- package/bizar-dash/dist/assets/mobile-Dvq2d53Y.js.map +1 -0
- package/bizar-dash/dist/index.html +40 -0
- package/bizar-dash/dist/mobile.html +22 -0
- package/bizar-dash/plans/debug-plan/comments.json +1 -0
- package/bizar-dash/plans/debug-plan/meta.json +10 -0
- package/bizar-dash/plans/debug-plan/plan.json +174 -0
- package/bizar-dash/scripts/smoke-bg-retry.mjs +246 -0
- package/bizar-dash/src/cli/dashboard-ports.mjs +488 -0
- package/bizar-dash/src/cli.mjs +522 -0
- package/bizar-dash/src/server/activity-log.mjs +174 -0
- package/bizar-dash/src/server/agents-store.mjs +465 -0
- package/bizar-dash/src/server/api.mjs +138 -0
- package/bizar-dash/src/server/artifact-template.html +810 -0
- package/bizar-dash/src/server/artifacts-store.mjs +733 -0
- package/bizar-dash/src/server/auth.mjs +381 -0
- package/bizar-dash/src/server/background-store.mjs +447 -0
- package/bizar-dash/src/server/bg-poller.mjs +305 -0
- package/bizar-dash/src/server/bg-retry.mjs +574 -0
- package/bizar-dash/src/server/browser.mjs +40 -0
- package/bizar-dash/src/server/diagnostics-store.mjs +148 -0
- package/bizar-dash/src/server/dialog-poller.mjs +105 -0
- package/bizar-dash/src/server/dialog-store.mjs +177 -0
- package/bizar-dash/src/server/glyphs/mdx-compiler.mjs +583 -0
- package/bizar-dash/src/server/lib/path-safe.mjs +283 -0
- package/bizar-dash/src/server/memory-git.mjs +249 -0
- package/bizar-dash/src/server/memory-schema.mjs +145 -0
- package/bizar-dash/src/server/memory-secrets.mjs +84 -0
- package/bizar-dash/src/server/memory-store.mjs +424 -0
- package/bizar-dash/src/server/mod-security.mjs +398 -0
- package/bizar-dash/src/server/mods-loader.mjs +1067 -0
- package/bizar-dash/src/server/notifications-store.mjs +243 -0
- package/bizar-dash/src/server/obsidian-store.mjs +318 -0
- package/bizar-dash/src/server/opencode-runner.mjs +279 -0
- package/bizar-dash/src/server/pair-store.mjs +138 -0
- package/bizar-dash/src/server/projects-store.mjs +364 -0
- package/bizar-dash/src/server/providers-store.mjs +789 -0
- package/bizar-dash/src/server/routes/_shared.mjs +415 -0
- package/bizar-dash/src/server/routes/activity.mjs +110 -0
- package/bizar-dash/src/server/routes/agents.mjs +134 -0
- package/bizar-dash/src/server/routes/artifacts.mjs +279 -0
- package/bizar-dash/src/server/routes/auth.mjs +69 -0
- package/bizar-dash/src/server/routes/background.mjs +165 -0
- package/bizar-dash/src/server/routes/chat.mjs +485 -0
- package/bizar-dash/src/server/routes/config.mjs +129 -0
- package/bizar-dash/src/server/routes/diagnostics.mjs +50 -0
- package/bizar-dash/src/server/routes/dialogs.mjs +86 -0
- package/bizar-dash/src/server/routes/fs.mjs +429 -0
- package/bizar-dash/src/server/routes/history.mjs +78 -0
- package/bizar-dash/src/server/routes/memory.mjs +499 -0
- package/bizar-dash/src/server/routes/misc.mjs +89 -0
- package/bizar-dash/src/server/routes/mods.mjs +359 -0
- package/bizar-dash/src/server/routes/notifications.mjs +54 -0
- package/bizar-dash/src/server/routes/obsidian.mjs +239 -0
- package/bizar-dash/src/server/routes/opencode-sessions.mjs +55 -0
- package/bizar-dash/src/server/routes/overview.mjs +91 -0
- package/bizar-dash/src/server/routes/pair.mjs +67 -0
- package/bizar-dash/src/server/routes/projects.mjs +175 -0
- package/bizar-dash/src/server/routes/providers.mjs +47 -0
- package/bizar-dash/src/server/routes/schedules.mjs +104 -0
- package/bizar-dash/src/server/routes/settings.mjs +51 -0
- package/bizar-dash/src/server/routes/skills.mjs +76 -0
- package/bizar-dash/src/server/routes/tasks.mjs +468 -0
- package/bizar-dash/src/server/routes/themes.mjs +51 -0
- package/bizar-dash/src/server/routes-v2/auth.mjs +59 -0
- package/bizar-dash/src/server/routes-v2/events.mjs +107 -0
- package/bizar-dash/src/server/routes-v2/health.mjs +21 -0
- package/bizar-dash/src/server/routes-v2/index.mjs +90 -0
- package/bizar-dash/src/server/routes-v2/sessions.mjs +111 -0
- package/bizar-dash/src/server/schedules-runner.mjs +369 -0
- package/bizar-dash/src/server/schedules-store.mjs +268 -0
- package/bizar-dash/src/server/search-store.mjs +220 -0
- package/bizar-dash/src/server/serve-info.mjs +684 -0
- package/bizar-dash/src/server/server.mjs +796 -0
- package/bizar-dash/src/server/settings-store.mjs +45 -0
- package/bizar-dash/src/server/skills-store.mjs +300 -0
- package/bizar-dash/src/server/state.mjs +437 -0
- package/bizar-dash/src/server/tailscale-store.mjs +113 -0
- package/bizar-dash/src/server/task-delegator.mjs +824 -0
- package/bizar-dash/src/server/tasks-store.mjs +508 -0
- package/bizar-dash/src/server/tui.mjs +923 -0
- package/bizar-dash/src/server/update-store.mjs +168 -0
- package/bizar-dash/src/server/v2-auth-file.mjs +99 -0
- package/bizar-dash/src/server/v2-event-bus.mjs +128 -0
- package/bizar-dash/src/server/watcher.mjs +81 -0
- package/bizar-dash/src/server/yaml.mjs +238 -0
- package/bizar-dash/src/web/App.tsx +718 -0
- package/bizar-dash/src/web/MobileApp.tsx +408 -0
- package/bizar-dash/src/web/components/ArtifactCreateDialog.tsx +95 -0
- package/bizar-dash/src/web/components/ArtifactListDialog.tsx +55 -0
- package/bizar-dash/src/web/components/ArtifactViewer.tsx +143 -0
- package/bizar-dash/src/web/components/AuditDialog.tsx +79 -0
- package/bizar-dash/src/web/components/BgStatusBadge.tsx +32 -0
- package/bizar-dash/src/web/components/Button.tsx +56 -0
- package/bizar-dash/src/web/components/CanvasContextMenu.tsx +68 -0
- package/bizar-dash/src/web/components/Card.tsx +40 -0
- package/bizar-dash/src/web/components/CollapsibleSection.tsx +72 -0
- package/bizar-dash/src/web/components/CommandDialog.tsx +66 -0
- package/bizar-dash/src/web/components/EmptyState.tsx +30 -0
- package/bizar-dash/src/web/components/FileBrowser.tsx +633 -0
- package/bizar-dash/src/web/components/HelpDialog.tsx +55 -0
- package/bizar-dash/src/web/components/KillConfirmDialog.tsx +88 -0
- package/bizar-dash/src/web/components/Modal.tsx +215 -0
- package/bizar-dash/src/web/components/Notifications.tsx +241 -0
- package/bizar-dash/src/web/components/SearchModal.tsx +224 -0
- package/bizar-dash/src/web/components/Sidebar.tsx +66 -0
- package/bizar-dash/src/web/components/Spinner.tsx +19 -0
- package/bizar-dash/src/web/components/StatusBadge.tsx +25 -0
- package/bizar-dash/src/web/components/Tag.tsx +28 -0
- package/bizar-dash/src/web/components/Toast.tsx +150 -0
- package/bizar-dash/src/web/components/Topbar.tsx +368 -0
- package/bizar-dash/src/web/components/VisualPlanDialog.tsx +58 -0
- package/bizar-dash/src/web/components/chat/AgentChip.tsx +68 -0
- package/bizar-dash/src/web/components/chat/ChatBubble.tsx +60 -0
- package/bizar-dash/src/web/components/chat/ChatThread.tsx +88 -0
- package/bizar-dash/src/web/components/chat/ChatTopBar.tsx +50 -0
- package/bizar-dash/src/web/components/chat/Composer.tsx +164 -0
- package/bizar-dash/src/web/components/chat/ConfirmModal.tsx +54 -0
- package/bizar-dash/src/web/components/chat/EmptyState.tsx +21 -0
- package/bizar-dash/src/web/components/chat/FirstRunGreeting.tsx +18 -0
- package/bizar-dash/src/web/components/chat/FloatingComposer.tsx +32 -0
- package/bizar-dash/src/web/components/chat/InfoPanel.tsx +119 -0
- package/bizar-dash/src/web/components/chat/LoadingSkeleton.tsx +19 -0
- package/bizar-dash/src/web/components/chat/MessageBubble.tsx +60 -0
- package/bizar-dash/src/web/components/chat/SessionList.tsx +153 -0
- package/bizar-dash/src/web/components/chat/StreamingIndicator.tsx +9 -0
- package/bizar-dash/src/web/components/chat/SuggestionCards.tsx +55 -0
- package/bizar-dash/src/web/components/chat/WelcomeScreen.tsx +36 -0
- package/bizar-dash/src/web/components/chat/index.ts +20 -0
- package/bizar-dash/src/web/components/chat/useAutoGrowTextarea.ts +18 -0
- package/bizar-dash/src/web/components/chat/useChat.ts +219 -0
- package/bizar-dash/src/web/components/chat/useSlashCommands.ts +47 -0
- package/bizar-dash/src/web/index.html +37 -0
- package/bizar-dash/src/web/lib/api.ts +193 -0
- package/bizar-dash/src/web/lib/markdown.tsx +59 -0
- package/bizar-dash/src/web/lib/types.ts +668 -0
- package/bizar-dash/src/web/lib/utils.ts +114 -0
- package/bizar-dash/src/web/lib/ws.ts +176 -0
- package/bizar-dash/src/web/main.tsx +34 -0
- package/bizar-dash/src/web/mobile/MobileApp.tsx +278 -0
- package/bizar-dash/src/web/mobile/MobileBottomNav.tsx +38 -0
- package/bizar-dash/src/web/mobile/MobileTopbar.tsx +115 -0
- package/bizar-dash/src/web/mobile/components/MobileBottomSheet.tsx +182 -0
- package/bizar-dash/src/web/mobile/components/MobileListItem.tsx +64 -0
- package/bizar-dash/src/web/mobile/components/MobileModal.tsx +123 -0
- package/bizar-dash/src/web/mobile/views/MobileActivity.tsx +273 -0
- package/bizar-dash/src/web/mobile/views/MobileAgents.tsx +374 -0
- package/bizar-dash/src/web/mobile/views/MobileArtifactCanvas.tsx +439 -0
- package/bizar-dash/src/web/mobile/views/MobileArtifacts.tsx +143 -0
- package/bizar-dash/src/web/mobile/views/MobileChat.tsx +180 -0
- package/bizar-dash/src/web/mobile/views/MobileConfig.tsx +175 -0
- package/bizar-dash/src/web/mobile/views/MobileHistory.tsx +191 -0
- package/bizar-dash/src/web/mobile/views/MobileMods.tsx +149 -0
- package/bizar-dash/src/web/mobile/views/MobileMore.tsx +121 -0
- package/bizar-dash/src/web/mobile/views/MobileNotifications.tsx +137 -0
- package/bizar-dash/src/web/mobile/views/MobilePlans.tsx +26 -0
- package/bizar-dash/src/web/mobile/views/MobileSchedules.tsx +685 -0
- package/bizar-dash/src/web/mobile/views/MobileSearchModal.tsx +172 -0
- package/bizar-dash/src/web/mobile/views/MobileSettings.tsx +388 -0
- package/bizar-dash/src/web/mobile/views/MobileSkills.tsx +153 -0
- package/bizar-dash/src/web/mobile/views/MobileTasks.tsx +564 -0
- package/bizar-dash/src/web/mobile.html +20 -0
- package/bizar-dash/src/web/mobile.tsx +13 -0
- package/bizar-dash/src/web/styles/chat.css +198 -0
- package/bizar-dash/src/web/styles/glyphs.css +960 -0
- package/bizar-dash/src/web/styles/main.css +8855 -0
- package/bizar-dash/src/web/styles/mobile-chat.css +5 -0
- package/bizar-dash/src/web/styles/mobile.css +1960 -0
- package/bizar-dash/src/web/views/Activity.tsx +1203 -0
- package/bizar-dash/src/web/views/Agents.tsx +701 -0
- package/bizar-dash/src/web/views/Artifacts.tsx +1480 -0
- package/bizar-dash/src/web/views/BackgroundAgents.tsx +450 -0
- package/bizar-dash/src/web/views/Chat.tsx +190 -0
- package/bizar-dash/src/web/views/Config.tsx +1603 -0
- package/bizar-dash/src/web/views/History.tsx +335 -0
- package/bizar-dash/src/web/views/ModView.tsx +207 -0
- package/bizar-dash/src/web/views/Mods.tsx +693 -0
- package/bizar-dash/src/web/views/Overview.tsx +812 -0
- package/bizar-dash/src/web/views/Providers.tsx +302 -0
- package/bizar-dash/src/web/views/Schedules.tsx +802 -0
- package/bizar-dash/src/web/views/Settings.tsx +1787 -0
- package/bizar-dash/src/web/views/Skills.tsx +431 -0
- package/bizar-dash/src/web/views/Tasks.tsx +1523 -0
- package/bizar-dash/src/web/views/glyphs/GlyphRenderer.tsx +613 -0
- package/bizar-dash/src/web/views/glyphs/components.tsx +1098 -0
- package/bizar-dash/templates/mod/FORMAT.md +76 -0
- package/bizar-dash/templates/mod/hello-mod/README.md +19 -0
- package/bizar-dash/templates/mod/hello-mod/agents/greeter.md +8 -0
- package/bizar-dash/templates/mod/hello-mod/commands/hello.md +6 -0
- package/bizar-dash/templates/mod/hello-mod/mod.json +20 -0
- package/bizar-dash/templates/mod/hello-mod/routes/ping.mjs +9 -0
- package/bizar-dash/templates/mod/hello-mod/views/HelloView.tsx +10 -0
- package/bizar-dash/tests/dashboard-ports.test.mjs +138 -0
- package/bizar-dash/tests/graphify-mod-spawn.node.test.mjs +90 -0
- package/bizar-dash/tests/memory-git.test.mjs +138 -0
- package/bizar-dash/tests/memory-schema.test.mjs +198 -0
- package/bizar-dash/tests/memory-secrets.test.mjs +121 -0
- package/bizar-dash/tests/memory-store.test.mjs +390 -0
- package/bizar-dash/tests/memory-sync.test.mjs +141 -0
- package/bizar-dash/tests/mod-instructions.node.test.mjs +188 -0
- package/bizar-dash/tests/mod-security.test.mjs +273 -0
- package/bizar-dash/tests/mod-upgrade.node.test.mjs +357 -0
- package/bizar-dash/tests/no-agent-browser.node.test.mjs +98 -0
- package/bizar-dash/tests/obsidian-back-compat.test.mjs +199 -0
- package/bizar-dash/tests/opencode-runner.test.mjs +172 -0
- package/bizar-dash/tests/path-safe.test.mjs +108 -0
- package/bizar-dash/tests/providers-store-backup-keys.node.test.mjs +333 -0
- package/bizar-dash/tests/smoke-v2.mjs +212 -0
- package/bizar-dash/tests/strip-thinking.test.mjs +175 -0
- package/bizar-dash/tests/submit-feedback.test.mjs +353 -0
- package/bizar-dash/tests/tmux-wrap.test.mjs +145 -0
- package/bizar-dash/tests/yaml.test.mjs +128 -0
- package/bizar-dash/tsconfig.json +23 -0
- package/bizar-dash/vite.config.ts +27 -0
- package/cli/atomic.mjs +73 -0
- package/cli/bin.mjs +43 -46
- package/cli/copy.mjs +3 -0
- package/cli/dev-link.mjs +17 -1
- package/cli/init.mjs +135 -1
- package/cli/install.mjs +10 -23
- package/cli/memory-constants.mjs +59 -0
- package/cli/memory.mjs +757 -0
- package/cli/service.mjs +5 -6
- package/config/skills/obsidian/SKILL.md +213 -65
- package/install.sh +48 -18
- package/package.json +49 -14
- package/packages/sdk/LICENSE +21 -0
- package/packages/sdk/README.md +80 -0
- package/packages/sdk/src/client.ts +183 -0
- package/packages/sdk/src/errors.ts +120 -0
- package/packages/sdk/src/events.ts +153 -0
- package/packages/sdk/src/index.ts +63 -0
- package/packages/sdk/src/types.ts +176 -0
- package/packages/sdk/src/version.ts +4 -0
- package/packages/sdk/tests/client.test.ts +217 -0
- package/packages/sdk/tests/errors.test.ts +108 -0
- package/packages/sdk/tests/events.test.ts +139 -0
- package/packages/sdk/tests/fixtures/fetch-mock.ts +152 -0
- package/packages/sdk/tests/fixtures/sse-mock.ts +30 -0
- package/packages/sdk/tsconfig.json +25 -0
- package/packages/sdk/vitest.config.ts +9 -0
- package/plugins/bizar/LICENSE +21 -0
- package/plugins/bizar/README.md +448 -0
- package/plugins/bizar/dist/index.js +29901 -0
- package/plugins/bizar/index.ts +1484 -0
- package/plugins/bizar/scripts/check-forbidden-imports.sh +33 -0
- package/plugins/bizar/src/background-state.ts +551 -0
- package/plugins/bizar/src/background.ts +1250 -0
- package/plugins/bizar/src/commands-impl.ts +464 -0
- package/plugins/bizar/src/commands.ts +1127 -0
- package/plugins/bizar/src/dashboard-client.ts +233 -0
- package/plugins/bizar/src/event-stream.ts +606 -0
- package/plugins/bizar/src/fingerprint.ts +120 -0
- package/plugins/bizar/src/handoff.ts +79 -0
- package/plugins/bizar/src/http-client.ts +467 -0
- package/plugins/bizar/src/key-rotation.ts +218 -0
- package/plugins/bizar/src/logger.ts +144 -0
- package/plugins/bizar/src/loop.ts +176 -0
- package/plugins/bizar/src/opencode-runner.ts +390 -0
- package/plugins/bizar/src/options.ts +421 -0
- package/plugins/bizar/src/plan-fs.ts +323 -0
- package/plugins/bizar/src/reasoning-clean.ts +454 -0
- package/plugins/bizar/src/report.ts +178 -0
- package/plugins/bizar/src/research-prompt.ts +35 -0
- package/plugins/bizar/src/serve-info.ts +228 -0
- package/plugins/bizar/src/serve.ts +496 -0
- package/plugins/bizar/src/settings.ts +349 -0
- package/plugins/bizar/src/state.ts +298 -0
- package/plugins/bizar/src/tools/bg-collect.ts +104 -0
- package/plugins/bizar/src/tools/bg-get-comments.ts +239 -0
- package/plugins/bizar/src/tools/bg-kill.ts +87 -0
- package/plugins/bizar/src/tools/bg-spawn.ts +401 -0
- package/plugins/bizar/src/tools/bg-status.ts +99 -0
- package/plugins/bizar/src/tools/plan-action.ts +767 -0
- package/plugins/bizar/src/tools/read-glyph-feedback.ts +170 -0
- package/plugins/bizar/src/tools/wait-for-feedback.ts +402 -0
- package/plugins/bizar/tests/attach-handler-bug.test.ts +169 -0
- package/plugins/bizar/tests/background-state.test.ts +277 -0
- package/plugins/bizar/tests/background.test.ts +402 -0
- package/plugins/bizar/tests/block.test.ts +195 -0
- package/plugins/bizar/tests/canonical-key-order.test.ts +75 -0
- package/plugins/bizar/tests/commands-impl.test.ts +442 -0
- package/plugins/bizar/tests/commands.test.ts +548 -0
- package/plugins/bizar/tests/config.test.ts +122 -0
- package/plugins/bizar/tests/dashboard-client.test.ts +159 -0
- package/plugins/bizar/tests/dispose.test.ts +336 -0
- package/plugins/bizar/tests/event-stream.test.ts +409 -0
- package/plugins/bizar/tests/event.test.ts +262 -0
- package/plugins/bizar/tests/fingerprint.test.ts +162 -0
- package/plugins/bizar/tests/http-client.test.ts +404 -0
- package/plugins/bizar/tests/init-helpers.test.ts +203 -0
- package/plugins/bizar/tests/integration/slash-command.test.ts +348 -0
- package/plugins/bizar/tests/integration/tool-routing.test.ts +314 -0
- package/plugins/bizar/tests/key-rotation.test.ts +396 -0
- package/plugins/bizar/tests/loop.test.ts +397 -0
- package/plugins/bizar/tests/options.test.ts +276 -0
- package/plugins/bizar/tests/reasoning-clean.test.ts +422 -0
- package/plugins/bizar/tests/serve.test.ts +339 -0
- package/plugins/bizar/tests/settings.test.ts +351 -0
- package/plugins/bizar/tests/stall-think.test.ts +750 -0
- package/plugins/bizar/tests/state.test.ts +276 -0
- package/plugins/bizar/tests/tools/bg-collect.test.ts +337 -0
- package/plugins/bizar/tests/tools/bg-get-comments.test.ts +485 -0
- package/plugins/bizar/tests/tools/bg-kill.test.ts +235 -0
- package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +147 -0
- package/plugins/bizar/tests/tools/bg-spawn.test.ts +311 -0
- package/plugins/bizar/tests/tools/bg-status.test.ts +217 -0
- package/plugins/bizar/tests/tools/opencode-runner.test.ts +115 -0
- package/plugins/bizar/tests/tools/plan-action.test.ts +599 -0
- package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +253 -0
- package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +390 -0
- package/plugins/bizar/tests/update-deadlock.test.ts +145 -0
- package/plugins/bizar/tsconfig.json +29 -0
|
@@ -0,0 +1,810 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<!--
|
|
3
|
+
============================================================================
|
|
4
|
+
BizarHarness Artifact Template
|
|
5
|
+
|
|
6
|
+
WHAT THIS IS
|
|
7
|
+
============
|
|
8
|
+
A self-contained, opinionated HTML template for artifacts produced by
|
|
9
|
+
BizarHarness agents. It is a starting point — agents fill in the marked
|
|
10
|
+
placeholders and ship the rendered output as their deliverable.
|
|
11
|
+
|
|
12
|
+
HOW TO USE IT
|
|
13
|
+
=============
|
|
14
|
+
1. Copy this file.
|
|
15
|
+
2. Replace every {{PLACEHOLDER}} with the actual content for your task.
|
|
16
|
+
Required placeholders are listed in the Required Sections section
|
|
17
|
+
below; everything else is optional.
|
|
18
|
+
3. Drop the rendered HTML into the html-artifact fenced block:
|
|
19
|
+
|
|
20
|
+
```html-artifact
|
|
21
|
+
{comment}artifact-name:My Report{comment-end}
|
|
22
|
+
<!doctype html>
|
|
23
|
+
...your rendered artifact...
|
|
24
|
+
```
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The first-line comment is optional; it sets the artifact's name in
|
|
28
|
+
the dashboard. If omitted, the dashboard falls back to a generic
|
|
29
|
+
"artifact-id" label.
|
|
30
|
+
|
|
31
|
+
4. Save the final HTML to disk or paste it into the chat. The
|
|
32
|
+
bg-poller in the dashboard scans every done agent output for the
|
|
33
|
+
html-artifact block, saves it to ~/.bizar/artifacts/, and links
|
|
34
|
+
it back to the originating task.
|
|
35
|
+
|
|
36
|
+
OUTPUT CONVENTION
|
|
37
|
+
=================
|
|
38
|
+
The convention the dashboard recognizes is:
|
|
39
|
+
|
|
40
|
+
```html-artifact
|
|
41
|
+
{comment}artifact-name:Optional Name Here{comment-end}
|
|
42
|
+
...HTML body...
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- The block MUST start with the literal fence ```html-artifact (or
|
|
46
|
+
```htmlartifact; both are accepted) on its own line.
|
|
47
|
+
- The block MUST close with a plain ``` fence on its own line.
|
|
48
|
+
- The first HTML comment of the body, if present, may be
|
|
49
|
+
`{comment} artifact-name:Foo {comment-end}` to set the
|
|
50
|
+
artifact display name.
|
|
51
|
+
- Everything else is just HTML — keep it self-contained (no
|
|
52
|
+
external assets, no fetch calls to localhost).
|
|
53
|
+
|
|
54
|
+
REQUIRED SECTIONS
|
|
55
|
+
=================
|
|
56
|
+
The template below is organized as `<section data-section=...>`
|
|
57
|
+
elements. The dashboard does NOT parse these; they are conventions
|
|
58
|
+
for human readers. Replace the placeholders in:
|
|
59
|
+
|
|
60
|
+
- h1 title (Hero) : page H1
|
|
61
|
+
- hero-subtitle (Hero) : one-line subtitle
|
|
62
|
+
- meta-row (Hero) : date / agent / model
|
|
63
|
+
- stat-card x4 (Quick Stats) : 3-4 numeric metrics
|
|
64
|
+
- summary-text (Summary) : TL;DR paragraph
|
|
65
|
+
- tab buttons + tab panels (Tabs) : at least 3 tabs
|
|
66
|
+
- pre blocks (Code) : syntax-highlighted code
|
|
67
|
+
- steps (Steps) : ordered timeline
|
|
68
|
+
- files (Files) : list of files touched
|
|
69
|
+
- next-steps (Next Steps) : recommendations
|
|
70
|
+
|
|
71
|
+
OPTIONAL SECTIONS
|
|
72
|
+
=================
|
|
73
|
+
- Screenshots (paste a base64 or https URL into the img tag)
|
|
74
|
+
- Interactive demo (HTMX swap region + button)
|
|
75
|
+
- Charts (chart.js or hand-rolled SVG)
|
|
76
|
+
|
|
77
|
+
STYLE GUIDELINES
|
|
78
|
+
================
|
|
79
|
+
- Use the supplied CSS custom properties (accent, surface-1, text-1)
|
|
80
|
+
so light/dark mode keeps working.
|
|
81
|
+
- Don't override the body font-family — the cascade handles it.
|
|
82
|
+
- Stick to Tailwind utility classes for layout. Custom CSS is fine
|
|
83
|
+
for unique components.
|
|
84
|
+
- Keep markup accessible: alt text on images, labels on inputs,
|
|
85
|
+
aria-labels on icon-only buttons.
|
|
86
|
+
|
|
87
|
+
DEPENDENCIES (CDN)
|
|
88
|
+
==================
|
|
89
|
+
- htmx.org 1.9.x
|
|
90
|
+
- alpinejs 3.x
|
|
91
|
+
- tailwindcss 3.x (CDN play)
|
|
92
|
+
- highlight.js 11.x (code blocks)
|
|
93
|
+
- lucide icons (inline SVG recommended to keep offline-friendly)
|
|
94
|
+
|
|
95
|
+
ALL SCRIPT TAGS use `defer` to avoid blocking the parser.
|
|
96
|
+
============================================================================
|
|
97
|
+
-->
|
|
98
|
+
<html lang="en" data-theme="auto">
|
|
99
|
+
<head>
|
|
100
|
+
<meta charset="UTF-8" />
|
|
101
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
102
|
+
<title>{{ARTIFACT_TITLE}} — BizarHarness</title>
|
|
103
|
+
|
|
104
|
+
<!-- Tailwind CSS via CDN. Configured to respect dark mode + theme tokens. -->
|
|
105
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
106
|
+
<script>
|
|
107
|
+
// Tailwind play CDN: configure the design tokens so utility classes
|
|
108
|
+
// map to the CSS custom properties defined in :root below.
|
|
109
|
+
tailwind.config = {
|
|
110
|
+
darkMode: 'media',
|
|
111
|
+
theme: {
|
|
112
|
+
extend: {
|
|
113
|
+
fontFamily: {
|
|
114
|
+
sans: ['Inter', 'system-ui', '-apple-system', 'Segoe UI', 'Roboto', 'sans-serif'],
|
|
115
|
+
mono: ['JetBrains Mono', 'ui-monospace', 'SFMono-Regular', 'Menlo', 'monospace'],
|
|
116
|
+
display: ['"Cal Sans"', 'Inter', 'system-ui', 'sans-serif'],
|
|
117
|
+
},
|
|
118
|
+
colors: {
|
|
119
|
+
accent: 'rgb(var(--accent) / <alpha-value>)',
|
|
120
|
+
surface: {
|
|
121
|
+
0: 'rgb(var(--surface-0) / <alpha-value>)',
|
|
122
|
+
1: 'rgb(var(--surface-1) / <alpha-value>)',
|
|
123
|
+
2: 'rgb(var(--surface-2) / <alpha-value>)',
|
|
124
|
+
3: 'rgb(var(--surface-3) / <alpha-value>)',
|
|
125
|
+
},
|
|
126
|
+
ink: {
|
|
127
|
+
0: 'rgb(var(--text-0) / <alpha-value>)',
|
|
128
|
+
1: 'rgb(var(--text-1) / <alpha-value>)',
|
|
129
|
+
2: 'rgb(var(--text-2) / <alpha-value>)',
|
|
130
|
+
},
|
|
131
|
+
line: 'rgb(var(--line) / <alpha-value>)',
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
</script>
|
|
137
|
+
|
|
138
|
+
<!-- Inter (UI) + JetBrains Mono (code) + Cal Sans (display). -->
|
|
139
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
140
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
141
|
+
<link
|
|
142
|
+
rel="stylesheet"
|
|
143
|
+
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"
|
|
144
|
+
/>
|
|
145
|
+
<link
|
|
146
|
+
rel="stylesheet"
|
|
147
|
+
href="https://fonts.cdnfonts.com/css/cal-sans"
|
|
148
|
+
/>
|
|
149
|
+
|
|
150
|
+
<!-- highlight.js for code blocks (atom-one-dark + atom-one-light). -->
|
|
151
|
+
<link
|
|
152
|
+
rel="stylesheet"
|
|
153
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css"
|
|
154
|
+
media="(prefers-color-scheme: dark)"
|
|
155
|
+
/>
|
|
156
|
+
<link
|
|
157
|
+
rel="stylesheet"
|
|
158
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-light.min.css"
|
|
159
|
+
media="(prefers-color-scheme: light)"
|
|
160
|
+
/>
|
|
161
|
+
|
|
162
|
+
<style>
|
|
163
|
+
/* --------------------------------------------------------------------
|
|
164
|
+
Design tokens — light & dark variants
|
|
165
|
+
Light mode: warm white surfaces, indigo accent.
|
|
166
|
+
Dark mode: graphite surfaces, violet accent.
|
|
167
|
+
Agents may override --accent to brand their artifact.
|
|
168
|
+
-------------------------------------------------------------------- */
|
|
169
|
+
:root {
|
|
170
|
+
--accent: 99 102 241; /* indigo-500 (light) */
|
|
171
|
+
--accent-strong: 79 70 229; /* indigo-600 */
|
|
172
|
+
--surface-0: 250 250 252; /* page bg (light) */
|
|
173
|
+
--surface-1: 255 255 255; /* card bg (light) */
|
|
174
|
+
--surface-2: 244 244 248; /* sunken (light) */
|
|
175
|
+
--surface-3: 228 228 235; /* border-ish (light) */
|
|
176
|
+
--text-0: 17 24 39; /* primary (light) */
|
|
177
|
+
--text-1: 55 65 81; /* secondary (light) */
|
|
178
|
+
--text-2: 107 114 128; /* tertiary (light) */
|
|
179
|
+
--line: 226 232 240;
|
|
180
|
+
--success: 16 185 129;
|
|
181
|
+
--warning: 245 158 11;
|
|
182
|
+
--danger: 239 68 68;
|
|
183
|
+
}
|
|
184
|
+
@media (prefers-color-scheme: dark) {
|
|
185
|
+
:root {
|
|
186
|
+
--accent: 167 139 250; /* violet-400 */
|
|
187
|
+
--accent-strong: 139 92 246; /* violet-500 */
|
|
188
|
+
--surface-0: 9 9 11; /* zinc-950 */
|
|
189
|
+
--surface-1: 17 17 23; /* zinc-900 */
|
|
190
|
+
--surface-2: 24 24 31; /* custom */
|
|
191
|
+
--surface-3: 39 39 48;
|
|
192
|
+
--text-0: 244 244 245; /* zinc-100 */
|
|
193
|
+
--text-1: 212 212 216; /* zinc-300 */
|
|
194
|
+
--text-2: 161 161 170; /* zinc-400 */
|
|
195
|
+
--line: 39 39 48;
|
|
196
|
+
--success: 52 211 153;
|
|
197
|
+
--warning: 251 191 36;
|
|
198
|
+
--danger: 248 113 113;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* Body / base typography. */
|
|
203
|
+
html, body {
|
|
204
|
+
background: rgb(var(--surface-0));
|
|
205
|
+
color: rgb(var(--text-0));
|
|
206
|
+
font-family: 'Inter', system-ui, sans-serif;
|
|
207
|
+
font-feature-settings: 'cv11', 'ss01', 'ss03';
|
|
208
|
+
-webkit-font-smoothing: antialiased;
|
|
209
|
+
}
|
|
210
|
+
.font-display { font-family: 'Cal Sans', 'Inter', system-ui, sans-serif; letter-spacing: -0.02em; }
|
|
211
|
+
.font-mono { font-family: 'JetBrains Mono', ui-monospace, monospace; }
|
|
212
|
+
|
|
213
|
+
/* --------------------------------------------------------------------
|
|
214
|
+
Hero — gradient halo behind the title
|
|
215
|
+
-------------------------------------------------------------------- */
|
|
216
|
+
.hero {
|
|
217
|
+
position: relative;
|
|
218
|
+
overflow: hidden;
|
|
219
|
+
border-radius: 1.5rem;
|
|
220
|
+
background:
|
|
221
|
+
radial-gradient(ellipse at top left, rgb(var(--accent) / 0.12), transparent 60%),
|
|
222
|
+
radial-gradient(ellipse at bottom right, rgb(var(--accent-strong) / 0.10), transparent 60%),
|
|
223
|
+
linear-gradient(180deg, rgb(var(--surface-1)), rgb(var(--surface-1)));
|
|
224
|
+
border: 1px solid rgb(var(--line));
|
|
225
|
+
}
|
|
226
|
+
.hero::before {
|
|
227
|
+
content: "";
|
|
228
|
+
position: absolute;
|
|
229
|
+
inset: 0;
|
|
230
|
+
background-image:
|
|
231
|
+
linear-gradient(rgb(var(--line) / 0.4) 1px, transparent 1px),
|
|
232
|
+
linear-gradient(90deg, rgb(var(--line) / 0.4) 1px, transparent 1px);
|
|
233
|
+
background-size: 40px 40px;
|
|
234
|
+
mask-image: radial-gradient(ellipse at center, black 30%, transparent 75%);
|
|
235
|
+
pointer-events: none;
|
|
236
|
+
opacity: 0.5;
|
|
237
|
+
}
|
|
238
|
+
.hero > * { position: relative; z-index: 1; }
|
|
239
|
+
|
|
240
|
+
/* --------------------------------------------------------------------
|
|
241
|
+
Cards / surfaces
|
|
242
|
+
-------------------------------------------------------------------- */
|
|
243
|
+
.card {
|
|
244
|
+
background: rgb(var(--surface-1));
|
|
245
|
+
border: 1px solid rgb(var(--line));
|
|
246
|
+
border-radius: 1rem;
|
|
247
|
+
}
|
|
248
|
+
.card-sunken {
|
|
249
|
+
background: rgb(var(--surface-2));
|
|
250
|
+
border: 1px solid rgb(var(--line));
|
|
251
|
+
border-radius: 0.75rem;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* --------------------------------------------------------------------
|
|
255
|
+
Stat card
|
|
256
|
+
-------------------------------------------------------------------- */
|
|
257
|
+
.stat-card {
|
|
258
|
+
background: rgb(var(--surface-1));
|
|
259
|
+
border: 1px solid rgb(var(--line));
|
|
260
|
+
border-radius: 1rem;
|
|
261
|
+
padding: 1.25rem;
|
|
262
|
+
transition: transform 200ms ease, border-color 200ms ease;
|
|
263
|
+
}
|
|
264
|
+
.stat-card:hover {
|
|
265
|
+
transform: translateY(-2px);
|
|
266
|
+
border-color: rgb(var(--accent) / 0.5);
|
|
267
|
+
}
|
|
268
|
+
.stat-value {
|
|
269
|
+
font-family: 'Cal Sans', 'Inter', sans-serif;
|
|
270
|
+
font-size: 2.25rem;
|
|
271
|
+
line-height: 1;
|
|
272
|
+
letter-spacing: -0.03em;
|
|
273
|
+
color: rgb(var(--text-0));
|
|
274
|
+
}
|
|
275
|
+
.stat-delta-up { color: rgb(var(--success)); }
|
|
276
|
+
.stat-delta-down { color: rgb(var(--danger)); }
|
|
277
|
+
.stat-delta-flat { color: rgb(var(--text-2)); }
|
|
278
|
+
|
|
279
|
+
/* --------------------------------------------------------------------
|
|
280
|
+
Tabs
|
|
281
|
+
-------------------------------------------------------------------- */
|
|
282
|
+
.tab-bar {
|
|
283
|
+
display: flex;
|
|
284
|
+
gap: 0.25rem;
|
|
285
|
+
padding: 0.25rem;
|
|
286
|
+
background: rgb(var(--surface-2));
|
|
287
|
+
border: 1px solid rgb(var(--line));
|
|
288
|
+
border-radius: 0.75rem;
|
|
289
|
+
overflow-x: auto;
|
|
290
|
+
scrollbar-width: none;
|
|
291
|
+
}
|
|
292
|
+
.tab-bar::-webkit-scrollbar { display: none; }
|
|
293
|
+
.tab {
|
|
294
|
+
flex: none;
|
|
295
|
+
padding: 0.5rem 1rem;
|
|
296
|
+
border-radius: 0.5rem;
|
|
297
|
+
font-weight: 500;
|
|
298
|
+
font-size: 0.875rem;
|
|
299
|
+
color: rgb(var(--text-1));
|
|
300
|
+
cursor: pointer;
|
|
301
|
+
transition: all 150ms ease;
|
|
302
|
+
user-select: none;
|
|
303
|
+
}
|
|
304
|
+
.tab:hover { color: rgb(var(--text-0)); }
|
|
305
|
+
.tab[aria-selected="true"] {
|
|
306
|
+
background: rgb(var(--surface-1));
|
|
307
|
+
color: rgb(var(--accent));
|
|
308
|
+
box-shadow: 0 1px 2px rgba(0,0,0,0.04);
|
|
309
|
+
}
|
|
310
|
+
.tab-panel { display: none; }
|
|
311
|
+
.tab-panel[data-active] { display: block; animation: fadeIn 200ms ease; }
|
|
312
|
+
@keyframes fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
|
|
313
|
+
|
|
314
|
+
/* --------------------------------------------------------------------
|
|
315
|
+
Code blocks — pad the highlighted pre so line numbers (if any) align
|
|
316
|
+
-------------------------------------------------------------------- */
|
|
317
|
+
pre.codeblock {
|
|
318
|
+
background: #0d1117; /* GitHub dark — works on both light/dark */
|
|
319
|
+
color: #c9d1d9;
|
|
320
|
+
border-radius: 0.75rem;
|
|
321
|
+
padding: 1.25rem 1.5rem;
|
|
322
|
+
overflow-x: auto;
|
|
323
|
+
font-family: 'JetBrains Mono', monospace;
|
|
324
|
+
font-size: 0.85rem;
|
|
325
|
+
line-height: 1.6;
|
|
326
|
+
border: 1px solid rgb(var(--line));
|
|
327
|
+
}
|
|
328
|
+
pre.codeblock code { font-family: inherit; }
|
|
329
|
+
|
|
330
|
+
/* --------------------------------------------------------------------
|
|
331
|
+
Steps timeline
|
|
332
|
+
-------------------------------------------------------------------- */
|
|
333
|
+
.step {
|
|
334
|
+
display: grid;
|
|
335
|
+
grid-template-columns: auto 1fr;
|
|
336
|
+
gap: 1rem;
|
|
337
|
+
align-items: flex-start;
|
|
338
|
+
padding: 0.75rem 0;
|
|
339
|
+
}
|
|
340
|
+
.step-dot {
|
|
341
|
+
width: 1.75rem;
|
|
342
|
+
height: 1.75rem;
|
|
343
|
+
border-radius: 9999px;
|
|
344
|
+
background: rgb(var(--accent) / 0.12);
|
|
345
|
+
color: rgb(var(--accent));
|
|
346
|
+
display: flex;
|
|
347
|
+
align-items: center;
|
|
348
|
+
justify-content: center;
|
|
349
|
+
font-weight: 600;
|
|
350
|
+
font-size: 0.85rem;
|
|
351
|
+
flex: none;
|
|
352
|
+
border: 1px solid rgb(var(--accent) / 0.3);
|
|
353
|
+
}
|
|
354
|
+
.step-line {
|
|
355
|
+
width: 2px;
|
|
356
|
+
background: rgb(var(--line));
|
|
357
|
+
margin-left: 0.85rem;
|
|
358
|
+
flex: none;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/* --------------------------------------------------------------------
|
|
362
|
+
File rows
|
|
363
|
+
-------------------------------------------------------------------- */
|
|
364
|
+
.file-row {
|
|
365
|
+
display: flex;
|
|
366
|
+
align-items: center;
|
|
367
|
+
gap: 0.75rem;
|
|
368
|
+
padding: 0.625rem 0.75rem;
|
|
369
|
+
border-radius: 0.5rem;
|
|
370
|
+
font-family: 'JetBrains Mono', monospace;
|
|
371
|
+
font-size: 0.85rem;
|
|
372
|
+
transition: background 100ms ease;
|
|
373
|
+
}
|
|
374
|
+
.file-row:hover { background: rgb(var(--surface-2)); }
|
|
375
|
+
.file-icon {
|
|
376
|
+
width: 1rem;
|
|
377
|
+
height: 1rem;
|
|
378
|
+
flex: none;
|
|
379
|
+
color: rgb(var(--text-2));
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/* --------------------------------------------------------------------
|
|
383
|
+
Pills / badges
|
|
384
|
+
-------------------------------------------------------------------- */
|
|
385
|
+
.pill {
|
|
386
|
+
display: inline-flex;
|
|
387
|
+
align-items: center;
|
|
388
|
+
gap: 0.25rem;
|
|
389
|
+
padding: 0.125rem 0.625rem;
|
|
390
|
+
border-radius: 9999px;
|
|
391
|
+
font-size: 0.75rem;
|
|
392
|
+
font-weight: 500;
|
|
393
|
+
background: rgb(var(--surface-2));
|
|
394
|
+
color: rgb(var(--text-1));
|
|
395
|
+
border: 1px solid rgb(var(--line));
|
|
396
|
+
}
|
|
397
|
+
.pill-accent { background: rgb(var(--accent) / 0.10); color: rgb(var(--accent)); border-color: rgb(var(--accent) / 0.3); }
|
|
398
|
+
.pill-success { background: rgb(var(--success) / 0.10); color: rgb(var(--success)); border-color: rgb(var(--success) / 0.3); }
|
|
399
|
+
.pill-warning { background: rgb(var(--warning) / 0.10); color: rgb(var(--warning)); border-color: rgb(var(--warning) / 0.3); }
|
|
400
|
+
|
|
401
|
+
/* --------------------------------------------------------------------
|
|
402
|
+
Footer signature
|
|
403
|
+
-------------------------------------------------------------------- */
|
|
404
|
+
.signature {
|
|
405
|
+
font-family: 'Cal Sans', 'Inter', sans-serif;
|
|
406
|
+
background: linear-gradient(120deg, rgb(var(--accent)), rgb(var(--accent-strong)));
|
|
407
|
+
-webkit-background-clip: text;
|
|
408
|
+
background-clip: text;
|
|
409
|
+
-webkit-text-fill-color: transparent;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/* --------------------------------------------------------------------
|
|
413
|
+
Small utility — clickable cursor on Alpine x-cloak hidden elements
|
|
414
|
+
-------------------------------------------------------------------- */
|
|
415
|
+
[x-cloak] { display: none !important; }
|
|
416
|
+
|
|
417
|
+
/* --------------------------------------------------------------------
|
|
418
|
+
Print: drop the gradient hero for a clean printout
|
|
419
|
+
-------------------------------------------------------------------- */
|
|
420
|
+
@media print {
|
|
421
|
+
.hero::before { display: none; }
|
|
422
|
+
.tab-bar { display: none; }
|
|
423
|
+
.tab-panel { display: block !important; }
|
|
424
|
+
}
|
|
425
|
+
</style>
|
|
426
|
+
</head>
|
|
427
|
+
<body class="min-h-screen antialiased">
|
|
428
|
+
|
|
429
|
+
<!-- ====================================================================
|
|
430
|
+
Top nav (lightweight — just a back-link + theme indicator)
|
|
431
|
+
==================================================================== -->
|
|
432
|
+
<header class="border-b border-line">
|
|
433
|
+
<div class="max-w-6xl mx-auto px-6 py-4 flex items-center justify-between">
|
|
434
|
+
<a href="/" class="flex items-center gap-2 text-ink-1 hover:text-ink-0 transition">
|
|
435
|
+
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
436
|
+
<path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
|
|
437
|
+
</svg>
|
|
438
|
+
<span class="font-medium text-sm">BizarHarness</span>
|
|
439
|
+
</a>
|
|
440
|
+
<div class="flex items-center gap-3 text-xs text-ink-2">
|
|
441
|
+
<span class="pill pill-accent">v3.5.5</span>
|
|
442
|
+
<span>{{AGENT_NAME}}</span>
|
|
443
|
+
</div>
|
|
444
|
+
</div>
|
|
445
|
+
</header>
|
|
446
|
+
|
|
447
|
+
<main class="max-w-6xl mx-auto px-6 py-10 space-y-12">
|
|
448
|
+
|
|
449
|
+
<!-- ================================================================
|
|
450
|
+
HERO — title, subtitle, metadata row
|
|
451
|
+
================================================================ -->
|
|
452
|
+
<section class="hero px-8 py-12 md:px-12 md:py-16" data-section="hero" x-data="{ ts: new Date() }" x-init="() => {}">
|
|
453
|
+
<div class="flex flex-col gap-4">
|
|
454
|
+
<div class="flex items-center gap-2">
|
|
455
|
+
<span class="pill pill-success">
|
|
456
|
+
<svg class="w-3 h-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
457
|
+
<path d="M5 13l4 4L19 7"></path>
|
|
458
|
+
</svg>
|
|
459
|
+
Completed
|
|
460
|
+
</span>
|
|
461
|
+
<span class="pill">{{ARTIFACT_TYPE}}</span>
|
|
462
|
+
<span class="pill" x-text="ts.toLocaleString()">—</span>
|
|
463
|
+
</div>
|
|
464
|
+
|
|
465
|
+
<h1 class="font-display text-4xl md:text-5xl lg:text-6xl text-ink-0 leading-[1.05]">
|
|
466
|
+
{{ARTIFACT_TITLE}}
|
|
467
|
+
</h1>
|
|
468
|
+
|
|
469
|
+
<p class="hero-subtitle text-ink-1 text-lg md:text-xl max-w-3xl">
|
|
470
|
+
{{ARTIFACT_SUBTITLE}}
|
|
471
|
+
</p>
|
|
472
|
+
|
|
473
|
+
<!-- Meta row: date · agent · model · duration · tokens -->
|
|
474
|
+
<div class="meta-row mt-4 flex flex-wrap gap-x-6 gap-y-2 text-sm text-ink-2">
|
|
475
|
+
<div class="flex items-center gap-1.5">
|
|
476
|
+
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
477
|
+
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
|
|
478
|
+
<line x1="16" y1="2" x2="16" y2="6"></line>
|
|
479
|
+
<line x1="8" y1="2" x2="8" y2="6"></line>
|
|
480
|
+
<line x1="3" y1="10" x2="21" y2="10"></line>
|
|
481
|
+
</svg>
|
|
482
|
+
<span>{{DATE}}</span>
|
|
483
|
+
</div>
|
|
484
|
+
<div class="flex items-center gap-1.5">
|
|
485
|
+
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
486
|
+
<path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"></path>
|
|
487
|
+
<circle cx="12" cy="7" r="4"></circle>
|
|
488
|
+
</svg>
|
|
489
|
+
<span>{{AGENT_NAME}}</span>
|
|
490
|
+
</div>
|
|
491
|
+
<div class="flex items-center gap-1.5">
|
|
492
|
+
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
493
|
+
<circle cx="12" cy="12" r="3"></circle>
|
|
494
|
+
<path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z"></path>
|
|
495
|
+
</svg>
|
|
496
|
+
<span>{{MODEL}}</span>
|
|
497
|
+
</div>
|
|
498
|
+
<div class="flex items-center gap-1.5">
|
|
499
|
+
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
500
|
+
<circle cx="12" cy="12" r="10"></circle>
|
|
501
|
+
<polyline points="12 6 12 12 16 14"></polyline>
|
|
502
|
+
</svg>
|
|
503
|
+
<span>{{DURATION}}</span>
|
|
504
|
+
</div>
|
|
505
|
+
</div>
|
|
506
|
+
</div>
|
|
507
|
+
</section>
|
|
508
|
+
|
|
509
|
+
<!-- ================================================================
|
|
510
|
+
QUICK STATS — 3-4 metric cards
|
|
511
|
+
================================================================ -->
|
|
512
|
+
<section data-section="stats">
|
|
513
|
+
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
514
|
+
<div class="stat-card">
|
|
515
|
+
<div class="text-xs text-ink-2 uppercase tracking-wider font-medium">Lines changed</div>
|
|
516
|
+
<div class="stat-value mt-2">{{STAT_1_VALUE}}</div>
|
|
517
|
+
<div class="mt-2 text-xs stat-delta-up flex items-center gap-1">
|
|
518
|
+
<svg class="w-3 h-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 15l7-7 7 7"></path></svg>
|
|
519
|
+
<span>{{STAT_1_DELTA}}</span>
|
|
520
|
+
</div>
|
|
521
|
+
</div>
|
|
522
|
+
<div class="stat-card">
|
|
523
|
+
<div class="text-xs text-ink-2 uppercase tracking-wider font-medium">Files touched</div>
|
|
524
|
+
<div class="stat-value mt-2">{{STAT_2_VALUE}}</div>
|
|
525
|
+
<div class="mt-2 text-xs stat-delta-flat">{{STAT_2_NOTE}}</div>
|
|
526
|
+
</div>
|
|
527
|
+
<div class="stat-card">
|
|
528
|
+
<div class="text-xs text-ink-2 uppercase tracking-wider font-medium">Tests passing</div>
|
|
529
|
+
<div class="stat-value mt-2">{{STAT_3_VALUE}}</div>
|
|
530
|
+
<div class="mt-2 text-xs stat-delta-up">{{STAT_3_NOTE}}</div>
|
|
531
|
+
</div>
|
|
532
|
+
<div class="stat-card">
|
|
533
|
+
<div class="text-xs text-ink-2 uppercase tracking-wider font-medium">Tokens used</div>
|
|
534
|
+
<div class="stat-value mt-2">{{STAT_4_VALUE}}</div>
|
|
535
|
+
<div class="mt-2 text-xs stat-delta-down">{{STAT_4_NOTE}}</div>
|
|
536
|
+
</div>
|
|
537
|
+
</div>
|
|
538
|
+
</section>
|
|
539
|
+
|
|
540
|
+
<!-- ================================================================
|
|
541
|
+
SUMMARY — TL;DR paragraph
|
|
542
|
+
================================================================ -->
|
|
543
|
+
<section data-section="summary" class="card p-8 md:p-10">
|
|
544
|
+
<div class="flex items-baseline justify-between mb-4">
|
|
545
|
+
<h2 class="font-display text-2xl text-ink-0">Summary</h2>
|
|
546
|
+
<span class="text-xs text-ink-2">TL;DR</span>
|
|
547
|
+
</div>
|
|
548
|
+
<p class="summary-text text-ink-1 text-base md:text-lg leading-relaxed">
|
|
549
|
+
{{SUMMARY_TEXT}}
|
|
550
|
+
</p>
|
|
551
|
+
</section>
|
|
552
|
+
|
|
553
|
+
<!-- ================================================================
|
|
554
|
+
TABS — Overview, Details, Code, Demo
|
|
555
|
+
================================================================ -->
|
|
556
|
+
<section data-section="tabs" x-data="{ tab: 'overview' }">
|
|
557
|
+
<div class="tab-bar mb-6" role="tablist">
|
|
558
|
+
<button class="tab" :aria-selected="tab === 'overview'" @click="tab = 'overview'" role="tab">Overview</button>
|
|
559
|
+
<button class="tab" :aria-selected="tab === 'details'" @click="tab = 'details'" role="tab">Details</button>
|
|
560
|
+
<button class="tab" :aria-selected="tab === 'code'" @click="tab = 'code'" role="tab">Code</button>
|
|
561
|
+
<button class="tab" :aria-selected="tab === 'demo'" @click="tab = 'demo'" role="tab">Demo</button>
|
|
562
|
+
</div>
|
|
563
|
+
|
|
564
|
+
<!-- Overview tab -->
|
|
565
|
+
<div class="tab-panel" :data-active="tab === 'overview'" role="tabpanel">
|
|
566
|
+
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
567
|
+
<div class="card p-6">
|
|
568
|
+
<h3 class="font-display text-xl mb-3 text-ink-0">What changed</h3>
|
|
569
|
+
<p class="text-ink-1 leading-relaxed">{{OVERVIEW_WHAT_CHANGED}}</p>
|
|
570
|
+
</div>
|
|
571
|
+
<div class="card p-6">
|
|
572
|
+
<h3 class="font-display text-xl mb-3 text-ink-0">Why it matters</h3>
|
|
573
|
+
<p class="text-ink-1 leading-relaxed">{{OVERVIEW_WHY_IT_MATTERS}}</p>
|
|
574
|
+
</div>
|
|
575
|
+
</div>
|
|
576
|
+
</div>
|
|
577
|
+
|
|
578
|
+
<!-- Details tab -->
|
|
579
|
+
<div class="tab-panel" :data-active="tab === 'details'" role="tabpanel">
|
|
580
|
+
<div class="card p-6">
|
|
581
|
+
<h3 class="font-display text-xl mb-3 text-ink-0">Details</h3>
|
|
582
|
+
<div class="prose text-ink-1 max-w-none">
|
|
583
|
+
<p>{{DETAILS_BODY}}</p>
|
|
584
|
+
<ul class="mt-4 space-y-2 list-disc list-inside text-ink-1">
|
|
585
|
+
<li>{{DETAILS_LI_1}}</li>
|
|
586
|
+
<li>{{DETAILS_LI_2}}</li>
|
|
587
|
+
<li>{{DETAILS_LI_3}}</li>
|
|
588
|
+
</ul>
|
|
589
|
+
</div>
|
|
590
|
+
</div>
|
|
591
|
+
</div>
|
|
592
|
+
|
|
593
|
+
<!-- Code tab -->
|
|
594
|
+
<div class="tab-panel" :data-active="tab === 'code'" role="tabpanel">
|
|
595
|
+
<div class="space-y-6">
|
|
596
|
+
<div>
|
|
597
|
+
<div class="flex items-center justify-between mb-2">
|
|
598
|
+
<h3 class="font-display text-xl text-ink-0">Primary change</h3>
|
|
599
|
+
<button
|
|
600
|
+
class="pill hover:bg-surface-3 transition"
|
|
601
|
+
onclick="navigator.clipboard.writeText(this.previousElementSibling.querySelector('code').innerText).then(() => this.textContent='Copied!').catch(() => this.textContent='Failed')"
|
|
602
|
+
>
|
|
603
|
+
Copy
|
|
604
|
+
</button>
|
|
605
|
+
</div>
|
|
606
|
+
<div>
|
|
607
|
+
<pre class="codeblock"><code class="language-javascript">// {{CODE_FILE_1}}
|
|
608
|
+
{{CODE_SNIPPET_1}}</code></pre>
|
|
609
|
+
</div>
|
|
610
|
+
</div>
|
|
611
|
+
<div>
|
|
612
|
+
<h3 class="font-display text-xl mb-2 text-ink-0">Supporting code</h3>
|
|
613
|
+
<pre class="codeblock"><code class="language-bash">$ {{CODE_SNIPPET_2}}</code></pre>
|
|
614
|
+
</div>
|
|
615
|
+
</div>
|
|
616
|
+
</div>
|
|
617
|
+
|
|
618
|
+
<!-- Demo tab — interactive HTMX swap -->
|
|
619
|
+
<div class="tab-panel" :data-active="tab === 'demo'" role="tabpanel">
|
|
620
|
+
<div class="card p-6">
|
|
621
|
+
<h3 class="font-display text-xl mb-3 text-ink-0">Interactive demo</h3>
|
|
622
|
+
<p class="text-ink-1 mb-4">
|
|
623
|
+
Click the button — the dashboard fetches a small JSON snippet
|
|
624
|
+
from <code class="text-accent">/api/health</code> and swaps it
|
|
625
|
+
into the region below via HTMX. This is a live demo; HTMX is
|
|
626
|
+
the same library the dashboard uses for partial updates.
|
|
627
|
+
</p>
|
|
628
|
+
|
|
629
|
+
<!-- HTMX swap region. hx-get fires when the button is pressed. -->
|
|
630
|
+
<div
|
|
631
|
+
id="demo-region"
|
|
632
|
+
class="card-sunken p-4 font-mono text-sm text-ink-1 min-h-[5rem]"
|
|
633
|
+
hx-get="/api/health"
|
|
634
|
+
hx-trigger="demo-requested from:body"
|
|
635
|
+
hx-swap="innerHTML"
|
|
636
|
+
>
|
|
637
|
+
<span class="text-ink-2">// press the button to load /api/health</span>
|
|
638
|
+
</div>
|
|
639
|
+
|
|
640
|
+
<button
|
|
641
|
+
class="mt-4 inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-accent text-white font-medium hover:opacity-90 transition"
|
|
642
|
+
onclick="htmx.trigger('#demo-region', 'demo-requested')"
|
|
643
|
+
>
|
|
644
|
+
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
645
|
+
<polyline points="23 4 23 10 17 10"></polyline>
|
|
646
|
+
<polyline points="1 20 1 14 7 14"></polyline>
|
|
647
|
+
<path d="M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15"></path>
|
|
648
|
+
</svg>
|
|
649
|
+
Load /api/health
|
|
650
|
+
</button>
|
|
651
|
+
</div>
|
|
652
|
+
</div>
|
|
653
|
+
</section>
|
|
654
|
+
|
|
655
|
+
<!-- ================================================================
|
|
656
|
+
STEPS / TIMELINE — what the agent did, in order
|
|
657
|
+
================================================================ -->
|
|
658
|
+
<section data-section="steps" class="card p-8">
|
|
659
|
+
<h2 class="font-display text-2xl text-ink-0 mb-6">Process</h2>
|
|
660
|
+
<ol class="space-y-2">
|
|
661
|
+
<li class="step">
|
|
662
|
+
<div class="step-dot">1</div>
|
|
663
|
+
<div>
|
|
664
|
+
<h4 class="font-medium text-ink-0">{{STEP_1_TITLE}}</h4>
|
|
665
|
+
<p class="text-ink-1 text-sm mt-1">{{STEP_1_DESC}}</p>
|
|
666
|
+
</div>
|
|
667
|
+
</li>
|
|
668
|
+
<li class="step">
|
|
669
|
+
<div class="step-dot">2</div>
|
|
670
|
+
<div>
|
|
671
|
+
<h4 class="font-medium text-ink-0">{{STEP_2_TITLE}}</h4>
|
|
672
|
+
<p class="text-ink-1 text-sm mt-1">{{STEP_2_DESC}}</p>
|
|
673
|
+
</div>
|
|
674
|
+
</li>
|
|
675
|
+
<li class="step">
|
|
676
|
+
<div class="step-dot">3</div>
|
|
677
|
+
<div>
|
|
678
|
+
<h4 class="font-medium text-ink-0">{{STEP_3_TITLE}}</h4>
|
|
679
|
+
<p class="text-ink-1 text-sm mt-1">{{STEP_3_DESC}}</p>
|
|
680
|
+
</div>
|
|
681
|
+
</li>
|
|
682
|
+
<li class="step">
|
|
683
|
+
<div class="step-dot">4</div>
|
|
684
|
+
<div>
|
|
685
|
+
<h4 class="font-medium text-ink-0">{{STEP_4_TITLE}}</h4>
|
|
686
|
+
<p class="text-ink-1 text-sm mt-1">{{STEP_4_DESC}}</p>
|
|
687
|
+
</div>
|
|
688
|
+
</li>
|
|
689
|
+
</ol>
|
|
690
|
+
</section>
|
|
691
|
+
|
|
692
|
+
<!-- ================================================================
|
|
693
|
+
FILES TOUCHED
|
|
694
|
+
================================================================ -->
|
|
695
|
+
<section data-section="files" class="card p-8">
|
|
696
|
+
<h2 class="font-display text-2xl text-ink-0 mb-4">Files touched</h2>
|
|
697
|
+
<div class="space-y-1">
|
|
698
|
+
<div class="file-row">
|
|
699
|
+
<svg class="file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
700
|
+
<path d="M13 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V9z"></path>
|
|
701
|
+
<polyline points="13 2 13 9 20 9"></polyline>
|
|
702
|
+
</svg>
|
|
703
|
+
<span class="flex-1 text-ink-1">{{FILE_1_PATH}}</span>
|
|
704
|
+
<span class="pill pill-success text-xs">{{FILE_1_DELTA}}</span>
|
|
705
|
+
</div>
|
|
706
|
+
<div class="file-row">
|
|
707
|
+
<svg class="file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
708
|
+
<path d="M13 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V9z"></path>
|
|
709
|
+
<polyline points="13 2 13 9 20 9"></polyline>
|
|
710
|
+
</svg>
|
|
711
|
+
<span class="flex-1 text-ink-1">{{FILE_2_PATH}}</span>
|
|
712
|
+
<span class="pill pill-warning text-xs">{{FILE_2_DELTA}}</span>
|
|
713
|
+
</div>
|
|
714
|
+
<div class="file-row">
|
|
715
|
+
<svg class="file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
716
|
+
<path d="M13 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V9z"></path>
|
|
717
|
+
<polyline points="13 2 13 9 20 9"></polyline>
|
|
718
|
+
</svg>
|
|
719
|
+
<span class="flex-1 text-ink-1">{{FILE_3_PATH}}</span>
|
|
720
|
+
<span class="pill text-xs">{{FILE_3_DELTA}}</span>
|
|
721
|
+
</div>
|
|
722
|
+
</div>
|
|
723
|
+
</section>
|
|
724
|
+
|
|
725
|
+
<!-- ================================================================
|
|
726
|
+
NEXT STEPS
|
|
727
|
+
================================================================ -->
|
|
728
|
+
<section data-section="next-steps" class="card p-8">
|
|
729
|
+
<h2 class="font-display text-2xl text-ink-0 mb-4">Next steps</h2>
|
|
730
|
+
<ul class="space-y-3 text-ink-1">
|
|
731
|
+
<li class="flex items-start gap-3">
|
|
732
|
+
<span class="step-dot !w-6 !h-6 !text-xs">1</span>
|
|
733
|
+
<span>{{NEXT_STEP_1}}</span>
|
|
734
|
+
</li>
|
|
735
|
+
<li class="flex items-start gap-3">
|
|
736
|
+
<span class="step-dot !w-6 !h-6 !text-xs">2</span>
|
|
737
|
+
<span>{{NEXT_STEP_2}}</span>
|
|
738
|
+
</li>
|
|
739
|
+
<li class="flex items-start gap-3">
|
|
740
|
+
<span class="step-dot !w-6 !h-6 !text-xs">3</span>
|
|
741
|
+
<span>{{NEXT_STEP_3}}</span>
|
|
742
|
+
</li>
|
|
743
|
+
</ul>
|
|
744
|
+
</section>
|
|
745
|
+
|
|
746
|
+
<!-- ================================================================
|
|
747
|
+
FOOTER
|
|
748
|
+
================================================================ -->
|
|
749
|
+
<footer class="border-t border-line pt-8 pb-12">
|
|
750
|
+
<div class="flex flex-col md:flex-row items-start md:items-center justify-between gap-4">
|
|
751
|
+
<div>
|
|
752
|
+
<div class="text-xs text-ink-2 uppercase tracking-wider mb-1">Generated by</div>
|
|
753
|
+
<div class="signature text-2xl">{{AGENT_NAME}}</div>
|
|
754
|
+
</div>
|
|
755
|
+
<div class="flex items-center gap-3 text-sm">
|
|
756
|
+
<a href="/" class="text-ink-1 hover:text-ink-0 transition flex items-center gap-1.5">
|
|
757
|
+
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
758
|
+
<path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
|
|
759
|
+
</svg>
|
|
760
|
+
Dashboard
|
|
761
|
+
</a>
|
|
762
|
+
<span class="text-ink-3">·</span>
|
|
763
|
+
<a href="#" class="text-ink-1 hover:text-ink-0 transition">View task</a>
|
|
764
|
+
<span class="text-ink-3">·</span>
|
|
765
|
+
<a href="#" class="text-ink-1 hover:text-ink-0 transition">Share artifact</a>
|
|
766
|
+
</div>
|
|
767
|
+
</div>
|
|
768
|
+
<p class="text-xs text-ink-2 mt-4">
|
|
769
|
+
Built with HTMX · Alpine.js · Tailwind CSS · highlight.js
|
|
770
|
+
</p>
|
|
771
|
+
</footer>
|
|
772
|
+
|
|
773
|
+
</main>
|
|
774
|
+
|
|
775
|
+
<!-- HTMX, Alpine.js, highlight.js. All `defer` so they don't block. -->
|
|
776
|
+
<script src="https://unpkg.com/htmx.org@1.9.12" defer></script>
|
|
777
|
+
<script src="https://cdn.jsdelivr.net/npm/alpinejs@3.13.5/dist/cdn.min.js" defer></script>
|
|
778
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" defer></script>
|
|
779
|
+
<script>
|
|
780
|
+
// Once the page is fully loaded, syntax-highlight any <pre><code>
|
|
781
|
+
// blocks. The CDN script is `defer`-ed so we wait for it.
|
|
782
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
783
|
+
// highlight.js may have finished loading by DOMContentLoaded when
|
|
784
|
+
// the page is fast; otherwise poll briefly.
|
|
785
|
+
function tryHighlight(attempts) {
|
|
786
|
+
if (window.hljs) {
|
|
787
|
+
document.querySelectorAll('pre.codeblock code').forEach(function (el) {
|
|
788
|
+
try { window.hljs.highlightElement(el); } catch (e) { /* ignore */ }
|
|
789
|
+
});
|
|
790
|
+
} else if (attempts > 0) {
|
|
791
|
+
setTimeout(function () { tryHighlight(attempts - 1); }, 50);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
tryHighlight(20);
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
// Tiny enhancement: format the HTMX demo response as pretty JSON
|
|
798
|
+
// (it arrives as a string when the response Content-Type is not
|
|
799
|
+
// application/json). We listen to htmx:afterSwap to re-render.
|
|
800
|
+
document.addEventListener('htmx:afterSwap', function (evt) {
|
|
801
|
+
if (evt.target && evt.target.id === 'demo-region') {
|
|
802
|
+
try {
|
|
803
|
+
const obj = JSON.parse(evt.target.textContent);
|
|
804
|
+
evt.target.textContent = JSON.stringify(obj, null, 2);
|
|
805
|
+
} catch (e) { /* leave as-is */ }
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
</script>
|
|
809
|
+
</body>
|
|
810
|
+
</html>
|