"use strict";
/**
 * AutonomousActionIsolator -- Cycle-composition gate for autonomous agents.
 *
 * Enforces the structural rule that an agent which READS the world in a cycle
 * cannot also CHANGE the world in that same cycle. This stops the prompt-injection
 * cascade: a hostile document retrieved in cycle N cannot trigger a consequential
 * action until cycle N+1, at which point the operator has visibility into what
 * cycle N retrieved before authorising cycle N+1's writes.
 *
 * BUILD_PLAN_V3_FULL_LIFECYCLE.md line 278:
 *   "Autonomous action isolation: no consequential action in same cycle as
 *    information gathering"
 *
 * OWASP A05 -- Security Misconfiguration (cascading hallucination + prompt injection):
 *   Without isolation, an agent that retrieves a hostile document ("delete all files")
 *   can obey in the same execution cycle. With isolation, the consequential action is
 *   deferred to a fresh cycle; the operator can review the cycle N retrieval before
 *   cycle N+1 is allowed to mutate state.
 *
 * Action taxonomy (orthogonal to PR #24 autonomy spectrum):
 *   - info-gathering  read, retrieve, query, search, fetch, list (non-mutating)
 *   - reasoning       self-check, regenerate, output (per PR #17 taxonomy)
 *   - consequential   write, send, deploy, transact, create, update, delete (mutates:true)
 *
 * Relation to PR #24 (autonomy spectrum):
 *   Both gates compose in the PreToolUse chain. Autonomy spectrum runs first and
 *   decides action class + autonomy level (WHAT kind of action, at WHAT level).
 *   Action isolation runs second and decides cycle composition (WHEN relative to
 *   info-gathering in the same cycle). Both must pass before tool dispatch.
 *
 * Three operating modes (operator-configured per agent):
 *   'none'          No enforcement. Agent can mix freely. Default for non-strict packs.
 *   'strict'        Any info-gathering in this cycle blocks ALL consequential actions.
 *                   Consequential actions throw ActionIsolationViolationError.
 *   'sourced-only'  Only blocks consequential actions that reference data sourced in the
 *                   same cycle (targetIds overlap with prior sourceIds). Allows same-cycle
 *                   consequential actions on pre-existing data. Used by strict packs
 *                   (HIPAA, GDPR, PCI DSS, HMDA, DORA) as a pragmatic default that
 *                   blocks the prompt-injection cascade without breaking legitimate
 *                   same-cycle workflows on pre-existing data.
 *
 * Pack-binding is mandatory on every operation (per feedback_pack_binding_primacy.md).
 *
 * Pen-test gates:
 *   PT-ACTION-ISO-1: source-spoofing -- agent declares info-gathering with empty
 *     sourceIds to evade sourced-only mode. Compensating control: INFO_GATHERING_NO_SOURCES_DECLARED
 *     warning event so auditors can detect the pattern.
 *   PT-ACTION-ISO-2: cycle-id reuse -- agent reuses a cleared cycleId hoping to carry
 *     over the cleared log. clearCycle() deletes the log; new cycleId starts empty.
 *   PT-ACTION-ISO-3: parallel-action timing -- agent fires info-gathering and consequential
 *     simultaneously hoping the guard sees an empty log. Per-cycle Mutex serialises calls.
 *
 * Compliance bindings:
 *   HIPAA 164.308(a)(5) -- Security awareness; anomaly detection
 *   GDPR Art. 25 -- Data protection by design; access minimisation
 *   PCI DSS Req 6.4 -- Protect public-facing web applications
 *   DORA Art. 9 -- ICT risk management; untrusted data handling
 *   SOC 2 CC7.2 -- System monitoring; anomaly response
 *   NIST 800-53 SI-10 -- Information input validation
 *
 * @connexum/ai-governance P3-T2
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutonomousActionIsolator = exports.UnauthorizedIsolationConfigError = exports.EmptyPackBindingError = exports.ActionIsolationViolationError = void 0;
exports.defaultIsolationModeForPacks = defaultIsolationModeForPacks;
const crypto = __importStar(require("node:crypto"));
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
/**
 * Pack IDs whose default isolation mode is 'sourced-only'.
 * These are strict regulated packs where prompt-injection via retrieved content
 * poses a specific compliance risk (PHI exfiltration, financial fraud, etc.).
 * 'sourced-only' is chosen over 'strict' because it blocks the cascade without
 * halting legitimate same-cycle writes on pre-existing (non-retrieved) data.
 */
