diff --git a/test/fixtures/wave-2/sidecar-negative/basename-path-mismatch/shard-doc.artifact.yaml b/test/fixtures/shard-doc/sidecar-negative/basename-path-mismatch/shard-doc.artifact.yaml similarity index 100% rename from test/fixtures/wave-2/sidecar-negative/basename-path-mismatch/shard-doc.artifact.yaml rename to test/fixtures/shard-doc/sidecar-negative/basename-path-mismatch/shard-doc.artifact.yaml diff --git a/test/fixtures/wave-2/sidecar-negative/unknown-major-version/shard-doc.artifact.yaml b/test/fixtures/shard-doc/sidecar-negative/unknown-major-version/shard-doc.artifact.yaml similarity index 100% rename from test/fixtures/wave-2/sidecar-negative/unknown-major-version/shard-doc.artifact.yaml rename to test/fixtures/shard-doc/sidecar-negative/unknown-major-version/shard-doc.artifact.yaml diff --git a/test/test-installation-components.js b/test/test-installation-components.js index 76fcda18e..e3ac496d1 100644 --- a/test/test-installation-components.js +++ b/test/test-installation-components.js @@ -61,9 +61,9 @@ const { const { PROJECTION_COMPATIBILITY_ERROR_CODES, TASK_MANIFEST_COMPATIBILITY_PREFIX_COLUMNS, - TASK_MANIFEST_WAVE1_ADDITIVE_COLUMNS, + TASK_MANIFEST_CANONICAL_ADDITIVE_COLUMNS, HELP_CATALOG_COMPATIBILITY_PREFIX_COLUMNS, - HELP_CATALOG_WAVE1_ADDITIVE_COLUMNS, + HELP_CATALOG_CANONICAL_ADDITIVE_COLUMNS, validateTaskManifestCompatibilitySurface, validateTaskManifestLoaderEntries, validateHelpCatalogCompatibilitySurface, @@ -72,15 +72,15 @@ const { validateCommandDocSurfaceConsistency, } = require('../tools/cli/installers/lib/core/projection-compatibility-validator'); const { - WAVE1_VALIDATION_ERROR_CODES, - WAVE1_VALIDATION_ARTIFACT_REGISTRY, - Wave1ValidationHarness, -} = require('../tools/cli/installers/lib/core/wave-1-validation-harness'); + HELP_VALIDATION_ERROR_CODES, + HELP_VALIDATION_ARTIFACT_REGISTRY, + HelpValidationHarness, +} = require('../tools/cli/installers/lib/core/help-validation-harness'); const { - WAVE2_VALIDATION_ERROR_CODES, - WAVE2_VALIDATION_ARTIFACT_REGISTRY, - Wave2ValidationHarness, -} = require('../tools/cli/installers/lib/core/wave-2-validation-harness'); + SHARD_DOC_VALIDATION_ERROR_CODES, + SHARD_DOC_VALIDATION_ARTIFACT_REGISTRY, + ShardDocValidationHarness, +} = require('../tools/cli/installers/lib/core/shard-doc-validation-harness'); // ANSI colors const colors = { @@ -399,9 +399,9 @@ async function runTests() { console.log(''); // ============================================================ - // Test 4b: Wave-2 shard-doc Sidecar Contract Validation + // Test 4b: Shard-doc Sidecar Contract Validation // ============================================================ - console.log(`${colors.yellow}Test Suite 4b: Wave-2 shard-doc Sidecar Contract Validation${colors.reset}\n`); + console.log(`${colors.yellow}Test Suite 4b: Shard-doc Sidecar Contract Validation${colors.reset}\n`); const validShardDocSidecar = { schemaVersion: 1, @@ -416,7 +416,7 @@ async function runTests() { }, }; - const shardDocFixtureRoot = path.join(projectRoot, 'test', 'fixtures', 'wave-2', 'sidecar-negative'); + const shardDocFixtureRoot = path.join(projectRoot, 'test', 'fixtures', 'shard-doc', 'sidecar-negative'); const unknownMajorFixturePath = path.join(shardDocFixtureRoot, 'unknown-major-version', 'shard-doc.artifact.yaml'); const basenameMismatchFixturePath = path.join(shardDocFixtureRoot, 'basename-path-mismatch', 'shard-doc.artifact.yaml'); @@ -587,7 +587,7 @@ async function runTests() { 'Shard-doc non-empty dependencies.requires', ); } catch (error) { - assert(false, 'Wave-2 shard-doc sidecar validation suite setup', error.message); + assert(false, 'Shard-doc sidecar validation suite setup', error.message); } finally { await fs.remove(tempShardDocRoot); } @@ -1109,7 +1109,7 @@ async function runTests() { } } - // 6b: Shard-doc fail-fast covers Wave-2 negative matrix classes. + // 6b: Shard-doc fail-fast covers Shard-doc negative matrix classes. { const deterministicShardDocFailFastSourcePath = 'bmad-fork/src/core/tasks/shard-doc.artifact.yaml'; const shardDocFailureScenarios = [ @@ -1967,7 +1967,7 @@ async function runTests() { assert( writtenTaskManifestLines[0] === expectedHeader, - 'Task manifest writes compatibility-prefix columns with locked wave-1 appended column order', + 'Task manifest writes compatibility-prefix columns with locked canonical appended column order', ); const writtenTaskManifestRecords = csv.parse(writtenTaskManifestRaw, { @@ -3147,7 +3147,7 @@ async function runTests() { const taskManifestColumns = [ ...TASK_MANIFEST_COMPATIBILITY_PREFIX_COLUMNS, - ...TASK_MANIFEST_WAVE1_ADDITIVE_COLUMNS, + ...TASK_MANIFEST_CANONICAL_ADDITIVE_COLUMNS, 'futureAdditiveField', ]; const validTaskRows = [ @@ -3162,7 +3162,7 @@ async function runTests() { canonicalId: 'bmad-help', authoritySourceType: 'sidecar', authoritySourcePath: 'bmad-fork/src/core/tasks/help.artifact.yaml', - futureAdditiveField: 'wave-1', + futureAdditiveField: 'canonical-additive', }, { name: 'create-story', @@ -3175,7 +3175,7 @@ async function runTests() { canonicalId: '', authoritySourceType: '', authoritySourcePath: '', - futureAdditiveField: 'wave-1', + futureAdditiveField: 'canonical-additive', }, ]; const validTaskManifestCsv = @@ -3188,11 +3188,11 @@ async function runTests() { assert( validatedTaskSurface.headerColumns[0] === 'name' && validatedTaskSurface.headerColumns[TASK_MANIFEST_COMPATIBILITY_PREFIX_COLUMNS.length] === 'legacyName', - 'Task-manifest compatibility validator enforces locked prefix plus additive wave-1 ordering', + 'Task-manifest compatibility validator enforces locked prefix plus additive canonical ordering', ); assert( validatedTaskSurface.headerColumns.at(-1) === 'futureAdditiveField', - 'Task-manifest compatibility validator allows additive columns appended after locked wave-1 columns', + 'Task-manifest compatibility validator allows additive columns appended after locked canonical columns', ); validateTaskManifestLoaderEntries(validatedTaskSurface.rows, { @@ -3229,8 +3229,8 @@ async function runTests() { assert(false, 'Task-manifest strict validator rejects legacy prefix-only header without migration mode'); } catch (error) { assert( - error.code === PROJECTION_COMPATIBILITY_ERROR_CODES.TASK_MANIFEST_HEADER_WAVE1_MISMATCH, - 'Task-manifest strict validator emits deterministic wave-1 mismatch error for legacy prefix-only headers', + error.code === PROJECTION_COMPATIBILITY_ERROR_CODES.TASK_MANIFEST_HEADER_CANONICAL_MISMATCH, + 'Task-manifest strict validator emits deterministic canonical mismatch error for legacy prefix-only headers', ); } @@ -3252,7 +3252,7 @@ async function runTests() { const helpCatalogColumns = [ ...HELP_CATALOG_COMPATIBILITY_PREFIX_COLUMNS, - ...HELP_CATALOG_WAVE1_ADDITIVE_COLUMNS, + ...HELP_CATALOG_CANONICAL_ADDITIVE_COLUMNS, 'futureAdditiveField', ]; const validHelpRows = [ @@ -3273,7 +3273,7 @@ async function runTests() { description: 'Help command', 'output-location': '', outputs: '', - futureAdditiveField: 'wave-1', + futureAdditiveField: 'canonical-additive', }, { module: 'core', @@ -3292,7 +3292,7 @@ async function runTests() { description: 'Shard document command', 'output-location': '', outputs: '', - futureAdditiveField: 'wave-1', + futureAdditiveField: 'canonical-additive', }, { module: 'bmm', @@ -3311,7 +3311,7 @@ async function runTests() { description: 'Create next story', 'output-location': '', outputs: '', - futureAdditiveField: 'wave-1', + futureAdditiveField: 'canonical-additive', }, ]; const validHelpCatalogCsv = @@ -3327,7 +3327,7 @@ async function runTests() { ); assert( validatedHelpSurface.headerColumns.at(-1) === 'futureAdditiveField', - 'Help-catalog compatibility validator allows additive columns appended after locked wave-1 columns', + 'Help-catalog compatibility validator allows additive columns appended after locked canonical columns', ); validateHelpCatalogLoaderEntries(validatedHelpSurface.rows, { @@ -3438,7 +3438,7 @@ async function runTests() { // ============================================================ console.log(`${colors.yellow}Test Suite 14: Deterministic Validation Artifact Suite${colors.reset}\n`); - const tempValidationHarnessRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-wave1-validation-suite-')); + const tempValidationHarnessRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-help-validation-suite-')); try { const tempProjectRoot = tempValidationHarnessRoot; const tempBmadDir = path.join(tempProjectRoot, '_bmad'); @@ -3509,7 +3509,7 @@ async function runTests() { await writeCsv( path.join(tempConfigDir, 'task-manifest.csv'), - [...TASK_MANIFEST_COMPATIBILITY_PREFIX_COLUMNS, ...TASK_MANIFEST_WAVE1_ADDITIVE_COLUMNS], + [...TASK_MANIFEST_COMPATIBILITY_PREFIX_COLUMNS, ...TASK_MANIFEST_CANONICAL_ADDITIVE_COLUMNS], [ { name: 'help', @@ -3576,7 +3576,7 @@ async function runTests() { ); await writeCsv( path.join(tempConfigDir, 'bmad-help.csv'), - [...HELP_CATALOG_COMPATIBILITY_PREFIX_COLUMNS, ...HELP_CATALOG_WAVE1_ADDITIVE_COLUMNS], + [...HELP_CATALOG_COMPATIBILITY_PREFIX_COLUMNS, ...HELP_CATALOG_CANONICAL_ADDITIVE_COLUMNS], [ { module: 'core', @@ -3764,7 +3764,7 @@ async function runTests() { ], ); - const harness = new Wave1ValidationHarness(); + const harness = new HelpValidationHarness(); const firstRun = await harness.generateAndValidate({ projectDir: tempProjectRoot, bmadDir: tempBmadDir, @@ -3773,18 +3773,18 @@ async function runTests() { sourceMarkdownPath: path.join(tempSourceTasksDir, 'help.md'), }); assert( - firstRun.terminalStatus === 'PASS' && firstRun.generatedArtifactCount === WAVE1_VALIDATION_ARTIFACT_REGISTRY.length, - 'Wave-1 validation harness generates and validates all required artifacts', + firstRun.terminalStatus === 'PASS' && firstRun.generatedArtifactCount === HELP_VALIDATION_ARTIFACT_REGISTRY.length, + 'Help validation harness generates and validates all required artifacts', ); const artifactPathsById = new Map( - WAVE1_VALIDATION_ARTIFACT_REGISTRY.map((artifact) => [ + HELP_VALIDATION_ARTIFACT_REGISTRY.map((artifact) => [ artifact.artifactId, path.join(tempProjectRoot, '_bmad-output', 'planning-artifacts', artifact.relativePath), ]), ); for (const [artifactId, artifactPath] of artifactPathsById.entries()) { - assert(await fs.pathExists(artifactPath), `Wave-1 validation harness outputs artifact ${artifactId}`); + assert(await fs.pathExists(artifactPath), `Help validation harness outputs artifact ${artifactId}`); } const artifactThreeBaselineRows = csv.parse(await fs.readFile(artifactPathsById.get(3), 'utf8'), { @@ -3810,7 +3810,7 @@ async function runTests() { manifestReplayEvidence.perturbationApplied === true && Number(manifestReplayEvidence.baselineTargetRowCount) > Number(manifestReplayEvidence.mutatedTargetRowCount) && manifestReplayEvidence.targetedRowLocator === manifestProvenanceRow.rowIdentity, - 'Wave-1 validation harness emits validator-observed replay evidence with baseline/perturbation impact', + 'Help validation harness emits validator-observed replay evidence with baseline/perturbation impact', ); const firstArtifactContents = new Map(); @@ -3834,18 +3834,18 @@ async function runTests() { break; } } - assert(deterministicOutputs, 'Wave-1 validation harness outputs are byte-stable across unchanged repeated runs'); + assert(deterministicOutputs, 'Help validation harness outputs are byte-stable across unchanged repeated runs'); await fs.remove(path.join(tempSkillDir, 'SKILL.md')); const noIdeInstaller = new Installer(); noIdeInstaller.codexExportDerivationRecords = []; - const noIdeValidationOptions = await noIdeInstaller.buildWave1ValidationOptions({ + const noIdeValidationOptions = await noIdeInstaller.buildHelpValidationOptions({ projectDir: tempProjectRoot, bmadDir: tempBmadDir, }); assert( noIdeValidationOptions.requireExportSkillProjection === false, - 'Installer wave-1 validation options disable export-surface requirement for no-IDE/non-Codex flow', + 'Installer help validation options disable export-surface requirement for no-IDE/non-Codex flow', ); const noIdeRun = await harness.generateAndValidate({ ...noIdeValidationOptions, @@ -3854,7 +3854,7 @@ async function runTests() { }); assert( noIdeRun.terminalStatus === 'PASS', - 'Wave-1 validation harness remains terminal-PASS for no-IDE/non-Codex flow when core projection surfaces are present', + 'Help validation harness remains terminal-PASS for no-IDE/non-Codex flow when core projection surfaces are present', ); const noIdeStandaloneValidation = await harness.validateGeneratedArtifacts({ projectDir: tempProjectRoot, @@ -3862,7 +3862,7 @@ async function runTests() { }); assert( noIdeStandaloneValidation.status === 'PASS', - 'Wave-1 validation harness infers no-IDE export prerequisite context during standalone validation when options are omitted', + 'Help validation harness infers no-IDE export prerequisite context during standalone validation when options are omitted', ); try { await harness.buildObservedBindingEvidence({ @@ -3873,11 +3873,11 @@ async function runTests() { optionalSurface: false, runtimeFolder: '_bmad', }); - assert(false, 'Wave-1 replay evidence generation rejects unmapped claimed rowIdentity'); + assert(false, 'Help replay evidence generation rejects unmapped claimed rowIdentity'); } catch (error) { assert( - error.code === WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, - 'Wave-1 replay evidence generation emits deterministic missing-claimed-rowIdentity error code', + error.code === HELP_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, + 'Help replay evidence generation emits deterministic missing-claimed-rowIdentity error code', ); } await fs.writeFile( @@ -3895,16 +3895,16 @@ async function runTests() { sidecarPath: path.join(tempSourceTasksDir, 'help.artifact.yaml'), sourceMarkdownPath: path.join(tempSourceTasksDir, 'help.md'), }); - assert(false, 'Wave-1 validation harness fails when required projection input surfaces are missing'); + assert(false, 'Help validation harness fails when required projection input surfaces are missing'); } catch (error) { assert( - error.code === WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, - 'Wave-1 validation harness emits deterministic missing-input-surface error code', + error.code === HELP_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, + 'Help validation harness emits deterministic missing-input-surface error code', ); } await writeCsv( path.join(tempConfigDir, 'task-manifest.csv'), - [...TASK_MANIFEST_COMPATIBILITY_PREFIX_COLUMNS, ...TASK_MANIFEST_WAVE1_ADDITIVE_COLUMNS], + [...TASK_MANIFEST_COMPATIBILITY_PREFIX_COLUMNS, ...TASK_MANIFEST_CANONICAL_ADDITIVE_COLUMNS], [ { name: 'help', @@ -3931,11 +3931,11 @@ async function runTests() { await fs.remove(artifactPathsById.get(14)); try { await harness.validateGeneratedArtifacts({ projectDir: tempProjectRoot }); - assert(false, 'Wave-1 validation harness fails when a required artifact is missing'); + assert(false, 'Help validation harness fails when a required artifact is missing'); } catch (error) { assert( - error.code === WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, - 'Wave-1 validation harness emits deterministic missing-artifact error code', + error.code === HELP_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, + 'Help validation harness emits deterministic missing-artifact error code', ); } @@ -3954,11 +3954,11 @@ async function runTests() { await fs.writeFile(artifactTwoPath, artifactTwoLines.join('\n'), 'utf8'); try { await harness.validateGeneratedArtifacts({ projectDir: tempProjectRoot }); - assert(false, 'Wave-1 validation harness rejects schema/header drift'); + assert(false, 'Help validation harness rejects schema/header drift'); } catch (error) { assert( - error.code === WAVE1_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, - 'Wave-1 validation harness emits deterministic schema-mismatch error code', + error.code === HELP_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, + 'Help validation harness emits deterministic schema-mismatch error code', ); } @@ -3975,11 +3975,11 @@ async function runTests() { await fs.writeFile(artifactNinePath, `${artifactNineHeader}\n`, 'utf8'); try { await harness.validateGeneratedArtifacts({ projectDir: tempProjectRoot }); - assert(false, 'Wave-1 validation harness rejects header-only required-identity artifacts'); + assert(false, 'Help validation harness rejects header-only required-identity artifacts'); } catch (error) { assert( - error.code === WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, - 'Wave-1 validation harness emits deterministic missing-row error code for header-only artifacts', + error.code === HELP_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, + 'Help validation harness emits deterministic missing-row error code for header-only artifacts', ); } @@ -4017,11 +4017,11 @@ async function runTests() { ); try { await harness.validateGeneratedArtifacts({ projectDir: tempProjectRoot }); - assert(false, 'Wave-1 validation harness rejects missing required row identity values'); + assert(false, 'Help validation harness rejects missing required row identity values'); } catch (error) { assert( - error.code === WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, - 'Wave-1 validation harness emits deterministic row-identity error code', + error.code === HELP_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, + 'Help validation harness emits deterministic row-identity error code', ); } @@ -4061,11 +4061,11 @@ async function runTests() { ); try { await harness.validateGeneratedArtifacts({ projectDir: tempProjectRoot }); - assert(false, 'Wave-1 validation harness rejects PASS rows missing required evidence-link fields'); + assert(false, 'Help validation harness rejects PASS rows missing required evidence-link fields'); } catch (error) { assert( - error.code === WAVE1_VALIDATION_ERROR_CODES.REQUIRED_EVIDENCE_LINK_MISSING, - 'Wave-1 validation harness emits deterministic evidence-link error code for missing row identity link', + error.code === HELP_VALIDATION_ERROR_CODES.REQUIRED_EVIDENCE_LINK_MISSING, + 'Help validation harness emits deterministic evidence-link error code for missing row identity link', ); } @@ -4111,11 +4111,11 @@ async function runTests() { ); try { await harness.validateGeneratedArtifacts({ projectDir: tempProjectRoot }); - assert(false, 'Wave-1 validation harness rejects self-attested issuer claims that diverge from validator evidence'); + assert(false, 'Help validation harness rejects self-attested issuer claims that diverge from validator evidence'); } catch (error) { assert( - error.code === WAVE1_VALIDATION_ERROR_CODES.SELF_ATTESTED_ISSUER_CLAIM, - 'Wave-1 validation harness emits deterministic self-attested issuer-claim rejection code', + error.code === HELP_VALIDATION_ERROR_CODES.SELF_ATTESTED_ISSUER_CLAIM, + 'Help validation harness emits deterministic self-attested issuer-claim rejection code', ); } @@ -4151,11 +4151,11 @@ async function runTests() { ); try { await harness.validateGeneratedArtifacts({ projectDir: tempProjectRoot }); - assert(false, 'Wave-1 validation harness rejects malformed replay-evidence payloads'); + assert(false, 'Help validation harness rejects malformed replay-evidence payloads'); } catch (error) { assert( - error.code === WAVE1_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, - 'Wave-1 validation harness emits deterministic replay-evidence validation error code', + error.code === HELP_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, + 'Help validation harness emits deterministic replay-evidence validation error code', ); } } catch (error) { @@ -4167,13 +4167,13 @@ async function runTests() { console.log(''); // ============================================================ - // Test 15: Wave-2 shard-doc Validation Artifact Suite + // Test 15: Shard-doc Validation Artifact Suite // ============================================================ - console.log(`${colors.yellow}Test Suite 15: Wave-2 shard-doc Validation Artifact Suite${colors.reset}\n`); + console.log(`${colors.yellow}Test Suite 15: Shard-doc Validation Artifact Suite${colors.reset}\n`); - const tempWave2ValidationHarnessRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-wave2-validation-suite-')); + const tempShardDocValidationHarnessRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-shard-doc-validation-suite-')); try { - const tempProjectRoot = tempWave2ValidationHarnessRoot; + const tempProjectRoot = tempShardDocValidationHarnessRoot; const tempBmadDir = path.join(tempProjectRoot, '_bmad'); const tempConfigDir = path.join(tempBmadDir, '_config'); const tempSourceTasksDir = path.join(tempProjectRoot, 'bmad-fork', 'src', 'core', 'tasks'); @@ -4245,7 +4245,7 @@ async function runTests() { await writeCsv( path.join(tempConfigDir, 'task-manifest.csv'), - [...TASK_MANIFEST_COMPATIBILITY_PREFIX_COLUMNS, ...TASK_MANIFEST_WAVE1_ADDITIVE_COLUMNS], + [...TASK_MANIFEST_COMPATIBILITY_PREFIX_COLUMNS, ...TASK_MANIFEST_CANONICAL_ADDITIVE_COLUMNS], [ { name: 'shard-doc', @@ -4263,7 +4263,7 @@ async function runTests() { ); await writeCsv( path.join(tempConfigDir, 'bmad-help.csv'), - [...HELP_CATALOG_COMPATIBILITY_PREFIX_COLUMNS, ...HELP_CATALOG_WAVE1_ADDITIVE_COLUMNS], + [...HELP_CATALOG_COMPATIBILITY_PREFIX_COLUMNS, ...HELP_CATALOG_CANONICAL_ADDITIVE_COLUMNS], [ { module: 'core', @@ -4353,7 +4353,7 @@ async function runTests() { }, ]; - const harness = new Wave2ValidationHarness(); + const harness = new ShardDocValidationHarness(); const firstRun = await harness.generateAndValidate({ projectDir: tempProjectRoot, bmadDir: tempBmadDir, @@ -4361,18 +4361,18 @@ async function runTests() { shardDocAuthorityRecords: authorityRecords, }); assert( - firstRun.terminalStatus === 'PASS' && firstRun.generatedArtifactCount === WAVE2_VALIDATION_ARTIFACT_REGISTRY.length, - 'Wave-2 validation harness generates and validates all required artifacts', + firstRun.terminalStatus === 'PASS' && firstRun.generatedArtifactCount === SHARD_DOC_VALIDATION_ARTIFACT_REGISTRY.length, + 'Shard-doc validation harness generates and validates all required artifacts', ); const artifactPathsById = new Map( - WAVE2_VALIDATION_ARTIFACT_REGISTRY.map((artifact) => [ + SHARD_DOC_VALIDATION_ARTIFACT_REGISTRY.map((artifact) => [ artifact.artifactId, path.join(tempProjectRoot, '_bmad-output', 'planning-artifacts', artifact.relativePath), ]), ); for (const [artifactId, artifactPath] of artifactPathsById.entries()) { - assert(await fs.pathExists(artifactPath), `Wave-2 validation harness outputs artifact ${artifactId}`); + assert(await fs.pathExists(artifactPath), `Shard-doc validation harness outputs artifact ${artifactId}`); } const firstArtifactContents = new Map(); @@ -4394,16 +4394,16 @@ async function runTests() { break; } } - assert(deterministicOutputs, 'Wave-2 validation harness outputs are byte-stable across unchanged repeated runs'); + assert(deterministicOutputs, 'Shard-doc validation harness outputs are byte-stable across unchanged repeated runs'); await fs.remove(artifactPathsById.get(8)); try { await harness.validateGeneratedArtifacts({ projectDir: tempProjectRoot }); - assert(false, 'Wave-2 validation harness fails when a required artifact is missing'); + assert(false, 'Shard-doc validation harness fails when a required artifact is missing'); } catch (error) { assert( - error.code === WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, - 'Wave-2 validation harness emits deterministic missing-artifact error code', + error.code === SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, + 'Shard-doc validation harness emits deterministic missing-artifact error code', ); } @@ -4422,11 +4422,11 @@ async function runTests() { bmadFolderName: '_bmad', shardDocAuthorityRecords: authorityRecords, }); - assert(false, 'Wave-2 validation harness rejects missing command-label report input surface'); + assert(false, 'Shard-doc validation harness rejects missing command-label report input surface'); } catch (error) { assert( - error.code === WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, - 'Wave-2 validation harness emits deterministic missing-input-surface error code', + error.code === SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, + 'Shard-doc validation harness emits deterministic missing-input-surface error code', ); } await writeCsv(commandLabelReportPath, commandLabelReportColumns, commandLabelReportRows); @@ -4437,11 +4437,11 @@ async function runTests() { await fs.writeFile(artifactSixPath, artifactSixLines.join('\n'), 'utf8'); try { await harness.validateGeneratedArtifacts({ projectDir: tempProjectRoot }); - assert(false, 'Wave-2 validation harness rejects schema/header drift'); + assert(false, 'Shard-doc validation harness rejects schema/header drift'); } catch (error) { assert( - error.code === WAVE2_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, - 'Wave-2 validation harness emits deterministic schema-mismatch error code', + error.code === SHARD_DOC_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, + 'Shard-doc validation harness emits deterministic schema-mismatch error code', ); } @@ -4459,7 +4459,7 @@ async function runTests() { }); const artifactSixInventoryRow = artifactEightRows.find((row) => row.artifactId === '6'); if (artifactSixInventoryRow) { - artifactSixInventoryRow.artifactPath = 'validation/wave-2/drifted-command-label-report.csv'; + artifactSixInventoryRow.artifactPath = 'validation/shard-doc/drifted-command-label-report.csv'; } await writeCsv( artifactEightPath, @@ -4468,11 +4468,11 @@ async function runTests() { ); try { await harness.validateGeneratedArtifacts({ projectDir: tempProjectRoot }); - assert(false, 'Wave-2 validation harness rejects inventory deterministic-identifier drift'); + assert(false, 'Shard-doc validation harness rejects inventory deterministic-identifier drift'); } catch (error) { assert( - error.code === WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, - 'Wave-2 validation harness emits deterministic inventory-row validation error code', + error.code === SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, + 'Shard-doc validation harness emits deterministic inventory-row validation error code', ); } @@ -4496,17 +4496,17 @@ async function runTests() { ); try { await harness.validateGeneratedArtifacts({ projectDir: tempProjectRoot }); - assert(false, 'Wave-2 validation harness rejects missing source-body authority records'); + assert(false, 'Shard-doc validation harness rejects missing source-body authority records'); } catch (error) { assert( - error.code === WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, - 'Wave-2 validation harness emits deterministic missing-row error code', + error.code === SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, + 'Shard-doc validation harness emits deterministic missing-row error code', ); } } catch (error) { - assert(false, 'Wave-2 shard-doc validation artifact suite setup', error.message); + assert(false, 'Shard-doc validation artifact suite setup', error.message); } finally { - await fs.remove(tempWave2ValidationHarnessRoot); + await fs.remove(tempShardDocValidationHarnessRoot); } console.log(''); diff --git a/tools/cli/installers/lib/core/wave-1-validation-harness.js b/tools/cli/installers/lib/core/help-validation-harness.js similarity index 92% rename from tools/cli/installers/lib/core/wave-1-validation-harness.js rename to tools/cli/installers/lib/core/help-validation-harness.js index e321d03ad..ccb17a343 100644 --- a/tools/cli/installers/lib/core/wave-1-validation-harness.js +++ b/tools/cli/installers/lib/core/help-validation-harness.js @@ -11,23 +11,23 @@ const { ManifestGenerator } = require('./manifest-generator'); const { buildSidecarAwareExemplarHelpRow } = require('./help-catalog-generator'); const { CodexSetup } = require('../ide/codex'); -const WAVE1_VALIDATION_ERROR_CODES = Object.freeze({ - REQUIRED_ARTIFACT_MISSING: 'ERR_WAVE1_VALIDATION_REQUIRED_ARTIFACT_MISSING', - CSV_SCHEMA_MISMATCH: 'ERR_WAVE1_VALIDATION_CSV_SCHEMA_MISMATCH', - REQUIRED_ROW_IDENTITY_MISSING: 'ERR_WAVE1_VALIDATION_REQUIRED_ROW_IDENTITY_MISSING', - REQUIRED_EVIDENCE_LINK_MISSING: 'ERR_WAVE1_VALIDATION_REQUIRED_EVIDENCE_LINK_MISSING', - EVIDENCE_LINK_REFERENCE_INVALID: 'ERR_WAVE1_VALIDATION_EVIDENCE_LINK_REFERENCE_INVALID', - BINDING_EVIDENCE_INVALID: 'ERR_WAVE1_VALIDATION_BINDING_EVIDENCE_INVALID', - ISSUER_PREREQUISITE_MISSING: 'ERR_WAVE1_VALIDATION_ISSUER_PREREQUISITE_MISSING', - SELF_ATTESTED_ISSUER_CLAIM: 'ERR_WAVE1_VALIDATION_SELF_ATTESTED_ISSUER_CLAIM', - YAML_SCHEMA_MISMATCH: 'ERR_WAVE1_VALIDATION_YAML_SCHEMA_MISMATCH', - DECISION_RECORD_SCHEMA_MISMATCH: 'ERR_WAVE1_VALIDATION_DECISION_RECORD_SCHEMA_MISMATCH', - DECISION_RECORD_PARSE_FAILED: 'ERR_WAVE1_VALIDATION_DECISION_RECORD_PARSE_FAILED', +const HELP_VALIDATION_ERROR_CODES = Object.freeze({ + REQUIRED_ARTIFACT_MISSING: 'ERR_HELP_VALIDATION_REQUIRED_ARTIFACT_MISSING', + CSV_SCHEMA_MISMATCH: 'ERR_HELP_VALIDATION_CSV_SCHEMA_MISMATCH', + REQUIRED_ROW_IDENTITY_MISSING: 'ERR_HELP_VALIDATION_REQUIRED_ROW_IDENTITY_MISSING', + REQUIRED_EVIDENCE_LINK_MISSING: 'ERR_HELP_VALIDATION_REQUIRED_EVIDENCE_LINK_MISSING', + EVIDENCE_LINK_REFERENCE_INVALID: 'ERR_HELP_VALIDATION_EVIDENCE_LINK_REFERENCE_INVALID', + BINDING_EVIDENCE_INVALID: 'ERR_HELP_VALIDATION_BINDING_EVIDENCE_INVALID', + ISSUER_PREREQUISITE_MISSING: 'ERR_HELP_VALIDATION_ISSUER_PREREQUISITE_MISSING', + SELF_ATTESTED_ISSUER_CLAIM: 'ERR_HELP_VALIDATION_SELF_ATTESTED_ISSUER_CLAIM', + YAML_SCHEMA_MISMATCH: 'ERR_HELP_VALIDATION_YAML_SCHEMA_MISMATCH', + DECISION_RECORD_SCHEMA_MISMATCH: 'ERR_HELP_VALIDATION_DECISION_RECORD_SCHEMA_MISMATCH', + DECISION_RECORD_PARSE_FAILED: 'ERR_HELP_VALIDATION_DECISION_RECORD_PARSE_FAILED', }); const SIDEcar_AUTHORITY_SOURCE_PATH = 'bmad-fork/src/core/tasks/help.artifact.yaml'; const SOURCE_MARKDOWN_SOURCE_PATH = 'bmad-fork/src/core/tasks/help.md'; -const EVIDENCE_ISSUER_COMPONENT = 'bmad-fork/tools/cli/installers/lib/core/wave-1-validation-harness.js'; +const EVIDENCE_ISSUER_COMPONENT = 'bmad-fork/tools/cli/installers/lib/core/help-validation-harness.js'; const FRONTMATTER_MISMATCH_DETAILS = Object.freeze({ [HELP_FRONTMATTER_MISMATCH_ERROR_CODES.CANONICAL_ID_MISMATCH]: 'frontmatter canonicalId must match sidecar canonicalId', @@ -37,16 +37,16 @@ const FRONTMATTER_MISMATCH_DETAILS = Object.freeze({ 'frontmatter dependencies.requires must match sidecar dependencies.requires', }); -const WAVE1_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ +const HELP_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ Object.freeze({ artifactId: 1, - relativePath: path.join('validation', 'wave-1', 'bmad-help-sidecar-snapshot.yaml'), + relativePath: path.join('validation', 'help', 'bmad-help-sidecar-snapshot.yaml'), type: 'yaml', requiredTopLevelKeys: ['schemaVersion', 'canonicalId', 'artifactType', 'module', 'sourcePath', 'displayName', 'description', 'status'], }), Object.freeze({ artifactId: 2, - relativePath: path.join('validation', 'wave-1', 'bmad-help-runtime-comparison.csv'), + relativePath: path.join('validation', 'help', 'bmad-help-runtime-comparison.csv'), type: 'csv', columns: [ 'surface', @@ -65,7 +65,7 @@ const WAVE1_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 3, - relativePath: path.join('validation', 'wave-1', 'bmad-help-issued-artifact-provenance.csv'), + relativePath: path.join('validation', 'help', 'bmad-help-issued-artifact-provenance.csv'), type: 'csv', columns: [ 'rowIdentity', @@ -84,7 +84,7 @@ const WAVE1_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 4, - relativePath: path.join('validation', 'wave-1', 'bmad-help-manifest-comparison.csv'), + relativePath: path.join('validation', 'help', 'bmad-help-manifest-comparison.csv'), type: 'csv', columns: [ 'surface', @@ -106,7 +106,7 @@ const WAVE1_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 5, - relativePath: path.join('validation', 'wave-1', 'bmad-help-alias-table.csv'), + relativePath: path.join('validation', 'help', 'bmad-help-alias-table.csv'), type: 'csv', columns: [ 'rowIdentity', @@ -124,7 +124,7 @@ const WAVE1_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 6, - relativePath: path.join('validation', 'wave-1', 'bmad-help-description-provenance.csv'), + relativePath: path.join('validation', 'help', 'bmad-help-description-provenance.csv'), type: 'csv', columns: [ 'surface', @@ -142,7 +142,7 @@ const WAVE1_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 7, - relativePath: path.join('validation', 'wave-1', 'bmad-help-export-comparison.csv'), + relativePath: path.join('validation', 'help', 'bmad-help-export-comparison.csv'), type: 'csv', columns: [ 'exportPath', @@ -166,7 +166,7 @@ const WAVE1_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 8, - relativePath: path.join('validation', 'wave-1', 'bmad-help-command-label-report.csv'), + relativePath: path.join('validation', 'help', 'bmad-help-command-label-report.csv'), type: 'csv', columns: [ 'surface', @@ -186,7 +186,7 @@ const WAVE1_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 9, - relativePath: path.join('validation', 'wave-1', 'bmad-help-catalog-pipeline.csv'), + relativePath: path.join('validation', 'help', 'bmad-help-catalog-pipeline.csv'), type: 'csv', columns: [ 'stage', @@ -215,7 +215,7 @@ const WAVE1_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 10, - relativePath: path.join('validation', 'wave-1', 'bmad-help-duplicate-report.csv'), + relativePath: path.join('validation', 'help', 'bmad-help-duplicate-report.csv'), type: 'csv', columns: [ 'surface', @@ -247,7 +247,7 @@ const WAVE1_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 11, - relativePath: path.join('validation', 'wave-1', 'bmad-help-dependency-report.csv'), + relativePath: path.join('validation', 'help', 'bmad-help-dependency-report.csv'), type: 'csv', columns: [ 'declaredIn', @@ -268,13 +268,13 @@ const WAVE1_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 12, - relativePath: path.join('decision-records', 'wave-1-native-skills-exit.md'), + relativePath: path.join('decision-records', 'help-native-skills-exit.md'), type: 'markdown', - requiredFrontmatterKeys: ['wave', 'goNoGo', 'status'], + requiredFrontmatterKeys: ['capability', 'goNoGo', 'status'], }), Object.freeze({ artifactId: 13, - relativePath: path.join('validation', 'wave-1', 'bmad-help-sidecar-negative-validation.csv'), + relativePath: path.join('validation', 'help', 'bmad-help-sidecar-negative-validation.csv'), type: 'csv', columns: [ 'scenario', @@ -291,7 +291,7 @@ const WAVE1_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 14, - relativePath: path.join('validation', 'wave-1', 'bmad-help-frontmatter-mismatch-validation.csv'), + relativePath: path.join('validation', 'help', 'bmad-help-frontmatter-mismatch-validation.csv'), type: 'csv', columns: [ 'scenario', @@ -314,11 +314,11 @@ const WAVE1_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), ]); -class Wave1ValidationHarnessError extends Error { +class HelpValidationHarnessError extends Error { constructor({ code, detail, artifactId, fieldPath, sourcePath, observedValue, expectedValue }) { const message = `${code}: ${detail} (artifact=${artifactId}, fieldPath=${fieldPath}, sourcePath=${sourcePath})`; super(message); - this.name = 'Wave1ValidationHarnessError'; + this.name = 'HelpValidationHarnessError'; this.code = code; this.detail = detail; this.artifactId = artifactId; @@ -505,7 +505,7 @@ function buildReplaySidecarFixture({ canonicalId = 'bmad-help', description = 'H function replayFailurePayload(error) { return canonicalJsonStringify({ - replayFailureCode: normalizeValue(error?.code || 'ERR_WAVE1_REPLAY_COMPONENT_FAILED'), + replayFailureCode: normalizeValue(error?.code || 'ERR_HELP_VALIDATION_REPLAY_COMPONENT_FAILED'), replayFailureDetail: normalizeValue(error?.detail || error?.message || 'component replay failed'), }); } @@ -514,9 +514,9 @@ function isSha256(value) { return /^[a-f0-9]{64}$/.test(String(value || '')); } -class Wave1ValidationHarness { +class HelpValidationHarness { constructor() { - this.registry = WAVE1_VALIDATION_ARTIFACT_REGISTRY; + this.registry = HELP_VALIDATION_ARTIFACT_REGISTRY; } getArtifactRegistry() { @@ -526,7 +526,7 @@ class Wave1ValidationHarness { resolveOutputPaths(options = {}) { const projectDir = path.resolve(options.projectDir || process.cwd()); const planningArtifactsRoot = path.join(projectDir, '_bmad-output', 'planning-artifacts'); - const validationRoot = path.join(planningArtifactsRoot, 'validation', 'wave-1'); + const validationRoot = path.join(planningArtifactsRoot, 'validation', 'help'); const decisionRecordsRoot = path.join(planningArtifactsRoot, 'decision-records'); return { projectDir, @@ -608,8 +608,8 @@ class Wave1ValidationHarness { if (await fs.pathExists(absolutePath)) { return; } - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, detail: `Required input surface is missing (${description})`, artifactId, fieldPath: '', @@ -624,8 +624,8 @@ class Wave1ValidationHarness { if (match) { return match; } - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, detail, artifactId, fieldPath, @@ -734,8 +734,8 @@ class Wave1ValidationHarness { resolveReplayContract({ artifactPath, componentPath, rowIdentity, runtimeFolder }) { const claimedRowIdentity = normalizeValue(rowIdentity); if (!claimedRowIdentity) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, detail: 'Claimed replay rowIdentity is required', artifactId: 3, fieldPath: 'rowIdentity', @@ -747,8 +747,8 @@ class Wave1ValidationHarness { const expectedRowIdentity = buildIssuedArtifactRowIdentity(artifactPath); if (claimedRowIdentity !== expectedRowIdentity) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, detail: 'Claimed replay rowIdentity does not match artifact claim rowIdentity contract', artifactId: 3, fieldPath: 'rowIdentity', @@ -809,8 +809,8 @@ class Wave1ValidationHarness { const contract = contractsByClaimRowIdentity.get(claimedRowIdentity); if (!contract) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, detail: 'Claimed rowIdentity is not mapped to a replay contract', artifactId: 3, fieldPath: 'rowIdentity', @@ -825,8 +825,8 @@ class Wave1ValidationHarness { normalizeValue(artifactPath) !== normalizeValue(contract.artifactPath) || !normalizedComponentPath.includes(String(contract.componentPathIncludes || '').toLowerCase()) ) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, detail: 'Claimed replay rowIdentity/component pair does not match replay contract mapping', artifactId: 3, fieldPath: 'issuingComponent', @@ -1024,14 +1024,14 @@ class Wave1ValidationHarness { rowIdentity, runtimeFolder, }); - const baselineWorkspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'wave1-replay-baseline-')); - const perturbedWorkspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'wave1-replay-perturbed-')); + const baselineWorkspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'help-replay-baseline-')); + const perturbedWorkspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'help-replay-perturbed-')); try { const baseline = await contract.run({ workspaceRoot: baselineWorkspaceRoot, perturbed: false }); if (Number(baseline.targetRowCount) <= 0) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, detail: 'Claimed rowIdentity target is absent in baseline component replay output', artifactId: 3, fieldPath: 'rowIdentity', @@ -1236,7 +1236,7 @@ class Wave1ValidationHarness { const runtimeHelpCatalogPath = `${runtimeFolder}/_config/bmad-help.csv`; const runtimePipelinePath = `${runtimeFolder}/_config/bmad-help-catalog-pipeline.csv`; const runtimeCommandLabelPath = `${runtimeFolder}/_config/bmad-help-command-label-report.csv`; - const evidenceArtifactPath = '_bmad-output/planning-artifacts/validation/wave-1/bmad-help-issued-artifact-provenance.csv'; + const evidenceArtifactPath = '_bmad-output/planning-artifacts/validation/help/bmad-help-issued-artifact-provenance.csv'; const exportSkillPath = '.agents/skills/bmad-help/SKILL.md'; const exportSkillAbsolutePath = path.join(outputPaths.projectDir, '.agents', 'skills', 'bmad-help', 'SKILL.md'); const codexExportRows = @@ -1445,8 +1445,8 @@ class Wave1ValidationHarness { status: 'PASS', })); if (aliasRowsForExemplar.length === 0) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, detail: 'Required canonical alias rows for exemplar are missing', artifactId: 5, fieldPath: 'rows[canonicalId=bmad-help]', @@ -1626,8 +1626,8 @@ class Wave1ValidationHarness { }; }); if (pipelineWithEvidence.length === 0) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, detail: 'Required help-catalog pipeline exemplar rows are missing', artifactId: 9, fieldPath: 'rows[canonicalId=bmad-help]', @@ -1883,11 +1883,11 @@ class Wave1ValidationHarness { // Artifact 12: decision record const decisionRecord = { - wave: 1, + capability: 'bmad-help', goNoGo: 'GO', status: 'PASS', }; - const decisionRecordContent = `---\n${yaml.stringify(decisionRecord).trimEnd()}\n---\n\n# Wave 1 Native Skills Exit\n\nStatus: PASS\n`; + const decisionRecordContent = `---\n${yaml.stringify(decisionRecord).trimEnd()}\n---\n\n# Help Native Skills Exit\n\nStatus: PASS\n`; await fs.writeFile(artifactPaths.get(12), decisionRecordContent, 'utf8'); // Fixtures for artifacts 13 and 14 @@ -1898,15 +1898,14 @@ class Wave1ValidationHarness { const sidecarNegativeScenarios = [ { scenario: 'unknown-major-version', - fixturePath: '_bmad-output/planning-artifacts/validation/wave-1/fixtures/sidecar-negative/unknown-major-version/help.artifact.yaml', + fixturePath: '_bmad-output/planning-artifacts/validation/help/fixtures/sidecar-negative/unknown-major-version/help.artifact.yaml', absolutePath: fixtures.unknownMajorFixturePath, expectedFailureCode: HELP_SIDECAR_ERROR_CODES.MAJOR_VERSION_UNSUPPORTED, expectedFailureDetail: 'sidecar schema major version is unsupported', }, { scenario: 'basename-path-mismatch', - fixturePath: - '_bmad-output/planning-artifacts/validation/wave-1/fixtures/sidecar-negative/basename-path-mismatch/help.artifact.yaml', + fixturePath: '_bmad-output/planning-artifacts/validation/help/fixtures/sidecar-negative/basename-path-mismatch/help.artifact.yaml', absolutePath: fixtures.basenameMismatchFixturePath, expectedFailureCode: HELP_SIDECAR_ERROR_CODES.SOURCEPATH_BASENAME_MISMATCH, expectedFailureDetail: 'sidecar basename does not match sourcePath basename', @@ -1991,7 +1990,7 @@ class Wave1ValidationHarness { for (const scope of ['source', 'runtime']) { for (const scenario of mismatchScenarios) { const fixturePath = path.join(outputPaths.validationRoot, 'fixtures', 'frontmatter-mismatch', scope, `${scenario.scenario}.md`); - const fixtureRelativePath = `_bmad-output/planning-artifacts/validation/wave-1/fixtures/frontmatter-mismatch/${scope}/${scenario.scenario}.md`; + const fixtureRelativePath = `_bmad-output/planning-artifacts/validation/help/fixtures/frontmatter-mismatch/${scope}/${scenario.scenario}.md`; let observedFailureCode = ''; let observedFailureDetail = ''; let observedFrontmatterValue = ''; @@ -2071,8 +2070,8 @@ class Wave1ValidationHarness { try { parsed = JSON.parse(String(payloadRaw || '')); } catch (error) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, detail: `Binding evidence payload is not valid JSON (${error.message})`, artifactId, fieldPath, @@ -2083,8 +2082,8 @@ class Wave1ValidationHarness { } if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, detail: 'Binding evidence payload must be a JSON object', artifactId, fieldPath, @@ -2108,8 +2107,8 @@ class Wave1ValidationHarness { }); if (normalizeValue(payload.evidenceVersion) !== '1') { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, detail: 'Binding evidence payload must use evidenceVersion=1', artifactId, fieldPath: 'issuingComponentBindingEvidence.evidenceVersion', @@ -2121,8 +2120,8 @@ class Wave1ValidationHarness { if (rowStatus === 'SKIP') { if (normalizeValue(payload.observationMethod) !== 'validator-observed-optional-surface-omitted') { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, detail: 'Optional-surface provenance rows must use optional-surface evidence method', artifactId, fieldPath: 'issuingComponentBindingEvidence.observationMethod', @@ -2150,8 +2149,8 @@ class Wave1ValidationHarness { ]; for (const key of requiredPayloadFields) { if (normalizeValue(payload[key]).length === 0 && payload[key] !== false) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, detail: 'Required binding evidence field is missing', artifactId, fieldPath: `issuingComponentBindingEvidence.${key}`, @@ -2167,8 +2166,8 @@ class Wave1ValidationHarness { normalizeValue(row.evidenceMethod) !== 'validator-observed-baseline-plus-isolated-single-component-perturbation' || normalizeValue(row.issuingComponentBindingBasis) !== 'validator-observed-baseline-plus-isolated-single-component-perturbation' ) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, detail: 'Replay evidence must use the baseline-plus-isolated-perturbation method', artifactId, fieldPath: 'evidenceMethod', @@ -2185,8 +2184,8 @@ class Wave1ValidationHarness { normalizeValue(payload.mutatedRowIdentity) !== normalizeValue(row.rowIdentity) || normalizeValue(payload.targetedRowLocator) !== normalizeValue(row.rowIdentity) ) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, detail: 'Binding evidence payload does not match provenance row contract fields', artifactId, fieldPath: 'issuingComponentBindingEvidence', @@ -2197,8 +2196,8 @@ class Wave1ValidationHarness { } if (!isSha256(payload.baselineArtifactSha256) || !isSha256(payload.mutatedArtifactSha256) || !isSha256(payload.rowLevelDiffSha256)) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, detail: 'Replay evidence hashes must be sha256 hex values', artifactId, fieldPath: 'issuingComponentBindingEvidence.*Sha256', @@ -2213,8 +2212,8 @@ class Wave1ValidationHarness { } if (payload.baselineArtifactSha256 === payload.mutatedArtifactSha256 || payload.perturbationApplied !== true) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, detail: 'Replay evidence must show isolated perturbation impact', artifactId, fieldPath: 'issuingComponentBindingEvidence.perturbationApplied', @@ -2229,8 +2228,8 @@ class Wave1ValidationHarness { } if (Number(payload.baselineTargetRowCount) <= Number(payload.mutatedTargetRowCount)) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.BINDING_EVIDENCE_INVALID, detail: 'Replay evidence must show reduced target-row impact after perturbation', artifactId, fieldPath: 'issuingComponentBindingEvidence.baselineTargetRowCount', @@ -2250,8 +2249,8 @@ class Wave1ValidationHarness { if (normalizeValue(value).length > 0) { return; } - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.REQUIRED_EVIDENCE_LINK_MISSING, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.REQUIRED_EVIDENCE_LINK_MISSING, detail: 'Required evidence-link field is missing or empty', artifactId, fieldPath, @@ -2276,8 +2275,8 @@ class Wave1ValidationHarness { } if (normalizeValue(row.issuedArtifactEvidencePath) !== evidencePath) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.EVIDENCE_LINK_REFERENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.EVIDENCE_LINK_REFERENCE_INVALID, detail: 'Evidence-link path does not point to required provenance artifact', artifactId, fieldPath: `rows[${index}].issuedArtifactEvidencePath`, @@ -2290,8 +2289,8 @@ class Wave1ValidationHarness { const linkedEvidenceRowIdentity = normalizeValue(row.issuedArtifactEvidenceRowIdentity); const provenanceRow = provenanceByIdentity.get(linkedEvidenceRowIdentity); if (!provenanceRow) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.EVIDENCE_LINK_REFERENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.EVIDENCE_LINK_REFERENCE_INVALID, detail: 'Evidence-link row identity does not resolve to provenance artifact row', artifactId, fieldPath: `rows[${index}].issuedArtifactEvidenceRowIdentity`, @@ -2302,8 +2301,8 @@ class Wave1ValidationHarness { } if (normalizeValue(provenanceRow.status) !== 'PASS') { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.ISSUER_PREREQUISITE_MISSING, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.ISSUER_PREREQUISITE_MISSING, detail: 'Terminal PASS requires linked provenance rows to be PASS', artifactId, fieldPath: `rows[${index}].issuedArtifactEvidenceRowIdentity`, @@ -2314,8 +2313,8 @@ class Wave1ValidationHarness { } if (rowArtifactPathField && normalizeValue(row[rowArtifactPathField]) !== normalizeValue(provenanceRow.artifactPath)) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.EVIDENCE_LINK_REFERENCE_INVALID, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.EVIDENCE_LINK_REFERENCE_INVALID, detail: 'Evidence-linked provenance row does not match claimed artifact path', artifactId, fieldPath: `rows[${index}].${rowArtifactPathField}`, @@ -2330,8 +2329,8 @@ class Wave1ValidationHarness { normalizeValue(row.issuingComponent).length > 0 && normalizeValue(row.issuingComponent) !== normalizeValue(provenanceRow.issuingComponent) ) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.SELF_ATTESTED_ISSUER_CLAIM, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.SELF_ATTESTED_ISSUER_CLAIM, detail: 'Issuer component claim diverges from validator-linked provenance evidence', artifactId, fieldPath: `rows[${index}].issuingComponent`, @@ -2346,8 +2345,8 @@ class Wave1ValidationHarness { normalizeValue(row.issuingComponentBindingEvidence).length > 0 && normalizeValue(row.issuingComponentBindingEvidence) !== normalizeValue(provenanceRow.issuingComponentBindingEvidence) ) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.SELF_ATTESTED_ISSUER_CLAIM, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.SELF_ATTESTED_ISSUER_CLAIM, detail: 'Issuer binding evidence claim diverges from validator-linked provenance evidence', artifactId, fieldPath: `rows[${index}].issuingComponentBindingEvidence`, @@ -2360,7 +2359,7 @@ class Wave1ValidationHarness { } validateIssuerPrerequisites({ artifactDataById, runtimeFolder, requireExportSkillProjection }) { - const evidencePath = '_bmad-output/planning-artifacts/validation/wave-1/bmad-help-issued-artifact-provenance.csv'; + const evidencePath = '_bmad-output/planning-artifacts/validation/help/bmad-help-issued-artifact-provenance.csv'; const provenanceArtifact = artifactDataById.get(3) || { rows: [] }; const provenanceRows = Array.isArray(provenanceArtifact.rows) ? provenanceArtifact.rows : []; const provenanceByIdentity = new Map(); @@ -2392,8 +2391,8 @@ class Wave1ValidationHarness { for (const artifactPath of requiredProvenanceArtifactPaths) { const row = provenanceByArtifactPath.get(artifactPath); if (!row || normalizeValue(row.status) !== 'PASS') { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.ISSUER_PREREQUISITE_MISSING, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.ISSUER_PREREQUISITE_MISSING, detail: 'Terminal PASS requires provenance prerequisite rows for all required issuing-component claims', artifactId: 3, fieldPath: `rows[artifactPath=${artifactPath}]`, @@ -2494,9 +2493,9 @@ class Wave1ValidationHarness { for (const artifact of this.registry) { const artifactPath = path.join(planningArtifactsRoot, artifact.relativePath); if (!(await fs.pathExists(artifactPath))) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, - detail: 'Required wave-1 validation artifact is missing', + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, + detail: 'Required help validation artifact is missing', artifactId: artifact.artifactId, fieldPath: '', sourcePath: normalizePath(artifact.relativePath), @@ -2519,8 +2518,8 @@ class Wave1ValidationHarness { }); if (observedHeader.length !== expectedHeader.length) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, detail: 'CSV header length does not match required schema', artifactId: artifact.artifactId, fieldPath: '
', @@ -2534,8 +2533,8 @@ class Wave1ValidationHarness { const observed = normalizeValue(observedHeader[index]); const expected = normalizeValue(expectedValue); if (observed !== expected) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, detail: 'CSV header ordering does not match required schema', artifactId: artifact.artifactId, fieldPath: `header[${index}]`, @@ -2548,8 +2547,8 @@ class Wave1ValidationHarness { if (Array.isArray(artifact.requiredRowIdentityFields) && artifact.requiredRowIdentityFields.length > 0) { if (rows.length === 0) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, detail: 'Required row identity rows are missing', artifactId: artifact.artifactId, fieldPath: 'rows', @@ -2560,8 +2559,8 @@ class Wave1ValidationHarness { } for (const field of artifact.requiredRowIdentityFields) { if (!expectedHeader.includes(field)) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, detail: 'Required row identity field is missing from artifact schema', artifactId: artifact.artifactId, fieldPath: `header.${field}`, @@ -2574,10 +2573,10 @@ class Wave1ValidationHarness { for (const [rowIndex, row] of rows.entries()) { if (normalizeValue(row[field]).length === 0) { const isEvidenceLinkField = field === 'issuedArtifactEvidenceRowIdentity'; - throw new Wave1ValidationHarnessError({ + throw new HelpValidationHarnessError({ code: isEvidenceLinkField - ? WAVE1_VALIDATION_ERROR_CODES.REQUIRED_EVIDENCE_LINK_MISSING - : WAVE1_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, + ? HELP_VALIDATION_ERROR_CODES.REQUIRED_EVIDENCE_LINK_MISSING + : HELP_VALIDATION_ERROR_CODES.REQUIRED_ROW_IDENTITY_MISSING, detail: isEvidenceLinkField ? 'Required evidence-link row identity is missing or empty' : 'Required row identity value is missing or empty', @@ -2601,8 +2600,8 @@ class Wave1ValidationHarness { parsed, }); if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.YAML_SCHEMA_MISMATCH, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.YAML_SCHEMA_MISMATCH, detail: 'YAML artifact root must be a mapping object', artifactId: artifact.artifactId, fieldPath: '', @@ -2613,8 +2612,8 @@ class Wave1ValidationHarness { } for (const requiredKey of artifact.requiredTopLevelKeys || []) { if (!Object.prototype.hasOwnProperty.call(parsed, requiredKey)) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.YAML_SCHEMA_MISMATCH, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.YAML_SCHEMA_MISMATCH, detail: 'Required YAML key is missing', artifactId: artifact.artifactId, fieldPath: requiredKey, @@ -2637,8 +2636,8 @@ class Wave1ValidationHarness { try { frontmatter = parseFrontmatter(content); } catch (error) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.DECISION_RECORD_PARSE_FAILED, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.DECISION_RECORD_PARSE_FAILED, detail: `Unable to parse decision record frontmatter (${error.message})`, artifactId: artifact.artifactId, fieldPath: '', @@ -2647,8 +2646,8 @@ class Wave1ValidationHarness { } for (const requiredKey of artifact.requiredFrontmatterKeys || []) { if (!Object.prototype.hasOwnProperty.call(frontmatter, requiredKey)) { - throw new Wave1ValidationHarnessError({ - code: WAVE1_VALIDATION_ERROR_CODES.DECISION_RECORD_SCHEMA_MISMATCH, + throw new HelpValidationHarnessError({ + code: HELP_VALIDATION_ERROR_CODES.DECISION_RECORD_SCHEMA_MISMATCH, detail: 'Required decision-record key is missing', artifactId: artifact.artifactId, fieldPath: requiredKey, @@ -2695,8 +2694,8 @@ class Wave1ValidationHarness { } module.exports = { - WAVE1_VALIDATION_ERROR_CODES, - WAVE1_VALIDATION_ARTIFACT_REGISTRY, - Wave1ValidationHarnessError, - Wave1ValidationHarness, + HELP_VALIDATION_ERROR_CODES, + HELP_VALIDATION_ARTIFACT_REGISTRY, + HelpValidationHarnessError, + HelpValidationHarness, }; diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index f6dde4454..81155aaa3 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -20,8 +20,8 @@ const { renderDisplayedCommandLabel, } = require('./help-catalog-generator'); const { validateHelpCatalogCompatibilitySurface } = require('./projection-compatibility-validator'); -const { Wave1ValidationHarness } = require('./wave-1-validation-harness'); -const { Wave2ValidationHarness } = require('./wave-2-validation-harness'); +const { HelpValidationHarness } = require('./help-validation-harness'); +const { ShardDocValidationHarness } = require('./shard-doc-validation-harness'); const { getProjectRoot, getSourcePath, getModulePath } = require('../../../lib/project-root'); const { CLIUtils } = require('../../../lib/cli-utils'); const { ManifestGenerator } = require('./manifest-generator'); @@ -59,10 +59,10 @@ class Installer { this.helpCatalogPipelineRows = []; this.helpCatalogCommandLabelReportRows = []; this.codexExportDerivationRecords = []; - this.latestWave1ValidationRun = null; - this.latestWave2ValidationRun = null; - this.wave1ValidationHarness = new Wave1ValidationHarness(); - this.wave2ValidationHarness = new Wave2ValidationHarness(); + this.latestHelpValidationRun = null; + this.latestShardDocValidationRun = null; + this.helpValidationHarness = new HelpValidationHarness(); + this.shardDocValidationHarness = new ShardDocValidationHarness(); } async runConfigurationGenerationTask({ message, bmadDir, moduleConfigs, config, allModules, addResult }) { @@ -151,7 +151,7 @@ class Installer { return 'Configurations generated'; } - async buildWave1ValidationOptions({ projectDir, bmadDir }) { + async buildHelpValidationOptions({ projectDir, bmadDir }) { const exportSkillProjectionPath = path.join(projectDir, '.agents', 'skills', 'bmad-help', 'SKILL.md'); const hasCodexExportDerivationRecords = Array.isArray(this.codexExportDerivationRecords) && this.codexExportDerivationRecords.length > 0; @@ -169,7 +169,7 @@ class Installer { }; } - async buildWave2ValidationOptions({ projectDir, bmadDir }) { + async buildShardDocValidationOptions({ projectDir, bmadDir }) { return { projectDir, bmadDir, @@ -1356,25 +1356,25 @@ class Installer { postIdeTasks.push({ title: 'Generating validation artifacts', task: async (message) => { - message('Generating deterministic wave-1 validation artifact suite...'); - const validationOptions = await this.buildWave1ValidationOptions({ + message('Generating deterministic help validation artifact suite...'); + const validationOptions = await this.buildHelpValidationOptions({ projectDir, bmadDir, }); - const validationRun = await this.wave1ValidationHarness.generateAndValidate(validationOptions); - this.latestWave1ValidationRun = validationRun; - addResult('Wave-1 validation artifacts', 'ok', `${validationRun.generatedArtifactCount} artifacts`); + const validationRun = await this.helpValidationHarness.generateAndValidate(validationOptions); + this.latestHelpValidationRun = validationRun; + addResult('Help validation artifacts', 'ok', `${validationRun.generatedArtifactCount} artifacts`); - message('Generating deterministic wave-2 shard-doc validation artifact suite...'); - const wave2ValidationOptions = await this.buildWave2ValidationOptions({ + message('Generating deterministic shard-doc validation artifact suite...'); + const shardDocValidationOptions = await this.buildShardDocValidationOptions({ projectDir, bmadDir, }); - const wave2ValidationRun = await this.wave2ValidationHarness.generateAndValidate(wave2ValidationOptions); - this.latestWave2ValidationRun = wave2ValidationRun; - addResult('Wave-2 validation artifacts', 'ok', `${wave2ValidationRun.generatedArtifactCount} artifacts`); + const shardDocValidationRun = await this.shardDocValidationHarness.generateAndValidate(shardDocValidationOptions); + this.latestShardDocValidationRun = shardDocValidationRun; + addResult('Shard-doc validation artifacts', 'ok', `${shardDocValidationRun.generatedArtifactCount} artifacts`); - return `${validationRun.generatedArtifactCount + wave2ValidationRun.generatedArtifactCount} validation artifacts generated`; + return `${validationRun.generatedArtifactCount + shardDocValidationRun.generatedArtifactCount} validation artifacts generated`; }, }); diff --git a/tools/cli/installers/lib/core/manifest-generator.js b/tools/cli/installers/lib/core/manifest-generator.js index bffd0a320..2bd05b944 100644 --- a/tools/cli/installers/lib/core/manifest-generator.js +++ b/tools/cli/installers/lib/core/manifest-generator.js @@ -1099,7 +1099,7 @@ class ManifestGenerator { } } - // Create CSV header with compatibility-prefix columns followed by additive wave-1 columns. + // Create CSV header with compatibility-prefix columns followed by additive canonical-identity columns. let csvContent = 'name,displayName,description,module,path,standalone,legacyName,canonicalId,authoritySourceType,authoritySourcePath\n'; // Combine existing and new tasks diff --git a/tools/cli/installers/lib/core/projection-compatibility-validator.js b/tools/cli/installers/lib/core/projection-compatibility-validator.js index 257bbd20f..0a350af20 100644 --- a/tools/cli/installers/lib/core/projection-compatibility-validator.js +++ b/tools/cli/installers/lib/core/projection-compatibility-validator.js @@ -2,7 +2,7 @@ const csv = require('csv-parse/sync'); const TASK_MANIFEST_COMPATIBILITY_PREFIX_COLUMNS = Object.freeze(['name', 'displayName', 'description', 'module', 'path', 'standalone']); -const TASK_MANIFEST_WAVE1_ADDITIVE_COLUMNS = Object.freeze(['legacyName', 'canonicalId', 'authoritySourceType', 'authoritySourcePath']); +const TASK_MANIFEST_CANONICAL_ADDITIVE_COLUMNS = Object.freeze(['legacyName', 'canonicalId', 'authoritySourceType', 'authoritySourcePath']); const HELP_CATALOG_COMPATIBILITY_PREFIX_COLUMNS = Object.freeze([ 'module', @@ -15,7 +15,7 @@ const HELP_CATALOG_COMPATIBILITY_PREFIX_COLUMNS = Object.freeze([ 'required', ]); -const HELP_CATALOG_WAVE1_ADDITIVE_COLUMNS = Object.freeze([ +const HELP_CATALOG_CANONICAL_ADDITIVE_COLUMNS = Object.freeze([ 'agent-name', 'agent-command', 'agent-display-name', @@ -29,12 +29,12 @@ const HELP_CATALOG_WAVE1_ADDITIVE_COLUMNS = Object.freeze([ const PROJECTION_COMPATIBILITY_ERROR_CODES = Object.freeze({ TASK_MANIFEST_CSV_PARSE_FAILED: 'ERR_TASK_MANIFEST_COMPAT_PARSE_FAILED', TASK_MANIFEST_HEADER_PREFIX_MISMATCH: 'ERR_TASK_MANIFEST_COMPAT_HEADER_PREFIX_MISMATCH', - TASK_MANIFEST_HEADER_WAVE1_MISMATCH: 'ERR_TASK_MANIFEST_COMPAT_HEADER_WAVE1_MISMATCH', + TASK_MANIFEST_HEADER_CANONICAL_MISMATCH: 'ERR_TASK_MANIFEST_COMPAT_HEADER_CANONICAL_MISMATCH', TASK_MANIFEST_REQUIRED_COLUMN_MISSING: 'ERR_TASK_MANIFEST_COMPAT_REQUIRED_COLUMN_MISSING', TASK_MANIFEST_ROW_FIELD_EMPTY: 'ERR_TASK_MANIFEST_COMPAT_ROW_FIELD_EMPTY', HELP_CATALOG_CSV_PARSE_FAILED: 'ERR_HELP_CATALOG_COMPAT_PARSE_FAILED', HELP_CATALOG_HEADER_PREFIX_MISMATCH: 'ERR_HELP_CATALOG_COMPAT_HEADER_PREFIX_MISMATCH', - HELP_CATALOG_HEADER_WAVE1_MISMATCH: 'ERR_HELP_CATALOG_COMPAT_HEADER_WAVE1_MISMATCH', + HELP_CATALOG_HEADER_CANONICAL_MISMATCH: 'ERR_HELP_CATALOG_COMPAT_HEADER_CANONICAL_MISMATCH', HELP_CATALOG_REQUIRED_COLUMN_MISSING: 'ERR_HELP_CATALOG_COMPAT_REQUIRED_COLUMN_MISSING', HELP_CATALOG_EXEMPLAR_ROW_CONTRACT_FAILED: 'ERR_HELP_CATALOG_COMPAT_EXEMPLAR_ROW_CONTRACT_FAILED', HELP_CATALOG_SHARD_DOC_ROW_CONTRACT_FAILED: 'ERR_HELP_CATALOG_COMPAT_SHARD_DOC_ROW_CONTRACT_FAILED', @@ -375,10 +375,10 @@ function validateTaskManifestCompatibilitySurface(csvContent, options = {}) { }); assertLockedColumns({ headerColumns, - expectedColumns: TASK_MANIFEST_WAVE1_ADDITIVE_COLUMNS, + expectedColumns: TASK_MANIFEST_CANONICAL_ADDITIVE_COLUMNS, offset: TASK_MANIFEST_COMPATIBILITY_PREFIX_COLUMNS.length, - code: PROJECTION_COMPATIBILITY_ERROR_CODES.TASK_MANIFEST_HEADER_WAVE1_MISMATCH, - detail: 'Task-manifest wave-1 additive columns must remain appended after compatibility-prefix columns', + code: PROJECTION_COMPATIBILITY_ERROR_CODES.TASK_MANIFEST_HEADER_CANONICAL_MISMATCH, + detail: 'Task-manifest canonical additive columns must remain appended after compatibility-prefix columns', surface, sourcePath, }); @@ -419,10 +419,10 @@ function validateHelpCatalogCompatibilitySurface(csvContent, options = {}) { }); assertLockedColumns({ headerColumns, - expectedColumns: HELP_CATALOG_WAVE1_ADDITIVE_COLUMNS, + expectedColumns: HELP_CATALOG_CANONICAL_ADDITIVE_COLUMNS, offset: HELP_CATALOG_COMPATIBILITY_PREFIX_COLUMNS.length, - code: PROJECTION_COMPATIBILITY_ERROR_CODES.HELP_CATALOG_HEADER_WAVE1_MISMATCH, - detail: 'Help-catalog wave-1 additive columns must remain appended after compatibility-prefix columns', + code: PROJECTION_COMPATIBILITY_ERROR_CODES.HELP_CATALOG_HEADER_CANONICAL_MISMATCH, + detail: 'Help-catalog canonical additive columns must remain appended after compatibility-prefix columns', surface, sourcePath, }); @@ -528,9 +528,9 @@ module.exports = { PROJECTION_COMPATIBILITY_ERROR_CODES, ProjectionCompatibilityError, TASK_MANIFEST_COMPATIBILITY_PREFIX_COLUMNS, - TASK_MANIFEST_WAVE1_ADDITIVE_COLUMNS, + TASK_MANIFEST_CANONICAL_ADDITIVE_COLUMNS, HELP_CATALOG_COMPATIBILITY_PREFIX_COLUMNS, - HELP_CATALOG_WAVE1_ADDITIVE_COLUMNS, + HELP_CATALOG_CANONICAL_ADDITIVE_COLUMNS, validateTaskManifestCompatibilitySurface, validateTaskManifestLoaderEntries, validateHelpCatalogCompatibilitySurface, diff --git a/tools/cli/installers/lib/core/wave-2-validation-harness.js b/tools/cli/installers/lib/core/shard-doc-validation-harness.js similarity index 89% rename from tools/cli/installers/lib/core/wave-2-validation-harness.js rename to tools/cli/installers/lib/core/shard-doc-validation-harness.js index 1403fdd72..932ed4db3 100644 --- a/tools/cli/installers/lib/core/wave-2-validation-harness.js +++ b/tools/cli/installers/lib/core/shard-doc-validation-harness.js @@ -8,23 +8,23 @@ const { normalizeDisplayedCommandLabel } = require('./help-catalog-generator'); const SHARD_DOC_SIDECAR_SOURCE_PATH = 'bmad-fork/src/core/tasks/shard-doc.artifact.yaml'; const SHARD_DOC_SOURCE_XML_SOURCE_PATH = 'bmad-fork/src/core/tasks/shard-doc.xml'; -const WAVE2_VALIDATION_ERROR_CODES = Object.freeze({ - REQUIRED_ARTIFACT_MISSING: 'ERR_WAVE2_VALIDATION_REQUIRED_ARTIFACT_MISSING', - CSV_SCHEMA_MISMATCH: 'ERR_WAVE2_VALIDATION_CSV_SCHEMA_MISMATCH', - REQUIRED_ROW_MISSING: 'ERR_WAVE2_VALIDATION_REQUIRED_ROW_MISSING', - YAML_SCHEMA_MISMATCH: 'ERR_WAVE2_VALIDATION_YAML_SCHEMA_MISMATCH', +const SHARD_DOC_VALIDATION_ERROR_CODES = Object.freeze({ + REQUIRED_ARTIFACT_MISSING: 'ERR_SHARD_DOC_VALIDATION_REQUIRED_ARTIFACT_MISSING', + CSV_SCHEMA_MISMATCH: 'ERR_SHARD_DOC_VALIDATION_CSV_SCHEMA_MISMATCH', + REQUIRED_ROW_MISSING: 'ERR_SHARD_DOC_VALIDATION_REQUIRED_ROW_MISSING', + YAML_SCHEMA_MISMATCH: 'ERR_SHARD_DOC_VALIDATION_YAML_SCHEMA_MISMATCH', }); -const WAVE2_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ +const SHARD_DOC_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ Object.freeze({ artifactId: 1, - relativePath: path.join('validation', 'wave-2', 'shard-doc-sidecar-snapshot.yaml'), + relativePath: path.join('validation', 'shard-doc', 'shard-doc-sidecar-snapshot.yaml'), type: 'yaml', requiredTopLevelKeys: ['schemaVersion', 'canonicalId', 'artifactType', 'module', 'sourcePath', 'displayName', 'description', 'status'], }), Object.freeze({ artifactId: 2, - relativePath: path.join('validation', 'wave-2', 'shard-doc-authority-records.csv'), + relativePath: path.join('validation', 'shard-doc', 'shard-doc-authority-records.csv'), type: 'csv', columns: [ 'rowIdentity', @@ -39,7 +39,7 @@ const WAVE2_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 3, - relativePath: path.join('validation', 'wave-2', 'shard-doc-task-manifest-comparison.csv'), + relativePath: path.join('validation', 'shard-doc', 'shard-doc-task-manifest-comparison.csv'), type: 'csv', columns: [ 'surface', @@ -56,13 +56,13 @@ const WAVE2_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 4, - relativePath: path.join('validation', 'wave-2', 'shard-doc-help-catalog-comparison.csv'), + relativePath: path.join('validation', 'shard-doc', 'shard-doc-help-catalog-comparison.csv'), type: 'csv', columns: ['surface', 'sourcePath', 'name', 'workflowFile', 'command', 'rowCountForCanonicalCommand', 'status'], }), Object.freeze({ artifactId: 5, - relativePath: path.join('validation', 'wave-2', 'shard-doc-alias-table.csv'), + relativePath: path.join('validation', 'shard-doc', 'shard-doc-alias-table.csv'), type: 'csv', columns: [ 'rowIdentity', @@ -80,7 +80,7 @@ const WAVE2_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 6, - relativePath: path.join('validation', 'wave-2', 'shard-doc-command-label-report.csv'), + relativePath: path.join('validation', 'shard-doc', 'shard-doc-command-label-report.csv'), type: 'csv', columns: [ 'surface', @@ -96,24 +96,24 @@ const WAVE2_VALIDATION_ARTIFACT_REGISTRY = Object.freeze([ }), Object.freeze({ artifactId: 7, - relativePath: path.join('validation', 'wave-2', 'shard-doc-duplicate-report.csv'), + relativePath: path.join('validation', 'shard-doc', 'shard-doc-duplicate-report.csv'), type: 'csv', columns: ['surface', 'canonicalId', 'normalizedVisibleKey', 'matchingRowCount', 'status'], }), Object.freeze({ artifactId: 8, - relativePath: path.join('validation', 'wave-2', 'shard-doc-artifact-inventory.csv'), + relativePath: path.join('validation', 'shard-doc', 'shard-doc-artifact-inventory.csv'), type: 'csv', columns: ['rowIdentity', 'artifactId', 'artifactPath', 'artifactType', 'required', 'rowCount', 'exists', 'schemaVersion', 'status'], requiredRowIdentityFields: ['rowIdentity'], }), ]); -class Wave2ValidationHarnessError extends Error { +class ShardDocValidationHarnessError extends Error { constructor({ code, detail, artifactId, fieldPath, sourcePath, observedValue, expectedValue }) { const message = `${code}: ${detail} (artifact=${artifactId}, fieldPath=${fieldPath}, sourcePath=${sourcePath})`; super(message); - this.name = 'Wave2ValidationHarnessError'; + this.name = 'ShardDocValidationHarnessError'; this.code = code; this.detail = detail; this.artifactId = artifactId; @@ -170,9 +170,9 @@ function sortRowsDeterministically(rows, columns) { }); } -class Wave2ValidationHarness { +class ShardDocValidationHarness { constructor() { - this.registry = WAVE2_VALIDATION_ARTIFACT_REGISTRY; + this.registry = SHARD_DOC_VALIDATION_ARTIFACT_REGISTRY; } getArtifactRegistry() { @@ -182,7 +182,7 @@ class Wave2ValidationHarness { resolveOutputPaths(options = {}) { const projectDir = path.resolve(options.projectDir || process.cwd()); const planningArtifactsRoot = path.join(projectDir, '_bmad-output', 'planning-artifacts'); - const validationRoot = path.join(planningArtifactsRoot, 'validation', 'wave-2'); + const validationRoot = path.join(planningArtifactsRoot, 'validation', 'shard-doc'); return { projectDir, planningArtifactsRoot, @@ -207,8 +207,8 @@ class Wave2ValidationHarness { if (await fs.pathExists(absolutePath)) { return; } - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, detail: `Required input surface is missing (${description})`, artifactId, fieldPath: '', @@ -223,8 +223,8 @@ class Wave2ValidationHarness { if (match) { return match; } - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, detail, artifactId, fieldPath, @@ -318,8 +318,8 @@ class Wave2ValidationHarness { normalizePath(normalizeValue(row['workflow-file'])).toLowerCase().endsWith('/core/tasks/shard-doc.xml'), ); if (shardDocHelpRows.length !== 1) { - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, detail: 'Expected exactly one shard-doc help-catalog command row', artifactId: 4, fieldPath: 'rows[*].command', @@ -334,8 +334,8 @@ class Wave2ValidationHarness { const observedAliasTypes = new Set(shardDocAliasRows.map((row) => normalizeValue(row.aliasType))); for (const aliasType of requiredAliasTypes) { if (!observedAliasTypes.has(aliasType)) { - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, detail: 'Required shard-doc alias type row is missing', artifactId: 5, fieldPath: 'rows[*].aliasType', @@ -348,8 +348,8 @@ class Wave2ValidationHarness { const shardDocCommandLabelRows = commandLabelRows.filter((row) => normalizeValue(row.canonicalId) === 'bmad-shard-doc'); if (shardDocCommandLabelRows.length !== 1) { - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, detail: 'Expected exactly one shard-doc command-label row', artifactId: 6, fieldPath: 'rows[*].canonicalId', @@ -536,9 +536,9 @@ class Wave2ValidationHarness { for (const artifact of this.registry) { const artifactPath = path.join(outputPaths.planningArtifactsRoot, artifact.relativePath); if (!(await fs.pathExists(artifactPath))) { - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, - detail: 'Required wave-2 validation artifact is missing', + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ARTIFACT_MISSING, + detail: 'Required shard-doc validation artifact is missing', artifactId: artifact.artifactId, fieldPath: '', sourcePath: normalizePath(artifact.relativePath), @@ -552,8 +552,8 @@ class Wave2ValidationHarness { const observedHeader = parseCsvHeader(content); const expectedHeader = artifact.columns || []; if (observedHeader.length !== expectedHeader.length) { - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, detail: 'CSV header length does not match required schema', artifactId: artifact.artifactId, fieldPath: '
', @@ -567,8 +567,8 @@ class Wave2ValidationHarness { const observed = normalizeValue(observedHeader[index]); const expected = normalizeValue(expectedValue); if (observed !== expected) { - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.CSV_SCHEMA_MISMATCH, detail: 'CSV header ordering does not match required schema', artifactId: artifact.artifactId, fieldPath: `header[${index}]`, @@ -581,8 +581,8 @@ class Wave2ValidationHarness { const rows = parseCsvRows(content); if (rows.length === 0) { - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, detail: 'Required CSV artifact rows are missing', artifactId: artifact.artifactId, fieldPath: 'rows', @@ -594,8 +594,8 @@ class Wave2ValidationHarness { for (const requiredField of artifact.requiredRowIdentityFields || []) { for (const [rowIndex, row] of rows.entries()) { if (!normalizeValue(row[requiredField])) { - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, detail: 'Required row identity field is empty', artifactId: artifact.artifactId, fieldPath: `rows[${rowIndex}].${requiredField}`, @@ -611,8 +611,8 @@ class Wave2ValidationHarness { } else if (artifact.type === 'yaml') { const parsed = yaml.parse(await fs.readFile(artifactPath, 'utf8')); if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.YAML_SCHEMA_MISMATCH, + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.YAML_SCHEMA_MISMATCH, detail: 'YAML artifact root must be a mapping object', artifactId: artifact.artifactId, fieldPath: '', @@ -623,8 +623,8 @@ class Wave2ValidationHarness { } for (const key of artifact.requiredTopLevelKeys || []) { if (!Object.prototype.hasOwnProperty.call(parsed, key)) { - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.YAML_SCHEMA_MISMATCH, + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.YAML_SCHEMA_MISMATCH, detail: 'Required YAML key is missing', artifactId: artifact.artifactId, fieldPath: key, @@ -664,8 +664,8 @@ class Wave2ValidationHarness { const inventoryRows = artifactDataById.get(8)?.rows || []; if (inventoryRows.length !== this.registry.length) { - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, detail: 'Artifact inventory must include one row per required artifact', artifactId: 8, fieldPath: 'rows', @@ -699,8 +699,8 @@ class Wave2ValidationHarness { Number.isFinite(observedRowCount) && (expectedInventoryRowCount === null ? observedRowCount >= 1 : observedRowCount === expectedInventoryRowCount); if (!rowCountIsValid) { - throw new Wave2ValidationHarnessError({ - code: WAVE2_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, + throw new ShardDocValidationHarnessError({ + code: SHARD_DOC_VALIDATION_ERROR_CODES.REQUIRED_ROW_MISSING, detail: 'Artifact inventory rowCount does not satisfy deterministic contract', artifactId: 8, fieldPath: `rows[artifactId=${artifact.artifactId}].rowCount`, @@ -729,8 +729,8 @@ class Wave2ValidationHarness { } module.exports = { - WAVE2_VALIDATION_ERROR_CODES, - WAVE2_VALIDATION_ARTIFACT_REGISTRY, - Wave2ValidationHarnessError, - Wave2ValidationHarness, + SHARD_DOC_VALIDATION_ERROR_CODES, + SHARD_DOC_VALIDATION_ARTIFACT_REGISTRY, + ShardDocValidationHarnessError, + ShardDocValidationHarness, }; diff --git a/tools/cli/installers/lib/core/sidecar-contract-validator.js b/tools/cli/installers/lib/core/sidecar-contract-validator.js index b9c4c02ba..57868e949 100644 --- a/tools/cli/installers/lib/core/sidecar-contract-validator.js +++ b/tools/cli/installers/lib/core/sidecar-contract-validator.js @@ -230,9 +230,9 @@ function validateHelpSidecarContractData(sidecarData, options = {}) { missingDependenciesDetail: 'Exemplar sidecar requires an explicit dependencies block.', dependenciesObjectDetail: 'Exemplar sidecar requires an explicit dependencies object.', dependenciesRequiresArrayDetail: 'Exemplar dependencies.requires must be an array.', - dependenciesRequiresNotEmptyDetail: 'Wave-1 exemplar requires explicit zero dependencies: dependencies.requires must be [].', - artifactTypeDetail: 'Wave-1 exemplar requires artifactType to equal "task".', - moduleDetail: 'Wave-1 exemplar requires module to equal "core".', + dependenciesRequiresNotEmptyDetail: 'help exemplar requires explicit zero dependencies: dependencies.requires must be [].', + artifactTypeDetail: 'help exemplar requires artifactType to equal "task".', + moduleDetail: 'help exemplar requires module to equal "core".', requiresMustBeEmpty: true, }); } @@ -250,9 +250,9 @@ function validateShardDocSidecarContractData(sidecarData, options = {}) { missingDependenciesDetail: 'Shard-doc sidecar requires an explicit dependencies block.', dependenciesObjectDetail: 'Shard-doc sidecar requires an explicit dependencies object.', dependenciesRequiresArrayDetail: 'Shard-doc dependencies.requires must be an array.', - dependenciesRequiresNotEmptyDetail: 'Wave-2 shard-doc contract requires explicit zero dependencies: dependencies.requires must be [].', - artifactTypeDetail: 'Wave-2 shard-doc contract requires artifactType to equal "task".', - moduleDetail: 'Wave-2 shard-doc contract requires module to equal "core".', + dependenciesRequiresNotEmptyDetail: 'Shard-doc contract requires explicit zero dependencies: dependencies.requires must be [].', + artifactTypeDetail: 'Shard-doc contract requires artifactType to equal "task".', + moduleDetail: 'Shard-doc contract requires module to equal "core".', requiresMustBeEmpty: true, }); }