/**
 * RED-GREEN tests for F-NEW-PRODUCT-PACK-INHERITANCE (W1.3 of
 * F-NEW-PRODUCT-AGENT-VISIBILITY-CLUSTER-2026-05-12).
 *
 * Customer-path probe:
 *   - Org-baseline declares "no MCP (BLOCK)" and "shell-exec (REQUIRE_APPROVAL)"
 *   - Per-agent pack declares "shell-exec (BLOCK)" and "filesystem-write (REQUIRE_APPROVAL)"
 *   - Composed pack:
 *       capability:mcp -> BLOCK            (from baseline)
 *       capability:shell-exec -> BLOCK     (strictest-wins; agent override)
 *       capability:filesystem-write -> REQUIRE_APPROVAL  (from agent)
 *   - Verify with real PackEvaluator: BLOCK -> DENY, REQUIRE_APPROVAL -> PENDING
 *
 * @connexum/ai-governance  F-NEW-PRODUCT-PACK-INHERITANCE
 */
import { describe, it } from 'node:test';
import * as assert from 'node:assert/strict';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { buildOrgBaselinePack, composeAgentPack, buildInheritedAgentPack, } from './pack-inheritance.js';
import { CAPABILITY_CLASS } from './capability-classes.js';
import { PackEvaluator } from './pack-evaluator.js';
import { PackRegistry } from '../packs/index.js';
import { EventBus } from '../audit/event-bus.js';
import { createActionContext } from '../adapters/index.js';
function evalActionWithPack(pack, toolName, input = {}) {
    const registry = new PackRegistry();
    registry.register(pack);
    registry.activate(pack.id);
    const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'inh-'));
    const bus = new EventBus({ eventDir: dir, agentName: 'inh-test' });
    const evaluator = new PackEvaluator(registry, bus, { ttlMs: 60_000, enableCache: false });
    const ac = createActionContext(toolName, input, { name: 'agent-1', orgId: 'org-x' });
    return evaluator.evaluate('org-x', 'agent-1', ac);
}
describe('F-NEW-PRODUCT-PACK-INHERITANCE — org-baseline + per-agent composition', () => {
    it('composed pack inherits baseline rules where agent has no override', () => {
        const baseline = buildOrgBaselinePack({
            orgId: 'org-x',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        const composed = composeAgentPack(baseline, {
            id: 'agent-x-pack',
            name: 'agent x pack',
            orgId: 'org-x',
            agentId: 'agent-x',
            rules: [{ capability: CAPABILITY_CLASS.FILESYSTEM_WRITE, action: 'REQUIRE_APPROVAL' }],
        });
        const v1 = evalActionWithPack(composed, 'mcp__list_resources');
        assert.equal(v1.verdict, 'DENY', 'MCP inherited from baseline');
        const v2 = evalActionWithPack(composed, 'Write', { file_path: '/tmp/x' });
        assert.equal(v2.verdict, 'PENDING', 'filesystem-write from agent-specific');
    });
    it('STRICTEST-WINS: agent BLOCK overrides baseline REQUIRE_APPROVAL', () => {
        const baseline = buildOrgBaselinePack({
            orgId: 'org-x',
            rules: [{ capability: CAPABILITY_CLASS.SHELL_EXEC, action: 'REQUIRE_APPROVAL' }],
        });
        const composed = composeAgentPack(baseline, {
            id: 'agent-strict',
            name: 'agent strict',
            orgId: 'org-x',
            agentId: 'agent-strict',
            rules: [{ capability: CAPABILITY_CLASS.SHELL_EXEC, action: 'BLOCK' }],
        });
        const verdict = evalActionWithPack(composed, 'Bash', { command: 'ls' });
        assert.equal(verdict.verdict, 'DENY', 'agent BLOCK wins over baseline REQUIRE_APPROVAL');
    });
    it('STRICTEST-WINS: baseline BLOCK survives agent LOG (less strict)', () => {
        const baseline = buildOrgBaselinePack({
            orgId: 'org-x',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        const composed = composeAgentPack(baseline, {
            id: 'agent-relaxed',
            name: 'agent relaxed',
            orgId: 'org-x',
            agentId: 'agent-relaxed',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'LOG' }],
        });
        const verdict = evalActionWithPack(composed, 'mcp__list_resources');
        assert.equal(verdict.verdict, 'DENY', 'baseline BLOCK cannot be relaxed by agent LOG');
    });
    it('composed pack carries provenance via aliases', () => {
        const baseline = buildOrgBaselinePack({
            orgId: 'org-x',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        });
        const composed = composeAgentPack(baseline, {
            id: 'agent-prov',
            name: 'agent prov',
            orgId: 'org-x',
            agentId: 'agent-prov',
            rules: [{ capability: CAPABILITY_CLASS.SHELL_EXEC, action: 'BLOCK' }],
        });
        assert.ok(composed.aliases?.includes('org-baseline-org-x'));
        assert.ok(composed.aliases?.includes('agent-prov'));
    });
    it('strictest isolation across baseline + agent', () => {
        const baseline = buildOrgBaselinePack({
            orgId: 'org-x',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
            isolation: 'sourced-only',
        });
        const composed = composeAgentPack(baseline, {
            id: 'agent-iso',
            name: 'agent iso',
            orgId: 'org-x',
            agentId: 'agent-iso',
            rules: [{ capability: CAPABILITY_CLASS.SHELL_EXEC, action: 'BLOCK' }],
            isolation: 'strict',
        });
        assert.equal(composed.requiresActionIsolation, 'strict');
        const baseline2 = buildOrgBaselinePack({
            orgId: 'org-y',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
            isolation: 'strict',
        });
        const composed2 = composeAgentPack(baseline2, {
            id: 'agent-iso-2',
            name: 'agent iso 2',
            orgId: 'org-y',
            agentId: 'agent-iso-2',
            rules: [{ capability: CAPABILITY_CLASS.SHELL_EXEC, action: 'BLOCK' }],
            isolation: 'none',
        });
        assert.equal(composed2.requiresActionIsolation, 'strict', 'baseline strict survives agent none');
    });
    it('buildInheritedAgentPack returns both baseline and composed', () => {
        const { baseline, composed } = buildInheritedAgentPack({
            orgId: 'org-x',
            rules: [{ capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' }],
        }, {
            id: 'a-1',
            name: 'a-1',
            orgId: 'org-x',
            agentId: 'a-1',
            rules: [{ capability: CAPABILITY_CLASS.SHELL_EXEC, action: 'REQUIRE_APPROVAL' }],
        });
        assert.equal(baseline.id, 'org-baseline-org-x');
        assert.equal(composed.id, 'a-1');
        assert.ok(composed.aliases?.includes(baseline.id));
        const v = evalActionWithPack(composed, 'mcp__list_resources');
        assert.equal(v.verdict, 'DENY');
    });
    it('non-overlapping baseline + agent unions all rules', () => {
        const baseline = buildOrgBaselinePack({
            orgId: 'org-x',
            rules: [
                { capability: CAPABILITY_CLASS.MCP, action: 'BLOCK' },
                { capability: CAPABILITY_CLASS.WEB_FETCH, action: 'REQUIRE_APPROVAL' },
            ],
        });
        const composed = composeAgentPack(baseline, {
            id: 'a-2',
            name: 'a-2',
            orgId: 'org-x',
            agentId: 'a-2',
            rules: [
                { capability: CAPABILITY_CLASS.SHELL_EXEC, action: 'BLOCK' },
                { capability: CAPABILITY_CLASS.FILESYSTEM_WRITE, action: 'REQUIRE_APPROVAL' },
            ],
        });
        const actions = composed.dataPolicy.categoryActions ?? {};
        assert.equal(actions[CAPABILITY_CLASS.MCP], 'BLOCK');
        assert.equal(actions[CAPABILITY_CLASS.WEB_FETCH], 'REQUIRE_APPROVAL');
        assert.equal(actions[CAPABILITY_CLASS.SHELL_EXEC], 'BLOCK');
        assert.equal(actions[CAPABILITY_CLASS.FILESYSTEM_WRITE], 'REQUIRE_APPROVAL');
    });
});
//# sourceMappingURL=pack-inheritance.test.js.map