(filePath, fixtureNames)
| 87 | } |
| 88 | |
| 89 | function lintFile(filePath, fixtureNames) { |
| 90 | const violations = []; |
| 91 | let doc; |
| 92 | try { |
| 93 | doc = yaml.load(fs.readFileSync(filePath, 'utf8')); |
| 94 | } catch (err) { |
| 95 | return [{ filePath, trail: [], name: null, reason: `skipped (YAML parse failed: ${err.message}) — fix via upstream YAML lint`, severity: 'warn' }]; |
| 96 | } |
| 97 | if (!doc) return violations; |
| 98 | for (const hit of findSubstitutionBindings(doc, [])) { |
| 99 | if (fixtureNames.has(hit.vector_name)) continue; |
| 100 | if (hit.has_override) { |
| 101 | // Custom vector with inline raw_value/expected_encoded — not required to |
| 102 | // match the canonical fixture. When the author provides an explicit |
| 103 | // `override_reason: "<justification>"` on the binding, suppress the |
| 104 | // warning entirely (opt-in override is a contract feature, not a |
| 105 | // violation). Without an override_reason, emit a warn so reviewers see |
| 106 | // the non-canonical binding. |
| 107 | if (hit.has_override_reason) continue; |
| 108 | violations.push({ |
| 109 | filePath, |
| 110 | trail: hit.trail, |
| 111 | name: hit.vector_name, |
| 112 | reason: `non-canonical vector (has raw_value/expected_encoded override) — add an \`override_reason: "..."\` field on the binding to document the justification and suppress this warning`, |
| 113 | severity: 'warn', |
| 114 | }); |
| 115 | continue; |
| 116 | } |
| 117 | violations.push({ |
| 118 | filePath, |
| 119 | trail: hit.trail, |
| 120 | name: hit.vector_name, |
| 121 | reason: `not in canonical fixture (static/test-vectors/catalog-macro-substitution.json)`, |
| 122 | severity: 'error', |
| 123 | }); |
| 124 | } |
| 125 | return violations; |
| 126 | } |
| 127 | |
| 128 | function formatTrail(trail) { |
| 129 | return trail.map(seg => (typeof seg === 'number' ? `[${seg}]` : `.${seg}`)).join('').replace(/^\./, ''); |
no test coverage detected