import type { RiskClassification, ReleaseDomain } from '@enterprise-skills/core'; /** * Semantic domain agents (Release Governance Architecture §25 Phase 3). * * The three semantic domains — architecture/API compatibility, migration * safety, observability/rollback readiness — get their evidence produced * automatically in the customer's CI (§7 execution model) instead of relying * on a developer's session agent to have committed it. Selection is driven by * the same diff classification the Governor uses (§10 — never run every agent * on every change), execution goes through a customer-supplied agent command * (the runner never picks an agent vendor), and completion is verified the * headless-runner way: an agent that exits 0 without writing valid evidence * is a failure, not a success. Agent output is evidence, never policy (§9). */ export interface SemanticAgentSpec { id: 'api-compat' | 'migration-safety' | 'observability-readiness' | 'code-review' | 'service-resilience'; /** Release-confidence domain this agent's evidence feeds. */ domain: ReleaseDomain; /** Skill-output basename the domain feeder reads (DOMAIN_FEEDERS). */ feeder: string; title: string; } export declare const SEMANTIC_AGENTS: readonly SemanticAgentSpec[]; export interface AgentSelection { run: SemanticAgentSpec[]; skipped: Array<{ agent: SemanticAgentSpec; reason: 'fresh-evidence-present' | 'not-required'; }>; } /** * Classification-driven selection (§10): an agent runs only when the diff * classification requires its domain (or the caller explicitly asked for the * domain) AND that domain already has evidence bound to the commit under review. * `force` re-runs regardless. * * `freshFeeders` is deliberately not "feeders whose file exists": skipping on * mere file PRESENCE meant one committed evidence file suppressed the agent for * every later commit, so the domain looked assessed forever. Existence is not * freshness — the caller resolves the binding (see lib/evidence-binding) and * passes only feeders that hold for this commit. */ export declare function selectSemanticAgents(params: { classification: RiskClassification; freshFeeders: ReadonlySet; explicitDomains?: ReleaseDomain[]; force?: boolean; }): AgentSelection; export interface AgentPromptContext { repository: string | null; base: string; headSha: string; changedFiles: string[]; } /** * The per-domain CI prompt. Deliberately self-contained: the agent gets the * diff coordinates, the domain checklist, the exact evidence contract * (§8 ingestion v1.1 skill-output shape), and hard limits. Honesty is part of * the contract — an agent that cannot assess must record status failed * (fail-closed), never a fabricated pass. */ export declare function buildSemanticAgentPrompt(agent: SemanticAgentSpec, ctx: AgentPromptContext): string; export interface SkillOutputValidation { ok: boolean; errors: string[]; } /** Agent-written evidence is untrusted input — cap it like the license client caps responses. */ /** * Cap on a single evidence file. Exported because the Governor's own read path * (`release-score.ts`) needs the SAME bound: this cap protected the semantic-agent * path while `es govern` parsed the identical untrusted files uncapped, which is * the half that actually gates merges. */ export declare const MAX_EVIDENCE_BYTES: number; /** * Boundary validation of agent-produced evidence (untrusted input): the file * must parse, carry a completed/failed status, and every finding must have a * recognized severity and a description. Anything else is refused — a * malformed evidence file must fail the run, not slide through as * "unverified" later. * * With `expectedCommit`, the file must ALSO declare the commit it was produced * against (spec §8). The runner never stamps this itself: a binding the reader * fabricates is the exact defect this closes, so an agent that omits or * mistypes it fails its run rather than emitting evidence that would later be * read as fresh forever. */ export declare function validateSkillOutputFile(filePath: string, opts?: { expectedCommit?: string; }): SkillOutputValidation; /** * Containment check (§7): everything the agent touched beyond what was * already dirty must live under .project-ai/skill-outputs/. Any other * mutation fails the run. */ export declare function findContainmentViolations(beforePorcelain: string, afterPorcelain: string): string[]; export interface AgentExecutionContext { agent: SemanticAgentSpec; prompt: string; } export interface AgentExecutionResult { ok: boolean; detail: string; /** Best-effort usage from the agent command's output (spec §21 cost ledger). */ usage?: import('./agent-costs').AgentUsage; durationMs?: number; } export type SemanticAgentExecutor = (ctx: AgentExecutionContext) => Promise; export interface AgentRunReport { agent: SemanticAgentSpec; outcome: 'produced' | 'failed'; detail: string; usage?: import('./agent-costs').AgentUsage; durationMs?: number; } export interface RunSemanticAgentsOptions { agents: SemanticAgentSpec[]; promptContext: AgentPromptContext; outputsDir: string; /** Bind-check produced evidence against this commit (defaults to the prompt's head). */ expectedCommit?: string; executor: SemanticAgentExecutor; /** Returns `git status --porcelain` output; injectable for tests. */ porcelainStatus: () => string; log?: (line: string) => void; } export interface RunSemanticAgentsResult { ok: boolean; reports: AgentRunReport[]; } /** * Execute the selected agents sequentially, verifying each one the * headless-runner way: executor success without a valid evidence file is a * failure, and any write outside skill-outputs/ is a containment failure. * Fail-closed: the first failure stops the run (the Governor would fail on * the missing domain anyway; stopping keeps the failure attributable). */ export declare function runSemanticAgents(options: RunSemanticAgentsOptions): Promise; //# sourceMappingURL=semantic-agents.d.ts.map