/** * lib/ba-placeholder.ts — « ce document porte-t-il un modèle de données ? » * * THE predicate, shared. Three CLIs each carried their own copy of * `/_À définir lors de la phase/` and tested it against the WHOLE file: * - ba-relations.parseEntities → skipped the doc SILENTLY * - create-plan-development/parse → fell back to index.md deps * - create-rbac/derive-lookup-grants → refused with « still a placeholder » * * The marker alone is NOT the test. `/ba-create-menu` writes it under every * not-yet-authored section (create-menu/SKILL.md, _workflow/doc-templates.md), * so a FULLY authored entité.md routinely keeps one leftover line — for the * screens phase, say. Testing that substring against the whole file then * discarded the entire document: every entity, and above all every relation, * i.e. every foreign key. The cascade was the treacherous part — DM-009/DM-014 * warned that everything was isolated while DM-004/DM-013/DM-005 went GREEN on * an empty graph, and audit-ba's control counts saw nothing (they reconcile * `### ENT-` headings, which ba-entities keeps parsing, never relations). * * A document is a placeholder when it declares NO entity block. Nothing else. */ /** The scaffolding marker — kept for MESSAGES only, never as the test. */ export const PLACEHOLDER_MARKER_RE = /_À définir lors de la phase/ /** `### ENT-001 — Client` / `### ENT-001 - Client` — em-dash or ASCII dash. */ const ENTITY_BLOCK_PROBE = /^###\s+ENT-\d+\s*[—-]/m /** True when the doc declares at least one `### ENT-NNN` block. */ export function hasEntityBlocks(content: string): boolean { return ENTITY_BLOCK_PROBE.test(content) } /** * True when the doc carries no data model at all. * * Use THIS, never a bare marker test: a leftover placeholder line inside an * authored document must not discard the document. A doc that DOES declare * entities but leaves their tables empty is NOT a placeholder — it is an * incomplete model, and DM-002 (« entité sans aucun attribut ») is the rule * that must say so, out loud, instead of the parser swallowing it. */ export function isPlaceholderEntityDoc(content: string): boolean { return !hasEntityBlocks(content) }