From c71db6627cb8b059513c81d739ae036896226fb7 Mon Sep 17 00:00:00 2001 From: "Dylan Mordaunt (ISLHD)" Date: Wed, 12 Aug 2026 08:26:51 +1000 Subject: [PATCH 1/2] feat(contracts): compile severity tables from the pattern registry Keep pattern bodies in Markdown and emit the compiled severity lists from patterns.json so table IDs cannot drift by hand. Refs #278 Co-authored-by: Cursor --- SKILL.md | 76 +++++++++--------- conductor/tracks.md | 1 + .../plan.md | 4 +- docs/agent-skills-contract.md | 4 +- references/core-patterns.md | 77 +++++++++---------- scripts/compile-skill.js | 23 ++++-- scripts/lib/skill-contracts.js | 46 +++++++++++ test/skill-contracts.test.js | 19 +++++ 8 files changed, 163 insertions(+), 87 deletions(-) diff --git a/SKILL.md b/SKILL.md index e5947aa..c51c35e 100644 --- a/SKILL.md +++ b/SKILL.md @@ -238,55 +238,55 @@ the detailed pattern definitions. ### Critical (immediate AI detection) -- Pattern 19: Collaborative communication artifacts -- Pattern 20: Knowledge-cutoff disclaimers -- Pattern 21: Sycophantic tone -- Pattern 25: AI signatures in code -- Pattern 27: Technical literal preservation (must preserve) +- Pattern 19: Collaborative Communication Artifacts +- Pattern 20: Knowledge-Cutoff Disclaimers and Speculative Gap-Filling (includes upstream v2.8 refinement) +- Pattern 21: Sycophantic Tone +- Pattern 25: AI Signatures in Code +- Pattern 27: Technical Literal Preservation (must preserve) ### High (strong AI signals) -- Pattern 1: Undue emphasis on significance -- Pattern 3: Superficial -ing analyses -- Pattern 4: Promotional language -- Pattern 31: Extended thinking tags +- Pattern 1: Undue Emphasis on Significance +- Pattern 3: Superficial -ing Analyses +- Pattern 4: Promotional Language +- Pattern 31: Extended Thinking Tags ### Medium (moderate AI signals) -- Pattern 2: Undue emphasis on notability -- Pattern 5: Vague attributions and back-references -- Pattern 6: Formulaic "Challenges" sections -- Pattern 7: Overused AI vocabulary -- Pattern 8: Copula avoidance -- Pattern 11: Elegant variation and repeated openings -- Pattern 32: JSON mode artifacts -- Pattern 33: Tool use documentation -- Pattern 40: Passive voice and subjectless fragments (Upstream §13) +- Pattern 2: Undue Emphasis on Notability +- Pattern 5: Vague Attributions and Back-References +- Pattern 6: Formulaic "Challenges" Sections +- Pattern 7: Overused AI Vocabulary +- Pattern 8: Copula Avoidance +- Pattern 11: Elegant Variation and Repeated Sentence Openings +- Pattern 32: JSON Mode Artifacts +- Pattern 33: Tool Use Documentation +- Pattern 40: Passive Voice and Subjectless Fragments (Upstream §13, #146) ### Low (weak AI signals) -- Pattern 9: Negative parallelisms -- Pattern 10: Rule of three overuse -- Pattern 12: False ranges -- Pattern 13: Em dash overuse -- Pattern 14: Overuse of boldface -- Pattern 15: Inline-header lists -- Pattern 16: Title case in headings +- Pattern 9: Negative Parallelisms +- Pattern 10: Rule of Three Overuse +- Pattern 12: False Ranges +- Pattern 13: Em/En Dash Hard Cut +- Pattern 14: Overuse of Boldface +- Pattern 15: Inline-Header Vertical Lists +- Pattern 16: Title Case in Headings - Pattern 17: Emojis -- Pattern 18: Quotation mark issues -- Pattern 22: Filler phrases -- Pattern 23: Excessive hedging -- Pattern 24: Generic positive conclusions -- Pattern 26: Over-structuring -- Pattern 28: Persuasive tropes +- Pattern 18: Quotation Mark Issues +- Pattern 22: Filler Phrases +- Pattern 23: Excessive Hedging +- Pattern 24: Generic Positive Conclusions +- Pattern 26: Over-Structuring +- Pattern 28: Persuasive Tropes - Pattern 29: Signposting -- Pattern 30: Fragmented headers -- Pattern 34: Over-polished conclusions -- Pattern 35: Manufactured punchlines and staccato drama (Upstream #31) -- Pattern 36: Aphorism formulas (Upstream #32) -- Pattern 37: Conversational rhetorical openers (Upstream #33) -- Pattern 38: Diff-anchored writing, shadowboxing, and editorial scar tissue -- Pattern 39: Hyphenated word pair overuse (narrowed, upstream) +- Pattern 30: Fragmented Headers +- Pattern 34: Over-Polished Conclusions +- Pattern 35: Manufactured Punchlines and Staccato Drama (Upstream #31) +- Pattern 36: Aphorism Formulas (Upstream #32) +- Pattern 37: Conversational Rhetorical Openers (Upstream #33) +- Pattern 38: Diff-Anchored Writing, Shadowboxing, and Editorial Scar Tissue +- Pattern 39: Hyphenated Word Pair Overuse (narrowed rule, upstream v2.8) ## DETECTION GUIDANCE diff --git a/conductor/tracks.md b/conductor/tracks.md index aeb3175..00efd46 100644 --- a/conductor/tracks.md +++ b/conductor/tracks.md @@ -30,6 +30,7 @@ This file tracks all major tracks for the project. Each track has its own detail `src/document-intelligence/`. [#278](https://github.com/edithatogo/authentext/issues/278). Contracts are [PR #293](https://github.com/edithatogo/authentext/pull/293). + Registry seed is [PR #296](https://github.com/edithatogo/authentext/pull/296). _Link: [tracks/pattern-registry-contracts_20260811/index.md](./tracks/pattern-registry-contracts_20260811/index.md)_ - [x] **voice-corpus-calibration_20260811** (P1) - Point Authentext at diff --git a/conductor/tracks/pattern-registry-contracts_20260811/plan.md b/conductor/tracks/pattern-registry-contracts_20260811/plan.md index 1d05de5..918aecf 100644 --- a/conductor/tracks/pattern-registry-contracts_20260811/plan.md +++ b/conductor/tracks/pattern-registry-contracts_20260811/plan.md @@ -15,7 +15,7 @@ registry entry fails `npm run sync` / validate. Concordance is enforced by `validate-skill-contracts.js` against Markdown headings rather than by rewriting `compile-skill.js`. -- [ ] Task: Teach `compile-skill.js` to emit the severity tables from +- [x] Task: Teach `compile-skill.js` to emit the severity tables from `patterns.json`. Keep pattern bodies in modules until a later slice migrates them. - [ ] Task: Migrate pattern bodies in small PRs, not one dump. @@ -44,5 +44,5 @@ - `src/document-intelligence/patterns-registry.schema.json` - `src/document-intelligence/patterns.json` - Concordance check: Markdown headings, severity-table IDs, frontmatter count -- Compiler path that emits severity tables (deferred if `compile-skill.js` is busy) +- Compiler path that emits severity tables from `patterns.json` - Documented Agent Skills contract diff --git a/docs/agent-skills-contract.md b/docs/agent-skills-contract.md index f773367..4fd59a9 100644 --- a/docs/agent-skills-contract.md +++ b/docs/agent-skills-contract.md @@ -48,5 +48,5 @@ Schemas live next to the other document-intelligence contracts: `patterns.json` is the machine-readable seed for the 40 core patterns. The validator checks it against `src/modules/SKILL_CORE_PATTERNS.md` headings, body severities, the severity-table IDs, and the frontmatter `patterns` -count. Pattern bodies stay in the Markdown module until a later compile -slice. +count. `npm run sync` emits the severity tables from that registry. Pattern +bodies stay in the Markdown module until a later compile slice. diff --git a/references/core-patterns.md b/references/core-patterns.md index d39af04..1fccdf8 100644 --- a/references/core-patterns.md +++ b/references/core-patterns.md @@ -789,56 +789,55 @@ The system processes requests in under 100ms. ### Critical (immediate AI detection) -- Pattern 19: Collaborative communication artifacts -- Pattern 20: Knowledge-cutoff disclaimers -- Pattern 21: Sycophantic tone -- Pattern 25: AI signatures in code -- Pattern 27: Technical literal preservation (must preserve) +- Pattern 19: Collaborative Communication Artifacts +- Pattern 20: Knowledge-Cutoff Disclaimers and Speculative Gap-Filling (includes upstream v2.8 refinement) +- Pattern 21: Sycophantic Tone +- Pattern 25: AI Signatures in Code +- Pattern 27: Technical Literal Preservation (must preserve) ### High (strong AI signals) -- Pattern 1: Undue emphasis on significance -- Pattern 3: Superficial -ing analyses -- Pattern 4: Promotional language -- Pattern 31: Extended thinking tags +- Pattern 1: Undue Emphasis on Significance +- Pattern 3: Superficial -ing Analyses +- Pattern 4: Promotional Language +- Pattern 31: Extended Thinking Tags ### Medium (moderate AI signals) -- Pattern 2: Undue emphasis on notability -- Pattern 5: Vague attributions and back-references -- Pattern 6: Formulaic "Challenges" sections -- Pattern 7: Overused AI vocabulary -- Pattern 8: Copula avoidance -- Pattern 11: Elegant variation and repeated openings -- Pattern 32: JSON mode artifacts -- Pattern 33: Tool use documentation -- Pattern 40: Passive voice and subjectless fragments (Upstream §13) +- Pattern 2: Undue Emphasis on Notability +- Pattern 5: Vague Attributions and Back-References +- Pattern 6: Formulaic "Challenges" Sections +- Pattern 7: Overused AI Vocabulary +- Pattern 8: Copula Avoidance +- Pattern 11: Elegant Variation and Repeated Sentence Openings +- Pattern 32: JSON Mode Artifacts +- Pattern 33: Tool Use Documentation +- Pattern 40: Passive Voice and Subjectless Fragments (Upstream §13, #146) ### Low (weak AI signals) -- Pattern 9: Negative parallelisms -- Pattern 10: Rule of three overuse -- Pattern 12: False ranges -- Pattern 13: Em dash overuse -- Pattern 14: Overuse of boldface -- Pattern 15: Inline-header lists -- Pattern 16: Title case in headings +- Pattern 9: Negative Parallelisms +- Pattern 10: Rule of Three Overuse +- Pattern 12: False Ranges +- Pattern 13: Em/En Dash Hard Cut +- Pattern 14: Overuse of Boldface +- Pattern 15: Inline-Header Vertical Lists +- Pattern 16: Title Case in Headings - Pattern 17: Emojis -- Pattern 18: Quotation mark issues -- Pattern 22: Filler phrases -- Pattern 23: Excessive hedging -- Pattern 24: Generic positive conclusions -- Pattern 26: Over-structuring -- Pattern 28: Persuasive tropes +- Pattern 18: Quotation Mark Issues +- Pattern 22: Filler Phrases +- Pattern 23: Excessive Hedging +- Pattern 24: Generic Positive Conclusions +- Pattern 26: Over-Structuring +- Pattern 28: Persuasive Tropes - Pattern 29: Signposting -- Pattern 30: Fragmented headers -- Pattern 34: Over-polished conclusions -- Pattern 35: Manufactured punchlines and staccato drama (Upstream #31) -- Pattern 36: Aphorism formulas (Upstream #32) -- Pattern 37: Conversational rhetorical openers (Upstream #33) -- Pattern 38: Diff-anchored writing, shadowboxing, and editorial scar tissue -- Pattern 39: Hyphenated word pair overuse (narrowed, upstream) - +- Pattern 30: Fragmented Headers +- Pattern 34: Over-Polished Conclusions +- Pattern 35: Manufactured Punchlines and Staccato Drama (Upstream #31) +- Pattern 36: Aphorism Formulas (Upstream #32) +- Pattern 37: Conversational Rhetorical Openers (Upstream #33) +- Pattern 38: Diff-Anchored Writing, Shadowboxing, and Editorial Scar Tissue +- Pattern 39: Hyphenated Word Pair Overuse (narrowed rule, upstream v2.8) --- _Module Version: 3.2.0_ diff --git a/scripts/compile-skill.js b/scripts/compile-skill.js index 18a51b6..58288d4 100644 --- a/scripts/compile-skill.js +++ b/scripts/compile-skill.js @@ -15,6 +15,12 @@ import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; +import { + loadContractJson, + PATTERNS_REGISTRY, + renderSeverityClassification, + replaceSeveritySection, +} from './lib/skill-contracts.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -271,6 +277,11 @@ policy: `; } +function renderedSeverityFromRegistry() { + const registry = loadContractJson(ROOT_DIR, PATTERNS_REGISTRY); + return renderSeverityClassification(registry.patterns); +} + /** * @param {Record} modules @@ -285,7 +296,11 @@ function writeReferenceTree(modules) { continue; } - const body = addReferenceNavigation(stripFrontmatter(moduleContent).trim()); + let stripped = stripFrontmatter(moduleContent).trim(); + if (key === 'core') { + stripped = replaceSeveritySection(stripped, renderedSeverityFromRegistry()); + } + const body = addReferenceNavigation(stripped); const targetPath = path.join(referencesDir, filename); fs.writeFileSync(targetPath, `${body}\n`, 'utf-8'); console.log(`✓ Written: ${OUTPUT.referencesDir}/${filename}`); @@ -306,11 +321,7 @@ function compileStandardSkill(modules) { const strippedCore = stripFrontmatter(modules.core); const intro = buildStandardIntro(strippedCore); - const severity = extractSection( - strippedCore, - 'SEVERITY CLASSIFICATION', - '\n---\n\n_Module Version' - ); + const severity = renderedSeverityFromRegistry(); const detection = extractSection(strippedCore, 'DETECTION GUIDANCE'); const referenceLinks = [ diff --git a/scripts/lib/skill-contracts.js b/scripts/lib/skill-contracts.js index dbb1850..1b51005 100644 --- a/scripts/lib/skill-contracts.js +++ b/scripts/lib/skill-contracts.js @@ -394,6 +394,52 @@ export function validatePatternRegistryConcordance(registry, source) { return errors; } +const SEVERITY_TABLE_HEADINGS = Object.freeze({ + critical: '### Critical (immediate AI detection)', + high: '### High (strong AI signals)', + medium: '### Medium (moderate AI signals)', + low: '### Low (weak AI signals)', +}); + +/** + * @param {unknown[]} records + * @returns {string} + */ +export function renderSeverityClassification(records) { + if (!Array.isArray(records)) { + throw new TypeError('pattern records must be an array'); + } + const buckets = { critical: [], high: [], medium: [], low: [] }; + for (const record of [...records].sort((left, right) => left.number - right.number)) { + const suffix = record.must_preserve ? ' (must preserve)' : ''; + buckets[record.severity].push(`- Pattern ${record.number}: ${record.title}${suffix}`); + } + const parts = ['## SEVERITY CLASSIFICATION', '']; + for (const severity of Object.keys(SEVERITY_TABLE_HEADINGS)) { + parts.push(SEVERITY_TABLE_HEADINGS[severity], '', ...buckets[severity], ''); + } + return parts.join('\n').trim(); +} + +/** + * Replace the compiled severity block while leaving pattern bodies in place. + * @param {string} content + * @param {string} rendered + * @returns {string} + */ +export function replaceSeveritySection(content, rendered) { + const startToken = '\n## SEVERITY CLASSIFICATION\n'; + const start = content.indexOf(startToken); + if (start === -1) { + throw new Error('missing ## SEVERITY CLASSIFICATION section'); + } + const endMarker = '\n---\n\n_Module Version'; + const end = content.indexOf(endMarker, start + 1); + const prefix = content.slice(0, start + 1); + const suffix = end === -1 ? '\n' : content.slice(end); + return `${prefix}${rendered}${suffix}`; +} + /** * @param {unknown[]} records * @param {Record} schema diff --git a/test/skill-contracts.test.js b/test/skill-contracts.test.js index a51efb8..1c3c688 100644 --- a/test/skill-contracts.test.js +++ b/test/skill-contracts.test.js @@ -22,6 +22,8 @@ import { parseFrontmatterPatternCount, parsePortableFrontmatter, parseSeverityTable, + renderSeverityClassification, + replaceSeveritySection, validateAgainstSchema, validatePackagedSkillLayout, validatePatternRecord, @@ -277,6 +279,23 @@ test('concordance reports missing headings, table gaps, and severity drift', () assert.deepEqual(validatePatternRegistryConcordance(registry.patterns, source), []); }); +test('severity tables compile from the registry without duplicate IDs', () => { + const registry = loadContractJson(ROOT, PATTERNS_REGISTRY); + const rendered = renderSeverityClassification(registry.patterns); + const ids = [...rendered.matchAll(/^- Pattern (\d+):/gm)].map((match) => match[1]); + assert.equal(ids.length, 40); + assert.equal(new Set(ids).size, 40); + assert.match(rendered, /### Critical \(immediate AI detection\)/); + assert.match(rendered, /Pattern 27: Technical Literal Preservation \(must preserve\)/); + assert.throws(() => renderSeverityClassification({}), /must be an array/); + + const source = fs.readFileSync(path.join(ROOT, CORE_PATTERNS_MODULE), 'utf8'); + const replaced = replaceSeveritySection(source, rendered); + assert.match(replaced, /Pattern 13: Em\/En Dash Hard Cut/); + assert.doesNotMatch(replaced, /Pattern 13: Em dash overuse/); + assert.throws(() => replaceSeveritySection('# no table\n', rendered), /missing ## SEVERITY/); +}); + test('collectContractErrors fails when the registry file is missing', () => { const fixture = fs.mkdtempSync(path.join(os.tmpdir(), 'authentext-no-registry-')); fs.cpSync(path.join(ROOT, CONTRACT_DIR), path.join(fixture, CONTRACT_DIR), { recursive: true }); From 018253118de6cb29bf1fdc0e2dc7a64ccaec44df Mon Sep 17 00:00:00 2001 From: "Dylan Mordaunt (ISLHD)" Date: Wed, 12 Aug 2026 08:37:12 +1000 Subject: [PATCH 2/2] fix(contracts): keep compiled severity labels stable Use the existing table labels from the registry so npm run sync keeps the prose maintainers already review. Co-authored-by: Cursor --- SKILL.md | 76 +++++------ references/core-patterns.md | 77 +++++------ scripts/lib/skill-contracts.js | 8 +- src/document-intelligence/pattern.schema.json | 1 + src/document-intelligence/patterns.json | 120 ++++++++++++------ test/skill-contracts.test.js | 7 +- 6 files changed, 167 insertions(+), 122 deletions(-) diff --git a/SKILL.md b/SKILL.md index c51c35e..e5947aa 100644 --- a/SKILL.md +++ b/SKILL.md @@ -238,55 +238,55 @@ the detailed pattern definitions. ### Critical (immediate AI detection) -- Pattern 19: Collaborative Communication Artifacts -- Pattern 20: Knowledge-Cutoff Disclaimers and Speculative Gap-Filling (includes upstream v2.8 refinement) -- Pattern 21: Sycophantic Tone -- Pattern 25: AI Signatures in Code -- Pattern 27: Technical Literal Preservation (must preserve) +- Pattern 19: Collaborative communication artifacts +- Pattern 20: Knowledge-cutoff disclaimers +- Pattern 21: Sycophantic tone +- Pattern 25: AI signatures in code +- Pattern 27: Technical literal preservation (must preserve) ### High (strong AI signals) -- Pattern 1: Undue Emphasis on Significance -- Pattern 3: Superficial -ing Analyses -- Pattern 4: Promotional Language -- Pattern 31: Extended Thinking Tags +- Pattern 1: Undue emphasis on significance +- Pattern 3: Superficial -ing analyses +- Pattern 4: Promotional language +- Pattern 31: Extended thinking tags ### Medium (moderate AI signals) -- Pattern 2: Undue Emphasis on Notability -- Pattern 5: Vague Attributions and Back-References -- Pattern 6: Formulaic "Challenges" Sections -- Pattern 7: Overused AI Vocabulary -- Pattern 8: Copula Avoidance -- Pattern 11: Elegant Variation and Repeated Sentence Openings -- Pattern 32: JSON Mode Artifacts -- Pattern 33: Tool Use Documentation -- Pattern 40: Passive Voice and Subjectless Fragments (Upstream §13, #146) +- Pattern 2: Undue emphasis on notability +- Pattern 5: Vague attributions and back-references +- Pattern 6: Formulaic "Challenges" sections +- Pattern 7: Overused AI vocabulary +- Pattern 8: Copula avoidance +- Pattern 11: Elegant variation and repeated openings +- Pattern 32: JSON mode artifacts +- Pattern 33: Tool use documentation +- Pattern 40: Passive voice and subjectless fragments (Upstream §13) ### Low (weak AI signals) -- Pattern 9: Negative Parallelisms -- Pattern 10: Rule of Three Overuse -- Pattern 12: False Ranges -- Pattern 13: Em/En Dash Hard Cut -- Pattern 14: Overuse of Boldface -- Pattern 15: Inline-Header Vertical Lists -- Pattern 16: Title Case in Headings +- Pattern 9: Negative parallelisms +- Pattern 10: Rule of three overuse +- Pattern 12: False ranges +- Pattern 13: Em dash overuse +- Pattern 14: Overuse of boldface +- Pattern 15: Inline-header lists +- Pattern 16: Title case in headings - Pattern 17: Emojis -- Pattern 18: Quotation Mark Issues -- Pattern 22: Filler Phrases -- Pattern 23: Excessive Hedging -- Pattern 24: Generic Positive Conclusions -- Pattern 26: Over-Structuring -- Pattern 28: Persuasive Tropes +- Pattern 18: Quotation mark issues +- Pattern 22: Filler phrases +- Pattern 23: Excessive hedging +- Pattern 24: Generic positive conclusions +- Pattern 26: Over-structuring +- Pattern 28: Persuasive tropes - Pattern 29: Signposting -- Pattern 30: Fragmented Headers -- Pattern 34: Over-Polished Conclusions -- Pattern 35: Manufactured Punchlines and Staccato Drama (Upstream #31) -- Pattern 36: Aphorism Formulas (Upstream #32) -- Pattern 37: Conversational Rhetorical Openers (Upstream #33) -- Pattern 38: Diff-Anchored Writing, Shadowboxing, and Editorial Scar Tissue -- Pattern 39: Hyphenated Word Pair Overuse (narrowed rule, upstream v2.8) +- Pattern 30: Fragmented headers +- Pattern 34: Over-polished conclusions +- Pattern 35: Manufactured punchlines and staccato drama (Upstream #31) +- Pattern 36: Aphorism formulas (Upstream #32) +- Pattern 37: Conversational rhetorical openers (Upstream #33) +- Pattern 38: Diff-anchored writing, shadowboxing, and editorial scar tissue +- Pattern 39: Hyphenated word pair overuse (narrowed, upstream) ## DETECTION GUIDANCE diff --git a/references/core-patterns.md b/references/core-patterns.md index 1fccdf8..d39af04 100644 --- a/references/core-patterns.md +++ b/references/core-patterns.md @@ -789,55 +789,56 @@ The system processes requests in under 100ms. ### Critical (immediate AI detection) -- Pattern 19: Collaborative Communication Artifacts -- Pattern 20: Knowledge-Cutoff Disclaimers and Speculative Gap-Filling (includes upstream v2.8 refinement) -- Pattern 21: Sycophantic Tone -- Pattern 25: AI Signatures in Code -- Pattern 27: Technical Literal Preservation (must preserve) +- Pattern 19: Collaborative communication artifacts +- Pattern 20: Knowledge-cutoff disclaimers +- Pattern 21: Sycophantic tone +- Pattern 25: AI signatures in code +- Pattern 27: Technical literal preservation (must preserve) ### High (strong AI signals) -- Pattern 1: Undue Emphasis on Significance -- Pattern 3: Superficial -ing Analyses -- Pattern 4: Promotional Language -- Pattern 31: Extended Thinking Tags +- Pattern 1: Undue emphasis on significance +- Pattern 3: Superficial -ing analyses +- Pattern 4: Promotional language +- Pattern 31: Extended thinking tags ### Medium (moderate AI signals) -- Pattern 2: Undue Emphasis on Notability -- Pattern 5: Vague Attributions and Back-References -- Pattern 6: Formulaic "Challenges" Sections -- Pattern 7: Overused AI Vocabulary -- Pattern 8: Copula Avoidance -- Pattern 11: Elegant Variation and Repeated Sentence Openings -- Pattern 32: JSON Mode Artifacts -- Pattern 33: Tool Use Documentation -- Pattern 40: Passive Voice and Subjectless Fragments (Upstream §13, #146) +- Pattern 2: Undue emphasis on notability +- Pattern 5: Vague attributions and back-references +- Pattern 6: Formulaic "Challenges" sections +- Pattern 7: Overused AI vocabulary +- Pattern 8: Copula avoidance +- Pattern 11: Elegant variation and repeated openings +- Pattern 32: JSON mode artifacts +- Pattern 33: Tool use documentation +- Pattern 40: Passive voice and subjectless fragments (Upstream §13) ### Low (weak AI signals) -- Pattern 9: Negative Parallelisms -- Pattern 10: Rule of Three Overuse -- Pattern 12: False Ranges -- Pattern 13: Em/En Dash Hard Cut -- Pattern 14: Overuse of Boldface -- Pattern 15: Inline-Header Vertical Lists -- Pattern 16: Title Case in Headings +- Pattern 9: Negative parallelisms +- Pattern 10: Rule of three overuse +- Pattern 12: False ranges +- Pattern 13: Em dash overuse +- Pattern 14: Overuse of boldface +- Pattern 15: Inline-header lists +- Pattern 16: Title case in headings - Pattern 17: Emojis -- Pattern 18: Quotation Mark Issues -- Pattern 22: Filler Phrases -- Pattern 23: Excessive Hedging -- Pattern 24: Generic Positive Conclusions -- Pattern 26: Over-Structuring -- Pattern 28: Persuasive Tropes +- Pattern 18: Quotation mark issues +- Pattern 22: Filler phrases +- Pattern 23: Excessive hedging +- Pattern 24: Generic positive conclusions +- Pattern 26: Over-structuring +- Pattern 28: Persuasive tropes - Pattern 29: Signposting -- Pattern 30: Fragmented Headers -- Pattern 34: Over-Polished Conclusions -- Pattern 35: Manufactured Punchlines and Staccato Drama (Upstream #31) -- Pattern 36: Aphorism Formulas (Upstream #32) -- Pattern 37: Conversational Rhetorical Openers (Upstream #33) -- Pattern 38: Diff-Anchored Writing, Shadowboxing, and Editorial Scar Tissue -- Pattern 39: Hyphenated Word Pair Overuse (narrowed rule, upstream v2.8) +- Pattern 30: Fragmented headers +- Pattern 34: Over-polished conclusions +- Pattern 35: Manufactured punchlines and staccato drama (Upstream #31) +- Pattern 36: Aphorism formulas (Upstream #32) +- Pattern 37: Conversational rhetorical openers (Upstream #33) +- Pattern 38: Diff-anchored writing, shadowboxing, and editorial scar tissue +- Pattern 39: Hyphenated word pair overuse (narrowed, upstream) + --- _Module Version: 3.2.0_ diff --git a/scripts/lib/skill-contracts.js b/scripts/lib/skill-contracts.js index 1b51005..4c6f60a 100644 --- a/scripts/lib/skill-contracts.js +++ b/scripts/lib/skill-contracts.js @@ -411,8 +411,10 @@ export function renderSeverityClassification(records) { } const buckets = { critical: [], high: [], medium: [], low: [] }; for (const record of [...records].sort((left, right) => left.number - right.number)) { - const suffix = record.must_preserve ? ' (must preserve)' : ''; - buckets[record.severity].push(`- Pattern ${record.number}: ${record.title}${suffix}`); + const label = record.table_label || record.title; + const suffix = + record.must_preserve && !/\(must preserve\)/i.test(label) ? ' (must preserve)' : ''; + buckets[record.severity].push(`- Pattern ${record.number}: ${label}${suffix}`); } const parts = ['## SEVERITY CLASSIFICATION', '']; for (const severity of Object.keys(SEVERITY_TABLE_HEADINGS)) { @@ -437,7 +439,7 @@ export function replaceSeveritySection(content, rendered) { const end = content.indexOf(endMarker, start + 1); const prefix = content.slice(0, start + 1); const suffix = end === -1 ? '\n' : content.slice(end); - return `${prefix}${rendered}${suffix}`; + return `${prefix}${rendered}\n${suffix}`; } /** diff --git a/src/document-intelligence/pattern.schema.json b/src/document-intelligence/pattern.schema.json index 6dd85fe..d565adf 100644 --- a/src/document-intelligence/pattern.schema.json +++ b/src/document-intelligence/pattern.schema.json @@ -20,6 +20,7 @@ "id": { "type": "string", "pattern": "^pattern-[1-9][0-9]*$" }, "number": { "type": "integer", "minimum": 1 }, "title": { "type": "string", "minLength": 1 }, + "table_label": { "type": "string", "minLength": 1 }, "severity": { "$ref": "#/$defs/severity" }, "must_preserve": { "type": "boolean" }, "domain_applicability": { diff --git a/src/document-intelligence/patterns.json b/src/document-intelligence/patterns.json index f85b9cc..2d4f59d 100644 --- a/src/document-intelligence/patterns.json +++ b/src/document-intelligence/patterns.json @@ -27,7 +27,8 @@ "indelible mark", "deeply rooted" ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Undue emphasis on significance" }, { "schema_version": 1, @@ -43,7 +44,8 @@ "written by a leading expert", "active social media presence" ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Undue emphasis on notability" }, { "schema_version": 1, @@ -62,7 +64,8 @@ "encompassing...", "showcasing..." ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Superficial -ing analyses" }, { "schema_version": 1, @@ -90,7 +93,8 @@ "must-visit", "stunning" ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Promotional language" }, { "schema_version": 1, @@ -117,7 +121,8 @@ ], "false_positive_guards": [ "A single \"This\" or \"This means\" has a clear antecedent you can point to. Demonstratives are ordinary English. The tell is a run of them, or one whose antecedent you cannot name." - ] + ], + "table_label": "Vague attributions and back-references" }, { "schema_version": 1, @@ -133,7 +138,8 @@ "Challenges and Legacy", "Future Outlook" ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Formulaic \"Challenges\" sections" }, { "schema_version": 1, @@ -169,7 +175,8 @@ "valuable", "vibrant" ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Overused AI vocabulary" }, { "schema_version": 1, @@ -180,7 +187,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": ["serves as/stands as/marks/represents [a]", "boasts/features/offers [a]"], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Copula avoidance" }, { "schema_version": 1, @@ -191,7 +199,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": ["Not only...but", "It's not just about", "It's not merely"], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Negative parallelisms" }, { "schema_version": 1, @@ -202,7 +211,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": [], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Rule of three overuse" }, { "schema_version": 1, @@ -213,7 +223,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": [], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Elegant variation and repeated openings" }, { "schema_version": 1, @@ -224,7 +235,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": [], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "False ranges" }, { "schema_version": 1, @@ -239,7 +251,8 @@ "Used sparingly by a human editor or journalist and not clustered with other sales-y tells.", "Match a user writing sample's em-dash frequency instead of banning dashes.", "Keep annotated-link or definition separators; embedded mode cannot ask, so keep them." - ] + ], + "table_label": "Em dash overuse" }, { "schema_version": 1, @@ -250,7 +263,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": [], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Overuse of boldface" }, { "schema_version": 1, @@ -261,7 +275,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": [], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Inline-header lists" }, { "schema_version": 1, @@ -272,7 +287,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": [], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Title case in headings" }, { "schema_version": 1, @@ -283,7 +299,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": [], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Emojis" }, { "schema_version": 1, @@ -294,7 +311,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": [], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Quotation mark issues" }, { "schema_version": 1, @@ -313,7 +331,8 @@ "let me know", "here is a..." ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Collaborative communication artifacts" }, { "schema_version": 1, @@ -331,7 +350,8 @@ "maintains a low profile", "keeps personal details private (when unsourced)" ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Knowledge-cutoff disclaimers" }, { "schema_version": 1, @@ -342,7 +362,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": ["Great question!", "You're absolutely right", "That's an excellent point"], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Sycophantic tone" }, { "schema_version": 1, @@ -360,7 +381,8 @@ "has the ability to", "It is important to note that" ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Filler phrases" }, { "schema_version": 1, @@ -378,7 +400,8 @@ "in some cases it may", "this is an inference" ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Excessive hedging" }, { "schema_version": 1, @@ -389,7 +412,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": [], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Generic positive conclusions" }, { "schema_version": 1, @@ -406,7 +430,8 @@ "/* AI-generated */", "// Here is the refactored code:" ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "AI signatures in code" }, { "schema_version": 1, @@ -422,7 +447,8 @@ "Breakdown:", "Key takeaways: (when used with mechanical lists)" ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Over-structuring" }, { "schema_version": 1, @@ -436,7 +462,8 @@ "false_positive_guards": [ "Never modify inline code, fenced code, URLs, paths, versions, hashes, API names, identifiers, CLI flags, config keys, or error messages." ], - "must_preserve": true + "must_preserve": true, + "table_label": "Technical literal preservation (must preserve)" }, { "schema_version": 1, @@ -452,7 +479,8 @@ "What this really means is", "The truth is" ], - "false_positive_guards": ["Used in legitimate contexts like op-eds or presentation scripts."] + "false_positive_guards": ["Used in legitimate contexts like op-eds or presentation scripts."], + "table_label": "Persuasive tropes" }, { "schema_version": 1, @@ -470,7 +498,8 @@ ], "false_positive_guards": [ "Used in legitimate contexts like presentation scripts or tutorials." - ] + ], + "table_label": "Signposting" }, { "schema_version": 1, @@ -481,7 +510,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": [], - "false_positive_guards": ["Used in legitimate contexts like op-eds or persuasive writing."] + "false_positive_guards": ["Used in legitimate contexts like op-eds or persuasive writing."], + "table_label": "Fragmented headers" }, { "schema_version": 1, @@ -502,7 +532,8 @@ ], "false_positive_guards": [ "Model is explicitly asked to show its reasoning in structured format." - ] + ], + "table_label": "Extended thinking tags" }, { "schema_version": 1, @@ -513,7 +544,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": ["Here is the", "json", "JSON:", "as requested"], - "false_positive_guards": ["Actual API responses or configuration files."] + "false_positive_guards": ["Actual API responses or configuration files."], + "table_label": "JSON mode artifacts" }, { "schema_version": 1, @@ -531,7 +563,8 @@ "Running", "invoking" ], - "false_positive_guards": ["Explicit tutorials or documentation about tool usage."] + "false_positive_guards": ["Explicit tutorials or documentation about tool usage."], + "table_label": "Tool use documentation" }, { "schema_version": 1, @@ -549,7 +582,8 @@ "don't hesitate to", "anytime" ], - "false_positive_guards": ["Genuine customer service contexts."] + "false_positive_guards": ["Genuine customer service contexts."], + "table_label": "Over-polished conclusions" }, { "schema_version": 1, @@ -560,7 +594,8 @@ "domain_applicability": ["all"], "mode_carve_outs": [], "trigger_terms": [], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Manufactured punchlines and staccato drama (Upstream #31)" }, { "schema_version": 1, @@ -578,7 +613,8 @@ "the currency of", "the architecture of" ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Aphorism formulas (Upstream #32)" }, { "schema_version": 1, @@ -596,7 +632,8 @@ "Let's be honest", "Real talk (when used as standalone hooks or fake-candid pauses before an ordinary point)." ], - "false_positive_guards": ["Genuine conversational speech or quoted dialogue."] + "false_positive_guards": ["Genuine conversational speech or quoted dialogue."], + "table_label": "Conversational rhetorical openers (Upstream #33)" }, { "schema_version": 1, @@ -621,7 +658,8 @@ "It would be easy to just", "Some would suggest" ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Diff-anchored writing, shadowboxing, and editorial scar tissue" }, { "schema_version": 1, @@ -643,7 +681,8 @@ "long-term", "end-to-end" ], - "false_positive_guards": [] + "false_positive_guards": [], + "table_label": "Hyphenated word pair overuse (narrowed, upstream)" }, { "schema_version": 1, @@ -656,7 +695,8 @@ "trigger_terms": [], "false_positive_guards": [ "The source already uses a standard imperative (\"Hit reply to opt out.\") or ordinary conversational ellipsis. Do not invent a subject the source never implied. Distinguished from Pattern 35: that pattern is a run of short fragments stacked for drama. This pattern is an isolated missing-subject line, including one produced while trying to sound casual." - ] + ], + "table_label": "Passive voice and subjectless fragments (Upstream §13)" } ] } diff --git a/test/skill-contracts.test.js b/test/skill-contracts.test.js index 1c3c688..cc21b64 100644 --- a/test/skill-contracts.test.js +++ b/test/skill-contracts.test.js @@ -286,13 +286,14 @@ test('severity tables compile from the registry without duplicate IDs', () => { assert.equal(ids.length, 40); assert.equal(new Set(ids).size, 40); assert.match(rendered, /### Critical \(immediate AI detection\)/); - assert.match(rendered, /Pattern 27: Technical Literal Preservation \(must preserve\)/); + assert.match(rendered, /Pattern 27: Technical literal preservation \(must preserve\)/); + assert.match(rendered, /Pattern 13: Em dash overuse/); assert.throws(() => renderSeverityClassification({}), /must be an array/); const source = fs.readFileSync(path.join(ROOT, CORE_PATTERNS_MODULE), 'utf8'); const replaced = replaceSeveritySection(source, rendered); - assert.match(replaced, /Pattern 13: Em\/En Dash Hard Cut/); - assert.doesNotMatch(replaced, /Pattern 13: Em dash overuse/); + assert.match(replaced, /Pattern 13: Em dash overuse/); + assert.match(replaced, /### Pattern 13: Em\/En Dash Hard Cut/); assert.throws(() => replaceSeveritySection('# no table\n', rendered), /missing ## SEVERITY/); });