/** * KANBAN_MIN_STATES — ONE threshold, stated by every document that teaches it. * * The cross-dimension audit XD-003 demanded a SmartKanban for ANY state field * while /ba-create-screen makes the board mandatory from 3 states on: the rule * and the skill it names as its own remedy disagreed, and a corpus with * two-value statuses could not satisfy both (support report 6819314a0164). * The number now lives in lib/page-spec-kanban; this test refuses a document * that states another one, or stops stating it. */ import { describe, it, expect } from 'vitest' import { readFileSync } from 'node:fs' import { KANBAN_MIN_STATES } from '../page-spec-kanban.js' import { baSkillFile } from './helpers/cli-options.js' /** Documents that state the threshold, with the sentence that carries it. */ const DOCS: { file: string; role: string }[] = [ { file: 'create-screen/levels/kanban-screens.md', role: 'authoring level — « Mandatory when »' }, { file: 'create-screen/references/type-mapping.md', role: 'authoring reference — SmartKanban auto-detection' }, { file: 'create-screen/references/post-check.md', role: 'authoring self-check' }, { file: 'audit-cross-dimension/SKILL.md', role: 'audit contract — XD-003' }, ] /** `≥3`, `≥ 3`, `at least 3` — followed by what is counted. */ const STATED = /(?:≥\s*|at\s+least\s+)(\d+)\s+(?:distinct\s+)?(?:options?|states?|values?)\b/gi function thresholdsIn(md: string): number[] { return [...md.replace(/\*\*/g, '').matchAll(STATED)].map((m) => Number(m[1])) } describe('KANBAN_MIN_STATES ↔ the documents that teach it', () => { for (const doc of DOCS) { it(`${doc.file} (${doc.role})`, () => { const found = thresholdsIn(readFileSync(baSkillFile(doc.file), 'utf8')) expect(found, 'the document no longer states the threshold').not.toEqual([]) expect([...new Set(found)], 'the document states another threshold than lib/page-spec-kanban').toEqual([KANBAN_MIN_STATES]) }) } it('the matcher reads the spellings in use, and only a threshold', () => { expect(thresholdsIn('a status enum with **≥3 options**')).toEqual([3]) expect(thresholdsIn('with at least 3\noptions — and that')).toEqual([3]) expect(thresholdsIn('at least 3 distinct states the user transitions between')).toEqual([3]) expect(thresholdsIn('declares **at least 3 values**')).toEqual([3]) expect(thresholdsIn('a lifecycle of ≥ 3 states')).toEqual([3]) expect(thresholdsIn('≤ 7 columns, at least one screen')).toEqual([]) }) })