@claudexor/orchestrator 2.1.2 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,9 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
- import { observeNativeSessionEvent, preflightCredentialProfile, preflightDefaultSubject, resolveCredentialProfile, resumeSessionForProfile, rotateSpecOnTypedLimit, } from "./credential-profiles.js";
2
+ import { observeNativeSessionEvent, preflightCredentialProfile, preflightDefaultSubject, resolveCredentialProfile, resumeSessionForProfile, rotateSpecOnTypedLimit, selectedProfileAvailability, } from "./credential-profiles.js";
3
3
  import { writeRunTelemetryArtifact } from "./runTelemetryWriter.js";
4
+ import { buildFileBackedSynthesisInput, materializeWinnerOutputs, stageFileBackedContext, writeCandidateAttemptArtifacts, } from "./candidateOutputs.js";
5
+ import { processAttemptUsage } from "./attemptUsage.js";
6
+ import { toCandidateEvidence } from "./candidateEvidence.js";
4
7
  import { capabilityIntents } from "@claudexor/gateway";
5
8
  import { policyFindings } from "./policyFindings.js";
6
9
  import { join } from "node:path";
@@ -31,7 +34,7 @@ import { HarnessGateway } from "@claudexor/gateway";
31
34
  import { ReadinessLedger, evaluateConvergence, failureSignature, gatesPassed, reviewCandidate, revalidateFindings, runGates, } from "@claudexor/review";
32
35
  import { arbitrate } from "@claudexor/arbitration";
33
36
  import { buildSynthesisPlan, decideSynthesis } from "@claudexor/synthesis";
34
- import { attemptCostEvidence, attemptUsageCostSettlement, BudgetLedger, isBudgetTerminal, loadHarnessMetrics, promptFingerprint, unknownCostSettlement, usageCostSettlement, rankHarnesses, } from "@claudexor/budget";
37
+ import { attemptCostEvidence, attemptUsageCostSettlement, BudgetLedger, isBudgetTerminal, loadHarnessMetrics, promptFingerprint, unknownCostSettlement, rankHarnesses, reviewUsageCostSettlement, } from "@claudexor/budget";
35
38
  import { appendLine, assertNoInlineSecretValues, containsSecretLikeToken, hashJson, newId, noProjectRepoRoot, nowIso, redactSecrets, safeInvoke, sha256, userConfigDir, writeText, } from "@claudexor/util";
36
39
  const LABELS = "ABCDEFGHIJ".split("");
37
40
  const NO_PROJECT_ROOT = noProjectRepoRoot();
@@ -334,29 +337,6 @@ export class Orchestrator {
334
337
  const policy = this.config(repoRoot)?.global.harnesses?.[harnessId]?.profile_policy;
335
338
  return policy ?? { limit_action: "fail", rotation_eligible: [], headroom_threshold: 0.9 };
336
339
  }
