@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,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* consensus/index.ts — Public orchestrator for the consensus layer.
|
|
3
|
+
*
|
|
4
|
+
* F-039 — wraps `ByzantineConsensus` behind a stable factory API and
|
|
5
|
+
* re-exports every type/utility callers need. This is the surface the
|
|
6
|
+
* MCP tool (`consensus_propose`) and any future dashboard wiring
|
|
7
|
+
* consume.
|
|
8
|
+
*
|
|
9
|
+
* The orchestrator is intentionally minimal — it's a thin facade over
|
|
10
|
+
* `ByzantineConsensus` plus the type re-exports. Anything fancier
|
|
11
|
+
* (proposer scheduling, fault dashboards, etc.) belongs in `queen.ts`
|
|
12
|
+
* or a future `dashboard.ts`.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { ByzantineConsensus, type ByzantineConsensusOpts } from "./byzantine.js";
|
|
16
|
+
import {
|
|
17
|
+
DEFAULT_MAX_FAULTS,
|
|
18
|
+
DEFAULT_QUORUM,
|
|
19
|
+
type CommitResult,
|
|
20
|
+
type ConsensusStatus,
|
|
21
|
+
type Decision,
|
|
22
|
+
type ProposeResult,
|
|
23
|
+
type ProposalSnapshot,
|
|
24
|
+
type Vote,
|
|
25
|
+
type VoteResult,
|
|
26
|
+
type ViewChangeResult,
|
|
27
|
+
} from "./types.js";
|
|
28
|
+
|
|
29
|
+
export interface CreateConsensusOpts extends Omit<ByzantineConsensusOpts, "localAgentId" | "peers"> {
|
|
30
|
+
localAgentId: string;
|
|
31
|
+
peers: string[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ConsensusHandle {
|
|
35
|
+
/** Identity of the local agent (vote short-circuits on its own calls). */
|
|
36
|
+
readonly localAgentId: string;
|
|
37
|
+
/** Read-only snapshot of every proposal the instance has tracked. */
|
|
38
|
+
status(): ConsensusStatus;
|
|
39
|
+
/** Snapshot of a single proposal, or `undefined` if unknown. */
|
|
40
|
+
getProposal(proposalId: string): ProposalSnapshot | undefined;
|
|
41
|
+
/** Initiate pre-prepare for a new proposal. Re-submitting the same
|
|
42
|
+
* payload under the same view returns the cached proposalId. */
|
|
43
|
+
propose(payload: unknown): ProposeResult;
|
|
44
|
+
/** Cast a vote for a peer during the `prepare` phase. */
|
|
45
|
+
castVote(proposalId: string, agentId: string, decision: Decision, signature?: string): VoteResult;
|
|
46
|
+
/** Transport-friendly entry point — `onPrepare(proposalId, vote)`. */
|
|
47
|
+
onPrepare(proposalId: string, vote: Vote): VoteResult;
|
|
48
|
+
/** Force-commit a proposal (admin override; rare). */
|
|
49
|
+
commit(proposalId: string): CommitResult;
|
|
50
|
+
/** Trigger a view-change; returns the new proposer + view number. */
|
|
51
|
+
viewChange(reason: string, proposalId?: string): ViewChangeResult;
|
|
52
|
+
/** Head of the round-robin proposer schedule. */
|
|
53
|
+
getCurrentProposer(): string;
|
|
54
|
+
/** Current view number (incremented on every view-change). */
|
|
55
|
+
getViewNumber(): number;
|
|
56
|
+
/** Quorum threshold in effect. */
|
|
57
|
+
getQuorum(): number;
|
|
58
|
+
/** Peer roster (read-only copy). */
|
|
59
|
+
getPeers(): string[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Build a `ConsensusHandle` for a given local agent + peer roster.
|
|
64
|
+
* The returned object is the public surface used by the MCP tool and
|
|
65
|
+
* any dashboard wiring.
|
|
66
|
+
*/
|
|
67
|
+
export function createConsensus(opts: CreateConsensusOpts): ConsensusHandle {
|
|
68
|
+
const instance = new ByzantineConsensus(opts);
|
|
69
|
+
return {
|
|
70
|
+
localAgentId: opts.localAgentId,
|
|
71
|
+
status: () => instance.status(),
|
|
72
|
+
getProposal: (id) => instance.getProposal(id),
|
|
73
|
+
propose: (payload) => instance.propose(payload),
|
|
74
|
+
castVote: (proposalId, agentId, decision, signature) =>
|
|
75
|
+
instance.castVote(proposalId, agentId, decision, signature),
|
|
76
|
+
onPrepare: (proposalId, vote) => instance.onPrepare(proposalId, vote),
|
|
77
|
+
commit: (proposalId) => instance.commit(proposalId),
|
|
78
|
+
viewChange: (reason, proposalId) => instance.viewChange(reason, proposalId),
|
|
79
|
+
getCurrentProposer: () => instance.getCurrentProposer(),
|
|
80
|
+
getViewNumber: () => instance.getViewNumber(),
|
|
81
|
+
getQuorum: () => instance.getQuorum(),
|
|
82
|
+
getPeers: () => instance.getPeers(),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ─── Re-exports ────────────────────────────────────────────────────────
|
|
87
|
+
|
|
88
|
+
export { ByzantineConsensus, type ByzantineConsensusOpts } from "./byzantine.js";
|
|
89
|
+
export { QueenCoordinator, type QueenCoordinatorOpts } from "./queen.js";
|
|
90
|
+
export {
|
|
91
|
+
DEFAULT_MAX_FAULTS,
|
|
92
|
+
DEFAULT_PEER_COUNT,
|
|
93
|
+
DEFAULT_QUORUM,
|
|
94
|
+
PHASE_ORDER,
|
|
95
|
+
} from "./types.js";
|
|
96
|
+
export type {
|
|
97
|
+
CommitResult,
|
|
98
|
+
ConsensusOpts,
|
|
99
|
+
ConsensusStatus,
|
|
100
|
+
Decision,
|
|
101
|
+
Phase,
|
|
102
|
+
ProposeResult,
|
|
103
|
+
Proposal,
|
|
104
|
+
ProposalSnapshot,
|
|
105
|
+
ProposalStatus,
|
|
106
|
+
Vote,
|
|
107
|
+
VoteResult,
|
|
108
|
+
ViewChangeResult,
|
|
109
|
+
} from "./types.js";
|
|
110
|
+
|
|
111
|
+
// ─── Process-wide singleton ───────────────────────────────────────────
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* The shared consensus singleton used by the MCP tool. Initialized
|
|
115
|
+
* with the Bizar default 5-peer roster (odin / frigg / vor / mimir /
|
|
116
|
+
* heimdall — the same five Norse agents F-033 routes between) and a
|
|
117
|
+
* deterministic seed so MCP-driven consensus is reproducible across
|
|
118
|
+
* restarts. Tests should call `createConsensus()` with their own
|
|
119
|
+
* `localAgentId` + `peers` to get an isolated instance.
|
|
120
|
+
*
|
|
121
|
+
* The roster here is intentional — it maps to the existing 5-agent
|
|
122
|
+
* surface F-033 already exposes, so a single MCP call can drive the
|
|
123
|
+
* same set of agents the orchestrator routes to.
|
|
124
|
+
*/
|
|
125
|
+
const DEFAULT_PEERS: readonly string[] = ["odin", "frigg", "vor", "mimir", "heimdall"];
|
|
126
|
+
const DEFAULT_LOCAL_AGENT = "odin";
|
|
127
|
+
const DEFAULT_PROPOSER_SEED = "bizar-f039-default";
|
|
128
|
+
|
|
129
|
+
let _shared: ConsensusHandle | null = null;
|
|
130
|
+
|
|
131
|
+
export function getSharedConsensus(): ConsensusHandle {
|
|
132
|
+
if (_shared) return _shared;
|
|
133
|
+
_shared = createConsensus({
|
|
134
|
+
localAgentId: DEFAULT_LOCAL_AGENT,
|
|
135
|
+
peers: [...DEFAULT_PEERS],
|
|
136
|
+
quorum: DEFAULT_QUORUM,
|
|
137
|
+
maxFaults: DEFAULT_MAX_FAULTS,
|
|
138
|
+
proposerSeed: DEFAULT_PROPOSER_SEED,
|
|
139
|
+
historyLimit: 50,
|
|
140
|
+
});
|
|
141
|
+
return _shared;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Reset the singleton — test/dev only. */
|
|
145
|
+
export function resetSharedConsensus(): void {
|
|
146
|
+
_shared = null;
|
|
147
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* consensus/queen.ts — Proposer election (QueenCoordinator).
|
|
3
|
+
*
|
|
4
|
+
* F-039 — thin port of ruflo's capability-scored QueenCoordinator
|
|
5
|
+
* (v3/@claude-flow/swarm/src/coordination/queen-coordinator.ts) for
|
|
6
|
+
* the consensus layer's proposer selection. Bizar needs a deterministic,
|
|
7
|
+
* fault-aware round-robin; we don't port the full ReasoningBank pattern
|
|
8
|
+
* matching because Bizar's review steps don't have agent capability
|
|
9
|
+
* vectors — they have peer rosters + a fault log.
|
|
10
|
+
*
|
|
11
|
+
* Algorithm: round-robin weighted by recent fault count. A peer with
|
|
12
|
+
* N faults is skipped N times before becoming proposer again. With
|
|
13
|
+
* `proposerSeed`, the initial head is computed deterministically so
|
|
14
|
+
* tests can pin it.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export interface QueenCoordinatorOpts {
|
|
18
|
+
/** Full peer roster, in the order round-robin walks them. Required. */
|
|
19
|
+
peers: string[];
|
|
20
|
+
/** Maximum Byzantine faults the cluster can tolerate (used as the
|
|
21
|
+
* skip-multiplier floor). Defaults to 1. */
|
|
22
|
+
maxFaults?: number;
|
|
23
|
+
/** Optional seed — when set, the initial head is `peers[seedHash % peers.length]`. */
|
|
24
|
+
seed?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Tracks per-peer fault counts and walks the peer list in
|
|
29
|
+
* round-robin order, skipping any peer whose `faultCount` is greater
|
|
30
|
+
* than the candidate's expected count at that position.
|
|
31
|
+
*
|
|
32
|
+
* Concretely: if peer X has faultCount 2, the next 2 round-robin
|
|
33
|
+
* positions that would land on X skip it instead and the proposer
|
|
34
|
+
* becomes the peer at the next non-skipped position. After 2
|
|
35
|
+
* `advance()` calls (or `selectProposer` calls that consumed a skip),
|
|
36
|
+
* X is eligible again.
|
|
37
|
+
*
|
|
38
|
+
* The fault penalty decays as the round-robin walks — this keeps
|
|
39
|
+
* the cluster moving even when one peer has accumulated many faults.
|
|
40
|
+
*/
|
|
41
|
+
export class QueenCoordinator {
|
|
42
|
+
private readonly peers: readonly string[];
|
|
43
|
+
/** Maximum Byzantine faults the cluster is sized for (used as the
|
|
44
|
+
* skip-multiplier floor — `recordFault` adds a skip of size
|
|
45
|
+
* `maxFaults` so the worst peer is skipped `maxFaults` rounds). */
|
|
46
|
+
private readonly maxFaults: number;
|
|
47
|
+
/** Per-peer cumulative fault count. */
|
|
48
|
+
private readonly faults: Map<string, number> = new Map();
|
|
49
|
+
/** Per-peer remaining-skip count (decremented on every advance). */
|
|
50
|
+
private readonly skips: Map<string, number> = new Map();
|
|
51
|
+
/** Current head of the round-robin walk. */
|
|
52
|
+
private cursor = 0;
|
|
53
|
+
|
|
54
|
+
constructor(opts: QueenCoordinatorOpts) {
|
|
55
|
+
if (!opts || !Array.isArray(opts.peers) || opts.peers.length === 0) {
|
|
56
|
+
throw new Error("QueenCoordinator: `peers` is required and must be non-empty");
|
|
57
|
+
}
|
|
58
|
+
const seen = new Set<string>();
|
|
59
|
+
for (const p of opts.peers) {
|
|
60
|
+
if (typeof p !== "string" || p.length === 0) {
|
|
61
|
+
throw new Error("QueenCoordinator: every peer id must be a non-empty string");
|
|
62
|
+
}
|
|
63
|
+
if (seen.has(p)) {
|
|
64
|
+
throw new Error(`QueenCoordinator: duplicate peer id "${p}"`);
|
|
65
|
+
}
|
|
66
|
+
seen.add(p);
|
|
67
|
+
this.faults.set(p, 0);
|
|
68
|
+
this.skips.set(p, 0);
|
|
69
|
+
}
|
|
70
|
+
this.peers = [...opts.peers];
|
|
71
|
+
this.maxFaults = Math.max(0, opts.maxFaults ?? 1);
|
|
72
|
+
if (opts.seed) {
|
|
73
|
+
this.cursor = this.seedCursor(opts.seed);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Current proposer (head of the round-robin walk). */
|
|
78
|
+
currentProposer(): string {
|
|
79
|
+
return this.peers[this.cursor % this.peers.length] as string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Record a fault against a peer (the proposer just voted `no`, or
|
|
83
|
+
* missed its pre-prepare window). Increments both the cumulative
|
|
84
|
+
* fault log and the per-peer skip counter — the peer is then
|
|
85
|
+
* skipped for `maxFaults` round-robin steps before becoming
|
|
86
|
+
* proposer-eligible again. With `maxFaults = 1` (the F-039
|
|
87
|
+
* default), one fault skips the peer for one round. */
|
|
88
|
+
recordFault(peerId: string): void {
|
|
89
|
+
if (!this.faults.has(peerId)) {
|
|
90
|
+
throw new Error(`recordFault: unknown peer "${peerId}"`);
|
|
91
|
+
}
|
|
92
|
+
this.faults.set(peerId, (this.faults.get(peerId) ?? 0) + 1);
|
|
93
|
+
this.skips.set(peerId, (this.skips.get(peerId) ?? 0) + this.maxFaults);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Walk one step forward. Skips any peer whose remaining-skip count
|
|
98
|
+
* is > 0 (decrementing the counter as it skips). Returns the new
|
|
99
|
+
* proposer.
|
|
100
|
+
*/
|
|
101
|
+
advance(): string {
|
|
102
|
+
const n = this.peers.length;
|
|
103
|
+
let steps = 0;
|
|
104
|
+
while (steps < n) {
|
|
105
|
+
this.cursor = (this.cursor + 1) % n;
|
|
106
|
+
const candidate = this.peers[this.cursor] as string;
|
|
107
|
+
const skip = this.skips.get(candidate) ?? 0;
|
|
108
|
+
if (skip > 0) {
|
|
109
|
+
this.skips.set(candidate, skip - 1);
|
|
110
|
+
steps++;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
return candidate;
|
|
114
|
+
}
|
|
115
|
+
// Everyone had skip > 0 — we walked the full circle and decremented
|
|
116
|
+
// everyone. Just return where we landed.
|
|
117
|
+
return this.peers[this.cursor] as string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Equivalent to `selectProposer(peers, recentFaults)` from the F-039
|
|
122
|
+
* spec — but stateful, because we own the fault log. Returns the
|
|
123
|
+
* current proposer without advancing.
|
|
124
|
+
*/
|
|
125
|
+
selectProposer(): string {
|
|
126
|
+
// If the current proposer has a non-zero skip, walk forward to find
|
|
127
|
+
// the next eligible peer.
|
|
128
|
+
const n = this.peers.length;
|
|
129
|
+
let probe = this.cursor;
|
|
130
|
+
for (let i = 0; i < n; i++) {
|
|
131
|
+
const candidate = this.peers[probe] as string;
|
|
132
|
+
const skip = this.skips.get(candidate) ?? 0;
|
|
133
|
+
if (skip === 0) return candidate;
|
|
134
|
+
probe = (probe + 1) % n;
|
|
135
|
+
}
|
|
136
|
+
// All peers have skip > 0 — same fallback as advance().
|
|
137
|
+
return this.peers[this.cursor] as string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Cumulative fault counts (read-only snapshot). */
|
|
141
|
+
faultCounts(): Record<string, number> {
|
|
142
|
+
return Object.fromEntries(this.faults);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Number of peers currently under a skip penalty. */
|
|
146
|
+
pendingSkipCount(): number {
|
|
147
|
+
let n = 0;
|
|
148
|
+
for (const v of this.skips.values()) if (v > 0) n++;
|
|
149
|
+
return n;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Test/dev helper: drop the cursor and fault counts. */
|
|
153
|
+
reset(): void {
|
|
154
|
+
this.cursor = 0;
|
|
155
|
+
for (const k of this.faults.keys()) this.faults.set(k, 0);
|
|
156
|
+
for (const k of this.skips.keys()) this.skips.set(k, 0);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ─── Helpers ────────────────────────────────────────────────────────
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Stable hash of an optional seed string → integer cursor in
|
|
163
|
+
* `[0, peers.length)`. Lets a test caller pin the initial proposer
|
|
164
|
+
* for replay safety (F-039 determinism rule).
|
|
165
|
+
*/
|
|
166
|
+
private seedCursor(seed: string): number {
|
|
167
|
+
let h = 5381;
|
|
168
|
+
for (let i = 0; i < seed.length; i++) {
|
|
169
|
+
h = ((h << 5) + h + seed.charCodeAt(i)) >>> 0;
|
|
170
|
+
}
|
|
171
|
+
return h % this.peers.length;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* consensus/types.ts — Shared type definitions for the in-process
|
|
3
|
+
* Byzantine consensus layer.
|
|
4
|
+
*
|
|
5
|
+
* F-039 — thin port of ruflo's `v3/@claude-flow/swarm/src/consensus/byzantine.ts`
|
|
6
|
+
* for Bizar's review/decision steps. We carry the full PBFT phase
|
|
7
|
+
* vocabulary (pre-prepare / prepare / commit / reply) and a 3-of-5
|
|
8
|
+
* simple-majority quorum — enough surface for Bizar to gate
|
|
9
|
+
* multi-agent review decisions without the operational cost of full
|
|
10
|
+
* PBFT (no transport, no crypto signatures, no checkpoint protocol).
|
|
11
|
+
*
|
|
12
|
+
* Determinism rule: quorum math is purely set-based. The only place
|
|
13
|
+
* randomness (or ordering) enters is the optional round-robin
|
|
14
|
+
* proposer election in `queen.ts`, and even there the caller can
|
|
15
|
+
* pass an explicit seed for replay safety.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// ─── Phase vocabulary ──────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* PBFT-style phase identifiers. Each proposal walks
|
|
22
|
+
* `pre-prepare → prepare → commit → reply` in order.
|
|
23
|
+
*/
|
|
24
|
+
export type Phase =
|
|
25
|
+
| "pre-prepare"
|
|
26
|
+
| "prepare"
|
|
27
|
+
| "commit"
|
|
28
|
+
| "reply";
|
|
29
|
+
|
|
30
|
+
export const PHASE_ORDER: readonly Phase[] = [
|
|
31
|
+
"pre-prepare",
|
|
32
|
+
"prepare",
|
|
33
|
+
"commit",
|
|
34
|
+
"reply",
|
|
35
|
+
] as const;
|
|
36
|
+
|
|
37
|
+
/** Decision a peer casts during the `prepare` phase. */
|
|
38
|
+
export type Decision = "yes" | "no" | "abstain";
|
|
39
|
+
|
|
40
|
+
// ─── Messages ──────────────────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A vote cast by a peer during the `prepare` phase. The signature
|
|
44
|
+
* field is a free-form string — we don't enforce cryptographic
|
|
45
|
+
* signatures in the thin port (no transport), but callers that
|
|
46
|
+
* wire in a transport can stuff an HMAC in here without changing
|
|
47
|
+
* the shape.
|
|
48
|
+
*/
|
|
49
|
+
export interface Vote {
|
|
50
|
+
agentId: string;
|
|
51
|
+
phase: Extract<Phase, "prepare">;
|
|
52
|
+
decision: Decision;
|
|
53
|
+
signature?: string;
|
|
54
|
+
/** Wall-clock timestamp at which the peer emitted the vote. */
|
|
55
|
+
timestamp: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* A proposal is the unit of agreement. `proposer` is the agent that
|
|
60
|
+
* initiated pre-prepare; `quorum` is the number of matching `yes`
|
|
61
|
+
* votes required for commit (3-of-5 simple majority by default).
|
|
62
|
+
*/
|
|
63
|
+
export interface Proposal {
|
|
64
|
+
id: string;
|
|
65
|
+
payload: unknown;
|
|
66
|
+
proposer: string;
|
|
67
|
+
quorum: number;
|
|
68
|
+
/** Total peer count this proposal was negotiated against (incl. proposer). */
|
|
69
|
+
peerCount: number;
|
|
70
|
+
/** Current phase, drives which transitions are legal. */
|
|
71
|
+
phase: Phase;
|
|
72
|
+
/** Set of agentIds that have voted `yes` in `prepare`. */
|
|
73
|
+
approvals: Set<string>;
|
|
74
|
+
/** Set of agentIds that have voted `no` in `prepare`. */
|
|
75
|
+
rejections: Set<string>;
|
|
76
|
+
/** Set of agentIds that have voted `abstain`. */
|
|
77
|
+
abstentions: Set<string>;
|
|
78
|
+
/** Free-form reason for `view-change` (set if status === 'view-change'). */
|
|
79
|
+
viewChangeReason?: string;
|
|
80
|
+
/** Set when the proposal is committed. */
|
|
81
|
+
committedAt?: string;
|
|
82
|
+
/** Set when the proposal is finalized (reply phase). */
|
|
83
|
+
finalizedAt?: string;
|
|
84
|
+
/** Wall-clock timestamp at which the proposer started pre-prepare. */
|
|
85
|
+
createdAt: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type ProposalStatus =
|
|
89
|
+
| "pending"
|
|
90
|
+
| "pre-prepare"
|
|
91
|
+
| "prepare"
|
|
92
|
+
| "commit"
|
|
93
|
+
| "reply"
|
|
94
|
+
| "view-change"
|
|
95
|
+
| "committed"
|
|
96
|
+
| "rejected"
|
|
97
|
+
| "expired";
|
|
98
|
+
|
|
99
|
+
/** A snapshot of a proposal for the public `status()` query. */
|
|
100
|
+
export interface ProposalSnapshot {
|
|
101
|
+
id: string;
|
|
102
|
+
status: ProposalStatus;
|
|
103
|
+
phase: Phase;
|
|
104
|
+
proposer: string;
|
|
105
|
+
quorum: number;
|
|
106
|
+
peerCount: number;
|
|
107
|
+
approvals: number;
|
|
108
|
+
rejections: number;
|
|
109
|
+
abstentions: number;
|
|
110
|
+
createdAt: string;
|
|
111
|
+
committedAt?: string;
|
|
112
|
+
finalizedAt?: string;
|
|
113
|
+
viewChangeReason?: string;
|
|
114
|
+
payload: unknown;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ─── Quorum ────────────────────────────────────────────────────────────
|
|
118
|
+
|
|
119
|
+
/** 3-of-5 simple majority quorum, per the F-039 spec. */
|
|
120
|
+
export const DEFAULT_QUORUM = 3;
|
|
121
|
+
export const DEFAULT_PEER_COUNT = 5;
|
|
122
|
+
|
|
123
|
+
/** The default fault tolerance — at most 1 Byzantine peer per cluster. */
|
|
124
|
+
export const DEFAULT_MAX_FAULTS = 1;
|
|
125
|
+
|
|
126
|
+
// ─── Consensus status (returned by `status()`) ─────────────────────────
|
|
127
|
+
|
|
128
|
+
export interface ConsensusStatus {
|
|
129
|
+
/** All proposals the instance has processed, in arrival order. */
|
|
130
|
+
proposals: ProposalSnapshot[];
|
|
131
|
+
/** Current proposer (head of the round-robin schedule, weighted by faults). */
|
|
132
|
+
currentProposer: string;
|
|
133
|
+
/** View number — increments on every view-change. */
|
|
134
|
+
viewNumber: number;
|
|
135
|
+
/** Total proposals ever committed (status === 'committed'). */
|
|
136
|
+
committed: number;
|
|
137
|
+
/** Total proposals ever rejected (status === 'rejected'). */
|
|
138
|
+
rejected: number;
|
|
139
|
+
/** Total proposals ever expired (status === 'expired'). */
|
|
140
|
+
expired: number;
|
|
141
|
+
/** Total view-changes triggered by a faulty proposer. */
|
|
142
|
+
viewChanges: number;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ─── Constructor / orchestrator options ─────────────────────────────────
|
|
146
|
+
|
|
147
|
+
export interface ConsensusOpts {
|
|
148
|
+
/** Local agent id — votes cast by `localAgentId` are short-circuited
|
|
149
|
+
* to `prepare`. Required. */
|
|
150
|
+
localAgentId: string;
|
|
151
|
+
/** Full peer roster (including `localAgentId`). Order matters for
|
|
152
|
+
* round-robin proposer election. Required. */
|
|
153
|
+
peers: string[];
|
|
154
|
+
/** Quorum threshold for `prepare → commit`. Defaults to 3. */
|
|
155
|
+
quorum?: number;
|
|
156
|
+
/** Maximum Byzantine faults the cluster is sized for. Defaults to 1. */
|
|
157
|
+
maxFaults?: number;
|
|
158
|
+
/** Wall-clock timeout (ms) after which a pending proposal expires. */
|
|
159
|
+
/** Optional seed for round-robin proposer election — makes proposer
|
|
160
|
+
* selection deterministic for tests. If absent, round-robin walks
|
|
161
|
+
* the peer list in the order given. */
|
|
162
|
+
proposerSeed?: string;
|
|
163
|
+
/** A clock function for deterministic timestamps in tests. */
|
|
164
|
+
now?: () => Date;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ─── Public result shapes ──────────────────────────────────────────────
|
|
168
|
+
|
|
169
|
+
export interface ProposeResult {
|
|
170
|
+
proposalId: string;
|
|
171
|
+
status: ProposalStatus;
|
|
172
|
+
phase: Phase;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface VoteResult {
|
|
176
|
+
proposalId: string;
|
|
177
|
+
status: ProposalStatus;
|
|
178
|
+
phase: Phase;
|
|
179
|
+
approvals: number;
|
|
180
|
+
rejections: number;
|
|
181
|
+
abstentions: number;
|
|
182
|
+
committed: boolean;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export interface CommitResult {
|
|
186
|
+
proposalId: string;
|
|
187
|
+
status: ProposalStatus;
|
|
188
|
+
committedAt: string;
|
|
189
|
+
finalizedAt: string;
|
|
190
|
+
approvals: number;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface ViewChangeResult {
|
|
194
|
+
previousProposer: string;
|
|
195
|
+
newProposer: string;
|
|
196
|
+
viewNumber: number;
|
|
197
|
+
reason: string;
|
|
198
|
+
proposalId: string;
|
|
199
|
+
}
|
|
@@ -5,20 +5,10 @@
|
|
|
5
5
|
* + OpenFang `crates/openfang-skills/src/verify.rs` + OpenClaw
|
|
6
6
|
* `src/security/external-content.ts:28-43`.
|
|
7
7
|
*
|
|
8
|
-
* Detects dangerous commands and blocks/requires approval before
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* Categories:
|
|
13
|
-
* - Filesystem destruction (rm -rf, mkfs, dd, fork bombs)
|
|
14
|
-
* - Privilege escalation (sudo, su, chmod 777, chown)
|
|
15
|
-
* - Network exfiltration (curl to metadata, wget, nc backdoors)
|
|
16
|
-
* - Process control (kill -9 1, pkill, shutdown)
|
|
17
|
-
* - Crypto mining (xmrig, minerd)
|
|
18
|
-
* - Path traversal in file paths (../../etc/passwd, ~/.ssh/)
|
|
19
|
-
*
|
|
20
|
-
* v6.0.0 — initial patterns. Tuned to catch the common exploits
|
|
21
|
-
* without false positives on legitimate dev work.
|
|
8
|
+
* Detects dangerous commands and blocks/requires approval before tool
|
|
9
|
+
* execution. Every tool that takes a "command" or "path" argument runs
|
|
10
|
+
* through `checkDangerous()` before being dispatched. Framework-agnostic
|
|
11
|
+
* — used by both the SDK MCP server and any Claude Code hook scripts.
|
|
22
12
|
*/
|
|
23
13
|
|
|
24
14
|
export type ApprovalDecision = "allow" | "require-approval" | "deny";
|
|
@@ -30,8 +20,6 @@ export interface ApprovalCheck {
|
|
|
30
20
|
pattern?: string;
|
|
31
21
|
}
|
|
32
22
|
|
|
33
|
-
// 30+ patterns from Hermes + OpenFang + OpenClaw. Catches the common
|
|
34
|
-
// dangerous operations in coding-agent contexts.
|
|
35
23
|
const DANGEROUS_PATTERNS: Array<{ name: string; pattern: RegExp; decision: ApprovalDecision; reason: string }> = [
|
|
36
24
|
// Filesystem destruction
|
|
37
25
|
{ name: "rm-rf-root", pattern: /\brm\s+(-\w*r\w*f\w*\s+)*\/\s*$/i, decision: "deny", reason: "Recursive delete of root filesystem" },
|
|
@@ -62,10 +50,10 @@ const DANGEROUS_PATTERNS: Array<{ name: string; pattern: RegExp; decision: Appro
|
|
|
62
50
|
{ name: "shutdown", pattern: /\b(shutdown|halt|poweroff|reboot)\b/i, decision: "deny", reason: "System shutdown" },
|
|
63
51
|
{ name: "init-0", pattern: /\binit\s+0\b/i, decision: "deny", reason: "init 0 (shutdown)" },
|
|
64
52
|
|
|
65
|
-
// Crypto mining
|
|
53
|
+
// Crypto mining
|
|
66
54
|
{ name: "xmrig", pattern: /\b(xmrig|minerd|cpuminer|cgminer)\b/i, decision: "deny", reason: "Crypto miner" },
|
|
67
55
|
|
|
68
|
-
// Package management
|
|
56
|
+
// Package management
|
|
69
57
|
{ name: "pip-install-shell", pattern: /\bpip\s+install\s+.*\|\s*(ba)?sh\b/i, decision: "deny", reason: "pip install piped to shell" },
|
|
70
58
|
{ name: "npm-install-shell", pattern: /\bnpm\s+install\s+.*\|\s*(ba)?sh\b/i, decision: "deny", reason: "npm install piped to shell" },
|
|
71
59
|
|
|
@@ -90,15 +78,7 @@ const DANGEROUS_PATTERNS: Array<{ name: string; pattern: RegExp; decision: Appro
|
|
|
90
78
|
{ name: "system-prompt-leak", pattern: /reveal\s+(your\s+)?system\s+prompt/i, decision: "deny", reason: "Prompt extraction attempt" },
|
|
91
79
|
];
|
|
92
80
|
|
|
93
|
-
/**
|
|
94
|
-
* Check a tool call's arguments for dangerous patterns.
|
|
95
|
-
* Returns a decision (allow / require-approval / deny) and a reason.
|
|
96
|
-
*
|
|
97
|
-
* The check is applied to the union of all string-typed arguments,
|
|
98
|
-
* so the caller doesn't need to know which arg is the "command".
|
|
99
|
-
*/
|
|
100
81
|
export function checkDangerous(args: Record<string, unknown>): ApprovalCheck {
|
|
101
|
-
// Collect all string values from the args object
|
|
102
82
|
const text = collectStrings(args);
|
|
103
83
|
if (!text) return { decision: "allow" };
|
|
104
84
|
|
|
@@ -128,12 +108,10 @@ function collectStrings(value: unknown, parts: string[] = []): string {
|
|
|
128
108
|
return parts.join("\n");
|
|
129
109
|
}
|
|
130
110
|
|
|
131
|
-
/** Get all pattern names (for audit / reporting). */
|
|
132
111
|
export function listDangerousPatterns(): string[] {
|
|
133
112
|
return DANGEROUS_PATTERNS.map((p) => p.name);
|
|
134
113
|
}
|
|
135
114
|
|
|
136
|
-
/** Count of patterns in each category. */
|
|
137
115
|
export function getDangerousPatternStats(): {
|
|
138
116
|
total: number;
|
|
139
117
|
deny: number;
|