bmad-method 6.0.5-next.8 → 6.1.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/package.json +1 -1
- package/src/bmm/agents/analyst.agent.yaml +1 -1
- package/src/bmm/module-help.csv +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md +31 -13
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +1 -1
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +6 -2
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +1 -1
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/templates/epics-template.md +4 -0
- package/src/bmm/workflows/4-implementation/code-review/workflow.md +4 -7
- package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/workflow.md +0 -4
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +1 -1
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +1 -1
- package/src/bmm/workflows/generate-project-context/steps/step-02-generate.md +1 -1
- package/src/core/module-help.csv +2 -2
- package/src/core/workflows/bmad-brainstorming/SKILL.md +6 -0
- package/src/core/workflows/bmad-brainstorming/bmad-skill-manifest.yaml +1 -0
- package/src/core/workflows/{brainstorming → bmad-brainstorming}/workflow.md +2 -5
- package/src/core/workflows/bmad-party-mode/SKILL.md +6 -0
- package/src/core/workflows/bmad-party-mode/bmad-skill-manifest.yaml +1 -0
- package/src/core/workflows/{party-mode → bmad-party-mode}/steps/step-03-graceful-exit.md +0 -1
- package/src/core/workflows/{party-mode → bmad-party-mode}/workflow.md +0 -4
- package/tools/cli/external-official-modules.yaml +18 -18
- package/tools/cli/installers/lib/core/installer.js +25 -8
- package/tools/cli/installers/lib/ide/_base-ide.js +0 -1
- package/tools/cli/installers/lib/ide/_config-driven.js +9 -4
- package/tools/cli/installers/lib/ide/manager.js +3 -3
- package/tools/cli/lib/agent/compiler.js +1 -1
- package/.augment/code_review_guidelines.yaml +0 -231
- package/.coderabbit.yaml +0 -85
- package/.github/CODE_OF_CONDUCT.md +0 -128
- package/.github/FUNDING.yaml +0 -15
- package/.github/ISSUE_TEMPLATE/bug-report.yaml +0 -124
- package/.github/ISSUE_TEMPLATE/config.yaml +0 -8
- package/.github/ISSUE_TEMPLATE/documentation.yaml +0 -55
- package/.github/ISSUE_TEMPLATE/feature-request.md +0 -22
- package/.github/ISSUE_TEMPLATE/issue.md +0 -32
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -13
- package/.github/scripts/discord-helpers.sh +0 -34
- package/.github/workflows/coderabbit-review.yaml +0 -22
- package/.github/workflows/discord.yaml +0 -90
- package/.github/workflows/docs.yaml +0 -64
- package/.github/workflows/publish.yaml +0 -133
- package/.github/workflows/quality.yaml +0 -116
- package/.husky/pre-commit +0 -20
- package/.markdownlint-cli2.yaml +0 -41
- package/.nvmrc +0 -1
- package/.prettierignore +0 -12
- package/.vscode/settings.json +0 -96
- package/CHANGELOG.md +0 -1785
- package/CNAME +0 -1
- package/CONTRIBUTING.md +0 -176
- package/CONTRIBUTORS.md +0 -32
- package/SECURITY.md +0 -85
- package/TRADEMARK.md +0 -55
- package/Wordmark.png +0 -0
- package/banner-bmad-method.png +0 -0
- package/docs/404.md +0 -9
- package/docs/_STYLE_GUIDE.md +0 -370
- package/docs/explanation/advanced-elicitation.md +0 -49
- package/docs/explanation/adversarial-review.md +0 -59
- package/docs/explanation/brainstorming.md +0 -33
- package/docs/explanation/established-projects-faq.md +0 -50
- package/docs/explanation/party-mode.md +0 -59
- package/docs/explanation/preventing-agent-conflicts.md +0 -112
- package/docs/explanation/project-context.md +0 -157
- package/docs/explanation/quick-dev-new-preview.md +0 -73
- package/docs/explanation/quick-flow.md +0 -77
- package/docs/explanation/why-solutioning-matters.md +0 -77
- package/docs/how-to/customize-bmad.md +0 -172
- package/docs/how-to/established-projects.md +0 -117
- package/docs/how-to/get-answers-about-bmad.md +0 -138
- package/docs/how-to/install-bmad.md +0 -116
- package/docs/how-to/non-interactive-installation.md +0 -171
- package/docs/how-to/project-context.md +0 -136
- package/docs/how-to/quick-fixes.md +0 -123
- package/docs/how-to/shard-large-documents.md +0 -78
- package/docs/how-to/upgrade-to-v6.md +0 -100
- package/docs/index.md +0 -60
- package/docs/reference/agents.md +0 -28
- package/docs/reference/commands.md +0 -145
- package/docs/reference/modules.md +0 -76
- package/docs/reference/testing.md +0 -106
- package/docs/reference/workflow-map.md +0 -89
- package/docs/roadmap.mdx +0 -136
- package/docs/tutorials/getting-started.md +0 -275
- package/docs/zh-cn/404.md +0 -9
- package/docs/zh-cn/_STYLE_GUIDE.md +0 -370
- package/docs/zh-cn/explanation/advanced-elicitation.md +0 -62
- package/docs/zh-cn/explanation/adversarial-review.md +0 -71
- package/docs/zh-cn/explanation/brainstorming.md +0 -43
- package/docs/zh-cn/explanation/established-projects-faq.md +0 -60
- package/docs/zh-cn/explanation/party-mode.md +0 -79
- package/docs/zh-cn/explanation/preventing-agent-conflicts.md +0 -137
- package/docs/zh-cn/explanation/project-context.md +0 -176
- package/docs/zh-cn/explanation/quick-flow.md +0 -93
- package/docs/zh-cn/explanation/why-solutioning-matters.md +0 -90
- package/docs/zh-cn/how-to/customize-bmad.md +0 -182
- package/docs/zh-cn/how-to/established-projects.md +0 -134
- package/docs/zh-cn/how-to/get-answers-about-bmad.md +0 -144
- package/docs/zh-cn/how-to/install-bmad.md +0 -105
- package/docs/zh-cn/how-to/non-interactive-installation.md +0 -181
- package/docs/zh-cn/how-to/project-context.md +0 -152
- package/docs/zh-cn/how-to/quick-fixes.md +0 -140
- package/docs/zh-cn/how-to/shard-large-documents.md +0 -86
- package/docs/zh-cn/how-to/upgrade-to-v6.md +0 -120
- package/docs/zh-cn/index.md +0 -69
- package/docs/zh-cn/reference/agents.md +0 -41
- package/docs/zh-cn/reference/commands.md +0 -166
- package/docs/zh-cn/reference/modules.md +0 -94
- package/docs/zh-cn/reference/testing.md +0 -122
- package/docs/zh-cn/reference/workflow-map.md +0 -104
- package/docs/zh-cn/roadmap.mdx +0 -152
- package/docs/zh-cn/tutorials/getting-started.md +0 -300
- package/eslint.config.mjs +0 -141
- package/prettier.config.mjs +0 -32
- package/src/core/workflows/brainstorming/bmad-skill-manifest.yaml +0 -3
- package/src/core/workflows/party-mode/bmad-skill-manifest.yaml +0 -3
- package/test/README.md +0 -295
- package/test/adversarial-review-tests/README.md +0 -56
- package/test/adversarial-review-tests/sample-content.md +0 -46
- package/test/adversarial-review-tests/test-cases.yaml +0 -103
- package/test/fixtures/agent-schema/invalid/critical-actions/actions-as-string.agent.yaml +0 -27
- package/test/fixtures/agent-schema/invalid/critical-actions/empty-string-in-actions.agent.yaml +0 -30
- package/test/fixtures/agent-schema/invalid/menu/empty-menu.agent.yaml +0 -22
- package/test/fixtures/agent-schema/invalid/menu/missing-menu.agent.yaml +0 -20
- package/test/fixtures/agent-schema/invalid/menu-commands/empty-command-target.agent.yaml +0 -25
- package/test/fixtures/agent-schema/invalid/menu-commands/no-command-target.agent.yaml +0 -24
- package/test/fixtures/agent-schema/invalid/menu-triggers/camel-case.agent.yaml +0 -25
- package/test/fixtures/agent-schema/invalid/menu-triggers/compound-invalid-format.agent.yaml +0 -25
- package/test/fixtures/agent-schema/invalid/menu-triggers/compound-mismatched-kebab.agent.yaml +0 -25
- package/test/fixtures/agent-schema/invalid/menu-triggers/duplicate-triggers.agent.yaml +0 -31
- package/test/fixtures/agent-schema/invalid/menu-triggers/empty-trigger.agent.yaml +0 -25
- package/test/fixtures/agent-schema/invalid/menu-triggers/leading-asterisk.agent.yaml +0 -25
- package/test/fixtures/agent-schema/invalid/menu-triggers/snake-case.agent.yaml +0 -25
- package/test/fixtures/agent-schema/invalid/menu-triggers/trigger-with-spaces.agent.yaml +0 -25
- package/test/fixtures/agent-schema/invalid/metadata/empty-module-string.agent.yaml +0 -26
- package/test/fixtures/agent-schema/invalid/metadata/empty-name.agent.yaml +0 -24
- package/test/fixtures/agent-schema/invalid/metadata/extra-metadata-fields.agent.yaml +0 -27
- package/test/fixtures/agent-schema/invalid/metadata/missing-id.agent.yaml +0 -23
- package/test/fixtures/agent-schema/invalid/persona/empty-principles-array.agent.yaml +0 -24
- package/test/fixtures/agent-schema/invalid/persona/empty-string-in-principles.agent.yaml +0 -27
- package/test/fixtures/agent-schema/invalid/persona/extra-persona-fields.agent.yaml +0 -27
- package/test/fixtures/agent-schema/invalid/persona/missing-role.agent.yaml +0 -24
- package/test/fixtures/agent-schema/invalid/prompts/empty-content.agent.yaml +0 -29
- package/test/fixtures/agent-schema/invalid/prompts/extra-prompt-fields.agent.yaml +0 -31
- package/test/fixtures/agent-schema/invalid/prompts/missing-content.agent.yaml +0 -28
- package/test/fixtures/agent-schema/invalid/prompts/missing-id.agent.yaml +0 -28
- package/test/fixtures/agent-schema/invalid/top-level/empty-file.agent.yaml +0 -5
- package/test/fixtures/agent-schema/invalid/top-level/extra-top-level-keys.agent.yaml +0 -28
- package/test/fixtures/agent-schema/invalid/top-level/missing-agent-key.agent.yaml +0 -11
- package/test/fixtures/agent-schema/invalid/yaml-errors/invalid-indentation.agent.yaml +0 -19
- package/test/fixtures/agent-schema/invalid/yaml-errors/malformed-yaml.agent.yaml +0 -18
- package/test/fixtures/agent-schema/valid/critical-actions/empty-critical-actions.agent.yaml +0 -24
- package/test/fixtures/agent-schema/valid/critical-actions/no-critical-actions.agent.yaml +0 -22
- package/test/fixtures/agent-schema/valid/critical-actions/valid-critical-actions.agent.yaml +0 -27
- package/test/fixtures/agent-schema/valid/menu/multiple-menu-items.agent.yaml +0 -31
- package/test/fixtures/agent-schema/valid/menu/single-menu-item.agent.yaml +0 -22
- package/test/fixtures/agent-schema/valid/menu-commands/all-command-types.agent.yaml +0 -38
- package/test/fixtures/agent-schema/valid/menu-commands/multiple-commands.agent.yaml +0 -23
- package/test/fixtures/agent-schema/valid/menu-triggers/compound-triggers.agent.yaml +0 -31
- package/test/fixtures/agent-schema/valid/menu-triggers/kebab-case-triggers.agent.yaml +0 -34
- package/test/fixtures/agent-schema/valid/metadata/core-agent-with-module.agent.yaml +0 -24
- package/test/fixtures/agent-schema/valid/metadata/empty-module-name-in-path.agent.yaml +0 -24
- package/test/fixtures/agent-schema/valid/metadata/malformed-path-treated-as-core.agent.yaml +0 -24
- package/test/fixtures/agent-schema/valid/metadata/module-agent-correct.agent.yaml +0 -24
- package/test/fixtures/agent-schema/valid/metadata/module-agent-missing-module.agent.yaml +0 -23
- package/test/fixtures/agent-schema/valid/metadata/wrong-module-value.agent.yaml +0 -24
- package/test/fixtures/agent-schema/valid/persona/complete-persona.agent.yaml +0 -24
- package/test/fixtures/agent-schema/valid/prompts/empty-prompts.agent.yaml +0 -24
- package/test/fixtures/agent-schema/valid/prompts/no-prompts.agent.yaml +0 -22
- package/test/fixtures/agent-schema/valid/prompts/valid-prompts-minimal.agent.yaml +0 -28
- package/test/fixtures/agent-schema/valid/prompts/valid-prompts-with-description.agent.yaml +0 -30
- package/test/fixtures/agent-schema/valid/top-level/minimal-core-agent.agent.yaml +0 -24
- package/test/fixtures/file-refs-csv/invalid/all-empty-workflow.csv +0 -3
- package/test/fixtures/file-refs-csv/invalid/empty-data.csv +0 -1
- package/test/fixtures/file-refs-csv/invalid/no-workflow-column.csv +0 -3
- package/test/fixtures/file-refs-csv/invalid/unresolvable-vars.csv +0 -3
- package/test/fixtures/file-refs-csv/valid/bmm-style.csv +0 -3
- package/test/fixtures/file-refs-csv/valid/core-style.csv +0 -3
- package/test/fixtures/file-refs-csv/valid/minimal.csv +0 -2
- package/test/test-agent-schema.js +0 -387
- package/test/test-cli-integration.sh +0 -159
- package/test/test-file-refs-csv.js +0 -133
- package/test/test-install-to-bmad.js +0 -154
- package/test/test-installation-components.js +0 -1796
- package/test/test-rehype-plugins.mjs +0 -1050
- package/test/test-workflow-path-regex.js +0 -88
- package/test/unit-test-schema.js +0 -133
- package/tools/build-docs.mjs +0 -464
- package/tools/docs/_prompt-external-modules-page.md +0 -59
- package/tools/docs/fix-refs.md +0 -91
- package/tools/docs/native-skills-migration-checklist.md +0 -281
- package/tools/fix-doc-links.js +0 -285
- package/tools/validate-agent-schema.js +0 -110
- package/tools/validate-doc-links.js +0 -407
- package/tools/validate-file-refs.js +0 -556
- package/website/README.md +0 -75
- package/website/astro.config.mjs +0 -157
- package/website/public/diagrams/quick-dev-diagram.png +0 -0
- package/website/public/favicon.ico +0 -0
- package/website/public/img/bmad-dark.png +0 -0
- package/website/public/img/bmad-light.png +0 -0
- package/website/public/workflow-map-diagram.html +0 -361
- package/website/src/components/Banner.astro +0 -62
- package/website/src/components/Header.astro +0 -96
- package/website/src/components/MobileMenuFooter.astro +0 -33
- package/website/src/content/config.ts +0 -7
- package/website/src/content/i18n/zh-CN.json +0 -28
- package/website/src/lib/site-url.mjs +0 -25
- package/website/src/pages/404.astro +0 -11
- package/website/src/pages/robots.txt.ts +0 -48
- package/website/src/rehype-base-paths.js +0 -112
- package/website/src/rehype-markdown-links.js +0 -119
- package/website/src/styles/custom.css +0 -805
- /package/src/core/workflows/{brainstorming → bmad-brainstorming}/brain-methods.csv +0 -0
- /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-01-session-setup.md +0 -0
- /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-01b-continue.md +0 -0
- /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-02a-user-selected.md +0 -0
- /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-02b-ai-recommended.md +0 -0
- /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-02c-random-selection.md +0 -0
- /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-02d-progressive-flow.md +0 -0
- /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-03-technique-execution.md +0 -0
- /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-04-idea-organization.md +0 -0
- /package/src/core/workflows/{brainstorming → bmad-brainstorming}/template.md +0 -0
- /package/src/core/workflows/{party-mode → bmad-party-mode}/steps/step-01-agent-loading.md +0 -0
- /package/src/core/workflows/{party-mode → bmad-party-mode}/steps/step-02-discussion-orchestration.md +0 -0
|
@@ -1,387 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Schema Validation Test Runner
|
|
3
|
-
*
|
|
4
|
-
* Runs all test fixtures and verifies expected outcomes.
|
|
5
|
-
* Reports pass/fail for each test and overall coverage statistics.
|
|
6
|
-
*
|
|
7
|
-
* Usage: node test/test-agent-schema.js
|
|
8
|
-
* Exit codes: 0 = all tests pass, 1 = test failures
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const fs = require('node:fs');
|
|
12
|
-
const path = require('node:path');
|
|
13
|
-
const yaml = require('yaml');
|
|
14
|
-
const { validateAgentFile } = require('../tools/schema/agent.js');
|
|
15
|
-
const { glob } = require('glob');
|
|
16
|
-
|
|
17
|
-
// ANSI color codes
|
|
18
|
-
const colors = {
|
|
19
|
-
reset: '\u001B[0m',
|
|
20
|
-
green: '\u001B[32m',
|
|
21
|
-
red: '\u001B[31m',
|
|
22
|
-
yellow: '\u001B[33m',
|
|
23
|
-
blue: '\u001B[34m',
|
|
24
|
-
cyan: '\u001B[36m',
|
|
25
|
-
dim: '\u001B[2m',
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Parse test metadata from YAML comments
|
|
30
|
-
* @param {string} filePath
|
|
31
|
-
* @returns {{shouldPass: boolean, errorExpectation?: object, pathContext?: string}}
|
|
32
|
-
*/
|
|
33
|
-
function parseTestMetadata(filePath) {
|
|
34
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
35
|
-
const lines = content.split('\n');
|
|
36
|
-
|
|
37
|
-
let shouldPass = true;
|
|
38
|
-
let pathContext = null;
|
|
39
|
-
const errorExpectation = {};
|
|
40
|
-
|
|
41
|
-
for (const line of lines) {
|
|
42
|
-
if (line.includes('Expected: PASS')) {
|
|
43
|
-
shouldPass = true;
|
|
44
|
-
} else if (line.includes('Expected: FAIL')) {
|
|
45
|
-
shouldPass = false;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Parse error metadata
|
|
49
|
-
const codeMatch = line.match(/^# Error code: (.+)$/);
|
|
50
|
-
if (codeMatch) {
|
|
51
|
-
errorExpectation.code = codeMatch[1].trim();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const pathMatch = line.match(/^# Error path: (.+)$/);
|
|
55
|
-
if (pathMatch) {
|
|
56
|
-
errorExpectation.path = pathMatch[1].trim();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const messageMatch = line.match(/^# Error message: (.+)$/);
|
|
60
|
-
if (messageMatch) {
|
|
61
|
-
errorExpectation.message = messageMatch[1].trim();
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const minimumMatch = line.match(/^# Error minimum: (\d+)$/);
|
|
65
|
-
if (minimumMatch) {
|
|
66
|
-
errorExpectation.minimum = parseInt(minimumMatch[1], 10);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const expectedMatch = line.match(/^# Error expected: (.+)$/);
|
|
70
|
-
if (expectedMatch) {
|
|
71
|
-
errorExpectation.expected = expectedMatch[1].trim();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const receivedMatch = line.match(/^# Error received: (.+)$/);
|
|
75
|
-
if (receivedMatch) {
|
|
76
|
-
errorExpectation.received = receivedMatch[1].trim();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const keysMatch = line.match(/^# Error keys: \[(.+)\]$/);
|
|
80
|
-
if (keysMatch) {
|
|
81
|
-
errorExpectation.keys = keysMatch[1].split(',').map((k) => k.trim().replaceAll(/['"]/g, ''));
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const contextMatch = line.match(/^# Path context: (.+)$/);
|
|
85
|
-
if (contextMatch) {
|
|
86
|
-
pathContext = contextMatch[1].trim();
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return {
|
|
91
|
-
shouldPass,
|
|
92
|
-
errorExpectation: Object.keys(errorExpectation).length > 0 ? errorExpectation : null,
|
|
93
|
-
pathContext,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Convert dot-notation path string to array (handles array indices)
|
|
99
|
-
* e.g., "agent.menu[0].trigger" => ["agent", "menu", 0, "trigger"]
|
|
100
|
-
*/
|
|
101
|
-
function parsePathString(pathString) {
|
|
102
|
-
return pathString
|
|
103
|
-
.replaceAll(/\[(\d+)\]/g, '.$1') // Convert [0] to .0
|
|
104
|
-
.split('.')
|
|
105
|
-
.map((part) => {
|
|
106
|
-
const num = parseInt(part, 10);
|
|
107
|
-
return isNaN(num) ? part : num;
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Validate error against expectations
|
|
113
|
-
* @param {object} error - Zod error issue
|
|
114
|
-
* @param {object} expectation - Expected error structure
|
|
115
|
-
* @returns {{valid: boolean, reason?: string}}
|
|
116
|
-
*/
|
|
117
|
-
function validateError(error, expectation) {
|
|
118
|
-
// Check error code
|
|
119
|
-
if (expectation.code && error.code !== expectation.code) {
|
|
120
|
-
return { valid: false, reason: `Expected code "${expectation.code}", got "${error.code}"` };
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Check error path
|
|
124
|
-
if (expectation.path) {
|
|
125
|
-
const expectedPath = parsePathString(expectation.path);
|
|
126
|
-
const actualPath = error.path;
|
|
127
|
-
|
|
128
|
-
if (JSON.stringify(expectedPath) !== JSON.stringify(actualPath)) {
|
|
129
|
-
return {
|
|
130
|
-
valid: false,
|
|
131
|
-
reason: `Expected path ${JSON.stringify(expectedPath)}, got ${JSON.stringify(actualPath)}`,
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// For custom errors, strictly check message
|
|
137
|
-
if (expectation.code === 'custom' && expectation.message && error.message !== expectation.message) {
|
|
138
|
-
return {
|
|
139
|
-
valid: false,
|
|
140
|
-
reason: `Expected message "${expectation.message}", got "${error.message}"`,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// For Zod errors, check type-specific fields
|
|
145
|
-
if (expectation.minimum !== undefined && error.minimum !== expectation.minimum) {
|
|
146
|
-
return { valid: false, reason: `Expected minimum ${expectation.minimum}, got ${error.minimum}` };
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (expectation.expected && error.expected !== expectation.expected) {
|
|
150
|
-
return { valid: false, reason: `Expected type "${expectation.expected}", got "${error.expected}"` };
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (expectation.received && error.received !== expectation.received) {
|
|
154
|
-
return { valid: false, reason: `Expected received "${expectation.received}", got "${error.received}"` };
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (expectation.keys) {
|
|
158
|
-
const expectedKeys = expectation.keys.sort();
|
|
159
|
-
const actualKeys = (error.keys || []).sort();
|
|
160
|
-
if (JSON.stringify(expectedKeys) !== JSON.stringify(actualKeys)) {
|
|
161
|
-
return {
|
|
162
|
-
valid: false,
|
|
163
|
-
reason: `Expected keys ${JSON.stringify(expectedKeys)}, got ${JSON.stringify(actualKeys)}`,
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return { valid: true };
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Run a single test case
|
|
173
|
-
* @param {string} filePath
|
|
174
|
-
* @returns {{passed: boolean, message: string}}
|
|
175
|
-
*/
|
|
176
|
-
function runTest(filePath) {
|
|
177
|
-
const metadata = parseTestMetadata(filePath);
|
|
178
|
-
const { shouldPass, errorExpectation, pathContext } = metadata;
|
|
179
|
-
|
|
180
|
-
try {
|
|
181
|
-
const fileContent = fs.readFileSync(filePath, 'utf8');
|
|
182
|
-
let agentData;
|
|
183
|
-
|
|
184
|
-
try {
|
|
185
|
-
agentData = yaml.parse(fileContent);
|
|
186
|
-
} catch (parseError) {
|
|
187
|
-
// YAML parse error
|
|
188
|
-
if (shouldPass) {
|
|
189
|
-
return {
|
|
190
|
-
passed: false,
|
|
191
|
-
message: `Expected PASS but got YAML parse error: ${parseError.message}`,
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
return {
|
|
195
|
-
passed: true,
|
|
196
|
-
message: 'Got expected YAML parse error',
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Determine validation path
|
|
201
|
-
// If pathContext is specified in comments, use it; otherwise derive from fixture location
|
|
202
|
-
let validationPath = pathContext;
|
|
203
|
-
if (!validationPath) {
|
|
204
|
-
// Map fixture location to simulated src/ path
|
|
205
|
-
const relativePath = path.relative(path.join(__dirname, 'fixtures/agent-schema'), filePath);
|
|
206
|
-
const parts = relativePath.split(path.sep);
|
|
207
|
-
|
|
208
|
-
if (parts.includes('metadata') && parts[0] === 'valid') {
|
|
209
|
-
// Valid metadata tests: check if filename suggests module or core
|
|
210
|
-
const filename = path.basename(filePath);
|
|
211
|
-
if (filename.includes('module')) {
|
|
212
|
-
validationPath = 'src/bmm/agents/test.agent.yaml';
|
|
213
|
-
} else {
|
|
214
|
-
validationPath = 'src/core/agents/test.agent.yaml';
|
|
215
|
-
}
|
|
216
|
-
} else if (parts.includes('metadata') && parts[0] === 'invalid') {
|
|
217
|
-
// Invalid metadata tests: derive from filename
|
|
218
|
-
const filename = path.basename(filePath);
|
|
219
|
-
if (filename.includes('module') || filename.includes('wrong-module')) {
|
|
220
|
-
validationPath = 'src/bmm/agents/test.agent.yaml';
|
|
221
|
-
} else if (filename.includes('core')) {
|
|
222
|
-
validationPath = 'src/core/agents/test.agent.yaml';
|
|
223
|
-
} else {
|
|
224
|
-
validationPath = 'src/core/agents/test.agent.yaml';
|
|
225
|
-
}
|
|
226
|
-
} else {
|
|
227
|
-
// Default to core agent path
|
|
228
|
-
validationPath = 'src/core/agents/test.agent.yaml';
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const result = validateAgentFile(validationPath, agentData);
|
|
233
|
-
|
|
234
|
-
if (result.success && shouldPass) {
|
|
235
|
-
return {
|
|
236
|
-
passed: true,
|
|
237
|
-
message: 'Validation passed as expected',
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (!result.success && !shouldPass) {
|
|
242
|
-
const actualError = result.error.issues[0];
|
|
243
|
-
|
|
244
|
-
// If we have error expectations, validate strictly
|
|
245
|
-
if (errorExpectation) {
|
|
246
|
-
const validation = validateError(actualError, errorExpectation);
|
|
247
|
-
|
|
248
|
-
if (!validation.valid) {
|
|
249
|
-
return {
|
|
250
|
-
passed: false,
|
|
251
|
-
message: `Error validation failed: ${validation.reason}`,
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
return {
|
|
256
|
-
passed: true,
|
|
257
|
-
message: `Got expected error (${errorExpectation.code}): ${actualError.message}`,
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// No specific expectations - just check that it failed
|
|
262
|
-
return {
|
|
263
|
-
passed: true,
|
|
264
|
-
message: `Got expected validation error: ${actualError?.message}`,
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (result.success && !shouldPass) {
|
|
269
|
-
return {
|
|
270
|
-
passed: false,
|
|
271
|
-
message: 'Expected validation to FAIL but it PASSED',
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
if (!result.success && shouldPass) {
|
|
276
|
-
return {
|
|
277
|
-
passed: false,
|
|
278
|
-
message: `Expected validation to PASS but it FAILED: ${result.error.issues[0]?.message}`,
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
return {
|
|
283
|
-
passed: false,
|
|
284
|
-
message: 'Unexpected test state',
|
|
285
|
-
};
|
|
286
|
-
} catch (error) {
|
|
287
|
-
return {
|
|
288
|
-
passed: false,
|
|
289
|
-
message: `Test execution error: ${error.message}`,
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Main test runner
|
|
296
|
-
*/
|
|
297
|
-
async function main() {
|
|
298
|
-
console.log(`${colors.cyan}╔═══════════════════════════════════════════════════════════╗${colors.reset}`);
|
|
299
|
-
console.log(`${colors.cyan}║ Agent Schema Validation Test Suite ║${colors.reset}`);
|
|
300
|
-
console.log(`${colors.cyan}╚═══════════════════════════════════════════════════════════╝${colors.reset}\n`);
|
|
301
|
-
|
|
302
|
-
// Find all test fixtures
|
|
303
|
-
const testFiles = await glob('test/fixtures/agent-schema/**/*.agent.yaml', {
|
|
304
|
-
cwd: path.join(__dirname, '..'),
|
|
305
|
-
absolute: true,
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
if (testFiles.length === 0) {
|
|
309
|
-
console.log(`${colors.yellow}⚠️ No test fixtures found${colors.reset}`);
|
|
310
|
-
process.exit(0);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
console.log(`Found ${colors.cyan}${testFiles.length}${colors.reset} test fixture(s)\n`);
|
|
314
|
-
|
|
315
|
-
// Group tests by category
|
|
316
|
-
const categories = {};
|
|
317
|
-
for (const testFile of testFiles) {
|
|
318
|
-
const relativePath = path.relative(path.join(__dirname, 'fixtures/agent-schema'), testFile);
|
|
319
|
-
const parts = relativePath.split(path.sep);
|
|
320
|
-
const validInvalid = parts[0]; // 'valid' or 'invalid'
|
|
321
|
-
const category = parts[1]; // 'top-level', 'metadata', etc.
|
|
322
|
-
|
|
323
|
-
const categoryKey = `${validInvalid}/${category}`;
|
|
324
|
-
if (!categories[categoryKey]) {
|
|
325
|
-
categories[categoryKey] = [];
|
|
326
|
-
}
|
|
327
|
-
categories[categoryKey].push(testFile);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// Run tests by category
|
|
331
|
-
let totalTests = 0;
|
|
332
|
-
let passedTests = 0;
|
|
333
|
-
const failures = [];
|
|
334
|
-
|
|
335
|
-
for (const [categoryKey, files] of Object.entries(categories).sort()) {
|
|
336
|
-
const [validInvalid, category] = categoryKey.split('/');
|
|
337
|
-
const categoryLabel = category.replaceAll('-', ' ').toUpperCase();
|
|
338
|
-
const validLabel = validInvalid === 'valid' ? '✅' : '❌';
|
|
339
|
-
|
|
340
|
-
console.log(`${colors.blue}${validLabel} ${categoryLabel} (${validInvalid})${colors.reset}`);
|
|
341
|
-
|
|
342
|
-
for (const testFile of files) {
|
|
343
|
-
totalTests++;
|
|
344
|
-
const testName = path.basename(testFile, '.agent.yaml');
|
|
345
|
-
const result = runTest(testFile);
|
|
346
|
-
|
|
347
|
-
if (result.passed) {
|
|
348
|
-
passedTests++;
|
|
349
|
-
console.log(` ${colors.green}✓${colors.reset} ${testName} ${colors.dim}${result.message}${colors.reset}`);
|
|
350
|
-
} else {
|
|
351
|
-
console.log(` ${colors.red}✗${colors.reset} ${testName} ${colors.red}${result.message}${colors.reset}`);
|
|
352
|
-
failures.push({
|
|
353
|
-
file: path.relative(process.cwd(), testFile),
|
|
354
|
-
message: result.message,
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
console.log('');
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
// Summary
|
|
362
|
-
console.log(`${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}`);
|
|
363
|
-
console.log(`${colors.cyan}Test Results:${colors.reset}`);
|
|
364
|
-
console.log(` Total: ${totalTests}`);
|
|
365
|
-
console.log(` Passed: ${colors.green}${passedTests}${colors.reset}`);
|
|
366
|
-
console.log(` Failed: ${passedTests === totalTests ? colors.green : colors.red}${totalTests - passedTests}${colors.reset}`);
|
|
367
|
-
console.log(`${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}\n`);
|
|
368
|
-
|
|
369
|
-
// Report failures
|
|
370
|
-
if (failures.length > 0) {
|
|
371
|
-
console.log(`${colors.red}❌ FAILED TESTS:${colors.reset}\n`);
|
|
372
|
-
for (const failure of failures) {
|
|
373
|
-
console.log(`${colors.red}✗${colors.reset} ${failure.file}`);
|
|
374
|
-
console.log(` ${failure.message}\n`);
|
|
375
|
-
}
|
|
376
|
-
process.exit(1);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
console.log(`${colors.green}✨ All tests passed!${colors.reset}\n`);
|
|
380
|
-
process.exit(0);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// Run
|
|
384
|
-
main().catch((error) => {
|
|
385
|
-
console.error(`${colors.red}Fatal error:${colors.reset}`, error);
|
|
386
|
-
process.exit(1);
|
|
387
|
-
});
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# CLI Integration Tests for Agent Schema Validator
|
|
3
|
-
# Tests the CLI wrapper (tools/validate-agent-schema.js) behavior and error handling
|
|
4
|
-
# NOTE: Tests CLI functionality using temporary test fixtures
|
|
5
|
-
|
|
6
|
-
echo "========================================"
|
|
7
|
-
echo "CLI Integration Tests"
|
|
8
|
-
echo "========================================"
|
|
9
|
-
echo ""
|
|
10
|
-
|
|
11
|
-
# Colors
|
|
12
|
-
GREEN='\033[0;32m'
|
|
13
|
-
RED='\033[0;31m'
|
|
14
|
-
YELLOW='\033[1;33m'
|
|
15
|
-
NC='\033[0m' # No Color
|
|
16
|
-
|
|
17
|
-
PASSED=0
|
|
18
|
-
FAILED=0
|
|
19
|
-
|
|
20
|
-
# Get the repo root (assuming script is in test/ directory)
|
|
21
|
-
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
22
|
-
|
|
23
|
-
# Create temp directory for test fixtures
|
|
24
|
-
TEMP_DIR=$(mktemp -d)
|
|
25
|
-
cleanup() {
|
|
26
|
-
rm -rf "$TEMP_DIR"
|
|
27
|
-
}
|
|
28
|
-
trap cleanup EXIT
|
|
29
|
-
|
|
30
|
-
# Test 1: CLI fails when no files found (exit 1)
|
|
31
|
-
echo "Test 1: CLI fails when no agent files found (should exit 1)"
|
|
32
|
-
mkdir -p "$TEMP_DIR/empty/src/core/agents"
|
|
33
|
-
OUTPUT=$(node "$REPO_ROOT/tools/validate-agent-schema.js" "$TEMP_DIR/empty" 2>&1)
|
|
34
|
-
EXIT_CODE=$?
|
|
35
|
-
if [ $EXIT_CODE -eq 1 ] && echo "$OUTPUT" | grep -q "No agent files found"; then
|
|
36
|
-
echo -e "${GREEN}✓${NC} CLI fails correctly when no files found (exit 1)"
|
|
37
|
-
PASSED=$((PASSED + 1))
|
|
38
|
-
else
|
|
39
|
-
echo -e "${RED}✗${NC} CLI failed to handle no files properly (exit code: $EXIT_CODE)"
|
|
40
|
-
FAILED=$((FAILED + 1))
|
|
41
|
-
fi
|
|
42
|
-
echo ""
|
|
43
|
-
|
|
44
|
-
# Test 2: CLI reports validation errors with exit code 1
|
|
45
|
-
echo "Test 2: CLI reports validation errors (should exit 1)"
|
|
46
|
-
mkdir -p "$TEMP_DIR/invalid/src/core/agents"
|
|
47
|
-
cat > "$TEMP_DIR/invalid/src/core/agents/bad.agent.yaml" << 'EOF'
|
|
48
|
-
agent:
|
|
49
|
-
metadata:
|
|
50
|
-
id: bad
|
|
51
|
-
name: Bad
|
|
52
|
-
title: Bad
|
|
53
|
-
icon: 🧪
|
|
54
|
-
persona:
|
|
55
|
-
role: Test
|
|
56
|
-
identity: Test
|
|
57
|
-
communication_style: Test
|
|
58
|
-
principles: []
|
|
59
|
-
menu: []
|
|
60
|
-
EOF
|
|
61
|
-
OUTPUT=$(node "$REPO_ROOT/tools/validate-agent-schema.js" "$TEMP_DIR/invalid" 2>&1)
|
|
62
|
-
EXIT_CODE=$?
|
|
63
|
-
if [ $EXIT_CODE -eq 1 ] && echo "$OUTPUT" | grep -q "failed validation"; then
|
|
64
|
-
echo -e "${GREEN}✓${NC} CLI reports errors correctly (exit 1)"
|
|
65
|
-
PASSED=$((PASSED + 1))
|
|
66
|
-
else
|
|
67
|
-
echo -e "${RED}✗${NC} CLI failed to report errors (exit code: $EXIT_CODE)"
|
|
68
|
-
FAILED=$((FAILED + 1))
|
|
69
|
-
fi
|
|
70
|
-
echo ""
|
|
71
|
-
|
|
72
|
-
# Test 3: CLI discovers and counts agent files correctly
|
|
73
|
-
echo "Test 3: CLI discovers and counts agent files"
|
|
74
|
-
mkdir -p "$TEMP_DIR/valid/src/core/agents"
|
|
75
|
-
cat > "$TEMP_DIR/valid/src/core/agents/test1.agent.yaml" << 'EOF'
|
|
76
|
-
agent:
|
|
77
|
-
metadata:
|
|
78
|
-
id: test1
|
|
79
|
-
name: Test1
|
|
80
|
-
title: Test1
|
|
81
|
-
icon: 🧪
|
|
82
|
-
persona:
|
|
83
|
-
role: Test
|
|
84
|
-
identity: Test
|
|
85
|
-
communication_style: Test
|
|
86
|
-
principles: [Test]
|
|
87
|
-
menu:
|
|
88
|
-
- trigger: help
|
|
89
|
-
description: Help
|
|
90
|
-
action: help
|
|
91
|
-
EOF
|
|
92
|
-
cat > "$TEMP_DIR/valid/src/core/agents/test2.agent.yaml" << 'EOF'
|
|
93
|
-
agent:
|
|
94
|
-
metadata:
|
|
95
|
-
id: test2
|
|
96
|
-
name: Test2
|
|
97
|
-
title: Test2
|
|
98
|
-
icon: 🧪
|
|
99
|
-
persona:
|
|
100
|
-
role: Test
|
|
101
|
-
identity: Test
|
|
102
|
-
communication_style: Test
|
|
103
|
-
principles: [Test]
|
|
104
|
-
menu:
|
|
105
|
-
- trigger: help
|
|
106
|
-
description: Help
|
|
107
|
-
action: help
|
|
108
|
-
EOF
|
|
109
|
-
OUTPUT=$(node "$REPO_ROOT/tools/validate-agent-schema.js" "$TEMP_DIR/valid" 2>&1)
|
|
110
|
-
EXIT_CODE=$?
|
|
111
|
-
if [ $EXIT_CODE -eq 0 ] && echo "$OUTPUT" | grep -q "Found 2 agent file"; then
|
|
112
|
-
echo -e "${GREEN}✓${NC} CLI discovers and counts files correctly"
|
|
113
|
-
PASSED=$((PASSED + 1))
|
|
114
|
-
else
|
|
115
|
-
echo -e "${RED}✗${NC} CLI file discovery failed"
|
|
116
|
-
echo "Output: $OUTPUT"
|
|
117
|
-
FAILED=$((FAILED + 1))
|
|
118
|
-
fi
|
|
119
|
-
echo ""
|
|
120
|
-
|
|
121
|
-
# Test 4: CLI provides detailed error messages
|
|
122
|
-
echo "Test 4: CLI provides detailed error messages"
|
|
123
|
-
OUTPUT=$(node "$REPO_ROOT/tools/validate-agent-schema.js" "$TEMP_DIR/invalid" 2>&1)
|
|
124
|
-
if echo "$OUTPUT" | grep -q "Path:" && echo "$OUTPUT" | grep -q "Error:"; then
|
|
125
|
-
echo -e "${GREEN}✓${NC} CLI provides error details (Path and Error)"
|
|
126
|
-
PASSED=$((PASSED + 1))
|
|
127
|
-
else
|
|
128
|
-
echo -e "${RED}✗${NC} CLI error details missing"
|
|
129
|
-
FAILED=$((FAILED + 1))
|
|
130
|
-
fi
|
|
131
|
-
echo ""
|
|
132
|
-
|
|
133
|
-
# Test 5: CLI validates real BMAD agents (smoke test)
|
|
134
|
-
echo "Test 5: CLI validates actual BMAD agents (smoke test)"
|
|
135
|
-
OUTPUT=$(node "$REPO_ROOT/tools/validate-agent-schema.js" 2>&1)
|
|
136
|
-
EXIT_CODE=$?
|
|
137
|
-
if [ $EXIT_CODE -eq 0 ] && echo "$OUTPUT" | grep -qE "Found [0-9]+ agent file"; then
|
|
138
|
-
echo -e "${GREEN}✓${NC} CLI validates real BMAD agents successfully"
|
|
139
|
-
PASSED=$((PASSED + 1))
|
|
140
|
-
else
|
|
141
|
-
echo -e "${RED}✗${NC} CLI failed on real BMAD agents (exit code: $EXIT_CODE)"
|
|
142
|
-
FAILED=$((FAILED + 1))
|
|
143
|
-
fi
|
|
144
|
-
echo ""
|
|
145
|
-
|
|
146
|
-
# Summary
|
|
147
|
-
echo "========================================"
|
|
148
|
-
echo "Test Results:"
|
|
149
|
-
echo " Passed: ${GREEN}$PASSED${NC}"
|
|
150
|
-
echo " Failed: ${RED}$FAILED${NC}"
|
|
151
|
-
echo "========================================"
|
|
152
|
-
|
|
153
|
-
if [ $FAILED -eq 0 ]; then
|
|
154
|
-
echo -e "\n${GREEN}✨ All CLI integration tests passed!${NC}\n"
|
|
155
|
-
exit 0
|
|
156
|
-
else
|
|
157
|
-
echo -e "\n${RED}❌ Some CLI integration tests failed${NC}\n"
|
|
158
|
-
exit 1
|
|
159
|
-
fi
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CSV File Reference Extraction Test Runner
|
|
3
|
-
*
|
|
4
|
-
* Tests extractCsvRefs() from validate-file-refs.js against fixtures.
|
|
5
|
-
* Verifies correct extraction of workflow-file references from CSV files.
|
|
6
|
-
*
|
|
7
|
-
* Usage: node test/test-file-refs-csv.js
|
|
8
|
-
* Exit codes: 0 = all tests pass, 1 = test failures
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const fs = require('node:fs');
|
|
12
|
-
const path = require('node:path');
|
|
13
|
-
const { extractCsvRefs } = require('../tools/validate-file-refs.js');
|
|
14
|
-
|
|
15
|
-
// ANSI color codes
|
|
16
|
-
const colors = {
|
|
17
|
-
reset: '\u001B[0m',
|
|
18
|
-
green: '\u001B[32m',
|
|
19
|
-
red: '\u001B[31m',
|
|
20
|
-
cyan: '\u001B[36m',
|
|
21
|
-
dim: '\u001B[2m',
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const FIXTURES = path.join(__dirname, 'fixtures/file-refs-csv');
|
|
25
|
-
|
|
26
|
-
let totalTests = 0;
|
|
27
|
-
let passedTests = 0;
|
|
28
|
-
const failures = [];
|
|
29
|
-
|
|
30
|
-
function test(name, fn) {
|
|
31
|
-
totalTests++;
|
|
32
|
-
try {
|
|
33
|
-
fn();
|
|
34
|
-
passedTests++;
|
|
35
|
-
console.log(` ${colors.green}\u2713${colors.reset} ${name}`);
|
|
36
|
-
} catch (error) {
|
|
37
|
-
console.log(` ${colors.red}\u2717${colors.reset} ${name} ${colors.red}${error.message}${colors.reset}`);
|
|
38
|
-
failures.push({ name, message: error.message });
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function assert(condition, message) {
|
|
43
|
-
if (!condition) throw new Error(message);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function loadFixture(relativePath) {
|
|
47
|
-
const fullPath = path.join(FIXTURES, relativePath);
|
|
48
|
-
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
49
|
-
return { fullPath, content };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// --- Valid fixtures ---
|
|
53
|
-
|
|
54
|
-
console.log(`\n${colors.cyan}CSV File Reference Extraction Tests${colors.reset}\n`);
|
|
55
|
-
console.log(`${colors.cyan}Valid fixtures${colors.reset}`);
|
|
56
|
-
|
|
57
|
-
test('bmm-style.csv: extracts workflow-file refs with trailing commas', () => {
|
|
58
|
-
const { fullPath, content } = loadFixture('valid/bmm-style.csv');
|
|
59
|
-
const refs = extractCsvRefs(fullPath, content);
|
|
60
|
-
assert(refs.length === 2, `Expected 2 refs, got ${refs.length}`);
|
|
61
|
-
assert(refs[0].raw === '_bmad/bmm/workflows/document-project/workflow.md', `Wrong raw[0]: ${refs[0].raw}`);
|
|
62
|
-
assert(refs[1].raw === '_bmad/core/workflows/brainstorming/workflow.md', `Wrong raw[1]: ${refs[1].raw}`);
|
|
63
|
-
assert(refs[0].type === 'project-root', `Wrong type: ${refs[0].type}`);
|
|
64
|
-
assert(refs[0].line === 2, `Wrong line for row 0: ${refs[0].line}`);
|
|
65
|
-
assert(refs[1].line === 3, `Wrong line for row 1: ${refs[1].line}`);
|
|
66
|
-
assert(refs[0].file === fullPath, 'Wrong file path');
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
test('core-style.csv: extracts refs from core module-help format', () => {
|
|
70
|
-
const { fullPath, content } = loadFixture('valid/core-style.csv');
|
|
71
|
-
const refs = extractCsvRefs(fullPath, content);
|
|
72
|
-
assert(refs.length === 2, `Expected 2 refs, got ${refs.length}`);
|
|
73
|
-
assert(refs[0].raw === '_bmad/core/workflows/brainstorming/workflow.md', `Wrong raw[0]: ${refs[0].raw}`);
|
|
74
|
-
assert(refs[1].raw === '_bmad/core/workflows/party-mode/workflow.md', `Wrong raw[1]: ${refs[1].raw}`);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test('minimal.csv: extracts refs from minimal 3-column CSV', () => {
|
|
78
|
-
const { fullPath, content } = loadFixture('valid/minimal.csv');
|
|
79
|
-
const refs = extractCsvRefs(fullPath, content);
|
|
80
|
-
assert(refs.length === 1, `Expected 1 ref, got ${refs.length}`);
|
|
81
|
-
assert(refs[0].raw === '_bmad/core/tasks/help.md', `Wrong raw: ${refs[0].raw}`);
|
|
82
|
-
assert(refs[0].line === 2, `Wrong line: ${refs[0].line}`);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// --- Invalid fixtures ---
|
|
86
|
-
|
|
87
|
-
console.log(`\n${colors.cyan}Invalid fixtures (expect 0 refs)${colors.reset}`);
|
|
88
|
-
|
|
89
|
-
test('no-workflow-column.csv: returns 0 refs when workflow-file column missing', () => {
|
|
90
|
-
const { fullPath, content } = loadFixture('invalid/no-workflow-column.csv');
|
|
91
|
-
const refs = extractCsvRefs(fullPath, content);
|
|
92
|
-
assert(refs.length === 0, `Expected 0 refs, got ${refs.length}`);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
test('empty-data.csv: returns 0 refs when CSV has header only', () => {
|
|
96
|
-
const { fullPath, content } = loadFixture('invalid/empty-data.csv');
|
|
97
|
-
const refs = extractCsvRefs(fullPath, content);
|
|
98
|
-
assert(refs.length === 0, `Expected 0 refs, got ${refs.length}`);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
test('all-empty-workflow.csv: returns 0 refs when all workflow-file cells empty', () => {
|
|
102
|
-
const { fullPath, content } = loadFixture('invalid/all-empty-workflow.csv');
|
|
103
|
-
const refs = extractCsvRefs(fullPath, content);
|
|
104
|
-
assert(refs.length === 0, `Expected 0 refs, got ${refs.length}`);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
test('unresolvable-vars.csv: filters out template variables, keeps normal refs', () => {
|
|
108
|
-
const { fullPath, content } = loadFixture('invalid/unresolvable-vars.csv');
|
|
109
|
-
const refs = extractCsvRefs(fullPath, content);
|
|
110
|
-
assert(refs.length === 1, `Expected 1 ref, got ${refs.length}`);
|
|
111
|
-
assert(refs[0].raw === '_bmad/core/tasks/help.md', `Wrong raw: ${refs[0].raw}`);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
// --- Summary ---
|
|
115
|
-
|
|
116
|
-
console.log(`\n${colors.cyan}${'═'.repeat(55)}${colors.reset}`);
|
|
117
|
-
console.log(`${colors.cyan}Test Results:${colors.reset}`);
|
|
118
|
-
console.log(` Total: ${totalTests}`);
|
|
119
|
-
console.log(` Passed: ${colors.green}${passedTests}${colors.reset}`);
|
|
120
|
-
console.log(` Failed: ${passedTests === totalTests ? colors.green : colors.red}${totalTests - passedTests}${colors.reset}`);
|
|
121
|
-
console.log(`${colors.cyan}${'═'.repeat(55)}${colors.reset}\n`);
|
|
122
|
-
|
|
123
|
-
if (failures.length > 0) {
|
|
124
|
-
console.log(`${colors.red}FAILED TESTS:${colors.reset}\n`);
|
|
125
|
-
for (const failure of failures) {
|
|
126
|
-
console.log(`${colors.red}\u2717${colors.reset} ${failure.name}`);
|
|
127
|
-
console.log(` ${failure.message}\n`);
|
|
128
|
-
}
|
|
129
|
-
process.exit(1);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
console.log(`${colors.green}All tests passed!${colors.reset}\n`);
|
|
133
|
-
process.exit(0);
|