337
- /** null = no profile selected (default verdict stands); "available" = the
338
- * profile's own probe admits the route; any other string = typed refusal. */
339
- async profileAvailabilityOverride(input, harnessId) {
340
- if (!input.credentialProfileId)
341
- return null;
342
- let profile;
343
- try {
344
- profile = this.resolveCredentialProfile(input, harnessId);
345
- }
346
- catch (err) {
347
- return err instanceof Error ? err.message : String(err);
348
- }
349
- if (!profile)
350
- return null;
351
- const adapter = this.deps.registry.get(harnessId);
352
- if (!adapter?.probeCredentialProfile) {
353
- return `harness "${harnessId}" has no profile probe`;
354
- }
355
- const probe = await adapter.probeCredentialProfile(profile);
356
- if (probe.availability === "available")
357
- return "available";
358
- return probe.detail ?? `${probe.availability}/${probe.verification}`;
359
- }
360
340
  preflightProfile(input, harnessId, log) {
361
341
  const profile = this.resolveCredentialProfile(input, harnessId);
362
342
  const policy = this.profilePolicy(input.repoRoot, harnessId);
@@ -537,9 +517,7 @@ export class Orchestrator {
537
517
  dropped.push(`${id} (unavailable)`);
538
518
  continue;
539
519
  }
540
- // Doctor status is the readiness truth: auto-pools take only doctor-OK
541
- // routes, and explicitly selecting an UNAVAILABLE harness fails loudly
542
- // with the doctor's reasons. A DEGRADED harness (e.g. key present but
520
+ // Doctor status is the readiness truth. A DEGRADED harness (e.g. key present but
543
521
  // unproven by isolated smoke) is admitted only by explicit user
544
522
  // selection — degraded means usable-with-caveats, and the caveats are
545
523
  // visible in doctor output and run events.
@@ -550,34 +528,40 @@ export class Orchestrator {
550
528
  // the profile's transport, so the default store's state is not the
551
529
  // routing truth). Capability/manifest gating above still applies.
552
530
  let profileAdmitted = false;
553
- if (status.status !== "ok") {
554
- const profileVerdict = await this.profileAvailabilityOverride(input, id);
531
+ const profileAdapter = this.deps.registry.get(id);
532
+ const profileVerdict = await selectedProfileAvailability({
533
+ registry: this.config(input.repoRoot)?.global.credential_profiles ?? [],
534
+ profileId: input.credentialProfileId,
535
+ harnessId: id,
536
+ probe: profileAdapter?.probeCredentialProfile?.bind(profileAdapter),
537
+ });
538
+ if (profileVerdict !== null) {
555
539
  if (profileVerdict === "available") {
556
- // The default-store failure may have zeroed enabled_intents; with
557
- // the profile probe as the auth verdict, MANIFEST capabilities are
558
- // the honest intent truth (degraded = usable-with-caveats).
559
- status = {
560
- ...status,
561
- status: "degraded",
562
- enabledIntents: capabilityIntents(manifest.capabilities),
563
- };
564
- statusById.set(id, status);
565
540
  profileAdmitted = true;
541
+ // A valid profile restores manifest intent truth when the default store failed.
542
+ if (status.status !== "ok") {
543
+ status = {
544
+ ...status,
545
+ status: "degraded",
546
+ enabledIntents: capabilityIntents(manifest.capabilities),
547
+ };
548
+ statusById.set(id, status);
549
+ }
566
550
  }
567
- else if (profileVerdict !== null) {
551
+ else {
568
552
  const why = `${id} credential profile is not ready: ${profileVerdict}`;
569
553
  if (explicitPool)
570
554
  throw new HarnessUnavailableError(why);
571
555
  dropped.push(why);
572
556
  continue;
573
557
  }
574
- else if (status.status === "unavailable") {
575
- const why = `${id} is unavailable${status.reasons.length ? `: ${status.reasons.join("; ")}` : ""}`;
576
- if (explicitPool)
577
- throw new HarnessUnavailableError(why);
578
- dropped.push(why);
579
- continue;
580
- }
558
+ }
559
+ if (status.status === "unavailable" && !profileAdmitted) {
560
+ const why = `${id} is unavailable${status.reasons.length ? `: ${status.reasons.join("; ")}` : ""}`;
561
+ if (explicitPool)
562
+ throw new HarnessUnavailableError(why);
563
+ dropped.push(why);
564
+ continue;
581
565
  }
582
566
  if (status.status !== "ok" && !explicitPool && !profileAdmitted) {
583
567
  dropped.push(`${id} is ${status.status}${status.reasons.length ? `: ${status.reasons.join("; ")}` : ""}`);
@@ -1089,12 +1073,10 @@ export class Orchestrator {
1089
1073
  ignored,
1090
1074
  };
1091
1075
  }
1092
- /** Run one candidate inside an already-created envelope. Never creates/disposes the envelope. */
1093
- async runCandidateInEnvelope(routed, envelope, attemptId, label, contract, prompt, store, paths, wsm, ledger, access = "workspace_write", onHarnessEvent, signal, modelHint, effortHint, intent = "implement", log, effectiveWebMode, interaction, budgetGuard, runInput, streamDeltas = false) {
1076
+ async runCandidateInEnvelope(routed, envelope, attemptId, label, contract, prompt, store, paths, wsm, ledger, access = "workspace_write", onHarnessEvent, signal, modelHint, effortHint, intent = "implement", log, effectiveWebMode, interaction, budgetGuard, runInput, streamDeltas = false, fileBackedContext) {
1094
1077
  const adapter = routed.adapter;
1095
1078
  const knobs = this.routeSpecKnobs(routed, contract, modelHint, effortHint);
1096
- // In-place envelopes can resume native sessions; isolated scoped homes cannot,
1097
- // so their session ids are never retained after disposal.
1079
+ // Isolated scoped-home sessions are never retained after disposal.
1098
1080
  const inPlaceEnvelope = envelope.worktree_path === envelope.repo_root;
1099
1081
  const rawContextPacket = await rawContextForEnvelope(routed.implementationTransport, envelope);
1100
1082
  const sessionFields = runInput ? this.sessionSpecFields(runInput, adapter.id, log) : undefined;
@@ -1163,6 +1145,7 @@ export class Orchestrator {
1163
1145
  }
1164
1146
  try {
1165
1147
  for (let nativeTry = 0; !signal?.aborted; nativeTry += 1) {
1148
+ const clearFileBackedContext = stageFileBackedContext(envelope.worktree_path, fileBackedContext);
1166
1149
  const runSpec = nativeTry === 0
1167
1150
  ? spec
1168
1151
  : HarnessRunSpec.parse({ ...spec, session_id: newId("ses"), extra: { ...spec.extra } });
@@ -1238,31 +1221,23 @@ export class Orchestrator {
1238
1221
  items: safeEv.plan_progress.items,
1239
1222
  });
1240
1223
  }
1241
- if (safeEv.type === "usage" && safeEv.usage?.cost_usd) {
1242
- cost += safeEv.usage.cost_usd;
1243
- if (safeEv.usage.estimated)
1244
- costEstimated = true;
1245
- log?.emit("budget.observation", {
1246
- harness_id: adapter.id,
1247
- attempt_id: attemptId,
1248
- kind: "spend",
1249
- usd: safeEv.usage.cost_usd,
1250
- estimated: safeEv.usage.estimated === true,
1224
+ if (safeEv.type === "usage") {
1225
+ const usage = processAttemptUsage({
1226
+ event: safeEv,
1227
+ telemetry,
1228
+ harnessId: adapter.id,
1229
+ attemptId,
1230
+ cost,
1231
+ costEstimated,
1232
+ emit: (type, payload) => log?.emit(type, payload),
1233
+ budgetGuard,
1234
+ cancel: () => void adapter.cancel?.(runSpec.session_id)?.catch(() => { }),
1251
1235
  });
1252
- // Mid-flight cap enforcement: the guard raises this attempt's hold
1253
- // to the streamed cost; a hard tier aborts NOW instead of letting a
1254
- // streaming candidate overshoot the paid budget until settlement.
1255
- const valuationOnly = safeEv.usage.estimated === true && telemetry.authMode === "local_session";
1256
- if (!valuationOnly && budgetGuard?.(cost)) {
1236
+ cost = usage.cost;
1237
+ costEstimated = usage.costEstimated;
1238
+ if (usage.hardCapReached) {
1257
1239
  harnessErrored = true;
1258
1240
  errors.push("budget hard cap reached mid-attempt; stream aborted");
1259
- log?.emit("budget.observation", {
1260
- harness_id: adapter.id,
1261
- attempt_id: attemptId,
1262
- kind: "cooldown",
1263
- detail: "hard cap mid-flight abort",
1264
- });
1265
- void adapter.cancel?.(runSpec.session_id)?.catch(() => { });
1266
1241
  break;
1267
1242
  }
1268
1243
  }
@@ -1293,6 +1268,9 @@ export class Orchestrator {
1293
1268
  harnessErrored = true;
1294
1269
  errors.push(safeErrorMessage(err));
1295
1270
  }
1271
+ finally {
1272
+ clearFileBackedContext();
1273
+ }
1296
1274
  const transient = telemetry.transientFailures.at(-1) ?? null;
1297
1275
  const sawTransient = telemetry.transientFailures.length > transientStart;
1298
1276
  const sawTypedLimit = telemetry.rateLimits.length > rateLimitStart;
@@ -1416,9 +1394,6 @@ export class Orchestrator {
1416
1394
  // must carry it so the slot catch settles the TRUE cost, not 0.
1417
1395
  throw Object.assign(err instanceof Error ? err : new Error(String(err)), { costUsd: cost });
1418
1396
  }
1419
- store.writeText(join(attemptDir, "patch.diff"), diff);
1420
- // Routing metrics (one owner in runSupport; clean attempts only —
1421
- // auth-route evidence recorded regardless).
1422
1397
  recordCleanAttemptMetrics(globalConfigDir(), adapter.id, {
1423
1398
  costUsd: cost,
1424
1399
  streamMs: attemptStreamEndedMs - attemptStartedMs,
@@ -1426,26 +1401,25 @@ export class Orchestrator {
1426
1401
  aborted: signal?.aborted === true,
1427
1402
  authMode: telemetry.authMode,
1428
1403
  });
1429
- const attemptDiffstat = diffStats(diff);
1430
- store.writeYaml(join(attemptDir, "attempt.yaml"), {
1431
- attempt_id: attemptId,
1432
- harness_id: adapter.id,
1433
- label,
1434
- cost_usd: cost,
1435
- cost_estimated: costEstimated,
1436
- errored,
1437
- errors: errors.slice(0, 5),
1438
- ...telemetrySummary(telemetry),
1439
- outcome: telemetry.outcome,
1440
- gates: gates.map((g) => ({ id: g.id, status: g.status })),
1441
- // Candidate-card evidence: the Candidates tab renders per-attempt
1442
- // diffstat without re-parsing patch bytes client-side.
1443
- diffstat: {
1444
- files: attemptDiffstat.paths.length,
1445
- additions: attemptDiffstat.additions,
1446
- deletions: attemptDiffstat.deletions,
1404
+ const producedFiles = writeCandidateAttemptArtifacts({
1405
+ store,
1406
+ attemptDir,
1407
+ worktreePath: envelope.worktree_path,
1408
+ diff,
1409
+ answerText,
1410
+ record: {
1411
+ attempt_id: attemptId,
1412
+ harness_id: adapter.id,
1413
+ label,
1414
+ cost_usd: cost,
1415
+ cost_estimated: costEstimated,
1416
+ errored,
1417
+ errors: errors.slice(0, 5),
1418
+ ...telemetrySummary(telemetry),
1419
+ outcome: telemetry.outcome,
1420
+ gates: gates.map((g) => ({ id: g.id, status: g.status })),
1421
+ branch: envelope.branch_name,
1447
1422
  },
1448
- branch: envelope.branch_name,
1449
1423
  });
1450
1424
  return {
1451
1425
  attemptId,
@@ -1455,6 +1429,7 @@ export class Orchestrator {
1455
1429
  answerText,
1456
1430
  reviewCwd: envelope.worktree_path,
1457
1431
  baseSha: envelope.base_sha ?? undefined,
1432
+ producedFiles,
1458
1433
  gates,
1459
1434
  cost,
1460
1435
  errored,
@@ -1463,51 +1438,6 @@ export class Orchestrator {
1463
1438
  telemetry,
1464
1439
  };
1465
1440
  }
1466
- toEvidence(run, contract, findings, finalReviewClean, reviewVerified = false) {
1467
- const passed = gatesPassed(run.gates) && !run.errored;
1468
- // Honest acceptance evidence: 0/0 when the contract has no success criteria
1469
- // (no spec). The old code fabricated a 1/1 ("AC-implicit") cover, which made
1470
- // arbitration report a vacuous "acceptance=100%" that just restated gates.
1471
- const acTotal = contract.success_criteria.length;
1472
- const acCovered = passed && contract.success_criteria.length > 0
1473
- ? contract.success_criteria.map((c) => c.id)
1474
- : [];
1475
- // Treat a harness error as a failed required gate so it cannot win arbitration.
1476
- const gates = run.errored
1477
- ? [
1478
- ...run.gates,
1479
- {
1480
- id: "harness",
1481
- command: "harness",
1482
- exit_code: 1,
1483
- status: "failed",
1484
- duration_ms: 0,
1485
- required: true,
1486
- stdout_tail: null,
1487
- stderr_tail: null,
1488
- output_truncated: false,
1489
- },
1490
- ]
1491
- : run.gates;
1492
- return {
1493
- attemptId: run.attemptId,
1494
- label: run.label,
1495
- gates,
1496
- acceptanceCovered: acCovered,
1497
- acceptanceTotal: acTotal,
1498
- findings,
1499
- // Counted from the EVIDENCE gates (including the injected harness-failure
1500
- // gate), so an errored candidate scores 0/1 — never a vacuous 0/0.
1501
- testsPassed: gates.filter((g) => g.status === "passed").length,
1502
- testsTotal: gates.length,
1503
- finalReviewClean,
1504
- reviewVerified,
1505
- toolWarningsCount: run.telemetry.outcome?.toolWarningsCount ?? toolWarnings(run.telemetry).length,
1506
- diffSize: run.diff.split("\n").length,
1507
- diffBytes: Buffer.byteLength(run.diff, "utf8"),
1508
- costUsd: run.cost,
1509
- };
1510
- }
1511
1441
  interactionChannelFor(input, log, runId, taskId, attemptId, harnessId,
1512
1442
  // REQUIRED (no default): every call site must state the routed manifest's
1513
1443
  // `interactive` capability, or a future site would silently bypass the gate.
@@ -1789,7 +1719,7 @@ export class Orchestrator {
1789
1719
  budgetStopped = true;
1790
1720
  return true;
1791
1721
  }, input, requestedSingleCandidate);
1792
- ledger.settle(slot.leaseId, attemptUsageCostSettlement(run.cost, run.costEstimated, run.attemptId, run.harnessId, run.telemetry.authMode));
1722
+ ledger.settle(slot.leaseId, attemptUsageCostSettlement(run.cost, run.costEstimated, run.attemptId, run.harnessId, run.telemetry.authMode, run.telemetry.usageCost));
1793
1723
  log.emit("harness.completed", {
1794
1724
  harness_id: adapter.id,
1795
1725
  attempt_id: slot.attemptId,
@@ -2030,9 +1960,11 @@ export class Orchestrator {
2030
1960
  let envelope;
2031
1961
  try {
2032
1962
  const plan = buildSynthesisPlan(evidences);
2033
- const sourceDiffs = workingRuns
2034
- .map((r) => `### ${r.label} (${r.attemptId})\n${r.diff}`)
2035
- .join("\n\n");
1963
+ const synthesisInput = buildFileBackedSynthesisInput({
1964
+ instructions: plan.instructions,
1965
+ findings: plan.fixFindings,
1966
+ candidates: workingRuns,
1967
+ });
2036
1968
  const synthAdapter = synthRouted.adapter;
2037
1969
  // Disclose against the PER-ROUTE policy (per-harness web defaults
2038
1970
  // included), exactly like the candidate slots do.
@@ -2045,13 +1977,12 @@ export class Orchestrator {
2045
1977
  dirtyPolicy: "snapshot",
2046
1978
  accessProfile: candidateAccess,
2047
1979
  });
2048
- const synthPrompt = `${plan.instructions}\n\nFindings to fix:\n${plan.fixFindings.map((f) => `- ${f}`).join("\n") || "(none)"}\n\nCandidate diffs:\n${sourceDiffs}`;
2049
- const run = await this.runCandidateInEnvelope(synthRouted, envelope, "synth", "Synthesis", contract, synthPrompt, store, paths, wsm, ledger, candidateAccess, (ev) => {
1980
+ const run = await this.runCandidateInEnvelope(synthRouted, envelope, "synth", "Synthesis", contract, synthesisInput.prompt, store, paths, wsm, ledger, candidateAccess, (ev) => {
2050
1981
  const safeEv = redactHarnessEvent(ev);
2051
1982
  safeInvoke(input.onHarnessEvent, safeEv);
2052
1983
  log.emit("harness.event", harnessEventPayload(synthAdapter.id, "synth", safeEv));
2053
- }, input.signal, undefined, input.effort, "synthesize", log, effectiveWeb, this.interactionChannelFor(input, log, runId, taskId, "synth", synthAdapter.id, synthRouted.supportsInteractive), undefined, input);
2054
- ledger.settle(lease.lease?.lease_id ?? "", attemptUsageCostSettlement(run.cost, run.costEstimated, run.attemptId, run.harnessId, run.telemetry.authMode));
1984
+ }, input.signal, undefined, input.effort, "synthesize", log, effectiveWeb, this.interactionChannelFor(input, log, runId, taskId, "synth", synthAdapter.id, synthRouted.supportsInteractive), undefined, input, false, synthesisInput.content);
1985
+ ledger.settle(lease.lease?.lease_id ?? "", attemptUsageCostSettlement(run.cost, run.costEstimated, run.attemptId, run.harnessId, run.telemetry.authMode, run.telemetry.usageCost));
2055
1986
  reviewEnvelopes.push(envelope);
2056
1987
  envelope = undefined;
2057
1988
  try {
@@ -2154,6 +2085,13 @@ export class Orchestrator {
2154
2085
  store.writeYaml(join(paths.arbitrationDir, "pairwise.yaml"), result.pairwise);
2155
2086
  const decisionPath = join(paths.arbitrationDir, "decision.yaml");
2156
2087
  if (winnerRun) {
2088
+ for (const path of materializeWinnerOutputs({
2089
+ attemptDir: join(paths.attemptsDir, winnerRun.attemptId),
2090
+ runRoot: paths.root,
2091
+ paths: winnerRun.producedFiles ?? [],
2092
+ })) {
2093
+ log.emit("output.ready", { kind: "artifact", path });
2094
+ }
2157
2095
  assertNoSecretLikeTokens("final patch diff", winnerRun.diff);
2158
2096
  const patchSha256 = sha256(winnerRun.diff);
2159
2097
  store.writeText(join(paths.finalDir, "patch.diff"), winnerRun.diff);
@@ -2290,7 +2228,7 @@ export class Orchestrator {
2290
2228
  log.emit("output.ready", {
2291
2229
  kind: "summary",
2292
2230
  path: "final/summary.md",
2293
- ...(status === "success" ? {} : { state: "diagnostic" }),
2231
+ state: status === "success" || winnerAnswer.length > 0 ? "ready" : "diagnostic",
2294
2232
  });
2295
2233
  }
2296
2234
  this.writeRunTelemetry(store, paths, contract, runId, taskId, mode, runs.map((r) => ({ attemptId: r.attemptId, harnessId: r.harnessId, telemetry: r.telemetry })), result.decision.status === "success"
@@ -2477,15 +2415,21 @@ export class Orchestrator {
2477
2415
  distinctProviders: [],
2478
2416
  reviewSpendUsd: 0,
2479
2417
  reviewSpendEstimated: false,
2418
+ reviewCashUsd: 0,
2419
+ reviewValuationUsd: 0,
2420
+ reviewUnknownUsd: 0,
2480
2421
  };
2481
2422
  if (reviewLease?.granted) {
2482
- ledger?.settle(reviewLease.lease?.lease_id ?? "", usageCostSettlement(result.reviewSpendUsd, result.reviewSpendEstimated, "review-usage", [`attempt:${run.attemptId}`, "review:panel"]));
2423
+ ledger?.settle(reviewLease.lease?.lease_id ?? "", reviewUsageCostSettlement(result.reviewCashUsd, result.reviewValuationUsd, result.reviewSpendEstimated, [`attempt:${run.attemptId}`, "review:panel"], result.reviewUnknownUsd));
2483
2424
  if ((result.reviewSpendUsd ?? 0) > 0) {
2484
2425
  log.emit("budget.observation", {
2485
2426
  harness_id: "review-panel",
2486
2427
  attempt_id: run.attemptId,
2487
2428
  kind: "spend",
2488
2429
  usd: result.reviewSpendUsd,
2430
+ cash_usd: result.reviewCashUsd,
2431
+ valuation_usd: result.reviewValuationUsd,
2432
+ unknown_usd: result.reviewUnknownUsd,
2489
2433
  estimated: result.reviewSpendEstimated === true,
2490
2434
  });
2491
2435
  }
@@ -2517,6 +2461,7 @@ export class Orchestrator {
2517
2461
  store.writeYaml(join(paths.reviewsDir, `${run.attemptId}.yaml`), {
2518
2462
  attempt_id: run.attemptId,
2519
2463
  review_verified: candidateReviewVerified,
2464
+ final_review_clean: reviewClean,
2520
2465
  cross_family_healthy: result.crossFamilyHealthy,
2521
2466
  cross_family_verified: result.crossFamilyVerified,
2522
2467
  healthy_providers: result.healthyProviders,
@@ -2532,7 +2477,7 @@ export class Orchestrator {
2532
2477
  severity: f.severity,
2533
2478
  status: f.status,
2534
2479
  });
2535
- evidences.push(this.toEvidence(run, contract, allFindings, reviewClean, candidateReviewVerified));
2480
+ evidences.push(toCandidateEvidence(run, contract, allFindings, reviewClean, candidateReviewVerified));
2536
2481
  }
2537
2482
  finally {
2538
2483
  this.recordReviewEvidenceCleanup(store, join(paths.reviewsDir, `${run.attemptId}-evidence-cleanup.yaml`), run.attemptId, candidateEvidenceDir, candidateCwd);
@@ -2818,7 +2763,7 @@ export class Orchestrator {
2818
2763
  ledger.updateHold(lease.lease?.lease_id ?? "", streamedUsd);
2819
2764
  return ledger.tier() === "hard";
2820
2765
  }, input, true);
2821
- ledger.settle(lease.lease?.lease_id ?? "", attemptUsageCostSettlement(run.cost, run.costEstimated, run.attemptId, run.harnessId, run.telemetry.authMode));
2766
+ ledger.settle(lease.lease?.lease_id ?? "", attemptUsageCostSettlement(run.cost, run.costEstimated, run.attemptId, run.harnessId, run.telemetry.authMode, run.telemetry.usageCost));
2822
2767
  log.emit("harness.completed", {
2823
2768
  harness_id: adapter.id,
2824
2769
  attempt_id: attemptId,
@@ -2906,15 +2851,21 @@ export class Orchestrator {
2906
2851
  distinctProviders: [],
2907
2852
  reviewSpendUsd: 0,
2908
2853
  reviewSpendEstimated: false,
2854
+ reviewCashUsd: 0,
2855
+ reviewValuationUsd: 0,
2856
+ reviewUnknownUsd: 0,
2909
2857
  };
2910
2858
  if (reviewLease?.granted) {
2911
- ledger.settle(reviewLease.lease?.lease_id ?? "", usageCostSettlement(reviewResult.reviewSpendUsd, reviewResult.reviewSpendEstimated, "review-usage", [`attempt:${attemptId}`, "review:panel"]));
2859
+ ledger.settle(reviewLease.lease?.lease_id ?? "", reviewUsageCostSettlement(reviewResult.reviewCashUsd, reviewResult.reviewValuationUsd, reviewResult.reviewSpendEstimated, [`attempt:${attemptId}`, "review:panel"], reviewResult.reviewUnknownUsd));
2912
2860
  if ((reviewResult.reviewSpendUsd ?? 0) > 0) {
2913
2861
  log.emit("budget.observation", {
2914
2862
  harness_id: "review-panel",
2915
2863
  attempt_id: attemptId,
2916
2864
  kind: "spend",
2917
2865
  usd: reviewResult.reviewSpendUsd,
2866
+ cash_usd: reviewResult.reviewCashUsd,
2867
+ valuation_usd: reviewResult.reviewValuationUsd,
2868
+ unknown_usd: reviewResult.reviewUnknownUsd,
2918
2869
  estimated: reviewResult.reviewSpendEstimated === true,
2919
2870
  });
2920
2871
  if (reviewResult.reviewSpendEstimated === true)
@@ -2941,9 +2892,15 @@ export class Orchestrator {
2941
2892
  const policy = policyFindings(run, actualReviewVerified, contract.constraints.protected_paths, contract.constraints.auto_protected_paths, contract.constraints.protected_path_approvals, contract.constraints.deny_paths);
2942
2893
  const allFindings = [...policy.findings, ...revalidated];
2943
2894
  lastFindings = allFindings;
2895
+ const inconclusive = allFindings.some((f) => f.severity === "INSUFFICIENT_EVIDENCE" || f.status === "insufficient_evidence");
2896
+ const finalReviewClean = reviewResult.crossFamilyHealthy &&
2897
+ reviewResult.crossFamilyVerified &&
2898
+ !inconclusive &&
2899
+ !allFindings.some((f) => isBlocking(f));
2944
2900
  store.writeYaml(join(paths.reviewsDir, `${attemptId}.yaml`), {
2945
2901
  attempt_id: attemptId,
2946
2902
  review_verified: actualReviewVerified,
2903
+ final_review_clean: finalReviewClean,
2947
2904
  cross_family_healthy: reviewResult.crossFamilyHealthy,
2948
2905
  cross_family_verified: reviewResult.crossFamilyVerified,
2949
2906
  healthy_providers: reviewResult.healthyProviders,
@@ -2953,11 +2910,6 @@ export class Orchestrator {
2953
2910
  findings: allFindings,
2954
2911
  route_proofs: reviewResult.routeProofs,
2955
2912
  });
2956
- const inconclusive = allFindings.some((f) => f.severity === "INSUFFICIENT_EVIDENCE" || f.status === "insufficient_evidence");
2957
- const finalReviewClean = reviewResult.crossFamilyHealthy &&
2958
- reviewResult.crossFamilyVerified &&
2959
- !inconclusive &&
2960
- !allFindings.some((f) => isBlocking(f));
2961
2913
  lastFinalReviewClean = finalReviewClean;
2962
2914
  // Measure diff stability instead of asserting it: the tree must not have
2963
2915
  // changed between the candidate diff capture and the end of review.
@@ -3081,7 +3033,7 @@ export class Orchestrator {
3081
3033
  let decision = null;
3082
3034
  if (lastRun) {
3083
3035
  const arb = arbitrate([
3084
- this.toEvidence(lastRun, contract, lastFindings, lastFinalReviewClean, actualReviewVerified),
3036
+ toCandidateEvidence(lastRun, contract, lastFindings, lastFinalReviewClean, actualReviewVerified),
3085
3037
  ], {
3086
3038
  spendUsd: ledger.spend(),
3087
3039
  estimatedSpend: lastRun.costEstimated || reviewSpendEstimated,
@@ -3519,7 +3471,7 @@ export class Orchestrator {
3519
3471
  }
3520
3472
  finally {
3521
3473
  input.signal?.removeEventListener("abort", onAbort);
3522
- ledger.settle(lease.lease?.lease_id ?? "", attemptUsageCostSettlement(cost, costEstimated, attemptId, adapter.id, telemetry.authMode));
3474
+ ledger.settle(lease.lease?.lease_id ?? "", attemptUsageCostSettlement(cost, costEstimated, attemptId, adapter.id, telemetry.authMode, telemetry.usageCost));
3523
3475
  }
3524
3476
  attemptTelemetries.push({ attemptId, harnessId: adapter.id, telemetry });
3525
3477
  const unrecovered = unrecoveredToolErrors(telemetry);
@@ -3643,6 +3595,7 @@ export class Orchestrator {
3643
3595
  if (lease.granted) {
3644
3596
  const res = await this.reviewScoped({
3645
3597
  candidateLabel: "Plan",
3598
+ reviewSubject: "plan",
3646
3599
  diff: planReviewDiff,
3647
3600
  evidenceDir: reviewDir,
3648
3601
  artifactsDir: join(paths.reviewsDir, "plan-reviewers"),
@@ -3662,15 +3615,15 @@ export class Orchestrator {
3662
3615
  route_proofs: res.routeProofs,
3663
3616
  reviewer_requests: res.reviewerRequests,
3664
3617
  });
3665
- ledger.settle(lease.lease?.lease_id ?? "", usageCostSettlement(res.reviewSpendUsd, res.reviewSpendEstimated, "review-usage", [
3666
- "attempt:plan-review",
3667
- "review:panel",
3668
- ]));
3618
+ ledger.settle(lease.lease?.lease_id ?? "", reviewUsageCostSettlement(res.reviewCashUsd, res.reviewValuationUsd, res.reviewSpendEstimated, ["attempt:plan-review", "review:panel"], res.reviewUnknownUsd));
3669
3619
  if ((res.reviewSpendUsd ?? 0) > 0) {
3670
3620
  log.emit("budget.observation", {
3671
3621
  harness_id: "review-panel",
3672
3622
  kind: "spend",
3673
3623
  usd: res.reviewSpendUsd,
3624
+ cash_usd: res.reviewCashUsd,
3625
+ valuation_usd: res.reviewValuationUsd,
3626
+ unknown_usd: res.reviewUnknownUsd,
3674
3627
  estimated: res.reviewSpendEstimated,
3675
3628
  });
3676
3629
  }
@@ -4226,7 +4179,7 @@ export class Orchestrator {
4226
4179
  }
4227
4180
  finally {
4228
4181
  input.signal?.removeEventListener("abort", onAbort);
4229
- ledger.settle(lease.lease?.lease_id ?? "", attemptUsageCostSettlement(cost, costEstimated, attemptId, adapter.id, telemetry.authMode));
4182
+ ledger.settle(lease.lease?.lease_id ?? "", attemptUsageCostSettlement(cost, costEstimated, attemptId, adapter.id, telemetry.authMode, telemetry.usageCost));
4230
4183
  }
4231
4184
  if (harnessError && telemetry.transientFailures.length > 0) {
4232
4185
  log.emit("route.transient.exhausted", {
@@ -4827,9 +4780,7 @@ export class Orchestrator {
4827
4780
  ledger.settle(reviewLease.lease?.lease_id ?? "", unknownCostSettlement("review-error"));
4828
4781
  throw error;
4829
4782
  });
4830
- ledger.settle(reviewLease.lease?.lease_id ?? "", usageCostSettlement(result.reviewSpendUsd, result.reviewSpendEstimated, "review-usage", [
4831
- `orchestrate:review:${call.run_id}`,
4832
- ]));
4783
+ ledger.settle(reviewLease.lease?.lease_id ?? "", reviewUsageCostSettlement(result.reviewCashUsd, result.reviewValuationUsd, result.reviewSpendEstimated, [`orchestrate:review:${call.run_id}`], result.reviewUnknownUsd));
4833
4784
  const revalidated = await revalidateFindings(result.findings, {
4834
4785
  candidateRoot: input.repoRoot,
4835
4786
  evidenceDir,
@@ -4851,7 +4802,7 @@ export class Orchestrator {
4851
4802
  detail: `reviewed ${call.run_id}: ${result.distinctProviders.length} family(ies), ${revalidated.length} finding(s), ${blockers} blocker(s)`,
4852
4803
  // Reviewer panels can spend real money on API-keyed routes; the
4853
4804
  // aggregate cap must charge it like any other step.
4854
- spendUsd: result.reviewSpendUsd ?? null,
4805
+ spendUsd: result.reviewCashUsd,
4855
4806
  };
4856
4807
  }
4857
4808
  case "answer_question": {