/**
 * RED-GREEN tests for pack-diff (W3.3 + W1.4 support).
 *
 * @connexum/ai-governance  F-NEW-PRODUCT-LIVE-PACK-EDITOR + F-NEW-PRODUCT-PACK-VERSIONING-ROLLBACK
 */
import { describe, it } from 'node:test';
import * as assert from 'node:assert/strict';
import { diffPacks, summarizeDiff } from './pack-diff.js';
import { buildCompanyPack } from './company-pack-builder.js';
import { CAPABILITY_CLASS } from './capability-classes.js';
describe('pack-diff', () => {
    it('identical packs produce noop diff', () => {
        const p = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.0.0',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        const p2 = { ...p, version: '1.0.1' };
        const diff = diffPacks(p, p2);
        assert.equal(diff.isNoop, true);
        assert.equal(diff.changes.length, 0);
        assert.equal(diff.isolationChange, undefined);
    });
    it('added category appears as added', () => {
        const v1 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.0.0',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        const v2 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.1.0',
            rules: [
                { capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' },
                { capability: CAPABILITY_CLASS.SHELL_EXEC, action: 'REQUIRE_APPROVAL' },
            ],
        });
        const diff = diffPacks(v1, v2);
        assert.equal(diff.isNoop, false);
        assert.deepEqual(diff.added, ['capability:shell-exec']);
        assert.equal(diff.removed.length, 0);
        assert.equal(diff.changed.length, 0);
    });
    it('removed category appears as removed', () => {
        const v1 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.0.0',
            rules: [
                { capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' },
                { capability: CAPABILITY_CLASS.SHELL_EXEC, action: 'REQUIRE_APPROVAL' },
            ],
        });
        const v2 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.1.0',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        const diff = diffPacks(v1, v2);
        assert.deepEqual(diff.removed, ['capability:shell-exec']);
    });
    it('changed action appears as changed with previous + new values', () => {
        const v1 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.0.0',
            rules: [{ capability: CAPABILITY_CLASS.SHELL_EXEC, action: 'REQUIRE_APPROVAL' }],
        });
        const v2 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.1.0',
            rules: [{ capability: CAPABILITY_CLASS.SHELL_EXEC, action: 'BLOCK' }],
        });
        const diff = diffPacks(v1, v2);
        assert.equal(diff.changes.length, 1);
        const c = diff.changes[0];
        assert.equal(c.kind, 'changed');
        if (c.kind === 'changed') {
            assert.equal(c.previousAction, 'REQUIRE_APPROVAL');
            assert.equal(c.newAction, 'BLOCK');
        }
        assert.deepEqual(diff.changed, ['capability:shell-exec']);
    });
    it('isolation mode change is captured', () => {
        const v1 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.0.0',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
            isolation: 'none',
        });
        const v2 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.1.0',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
            isolation: 'sourced-only',
        });
        const diff = diffPacks(v1, v2);
        assert.deepEqual(diff.isolationChange, { from: 'none', to: 'sourced-only' });
        assert.equal(diff.isNoop, false);
    });
    it('mixed add + remove + change produces all three lists populated', () => {
        const v1 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.0.0',
            rules: [
                { capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' },
                { capability: CAPABILITY_CLASS.SHELL_EXEC, action: 'REQUIRE_APPROVAL' },
            ],
        });
        const v2 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '2.0.0',
            rules: [
                { capability: CAPABILITY_CLASS.MCP, action: 'WARN' }, // changed
                // SHELL_EXEC removed
                { capability: CAPABILITY_CLASS.FILESYSTEM_WRITE, action: 'BLOCK' }, // added
            ],
        });
        const diff = diffPacks(v1, v2);
        assert.deepEqual(diff.added, ['capability:filesystem-write']);
        assert.deepEqual(diff.removed, ['capability:shell-exec']);
        assert.deepEqual(diff.changed, ['capability:mcp']);
        assert.equal(diff.changes.length, 3);
    });
    it('changes list is sorted by category for stable diffs', () => {
        const v1 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.0.0',
            rules: [],
        });
        const v2 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.1.0',
            rules: [
                { capability: CAPABILITY_CLASS.WEB_FETCH, action: 'BLOCK' },
                { capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' },
                { capability: CAPABILITY_CLASS.FILESYSTEM_WRITE, action: 'BLOCK' },
            ],
        });
        const diff = diffPacks(v1, v2);
        // Sorted: capability:filesystem-write, capability:mcp, capability:web-fetch
        assert.deepEqual(diff.added, [
            'capability:filesystem-write',
            'capability:mcp',
            'capability:web-fetch',
        ]);
    });
    it('summarizeDiff produces compact human-readable text', () => {
        const v1 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.0.0',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        const v2 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.1.0',
            rules: [
                { capability: CAPABILITY_CLASS.MCP, action: 'WARN' },
                { capability: CAPABILITY_CLASS.SHELL_EXEC, action: 'BLOCK' },
            ],
        });
        const s = summarizeDiff(diffPacks(v1, v2));
        assert.match(s, /co: 1.0.0 -> 1.1.0/);
        assert.match(s, /1 added/);
        assert.match(s, /1 changed/);
    });
    it('summarizeDiff on a noop reports no functional changes', () => {
        const v1 = buildCompanyPack({
            id: 'co',
            name: 'co',
            orgId: 'org-x',
            version: '1.0.0',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        const v2 = { ...v1, version: '1.0.1' };
        assert.match(summarizeDiff(diffPacks(v1, v2)), /no functional changes/);
    });
});
//# sourceMappingURL=pack-diff.test.js.map