import { hasImplementationContract, IMPLEMENTATION_CONTRACT_SECTION } from './common.js';
export function buildImplementationContractSection(input) {
    const criteria = input.criteria.length > 0 ? input.criteria : fallbackCriteria();
    const testFiles = input.files.test.map((file) => file.path);
    const verificationCommands = input.verificationCommands.length > 0
        ? input.verificationCommands
        : ['pnpm typecheck', 'pnpm lint', 'pnpm test'];
    const lines = [
        `## ${IMPLEMENTATION_CONTRACT_SECTION}`,
        '### User Outcome',
        firstConcreteSentence(input.description) ??
            'Needs decision: define the exact user-visible outcome this spec must deliver.',
        '',
        '### Behavior Contract',
        ...renderBehaviorContract(criteria),
        '- Inputs: use the user request and existing project conventions as the source of truth.',
        '- Outputs: update canonical `spec.md` behavior without creating sidecar implementation docs.',
        '- State changes: persist only the files and metadata required by the spec workflow.',
        '- Errors: missing implementation detail must surface as `Needs decision:` instead of generic filler.',
        '',
        '### File-Level Work Plan',
        ...renderFilePlan(input.files),
        '',
        '### Acceptance-To-Verification Map',
        ...criteria.map((criterion, index) => renderVerificationRow(criterion.text, index + 1, testFiles, verificationCommands)),
        '',
        '### Edge Cases And Failure Modes',
        '- Generated specs with too little context must use `Needs decision:` placeholders.',
        '- Existing specs without this section must remain readable and must not be rewritten by readiness checks.',
        '- A heading with filler text must not count as a usable implementation contract.',
        '- Manual verification must include exact observable steps when no automated proof is practical.',
        '',
        '### Non-Goals And Forbidden Approaches',
        ...renderNonGoals(input.outOfScope),
        '',
        '### Verification Commands',
        ...verificationCommands.map((command) => `- \`${command}\``),
        '',
    ];
    return lines.join('\n');
}
export function appendImplementationContractIfMissing(specBody, input) {
    if (hasImplementationContract(specBody)) {
        return specBody.endsWith('\n') ? specBody : `${specBody}\n`;
    }
    return `${specBody.trimEnd()}\n\n${buildImplementationContractSection(input)}`;
}
function fallbackCriteria() {
    return [
        {
            text: 'Needs decision: define at least one acceptance criterion with executable verification.',
            done: false,
        },
    ];
}
function firstConcreteSentence(description) {
    const body = description
        .replace(/^---[\s\S]*?---/, '')
        .replace(/^#{1,6}\s+.+$/gm, '')
        .split('\n')
        .map((line) => line.trim())
        .find((line) => line.length >= 24 && !line.startsWith('-'));
    if (!body) {
        return null;
    }
    return body.replace(/\s+/g, ' ').slice(0, 240);
}
function renderFilePlan(files) {
    const lines = [];
    for (const [label, entries] of [
        ['Create', files.create],
        ['Modify', files.modify],
        ['Test', files.test],
    ]) {
        for (const entry of entries) {
            lines.push(`- ${label}: \`${entry.path}\` (${entry.status})`);
        }
    }
    return lines.length > 0 ? lines : ['- Needs decision: identify expected source and test files.'];
}
function renderBehaviorContract(criteria) {
    return criteria.map((criterion, index) => `- Expected behavior AC${String(index + 1)}: ${criterion.text}`);
}
function renderVerificationRow(criterion, index, testFiles, commands) {
    const test = testFiles[0];
    if (test) {
        return `- AC${String(index)}: ${criterion} -> unit test \`${test}\` plus \`${commands[0] ?? 'pnpm test'}\`.`;
    }
    return `- AC${String(index)}: ${criterion} -> Needs decision: choose unit test, integration test, CLI/tool result, snapshot/golden fixture, or exact manual verification.`;
}
function renderNonGoals(outOfScope) {
    const base = [
        '- Do not create durable sidecar implementation docs outside canonical `spec.md`.',
        '- Do not treat headings or filler text as implementation-ready detail.',
    ];
    return outOfScope.length > 0 ? [...base, ...outOfScope.map((item) => `- ${item}`)] : base;
}
//# sourceMappingURL=renderer.js.map