@polderlabs/bizar 8.1.0 → 9.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/.claude/worktrees/kanban-overhaul/.claude/CLAUDE.md +15 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/_shared/AGENT_BASELINE.md +168 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/_shared/CLAUDE_TOOLS.md +412 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/_shared/SKILLS.md +109 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/agent-browser.md +80 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/baldr.md +49 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/forseti.md +51 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/frigg.md +42 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/heimdall.md +33 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/hermod.md +53 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/mimir.md +49 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/odin.md +287 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/quick.md +34 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/semble-search.md +50 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/thor.md +53 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/tyr.md +56 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/vidarr.md +54 -0
- package/.claude/worktrees/kanban-overhaul/.claude/agents/vor.md +53 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/audit.md +25 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/bizar.md +22 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/explain.md +17 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/init.md +29 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/learn.md +44 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/plan.md +35 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/plow-through.md +50 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/pr-review.md +49 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/setup-provider.md +96 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/tailscale-serve.md +100 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/team.md +132 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/test.md +62 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/validate.md +68 -0
- package/.claude/worktrees/kanban-overhaul/.claude/commands/visual-plan.md +24 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/README.md +92 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/posttooluse-editwrite.mjs +91 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/pretooluse-bash.mjs +81 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/pretooluse-editwrite.mjs +139 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/sessionend-recall.mjs +74 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/sessionstart-prime.mjs +80 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/userpromptsubmit-tag.mjs +80 -0
- package/.claude/worktrees/kanban-overhaul/.claude/hooks/worker-suggest.mjs +110 -0
- package/.claude/worktrees/kanban-overhaul/.claude/settings.json +125 -0
- package/.claude/worktrees/kanban-overhaul/.claude/settings.local.json +8 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router/SKILL.md +80 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-chat/SKILL.md +73 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-embeddings/SKILL.md +69 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-image/SKILL.md +86 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-stt/SKILL.md +79 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-tts/SKILL.md +80 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-web-fetch/SKILL.md +99 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-web-search/SKILL.md +91 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/bizar/README.md +9 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/bizar/SKILL.md +450 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/README.md +28 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/README.md +28 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/SKILL.md +304 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/coverage.md +370 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/mocking.md +364 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/cubesandbox/SKILL.md +148 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/README.md +41 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/glyph/SKILL.md +163 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/harness-engineering/SKILL.md +143 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/lightrag/SKILL.md +81 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/memory-protocol/SKILL.md +105 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/obsidian/SKILL.md +306 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
- package/.claude/worktrees/kanban-overhaul/.claude/skills/self-improvement/SKILL.md +64 -0
- package/.claude/worktrees/kanban-overhaul/.dockerignore +31 -0
- package/.claude/worktrees/kanban-overhaul/.gitattributes +27 -0
- package/.claude/worktrees/kanban-overhaul/.harness/agents.json +17 -0
- package/.claude/worktrees/kanban-overhaul/.harness/arch-rules.json +69 -0
- package/.claude/worktrees/kanban-overhaul/.harness/topology.json +4 -0
- package/.claude/worktrees/kanban-overhaul/.nvmrc +1 -0
- package/.claude/worktrees/kanban-overhaul/.serena/project.yml +159 -0
- package/.claude/worktrees/kanban-overhaul/AGENTS.md +250 -0
- package/.claude/worktrees/kanban-overhaul/CHANGELOG.md +5410 -0
- package/.claude/worktrees/kanban-overhaul/CLAUDE.md +260 -0
- package/.claude/worktrees/kanban-overhaul/CURRENT_ISSUES_ AND_NEW_FEATURES.md +18 -0
- package/.claude/worktrees/kanban-overhaul/DECISIONS.md +66 -0
- package/.claude/worktrees/kanban-overhaul/Dockerfile +48 -0
- package/.claude/worktrees/kanban-overhaul/FINAL_GOAL.md +397 -0
- package/.claude/worktrees/kanban-overhaul/IMPLEMENTATION_PLAN.md +250 -0
- package/.claude/worktrees/kanban-overhaul/LICENSE +21 -0
- package/.claude/worktrees/kanban-overhaul/MILESTONES.md +257 -0
- package/.claude/worktrees/kanban-overhaul/Makefile +93 -0
- package/.claude/worktrees/kanban-overhaul/PROGRESS.md +1406 -0
- package/.claude/worktrees/kanban-overhaul/README.md +483 -0
- package/.claude/worktrees/kanban-overhaul/ROADMAP.md +609 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.graphifyignore +40 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.obsidian/README.md +14 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.obsidian/daily/2026-06-25.md +9 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.obsidian/vault.json +7 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/SKILL.md +103 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/assets/template.html +338 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/example.html +81 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/open-design.json +172 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/references/checklist.md +44 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/references/layouts.md +247 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/ARCHITECTURE.md +197 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/CHANGELOG.md +235 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/DESIGN.md +912 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/GLYPH.md +418 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/PLAN.md +1135 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/critique.json +26 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/plans/debug-plan/comments.json +1 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/plans/debug-plan/meta.json +10 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/plans/debug-plan/plan.json +174 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/scripts/smoke-bg-retry.mjs +246 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/agent-baseline/SKILL.md +80 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/agent-browser/SKILL.md +181 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/bizar/SKILL.md +116 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/chat/SKILL.md +74 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/eval/SKILL.md +237 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/headroom/SKILL.md +94 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/lightrag/SKILL.md +86 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/minimax/SKILL.md +80 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/obsidian/SKILL.md +68 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/providers/SKILL.md +75 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/publishing/SKILL.md +146 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/sdk/SKILL.md +138 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/self-improvement/SKILL.md +53 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/skills-cli/SKILL.md +94 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/usage/SKILL.md +62 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/cli/dashboard-ports.mjs +488 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/cli.mjs +537 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/activity-log.mjs +174 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/agents-store.mjs +465 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/api.mjs +223 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/artifact-template.html +810 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/artifacts-store.mjs +733 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/auth.mjs +548 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/background-store.mjs +446 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/backup-store.mjs +530 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/bg-poller.mjs +375 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/bg-retry.mjs +446 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/bg-spawner.mjs +390 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/browser.mjs +40 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-bg-spawner.mjs +390 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-info.mjs +412 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-runner.mjs +284 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-sdk.mjs +191 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/diagnostics-store.mjs +598 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/dialog-poller.mjs +105 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/dialog-store.mjs +177 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/digest-store.mjs +558 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/eval-store.mjs +281 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/eval.mjs +500 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/glyphs/mdx-compiler.mjs +596 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/headroom.mjs +649 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/lib/path-safe.mjs +283 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/lib/rate-limit.mjs +122 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/logger.mjs +71 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-consolidator.mjs +225 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-distillation.mjs +296 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-git.mjs +473 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-lightrag.mjs +1478 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-obsidian.mjs +230 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-schema.mjs +145 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-secrets.mjs +84 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-store.mjs +1093 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/metrics.mjs +268 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/minimax-usage-store.mjs +372 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/minimax.mjs +683 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/mod-security.mjs +398 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/mods-loader.mjs +1243 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/notifications-store.mjs +243 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/obsidian-store.mjs +318 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/ocr.mjs +55 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/otel.mjs +260 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/pair-store.mjs +138 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/progress-parser.mjs +221 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/projects-store.mjs +364 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/providers-store.mjs +1801 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/_shared.mjs +447 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/activity.mjs +195 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/agents-cc.mjs +194 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/agents.mjs +134 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/artifacts.mjs +279 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/auth.mjs +69 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/background.mjs +422 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/backup.mjs +112 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/chat.mjs +727 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/claude-session-detail.mjs +329 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/claude-sessions.mjs +259 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/clipboard.mjs +173 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/config.mjs +180 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/diagnostics.mjs +50 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/dialogs.mjs +86 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/digests.mjs +82 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/distill.mjs +129 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/doctor.mjs +71 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/env-vars.mjs +231 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/eval.mjs +187 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/fs.mjs +429 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/goal-planner.mjs +236 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/goals.mjs +212 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/headroom.mjs +126 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/history.mjs +78 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/lightrag.mjs +169 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/memory.mjs +1524 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/minimax.mjs +133 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/misc.mjs +90 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/mods.mjs +359 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/notifications.mjs +54 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/obsidian.mjs +239 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/ocr.mjs +182 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/overview.mjs +92 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/pair.mjs +67 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/projects.mjs +175 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/providers.mjs +308 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/schedules.mjs +159 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/settings.mjs +51 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/skills.mjs +65 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/tailscale.mjs +46 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/tasks.mjs +518 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/themes.mjs +51 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/update.mjs +340 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/usage.mjs +136 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/users.mjs +102 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/voice.mjs +167 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/workspaces.mjs +299 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/auth.mjs +59 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/events.mjs +121 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/health.mjs +21 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/index.mjs +90 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/sessions.mjs +111 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/schedules-runner.mjs +556 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/schedules-store.mjs +268 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/search-store.mjs +220 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/serve-info.mjs +1110 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/server.mjs +966 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/settings-store.mjs +45 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/skills-store.mjs +190 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/state.mjs +437 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/tailscale-store.mjs +113 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/task-delegator.mjs +969 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/tasks-store.mjs +556 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/tui.mjs +923 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/update-store.mjs +168 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/v2-auth-file.mjs +99 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/v2-event-bus.mjs +128 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/voice-store.mjs +229 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/voice-transcribe.mjs +72 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/watcher.mjs +81 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/workers/transcription-worker.mjs +213 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/workspaces.mjs +626 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/yaml.mjs +238 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/App.tsx +200 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/fetcher.ts +59 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/types.ts +168 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/useFetch.ts +62 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/useWebSocket.ts +153 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/main.tsx +28 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/AppShell.tsx +90 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/PageSkeleton.tsx +29 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/Sidebar.tsx +361 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/StatusBar.tsx +63 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/Topbar.tsx +113 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/index.ts +15 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/activity/ActivityFeed.tsx +137 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/agents/AgentActivity.tsx +101 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/agents/AgentCard.tsx +158 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/agents/AgentDetail.tsx +232 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Button.tsx +141 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/ButtonGroup.tsx +32 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Checkbox.tsx +49 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Field.tsx +78 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Form.tsx +23 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/IconButton.tsx +112 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Input.tsx +94 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/RadioGroup.tsx +74 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Select.tsx +171 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Slider.tsx +68 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Switch.tsx +56 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Textarea.tsx +64 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Toggle.tsx +36 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/ToggleGroup.tsx +85 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Accordion.tsx +134 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Avatar.tsx +175 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Badge.tsx +93 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/BarList.tsx +101 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Card.tsx +140 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Chip.tsx +96 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Kbd.tsx +42 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/ProgressBar.tsx +93 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Sparkline.tsx +98 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/StatTile.tsx +150 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Table.tsx +170 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Timeline.tsx +130 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/ViewHeader.tsx +122 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Alert.tsx +95 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Banner.tsx +39 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/ContextMenu.tsx +143 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Dialog.tsx +149 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Drawer.tsx +8 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/DropdownMenu.tsx +231 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/EmptyState.tsx +48 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Popover.tsx +56 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Sheet.tsx +103 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Skeleton.tsx +67 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Spinner.tsx +30 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Toast.tsx +66 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Tooltip.tsx +89 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/goals/GoalCard.tsx +176 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/goals/GoalDetail.tsx +245 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/goals/KeyResult.tsx +115 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/index.ts +349 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanBoard.tsx +115 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanCard.tsx +391 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanCardBadges.tsx +111 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanColumn.tsx +181 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanContextMenu.tsx +126 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanDetailDialog.tsx +638 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanEmptyColumn.tsx +43 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanProgress.tsx +130 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanQuickAdd.tsx +141 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanToolbar.tsx +291 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/useKanbanSelection.ts +90 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/libraries/LibraryGrid.tsx +30 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/libraries/LibraryItem.tsx +161 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/memory/MemoryVault.tsx +144 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/CommandPalette.tsx +224 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/NavLink.tsx +81 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/Pagination.tsx +164 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/Tabs.tsx +128 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Box.tsx +144 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Center.tsx +40 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Cluster.tsx +67 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Grid.tsx +104 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Inline.tsx +77 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Portal.tsx +33 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/ScrollArea.tsx +62 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Separator.tsx +42 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Stack.tsx +73 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/VisuallyHidden.tsx +49 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/settings/SettingsNav.tsx +91 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/settings/SettingsRow.tsx +88 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/settings/SettingsSection.tsx +109 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/styles/globals.css +220 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/styles/reset.css +57 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/styles/tokens.css +217 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/DensityProvider.tsx +66 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/ThemeProvider.tsx +94 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/ThemeToggle.tsx +88 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/useDensity.ts +15 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/useTheme.ts +16 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/utils/cx.ts +19 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Activity/ActivityView.tsx +71 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +172 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +247 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Goals/GoalsView.tsx +137 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Libraries/LibrariesView.tsx +108 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Memory/MemoryView.tsx +77 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +152 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Router.tsx +72 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Settings/SettingsView.tsx +330 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Tasks/CommandPalettePlaceholder.tsx +106 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Tasks/TasksView.tsx +792 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/vite-env.d.ts +15 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8.html +17 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/FORMAT.md +76 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/README.md +19 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/agents/greeter.md +8 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/commands/hello.md +6 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/mod.json +20 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/routes/ping.mjs +9 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/views/HelloView.tsx +10 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/tests/setup.ts +63 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/tests/smoke-v2.mjs +212 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/tsconfig.json +23 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/vite.config.ts +66 -0
- package/.claude/worktrees/kanban-overhaul/bizar-dash/vitest.config.ts +20 -0
- package/.claude/worktrees/kanban-overhaul/bizar-plugins/registry.json +62 -0
- package/.claude/worktrees/kanban-overhaul/bookmarklet/bizar-clipper.js +48 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/README.md +43 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/background.js +95 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/content.js +170 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon-128.png +0 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon-16.png +0 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon-48.png +0 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon.svg +4 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/manifest.json +32 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/popup.html +66 -0
- package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/popup.js +110 -0
- package/.claude/worktrees/kanban-overhaul/bun.lock +1558 -0
- package/.claude/worktrees/kanban-overhaul/cli/agent-browser-up.sh +152 -0
- package/.claude/worktrees/kanban-overhaul/cli/agent-browser-update.mjs +322 -0
- package/.claude/worktrees/kanban-overhaul/cli/artifact-cli.mjs +605 -0
- package/.claude/worktrees/kanban-overhaul/cli/artifact-render.mjs +621 -0
- package/.claude/worktrees/kanban-overhaul/cli/artifact-server.mjs +847 -0
- package/.claude/worktrees/kanban-overhaul/cli/artifact-templates.mjs +523 -0
- package/.claude/worktrees/kanban-overhaul/cli/artifact.mjs +63 -0
- package/.claude/worktrees/kanban-overhaul/cli/atomic.mjs +73 -0
- package/.claude/worktrees/kanban-overhaul/cli/audit.mjs +141 -0
- package/.claude/worktrees/kanban-overhaul/cli/banner.mjs +41 -0
- package/.claude/worktrees/kanban-overhaul/cli/bg.mjs +471 -0
- package/.claude/worktrees/kanban-overhaul/cli/bin.mjs +698 -0
- package/.claude/worktrees/kanban-overhaul/cli/bootstrap.mjs +77 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/artifact.mjs +20 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/claim.mjs +282 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/claude-cmd.mjs +348 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/clip.mjs +163 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/cost.mjs +279 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/dash.mjs +193 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/cloudflare.mjs +250 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/docker.mjs +222 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/fly.mjs +161 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/vercel.mjs +225 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/deploy.mjs +240 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/eval.mjs +396 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/headroom.mjs +204 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/install.mjs +170 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/lightrag.mjs +170 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/marketplace.mjs +64 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/memory.mjs +25 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/minimax.mjs +288 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/mod.mjs +185 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/ocr.mjs +182 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/plugin.mjs +358 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/rca.mjs +198 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/sandbox.mjs +220 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/service.mjs +79 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/setup-provider.mjs +466 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/tailscale.mjs +258 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/usage.mjs +113 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/util.mjs +577 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/validate.mjs +541 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/voice.mjs +211 -0
- package/.claude/worktrees/kanban-overhaul/cli/commands/workspace.mjs +247 -0
- package/.claude/worktrees/kanban-overhaul/cli/copy.mjs +586 -0
- package/.claude/worktrees/kanban-overhaul/cli/cost-gate.mjs +501 -0
- package/.claude/worktrees/kanban-overhaul/cli/dev-link.mjs +191 -0
- package/.claude/worktrees/kanban-overhaul/cli/digest.mjs +149 -0
- package/.claude/worktrees/kanban-overhaul/cli/doctor.mjs +217 -0
- package/.claude/worktrees/kanban-overhaul/cli/export.mjs +95 -0
- package/.claude/worktrees/kanban-overhaul/cli/feature-list-bridge.mjs +400 -0
- package/.claude/worktrees/kanban-overhaul/cli/heads-up.mjs +295 -0
- package/.claude/worktrees/kanban-overhaul/cli/init.mjs +368 -0
- package/.claude/worktrees/kanban-overhaul/cli/install.mjs +640 -0
- package/.claude/worktrees/kanban-overhaul/cli/memory-constants.mjs +76 -0
- package/.claude/worktrees/kanban-overhaul/cli/memory.mjs +1850 -0
- package/.claude/worktrees/kanban-overhaul/cli/plugin-runtime-deps.mjs +250 -0
- package/.claude/worktrees/kanban-overhaul/cli/post-install-smoke.mjs +256 -0
- package/.claude/worktrees/kanban-overhaul/cli/prompts.mjs +168 -0
- package/.claude/worktrees/kanban-overhaul/cli/providers-detect.mjs +233 -0
- package/.claude/worktrees/kanban-overhaul/cli/provision-claude.mjs +1176 -0
- package/.claude/worktrees/kanban-overhaul/cli/provision.mjs +2233 -0
- package/.claude/worktrees/kanban-overhaul/cli/repair.mjs +209 -0
- package/.claude/worktrees/kanban-overhaul/cli/service-controller.mjs +927 -0
- package/.claude/worktrees/kanban-overhaul/cli/service-env.mjs +139 -0
- package/.claude/worktrees/kanban-overhaul/cli/service.mjs +492 -0
- package/.claude/worktrees/kanban-overhaul/cli/update.mjs +29 -0
- package/.claude/worktrees/kanban-overhaul/cli/utils.mjs +221 -0
- package/.claude/worktrees/kanban-overhaul/cli/worker-dispatcher.mjs +259 -0
- package/.claude/worktrees/kanban-overhaul/config/AGENTS.md +595 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/_shared/AGENT_BASELINE.md +155 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/_shared/CLINE_TOOLS.md +398 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/_shared/SKILLS.md +109 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/agent-browser.md +90 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/baldr.md +60 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/forseti.md +60 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/frigg.md +52 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/heimdall.md +44 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/hermod.md +64 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/mimir.md +60 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/odin.md +310 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/quick.md +47 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/semble-search.md +59 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/thor.md +64 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/tyr.md +67 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/vidarr.md +65 -0
- package/.claude/worktrees/kanban-overhaul/config/agents/vor.md +62 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/audit.md +5 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/bizar.md +22 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/explain.md +5 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/init.md +26 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/learn.md +5 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/plan.md +30 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/plow-through.md +47 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/pr-review.md +5 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/setup-provider.md +95 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/tailscale-serve.md +97 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/team.md +124 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/test.md +60 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/validate.md +66 -0
- package/.claude/worktrees/kanban-overhaul/config/commands/visual-plan.md +19 -0
- package/.claude/worktrees/kanban-overhaul/config/hooks/PostToolUse +66 -0
- package/.claude/worktrees/kanban-overhaul/config/hooks/PreToolUse +82 -0
- package/.claude/worktrees/kanban-overhaul/config/hooks/README.md +68 -0
- package/.claude/worktrees/kanban-overhaul/config/hooks/TaskResume +48 -0
- package/.claude/worktrees/kanban-overhaul/config/hooks/TaskStart +47 -0
- package/.claude/worktrees/kanban-overhaul/config/hooks/UserPromptSubmit +55 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/general.md +9 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/git.md +11 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/javascript.md +10 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/python.md +10 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/testing.md +10 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/thinking.md +56 -0
- package/.claude/worktrees/kanban-overhaul/config/rules/uncertainty.md +70 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router/SKILL.md +80 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-chat/SKILL.md +73 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-embeddings/SKILL.md +69 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-image/SKILL.md +86 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-stt/SKILL.md +79 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-tts/SKILL.md +80 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-web-fetch/SKILL.md +99 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/9router-web-search/SKILL.md +91 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/bizar/README.md +9 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/bizar/SKILL.md +447 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/README.md +28 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/SKILL.md +634 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/agents/openai.yaml +4 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/concurrency.md +320 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/error-handling.md +229 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/memory-safety.md +216 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/review-checklist.md +96 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/README.md +28 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/SKILL.md +304 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/agents/openai.yaml +4 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/coverage.md +370 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/framework-compare.md +175 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/mocking.md +364 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/tdd-workflow.md +308 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/cubesandbox/SKILL.md +148 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/README.md +41 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/SKILL.md +439 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/agents/openai.yaml +4 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/host-tests.md +164 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/kconfig.md +159 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/nvs.md +121 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/packed-structs.md +192 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/glyph/SKILL.md +163 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/harness-engineering/SKILL.md +142 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/lightrag/SKILL.md +81 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/memory-protocol/SKILL.md +105 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/obsidian/SKILL.md +306 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/read-the-damn-docs/SKILL.md +113 -0
- package/.claude/worktrees/kanban-overhaul/config/skills/self-improvement/SKILL.md +64 -0
- package/.claude/worktrees/kanban-overhaul/config/trigger-patterns.json +186 -0
- package/.claude/worktrees/kanban-overhaul/docker-compose.yml +50 -0
- package/.claude/worktrees/kanban-overhaul/docs/A11Y.md +81 -0
- package/.claude/worktrees/kanban-overhaul/docs/DEPLOY.md +360 -0
- package/.claude/worktrees/kanban-overhaul/docs/DOCKER.md +250 -0
- package/.claude/worktrees/kanban-overhaul/docs/INDEX.md +223 -0
- package/.claude/worktrees/kanban-overhaul/docs/PLUGIN_REGISTRY.md +107 -0
- package/.claude/worktrees/kanban-overhaul/docs/RELEASING.md +693 -0
- package/.claude/worktrees/kanban-overhaul/docs/architecture.md +317 -0
- package/.claude/worktrees/kanban-overhaul/docs/code-review.md +242 -0
- package/.claude/worktrees/kanban-overhaul/docs/curator.md +144 -0
- package/.claude/worktrees/kanban-overhaul/docs/dashboard-ui-migration.md +807 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-001-cline-rewrite.md +114 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-002-in-process-clinecore.md +139 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-003-in-process-memory-vault.md +101 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-004-cline-agent-teams.md +112 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-005-bg-agents-via-dashboard.md +77 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-006-kanban-board.md +69 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-007-tool-approval-gate.md +147 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-008-skill-curator.md +100 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-009-pre-compaction-flush.md +106 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-010-knowledge-graph-tools.md +95 -0
- package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-011-claude-code-migration.md +172 -0
- package/.claude/worktrees/kanban-overhaul/docs/graph-tools.md +130 -0
- package/.claude/worktrees/kanban-overhaul/docs/migration-guide.md +471 -0
- package/.claude/worktrees/kanban-overhaul/docs/migrations/cline-replacement.md +118 -0
- package/.claude/worktrees/kanban-overhaul/docs/postmortems/2026-06-18-plugin-state-deadlock.md +250 -0
- package/.claude/worktrees/kanban-overhaul/docs/quality-document.md +74 -0
- package/.claude/worktrees/kanban-overhaul/docs/releases/v0.5.2.md +66 -0
- package/.claude/worktrees/kanban-overhaul/docs/releases/v0.5.4.md +85 -0
- package/.claude/worktrees/kanban-overhaul/docs/releases/v2.3.0.md +96 -0
- package/.claude/worktrees/kanban-overhaul/docs/releases/v3.24.0.md +155 -0
- package/.claude/worktrees/kanban-overhaul/docs/releases/v4.0.0.md +123 -0
- package/.claude/worktrees/kanban-overhaul/docs/releases/v7.0.0.md +173 -0
- package/.claude/worktrees/kanban-overhaul/docs/safety.md +216 -0
- package/.claude/worktrees/kanban-overhaul/feature_list.json +1297 -0
- package/.claude/worktrees/kanban-overhaul/init.sh +211 -0
- package/.claude/worktrees/kanban-overhaul/install.sh +498 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/INSTRUCTIONS.md +82 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/mod.json +37 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/route.mjs +136 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/web/index.html +180 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/INSTRUCTIONS.md +81 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/mod.json +61 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/route.mjs +461 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/web/index.html +263 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/INSTRUCTIONS.md +87 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/agents/thor.md +64 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/mod.json +36 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/route.mjs +98 -0
- package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/web/index.html +126 -0
- package/.claude/worktrees/kanban-overhaul/package.json +154 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/ARCHITECTURE.md +70 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/LICENSE +21 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/README.md +80 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/package.json +30 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/agent-registry.ts +304 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/byzantine.ts +587 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/index.ts +147 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/queen.ts +173 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/types.ts +199 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/dangerous-patterns.ts +127 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/audit.ts +156 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/budget.ts +269 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/envelope.ts +144 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/hmac.ts +160 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/index.ts +443 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/pii.ts +241 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/policy.ts +112 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/trust.ts +146 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/fingerprint.ts +0 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/index.ts +114 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/mcp/bin.ts +51 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/mcp/server.ts +848 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/memory/index.ts +160 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/codemod-intent.ts +125 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/index.ts +247 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/memory-distillation-shim.mjs +18 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/memory-distillation.ts +249 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/model-router.ts +235 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/q-learning-router.ts +304 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/swarm-topology.ts +279 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/src/version.ts +4 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/tsconfig.json +25 -0
- package/.claude/worktrees/kanban-overhaul/packages/sdk/vitest.config.ts +9 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/ARCHITECTURE.md +72 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/CONSTRAINTS.md +62 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/LICENSE +21 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/README.md +46 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/index.ts +50 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/package.json +18 -0
- package/.claude/worktrees/kanban-overhaul/plugins/bizar/tsconfig.json +29 -0
- package/.claude/worktrees/kanban-overhaul/scripts/bh-full-e2e.mjs +298 -0
- package/.claude/worktrees/kanban-overhaul/scripts/check-agents.mjs +73 -0
- package/.claude/worktrees/kanban-overhaul/scripts/check-arch.sh +80 -0
- package/.claude/worktrees/kanban-overhaul/scripts/check-deps.mjs +492 -0
- package/.claude/worktrees/kanban-overhaul/scripts/clean-state-check.sh +81 -0
- package/.claude/worktrees/kanban-overhaul/scripts/git-hooks/pre-commit +59 -0
- package/.claude/worktrees/kanban-overhaul/scripts/git-hooks/pre-push +54 -0
- package/.claude/worktrees/kanban-overhaul/scripts/install-hooks.sh +29 -0
- package/.claude/worktrees/kanban-overhaul/scripts/install-service.mjs +190 -0
- package/.claude/worktrees/kanban-overhaul/scripts/mirror-claude-md.sh +78 -0
- package/.claude/worktrees/kanban-overhaul/scripts/session-trace.sh +52 -0
- package/.claude/worktrees/kanban-overhaul/scripts/test-in-container.sh +157 -0
- package/.claude/worktrees/kanban-overhaul/scripts/verify-feature.sh +102 -0
- package/.claude/worktrees/kanban-overhaul/skills-lock.json +11 -0
- package/.claude/worktrees/kanban-overhaul/templates/clean-state-checklist.md +55 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/cloudflare/README.md +32 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/cloudflare/functions-index.template.js +15 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/cloudflare/wrangler.toml.template +9 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/docker/.env.template +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/docker/README.md +58 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/docker/docker-compose.template.yml +23 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/fly/README.md +35 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/fly/fly.toml.template +28 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/vercel/README.md +29 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/vercel/api-index.template.js +18 -0
- package/.claude/worktrees/kanban-overhaul/templates/deploy/vercel/vercel.json.template +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/README.md +58 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/citation.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/code-review.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/code-search-basic.json +28 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/concise-output.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/context-window.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/error-recovery.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/json-output.json +20 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/latency-bounds.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/multi-language.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/regression-suite.json +79 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/response-format.json +30 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/safe-paths.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/tool-call-correctness.json +24 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/tool-call-multi-step.json +18 -0
- package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/unicode-handling.json +16 -0
- package/.claude/worktrees/kanban-overhaul/templates/evaluator-rubric.md +50 -0
- package/.claude/worktrees/kanban-overhaul/templates/plan/htmx.min.js +1 -0
- package/.claude/worktrees/kanban-overhaul/templates/plan/library/bug-investigation.mdx +79 -0
- package/.claude/worktrees/kanban-overhaul/templates/plan/library/decision-record.mdx +71 -0
- package/.claude/worktrees/kanban-overhaul/templates/plan/library/feature-design.mdx +92 -0
- package/.claude/worktrees/kanban-overhaul/templates/plan/meta.json.template +8 -0
- package/.claude/worktrees/kanban-overhaul/templates/plan/plan.mdx.template +46 -0
- package/.claude/worktrees/kanban-overhaul/templates/plugin-template/README.md +121 -0
- package/.claude/worktrees/kanban-overhaul/templates/plugin-template/index.js +66 -0
- package/.claude/worktrees/kanban-overhaul/templates/plugin-template/plugin.json +42 -0
- package/.claude/worktrees/kanban-overhaul/templates/plugin-template/tests/plugin.test.js +83 -0
- package/.claude/worktrees/kanban-overhaul/templates/schedules/daily-backup.json +12 -0
- package/.claude/worktrees/kanban-overhaul/templates/schedules/daily-cleanup.json +12 -0
- package/.claude/worktrees/kanban-overhaul/templates/schedules/hourly-health-check.json +12 -0
- package/.claude/worktrees/kanban-overhaul/templates/schedules/webhook-on-push.json +13 -0
- package/.claude/worktrees/kanban-overhaul/templates/schedules/weekly-digest.json +13 -0
- package/.claude/worktrees/kanban-overhaul/templates/sprint-contract.md +47 -0
- package/.claude/worktrees/kanban-overhaul/tsconfig.json +44 -0
- package/.claude/worktrees/kanban-overhaul/vite.config.ts +51 -0
- package/bizar-dash/dist/assets/ActivityFeed-BXIkGGQ1.js +16 -0
- package/bizar-dash/dist/assets/ActivityFeed-BXIkGGQ1.js.map +1 -0
- package/bizar-dash/dist/assets/ActivityView-CBxNNrZa.js +12 -0
- package/bizar-dash/dist/assets/ActivityView-CBxNNrZa.js.map +1 -0
- package/bizar-dash/dist/assets/AgentsView-uv4l21AH.js +23 -0
- package/bizar-dash/dist/assets/AgentsView-uv4l21AH.js.map +1 -0
- package/bizar-dash/dist/assets/BackgroundJobsView-CB4WXIpk.js +6 -0
- package/bizar-dash/dist/assets/BackgroundJobsView-CB4WXIpk.js.map +1 -0
- package/bizar-dash/dist/assets/{Card-BzJeYR2D.js → Card-CeZsWlcP.js} +1 -1
- package/bizar-dash/dist/assets/{Card-BzJeYR2D.js.map → Card-CeZsWlcP.js.map} +1 -1
- package/bizar-dash/dist/assets/{Chip-CN2bvm7a.js → Chip-OPjSKl2I.js} +1 -1
- package/bizar-dash/dist/assets/{Chip-CN2bvm7a.js.map → Chip-OPjSKl2I.js.map} +1 -1
- package/bizar-dash/dist/assets/{EmptyState-DEiBv4-r.js → EmptyState-BrLA8mbE.js} +1 -1
- package/bizar-dash/dist/assets/{EmptyState-DEiBv4-r.js.map → EmptyState-BrLA8mbE.js.map} +1 -1
- package/bizar-dash/dist/assets/GoalsView-B8R-kxQr.js +11 -0
- package/bizar-dash/dist/assets/GoalsView-B8R-kxQr.js.map +1 -0
- package/bizar-dash/dist/assets/Grid-B7NgNtff.js +1 -0
- package/bizar-dash/dist/assets/Grid-B7NgNtff.js.map +1 -0
- package/bizar-dash/dist/assets/Input-BW_5Sl6N.js +1 -0
- package/bizar-dash/dist/assets/Input-BW_5Sl6N.js.map +1 -0
- package/bizar-dash/dist/assets/{KanbanCard-DZEaAiEr.js → KanbanCard-B-NOSfMN.js} +1 -1
- package/bizar-dash/dist/assets/{KanbanCard-DZEaAiEr.js.map → KanbanCard-B-NOSfMN.js.map} +1 -1
- package/bizar-dash/dist/assets/{LibrariesView-CPgKGPpM.js → LibrariesView-D6eB7B2A.js} +6 -6
- package/bizar-dash/dist/assets/{LibrariesView-CPgKGPpM.js.map → LibrariesView-D6eB7B2A.js.map} +1 -1
- package/bizar-dash/dist/assets/MemoryView-MK4m1KbR.js +13 -0
- package/bizar-dash/dist/assets/MemoryView-MK4m1KbR.js.map +1 -0
- package/bizar-dash/dist/assets/OverviewView-CHavfYBa.js +1 -0
- package/bizar-dash/dist/assets/{OverviewView-BDegBWgg.js.map → OverviewView-CHavfYBa.js.map} +1 -1
- package/bizar-dash/dist/assets/SchedulesView-zV-0pbsz.js +1 -0
- package/bizar-dash/dist/assets/SchedulesView-zV-0pbsz.js.map +1 -0
- package/bizar-dash/dist/assets/{Select-xwxbK8Ed.js → Select-B6Ho36Tq.js} +3 -8
- package/bizar-dash/dist/assets/Select-B6Ho36Tq.js.map +1 -0
- package/bizar-dash/dist/assets/SettingsRow-Br21uRFz.js +1 -0
- package/bizar-dash/dist/assets/SettingsRow-Br21uRFz.js.map +1 -0
- package/bizar-dash/dist/assets/SettingsView-Cx3uJrus.js +38 -0
- package/bizar-dash/dist/assets/SettingsView-Cx3uJrus.js.map +1 -0
- package/bizar-dash/dist/assets/{Sheet-C_sIEw35.js → Sheet-Cmu_4Zea.js} +1 -1
- package/bizar-dash/dist/assets/{Sheet-C_sIEw35.js.map → Sheet-Cmu_4Zea.js.map} +1 -1
- package/bizar-dash/dist/assets/Slider-B_jPr-SR.js +1 -0
- package/bizar-dash/dist/assets/Slider-B_jPr-SR.js.map +1 -0
- package/bizar-dash/dist/assets/{Sparkline-D664vGWW.js → Sparkline-Cmqw0N39.js} +1 -1
- package/bizar-dash/dist/assets/{Sparkline-D664vGWW.js.map → Sparkline-Cmqw0N39.js.map} +1 -1
- package/bizar-dash/dist/assets/Switch-C7Qyu50Y.js +10 -0
- package/bizar-dash/dist/assets/Switch-C7Qyu50Y.js.map +1 -0
- package/bizar-dash/dist/assets/TasksView-BXADmjgb.js +1 -0
- package/bizar-dash/dist/assets/TasksView-BXADmjgb.js.map +1 -0
- package/bizar-dash/dist/assets/{Textarea-Dk97nmjO.js → Textarea-KIN98DVH.js} +1 -1
- package/bizar-dash/dist/assets/{Textarea-Dk97nmjO.js.map → Textarea-KIN98DVH.js.map} +1 -1
- package/bizar-dash/dist/assets/{ViewHeader-dPd4zAyj.js → ViewHeader-CPbqI-w8.js} +1 -1
- package/bizar-dash/dist/assets/{ViewHeader-dPd4zAyj.js.map → ViewHeader-CPbqI-w8.js.map} +1 -1
- package/bizar-dash/dist/assets/{brain-BajPVibR.js → brain-jN_ldx3U.js} +1 -1
- package/bizar-dash/dist/assets/{brain-BajPVibR.js.map → brain-jN_ldx3U.js.map} +1 -1
- package/bizar-dash/dist/assets/{calendar-CaP_Bbgc.js → calendar-DZGgPP2_.js} +1 -1
- package/bizar-dash/dist/assets/{calendar-CaP_Bbgc.js.map → calendar-DZGgPP2_.js.map} +1 -1
- package/bizar-dash/dist/assets/circle-check-XhUtiACZ.js +6 -0
- package/bizar-dash/dist/assets/circle-check-XhUtiACZ.js.map +1 -0
- package/bizar-dash/dist/assets/clock-BXBnSbox.js +6 -0
- package/bizar-dash/dist/assets/clock-BXBnSbox.js.map +1 -0
- package/bizar-dash/dist/assets/{cmdk-BLWIhKrV.js → cmdk-D15rXxc5.js} +2 -2
- package/bizar-dash/dist/assets/{cmdk-BLWIhKrV.js.map → cmdk-D15rXxc5.js.map} +1 -1
- package/bizar-dash/dist/assets/{dnd-kit-DU8GZk7s.js → dnd-kit-Bormfg7j.js} +1 -1
- package/bizar-dash/dist/assets/{dnd-kit-DU8GZk7s.js.map → dnd-kit-Bormfg7j.js.map} +1 -1
- package/bizar-dash/dist/assets/{git-pull-request-CFRRwdxp.js → git-pull-request-BCt0CEjc.js} +1 -1
- package/bizar-dash/dist/assets/{git-pull-request-CFRRwdxp.js.map → git-pull-request-BCt0CEjc.js.map} +1 -1
- package/bizar-dash/dist/assets/index-C0JBGB5M.js +1 -0
- package/bizar-dash/dist/assets/index-C0JBGB5M.js.map +1 -0
- package/bizar-dash/dist/assets/index-CrWI7sQR.js +1 -0
- package/bizar-dash/dist/assets/index-CrWI7sQR.js.map +1 -0
- package/bizar-dash/dist/assets/main-CCimEcWH.js +134 -0
- package/bizar-dash/dist/assets/main-CCimEcWH.js.map +1 -0
- package/bizar-dash/dist/assets/play-B0rTjpSg.js +6 -0
- package/bizar-dash/dist/assets/play-B0rTjpSg.js.map +1 -0
- package/bizar-dash/dist/assets/{plus-CVH1JB04.js → plus-BaTQsS9G.js} +1 -1
- package/bizar-dash/dist/assets/{plus-CVH1JB04.js.map → plus-BaTQsS9G.js.map} +1 -1
- package/bizar-dash/dist/assets/refresh-cw-CoatVcs3.js +6 -0
- package/bizar-dash/dist/assets/refresh-cw-CoatVcs3.js.map +1 -0
- package/bizar-dash/dist/assets/{terminal-B2sSd5t7.js → terminal-k-1HFHcN.js} +1 -1
- package/bizar-dash/dist/assets/{terminal-B2sSd5t7.js.map → terminal-k-1HFHcN.js.map} +1 -1
- package/bizar-dash/dist/assets/{trash-2-JtYRQ79q.js → trash-2-DtpKnAn2.js} +1 -1
- package/bizar-dash/dist/assets/{trash-2-JtYRQ79q.js.map → trash-2-DtpKnAn2.js.map} +1 -1
- package/bizar-dash/dist/assets/{triangle-alert-Nzbrm0I2.js → triangle-alert-FHSs_e5b.js} +1 -1
- package/bizar-dash/dist/assets/{triangle-alert-Nzbrm0I2.js.map → triangle-alert-FHSs_e5b.js.map} +1 -1
- package/bizar-dash/dist/assets/{wrench-B7go551L.js → wrench-CbBE0oQ0.js} +2 -2
- package/bizar-dash/dist/assets/{wrench-B7go551L.js.map → wrench-CbBE0oQ0.js.map} +1 -1
- package/bizar-dash/dist/v8.html +2 -2
- package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/bizar-dash/src/server/api.mjs +5 -0
- package/bizar-dash/src/server/progress-parser.mjs +20 -4
- package/bizar-dash/src/server/routes/goals.mjs +10 -10
- package/bizar-dash/src/server/routes/spawn.mjs +59 -0
- package/bizar-dash/src/server/server.mjs +1 -1
- package/bizar-dash/src/web/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/bizar-dash/src/web/v8/App.tsx +56 -7
- package/bizar-dash/src/web/v8/__tests__/BackgroundJobsView.test.tsx +172 -0
- package/bizar-dash/src/web/v8/__tests__/MemoryView.test.tsx +91 -0
- package/bizar-dash/src/web/v8/__tests__/NotificationsPopover.test.tsx +91 -0
- package/bizar-dash/src/web/v8/__tests__/SchedulesView.test.tsx +157 -0
- package/bizar-dash/src/web/v8/__tests__/Topbar.test.tsx +86 -0
- package/bizar-dash/src/web/v8/__tests__/changelog.test.tsx +79 -0
- package/bizar-dash/src/web/v8/__tests__/theme.test.tsx +10 -4
- package/bizar-dash/src/web/v8/__tests__/views.test.tsx +6 -0
- package/bizar-dash/src/web/v8/data/types.ts +2 -0
- package/bizar-dash/src/web/v8/data/useWebSocket.ts +9 -1
- package/bizar-dash/src/web/v8/shell/Sidebar.tsx +46 -12
- package/bizar-dash/src/web/v8/shell/Topbar.tsx +30 -4
- package/bizar-dash/src/web/v8/ui/agents/AgentDetail.tsx +34 -3
- package/bizar-dash/src/web/v8/ui/agents/AgentStreamPanel.tsx +1 -1
- package/bizar-dash/src/web/v8/ui/feedback/NotificationsPopover.tsx +239 -0
- package/bizar-dash/src/web/v8/ui/goals/GoalDetail.tsx +7 -1
- package/bizar-dash/src/web/v8/views/Activity/ActivityView.tsx +393 -32
- package/bizar-dash/src/web/v8/views/BackgroundJobs/BackgroundJobsView.tsx +442 -0
- package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +22 -7
- package/bizar-dash/src/web/v8/views/Goals/GoalsView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/Memory/MemoryView.tsx +174 -20
- package/bizar-dash/src/web/v8/views/Router.tsx +10 -0
- package/bizar-dash/src/web/v8/views/Schedules/SchedulesView.tsx +395 -0
- package/bizar-dash/src/web/v8/views/Settings/SettingsView.tsx +21 -5
- package/bizar-dash/src/web/v8/views/Tasks/TasksView.tsx +9 -7
- package/bizar-dash/tests/goals-decompose.test.mjs +5 -3
- package/package.json +1 -1
- package/packages/sdk/.harness/agents.json +17 -0
- package/packages/sdk/.harness/topology.json +4 -0
- package/bizar-dash/dist/assets/ActivityFeed-CqF6iSDQ.js +0 -6
- package/bizar-dash/dist/assets/ActivityFeed-CqF6iSDQ.js.map +0 -1
- package/bizar-dash/dist/assets/ActivityView-qdhDjRtL.js +0 -1
- package/bizar-dash/dist/assets/ActivityView-qdhDjRtL.js.map +0 -1
- package/bizar-dash/dist/assets/AgentsView-BwXkOayl.js +0 -28
- package/bizar-dash/dist/assets/AgentsView-BwXkOayl.js.map +0 -1
- package/bizar-dash/dist/assets/Badge-BH4C3aUF.js +0 -1
- package/bizar-dash/dist/assets/Badge-BH4C3aUF.js.map +0 -1
- package/bizar-dash/dist/assets/Button-RmN1RKhE.js +0 -6
- package/bizar-dash/dist/assets/Button-RmN1RKhE.js.map +0 -1
- package/bizar-dash/dist/assets/GoalsView-CvsrzEez.js +0 -6
- package/bizar-dash/dist/assets/GoalsView-CvsrzEez.js.map +0 -1
- package/bizar-dash/dist/assets/MemoryView-Bbez5pMN.js +0 -13
- package/bizar-dash/dist/assets/MemoryView-Bbez5pMN.js.map +0 -1
- package/bizar-dash/dist/assets/OverviewView-BDegBWgg.js +0 -1
- package/bizar-dash/dist/assets/Select-xwxbK8Ed.js.map +0 -1
- package/bizar-dash/dist/assets/SettingsRow-CppSgkT_.js +0 -10
- package/bizar-dash/dist/assets/SettingsRow-CppSgkT_.js.map +0 -1
- package/bizar-dash/dist/assets/SettingsView-DUc2meHV.js +0 -43
- package/bizar-dash/dist/assets/SettingsView-DUc2meHV.js.map +0 -1
- package/bizar-dash/dist/assets/StatTile-BRsUIA6P.js +0 -16
- package/bizar-dash/dist/assets/StatTile-BRsUIA6P.js.map +0 -1
- package/bizar-dash/dist/assets/TasksView-DVyX5-DY.js +0 -1
- package/bizar-dash/dist/assets/TasksView-DVyX5-DY.js.map +0 -1
- package/bizar-dash/dist/assets/index-AL3OLUfz.js +0 -1
- package/bizar-dash/dist/assets/index-AL3OLUfz.js.map +0 -1
- package/bizar-dash/dist/assets/main-LxX9zTRk.js +0 -109
- package/bizar-dash/dist/assets/main-LxX9zTRk.js.map +0 -1
- package/bizar-dash/dist/assets/useFetch-CoVWwbml.js +0 -1
- package/bizar-dash/dist/assets/useFetch-CoVWwbml.js.map +0 -1
- package/bizar-dash/dist/assets/useWebSocket-CVIQB8yG.js +0 -1
- package/bizar-dash/dist/assets/useWebSocket-CVIQB8yG.js.map +0 -1
|
@@ -0,0 +1,1093 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/server/memory-store.mjs
|
|
3
|
+
*
|
|
4
|
+
* MarkdownMemoryStore — reads/writes Obsidian-compatible `.md` notes with YAML
|
|
5
|
+
* frontmatter for the Bizar Memory Service. Supports three modes:
|
|
6
|
+
* local-only — vault at <projectRoot>/.obsidian/
|
|
7
|
+
* managed — vault at ~/.bizar_memory/<repoName>/projects/<projectId>/
|
|
8
|
+
* linked — alias for managed
|
|
9
|
+
*
|
|
10
|
+
* The project namespace directory is created LAZY on first writeNote, not at
|
|
11
|
+
* initVault time (F7 invariant).
|
|
12
|
+
*
|
|
13
|
+
* v5.x — Default vault root relocated from `~/.local/share/bizar/memory` to
|
|
14
|
+
* `~/.bizar_memory` per issue #5. The old path still works if `BIZAR_MEMORY_VAULT`
|
|
15
|
+
* is set; on first run, `ensureVaultExists()` emits a one-time notice when the
|
|
16
|
+
* old path exists and the new one doesn't, but does NOT auto-migrate (too
|
|
17
|
+
* risky to move user data without consent).
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, statSync, lstatSync, unlinkSync } from 'node:fs';
|
|
21
|
+
import { execFileSync as _execFileSync } from 'node:child_process';
|
|
22
|
+
import { join, dirname, relative, resolve as pathResolve, sep } from 'node:path';
|
|
23
|
+
import { homedir } from 'node:os';
|
|
24
|
+
import { parseFrontmatter, serializeFrontmatter } from './yaml.mjs';
|
|
25
|
+
import { validateNote } from './memory-schema.mjs';
|
|
26
|
+
import { scan as scanSecrets, hasHighFindings } from './memory-secrets.mjs';
|
|
27
|
+
import { atomicWriteJson, safeReadJSON, safeReadText } from '../../../cli/atomic.mjs';
|
|
28
|
+
import * as memoryGit from './memory-git.mjs';
|
|
29
|
+
import { warn as loggerWarn } from './logger.mjs';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the `git` binary path once at module load time.
|
|
33
|
+
*
|
|
34
|
+
* When the dashboard runs under systemd, PATH typically does not include
|
|
35
|
+
* /usr/bin — this helper finds git's absolute path so that all
|
|
36
|
+
* execFileSync calls work regardless of the process's environment.
|
|
37
|
+
*
|
|
38
|
+
* @returns {string} absolute path to git, or 'git' as a best-effort fallback
|
|
39
|
+
*/
|
|
40
|
+
function resolveGitBinary() {
|
|
41
|
+
try {
|
|
42
|
+
const out = _execFileSync('which', ['git'], {
|
|
43
|
+
encoding: 'utf8',
|
|
44
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
45
|
+
}).trim();
|
|
46
|
+
if (out) return out;
|
|
47
|
+
} catch { /* which not available or failed */ }
|
|
48
|
+
|
|
49
|
+
const fallbacks = ['/usr/bin/git', '/usr/local/bin/git', '/opt/homebrew/bin/git', '/opt/git/bin/git'];
|
|
50
|
+
for (const f of fallbacks) {
|
|
51
|
+
try {
|
|
52
|
+
_execFileSync(f, ['--version'], { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
53
|
+
return f;
|
|
54
|
+
} catch { /* keep looking */ }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return 'git';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Cached absolute path to the git binary. */
|
|
61
|
+
const GIT_BIN = resolveGitBinary();
|
|
62
|
+
|
|
63
|
+
/** Wrapper that always uses the resolved GIT_BIN path. */
|
|
64
|
+
function execFileSync(args, opts) {
|
|
65
|
+
return _execFileSync(GIT_BIN, args, opts);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const HOME = homedir();
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Default vault root — auto-created on first use.
|
|
72
|
+
* Override with BIZAR_MEMORY_VAULT env var.
|
|
73
|
+
*
|
|
74
|
+
* v5.x — moved from `~/.local/share/bizar/memory` to `~/.bizar_memory` so the
|
|
75
|
+
* vault lives at a memorable, top-level location in the user's home.
|
|
76
|
+
*/
|
|
77
|
+
export const DEFAULT_MEMORY_VAULT = join(HOME, '.bizar_memory');
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* v5.x — Legacy vault path kept for migration detection only. The old
|
|
81
|
+
* `~/.local/share/bizar/memory` location is no longer the default; if a
|
|
82
|
+
* user still has notes there, `ensureVaultExists()` logs a one-time
|
|
83
|
+
* notice pointing them at the migration command.
|
|
84
|
+
*/
|
|
85
|
+
export const LEGACY_MEMORY_VAULT = join(HOME, '.local', 'share', 'bizar', 'memory');
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Default git remote — set via BIZAR_MEMORY_GIT_REMOTE to enable sync.
|
|
89
|
+
*/
|
|
90
|
+
export const DEFAULT_GIT_REMOTE = process.env.BIZAR_MEMORY_GIT_REMOTE || null;
|
|
91
|
+
|
|
92
|
+
const BIZAR_MEMORY_ROOT = join(HOME, '.bizar_memory');
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Return the effective vault root for the default memory vault.
|
|
96
|
+
* Override with BIZAR_MEMORY_VAULT env var.
|
|
97
|
+
*
|
|
98
|
+
* @returns {string}
|
|
99
|
+
*/
|
|
100
|
+
export function currentVault() {
|
|
101
|
+
return process.env.BIZAR_MEMORY_VAULT || DEFAULT_MEMORY_VAULT;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Ensure the default memory vault directory exists and is git-initialised.
|
|
106
|
+
* Idempotent — calling multiple times is safe.
|
|
107
|
+
*
|
|
108
|
+
* v5.x — On first call with a fresh default vault, if the legacy
|
|
109
|
+
* `~/.local/share/bizar/memory` path exists and the new
|
|
110
|
+
* `~/.bizar_memory` doesn't, log a one-time migration notice. We do
|
|
111
|
+
* NOT auto-migrate: the user owns the data and may have already moved
|
|
112
|
+
* it, or may want to keep the old path via `BIZAR_MEMORY_VAULT`.
|
|
113
|
+
*
|
|
114
|
+
* @returns {string} the vault path that was ensured
|
|
115
|
+
*/
|
|
116
|
+
export function ensureVaultExists() {
|
|
117
|
+
const vault = currentVault();
|
|
118
|
+
if (!existsSync(vault)) {
|
|
119
|
+
// v5.x — Migration notice: legacy path exists, new default does not.
|
|
120
|
+
// Only emit when the user is using the default (no env override) and
|
|
121
|
+
// the new path doesn't exist yet.
|
|
122
|
+
if (
|
|
123
|
+
!process.env.BIZAR_MEMORY_VAULT &&
|
|
124
|
+
vault === DEFAULT_MEMORY_VAULT &&
|
|
125
|
+
existsSync(LEGACY_MEMORY_VAULT)
|
|
126
|
+
) {
|
|
127
|
+
console.warn(
|
|
128
|
+
`[memory-store] Detected a legacy memory vault at ${LEGACY_MEMORY_VAULT}.\n` +
|
|
129
|
+
`[memory-store] The default location has moved to ${DEFAULT_MEMORY_VAULT}.\n` +
|
|
130
|
+
`[memory-store] To keep using the old vault, set BIZAR_MEMORY_VAULT=${LEGACY_MEMORY_VAULT}.\n` +
|
|
131
|
+
`[memory-store] To migrate, move the contents manually: ` +
|
|
132
|
+
`mv ${LEGACY_MEMORY_VAULT}/* ${DEFAULT_MEMORY_VAULT}/\n` +
|
|
133
|
+
`[memory-store] (not auto-migrated — please review before moving user data).`,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
mkdirSync(vault, { recursive: true, mode: 0o700 });
|
|
137
|
+
if (!existsSync(join(vault, '.git'))) {
|
|
138
|
+
try {
|
|
139
|
+
execFileSync(['init'], { cwd: vault, stdio: 'pipe' });
|
|
140
|
+
execFileSync(['config', 'user.email', 'bizar@localhost'], { cwd: vault, stdio: 'pipe' });
|
|
141
|
+
execFileSync(['config', 'user.name', 'BizarHarness'], { cwd: vault, stdio: 'pipe' });
|
|
142
|
+
} catch (err) {
|
|
143
|
+
loggerWarn('failed to init git in vault', { vault, err: err.message });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return vault;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Path safety: reject any relPath that would escape the vault root.
|
|
152
|
+
*
|
|
153
|
+
* Defenses (in order):
|
|
154
|
+
* 1. Empty / null-byte injection → reject.
|
|
155
|
+
* 2. Explicit segment check for `..` and absolute path prefixes → reject
|
|
156
|
+
* before path.resolve normalizes them away. The check is on SEGMENTS
|
|
157
|
+
* (`..` separated by `/` or `\`), so filenames like `my..note.md` are
|
|
158
|
+
* still allowed.
|
|
159
|
+
* 3. Post-resolve check: the resulting absolute path must be inside
|
|
160
|
+
* vaultRoot (relative path must not start with `..`).
|
|
161
|
+
* 4. Symlink guard: if the resolved path is a pre-existing symlink, refuse.
|
|
162
|
+
* This blocks an attacker who placed a symlink inside the vault pointing
|
|
163
|
+
* outside from writing/reading through it.
|
|
164
|
+
*
|
|
165
|
+
* Known limitation: the symlink guard is not TOCTOU-safe. A swap between
|
|
166
|
+
* lstatSync and the subsequent read/write/delete is still possible. For a
|
|
167
|
+
* full TOCTOU fix the read/write/delete would need to use O_NOFOLLOW and
|
|
168
|
+
* operate on an open fd, not a path. This is acceptable for the current
|
|
169
|
+
* threat model (the vault is a per-user directory, not a multi-tenant FS).
|
|
170
|
+
*
|
|
171
|
+
* @param {string} vaultRoot
|
|
172
|
+
* @param {string} relPath
|
|
173
|
+
* @returns {string | null} — resolved absolute path, or null if unsafe
|
|
174
|
+
*/
|
|
175
|
+
function resolveSafe(vaultRoot, relPath) {
|
|
176
|
+
if (!relPath || relPath.includes('\0')) return null;
|
|
177
|
+
// Segment-level check: reject any `..` segment or absolute-path prefix
|
|
178
|
+
// BEFORE path.resolve normalizes them away. This explicitly rejects
|
|
179
|
+
// paths like `notes/../escape.md`, while still allowing filenames like
|
|
180
|
+
// `my..note.md` (the substring `..` inside a single segment is fine).
|
|
181
|
+
const segments = relPath.split(/[\\/]+/);
|
|
182
|
+
if (segments.includes('..') || segments[0] === '') return null;
|
|
183
|
+
const abs = pathResolve(vaultRoot, relPath);
|
|
184
|
+
const rel = relative(vaultRoot, abs);
|
|
185
|
+
if (rel.startsWith('..') || abs !== pathResolve(abs)) return null;
|
|
186
|
+
// Symlink guard (see note above re: TOCTOU). Note: existsSync follows
|
|
187
|
+
// symlinks, so we MUST use lstatSync directly — existsSync + isSymbolicLink
|
|
188
|
+
// misses dangling symlinks (target doesn't exist). lstatSync returns a
|
|
189
|
+
// Stats object even for dangling symlinks; catch only unexpected errors
|
|
190
|
+
// (e.g. EACCES on the parent directory).
|
|
191
|
+
try {
|
|
192
|
+
if (lstatSync(abs).isSymbolicLink()) return null;
|
|
193
|
+
} catch {
|
|
194
|
+
// Path doesn't exist or parent dir inaccessible — not a symlink,
|
|
195
|
+
// proceed. (A fresh write won't traverse a symlink because the
|
|
196
|
+
// symlink itself doesn't exist yet at write time.)
|
|
197
|
+
}
|
|
198
|
+
return abs;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Read the per-project memory config file (.bizar/memory.json).
|
|
203
|
+
*
|
|
204
|
+
* @param {string} projectRoot
|
|
205
|
+
* @returns {{ exists: boolean, config: Record<string, unknown>, error?: string }}
|
|
206
|
+
*/
|
|
207
|
+
export function loadConfig(projectRoot) {
|
|
208
|
+
const configPath = join(projectRoot, '.bizar', 'memory.json');
|
|
209
|
+
const raw = safeReadJSON(configPath, null);
|
|
210
|
+
if (raw === null) {
|
|
211
|
+
return {
|
|
212
|
+
exists: false,
|
|
213
|
+
config: {
|
|
214
|
+
mode: 'local-only',
|
|
215
|
+
projectId: projectRoot.split('/').pop() || 'unknown',
|
|
216
|
+
repoName: '',
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
return { exists: true, config: raw };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Write the per-project memory config file.
|
|
225
|
+
*
|
|
226
|
+
* @param {string} projectRoot
|
|
227
|
+
* @param {Record<string, unknown>} config
|
|
228
|
+
* @returns {{ ok: boolean, error?: string }}
|
|
229
|
+
*/
|
|
230
|
+
export function saveConfig(projectRoot, config) {
|
|
231
|
+
try {
|
|
232
|
+
const configDir = join(projectRoot, '.bizar');
|
|
233
|
+
if (!existsSync(configDir)) {
|
|
234
|
+
mkdirSync(configDir, { recursive: true });
|
|
235
|
+
}
|
|
236
|
+
const configPath = join(configDir, 'memory.json');
|
|
237
|
+
atomicWriteJson(configPath, config);
|
|
238
|
+
return { ok: true };
|
|
239
|
+
} catch (err) {
|
|
240
|
+
return { ok: false, error: err.message };
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Resolve the effective vault root, namespaces, and related paths based on mode.
|
|
246
|
+
*
|
|
247
|
+
* v6.x — `vaultRoot` is now always the GENERAL vault root (e.g. `~/.bizar_memory`).
|
|
248
|
+
* A new `projectVaultRoot` field carries the project-specific subdirectory for
|
|
249
|
+
* note storage in managed/linked mode (`~/.bizar_memory/projects/<projectId>`).
|
|
250
|
+
* This distinction lets the UI display the general root while the store still
|
|
251
|
+
* writes notes to the correct project subdirectory.
|
|
252
|
+
*
|
|
253
|
+
* @param {string} projectRoot
|
|
254
|
+
* @returns {{ mode: string, projectId: string, vaultRoot: string, projectVaultRoot: string, repoPath: string | null, configDir: string, gitRemote: string | null, branch: string, lightragDir: string, namespaces: object }}
|
|
255
|
+
*/
|
|
256
|
+
export function resolveVault(projectRoot) {
|
|
257
|
+
const { config } = loadConfig(projectRoot);
|
|
258
|
+
const mr = config.memoryRepo || {};
|
|
259
|
+
const mode = mr.mode || config.mode || 'local-only';
|
|
260
|
+
const projectId = config.projectId || projectRoot.split('/').pop() || 'unknown';
|
|
261
|
+
const branch = mr.branch || config.branch || 'main';
|
|
262
|
+
const gitRemote = mr.remote || config.gitRemote || null;
|
|
263
|
+
|
|
264
|
+
let vaultRoot;
|
|
265
|
+
let projectVaultRoot;
|
|
266
|
+
let repoPath;
|
|
267
|
+
if (mode === 'local-only') {
|
|
268
|
+
vaultRoot = join(projectRoot, '.obsidian');
|
|
269
|
+
projectVaultRoot = vaultRoot;
|
|
270
|
+
repoPath = null;
|
|
271
|
+
} else {
|
|
272
|
+
// managed or linked — path may be absolute, ~-relative, or a sibling of projectRoot
|
|
273
|
+
const rawPath = mr.path || config.repoName || join(projectRoot, '.bizar', 'memory');
|
|
274
|
+
const expanded = rawPath.startsWith('~') ? join(HOME, rawPath.slice(1)) : rawPath;
|
|
275
|
+
repoPath = expanded;
|
|
276
|
+
vaultRoot = expanded; // v6.x — general root, e.g. ~/.bizar_memory
|
|
277
|
+
projectVaultRoot = join(expanded, 'projects', projectId); // project-specific subdirectory
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const configDir = join(projectRoot, '.bizar');
|
|
281
|
+
const lightragDir = join(projectRoot, '.bizar', 'memory-cache');
|
|
282
|
+
const namespaces = config.namespaces || {
|
|
283
|
+
project: `projects/${projectId}`,
|
|
284
|
+
global: 'global/bizar',
|
|
285
|
+
user: `users/${process.env.USER || process.env.USERNAME || 'local'}`,
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
return { mode, projectId, vaultRoot, projectVaultRoot, repoPath, configDir, gitRemote, branch, lightragDir, namespaces };
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Resolve the absolute path of a namespace root.
|
|
293
|
+
*
|
|
294
|
+
* For `project`, returns projectVaultRoot (the directory where project notes
|
|
295
|
+
* are stored: `<vaultRoot>/projects/<projectId>` in managed mode, or
|
|
296
|
+
* `<projectRoot>/.obsidian` in local-only mode). For `global` and `user`,
|
|
297
|
+
* returns `<vaultRoot>/<namespaces.X>` — these namespaces live at the vault
|
|
298
|
+
* root level, not inside the project subdirectory.
|
|
299
|
+
*
|
|
300
|
+
* Routing: writeNote/readNote/deleteNote use this to determine where files
|
|
301
|
+
* live. Project relPaths go to projectVaultRoot; global/ and users/ relPaths
|
|
302
|
+
* go to vaultRoot-based paths.
|
|
303
|
+
*
|
|
304
|
+
* @param {{ mode: string, vaultRoot: string, projectVaultRoot: string, namespaces: object }} vaultInfo
|
|
305
|
+
* @param {'project'|'global'|'user'} namespace
|
|
306
|
+
* @returns {string|null} absolute path, or null if the namespace is unknown
|
|
307
|
+
*/
|
|
308
|
+
export function resolveNamespaceRoot(vaultInfo, namespace) {
|
|
309
|
+
if (namespace === 'project') return vaultInfo.projectVaultRoot;
|
|
310
|
+
const ns = vaultInfo.namespaces?.[namespace];
|
|
311
|
+
if (!ns) return null;
|
|
312
|
+
return join(vaultInfo.vaultRoot, ns);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Initialize the vault for a project. In local-only mode, creates .obsidian/
|
|
317
|
+
* and standard subdirectories. In managed mode, the shared repo is assumed to
|
|
318
|
+
* already exist; this function only ensures the .bizar/memory.json is set up.
|
|
319
|
+
*
|
|
320
|
+
* NOTE: The project namespace directory (projects/<id>/) is NOT created here.
|
|
321
|
+
* It is created lazily on first writeNote (F7 invariant).
|
|
322
|
+
*
|
|
323
|
+
* @param {string} projectRoot
|
|
324
|
+
* @returns {{ ok: boolean, vaultRoot: string, created: string[], error?: string }}
|
|
325
|
+
*/
|
|
326
|
+
export function initVault(projectRoot) {
|
|
327
|
+
const { config } = loadConfig(projectRoot);
|
|
328
|
+
const mr = config.memoryRepo || {};
|
|
329
|
+
const mode = mr.mode || config.mode || 'local-only';
|
|
330
|
+
const created = [];
|
|
331
|
+
|
|
332
|
+
if (mode === 'local-only') {
|
|
333
|
+
const vaultRoot = join(projectRoot, '.obsidian');
|
|
334
|
+
const subdirs = ['daily', 'decisions', 'patterns', 'api', 'tasks', 'global', 'users'];
|
|
335
|
+
if (!existsSync(vaultRoot)) {
|
|
336
|
+
mkdirSync(vaultRoot, { recursive: true });
|
|
337
|
+
created.push('.obsidian/');
|
|
338
|
+
}
|
|
339
|
+
for (const sub of subdirs) {
|
|
340
|
+
const subPath = join(vaultRoot, sub);
|
|
341
|
+
if (!existsSync(subPath)) {
|
|
342
|
+
mkdirSync(subPath, { recursive: true });
|
|
343
|
+
created.push(`.obsidian/${sub}/`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return { ok: true, vaultRoot, created };
|
|
347
|
+
} else {
|
|
348
|
+
// managed / linked — create the shared repo at repoPath with `git init`
|
|
349
|
+
const { repoPath, vaultRoot } = resolveVault(projectRoot);
|
|
350
|
+
if (!existsSync(repoPath)) {
|
|
351
|
+
mkdirSync(repoPath, { recursive: true });
|
|
352
|
+
created.push(repoPath);
|
|
353
|
+
}
|
|
354
|
+
// git init if not already a git repo
|
|
355
|
+
const isGit = existsSync(join(repoPath, '.git'));
|
|
356
|
+
if (!isGit) {
|
|
357
|
+
try {
|
|
358
|
+
execFileSync(['init', '-b', 'main'], { cwd: repoPath, stdio: 'pipe' });
|
|
359
|
+
created.push(`${repoPath}/.git/`);
|
|
360
|
+
} catch (err) {
|
|
361
|
+
return { ok: false, vaultRoot, created, error: `git init failed: ${err.message}` };
|
|
362
|
+
}
|
|
363
|
+
// Write and commit a .gitignore for runtime artifacts
|
|
364
|
+
const gitignorePath = join(repoPath, '.gitignore');
|
|
365
|
+
if (!existsSync(gitignorePath)) {
|
|
366
|
+
writeFileSync(gitignorePath,
|
|
367
|
+
'# Lock files — runtime state, not memory\n' +
|
|
368
|
+
'**/.sync.lock\n' +
|
|
369
|
+
'**/*.pid\n' +
|
|
370
|
+
'**/*.log\n' +
|
|
371
|
+
'**/.DS_Store\n' +
|
|
372
|
+
'\n' +
|
|
373
|
+
'# Local-only metadata\n' +
|
|
374
|
+
'**/.bizar-memory/cache/\n' +
|
|
375
|
+
'**/.bizar-memory/index-ledger.local.json\n',
|
|
376
|
+
'utf8');
|
|
377
|
+
created.push(`${repoPath}/.gitignore`);
|
|
378
|
+
try {
|
|
379
|
+
execFileSync(['add', '.gitignore'], { cwd: repoPath });
|
|
380
|
+
execFileSync(['commit', '-m', 'chore: initial .gitignore for memory repo'], {
|
|
381
|
+
cwd: repoPath,
|
|
382
|
+
env: {
|
|
383
|
+
...process.env,
|
|
384
|
+
GIT_AUTHOR_NAME: 'Bizar Memory',
|
|
385
|
+
GIT_AUTHOR_EMAIL: 'bizar-memory@local',
|
|
386
|
+
GIT_COMMITTER_NAME: 'Bizar Memory',
|
|
387
|
+
GIT_COMMITTER_EMAIL: 'bizar-memory@local',
|
|
388
|
+
},
|
|
389
|
+
});
|
|
390
|
+
} catch (e) {
|
|
391
|
+
// best-effort; not fatal
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
// Ensure projects/, global/, users/ exist so writeNote can find them without
|
|
396
|
+
// creating the project-specific namespace (F7 invariant — only the projects/<id>
|
|
397
|
+
// subdirectory is created lazily on first writeNote)
|
|
398
|
+
const projectsDir = join(repoPath, 'projects');
|
|
399
|
+
if (!existsSync(projectsDir)) {
|
|
400
|
+
mkdirSync(projectsDir, { recursive: true });
|
|
401
|
+
created.push(`${repoPath}/projects/`);
|
|
402
|
+
}
|
|
403
|
+
const globalDir = join(repoPath, 'global', 'bizar');
|
|
404
|
+
if (!existsSync(globalDir)) {
|
|
405
|
+
mkdirSync(globalDir, { recursive: true });
|
|
406
|
+
created.push(`${repoPath}/global/bizar/`);
|
|
407
|
+
}
|
|
408
|
+
const usersDir = join(repoPath, 'users');
|
|
409
|
+
if (!existsSync(usersDir)) {
|
|
410
|
+
mkdirSync(usersDir, { recursive: true });
|
|
411
|
+
created.push(`${repoPath}/users/`);
|
|
412
|
+
}
|
|
413
|
+
return { ok: true, vaultRoot, created };
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* List all notes in the vault. Returns enriched note metadata.
|
|
419
|
+
*
|
|
420
|
+
* @param {string} projectRoot
|
|
421
|
+
* @param {{ namespace?: string, root?: string }} [opts]
|
|
422
|
+
* `namespace`: subdirectory under `root` to walk (e.g. `projects/<id>`).
|
|
423
|
+
* `root`: override the root used as the walking base. Defaults to
|
|
424
|
+
* `vaultRoot` from resolveVault. Used by namespace helpers
|
|
425
|
+
* in cli/memory.mjs to list global / user notes.
|
|
426
|
+
* @returns {Array<{ relPath: string, mtime: number, size: number, frontmatter: Record<string, unknown>, body: string, schemaValid: boolean }>}
|
|
427
|
+
*/
|
|
428
|
+
export function listNotes(projectRoot, opts = {}) {
|
|
429
|
+
const { projectVaultRoot } = resolveVault(projectRoot);
|
|
430
|
+
const root = opts.root || projectVaultRoot;
|
|
431
|
+
if (!existsSync(root)) return [];
|
|
432
|
+
|
|
433
|
+
const namespace = opts.namespace || '';
|
|
434
|
+
const searchRoot = namespace ? join(root, namespace) : root;
|
|
435
|
+
if (!existsSync(searchRoot)) return [];
|
|
436
|
+
|
|
437
|
+
const out = [];
|
|
438
|
+
function walk(dir, prefix) {
|
|
439
|
+
let entries;
|
|
440
|
+
try { entries = readdirSync(dir, { withFileTypes: true }); }
|
|
441
|
+
catch { return; }
|
|
442
|
+
for (const e of entries) {
|
|
443
|
+
const full = join(dir, e.name);
|
|
444
|
+
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
445
|
+
if (e.isDirectory()) {
|
|
446
|
+
if (e.name === 'node_modules' || e.name.startsWith('.')) continue;
|
|
447
|
+
walk(full, rel);
|
|
448
|
+
} else if (e.name.endsWith('.md')) {
|
|
449
|
+
try {
|
|
450
|
+
const st = statSync(full);
|
|
451
|
+
const raw = readFileSync(full, 'utf8');
|
|
452
|
+
const { frontmatter, body } = parseFrontmatter(raw);
|
|
453
|
+
const { valid } = validateNote(frontmatter, body);
|
|
454
|
+
out.push({ relPath: rel, mtime: st.mtimeMs, size: st.size, frontmatter, body, schemaValid: valid });
|
|
455
|
+
} catch { /* skip unreadable */ }
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
walk(searchRoot, '');
|
|
460
|
+
return out.sort((a, b) => b.mtime - a.mtime);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Read a single note by relative path. Returns null if not found.
|
|
465
|
+
*
|
|
466
|
+
* @param {string} projectRoot
|
|
467
|
+
* @param {string} relPath
|
|
468
|
+
* @param {{ root?: string }} [opts] optional override for the root used by
|
|
469
|
+
* resolveSafe; defaults to vaultRoot
|
|
470
|
+
* @returns {{ relPath: string, frontmatter: Record<string, unknown>, body: string, raw: string, mtime: number, size: number, schemaValid: boolean } | null}
|
|
471
|
+
*/
|
|
472
|
+
export function readNote(projectRoot, relPath, opts = {}) {
|
|
473
|
+
const { vaultRoot, projectVaultRoot } = resolveVault(projectRoot);
|
|
474
|
+
// When opts.root is explicitly provided, use it. Otherwise route based on
|
|
475
|
+
// namespace so reads find notes where writeNote placed them.
|
|
476
|
+
let root;
|
|
477
|
+
if (opts.root) {
|
|
478
|
+
root = opts.root;
|
|
479
|
+
} else {
|
|
480
|
+
const isProjectNamespace = !relPath.startsWith('global/') && !relPath.startsWith('users/');
|
|
481
|
+
root = isProjectNamespace ? projectVaultRoot : vaultRoot;
|
|
482
|
+
}
|
|
483
|
+
const filePath = resolveSafe(root, relPath);
|
|
484
|
+
if (!filePath || !existsSync(filePath)) return null;
|
|
485
|
+
try {
|
|
486
|
+
const raw = readFileSync(filePath, 'utf8');
|
|
487
|
+
const st = statSync(filePath);
|
|
488
|
+
const { frontmatter, body } = parseFrontmatter(raw);
|
|
489
|
+
const { valid } = validateNote(frontmatter, body);
|
|
490
|
+
return { relPath, frontmatter, body, raw, mtime: st.mtimeMs, size: st.size, schemaValid: valid };
|
|
491
|
+
} catch {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Write a note. Validates frontmatter, scans for secrets, writes the file.
|
|
498
|
+
*
|
|
499
|
+
* @param {string} projectRoot
|
|
500
|
+
* @param {string} relPath
|
|
501
|
+
* @param {{ frontmatter: Record<string, unknown>, body: string }} note
|
|
502
|
+
* @returns {{ relPath: string, frontmatter: Record<string, unknown>, body: string, raw: string, mtime: number, size: number, schemaValid: boolean }}
|
|
503
|
+
* @throws {Error} if schema validation fails or HIGH-severity secret found
|
|
504
|
+
*/
|
|
505
|
+
export function writeNote(projectRoot, relPath, { frontmatter, body }) {
|
|
506
|
+
const { vaultRoot, projectVaultRoot } = resolveVault(projectRoot);
|
|
507
|
+
|
|
508
|
+
// Validate frontmatter
|
|
509
|
+
const { valid, errors, warnings } = validateNote(frontmatter, body);
|
|
510
|
+
if (!valid) {
|
|
511
|
+
const err = new Error(`schema validation failed: ${errors.join('; ')}`);
|
|
512
|
+
err.code = 'SCHEMA_VALIDATION_FAILED';
|
|
513
|
+
throw err;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Scan for secrets
|
|
517
|
+
const secretResult = scanSecrets(body);
|
|
518
|
+
if (hasHighFindings(secretResult)) {
|
|
519
|
+
const snippets = secretResult.findings
|
|
520
|
+
.filter((f) => f.severity === 'HIGH')
|
|
521
|
+
.map((f) => `line ${f.line}: ${f.snippet}`)
|
|
522
|
+
.join('\n');
|
|
523
|
+
const err = new Error(`HIGH-severity secret detected:\n${snippets}`);
|
|
524
|
+
err.code = 'SECRET_DETECTED';
|
|
525
|
+
err.findings = secretResult.findings;
|
|
526
|
+
throw err;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Determine the effective vault root based on namespace.
|
|
530
|
+
// Project notes (relPaths that don't start with global/ or users/) go under
|
|
531
|
+
// projectVaultRoot. Global and user notes go under vaultRoot.
|
|
532
|
+
// This matches the layout resolveNamespaceRoot returns for each namespace.
|
|
533
|
+
const isProjectNamespace = !relPath.startsWith('global/') && !relPath.startsWith('users/');
|
|
534
|
+
const noteVaultRoot = isProjectNamespace ? projectVaultRoot : vaultRoot;
|
|
535
|
+
|
|
536
|
+
// Build file content
|
|
537
|
+
const filePath = resolveSafe(noteVaultRoot, relPath);
|
|
538
|
+
if (!filePath) {
|
|
539
|
+
throw new Error(`Invalid note path: ${relPath}`);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// Lazily create the namespace directory (not created at initVault)
|
|
543
|
+
const nsDir = dirname(filePath);
|
|
544
|
+
if (!existsSync(nsDir)) {
|
|
545
|
+
mkdirSync(nsDir, { recursive: true });
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const yamlBlock = serializeFrontmatter(frontmatter);
|
|
549
|
+
const content = `---\n${yamlBlock}\n---\n\n${body}`;
|
|
550
|
+
writeFileSync(filePath, content, 'utf8');
|
|
551
|
+
|
|
552
|
+
// Auto-commit the written file to git (if configured).
|
|
553
|
+
// The lock serializes commits, not writes — concurrent writes will each
|
|
554
|
+
// trigger their own commit, which is the intended behaviour.
|
|
555
|
+
(() => {
|
|
556
|
+
try {
|
|
557
|
+
if (!memoryGit.isGitInstalled()) return;
|
|
558
|
+
const { config } = loadConfig(projectRoot);
|
|
559
|
+
if (config.mode === 'local-only') return;
|
|
560
|
+
if (config.git?.autoCommitOnMemoryWrite !== true) return;
|
|
561
|
+
const lockResult = memoryGit.acquireLock(vaultRoot);
|
|
562
|
+
if (!lockResult || lockResult.error) return; // skip if locked or error
|
|
563
|
+
try {
|
|
564
|
+
memoryGit.addFile(vaultRoot, relPath);
|
|
565
|
+
const summary = frontmatter.title || relPath;
|
|
566
|
+
const message = (config.git.commitMessageTemplate || 'memory(BizarHarness): {summary}')
|
|
567
|
+
.replace('{summary}', summary);
|
|
568
|
+
memoryGit.commit(vaultRoot, message, { author: config.git.commitAuthor });
|
|
569
|
+
} finally {
|
|
570
|
+
lockResult.release();
|
|
571
|
+
}
|
|
572
|
+
} catch (err) {
|
|
573
|
+
// Log but never re-throw — the write already succeeded; a failed
|
|
574
|
+
// auto-commit is recoverable on next write or manual commit.
|
|
575
|
+
console.error('[memory-store] autoCommitOnMemoryWrite failed:', err?.message || err);
|
|
576
|
+
}
|
|
577
|
+
})();
|
|
578
|
+
|
|
579
|
+
const st = statSync(filePath);
|
|
580
|
+
return {
|
|
581
|
+
relPath,
|
|
582
|
+
frontmatter,
|
|
583
|
+
body,
|
|
584
|
+
raw: content,
|
|
585
|
+
mtime: st.mtimeMs,
|
|
586
|
+
size: st.size,
|
|
587
|
+
schemaValid: true,
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Delete a note by relative path.
|
|
593
|
+
*
|
|
594
|
+
* @param {string} projectRoot
|
|
595
|
+
* @param {string} relPath
|
|
596
|
+
* @param {{ root?: string }} [opts] optional override for the root used by
|
|
597
|
+
* resolveSafe; defaults to vaultRoot
|
|
598
|
+
* @returns {boolean}
|
|
599
|
+
*/
|
|
600
|
+
export function deleteNote(projectRoot, relPath, opts = {}) {
|
|
601
|
+
const { vaultRoot, projectVaultRoot } = resolveVault(projectRoot);
|
|
602
|
+
// When opts.root is explicitly provided, use it. Otherwise route based on
|
|
603
|
+
// namespace so deletes find notes where writeNote placed them.
|
|
604
|
+
let root;
|
|
605
|
+
if (opts.root) {
|
|
606
|
+
root = opts.root;
|
|
607
|
+
} else {
|
|
608
|
+
const isProjectNamespace = !relPath.startsWith('global/') && !relPath.startsWith('users/');
|
|
609
|
+
root = isProjectNamespace ? projectVaultRoot : vaultRoot;
|
|
610
|
+
}
|
|
611
|
+
const filePath = resolveSafe(root, relPath);
|
|
612
|
+
if (!filePath || !existsSync(filePath)) return false;
|
|
613
|
+
unlinkSync(filePath);
|
|
614
|
+
return true;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Full-text search across vault notes.
|
|
619
|
+
*
|
|
620
|
+
* @param {string} projectRoot
|
|
621
|
+
* @param {string} query
|
|
622
|
+
* @param {{ limit?: number }} [opts]
|
|
623
|
+
* @returns {Array<{ relPath: string, snippet: string, score: number, mtime: number }>}
|
|
624
|
+
*/
|
|
625
|
+
export function searchVault(projectRoot, query, { limit = 25 } = {}) {
|
|
626
|
+
if (!query || typeof query !== 'string') return [];
|
|
627
|
+
const q = query.toLowerCase();
|
|
628
|
+
const tokens = q.split(/\s+/).filter((t) => t.length >= 2);
|
|
629
|
+
if (tokens.length === 0) return [];
|
|
630
|
+
|
|
631
|
+
const { vaultRoot, projectVaultRoot } = resolveVault(projectRoot);
|
|
632
|
+
|
|
633
|
+
// Collect notes from all namespaces by walking vaultRoot (which contains
|
|
634
|
+
// projects/<id>/, global/, and users/ as siblings). This finds project,
|
|
635
|
+
// global, and user notes in a single scan. relPaths returned are vaultRoot-
|
|
636
|
+
// relative (e.g. "projects/<id>/decisions/foo.md" or "global/bizar/foo.md").
|
|
637
|
+
// For project notes, strip the "projects/<id>/" prefix so the relPath matches
|
|
638
|
+
// what writeNote uses (projectVaultRoot-relative).
|
|
639
|
+
const projectPrefix = join('projects', projectVaultRoot.split('/').pop());
|
|
640
|
+
const allNotes = listNotes(projectRoot, { root: vaultRoot });
|
|
641
|
+
|
|
642
|
+
const results = [];
|
|
643
|
+
for (const note of allNotes) {
|
|
644
|
+
let relPath = note.relPath;
|
|
645
|
+
if (relPath.startsWith(projectPrefix)) {
|
|
646
|
+
relPath = relPath.slice(projectPrefix.length + 1);
|
|
647
|
+
}
|
|
648
|
+
const lower = (note.body + ' ' + JSON.stringify(note.frontmatter)).toLowerCase();
|
|
649
|
+
let score = 0;
|
|
650
|
+
for (const t of tokens) {
|
|
651
|
+
if (lower.includes(t)) score += (lower.split(t).length - 1);
|
|
652
|
+
}
|
|
653
|
+
if (score === 0) continue;
|
|
654
|
+
const idx = lower.indexOf(tokens[0]);
|
|
655
|
+
const start = Math.max(0, idx - 60);
|
|
656
|
+
const end = Math.min(lower.length, idx + 160);
|
|
657
|
+
const snippet = (start > 0 ? '…' : '') + lower.slice(start, end).replace(/\s+/g, ' ').trim();
|
|
658
|
+
results.push({ relPath, snippet, score, mtime: note.mtime });
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
return results.sort((a, b) => b.score - a.score).slice(0, limit);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* Scan a single note for secrets.
|
|
666
|
+
*
|
|
667
|
+
* @param {string} projectRoot
|
|
668
|
+
* @param {string} relPath
|
|
669
|
+
* @returns {{ safe: boolean, findings: Array<{ id: string, severity: string, line: number, snippet: string }> }}
|
|
670
|
+
*/
|
|
671
|
+
export function scanForSecrets(projectRoot, relPath) {
|
|
672
|
+
const note = readNote(projectRoot, relPath);
|
|
673
|
+
if (!note) return { safe: true, findings: [] };
|
|
674
|
+
return scanSecrets(note.body);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Validate all notes in the vault against the schema.
|
|
679
|
+
*
|
|
680
|
+
* @param {string} projectRoot
|
|
681
|
+
* @returns {Array<{ relPath: string, errors: string[] }>}
|
|
682
|
+
*/
|
|
683
|
+
export function validateAll(projectRoot) {
|
|
684
|
+
const notes = listNotes(projectRoot);
|
|
685
|
+
const results = [];
|
|
686
|
+
for (const note of notes) {
|
|
687
|
+
const { errors } = validateNote(note.frontmatter, note.body);
|
|
688
|
+
if (errors.length > 0) {
|
|
689
|
+
results.push({ relPath: note.relPath, errors });
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
return results;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
// ── v4.7.0 — Memory tab helpers ─────────────────────────────────────────────
|
|
696
|
+
//
|
|
697
|
+
// Lightweight helpers used by the dedicated Memory view: backlinks (wikilink
|
|
698
|
+
// reverse index) and a vault-stats summary for the overview card.
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Find every note in the vault that links TO `targetRelPath` via a wikilink.
|
|
702
|
+
*
|
|
703
|
+
* A wikilink matches one of:
|
|
704
|
+
* - `[[target]]`
|
|
705
|
+
* - `[[target|alias]]`
|
|
706
|
+
* - `[[target#heading]]`
|
|
707
|
+
* - `[[target#heading|alias]]`
|
|
708
|
+
*
|
|
709
|
+
* The match is by basename without extension (Obsidian's wikilink semantics)
|
|
710
|
+
* AND by full relPath-without-extension, so `[[notes/foo]]` matches
|
|
711
|
+
* `notes/foo.md` and `[[foo]]` matches `foo.md` anywhere in the vault.
|
|
712
|
+
*
|
|
713
|
+
* @param {string} projectRoot
|
|
714
|
+
* @param {string} targetRelPath — the note we want backlinks for
|
|
715
|
+
* @returns {Array<{ fromRelPath: string, fromTitle: string, snippet: string, mtime: number }>}
|
|
716
|
+
*/
|
|
717
|
+
export function findBacklinks(projectRoot, targetRelPath) {
|
|
718
|
+
if (!targetRelPath) return [];
|
|
719
|
+
const targetBase = basenameOf(targetRelPath).replace(/\.md$/i, '');
|
|
720
|
+
const targetStripped = targetRelPath.replace(/\.md$/i, '');
|
|
721
|
+
if (!targetBase && !targetStripped) return [];
|
|
722
|
+
|
|
723
|
+
const out = [];
|
|
724
|
+
const WIKILINK_RE = /\[\[([^\]\n|]+?)(?:\|[^\]\n]+?)?(?:#[^\]\n]+?)?\]\]/g;
|
|
725
|
+
|
|
726
|
+
for (const note of listNotes(projectRoot)) {
|
|
727
|
+
if (note.relPath === targetRelPath) continue; // skip self
|
|
728
|
+
const body = note.body || '';
|
|
729
|
+
const matches = [];
|
|
730
|
+
let m;
|
|
731
|
+
WIKILINK_RE.lastIndex = 0;
|
|
732
|
+
while ((m = WIKILINK_RE.exec(body)) !== null) {
|
|
733
|
+
const raw = (m[1] || '').trim();
|
|
734
|
+
if (!raw) continue;
|
|
735
|
+
const stripped = raw.split('#')[0].trim();
|
|
736
|
+
if (!stripped) continue;
|
|
737
|
+
const baseOnly = stripped.split('/').pop() || stripped;
|
|
738
|
+
if (baseOnly === targetBase || stripped === targetStripped) {
|
|
739
|
+
matches.push({ raw, idx: m.index });
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
if (matches.length === 0) continue;
|
|
743
|
+
|
|
744
|
+
// Build a snippet around the FIRST match — 80 chars each side.
|
|
745
|
+
const first = matches[0];
|
|
746
|
+
const start = Math.max(0, first.idx - 80);
|
|
747
|
+
const end = Math.min(body.length, first.idx + first.raw.length + 80);
|
|
748
|
+
const snippet = (start > 0 ? '…' : '') +
|
|
749
|
+
body.slice(start, end).replace(/\s+/g, ' ').trim() +
|
|
750
|
+
(end < body.length ? '…' : '');
|
|
751
|
+
|
|
752
|
+
out.push({
|
|
753
|
+
fromRelPath: note.relPath,
|
|
754
|
+
fromTitle: note.frontmatter?.title || basenameOf(note.relPath).replace(/\.md$/i, ''),
|
|
755
|
+
snippet,
|
|
756
|
+
mtime: note.mtime,
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
return out.sort((a, b) => b.mtime - a.mtime);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
/** Minimal basename helper — avoids pulling `path.basename` into the bundle. */
|
|
764
|
+
function basenameOf(p) {
|
|
765
|
+
if (!p) return '';
|
|
766
|
+
const idx = Math.max(p.lastIndexOf('/'), p.lastIndexOf('\\'));
|
|
767
|
+
return idx >= 0 ? p.slice(idx + 1) : p;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* High-level stats used by the Memory tab and Overview status card.
|
|
772
|
+
*
|
|
773
|
+
* @param {string} projectRoot
|
|
774
|
+
* @returns {{ exists: boolean, vaultRoot: string, mode: string, noteCount: number, totalSize: number, folderCount: number, folders: string[], lastModified: number|null, gitClean: boolean|null, gitBranch: string|null }}
|
|
775
|
+
*/
|
|
776
|
+
export function vaultStats(projectRoot) {
|
|
777
|
+
const { exists, config } = loadConfig(projectRoot);
|
|
778
|
+
if (!exists) {
|
|
779
|
+
return {
|
|
780
|
+
exists: false,
|
|
781
|
+
vaultRoot: '',
|
|
782
|
+
mode: 'local-only',
|
|
783
|
+
noteCount: 0,
|
|
784
|
+
totalSize: 0,
|
|
785
|
+
folderCount: 0,
|
|
786
|
+
folders: [],
|
|
787
|
+
lastModified: null,
|
|
788
|
+
gitClean: null,
|
|
789
|
+
gitBranch: null,
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
const { vaultRoot, projectVaultRoot, mode, branch } = resolveVault(projectRoot);
|
|
794
|
+
if (!projectVaultRoot || !existsSync(projectVaultRoot)) {
|
|
795
|
+
return {
|
|
796
|
+
exists: true,
|
|
797
|
+
vaultRoot: vaultRoot || '',
|
|
798
|
+
mode,
|
|
799
|
+
noteCount: 0,
|
|
800
|
+
totalSize: 0,
|
|
801
|
+
folderCount: 0,
|
|
802
|
+
folders: [],
|
|
803
|
+
lastModified: null,
|
|
804
|
+
gitClean: null,
|
|
805
|
+
gitBranch: branch || config?.branch || 'main',
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
const notes = listNotes(projectRoot);
|
|
810
|
+
const totalSize = notes.reduce((acc, n) => acc + (n.size || 0), 0);
|
|
811
|
+
const folders = new Set();
|
|
812
|
+
for (const n of notes) {
|
|
813
|
+
const seg = n.relPath.split('/');
|
|
814
|
+
if (seg.length > 1) folders.add(seg[0]);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
let gitClean = null;
|
|
818
|
+
let gitBranch = null;
|
|
819
|
+
if (mode === 'managed' || mode === 'linked') {
|
|
820
|
+
try {
|
|
821
|
+
const { isGitInstalled, status: gitStatus } = memoryGit;
|
|
822
|
+
if (isGitInstalled()) {
|
|
823
|
+
const gs = gitStatus(projectVaultRoot);
|
|
824
|
+
gitClean = gs.clean;
|
|
825
|
+
gitBranch = gs.branch;
|
|
826
|
+
}
|
|
827
|
+
} catch {
|
|
828
|
+
// ignore — git is optional
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
return {
|
|
833
|
+
exists: true,
|
|
834
|
+
vaultRoot,
|
|
835
|
+
mode,
|
|
836
|
+
noteCount: notes.length,
|
|
837
|
+
totalSize,
|
|
838
|
+
folderCount: folders.size,
|
|
839
|
+
folders: [...folders].sort(),
|
|
840
|
+
lastModified: notes[0]?.mtime || null,
|
|
841
|
+
gitClean,
|
|
842
|
+
gitBranch: gitBranch || branch || config?.branch || 'main',
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// ── v5.5.2 Legacy config migration ─────────────────────────────────────────
|
|
847
|
+
//
|
|
848
|
+
// When the user upgrades from pre-v5.5.2, their `.bizar/memory.json` may
|
|
849
|
+
// still point `git.repoPath` at the legacy path
|
|
850
|
+
// (`~/.local/share/bizar/memory/bizar-memory`). The new default vault root
|
|
851
|
+
// is `~/.bizar_memory/bizar-memory`. This helper detects the stale path and
|
|
852
|
+
// auto-corrects the config so all git checks work immediately after upgrade.
|
|
853
|
+
//
|
|
854
|
+
// Behaviour:
|
|
855
|
+
// - Only migrates if the legacy path doesn't exist but the new one does.
|
|
856
|
+
// - Only migrates if `git.repoPath` is explicitly set in the config.
|
|
857
|
+
// - Idempotent — once migrated, the new path exists and the check is a
|
|
858
|
+
// no-op on subsequent boots.
|
|
859
|
+
// - Returns { migrated: true } only on actual change; { migrated: false }
|
|
860
|
+
// for all other cases (already correct, not applicable, or failure).
|
|
861
|
+
//
|
|
862
|
+
// Called once at dashboard startup from server.mjs.
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
* Detect and fix a stale `git.repoPath` pointing at the legacy vault location.
|
|
866
|
+
*
|
|
867
|
+
* @param {string} projectRoot — project root (where `.bizar/memory.json` lives)
|
|
868
|
+
* @returns {{ migrated: boolean, from?: string, to?: string, error?: string }}
|
|
869
|
+
*/
|
|
870
|
+
export function migrateLegacyGitRepoPath(projectRoot) {
|
|
871
|
+
const configPath = join(projectRoot, '.bizar', 'memory.json');
|
|
872
|
+
let raw;
|
|
873
|
+
try {
|
|
874
|
+
raw = safeReadJSON(configPath, null);
|
|
875
|
+
} catch {
|
|
876
|
+
return { migrated: false };
|
|
877
|
+
}
|
|
878
|
+
if (!raw) return { migrated: false };
|
|
879
|
+
|
|
880
|
+
const gitBlock = raw.git || raw.memoryRepo || {};
|
|
881
|
+
const currentRepoPath = gitBlock.repoPath;
|
|
882
|
+
if (!currentRepoPath || typeof currentRepoPath !== 'string') return { migrated: false };
|
|
883
|
+
|
|
884
|
+
const expanded = currentRepoPath.startsWith('~')
|
|
885
|
+
? join(HOME, currentRepoPath.slice(1))
|
|
886
|
+
: currentRepoPath;
|
|
887
|
+
|
|
888
|
+
// Only migrate when the configured path doesn't exist but the new default does.
|
|
889
|
+
if (existsSync(expanded)) return { migrated: false };
|
|
890
|
+
|
|
891
|
+
const newDefault = join(DEFAULT_MEMORY_VAULT, 'bizar-memory');
|
|
892
|
+
if (!existsSync(newDefault)) return { migrated: false };
|
|
893
|
+
|
|
894
|
+
// Verify the new path is actually a git repo before migrating.
|
|
895
|
+
if (!existsSync(join(newDefault, '.git'))) return { migrated: false };
|
|
896
|
+
|
|
897
|
+
// Apply the fix: update gitBlock.repoPath (or memoryRepo.repoPath) to newDefault.
|
|
898
|
+
try {
|
|
899
|
+
const updated = JSON.parse(JSON.stringify(raw));
|
|
900
|
+
if (!updated.git) updated.git = {};
|
|
901
|
+
if (!updated.memoryRepo) updated.memoryRepo = {};
|
|
902
|
+
updated.git.repoPath = newDefault;
|
|
903
|
+
updated.memoryRepo.path = newDefault;
|
|
904
|
+
atomicWriteJson(configPath, updated);
|
|
905
|
+
console.warn(
|
|
906
|
+
`[memory-store] Auto-migrated git.repoPath from legacy path\n` +
|
|
907
|
+
`[memory-store] FROM: ${expanded}\n` +
|
|
908
|
+
`[memory-store] TO: ${newDefault}\n` +
|
|
909
|
+
`[memory-store] Please restart the dashboard to pick up the new path.`,
|
|
910
|
+
);
|
|
911
|
+
return { migrated: true, from: expanded, to: newDefault };
|
|
912
|
+
} catch (err) {
|
|
913
|
+
return { migrated: false, error: err.message };
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// ── LightRAG integration (v4.1.0) ──────────────────────────────────────────
|
|
918
|
+
//
|
|
919
|
+
// Re-export the LightRAG orchestrator from the memory-store module so the
|
|
920
|
+
// dashboard, CLI, and tests have a single import surface. The actual
|
|
921
|
+
// implementation lives in `memory-lightrag.mjs`.
|
|
922
|
+
|
|
923
|
+
export {
|
|
924
|
+
resolveLightRAGConfig,
|
|
925
|
+
isInstalled as isLightRAGInstalled,
|
|
926
|
+
isRunning as isLightRAGRunning,
|
|
927
|
+
startServer as startLightRAG,
|
|
928
|
+
stopServer as stopLightRAG,
|
|
929
|
+
ensureRunning as ensureLightRAGRunning,
|
|
930
|
+
insertNote as insertLightRAGNote,
|
|
931
|
+
insertAllNotes as insertLightRAGAll,
|
|
932
|
+
reindexVault,
|
|
933
|
+
query as queryLightRAG,
|
|
934
|
+
} from './memory-lightrag.mjs';
|
|
935
|
+
|
|
936
|
+
// ── v4.6.0 LightRAG default model helpers ──────────────────────────────────
|
|
937
|
+
//
|
|
938
|
+
// Free cline Zen defaults — no API key required for free-tier models.
|
|
939
|
+
// Operators can override per-project via:
|
|
940
|
+
// - env: BIZAR_LIGHTRAG_LLM, BIZAR_LIGHTRAG_EMBEDDING
|
|
941
|
+
// - config: .bizar/memory.json#lightrag.llmModel / .embeddingModel
|
|
942
|
+
//
|
|
943
|
+
// The dashboard surfaces these via /api/lightrag/defaults so the
|
|
944
|
+
// settings view can show "currently using: cline/gpt-5-nano (free)".
|
|
945
|
+
|
|
946
|
+
export const LIGHTRAG_DEFAULT_LLM = 'cline/gpt-5-nano';
|
|
947
|
+
export const LIGHTRAG_DEFAULT_EMBEDDING = 'cline/text-embedding-3-small';
|
|
948
|
+
|
|
949
|
+
/**
|
|
950
|
+
* Build a wikilink link graph from all .md notes in the vault.
|
|
951
|
+
*
|
|
952
|
+
* Nodes: one per note (id = relPath, label = title or basename).
|
|
953
|
+
* Edges: one per wikilink [[Target]] found in note bodies.
|
|
954
|
+
*
|
|
955
|
+
* @param {{ projectRoot: string, vaultPath?: string|null, limit?: number }} opts
|
|
956
|
+
* @returns {{ nodes: Array<{id:string,label:string,type:string,size:number,group:string}>, edges: Array<{source:string,target:string,type:string,weight:number}> }}
|
|
957
|
+
*/
|
|
958
|
+
export function getObsidianLinkGraph({ projectRoot, vaultPath = null, limit = 200 }) {
|
|
959
|
+
const { vaultRoot } = resolveVault(projectRoot);
|
|
960
|
+
const root = vaultPath || vaultRoot;
|
|
961
|
+
const nodesMap = new Map(); // id → node
|
|
962
|
+
const edges = [];
|
|
963
|
+
|
|
964
|
+
// Collect all notes.
|
|
965
|
+
const notes = listNotesForGraph(root);
|
|
966
|
+
const sliced = notes.slice(0, limit);
|
|
967
|
+
|
|
968
|
+
for (const note of sliced) {
|
|
969
|
+
if (!nodesMap.has(note.relPath)) {
|
|
970
|
+
nodesMap.set(note.relPath, {
|
|
971
|
+
id: note.relPath,
|
|
972
|
+
label: note.frontmatter?.title || note.relPath.split('/').pop()?.replace(/\.md$/i, '') || note.relPath,
|
|
973
|
+
type: 'note',
|
|
974
|
+
size: 1,
|
|
975
|
+
group: note.relPath.split('/')[0] || 'root',
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
// Extract wikilinks from body.
|
|
980
|
+
const WIKILINK_RE = /\[\[([^\]\n|]+?)(?:\|[^\]\n]+?)?(?:#[^\]\n]+?)?\]\]/g;
|
|
981
|
+
const body = note.body || '';
|
|
982
|
+
let m;
|
|
983
|
+
WIKILINK_RE.lastIndex = 0;
|
|
984
|
+
while ((m = WIKILINK_RE.exec(body)) !== null) {
|
|
985
|
+
const raw = (m[1] || '').trim();
|
|
986
|
+
if (!raw) continue;
|
|
987
|
+
const target = raw.split('#')[0].trim().split('/').pop() || raw;
|
|
988
|
+
// Resolve to a note id (basename match).
|
|
989
|
+
const targetId = resolveWikilinkTarget(target, notes);
|
|
990
|
+
if (targetId && targetId !== note.relPath) {
|
|
991
|
+
edges.push({
|
|
992
|
+
source: note.relPath,
|
|
993
|
+
target: targetId,
|
|
994
|
+
type: 'links_to',
|
|
995
|
+
weight: 1,
|
|
996
|
+
});
|
|
997
|
+
// Ensure target node exists.
|
|
998
|
+
if (!nodesMap.has(targetId)) {
|
|
999
|
+
nodesMap.set(targetId, {
|
|
1000
|
+
id: targetId,
|
|
1001
|
+
label: target,
|
|
1002
|
+
type: 'note',
|
|
1003
|
+
size: 1,
|
|
1004
|
+
group: targetId.split('/')[0] || 'root',
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
return {
|
|
1012
|
+
nodes: [...nodesMap.values()].slice(0, limit),
|
|
1013
|
+
edges: edges.slice(0, limit * 3),
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
/**
|
|
1018
|
+
* List notes from a specific root path (not the project vault root).
|
|
1019
|
+
* Used by getObsidianLinkGraph for scanning arbitrary vaults.
|
|
1020
|
+
*/
|
|
1021
|
+
function listNotesForGraph(scanRoot) {
|
|
1022
|
+
if (!existsSync(scanRoot)) return [];
|
|
1023
|
+
const out = [];
|
|
1024
|
+
function walk(dir, prefix) {
|
|
1025
|
+
let entries;
|
|
1026
|
+
try { entries = readdirSync(dir, { withFileTypes: true }); }
|
|
1027
|
+
catch { return; }
|
|
1028
|
+
for (const e of entries) {
|
|
1029
|
+
if (e.name.startsWith('.')) continue;
|
|
1030
|
+
const full = join(dir, e.name);
|
|
1031
|
+
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
1032
|
+
if (e.isDirectory()) {
|
|
1033
|
+
walk(full, rel);
|
|
1034
|
+
} else if (e.name.endsWith('.md')) {
|
|
1035
|
+
try {
|
|
1036
|
+
const raw = readFileSync(full, 'utf8');
|
|
1037
|
+
const { frontmatter, body } = parseFrontmatter(raw);
|
|
1038
|
+
out.push({ relPath: rel, frontmatter, body });
|
|
1039
|
+
} catch { /* skip */ }
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
walk(scanRoot, '');
|
|
1044
|
+
return out;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
/**
|
|
1048
|
+
* Resolve a wikilink target (e.g. "My Note" or "subdir/My Note") to a note id.
|
|
1049
|
+
* Uses basename matching (Obsidian semantics).
|
|
1050
|
+
*/
|
|
1051
|
+
function resolveWikilinkTarget(targetName, notes) {
|
|
1052
|
+
const normalized = targetName.replace(/\.md$/i, '').toLowerCase();
|
|
1053
|
+
// Try exact relPath match first.
|
|
1054
|
+
for (const n of notes) {
|
|
1055
|
+
const base = n.relPath.replace(/\.md$/i, '').toLowerCase();
|
|
1056
|
+
if (base === normalized || base.endsWith('/' + normalized)) {
|
|
1057
|
+
return n.relPath;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
// Fallback: basename-only match.
|
|
1061
|
+
for (const n of notes) {
|
|
1062
|
+
const base = n.relPath.split('/').pop()?.replace(/\.md$/i, '').toLowerCase();
|
|
1063
|
+
if (base === normalized) {
|
|
1064
|
+
return n.relPath;
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
return null;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
/**
|
|
1071
|
+
* Return the effective LightRAG model defaults, applying env-var
|
|
1072
|
+
* overrides on top of the built-in cline-Zen-free defaults.
|
|
1073
|
+
*
|
|
1074
|
+
* @returns {{ llm: string, embedding: string, source: 'cline-free' | 'env', llmSource: 'default' | 'env', embeddingSource: 'default' | 'env' }}
|
|
1075
|
+
*/
|
|
1076
|
+
export function getDefaultLightRAGConfig() {
|
|
1077
|
+
const llmEnv = typeof process.env.BIZAR_LIGHTRAG_LLM === 'string' && process.env.BIZAR_LIGHTRAG_LLM.trim()
|
|
1078
|
+
? process.env.BIZAR_LIGHTRAG_LLM.trim()
|
|
1079
|
+
: null;
|
|
1080
|
+
const embEnv = typeof process.env.BIZAR_LIGHTRAG_EMBEDDING === 'string' && process.env.BIZAR_LIGHTRAG_EMBEDDING.trim()
|
|
1081
|
+
? process.env.BIZAR_LIGHTRAG_EMBEDDING.trim()
|
|
1082
|
+
: null;
|
|
1083
|
+
const llm = llmEnv || LIGHTRAG_DEFAULT_LLM;
|
|
1084
|
+
const embedding = embEnv || LIGHTRAG_DEFAULT_EMBEDDING;
|
|
1085
|
+
const source = (llmEnv || embEnv) ? 'env' : 'cline-free';
|
|
1086
|
+
return {
|
|
1087
|
+
llm,
|
|
1088
|
+
embedding,
|
|
1089
|
+
source,
|
|
1090
|
+
llmSource: llmEnv ? 'env' : 'default',
|
|
1091
|
+
embeddingSource: embEnv ? 'env' : 'default',
|
|
1092
|
+
};
|
|
1093
|
+
}
|