@polderlabs/bizar 6.2.5 → 7.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/CLAUDE.md +15 -0
- package/.claude/agents/_shared/AGENT_BASELINE.md +168 -0
- package/.claude/agents/_shared/CLAUDE_TOOLS.md +412 -0
- package/.claude/agents/_shared/SKILLS.md +109 -0
- package/.claude/agents/agent-browser.md +80 -0
- package/.claude/agents/baldr.md +49 -0
- package/.claude/agents/forseti.md +51 -0
- package/.claude/agents/frigg.md +42 -0
- package/.claude/agents/heimdall.md +33 -0
- package/.claude/agents/hermod.md +53 -0
- package/.claude/agents/mimir.md +49 -0
- package/.claude/agents/odin.md +287 -0
- package/.claude/agents/quick.md +34 -0
- package/.claude/agents/semble-search.md +50 -0
- package/.claude/agents/thor.md +53 -0
- package/.claude/agents/tyr.md +56 -0
- package/.claude/agents/vidarr.md +54 -0
- package/.claude/agents/vor.md +53 -0
- package/.claude/commands/audit.md +25 -0
- package/.claude/commands/bizar.md +22 -0
- package/.claude/commands/explain.md +17 -0
- package/.claude/commands/init.md +29 -0
- package/.claude/commands/learn.md +44 -0
- package/.claude/commands/plan.md +35 -0
- package/.claude/commands/plow-through.md +50 -0
- package/.claude/commands/pr-review.md +49 -0
- package/.claude/commands/setup-provider.md +96 -0
- package/.claude/commands/tailscale-serve.md +100 -0
- package/.claude/commands/team.md +132 -0
- package/.claude/commands/test.md +62 -0
- package/.claude/commands/validate.md +68 -0
- package/.claude/commands/visual-plan.md +24 -0
- package/.claude/hooks/README.md +92 -0
- package/.claude/hooks/posttooluse-editwrite.mjs +91 -0
- package/.claude/hooks/pretooluse-bash.mjs +81 -0
- package/.claude/hooks/pretooluse-editwrite.mjs +139 -0
- package/.claude/hooks/sessionend-recall.mjs +74 -0
- package/.claude/hooks/sessionstart-prime.mjs +80 -0
- package/.claude/hooks/userpromptsubmit-tag.mjs +80 -0
- package/.claude/hooks/worker-suggest.mjs +110 -0
- package/.claude/settings.json +125 -0
- package/.claude/skills/9router/SKILL.md +80 -0
- package/.claude/skills/9router-chat/SKILL.md +73 -0
- package/.claude/skills/9router-embeddings/SKILL.md +69 -0
- package/.claude/skills/9router-image/SKILL.md +86 -0
- package/.claude/skills/9router-stt/SKILL.md +79 -0
- package/.claude/skills/9router-tts/SKILL.md +80 -0
- package/.claude/skills/9router-web-fetch/SKILL.md +99 -0
- package/.claude/skills/9router-web-search/SKILL.md +91 -0
- package/.claude/skills/bizar/README.md +9 -0
- package/.claude/skills/bizar/SKILL.md +450 -0
- package/.claude/skills/cpp-coding-standards/README.md +28 -0
- package/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
- package/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
- package/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
- package/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
- package/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
- package/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
- package/.claude/skills/cpp-testing/README.md +28 -0
- package/.claude/skills/cpp-testing/SKILL.md +304 -0
- package/.claude/skills/cpp-testing/references/coverage.md +370 -0
- package/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
- package/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
- package/.claude/skills/cpp-testing/references/mocking.md +364 -0
- package/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
- package/.claude/skills/cubesandbox/SKILL.md +148 -0
- package/.claude/skills/embedded-esp-idf/README.md +41 -0
- package/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
- package/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
- package/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
- package/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
- package/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
- package/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
- package/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
- package/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
- package/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
- package/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
- package/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
- package/.claude/skills/glyph/SKILL.md +163 -0
- package/.claude/skills/harness-engineering/SKILL.md +143 -0
- package/.claude/skills/lightrag/SKILL.md +81 -0
- package/.claude/skills/memory-protocol/SKILL.md +105 -0
- package/.claude/skills/obsidian/SKILL.md +306 -0
- package/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
- package/.claude/skills/self-improvement/SKILL.md +64 -0
- package/README.md +87 -59
- package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js → EnvVarsSection-CW6fWKds.js} +3 -3
- package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js.map → EnvVarsSection-CW6fWKds.js.map} +1 -1
- package/bizar-dash/dist/assets/MobileChat-D7zRhU9K.js +1 -0
- package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js.map → MobileChat-D7zRhU9K.js.map} +1 -1
- package/bizar-dash/dist/assets/MobileSettings-K-sNsn_r.js +1 -0
- package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js.map → MobileSettings-K-sNsn_r.js.map} +1 -1
- package/bizar-dash/dist/assets/{Toast-Cpl6-E63.js → Toast-WTxc3m2g.js} +1 -1
- package/bizar-dash/dist/assets/{Toast-Cpl6-E63.js.map → Toast-WTxc3m2g.js.map} +1 -1
- package/bizar-dash/dist/assets/flow-BpU0-gK2.js +1 -0
- package/bizar-dash/dist/assets/flow-BpU0-gK2.js.map +1 -0
- package/bizar-dash/dist/assets/fuzzy-l0sNRNKZ.js +1 -0
- package/bizar-dash/dist/assets/fuzzy-l0sNRNKZ.js.map +1 -0
- package/bizar-dash/dist/assets/{icons-Do5N2jmX.js → icons-B0AKnYI3.js} +98 -103
- package/bizar-dash/dist/assets/icons-B0AKnYI3.js.map +1 -0
- package/bizar-dash/dist/assets/main-C-Md3DaY.css +1 -0
- package/bizar-dash/dist/assets/main-CO8fIxQK.js +18 -0
- package/bizar-dash/dist/assets/main-CO8fIxQK.js.map +1 -0
- package/bizar-dash/dist/assets/markdown-w2bDDkAH.js +1 -0
- package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js.map → markdown-w2bDDkAH.js.map} +1 -1
- package/bizar-dash/dist/assets/mobile-DXYCA0hC.js +1 -0
- package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js.map → mobile-DXYCA0hC.js.map} +1 -1
- package/bizar-dash/dist/assets/mobile-layout-DSmtNPja.js +2 -0
- package/bizar-dash/dist/assets/mobile-layout-DSmtNPja.js.map +1 -0
- package/bizar-dash/dist/assets/react-vendor-BnuhLJ6X.css +1 -0
- package/bizar-dash/dist/assets/react-vendor-D3pra6w-.js +46 -0
- package/bizar-dash/dist/assets/react-vendor-D3pra6w-.js.map +1 -0
- package/bizar-dash/dist/assets/useSlashCommands-3DFLOfpk.js +2 -0
- package/bizar-dash/dist/assets/useSlashCommands-3DFLOfpk.js.map +1 -0
- package/bizar-dash/dist/assets/vendor-Di7Cp-rw.js +45 -0
- package/bizar-dash/dist/assets/vendor-Di7Cp-rw.js.map +1 -0
- package/bizar-dash/dist/index.html +12 -10
- package/bizar-dash/dist/mobile.html +7 -4
- package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/bizar-dash/src/server/api.mjs +15 -4
- package/bizar-dash/src/server/background-store.mjs +15 -16
- package/bizar-dash/src/server/bg-poller.mjs +25 -35
- package/bizar-dash/src/server/bg-retry.mjs +66 -194
- package/bizar-dash/src/server/claude-bg-spawner.mjs +390 -0
- package/bizar-dash/src/server/claude-info.mjs +412 -0
- package/bizar-dash/src/server/{cline-runner.mjs → claude-runner.mjs} +53 -48
- package/bizar-dash/src/server/claude-sdk.mjs +191 -0
- package/bizar-dash/src/server/memory-consolidator.mjs +218 -0
- package/bizar-dash/src/server/memory-distillation.mjs +296 -0
- package/bizar-dash/src/server/providers-store.mjs +22 -49
- package/bizar-dash/src/server/routes/background.mjs +24 -20
- package/bizar-dash/src/server/routes/chat.mjs +223 -326
- package/bizar-dash/src/server/routes/claude-session-detail.mjs +329 -0
- package/bizar-dash/src/server/routes/claude-sessions.mjs +259 -0
- package/bizar-dash/src/server/routes/distill.mjs +129 -0
- package/bizar-dash/src/server/routes/goal-planner.mjs +236 -0
- package/bizar-dash/src/server/routes/tasks.mjs +20 -28
- package/bizar-dash/src/server/task-delegator.mjs +76 -77
- package/bizar-dash/src/web/App.tsx +4 -0
- package/bizar-dash/src/web/components/Tag.tsx +18 -5
- package/bizar-dash/src/web/components/Topbar.tsx +3 -0
- package/bizar-dash/src/web/components/agents/CommunicationLog.tsx +126 -0
- package/bizar-dash/src/web/components/agents/DependencyGraph.tsx +163 -0
- package/bizar-dash/src/web/components/agents/QualityGates.tsx +123 -0
- package/bizar-dash/src/web/components/agents/RealTimeEventLog.tsx +127 -0
- package/bizar-dash/src/web/components/agents/RoutingDecisions.test.tsx +148 -0
- package/bizar-dash/src/web/components/agents/RoutingDecisions.tsx +160 -0
- package/bizar-dash/src/web/components/chat/useChat.ts +23 -27
- package/bizar-dash/src/web/components/goals/GoalInput.tsx +86 -0
- package/bizar-dash/src/web/components/goals/PlanVisualization.tsx +111 -0
- package/bizar-dash/src/web/lib/goapPlanner.ts +614 -0
- package/bizar-dash/src/web/lib/types.ts +25 -0
- package/bizar-dash/src/web/styles/agents-redesign.css +311 -0
- package/bizar-dash/src/web/styles/main.css +251 -0
- package/bizar-dash/src/web/styles/tasks-redesign.css +231 -0
- package/bizar-dash/src/web/ui/controls/Button.tsx +77 -0
- package/bizar-dash/src/web/ui/controls/Checkbox.tsx +95 -0
- package/bizar-dash/src/web/ui/controls/IconButton.tsx +66 -0
- package/bizar-dash/src/web/ui/controls/Kbd.tsx +24 -0
- package/bizar-dash/src/web/ui/controls/NumberInput.tsx +77 -0
- package/bizar-dash/src/web/ui/controls/RadioGroup.tsx +109 -0
- package/bizar-dash/src/web/ui/controls/SearchInput.tsx +91 -0
- package/bizar-dash/src/web/ui/controls/Select.tsx +92 -0
- package/bizar-dash/src/web/ui/controls/Slider.tsx +70 -0
- package/bizar-dash/src/web/ui/controls/TextInput.tsx +67 -0
- package/bizar-dash/src/web/ui/controls/Toggle.tsx +79 -0
- package/bizar-dash/src/web/ui/controls/controls.css +454 -0
- package/bizar-dash/src/web/ui/controls/index.ts +33 -0
- package/bizar-dash/src/web/ui/data/BarChart.tsx +60 -0
- package/bizar-dash/src/web/ui/data/DataTable.tsx +216 -0
- package/bizar-dash/src/web/ui/data/EmptyState.tsx +60 -0
- package/bizar-dash/src/web/ui/data/ErrorState.tsx +56 -0
- package/bizar-dash/src/web/ui/data/KeyValueList.tsx +106 -0
- package/bizar-dash/src/web/ui/data/LoadingState.tsx +65 -0
- package/bizar-dash/src/web/ui/data/Sparkline.tsx +87 -0
- package/bizar-dash/src/web/ui/data/StatTile.tsx +87 -0
- package/bizar-dash/src/web/ui/data/data.css +535 -0
- package/bizar-dash/src/web/ui/data/index.ts +31 -0
- package/bizar-dash/src/web/ui/feedback/Badge.tsx +49 -0
- package/bizar-dash/src/web/ui/feedback/Dialog.tsx +209 -0
- package/bizar-dash/src/web/ui/feedback/ProgressBar.tsx +69 -0
- package/bizar-dash/src/web/ui/feedback/StatusDot.tsx +50 -0
- package/bizar-dash/src/web/ui/feedback/Toast.tsx +200 -0
- package/bizar-dash/src/web/ui/feedback/Tooltip.tsx +126 -0
- package/bizar-dash/src/web/ui/feedback/feedback.css +314 -0
- package/bizar-dash/src/web/ui/feedback/index.ts +43 -0
- package/bizar-dash/src/web/ui/index.ts +56 -0
- package/bizar-dash/src/web/ui/layout/AppShell.tsx +51 -0
- package/bizar-dash/src/web/ui/layout/Breadcrumbs.tsx +97 -0
- package/bizar-dash/src/web/ui/layout/Panel.tsx +73 -0
- package/bizar-dash/src/web/ui/layout/PanelHeader.tsx +39 -0
- package/bizar-dash/src/web/ui/layout/Sidebar.tsx +131 -0
- package/bizar-dash/src/web/ui/layout/Tabs.tsx +133 -0
- package/bizar-dash/src/web/ui/layout/Topbar.tsx +42 -0
- package/bizar-dash/src/web/ui/layout/index.ts +33 -0
- package/bizar-dash/src/web/ui/layout/layout.css +413 -0
- package/bizar-dash/src/web/ui/navigation/CommandPalette.tsx +199 -0
- package/bizar-dash/src/web/ui/navigation/NavGroup.tsx +95 -0
- package/bizar-dash/src/web/ui/navigation/NavLink.tsx +93 -0
- package/bizar-dash/src/web/ui/navigation/index.ts +17 -0
- package/bizar-dash/src/web/ui/navigation/navigation.css +343 -0
- package/bizar-dash/src/web/ui/primitives/Box.tsx +91 -0
- package/bizar-dash/src/web/ui/primitives/Grid.tsx +49 -0
- package/bizar-dash/src/web/ui/primitives/Inline.tsx +55 -0
- package/bizar-dash/src/web/ui/primitives/Separator.tsx +46 -0
- package/bizar-dash/src/web/ui/primitives/Stack.tsx +54 -0
- package/bizar-dash/src/web/ui/primitives/VisuallyHidden.tsx +26 -0
- package/bizar-dash/src/web/ui/primitives/index.ts +23 -0
- package/bizar-dash/src/web/ui/primitives/primitives.css +183 -0
- package/bizar-dash/src/web/ui/styles/globals.css +86 -0
- package/bizar-dash/src/web/ui/styles/reset.css +125 -0
- package/bizar-dash/src/web/ui/styles/tokens.css +195 -0
- package/bizar-dash/src/web/ui/theme/ThemeProvider.tsx +142 -0
- package/bizar-dash/src/web/ui/theme/tokens.ts +131 -0
- package/bizar-dash/src/web/ui/theme/useTheme.ts +22 -0
- package/bizar-dash/src/web/ui/utils/cx.ts +42 -0
- package/bizar-dash/src/web/views/Agents.tsx +506 -266
- package/bizar-dash/src/web/views/Chat.tsx +8 -8
- package/bizar-dash/src/web/views/GoalPlanner.tsx +158 -0
- package/bizar-dash/src/web/views/Overview.tsx +996 -448
- package/bizar-dash/src/web/views/Tasks.tsx +277 -273
- package/bizar-dash/tests/communication-log.test.tsx +67 -0
- package/bizar-dash/tests/dep-graph.test.tsx +40 -0
- package/bizar-dash/tests/event-log.test.tsx +61 -0
- package/bizar-dash/tests/goal-input.test.tsx +72 -0
- package/bizar-dash/tests/goap-planner.test.ts +68 -0
- package/bizar-dash/tests/quality-gates.test.tsx +59 -0
- package/bizar-dash/tests/setup.ts +31 -1
- package/bizar-dash/tests/ui/controls/Button.test.tsx +50 -0
- package/bizar-dash/tests/ui/controls/Checkbox.test.tsx +44 -0
- package/bizar-dash/tests/ui/controls/IconButton.test.tsx +37 -0
- package/bizar-dash/tests/ui/controls/Kbd.test.tsx +39 -0
- package/bizar-dash/tests/ui/controls/NumberInput.test.tsx +56 -0
- package/bizar-dash/tests/ui/controls/RadioGroup.test.tsx +58 -0
- package/bizar-dash/tests/ui/controls/SearchInput.test.tsx +52 -0
- package/bizar-dash/tests/ui/controls/Select.test.tsx +66 -0
- package/bizar-dash/tests/ui/controls/Slider.test.tsx +41 -0
- package/bizar-dash/tests/ui/controls/TextInput.test.tsx +44 -0
- package/bizar-dash/tests/ui/controls/Toggle.test.tsx +39 -0
- package/bizar-dash/tests/ui/data/BarChart.test.tsx +55 -0
- package/bizar-dash/tests/ui/data/DataTable.test.tsx +112 -0
- package/bizar-dash/tests/ui/data/EmptyState.test.tsx +57 -0
- package/bizar-dash/tests/ui/data/ErrorState.test.tsx +47 -0
- package/bizar-dash/tests/ui/data/KeyValueList.test.tsx +59 -0
- package/bizar-dash/tests/ui/data/LoadingState.test.tsx +37 -0
- package/bizar-dash/tests/ui/data/Sparkline.test.tsx +56 -0
- package/bizar-dash/tests/ui/data/StatTile.test.tsx +69 -0
- package/bizar-dash/tests/ui/feedback/Badge.test.tsx +41 -0
- package/bizar-dash/tests/ui/feedback/Dialog.test.tsx +99 -0
- package/bizar-dash/tests/ui/feedback/ProgressBar.test.tsx +66 -0
- package/bizar-dash/tests/ui/feedback/StatusDot.test.tsx +41 -0
- package/bizar-dash/tests/ui/feedback/Toast.test.tsx +124 -0
- package/bizar-dash/tests/ui/feedback/Tooltip.test.tsx +102 -0
- package/bizar-dash/tests/ui/layout/AppShell.test.tsx +50 -0
- package/bizar-dash/tests/ui/layout/Breadcrumbs.test.tsx +85 -0
- package/bizar-dash/tests/ui/layout/Panel.test.tsx +52 -0
- package/bizar-dash/tests/ui/layout/PanelHeader.test.tsx +32 -0
- package/bizar-dash/tests/ui/layout/Sidebar.test.tsx +95 -0
- package/bizar-dash/tests/ui/layout/Tabs.test.tsx +87 -0
- package/bizar-dash/tests/ui/layout/Topbar.test.tsx +41 -0
- package/bizar-dash/tests/ui/navigation/CommandPalette.test.tsx +105 -0
- package/bizar-dash/tests/ui/navigation/NavGroup.test.tsx +55 -0
- package/bizar-dash/tests/ui/navigation/NavLink.test.tsx +61 -0
- package/bizar-dash/tests/ui/primitives/Box.test.tsx +49 -0
- package/bizar-dash/tests/ui/primitives/Grid.test.tsx +37 -0
- package/bizar-dash/tests/ui/primitives/Inline.test.tsx +33 -0
- package/bizar-dash/tests/ui/primitives/Separator.test.tsx +34 -0
- package/bizar-dash/tests/ui/primitives/Stack.test.tsx +45 -0
- package/bizar-dash/tests/ui/primitives/VisuallyHidden.test.tsx +27 -0
- package/bizar-dash/tests/views/Agents.test.tsx +359 -0
- package/bizar-dash/tests/views/Overview.test.tsx +413 -0
- package/bizar-dash/tests/views/Tasks.test.tsx +250 -0
- package/bizar-dash/vitest.config.ts +3 -1
- package/cli/__tests__/cost-gate.test.mjs +301 -0
- package/cli/__tests__/feature-list-bridge.test.mjs +371 -0
- package/cli/bin.mjs +55 -18
- package/cli/commands/claim.mjs +282 -0
- package/cli/commands/claude-cmd.mjs +348 -0
- package/cli/commands/cost.mjs +279 -0
- package/cli/commands/install.mjs +12 -11
- package/cli/commands/validate.mjs +252 -325
- package/cli/cost-gate.mjs +501 -0
- package/cli/dev-link.test.mjs +11 -11
- package/cli/doctor.mjs +131 -213
- package/cli/feature-list-bridge.mjs +400 -0
- package/cli/install.mjs +33 -37
- package/cli/install.test.mjs +9 -9
- package/cli/memory-constants.mjs +17 -0
- package/cli/provision-claude.mjs +893 -0
- package/cli/provision.mjs +224 -227
- package/cli/utils.mjs +72 -58
- package/cli/worker-dispatcher.mjs +259 -0
- package/cli/worker-dispatcher.test.mjs +204 -0
- package/config/AGENTS.md +28 -28
- package/config/trigger-patterns.json +186 -0
- package/install.sh +66 -44
- package/package.json +19 -11
- package/packages/sdk/ARCHITECTURE.md +40 -36
- package/packages/sdk/package.json +15 -5
- package/packages/sdk/src/agent-registry.ts +304 -0
- package/packages/sdk/src/consensus/byzantine.ts +587 -0
- package/packages/sdk/src/consensus/index.ts +147 -0
- package/packages/sdk/src/consensus/queen.ts +173 -0
- package/packages/sdk/src/consensus/types.ts +199 -0
- package/{plugins/bizar → packages/sdk}/src/dangerous-patterns.ts +6 -28
- package/packages/sdk/src/federation/audit.ts +156 -0
- package/packages/sdk/src/federation/budget.ts +269 -0
- package/packages/sdk/src/federation/envelope.ts +144 -0
- package/packages/sdk/src/federation/hmac.ts +160 -0
- package/packages/sdk/src/federation/index.ts +443 -0
- package/packages/sdk/src/federation/pii.ts +241 -0
- package/packages/sdk/src/federation/policy.ts +112 -0
- package/packages/sdk/src/federation/trust.ts +146 -0
- package/packages/sdk/src/fingerprint.ts +0 -0
- package/packages/sdk/src/index.ts +101 -69
- package/packages/sdk/src/mcp/bin.ts +51 -0
- package/packages/sdk/src/mcp/server.ts +848 -0
- package/{plugins/bizar/src/memory-vault.ts → packages/sdk/src/memory/index.ts} +18 -21
- package/packages/sdk/src/router/codemod-intent.ts +125 -0
- package/packages/sdk/src/router/index.ts +247 -0
- package/packages/sdk/src/router/memory-distillation-shim.mjs +18 -0
- package/packages/sdk/src/router/memory-distillation.ts +249 -0
- package/packages/sdk/src/router/model-router.ts +235 -0
- package/packages/sdk/src/router/q-learning-router.ts +304 -0
- package/packages/sdk/src/swarm-topology.ts +279 -0
- package/packages/sdk/tests/agent-registry.test.ts +285 -0
- package/packages/sdk/tests/consensus.test.ts +376 -0
- package/packages/sdk/tests/federation/audit.test.ts +164 -0
- package/packages/sdk/tests/federation/budget.test.ts +189 -0
- package/packages/sdk/tests/federation/envelope.test.ts +120 -0
- package/packages/sdk/tests/federation/hmac.test.ts +194 -0
- package/packages/sdk/tests/federation/orchestrator.test.ts +176 -0
- package/packages/sdk/tests/federation/pii.test.ts +106 -0
- package/packages/sdk/tests/federation/policy.test.ts +140 -0
- package/packages/sdk/tests/federation/trust.test.ts +124 -0
- package/packages/sdk/tests/mcp-tools.test.ts +204 -0
- package/packages/sdk/tests/memory-distillation.test.mjs +186 -0
- package/packages/sdk/tests/model-router.test.mjs +108 -0
- package/packages/sdk/tests/q-learning-router.test.mjs +100 -0
- package/packages/sdk/tests/router-orchestrator.test.mjs +172 -0
- package/packages/sdk/tests/router.test.mjs +91 -0
- package/packages/sdk/tests/sdk.test.mjs +172 -0
- package/packages/sdk/tests/swarm-topology.test.ts +258 -0
- package/packages/sdk/vitest.config.ts +1 -1
- package/scripts/bh-full-e2e.mjs +167 -368
- package/scripts/check-deps.mjs +28 -46
- package/scripts/mirror-claude-md.sh +78 -0
- package/scripts/test-in-container.sh +31 -9
- package/templates/clean-state-checklist.md +3 -3
- package/templates/sprint-contract.md +2 -2
- package/bizar-dash/.bizar/activity.log +0 -3
- package/bizar-dash/.omx/logs/omx-2026-07-07.jsonl +0 -1
- package/bizar-dash/.omx/state/session.json +0 -10
- package/bizar-dash/bizar-design/EXPLANATION.md +0 -307
- package/bizar-dash/bizar-design/INSTRUCTIONS.md +0 -149
- package/bizar-dash/bizar-design/canvas.html +0 -281
- package/bizar-dash/bizar-design/canvas.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/components.css +0 -1665
- package/bizar-dash/bizar-design/components.html +0 -557
- package/bizar-dash/bizar-design/components.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/agents.html +0 -74
- package/bizar-dash/bizar-design/desktop/agents.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/memory.html +0 -75
- package/bizar-dash/bizar-design/desktop/memory.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/metrics.html +0 -63
- package/bizar-dash/bizar-design/desktop/metrics.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/overview.html +0 -95
- package/bizar-dash/bizar-design/desktop/overview.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/settings.html +0 -70
- package/bizar-dash/bizar-design/desktop/settings.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/icons.svg +0 -44
- package/bizar-dash/bizar-design/index.html +0 -192
- package/bizar-dash/bizar-design/index.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/agents.html +0 -29
- package/bizar-dash/bizar-design/mobile/agents.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/memory.html +0 -28
- package/bizar-dash/bizar-design/mobile/memory.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/metrics.html +0 -29
- package/bizar-dash/bizar-design/mobile/metrics.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/overview.html +0 -33
- package/bizar-dash/bizar-design/mobile/overview.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/settings.html +0 -28
- package/bizar-dash/bizar-design/mobile/settings.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/prototype.js +0 -114
- package/bizar-dash/bizar-design/tokens.css +0 -106
- package/bizar-dash/dist/assets/MobileChat-BnKN_Ks_.js +0 -1
- package/bizar-dash/dist/assets/MobileSettings-DjCPxC-Q.js +0 -1
- package/bizar-dash/dist/assets/icons-Do5N2jmX.js.map +0 -1
- package/bizar-dash/dist/assets/main-DYiZqMrn.js +0 -18
- package/bizar-dash/dist/assets/main-DYiZqMrn.js.map +0 -1
- package/bizar-dash/dist/assets/main-ietCEg_R.css +0 -1
- package/bizar-dash/dist/assets/markdown-C6mXtQxD.js +0 -1
- package/bizar-dash/dist/assets/mobile-CMHqtLV2.js +0 -1
- package/bizar-dash/dist/assets/mobile-layout-3jIhHX_p.js +0 -2
- package/bizar-dash/dist/assets/mobile-layout-3jIhHX_p.js.map +0 -1
- package/bizar-dash/dist/assets/react-vendor-Dn4wqh4Z.js +0 -40
- package/bizar-dash/dist/assets/react-vendor-Dn4wqh4Z.js.map +0 -1
- package/bizar-dash/dist/assets/useSlashCommands-DtITw8Xv.js +0 -2
- package/bizar-dash/dist/assets/useSlashCommands-DtITw8Xv.js.map +0 -1
- package/bizar-dash/dist/assets/vendor-CeHGtduv.js +0 -29
- package/bizar-dash/dist/assets/vendor-CeHGtduv.js.map +0 -1
- package/bizar-dash/node_modules/.package-lock.json +0 -6
- package/bizar-dash/package-lock.json +0 -6
- package/bizar-dash/src/server/cline-sdk.mjs +0 -132
- package/bizar-dash/src/server/routes/cline-session-detail.mjs +0 -559
- package/bizar-dash/src/server/routes/cline-sessions.mjs +0 -291
- package/cli/commands/cline-cmd.mjs +0 -289
- package/cli/commands/validate.test.mjs +0 -379
- package/cli/doctor.test.mjs +0 -350
- package/config/cline.json.template +0 -342
- package/packages/sdk/src/client.ts +0 -188
- package/packages/sdk/src/cline-events.ts +0 -134
- package/packages/sdk/src/cline-types.ts +0 -66
- package/packages/sdk/src/cline.ts +0 -339
- package/packages/sdk/src/errors.ts +0 -129
- package/packages/sdk/src/events.ts +0 -153
- package/packages/sdk/src/types.ts +0 -176
- package/packages/sdk/tests/client.test.ts +0 -217
- package/packages/sdk/tests/errors.test.ts +0 -108
- package/packages/sdk/tests/events.test.ts +0 -139
- package/packages/sdk/tests/fixtures/fetch-mock.ts +0 -152
- package/packages/sdk/tests/fixtures/sse-mock.ts +0 -30
- package/plugins/bizar/ARCHITECTURE.md +0 -142
- package/plugins/bizar/CONSTRAINTS.md +0 -67
- package/plugins/bizar/LICENSE +0 -21
- package/plugins/bizar/README.md +0 -448
- package/plugins/bizar/index.ts +0 -925
- package/plugins/bizar/package.json +0 -39
- package/plugins/bizar/scripts/check-forbidden-imports.sh +0 -33
- package/plugins/bizar/src/background-state.ts +0 -641
- package/plugins/bizar/src/background.ts +0 -1806
- package/plugins/bizar/src/cline-runner.ts +0 -203
- package/plugins/bizar/src/clineruntime.ts +0 -227
- package/plugins/bizar/src/commands-impl.ts +0 -151
- package/plugins/bizar/src/commands.ts +0 -1799
- package/plugins/bizar/src/compaction.d.mts +0 -48
- package/plugins/bizar/src/compaction.mjs +0 -192
- package/plugins/bizar/src/dashboard-client.ts +0 -233
- package/plugins/bizar/src/event-stream.ts +0 -606
- package/plugins/bizar/src/fingerprint.ts +0 -120
- package/plugins/bizar/src/handoff.ts +0 -79
- package/plugins/bizar/src/hooks/memory-flush-on-compact.ts +0 -123
- package/plugins/bizar/src/hooks/memory-inject.ts +0 -247
- package/plugins/bizar/src/hooks/memory-write-on-end.ts +0 -188
- package/plugins/bizar/src/hooks/skill-curator.ts +0 -180
- package/plugins/bizar/src/http-client.ts +0 -467
- package/plugins/bizar/src/key-rotation.ts +0 -218
- package/plugins/bizar/src/logger.ts +0 -144
- package/plugins/bizar/src/loop-engineering.ts +0 -241
- package/plugins/bizar/src/loop.ts +0 -176
- package/plugins/bizar/src/mistake-recovery.ts +0 -98
- package/plugins/bizar/src/odin.ts +0 -227
- package/plugins/bizar/src/options.ts +0 -470
- package/plugins/bizar/src/plan-fs.ts +0 -323
- package/plugins/bizar/src/reasoning-clean.ts +0 -454
- package/plugins/bizar/src/report.ts +0 -178
- package/plugins/bizar/src/research-prompt.ts +0 -35
- package/plugins/bizar/src/serve-info.ts +0 -228
- package/plugins/bizar/src/serve.ts +0 -496
- package/plugins/bizar/src/settings.ts +0 -349
- package/plugins/bizar/src/state.ts +0 -298
- package/plugins/bizar/src/tool-discipline.ts +0 -105
- package/plugins/bizar/src/tools/agent-browser.ts +0 -315
- package/plugins/bizar/src/tools/bg-collect.ts +0 -131
- package/plugins/bizar/src/tools/bg-get-comments.ts +0 -266
- package/plugins/bizar/src/tools/bg-kill.ts +0 -116
- package/plugins/bizar/src/tools/bg-pause.ts +0 -99
- package/plugins/bizar/src/tools/bg-report-progress.ts +0 -115
- package/plugins/bizar/src/tools/bg-resume.ts +0 -94
- package/plugins/bizar/src/tools/bg-send-message.ts +0 -223
- package/plugins/bizar/src/tools/bg-spawn.ts +0 -502
- package/plugins/bizar/src/tools/bg-status.ts +0 -130
- package/plugins/bizar/src/tools/graph-query.ts +0 -278
- package/plugins/bizar/src/tools/loop-engineering.ts +0 -193
- package/plugins/bizar/src/tools/memory-list.ts +0 -43
- package/plugins/bizar/src/tools/memory-read.ts +0 -69
- package/plugins/bizar/src/tools/memory-search.ts +0 -47
- package/plugins/bizar/src/tools/memory-write.ts +0 -54
- package/plugins/bizar/src/tools/open-kb.ts +0 -198
- package/plugins/bizar/src/tools/plan-action.ts +0 -785
- package/plugins/bizar/src/tools/read-glyph-feedback.ts +0 -191
- package/plugins/bizar/src/tools/sandbox.ts +0 -232
- package/plugins/bizar/src/tools/team-spawn.ts +0 -73
- package/plugins/bizar/src/tools/team-status.ts +0 -76
- package/plugins/bizar/src/tools/wait-for-feedback.ts +0 -415
- package/plugins/bizar/src/trajectory.ts +0 -104
- package/plugins/bizar/tests/README.md +0 -99
- package/plugins/bizar/tests/attach-handler-bug.test.ts +0 -169
- package/plugins/bizar/tests/background-state.test.ts +0 -277
- package/plugins/bizar/tests/background.test.ts +0 -402
- package/plugins/bizar/tests/block.test.ts +0 -195
- package/plugins/bizar/tests/canonical-key-order.test.ts +0 -75
- package/plugins/bizar/tests/clineruntime-config.test.ts +0 -283
- package/plugins/bizar/tests/commands-impl.test.ts +0 -316
- package/plugins/bizar/tests/commands.test.ts +0 -584
- package/plugins/bizar/tests/compaction.test.ts +0 -264
- package/plugins/bizar/tests/config.test.ts +0 -128
- package/plugins/bizar/tests/dashboard-client.test.ts +0 -159
- package/plugins/bizar/tests/dispose.test.ts +0 -336
- package/plugins/bizar/tests/event-stream.test.ts +0 -409
- package/plugins/bizar/tests/event.test.ts +0 -262
- package/plugins/bizar/tests/fingerprint.test.ts +0 -190
- package/plugins/bizar/tests/http-client.test.ts +0 -404
- package/plugins/bizar/tests/init-helpers.test.ts +0 -203
- package/plugins/bizar/tests/integration/slash-command.test.ts +0 -349
- package/plugins/bizar/tests/integration/tool-routing.test.ts +0 -98
- package/plugins/bizar/tests/key-rotation.test.ts +0 -396
- package/plugins/bizar/tests/loop-engineering.test.ts +0 -168
- package/plugins/bizar/tests/loop.test.ts +0 -397
- package/plugins/bizar/tests/memory-write-on-end.test.ts +0 -92
- package/plugins/bizar/tests/mistake-recovery.test.ts +0 -116
- package/plugins/bizar/tests/odin.test.ts +0 -125
- package/plugins/bizar/tests/options.test.ts +0 -329
- package/plugins/bizar/tests/reasoning-clean.test.ts +0 -422
- package/plugins/bizar/tests/safety.test.ts +0 -281
- package/plugins/bizar/tests/serve.test.ts +0 -339
- package/plugins/bizar/tests/settings.test.ts +0 -351
- package/plugins/bizar/tests/stall-think.test.ts +0 -750
- package/plugins/bizar/tests/state.test.ts +0 -276
- package/plugins/bizar/tests/tool-discipline.test.ts +0 -77
- package/plugins/bizar/tests/tools/agent-browser.test.ts +0 -98
- package/plugins/bizar/tests/tools/bg-collect.test.ts +0 -337
- package/plugins/bizar/tests/tools/bg-get-comments.test.ts +0 -485
- package/plugins/bizar/tests/tools/bg-kill.test.ts +0 -235
- package/plugins/bizar/tests/tools/bg-pause.test.ts +0 -61
- package/plugins/bizar/tests/tools/bg-report-progress.test.ts +0 -79
- package/plugins/bizar/tests/tools/bg-resume.test.ts +0 -40
- package/plugins/bizar/tests/tools/bg-send-message.test.ts +0 -116
- package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +0 -147
- package/plugins/bizar/tests/tools/bg-spawn-http.test.ts +0 -233
- package/plugins/bizar/tests/tools/bg-spawn.test.ts +0 -311
- package/plugins/bizar/tests/tools/bg-status.test.ts +0 -217
- package/plugins/bizar/tests/tools/cline-runner.test.ts +0 -115
- package/plugins/bizar/tests/tools/plan-action.test.ts +0 -599
- package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +0 -253
- package/plugins/bizar/tests/tools/sandbox.test.ts +0 -117
- package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +0 -390
- package/plugins/bizar/tests/update-deadlock.test.ts +0 -151
- package/plugins/bizar/tsconfig.json +0 -29
- package/scripts/mirror-agents-md.sh +0 -69
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/server/claude-sdk.mjs
|
|
3
|
+
*
|
|
4
|
+
* v6.3.0 — Dashboard-side wrapper around the Claude Code Agent SDK
|
|
5
|
+
* (`@anthropic-ai/claude-agent-sdk`).
|
|
6
|
+
*
|
|
7
|
+
* Replaces cline-sdk.mjs (the legacy wrapper around
|
|
8
|
+
* `@polderlabs/bizar-sdk/cline`). Claude Code's SDK is an in-process
|
|
9
|
+
* library: it exposes `query()` for one-shot prompts and
|
|
10
|
+
* `ClaudeSDKClient` for streaming sessions. There is no equivalent
|
|
11
|
+
* of cline's `serve` subprocess — Claude Code runs in-process by
|
|
12
|
+
* default.
|
|
13
|
+
*
|
|
14
|
+
* Public surface:
|
|
15
|
+
* - `getClaudeSdk()` — returns the SDK module or `null`
|
|
16
|
+
* if not installed (so callers can
|
|
17
|
+
* degrade gracefully).
|
|
18
|
+
* - `getClaudeSdkOrThrow()` — same, but throws when missing.
|
|
19
|
+
* - `subscribeToSession(id)` — wraps `ClaudeSDKClient.subscribe()`
|
|
20
|
+
* for streaming a session's events.
|
|
21
|
+
* - `pingClaudeSdk()` — quick health probe; uses a short
|
|
22
|
+
* `query()` against `--model haiku`
|
|
23
|
+
* to verify the SDK is reachable.
|
|
24
|
+
*
|
|
25
|
+
* Storage location for Claude Code sessions:
|
|
26
|
+
* - Sessions live at `~/.claude/sessions/<sessionId>/` with the
|
|
27
|
+
* conversation as `messages.jsonl`. This module does not own
|
|
28
|
+
* that directory — Claude Code writes it directly. We read it
|
|
29
|
+
* when callers ask for `listClaudeSessions` / `listClaudeMessages`.
|
|
30
|
+
*
|
|
31
|
+
* Environment:
|
|
32
|
+
* - Claude Code reads API keys from the environment
|
|
33
|
+
* (`ANTHROPIC_API_KEY` or the OAuth flow). We do NOT need to
|
|
34
|
+
* build an `Authorization: Basic base64("cline:<password>")`
|
|
35
|
+
* header — Claude Code handles authentication itself.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import { homedir } from 'node:os';
|
|
39
|
+
import { join } from 'node:path';
|
|
40
|
+
import { existsSync } from 'node:fs';
|
|
41
|
+
|
|
42
|
+
let _sdk = null;
|
|
43
|
+
/** @type {Promise<any> | null} */
|
|
44
|
+
let _sdkPromise = null;
|
|
45
|
+
|
|
46
|
+
const HOME = homedir();
|
|
47
|
+
const CLAUDE_SESSIONS_DIR = join(HOME, '.claude', 'sessions');
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Lazily import the Claude Code Agent SDK. Returns the module on
|
|
51
|
+
* success and `null` if the package is not installed (so callers can
|
|
52
|
+
* fall back to subprocess execution via claude-runner.mjs).
|
|
53
|
+
*
|
|
54
|
+
* The result is cached so subsequent calls are synchronous.
|
|
55
|
+
*
|
|
56
|
+
* @returns {Promise<any | null>}
|
|
57
|
+
*/
|
|
58
|
+
export async function getClaudeSdk() {
|
|
59
|
+
if (_sdk) return _sdk;
|
|
60
|
+
if (_sdkPromise) return _sdkPromise;
|
|
61
|
+
_sdkPromise = (async () => {
|
|
62
|
+
try {
|
|
63
|
+
const mod = await import('@anthropic-ai/claude-agent-sdk');
|
|
64
|
+
_sdk = mod;
|
|
65
|
+
return mod;
|
|
66
|
+
} catch {
|
|
67
|
+
// SDK package not installed — caller should use the
|
|
68
|
+
// subprocess fallback in claude-runner.mjs.
|
|
69
|
+
_sdk = null;
|
|
70
|
+
return null;
|
|
71
|
+
} finally {
|
|
72
|
+
_sdkPromise = null;
|
|
73
|
+
}
|
|
74
|
+
})();
|
|
75
|
+
return _sdkPromise;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Same as {@link getClaudeSdk} but throws when the SDK isn't
|
|
80
|
+
* available. Use this from code paths that REQUIRE the in-process
|
|
81
|
+
* SDK (e.g. callers that want typed event streams rather than the
|
|
82
|
+
* JSONL subprocess path).
|
|
83
|
+
*
|
|
84
|
+
* @returns {Promise<any>}
|
|
85
|
+
*/
|
|
86
|
+
export async function getClaudeSdkOrThrow() {
|
|
87
|
+
const sdk = await getClaudeSdk();
|
|
88
|
+
if (!sdk) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
'claude_sdk_unavailable: @anthropic-ai/claude-agent-sdk is not installed. ' +
|
|
91
|
+
'Run `npm install @anthropic-ai/claude-agent-sdk` at the repo root, ' +
|
|
92
|
+
'or use the subprocess path (claude-runner.mjs).',
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
return sdk;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Subscribe to a Claude Code session's event stream. Thin wrapper
|
|
100
|
+
* around `ClaudeSDKClient.subscribe({ sessionId })`.
|
|
101
|
+
*
|
|
102
|
+
* Returns `{ stream, close }` — `stream` is an `AsyncIterable` of
|
|
103
|
+
* typed event envelopes; `close()` aborts the underlying subscription.
|
|
104
|
+
*
|
|
105
|
+
* Returns `null` when the SDK is unavailable or the session id is
|
|
106
|
+
* missing — callers should fall back to the JSONL tailing path in
|
|
107
|
+
* `claude-sessions.mjs`.
|
|
108
|
+
*
|
|
109
|
+
* @param {string} sessionId
|
|
110
|
+
* @returns {Promise<AsyncIterable<unknown> & { close: () => void } | null>}
|
|
111
|
+
*/
|
|
112
|
+
export async function subscribeToSession(sessionId) {
|
|
113
|
+
if (!sessionId) return null;
|
|
114
|
+
const sdk = await getClaudeSdk();
|
|
115
|
+
if (!sdk || typeof sdk.subscribe !== 'function') return null;
|
|
116
|
+
try {
|
|
117
|
+
const sub = await sdk.subscribe({ sessionId });
|
|
118
|
+
return sub;
|
|
119
|
+
} catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Quick liveness probe for the Claude Code SDK. Performs a tiny
|
|
126
|
+
* `query()` call against `haiku` and waits up to 1.5s for the
|
|
127
|
+
* response. Returns `true` on any successful response, `false`
|
|
128
|
+
* otherwise.
|
|
129
|
+
*
|
|
130
|
+
* Used by the dashboard's /api/health endpoint and by callers that
|
|
131
|
+
* want to decide between the in-process SDK and the subprocess
|
|
132
|
+
* fallback.
|
|
133
|
+
*
|
|
134
|
+
* @returns {Promise<boolean>}
|
|
135
|
+
*/
|
|
136
|
+
export async function pingClaudeSdk() {
|
|
137
|
+
const sdk = await getClaudeSdk();
|
|
138
|
+
if (!sdk || typeof sdk.query !== 'function') return false;
|
|
139
|
+
try {
|
|
140
|
+
const ac = new AbortController();
|
|
141
|
+
const timer = setTimeout(() => ac.abort(), 1500);
|
|
142
|
+
try {
|
|
143
|
+
const stream = sdk.query({
|
|
144
|
+
prompt: 'ping',
|
|
145
|
+
options: { model: 'haiku', maxTurns: 1, permissionMode: 'plan' },
|
|
146
|
+
});
|
|
147
|
+
// Drain the first event or the abort signal — either proves
|
|
148
|
+
// the SDK is reachable.
|
|
149
|
+
const result = await Promise.race([
|
|
150
|
+
stream[Symbol.asyncIterator]().next().then(() => true),
|
|
151
|
+
new Promise((resolve) => {
|
|
152
|
+
ac.signal.addEventListener('abort', () => resolve(false));
|
|
153
|
+
}),
|
|
154
|
+
]);
|
|
155
|
+
// Best-effort close of the stream.
|
|
156
|
+
try { await stream.close?.(); } catch { /* ignore */ }
|
|
157
|
+
return Boolean(result);
|
|
158
|
+
} finally {
|
|
159
|
+
clearTimeout(timer);
|
|
160
|
+
ac.abort();
|
|
161
|
+
}
|
|
162
|
+
} catch {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Return the canonical on-disk directory for Claude Code sessions.
|
|
169
|
+
* Useful for callers that need to enumerate `messages.jsonl` files
|
|
170
|
+
* directly (e.g. listing historical messages for a session).
|
|
171
|
+
*
|
|
172
|
+
* @returns {string}
|
|
173
|
+
*/
|
|
174
|
+
export function claudeSessionsDir() {
|
|
175
|
+
return CLAUDE_SESSIONS_DIR;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Best-effort check that the Claude Code session directory exists
|
|
180
|
+
* (or its parent does). Lets callers fall back to "no sessions yet"
|
|
181
|
+
* rather than throwing when the user has never run `claude`.
|
|
182
|
+
*
|
|
183
|
+
* @returns {boolean}
|
|
184
|
+
*/
|
|
185
|
+
export function claudeSessionsDirExists() {
|
|
186
|
+
try {
|
|
187
|
+
return existsSync(CLAUDE_SESSIONS_DIR) || existsSync(join(HOME, '.claude'));
|
|
188
|
+
} catch {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* memory-consolidator.mjs — thin wrapper around `memory-distillation.mjs`.
|
|
3
|
+
*
|
|
4
|
+
* v6.4.0 — ported from ruflo ADR-174. The consolidator reads from the
|
|
5
|
+
* dashboard's `memory-store.mjs`, runs the RETRIEVE → JUDGE → DISTILL
|
|
6
|
+
* → CONSOLIDATE pipeline, and writes promoted patterns back to the
|
|
7
|
+
* vault as new entries of `kind: 'pattern'`.
|
|
8
|
+
*
|
|
9
|
+
* Idempotency: a second run with the same input produces the same
|
|
10
|
+
* patterns. The write-back is deduped by `pattern.id` (file stem
|
|
11
|
+
* `pat_<hash>.md`); already-existing pattern files are skipped, not
|
|
12
|
+
* overwritten. This honours the ADR-174 invariant:
|
|
13
|
+
* "memory_entries source preservation — row count + content
|
|
14
|
+
* unchanged after a run; promoted patterns are additive"
|
|
15
|
+
*
|
|
16
|
+
* Public surface:
|
|
17
|
+
* - runConsolidation({ projectRoot, since }) → { distilled, promoted, byTier, written }
|
|
18
|
+
* - runConsolidationInMemory(entries) → same shape minus `written`
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
22
|
+
import { dirname, join } from "node:path";
|
|
23
|
+
|
|
24
|
+
import { listNotes, writeNote } from "./memory-store.mjs";
|
|
25
|
+
import { resolveVaultRoot } from "../../../packages/sdk/src/memory/index.js";
|
|
26
|
+
import { runDistillation } from "./memory-distillation.mjs";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Where the dashboard-side machine-readable distill log is written.
|
|
30
|
+
* `.bizar/distilled-patterns.json` lives at the repo root so that the
|
|
31
|
+
* dashboard UI, the Odin prompt primer, and the verification scripts
|
|
32
|
+
* can all reach it without dipping into the vault. Format is
|
|
33
|
+
* ADR-174-compliant:
|
|
34
|
+
*
|
|
35
|
+
* {
|
|
36
|
+
* "version": 1,
|
|
37
|
+
* "generatedAt": "<iso8601>",
|
|
38
|
+
* "byTier": { "oracle:test-exec": N, "proxy:structural": N, "judge:fable": N },
|
|
39
|
+
* "patterns": [
|
|
40
|
+
* { "id", "kind", "summary", "uses": [...], "evidence": [...],
|
|
41
|
+
* "provenance_tier", "promoted", "score", "forgettingRate" },
|
|
42
|
+
* ...
|
|
43
|
+
* ]
|
|
44
|
+
* }
|
|
45
|
+
*/
|
|
46
|
+
export const DISTILLED_PATTERNS_FILE = ".bizar/distilled-patterns.json";
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* In-memory variant — pure function over the entries you pass in.
|
|
50
|
+
* Exposed for unit tests and the `memory_distill` MCP tool.
|
|
51
|
+
*
|
|
52
|
+
* @param {Array<Record<string, unknown>>} entries
|
|
53
|
+
*/
|
|
54
|
+
export function runConsolidationInMemory(entries) {
|
|
55
|
+
const result = runDistillation(entries);
|
|
56
|
+
return {
|
|
57
|
+
distilled: result.patterns.length,
|
|
58
|
+
promoted: result.promoted.map((p) => p.id),
|
|
59
|
+
patterns: result.patterns,
|
|
60
|
+
byTier: result.byTier,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Vault-backed variant — reads notes from the dashboard vault, runs
|
|
66
|
+
* the pipeline, and writes promoted patterns back.
|
|
67
|
+
*
|
|
68
|
+
* @param {{ projectRoot?: string, since?: string }} [opts]
|
|
69
|
+
*/
|
|
70
|
+
export function runConsolidation(opts = {}) {
|
|
71
|
+
const projectRoot = opts.projectRoot ?? process.cwd();
|
|
72
|
+
const since = opts.since ? new Date(opts.since) : null;
|
|
73
|
+
|
|
74
|
+
// Read every note. `listNotes` is gitignore-aware and skips .obsidian/.
|
|
75
|
+
const notes = listNotes(projectRoot, { limit: 10000 });
|
|
76
|
+
|
|
77
|
+
// Adapter: dashboard's `listNotes` returns the SDK `MemoryNote`
|
|
78
|
+
// shape; the distiller wants the Bizar memory schema. We bridge by
|
|
79
|
+
// aliasing frontmatter fields the distiller reads.
|
|
80
|
+
const entries = notes
|
|
81
|
+
.filter((n) => !since || since <= parseCreatedAt(n))
|
|
82
|
+
.map((n) => ({
|
|
83
|
+
memory_id: n.relPath,
|
|
84
|
+
path: n.relPath,
|
|
85
|
+
relPath: n.relPath,
|
|
86
|
+
frontmatter: n.frontmatter ?? {},
|
|
87
|
+
body: n.body ?? "",
|
|
88
|
+
kind: n.frontmatter?.kind ?? n.frontmatter?.type,
|
|
89
|
+
created: n.frontmatter?.createdAt ?? n.frontmatter?.created,
|
|
90
|
+
createdAt: n.frontmatter?.createdAt,
|
|
91
|
+
updatedAt: n.frontmatter?.updatedAt,
|
|
92
|
+
tags: n.frontmatter?.tags,
|
|
93
|
+
}));
|
|
94
|
+
|
|
95
|
+
const result = runDistillation(entries);
|
|
96
|
+
|
|
97
|
+
// Write promoted patterns back. Idempotent: skip if already exists
|
|
98
|
+
// (a prior run produced the same pattern file).
|
|
99
|
+
const written = [];
|
|
100
|
+
for (const p of result.promoted) {
|
|
101
|
+
const fm = {
|
|
102
|
+
kind: "pattern",
|
|
103
|
+
promoted: true,
|
|
104
|
+
provenance_tier: p.provenance_tier,
|
|
105
|
+
uses: p.uses.length,
|
|
106
|
+
score: p.score,
|
|
107
|
+
createdAt: new Date().toISOString(),
|
|
108
|
+
tags: ["pattern", "distilled"],
|
|
109
|
+
};
|
|
110
|
+
const body = [
|
|
111
|
+
`# ${p.summary}`,
|
|
112
|
+
"",
|
|
113
|
+
`_provenance_tier: ${p.provenance_tier}_`,
|
|
114
|
+
`_promoted: yes_`,
|
|
115
|
+
`_uses: ${p.uses.length}_`,
|
|
116
|
+
"",
|
|
117
|
+
"## Evidence",
|
|
118
|
+
"",
|
|
119
|
+
...p.evidence,
|
|
120
|
+
].join("\n");
|
|
121
|
+
|
|
122
|
+
const relPath = `patterns/${p.id}.md`;
|
|
123
|
+
// If the file already exists, leave it alone (idempotent).
|
|
124
|
+
const existing = notes.find((n) => n.relPath === relPath);
|
|
125
|
+
if (existing) continue;
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
const out = writeNote(projectRoot, relPath, { frontmatter: fm, body });
|
|
129
|
+
written.push(out.relPath);
|
|
130
|
+
} catch {
|
|
131
|
+
// Best-effort writes — a vault with read-only test vault
|
|
132
|
+
// shouldn't crash the distillation.
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
distilled: result.patterns.length,
|
|
138
|
+
promoted: result.promoted.map((p) => p.id),
|
|
139
|
+
patterns: result.patterns,
|
|
140
|
+
byTier: result.byTier,
|
|
141
|
+
written,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Write the on-disk distill log (`.bizar/distilled-patterns.json`).
|
|
147
|
+
* Idempotent and best-effort — does NOT throw. Returns the absolute
|
|
148
|
+
* (or relative-to-projectRoot) path of the file written, or `null`
|
|
149
|
+
* if the write was skipped (e.g. directory not writable).
|
|
150
|
+
*
|
|
151
|
+
* Decorates each pattern with:
|
|
152
|
+
* - `forgettingRate`: 0.0–1.0 (smaller = more durable). Computed
|
|
153
|
+
* as `1 / (1 + uses.length)` per ADR-174 §"CONSOLIDATE".
|
|
154
|
+
* - `promoted`: copied from the distiller.
|
|
155
|
+
* - `provenance_tier`: copied verbatim.
|
|
156
|
+
*
|
|
157
|
+
* @param {ReturnType<typeof runConsolidation>} consolidation
|
|
158
|
+
* @param {{ projectRoot?: string, filePath?: string }} [opts]
|
|
159
|
+
* @returns {string | null}
|
|
160
|
+
*/
|
|
161
|
+
export function writeDistilledPatternsFile(consolidation, opts = {}) {
|
|
162
|
+
const projectRoot = opts.projectRoot ?? process.cwd();
|
|
163
|
+
const fp = opts.filePath
|
|
164
|
+
? (opts.filePath.startsWith("/") ? opts.filePath : join(projectRoot, opts.filePath))
|
|
165
|
+
: join(projectRoot, DISTILLED_PATTERNS_FILE);
|
|
166
|
+
|
|
167
|
+
const payload = {
|
|
168
|
+
version: 1,
|
|
169
|
+
generatedAt: new Date().toISOString(),
|
|
170
|
+
byTier: consolidation.byTier ?? {
|
|
171
|
+
"oracle:test-exec": 0,
|
|
172
|
+
"proxy:structural": 0,
|
|
173
|
+
"judge:fable": 0,
|
|
174
|
+
},
|
|
175
|
+
distilled: consolidation.distilled ?? 0,
|
|
176
|
+
promoted: consolidation.promoted ?? [],
|
|
177
|
+
patterns: (consolidation.patterns ?? []).map((p) => ({
|
|
178
|
+
id: p.id,
|
|
179
|
+
kind: p.kind ?? "pattern",
|
|
180
|
+
summary: p.summary ?? "",
|
|
181
|
+
uses: p.uses ?? [],
|
|
182
|
+
evidence: p.evidence ?? [],
|
|
183
|
+
provenance_tier: p.provenance_tier ?? "proxy:structural",
|
|
184
|
+
promoted: Boolean(p.promoted),
|
|
185
|
+
score: typeof p.score === "number" ? p.score : 0.5,
|
|
186
|
+
forgettingRate: forgettingRate(p.uses ?? []),
|
|
187
|
+
})),
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
mkdirSync(dirname(fp), { recursive: true });
|
|
192
|
+
writeFileSync(fp, JSON.stringify(payload, null, 2), "utf-8");
|
|
193
|
+
return fp;
|
|
194
|
+
} catch {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Forgetfulness score (ADR-174 §"forgetting curve"). Patterns with
|
|
201
|
+
* more `uses` are more durable; a brand-new pattern is 1.0 (fully
|
|
202
|
+
* forgettable); a pattern with 4 uses settles at 0.2.
|
|
203
|
+
*/
|
|
204
|
+
function forgettingRate(uses) {
|
|
205
|
+
const n = Array.isArray(uses) ? uses.length : 0;
|
|
206
|
+
return 1 / (1 + n);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function parseCreatedAt(note) {
|
|
210
|
+
const t = note?.frontmatter?.createdAt ?? note?.frontmatter?.created;
|
|
211
|
+
if (!t) return new Date(0);
|
|
212
|
+
const d = new Date(t);
|
|
213
|
+
return Number.isNaN(d.getTime()) ? new Date(0) : d;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** Re-export so the dashboard server can `import { resolveVaultRoot }
|
|
217
|
+
* from './memory-consolidator.mjs'` when wiring the MCP tool. */
|
|
218
|
+
export { resolveVaultRoot };
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* memory-distillation.mjs — RETRIEVE → JUDGE → DISTILL → CONSOLIDATE
|
|
3
|
+
* (ADR-174) applied to an in-memory array of Bizar memory entries.
|
|
4
|
+
*
|
|
5
|
+
* v6.4.0 — ported from ruflo `@claude-flow/neural/src/reasoning-bank.ts`
|
|
6
|
+
* (the 4-step pipeline) + ADR-174 (provenance-tiered promote gate).
|
|
7
|
+
*
|
|
8
|
+
* This is the deterministic, $0 default path. It does NOT call any
|
|
9
|
+
* LLM. Provenance is inferred from the entry's frontmatter: entries
|
|
10
|
+
* flagged with `kind: feedback` or executing a test result become
|
|
11
|
+
* `oracle:test-exec`; everything else becomes `proxy:structural`.
|
|
12
|
+
* (`judge:fable` is reserved for the cost-bounded LLM-judge path
|
|
13
|
+
* enabled by `BIZAR_DISTILL_BUDGET_USD > 0` — out of scope here.)
|
|
14
|
+
*
|
|
15
|
+
* Returned `Pattern` objects carry a `provenance_tier` and a
|
|
16
|
+
* `promoted` flag. Only `oracle:test-exec` (and `judge:fable`)
|
|
17
|
+
* patterns can be promoted; `proxy:structural` patterns stay
|
|
18
|
+
* searchable but never earn the `promoted` boolean.
|
|
19
|
+
*
|
|
20
|
+
* Pure function — no I/O. Idempotent: same input → same output.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** Allowed provenance_tier values per ADR-174. */
|
|
24
|
+
export const PROVENANCE_TIERS = /** @type {const} */ ([
|
|
25
|
+
"oracle:test-exec",
|
|
26
|
+
"proxy:structural",
|
|
27
|
+
"judge:fable",
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
/** Default complexity bucket thresholds (length-based, retrofitted with
|
|
31
|
+
* a code-block bonus). Matches ADR-174 §"RETRIEVE" cost = $0 default. */
|
|
32
|
+
const COMPLEXITY_BOUNDS = {
|
|
33
|
+
/** longest body length considered "simple". */
|
|
34
|
+
simpleMax: 600,
|
|
35
|
+
/** longest body length considered "moderate". */
|
|
36
|
+
moderateMax: 2400,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @typedef {Object} MemoryEntry
|
|
41
|
+
* @property {string} [memory_id]
|
|
42
|
+
* @property {string} [id]
|
|
43
|
+
* @property {string} [path]
|
|
44
|
+
* @property {string} [relPath]
|
|
45
|
+
* @property {Record<string, unknown>} [frontmatter]
|
|
46
|
+
* @property {string} [body]
|
|
47
|
+
* @property {string} [kind] — One of: coding_convention | bug_pattern | task_summary | session_summary | feedback | …
|
|
48
|
+
* @property {string} [type]
|
|
49
|
+
* @property {string} [created]
|
|
50
|
+
* @property {string} [createdAt]
|
|
51
|
+
* @property {string} [updatedAt]
|
|
52
|
+
* @property {string[]} [tags]
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @typedef {Object} Pattern
|
|
57
|
+
* @property {string} id — "pat_<hash>"
|
|
58
|
+
* @property {string} kind — "pattern"
|
|
59
|
+
* @property {string} summary — short headline
|
|
60
|
+
* @property {string[]} uses — entry ids that contributed
|
|
61
|
+
* @property {string[]} evidence — excerpt lines cited as evidence
|
|
62
|
+
* @property {"oracle:test-exec"|"proxy:structural"|"judge:fable"} provenance_tier
|
|
63
|
+
* @property {boolean} promoted — promote gate
|
|
64
|
+
* @property {number} score — heuristic quality
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* RETRIEVE → tag each entry with a complexity bucket.
|
|
69
|
+
* Simple: short body, no code block, no test_exec tag.
|
|
70
|
+
* Complex: long body OR has a code block.
|
|
71
|
+
* @param {MemoryEntry} entry
|
|
72
|
+
*/
|
|
73
|
+
export function retrieve(entry) {
|
|
74
|
+
const body = String(entry?.body ?? "");
|
|
75
|
+
const fm = entry?.frontmatter ?? {};
|
|
76
|
+
const hasCodeBlock = /```/.test(body);
|
|
77
|
+
const testExec =
|
|
78
|
+
Boolean(fm.test_exec) ||
|
|
79
|
+
Boolean(fm.testExec) ||
|
|
80
|
+
(Array.isArray(fm.tags) && fm.tags.some((t) => String(t).includes("test-exec"))) ||
|
|
81
|
+
(typeof fm.kind === "string" && fm.kind === "feedback");
|
|
82
|
+
const len = body.length;
|
|
83
|
+
let complexity;
|
|
84
|
+
if (hasCodeBlock || len > COMPLEXITY_BOUNDS.moderateMax) complexity = "complex";
|
|
85
|
+
else if (len > COMPLEXITY_BOUNDS.simpleMax) complexity = "moderate";
|
|
86
|
+
else complexity = "simple";
|
|
87
|
+
return { complexity, testExec, hasCodeBlock, length: len };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* JUDGE → assign provenance_tier based on complexity + tags.
|
|
92
|
+
* Oracle tier requires `testExec === true` (execution-observed).
|
|
93
|
+
* @param {MemoryEntry} entry
|
|
94
|
+
* @param {{ complexity: string, testExec: boolean, hasCodeBlock: boolean, length: number }} retrieval
|
|
95
|
+
*/
|
|
96
|
+
export function judge(entry, retrieval) {
|
|
97
|
+
if (retrieval.testExec) return "oracle:test-exec";
|
|
98
|
+
// `judge:fable` reserved for the cost-bounded LLM path — not set
|
|
99
|
+
// here. Empty / null bodies (e.g. test stubs) get the proxy
|
|
100
|
+
// structural tier; that's correct — no execution observation, no
|
|
101
|
+
// Fable budget spend, so proxy is honest.
|
|
102
|
+
void entry;
|
|
103
|
+
return "proxy:structural";
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* DISTILL → produce a Pattern candidate from a memory entry, if the
|
|
108
|
+
* entry is the kind we surface as a "pattern". Coding conventions and
|
|
109
|
+
* bug patterns are surfaced directly (one each); task/session
|
|
110
|
+
* summaries produce a meta-pattern only if their bodies contain
|
|
111
|
+
* structural keys (`use`, `avoid`, `pattern:`).
|
|
112
|
+
* @param {MemoryEntry} entry
|
|
113
|
+
*/
|
|
114
|
+
export function distill(entry) {
|
|
115
|
+
const fm = entry?.frontmatter ?? {};
|
|
116
|
+
const body = String(entry?.body ?? "").trim();
|
|
117
|
+
const id = String(entry?.memory_id ?? entry?.id ?? entry?.path ?? entry?.relPath ?? "");
|
|
118
|
+
|
|
119
|
+
// Surface coding convention / bug pattern entries as 1:1 patterns.
|
|
120
|
+
const kindRaw = (fm.kind ?? entry?.kind ?? entry?.type ?? "").toString().toLowerCase();
|
|
121
|
+
if (kindRaw === "coding_convention" || kindRaw === "bug_pattern") {
|
|
122
|
+
return {
|
|
123
|
+
id: `pat_${shorten(id || body.slice(0, 24))}`,
|
|
124
|
+
kind: "pattern",
|
|
125
|
+
summary: firstLine(body) || "(empty)",
|
|
126
|
+
uses: id ? [id] : [],
|
|
127
|
+
evidence: [snippet(body)],
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// task_summary / session_summary → look for an embedded pattern
|
|
132
|
+
// tag in the body ("use", "avoid", "pattern:").
|
|
133
|
+
const head = firstLine(body).toLowerCase();
|
|
134
|
+
if (
|
|
135
|
+
kindRaw === "task_summary" ||
|
|
136
|
+
kindRaw === "session_summary" ||
|
|
137
|
+
/\bpattern\s*:/.test(head) ||
|
|
138
|
+
/^\s*(use|avoid|do|don't)\s*:/.test(head)
|
|
139
|
+
) {
|
|
140
|
+
return {
|
|
141
|
+
id: `pat_${shorten(id || head.replace(/\W+/g, " ").slice(0, 24))}`,
|
|
142
|
+
kind: "pattern",
|
|
143
|
+
summary: firstLine(body) || "(empty)",
|
|
144
|
+
uses: id ? [id] : [],
|
|
145
|
+
evidence: [snippet(body)],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* CONSOLIDATE — given candidate `Pattern` objects, dedupe by
|
|
154
|
+
* substring overlap, count `uses`, set `provenance_tier` (max tier
|
|
155
|
+
* across the cluster) and `promoted` (only if any contributing entry
|
|
156
|
+
* is oracle or judge).
|
|
157
|
+
* @param {Array<Pattern & { _tier: string }>} candidates
|
|
158
|
+
* @returns {{ patterns: Pattern[], promoted: Pattern[], byTier: Record<string, number> }}
|
|
159
|
+
*/
|
|
160
|
+
export function consolidate(candidates) {
|
|
161
|
+
// Group near-duplicates by Jaccard-like word-set similarity.
|
|
162
|
+
const groups = [];
|
|
163
|
+
for (const c of candidates) {
|
|
164
|
+
const ws = wordSet(c.summary + " " + c.evidence.join(" "));
|
|
165
|
+
let placed = false;
|
|
166
|
+
for (const g of groups) {
|
|
167
|
+
const gs = wordSet(g.rep.summary + " " + g.rep.evidence.join(" "));
|
|
168
|
+
const sim = jaccard(ws, gs);
|
|
169
|
+
if (sim >= 0.5) {
|
|
170
|
+
g.members.push(c);
|
|
171
|
+
placed = true;
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (!placed) groups.push({ rep: c, members: [c] });
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const patterns = [];
|
|
179
|
+
const byTier = { "oracle:test-exec": 0, "proxy:structural": 0, "judge:fable": 0 };
|
|
180
|
+
for (const g of groups) {
|
|
181
|
+
const allUses = new Set();
|
|
182
|
+
const evidence = [];
|
|
183
|
+
for (const m of g.members) {
|
|
184
|
+
for (const u of m.uses ?? []) allUses.add(u);
|
|
185
|
+
for (const e of m.evidence ?? []) evidence.push(e);
|
|
186
|
+
}
|
|
187
|
+
// Promote-tier max: oracle > judge > proxy.
|
|
188
|
+
const tiers = g.members.map((m) => m._tier);
|
|
189
|
+
let tier = "proxy:structural";
|
|
190
|
+
if (tiers.includes("oracle:test-exec")) tier = "oracle:test-exec";
|
|
191
|
+
else if (tiers.includes("judge:fable")) tier = "judge:fable";
|
|
192
|
+
|
|
193
|
+
const promoted = usesAllows(allUses.size) && (tier === "oracle:test-exec" || tier === "judge:fable");
|
|
194
|
+
const score = 0.5 + (allUses.size * 0.1);
|
|
195
|
+
const pattern = {
|
|
196
|
+
id: g.rep.id,
|
|
197
|
+
kind: "pattern",
|
|
198
|
+
summary: g.rep.summary,
|
|
199
|
+
uses: Array.from(allUses),
|
|
200
|
+
evidence: dedupe(evidence).slice(0, 5),
|
|
201
|
+
provenance_tier: tier,
|
|
202
|
+
promoted,
|
|
203
|
+
score,
|
|
204
|
+
};
|
|
205
|
+
patterns.push(pattern);
|
|
206
|
+
byTier[tier] += 1;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const promoted = patterns.filter((p) => p.promoted);
|
|
210
|
+
return { patterns, promoted, byTier };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Public entry point. Takes an array of memory entries, applies the
|
|
215
|
+
* 4 stages and returns the consolidated pattern set + tier counts.
|
|
216
|
+
* @param {MemoryEntry[]} entries
|
|
217
|
+
*/
|
|
218
|
+
export function runDistillation(entries) {
|
|
219
|
+
if (!Array.isArray(entries) || entries.length === 0) {
|
|
220
|
+
return {
|
|
221
|
+
patterns: [],
|
|
222
|
+
promoted: [],
|
|
223
|
+
byTier: { "oracle:test-exec": 0, "proxy:structural": 0, "judge:fable": 0 },
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const candidates = [];
|
|
228
|
+
for (const entry of entries) {
|
|
229
|
+
const retrieval = retrieve(entry);
|
|
230
|
+
const tier = judge(entry, retrieval);
|
|
231
|
+
const pattern = distill(entry);
|
|
232
|
+
if (!pattern) continue;
|
|
233
|
+
candidates.push({ ...pattern, _tier: tier });
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return consolidate(candidates);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// -----------------------------------------------------------------
|
|
240
|
+
// Tiny helpers (private).
|
|
241
|
+
// -----------------------------------------------------------------
|
|
242
|
+
|
|
243
|
+
function firstLine(s) {
|
|
244
|
+
if (!s) return "";
|
|
245
|
+
const i = s.indexOf("\n");
|
|
246
|
+
return (i < 0 ? s : s.slice(0, i)).trim();
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function snippet(body) {
|
|
250
|
+
const cleaned = body.replace(/\s+/g, " ").trim();
|
|
251
|
+
return cleaned.length <= 200 ? cleaned : cleaned.slice(0, 200) + "…";
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function shorten(s) {
|
|
255
|
+
// Stable, short id-hash from arbitrary text.
|
|
256
|
+
let h = 5381 >>> 0;
|
|
257
|
+
for (let i = 0; i < s.length; i++) {
|
|
258
|
+
h = ((h << 5) + h + s.charCodeAt(i)) >>> 0;
|
|
259
|
+
}
|
|
260
|
+
return h.toString(36).slice(0, 10);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function wordSet(s) {
|
|
264
|
+
return new Set(
|
|
265
|
+
String(s)
|
|
266
|
+
.toLowerCase()
|
|
267
|
+
.replace(/[^a-z0-9\s]+/g, " ")
|
|
268
|
+
.split(/\s+/)
|
|
269
|
+
.filter((w) => w.length > 2),
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function jaccard(a, b) {
|
|
274
|
+
if (a.size === 0 && b.size === 0) return 0;
|
|
275
|
+
let inter = 0;
|
|
276
|
+
for (const x of a) if (b.has(x)) inter += 1;
|
|
277
|
+
const union = a.size + b.size - inter;
|
|
278
|
+
return union === 0 ? 0 : inter / union;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function usesAllows(n) {
|
|
282
|
+
// ADR-174 promote gate default: requires N≥1 contributing entry.
|
|
283
|
+
// We tighten to N≥3 in consolidate-callers if they want the
|
|
284
|
+
// 'agenticow substrate' default (ADR-170). Here we keep the
|
|
285
|
+
// public function permissive; callers can filter.
|
|
286
|
+
return n >= 1;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function dedupe(arr) {
|
|
290
|
+
const seen = new Set();
|
|
291
|
+
const out = [];
|
|
292
|
+
for (const x of arr) {
|
|
293
|
+
if (!seen.has(x)) { seen.add(x); out.push(x); }
|
|
294
|
+
}
|
|
295
|
+
return out;
|
|
296
|
+
}
|