/**
 * RED-GREEN tests for the compliance & insurance report generator.
 *
 * @connexum/ai-governance  Insurance & Compliance Report
 */
import { describe, it } from 'node:test';
import * as assert from 'node:assert/strict';
import { generateAgentTrustReport, reportToCsvRow, topRecommendations, CSV_HEADER, } from './agent-trust-report.js';
import { composeThreeDimensionalScore } from './trust-score-three-dim.js';
import { scanAgent } from './owasp-agentic-scanner.js';
import { buildRecommendationSet } from './improvement-recommendations.js';
const cleanManifest = () => ({
    agentId: 'agent-x',
    tools: [],
    hooks: { preToolUse: true, postToolUse: true, postResponse: true },
    llmProvider: 'connexum-proxy/anthropic',
    pluginIntegrityVerified: true,
    rateLimitsConfigured: true,
    declaredApprovalGates: [],
    declaredForbiddenCapabilities: [],
});
const dirtyManifest = () => ({
    ...cleanManifest(),
    tools: ['WebFetch', 'Bash'],
    pluginIntegrityVerified: false,
    llmProvider: 'anthropic/direct',
});
const dim = (c) => ({
    scope_adherence: c, policy_compliance: c, anomaly_rate: c,
    incident_history: c, behavioral_consistency: c, composite: c,
});
const opDim = (c) => ({
    out_of_scope_ingestion: c, scope_violation_by_team: c,
    scope_violation_by_data_class: c, human_override_frequency: c, composite: c,
});
const bDim = (c) => ({
    owasp_agentic_score: c, hook_coverage_count: 3,
    declared_capability_class_count: 4, has_human_in_loop: true,
    plugin_integrity_verified: true, proxy_routed: true, composite: c,
});
function mockOrgRep(score, confidence) {
    return {
        org_id: 'org-x',
        score,
        confidence,
        based_on_signal_count: 100,
        agent_count: 5,
        axis_breakdown: { agent_activity: score, operator_activity: score, agent_build_structure: score },
        computed_at: '2026-05-12T00:00:00.000Z',
    };
}
describe('compliance & insurance report', () => {
    it('CRIT finding -> NON_COMPLIANT verdict regardless of score', () => {
        const scan = scanAgent(dirtyManifest());
        assert.ok(scan.countsBySeverity.CRIT > 0);
        const report = generateAgentTrustReport({
            agentId: 'agent-x',
            agentName: 'X',
            orgId: 'org-x',
            period: { from: '2026-05-01T00:00:00.000Z', to: '2026-05-12T00:00:00.000Z' },
            packBindings: ['hipaa', 'company-pack-1'],
            score: composeThreeDimensionalScore({
                agent_activity: dim(95),
                operator_activity: opDim(95),
                agent_build_structure: bDim(95),
            }),
            scanReport: scan,
            recommendations: buildRecommendationSet({ agentId: 'agent-x', buildScan: scan }),
        });
        assert.equal(report.verdict, 'NON_COMPLIANT');
    });
    it('Clean scan + high score + high-confidence rep -> COMPLIANT', () => {
        const scan = scanAgent(cleanManifest());
        const report = generateAgentTrustReport({
            agentId: 'agent-x',
            orgId: 'org-x',
            period: { from: '2026-05-01T00:00:00.000Z', to: '2026-05-12T00:00:00.000Z' },
            packBindings: ['soc2'],
            score: composeThreeDimensionalScore({
                agent_activity: dim(90),
                operator_activity: opDim(90),
                agent_build_structure: bDim(90),
            }),
            scanReport: scan,
            orgReputation: mockOrgRep(90, 'high'),
            recommendations: buildRecommendationSet({ agentId: 'agent-x', buildScan: scan }),
        });
        assert.equal(report.verdict, 'COMPLIANT');
    });
    it('Clean scan + high score + LOW-confidence rep -> PROVISIONAL', () => {
        const scan = scanAgent(cleanManifest());
        const report = generateAgentTrustReport({
            agentId: 'agent-x',
            orgId: 'org-x',
            period: { from: '2026-05-01T00:00:00.000Z', to: '2026-05-12T00:00:00.000Z' },
            packBindings: [],
            score: composeThreeDimensionalScore({
                agent_activity: dim(88),
                operator_activity: opDim(88),
                agent_build_structure: bDim(88),
            }),
            scanReport: scan,
            orgReputation: mockOrgRep(60, 'low'),
            recommendations: buildRecommendationSet({ agentId: 'agent-x', buildScan: scan }),
        });
        assert.equal(report.verdict, 'PROVISIONAL');
    });
    it('Mid-band composite -> CONDITIONAL / AT_RISK / NON_COMPLIANT', () => {
        const make = (composite) => generateAgentTrustReport({
            agentId: 'agent-x',
            orgId: 'org-x',
            period: { from: '2026-05-01T00:00:00.000Z', to: '2026-05-12T00:00:00.000Z' },
            packBindings: [],
            score: composeThreeDimensionalScore({
                agent_activity: dim(composite),
                operator_activity: opDim(composite),
                agent_build_structure: bDim(composite),
            }),
            scanReport: scanAgent(cleanManifest()),
            recommendations: buildRecommendationSet({ agentId: 'agent-x' }),
        });
        assert.equal(make(70).verdict, 'CONDITIONAL');
        assert.equal(make(50).verdict, 'AT_RISK');
        assert.equal(make(20).verdict, 'NON_COMPLIANT');
    });
    it('headline + sections + summary populated', () => {
        const scan = scanAgent(dirtyManifest());
        const report = generateAgentTrustReport({
            agentId: 'agent-x',
            agentName: 'Agent X',
            orgId: 'org-x',
            period: { from: '2026-05-01T00:00:00.000Z', to: '2026-05-12T00:00:00.000Z' },
            packBindings: ['hipaa', 'company-pack-1'],
            score: composeThreeDimensionalScore({
                agent_activity: dim(60), operator_activity: opDim(60), agent_build_structure: bDim(60),
            }),
            scanReport: scan,
            recommendations: buildRecommendationSet({ agentId: 'agent-x', buildScan: scan }),
        });
        assert.equal(report.headline.composite_score, 60);
        assert.deepEqual(report.headline.pack_bindings, ['hipaa', 'company-pack-1']);
        assert.equal(report.headline.open_critical_findings, scan.countsBySeverity.CRIT);
        assert.match(report.sections.summary.body, /Agent X/);
        assert.match(report.sections.summary.body, /Verdict: NON_COMPLIANT/);
        assert.equal(report.sections.trust_score.body.composite, 60);
        assert.equal(report.sections.recommendations.body.agentId, 'agent-x');
    });
    it('runtimeTotals appear in the report when supplied', () => {
        const scan = scanAgent(cleanManifest());
        const report = generateAgentTrustReport({
            agentId: 'a',
            orgId: 'org-x',
            period: { from: '2026-05-01T00:00:00.000Z', to: '2026-05-12T00:00:00.000Z' },
            packBindings: [],
            score: composeThreeDimensionalScore({
                agent_activity: dim(80), operator_activity: opDim(80), agent_build_structure: bDim(80),
            }),
            scanReport: scan,
            recommendations: buildRecommendationSet({ agentId: 'a' }),
            runtimeTotals: {
                allow: 412, deny: 6, pending: 3, approved: 2, denied_by_human: 1,
            },
        });
        assert.deepEqual(report.sections.runtime_totals.body, {
            allow: 412, deny: 6, pending: 3, approved: 2, denied_by_human: 1,
        });
    });
    it('id auto-generates when not supplied', () => {
        const scan = scanAgent(cleanManifest());
        const r = generateAgentTrustReport({
            agentId: 'a-1',
            orgId: 'org-x',
            period: { from: '2026-05-01T00:00:00.000Z', to: '2026-05-12T00:00:00.000Z' },
            packBindings: [],
            score: composeThreeDimensionalScore({
                agent_activity: dim(80), operator_activity: opDim(80), agent_build_structure: bDim(80),
            }),
            scanReport: scan,
            recommendations: buildRecommendationSet({ agentId: 'a-1' }),
        });
        assert.match(r.id, /^cr-a-1-2026-05-01-2026-05-12$/);
    });
    it('reportToCsvRow + CSV_HEADER produce a parseable CSV pair', () => {
        const scan = scanAgent(cleanManifest());
        const r = generateAgentTrustReport({
            agentId: 'a-1',
            orgId: 'org-x',
            period: { from: '2026-05-01T00:00:00.000Z', to: '2026-05-12T00:00:00.000Z' },
            packBindings: ['hipaa', 'soc2'],
            score: composeThreeDimensionalScore({
                agent_activity: dim(80), operator_activity: opDim(80), agent_build_structure: bDim(80),
            }),
            scanReport: scan,
            orgReputation: mockOrgRep(80, 'medium'),
            recommendations: buildRecommendationSet({ agentId: 'a-1' }),
        });
        const row = reportToCsvRow(r);
        const headerCols = CSV_HEADER.split(',');
        const rowCols = row.split(',');
        assert.equal(rowCols.length, headerCols.length);
        assert.ok(row.includes('hipaa|soc2'));
        assert.ok(row.includes('a-1'));
        assert.ok(row.includes('CONDITIONAL'));
    });
    it('reportToCsvRow escapes fields containing commas', () => {
        const scan = scanAgent(cleanManifest());
        const r = generateAgentTrustReport({
            agentId: 'a, with comma',
            orgId: 'org-x',
            period: { from: '2026-05-01T00:00:00.000Z', to: '2026-05-12T00:00:00.000Z' },
            packBindings: [],
            score: composeThreeDimensionalScore({
                agent_activity: dim(80), operator_activity: opDim(80), agent_build_structure: bDim(80),
            }),
            scanReport: scan,
            recommendations: buildRecommendationSet({ agentId: 'a, with comma' }),
        });
        const row = reportToCsvRow(r);
        assert.ok(row.includes('"a, with comma"'));
    });
    it('topRecommendations filters by severity + applies limit', () => {
        const scan = scanAgent(dirtyManifest());
        const set = buildRecommendationSet({ agentId: 'a', buildScan: scan });
        const top = topRecommendations(set, { minSeverity: 'CRIT' });
        assert.ok(top.every((r) => r.severity === 'CRIT'));
        const limited = topRecommendations(set, { minSeverity: 'LOW', limit: 2 });
        assert.ok(limited.length <= 2);
    });
    it('topRecommendations sorts highest-severity-first', () => {
        const scan = scanAgent(dirtyManifest());
        const set = buildRecommendationSet({ agentId: 'a', buildScan: scan });
        const sorted = topRecommendations(set, { minSeverity: 'LOW' });
        const SEV = { LOW: 0, MED: 1, HIGH: 2, CRIT: 3 };
        for (let i = 1; i < sorted.length; i++) {
            assert.ok(SEV[sorted[i].severity] <= SEV[sorted[i - 1].severity], `recommendation at index ${i} (${sorted[i].severity}) is more severe than previous (${sorted[i - 1].severity})`);
        }
    });
    it('missing agentId / orgId / period throws (fail-closed)', () => {
        const scan = scanAgent(cleanManifest());
        const base = {
            orgId: 'o',
            period: { from: 'a', to: 'b' },
            packBindings: [],
            score: composeThreeDimensionalScore({
                agent_activity: dim(80), operator_activity: opDim(80), agent_build_structure: bDim(80),
            }),
            scanReport: scan,
            recommendations: buildRecommendationSet({ agentId: 'a' }),
        };
        assert.throws(() => generateAgentTrustReport({ ...base, agentId: '' }), /agentId is required/);
        assert.throws(() => generateAgentTrustReport({ ...base, agentId: 'a', orgId: '' }), /orgId is required/);
        assert.throws(() => generateAgentTrustReport({
            ...base,
            agentId: 'a',
            period: { from: '', to: 'b' },
        }), /period.from and period.to are required/);
    });
});
//# sourceMappingURL=agent-trust-report.test.js.map