/** * `cleo done` / `cleo verify --auto` — record every required gate in one write. * * {@link recordTaskDone} turns the read-only plan from * {@link deriveTaskEvidence} into recorded gates, in a fixed order that keeps * every slow step OUTSIDE the task write transaction: * * 1. plan — change set, gate evidence, AC links, blockers (git and gh only); * 2. tools — `lint` and `typecheck` in parallel, then `test`, each through the * ADR-061 resolver and cache (`runToolCached`, under its global semaphore * and memory caps); a cached result is reused, a failure stops here; * 3. typed gates — executed once by `previewTaskGates` (which caches each * pass, T12621) ONLY with `--run-typed`; since T13521 (owner decision) * `cleo done` otherwise executes no typed gate command; a failure stops here; * 4. write — ONE `validateGateVerify` call with per-gate evidence * (`gateEvidence`), which parses and validates every atom through the * existing `parseEvidence` → `validateAtom` → gate minimum → * `checkTaskEvidenceContext` path, serves the typed gates from the cache * (cache-only by default; a linked gate with no cached pass refuses with * `E_GATE_NOT_CACHED`), and persists all gates in a single transaction. * * Tool atoms re-enter `validateAtom` at step 4, where they hit the cache entry * step 2 wrote — the same key, because the tools ran in the same execution * root the validator resolves. That is why a plan whose change set lives in the * task's worktree refuses to run from the main checkout: the validator would * measure the wrong tree. * * There is no override: `CLEO_OWNER_OVERRIDE` is refused by the multi-gate * write and stays a single-gate `cleo verify` path. Completion is the caller's * next step (`cleo done` dispatches `tasks.complete`, unchanged). * * Spec: `verify-streamlined-design` §3.2 steps 3-7 and §4. * * @task T12625 */ import type { DoneRecordResult, VerificationGate } from '@cleocode/contracts'; import { type EngineResult } from '../engine-result.js'; import { type DeriveTaskEvidenceOptions } from './done-plan.js'; /** A tool run as `recordTaskDone` needs it; injectable for tests. */ export type DoneToolRunner = (tool: string, storeRoot: string, executionRoot: string) => Promise<{ exitCode: number | null; cacheHit: boolean; durationMs: number; timedOut: boolean; tail: string; /** * Why the run is a kill, not a result (T13013): the `E_EVIDENCE_TOOL_KILLED` * message, set when it was killed by a signal or for resources. */ killed?: string; }>; /** Typed-gate execution before the write; injectable for tests. */ export type DoneTypedGateRunner = (storeRoot: string, taskId: string) => Promise<{ gateCount: number; passed: boolean; failing: string[]; }>; /** The single multi-gate write; injectable for tests. */ export type DoneGateWriter = (storeRoot: string, params: { taskId: string; gateEvidence: Partial>; /** Execute uncached typed gates in the write (`--run-typed` with the cache off). */ runTyped?: boolean; /** `--shared-evidence`: acknowledge an atom reused across >3 tasks (T14072). */ sharedEvidence?: boolean; sessionId?: string; agent?: string; }) => Promise>; /** Options for {@link recordTaskDone}. */ export interface RecordTaskDoneOptions extends DeriveTaskEvidenceOptions { /** Agent recorded as the gate author. */ agent?: string; /** Session for the audit trail; defaults to the caller's bound session. */ sessionId?: string; /** Injectable slow steps (tests assert their order). */ steps?: { runTool?: DoneToolRunner; runTypedGates?: DoneTypedGateRunner; write?: DoneGateWriter; }; /** * `cleo done --if-match`: the task version (`updatedAt`) the caller read. * Checked before anything is recorded — once on entry and again right * before the gate write — and a mismatch returns `E_CONFLICT` with nothing * written. Recording the gates advances the version, so the completion that * follows uses its own post-record read, never this value. A single-task * guard: {@link recordTasksDone} refuses it. * * @task T12503 */ expectedUpdatedAt?: string; /** * `cleo done --run-typed` (T13521): execute the task's typed gates (via * `previewTaskGates`, which caches each pass) before the write. Without it * `cleo done` executes no typed gate command: the write reads passes cached * by `cleo verify --run` and refuses a linked gate that has none. */ runTyped?: boolean; /** * `cleo done --shared-evidence` (T14072): acknowledge that an evidence atom * (`ci:`, `pr:`) is applied to more than three tasks in the session, * exactly as `cleo verify --shared-evidence` does. Without it the write warns * `W_EVIDENCE_AUDIT_MISS`, or refuses under `CLEO_STRICT_EVIDENCE=1`. */ sharedEvidence?: boolean; } /** * Default tool runner: resolve through ADR-061 and run through its cache. * * @internal Exported for tests only. */ export declare const defaultRunTool: DoneToolRunner; /** * Record every required gate a task lacks, in one write, from derived * evidence. Does not complete the task. * * @param taskId - Task to record. * @param opts - Planner options (`satisfies`, `prNumber`, roots) plus author, * session and injectable steps. * @returns The recorded gates, or `E_DONE_BLOCKED` with one next step and * the original cause in `details.cause`. * @example * ```ts * const r = await recordTaskDone('T123', { satisfies: 'all' }); * if (!r.success) console.error(r.error.fix); * ``` * @task T12625 */ export declare function recordTaskDone(taskId: string, opts?: RecordTaskDoneOptions): Promise>; /** * A tool runner shared by a batch: each (tool, execution root) pair runs once * and every later caller gets the same outcome. Keyed on the root as well as * the tool — two tasks whose work lives in different trees must each be * measured in their own tree. * * @param base - The runner that actually executes. * @returns A memoising runner. * @task T12628 */ export declare function sharedToolRunner(base: DoneToolRunner): DoneToolRunner; /** One task's outcome in a batch close. */ export interface BatchDoneEntry { /** Task the entry is for. */ taskId: string; /** Its record result, or its `E_DONE_BLOCKED`. */ result: EngineResult; } /** * Close several tasks shipped by one PR (T12628): each task is planned and * recorded on its own, and one task's blocker never stops the others. The * tools run once per execution root for the whole batch — every task shares * one memoised runner — and each task still gets its own validated write. * Shared evidence is NOT pre-acknowledged: the ADR-059 warning fires as for * any other reuse. * * @param taskIds - Tasks to record, in order. * @param opts - Shared options (`prNumber`, `satisfies`, roots, author, steps). * @returns One entry per task, in the given order. * @throws {CleoError} `ExitCode.INVALID_INPUT` when `expectedUpdatedAt` is set * for more than one task (T12503). * @example * ```ts * const entries = await recordTasksDone(['T1', 'T2', 'T3'], { prNumber: 42 }); * ``` * @task T12628 */ export declare function recordTasksDone(taskIds: readonly string[], opts?: RecordTaskDoneOptions): Promise; //# sourceMappingURL=done-record.d.ts.map