/** * Fresh advice with journal intent → adapter → completion. * * - target_attempt = task.attempt + 1 is part of identity (not consumed here). * - Does NOT increment execution attempt (launch does). * - Runtime-parses adapter output: short|long + 64-hex notes_digest only. * - Failed completion replays as failure forever for that identity. */ import { type RolePolicyConfig } from "../domain/role-policy.js"; import { type GithubIssueAssignmentSnapshot } from "./assignment.js"; import type { TaskAdviceEvidence } from "./loop-decision.js"; import type { Clock, KernelPaths } from "./types.js"; export interface AdviceAdapterRequest { readonly task_id: string; readonly target_attempt: number; readonly task_version: number; readonly engine: "codex"; readonly model: string; readonly source_digest: string | null; readonly policy_digest: string; readonly goal_version: number; readonly assignment: AdviceAssignment; /** Prior failure lineage — required for target_attempt >= 2; null on attempt 1. */ readonly prior_result_lineage_operation_id: string | null; readonly prior_result_lineage_digest: string | null; } export type AdviceAssignment = Readonly<{ readonly kind: "single_goal"; readonly goal: string; readonly source_digest: string; }> | Readonly<{ readonly kind: "github_issue"; readonly repository: string; readonly issue: GithubIssueAssignmentSnapshot; }>; export type AdviceAdapterResult = { readonly ok: true; readonly recommendation: "short" | "long"; readonly notes_digest: string; } | { readonly ok: false; readonly reason: string; readonly ambiguous?: boolean; }; export interface AdviceAdapter { readonly advise: (request: AdviceAdapterRequest) => unknown; } export interface FreshAdviceResult { readonly ok: boolean; readonly operation_id: string; readonly target_attempt: number; readonly task_attempt: number; readonly advice_digest: string | null; readonly reason?: string; readonly reused: boolean; readonly advisor_engine: "codex"; readonly advisor_model: string; readonly policy_digest: string; readonly recommendation: "short" | "long" | null; } export type CurrentAdviceResolution = TaskAdviceEvidence; /** * Identity: target_attempt + source (task revision) + goal + policy. * Same target attempt reuses one completion; next attempt mints a new identity. * Canonical key: computeAdviceIdentityKey (dispatch-identity) — no local fallback. */ export declare function adviceIntentOpId(identityKey: string): string; export declare function adviceCompleteOpId(identityKey: string): string; /** * Resolve the one advice completion valid for the task's next attempt. * * This is a read-only journal replay: it does not acquire the mutating kernel * lock, repair projections, append evidence, or contact the advice adapter. * The active run namespace, run, task, and operation evidence all come from * journal authority. */ export declare function resolveCurrentAdvice(input: { readonly paths: KernelPaths; readonly taskId: string; readonly rolePolicy: RolePolicyConfig; }): CurrentAdviceResolution; /** Runtime-parse adapter output; never persist raw secrets. */ export declare function parseAdviceAdapterOutput(raw: unknown): AdviceAdapterResult; /** * Request advice for the next target attempt of a task. * Policy/model are factory-bound; callers do not supply them. */ export declare function requestFreshAdvice(input: { readonly paths: KernelPaths; readonly clock: Clock; readonly expectedRunId?: string; readonly expectedRunVersion?: number; readonly taskId: string; readonly expectedTaskVersion: number; readonly expectedSourceDigest: string; readonly adapter: AdviceAdapter; /** Factory-snapshot policy — required; no downstream default fallback. */ readonly rolePolicy: RolePolicyConfig; }): FreshAdviceResult;