/**
 * PARITY-SPOT-WORKFLOW B5/F2 (CC pretty.js:449105-449141 + `Pqi` :149631) — the script-persistence seam behind
 * the Workflow tool's `scriptPath`/`name` calling surface. CC persists EVERY invocation's script under the
 * session directory and returns the path in the tool result, so the model iterates by EDITING THE FILE and
 * re-invoking with `{scriptPath}` instead of resending the whole script; `{name}` resolves a saved workflow.
 *
 * Core is deployment-neutral: the tool takes this seam via `RunWorkflowToolDeps.scriptStore` (optional — when
 * absent, `scriptPath`/`name` calls get an honest structured error and inline `script` works as before). The
 * file-backed implementation below is the TOC default (mirrors CC's session-dir posture: dir 0o700 / file
 * 0o600, best-effort persist that never blocks a launch).
 */
/**
 * design/140 §6 1a — a named-registry entry's RESOLVED form: the script source plus the registration's
 * `defaultArgs` layer (the middle tier of the merge chain: call-time args > registered defaultArgs >
 * script-internal fallbacks). ONE return shape: a registry that carries no defaults returns `{ script }`
 * — the bare-string return is RETIRED (RB-482 #9, ruled 2026-08-03), matching {@link
 * WorkflowScriptStore.resolveName}'s contract. A plain-JS store still returning a bare string is refused
 * with a structured migration error at the tool boundary, not read as a resolution.
 */
export interface NamedWorkflowResolution {
    script: string;
    /** Registration-time default args (a JSON value — this is where a control-plane/center下发的默认 lands).
     *  Merged UNDER the call-time args by {@link mergeWorkflowArgs} at tool-resolve time (parse-time snapshot:
     *  the run receives the merged VALUE; nothing re-queries the registry after launch). */
    defaultArgs?: unknown;
    /**
     * CORE-1 — the top-level key a BARE STRING call-time arg normalizes into, so the "裸 string =
     * <key>" ergonomic entry (published by the built-in `discussion` script: a bare string args IS the
     * topic) composes with a registered object `defaultArgs` instead of colliding with it. When a `{name}` call
     * passes a raw string AND this resolution carries an object `defaultArgs`, the tool wraps the string as
     * `{ [stringArgKey]: <string> }` BEFORE the object merge (see {@link normalizeStringArg} / the run-workflow
     * tool's resolve path). Defaults to `"topic"` (the built-in ergonomic contract). Ignored when `defaultArgs`
     * is not a plain object (a bare string then reaches the script verbatim — pre- behavior preserved). */
    stringArgKey?: string;
}
/**
 * design/140 §6 1b — one row of the named-workflow LISTING projection (the LLM-facing consumption face of
 * `meta.whenToUse`). Mirrors the agents-side roster entry (subagent.ts `agentWhenToUseText`/CC `tIl`):
 * `whenToUse` is shown when present, else `description`.
 */
