|
| 1 | +#!/usr/bin/env node |
| 2 | +/* |
| 3 | +Validates that `.github/copilot-instructions.md` contains required SSOT tags/sections. |
| 4 | +Checks: |
| 5 | +- Presence of XML-like tags: <CRITICAL_REQUIREMENT>, <WORKFLOW_ENFORCEMENT>, <NAMING_REQUIREMENTS>, <COMMIT_REQUIREMENTS>, <PROCESS_REQUIREMENTS>, <CODING_REQUIREMENTS> |
| 6 | +- Presence of anchor #quality-policy |
| 7 | +- Presence of key headings: Project Methodologies, Coding Standards |
| 8 | +Exit non-zero with a readable message if any check fails. |
| 9 | +*/ |
| 10 | + |
| 11 | +const fs = require('fs'); |
| 12 | +const path = require('path'); |
| 13 | + |
| 14 | +function fail(msg) { |
| 15 | + console.error(msg); |
| 16 | + process.exit(1); |
| 17 | +} |
| 18 | + |
| 19 | +function main() { |
| 20 | + const repoRoot = process.cwd(); |
| 21 | + const filePath = path.join(repoRoot, '.github', 'copilot-instructions.md'); |
| 22 | + if (!fs.existsSync(filePath)) fail(`File not found: ${filePath}`); |
| 23 | + const content = fs.readFileSync(filePath, 'utf8'); |
| 24 | + |
| 25 | + const requiredTags = [ |
| 26 | + '<CRITICAL_REQUIREMENT', |
| 27 | + '<WORKFLOW_ENFORCEMENT', |
| 28 | + '<NAMING_REQUIREMENTS', |
| 29 | + '<COMMIT_REQUIREMENTS', |
| 30 | + '<PROCESS_REQUIREMENTS', |
| 31 | + '<CODING_REQUIREMENTS' |
| 32 | + ]; |
| 33 | + const missingTags = requiredTags.filter(t => !content.includes(t)); |
| 34 | + if (missingTags.length) { |
| 35 | + fail('Missing required tags: ' + missingTags.join(', ')); |
| 36 | + } |
| 37 | + |
| 38 | + if (!content.includes('# Quality & Coverage Policy') && !content.includes('# Quality & Coverage Policy'.toLowerCase())) { |
| 39 | + // Also allow anchor reference if heading case changes |
| 40 | + if (!content.toLowerCase().includes('## quality & coverage policy') && !content.includes('#quality-policy')) { |
| 41 | + fail('Missing Quality & Coverage Policy section or anchor (#quality-policy).'); |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + const requiredHeadings = [ |
| 46 | + '## Project Methodologies', |
| 47 | + '## Coding Standards' |
| 48 | + ]; |
| 49 | + const missingHeadings = requiredHeadings.filter(h => !content.includes(h)); |
| 50 | + if (missingHeadings.length) { |
| 51 | + fail('Missing required headings: ' + missingHeadings.join(', ')); |
| 52 | + } |
| 53 | + |
| 54 | + console.log('Policy validation passed.'); |
| 55 | +} |
| 56 | + |
| 57 | +if (require.main === module) { |
| 58 | + main(); |
| 59 | +} |
0 commit comments