@polderlabs/bizar 6.2.5 → 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 +17 -18
- package/cli/commands/claude-cmd.mjs +348 -0
- package/cli/commands/install.mjs +12 -11
- package/cli/commands/validate.mjs +252 -325
- 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 +224 -227
- package/cli/utils.mjs +72 -58
- package/config/AGENTS.md +28 -28
- 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 +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/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
|
@@ -1,379 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* cli/commands/validate.test.mjs
|
|
3
|
-
*
|
|
4
|
-
* v6.2.0 — Unit tests for the new `bizar validate` subcommand.
|
|
5
|
-
*
|
|
6
|
-
* We exercise `runValidate()` directly. CLINE_DIR is mocked via
|
|
7
|
-
* `process.env.CLINE_DIR`; a minimal-but-complete Bizar install is
|
|
8
|
-
* staged inside a tmpdir. We then progressively delete files to
|
|
9
|
-
* verify each check fails with a sensible message.
|
|
10
|
-
*/
|
|
11
|
-
import { test, describe, beforeEach, afterEach } from 'node:test';
|
|
12
|
-
import assert from 'node:assert/strict';
|
|
13
|
-
import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, readFileSync, chmodSync } from 'node:fs';
|
|
14
|
-
import { tmpdir } from 'node:os';
|
|
15
|
-
import { join } from 'node:path';
|
|
16
|
-
import { Writable } from 'node:stream';
|
|
17
|
-
|
|
18
|
-
const { runValidate } = await import('./validate.mjs');
|
|
19
|
-
|
|
20
|
-
const ORIG_CLINE_DIR = process.env.CLINE_DIR;
|
|
21
|
-
const ORIG_HOME = process.env.HOME;
|
|
22
|
-
|
|
23
|
-
let workDir;
|
|
24
|
-
|
|
25
|
-
function freshWorkDir() {
|
|
26
|
-
const root = mkdtempSync(join(tmpdir(), 'bizar-validate-'));
|
|
27
|
-
process.env.CLINE_DIR = root;
|
|
28
|
-
// v6.2.5 — also redirect HOME so the skill-marketplace-registered
|
|
29
|
-
// check (which reads ~/.agents/.skill-lock.json) points at the
|
|
30
|
-
// test's tmpdir and doesn't fail because the user's real $HOME
|
|
31
|
-
// doesn't happen to have one.
|
|
32
|
-
process.env.HOME = root;
|
|
33
|
-
return root;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function makeFakeClineInstall(root) {
|
|
37
|
-
writeFileSync(
|
|
38
|
-
join(root, 'cline.json'),
|
|
39
|
-
JSON.stringify({
|
|
40
|
-
$schema: 'https://docs.cline.bot/config.json',
|
|
41
|
-
plugin: [[
|
|
42
|
-
'./plugins/bizar',
|
|
43
|
-
{ loopThresholdWarn: 5, loopThresholdEscalate: 8, loopThresholdBlock: 12, loopWindowSize: 10 },
|
|
44
|
-
]],
|
|
45
|
-
default_agent: 'odin',
|
|
46
|
-
permission: 'allow',
|
|
47
|
-
snapshot: false,
|
|
48
|
-
instructions: ['.cline/instructions/bizar-tools.md'],
|
|
49
|
-
provider: {
|
|
50
|
-
'9router': {
|
|
51
|
-
baseUrl: 'http://localhost:20128/v1',
|
|
52
|
-
apiKey: '${env:NINEROUTER_KEY}',
|
|
53
|
-
models: { 'minimax/MiniMax-M3': { reasoning: true } },
|
|
54
|
-
},
|
|
55
|
-
minimax: { models: {} },
|
|
56
|
-
},
|
|
57
|
-
}, null, 2),
|
|
58
|
-
);
|
|
59
|
-
const agentsDir = join(root, 'agents');
|
|
60
|
-
mkdirSync(agentsDir, { recursive: true });
|
|
61
|
-
for (const f of [
|
|
62
|
-
'odin.md', 'vor.md', 'frigg.md', 'quick.md',
|
|
63
|
-
'mimir.md', 'heimdall.md', 'hermod.md', 'thor.md', 'baldr.md',
|
|
64
|
-
'tyr.md', 'vidarr.md', 'forseti.md',
|
|
65
|
-
'semble-search.md', 'agent-browser.md',
|
|
66
|
-
]) {
|
|
67
|
-
writeFileSync(join(agentsDir, f), '# fake agent');
|
|
68
|
-
}
|
|
69
|
-
writeFileSync(join(agentsDir, 'odin.yaml'), 'name: odin\ndescription: odin\n');
|
|
70
|
-
const cmdsDir = join(root, 'commands');
|
|
71
|
-
mkdirSync(cmdsDir, { recursive: true });
|
|
72
|
-
for (const f of [
|
|
73
|
-
'audit.md', 'bizar.md', 'explain.md', 'init.md', 'learn.md',
|
|
74
|
-
'plan.md', 'plow-through.md', 'pr-review.md', 'tailscale-serve.md',
|
|
75
|
-
'visual-plan.md',
|
|
76
|
-
'team.md', 'test.md', 'validate.md', 'setup-provider.md',
|
|
77
|
-
]) {
|
|
78
|
-
writeFileSync(join(cmdsDir, f), '# fake command');
|
|
79
|
-
}
|
|
80
|
-
const skillsDir = join(root, 'skills');
|
|
81
|
-
mkdirSync(skillsDir, { recursive: true });
|
|
82
|
-
for (const skill of ['9router', 'bizar', 'obsidian']) {
|
|
83
|
-
mkdirSync(join(skillsDir, skill), { recursive: true });
|
|
84
|
-
writeFileSync(join(skillsDir, skill, 'SKILL.md'), '# fake skill');
|
|
85
|
-
}
|
|
86
|
-
const rulesDir = join(root, 'rules');
|
|
87
|
-
mkdirSync(rulesDir, { recursive: true });
|
|
88
|
-
for (const r of ['general.md', 'git.md', 'javascript.md', 'python.md', 'testing.md', 'thinking.md', 'uncertainty.md']) {
|
|
89
|
-
writeFileSync(join(rulesDir, r), '# fake rule');
|
|
90
|
-
}
|
|
91
|
-
const hooksDir = join(root, 'hooks');
|
|
92
|
-
mkdirSync(hooksDir, { recursive: true });
|
|
93
|
-
for (const h of ['PreToolUse', 'PostToolUse', 'TaskStart', 'TaskResume', 'UserPromptSubmit']) {
|
|
94
|
-
// Cline hooks must be executable scripts with a shebang line.
|
|
95
|
-
writeFileSync(join(hooksDir, h), '#!/usr/bin/env node\n// fake hook\n');
|
|
96
|
-
chmodSync(join(hooksDir, h), 0o755);
|
|
97
|
-
}
|
|
98
|
-
// v6.2.5 — also register each skill in ~/.agents/.skill-lock.json
|
|
99
|
-
// (the SOURCE OF TRUTH for `npx skills list` since Cline v3.0.39).
|
|
100
|
-
// The fake install writes an entry per skill in `config/skills/`
|
|
101
|
-
// (the real source of truth, derived from disk) so the
|
|
102
|
-
// skill-marketplace-registered check passes.
|
|
103
|
-
const agentsSkillsDir = join(root, '.agents', 'skills');
|
|
104
|
-
mkdirSync(agentsSkillsDir, { recursive: true });
|
|
105
|
-
const skillLockPath = join(root, '.agents', '.skill-lock.json');
|
|
106
|
-
const lockEntries = {};
|
|
107
|
-
const actualSkillsRoot = '/home/drb0rk/Projects/BizarHarness/config/skills';
|
|
108
|
-
const skillList = ['9router', '9router-chat', '9router-embeddings', '9router-image',
|
|
109
|
-
'9router-stt', '9router-tts', '9router-web-fetch', '9router-web-search',
|
|
110
|
-
'bizar', 'cpp-coding-standards', 'cpp-testing', 'cubesandbox',
|
|
111
|
-
'embedded-esp-idf', 'glyph', 'harness-engineering', 'lightrag',
|
|
112
|
-
'memory-protocol', 'obsidian', 'read-the-damn-docs', 'self-improvement'];
|
|
113
|
-
for (const skill of skillList) {
|
|
114
|
-
mkdirSync(join(agentsSkillsDir, skill), { recursive: true });
|
|
115
|
-
writeFileSync(join(agentsSkillsDir, skill, 'SKILL.md'), '# fake skill');
|
|
116
|
-
lockEntries[skill] = {
|
|
117
|
-
source: 'bizar/builtin',
|
|
118
|
-
sourceType: 'local',
|
|
119
|
-
sourceUrl: 'https://github.com/DrB0rk/BizarHarness',
|
|
120
|
-
skillPath: `config/skills/${skill}/SKILL.md`,
|
|
121
|
-
skillFolderHash: 'fake',
|
|
122
|
-
pluginName: 'bizar',
|
|
123
|
-
installedAt: '2026-07-10T00:00:00.000Z',
|
|
124
|
-
updatedAt: '2026-07-10T00:00:00.000Z',
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
writeFileSync(skillLockPath, JSON.stringify({ version: 3, skills: lockEntries }, null, 2));
|
|
128
|
-
const pluginDir = join(root, 'plugins', 'bizar');
|
|
129
|
-
mkdirSync(pluginDir, { recursive: true });
|
|
130
|
-
writeFileSync(join(pluginDir, 'index.ts'), '// fake plugin entry — >100 bytes to pass size check\n'.repeat(10));
|
|
131
|
-
mkdirSync(join(pluginDir, 'src'), { recursive: true });
|
|
132
|
-
writeFileSync(
|
|
133
|
-
join(pluginDir, 'src', 'clineruntime.ts'),
|
|
134
|
-
'export class ClineRuntime { config = { enableAgentTeams: true }; }\n',
|
|
135
|
-
);
|
|
136
|
-
// node_modules with the required runtime deps
|
|
137
|
-
const nmDir = join(pluginDir, 'node_modules');
|
|
138
|
-
mkdirSync(nmDir, { recursive: true });
|
|
139
|
-
mkdirSync(join(nmDir, 'zod'), { recursive: true });
|
|
140
|
-
writeFileSync(join(nmDir, 'zod', 'package.json'), '{}');
|
|
141
|
-
mkdirSync(join(nmDir, '@cline'), { recursive: true });
|
|
142
|
-
for (const dep of ['@cline/sdk', '@cline/core', '@cline/shared']) {
|
|
143
|
-
mkdirSync(join(nmDir, dep), { recursive: true });
|
|
144
|
-
writeFileSync(join(nmDir, dep, 'package.json'), '{}');
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
beforeEach(() => {
|
|
149
|
-
workDir = freshWorkDir();
|
|
150
|
-
makeFakeClineInstall(workDir);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
afterEach(() => {
|
|
154
|
-
if (workDir && existsSync(workDir)) rmSync(workDir, { recursive: true, force: true });
|
|
155
|
-
if (ORIG_CLINE_DIR === undefined) delete process.env.CLINE_DIR;
|
|
156
|
-
else process.env.CLINE_DIR = ORIG_CLINE_DIR;
|
|
157
|
-
if (ORIG_HOME === undefined) delete process.env.HOME;
|
|
158
|
-
else process.env.HOME = ORIG_HOME;
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Capture stdout + exit code for a single runValidate() call.
|
|
163
|
-
* The test runner writes its own progress to stdout, so we swap
|
|
164
|
-
* process.stdout for a sink Writable during the call.
|
|
165
|
-
*/
|
|
166
|
-
async function captureRun(opts) {
|
|
167
|
-
const captured = [];
|
|
168
|
-
const sink = new Writable({
|
|
169
|
-
write(chunk, _enc, cb) {
|
|
170
|
-
captured.push(Buffer.from(chunk));
|
|
171
|
-
cb();
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
|
-
const origStdoutDescriptor = Object.getOwnPropertyDescriptor(process, 'stdout');
|
|
175
|
-
const origExit = process.exit;
|
|
176
|
-
let exitCode = null;
|
|
177
|
-
Object.defineProperty(process, 'stdout', { value: sink, configurable: true, writable: true });
|
|
178
|
-
process.exit = (code) => { exitCode = code; };
|
|
179
|
-
try {
|
|
180
|
-
await runValidate(opts);
|
|
181
|
-
} finally {
|
|
182
|
-
if (origStdoutDescriptor) Object.defineProperty(process, 'stdout', origStdoutDescriptor);
|
|
183
|
-
process.exit = origExit;
|
|
184
|
-
}
|
|
185
|
-
return { stdout: Buffer.concat(captured).toString('utf8'), exitCode };
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
describe('runValidate() — JSON output', () => {
|
|
189
|
-
test('returns structured JSON with passed/failed/results', async () => {
|
|
190
|
-
const { stdout, exitCode } = await captureRun({ json: true });
|
|
191
|
-
assert.equal(exitCode, 0, 'should exit 0 on success');
|
|
192
|
-
const parsed = JSON.parse(stdout);
|
|
193
|
-
assert.equal(typeof parsed.passed, 'number');
|
|
194
|
-
assert.equal(typeof parsed.failed, 'number');
|
|
195
|
-
assert.ok(Array.isArray(parsed.results));
|
|
196
|
-
assert.ok(parsed.results.length >= 18, 'expected at least 18 checks');
|
|
197
|
-
for (const r of parsed.results) {
|
|
198
|
-
assert.ok(typeof r.name === 'string');
|
|
199
|
-
assert.ok(typeof r.ok === 'boolean');
|
|
200
|
-
assert.ok(typeof r.message === 'string');
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
test('fails on missing team command', async () => {
|
|
205
|
-
rmSync(join(workDir, 'commands', 'team.md'));
|
|
206
|
-
const { exitCode } = await captureRun({ json: true });
|
|
207
|
-
assert.equal(exitCode, 1, 'should exit 1 on team-command-present failure');
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
test('fails on missing test command', async () => {
|
|
211
|
-
rmSync(join(workDir, 'commands', 'test.md'));
|
|
212
|
-
const { exitCode } = await captureRun({ json: true });
|
|
213
|
-
assert.equal(exitCode, 1);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
test('fails on missing validate command', async () => {
|
|
217
|
-
rmSync(join(workDir, 'commands', 'validate.md'));
|
|
218
|
-
const { exitCode } = await captureRun({ json: true });
|
|
219
|
-
assert.equal(exitCode, 1);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
test('fails on missing agent file', async () => {
|
|
223
|
-
rmSync(join(workDir, 'agents', 'mimir.md'));
|
|
224
|
-
const { exitCode } = await captureRun({ json: true });
|
|
225
|
-
assert.equal(exitCode, 1);
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
test('fails when cline.json missing', async () => {
|
|
229
|
-
rmSync(join(workDir, 'cline.json'));
|
|
230
|
-
const { exitCode } = await captureRun({ json: true });
|
|
231
|
-
assert.equal(exitCode, 1);
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
test('fails when enableAgentTeams is false in clineruntime.ts', async () => {
|
|
235
|
-
writeFileSync(
|
|
236
|
-
join(workDir, 'plugins', 'bizar', 'src', 'clineruntime.ts'),
|
|
237
|
-
'export class ClineRuntime { config = { enableAgentTeams: false }; }\n',
|
|
238
|
-
);
|
|
239
|
-
const { exitCode } = await captureRun({ json: true });
|
|
240
|
-
assert.equal(exitCode, 1, 'should fail when enableAgentTeams is false');
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
test('passes when no provider is configured (v6.2.2+ — user must configure)', async () => {
|
|
244
|
-
// v6.2.2: the installer no longer touches provider config. The
|
|
245
|
-
// user must add their own provider. The provider-config check
|
|
246
|
-
// is therefore ALWAYS lenient — it just reports state.
|
|
247
|
-
const cfg = JSON.parse(readFileSync(join(workDir, 'cline.json'), 'utf8'));
|
|
248
|
-
delete cfg.provider;
|
|
249
|
-
writeFileSync(join(workDir, 'cline.json'), JSON.stringify(cfg, null, 2));
|
|
250
|
-
const { exitCode, stdout } = await captureRun({ json: true });
|
|
251
|
-
assert.equal(exitCode, 0, 'no-provider must not fail validation (v6.2.2+ contract)');
|
|
252
|
-
const parsed = JSON.parse(stdout);
|
|
253
|
-
const p = parsed.results.find((r) => r.name === 'provider-config');
|
|
254
|
-
assert.ok(p, 'provider-config check should be present');
|
|
255
|
-
assert.equal(p.ok, true, 'provider-config always returns ok (lenient)');
|
|
256
|
-
assert.match(p.message, /no provider configured/);
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
test('reports user-configured providers when present', async () => {
|
|
260
|
-
// User has set up their own provider (anything goes).
|
|
261
|
-
const cfg = JSON.parse(readFileSync(join(workDir, 'cline.json'), 'utf8'));
|
|
262
|
-
cfg.provider = {
|
|
263
|
-
'my-custom-provider': {
|
|
264
|
-
baseUrl: 'https://my-llm.example/v1',
|
|
265
|
-
apiKey: 'sk-test',
|
|
266
|
-
models: { 'my-model-1': {}, 'my-model-2': {} },
|
|
267
|
-
},
|
|
268
|
-
};
|
|
269
|
-
writeFileSync(join(workDir, 'cline.json'), JSON.stringify(cfg, null, 2));
|
|
270
|
-
const { exitCode, stdout } = await captureRun({ json: true });
|
|
271
|
-
assert.equal(exitCode, 0);
|
|
272
|
-
const parsed = JSON.parse(stdout);
|
|
273
|
-
const p = parsed.results.find((r) => r.name === 'provider-config');
|
|
274
|
-
assert.match(p.message, /my-custom-provider/);
|
|
275
|
-
assert.match(p.message, /2 models/);
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
test('reports both providers if user has multiple', async () => {
|
|
279
|
-
const cfg = JSON.parse(readFileSync(join(workDir, 'cline.json'), 'utf8'));
|
|
280
|
-
cfg.provider = {
|
|
281
|
-
'a': { baseUrl: 'https://a.example/v1', models: { 'm1': {} } },
|
|
282
|
-
'b': { baseUrl: 'https://b.example/v1', models: { 'm2': {}, 'm3': {} } },
|
|
283
|
-
};
|
|
284
|
-
writeFileSync(join(workDir, 'cline.json'), JSON.stringify(cfg, null, 2));
|
|
285
|
-
const { exitCode, stdout } = await captureRun({ json: true });
|
|
286
|
-
assert.equal(exitCode, 0);
|
|
287
|
-
const parsed = JSON.parse(stdout);
|
|
288
|
-
const p = parsed.results.find((r) => r.name === 'provider-config');
|
|
289
|
-
assert.match(p.message, /\ba\b/);
|
|
290
|
-
assert.match(p.message, /\bb\b/);
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
test('default mode is lenient on 9router-unreachable', async () => {
|
|
294
|
-
const { stdout, exitCode } = await captureRun({ json: true });
|
|
295
|
-
const parsed = JSON.parse(stdout);
|
|
296
|
-
const nineR = parsed.results.find((r) => r.name === '9router-reachable');
|
|
297
|
-
assert.ok(nineR, '9router-reachable check should be present');
|
|
298
|
-
if (!nineR.ok) {
|
|
299
|
-
// 9router is not running. Default mode must be lenient.
|
|
300
|
-
assert.equal(exitCode, 0, 'default mode should be lenient when 9router is down');
|
|
301
|
-
} else {
|
|
302
|
-
// 9router is running (some test envs have it). Just confirm the
|
|
303
|
-
// check is in the list and exit code is sane.
|
|
304
|
-
assert.equal(exitCode, 0, 'expected exit 0 when all critical checks pass');
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
test('--strict fails when 9router is unreachable', async () => {
|
|
309
|
-
// We can't easily kill 9router in a test, but we can prove that
|
|
310
|
-
// --strict mode would fail if 9router were down: set NINEROUTER_URL
|
|
311
|
-
// to a port nothing is listening on.
|
|
312
|
-
const origUrl = process.env.NINEROUTER_URL;
|
|
313
|
-
process.env.NINEROUTER_URL = 'http://127.0.0.1:1'; // nothing here
|
|
314
|
-
try {
|
|
315
|
-
const { exitCode } = await captureRun({ json: true, strict: true });
|
|
316
|
-
assert.equal(exitCode, 1, 'strict mode should fail when 9router is unreachable');
|
|
317
|
-
} finally {
|
|
318
|
-
if (origUrl === undefined) delete process.env.NINEROUTER_URL;
|
|
319
|
-
else process.env.NINEROUTER_URL = origUrl;
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
test('--only filters to a single check', async () => {
|
|
324
|
-
const { stdout, exitCode } = await captureRun({ json: true, only: 'team-command-present' });
|
|
325
|
-
assert.equal(exitCode, 0);
|
|
326
|
-
const parsed = JSON.parse(stdout);
|
|
327
|
-
assert.equal(parsed.results.length, 1);
|
|
328
|
-
assert.equal(parsed.results[0].name, 'team-command-present');
|
|
329
|
-
assert.equal(parsed.results[0].ok, true);
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
test('--only on a missing file fails with exit 1', async () => {
|
|
333
|
-
rmSync(join(workDir, 'commands', 'team.md'));
|
|
334
|
-
const { exitCode } = await captureRun({ json: true, only: 'team-command-present' });
|
|
335
|
-
assert.equal(exitCode, 1);
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
test('--only with an unknown name exits 2', async () => {
|
|
339
|
-
const { exitCode } = await captureRun({ json: true, only: 'this-does-not-exist' });
|
|
340
|
-
assert.equal(exitCode, 2);
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
test('v6.2.4 — mistake-limit-floor warns when clineruntimeMaxConsecutiveMistakes is < 10', async () => {
|
|
344
|
-
const cfg = JSON.parse(readFileSync(join(workDir, 'cline.json'), 'utf8'));
|
|
345
|
-
cfg.plugin = [['./plugins/bizar', { clineruntimeMaxConsecutiveMistakes: 3 }]];
|
|
346
|
-
writeFileSync(join(workDir, 'cline.json'), JSON.stringify(cfg, null, 2));
|
|
347
|
-
const { stdout, exitCode } = await captureRun({ json: true });
|
|
348
|
-
assert.equal(exitCode, 0, 'mistake-limit-floor is lenient so exit stays 0');
|
|
349
|
-
const parsed = JSON.parse(stdout);
|
|
350
|
-
const check = parsed.results.find((r) => r.name === 'mistake-limit-floor');
|
|
351
|
-
assert.ok(check, 'mistake-limit-floor check should be present');
|
|
352
|
-
assert.equal(check.ok, false, 'low mistake limit should warn');
|
|
353
|
-
assert.match(check.message, /BELOW the recommended minimum/);
|
|
354
|
-
assert.match(check.message, /clineruntimeMaxConsecutiveMistakes=3/);
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
test('v6.2.4 — mistake-limit-floor OK when clineruntimeMaxConsecutiveMistakes >= 10', async () => {
|
|
358
|
-
const cfg = JSON.parse(readFileSync(join(workDir, 'cline.json'), 'utf8'));
|
|
359
|
-
cfg.plugin = [['./plugins/bizar', { clineruntimeMaxConsecutiveMistakes: 15 }]];
|
|
360
|
-
writeFileSync(join(workDir, 'cline.json'), JSON.stringify(cfg, null, 2));
|
|
361
|
-
const { stdout, exitCode } = await captureRun({ json: true });
|
|
362
|
-
assert.equal(exitCode, 0);
|
|
363
|
-
const parsed = JSON.parse(stdout);
|
|
364
|
-
const check = parsed.results.find((r) => r.name === 'mistake-limit-floor');
|
|
365
|
-
assert.equal(check.ok, true);
|
|
366
|
-
assert.match(check.message, /15/);
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
test('v6.2.4 — mistake-limit-floor OK when no plugin entry (legacy cline.json)', async () => {
|
|
370
|
-
const cfg = JSON.parse(readFileSync(join(workDir, 'cline.json'), 'utf8'));
|
|
371
|
-
delete cfg.plugin;
|
|
372
|
-
writeFileSync(join(workDir, 'cline.json'), JSON.stringify(cfg, null, 2));
|
|
373
|
-
const { stdout } = await captureRun({ json: true });
|
|
374
|
-
const parsed = JSON.parse(stdout);
|
|
375
|
-
const check = parsed.results.find((r) => r.name === 'mistake-limit-floor');
|
|
376
|
-
assert.match(check.message, /no plugin entries/);
|
|
377
|
-
assert.equal(check.ok, true);
|
|
378
|
-
});
|
|
379
|
-
});
|