/**
 * A delegated AGENT's definition and the skills it may mount: `AgentDefinition` (the agent a subagent
 * tool spawns) and `SkillSpec` (the wired form the runner mounts). Layer 0 vocabulary; `types.ts`
 * re-exports the two, so no consumer's import changes.
 */
import type { ThinkingLevel } from "../internal/harness.js";
import type { ModelRef } from "./model-seat.js";
import type { TaskSpec } from "./task-spec.js";
/**
 * A declarative, reusable named sub-agent (design/38 1B). Hand a set to {@link createSubagentTool} and the
 * model picks one (by `whenToUse`) to delegate to; the chosen definition's config builds the child task.
 *
 * **Deployment-side config, NOT user input** — `systemPrompt`/`allowTools` shape what the sub-agent can do
 * and see, so they must be set by the deployment, never taken from an end-user message.
 */
export interface AgentDefinition {
    /** Stable identifier + the value the delegation tool's `agent` parameter selects. Must be unique. */
    name: string;
    /** Guidance shown to the model for WHEN to pick this agent (listed in the delegation tool's description). */
    whenToUse?: string;
    /**
     * F4 (CC 2.1.198 parity, `whenToUseLean` — 锚 pretty.js:409174 `rbm` + selection `tIl` :453029
     * `(lean && e.whenToUseLean) || e.whenToUse`): a SHORT variant of {@link whenToUse} preferred on
     * lean-prompt surfaces. sema posture: the engine runs the CC lean-prompt arm wholesale (web.ts
     * lean-card precedent), so roster listings/descriptions prefer this text whenever present;
     * {@link whenToUse} remains the fallback. Optional — a single-text agent behaves exactly as before.
     */
    whenToUseLean?: string;
    /** Tool allowlist over the delegation pool (`["*"]` = all). Replaces (does not merge with) the tool's
     *  own `allowTools`/`denyTools` when this agent is selected. F1 (CC parity): unlike the TOOL-level
     *  allow/deny (which never filters the nested delegation tool — that stays `maxDepth`-governed), a
     *  PER-AGENT allow/deny ALSO governs the nested delegation tool: an agent whose allow/deny excludes
     *  the delegation tool's name cannot re-delegate (CC Explore/Plan `disallowedTools` include Agent,
     *  pretty.js:409189/486948). */
    allowTools?: string[];
    /** Tool denylist (a deny always wins), tool NAMES: `Tool(content)` hides the whole `Tool`. See {@link allowTools} for the per-agent delegation-tool note. */
    denyTools?: string[];
    /**
     * F7 (CC 2.1.198 parity, per-agent `skills` — 锚 pretty.js:422126 `e.skills ?? []`, GA/ungated in 198:
     * CC preloads each named skill's prompt content into the child's opening messages, warning on misses).
     * sema shape: full {@link SkillSpec} objects (sema has no ambient skill registry to resolve bare names
     * against) threaded into the chosen child's `TaskSpec.skills` — disclosed in its `<skills>` block +
     * invocable via the `skill` tool. Deployment-trusted, same trust tier as `systemPrompt`.
     */
    skills?: SkillSpec[];
    /**
     * F7 (CC 2.1.198 parity, per-agent `background` — 锚 pretty.js:453611 `H.background===!0` OR-ed into
     * the background predicate, GA/ungated): `true` = this agent ALWAYS launches on the background lane
     * (an omitted `run_in_background` no longer means sync, and the per-call parameter cannot force sync —
     * CC-same OR semantics). Requires the delegation tool's `background` surface; without one the child
     * runs synchronously (CC-same quiet fallback — CC's env kill-switch arm, :453611 `&& !sJt`).
     */
    background?: boolean;
    /**
     * F7 (CC 2.1.198 parity, per-agent `isolation` — 锚 pretty.js:453599 `z = a ?? H.isolation`, GA):
     * default isolation for this agent; an explicit per-call `isolation` argument wins. sema supports
     * `"worktree"` (CC's `"remote"` arm is a claude.ai-session concern, not ported).
     */
    isolation?: "worktree";
    /** Model for this agent. **Omit to INHERIT the caller's current model** (design/38 1B finding 7) — the
     *  recommended default; a concrete `ModelRef` pins it instead. */
    model?: ModelRef;
    /** Thinking level for this agent. **Omit to INHERIT the caller's current thinking level** (the model
     *  companion above — a mid-run degrade/boost on the parent carries into new children); a concrete
     *  level pins it instead. */
    thinking?: ThinkingLevel;
    /** System prompt / persona for this agent. Falls back to the delegation tool's `systemPrompt`. */
    systemPrompt?: string;
    /** Per-agent turn cap. Falls back to the delegation tool's `limits.maxTurns`. Must be POSITIVE: a
     *  non-positive/non-finite value is ignored (CLS-A-3) rather than folded in, because downstream an
     *  explicit `0` DISABLES the turn cap — the opposite of the tightening this field expresses. */
    maxTurns?: number;
    /** Long-term memory scope for this agent (same shape as {@link TaskSpec.memory}). */
    memory?: TaskSpec["memory"];
    /**
     * This agent's own {@link TaskSpec.memoryPersistenceCapable} declaration — the same three-state
     * statement, made per definition: an agent whose closure tools persist memory declares `true`
     * (suppressing the read-only-memory disclosure no roster inference can clear), one whose roster
     * looks write-capable but reaches no durable store declares `false` (forcing the disclosure).
     * Arbitration with the spawning run's declaration: a parent's explicit `false` is a FLOOR and wins
     * over a definition `true` (the disclosure is about the deployment's storage, which choosing this
     * agent does not change); otherwise a declared definition value wins over the parent's; absent
     * both, the child spec carries no value and the child's own roster inference decides.
     * On the workflow lane (`agent(…, {agentType})`) the definition value fills an ABSENT governed-spec
     * value only — a base/spec declaration of either polarity wins (the lane's spec-pinned-fields rule).
     */
    memoryPersistenceCapable?: boolean;
    /**
     * Observer agents (CC 2.1.206 parity — 逐字锚 docs/CC206-OBSERVER-ANCHORS-2026-07-11.md, schema
     * 面 C @28385708): "Agent type auto-spawned as a background observer whenever this agent runs.
     * The observer receives read-only activity digests and reports via the ObserverReport tool; it
     * never participates in the task." Resolution is warn-and-unobserved on an unknown type and
     * refuses chaining (an observer's own `observer` declaration is ignored). Gated by
     * {@link RuntimeCaps.allowObservers} — EXPLICIT opt-in, default OFF (the sema seat of CC's
     * default-unset env `CLAUDE_CODE_EXPERIMENTAL_OBSERVER_AGENTS` + default-true statsig pair).
     */
    observer?: string;
    /**
     * CC 面 C: "Supplemental postamble appended (after the harness-owned default) to each activity
     * digest sent to the observer. Blank values are ignored."
     */
    observerMessage?: string;
}
/** A skill made available to this task (passed as an object; not loaded from disk). */
export interface SkillSpec {
    name: string;
    description: string;
    content: string;
    /**
     * The tools this skill lets run WITHOUT ASKING for the rest of the run it is activated in — the frontmatter
     * `allowed-tools` list, spelled as a permission rule is spelled: a tool name (`Read`, `mcp__srv__get_issue`), a
     * protocol namespace (`mcp__srv` / `mcp__srv__*` / `mcp__srv__get_*`), a shell command rule (`Bash(git:*)`) or the Read
     * directory form (`Read(//abs/dir/**)`). The list is an allow-rule source, not a fence: an unlisted tool is judged as
     * it always is, and a listed one is released only from the questions an allow rule may clear (a deny or ask rule, the
     * plan mode, the organization ceiling and every mandated question still stand). Activating a skill that declares
     * either list asks once (`Execute skill: <name>`, the card listing what it releases); a skill the person invoked by
     * name ({@link import("./task-spec.js").TaskSpec.userInvokedSkills}) grants without asking. The grant holds for that
     * run (a steer it takes in does not end it) and the next runTask starts without it. An entry this grammar reads as nothing — `*` (it voids an allow list; on a deny list it is inert and the rest of the
     * list still refuses), `mcp__*`, a write path, a domain — grants nothing and is announced at the start of the run (`permission.allowed_tool_not_granted`). A table whose value is not a list (a string, an object…) reads as one such entry; `null` is no table.
     */
    allowedTools?: string[];
    /** The tools refused for the rest of the run this skill is activated in — the frontmatter `disallowed-tools` list,
     *  in the {@link allowedTools} grammar (a path tool also takes a path pattern here); read wherever a person's deny
     *  rows are read, ahead of every allow. */
    disallowedTools?: string[];
    /**
     * Optional attachments bundled with the skill (additive) — the CC bundled-skill shape (a SKILL.md whose
     * body references sibling files by relative path) translated to sema's brain-outside posture, where the
     * ruling is: **core never writes to disk.** CC extracts a bundle and lets the body reference files on
     * the filesystem; sema core has no filesystem authority of its own, so materializing attachments into a
     * working directory (making `Read`-by-path work) is the DEPLOYMENT's half. What core owns is exactly two
     * faces, both bounded:
     * 1. **disclosure** — each attachment's relative `path` is listed on the skill's `<skills>`-block line
     *    (metadata only, capped like the rest of the block), so the model knows the material exists before
     *    it loads the skill;
     * 2. **delivery** — a `Skill` invoke appends an `## Attachments` section after the body (which is
     *    itself delivered untruncated): each file as `### <path>` + its content, under a SEPARATE total
     *    cap (`SKILL_ATTACHMENTS_MAX_CHARS`, 50k chars — an attachments-face budget; truncation/omission
     *    is always disclosed in-band). Without deployment-side materialization this inline delivery is the
     *    attachment's ONLY reachable face — that is the deliberate minimal shape, not an oversight.
     *
     * `path` is a relative, display-oriented identifier (how the body refers to the file); core never
     * resolves it against a filesystem. `content` carries the SAME trust contract as {@link content}: skill
     * material is CALLER-trusted instructions by design (see the skills module note) — a caller forwarding
     * end-user skills is responsible for vetting attachments exactly like the body.
     */
    files?: Array<{
        path: string;
        content: string;
    }>;
    /**
     * The skill's own DIRECTORY on the machine the tools run on, so the model can reach its bundled material
     * by path instead of searching the workspace. Core does not resolve it, read it, or check that it exists
     * (the brain-outside posture {@link files} states). Core does exactly two textual things with it: the
     * result opens with `Base directory for this skill: <baseDir>`, and both root placeholder spellings
     * (`${SKILL_ROOT}`, `${CLAUDE_PLUGIN_ROOT}`) are substituted for it in the body and in every attachment's
     * content, with `files[].path` then read RELATIVE to it. Absent ⇒ no line, no substitution, a
     * byte-identical result; a placeholder with no directory stays verbatim.
     */
    baseDir?: string;
}