const STRICT_PACK_IDS = new Set([
    'hipaa',
    'hipaa-security',
    'hipaa-privacy',
    'gdpr',
    'gdpr-eu',
    'eu-gdpr',
    'uk-gdpr',
    'pcidss',
    'pci-dss',
    'hmda',
    'dora',
    'dora-eu',
]);
// ---------------------------------------------------------------------------
// Errors
// ---------------------------------------------------------------------------
class ActionIsolationViolationError extends Error {
    orgId;
    agentId;
    cycleId;
    mode;
    remediation;
    constructor(opts) {
        super(`ActionIsolationViolationError: Consequential action blocked for agent ` +
            `'${opts.agentId}' (org '${opts.orgId}') in cycle '${opts.cycleId}'. ` +
            `Mode: ${opts.mode}. Remediation: ${opts.remediation}. Detail: ${opts.detail}`);
        this.name = 'ActionIsolationViolationError';
        this.orgId = opts.orgId;
        this.agentId = opts.agentId;
        this.cycleId = opts.cycleId;
        this.mode = opts.mode;
        this.remediation = opts.remediation;
    }
}
exports.ActionIsolationViolationError = ActionIsolationViolationError;
class EmptyPackBindingError extends Error {
    constructor(operation) {
        super(`EmptyPackBindingError: packBinding must be a non-empty array for '${operation}'. ` +
            'Every action isolation operation must declare which compliance packs govern it.');
        this.name = 'EmptyPackBindingError';
    }
}
exports.EmptyPackBindingError = EmptyPackBindingError;
class UnauthorizedIsolationConfigError extends Error {
    approverIdentity;
    constructor(approverIdentity, detail) {
        super(`UnauthorizedIsolationConfigError: '${approverIdentity}' is not authorized to ` +
            `configure action isolation. Requires ADMIN role. Detail: ${detail}`);
        this.name = 'UnauthorizedIsolationConfigError';
        this.approverIdentity = approverIdentity;
    }
}
exports.UnauthorizedIsolationConfigError = UnauthorizedIsolationConfigError;
/**
 * Simple async mutex for per-cycle serialisation.
 * PT-ACTION-ISO-3: ensures recordAction and guardConsequentialAction
 * cannot race even if called near-simultaneously.
 */
class CycleMutex {
    queue = [];
    locked = false;
    async acquire() {
        if (!this.locked) {
            this.locked = true;
            return;
        }
        return new Promise((resolve) => {
            this.queue.push(resolve);
        });
    }
    release() {
        if (this.queue.length > 0) {
            const next = this.queue.shift();
            next();
        }
        else {
            this.locked = false;
        }
    }
}
// ---------------------------------------------------------------------------
// AutonomousActionIsolator
// ---------------------------------------------------------------------------
/**
 * AutonomousActionIsolator
 *
 * Operator-configured gate that enforces cycle-composition isolation between
 * information-gathering and consequential actions.
 *
 * Usage:
 *   const isolator = new AutonomousActionIsolator(auditSink, operatorRoles);
 *
 *   // Operator configures mode (requires ADMIN role):
 *   isolator.configure('org-1', 'agent-1', 'strict', ['hipaa'], 'admin-alice');
 *
 *   // PreToolUse chain -- info-gathering tool:
 *   await isolator.recordAction('org-1', 'agent-1', 'cycle-abc', {
 *     kind: 'info-gathering',
 *     sourceIds: ['vs_pubmed_2026'],
 *   }, ['hipaa']);
 *
 *   // PreToolUse chain -- before mutating tool (after autonomy-spectrum check):
 *   const result = await isolator.guardConsequentialAction(
 *     'org-1', 'agent-1', 'cycle-abc',
 *     { class: 'production-write', mutates: true, targetIds: ['doc-123'] },
 *     ['hipaa'],
 *   );
 *   // mode:'strict' + info-gathering present -> throws ActionIsolationViolationError
 *
 *   // Cycle teardown:
 *   isolator.clearCycle('cycle-abc');
 */
