From 5373c8281075131c7dbbc17e7999d4116ffa3f55 Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Wed, 15 Jul 2026 10:12:36 -0600 Subject: [PATCH] refactor(agent-interface): collapse candidate contracts --- .changeset/clean-candidate-contract.md | 5 + .../agent-candidate-artifact-schema.test.ts | 8 +- .../src/agent-candidate-artifact-schema.ts | 2 - .../src/agent-candidate-compat.test.ts | 93 --- .../src/agent-candidate-compat.ts | 701 ------------------ ...nt-candidate-execution-plan-schema.test.ts | 9 +- .../agent-candidate-execution-plan-schema.ts | 15 +- .../src/agent-candidate-lineage-schema.ts | 1 - .../agent-candidate-outcome-schema.test.ts | 61 +- .../src/agent-candidate-outcome-schema.ts | 10 +- .../agent-candidate-profile-schema.test.ts | 2 +- .../src/agent-candidate-promotion-schema.ts | 4 - .../src/agent-candidate-receipt-schema.ts | 3 - .../src/agent-candidate-schema.test.ts | 9 +- .../src/agent-candidate-schema.ts | 1 - .../src/agent-candidate.test-fixture.ts | 6 - .../agent-interface/src/agent-candidate.ts | 22 - packages/agent-interface/src/index.ts | 1 - .../agent-interface/src/profile-diff.test.ts | 21 +- packages/agent-interface/src/profile-diff.ts | 1 - .../agent-interface/src/profile-schema.ts | 49 +- 21 files changed, 53 insertions(+), 971 deletions(-) create mode 100644 .changeset/clean-candidate-contract.md delete mode 100644 packages/agent-interface/src/agent-candidate-compat.test.ts delete mode 100644 packages/agent-interface/src/agent-candidate-compat.ts diff --git a/.changeset/clean-candidate-contract.md b/.changeset/clean-candidate-contract.md new file mode 100644 index 0000000..99c88da --- /dev/null +++ b/.changeset/clean-candidate-contract.md @@ -0,0 +1,5 @@ +--- +"@tangle-network/agent-interface": minor +--- + +Collapse the unlaunched candidate, profile-diff, and improvement contracts to one canonical shape without schema version fields or frozen compatibility exports. diff --git a/packages/agent-interface/src/agent-candidate-artifact-schema.test.ts b/packages/agent-interface/src/agent-candidate-artifact-schema.test.ts index 9a35f0f..11bf421 100644 --- a/packages/agent-interface/src/agent-candidate-artifact-schema.test.ts +++ b/packages/agent-interface/src/agent-candidate-artifact-schema.test.ts @@ -248,16 +248,15 @@ describe("candidate artifact schemas", () => { ]; expect(() => agentCandidateWorkspaceManifestMaterialSchema.parse({ - schemaVersion: 2, kind: "agent-candidate-workspace-manifest", files, }), ).not.toThrow(); expect( agentCandidateWorkspaceManifestMaterialSchema.safeParse({ - schemaVersion: 1, kind: "agent-candidate-workspace-manifest", files, + schemaVersion: 2, }).success, ).toBe(false); for (const invalidFiles of [ @@ -269,7 +268,6 @@ describe("candidate artifact schemas", () => { ]) { expect(() => agentCandidateWorkspaceManifestMaterialSchema.parse({ - schemaVersion: 2, kind: "agent-candidate-workspace-manifest", files: invalidFiles, }), @@ -279,11 +277,9 @@ describe("candidate artifact schemas", () => { it("requires workspace manifest and archive evidence", () => { const evidence = { - schemaVersion: 2, kind: "agent-candidate-workspace-snapshot", digest: candidateSha("1"), material: { - schemaVersion: 2, kind: "agent-candidate-workspace-manifest", files: [], }, @@ -306,7 +302,7 @@ describe("candidate artifact schemas", () => { expect( agentCandidateWorkspaceSnapshotEvidenceSchema.safeParse({ ...evidence, - schemaVersion: 1, + schemaVersion: 2, }).success, ).toBe(false); expect(() => diff --git a/packages/agent-interface/src/agent-candidate-artifact-schema.ts b/packages/agent-interface/src/agent-candidate-artifact-schema.ts index 7fd31c8..bad5fe7 100644 --- a/packages/agent-interface/src/agent-candidate-artifact-schema.ts +++ b/packages/agent-interface/src/agent-candidate-artifact-schema.ts @@ -133,7 +133,6 @@ export const agentCandidateCapturedArtifactSchema = z.union([ export const agentCandidateWorkspaceManifestMaterialSchema = z .object({ - schemaVersion: z.literal(2), kind: z.literal("agent-candidate-workspace-manifest"), files: z.array( z @@ -168,7 +167,6 @@ export const agentCandidateWorkspaceManifestMaterialSchema = z export const agentCandidateWorkspaceSnapshotEvidenceSchema = z .object({ - schemaVersion: z.literal(2), kind: z.literal("agent-candidate-workspace-snapshot"), digest: sha256DigestSchema, material: agentCandidateWorkspaceManifestMaterialSchema, diff --git a/packages/agent-interface/src/agent-candidate-compat.test.ts b/packages/agent-interface/src/agent-candidate-compat.test.ts deleted file mode 100644 index ec1d3d5..0000000 --- a/packages/agent-interface/src/agent-candidate-compat.test.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { describe, expect, expectTypeOf, it } from "vitest"; -import * as index from "./index.js"; -import { - agentCandidateModelSettlementCallSchema, - agentCandidateModelSettlementMaterialSchema, -} from "./agent-candidate-outcome-schema.js"; -import type { - AgentCandidateBenchmarkResultMaterial, - AgentCandidateModelSettlementCall, - AgentCandidateModelSettlementMaterial, - AgentCandidateProfilePlanMaterial, -} from "./agent-candidate.js"; -import type { - AgentCandidateBenchmarkResultMaterialV1, - AgentCandidateBundleV1, - AgentCandidateExecutionPlanMaterialV1, - AgentCandidateMaterializationReceiptV1, - AgentCandidateModelSettlementCallV2, - AgentCandidateModelSettlementMaterialV1, - AgentCandidateModelSettlementMaterialV2, - AgentCandidateModelUsage, - AgentCandidateProfilePlanMaterialV1, - AgentCandidateRunReceiptAnyVersion, - AgentCandidateRunReceiptV1, - AgentCandidateRunReceiptV2, - AgentCandidateTaskOutcomeMaterialV1, - AgentCandidateWorkspaceManifestMaterialV1, -} from "./agent-candidate-compat.js"; - -/** The eight restored runtime values (zod schemas and functions). */ -const restoredValues = [ - "agentCandidateModelSettlementCallV2Schema", - "agentCandidateModelSettlementMaterialV1Schema", - "agentCandidateModelSettlementMaterialV2Schema", - "agentCandidateModelUsageSchema", - "agentCandidateRunReceiptAnyVersionSchema", - "agentCandidateRunReceiptV1Schema", - "agentCandidateRunReceiptV2Schema", - "sameFixedSpend", -] as const; - -describe("candidate compat exports", () => { - it("re-exports every restored runtime value from the package index", () => { - for (const name of restoredValues) { - expect( - index[name as keyof typeof index], - `missing export: ${name}`, - ).toBeDefined(); - } - }); - - it("keeps aliased schemas reference-equal to their current counterpart", () => { - expect(index.agentCandidateModelSettlementCallV2Schema).toBe( - agentCandidateModelSettlementCallSchema, - ); - expect(index.agentCandidateModelSettlementMaterialV2Schema).toBe( - agentCandidateModelSettlementMaterialSchema, - ); - }); - - it("re-adds schemas that changed shape as distinct objects", () => { - // The V1 settlement material is a genuinely different parser, not an alias. - expect(index.agentCandidateModelSettlementMaterialV1Schema).not.toBe( - agentCandidateModelSettlementMaterialSchema, - ); - // The V1 run receipt pins schemaVersion 1; the current schema is version 3. - const v1 = index.agentCandidateRunReceiptV1Schema.safeParse({ - schemaVersion: 3, - }); - expect(v1.success).toBe(false); - expect(typeof index.sameFixedSpend).toBe("function"); - }); - - it("exposes every restored type as a named export (compile-time)", () => { - // These assertions erase at runtime; a missing type export fails `tsc`. - expectTypeOf().toBeObject(); - expectTypeOf().toBeObject(); - expectTypeOf().toBeObject(); - expectTypeOf().toBeObject(); - expectTypeOf().toBeObject(); - expectTypeOf().toBeObject(); - expectTypeOf().toBeObject(); - expectTypeOf().not.toBeNever(); - expectTypeOf().toBeObject(); - expectTypeOf().toBeObject(); - - // Aliased types must stay mutually assignable with their new counterpart. - expectTypeOf().toEqualTypeOf(); - expectTypeOf().toEqualTypeOf(); - expectTypeOf().toEqualTypeOf(); - expectTypeOf().toEqualTypeOf(); - }); -}); diff --git a/packages/agent-interface/src/agent-candidate-compat.ts b/packages/agent-interface/src/agent-candidate-compat.ts deleted file mode 100644 index 002e608..0000000 --- a/packages/agent-interface/src/agent-candidate-compat.ts +++ /dev/null @@ -1,701 +0,0 @@ -/** - * Backward-compatibility surface for the candidate outcome and receipt exports - * that were renamed or collapsed when the candidate contract was unified. - * - * Every symbol here is deprecated and exists only so published consumers that - * still import the pre-unification names keep resolving at ESM import time. - * Prefer the current names; these will be removed in a future major. - * - * Two shapes of compat live in this module: - * - Pure renames (shape-identical to a current export) are re-exported as - * deprecated aliases and remain reference-equal to their new counterpart. - * - Symbols whose shape changed (a different `schemaVersion` literal, a - * restructured field, or a union that no longer exists) are re-declared here - * verbatim from the last release that published them, so old data still - * parses against the old name instead of silently binding to a newer shape. - */ - -import { z } from "zod"; -import type { - AgentCandidateArtifactRef, - AgentCandidateAttemptPolicy, - AgentCandidateBenchmarkResultEvidence, - AgentCandidateBenchmarkResultMaterial, - AgentCandidateCode, - AgentCandidateConfigValue, - AgentCandidateDigestAlgorithm, - AgentCandidateEffectiveMemory, - AgentCandidateEntrypointReceipt, - AgentCandidateExecution, - AgentCandidateExecutionEnvironment, - AgentCandidateExecutionLimits, - AgentCandidateExecutionPlanEvidence, - AgentCandidateFixedSpend, - AgentCandidateInstructionDelivery, - AgentCandidateKnowledge, - AgentCandidateLineage, - AgentCandidateMemoryPolicy, - AgentCandidateMemoryReceipt, - AgentCandidateModelAccessNetwork, - AgentCandidateModelSettlementCall, - AgentCandidateModelSettlementEvidence, - AgentCandidateModelSettlementMaterial, - AgentCandidateOciPlatform, - AgentCandidateProfile, - AgentCandidateProfileApplication, - AgentCandidateProfilePlanEvidence, - AgentCandidateProfilePlanMaterial, - AgentCandidateRepositoryState, - AgentCandidateResolvedModel, - AgentCandidateSpend, - AgentCandidateTaskOutcomeEvidence, - AgentCandidateTermination, - AgentCandidateTraceEvidence, - AgentCandidateWorkingDirectory, - AgentCandidateWorkspaceSnapshotEvidence, - Sha256Digest, -} from "./agent-candidate.js"; -import { - agentCandidateModelSettlementCallSchema, - agentCandidateModelSettlementEvidenceSchema, - agentCandidateModelSettlementMaterialSchema, - agentCandidateBenchmarkResultEvidenceSchema, - agentCandidateFixedSpendSchema, - agentCandidateTaskOutcomeEvidenceSchema, -} from "./agent-candidate-outcome-schema.js"; -import { agentCandidateResolvedModelSchema } from "./agent-candidate-execution-plan-schema.js"; -import { agentCandidateSpendSchema } from "./agent-candidate-lineage-schema.js"; -import { - agentCandidateMemoryReceiptSchema, - agentCandidateTerminationSchema, - agentCandidateTraceEvidenceSchema, -} from "./agent-candidate-receipt-schema.js"; -import { - isCanonicalJsonValue, - sha256DigestSchema, -} from "./agent-candidate-schema-common.js"; -import type { HarnessType } from "./harness.js"; - -// ============================================================================= -// Pure renames — shape-identical to a current export. -// ============================================================================= - -/** @deprecated Renamed to {@link AgentCandidateProfilePlanMaterial}. */ -export type AgentCandidateProfilePlanMaterialV1 = AgentCandidateProfilePlanMaterial; - -/** @deprecated Renamed to {@link AgentCandidateBenchmarkResultMaterial}. */ -export type AgentCandidateBenchmarkResultMaterialV1 = - AgentCandidateBenchmarkResultMaterial; - -/** - * @deprecated The router-authored call fields folded into - * {@link AgentCandidateModelSettlementCall}; this alias is shape-identical. - */ -export type AgentCandidateModelSettlementCallV2 = - AgentCandidateModelSettlementCall; - -/** - * @deprecated The settlement material union collapsed to the single current - * {@link AgentCandidateModelSettlementMaterial}; this alias is shape-identical. - */ -export type AgentCandidateModelSettlementMaterialV2 = - AgentCandidateModelSettlementMaterial; - -/** - * @deprecated Renamed to {@link agentCandidateModelSettlementCallSchema}. - * Reference-equal to the current export. - */ -export const agentCandidateModelSettlementCallV2Schema = - agentCandidateModelSettlementCallSchema; - -/** - * @deprecated Renamed to {@link agentCandidateModelSettlementMaterialSchema}. - * Reference-equal to the current export. - */ -export const agentCandidateModelSettlementMaterialV2Schema = - agentCandidateModelSettlementMaterialSchema; - -// ============================================================================= -// Re-added definitions — the current export changed shape, so the original is -// restored verbatim under its old name. Marked for removal in a future major. -// ============================================================================= - -/** - * @deprecated The bundle contract advanced to `schemaVersion: 2` - * ({@link AgentCandidateBundle}). This is the frozen `schemaVersion: 1` shape. - */ -export interface AgentCandidateBundleV1 { - schemaVersion: 1; - kind: "agent-candidate-bundle"; - digestAlgorithm: AgentCandidateDigestAlgorithm; - profile: AgentCandidateProfile; - code: AgentCandidateCode; - execution: AgentCandidateExecution; - knowledge?: AgentCandidateKnowledge; - memory: AgentCandidateMemoryPolicy; - lineage: AgentCandidateLineage; - digest: Sha256Digest; -} - -/** - * @deprecated The workspace manifest advanced to `schemaVersion: 2` with an - * unconstrained numeric `mode` ({@link AgentCandidateWorkspaceManifestMaterial}). - * This is the frozen `schemaVersion: 1` shape. - */ -export interface AgentCandidateWorkspaceManifestMaterialV1 { - schemaVersion: 1; - kind: "agent-candidate-workspace-manifest"; - files: Array<{ - path: string; - mode: 0o644 | 0o755; - sha256: Sha256Digest; - byteLength: number; - }>; -} - -/** - * @deprecated The profile-plan material now carries `usage` (see - * {@link AgentCandidateModelUsage}'s successor). This is the original - * `resolved`/`usage` pairing kept for consumers of the old run receipt. - */ -export interface AgentCandidateModelUsage { - resolved: AgentCandidateResolvedModel; - usage: AgentCandidateSpend; -} - -/** - * @deprecated The execution-plan material advanced to `schemaVersion: 2` with a - * restructured `task` ({@link AgentCandidateExecutionPlanMaterial}). This is the - * frozen `schemaVersion: 1` shape. - */ -export interface AgentCandidateExecutionPlanMaterialV1 { - schemaVersion: 1; - kind: "agent-candidate-execution-plan-material"; - bundleDigest: Sha256Digest; - executionId: string; - attempt: AgentCandidateAttemptPolicy; - task: { - benchmark: string; - benchmarkVersion: string; - taskId: string; - splitDigest: Sha256Digest; - instruction: { - encoding: "utf8"; - sha256: Sha256Digest; - byteLength: number; - delivery: AgentCandidateInstructionDelivery; - }; - repository: { - identity: string; - rootIdentity: string; - baseCommit: string; - baseTree: string; - }; - workspace: AgentCandidateWorkspaceSnapshotEvidence; - }; - workspaces: { - taskRoot: string; - candidateRoot?: string; - }; - codeKind: AgentCandidateCode["kind"]; - candidateWorkspace?: AgentCandidateWorkspaceSnapshotEvidence; - profile: AgentCandidateProfileApplication; - harness: HarnessType; - harnessVersion: string; - container: { - source: AgentCandidateExecutionEnvironment["kind"]; - image: string; - indexDigest: Sha256Digest; - manifestDigest: Sha256Digest; - platform: AgentCandidateOciPlatform; - }; - model: { - policy: "single"; - resolved: AgentCandidateResolvedModel; - access: { - kind: "evaluator-mediated"; - grantDigest: Sha256Digest; - network: AgentCandidateModelAccessNetwork; - }; - routes: Array< - | { kind: "primary"; requested?: string } - | { kind: "small"; requested: string } - | { kind: "mode"; name: string; requested: string } - | { kind: "subagent"; name: string; requested: string } - >; - }; - grader: { - name: string; - version: string; - artifact: AgentCandidateArtifactRef; - }; - launch: { - executable: string; - args: AgentCandidateConfigValue[]; - env: Record; - cwd: AgentCandidateWorkingDirectory; - }; - knowledgeManifestDigest?: Sha256Digest; - memory: AgentCandidateEffectiveMemory; - limits: AgentCandidateExecutionLimits; - network: { mode: "disabled" }; -} - -/** - * @deprecated The materialization receipt advanced to `schemaVersion: 2` - * ({@link AgentCandidateMaterializationReceipt}). This is the frozen - * `schemaVersion: 1` shape. - */ -export interface AgentCandidateMaterializationReceiptV1 { - schemaVersion: 1; - kind: "agent-candidate-materialization"; - digestAlgorithm: AgentCandidateDigestAlgorithm; - bundleDigest: Sha256Digest; - profilePlan: AgentCandidateProfilePlanEvidence; - executionPlan: AgentCandidateExecutionPlanEvidence; - candidateWorkspace?: AgentCandidateWorkspaceSnapshotEvidence; - codeKind: AgentCandidateCode["kind"]; - materializedTree?: string; - harness: HarnessType; - harnessVersion: string; - container: { - source: AgentCandidateExecutionEnvironment["kind"]; - image: string; - indexDigest: Sha256Digest; - manifestDigest: Sha256Digest; - platform: AgentCandidateOciPlatform; - }; - resolvedModel: AgentCandidateResolvedModel; - knowledgeManifestDigest?: Sha256Digest; - entrypoint?: AgentCandidateEntrypointReceipt; - digest: Sha256Digest; -} - -/** - * @deprecated The run receipt advanced to `schemaVersion: 3` - * ({@link AgentCandidateRunReceipt}). This is the frozen `schemaVersion: 1` - * shape with its aggregate `usage`/`modelUsage` accounting. - */ -export interface AgentCandidateRunReceiptV1 { - schemaVersion: 1; - kind: "agent-candidate-run"; - digestAlgorithm: AgentCandidateDigestAlgorithm; - bundleDigest: Sha256Digest; - materializationReceiptDigest: Sha256Digest; - executionPlanDigest: Sha256Digest; - memory: AgentCandidateMemoryReceipt; - usage: AgentCandidateSpend; - modelUsage: AgentCandidateModelUsage; - trace: AgentCandidateTraceEvidence; - termination: AgentCandidateTermination; - digest: Sha256Digest; -} - -/** - * @deprecated The run receipt advanced to `schemaVersion: 3` - * ({@link AgentCandidateRunReceipt}). This is the frozen `schemaVersion: 2` - * shape that layered fixed-point spend and evidence over the V1 receipt. - */ -export interface AgentCandidateRunReceiptV2 - extends Omit { - schemaVersion: 2; - fixedUsage: AgentCandidateFixedSpend; - modelSettlement: AgentCandidateModelSettlementEvidence; - taskOutcome: AgentCandidateTaskOutcomeEvidence; - benchmarkResult: AgentCandidateBenchmarkResultEvidence; -} - -/** - * @deprecated The V1/V2 run receipt generations collapsed into the single - * current {@link AgentCandidateRunReceipt}. This union no longer has a current - * counterpart. - */ -export type AgentCandidateRunReceiptAnyVersion = - | AgentCandidateRunReceiptV1 - | AgentCandidateRunReceiptV2; - -/** - * Canonical model-access ledger written with the pre-router base call shape, - * before per-call generation identity and terminal status were required. - * - * @deprecated The settlement material collapsed to the single current - * {@link AgentCandidateModelSettlementMaterial} (`schemaVersion: 2`). This is - * the frozen `schemaVersion: 1` shape. - */ -export interface AgentCandidateModelSettlementMaterialV1 { - schemaVersion: 1; - kind: "agent-candidate-model-settlement-material"; - executionPlanDigest: Sha256Digest; - preparationId: string; - grantDigest: Sha256Digest; - closed: true; - resolved: AgentCandidateResolvedModel; - calls: LegacyModelSettlementCallV1[]; - usage: AgentCandidateFixedSpend; -} - -/** Pre-router settlement call shape used only by {@link AgentCandidateModelSettlementMaterialV1}. */ -interface LegacyModelSettlementCallV1 { - callId: string; - traceSpanId: string; - model: string; - inputTokens: number; - outputTokens: number; - cachedInputTokens: number; - reasoningTokens: number; - costUsdNanos: number; -} - -// ----------------------------------------------------------------------------- -// Re-added schemas. -// ----------------------------------------------------------------------------- - -const safeCountSchema = z - .number() - .int() - .nonnegative() - .refine(Number.isSafeInteger, "value must be a nonnegative safe integer"); -const boundedIdentifierSchema = z.string().min(1).max(256); - -/** - * @deprecated The run receipt no longer carries a standalone model-usage block. - * Restored `resolved`/`usage` schema for consumers of the V1/V2 run receipt. - */ -export const agentCandidateModelUsageSchema = z - .object({ - resolved: agentCandidateResolvedModelSchema, - usage: agentCandidateSpendSchema, - }) - .strict() satisfies z.ZodType; - -/** - * Restored per-call aggregate and canonical-value checks shared by the V1 - * settlement material. Mirrors the current internal refinement but tolerates - * the pre-router call shape that omits `generationId`. - */ -function refineLegacyModelSettlementMaterial( - material: { - resolved: AgentCandidateResolvedModel; - calls: LegacyModelSettlementCallV1[]; - usage: AgentCandidateFixedSpend; - }, - ctx: z.RefinementCtx, -): void { - const callIds = new Set(); - const traceSpanIds = new Set(); - const totals: AgentCandidateFixedSpend = { - inputTokens: 0, - outputTokens: 0, - cachedInputTokens: 0, - reasoningTokens: 0, - modelCalls: material.calls.length, - costUsdNanos: 0, - }; - - for (const [index, call] of material.calls.entries()) { - if (callIds.has(call.callId)) { - ctx.addIssue({ - code: "custom", - path: ["calls", index, "callId"], - message: "model settlement call ids must be unique", - }); - } - callIds.add(call.callId); - if (traceSpanIds.has(call.traceSpanId)) { - ctx.addIssue({ - code: "custom", - path: ["calls", index, "traceSpanId"], - message: "model settlement trace span ids must be unique", - }); - } - traceSpanIds.add(call.traceSpanId); - if (call.model !== material.resolved.model) { - ctx.addIssue({ - code: "custom", - path: ["calls", index, "model"], - message: "settled call model must match the resolved single model", - }); - } - - for (const field of [ - "inputTokens", - "outputTokens", - "cachedInputTokens", - "reasoningTokens", - "costUsdNanos", - ] as const) { - const sum = totals[field] + call[field]; - if (!Number.isSafeInteger(sum)) { - ctx.addIssue({ - code: "custom", - path: ["calls", index, field], - message: `model settlement ${field} total exceeds safe integer range`, - }); - } else { - totals[field] = sum; - } - } - } - - if (!sameFixedSpend(totals, material.usage)) { - ctx.addIssue({ - code: "custom", - path: ["usage"], - message: "model settlement usage must equal the exact per-call aggregate", - }); - } - if (!isCanonicalJsonValue(material)) { - ctx.addIssue({ - code: "custom", - message: "model settlement material must contain only RFC 8785 JSON values", - }); - } -} - -const legacyModelSettlementCallV1Schema = z - .object({ - callId: boundedIdentifierSchema, - traceSpanId: boundedIdentifierSchema, - model: boundedIdentifierSchema, - inputTokens: safeCountSchema, - outputTokens: safeCountSchema, - cachedInputTokens: safeCountSchema, - reasoningTokens: safeCountSchema, - costUsdNanos: safeCountSchema, - }) - .strict(); - -/** - * @deprecated The settlement material collapsed to - * {@link agentCandidateModelSettlementMaterialSchema} (`schemaVersion: 2`). - * Restored `schemaVersion: 1` parser for the pre-router base call shape. - */ -export const agentCandidateModelSettlementMaterialV1Schema = z - .object({ - schemaVersion: z.literal(1), - kind: z.literal("agent-candidate-model-settlement-material"), - executionPlanDigest: sha256DigestSchema, - preparationId: boundedIdentifierSchema, - grantDigest: sha256DigestSchema, - closed: z.literal(true), - resolved: agentCandidateResolvedModelSchema, - usage: agentCandidateFixedSpendSchema, - calls: z.array(legacyModelSettlementCallV1Schema), - }) - .strict() - .superRefine( - refineLegacyModelSettlementMaterial, - ) satisfies z.ZodType; - -/** - * @deprecated The run receipt collapsed to - * {@link agentCandidateRunReceiptSchema} (`schemaVersion: 3`). Restored - * `schemaVersion: 1` parser with aggregate usage accounting. - */ -export const agentCandidateRunReceiptV1Schema = z - .object({ - schemaVersion: z.literal(1), - kind: z.literal("agent-candidate-run"), - digestAlgorithm: z.literal("rfc8785-sha256"), - bundleDigest: sha256DigestSchema, - materializationReceiptDigest: sha256DigestSchema, - executionPlanDigest: sha256DigestSchema, - memory: agentCandidateMemoryReceiptSchema, - usage: agentCandidateSpendSchema, - modelUsage: agentCandidateModelUsageSchema, - trace: agentCandidateTraceEvidenceSchema, - termination: agentCandidateTerminationSchema, - digest: sha256DigestSchema, - }) - .strict() - .superRefine((receipt, ctx) => { - const usageMatchesModel = - receipt.usage.costUsd === receipt.modelUsage.usage.costUsd && - receipt.usage.inputTokens === receipt.modelUsage.usage.inputTokens && - receipt.usage.outputTokens === receipt.modelUsage.usage.outputTokens && - receipt.usage.cachedInputTokens === - receipt.modelUsage.usage.cachedInputTokens && - receipt.usage.modelCalls === receipt.modelUsage.usage.modelCalls; - if (!usageMatchesModel) { - ctx.addIssue({ - code: "custom", - path: ["modelUsage", "usage"], - message: "single-model usage must equal aggregate protected usage", - }); - } - if (receipt.trace.modelCallCount !== receipt.modelUsage.usage.modelCalls) { - ctx.addIssue({ - code: "custom", - path: ["trace", "modelCallCount"], - message: "trace model-call count must match protected single-model usage", - }); - } - if (!isCanonicalJsonValue(receipt)) { - ctx.addIssue({ - code: "custom", - message: "run receipt must contain only RFC 8785 JSON values", - }); - } - }) satisfies z.ZodType; - -function legacyUsageMatchesFixed( - legacy: AgentCandidateModelUsage["usage"], - fixed: AgentCandidateFixedSpend, -): boolean { - return ( - legacy.costUsd === fixed.costUsdNanos / 1_000_000_000 && - legacy.inputTokens === fixed.inputTokens && - legacy.outputTokens === fixed.outputTokens && - (legacy.cachedInputTokens ?? 0) === fixed.cachedInputTokens && - legacy.modelCalls === fixed.modelCalls - ); -} - -/** - * @deprecated The run receipt collapsed to - * {@link agentCandidateRunReceiptSchema} (`schemaVersion: 3`). Restored - * `schemaVersion: 2` parser. Its evidence members bind the current settlement, - * task-outcome, and benchmark-result schemas. - */ -export const agentCandidateRunReceiptV2Schema = z - .object({ - schemaVersion: z.literal(2), - kind: z.literal("agent-candidate-run"), - digestAlgorithm: z.literal("rfc8785-sha256"), - bundleDigest: sha256DigestSchema, - materializationReceiptDigest: sha256DigestSchema, - executionPlanDigest: sha256DigestSchema, - memory: agentCandidateMemoryReceiptSchema, - usage: agentCandidateSpendSchema, - modelUsage: agentCandidateModelUsageSchema, - trace: agentCandidateTraceEvidenceSchema, - termination: agentCandidateTerminationSchema, - fixedUsage: agentCandidateFixedSpendSchema, - modelSettlement: agentCandidateModelSettlementEvidenceSchema, - taskOutcome: agentCandidateTaskOutcomeEvidenceSchema, - benchmarkResult: agentCandidateBenchmarkResultEvidenceSchema, - digest: sha256DigestSchema, - }) - .strict() - .superRefine((receipt, ctx) => { - const legacyUsageMatchesModel = - receipt.usage.costUsd === receipt.modelUsage.usage.costUsd && - receipt.usage.inputTokens === receipt.modelUsage.usage.inputTokens && - receipt.usage.outputTokens === receipt.modelUsage.usage.outputTokens && - receipt.usage.cachedInputTokens === - receipt.modelUsage.usage.cachedInputTokens && - receipt.usage.modelCalls === receipt.modelUsage.usage.modelCalls; - if (!legacyUsageMatchesModel) { - ctx.addIssue({ - code: "custom", - path: ["modelUsage", "usage"], - message: "single-model usage must equal aggregate protected usage", - }); - } - if (!legacyUsageMatchesFixed(receipt.usage, receipt.fixedUsage)) { - ctx.addIssue({ - code: "custom", - path: ["fixedUsage"], - message: "fixed usage must exactly preserve the legacy usage totals", - }); - } - if ( - !sameFixedSpend(receipt.fixedUsage, receipt.modelSettlement.material.usage) - ) { - ctx.addIssue({ - code: "custom", - path: ["modelSettlement", "material", "usage"], - message: "model settlement aggregate must equal fixed run usage", - }); - } - if ( - JSON.stringify(receipt.modelUsage.resolved) !== - JSON.stringify(receipt.modelSettlement.material.resolved) - ) { - ctx.addIssue({ - code: "custom", - path: ["modelSettlement", "material", "resolved"], - message: "model settlement must bind the run's resolved model", - }); - } - if ( - receipt.modelSettlement.material.executionPlanDigest !== - receipt.executionPlanDigest - ) { - ctx.addIssue({ - code: "custom", - path: ["modelSettlement", "material", "executionPlanDigest"], - message: "model settlement must bind the executed plan", - }); - } - if (receipt.trace.modelCallCount !== receipt.fixedUsage.modelCalls) { - ctx.addIssue({ - code: "custom", - path: ["trace", "modelCallCount"], - message: "trace model-call count must match fixed run usage", - }); - } - if ( - receipt.taskOutcome.material.executionPlanDigest !== - receipt.executionPlanDigest - ) { - ctx.addIssue({ - code: "custom", - path: ["taskOutcome", "material", "executionPlanDigest"], - message: "task outcome must bind the executed plan", - }); - } - if ( - receipt.benchmarkResult.material.executionPlanDigest !== - receipt.executionPlanDigest - ) { - ctx.addIssue({ - code: "custom", - path: ["benchmarkResult", "material", "executionPlanDigest"], - message: "benchmark result must bind the executed plan", - }); - } - if ( - receipt.benchmarkResult.material.taskOutcomeDigest !== - receipt.taskOutcome.digest - ) { - ctx.addIssue({ - code: "custom", - path: ["benchmarkResult", "material", "taskOutcomeDigest"], - message: "benchmark result must bind the exact task outcome", - }); - } - if (!isCanonicalJsonValue(receipt)) { - ctx.addIssue({ - code: "custom", - message: "run receipt must contain only RFC 8785 JSON values", - }); - } - }) satisfies z.ZodType; - -/** - * @deprecated The run receipt generations collapsed into a single current - * schema. Restored union parser for consumers that accepted both generations. - */ -export const agentCandidateRunReceiptAnyVersionSchema = z.union([ - agentCandidateRunReceiptV1Schema, - agentCandidateRunReceiptV2Schema, -]) satisfies z.ZodType; - -/** - * @deprecated No longer exported from the outcome module. Restored spend-equality - * helper for consumers that compared fixed-point usage totals. - */ -export function sameFixedSpend( - left: AgentCandidateFixedSpend, - right: AgentCandidateFixedSpend, -): boolean { - return ( - left.inputTokens === right.inputTokens && - left.outputTokens === right.outputTokens && - left.cachedInputTokens === right.cachedInputTokens && - left.reasoningTokens === right.reasoningTokens && - left.modelCalls === right.modelCalls && - left.costUsdNanos === right.costUsdNanos - ); -} diff --git a/packages/agent-interface/src/agent-candidate-execution-plan-schema.test.ts b/packages/agent-interface/src/agent-candidate-execution-plan-schema.test.ts index 95886c9..e0e9aea 100644 --- a/packages/agent-interface/src/agent-candidate-execution-plan-schema.test.ts +++ b/packages/agent-interface/src/agent-candidate-execution-plan-schema.test.ts @@ -9,11 +9,9 @@ import { candidateSha } from "./agent-candidate.test-fixture.js"; function workspace(path: string, digit: string) { return { - schemaVersion: 2 as const, kind: "agent-candidate-workspace-snapshot" as const, digest: candidateSha(digit), material: { - schemaVersion: 2 as const, kind: "agent-candidate-workspace-manifest" as const, files: [ { @@ -48,7 +46,6 @@ function planFixture() { reasoningEffort: "high" as const, }; return { - schemaVersion: 2 as const, kind: "agent-candidate-execution-plan-material" as const, bundleDigest: candidateSha("1"), executionId: "execution-1", @@ -157,11 +154,9 @@ function planFixture() { describe("agentCandidateExecutionPlanMaterialSchema", () => { it("binds native activation paths and modes to the canonical profile plan", () => { const profilePlan = { - schemaVersion: 1 as const, kind: "agent-profile-workspace-plan" as const, digest: candidateSha("1"), material: { - version: 1 as const, harness: "codex" as const, files: [ { @@ -183,7 +178,6 @@ describe("agentCandidateExecutionPlanMaterialSchema", () => { }, }; const activation = { - schemaVersion: 1 as const, kind: "agent-candidate-profile-activation" as const, profilePlan, files: [{ path: ".codex/instructions.md", mode: 0o664, content: "exact" }], @@ -218,7 +212,7 @@ describe("agentCandidateExecutionPlanMaterialSchema", () => { expect( agentCandidateExecutionPlanMaterialSchema.safeParse({ ...planFixture(), - schemaVersion: 1, + schemaVersion: 2, }).success, ).toBe(false); expect(() => @@ -347,7 +341,6 @@ describe("agentCandidateExecutionPlanMaterialSchema", () => { } const profilePlan = { - version: 1, harness: "codex", files: [], env: {}, diff --git a/packages/agent-interface/src/agent-candidate-execution-plan-schema.ts b/packages/agent-interface/src/agent-candidate-execution-plan-schema.ts index d59fb35..b429c05 100644 --- a/packages/agent-interface/src/agent-candidate-execution-plan-schema.ts +++ b/packages/agent-interface/src/agent-candidate-execution-plan-schema.ts @@ -115,7 +115,6 @@ export const agentCandidateResolvedModelSchema = z export const agentCandidateProfilePlanMaterialSchema = z .object({ - version: z.literal(1), harness: harnessTypeSchema, files: z.array( z @@ -227,7 +226,6 @@ export const agentCandidateTaskOutcomeSpecSchema = z.discriminatedUnion("kind", export const agentCandidateExecutionPlanMaterialSchema = z .object({ - schemaVersion: z.literal(2), kind: z.literal("agent-candidate-execution-plan-material"), bundleDigest: sha256DigestSchema, executionId: z.string().min(1), @@ -591,14 +589,12 @@ export const agentCandidateExecutionPlanMaterialSchema = z } }) satisfies z.ZodType; -function planEvidenceSchema< - TVersion extends number, - TKind extends string, - TMaterial, ->(schemaVersion: TVersion, kind: TKind, material: z.ZodType) { +function planEvidenceSchema( + kind: TKind, + material: z.ZodType, +) { return z .object({ - schemaVersion: z.literal(schemaVersion), kind: z.literal(kind), digest: sha256DigestSchema, material, @@ -624,14 +620,12 @@ function planEvidenceSchema< } export const agentCandidateProfilePlanEvidenceSchema = planEvidenceSchema( - 1, "agent-profile-workspace-plan", agentCandidateProfilePlanMaterialSchema, ) satisfies z.ZodType; export const agentCandidateProfileActivationSchema = z .object({ - schemaVersion: z.literal(1), kind: z.literal("agent-candidate-profile-activation"), profilePlan: agentCandidateProfilePlanEvidenceSchema, files: z.array( @@ -688,7 +682,6 @@ export const agentCandidateProfileActivationSchema = z }) satisfies z.ZodType; export const agentCandidateExecutionPlanEvidenceSchema = planEvidenceSchema( - 2, "agent-candidate-execution-plan", agentCandidateExecutionPlanMaterialSchema, ) satisfies z.ZodType; diff --git a/packages/agent-interface/src/agent-candidate-lineage-schema.ts b/packages/agent-interface/src/agent-candidate-lineage-schema.ts index b0717af..ecd4026 100644 --- a/packages/agent-interface/src/agent-candidate-lineage-schema.ts +++ b/packages/agent-interface/src/agent-candidate-lineage-schema.ts @@ -19,7 +19,6 @@ export const agentCandidateKnowledgeSchema = z .object({ candidate: z .object({ - schemaVersion: z.literal(1), kind: z.literal("knowledge-improvement-candidate"), runId: z.string().min(1), candidateId: z.string().min(1), diff --git a/packages/agent-interface/src/agent-candidate-outcome-schema.test.ts b/packages/agent-interface/src/agent-candidate-outcome-schema.test.ts index 9056296..a8e081c 100644 --- a/packages/agent-interface/src/agent-candidate-outcome-schema.test.ts +++ b/packages/agent-interface/src/agent-candidate-outcome-schema.test.ts @@ -40,11 +40,9 @@ function durableArtifact(key: string, digit: string, byteLength = 1) { function workspaceSnapshot(name: string, digit: string) { return { - schemaVersion: 2 as const, kind: "agent-candidate-workspace-snapshot" as const, digest: candidateSha(digit), material: { - schemaVersion: 2 as const, kind: "agent-candidate-workspace-manifest" as const, files: [ { @@ -70,11 +68,9 @@ const resolvedModel = { function materializationReceipt(receipt: ReturnType) { const profilePlan = { - schemaVersion: 1 as const, kind: "agent-profile-workspace-plan" as const, digest: candidateSha("1"), material: { - version: 1 as const, harness: "codex" as const, files: [], env: {}, @@ -84,7 +80,6 @@ function materializationReceipt(receipt: ReturnType) { artifact: durableArtifact("plans/profile.json", "1", 72), }; const executionPlanMaterial = { - schemaVersion: 2 as const, kind: "agent-candidate-execution-plan-material" as const, bundleDigest: receipt.bundleDigest, executionId: "candidate-execution-1", @@ -154,13 +149,11 @@ function materializationReceipt(receipt: ReturnType) { network: { mode: "disabled" as const }, }; return { - schemaVersion: 2 as const, kind: "agent-candidate-materialization" as const, digestAlgorithm: "rfc8785-sha256" as const, bundleDigest: receipt.bundleDigest, profilePlan, executionPlan: { - schemaVersion: 2 as const, kind: "agent-candidate-execution-plan" as const, digest: receipt.executionPlanDigest, material: executionPlanMaterial, @@ -186,10 +179,9 @@ function runReceipt() { costUsdNanos: 1_250_000_000, }; const modelSettlementMaterial = { - schemaVersion: 2 as const, kind: "agent-candidate-model-settlement-material" as const, executionPlanDigest, - preparationId: "candidate-preparation-v1.abc123", + preparationId: "candidate-preparation.abc123", grantDigest: candidateSha("4"), closed: true as const, resolved: resolvedModel, @@ -226,14 +218,12 @@ function runReceipt() { usage: fixedUsage, }; const modelSettlement = { - schemaVersion: 2 as const, kind: "agent-candidate-model-settlement" as const, digest: candidateSha("5"), material: modelSettlementMaterial, artifact: durableArtifact("settlements/run-1.json", "5", 300), }; const taskOutcomeMaterial = { - schemaVersion: 2 as const, kind: "agent-candidate-task-outcome-material" as const, executionPlanDigest, outcome: { @@ -258,14 +248,12 @@ function runReceipt() { }, }; const taskOutcome = { - schemaVersion: 2 as const, kind: "agent-candidate-task-outcome" as const, digest: candidateSha("8"), material: taskOutcomeMaterial, artifact: durableArtifact("outcomes/run-1/outcome.json", "8", 500), }; const benchmarkResultMaterial = { - schemaVersion: 1 as const, kind: "agent-candidate-benchmark-result-material" as const, executionPlanDigest, taskOutcomeDigest: taskOutcome.digest, @@ -289,7 +277,6 @@ function runReceipt() { ], }; const benchmarkResult = { - schemaVersion: 1 as const, kind: "agent-candidate-benchmark-result" as const, digest: candidateSha("b"), material: benchmarkResultMaterial, @@ -297,7 +284,6 @@ function runReceipt() { }; return { - schemaVersion: 3 as const, kind: "agent-candidate-run" as const, digestAlgorithm: "rfc8785-sha256" as const, bundleDigest: candidateSha("c"), @@ -305,7 +291,6 @@ function runReceipt() { executionPlanDigest, memory: { mode: "disabled" as const }, trace: { - schemaVersion: 1 as const, artifact: durableArtifact("traces/run-1.json", "e", 500), eventCount: 8, modelCallCount: 2, @@ -323,7 +308,6 @@ describe("candidate outcome contracts", () => { it("owns the current proposal, review, and receipt-bearing execution evidence", () => { const bundle = candidateFixture(); const evaluation = { - schemaVersion: 1 as const, kind: "agent-improvement-measured-comparison" as const, benchmark: { name: "pier", version: "0.3", splitDigest: candidateSha("9") }, baselineProfileDigest: candidateSha("8"), @@ -453,7 +437,6 @@ describe("candidate outcome contracts", () => { evaluation: { generationsExplored: 1, durationMs: 100, totalCostUsd: 0.5 }, }; const proposal = { - schemaVersion: 1 as const, kind: "agent-improvement-proposal" as const, runId: "eval-1", changedSurfaces: ["prompt"] as const, @@ -544,7 +527,6 @@ describe("candidate outcome contracts", () => { }).success, ).toBe(false); const review = { - schemaVersion: 1 as const, kind: "agent-improvement-review" as const, proposalDigest: proposal.digest, candidateBundleDigest: proposal.candidateBundle.digest, @@ -565,7 +547,6 @@ describe("candidate outcome contracts", () => { const receipt = runReceipt(); const materialization = materializationReceipt(receipt); const evidence = { - schemaVersion: 1 as const, kind: "agent-candidate-execution-evidence" as const, proposalDigest: proposal.digest, reviewDigest: review.digest, @@ -573,7 +554,6 @@ describe("candidate outcome contracts", () => { succeeded: true as const, materializationReceipt: materialization, profileActivation: { - schemaVersion: 1 as const, kind: "agent-candidate-profile-activation" as const, profilePlan: materialization.profilePlan, files: [], @@ -622,49 +602,16 @@ describe("candidate outcome contracts", () => { expect(agentCandidateRunReceiptSchema.parse(receipt)).toEqual(receipt); }); - it("rejects record versions already published with different shapes", () => { + it("rejects obsolete schema version markers", () => { const receipt = runReceipt(); const materialization = materializationReceipt(receipt); expect( - agentCandidateRunReceiptSchema.safeParse({ ...receipt, schemaVersion: 1 }).success, - ).toBe(false); - expect( - agentCandidateRunReceiptSchema.safeParse({ ...receipt, schemaVersion: 2 }).success, - ).toBe(false); - expect( - agentCandidateModelSettlementMaterialSchema.safeParse({ - ...receipt.modelSettlement.material, - schemaVersion: 1, - }).success, - ).toBe(false); - expect( - agentCandidateModelSettlementEvidenceSchema.safeParse({ - ...receipt.modelSettlement, - schemaVersion: 1, - }).success, - ).toBe(false); - expect( - agentCandidateTaskOutcomeMaterialSchema.safeParse({ - ...receipt.taskOutcome.material, - schemaVersion: 1, - }).success, - ).toBe(false); - expect( - agentCandidateTaskOutcomeEvidenceSchema.safeParse({ - ...receipt.taskOutcome, - schemaVersion: 1, - }).success, - ).toBe(false); - expect( - agentCandidateMaterializationReceiptSchema.safeParse({ - ...materialization, - schemaVersion: 1, - }).success, + agentCandidateRunReceiptSchema.safeParse({ ...receipt, schemaVersion: 3 }).success, ).toBe(false); expect( agentCandidateMaterializationReceiptSchema.safeParse({ ...materialization, - executionPlan: { ...materialization.executionPlan, schemaVersion: 1 }, + schemaVersion: 2, }).success, ).toBe(false); }); diff --git a/packages/agent-interface/src/agent-candidate-outcome-schema.ts b/packages/agent-interface/src/agent-candidate-outcome-schema.ts index 1bcadfa..76f84d9 100644 --- a/packages/agent-interface/src/agent-candidate-outcome-schema.ts +++ b/packages/agent-interface/src/agent-candidate-outcome-schema.ts @@ -95,7 +95,6 @@ const modelSettlementMaterialShape = { export const agentCandidateModelSettlementMaterialSchema = z .object({ - schemaVersion: z.literal(2), ...modelSettlementMaterialShape, calls: z.array(agentCandidateModelSettlementCallSchema), }) @@ -189,7 +188,6 @@ function refineModelSettlementMaterial( } export const agentCandidateModelSettlementEvidenceSchema = evidenceSchema( - 2, "agent-candidate-model-settlement", agentCandidateModelSettlementMaterialSchema, "model settlement", @@ -215,7 +213,6 @@ export const agentCandidateRepositoryStateSchema = z export const agentCandidateTaskOutcomeMaterialSchema = z .object({ - schemaVersion: z.literal(2), kind: z.literal("agent-candidate-task-outcome-material"), executionPlanDigest: sha256DigestSchema, outcome: z.discriminatedUnion("kind", [ @@ -318,7 +315,6 @@ export const agentCandidateTaskOutcomeMaterialSchema = z }) satisfies z.ZodType; export const agentCandidateTaskOutcomeEvidenceSchema = evidenceSchema( - 2, "agent-candidate-task-outcome", agentCandidateTaskOutcomeMaterialSchema, "task outcome", @@ -333,7 +329,6 @@ export const agentCandidateBenchmarkDimensionSchema = z export const agentCandidateBenchmarkResultMaterialSchema = z .object({ - schemaVersion: z.literal(1), kind: z.literal("agent-candidate-benchmark-result-material"), executionPlanDigest: sha256DigestSchema, taskOutcomeDigest: sha256DigestSchema, @@ -400,7 +395,6 @@ export const agentCandidateBenchmarkResultMaterialSchema = z }) satisfies z.ZodType; export const agentCandidateBenchmarkResultEvidenceSchema = evidenceSchema( - 1, "agent-candidate-benchmark-result", agentCandidateBenchmarkResultMaterialSchema, "benchmark result", @@ -420,15 +414,13 @@ function sameFixedSpend( ); } -function evidenceSchema( - schemaVersion: TVersion, +function evidenceSchema( kind: TKind, material: z.ZodType, label: string, ) { return z .object({ - schemaVersion: z.literal(schemaVersion), kind: z.literal(kind), digest: sha256DigestSchema, material, diff --git a/packages/agent-interface/src/agent-candidate-profile-schema.test.ts b/packages/agent-interface/src/agent-candidate-profile-schema.test.ts index 0e2e481..7e44122 100644 --- a/packages/agent-interface/src/agent-candidate-profile-schema.test.ts +++ b/packages/agent-interface/src/agent-candidate-profile-schema.test.ts @@ -73,7 +73,7 @@ describe("agentCandidateProfileSchema", () => { ).not.toThrow(); }); - it("rejects arbitrary backend extensions in frozen profile v1", () => { + it("rejects arbitrary backend extensions in a frozen profile", () => { expect(() => agentCandidateProfileSchema.parse({ extensions: { provider: { auth: "sk-live-abcdefghijkl" } }, diff --git a/packages/agent-interface/src/agent-candidate-promotion-schema.ts b/packages/agent-interface/src/agent-candidate-promotion-schema.ts index 9bd9eea..dad5e0b 100644 --- a/packages/agent-interface/src/agent-candidate-promotion-schema.ts +++ b/packages/agent-interface/src/agent-candidate-promotion-schema.ts @@ -117,7 +117,6 @@ const improvementSurfaceSchema = z.enum([ export const agentImprovementMeasuredComparisonSchema = z .object({ - schemaVersion: z.literal(1), kind: z.literal("agent-improvement-measured-comparison"), benchmark: z .object({ @@ -268,7 +267,6 @@ export const agentImprovementMeasuredComparisonSchema = z export const agentImprovementProposalSchema = z .object({ - schemaVersion: z.literal(1), kind: z.literal("agent-improvement-proposal"), runId: z.string().min(1).max(200), changedSurfaces: z @@ -350,7 +348,6 @@ function refineEstimate( export const agentImprovementReviewSchema = z .object({ - schemaVersion: z.literal(1), kind: z.literal("agent-improvement-review"), proposalDigest: sha256DigestSchema, candidateBundleDigest: sha256DigestSchema, @@ -366,7 +363,6 @@ export const agentImprovementReviewSchema = z export const candidateExecutionEvidenceSchema = z .object({ - schemaVersion: z.literal(1), kind: z.literal("agent-candidate-execution-evidence"), proposalDigest: sha256DigestSchema, reviewDigest: sha256DigestSchema, diff --git a/packages/agent-interface/src/agent-candidate-receipt-schema.ts b/packages/agent-interface/src/agent-candidate-receipt-schema.ts index d4d087d..d76072d 100644 --- a/packages/agent-interface/src/agent-candidate-receipt-schema.ts +++ b/packages/agent-interface/src/agent-candidate-receipt-schema.ts @@ -52,7 +52,6 @@ const ociPlatformSchema = z export const agentCandidateTraceEvidenceSchema = z .object({ - schemaVersion: z.literal(1), artifact: agentCandidateCapturedArtifactSchema, eventCount: z.number().int().positive(), modelCallCount: z.number().int().nonnegative(), @@ -108,7 +107,6 @@ export const agentCandidateTerminationSchema = z.discriminatedUnion("kind", [ export const agentCandidateMaterializationReceiptSchema = z .object({ - schemaVersion: z.literal(2), kind: z.literal("agent-candidate-materialization"), digestAlgorithm: z.literal("rfc8785-sha256"), bundleDigest: sha256DigestSchema, @@ -250,7 +248,6 @@ export const agentCandidateMaterializationReceiptSchema = z export const agentCandidateRunReceiptSchema = z .object({ - schemaVersion: z.literal(3), kind: z.literal("agent-candidate-run"), digestAlgorithm: z.literal("rfc8785-sha256"), bundleDigest: sha256DigestSchema, diff --git a/packages/agent-interface/src/agent-candidate-schema.test.ts b/packages/agent-interface/src/agent-candidate-schema.test.ts index c5ac504..581b83e 100644 --- a/packages/agent-interface/src/agent-candidate-schema.test.ts +++ b/packages/agent-interface/src/agent-candidate-schema.test.ts @@ -21,7 +21,7 @@ describe("agentCandidateBundleSchema", () => { expect( agentCandidateBundleSchema.safeParse({ ...candidateFixture(), - schemaVersion: 1, + schemaVersion: 2, }).success, ).toBe(false); }); @@ -316,13 +316,11 @@ describe("candidate receipts", () => { archiveName: string, ) => { const material = { - schemaVersion: 2 as const, kind: "agent-candidate-workspace-manifest" as const, files, }; const manifest = capturedMaterial(material); return { - schemaVersion: 2 as const, kind: "agent-candidate-workspace-snapshot" as const, digest: manifest.digest, material, @@ -362,7 +360,6 @@ describe("candidate receipts", () => { reasoningEffort: "high" as const, }; const profilePlanMaterial = { - version: 1 as const, harness: "codex" as const, files: [], env: {}, @@ -371,7 +368,6 @@ describe("candidate receipts", () => { }; const capturedProfilePlan = capturedMaterial(profilePlanMaterial); const profilePlan = { - schemaVersion: 1 as const, kind: "agent-profile-workspace-plan" as const, digest: capturedProfilePlan.digest, material: profilePlanMaterial, @@ -379,7 +375,6 @@ describe("candidate receipts", () => { }; const resetEvidence = embeddedBytes("fresh-memory-reset"); const executionPlanMaterial = { - schemaVersion: 2 as const, kind: "agent-candidate-execution-plan-material" as const, bundleDigest: candidateSha("1"), executionId: "run-1", @@ -480,13 +475,11 @@ describe("candidate receipts", () => { }; const capturedExecutionPlan = capturedMaterial(executionPlanMaterial); const materialization = { - schemaVersion: 2, kind: "agent-candidate-materialization", digestAlgorithm: "rfc8785-sha256", bundleDigest: candidateSha("1"), profilePlan, executionPlan: { - schemaVersion: 2, kind: "agent-candidate-execution-plan", digest: capturedExecutionPlan.digest, material: executionPlanMaterial, diff --git a/packages/agent-interface/src/agent-candidate-schema.ts b/packages/agent-interface/src/agent-candidate-schema.ts index 6864d33..ca366ee 100644 --- a/packages/agent-interface/src/agent-candidate-schema.ts +++ b/packages/agent-interface/src/agent-candidate-schema.ts @@ -23,7 +23,6 @@ import { canonicalizeHarness } from "./harness.js"; */ export const agentCandidateBundleSchema = z .object({ - schemaVersion: z.literal(2), kind: z.literal("agent-candidate-bundle"), digestAlgorithm: z.literal("rfc8785-sha256"), profile: agentCandidateProfileSchema, diff --git a/packages/agent-interface/src/agent-candidate.test-fixture.ts b/packages/agent-interface/src/agent-candidate.test-fixture.ts index ba4d0a9..7e7adfb 100644 --- a/packages/agent-interface/src/agent-candidate.test-fixture.ts +++ b/packages/agent-interface/src/agent-candidate.test-fixture.ts @@ -6,7 +6,6 @@ export const candidateGit = (digit: string) => digit.repeat(40); export function candidateFixture() { return defineAgentCandidateBundle({ - schemaVersion: 2, kind: "agent-candidate-bundle", digestAlgorithm: "rfc8785-sha256", profile: { @@ -72,11 +71,9 @@ export function candidateFixture() { container: { image: "node:22", indexDigest: candidateSha("6") }, }, workspace: { - schemaVersion: 2, kind: "agent-candidate-workspace-snapshot", digest: candidateSha("c"), material: { - schemaVersion: 2, kind: "agent-candidate-workspace-manifest", files: [ { @@ -108,7 +105,6 @@ export function candidateFixture() { }, knowledge: { candidate: { - schemaVersion: 1, kind: "knowledge-improvement-candidate", runId: "knowledge-run-17", candidateId: "knowledge-17", @@ -119,11 +115,9 @@ export function candidateFixture() { promotionPlanHash: candidateSha("9"), }, snapshot: { - schemaVersion: 2, kind: "agent-candidate-workspace-snapshot", digest: candidateSha("7"), material: { - schemaVersion: 2, kind: "agent-candidate-workspace-manifest", files: [], }, diff --git a/packages/agent-interface/src/agent-candidate.ts b/packages/agent-interface/src/agent-candidate.ts index 168e662..133097e 100644 --- a/packages/agent-interface/src/agent-candidate.ts +++ b/packages/agent-interface/src/agent-candidate.ts @@ -292,7 +292,6 @@ export interface AgentCandidateExecution { /** Exact frozen knowledge candidate admitted only through an approved review. */ export interface AgentCandidateKnowledgeRef { - schemaVersion: 1; kind: "knowledge-improvement-candidate"; runId: string; candidateId: string; @@ -366,7 +365,6 @@ export interface AgentCandidateLineage { * artifact hashes are untrusted until recomputed. */ export interface AgentCandidateBundle { - schemaVersion: 2; kind: "agent-candidate-bundle"; digestAlgorithm: AgentCandidateDigestAlgorithm; profile: AgentCandidateProfile; @@ -400,7 +398,6 @@ export interface AgentCandidateResolvedModel { /** Canonical, digest-free profile-plan identity document. */ export interface AgentCandidateProfilePlanMaterial { - version: 1; harness: HarnessType; files: Array<{ relPath: string; @@ -413,7 +410,6 @@ export interface AgentCandidateProfilePlanMaterial { } export interface AgentCandidateWorkspaceManifestMaterial { - schemaVersion: 2; kind: "agent-candidate-workspace-manifest"; files: Array<{ path: string; @@ -426,7 +422,6 @@ export interface AgentCandidateWorkspaceManifestMaterial { /** Content-addressed manifest of every file uploaded to one workspace. */ export interface AgentCandidateWorkspaceSnapshotEvidence { - schemaVersion: 2; kind: "agent-candidate-workspace-snapshot"; digest: Sha256Digest; material: AgentCandidateWorkspaceManifestMaterial; @@ -507,7 +502,6 @@ export type AgentCandidateTaskOutcomeSpec = * its raw SHA-256 is the execution-plan digest. */ export interface AgentCandidateExecutionPlanMaterial { - schemaVersion: 2; kind: "agent-candidate-execution-plan-material"; bundleDigest: Sha256Digest; executionId: string; @@ -577,7 +571,6 @@ export interface AgentCandidateExecutionPlanMaterial { } export interface AgentCandidateProfilePlanEvidence { - schemaVersion: 1; kind: "agent-profile-workspace-plan"; digest: Sha256Digest; material: AgentCandidateProfilePlanMaterial; @@ -586,7 +579,6 @@ export interface AgentCandidateProfilePlanEvidence { /** Exact native profile files and the canonical plan that activated them. */ export interface AgentCandidateProfileActivation { - schemaVersion: 1; kind: "agent-candidate-profile-activation"; profilePlan: AgentCandidateProfilePlanEvidence; files: Array<{ @@ -598,7 +590,6 @@ export interface AgentCandidateProfileActivation { } export interface AgentCandidateExecutionPlanEvidence { - schemaVersion: 2; kind: "agent-candidate-execution-plan"; digest: Sha256Digest; material: AgentCandidateExecutionPlanMaterial; @@ -606,7 +597,6 @@ export interface AgentCandidateExecutionPlanEvidence { } export interface AgentCandidateTraceEvidence { - schemaVersion: 1; artifact: AgentCandidateCapturedArtifact; eventCount: number; modelCallCount: number; @@ -625,7 +615,6 @@ export type AgentCandidateMemoryReceipt = /** Proof emitted after a runtime materializes, but before it executes, a bundle. */ export interface AgentCandidateMaterializationReceipt { - schemaVersion: 2; kind: "agent-candidate-materialization"; digestAlgorithm: AgentCandidateDigestAlgorithm; bundleDigest: Sha256Digest; @@ -658,7 +647,6 @@ export type AgentCandidateTermination = /** Proof emitted after the exact materialized plan finishes executing. */ export interface AgentCandidateRunReceipt { - schemaVersion: 3; kind: "agent-candidate-run"; digestAlgorithm: AgentCandidateDigestAlgorithm; bundleDigest: Sha256Digest; @@ -688,7 +676,6 @@ export type AgentImprovementSurface = /** Portable paired held-out comparison produced by an evaluation package. */ export interface AgentImprovementMeasuredComparison { - schemaVersion: 1; kind: "agent-improvement-measured-comparison"; benchmark: { name: string; @@ -802,7 +789,6 @@ export interface AgentImprovementMeasuredComparison { } export interface AgentImprovementProposal { - schemaVersion: 1; kind: "agent-improvement-proposal"; runId: string; changedSurfaces: [AgentImprovementSurface, ...AgentImprovementSurface[]]; @@ -821,7 +807,6 @@ export type AgentImprovementReviewDecision = /** Human or tenant-policy decision bound to one exact proposal. */ export interface AgentImprovementReview { - schemaVersion: 1; kind: "agent-improvement-review"; proposalDigest: Sha256Digest; candidateBundleDigest: Sha256Digest; @@ -835,7 +820,6 @@ export interface AgentImprovementReview { /** Successful post-approval execution, carrying the exact Runtime receipt. */ export interface CandidateExecutionEvidence { - schemaVersion: 1; kind: "agent-candidate-execution-evidence"; proposalDigest: Sha256Digest; reviewDigest: Sha256Digest; @@ -865,7 +849,6 @@ export interface AgentCandidateModelSettlementCall { /** Canonical model-access ledger after the evaluator has revoked access. */ export interface AgentCandidateModelSettlementMaterial { - schemaVersion: 2; kind: "agent-candidate-model-settlement-material"; executionPlanDigest: Sha256Digest; preparationId: string; @@ -877,7 +860,6 @@ export interface AgentCandidateModelSettlementMaterial { } export interface AgentCandidateModelSettlementEvidence { - schemaVersion: 2; kind: "agent-candidate-model-settlement"; digest: Sha256Digest; material: AgentCandidateModelSettlementMaterial; @@ -894,7 +876,6 @@ export interface AgentCandidateRepositoryState { /** Canonical result captured by the evaluator after one candidate task. */ export interface AgentCandidateTaskOutcomeMaterial { - schemaVersion: 2; kind: "agent-candidate-task-outcome-material"; executionPlanDigest: Sha256Digest; outcome: @@ -916,7 +897,6 @@ export interface AgentCandidateTaskOutcomeMaterial { } export interface AgentCandidateTaskOutcomeEvidence { - schemaVersion: 2; kind: "agent-candidate-task-outcome"; digest: Sha256Digest; material: AgentCandidateTaskOutcomeMaterial; @@ -930,7 +910,6 @@ export interface AgentCandidateBenchmarkDimension { /** Canonical executable-grade result for one task outcome. */ export interface AgentCandidateBenchmarkResultMaterial { - schemaVersion: 1; kind: "agent-candidate-benchmark-result-material"; executionPlanDigest: Sha256Digest; taskOutcomeDigest: Sha256Digest; @@ -953,7 +932,6 @@ export interface AgentCandidateBenchmarkResultMaterial { } export interface AgentCandidateBenchmarkResultEvidence { - schemaVersion: 1; kind: "agent-candidate-benchmark-result"; digest: Sha256Digest; material: AgentCandidateBenchmarkResultMaterial; diff --git a/packages/agent-interface/src/index.ts b/packages/agent-interface/src/index.ts index a0bc510..b585d55 100644 --- a/packages/agent-interface/src/index.ts +++ b/packages/agent-interface/src/index.ts @@ -824,7 +824,6 @@ export * from "./interaction.js"; export * from "./agent-candidate.js"; export * from "./agent-candidate-schema.js"; export * from "./agent-candidate-promotion-schema.js"; -export * from "./agent-candidate-compat.js"; export * from "./agent-profile.js"; export * from "./profile-diff.js"; export * from "./harness.js"; diff --git a/packages/agent-interface/src/profile-diff.test.ts b/packages/agent-interface/src/profile-diff.test.ts index 327009d..e783f29 100644 --- a/packages/agent-interface/src/profile-diff.test.ts +++ b/packages/agent-interface/src/profile-diff.test.ts @@ -50,7 +50,6 @@ describe("AgentProfileDiff", () => { expect( applyAgentProfileDiff(profile, { - schemaVersion: 1, kind: "agent-profile-diff", }), ).toEqual(profile); @@ -58,7 +57,6 @@ describe("AgentProfileDiff", () => { it("applies a full-profile overlay and named removals", () => { const diff = defineAgentProfileDiff({ - schemaVersion: 1, kind: "agent-profile-diff", id: "stateful-small-model-pack", set: { @@ -118,7 +116,6 @@ describe("AgentProfileDiff", () => { it("reports and prunes changed axes for causal ablations", () => { const diff = defineAgentProfileDiff({ - schemaVersion: 1, kind: "agent-profile-diff", set: { prompt: { instructions: ["Use evidence first."] }, @@ -138,7 +135,6 @@ describe("AgentProfileDiff", () => { it("validates generated diffs with the public schema", () => { const parsed = agentProfileDiffSchema.parse({ - schemaVersion: 1, kind: "agent-profile-diff", source: { kind: "frontier-author", @@ -163,16 +159,23 @@ describe("AgentProfileDiff", () => { expect(changedAgentProfileAxes(parsed)).toEqual(["model", "subagents"]); }); + it("rejects obsolete schema markers", () => { + expect( + agentProfileDiffSchema.safeParse({ + schemaVersion: 1, + kind: "agent-profile-diff", + }).success, + ).toBe(false); + }); + it("sets only the harness axis", () => { const diff = defineAgentProfileDiff({ - schemaVersion: 1, kind: "agent-profile-diff", set: { harness: "codex" }, }); const profile = applyAgentProfileDiff(baseProfile, diff); const control = applyAgentProfileDiff(baseProfile, { - schemaVersion: 1, kind: "agent-profile-diff", }); @@ -184,14 +187,12 @@ describe("AgentProfileDiff", () => { it("explicitly removes only the harness axis", () => { const diff = agentProfileDiffSchema.parse({ - schemaVersion: 1, kind: "agent-profile-diff", remove: { harness: true }, }); const profile = applyAgentProfileDiff(baseProfile, diff); const control = applyAgentProfileDiff(baseProfile, { - schemaVersion: 1, kind: "agent-profile-diff", }); @@ -200,7 +201,6 @@ describe("AgentProfileDiff", () => { expect(profile).toEqual({ ...control, harness: undefined }); expect(() => agentProfileDiffSchema.parse({ - schemaVersion: 1, kind: "agent-profile-diff", remove: { harness: false }, }), @@ -209,7 +209,6 @@ describe("AgentProfileDiff", () => { it("applies harness removal after a harness overlay", () => { const profile = applyAgentProfileDiff(baseProfile, { - schemaVersion: 1, kind: "agent-profile-diff", set: { harness: "codex" }, remove: { harness: true }, @@ -220,7 +219,6 @@ describe("AgentProfileDiff", () => { it("prunes harness set and removal without changing other axes", () => { const diff = defineAgentProfileDiff({ - schemaVersion: 1, kind: "agent-profile-diff", set: { harness: "codex", @@ -233,7 +231,6 @@ describe("AgentProfileDiff", () => { const profile = applyAgentProfileDiff(baseProfile, pruned); const toolsOnlyControl = applyAgentProfileDiff(baseProfile, { - schemaVersion: 1, kind: "agent-profile-diff", set: { tools: { shell: true } }, }); diff --git a/packages/agent-interface/src/profile-diff.ts b/packages/agent-interface/src/profile-diff.ts index b02a85c..32525db 100644 --- a/packages/agent-interface/src/profile-diff.ts +++ b/packages/agent-interface/src/profile-diff.ts @@ -83,7 +83,6 @@ export interface AgentProfileDiffRemoval { * AgentProfile instead of a benchmark-specific file mount. */ export interface AgentProfileDiff { - schemaVersion: 1; kind: "agent-profile-diff"; id?: string; title?: string; diff --git a/packages/agent-interface/src/profile-schema.ts b/packages/agent-interface/src/profile-schema.ts index 23fee21..7eaf440 100644 --- a/packages/agent-interface/src/profile-schema.ts +++ b/packages/agent-interface/src/profile-schema.ts @@ -186,30 +186,31 @@ export const agentProfileSchema = z.object({ .optional(), }); -export const agentProfileDiffSchema: z.ZodType = z.object({ - schemaVersion: z.literal(1), - kind: z.literal("agent-profile-diff"), - id: z.string().min(1).optional(), - title: z.string().min(1).optional(), - description: z.string().optional(), - rationale: z.string().optional(), - source: z - .object({ - kind: z.enum([ - "trace", - "frontier-author", - "human", - "optimizer", - "compound", - ]), - artifacts: z.array(z.string().min(1)).optional(), - notes: z.array(z.string()).optional(), - }) - .optional(), - set: agentProfileSchema.optional(), - remove: agentProfileDiffRemovalSchema.optional(), - metadata: z.record(z.string(), z.unknown()).optional(), -}); +export const agentProfileDiffSchema: z.ZodType = z + .object({ + kind: z.literal("agent-profile-diff"), + id: z.string().min(1).optional(), + title: z.string().min(1).optional(), + description: z.string().optional(), + rationale: z.string().optional(), + source: z + .object({ + kind: z.enum([ + "trace", + "frontier-author", + "human", + "optimizer", + "compound", + ]), + artifacts: z.array(z.string().min(1)).optional(), + notes: z.array(z.string()).optional(), + }) + .optional(), + set: agentProfileSchema.optional(), + remove: agentProfileDiffRemovalSchema.optional(), + metadata: z.record(z.string(), z.unknown()).optional(), + }) + .strict(); // ── Compile-time drift guard ────────────────────────────────────────────────── // The Zod schema and the hand-written {@link AgentProfile} interface must agree in