export interface NamedWorkflowListing {
    name: string;
    description?: string;
    whenToUse?: string;
}
export interface WorkflowScriptStore {
    /** B-4 — the CONFORMANCE MARKER for the scope-partitioned contract. Structural
     *  typing would otherwise let a pre-partition adapter (`load(path)`, `persist(runId, script)`)
     *  remain assignable — fewer-parameter functions are compatible in TypeScript — and silently
     *  ignore the scope argument, serving cross-tenant reads while the tool presents the operation as
     *  scope-bounded. A REQUIRED literal field breaks that assignability at compile time; the
     *  run-workflow tool also refuses at runtime when it is absent (plain-JS adapters). */
    readonly scopePartitioned: true;
    /** Persist THIS invocation's resolved script, keyed by its runId. Returns the persisted path (what the tool
     *  reports back to the model). Failures should throw — the tool treats persistence as best-effort.
     *  B-4 (BREAKING): `scope` PARTITIONS per-run scripts — the CC anchor is a per-session directory,
     *  and the port had dropped the axis (one flat directory let a model-supplied scriptPath read another
     *  scope's script). Implementations key storage by scope (the file store uses per-scope subdirs). */
    persist(runId: string, script: string, scope: string): Promise<string> | string;
    /** Read a previously persisted script back. MUST refuse paths outside the store (the argument is
     *  model-supplied — containment is the store's contract, not the tool's).
     *  B-4 (BREAKING): `scope` bounds the read to the CALLER's partition — a path pointing into
     *  another scope's partition must be refused exactly like a path outside the store. */
    load(scriptPath: string, scope: string): Promise<string> | string;
    /** Resolve a SAVED workflow name to its registration (undefined = unknown name). Optional — a deployment
     *  without a named registry simply omits it. RB-482 #9 (ruled 2026-08-03): ONE return form — a
     *  {@link NamedWorkflowResolution} ({ script, defaultArgs? }); the legacy bare-string return is retired. A
     *  deployment entry of the SAME NAME as a built-in workflow SHADOWS the built-in (design/140 §6 1c).
     *  RULING: deliberately NO scope axis here — saved names are a DEPLOYMENT-level registry (the
     *  built-ins' tier), shared across scopes like agent definitions; a multi-tenant deployment that wants
     *  per-tenant registries mounts per-tenant store instances.
     *  CONTRACT (stated 2026-08-16, C-R14): this is a STABLE, SIDE-EFFECT-FREE lookup. Resolving ONE call
     *  may ask it more than once with different spellings of the same slot (a built-in's retired name and
     *  its canonical one), and the tool card probes it independently of the execute path — so an
     *  implementation that counts queries, rate-limits, or mutates state per call is out of contract and
     *  will behave differently depending on how many spellings a name has. */
    resolveName?(name: string): Promise<NamedWorkflowResolution | undefined> | NamedWorkflowResolution | undefined;
    /**
     * design/140 §6 1b — enumerate the registry's SAVED workflows for the listing projection (tool card /
     * roster faces). Optional: a store without a stable name registry omits it (the file store below does —
     * its directory mixes per-run persisted scripts with saved names, so enumeration would advertise every
     * past run as a "named workflow"). NOTE: only a SYNCHRONOUS return reaches the statically-built Workflow
     * tool card; an async store should precompute if it wants card visibility.
     */
    list?(): NamedWorkflowListing[] | Promise<NamedWorkflowListing[]>;
}
/**
 * design/140 §6 1a — the default-args merge: **call-time args > registered defaultArgs** (the script's own
 * internal fallbacks remain the third tier, applied by the script itself). Semantics (locked by test):
 * - both sides plain objects → SHALLOW top-level merge (`{...defaults, ...call}`): a top-level key present in
 *   the call args wins WHOLESALE — nested objects/arrays/scalars are replaced, never deep-merged;
 * - call args absent (`undefined`) → the registered defaults verbatim;
 * - call args a non-object (array / scalar / null) → the call args win wholesale (no structural mixing).
 * Pure value-in/value-out: the caller snapshots the RESULT into the run (parse-time discipline, design/140 §2 —
 * a resume replay never re-queries the registry; a post-launch registry change cannot reach an in-flight run).
 */
export declare function mergeWorkflowArgs(callArgs: unknown, defaultArgs: unknown): unknown;
/**
 * CORE-1 — NORMALIZE a bare-string call-time arg into `{ [key]: <string> }` so the published
 * "裸 string = <key>" ergonomic entry (built-in `discussion`: bare string args IS the topic) COMPOSES
 * with a registered object `defaultArgs` instead of colliding with it.
 *
 * The bug it fixes: {@link mergeWorkflowArgs}'s non-object branch lets a bare string win WHOLESALE — so a
 * named workflow whose registration carries object `defaultArgs` (center 配的 members/rounds/finalizer) had
 * its whole defaults block silently wiped the moment a caller used the ergonomic `{name, args: "<topic>"}`
 * form, and the collab template quietly ran as a generic advocate/skeptic. Wrapping the string here lets the
 * subsequent object merge preserve the defaults AND honor the topic.
 *
 * Applied ONLY when BOTH hold (otherwise return `callArgs` untouched — pre- behavior byte-preserved):
 *  - `callArgs` is a string (the ergonomic form), AND
 *  - `defaultArgs` is a PLAIN OBJECT (there ARE object defaults to merge under; with no/scalar defaults a bare
 *    string must still reach the script verbatim — the built-in's own `raw === "string"` fallback handles it).
 * `key` is the resolution's `stringArgKey` (a registry may declare which key its bare string maps to); the
 * caller passes the built-in default `"topic"` when the resolution omits it.
 */
export declare function normalizeStringArg(callArgs: unknown, defaultArgs: unknown, key?: string): unknown;
/**
 * File-backed {@link WorkflowScriptStore}: per-run scripts land as `<dir>/<scopeDir>/<runId>.js`
 * (B-4: per-scope partition — the CC per-session-dir posture restored on the tenant axis);
 * `resolveName` reads `<dir>/<name>.js` at the ROOT (the deployment-level saved-name tier, see the
 * interface RULING — deliberately outside every scope partition).
 */
export declare function createFileWorkflowScriptStore(dir: string): WorkflowScriptStore;