class AutonomousActionIsolator {
    auditSink;
    operatorRoles;
    /**
     * Test-only operator map. When provided, OperatorRoles RBAC is bypassed
     * in favour of this simple identity->role map.
     */
    testOperatorMap;
    /** Per-agent isolation config. Key: orgId::agentId */
    configs = new Map();
    /**
     * Per-agent-cycle action log. Key: orgId::agentId::cycleId
     * Keyed by agent+cycle so that two different agents' cycle logs
     * are fully independent even if they share the same cycleId string.
     */
    cycleLogs = new Map();
    /**
     * Per-agent-cycle mutex. Key: orgId::agentId::cycleId
     * PT-ACTION-ISO-3: ensures recordAction and guardConsequentialAction
     * are serialised per agent+cycle pair, not globally.
     */
    cycleMutexes = new Map();
    /** Per-agent SHA chain head. Key: orgId::agentId */
    chainHead = new Map();
    constructor(auditSink, operatorRoles, options) {
        this.auditSink = auditSink ?? (() => undefined);
        this.operatorRoles = operatorRoles ?? null;
        this.testOperatorMap = options?.testOperatorMap;
    }
    // -------------------------------------------------------------------------
    // Public API
    // -------------------------------------------------------------------------
    /**
     * Configure isolation mode for an agent. Operator-only (ADMIN role required).
     *
     * @param orgId          Organisation identifier.
     * @param agentId        Agent identifier.
     * @param mode           Isolation mode: 'none' | 'strict' | 'sourced-only'.
     * @param packBinding    Non-empty array of compliance pack IDs.
     * @param approverIdentity Operator identity (must have ADMIN role).
     */
    configure(orgId, agentId, mode, packBinding, approverIdentity) {
        this.validatePackBinding(packBinding, 'configure');
        this.verifyOperatorIdentity(approverIdentity, orgId, agentId);
        const key = this.agentKey(orgId, agentId);
        const config = {
            mode,
            packBinding: [...packBinding],
            approverIdentity,
            configuredAt: new Date().toISOString(),
        };
        this.configs.set(key, config);
        this.emitEvent({
            type: 'ACTION_ISOLATION_CONFIGURED',
            severity: 'INFO',
            orgId,
            agentId,
            cycleId: 'n/a',
            data: { mode, packBinding, approverIdentity },
        }, key);
    }
    /**
     * Record an action in a cycle's log.
     *
     * This is called from existing audit chain emit points:
     *   - PR #18 (rag-source-allowlist) allowed retrievals -> kind: 'info-gathering'
     *   - PR #17 (anomaly-self-reflection) actions -> kind: 'reasoning'
     *   - PR #24 (autonomy-spectrum) mutating tool calls -> kind: 'consequential'
     *   - PR #24 non-mutating tool calls -> kind: 'info-gathering' or 'reasoning'
     *
     * PT-ACTION-ISO-1 compensating control: if kind is 'info-gathering' and
     * sourceIds is empty, emits INFO_GATHERING_NO_SOURCES_DECLARED warning.
     *
     * @param orgId       Organisation identifier.
     * @param agentId     Agent identifier.
     * @param cycleId     Cycle identifier (server-generated, one-shot per PR #15).
     * @param action      Action descriptor.
     * @param packBinding Non-empty array of compliance pack IDs.
     */
    async recordAction(orgId, agentId, cycleId, action, packBinding) {
        this.validatePackBinding(packBinding, 'recordAction');
        const mutex = this.getCycleMutex(orgId, agentId, cycleId);
        await mutex.acquire();
        try {
            const log = this.getCycleLog(orgId, agentId, cycleId);
            const recordedAt = action.timestamp ?? new Date().toISOString();
            log.actions.push({ ...action, recordedAt });
            if (action.kind === 'info-gathering') {
                log.hasInfoGathering = true;
                for (const srcId of action.sourceIds ?? []) {
                    log.infoGatheringSourceIds.add(srcId);
                }
                // PT-ACTION-ISO-1: compensating control for source-spoofing.
                if (!action.sourceIds || action.sourceIds.length === 0) {
                    const agentKey = this.agentKey(orgId, agentId);
                    this.emitEvent({
                        type: 'INFO_GATHERING_NO_SOURCES_DECLARED',
                        severity: 'WARN',
                        orgId,
                        agentId,
                        cycleId,
                        data: {
                            detail: 'info-gathering action recorded with empty sourceIds. ' +
                                'This pattern may indicate source-spoofing to evade sourced-only isolation mode. ' +
                                'Review cycle actions for compliance (PT-ACTION-ISO-1).',
                            packBinding,
                        },
                    }, agentKey);
                }
            }
        }
        finally {
            mutex.release();
        }
    }
    /**
     * Pre-execution gate for consequential actions.
     *
     * Must run AFTER PR #24 autonomy-spectrum gate and BEFORE tool dispatch.
     * Order: autonomy-spectrum (class+level check) -> action-isolation (cycle-composition) -> dispatch.
     *
     * Returns { decision: 'execute', reason } when allowed.
     * Throws ActionIsolationViolationError when blocked.
     * Emits ACTION_ISOLATION_PASSED (NOTICE) when mode is non-'none' and allowed.
     * Emits ACTION_ISOLATION_VIOLATION (ERROR) when blocked.
     *
     * @param orgId       Organisation identifier.
     * @param agentId     Agent identifier.
     * @param cycleId     Cycle identifier.
     * @param action      Consequential action descriptor.
     * @param packBinding Non-empty array of compliance pack IDs.
     */
    async guardConsequentialAction(orgId, agentId, cycleId, action, packBinding) {
        this.validatePackBinding(packBinding, 'guardConsequentialAction');
        const mutex = this.getCycleMutex(orgId, agentId, cycleId);
        await mutex.acquire();
        try {
            const mode = this.resolveMode(orgId, agentId, packBinding);
            const agentKey = this.agentKey(orgId, agentId);
            if (mode === 'none') {
                return { decision: 'execute', reason: 'mode:none -- no cycle-composition enforcement' };
            }
            const agentCycleKey = this.agentCycleKey(orgId, agentId, cycleId);
            const cycleLog = this.cycleLogs.get(agentCycleKey);
            if (mode === 'strict') {
                const hasInfoGathering = cycleLog?.hasInfoGathering ?? false;
                if (hasInfoGathering) {
                    this.emitEvent({
                        type: 'ACTION_ISOLATION_VIOLATION',
                        severity: 'ERROR',
                        orgId,
                        agentId,
                        cycleId,
                        data: {
                            mode,
                            remediation: 'deferred-to-next-cycle',
                            actionClass: action.class,
                            detail: 'Consequential action blocked: info-gathering actions exist in this cycle. ' +
                                'Defer the consequential action to a new cycle so the operator can review ' +
                                'retrieved content before mutation proceeds.',
                            packBinding,
                        },
                    }, agentKey);
                    throw new ActionIsolationViolationError({
                        orgId,
                        agentId,
                        cycleId,
                        mode,
                        remediation: 'deferred-to-next-cycle',
                        detail: 'Info-gathering detected in this cycle. Consequential action must be deferred to next cycle.',
                    });
                }
                // Allowed in strict mode (no info-gathering in this cycle).
                this.emitEvent({
                    type: 'ACTION_ISOLATION_PASSED',
                    severity: 'NOTICE',
                    orgId,
                    agentId,
                    cycleId,
                    data: { mode, actionClass: action.class, packBinding },
                }, agentKey);
                return {
                    decision: 'execute',
                    reason: 'mode:strict -- no info-gathering in this cycle',
                };
            }
            // mode === 'sourced-only'
            const targetIds = action.targetIds ?? [];
            const infoGatheringSourceIds = cycleLog?.infoGatheringSourceIds ?? new Set();
            const overlappingIds = targetIds.filter((id) => infoGatheringSourceIds.has(id));
            if (overlappingIds.length > 0) {
                this.emitEvent({
                    type: 'ACTION_ISOLATION_VIOLATION',
                    severity: 'ERROR',
                    orgId,
                    agentId,
                    cycleId,
                    data: {
                        mode,
                        remediation: 'sourced-this-cycle',
                        actionClass: action.class,
                        overlappingIds,
                        detail: `Consequential action blocked: targetIds [${overlappingIds.join(', ')}] overlap ` +
                            `with sourceIds from info-gathering actions in this cycle. ` +
                            `The agent may be acting on freshly-retrieved (potentially hostile) content. ` +
                            `Defer to next cycle or use pre-existing data not sourced in this cycle.`,
                        packBinding,
                    },
                }, agentKey);
                throw new ActionIsolationViolationError({
                    orgId,
                    agentId,
                    cycleId,
                    mode,
                    remediation: 'sourced-this-cycle',
                    detail: `targetIds ${JSON.stringify(overlappingIds)} were sourced in this cycle.`,
                });
            }
            // Allowed: no overlap.
            this.emitEvent({
                type: 'ACTION_ISOLATION_PASSED',
                severity: 'NOTICE',
                orgId,
                agentId,
                cycleId,
                data: {
                    mode,
                    actionClass: action.class,
                    targetIds,
                    infoGatheringSourceCount: infoGatheringSourceIds.size,
                    packBinding,
                },
            }, agentKey);
            return {
                decision: 'execute',
                reason: 'mode:sourced-only -- no targetId overlap with cycle info-gathering sources',
            };
        }
        finally {
            mutex.release();
        }
    }
    /**
     * Release the per-cycle action log when a cycle completes.
     * PT-ACTION-ISO-2: A new cycleId starts with an empty log; cleared state
     * is not carried over even if the cycleId string is reused by a caller.
     *
     * The key is agent-scoped (orgId::agentId::cycleId), so clearing agent A's
     * cycle does not affect agent B's cycle with the same cycleId string.
     *
     * @param orgId   Organisation identifier.
     * @param agentId Agent identifier.
     * @param cycleId Cycle identifier to clear.
     */
    clearCycle(orgId, agentId, cycleId) {
        const key = this.agentCycleKey(orgId, agentId, cycleId);
        this.cycleLogs.delete(key);
        this.cycleMutexes.delete(key);
    }
    // -------------------------------------------------------------------------
    // Private helpers
    // -------------------------------------------------------------------------
    agentKey(orgId, agentId) {
        return `${orgId}::${agentId}`;
    }
    /**
     * Per-agent-cycle compound key. Ensures that two agents running the same
     * cycleId string have fully independent action logs (multi-agent isolation).
     */
    agentCycleKey(orgId, agentId, cycleId) {
        return `${orgId}::${agentId}::${cycleId}`;
    }
    getCycleLog(orgId, agentId, cycleId) {
        const key = this.agentCycleKey(orgId, agentId, cycleId);
        if (!this.cycleLogs.has(key)) {
            this.cycleLogs.set(key, {
                actions: [],
                infoGatheringSourceIds: new Set(),
                hasInfoGathering: false,
            });
        }
        return this.cycleLogs.get(key);
    }
    getCycleMutex(orgId, agentId, cycleId) {
        const key = this.agentCycleKey(orgId, agentId, cycleId);
        if (!this.cycleMutexes.has(key)) {
            this.cycleMutexes.set(key, new CycleMutex());
        }
        return this.cycleMutexes.get(key);
    }
    /**
     * Resolve the effective isolation mode for an agent.
     *
     * Priority order:
     * 1. Explicitly configured mode (via configure()).
     * 2. Pack-derived default: if any pack in packBinding is a strict pack,
     *    default to 'sourced-only'.
     * 3. Fallback: 'none'.
     */
    resolveMode(orgId, agentId, packBinding) {
        const key = this.agentKey(orgId, agentId);
        const config = this.configs.get(key);
        if (config) {
            return config.mode;
        }
        // Pack-derived default.
        for (const packId of packBinding) {
            if (STRICT_PACK_IDS.has(packId.toLowerCase())) {
                return 'sourced-only';
            }
        }
        return 'none';
    }
    validatePackBinding(packBinding, operation) {
        if (!Array.isArray(packBinding) || packBinding.length === 0) {
            throw new EmptyPackBindingError(operation);
        }
    }
    verifyOperatorIdentity(approverIdentity, orgId, agentId) {
        if (!approverIdentity || typeof approverIdentity !== 'string' || approverIdentity.trim() === '') {
            throw new UnauthorizedIsolationConfigError(approverIdentity ?? '', 'approverIdentity must be a non-empty string.');
        }
        // Test mode: use injected operator map.
        if (this.testOperatorMap) {
            const role = this.testOperatorMap.get(approverIdentity);
            if (role !== 'ADMIN') {
                throw new UnauthorizedIsolationConfigError(approverIdentity, `Test operator map: identity '${approverIdentity}' has role '${role ?? 'unknown'}', requires ADMIN.`);
            }
            return;
        }
        // Production: check via OperatorRoles.
        if (!this.operatorRoles) {
            throw new UnauthorizedIsolationConfigError(approverIdentity, 'No OperatorRoles instance provided and no testOperatorMap set.');
        }
        const operators = this.operatorRoles.listOperators();
        const match = operators.find((op) => op.name === approverIdentity || op.id === approverIdentity);
        if (!match) {
            throw new UnauthorizedIsolationConfigError(approverIdentity, `Operator '${approverIdentity}' not found in operator registry. ` +
                'Register via OperatorRoles.createOperator() first.');
        }
        if (!match.active) {
            throw new UnauthorizedIsolationConfigError(approverIdentity, `Operator '${approverIdentity}' (id: ${match.id}) is deactivated.`);
        }
        const check = this.operatorRoles.checkPermission(match.id, 'governance.configure');
        if (!check.allowed) {
            throw new UnauthorizedIsolationConfigError(approverIdentity, `Operator role '${match.role}' lacks 'governance.configure' permission. ${check.reason}`);
        }
    }
    emitEvent(event, agentKey) {
        const prevSha = this.chainHead.get(agentKey) ?? this.genesisHash(agentKey);
        const full = {
            ...event,
            timestamp: event.timestamp ?? new Date().toISOString(),
            prevSha,
        };
        // Advance chain head.
        const newHead = crypto
            .createHash('sha256')
            .update(`${prevSha}:${event.type}:${event.cycleId}:${event.timestamp}`)
            .digest('hex');
        this.chainHead.set(agentKey, newHead);
        try {
            this.auditSink(full);
        }
        catch {
            process.stderr.write(`[ACTION ISOLATION] Audit sink threw for event type: ${event.type}\n`);
        }
    }
    genesisHash(agentKey) {
        return crypto
            .createHash('sha256')
            .update(`action-isolation-genesis-${agentKey}`)
            .digest('hex');
    }
}
exports.AutonomousActionIsolator = AutonomousActionIsolator;
// ---------------------------------------------------------------------------
// Pack default mode helper (exported for pack contributions)
// ---------------------------------------------------------------------------
/**
 * Returns the default isolation mode for a set of pack IDs.
 * Used by packs that set requiresActionIsolation to communicate their
 * preferred default to the runtime.
 *
 * Strict regulated packs default to 'sourced-only' (not 'strict') because:
 *   - 'strict' would block all same-cycle mutating actions whenever ANY
 *     retrieval happened, which is too broad for most regulated workflows.
 *   - 'sourced-only' specifically blocks consequential actions on freshly-retrieved
 *     content, which is the precise attack vector (prompt-injection cascade).
 *   - Operators who need full 'strict' isolation can configure it explicitly.
 */
function defaultIsolationModeForPacks(packIds) {
    for (const id of packIds) {
        if (STRICT_PACK_IDS.has(id.toLowerCase())) {
            return 'sourced-only';
        }
    }
    return 'none';
}
//# sourceMappingURL=action-isolation.js.map