import type { GoalSpec, MetricSpec } from "./goal-parser.js"; import { type CycleStatus } from "./tracker.js"; /** * v0.4 — evaluator. * * Per docs/plan/v0.4-autonomous-engine.md §4.2: * * v0.3 git-snapshot.commit (pre-cycle) * ↓ * PM runs pipeline via Task tool * ↓ * evaluator.measure(metric, provenance) → keep|discard * ↓ keep: new commit (metric=value), append results row * ↓ discard: git-snapshot.revert(pre-cycle), append discard row (commit="-") * * The evaluator does NOT itself reach into the model — it accepts pre-measured * values from the goal-runner (which delegates measurement to specialists via * the Task tool, or to a deterministic measurer when one exists for this * metric's source). * * `MetricMeasurer` is the injection point: production passes a measurer that * reads `metric.source` from disk and applies `metric.formula`. Tests pass a * fake that returns scripted values. */ export interface MetricMeasurement { spec: MetricSpec; value: number; /** Composed provenance string for the results row. */ provenance: string; } export interface MetricMeasurer { measure(spec: MetricSpec, ctx: MeasureContext): Promise; } export interface MeasureContext { workspace: string; orgSlug: string; goalId: string; /** Optional pre-cycle commit SHA (for verify replay). */ commitSha?: string; } export interface CycleEvaluationInput { workspace: string; orgSlug: string; goalId: string; goal: GoalSpec; cycle: number; /** SHA of the pre-cycle snapshot (created by goal-runner before stages ran). */ preCycleCommit: string; /** spawn events that produced this cycle's artifacts. */ taskIds: string[]; /** Cycle wall-clock when stages completed. ISO. */ timestamp: string; /** Short label written into results.tsv `description` and commit msg. */ description: string; } export interface CycleEvaluationOutput { status: CycleStatus; measurements: MetricMeasurement[]; /** SHA of the keep commit (status=keep) OR the snapshot HEAD after revert * (status=discard). */ postCycleCommit: string; /** Composite score (sum over normalized metric contributions). 0 when discarded. */ compositeScore: number; /** Did this cycle bump the `_best.json`? */ isNewBest: boolean; } /** * Run measurement, decide keep/discard, commit/revert, append results.tsv. * * Decision rule (per metric): * maximize → keep iff value >= threshold * minimize → keep iff value <= threshold * Cycle is `keep` iff ALL metrics pass; `discard` otherwise. */ export declare function evaluateCycle(input: CycleEvaluationInput, measurer: MetricMeasurer): Promise; export declare function metricPasses(spec: MetricSpec, value: number): boolean; /** * Goal-runner calls this before invoking the pipeline for a cycle. Returns * the commit SHA that evaluator will reference for keep/discard branching. */ export declare function takePreCycleSnapshot(workspace: string, orgSlug: string, goalId: string, cycle: number): string;