@dotsetlabs/bellwether 0.10.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/CHANGELOG.md +291 -0
- package/LICENSE +21 -0
- package/README.md +739 -0
- package/dist/auth/credentials.d.ts +64 -0
- package/dist/auth/credentials.js +218 -0
- package/dist/auth/index.d.ts +6 -0
- package/dist/auth/index.js +6 -0
- package/dist/auth/keychain.d.ts +64 -0
- package/dist/auth/keychain.js +268 -0
- package/dist/baseline/ab-testing.d.ts +80 -0
- package/dist/baseline/ab-testing.js +236 -0
- package/dist/baseline/ai-compatibility-scorer.d.ts +95 -0
- package/dist/baseline/ai-compatibility-scorer.js +606 -0
- package/dist/baseline/calibration.d.ts +77 -0
- package/dist/baseline/calibration.js +136 -0
- package/dist/baseline/category-matching.d.ts +85 -0
- package/dist/baseline/category-matching.js +289 -0
- package/dist/baseline/change-impact-analyzer.d.ts +98 -0
- package/dist/baseline/change-impact-analyzer.js +592 -0
- package/dist/baseline/comparator.d.ts +64 -0
- package/dist/baseline/comparator.js +916 -0
- package/dist/baseline/confidence.d.ts +55 -0
- package/dist/baseline/confidence.js +122 -0
- package/dist/baseline/converter.d.ts +61 -0
- package/dist/baseline/converter.js +585 -0
- package/dist/baseline/dependency-analyzer.d.ts +89 -0
- package/dist/baseline/dependency-analyzer.js +567 -0
- package/dist/baseline/deprecation-tracker.d.ts +133 -0
- package/dist/baseline/deprecation-tracker.js +322 -0
- package/dist/baseline/diff.d.ts +55 -0
- package/dist/baseline/diff.js +1584 -0
- package/dist/baseline/documentation-scorer.d.ts +205 -0
- package/dist/baseline/documentation-scorer.js +466 -0
- package/dist/baseline/embeddings.d.ts +118 -0
- package/dist/baseline/embeddings.js +251 -0
- package/dist/baseline/error-analyzer.d.ts +198 -0
- package/dist/baseline/error-analyzer.js +721 -0
- package/dist/baseline/evaluation/evaluator.d.ts +42 -0
- package/dist/baseline/evaluation/evaluator.js +323 -0
- package/dist/baseline/evaluation/expanded-dataset.d.ts +45 -0
- package/dist/baseline/evaluation/expanded-dataset.js +1164 -0
- package/dist/baseline/evaluation/golden-dataset.d.ts +58 -0
- package/dist/baseline/evaluation/golden-dataset.js +717 -0
- package/dist/baseline/evaluation/index.d.ts +15 -0
- package/dist/baseline/evaluation/index.js +15 -0
- package/dist/baseline/evaluation/types.d.ts +186 -0
- package/dist/baseline/evaluation/types.js +8 -0
- package/dist/baseline/external-dependency-detector.d.ts +181 -0
- package/dist/baseline/external-dependency-detector.js +524 -0
- package/dist/baseline/golden-output.d.ts +162 -0
- package/dist/baseline/golden-output.js +636 -0
- package/dist/baseline/health-scorer.d.ts +174 -0
- package/dist/baseline/health-scorer.js +451 -0
- package/dist/baseline/incremental-checker.d.ts +97 -0
- package/dist/baseline/incremental-checker.js +174 -0
- package/dist/baseline/index.d.ts +31 -0
- package/dist/baseline/index.js +42 -0
- package/dist/baseline/migration-generator.d.ts +137 -0
- package/dist/baseline/migration-generator.js +554 -0
- package/dist/baseline/migrations.d.ts +60 -0
- package/dist/baseline/migrations.js +197 -0
- package/dist/baseline/performance-tracker.d.ts +214 -0
- package/dist/baseline/performance-tracker.js +577 -0
- package/dist/baseline/pr-comment-generator.d.ts +117 -0
- package/dist/baseline/pr-comment-generator.js +546 -0
- package/dist/baseline/response-fingerprint.d.ts +127 -0
- package/dist/baseline/response-fingerprint.js +728 -0
- package/dist/baseline/response-schema-tracker.d.ts +129 -0
- package/dist/baseline/response-schema-tracker.js +420 -0
- package/dist/baseline/risk-scorer.d.ts +54 -0
- package/dist/baseline/risk-scorer.js +434 -0
- package/dist/baseline/saver.d.ts +89 -0
- package/dist/baseline/saver.js +554 -0
- package/dist/baseline/scenario-generator.d.ts +151 -0
- package/dist/baseline/scenario-generator.js +905 -0
- package/dist/baseline/schema-compare.d.ts +86 -0
- package/dist/baseline/schema-compare.js +557 -0
- package/dist/baseline/schema-evolution.d.ts +189 -0
- package/dist/baseline/schema-evolution.js +467 -0
- package/dist/baseline/semantic.d.ts +203 -0
- package/dist/baseline/semantic.js +908 -0
- package/dist/baseline/synonyms.d.ts +60 -0
- package/dist/baseline/synonyms.js +386 -0
- package/dist/baseline/telemetry.d.ts +165 -0
- package/dist/baseline/telemetry.js +294 -0
- package/dist/baseline/test-pruner.d.ts +120 -0
- package/dist/baseline/test-pruner.js +387 -0
- package/dist/baseline/types.d.ts +449 -0
- package/dist/baseline/types.js +5 -0
- package/dist/baseline/version.d.ts +138 -0
- package/dist/baseline/version.js +206 -0
- package/dist/cache/index.d.ts +5 -0
- package/dist/cache/index.js +5 -0
- package/dist/cache/response-cache.d.ts +151 -0
- package/dist/cache/response-cache.js +287 -0
- package/dist/ci/index.d.ts +60 -0
- package/dist/ci/index.js +342 -0
- package/dist/cli/commands/auth.d.ts +12 -0
- package/dist/cli/commands/auth.js +352 -0
- package/dist/cli/commands/badge.d.ts +3 -0
- package/dist/cli/commands/badge.js +74 -0
- package/dist/cli/commands/baseline-accept.d.ts +15 -0
- package/dist/cli/commands/baseline-accept.js +178 -0
- package/dist/cli/commands/baseline-migrate.d.ts +12 -0
- package/dist/cli/commands/baseline-migrate.js +164 -0
- package/dist/cli/commands/baseline.d.ts +14 -0
- package/dist/cli/commands/baseline.js +449 -0
- package/dist/cli/commands/beta.d.ts +10 -0
- package/dist/cli/commands/beta.js +231 -0
- package/dist/cli/commands/check.d.ts +11 -0
- package/dist/cli/commands/check.js +820 -0
- package/dist/cli/commands/cloud/badge.d.ts +3 -0
- package/dist/cli/commands/cloud/badge.js +74 -0
- package/dist/cli/commands/cloud/diff.d.ts +6 -0
- package/dist/cli/commands/cloud/diff.js +79 -0
- package/dist/cli/commands/cloud/history.d.ts +6 -0
- package/dist/cli/commands/cloud/history.js +102 -0
- package/dist/cli/commands/cloud/link.d.ts +9 -0
- package/dist/cli/commands/cloud/link.js +119 -0
- package/dist/cli/commands/cloud/login.d.ts +7 -0
- package/dist/cli/commands/cloud/login.js +499 -0
- package/dist/cli/commands/cloud/projects.d.ts +6 -0
- package/dist/cli/commands/cloud/projects.js +44 -0
- package/dist/cli/commands/cloud/shared.d.ts +7 -0
- package/dist/cli/commands/cloud/shared.js +42 -0
- package/dist/cli/commands/cloud/teams.d.ts +8 -0
- package/dist/cli/commands/cloud/teams.js +169 -0
- package/dist/cli/commands/cloud/upload.d.ts +8 -0
- package/dist/cli/commands/cloud/upload.js +181 -0
- package/dist/cli/commands/contract.d.ts +11 -0
- package/dist/cli/commands/contract.js +280 -0
- package/dist/cli/commands/discover.d.ts +3 -0
- package/dist/cli/commands/discover.js +82 -0
- package/dist/cli/commands/eval.d.ts +9 -0
- package/dist/cli/commands/eval.js +187 -0
- package/dist/cli/commands/explore.d.ts +11 -0
- package/dist/cli/commands/explore.js +437 -0
- package/dist/cli/commands/feedback.d.ts +9 -0
- package/dist/cli/commands/feedback.js +174 -0
- package/dist/cli/commands/golden.d.ts +12 -0
- package/dist/cli/commands/golden.js +407 -0
- package/dist/cli/commands/history.d.ts +10 -0
- package/dist/cli/commands/history.js +202 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.js +219 -0
- package/dist/cli/commands/interview.d.ts +3 -0
- package/dist/cli/commands/interview.js +903 -0
- package/dist/cli/commands/link.d.ts +10 -0
- package/dist/cli/commands/link.js +169 -0
- package/dist/cli/commands/login.d.ts +7 -0
- package/dist/cli/commands/login.js +499 -0
- package/dist/cli/commands/preset.d.ts +33 -0
- package/dist/cli/commands/preset.js +297 -0
- package/dist/cli/commands/profile.d.ts +33 -0
- package/dist/cli/commands/profile.js +286 -0
- package/dist/cli/commands/registry.d.ts +11 -0
- package/dist/cli/commands/registry.js +146 -0
- package/dist/cli/commands/shared.d.ts +79 -0
- package/dist/cli/commands/shared.js +196 -0
- package/dist/cli/commands/teams.d.ts +8 -0
- package/dist/cli/commands/teams.js +169 -0
- package/dist/cli/commands/test.d.ts +9 -0
- package/dist/cli/commands/test.js +500 -0
- package/dist/cli/commands/upload.d.ts +8 -0
- package/dist/cli/commands/upload.js +223 -0
- package/dist/cli/commands/validate-config.d.ts +6 -0
- package/dist/cli/commands/validate-config.js +35 -0
- package/dist/cli/commands/verify.d.ts +11 -0
- package/dist/cli/commands/verify.js +283 -0
- package/dist/cli/commands/watch.d.ts +12 -0
- package/dist/cli/commands/watch.js +253 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +178 -0
- package/dist/cli/interactive.d.ts +47 -0
- package/dist/cli/interactive.js +216 -0
- package/dist/cli/output/terminal-reporter.d.ts +19 -0
- package/dist/cli/output/terminal-reporter.js +104 -0
- package/dist/cli/output.d.ts +226 -0
- package/dist/cli/output.js +438 -0
- package/dist/cli/utils/env.d.ts +5 -0
- package/dist/cli/utils/env.js +14 -0
- package/dist/cli/utils/progress.d.ts +59 -0
- package/dist/cli/utils/progress.js +206 -0
- package/dist/cli/utils/server-context.d.ts +10 -0
- package/dist/cli/utils/server-context.js +36 -0
- package/dist/cloud/auth.d.ts +144 -0
- package/dist/cloud/auth.js +374 -0
- package/dist/cloud/client.d.ts +24 -0
- package/dist/cloud/client.js +65 -0
- package/dist/cloud/http-client.d.ts +38 -0
- package/dist/cloud/http-client.js +215 -0
- package/dist/cloud/index.d.ts +23 -0
- package/dist/cloud/index.js +25 -0
- package/dist/cloud/mock-client.d.ts +107 -0
- package/dist/cloud/mock-client.js +545 -0
- package/dist/cloud/types.d.ts +515 -0
- package/dist/cloud/types.js +15 -0
- package/dist/config/defaults.d.ts +160 -0
- package/dist/config/defaults.js +169 -0
- package/dist/config/loader.d.ts +24 -0
- package/dist/config/loader.js +122 -0
- package/dist/config/template.d.ts +42 -0
- package/dist/config/template.js +647 -0
- package/dist/config/validator.d.ts +2112 -0
- package/dist/config/validator.js +658 -0
- package/dist/constants/cloud.d.ts +107 -0
- package/dist/constants/cloud.js +110 -0
- package/dist/constants/core.d.ts +521 -0
- package/dist/constants/core.js +556 -0
- package/dist/constants/testing.d.ts +1283 -0
- package/dist/constants/testing.js +1568 -0
- package/dist/constants.d.ts +10 -0
- package/dist/constants.js +10 -0
- package/dist/contract/index.d.ts +6 -0
- package/dist/contract/index.js +5 -0
- package/dist/contract/validator.d.ts +177 -0
- package/dist/contract/validator.js +574 -0
- package/dist/cost/index.d.ts +6 -0
- package/dist/cost/index.js +5 -0
- package/dist/cost/tracker.d.ts +134 -0
- package/dist/cost/tracker.js +313 -0
- package/dist/discovery/discovery.d.ts +16 -0
- package/dist/discovery/discovery.js +173 -0
- package/dist/discovery/types.d.ts +51 -0
- package/dist/discovery/types.js +2 -0
- package/dist/docs/agents.d.ts +3 -0
- package/dist/docs/agents.js +995 -0
- package/dist/docs/contract.d.ts +51 -0
- package/dist/docs/contract.js +1681 -0
- package/dist/docs/generator.d.ts +4 -0
- package/dist/docs/generator.js +4 -0
- package/dist/docs/html-reporter.d.ts +9 -0
- package/dist/docs/html-reporter.js +757 -0
- package/dist/docs/index.d.ts +10 -0
- package/dist/docs/index.js +11 -0
- package/dist/docs/junit-reporter.d.ts +18 -0
- package/dist/docs/junit-reporter.js +210 -0
- package/dist/docs/report.d.ts +14 -0
- package/dist/docs/report.js +44 -0
- package/dist/docs/sarif-reporter.d.ts +19 -0
- package/dist/docs/sarif-reporter.js +335 -0
- package/dist/docs/shared.d.ts +35 -0
- package/dist/docs/shared.js +162 -0
- package/dist/docs/templates.d.ts +12 -0
- package/dist/docs/templates.js +76 -0
- package/dist/errors/index.d.ts +6 -0
- package/dist/errors/index.js +6 -0
- package/dist/errors/retry.d.ts +92 -0
- package/dist/errors/retry.js +323 -0
- package/dist/errors/types.d.ts +321 -0
- package/dist/errors/types.js +584 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +32 -0
- package/dist/interview/dependency-resolver.d.ts +11 -0
- package/dist/interview/dependency-resolver.js +32 -0
- package/dist/interview/interviewer.d.ts +232 -0
- package/dist/interview/interviewer.js +1939 -0
- package/dist/interview/mock-response-generator.d.ts +7 -0
- package/dist/interview/mock-response-generator.js +102 -0
- package/dist/interview/orchestrator.d.ts +237 -0
- package/dist/interview/orchestrator.js +1296 -0
- package/dist/interview/rate-limiter.d.ts +15 -0
- package/dist/interview/rate-limiter.js +55 -0
- package/dist/interview/response-validator.d.ts +10 -0
- package/dist/interview/response-validator.js +132 -0
- package/dist/interview/schema-inferrer.d.ts +8 -0
- package/dist/interview/schema-inferrer.js +71 -0
- package/dist/interview/schema-test-generator.d.ts +71 -0
- package/dist/interview/schema-test-generator.js +834 -0
- package/dist/interview/smart-value-generator.d.ts +155 -0
- package/dist/interview/smart-value-generator.js +554 -0
- package/dist/interview/stateful-test-runner.d.ts +19 -0
- package/dist/interview/stateful-test-runner.js +106 -0
- package/dist/interview/types.d.ts +561 -0
- package/dist/interview/types.js +2 -0
- package/dist/llm/anthropic.d.ts +41 -0
- package/dist/llm/anthropic.js +355 -0
- package/dist/llm/client.d.ts +123 -0
- package/dist/llm/client.js +42 -0
- package/dist/llm/factory.d.ts +38 -0
- package/dist/llm/factory.js +145 -0
- package/dist/llm/fallback.d.ts +140 -0
- package/dist/llm/fallback.js +379 -0
- package/dist/llm/index.d.ts +18 -0
- package/dist/llm/index.js +15 -0
- package/dist/llm/ollama.d.ts +37 -0
- package/dist/llm/ollama.js +330 -0
- package/dist/llm/openai.d.ts +25 -0
- package/dist/llm/openai.js +320 -0
- package/dist/llm/token-budget.d.ts +161 -0
- package/dist/llm/token-budget.js +395 -0
- package/dist/logging/logger.d.ts +70 -0
- package/dist/logging/logger.js +130 -0
- package/dist/metrics/collector.d.ts +106 -0
- package/dist/metrics/collector.js +547 -0
- package/dist/metrics/index.d.ts +7 -0
- package/dist/metrics/index.js +7 -0
- package/dist/metrics/prometheus.d.ts +20 -0
- package/dist/metrics/prometheus.js +241 -0
- package/dist/metrics/types.d.ts +209 -0
- package/dist/metrics/types.js +5 -0
- package/dist/persona/builtins.d.ts +54 -0
- package/dist/persona/builtins.js +219 -0
- package/dist/persona/index.d.ts +8 -0
- package/dist/persona/index.js +8 -0
- package/dist/persona/loader.d.ts +30 -0
- package/dist/persona/loader.js +190 -0
- package/dist/persona/types.d.ts +144 -0
- package/dist/persona/types.js +5 -0
- package/dist/persona/validation.d.ts +94 -0
- package/dist/persona/validation.js +332 -0
- package/dist/prompts/index.d.ts +5 -0
- package/dist/prompts/index.js +5 -0
- package/dist/prompts/templates.d.ts +180 -0
- package/dist/prompts/templates.js +431 -0
- package/dist/registry/client.d.ts +49 -0
- package/dist/registry/client.js +191 -0
- package/dist/registry/index.d.ts +7 -0
- package/dist/registry/index.js +6 -0
- package/dist/registry/types.d.ts +140 -0
- package/dist/registry/types.js +6 -0
- package/dist/scenarios/evaluator.d.ts +43 -0
- package/dist/scenarios/evaluator.js +206 -0
- package/dist/scenarios/index.d.ts +10 -0
- package/dist/scenarios/index.js +9 -0
- package/dist/scenarios/loader.d.ts +20 -0
- package/dist/scenarios/loader.js +285 -0
- package/dist/scenarios/types.d.ts +153 -0
- package/dist/scenarios/types.js +8 -0
- package/dist/security/index.d.ts +17 -0
- package/dist/security/index.js +18 -0
- package/dist/security/payloads.d.ts +61 -0
- package/dist/security/payloads.js +268 -0
- package/dist/security/security-tester.d.ts +42 -0
- package/dist/security/security-tester.js +582 -0
- package/dist/security/types.d.ts +166 -0
- package/dist/security/types.js +8 -0
- package/dist/transport/base-transport.d.ts +59 -0
- package/dist/transport/base-transport.js +38 -0
- package/dist/transport/http-transport.d.ts +67 -0
- package/dist/transport/http-transport.js +238 -0
- package/dist/transport/mcp-client.d.ts +141 -0
- package/dist/transport/mcp-client.js +496 -0
- package/dist/transport/sse-transport.d.ts +88 -0
- package/dist/transport/sse-transport.js +316 -0
- package/dist/transport/stdio-transport.d.ts +43 -0
- package/dist/transport/stdio-transport.js +238 -0
- package/dist/transport/types.d.ts +125 -0
- package/dist/transport/types.js +16 -0
- package/dist/utils/concurrency.d.ts +123 -0
- package/dist/utils/concurrency.js +213 -0
- package/dist/utils/formatters.d.ts +16 -0
- package/dist/utils/formatters.js +37 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/jsonpath.d.ts +87 -0
- package/dist/utils/jsonpath.js +326 -0
- package/dist/utils/markdown.d.ts +113 -0
- package/dist/utils/markdown.js +265 -0
- package/dist/utils/network.d.ts +14 -0
- package/dist/utils/network.js +17 -0
- package/dist/utils/sanitize.d.ts +92 -0
- package/dist/utils/sanitize.js +191 -0
- package/dist/utils/semantic.d.ts +194 -0
- package/dist/utils/semantic.js +1051 -0
- package/dist/utils/smart-truncate.d.ts +94 -0
- package/dist/utils/smart-truncate.js +361 -0
- package/dist/utils/timeout.d.ts +153 -0
- package/dist/utils/timeout.js +205 -0
- package/dist/utils/yaml-parser.d.ts +58 -0
- package/dist/utils/yaml-parser.js +86 -0
- package/dist/validation/index.d.ts +32 -0
- package/dist/validation/index.js +32 -0
- package/dist/validation/semantic-test-generator.d.ts +50 -0
- package/dist/validation/semantic-test-generator.js +176 -0
- package/dist/validation/semantic-types.d.ts +66 -0
- package/dist/validation/semantic-types.js +94 -0
- package/dist/validation/semantic-validator.d.ts +38 -0
- package/dist/validation/semantic-validator.js +340 -0
- package/dist/verification/index.d.ts +6 -0
- package/dist/verification/index.js +5 -0
- package/dist/verification/types.d.ts +133 -0
- package/dist/verification/types.js +5 -0
- package/dist/verification/verifier.d.ts +30 -0
- package/dist/verification/verifier.js +309 -0
- package/dist/version.d.ts +19 -0
- package/dist/version.js +48 -0
- package/dist/workflow/auto-generator.d.ts +27 -0
- package/dist/workflow/auto-generator.js +513 -0
- package/dist/workflow/discovery.d.ts +40 -0
- package/dist/workflow/discovery.js +195 -0
- package/dist/workflow/executor.d.ts +82 -0
- package/dist/workflow/executor.js +611 -0
- package/dist/workflow/index.d.ts +10 -0
- package/dist/workflow/index.js +10 -0
- package/dist/workflow/loader.d.ts +24 -0
- package/dist/workflow/loader.js +194 -0
- package/dist/workflow/state-tracker.d.ts +98 -0
- package/dist/workflow/state-tracker.js +424 -0
- package/dist/workflow/types.d.ts +337 -0
- package/dist/workflow/types.js +5 -0
- package/package.json +94 -0
- package/schemas/bellwether-check.schema.json +651 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upload command for uploading baselines to Bellwether Cloud.
|
|
3
|
+
*
|
|
4
|
+
* Can read baseline path from bellwether.yaml config.
|
|
5
|
+
*/
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import { existsSync, readFileSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
import { getSessionToken, getLinkedProject } from '../../cloud/auth.js';
|
|
10
|
+
import { createCloudClient } from '../../cloud/client.js';
|
|
11
|
+
import { loadBaseline } from '../../baseline/saver.js';
|
|
12
|
+
import { convertToCloudBaseline } from '../../baseline/converter.js';
|
|
13
|
+
import { loadConfig } from '../../config/loader.js';
|
|
14
|
+
import { PATHS, EXIT_CODES } from '../../constants.js';
|
|
15
|
+
import * as output from '../output.js';
|
|
16
|
+
import { getSeverityIcon } from '../output.js';
|
|
17
|
+
/**
|
|
18
|
+
* Default baseline file name.
|
|
19
|
+
*/
|
|
20
|
+
const DEFAULT_BASELINE_FILE = PATHS.DEFAULT_BASELINE_FILE;
|
|
21
|
+
/**
|
|
22
|
+
* Try to get baseline config from config file.
|
|
23
|
+
* Returns output directory and optional baseline path from config.
|
|
24
|
+
*/
|
|
25
|
+
function getBaselineConfigFromFile(configPath) {
|
|
26
|
+
try {
|
|
27
|
+
const config = loadConfig(configPath);
|
|
28
|
+
return {
|
|
29
|
+
outputDir: config.output.dir,
|
|
30
|
+
baselinePath: config.baseline.path,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return { outputDir: '.' };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export const uploadCommand = new Command('upload')
|
|
38
|
+
.description('Upload a baseline to Bellwether Cloud')
|
|
39
|
+
.argument('[baseline]', `Path to baseline JSON file (default: ${DEFAULT_BASELINE_FILE})`)
|
|
40
|
+
.option('-b, --baseline <path>', 'Path to baseline JSON file')
|
|
41
|
+
.option('-c, --config <path>', 'Path to config file')
|
|
42
|
+
.option('-p, --project <id>', 'Project ID to upload to (uses linked project if not specified)')
|
|
43
|
+
.option('--ci', 'CI mode - output URL only, exit 1 on breaking drift')
|
|
44
|
+
.option('--session <session>', 'Session token (overrides stored/env session)')
|
|
45
|
+
.option('--fail-on-drift', 'Exit with error if any behavioral drift detected')
|
|
46
|
+
.action(async (baselineArg, options) => {
|
|
47
|
+
// Get config settings
|
|
48
|
+
const configSettings = getBaselineConfigFromFile(options.config);
|
|
49
|
+
const outputDir = configSettings.outputDir;
|
|
50
|
+
// Determine baseline path with priority:
|
|
51
|
+
// 1. Positional argument
|
|
52
|
+
// 2. --baseline flag
|
|
53
|
+
// 3. baseline.path from config
|
|
54
|
+
// 4. Default file in output.dir
|
|
55
|
+
// 5. Default file in current directory
|
|
56
|
+
let baselinePath = baselineArg ?? options.baseline ?? configSettings.baselinePath;
|
|
57
|
+
if (!baselinePath) {
|
|
58
|
+
const configBaseline = join(outputDir, DEFAULT_BASELINE_FILE);
|
|
59
|
+
if (existsSync(configBaseline)) {
|
|
60
|
+
baselinePath = configBaseline;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
baselinePath = DEFAULT_BASELINE_FILE;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const isCiMode = options.ci;
|
|
67
|
+
// Get session
|
|
68
|
+
const sessionToken = options.session ?? getSessionToken();
|
|
69
|
+
if (!sessionToken) {
|
|
70
|
+
if (isCiMode) {
|
|
71
|
+
output.error('BELLWETHER_SESSION not set');
|
|
72
|
+
process.exit(EXIT_CODES.ERROR);
|
|
73
|
+
}
|
|
74
|
+
output.error('Not authenticated. Run `bellwether login` first or set BELLWETHER_SESSION.');
|
|
75
|
+
process.exit(EXIT_CODES.ERROR);
|
|
76
|
+
}
|
|
77
|
+
// Check baseline file exists
|
|
78
|
+
if (!existsSync(baselinePath)) {
|
|
79
|
+
if (isCiMode) {
|
|
80
|
+
output.error(`Baseline not found: ${baselinePath}`);
|
|
81
|
+
process.exit(EXIT_CODES.ERROR);
|
|
82
|
+
}
|
|
83
|
+
output.error(`Baseline file not found: ${baselinePath}`);
|
|
84
|
+
output.error('\nCreate a baseline first:');
|
|
85
|
+
output.error(' 1. Run `bellwether check` (with output.format: json in config)');
|
|
86
|
+
output.error(' 2. Run `bellwether baseline save`');
|
|
87
|
+
process.exit(EXIT_CODES.ERROR);
|
|
88
|
+
}
|
|
89
|
+
// Determine project ID
|
|
90
|
+
let projectId = options.project;
|
|
91
|
+
if (!projectId) {
|
|
92
|
+
const link = getLinkedProject();
|
|
93
|
+
if (link) {
|
|
94
|
+
projectId = link.projectId;
|
|
95
|
+
if (!isCiMode) {
|
|
96
|
+
output.info(`Using linked project: ${link.projectName}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!projectId) {
|
|
101
|
+
if (isCiMode) {
|
|
102
|
+
output.error('No project specified');
|
|
103
|
+
process.exit(EXIT_CODES.ERROR);
|
|
104
|
+
}
|
|
105
|
+
output.error('No project specified.');
|
|
106
|
+
output.error('\nEither:');
|
|
107
|
+
output.error(' - Use --project <id> to specify a project');
|
|
108
|
+
output.error(' - Run `bellwether link` to link this directory to a project');
|
|
109
|
+
process.exit(EXIT_CODES.ERROR);
|
|
110
|
+
}
|
|
111
|
+
// Load and convert baseline
|
|
112
|
+
let cloudBaseline;
|
|
113
|
+
try {
|
|
114
|
+
// Try loading as cloud baseline first
|
|
115
|
+
const content = readFileSync(baselinePath, 'utf-8');
|
|
116
|
+
const parsed = JSON.parse(content);
|
|
117
|
+
if (parsed.version === '1.0' && parsed.metadata?.formatVersion === '1.0') {
|
|
118
|
+
// Already in cloud format
|
|
119
|
+
cloudBaseline = parsed;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// Convert from local format
|
|
123
|
+
const localBaseline = loadBaseline(baselinePath);
|
|
124
|
+
cloudBaseline = convertToCloudBaseline(localBaseline);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
if (isCiMode) {
|
|
129
|
+
output.error(`Failed to load baseline: ${error instanceof Error ? error.message : error}`);
|
|
130
|
+
process.exit(EXIT_CODES.ERROR);
|
|
131
|
+
}
|
|
132
|
+
output.error('Failed to load baseline: ' + (error instanceof Error ? error.message : String(error)));
|
|
133
|
+
process.exit(EXIT_CODES.ERROR);
|
|
134
|
+
}
|
|
135
|
+
// Create client and upload
|
|
136
|
+
const client = createCloudClient({ sessionToken });
|
|
137
|
+
if (!client.isAuthenticated()) {
|
|
138
|
+
if (isCiMode) {
|
|
139
|
+
output.error('Authentication failed');
|
|
140
|
+
process.exit(EXIT_CODES.ERROR);
|
|
141
|
+
}
|
|
142
|
+
output.error('Authentication failed. Run `bellwether login` to re-authenticate.');
|
|
143
|
+
process.exit(EXIT_CODES.ERROR);
|
|
144
|
+
}
|
|
145
|
+
if (!isCiMode) {
|
|
146
|
+
output.info(`Uploading baseline to project ${projectId}...`);
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
const result = await client.uploadBaseline(projectId, cloudBaseline);
|
|
150
|
+
if (isCiMode) {
|
|
151
|
+
// CI mode - minimal output
|
|
152
|
+
output.info(result.viewUrl);
|
|
153
|
+
// Check for drift
|
|
154
|
+
if (result.version > 1) {
|
|
155
|
+
const diff = await client.getLatestDiff(projectId);
|
|
156
|
+
if (diff) {
|
|
157
|
+
if (diff.severity === 'breaking') {
|
|
158
|
+
output.error('Breaking changes detected');
|
|
159
|
+
process.exit(EXIT_CODES.ERROR);
|
|
160
|
+
}
|
|
161
|
+
if (options.failOnDrift && diff.severity !== 'none') {
|
|
162
|
+
output.error(`Behavioral drift detected: ${diff.severity}`);
|
|
163
|
+
process.exit(EXIT_CODES.ERROR);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
// Interactive mode - detailed output
|
|
170
|
+
output.info(`\nUpload successful!`);
|
|
171
|
+
output.info(`Version: ${result.version}`);
|
|
172
|
+
output.info(`View: ${result.viewUrl}`);
|
|
173
|
+
if (result.diffUrl) {
|
|
174
|
+
output.info(`Diff: ${result.diffUrl}`);
|
|
175
|
+
// Show diff summary
|
|
176
|
+
const diff = await client.getLatestDiff(projectId);
|
|
177
|
+
if (diff) {
|
|
178
|
+
output.info('\nChanges from previous version:');
|
|
179
|
+
printDiffSummary(diff);
|
|
180
|
+
if (diff.severity === 'breaking') {
|
|
181
|
+
output.info('\n⚠️ Breaking changes detected!');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
output.info('\nThis is the first baseline for this project.');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
if (isCiMode) {
|
|
192
|
+
output.error(`Upload failed: ${error instanceof Error ? error.message : error}`);
|
|
193
|
+
process.exit(EXIT_CODES.ERROR);
|
|
194
|
+
}
|
|
195
|
+
output.error('Upload failed: ' + (error instanceof Error ? error.message : String(error)));
|
|
196
|
+
process.exit(EXIT_CODES.ERROR);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
/**
|
|
200
|
+
* Print a diff summary in human-readable format (verbose format).
|
|
201
|
+
*/
|
|
202
|
+
function printDiffSummary(diff) {
|
|
203
|
+
output.info(` Severity: ${getSeverityIcon(diff.severity)} ${diff.severity}`);
|
|
204
|
+
if (diff.toolsAdded > 0) {
|
|
205
|
+
output.info(` Tools added: +${diff.toolsAdded}`);
|
|
206
|
+
}
|
|
207
|
+
if (diff.toolsRemoved > 0) {
|
|
208
|
+
output.info(` Tools removed: -${diff.toolsRemoved}`);
|
|
209
|
+
}
|
|
210
|
+
if (diff.toolsModified > 0) {
|
|
211
|
+
output.info(` Tools modified: ~${diff.toolsModified}`);
|
|
212
|
+
}
|
|
213
|
+
if (diff.behaviorChanges > 0) {
|
|
214
|
+
output.info(` Behavior changes: ${diff.behaviorChanges}`);
|
|
215
|
+
}
|
|
216
|
+
if (diff.toolsAdded === 0 &&
|
|
217
|
+
diff.toolsRemoved === 0 &&
|
|
218
|
+
diff.toolsModified === 0 &&
|
|
219
|
+
diff.behaviorChanges === 0) {
|
|
220
|
+
output.info(' No changes detected');
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=upload.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* validate-config command - Validate bellwether.yaml without running tests.
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { loadConfig, ConfigNotFoundError } from '../../config/loader.js';
|
|
6
|
+
import { getConfigWarnings } from '../../config/validator.js';
|
|
7
|
+
import { EXIT_CODES, PATHS } from '../../constants.js';
|
|
8
|
+
import * as output from '../output.js';
|
|
9
|
+
export const validateConfigCommand = new Command('validate-config')
|
|
10
|
+
.description('Validate bellwether.yaml configuration without running tests')
|
|
11
|
+
.option('-c, --config <path>', 'Path to config file', PATHS.DEFAULT_CONFIG_FILENAME)
|
|
12
|
+
.action((options) => {
|
|
13
|
+
try {
|
|
14
|
+
const config = loadConfig(options.config);
|
|
15
|
+
output.success('Configuration is valid.');
|
|
16
|
+
const warnings = getConfigWarnings(config);
|
|
17
|
+
if (warnings.length > 0) {
|
|
18
|
+
output.warn('Configuration warnings:');
|
|
19
|
+
for (const warning of warnings) {
|
|
20
|
+
output.warn(` - ${warning}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
process.exit(EXIT_CODES.CLEAN);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (error instanceof ConfigNotFoundError) {
|
|
27
|
+
output.error(error.message);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
output.error(error instanceof Error ? error.message : String(error));
|
|
31
|
+
}
|
|
32
|
+
process.exit(EXIT_CODES.ERROR);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=validate-config.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verify command - generate verification reports for the Verified by Bellwether program.
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
/**
|
|
6
|
+
* Create a new verify command instance.
|
|
7
|
+
* Useful for testing where fresh command instances are needed.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createVerifyCommand(): Command;
|
|
10
|
+
export declare const verifyCommand: Command;
|
|
11
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verify command - generate verification reports for the Verified by Bellwether program.
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { writeFile } from 'fs/promises';
|
|
7
|
+
import { join } from 'path';
|
|
8
|
+
import { generateVerificationReport, generateBadgeUrl, generateBadgeMarkdown, } from '../../verification/index.js';
|
|
9
|
+
import { Interviewer, DEFAULT_CONFIG } from '../../interview/interviewer.js';
|
|
10
|
+
import { MCPClient } from '../../transport/mcp-client.js';
|
|
11
|
+
import { discover } from '../../discovery/discovery.js';
|
|
12
|
+
import { createLLMClient, DEFAULT_MODELS } from '../../llm/index.js';
|
|
13
|
+
import { loadConfig, ConfigNotFoundError } from '../../config/loader.js';
|
|
14
|
+
import { CostTracker } from '../../cost/index.js';
|
|
15
|
+
import { BUILTIN_PERSONAS } from '../../persona/builtins.js';
|
|
16
|
+
import { EXIT_CODES, PATHS } from '../../constants.js';
|
|
17
|
+
import * as output from '../output.js';
|
|
18
|
+
import { InterviewProgressBar } from '../utils/progress.js';
|
|
19
|
+
import { createCloudClient } from '../../cloud/client.js';
|
|
20
|
+
import { getLinkedProject, getSessionToken } from '../../cloud/auth.js';
|
|
21
|
+
// Convert BUILTIN_PERSONAS record to array
|
|
22
|
+
const ALL_PERSONAS = Object.values(BUILTIN_PERSONAS);
|
|
23
|
+
/**
|
|
24
|
+
* Create a new verify command instance.
|
|
25
|
+
* Useful for testing where fresh command instances are needed.
|
|
26
|
+
*/
|
|
27
|
+
export function createVerifyCommand() {
|
|
28
|
+
return new Command('verify')
|
|
29
|
+
.description('Generate a verification report for the Verified by Bellwether program')
|
|
30
|
+
.argument('[server-command]', 'Server command (overrides config)')
|
|
31
|
+
.argument('[args...]', 'Server arguments')
|
|
32
|
+
.option('-c, --config <path>', 'Path to config file', PATHS.DEFAULT_CONFIG_FILENAME)
|
|
33
|
+
.option('-o, --output <dir>', 'Output directory')
|
|
34
|
+
.option('--server-id <id>', 'Server identifier (namespace/name)')
|
|
35
|
+
.option('--version <version>', 'Server version to verify')
|
|
36
|
+
.option('--tier <tier>', 'Target verification tier (bronze, silver, gold, platinum)')
|
|
37
|
+
.option('--security', 'Include security testing (required for gold+ tiers)')
|
|
38
|
+
.option('--json', 'Output verification result as JSON')
|
|
39
|
+
.option('--badge-only', 'Only output badge URL')
|
|
40
|
+
.option('-p, --project <id>', 'Project ID to submit verification to (requires login)')
|
|
41
|
+
.action(async (serverCommandArg, serverArgs, options) => {
|
|
42
|
+
await handleVerify(serverCommandArg, serverArgs, options);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
export const verifyCommand = createVerifyCommand();
|
|
46
|
+
async function handleVerify(serverCommandArg, serverArgs, options) {
|
|
47
|
+
output.info(chalk.bold('\n🔒 Bellwether Verification\n'));
|
|
48
|
+
// Load configuration
|
|
49
|
+
let bellwetherConfig;
|
|
50
|
+
try {
|
|
51
|
+
bellwetherConfig = loadConfig(options.config);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error instanceof ConfigNotFoundError) {
|
|
55
|
+
output.error(error.message);
|
|
56
|
+
process.exit(EXIT_CODES.ERROR);
|
|
57
|
+
}
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
// Determine server command (CLI arg overrides config)
|
|
61
|
+
const serverCommand = serverCommandArg || bellwetherConfig.server.command;
|
|
62
|
+
const args = serverArgs.length > 0 ? serverArgs : bellwetherConfig.server.args;
|
|
63
|
+
if (!serverCommand) {
|
|
64
|
+
output.error('Error: No server command provided.');
|
|
65
|
+
output.error('Either specify a server command as an argument or configure it in bellwether.yaml');
|
|
66
|
+
process.exit(EXIT_CODES.ERROR);
|
|
67
|
+
}
|
|
68
|
+
// Get LLM settings from config
|
|
69
|
+
const provider = bellwetherConfig.llm.provider;
|
|
70
|
+
const model = bellwetherConfig.llm.model || undefined;
|
|
71
|
+
const outputDir = options.output ?? bellwetherConfig.output.dir;
|
|
72
|
+
const serverTimeout = bellwetherConfig.server.timeout;
|
|
73
|
+
const serverEnv = bellwetherConfig.server.env;
|
|
74
|
+
const targetTier = (options.tier ?? bellwetherConfig.verify.tier);
|
|
75
|
+
const includeSecurity = options.security ? true : bellwetherConfig.verify.security;
|
|
76
|
+
const outputJson = options.json ? true : bellwetherConfig.verify.json;
|
|
77
|
+
const badgeOnly = options.badgeOnly ? true : bellwetherConfig.verify.badgeOnly;
|
|
78
|
+
// Initialize cost tracker
|
|
79
|
+
const effectiveModel = model || DEFAULT_MODELS[provider];
|
|
80
|
+
const costTracker = new CostTracker(effectiveModel);
|
|
81
|
+
// Create LLM client with usage tracking
|
|
82
|
+
let llm;
|
|
83
|
+
try {
|
|
84
|
+
llm = createLLMClient({
|
|
85
|
+
provider: provider,
|
|
86
|
+
model,
|
|
87
|
+
onUsage: (inputTokens, outputTokens) => {
|
|
88
|
+
costTracker.addUsage(inputTokens, outputTokens);
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
output.error(chalk.red('Error: Could not create LLM client. Check your API keys.'));
|
|
94
|
+
process.exit(EXIT_CODES.ERROR);
|
|
95
|
+
}
|
|
96
|
+
output.info(chalk.gray(`Using model: ${effectiveModel}`));
|
|
97
|
+
// Connect to server
|
|
98
|
+
output.info(chalk.gray(`Connecting to ${serverCommand} ${args.join(' ')}...`));
|
|
99
|
+
const client = new MCPClient({ timeout: serverTimeout });
|
|
100
|
+
try {
|
|
101
|
+
await client.connect(serverCommand, args, serverEnv);
|
|
102
|
+
const discovery = await discover(client, serverCommand, args);
|
|
103
|
+
output.info(chalk.green(`✓ Connected to ${discovery.serverInfo.name} v${discovery.serverInfo.version}`));
|
|
104
|
+
output.info(chalk.gray(` ${discovery.tools.length} tools, ${discovery.prompts.length} prompts, ${(discovery.resources ?? []).length} resources`));
|
|
105
|
+
output.newline();
|
|
106
|
+
// Determine personas based on tier and security option
|
|
107
|
+
const personas = selectPersonasForTier(targetTier, includeSecurity);
|
|
108
|
+
output.info(chalk.gray(`Target tier: ${targetTier}`));
|
|
109
|
+
output.info(chalk.gray(`Using personas: ${personas.map((p) => p.name).join(', ')}`));
|
|
110
|
+
output.newline();
|
|
111
|
+
// Run interview
|
|
112
|
+
output.info(chalk.bold('Running verification test...\n'));
|
|
113
|
+
const interviewer = new Interviewer(llm, {
|
|
114
|
+
...DEFAULT_CONFIG,
|
|
115
|
+
personas,
|
|
116
|
+
maxQuestionsPerTool: targetTier === 'platinum' ? 5 : targetTier === 'gold' ? 4 : 3,
|
|
117
|
+
});
|
|
118
|
+
// Set up progress bar
|
|
119
|
+
const progressBar = new InterviewProgressBar({ enabled: !output.isQuiet() });
|
|
120
|
+
const progressCallback = (progress) => {
|
|
121
|
+
if (progress.phase === 'starting') {
|
|
122
|
+
progressBar.start(progress.totalTools, progress.totalPersonas, progress.totalPrompts ?? 0, progress.totalResources ?? 0);
|
|
123
|
+
}
|
|
124
|
+
else if (['interviewing', 'prompts', 'resources'].includes(progress.phase)) {
|
|
125
|
+
progressBar.update(progress);
|
|
126
|
+
}
|
|
127
|
+
else if (progress.phase === 'complete' || progress.phase === 'synthesizing') {
|
|
128
|
+
progressBar.stop();
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
const interview = await interviewer.interview(client, discovery, progressCallback);
|
|
132
|
+
progressBar.stop();
|
|
133
|
+
output.newline();
|
|
134
|
+
output.info(chalk.green('✓ Test complete'));
|
|
135
|
+
// Display cost summary
|
|
136
|
+
const costEstimate = costTracker.getCost();
|
|
137
|
+
const usage = costEstimate.usage;
|
|
138
|
+
if (usage.totalTokens > 0) {
|
|
139
|
+
const costStr = costEstimate.costUSD > 0
|
|
140
|
+
? `$${costEstimate.costUSD.toFixed(4)}`
|
|
141
|
+
: 'Free (local model)';
|
|
142
|
+
output.info(chalk.gray(` Tokens: ${usage.totalTokens.toLocaleString()} (${usage.inputTokens.toLocaleString()} in, ${usage.outputTokens.toLocaleString()} out)`));
|
|
143
|
+
output.info(chalk.gray(` Estimated cost: ${costStr}`));
|
|
144
|
+
}
|
|
145
|
+
output.newline();
|
|
146
|
+
// Generate verification
|
|
147
|
+
const serverId = options.serverId ?? `${discovery.serverInfo.name}`;
|
|
148
|
+
const verificationConfig = {
|
|
149
|
+
serverId,
|
|
150
|
+
version: options.version ?? discovery.serverInfo.version,
|
|
151
|
+
targetTier,
|
|
152
|
+
includeSecurity,
|
|
153
|
+
outputDir,
|
|
154
|
+
};
|
|
155
|
+
const report = generateVerificationReport(interview, verificationConfig);
|
|
156
|
+
const result = report.result;
|
|
157
|
+
// Output results
|
|
158
|
+
if (badgeOnly) {
|
|
159
|
+
output.info(generateBadgeUrl(result));
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (outputJson) {
|
|
163
|
+
output.json(report);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Display verification result
|
|
167
|
+
displayVerificationResult(result);
|
|
168
|
+
// Save report
|
|
169
|
+
const reportPath = join(outputDir, bellwetherConfig.output.files.verificationReport);
|
|
170
|
+
await writeFile(reportPath, JSON.stringify(report, null, 2));
|
|
171
|
+
output.info(chalk.gray(`\nReport saved to: ${reportPath}`));
|
|
172
|
+
// Display badge
|
|
173
|
+
output.info('\n' + chalk.bold('Badge:'));
|
|
174
|
+
output.info(chalk.cyan(generateBadgeUrl(result)));
|
|
175
|
+
output.newline();
|
|
176
|
+
output.info(chalk.bold('Markdown:'));
|
|
177
|
+
output.info(chalk.gray(generateBadgeMarkdown(result)));
|
|
178
|
+
// Submit to cloud if project ID is specified
|
|
179
|
+
const projectId = options.project ?? getLinkedProject()?.projectId;
|
|
180
|
+
if (projectId) {
|
|
181
|
+
output.newline();
|
|
182
|
+
// Check if logged in
|
|
183
|
+
if (!getSessionToken()) {
|
|
184
|
+
output.warn(chalk.yellow('⚠ Not logged in. Run `bellwether login` to submit verification to the platform.'));
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
output.info(chalk.gray('Submitting verification to platform...'));
|
|
188
|
+
try {
|
|
189
|
+
const cloudClient = createCloudClient();
|
|
190
|
+
// Convert local result to cloud format
|
|
191
|
+
const cloudResult = {
|
|
192
|
+
serverId: result.serverId,
|
|
193
|
+
version: result.version,
|
|
194
|
+
status: result.status,
|
|
195
|
+
tier: result.tier,
|
|
196
|
+
verifiedAt: result.verifiedAt,
|
|
197
|
+
expiresAt: result.expiresAt,
|
|
198
|
+
toolsVerified: result.toolsVerified,
|
|
199
|
+
testsPassed: result.testsPassed,
|
|
200
|
+
testsTotal: result.testsTotal,
|
|
201
|
+
passRate: result.passRate,
|
|
202
|
+
reportHash: result.reportHash,
|
|
203
|
+
bellwetherVersion: result.bellwetherVersion,
|
|
204
|
+
};
|
|
205
|
+
const submission = await cloudClient.submitVerification(projectId, cloudResult, report);
|
|
206
|
+
output.info(chalk.green(`✓ Verification submitted successfully`));
|
|
207
|
+
output.info(chalk.gray(` View at: ${submission.viewUrl}`));
|
|
208
|
+
}
|
|
209
|
+
catch (submitError) {
|
|
210
|
+
output.error(chalk.red(`Failed to submit verification: ${submitError instanceof Error ? submitError.message : 'Unknown error'}`));
|
|
211
|
+
// Don't exit with error - local verification succeeded
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// Exit with appropriate code
|
|
216
|
+
if (result.status !== 'verified') {
|
|
217
|
+
process.exit(EXIT_CODES.ERROR);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
output.error(chalk.red(`\nError: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
222
|
+
process.exit(EXIT_CODES.ERROR);
|
|
223
|
+
}
|
|
224
|
+
finally {
|
|
225
|
+
await client.disconnect();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function selectPersonasForTier(tier, includeSecurity) {
|
|
229
|
+
switch (tier) {
|
|
230
|
+
case 'platinum':
|
|
231
|
+
// All personas including security
|
|
232
|
+
return ALL_PERSONAS;
|
|
233
|
+
case 'gold':
|
|
234
|
+
// Technical Writer, QA Engineer, Security Tester
|
|
235
|
+
if (includeSecurity) {
|
|
236
|
+
return ALL_PERSONAS.filter((p) => ['technical_writer', 'qa_engineer', 'security_tester'].includes(p.id));
|
|
237
|
+
}
|
|
238
|
+
return ALL_PERSONAS.filter((p) => ['technical_writer', 'qa_engineer', 'novice_user'].includes(p.id));
|
|
239
|
+
case 'silver':
|
|
240
|
+
// Technical Writer and QA Engineer
|
|
241
|
+
return ALL_PERSONAS.filter((p) => ['technical_writer', 'qa_engineer'].includes(p.id));
|
|
242
|
+
case 'bronze':
|
|
243
|
+
default:
|
|
244
|
+
// Just Technical Writer
|
|
245
|
+
return ALL_PERSONAS.filter((p) => p.id === 'technical_writer');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function displayVerificationResult(result) {
|
|
249
|
+
const statusColor = result.status === 'verified' ? chalk.green : chalk.red;
|
|
250
|
+
const tierColor = getTierChalk(result.tier);
|
|
251
|
+
output.info('─'.repeat(60));
|
|
252
|
+
output.newline();
|
|
253
|
+
output.info(chalk.bold('Verification Result'));
|
|
254
|
+
output.newline();
|
|
255
|
+
output.info(` Server: ${result.serverId} v${result.version}`);
|
|
256
|
+
output.info(` Status: ${statusColor(result.status.toUpperCase())}`);
|
|
257
|
+
if (result.tier) {
|
|
258
|
+
output.info(` Tier: ${tierColor(result.tier.toUpperCase())}`);
|
|
259
|
+
}
|
|
260
|
+
output.newline();
|
|
261
|
+
output.info(` Pass Rate: ${result.passRate}% (${result.testsPassed}/${result.testsTotal} tests)`);
|
|
262
|
+
output.info(` Tools: ${result.toolsVerified} verified`);
|
|
263
|
+
output.newline();
|
|
264
|
+
output.info(` Verified: ${new Date(result.verifiedAt).toLocaleDateString()}`);
|
|
265
|
+
output.info(` Expires: ${new Date(result.expiresAt).toLocaleDateString()}`);
|
|
266
|
+
output.newline();
|
|
267
|
+
output.info('─'.repeat(60));
|
|
268
|
+
}
|
|
269
|
+
function getTierChalk(tier) {
|
|
270
|
+
switch (tier) {
|
|
271
|
+
case 'platinum':
|
|
272
|
+
return (text) => chalk.cyan(text);
|
|
273
|
+
case 'gold':
|
|
274
|
+
return (text) => chalk.yellow(text);
|
|
275
|
+
case 'silver':
|
|
276
|
+
return (text) => chalk.gray(text);
|
|
277
|
+
case 'bronze':
|
|
278
|
+
return (text) => chalk.hex('#CD7F32')(text);
|
|
279
|
+
default:
|
|
280
|
+
return (text) => text;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Watch command - watch for file changes and auto-check.
|
|
3
|
+
*
|
|
4
|
+
* Uses bellwether.yaml for configuration.
|
|
5
|
+
* Only watch-specific options are available as flags.
|
|
6
|
+
*
|
|
7
|
+
* Note: Watch mode only runs schema validation (check mode).
|
|
8
|
+
* For LLM-powered exploration, use 'bellwether explore' directly.
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from 'commander';
|
|
11
|
+
export declare const watchCommand: Command;
|
|
12
|
+
//# sourceMappingURL=watch.d.ts.map
|