@polderlabs/bizar 6.2.4 → 6.3.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/settings.json +116 -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-B58aiJiE.js} +1 -1
- package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js.map → EnvVarsSection-B58aiJiE.js.map} +1 -1
- package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js → MobileChat-BJrqwVDd.js} +1 -1
- package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js.map → MobileChat-BJrqwVDd.js.map} +1 -1
- package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js → MobileSettings-CEQNJNLJ.js} +1 -1
- package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js.map → MobileSettings-CEQNJNLJ.js.map} +1 -1
- package/bizar-dash/dist/assets/{main-DYiZqMrn.js → main-IvfQAOfy.js} +1 -1
- package/bizar-dash/dist/assets/{main-DYiZqMrn.js.map → main-IvfQAOfy.js.map} +1 -1
- package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js → markdown-tOLaD6nm.js} +1 -1
- package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js.map → markdown-tOLaD6nm.js.map} +1 -1
- package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js → mobile-DYCHcUpq.js} +1 -1
- package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js.map → mobile-DYCHcUpq.js.map} +1 -1
- package/bizar-dash/dist/assets/{mobile-layout-3jIhHX_p.js → mobile-layout-CBHjpwsb.js} +2 -2
- package/bizar-dash/dist/assets/{mobile-layout-3jIhHX_p.js.map → mobile-layout-CBHjpwsb.js.map} +1 -1
- package/bizar-dash/dist/assets/{useSlashCommands-DtITw8Xv.js → useSlashCommands-Bd7_FA6U.js} +2 -2
- package/bizar-dash/dist/assets/{useSlashCommands-DtITw8Xv.js.map → useSlashCommands-Bd7_FA6U.js.map} +1 -1
- package/bizar-dash/dist/assets/{vendor-CeHGtduv.js → vendor-C843201K.js} +12 -12
- package/bizar-dash/dist/assets/vendor-C843201K.js.map +1 -0
- package/bizar-dash/dist/index.html +6 -6
- package/bizar-dash/dist/mobile.html +2 -2
- package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/bizar-dash/src/server/api.mjs +4 -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/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/tasks.mjs +20 -28
- package/bizar-dash/src/server/task-delegator.mjs +76 -77
- package/bizar-dash/src/web/components/chat/useChat.ts +23 -27
- package/bizar-dash/src/web/views/Chat.tsx +8 -8
- package/cli/bin.mjs +31 -18
- package/cli/commands/claude-cmd.mjs +348 -0
- package/cli/commands/install.mjs +12 -11
- package/cli/commands/sandbox.mjs +220 -0
- package/cli/commands/validate.mjs +252 -288
- package/cli/dev-link.test.mjs +11 -11
- package/cli/doctor.mjs +131 -213
- package/cli/install.mjs +33 -37
- package/cli/install.test.mjs +9 -9
- package/cli/provision-claude.mjs +893 -0
- package/cli/provision.mjs +330 -226
- package/cli/provision.test.mjs +102 -0
- package/cli/utils.mjs +72 -58
- package/config/AGENTS.md +28 -28
- package/config/agents/_shared/AGENT_BASELINE.md +104 -684
- package/config/skills/bizar/SKILL.md +197 -0
- package/config/skills/cubesandbox/SKILL.md +148 -0
- package/config/skills/harness-engineering/SKILL.md +142 -0
- package/install.sh +66 -44
- package/package.json +19 -11
- package/packages/sdk/ARCHITECTURE.md +40 -36
- package/packages/sdk/package-lock.json +32 -0
- package/packages/sdk/package.json +15 -5
- package/{plugins/bizar → packages/sdk}/src/dangerous-patterns.ts +6 -28
- package/packages/sdk/src/fingerprint.ts +0 -0
- package/packages/sdk/src/index.ts +38 -73
- package/packages/sdk/src/mcp/bin.ts +51 -0
- package/packages/sdk/src/mcp/server.ts +498 -0
- package/{plugins/bizar/src/memory-vault.ts → packages/sdk/src/memory/index.ts} +18 -21
- package/packages/sdk/tests/sdk.test.mjs +148 -0
- package/packages/sdk/vitest.config.ts +1 -1
- package/scripts/bh-full-e2e.mjs +166 -363
- package/scripts/check-deps.mjs +28 -46
- package/scripts/mirror-claude-md.sh +78 -0
- package/scripts/test-in-container.sh +157 -0
- 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/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 -344
- 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 -872
- 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/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 -162
- 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 -256
- 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/wait-for-feedback.test.ts +0 -390
- package/plugins/bizar/tests/update-deadlock.test.ts +0 -151
- package/plugins/bizar/tsconfig.json +0 -29
|
@@ -1,24 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* cli/commands/validate.mjs
|
|
3
3
|
*
|
|
4
|
-
* v6.
|
|
4
|
+
* v6.3.0 — `bizar validate` subcommand (Claude Code-native).
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
7
|
-
* battery of checks specific to a "flawless
|
|
6
|
+
* The Claude Code-aware health check. Extends `bizar doctor` with a
|
|
7
|
+
* longer battery of checks specific to a "flawless Claude Code
|
|
8
|
+
* integration":
|
|
8
9
|
*
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
15
|
-
* -
|
|
16
|
-
* -
|
|
17
|
-
*
|
|
18
|
-
*
|
|
10
|
+
* - `claude` CLI reachable + version
|
|
11
|
+
* - `~/.claude/settings.json` exists + parses
|
|
12
|
+
* - Bizar MCP server registered (mcpServers.bizar.*)
|
|
13
|
+
* - Bizar plugin entry in MCP config
|
|
14
|
+
* - 14 agent files in `~/.claude/agents/`
|
|
15
|
+
* - 14 skills mirrored from `config/skills/` → `~/.claude/skills/`
|
|
16
|
+
* - 7 rules mirrored from `config/rules/` → `~/.claude/rules/`
|
|
17
|
+
* - 4-5 hook adapter scripts in `~/.claude/hooks/`
|
|
18
|
+
* (PreToolUse / PostToolUse / SessionStart / UserPromptSubmit /
|
|
19
|
+
* SessionEnd, all chmod +x)
|
|
20
|
+
* - 14 slash commands in `~/.claude/commands/`
|
|
21
|
+
* (incl. /team /test /validate)
|
|
22
|
+
* - permissions.allow includes mcp__bizar__*
|
|
23
|
+
* - permissions.deny covers dangerous patterns
|
|
24
|
+
* - ~/.bizar_home/ exists (memory vault + loops dir)
|
|
19
25
|
*
|
|
20
26
|
* Exits non-zero if any check fails. Use `--json` for machine output.
|
|
21
|
-
* Use `--strict` to also fail on lenient checks
|
|
27
|
+
* Use `--strict` to also fail on lenient checks.
|
|
22
28
|
*/
|
|
23
29
|
import chalk from 'chalk';
|
|
24
30
|
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
@@ -28,14 +34,28 @@ import { homedir } from 'node:os';
|
|
|
28
34
|
|
|
29
35
|
const HOME = homedir();
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Resolve the Claude Code global config directory.
|
|
39
|
+
* Mirrors `cli/utils.mjs:claudeConfigDir()` → `~/.claude/`.
|
|
40
|
+
*/
|
|
41
|
+
function claudeDir() {
|
|
42
|
+
if (process.env.CLAUDE_CONFIG_DIR && process.env.CLAUDE_CONFIG_DIR.trim()) {
|
|
43
|
+
return process.env.CLAUDE_CONFIG_DIR.trim();
|
|
34
44
|
}
|
|
35
45
|
if (process.platform === 'win32') {
|
|
36
|
-
return
|
|
46
|
+
return process.env.APPDATA
|
|
47
|
+
? join(process.env.APPDATA, 'Claude')
|
|
48
|
+
: join(HOME, '.claude');
|
|
37
49
|
}
|
|
38
|
-
return join(HOME, '.
|
|
50
|
+
return join(HOME, '.claude');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Resolve the Bizar HOME directory (memory vault + loops).
|
|
55
|
+
*/
|
|
56
|
+
function bizarHome() {
|
|
57
|
+
return process.env.BIZAR_HOME
|
|
58
|
+
|| join(process.env.XDG_CONFIG_HOME || join(HOME, '.config'), 'bizar');
|
|
39
59
|
}
|
|
40
60
|
|
|
41
61
|
const REPO_ROOT = process.env.BIZAR_REPO_ROOT || process.cwd();
|
|
@@ -54,33 +74,18 @@ const REQUIRED_COMMANDS = [
|
|
|
54
74
|
'team.md', 'test.md', 'validate.md', 'setup-provider.md',
|
|
55
75
|
];
|
|
56
76
|
|
|
57
|
-
// v6.
|
|
58
|
-
// These are real Cline hooks (https://docs.cline.bot/customization/hooks).
|
|
59
|
-
// The previous v6.x hook contract was markdown behavioral files, which
|
|
60
|
-
// Cline silently ignored — leading to the "I see skills but no hooks"
|
|
61
|
-
// user report.
|
|
77
|
+
// v6.3.0 — Claude Code hook adapter scripts (executable, .mjs extension).
|
|
62
78
|
const REQUIRED_HOOKS = [
|
|
63
|
-
'
|
|
79
|
+
'pretooluse-editwrite.mjs',
|
|
80
|
+
'posttooluse-editwrite.mjs',
|
|
81
|
+
'sessionstart-prime.mjs',
|
|
82
|
+
'userpromptsubmit-tag.mjs',
|
|
83
|
+
'sessionend-record.mjs',
|
|
64
84
|
];
|
|
65
85
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// "OpenAI-compatible endpoint" use case. The harness warns about
|
|
70
|
-
// any providerId NOT in this set (since they fail in kanban mode).
|
|
71
|
-
const OPENAI_COMPATIBLE_BUILTIN_IDS = new Set([
|
|
72
|
-
'litellm', 'cline', 'ollama', 'lmstudio', 'huggingface',
|
|
73
|
-
// Plus the first-class providers (also OpenAI-compatible):
|
|
74
|
-
'openrouter', 'deepseek', 'xai', 'together', 'fireworks',
|
|
75
|
-
'groq', 'cerebras', 'sambanova', 'nebius', 'baseten',
|
|
76
|
-
'requesty', 'vercel-ai-gateway', 'v0', 'aihubmix', 'hicap',
|
|
77
|
-
'nousResearch', 'huawei-cloud-maas', 'qwen', 'qwen-code',
|
|
78
|
-
'doubao', 'zai', 'zai-coding-plan', 'moonshot', 'wandb',
|
|
79
|
-
'xiaomi', 'kilo', 'oca', 'asksage', 'sapaicore',
|
|
80
|
-
// Non-OpenAI-compatible (kept so we don't false-positive):
|
|
81
|
-
'anthropic', 'google', 'bedrock', 'vertex', 'gemini',
|
|
82
|
-
'openai', 'openai-native', 'openai-codex',
|
|
83
|
-
]);
|
|
86
|
+
// v6.3.0 — Claude Code-aware runtime deps. The Bizar SDK + the Claude
|
|
87
|
+
// Code agent SDK are the only required deps for the Bizar MCP server.
|
|
88
|
+
const REQUIRED_RUNTIME_DEPS = ['zod', '@anthropic-ai/claude-agent-sdk'];
|
|
84
89
|
|
|
85
90
|
function check(name, fn) {
|
|
86
91
|
return Promise.resolve()
|
|
@@ -89,8 +94,8 @@ function check(name, fn) {
|
|
|
89
94
|
.catch((err) => ({ name, ok: false, message: (err && err.message) ? err.message : String(err) }));
|
|
90
95
|
}
|
|
91
96
|
|
|
92
|
-
function
|
|
93
|
-
return join(
|
|
97
|
+
function settingsJsonPath() {
|
|
98
|
+
return join(claudeDir(), 'settings.json');
|
|
94
99
|
}
|
|
95
100
|
|
|
96
101
|
function readJsonSafe(file) {
|
|
@@ -102,97 +107,157 @@ function readJsonSafe(file) {
|
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
109
|
|
|
105
|
-
function pluginDepsDir() {
|
|
106
|
-
return join(clineDir(), 'plugins', 'bizar', 'node_modules');
|
|
107
|
-
}
|
|
108
|
-
|
|
109
110
|
const CHECKS = {
|
|
110
|
-
'
|
|
111
|
-
const r = spawnSync('
|
|
112
|
-
if (r.status !== 0) throw new Error(`
|
|
113
|
-
return (r.stdout || r.stderr || '').trim().split('\n')[0] || '
|
|
111
|
+
'claude-cli-reachable': async () => {
|
|
112
|
+
const r = spawnSync('claude', ['--version'], { encoding: 'utf8', timeout: 5000 });
|
|
113
|
+
if (r.status !== 0) throw new Error(`claude --version exited ${r.status}`);
|
|
114
|
+
return (r.stdout || r.stderr || '').trim().split('\n')[0] || 'claude available';
|
|
114
115
|
},
|
|
115
116
|
|
|
116
|
-
'
|
|
117
|
-
const p =
|
|
117
|
+
'claude-settings-exists': async () => {
|
|
118
|
+
const p = settingsJsonPath();
|
|
118
119
|
if (!existsSync(p)) throw new Error(`not found at ${p}`);
|
|
119
120
|
return p;
|
|
120
121
|
},
|
|
121
122
|
|
|
122
|
-
'
|
|
123
|
-
const cfg = readJsonSafe(
|
|
123
|
+
'claude-settings-parses': async () => {
|
|
124
|
+
const cfg = readJsonSafe(settingsJsonPath());
|
|
124
125
|
if (!cfg) throw new Error('invalid JSON');
|
|
125
|
-
return '
|
|
126
|
+
return '~/.claude/settings.json parses';
|
|
126
127
|
},
|
|
127
128
|
|
|
128
|
-
'
|
|
129
|
-
const cfg = readJsonSafe(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return false;
|
|
138
|
-
});
|
|
139
|
-
if (!hasBizar) throw new Error('bizar plugin entry not in cline.json');
|
|
140
|
-
return 'bizar plugin registered';
|
|
129
|
+
'claude-settings-schema': async () => {
|
|
130
|
+
const cfg = readJsonSafe(settingsJsonPath());
|
|
131
|
+
if (!cfg?.$schema) {
|
|
132
|
+
return 'no $schema declared (advisory only)';
|
|
133
|
+
}
|
|
134
|
+
if (!cfg.$schema.includes('claude-code-settings')) {
|
|
135
|
+
throw new Error(`unexpected $schema: ${cfg.$schema}`);
|
|
136
|
+
}
|
|
137
|
+
return `$schema = ${cfg.$schema}`;
|
|
141
138
|
},
|
|
142
139
|
|
|
143
|
-
'
|
|
144
|
-
const cfg = readJsonSafe(
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
let entryPath = null;
|
|
149
|
-
if (Array.isArray(p) && typeof p[0] === 'string') entryPath = p[0];
|
|
150
|
-
else if (p && typeof p === 'object' && p.path) entryPath = p.path;
|
|
151
|
-
if (!entryPath) continue;
|
|
152
|
-
const isAbs = entryPath.startsWith('/') || /^[a-z]:[\\/]/i.test(entryPath);
|
|
153
|
-
const resolved = isAbs ? entryPath : join(clineDir(), entryPath);
|
|
154
|
-
lastChecked = resolved;
|
|
155
|
-
if (!existsSync(resolved)) {
|
|
156
|
-
throw new Error(`plugin path does not exist: ${resolved}`);
|
|
157
|
-
}
|
|
140
|
+
'mcp-server-bizar-registered': async () => {
|
|
141
|
+
const cfg = readJsonSafe(settingsJsonPath());
|
|
142
|
+
const servers = cfg?.mcpServers;
|
|
143
|
+
if (!servers || !servers.bizar) {
|
|
144
|
+
throw new Error(`mcpServers.bizar missing in ${settingsJsonPath()} — run \`bizar install\``);
|
|
158
145
|
}
|
|
159
|
-
|
|
146
|
+
const s = servers.bizar;
|
|
147
|
+
return `bizar MCP server registered: command=${s.command || '(unset)'}, type=${s.type || 'stdio'}`;
|
|
160
148
|
},
|
|
161
149
|
|
|
162
|
-
'
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
150
|
+
'mcp-server-bizar-command': async () => {
|
|
151
|
+
const cfg = readJsonSafe(settingsJsonPath());
|
|
152
|
+
const s = cfg?.mcpServers?.bizar;
|
|
153
|
+
if (!s) throw new Error('bizar MCP server not registered');
|
|
154
|
+
const args = Array.isArray(s.args) ? s.args.join(' ') : '';
|
|
155
|
+
const expected = 'npx -y @polderlabs/bizar-sdk mcp';
|
|
156
|
+
const actual = `${s.command || ''} ${args}`.trim();
|
|
157
|
+
if (!actual.includes('@polderlabs/bizar-sdk')) {
|
|
158
|
+
throw new Error(`MCP server command does not reference @polderlabs/bizar-sdk: ${actual}`);
|
|
166
159
|
}
|
|
167
|
-
|
|
160
|
+
return `MCP command OK: ${actual}`;
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
'permissions-allow-bizar': async () => {
|
|
164
|
+
const cfg = readJsonSafe(settingsJsonPath());
|
|
165
|
+
const allow = cfg?.permissions?.allow || [];
|
|
166
|
+
const hasBizar = allow.some((p) => typeof p === 'string' && p.startsWith('mcp__bizar__'));
|
|
167
|
+
if (!hasBizar) {
|
|
168
|
+
throw new Error('permissions.allow does not include any mcp__bizar__* entries');
|
|
169
|
+
}
|
|
170
|
+
return `${allow.filter((p) => p.startsWith('mcp__bizar__')).length} mcp__bizar__* allowed`;
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
'permissions-deny-dangerous': async () => {
|
|
174
|
+
const cfg = readJsonSafe(settingsJsonPath());
|
|
175
|
+
const deny = cfg?.permissions?.deny || [];
|
|
176
|
+
const required = [
|
|
177
|
+
'Read(./.env)',
|
|
178
|
+
'Bash(rm -rf /)',
|
|
179
|
+
'Bash(sudo *)',
|
|
180
|
+
'Write(./node_modules/**)',
|
|
181
|
+
'Write(./package-lock.json)',
|
|
182
|
+
];
|
|
183
|
+
const missing = required.filter((r) => !deny.includes(r));
|
|
168
184
|
if (missing.length > 0) {
|
|
169
|
-
|
|
185
|
+
return `missing ${missing.length} deny pattern(s) (advisory): ${missing.join(', ')}`;
|
|
186
|
+
}
|
|
187
|
+
return `${deny.length} deny pattern(s) — all 5 required present`;
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
'hooks-pretooluse-wired': async () => {
|
|
191
|
+
const cfg = readJsonSafe(settingsJsonPath());
|
|
192
|
+
const arr = cfg?.hooks?.PreToolUse;
|
|
193
|
+
if (!Array.isArray(arr) || arr.length === 0) {
|
|
194
|
+
throw new Error('no PreToolUse hooks wired in settings.json');
|
|
195
|
+
}
|
|
196
|
+
const m = arr.find((h) => h.matcher && h.matcher.includes('Write') && h.matcher.includes('Edit'));
|
|
197
|
+
if (!m) throw new Error('PreToolUse matcher missing Write|Edit pattern');
|
|
198
|
+
return `${arr.length} PreToolUse hook(s) wired (matcher: ${m.matcher})`;
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
'hooks-posttooluse-wired': async () => {
|
|
202
|
+
const cfg = readJsonSafe(settingsJsonPath());
|
|
203
|
+
const arr = cfg?.hooks?.PostToolUse;
|
|
204
|
+
if (!Array.isArray(arr) || arr.length === 0) {
|
|
205
|
+
throw new Error('no PostToolUse hooks wired in settings.json');
|
|
206
|
+
}
|
|
207
|
+
return `${arr.length} PostToolUse hook(s) wired`;
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
'hooks-sessionstart-wired': async () => {
|
|
211
|
+
const cfg = readJsonSafe(settingsJsonPath());
|
|
212
|
+
const arr = cfg?.hooks?.SessionStart;
|
|
213
|
+
if (!Array.isArray(arr) || arr.length === 0) {
|
|
214
|
+
throw new Error('no SessionStart hooks wired in settings.json');
|
|
215
|
+
}
|
|
216
|
+
return `${arr.length} SessionStart hook(s) wired`;
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
'hooks-userpromptsubmit-wired': async () => {
|
|
220
|
+
const cfg = readJsonSafe(settingsJsonPath());
|
|
221
|
+
const arr = cfg?.hooks?.UserPromptSubmit;
|
|
222
|
+
if (!Array.isArray(arr) || arr.length === 0) {
|
|
223
|
+
throw new Error('no UserPromptSubmit hooks wired in settings.json');
|
|
170
224
|
}
|
|
171
|
-
return
|
|
225
|
+
return `${arr.length} UserPromptSubmit hook(s) wired`;
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
'hooks-sessionend-wired': async () => {
|
|
229
|
+
const cfg = readJsonSafe(settingsJsonPath());
|
|
230
|
+
const arr = cfg?.hooks?.SessionEnd;
|
|
231
|
+
if (!Array.isArray(arr) || arr.length === 0) {
|
|
232
|
+
return 'no SessionEnd hook wired (advisory)';
|
|
233
|
+
}
|
|
234
|
+
return `${arr.length} SessionEnd hook(s) wired`;
|
|
172
235
|
},
|
|
173
236
|
|
|
174
237
|
'agent-files-installed': async () => {
|
|
175
|
-
const dir = join(
|
|
238
|
+
const dir = join(claudeDir(), 'agents');
|
|
176
239
|
if (!existsSync(dir)) throw new Error(`agents dir missing: ${dir}`);
|
|
177
240
|
const missing = REQUIRED_AGENTS.filter((f) => !existsSync(join(dir, f)));
|
|
178
241
|
if (missing.length > 0) throw new Error(`missing: ${missing.join(', ')}`);
|
|
179
|
-
return `all ${REQUIRED_AGENTS.length} agents present`;
|
|
242
|
+
return `all ${REQUIRED_AGENTS.length} agents present in ${dir}`;
|
|
180
243
|
},
|
|
181
244
|
|
|
182
|
-
'agent-
|
|
183
|
-
//
|
|
184
|
-
//
|
|
185
|
-
const dir = join(
|
|
245
|
+
'agent-frontmatter-format': async () => {
|
|
246
|
+
// Claude Code reads agents via `.md` files with YAML frontmatter.
|
|
247
|
+
// Spot-check that at least the odin.md agent has frontmatter.
|
|
248
|
+
const dir = join(claudeDir(), 'agents');
|
|
186
249
|
if (!existsSync(dir)) throw new Error('agents dir missing');
|
|
187
|
-
const
|
|
188
|
-
if (
|
|
189
|
-
|
|
250
|
+
const odin = join(dir, 'odin.md');
|
|
251
|
+
if (!existsSync(odin)) throw new Error('odin.md missing');
|
|
252
|
+
const text = readFileSync(odin, 'utf8');
|
|
253
|
+
if (!text.startsWith('---')) {
|
|
254
|
+
throw new Error('odin.md has no YAML frontmatter — Claude Code may not load it');
|
|
190
255
|
}
|
|
191
|
-
return
|
|
256
|
+
return 'odin.md has YAML frontmatter';
|
|
192
257
|
},
|
|
193
258
|
|
|
194
259
|
'slash-commands-installed': async () => {
|
|
195
|
-
const dir = join(
|
|
260
|
+
const dir = join(claudeDir(), 'commands');
|
|
196
261
|
if (!existsSync(dir)) throw new Error(`commands dir missing: ${dir}`);
|
|
197
262
|
const missing = REQUIRED_COMMANDS.filter((f) => !existsSync(join(dir, f)));
|
|
198
263
|
if (missing.length > 0) {
|
|
@@ -202,26 +267,25 @@ const CHECKS = {
|
|
|
202
267
|
},
|
|
203
268
|
|
|
204
269
|
'team-command-present': async () => {
|
|
205
|
-
|
|
206
|
-
const team = join(clineDir(), 'commands', 'team.md');
|
|
270
|
+
const team = join(claudeDir(), 'commands', 'team.md');
|
|
207
271
|
if (!existsSync(team)) throw new Error(`${team} missing — run \`bizar update\``);
|
|
208
272
|
return '/team command installed';
|
|
209
273
|
},
|
|
210
274
|
|
|
211
275
|
'test-command-present': async () => {
|
|
212
|
-
const testCmd = join(
|
|
276
|
+
const testCmd = join(claudeDir(), 'commands', 'test.md');
|
|
213
277
|
if (!existsSync(testCmd)) throw new Error(`${testCmd} missing — run \`bizar update\``);
|
|
214
278
|
return '/test command installed';
|
|
215
279
|
},
|
|
216
280
|
|
|
217
281
|
'validate-command-present': async () => {
|
|
218
|
-
const v = join(
|
|
282
|
+
const v = join(claudeDir(), 'commands', 'validate.md');
|
|
219
283
|
if (!existsSync(v)) throw new Error(`${v} missing — run \`bizar update\``);
|
|
220
284
|
return '/validate command installed';
|
|
221
285
|
},
|
|
222
286
|
|
|
223
287
|
'skills-installed': async () => {
|
|
224
|
-
const dir = join(
|
|
288
|
+
const dir = join(claudeDir(), 'skills');
|
|
225
289
|
if (!existsSync(dir)) throw new Error(`skills dir missing: ${dir} — run \`bizar update\``);
|
|
226
290
|
const entries = readdirSync(dir, { withFileTypes: true });
|
|
227
291
|
const skills = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
@@ -230,7 +294,7 @@ const CHECKS = {
|
|
|
230
294
|
},
|
|
231
295
|
|
|
232
296
|
'rules-installed': async () => {
|
|
233
|
-
const dir = join(
|
|
297
|
+
const dir = join(claudeDir(), 'rules');
|
|
234
298
|
if (!existsSync(dir)) throw new Error(`rules dir missing: ${dir} — run \`bizar update\``);
|
|
235
299
|
const entries = readdirSync(dir).filter((f) => f.endsWith('.md') || f.endsWith('.txt'));
|
|
236
300
|
if (entries.length === 0) throw new Error('no rules installed — run `bizar update`');
|
|
@@ -238,17 +302,15 @@ const CHECKS = {
|
|
|
238
302
|
},
|
|
239
303
|
|
|
240
304
|
'hooks-installed': async () => {
|
|
241
|
-
const dir = join(
|
|
305
|
+
const dir = join(claudeDir(), 'hooks');
|
|
242
306
|
if (!existsSync(dir)) throw new Error(`hooks dir missing: ${dir} — run \`bizar update\``);
|
|
243
307
|
const missing = REQUIRED_HOOKS.filter((f) => !existsSync(join(dir, f)));
|
|
244
308
|
if (missing.length > 0) {
|
|
245
309
|
throw new Error(`missing: ${missing.join(', ')} — run \`bizar update\``);
|
|
246
310
|
}
|
|
247
|
-
// Verify hooks are executable
|
|
248
|
-
//
|
|
249
|
-
// no-op so skip the check there.
|
|
311
|
+
// Verify hooks are executable. On Windows, chmod is a no-op so
|
|
312
|
+
// skip the check there.
|
|
250
313
|
if (process.platform !== 'win32') {
|
|
251
|
-
const { statSync } = await import('node:fs');
|
|
252
314
|
const nonExec = [];
|
|
253
315
|
for (const f of REQUIRED_HOOKS) {
|
|
254
316
|
try {
|
|
@@ -260,89 +322,49 @@ const CHECKS = {
|
|
|
260
322
|
}
|
|
261
323
|
}
|
|
262
324
|
if (nonExec.length > 0) {
|
|
263
|
-
throw new Error(`hooks not executable: ${nonExec.join(', ')} — run \`chmod +x ~/.
|
|
325
|
+
throw new Error(`hooks not executable: ${nonExec.join(', ')} — run \`chmod +x ~/.claude/hooks/*\``);
|
|
264
326
|
}
|
|
265
327
|
}
|
|
266
|
-
return `all ${REQUIRED_HOOKS.length}
|
|
328
|
+
return `all ${REQUIRED_HOOKS.length} Claude Code hook file(s) executable in ${dir}`;
|
|
267
329
|
},
|
|
268
330
|
|
|
269
|
-
'
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
// ~/Documents/Cline/Hooks/ for max compatibility).
|
|
274
|
-
const canonical = join(homedir(), 'Documents', 'Cline', 'Hooks');
|
|
275
|
-
if (!existsSync(canonical)) {
|
|
276
|
-
return `optional: ${canonical} does not exist yet — \`bizar install\` creates it`;
|
|
277
|
-
}
|
|
278
|
-
const missing = REQUIRED_HOOKS.filter((f) => !existsSync(join(canonical, f)));
|
|
279
|
-
if (missing.length > 0) {
|
|
280
|
-
return `optional: ${missing.length} hook(s) missing in ${canonical} — re-run \`bizar install\``;
|
|
331
|
+
'bizar-home-exists': async () => {
|
|
332
|
+
const h = bizarHome();
|
|
333
|
+
if (!existsSync(h)) {
|
|
334
|
+
throw new Error(`BIZAR_HOME missing at ${h} — run \`bizar install\``);
|
|
281
335
|
}
|
|
282
|
-
return `
|
|
336
|
+
return `BIZAR_HOME = ${h}`;
|
|
283
337
|
},
|
|
284
338
|
|
|
285
|
-
'
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
// what's in cline.json so the user can see the current state.
|
|
290
|
-
const cfg = readJsonSafe(clineJsonPath());
|
|
291
|
-
if (!cfg?.provider || Object.keys(cfg.provider).length === 0) {
|
|
292
|
-
return 'no provider configured — user must add one. `bizar install` no longer touches provider config (v6.2.2+).';
|
|
339
|
+
'bizar-memory-vault-exists': async () => {
|
|
340
|
+
const vault = join(bizarHome(), 'memory-vault');
|
|
341
|
+
if (!existsSync(vault)) {
|
|
342
|
+
throw new Error(`memory vault missing at ${vault} — run \`bizar install\``);
|
|
293
343
|
}
|
|
294
|
-
|
|
295
|
-
const summary = names.map((n) => {
|
|
296
|
-
const p = cfg.provider[n];
|
|
297
|
-
const url = p?.baseUrl || p?.options?.baseURL || '(no baseUrl)';
|
|
298
|
-
const modelCount = Object.keys(p?.models || {}).length;
|
|
299
|
-
return `${n} (${modelCount} models, baseUrl=${url})`;
|
|
300
|
-
});
|
|
301
|
-
return `user-configured providers: ${summary.join('; ')}`;
|
|
344
|
+
return `memory vault = ${vault}`;
|
|
302
345
|
},
|
|
303
346
|
|
|
304
|
-
'
|
|
305
|
-
// v6.
|
|
306
|
-
// `~/.
|
|
307
|
-
//
|
|
308
|
-
//
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const file = join(homedir(), '.cline', 'data', 'settings', 'providers.json');
|
|
317
|
-
if (!existsSync(file)) {
|
|
318
|
-
return 'no settings file at ~/.cline/data/settings/providers.json — run `bizar setup-provider` to add one';
|
|
319
|
-
}
|
|
320
|
-
const settings = readJsonSafe(file);
|
|
321
|
-
if (!settings || !settings.providers) {
|
|
322
|
-
return 'settings file is empty or invalid — run `bizar setup-provider`';
|
|
323
|
-
}
|
|
324
|
-
const names = Object.keys(settings.providers);
|
|
325
|
-
if (names.length === 0) {
|
|
326
|
-
throw new Error('no providers configured in Cline settings — run `bizar setup-provider`');
|
|
327
|
-
}
|
|
328
|
-
const issues = [];
|
|
329
|
-
if (names.includes('openai-compatible')) {
|
|
330
|
-
issues.push(`legacy 'openai-compatible' providerId present (broken in kanban mode) — run \`bizar setup-provider\` to auto-migrate to 'litellm'`);
|
|
331
|
-
}
|
|
332
|
-
// Check for any providerId that's not in Cline's built-in catalog.
|
|
333
|
-
for (const n of names) {
|
|
334
|
-
if (n === 'openai-compatible') continue; // handled above
|
|
335
|
-
if (!OPENAI_COMPATIBLE_BUILTIN_IDS.has(n)) {
|
|
336
|
-
issues.push(`'${n}' providerId is NOT in Cline's built-in catalog (likely broken in kanban mode)`);
|
|
347
|
+
'plugin-runtime-deps': async () => {
|
|
348
|
+
// v6.3.0 — for Claude Code, the runtime deps live in the
|
|
349
|
+
// Bizar SDK's node_modules, not in a `~/.claude/plugins/bizar/`
|
|
350
|
+
// dir. We probe the SDK install via npm root -g + the
|
|
351
|
+
// bizar-sdk entry. This is best-effort.
|
|
352
|
+
try {
|
|
353
|
+
const out = spawnSync('npm', ['root', '-g'], { encoding: 'utf8', timeout: 5000 }).stdout || '';
|
|
354
|
+
const root = out.trim();
|
|
355
|
+
if (!root) throw new Error('npm root -g returned empty');
|
|
356
|
+
const sdkPath = join(root, '@polderlabs', 'bizar-sdk');
|
|
357
|
+
if (!existsSync(sdkPath)) {
|
|
358
|
+
return `Bizar SDK not found at ${sdkPath} — install via npm install -g @polderlabs/bizar-sdk (advisory)`;
|
|
337
359
|
}
|
|
360
|
+
const missing = REQUIRED_RUNTIME_DEPS.filter((d) => !existsSync(join(sdkPath, 'node_modules', d)));
|
|
361
|
+
if (missing.length > 0) {
|
|
362
|
+
return `missing runtime deps in SDK: ${missing.join(', ')} (advisory)`;
|
|
363
|
+
}
|
|
364
|
+
return `runtime deps present (${REQUIRED_RUNTIME_DEPS.join(', ')})`;
|
|
365
|
+
} catch (err) {
|
|
366
|
+
return `could not probe SDK install: ${err.message} (advisory)`;
|
|
338
367
|
}
|
|
339
|
-
const lastUsed = settings.lastUsedProvider || '(none)';
|
|
340
|
-
if (issues.length > 0) {
|
|
341
|
-
// Throw so the ⚠ marker shows up; the check is in LENIENT_CHECKS
|
|
342
|
-
// so this won't cause `bizar validate` to exit non-zero.
|
|
343
|
-
throw new Error(`WARN: ${issues.join('; ')}. lastUsedProvider=${lastUsed} (${names.join(', ')})`);
|
|
344
|
-
}
|
|
345
|
-
return `lastUsedProvider=${lastUsed}; providers: ${names.join(', ')}`;
|
|
346
368
|
},
|
|
347
369
|
|
|
348
370
|
'9router-reachable': async () => {
|
|
@@ -362,92 +384,33 @@ const CHECKS = {
|
|
|
362
384
|
}
|
|
363
385
|
},
|
|
364
386
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
'mistake-limit-floor': async () => {
|
|
370
|
-
const MIN = 10;
|
|
371
|
-
const cfg = readJsonSafe(clineJsonPath());
|
|
372
|
-
if (!cfg?.plugin || !Array.isArray(cfg.plugin)) {
|
|
373
|
-
return 'no plugin entries in cline.json — skip mistake-limit check';
|
|
374
|
-
}
|
|
375
|
-
const bizarEntry = cfg.plugin.find((p) => Array.isArray(p) && p[0] && p[0].includes('plugins/bizar'));
|
|
376
|
-
if (!bizarEntry) {
|
|
377
|
-
return 'Bizar plugin not registered — skip mistake-limit check';
|
|
387
|
+
'claude-md-mirrored': async () => {
|
|
388
|
+
const f = join(claudeDir(), 'CLAUDE.md');
|
|
389
|
+
if (!existsSync(f)) {
|
|
390
|
+
throw new Error(`${f} missing — run \`bizar install\` to mirror AGENTS.md`);
|
|
378
391
|
}
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
return `clineruntimeMaxConsecutiveMistakes=${raw ?? 'default 10'} (≥ ${MIN}) — OK`;
|
|
383
|
-
}
|
|
384
|
-
throw new Error(
|
|
385
|
-
`clineruntimeMaxConsecutiveMistakes=${raw} is BELOW the recommended minimum (${MIN}). ` +
|
|
386
|
-
`Cline's default of 3 aborts the session on the 3rd tool mistake. ` +
|
|
387
|
-
`Edit ~/.cline/cline.json plugin[1].clineruntimeMaxConsecutiveMistakes to ${MIN}, or run ` +
|
|
388
|
-
`\`bizar install\` to reset to defaults. (See _shared/CLINE_TOOLS.md for the top-5 mistakes.)`,
|
|
389
|
-
);
|
|
390
|
-
},
|
|
391
|
-
|
|
392
|
-
'default-agent-set': async () => {
|
|
393
|
-
const cfg = readJsonSafe(clineJsonPath());
|
|
394
|
-
if (!cfg?.default_agent) {
|
|
395
|
-
throw new Error('no default_agent in cline.json — should be "odin"');
|
|
396
|
-
}
|
|
397
|
-
return `default_agent=${cfg.default_agent}`;
|
|
398
|
-
},
|
|
399
|
-
|
|
400
|
-
'instructions-loaded': async () => {
|
|
401
|
-
const cfg = readJsonSafe(clineJsonPath());
|
|
402
|
-
if (!cfg?.instructions || (Array.isArray(cfg.instructions) && cfg.instructions.length === 0)) {
|
|
403
|
-
throw new Error('no instructions[] in cline.json — Cline won\'t load the tools reference');
|
|
404
|
-
}
|
|
405
|
-
const ins = Array.isArray(cfg.instructions) ? cfg.instructions : [cfg.instructions];
|
|
406
|
-
return `${ins.length} instruction file(s) referenced`;
|
|
407
|
-
},
|
|
408
|
-
|
|
409
|
-
'plugin-index-loadable': async () => {
|
|
410
|
-
// Spot-check that the deployed plugin's index.ts is on disk and looks
|
|
411
|
-
// like a Cline plugin (has the `setup` function + registerTool pattern).
|
|
412
|
-
const idx = join(clineDir(), 'plugins', 'bizar', 'index.ts');
|
|
413
|
-
if (!existsSync(idx)) {
|
|
414
|
-
throw new Error(`${idx} missing — plugin not copied`);
|
|
415
|
-
}
|
|
416
|
-
const stat = statSync(idx);
|
|
417
|
-
if (stat.size < 100) {
|
|
418
|
-
throw new Error(`${idx} is suspiciously small (${stat.size} bytes)`);
|
|
419
|
-
}
|
|
420
|
-
return `plugin index.ts: ${stat.size} bytes`;
|
|
421
|
-
},
|
|
422
|
-
|
|
423
|
-
'enable-agent-teams': async () => {
|
|
424
|
-
// The /team command depends on `enableAgentTeams: true` in
|
|
425
|
-
// plugins/bizar/src/clineruntime.ts. Static check by reading the
|
|
426
|
-
// source file from the deployed plugin dir.
|
|
427
|
-
const rt = join(clineDir(), 'plugins', 'bizar', 'src', 'clineruntime.ts');
|
|
428
|
-
if (!existsSync(rt)) {
|
|
429
|
-
// Source-only install (npm bundled): can't check here, skip leniently.
|
|
430
|
-
return 'skipped (bundled install)';
|
|
431
|
-
}
|
|
432
|
-
const text = readFileSync(rt, 'utf8');
|
|
433
|
-
if (!/enableAgentTeams:\s*true/.test(text)) {
|
|
434
|
-
throw new Error('enableAgentTeams is not true in clineruntime.ts — /team will not work');
|
|
435
|
-
}
|
|
436
|
-
return 'enableAgentTeams: true in clineruntime.ts';
|
|
392
|
+
const stat = statSync(f);
|
|
393
|
+
if (stat.size < 200) throw new Error(`${f} is suspiciously small (${stat.size} bytes)`);
|
|
394
|
+
return `CLAUDE.md mirrored (${stat.size} bytes)`;
|
|
437
395
|
},
|
|
438
396
|
};
|
|
439
397
|
|
|
440
398
|
const CHECK_ORDER = [
|
|
441
|
-
'
|
|
442
|
-
'
|
|
443
|
-
'
|
|
444
|
-
'
|
|
445
|
-
'
|
|
446
|
-
'
|
|
447
|
-
'
|
|
448
|
-
'
|
|
399
|
+
'claude-cli-reachable',
|
|
400
|
+
'claude-settings-exists',
|
|
401
|
+
'claude-settings-parses',
|
|
402
|
+
'claude-settings-schema',
|
|
403
|
+
'mcp-server-bizar-registered',
|
|
404
|
+
'mcp-server-bizar-command',
|
|
405
|
+
'permissions-allow-bizar',
|
|
406
|
+
'permissions-deny-dangerous',
|
|
407
|
+
'hooks-pretooluse-wired',
|
|
408
|
+
'hooks-posttooluse-wired',
|
|
409
|
+
'hooks-sessionstart-wired',
|
|
410
|
+
'hooks-userpromptsubmit-wired',
|
|
411
|
+
'hooks-sessionend-wired',
|
|
449
412
|
'agent-files-installed',
|
|
450
|
-
'agent-
|
|
413
|
+
'agent-frontmatter-format',
|
|
451
414
|
'slash-commands-installed',
|
|
452
415
|
'team-command-present',
|
|
453
416
|
'test-command-present',
|
|
@@ -455,20 +418,20 @@ const CHECK_ORDER = [
|
|
|
455
418
|
'skills-installed',
|
|
456
419
|
'rules-installed',
|
|
457
420
|
'hooks-installed',
|
|
458
|
-
'
|
|
459
|
-
'
|
|
460
|
-
'
|
|
461
|
-
'
|
|
462
|
-
'cline-settings-provider',
|
|
421
|
+
'bizar-home-exists',
|
|
422
|
+
'bizar-memory-vault-exists',
|
|
423
|
+
'claude-md-mirrored',
|
|
424
|
+
'plugin-runtime-deps',
|
|
463
425
|
'9router-reachable',
|
|
464
|
-
'mistake-limit-floor',
|
|
465
426
|
];
|
|
466
427
|
|
|
467
428
|
const LENIENT_CHECKS = new Set([
|
|
429
|
+
'claude-cli-reachable', // Claude Code CLI is normally on $PATH only on dev hosts; CI containers without it shouldn't fail validation
|
|
468
430
|
'9router-reachable',
|
|
469
|
-
'
|
|
470
|
-
'
|
|
471
|
-
'
|
|
431
|
+
'plugin-runtime-deps', // best-effort probe via `npm root -g`
|
|
432
|
+
'permissions-deny-dangerous', // advisory — user may have intentionally customized
|
|
433
|
+
'hooks-sessionend-wired', // advisory — SessionEnd is optional
|
|
434
|
+
'claude-settings-schema', // advisory — schema field is documentation
|
|
472
435
|
]);
|
|
473
436
|
|
|
474
437
|
export function showValidateHelp() {
|
|
@@ -484,19 +447,20 @@ export function showValidateHelp() {
|
|
|
484
447
|
|
|
485
448
|
Description:
|
|
486
449
|
A 21-point health check that confirms the Bizar install is fully
|
|
487
|
-
integrated with
|
|
488
|
-
•
|
|
489
|
-
•
|
|
490
|
-
•
|
|
491
|
-
•
|
|
492
|
-
•
|
|
493
|
-
|
|
450
|
+
integrated with Claude Code:
|
|
451
|
+
• claude CLI reachable + version
|
|
452
|
+
• ~/.claude/settings.json parses + Bizar MCP server registered
|
|
453
|
+
• permissions.allow includes mcp__bizar__*
|
|
454
|
+
• permissions.deny covers dangerous patterns
|
|
455
|
+
• hooks (PreToolUse / PostToolUse / SessionStart / UserPromptSubmit
|
|
456
|
+
/ SessionEnd) wired in settings.json
|
|
457
|
+
• all 14 agent files installed with Claude Code frontmatter
|
|
458
|
+
• all 14 slash commands (/audit, /bizar, /explain, /init, /learn,
|
|
494
459
|
/plan, /plow-through, /pr-review, /tailscale-serve,
|
|
495
460
|
/visual-plan, /team, /test, /validate)
|
|
496
|
-
• all skills / rules / hooks mirrored to ~/.
|
|
497
|
-
•
|
|
461
|
+
• all skills / rules / hooks mirrored to ~/.claude/
|
|
462
|
+
• ~/.bizar_home/ + memory vault ready
|
|
498
463
|
• 9Router gateway reachable (lenient unless --strict)
|
|
499
|
-
• default_agent + instructions[] in cline.json
|
|
500
464
|
|
|
501
465
|
Exit codes:
|
|
502
466
|
0 All checks passed (or only lenient ones failed)
|
|
@@ -505,7 +469,7 @@ export function showValidateHelp() {
|
|
|
505
469
|
|
|
506
470
|
Related:
|
|
507
471
|
bizar doctor Simpler 8-point check (legacy)
|
|
508
|
-
bizar update Refresh the install (re-runs
|
|
472
|
+
bizar update Refresh the install (re-runs the provisioner)
|
|
509
473
|
bizar repair Fix common issues (stale symlinks, version drift)
|
|
510
474
|
`);
|
|
511
475
|
}
|
|
@@ -541,7 +505,7 @@ export async function runValidate(opts = {}) {
|
|
|
541
505
|
for (const r of results) {
|
|
542
506
|
const isLenient = LENIENT_CHECKS.has(r.name);
|
|
543
507
|
const marker = r.ok ? chalk.green('✓') : (isLenient ? chalk.yellow('⚠') : chalk.red('✗'));
|
|
544
|
-
const label = r.name.padEnd(
|
|
508
|
+
const label = r.name.padEnd(32);
|
|
545
509
|
const msg = r.ok ? chalk.dim(` ${r.message}`) : (isLenient ? chalk.yellow(` ${r.message}`) : chalk.red(` ${r.message}`));
|
|
546
510
|
console.log(` ${marker} ${label}${msg}`);
|
|
547
511
|
}
|