import { type NodeMeta, type Mode, type Lifecycle, type LaunchSpec, type ManagedWorktree, type HumanWorkTarget, type PrivateForkPhase, type PrivateForkRecipe } from '../canvas/index.js'; /** Explicitly set the resolved install id. crtrd calls this once at boot, * immediately after `resolveInstallId()` — see crtrd.ts — so a provisioning * mismatch fails the daemon loudly at STARTUP rather than lazily on first * spawn. Exported for the daemon only; every other caller gets it lazily via * `installId()` below. */ export declare function setInstallId(id: string): void; /** Raw time-sortable + random id shape — used for non-node opaque ids such as * focus ids (`f-…`) that are NOT canvas node identities and keep their * historical 2-segment shape (unstamped by the canvas-install id). */ export declare function newJobId(): string; /** Generate a NODE id: `--` (3 segments) — the * canvas-install id stamped onto the historical job-id shape, so every * minted node id is a globally-unique NAME that also names the canvas that * minted it (see the unified-chat/addressing design's "ID scheme"). crtrd is * the sole node minter. */ export declare function newNodeId(): string; /** Thrown when a caller-specified `--node-id` (or its API twin `node_id`) * already names a live node. Distinguishable from every other spawn failure * so a caller can treat it as "attach instead of create" per the unified * chat/addressing design's ensure semantics — never overwrite, never * double-spawn. Mapped to HTTP 409 in `src/daemon/api/map.ts`. */ export declare class NodeIdConflictError extends Error { readonly nodeId: string; constructor(nodeId: string); } /** Best-effort preflight for a caller-supplied `--node-id`, run BEFORE any * worktree is allocated for it (`spawnChild` in spawn.ts) — so a malformed or * already-taken id fails before there is anything to leak/clean up. Format * validation here is authoritative (an id that fails it can never become * valid); the duplicate check is advisory only — a concurrent create can * still win the race between this check and the synchronous check-then- * create below, which remains the SOLE authoritative decider. */ export declare function preflightNodeId(nodeId: string): void; /** The root of a node's spine: walk the `parent` column up to `parent == null`. * Cycle-guarded (parents must not cycle, but never loop forever). Lives in the * node layer (not placement) so the env-builder and placement both reach it * without an import cycle — `CRTR_SUBTREE` is emitted as `rootOfSpine(nodeId)` * at every launch site. */ export declare function rootOfSpine(nodeId: string): string; export interface NodeContext { nodeId: string | null; kind: string | null; mode: Mode | null; } /** Read the current node's identity from the environment. A spawned pi process * runs with CRTR_NODE_ID set; its own `crtr` invocations spawn children under * it by reading CRTR_NODE_ID as the parent. */ export declare function currentNodeContext(): NodeContext; /** The env injected into a node's pi process. Self-gating extensions read * CRTR_KIND/CRTR_MODE to flip behavior on polymorph without a respawn; the * feed/inbox machinery reads CRTR_NODE_ID. */ export declare function nodeEnv(meta: NodeMeta): Record; export interface SpawnNodeOpts { kind: string; mode?: Mode; lifecycle?: Lifecycle; cwd: string; name?: string; /** Editor-label handle (2-4 word kebab-case) for the node's first prompt. */ description?: string; /** Parent node id. Omit for a user-opened root. */ parent?: string | null; /** Who spawned me (the `spawned_by` provenance edge), when it differs from * `parent` — e.g. an independent root (parent=null) still records its * spawner. Defaults to `parent`. */ spawnedBy?: string | null; /** Fork provenance — the `--fork-from` reference this node was forked from (a * node id / session path / pi session uuid). Persisted to `meta.fork_from` so * the boot intro can re-assert this node's OWN identity over the source's * copied-in conversation. Omit for a fresh node. */ forkFrom?: string | null; /** Immutable private-human-work binding. Omit for every ordinary node. */ humanWorkTarget?: HumanWorkTarget | null; /** Explicit private-fork birth phase. Set with `privateForkRecipe` only for a * lifecycle-owned human-work child. */ privateForkPhase?: PrivateForkPhase | null; /** Immutable one-shot kickoff consumed only while `privateForkPhase` is * `fork_pending`; the recipe remains persisted after session bind for audit. */ privateForkRecipe?: PrivateForkRecipe | null; /** New subscriptions this node opens default to passive when true. */ passiveDefault?: boolean; /** Resolved pi launch recipe (from resolve(kind,mode)). */ launch?: LaunchSpec; /** Caller-pinned model tier (ultra/strong/medium/light) that overrides the * persona default. Persisted to `meta.model_override` so polymorphs preserve * it. Omit to use the persona default. */ modelOverride?: string | null; /** The profile-directory id (`-`) this node runs under; null only * for historical root/no-profile nodes. Written to `meta.profile_id` and the * row, and mirrored into the pi process env as `CRTR_PROFILE_ID` by * `nodeEnv` — the runtime → resolver seam every downstream memory/gate * consumer reads. Callers resolve/validate the operand (via * `loadProfileManifest`) before it reaches here; this layer just persists the * already-resolved id. */ profile_id?: string | null; /** Managed worktree already created for this node, if any. */ managedWorktree?: ManagedWorktree; /** Keep a private human-work child inert until its request has been rechecked * and `reviveNode()` authorizes its one lifecycle-owned launch. */ initialStatus?: 'canceled'; /** Override the generated id — either an internally pre-allocated id * (worktree naming, private-fork births; always valid+fresh) or an * external caller's explicit id (`--node-id`), which is format-validated * and duplicate-rejected (`NodeIdConflictError`) here. */ nodeId?: string; } /** Create a node on the canvas and wire its spawn-time edges. * * For a child (parent given): the parent auto-subscribes ACTIVE to the child * (so it's woken when the child finishes), and a spawned_by audit edge is * recorded. For a root (no parent): no edges, resident by default. */ export declare function spawnNode(opts: SpawnNodeOpts): NodeMeta;