/** * Canonical spawn prompt builder — T882. * * Produces fully-resolved, self-contained spawn prompts for subagents spawned * via `cleo orchestrate spawn `. The resulting prompt is 100% * copy-pastable into any LLM runtime (Claude, GPT-4, Gemini, open-source) and * embeds everything the subagent needs to execute without re-resolving * protocol content. * * ## Tier system * * | Tier | Content | * |------|---------| * | 0 | Minimal: task metadata + return-format contract + evidence-gate commands | * | 1 | Standard (DEFAULT): tier 0 + CLEO-INJECTION.md embed + stage-specific guidance + quality-gate commands + absolute paths + session linkage | * | 2 | Full: tier 1 + ct-cleo + ct-orchestrator skill excerpts + SUBAGENT-PROTOCOL-BLOCK + anti-pattern reference | * * ## Protocol phases (RCASD-IVTR+C) * * Ten phases get stage-specific guidance blocks (research, consensus, * architecture_decision, specification, decomposition, implementation, * validation, testing, release, contribution). Every phase produces the * same outer prompt structure — only the `Stage-Specific Guidance` section * varies. * * ## Consolidation * * Replaces the inlined `buildSpawnPrompt` helper that previously lived in * `packages/core/src/orchestration/index.ts`. `prepareSpawn` delegates here. * `prepareSpawnContext` in `packages/core/src/skills/dispatch.ts` is a * skill-auto-dispatch helper (different role — selects WHICH skill to use) * and is not a spawn prompt builder; callers can compose it with * {@link buildSpawnPrompt} but should not confuse the two. * * @task T882 * @task T883 * @task T884 * @task T885 */ import type { Task } from '@cleocode/contracts'; /** * Glob patterns always excluded from the worktree spawn-clone. * * These patterns are applied via sparse-checkout negation after worktree * creation. The intent is to keep each spawned worktree lean by excluding * heavyweight or task-irrelevant artefacts that would otherwise grow * linearly with the number of tasks in the project. * * `.gitnexus/` contains large vector/graph indices that agents never need * inside a worktree (queries route through the primary project root). * * Per T9337 / Council 20260515T211404Z, the per-task `scripts/verify-*.mjs` * exclusion was removed alongside the verifier substrate itself. Workers * attest completion via ADR-051 evidence atoms, not per-task scripts. * * @task T9226 * @task T9337 */ export declare const SPAWN_CLONE_EXCLUDE_PATTERNS: readonly string[]; /** * Metadata for a single task document attachment to be embedded in the spawn prompt. * * Passed via {@link BuildSpawnPromptInput.docAttachments} by the * {@link composeSpawnPayload} caller after auto-fetching via `blobList`. * Text-based attachments (`text/plain`, `text/markdown`) have their `textContent` * inlined so the agent can read them without additional CLI calls. All others * are listed by name so the agent knows they exist and can use * `cleo docs fetch` if needed. * * @task T1614 — spawn auto-attaches docs to subagent task */ export interface TaskDocAttachment { /** User-visible attachment name (e.g. `"design.md"`). */ readonly name: string; /** Lowercase hex SHA-256 digest (64 chars). Content-address. */ readonly sha256: string; /** Byte size of the stored blob. */ readonly sizeBytes: number; /** IANA MIME type, when known. */ readonly mimeType?: string; /** * Inline text content for text-based attachments (text/plain, text/markdown). * * Populated by {@link composeSpawnPayload} for small text blobs (≤ {@link INLINE_TEXT_SIZE_LIMIT_BYTES}). * Larger blobs or non-text MIME types leave this field `undefined` — the * agent must call `cleo docs fetch` to retrieve them. */ readonly textContent?: string; } /** * Inline size limit for text attachments (bytes). * * Blobs at or below this size that carry a text MIME type are inlined directly * into the `## Task Documents` section. Larger blobs are listed with a * `cleo docs fetch` pointer so the agent can retrieve them on-demand. * * Exported so {@link composeSpawnPayload} can apply the same threshold when * deciding whether to populate {@link TaskDocAttachment.textContent}. * * @task T1614 */ export declare const INLINE_TEXT_SIZE_LIMIT_BYTES: number; /** Protocol tiers per ADR-051 / T882 spawn contract. */ export type SpawnTier = 0 | 1 | 2; /** Default tier when none specified. */ export declare const DEFAULT_SPAWN_TIER: SpawnTier; /** * Canonical set of RCASD-IVTR+C protocol phases. * * The orchestrator's `autoDispatch` may emit any of these strings; the * `architecture_decision`, `validation`, and `testing` phases are available * here even if `autoDispatch` falls back to `implementation` / `consensus`. */ export type SpawnProtocolPhase = 'research' | 'consensus' | 'architecture_decision' | 'specification' | 'decomposition' | 'implementation' | 'validation' | 'testing' | 'release' | 'contribution'; /** All known protocol phases (for iteration in tests). */ export declare const ALL_SPAWN_PROTOCOL_PHASES: readonly SpawnProtocolPhase[]; /** * CONDUIT subscription configuration injected into tier-1 / tier-2 spawn prompts. * * When present, the spawn prompt includes a `## CONDUIT Subscription` section * that names the wave topic and coordination topic the agent should subscribe to. * * @see T1252 CONDUIT A2A */ export interface ConduitSubscriptionConfig { /** Parent epic ID, e.g. `"T1149"`. */ epicId: string; /** Wave number (integer), e.g. `2`. */ waveId: number; /** Spawned agent peer ID, e.g. `"cleo-lead-2"`. */ peerId: string; } /** * Input to {@link buildSpawnPrompt}. * * Absolute paths (rcasd dir, test-runs dir, output dir) are resolved by the * caller against the orchestrator's project root so the subagent never has * to guess. Manifest storage is SQLite (`pipeline_manifest`) — not a file * path (ADR-027 §6.2, T1096). The session id is threaded from `session.status` so the subagent * logs every mutation against the orchestrator's active session. */ export interface BuildSpawnPromptInput { /** Full task record as loaded from the store. */ task: Task; /** Dispatched protocol phase (auto-selected or overridden). */ protocol: SpawnProtocolPhase | string; /** Tier 0/1/2 — defaults to {@link DEFAULT_SPAWN_TIER}. */ tier?: SpawnTier; /** Absolute project root. */ projectRoot: string; /** * Per-agent session id for the spawned task, if known. * * T11343: this is the spawned agent's OWN session (allocated by * {@link allocateSpawnSession}), not the orchestrator's. Injected into the * `## Worktree Setup` export block as `CLEO_SESSION_ID` so the agent's * `cleo` calls resolve its own session via env-first resolution. Also * rendered in the `## Session Linkage` block. */ sessionId?: string | null; /** * Per-agent identity handle for the spawned task (T11343). * * Injected into the `## Worktree Setup` export block as `CLEO_AGENT_ID` so * audit rows / memory observations are attributed to the spawned agent. * Defaults to a deterministic handle derived from the task id when absent. */ agentId?: string | null; /** Current date (ISO yyyy-mm-dd). Defaults to today. */ date?: string; /** * Harness context the prompt is being rendered for. * * Purely informational inside this builder — the active * {@link BuildSpawnPromptInput.skipCleoInjectionEmbed} flag is what * actually gates the embed. The harness hint is recorded so callers can * surface it in telemetry / manifest envelopes. * * @task T889 / T893 / W3-2 */ harnessHint?: 'claude-code' | 'generic' | 'bare'; /** * When `true`, the tier-1 / tier-2 CLEO-INJECTION.md embed is replaced * with a one-line pointer back to the canonical template path. Keeps the * prompt self-contained for bare/generic harnesses while letting * Claude-Code harnesses (which auto-load the injection via `AGENTS.md`) * skip the ~9KB duplicate. * * @task T889 / T893 / W3-2 */ skipCleoInjectionEmbed?: boolean; /** * Absolute path to the pre-provisioned worktree for this task. * * When provided, a `## Worktree Setup (REQUIRED)` section is emitted in * the prompt body that names the worktree path, the branch, and the * context-isolation constraint. When absent (e.g. `--no-worktree` was * passed at spawn time), the section is omitted entirely. * * The path is also injected as `{{ worktreePath }}` into the token map so * stage-guidance templates can reference it without hard-coding. * * @task T1140 — worktree-by-default spawn prompt */ worktreePath?: string; /** * Git branch name for the worktree (e.g. `task/T1234`). * * Only used when {@link worktreePath} is set. Defaults to `task/`. * * @task T1140 */ worktreeBranch?: string; /** * CONDUIT A2A subscription configuration. * * When provided, a `## CONDUIT Subscription` section is injected into * tier-1 and tier-2 prompts, giving the spawned agent its wave topic and * coordination topic. Omitted for tier-0 prompts (minimal content) and * when not set. * * @task T1252 CONDUIT A2A */ conduitSubscription?: ConduitSubscriptionConfig; /** * Compact orchestration dashboard summary. * * When provided and `tier >= 1`, a small one-line context block is injected * so leads/orchestrators can see queue pressure, merge throughput, bypass * pressure, and active worktree count without bloating worker prompts. * * @task T10464 */ dashboardSummary?: string; /** * Memory retrieval bundle from `buildRetrievalBundle`. * * When provided and `tier >= 1`, a `## PSYCHE-MEMORY` section is injected * into the spawn prompt (between CONDUIT and File Paths blocks), carrying * the user profile, peer memory, and session narrative slices. * * This is the M4 injection primitive and M1 parity requirement (T1260 PSYCHE E3). * Best-effort: callers should not crash if the bundle is empty. * * @task T1260 PSYCHE E3 */ retrievalBundle?: import('@cleocode/contracts').RetrievalBundle; /** * Tier-2 attention digest lines for the PSYCHE-MEMORY block (T11374). * * Pre-rendered, budget-bounded markdown lines from * `renderAttentionDigestLines(buildAttentionDigest(...))` for the spawned * task's scope. Injected into the `## PSYCHE-MEMORY` block alongside the * retrieval bundle when `tier >= 1`. Empty/absent ⇒ nothing is injected (the * empty-attention contract). * * @task T11374 * @epic T11288 */ attentionDigestLines?: readonly string[]; /** * Task document attachments to embed in the spawn prompt. * * Auto-fetched by {@link composeSpawnPayload} via `blobList` for the task ID. * When non-empty, a `## Task Documents` section is injected between File Paths * and Stage-Specific Guidance. Text-based attachments (≤ 32 KB) have their * content inlined so the agent does not need to call `cleo docs fetch` for them. * Binary or large attachments are listed by name only. * * When empty or absent, the section is omitted entirely — no bloat for tasks * with no attachments. * * @task T1614 — spawn auto-attaches docs to subagent task */ docAttachments?: readonly TaskDocAttachment[]; /** * Agent role for tier-specific skill selection. * * Used by {@link buildTierSkillExcerpts} to determine which skill excerpts to * embed. At tier 1 `'lead'` loads ct-cleo + ct-lead; at tier 2 * `'orchestrator'` loads ct-cleo + ct-orchestrator (unchanged). For other * combinations no skill excerpts are emitted. * * Optional — defaults to `'worker'` (no skill excerpts) when absent. * * @task T9213 — auto-load ct-lead at tier-1 lead spawns */ role?: 'orchestrator' | 'lead' | 'worker'; /** * Glob patterns excluded from the worktree via spawn-clone-exclude filter * (T9226). When set, a `## Worktree Scope (spawn-clone-exclude)` section * is injected so the agent understands why certain files are absent from * its working tree. The canonical default list is * {@link SPAWN_CLONE_EXCLUDE_PATTERNS}. * * Omit when no exclusions were applied (e.g. `--no-worktree` was passed). * * @task T9226 */ spawnCloneExclude?: readonly string[]; /** * ORC-006 worker budget constraints injected into the spawn prompt. * * When present, a `## Worker Budget Constraints` section is emitted so the * agent knows its tool-call budget and allowed-files ACL before it starts. * The harness enforces `max_tool_calls` mechanically; the prompt injection * ensures the agent halts gracefully rather than crashing on budget * exhaustion. * * `allowedFiles` is derived from the task's `files` field by the caller * (orchestrate engine) and represents the scoped ACL for this worker. * * @task T1656 — max-tool-call budget enforcement * @task T1657 — worker scope boundary enforcement (allowed-files ACL) */ workerConstraints?: { /** Maximum tool calls before `E_TOOL_BUDGET_EXCEEDED` is emitted. */ max_tool_calls?: number; /** Allowed-files ACL derived from task.files. */ allowedFiles?: readonly string[]; }; } /** * Output of {@link buildSpawnPrompt}. * * `prompt` is the fully-resolved text. `unresolvedTokens` is non-empty only * if a `{{TOKEN}}` or `@missing.md` reference could not be resolved — callers * should surface this as a validation error so no unresolved prompt ships. */ export interface BuildSpawnPromptResult { prompt: string; tier: SpawnTier; protocol: string; unresolvedTokens: string[]; /** Token kv map used to resolve the prompt (for diagnostics/tests). */ tokens: Record; } /** * Reset the template content cache. * * Intended for tests — every production call uses the memoized content so * that tier 2 prompt assembly does not re-read the filesystem per call. */ export declare function resetSpawnPromptCache(): void; /** * Build tier-specific skill excerpts for spawn prompts. * * Routing: * - tier=1, role='lead' → ct-cleo + ct-lead * - tier=2, role='orchestrator' → ct-cleo + ct-orchestrator + subagent protocol block (legacy behavior) * - all other combinations → empty string (no excerpts) * * @param tier - Spawn tier (0, 1, or 2). * @param role - Agent role string ('orchestrator', 'lead', 'worker', or any string). * @param projectRoot - Absolute path to the project root. * @returns Markdown skill excerpt block ready to embed in a spawn prompt. * * @task T9213 — generalize tier-specific skill loading */ export declare function buildTierSkillExcerpts(tier: number, role: string, projectRoot: string): string; /** * @deprecated Use {@link buildTierSkillExcerpts}(2, 'orchestrator', projectRoot) instead. * Kept for backward compatibility. */ export declare function buildTier2SkillExcerpts(projectRoot: string): string; /** * Build a fully-resolved, self-contained spawn prompt. * * The returned prompt is copy-pastable into any LLM runtime and contains * everything the subagent needs to execute, verify, and close the task * without re-resolving protocol content. * * @see {@link BuildSpawnPromptInput} for input shape. * @see {@link BuildSpawnPromptResult} for output shape including unresolved-token diagnostics. */ export declare function buildSpawnPrompt(input: BuildSpawnPromptInput): BuildSpawnPromptResult; /** * Resolve `{{TOKEN}}` placeholders in a prompt string. * * Unknown tokens are left as-is and reported via `unresolved`. `@path.md` * references are checked separately — if the file exists on disk the * reference is considered resolved; otherwise it is reported. * * Exported for reuse and testing. */ export declare function resolvePromptTokens(prompt: string, context: Record): { resolved: string; unresolved: string[]; }; /** * Slugify a title into a URL-safe topic slug. * * Delegates normalization to {@link ../docs/slug-normalize.normalizeSlug} * (T11180 SSoT), then truncates to 60 characters for filesystem safety. * The truncation is topic-specific and NOT part of the canonical doc-slug * normalization — document slugs have no length cap. * * Exported for reuse by the orchestrate engine (spawn filename generation). */ export declare function slugify(title: string): string; //# sourceMappingURL=spawn-prompt.d.ts.map