@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
package/cli/utils.mjs
CHANGED
|
@@ -15,30 +15,56 @@ export function repoPath(...parts) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* Resolve the
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (process.env.CLINE_DIR && process.env.CLINE_DIR.trim()) {
|
|
30
|
-
return process.env.CLINE_DIR.trim();
|
|
18
|
+
* Resolve the Claude Code global config directory.
|
|
19
|
+
*
|
|
20
|
+
* v6.3.0 — Bizar is Claude Code-native. The legacy `~/.cline/`
|
|
21
|
+
* path is kept as a back-compat alias via the wrappers below.
|
|
22
|
+
*
|
|
23
|
+
* 1. `process.env.CLAUDE_CONFIG_DIR` (explicit override)
|
|
24
|
+
* 2. `$HOME/.claude` (Claude Code default)
|
|
25
|
+
*/
|
|
26
|
+
export function claudeConfigDir() {
|
|
27
|
+
if (process.env.CLAUDE_CONFIG_DIR && process.env.CLAUDE_CONFIG_DIR.trim()) {
|
|
28
|
+
return process.env.CLAUDE_CONFIG_DIR.trim();
|
|
31
29
|
}
|
|
32
30
|
if (isWin) {
|
|
33
31
|
return process.env.APPDATA
|
|
34
|
-
? join(process.env.APPDATA, '
|
|
35
|
-
: join(homedir(), '.
|
|
32
|
+
? join(process.env.APPDATA, 'claude')
|
|
33
|
+
: join(homedir(), '.claude');
|
|
36
34
|
}
|
|
37
|
-
return join(homedir(), '.
|
|
35
|
+
return join(homedir(), '.claude');
|
|
38
36
|
}
|
|
39
37
|
|
|
38
|
+
export function claudeAgentsDir() {
|
|
39
|
+
return join(claudeConfigDir(), 'agents');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function claudeSkillsDir() {
|
|
43
|
+
return join(claudeConfigDir(), 'skills');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function claudeCommandsDir() {
|
|
47
|
+
return join(claudeConfigDir(), 'commands');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function claudeHooksDir() {
|
|
51
|
+
return join(claudeConfigDir(), 'hooks');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @deprecated v6.3.0 — Claude Code migration. Use `claudeConfigDir()`.
|
|
56
|
+
* Thin wrapper so older scripts that haven't been migrated keep working.
|
|
57
|
+
*/
|
|
58
|
+
export function clineConfigDir() {
|
|
59
|
+
return claudeConfigDir();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @deprecated v6.3.0 — Claude Code migration. Use `claudeAgentsDir()`.
|
|
64
|
+
* Thin wrapper so older scripts that haven't been migrated keep working.
|
|
65
|
+
*/
|
|
40
66
|
export function clineAgentsDir() {
|
|
41
|
-
return
|
|
67
|
+
return claudeAgentsDir();
|
|
42
68
|
}
|
|
43
69
|
|
|
44
70
|
async function tryReadVersion(filePath) {
|
|
@@ -58,53 +84,41 @@ function commandExists(command) {
|
|
|
58
84
|
return probe.status === 0;
|
|
59
85
|
}
|
|
60
86
|
|
|
87
|
+
/**
|
|
88
|
+
* @deprecated v6.3.0 — Claude Code migration. Use `detectClaude()`.
|
|
89
|
+
* Probe for the legacy Cline CLI to power compat reports.
|
|
90
|
+
*/
|
|
61
91
|
export async function detectCline() {
|
|
62
|
-
const configDir =
|
|
63
|
-
const agentsDir =
|
|
64
|
-
|
|
92
|
+
const configDir = claudeConfigDir();
|
|
93
|
+
const agentsDir = claudeAgentsDir();
|
|
65
94
|
let exists = false;
|
|
66
95
|
let version = '';
|
|
67
|
-
|
|
68
96
|
try {
|
|
69
97
|
await access(configDir, constants.F_OK);
|
|
70
98
|
exists = true;
|
|
99
|
+
} catch {
|
|
100
|
+
exists = false;
|
|
101
|
+
}
|
|
102
|
+
return { exists, version, configDir, agentsDir };
|
|
103
|
+
}
|
|
71
104
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
} else {
|
|
86
|
-
const posixPaths = [
|
|
87
|
-
join(homedir(), '.local', 'share', 'cline', 'package.json'),
|
|
88
|
-
join(homedir(), '.local', 'share', 'cline', 'package.json'),
|
|
89
|
-
'/usr/local/lib/node_modules/cline/package.json',
|
|
90
|
-
'/usr/local/lib/node_modules/cline/package.json',
|
|
91
|
-
'/usr/lib/node_modules/cline/package.json',
|
|
92
|
-
'/usr/lib/node_modules/cline/package.json',
|
|
93
|
-
join(homedir(), '.npm-global', 'lib', 'node_modules', 'cline', 'package.json'),
|
|
94
|
-
join(homedir(), '.npm-global', 'lib', 'node_modules', 'cline', 'package.json'),
|
|
95
|
-
join(homedir(), 'node_modules', 'cline', 'package.json'),
|
|
96
|
-
join(homedir(), 'node_modules', 'cline', 'package.json'),
|
|
97
|
-
];
|
|
98
|
-
for (const p of posixPaths) {
|
|
99
|
-
version = await tryReadVersion(p);
|
|
100
|
-
if (version) break;
|
|
101
|
-
}
|
|
105
|
+
/**
|
|
106
|
+
* Probe for the Claude Code CLI on PATH.
|
|
107
|
+
* Returns `{ exists, version }`. v6.3.0+ replacement for `detectCline()`.
|
|
108
|
+
*/
|
|
109
|
+
export async function detectClaude() {
|
|
110
|
+
let exists = false;
|
|
111
|
+
let version = '';
|
|
112
|
+
try {
|
|
113
|
+
const probe = spawnSync('claude', ['--version'], { encoding: 'utf8', timeout: 5000 });
|
|
114
|
+
if (probe.status === 0) {
|
|
115
|
+
exists = true;
|
|
116
|
+
version = (probe.stdout || probe.stderr || '').trim().split('\n')[0];
|
|
102
117
|
}
|
|
103
118
|
} catch {
|
|
104
119
|
exists = false;
|
|
105
120
|
}
|
|
106
|
-
|
|
107
|
-
return { exists, version, configDir, agentsDir };
|
|
121
|
+
return { exists, version, configDir: claudeConfigDir(), agentsDir: claudeAgentsDir() };
|
|
108
122
|
}
|
|
109
123
|
|
|
110
124
|
export async function detectHeadroom() {
|
|
@@ -133,7 +147,7 @@ export async function detectSkillsCli() {
|
|
|
133
147
|
}
|
|
134
148
|
|
|
135
149
|
export async function detectInstalledAgents() {
|
|
136
|
-
const agentsDir =
|
|
150
|
+
const agentsDir = claudeAgentsDir();
|
|
137
151
|
try {
|
|
138
152
|
await access(agentsDir, constants.F_OK);
|
|
139
153
|
return agentsDir;
|
|
@@ -148,9 +162,9 @@ export function buildSummary(components, agents, target, skillPacks = []) {
|
|
|
148
162
|
if (components.includes('agents-md')) parts.push('AGENTS.md');
|
|
149
163
|
if (components.includes('skill-bizar')) parts.push('bizar skill');
|
|
150
164
|
if (components.includes('skill-improve')) parts.push('self-improvement skill');
|
|
151
|
-
if (components.includes('
|
|
165
|
+
if (components.includes('settings-json')) parts.push('settings.json');
|
|
152
166
|
if (components.includes('bizar')) parts.push('.bizar/ folder');
|
|
153
|
-
if (components.includes('
|
|
167
|
+
if (components.includes('mcp-bizar')) parts.push('Bizar MCP server');
|
|
154
168
|
if (components.includes('rules')) parts.push('rules');
|
|
155
169
|
if (components.includes('hooks')) parts.push('hooks');
|
|
156
170
|
if (components.includes('commands')) parts.push('commands');
|
|
@@ -167,7 +181,7 @@ export function buildSummary(components, agents, target, skillPacks = []) {
|
|
|
167
181
|
};
|
|
168
182
|
}
|
|
169
183
|
|
|
170
|
-
//
|
|
184
|
+
// Path helpers
|
|
171
185
|
|
|
172
186
|
/**
|
|
173
187
|
* Return the platform-specific Bizar config directory.
|
|
@@ -204,4 +218,4 @@ export function whichPath(cmd) {
|
|
|
204
218
|
} catch {
|
|
205
219
|
return null;
|
|
206
220
|
}
|
|
207
|
-
}
|
|
221
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* cli/worker-dispatcher.mjs
|
|
4
|
+
*
|
|
5
|
+
* Bizar Background Workers — trigger-pattern dispatcher.
|
|
6
|
+
*
|
|
7
|
+
* Reads `config/trigger-patterns.json` (cached for the lifetime of the
|
|
8
|
+
* process) and matches user prompts against each worker's `regex` array.
|
|
9
|
+
* Returns up to `opts.maxSuggestions` (default 3) weighted matches, sorted
|
|
10
|
+
* by weight desc.
|
|
11
|
+
*
|
|
12
|
+
* The hook at `.claude/hooks/worker-suggest.mjs` calls `dispatch()` on
|
|
13
|
+
* every `UserPromptSubmit` event. Pure JS, no external deps; safe to
|
|
14
|
+
* import from either Node or Bun.
|
|
15
|
+
*
|
|
16
|
+
* Public API
|
|
17
|
+
* ──────────
|
|
18
|
+
* dispatch(text, { maxSuggestions }?) -> Array<{
|
|
19
|
+
* workerId: string,
|
|
20
|
+
* weight: number,
|
|
21
|
+
* skill: string | null,
|
|
22
|
+
* agent: string | null,
|
|
23
|
+
* description: string | undefined,
|
|
24
|
+
* matchedPattern: string, // the literal regex string that hit
|
|
25
|
+
* matchedIndex: number // the prompt char-offset of the match
|
|
26
|
+
* }>
|
|
27
|
+
*
|
|
28
|
+
* listWorkers() -> string[] // all worker ids (even with no regex)
|
|
29
|
+
*
|
|
30
|
+
* resetCache() -> void // force re-read of the JSON on next dispatch
|
|
31
|
+
*
|
|
32
|
+
* loadPatterns({ configPath? }?) -> object // explicit loader for tests
|
|
33
|
+
*
|
|
34
|
+
* Honesty note: ruflo's equivalent worker bodies are stubs
|
|
35
|
+
* (`await new Promise(r => setTimeout(r, …))`); this port is just a
|
|
36
|
+
* dispatcher — actual work happens in Bizar skills/agents invoked
|
|
37
|
+
* separately by the model.
|
|
38
|
+
*/
|
|
39
|
+
'use strict';
|
|
40
|
+
|
|
41
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
42
|
+
import { dirname, resolve, join } from 'node:path';
|
|
43
|
+
import { fileURLToPath } from 'node:url';
|
|
44
|
+
|
|
45
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
46
|
+
|
|
47
|
+
// ── Config path resolution ──────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Locate `config/trigger-patterns.json`. Resolution order:
|
|
51
|
+
* 1. opts.configPath (explicit, used by tests)
|
|
52
|
+
* 2. BIZAR_TRIGGER_PATTERNS env var
|
|
53
|
+
* 3. <projectRoot>/config/trigger-patterns.json (projectRoot = parent of cli/)
|
|
54
|
+
*/
|
|
55
|
+
export function defaultConfigPath() {
|
|
56
|
+
if (process.env.BIZAR_TRIGGER_PATTERNS) {
|
|
57
|
+
return process.env.BIZAR_TRIGGER_PATTERNS;
|
|
58
|
+
}
|
|
59
|
+
const projectRoot = resolve(__dirname, '..');
|
|
60
|
+
return join(projectRoot, 'config', 'trigger-patterns.json');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ── Cached patterns + pre-compiled regexes ──────────────────────────────────
|
|
64
|
+
|
|
65
|
+
/** @type {Array<CompiledWorker> | null} */
|
|
66
|
+
let _cache = null;
|
|
67
|
+
/** @type {string | null} */
|
|
68
|
+
let _cachePath = null;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @typedef CompiledWorker
|
|
72
|
+
* @property {string} id
|
|
73
|
+
* @property {number} weight
|
|
74
|
+
* @property {string|null} skill
|
|
75
|
+
* @property {string|null} agent
|
|
76
|
+
* @property {string|undefined} description
|
|
77
|
+
* @property {Array<{ pattern: string, regex: RegExp }>} compiled
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Load + compile the patterns file. Cached on first call.
|
|
82
|
+
* @param {{ configPath?: string }=} opts
|
|
83
|
+
* @returns {Array<CompiledWorker>}
|
|
84
|
+
*/
|
|
85
|
+
export function loadPatterns(opts = {}) {
|
|
86
|
+
const path = opts.configPath || defaultConfigPath();
|
|
87
|
+
if (_cache && _cachePath === path) return _cache;
|
|
88
|
+
|
|
89
|
+
if (!existsSync(path)) {
|
|
90
|
+
// Empty dispatcher — no patterns means no suggestions, but the API
|
|
91
|
+
// remains available (so a missing config never throws at the hook).
|
|
92
|
+
_cache = [];
|
|
93
|
+
_cachePath = path;
|
|
94
|
+
return _cache;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let raw;
|
|
98
|
+
try {
|
|
99
|
+
raw = JSON.parse(readFileSync(path, 'utf8'));
|
|
100
|
+
} catch (err) {
|
|
101
|
+
// Invalid JSON is a config bug, not a runtime bug — log + fall back
|
|
102
|
+
// to an empty dispatcher so the hook still exits 0.
|
|
103
|
+
process.stderr.write(
|
|
104
|
+
`[bizar.workers] WARN: failed to parse ${path}: ${
|
|
105
|
+
err && err.message ? err.message : String(err)
|
|
106
|
+
}\n`,
|
|
107
|
+
);
|
|
108
|
+
_cache = [];
|
|
109
|
+
_cachePath = path;
|
|
110
|
+
return _cache;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const workers = Array.isArray(raw && raw.workers) ? raw.workers : [];
|
|
114
|
+
|
|
115
|
+
/** @type {Array<CompiledWorker>} */
|
|
116
|
+
const compiled = [];
|
|
117
|
+
for (const w of workers) {
|
|
118
|
+
if (!w || typeof w.id !== 'string') continue;
|
|
119
|
+
const regexSources = Array.isArray(w.regex) ? w.regex : [];
|
|
120
|
+
/** @type {Array<{ pattern: string, regex: RegExp }>} */
|
|
121
|
+
const compiled_ = [];
|
|
122
|
+
for (const src of regexSources) {
|
|
123
|
+
if (typeof src !== 'string' || src.length === 0) continue;
|
|
124
|
+
try {
|
|
125
|
+
compiled_.push({ pattern: src, regex: new RegExp(src, 'i') });
|
|
126
|
+
} catch {
|
|
127
|
+
// Skip invalid regex sources; never throw from the hook path.
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
compiled.push({
|
|
131
|
+
id: w.id,
|
|
132
|
+
weight: typeof w.weight === 'number' ? w.weight : 0.5,
|
|
133
|
+
skill: typeof w.skill === 'string' ? w.skill : null,
|
|
134
|
+
agent: typeof w.agent === 'string' ? w.agent : null,
|
|
135
|
+
description: typeof w.description === 'string' ? w.description : undefined,
|
|
136
|
+
compiled: compiled_,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
_cache = compiled;
|
|
141
|
+
_cachePath = path;
|
|
142
|
+
return _cache;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Force re-read of the patterns JSON on the next `dispatch()` call. */
|
|
146
|
+
export function resetCache() {
|
|
147
|
+
_cache = null;
|
|
148
|
+
_cachePath = null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ── Public API ──────────────────────────────────────────────────────────────
|
|
152
|
+
|
|
153
|
+
const DEFAULT_MAX_SUGGESTIONS = 3;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Match a prompt against all worker patterns and return ranked suggestions.
|
|
157
|
+
*
|
|
158
|
+
* @param {string} text
|
|
159
|
+
* @param {{ maxSuggestions?: number, configPath?: string }=} opts
|
|
160
|
+
* @returns {Array<{
|
|
161
|
+
* workerId: string,
|
|
162
|
+
* weight: number,
|
|
163
|
+
* skill: string|null,
|
|
164
|
+
* agent: string|null,
|
|
165
|
+
* description: string|undefined,
|
|
166
|
+
* matchedPattern: string,
|
|
167
|
+
* matchedIndex: number
|
|
168
|
+
* }>}
|
|
169
|
+
*/
|
|
170
|
+
export function dispatch(text, opts = {}) {
|
|
171
|
+
const out = [];
|
|
172
|
+
const source = typeof text === 'string' ? text : '';
|
|
173
|
+
if (source.length === 0) return out;
|
|
174
|
+
|
|
175
|
+
const workers = loadPatterns(
|
|
176
|
+
opts.configPath ? { configPath: opts.configPath } : {},
|
|
177
|
+
);
|
|
178
|
+
if (workers.length === 0) return out;
|
|
179
|
+
|
|
180
|
+
const max = Number.isInteger(opts.maxSuggestions)
|
|
181
|
+
? Math.max(0, opts.maxSuggestions)
|
|
182
|
+
: DEFAULT_MAX_SUGGESTIONS;
|
|
183
|
+
|
|
184
|
+
for (const w of workers) {
|
|
185
|
+
let bestIndex = -1;
|
|
186
|
+
let bestPattern = null;
|
|
187
|
+
for (const c of w.compiled) {
|
|
188
|
+
const m = c.regex.exec(source);
|
|
189
|
+
if (m && m.index >= 0) {
|
|
190
|
+
if (bestIndex === -1 || m.index < bestIndex) {
|
|
191
|
+
bestIndex = m.index;
|
|
192
|
+
bestPattern = c.pattern;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (bestPattern !== null) {
|
|
197
|
+
out.push({
|
|
198
|
+
workerId: w.id,
|
|
199
|
+
weight: w.weight,
|
|
200
|
+
skill: w.skill,
|
|
201
|
+
agent: w.agent,
|
|
202
|
+
description: w.description,
|
|
203
|
+
matchedPattern: bestPattern,
|
|
204
|
+
matchedIndex: bestIndex,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
out.sort((a, b) => {
|
|
210
|
+
if (b.weight !== a.weight) return b.weight - a.weight;
|
|
211
|
+
// Tie-break deterministically by workerId so the output is stable
|
|
212
|
+
// across runs (useful for tests + logs).
|
|
213
|
+
return a.workerId.localeCompare(b.workerId);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
return max === 0 ? [] : out.slice(0, max);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Return all worker ids declared in the patterns file. Workers with no
|
|
221
|
+
* regex are returned too — they simply never surface as suggestions.
|
|
222
|
+
*
|
|
223
|
+
* @param {{ configPath?: string }=} opts
|
|
224
|
+
* @returns {string[]}
|
|
225
|
+
*/
|
|
226
|
+
export function listWorkers(opts = {}) {
|
|
227
|
+
const workers = loadPatterns(
|
|
228
|
+
opts.configPath ? { configPath: opts.configPath } : {},
|
|
229
|
+
);
|
|
230
|
+
return workers.map((w) => w.id);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Direct CLI entrypoint for dry-runs / debugging.
|
|
234
|
+
// node cli/worker-dispatcher.mjs "your prompt here" [--max N] [--list]
|
|
235
|
+
if (
|
|
236
|
+
process.argv[1] &&
|
|
237
|
+
fileURLToPath(import.meta.url) === process.argv[1]
|
|
238
|
+
) {
|
|
239
|
+
const argv = process.argv.slice(2);
|
|
240
|
+
const wantList = argv.includes('--list');
|
|
241
|
+
const maxIdx = argv.indexOf('--max');
|
|
242
|
+
const maxVal =
|
|
243
|
+
maxIdx >= 0 && argv[maxIdx + 1] ? Number.parseInt(argv[maxIdx + 1], 10) : undefined;
|
|
244
|
+
|
|
245
|
+
if (wantList) {
|
|
246
|
+
const ids = listWorkers();
|
|
247
|
+
process.stdout.write(JSON.stringify(ids, null, 2) + '\n');
|
|
248
|
+
process.exit(0);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Build the prompt by dropping only `--max` and the value that follows it
|
|
252
|
+
// (and only when `--max` was actually present).
|
|
253
|
+
const prompt = argv
|
|
254
|
+
.filter((a, i) => !(maxIdx >= 0 && (i === maxIdx || i === maxIdx + 1)))
|
|
255
|
+
.join(' ');
|
|
256
|
+
const result = dispatch(prompt, { maxSuggestions: maxVal });
|
|
257
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
258
|
+
process.exit(0);
|
|
259
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cli/worker-dispatcher.test.mjs
|
|
3
|
+
*
|
|
4
|
+
* F-034 Background Workers — unit tests for the trigger-pattern dispatcher.
|
|
5
|
+
* Uses Node's built-in `node:test`. No external test framework.
|
|
6
|
+
*
|
|
7
|
+
* Strategy:
|
|
8
|
+
* - Use the real `config/trigger-patterns.json` (already on disk).
|
|
9
|
+
* - Call `dispatch()` and `listWorkers()` exported from
|
|
10
|
+
* `cli/worker-dispatcher.mjs`.
|
|
11
|
+
* - 5 sample prompts → expected worker ids (the canonical F-034 dry run).
|
|
12
|
+
* - Edge cases: empty prompt, case-insensitive matches, maxSuggestions
|
|
13
|
+
* clipping, no-match prompt, listWorkers completeness.
|
|
14
|
+
*/
|
|
15
|
+
import { test, describe, before, after } from 'node:test';
|
|
16
|
+
import assert from 'node:assert/strict';
|
|
17
|
+
import { mkdtempSync, writeFileSync, rmSync, existsSync } from 'node:fs';
|
|
18
|
+
import { tmpdir } from 'node:os';
|
|
19
|
+
import { join, dirname } from 'node:path';
|
|
20
|
+
import { fileURLToPath } from 'node:url';
|
|
21
|
+
|
|
22
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
|
|
24
|
+
const dispatcherModule = await import('./worker-dispatcher.mjs');
|
|
25
|
+
const { dispatch, listWorkers, resetCache, loadPatterns } = dispatcherModule;
|
|
26
|
+
|
|
27
|
+
// ── Fixture: optional override path (not used by the canonical suite) ──────
|
|
28
|
+
const ORIG_BIZAR = process.env.BIZAR_TRIGGER_PATTERNS;
|
|
29
|
+
|
|
30
|
+
after(() => {
|
|
31
|
+
if (ORIG_BIZAR === undefined) delete process.env.BIZAR_TRIGGER_PATTERNS;
|
|
32
|
+
else process.env.BIZAR_TRIGGER_PATTERNS = ORIG_BIZAR;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// ── Canonical F-034 dry-run: 5 sample prompts → expected worker ids ─────────
|
|
36
|
+
|
|
37
|
+
describe('dispatch() — canonical 5-prompt dry run', () => {
|
|
38
|
+
let tmpdir_created = false;
|
|
39
|
+
// Make sure cache is fresh for each run.
|
|
40
|
+
before(() => { resetCache(); });
|
|
41
|
+
|
|
42
|
+
test('"missing tests" → suggests testgaps', () => {
|
|
43
|
+
const out = dispatch('missing tests in the auth module');
|
|
44
|
+
const ids = out.map((s) => s.workerId);
|
|
45
|
+
assert.ok(ids.includes('testgaps'), `expected testgaps, got ${JSON.stringify(ids)}`);
|
|
46
|
+
assert.equal(out.find((s) => s.workerId === 'testgaps').matchedPattern, 'missing tests');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('"deep dive into fn()" → suggests deepdive', () => {
|
|
50
|
+
const out = dispatch('deep dive into fn()');
|
|
51
|
+
const ids = out.map((s) => s.workerId);
|
|
52
|
+
assert.ok(ids.includes('deepdive'), `expected deepdive, got ${JSON.stringify(ids)}`);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('"refactor this module" → suggests refactor', () => {
|
|
56
|
+
const out = dispatch('refactor this module');
|
|
57
|
+
const ids = out.map((s) => s.workerId);
|
|
58
|
+
assert.ok(ids.includes('refactor'), `expected refactor, got ${JSON.stringify(ids)}`);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('"security scan the API" → suggests audit', () => {
|
|
62
|
+
const out = dispatch('security scan the API');
|
|
63
|
+
const ids = out.map((s) => s.workerId);
|
|
64
|
+
assert.ok(ids.includes('audit'), `expected audit, got ${JSON.stringify(ids)}`);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('"optimize the build for size" → suggests optimize', () => {
|
|
68
|
+
const out = dispatch('optimize the build for size');
|
|
69
|
+
const ids = out.map((s) => s.workerId);
|
|
70
|
+
assert.ok(ids.includes('optimize'), `expected optimize, got ${JSON.stringify(ids)}`);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// ── Empty / no-match paths ──────────────────────────────────────────────────
|
|
75
|
+
|
|
76
|
+
describe('dispatch() — edge cases', () => {
|
|
77
|
+
before(() => { resetCache(); });
|
|
78
|
+
|
|
79
|
+
test('empty prompt returns []', () => {
|
|
80
|
+
assert.deepEqual(dispatch(''), []);
|
|
81
|
+
assert.deepEqual(dispatch(' '), []);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('no-match prompt returns []', () => {
|
|
85
|
+
assert.deepEqual(dispatch('hello world, no actionable words here'), []);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('case-insensitive match', () => {
|
|
89
|
+
const a = dispatch('Refactor this MODULE');
|
|
90
|
+
const b = dispatch('refactor this module');
|
|
91
|
+
const aIds = a.map((s) => s.workerId).sort();
|
|
92
|
+
const bIds = b.map((s) => s.workerId).sort();
|
|
93
|
+
assert.ok(aIds.includes('refactor'), 'refactor must match even in ALLCAPS');
|
|
94
|
+
assert.deepEqual(aIds, bIds);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('maxSuggestions: 1 clips to a single suggestion', () => {
|
|
98
|
+
// Construct a prompt that hits MANY workers (refactor + optimize +
|
|
99
|
+
// document + audit + testgaps). With maxSuggestions=1 we get exactly 1.
|
|
100
|
+
const out = dispatch(
|
|
101
|
+
'refactor this module; optimize the build for size; write docs; security scan; missing tests',
|
|
102
|
+
{ maxSuggestions: 1 },
|
|
103
|
+
);
|
|
104
|
+
assert.equal(out.length, 1, 'should clip to maxSuggestions=1');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('maxSuggestions: 0 returns []', () => {
|
|
108
|
+
const out = dispatch('missing tests', { maxSuggestions: 0 });
|
|
109
|
+
assert.deepEqual(out, []);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test('default maxSuggestions clips at 3', () => {
|
|
113
|
+
// Same long prompt as above — default should clamp at 3.
|
|
114
|
+
const out = dispatch(
|
|
115
|
+
'refactor this module; optimize the build for size; write docs; security scan; missing tests',
|
|
116
|
+
);
|
|
117
|
+
assert.equal(out.length, 3, 'default maxSuggestions must be 3');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('output is sorted by weight desc (then workerId)', () => {
|
|
121
|
+
const out = dispatch(
|
|
122
|
+
'refactor this module; security scan; missing tests; write docs',
|
|
123
|
+
);
|
|
124
|
+
// Find weights and assert strictly non-increasing.
|
|
125
|
+
for (let i = 1; i < out.length; i++) {
|
|
126
|
+
assert.ok(
|
|
127
|
+
out[i - 1].weight >= out[i].weight,
|
|
128
|
+
`weights must be non-increasing (${out[i - 1].workerId}=${out[i - 1].weight} < ${out[i].workerId}=${out[i].weight})`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test('every suggestion exposes skill + agent + matchedPattern', () => {
|
|
134
|
+
const out = dispatch('missing tests');
|
|
135
|
+
for (const s of out) {
|
|
136
|
+
assert.equal(typeof s.workerId, 'string');
|
|
137
|
+
assert.equal(typeof s.weight, 'number');
|
|
138
|
+
assert.ok(s.skill === null || typeof s.skill === 'string');
|
|
139
|
+
assert.ok(s.agent === null || typeof s.agent === 'string');
|
|
140
|
+
assert.equal(typeof s.matchedPattern, 'string');
|
|
141
|
+
assert.ok(s.matchedPattern.length > 0);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// ── listWorkers / loadPatterns ───────────────────────────────────────────────
|
|
147
|
+
|
|
148
|
+
describe('listWorkers()', () => {
|
|
149
|
+
before(() => { resetCache(); });
|
|
150
|
+
|
|
151
|
+
test('returns the full worker set (all 12)', () => {
|
|
152
|
+
const ids = listWorkers();
|
|
153
|
+
const expected = [
|
|
154
|
+
'testgaps', 'audit', 'deepdive', 'refactor', 'document', 'optimize',
|
|
155
|
+
'ultralearn', 'consolidate', 'predict', 'map', 'preload', 'benchmark',
|
|
156
|
+
];
|
|
157
|
+
for (const id of expected) {
|
|
158
|
+
assert.ok(ids.includes(id), `expected worker ${id} in ${JSON.stringify(ids)}`);
|
|
159
|
+
}
|
|
160
|
+
assert.equal(ids.length, expected.length, `worker count must be exactly ${expected.length}`);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
describe('loadPatterns()', () => {
|
|
165
|
+
before(() => { resetCache(); });
|
|
166
|
+
|
|
167
|
+
test('caches on second call (same instance)', () => {
|
|
168
|
+
const a = loadPatterns();
|
|
169
|
+
const b = loadPatterns();
|
|
170
|
+
assert.equal(a, b, 'second call must return cached array');
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test('resetCache() forces a fresh load', () => {
|
|
174
|
+
const a = loadPatterns();
|
|
175
|
+
resetCache();
|
|
176
|
+
const b = loadPatterns();
|
|
177
|
+
assert.notEqual(a, b, 'after resetCache the new array must be a fresh object');
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test('missing configPath yields empty dispatcher (no throw)', () => {
|
|
181
|
+
resetCache();
|
|
182
|
+
const tmp = mkdtempSync(join(tmpdir(), 'bizar-workers-'));
|
|
183
|
+
const phantom = join(tmp, 'does-not-exist.json');
|
|
184
|
+
const out = dispatch('missing tests', { configPath: phantom });
|
|
185
|
+
assert.deepEqual(out, []);
|
|
186
|
+
// Restore default config by clearing the override.
|
|
187
|
+
delete process.env.BIZAR_TRIGGER_PATTERNS;
|
|
188
|
+
resetCache();
|
|
189
|
+
// Sanity: the real config still works.
|
|
190
|
+
assert.ok(dispatch('missing tests').length > 0);
|
|
191
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test('malformed JSON yields empty dispatcher (no throw)', () => {
|
|
195
|
+
resetCache();
|
|
196
|
+
const tmp = mkdtempSync(join(tmpdir(), 'bizar-workers-'));
|
|
197
|
+
const broken = join(tmp, 'broken.json');
|
|
198
|
+
writeFileSync(broken, '{not valid json');
|
|
199
|
+
const out = dispatch('missing tests', { configPath: broken });
|
|
200
|
+
assert.deepEqual(out, []);
|
|
201
|
+
resetCache();
|
|
202
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
203
|
+
});
|
|
204
|
+
});
|