/**
 * The two envelopes that say what a run MAY do: `WorkflowGovernanceBaseline` (the floor a deployment
 * puts under every workflow step) and `RuntimeCaps` (the per-agent capability projection). Neither
 * names the other; they share a module because "the host's declared ceiling" is one concern, and both
 * are read off `RunnerDeps`. Layer 0 vocabulary; `types.ts` re-exports both, so no consumer's import
 * changes.
 */
import type { TaskSpec } from "./task-spec.js";
/**
 * design/98 §E.2 / §2.5 (S8b) — the deployment-trusted governance that EVERY sub-agent an LLM-authored
 * workflow script spawns INHERITS (tighten-only). The child spec is BUILT from this baseline + a strict
 * WHITELIST of safe work-fields the script may set — `{ ...base, ...pick(scriptSpec, WHITELIST_KEYS) }` then
 * `tightenTaskSpec(base, child)` (default-deny / complete-by-construction, NOT a blacklist
 * strip — a missed control-plane field would otherwise leak). It is captured from `RunnerDeps` (trusted,
 * never LLM-influenced), NEVER from the LLM-influenced initiating task spec.
 *
 * Why an EXPLICIT field (arbitration): `RunnerDeps` has no `tools`/`mcp`/`skills`/`principal`
 * (those are TaskSpec-only), so the capability a workflow child gets cannot be auto-derived from deps —
 * the deployment must DECLARE it here. Unset ⇒ self-orchestration is FAIL-CLOSED (the `run_workflow` tool is
 * not mounted, same hard deploy gate as a missing sandbox): a script-spawned agent must never run without a
 * governed baseline.
 */
export interface WorkflowGovernanceBaseline {
    /**
     * The deployment's trusted control-plane the child inherits — toolPolicy / onAsk / onQuestion / hooks /
     * principal / tools / mcp / skills / lspManager / checkpointStore / getApiKeyAndHeaders / promptProvider /
     * handsReadOnly / shellGate / limits / maxCostUsd / maxTokens, etc. Snapshotted into each child spec FIRST,
     * so every governance field comes from here; only whitelisted work-fields overlay it.
     */
    base: Partial<TaskSpec>;
    /**
     * OPTIONAL baseline OVERLAY for a child the script spawns WITH `isolation: "worktree"` (design/97 CORE-6 ×
     * governance). A worktree-isolated agent works in its OWN detached git worktree, so a deployment whose `base`
     * clamps writes (e.g. `handsReadOnly: true` — the right default for children sharing one working tree) can
     * grant isolated children write access WITHOUT loosening the shared-tree baseline — typically
     * `worktreeBase: { handsReadOnly: false }` (lift only the write clamp; the worktree provides the file
     * containment instead of the spec clamp).
     *
     * **Overlay semantics (shallow merge)**: when — and only when — the spawn requested `isolation: "worktree"`,
     * the effective baseline is `{ ...base, ...worktreeBase }`. Field-level at the TOP level only: a field
     * present here overrides the same-named `base` field WHOLESALE (a nested object such as `limits` or
     * `toolPolicy` is replaced entirely, never deep-merged); an absent field inherits from `base` — so
     * toolPolicy / shellGate / limits / maxCostUsd keep governing isolated children unless deliberately
     * overridden. The same whitelist/allowlist/clamp construction applies on top. **Absent ⇒ `base` governs
     * every child, isolated or not (zero behavior change).**
     *
     * **What the containment actually is (honest scope)**: the worktree is COOPERATIVE file isolation — it is
     * the cwd domain the file tools resolve against, not a jail. Bash can `cd` out of it (same posture as the
     * upstream worktree-isolation feature this mirrors; a worktree was never a shell sandbox). Relaxing writes
     * here is therefore safe only under the deployment's trust in the workflow-script author lane it already
     * accepted. Residuals: an isolation request that cannot be honored FAILS the spawn (fail-closed, see
     * {@link ExecutionEnvFactoryContext.isolation}) with the observable degrade shapes rejected outright, but a
     * factory that mints a worktree DEEP INSIDE the shared tree is within-contract — verifying that the minted
     * dir is a genuine fresh worktree is the factory's MUST-throw contract, not an engine receipt.
     */
    worktreeBase?: Partial<TaskSpec>;
    /**
     * The allowed model NAMES an LLM-authored script may pick (design/98 §2.5 新洞2). A script gives a
     * `modelName` string (never a `Model` object — that carries `baseUrl`/`headers` = exfil); the engine
     * resolves it against this list to a deploy-configured `Model` (the script never sees the object).
     * **FAIL-CLOSED**: `undefined`/empty ⇒ the script CANNOT pick a model — a spec that names `modelName`
     * THROWS `WorkflowModelNotAllowedError` and the child is never spawned. The refusal is loud, not a
     * silent downgrade: the script asked for a model it may not have, so the agent call FAILS rather than
     * quietly running on the workflow's default role (a script that wants the default must simply OMIT
     * the field). The same throw covers a name that is off the list, and a listed name the `models`
     * catalog does not hold — so the legal set is the INTERSECTION of this list and the catalog keys
     * (note the catalog is the Runner's TIER-EXPANDED one, so on a deployment with `RunnerDeps.tiers`
     * the tier words and CC aliases are catalog keys here too, still gated by this list).
     * NEVER fail-open to the whole `models` catalog for an LLM-authored workflow.
     */
    workflowModelAllowlist?: string[];
}
/**
 * design/99 §K — the per-principal runtime ENTITLEMENTS the engine enforces server-side, resolved by a
 * deployment via {@link RunnerDeps.runtimeCapsResolver} from center's `GET /api/config/effective?principal=`.
 * Every field is TIGHTEN-ONLY (a cap only ever DENIES or FORCES) — but the family carries THREE
 * polarities, and "absent" does not read the same on each:
 *  · DENY-shaped, `false` denies / absent is no restriction: {@link allowWorkflows}, {@link allowFork},
 *    {@link autoMode} (the per-principal deny bit of a user-enabled mode), {@link allowMemoryOptOut}
 *    (the one member whose resolver-FAULT degrade is allow, on the privacy axis);
 *  · GRANT-shaped, `=== true` opts in / absent is OFF: {@link allowObservers};
 *  · FORCE-shaped, `true` mandates / absent is the caller's opt-in default: {@link forceDurableGate}
 *    (binds only where a checkpoint store is wired; announced `config.durable_gate_unavailable` where none is).
 * These seven are the caps the ENGINE enforces — {@link bypassPermissions} is the seventh, the deny bit of the
 * `bypassPermissions` mode; `allowUltracode` stays a shell-UX concern (see {@link RunnerDeps.runtimeCapsResolver}).
 */
