// allow-test-rule: source-text-is-the-product // The PROJECT.md template + complete-milestone workflow .md ARE the product surface // the runtime loads; asserting on their text tests the deployed contract directly. /** * Enhancement #72 — optional Business Context section in the PROJECT.md template. * * Contract tests over the product-text surfaces (template + milestone workflow .md): * the template offers a Business Context section that is explicitly OPTIONAL, capped * at the four approved one-line fields, and the milestone evolution review treats it * as conditional so non-business projects that deleted it are never forced to review it. */ const { test, describe } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); const TEMPLATE = path.join(__dirname, '..', 'gsd-core', 'templates', 'project.md'); const COMPLETE_MILESTONE = path.join(__dirname, '..', 'gsd-core', 'workflows', 'complete-milestone.md'); function parseTemplateContract(content) { const lines = content.split(/\r?\n/); const lower = content.toLowerCase(); // The Business Context block lives between its heading and the next "## " heading. const startIdx = lines.findIndex(l => l.trim() === '## Business Context'); let sectionBody = ''; if (startIdx !== -1) { const rest = lines.slice(startIdx + 1); const endOffset = rest.findIndex(l => l.startsWith('## ')); sectionBody = (endOffset === -1 ? rest : rest.slice(0, endOffset)).join('\n'); } const fieldOf = (label) => new RegExp(`^- \\*\\*${label}\\*\\*:`, 'm').test(sectionBody); return { hasSection: startIdx !== -1, // Optional-by-default: an HTML comment tells non-business projects to delete it. hasOptionalMarker: /