/**
 * RED-GREEN tests for F-NEW-PRODUCT-TRUST-IMPROVEMENT-RECOMMENDATIONS (W1.11).
 *
 * Validates the trademark three-axis remediation engine: every score-lowering
 * finding (build / runtime / human) produces a structured Recommendation
 * with actionable next-step pointer.
 *
 * @connexum/ai-governance  F-NEW-PRODUCT-TRUST-IMPROVEMENT-RECOMMENDATIONS
 */
import { describe, it } from 'node:test';
import * as assert from 'node:assert/strict';
import { buildAxisRecommendations, runtimeAxisRecommendations, humanAxisRecommendations, buildRecommendationSet, } from './improvement-recommendations.js';
import { scanAgent } from './owasp-agentic-scanner.js';
const baseManifest = (over = {}) => ({
    agentId: 'agent-x',
    tools: [],
    hooks: { preToolUse: true, postToolUse: true, postResponse: true },
    llmProvider: 'connexum-proxy/anthropic',
    pluginIntegrityVerified: true,
    rateLimitsConfigured: true,
    declaredApprovalGates: [],
    declaredForbiddenCapabilities: [],
    ...over,
});
describe('F-NEW-PRODUCT-TRUST-IMPROVEMENT-RECOMMENDATIONS (W1.11)', () => {
    it('build axis: every OWASP finding becomes a build-axis Recommendation', () => {
        const scan = scanAgent(baseManifest({ tools: ['WebFetch', 'Bash'] }));
        const recs = buildAxisRecommendations('agent-x', scan);
        assert.ok(recs.length > 0);
        assert.ok(recs.every((r) => r.axis === 'build'));
        assert.ok(recs.every((r) => r.actionHint.length > 0));
        assert.ok(recs.every((r) => r.sourceRef.startsWith('owasp:')));
    });
    it('build axis: A01 Lethal Trifecta maps to enable-isolation kind', () => {
        const scan = scanAgent(baseManifest({ tools: ['WebFetch', 'Bash'] }));
        const recs = buildAxisRecommendations('agent-x', scan);
        const trifecta = recs.find((r) => /Lethal Trifecta/.test(r.headline));
        assert.ok(trifecta);
        assert.equal(trifecta.kind, 'enable-isolation');
    });
    it('build axis: A05 plugin integrity maps to verify-plugin-integrity', () => {
        const scan = scanAgent(baseManifest({ pluginIntegrityVerified: false }));
        const recs = buildAxisRecommendations('agent-x', scan);
        const a05 = recs.find((r) => r.sourceRef.includes('A05'));
        assert.ok(a05);
        assert.equal(a05.kind, 'verify-plugin-integrity');
    });
    it('build axis: A06 LLM-not-via-proxy maps to swap-provider', () => {
        const scan = scanAgent(baseManifest({ llmProvider: 'anthropic/claude-direct' }));
        const recs = buildAxisRecommendations('agent-x', scan);
        const a06 = recs.find((r) => r.sourceRef.includes('A06'));
        assert.ok(a06);
        assert.equal(a06.kind, 'swap-provider');
    });
    it('runtime axis: regulatory denial with citation maps to cite-regulatory-clause', () => {
        const recs = runtimeAxisRecommendations('agent-x', [
            {
                packId: 'hipaa',
                checkId: 'phi-recipient',
                severity: 'CRIT',
                citation: 'HIPAA 164.502(e)',
                toolName: 'email_send',
                reason: 'PHI cannot flow to non-BAA recipient',
            },
        ]);
        assert.equal(recs.length, 1);
        assert.equal(recs[0].kind, 'cite-regulatory-clause');
        assert.match(recs[0].actionHint, /HIPAA 164.502\(e\)/);
        assert.equal(recs[0].axis, 'runtime');
    });
    it('runtime axis: pack denial without citation maps to add-pack-rule', () => {
        const recs = runtimeAxisRecommendations('agent-x', [
            {
                packId: 'company-pack-1',
                checkId: 'capability:mcp',
                severity: 'HIGH',
                toolName: 'mcp__list_resources',
                reason: 'capability forbidden by org-baseline rule',
            },
        ]);
        assert.equal(recs[0].kind, 'add-pack-rule');
    });
    it('human axis: PHI ingestion maps to assign-training with hipaa-phi-awareness id', () => {
        const recs = humanAxisRecommendations('agent-x', [
            {
                operatorId: 'user-bob',
                kind: 'phi-ingestion',
                severity: 'HIGH',
                count: 7,
                windowLabel: '30d',
            },
        ]);
        assert.equal(recs.length, 1);
        assert.equal(recs[0].axis, 'human');
        assert.equal(recs[0].kind, 'assign-training');
        assert.match(recs[0].actionHint, /training:hipaa-phi-awareness/);
        assert.match(recs[0].actionHint, /user-bob/);
    });
    it('human axis: all five drift kinds map to distinct training topics', () => {
        const kinds = [
            'phi-ingestion',
            'out-of-scope-prompt',
            'override-abuse',
            'repeated-denial-bypass',
            'low-review-responsiveness',
        ];
        const recs = humanAxisRecommendations('agent-x', kinds.map((k) => ({
            operatorId: 'user-bob',
            kind: k,
            severity: 'MED',
            count: 1,
        })));
        const trainingIds = new Set(recs.map((r) => {
            const m = r.actionHint.match(/training:[A-Za-z0-9-]+/);
            return m?.[0] ?? '';
        }));
        assert.equal(trainingIds.size, 5);
    });
    it('buildRecommendationSet combines all three axes', () => {
        const scan = scanAgent(baseManifest({ tools: ['Bash'] }));
        const set = buildRecommendationSet({
            agentId: 'agent-x',
            buildScan: scan,
            runtimeFindings: [
                {
                    packId: 'hipaa',
                    checkId: 'phi-recipient',
                    severity: 'CRIT',
                    citation: 'HIPAA 164.502(e)',
                    toolName: 'email_send',
                    reason: 'PHI denied',
                },
            ],
            humanFindings: [
                { operatorId: 'user-bob', kind: 'phi-ingestion', severity: 'HIGH', count: 5 },
            ],
        });
        assert.ok(set.countsByAxis.build > 0);
        assert.ok(set.countsByAxis.runtime > 0);
        assert.ok(set.countsByAxis.human > 0);
        assert.ok(set.potentialScoreGain > 0);
        assert.ok(set.potentialScoreGain <= 100);
    });
    it('buildRecommendationSet potentialScoreGain weights by severity', () => {
        const critOnly = buildRecommendationSet({
            agentId: 'agent-x',
            runtimeFindings: [
                {
                    packId: 'p1',
                    checkId: 'x',
                    severity: 'CRIT',
                    toolName: 'x',
                    reason: 'r',
                },
            ],
        });
        const lowOnly = buildRecommendationSet({
            agentId: 'agent-x',
            runtimeFindings: [
                {
                    packId: 'p1',
                    checkId: 'x',
                    severity: 'LOW',
                    toolName: 'x',
                    reason: 'r',
                },
            ],
        });
        assert.ok(critOnly.potentialScoreGain > lowOnly.potentialScoreGain);
    });
    it('empty input set returns zero counts and gain', () => {
        const set = buildRecommendationSet({ agentId: 'agent-x' });
        assert.equal(set.recommendations.length, 0);
        assert.deepEqual(set.countsByAxis, { build: 0, runtime: 0, human: 0 });
        assert.equal(set.potentialScoreGain, 0);
    });
});
//# sourceMappingURL=improvement-recommendations.test.js.map