/**
 * #692 C-d — WHICH plane's ratchet denied auto mode, when the resolver knows: the three settings sources
 * CC 2.1.250's `permissions.disableAutoMode` can come from, as the resolver folds them into the one deny bit
 * ({@link RuntimeCaps.autoMode} `=== false`). `org` = a managed / organization policy plane; `local` = the
 * machine's local settings; `settings` = the user's / project's settings file. Read ONLY beside the deny bit
 * (a source with no denial is a contradiction the value screen refuses as a resolver fault); projected onto
 * the leg's manifest read face (`WiringManifest.autoMode.deniedSource`) so a shell can say "your organization
 * turned auto mode off" vs "your settings did" instead of one word for both.
 */
export declare const AUTO_MODE_DENY_SOURCES: readonly ["org", "local", "settings"];
export type AutoModeDenySource = (typeof AUTO_MODE_DENY_SOURCES)[number];
/** Membership test for {@link AutoModeDenySource}. */
export declare function isAutoModeDenySource(v: unknown): v is AutoModeDenySource;
export interface RuntimeCaps {
    /** `false` DENIES workflow self-orchestration for this principal server-side — even on a deployment that is
     *  capable ({@link RunnerDeps.workflowScriptRunner} + governance). The third stage of the workflows gate.
     *  `undefined`/`true` = no per-principal restriction (the deployment capability still governs). */
    allowWorkflows?: boolean;
    /** `false` DENIES fork (`Agent(subagent_type:"fork")` — design/136: the only fork face since the standalone
     *  tool was retired; the deny is the honest `fork.disabled` result, and since 1.256 it binds the Agent-fork
     *  route too, closing the 1.254 governance circumvention) for this principal server-side — even on a fork-capable
     *  (durable-store) deployment. Fork is a compute-amplification primitive (a principal spawns
     *  context-inheriting children, each spending on its own quota), so a multi-tenant operator gates it
     *  per-principal the SAME way as {@link allowWorkflows}. `undefined`/`true` = no per-principal restriction
     *  (the task `enableFork` + durable-store capability still govern). Tighten-only: it can DENY a capable
     *  deployment, never GRANT beyond it. */
    allowFork?: boolean;
    /**
     * Observer agents (CC 2.1.206 parity, docs/CC206-OBSERVER-ANCHORS-2026-07-11.md §6): honor
     * {@link AgentDefinition.observer} auto-spawn declarations. **POLARITY NOTE — unlike
     * `allowWorkflows`/`allowFork` (`undefined` = unrestricted), this one is `=== true` EXPLICIT
     * opt-in, default OFF**: CC's gate pair is a default-UNSET experimental env var
     * (`CLAUDE_CODE_EXPERIMENTAL_OBSERVER_AGENTS`) ANDed with a default-true statsig gate — the
     * composite ships dark. `undefined`/`false` ⇒ declarations resolve to unobserved (no warn: the
     * gate, not a config mistake).
     */
    allowObservers?: boolean;
    /** `true` FORCES this principal's run onto the durable-approval path: the engine synthesizes a
     *  `durableApproval{scope: principal}` so a policy `ask` suspends to the wire (a per-tool CC-faithful gate)
     *  even when the caller did not opt in — center's fleet-wide "interactive runs gate" mandate. A
     *  caller-supplied `TaskSpec.durableApproval` always wins (it may carry a tighter scope/ttl).
     *  The mandate binds only where a {@link RunnerDeps.checkpointStore} is wired — the park facility it
     *  forces the run onto. On a store-less deployment it has no facility: the leg announces
     *  `config.durable_gate_unavailable` once (before its first ask), every ask resolves on the live chain
     *  (a live approver / question face in-stream, or the fail-closed deny with none), no durable record
     *  is written, and a live question face is consulted rather than vetoed (a mandate that cannot park
     *  must not demote a reachable person into the model answering for them). */
    forceDurableGate?: boolean;
    /**
     * The per-principal auto-mode DENY bit (CC 2.1.250 polarity — the mirror of the settings-plane
     * `permissions.disableAutoMode` ratchet: an organization may only take auto mode AWAY; it is the
     * USER who turns it on, by requesting the mode at {@link TaskSpec.permissionMode}).
     *
     * **POLARITY: `=== false` DENIES; ABSENT IS NOT A DENIAL.** This is the family's deny-shaped
     * member (like {@link allowWorkflows} / {@link allowFork}), NOT a grant-shaped one like
     * {@link allowObservers}: a deployment with no entitlement source at all resolves `undefined` here
     * and still arms on intent + capability. `true` is accepted and means the same as absent (no
     * per-principal restriction) — it is not a grant, and it cannot arm a task whose intent seat is
     * unset. The arming itself: intent ∧ {@link RunnerDeps.autoMode} present ∧ this bit not `false`
     * (allow → run; block → deny `source:"classifier"`; classifier failure → FAIL-CLOSED back to the
     * original ask chain). The trust gate is unchanged: classifier RULES enter only through the
     * deployment assembly face, never a repo-controlled plane (the CC 2.1.207 three-source invariant).
     * A denial resolves to a no-op (asks flow the original chain; no warn — the gate, not a mistake).
     */
    autoMode?: boolean;
    /**
     * #692 C-d (additive) — WHICH source's ratchet set {@link autoMode} to `false`, when the resolver folded
     * several ({@link AutoModeDenySource}). Optional: a resolver that does not track sources omits it and the
     * manifest reads `denied` with no source. Present with `autoMode` not `false`, or spelled outside the set,
     * is a resolver FAULT (announced through `onError`, the deny bit coined fail-closed, `resolver_fault` on the
     * manifest) — a source named for a denial that did not happen is a marshalling error, never a fact.
     */
    autoModeDenySource?: AutoModeDenySource;
    /**
     * The per-principal `bypassPermissions` DENY bit — the engine seat of the settings-plane
     * `permissions.disableBypassPermissionsMode: "disable"` ratchet. **`=== false` DENIES; ABSENT IS NOT A DENIAL**
     * (the family's deny shape, like {@link autoMode}). A task that requests `bypassPermissions` on a leg whose
     * caps carry `false` runs in `default` instead, announced once (`config.permission_mode_unavailable`,
     * `by: "operator_deny"`) and reported on `wiring_manifest.permissionMode` — a mode declaration is folded, never
     * a 4xx. A steer into `bypassPermissions` on such a leg folds the same way.
     */
    bypassPermissions?: boolean;
    /**
     * design/383 §3.1 — may this principal declare a session memory-capture OPT-OUT
     * (`TaskSpec.memory.capture: "off"` / the Runner flip verb)? `false` = the deployment REQUIRES
     * capture for this principal (compliance / knowledge retention) — the declaration is refused
     * terminal (`memory.capture_optout_denied`). `undefined` / `true` = no per-principal restriction.
     *
     * ⚠️ POLARITY REVERSAL — this member is the family's one deliberate exception to the
     * fail-closed resolver degrade (`{allowWorkflows:false, allowFork:false}`): on the PRIVACY axis
     * "deny" means "capture the session of a user who explicitly said no", which is the IRREVERSIBLE
     * side (a wrongly-captured session has been read, may be folded into products, may have synced —
     * deleting later does not unhappen it), while a wrongly-honored opt-out costs one uncaptured
     * session (recoverable). Under the default/`"open"` posture a resolver FAULT therefore reads as
     * ALLOW (+ a named `onError` disclosure), and only an explicit `false` denies; a deployment for
     * which the compliance side is the heavier irreversibility declares `memoryCapturePolicy:
     * "governed"`, which flips the fault arm to refuse-to-run (see {@link RunnerDeps.memoryCapturePolicy}).
     *
     * 🔒 FAULT-TRANSIT CONTRACT (server F2, written here because the resolver's habits run the other
     * way): a resolver failure for THIS member must surface as the member being ABSENT (`undefined`)
     * or as a THROW — both read as "fault". The resolver MUST NOT coin a stand-in explicit value on
     * failure (the `{allowWorkflows:false}` degrade habit): an explicit `false` IS the denied
     * verdict, and encoding an outage as one silently swaps the fault arm for the verdict arm — under
     * `"open"` that is the exact polarity inversion this member exists to prevent. A non-boolean
     * value here is treated as a fault (never truthiness-read) and disclosed.
     */
    allowMemoryOptOut?: boolean;
}
