// tools/generate-adr/decisions.ts — Architecture decision generators
export function generateDecisions(spec, knowledge, patterns, specContent, requestedDecisions) {
    const decisions = [];
    if (!requestedDecisions ||
        requestedDecisions.some((d) => d.toLowerCase().includes('architect'))) {
        decisions.push(generateArchitecturePatternDecision(spec, knowledge, patterns));
    }
    if (!requestedDecisions ||
        requestedDecisions.some((d) => d.toLowerCase().includes('data') || d.toLowerCase().includes('schema'))) {
        if (/(?:database|schema|table|model|entity|store|persist)/i.exec(specContent) ||
            spec.target === 'backend' ||
            spec.target === 'fullstack' ||
            spec.target === 'database') {
            decisions.push(generateDataLayerDecision(spec, knowledge));
        }
    }
    if (!requestedDecisions || requestedDecisions.some((d) => d.toLowerCase().includes('api'))) {
        if (spec.target === 'backend' || spec.target === 'fullstack') {
            decisions.push(generateApiDecision(spec, knowledge));
        }
    }
    if (!requestedDecisions ||
        requestedDecisions.some((d) => d.toLowerCase().includes('state') || d.toLowerCase().includes('ui'))) {
        if (spec.target === 'frontend' || spec.target === 'fullstack') {
            decisions.push(generateStateManagementDecision(spec, knowledge));
        }
    }
    if (!requestedDecisions || requestedDecisions.some((d) => d.toLowerCase().includes('error'))) {
        decisions.push(generateErrorHandlingDecision(spec, knowledge));
    }
    if (requestedDecisions) {
        for (const requested of requestedDecisions) {
            const alreadyCovered = decisions.some((d) => d.decision.toLowerCase().includes(requested.toLowerCase()));
            if (!alreadyCovered) {
                decisions.push(generateGenericDecision(requested, spec, knowledge));
            }
        }
    }
    return decisions;
}
function generateArchitecturePatternDecision(spec, knowledge, patterns) {
    const currentArch = knowledge.architecture.primary;
    const patternNotes = patterns.map((p) => p.pattern).join('; ');
    const options = [
        {
            name: 'Keep current pattern',
            pros: ['No migration needed', 'Team already familiar', 'Existing tooling works'],
            cons: ['May not scale for this feature', 'Possible tech debt accumulation'],
            effort: 'None',
            scalability: currentArch === 'monolith' ? 'Limited' : 'Good',
            fitsEcosystem: true,
        },
        {
            name: 'Vertical slice for this feature',
            pros: ['Isolated changes', 'Easy to test', 'Minimal blast radius'],
            cons: ['May diverge from existing patterns', 'Requires clear boundaries'],
            effort: 'Low',
            scalability: 'Good',
            fitsEcosystem: true,
        },
    ];
    if (spec.scope === 'architectural' || spec.scope === 'cross-module') {
        options.push({
            name: 'Modular approach with clear boundaries',
            pros: ['Better separation of concerns', 'Independent deployability possible', 'Scalable'],
            cons: ['Higher initial effort', 'Requires team alignment', 'More boilerplate'],
            effort: 'Medium to High',
            scalability: 'Excellent',
            fitsEcosystem: knowledge.architecture.secondary.includes('modular-monolith'),
        });
    }
    return {
        decision: `Architecture pattern for "${spec.title}"`,
        context: `Current architecture: ${currentArch}. Spec scope: ${spec.scope}. ${patternNotes ? `Learned patterns: ${patternNotes}` : ''}`.trim(),
        options,
        chosen: options[0]?.name ?? 'Keep current pattern',
        rationale: `Maintain consistency with the existing ${currentArch} architecture unless the scope demands a structural change.`,
        consequences: [
            'New code follows existing architectural conventions',
            'Changes are localized to the feature scope',
            spec.scope === 'architectural'
                ? 'May require follow-up refactoring spec'
                : 'Minimal impact on other modules',
        ],
        tradeoffs: [
            'Consistency vs. optimal structure for this specific feature',
            'Short-term velocity vs. long-term maintainability',
        ],
    };
}
function generateDataLayerDecision(spec, knowledge) {
    const dbEngine = knowledge.database;
    const options = [
        {
            name: `Use existing ${dbEngine} with current ORM/driver`,
            pros: [
                'No migration',
                'Consistent with existing data layer',
                'Known performance characteristics',
            ],
            cons: ['May not be optimal for new data patterns'],
            effort: 'Low',
            scalability: 'Good',
            fitsEcosystem: true,
        },
        {
            name: 'Add a new data store for this feature',
            pros: ['Optimized for use case', 'No schema conflicts'],
            cons: ['Operational complexity', 'Data synchronization needed', 'Higher cost'],
            effort: 'High',
            scalability: 'Excellent for specific use case',
            fitsEcosystem: false,
        },
    ];
    return {
        decision: `Data storage strategy for "${spec.title}"`,
        context: `Current database: ${dbEngine}. Spec type: ${spec.type}, target: ${spec.target}.`,
        options,
        chosen: options[0]?.name ?? `Use existing ${dbEngine} with current ORM/driver`,
        rationale: `Leverage the existing ${dbEngine} infrastructure. Adding a separate store is only justified for fundamentally different data access patterns.`,
        consequences: [
            `Schema changes in ${dbEngine}`,
            'Migration scripts required',
            'Existing backup/restore procedures apply',
        ],
        tradeoffs: ['Simplicity vs. optimization', 'Single source of truth vs. polyglot persistence'],
    };
}
function generateApiDecision(spec, knowledge) {
    const hasApi = knowledge.apiContracts.length > 0;
    const firstContract = knowledge.apiContracts[0];
    const apiType = hasApi && firstContract ? firstContract.type : 'rest-informal';
    const options = [
        {
            name: `Extend existing ${apiType} API`,
            pros: ['Consistent API surface', 'Existing clients work', 'Shared auth/middleware'],
            cons: ['May bloat existing API', 'Versioning concerns'],
            effort: 'Low',
            scalability: 'Good',
            fitsEcosystem: true,
        },
        {
            name: 'Create a separate API module/service',
            pros: ['Clean separation', 'Independent versioning', 'Focused responsibility'],
            cons: ['More infrastructure', 'Cross-service communication overhead'],
            effort: 'Medium',
            scalability: 'Excellent',
            fitsEcosystem: false,
        },
    ];
    return {
        decision: `API design for "${spec.title}"`,
        context: `Existing API type: ${apiType}. ${knowledge.apiContracts.length} contracts detected.`,
        options,
        chosen: options[0]?.name ?? `Extend existing ${apiType} API`,
        rationale: `Extend the existing ${apiType} API to maintain a unified API surface for clients.`,
        consequences: [
            'New endpoints added to existing API',
            'API documentation updated',
            'Existing authentication middleware reused',
        ],
        tradeoffs: [
            'Unified API vs. microservice boundaries',
            'Shared middleware vs. feature-specific requirements',
        ],
    };
}
function generateStateManagementDecision(spec, knowledge) {
    const framework = knowledge.framework ?? 'unknown';
    const options = [
        {
            name: 'Local component state',
            pros: ['Simple', 'No dependencies', 'Easy to reason about'],
            cons: ['No sharing between components', 'Prop drilling for deep trees'],
            effort: 'Low',
            scalability: 'Limited',
            fitsEcosystem: true,
        },
        {
            name: 'Context/Provider pattern',
            pros: ['No external library', 'Framework-native', 'Good for moderate sharing'],
            cons: ['Re-render concerns', 'Not ideal for frequent updates'],
            effort: 'Low',
            scalability: 'Moderate',
            fitsEcosystem: true,
        },
        {
            name: 'Dedicated state library',
            pros: ['Powerful', 'DevTools', 'Middleware support'],
            cons: ['Added dependency', 'Learning curve', 'Boilerplate'],
            effort: 'Medium',
            scalability: 'Excellent',
            fitsEcosystem: true,
        },
    ];
    return {
        decision: `State management for "${spec.title}" UI components`,
        context: `Frontend framework: ${framework}. Spec scope: ${spec.scope}.`,
        options,
        chosen: spec.scope === 'trivial' || spec.scope === 'feature'
            ? (options[0]?.name ?? 'Local component state')
            : (options[1]?.name ?? 'Context/Provider pattern'),
        rationale: `For ${spec.scope} scope, ${spec.scope === 'trivial' || spec.scope === 'feature' ? 'local state is sufficient' : 'a shared state solution avoids prop drilling across modules'}.`,
        consequences: [
            'State management approach documented for this feature',
            'Consistent with other features of similar scope',
        ],
        tradeoffs: ['Simplicity vs. power', 'Bundle size vs. developer experience'],
    };
}
function generateErrorHandlingDecision(spec, knowledge) {
    const options = [
        {
            name: 'Try-catch with structured error types',
            pros: ['Explicit', 'Type-safe', 'Easy to trace'],
            cons: ['Verbose', 'Requires discipline'],
            effort: 'Low',
            scalability: 'Good',
            fitsEcosystem: true,
        },
        {
            name: 'Result/Either pattern',
            pros: ['Functional', 'No thrown exceptions', 'Composable'],
            cons: ['Learning curve', 'Different from standard patterns'],
            effort: 'Medium',
            scalability: 'Excellent',
            fitsEcosystem: knowledge.language === 'rust' || knowledge.language === 'go',
        },
    ];
    return {
        decision: `Error handling strategy for "${spec.title}"`,
        context: `Language: ${knowledge.language}. Risk level: ${spec.risk}.`,
        options,
        chosen: options[0]?.name ?? 'Try-catch with structured error types',
        rationale: 'Structured try-catch with typed errors provides a good balance of safety and readability.',
        consequences: [
            'All new functions have explicit error handling',
            'Error types documented in spec',
            'Logging integrated at catch boundaries',
        ],
        tradeoffs: ['Verbosity vs. safety', 'Performance overhead of try-catch vs. uncaught errors'],
    };
}
function generateGenericDecision(topic, spec, knowledge) {
    return {
        decision: `${topic} for "${spec.title}"`,
        context: `Spec type: ${spec.type}, scope: ${spec.scope}. Stack: ${knowledge.stack.join(', ')}.`,
        options: [
            {
                name: `Follow existing ${topic} patterns`,
                pros: ['Consistency', 'Known approach'],
                cons: ['May not be optimal'],
                effort: 'Low',
                scalability: 'Moderate',
                fitsEcosystem: true,
            },
            {
                name: `Introduce new ${topic} approach`,
                pros: ['Potentially better fit', 'Modern practices'],
                cons: ['Migration effort', 'Team alignment needed'],
                effort: 'Medium to High',
                scalability: 'Good',
                fitsEcosystem: false,
            },
        ],
        chosen: `Follow existing ${topic} patterns`,
        rationale: `Default to consistency unless there is a strong reason to diverge. Document the decision for future review.`,
        consequences: [
            `${topic} approach is documented`,
            'Team can reference this ADR for future decisions',
        ],
        tradeoffs: ['Consistency vs. innovation', 'Short-term vs. long-term optimization'],
    };
}
//# sourceMappingURL=decisions.js.map