@claudexor/orchestrator 3.17.2 → 3.20.1
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.
- package/dist/account-evidence.d.ts +13 -0
- package/dist/account-evidence.d.ts.map +1 -0
- package/dist/account-evidence.js +55 -0
- package/dist/account-evidence.js.map +1 -0
- package/dist/account-resolution.d.ts.map +1 -1
- package/dist/account-resolution.js +22 -5
- package/dist/account-resolution.js.map +1 -1
- package/dist/auth-route-classification.d.ts +22 -1
- package/dist/auth-route-classification.d.ts.map +1 -1
- package/dist/auth-route-classification.js +38 -0
- package/dist/auth-route-classification.js.map +1 -1
- package/dist/candidateEvidence.js +1 -1
- package/dist/candidateEvidence.js.map +1 -1
- package/dist/candidateTerminals.d.ts +6 -0
- package/dist/candidateTerminals.d.ts.map +1 -1
- package/dist/candidateTerminals.js +28 -0
- package/dist/candidateTerminals.js.map +1 -1
- package/dist/candidateWorkProduct.d.ts +21 -0
- package/dist/candidateWorkProduct.d.ts.map +1 -0
- package/dist/candidateWorkProduct.js +43 -0
- package/dist/candidateWorkProduct.js.map +1 -0
- package/dist/continuity-facts.d.ts +3 -0
- package/dist/continuity-facts.d.ts.map +1 -1
- package/dist/continuity-facts.js +3 -0
- package/dist/continuity-facts.js.map +1 -1
- package/dist/continuity-summary.d.ts +5 -1
- package/dist/continuity-summary.d.ts.map +1 -1
- package/dist/continuity-summary.js +5 -4
- package/dist/continuity-summary.js.map +1 -1
- package/dist/credential-cooldown.d.ts +0 -10
- package/dist/credential-cooldown.d.ts.map +1 -1
- package/dist/credential-cooldown.js +0 -24
- package/dist/credential-cooldown.js.map +1 -1
- package/dist/credential-differential.d.ts +12 -1
- package/dist/credential-differential.d.ts.map +1 -1
- package/dist/credential-differential.js +42 -13
- package/dist/credential-differential.js.map +1 -1
- package/dist/credential-execution.d.ts +4 -0
- package/dist/credential-execution.d.ts.map +1 -0
- package/dist/credential-execution.js +101 -0
- package/dist/credential-execution.js.map +1 -0
- package/dist/credential-profile-rotation.d.ts.map +1 -1
- package/dist/credential-profile-rotation.js +8 -2
- package/dist/credential-profile-rotation.js.map +1 -1
- package/dist/credential-profiles.d.ts +3 -4
- package/dist/credential-profiles.d.ts.map +1 -1
- package/dist/credential-profiles.js +28 -6
- package/dist/credential-profiles.js.map +1 -1
- package/dist/deepScanReducer.d.ts.map +1 -1
- package/dist/deepScanReducer.js +5 -4
- package/dist/deepScanReducer.js.map +1 -1
- package/dist/delegationFailure.d.ts.map +1 -1
- package/dist/delegationFailure.js +7 -32
- package/dist/delegationFailure.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/laneStreamEvents.d.ts +2 -4
- package/dist/laneStreamEvents.d.ts.map +1 -1
- package/dist/laneStreamEvents.js +3 -5
- package/dist/laneStreamEvents.js.map +1 -1
- package/dist/modelGovernance.d.ts +5 -31
- package/dist/modelGovernance.d.ts.map +1 -1
- package/dist/modelGovernance.js +51 -6
- package/dist/modelGovernance.js.map +1 -1
- package/dist/orchestrator-credentials.d.ts +23 -2
- package/dist/orchestrator-credentials.d.ts.map +1 -1
- package/dist/orchestrator-credentials.js +61 -6
- package/dist/orchestrator-credentials.js.map +1 -1
- package/dist/orchestrator.d.ts +10 -12
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +129 -144
- package/dist/orchestrator.js.map +1 -1
- package/dist/planRun.d.ts +3 -7
- package/dist/planRun.d.ts.map +1 -1
- package/dist/planRun.js +15 -13
- package/dist/planRun.js.map +1 -1
- package/dist/plannerAttempt.d.ts +15 -4
- package/dist/plannerAttempt.d.ts.map +1 -1
- package/dist/plannerAttempt.js +57 -30
- package/dist/plannerAttempt.js.map +1 -1
- package/dist/processing-dispatch.d.ts +7 -5
- package/dist/processing-dispatch.d.ts.map +1 -1
- package/dist/processing-dispatch.js +65 -31
- package/dist/processing-dispatch.js.map +1 -1
- package/dist/retainedOutput.d.ts +4 -0
- package/dist/retainedOutput.d.ts.map +1 -0
- package/dist/retainedOutput.js +31 -0
- package/dist/retainedOutput.js.map +1 -0
- package/dist/runFactsPresentation.d.ts.map +1 -1
- package/dist/runFactsPresentation.js +6 -1
- package/dist/runFactsPresentation.js.map +1 -1
- package/dist/runTerminalResults.d.ts.map +1 -1
- package/dist/runTerminalResults.js +20 -2
- package/dist/runTerminalResults.js.map +1 -1
- package/dist/runTerminals.d.ts.map +1 -1
- package/dist/runTerminals.js +9 -2
- package/dist/runTerminals.js.map +1 -1
- package/package.json +17 -17
package/dist/orchestrator.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { applyWorkEnvelope, promptWithPointers as renderPromptWithPointers, threadContextPointer, } from "./prompt-framing.js";
|
|
2
2
|
import { requestRefusalFailure } from "./runTerminalResults.js";
|
|
3
3
|
import { delegationBeltFor } from "./delegationBelt.js";
|
|
4
|
-
import { bindProcessingAdmission, processingAdmissionForLease, updateProcessingStreamHold, ProcessingBudgetAdmissionError, } from "./processing-dispatch.js";
|
|
4
|
+
import { bindProcessingAdmission, processingAttemptCostEvidence, processingAdmissionForLease, updateProcessingStreamHold, ProcessingBudgetAdmissionError, } from "./processing-dispatch.js";
|
|
5
5
|
import { cancelledCandidatesResult, emptyCandidateResult, failedCandidatesResult, } from "./candidateTerminals.js";
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { effectiveAuthPreference, observeNativeSessionEvent, resumeSessionForProfile, rotateSpecOnTypedLimit, } from "./credential-profiles.js";
|
|
8
|
-
import { OrchestratorCredentials, reviewerProfileResolver, rotatedSpecInLaneHome, } from "./orchestrator-credentials.js";
|
|
8
|
+
import { AdmissionProfileProbes, OrchestratorCredentials, reviewerProfileResolver, rotatedSpecInLaneHome, } from "./orchestrator-credentials.js";
|
|
9
9
|
import { accountPoolRows } from "./account-pool.js";
|
|
10
10
|
import { writeRunTelemetryArtifact } from "./runTelemetryWriter.js";
|
|
11
11
|
import { buildFileBackedSynthesisInput, materializeWinnerOutputs, stageFileBackedContext, writeCandidateAttemptArtifacts, } from "./candidateOutputs.js";
|
|
@@ -18,13 +18,13 @@ import { capabilityIntents } from "@claudexor/gateway";
|
|
|
18
18
|
import { reviewCandidateRuns, resolveEngineReview, unreviewedCandidateEvidence, evaluateUnreviewedConvergence, } from "./candidateReview.js";
|
|
19
19
|
import { join } from "node:path";
|
|
20
20
|
import { finalizePlanRun, runCouncilPlan, writePlanHarnessFailure, } from "./planRun.js";
|
|
21
|
-
import { runPlannerAttempt as executePlannerAttempt, } from "./plannerAttempt.js";
|
|
21
|
+
import { runPlannerAttempt as executePlannerAttempt, plannerAttemptSummary, } from "./plannerAttempt.js";
|
|
22
22
|
import { HarnessRunSpec, MAX_COUNCIL_MEMBERS_DEFAULT, ModeKind as ModeKindSchema, QuotaSnapshot as QuotaSnapshotSchema, isBlocking, makeOutcomeFacts, reviewAllowsApply, workStateVetoes, strictifyOutputSchema, estimateEffectiveAuthRoute, } from "@claudexor/schema";
|
|
23
23
|
import { globalConfigDir, loadConfig } from "@claudexor/config";
|
|
24
24
|
import { prepareRoutedProcessing, processingCostEvidence, prepareReviewerProcessing, } from "./processing-routing.js";
|
|
25
25
|
import { acceptedTryOutput, AccessProfileIncompatibleError, AnswerAssembly, CLAUDEXOR_BROWSER_ARTIFACT_SUBDIR, countsAsAgentProgress, HarnessUnavailableError, summarizeDiffPaths as diffStats, withInactivityWatchdog, } from "@claudexor/core";
|
|
26
26
|
import { assertRouteModelsAllowed, runModelGovernedRoute } from "./modelGovernance.js";
|
|
27
|
-
import { authModeForCredentialRoute, authModeForPreference } from "./auth-route-classification.js";
|
|
27
|
+
import { authModeForCredentialRoute, authModeForPreference, authRouteEvidenceFor, } from "./auth-route-classification.js";
|
|
28
28
|
import { governRouteEffort } from "./effortGovernance.js";
|
|
29
29
|
import { isFullAccess, RequestRequirementsResolver } from "./requestRequirements.js";
|
|
30
30
|
import { activateDelegationParent } from "./delegation-parent-activation.js";
|
|
@@ -69,7 +69,7 @@ import { HarnessGateway } from "@claudexor/gateway";
|
|
|
69
69
|
import { ReadinessLedger, evaluateConvergence, failureSignature, gatesPassed, reviewCandidate, runGates, } from "@claudexor/review";
|
|
70
70
|
import { arbitrate } from "@claudexor/arbitration";
|
|
71
71
|
import { buildSynthesisPlan, decideSynthesis } from "@claudexor/synthesis";
|
|
72
|
-
import {
|
|
72
|
+
import { billingKnowledgeForAuthRoute, attemptUsageCostSettlement, BudgetLedger, isBudgetTerminal, RoutingPreflightError, explainRanking, loadHarnessMetrics, promptFingerprint, rankHarnesses, } from "@claudexor/budget";
|
|
73
73
|
import { readTextSafe, appendLine, assertNoInlineSecretValues, hashJson, newId, noProjectRepoRoot, redactSecrets, safeInvoke, sha256, userConfigDir, } from "@claudexor/util";
|
|
74
74
|
const LABELS = "ABCDEFGHIJ".split("");
|
|
75
75
|
const NO_PROJECT_ROOT = noProjectRepoRoot();
|
|
@@ -368,6 +368,8 @@ export class Orchestrator {
|
|
|
368
368
|
quotaAbsences: () => this.deps.quotaAbsences?.() ?? [],
|
|
369
369
|
credentialUnusable: () => this.deps.credentialUnusable?.() ?? [],
|
|
370
370
|
recordCredentialUnusable: (obs) => this.deps.recordCredentialUnusable?.(obs),
|
|
371
|
+
credentialObserverFactory: () => this.deps.credentialObserverFactory,
|
|
372
|
+
credentialEvidence: () => this.deps.credentialEvidence,
|
|
371
373
|
preProgressRefusals: () => this.deps.preProgressRefusals,
|
|
372
374
|
authPreferenceForHarness: (repoRoot, harnessId, runPreference) => this.authPreferenceForHarness(repoRoot, harnessId, runPreference),
|
|
373
375
|
});
|
|
@@ -489,9 +491,11 @@ export class Orchestrator {
|
|
|
489
491
|
dropped.push(detail);
|
|
490
492
|
droppedLanes.push({ harnessId, stage, detail });
|
|
491
493
|
};
|
|
492
|
-
//
|
|
493
|
-
//
|
|
494
|
+
// Initial lane readiness shares one quota observation. Selection and each
|
|
495
|
+
// physical dispatch still consume the latest exact-profile evidence.
|
|
494
496
|
const vendorQuota = this.credentials.vendorQuotaObservations();
|
|
497
|
+
// Billing later reuses the probe that admitted each row (#260).
|
|
498
|
+
const admissionProbes = new AdmissionProfileProbes();
|
|
495
499
|
const liveUnusable = this.deps.credentialUnusable?.() ?? [];
|
|
496
500
|
for (const id of ids) {
|
|
497
501
|
const adapter = this.deps.registry.get(id);
|
|
@@ -558,6 +562,7 @@ export class Orchestrator {
|
|
|
558
562
|
// the profile's transport, so the default store's state is not the
|
|
559
563
|
// routing truth). Capability/manifest gating above still applies.
|
|
560
564
|
const profileAdapter = this.deps.registry.get(id);
|
|
565
|
+
const profileProbe = admissionProbes.record(profileAdapter?.probeCredentialProfile?.bind(profileAdapter));
|
|
561
566
|
const explicitPin = this.credentials.effectiveProfileId(input, id);
|
|
562
567
|
// Pins and bound/pool rows are checked against their own readiness.
|
|
563
568
|
const rows = await this.credentials.admitRouteRows({
|
|
@@ -567,7 +572,7 @@ export class Orchestrator {
|
|
|
567
572
|
model: input.models?.[id] ?? cfgEntry?.default_model ?? null,
|
|
568
573
|
quota: vendorQuota,
|
|
569
574
|
unusable: liveUnusable,
|
|
570
|
-
probe:
|
|
575
|
+
probe: profileProbe,
|
|
571
576
|
});
|
|
572
577
|
const profileAdmitted = rows.admitted;
|
|
573
578
|
if (profileAdmitted) {
|
|
@@ -661,7 +666,7 @@ export class Orchestrator {
|
|
|
661
666
|
// the default store's sources apply only to profile-less runs.
|
|
662
667
|
authRouteEstimate: this.credentials.profileAuthRoute(input, id) ??
|
|
663
668
|
estimateEffectiveAuthRoute(this.authPreferenceForHarness(input.repoRoot, id, input.authPreference), status.authSources),
|
|
664
|
-
quotaAdmission: { model: null, profile: null, route: null },
|
|
669
|
+
quotaAdmission: { model: null, profile: null, route: null, profileVerification: null },
|
|
665
670
|
supportsSynthesize: manifest.capabilities.synthesize,
|
|
666
671
|
supportsInteractive: manifest.capabilities.interactive,
|
|
667
672
|
liveInput: manifest.capability_profile.live_input,
|
|
@@ -706,7 +711,7 @@ export class Orchestrator {
|
|
|
706
711
|
const model = input.models?.[routed.adapter.id] ?? routed.settings?.defaultModel ?? null;
|
|
707
712
|
let profile;
|
|
708
713
|
try {
|
|
709
|
-
profile = await this.credentials.preflightProfile(input, routed.adapter.id, model, log, routed.authRouteEstimate);
|
|
714
|
+
profile = await this.credentials.preflightProfile(input, routed.adapter.id, model, log, routed.authRouteEstimate, admissionProbes);
|
|
710
715
|
}
|
|
711
716
|
catch (err) {
|
|
712
717
|
// AUTO drops typed lane-local unavailability only when a sibling
|
|
@@ -730,8 +735,16 @@ export class Orchestrator {
|
|
|
730
735
|
: routed.authRouteEstimate === "local_session"
|
|
731
736
|
? "vendor_native"
|
|
732
737
|
: null;
|
|
738
|
+
const profileVerification = profile
|
|
739
|
+
? await this.credentials.selectedProfileBillingVerification(profile, admissionProbes)
|
|
740
|
+
: null;
|
|
733
741
|
return {
|
|
734
|
-
prepared: {
|
|
742
|
+
prepared: {
|
|
743
|
+
...routed,
|
|
744
|
+
quotaAdmission: { model, profile, route, profileVerification },
|
|
745
|
+
paidFallback: this.config(input.repoRoot).global.routing.paid_fallback,
|
|
746
|
+
billingVerificationForProfile: (actual) => this.credentials.selectedProfileBillingVerification(actual),
|
|
747
|
+
},
|
|
735
748
|
refused: null,
|
|
736
749
|
};
|
|
737
750
|
}));
|
|
@@ -862,13 +875,14 @@ export class Orchestrator {
|
|
|
862
875
|
// engine default. Profile A's cooldown never excludes profile B or the
|
|
863
876
|
// default on the same harness and route.
|
|
864
877
|
const credentialSubjectId = r.quotaAdmission.profile?.profile_id ?? null;
|
|
865
|
-
// QA-034: the typed auth-route evidence (
|
|
866
|
-
//
|
|
867
|
-
//
|
|
878
|
+
// QA-034: the typed auth-route evidence (the admitted profile's own
|
|
879
|
+
// verification, else doctor source verification, x the resolved route)
|
|
880
|
+
// is AUTHORITATIVE for billing knowledge in the router — a VERIFIED
|
|
881
|
+
// native route proves subscription_entitlement, so it survives
|
|
868
882
|
// paid_fallback:never and ranks with a real economy tuple instead of
|
|
869
883
|
// reading as unknown/paid. Absent (unknown route) falls back to the
|
|
870
884
|
// metric-derived billingKnowledge below.
|
|
871
|
-
const authRoute =
|
|
885
|
+
const authRoute = authRouteEvidenceFor(authMode, status?.authSources ?? [], r.quotaAdmission.profileVerification);
|
|
872
886
|
const processingCost = processingCostEvidence(r.processing, authRoute ? billingKnowledgeForAuthRoute(authRoute) : "unknown", [`harness:${r.adapter.id}`, `profile:${credentialSubjectId ?? "default"}`]);
|
|
873
887
|
return {
|
|
874
888
|
harnessId: r.adapter.id,
|
|
@@ -968,30 +982,6 @@ export class Orchestrator {
|
|
|
968
982
|
},
|
|
969
983
|
};
|
|
970
984
|
}
|
|
971
|
-
/**
|
|
972
|
-
* Typed auth-route evidence for one candidate (QA-034): the concrete
|
|
973
|
-
* credential route the resolved auth mode maps to, plus the doctor's
|
|
974
|
-
* verification for the source that route runs under. `local_session` →
|
|
975
|
-
* vendor_native + the native/OAuth source verification; `api_key` →
|
|
976
|
-
* managed_api_key + the key source verification. Unknown route → no evidence
|
|
977
|
-
* (the router keeps its conservative metric-derived billing). Verification is
|
|
978
|
-
* the source's typed verdict — never inferred from mere availability.
|
|
979
|
-
*/
|
|
980
|
-
authRouteEvidenceFor(authMode, sources) {
|
|
981
|
-
const usable = (s) => s.availability === "available" && s.verification !== "failed";
|
|
982
|
-
if (authMode === "local_session") {
|
|
983
|
-
const native = sources.find((s) => usable(s) && (s.source === "native_session" || s.source === "oauth_token_env"));
|
|
984
|
-
return { route: "vendor_native", verification: native?.verification ?? "not_run" };
|
|
985
|
-
}
|
|
986
|
-
if (authMode === "api_key") {
|
|
987
|
-
const key = sources.find((s) => usable(s) &&
|
|
988
|
-
(s.source === "api_key_env" ||
|
|
989
|
-
s.source === "api_key_flag" ||
|
|
990
|
-
s.source === "provider_auth_file"));
|
|
991
|
-
return { route: "managed_api_key", verification: key?.verification ?? "not_run" };
|
|
992
|
-
}
|
|
993
|
-
return undefined;
|
|
994
|
-
}
|
|
995
985
|
/**
|
|
996
986
|
* Lazy ContextPack: built ONLY for the read-only report modes
|
|
997
987
|
* (explore/plan/readonly_audit) that consume it. Persisted to
|
|
@@ -1234,6 +1224,9 @@ export class Orchestrator {
|
|
|
1234
1224
|
processing,
|
|
1235
1225
|
processingAdmission,
|
|
1236
1226
|
physicalDispatchStarted,
|
|
1227
|
+
credentialObserverFactory: this.deps.credentialObserverFactory,
|
|
1228
|
+
billingVerificationForProfile: (profile) => this.credentials.selectedProfileBillingVerification(profile),
|
|
1229
|
+
paidFallback: this.config(runInput.repoRoot).global.routing.paid_fallback,
|
|
1237
1230
|
});
|
|
1238
1231
|
const result = buildContinuation(req);
|
|
1239
1232
|
// Disclose on every lane and stamp the turn (INV-137: never silent).
|
|
@@ -1319,7 +1312,7 @@ export class Orchestrator {
|
|
|
1319
1312
|
const sessionFields = runInput
|
|
1320
1313
|
? await this.sessionSpecFields(runInput, adapter.id, knobs.model, log, routed.authRouteEstimate, routed.quotaAdmission)
|
|
1321
1314
|
: undefined;
|
|
1322
|
-
const processingAdmission = processingAdmissionForLease(ledger, processingLease.
|
|
1315
|
+
const processingAdmission = processingAdmissionForLease(ledger, processingLease.lease, adapter.id, attemptId, processingLease.onDenied);
|
|
1323
1316
|
const capturedProcessing = {
|
|
1324
1317
|
processing_preference: contract.processing_preference,
|
|
1325
1318
|
processing: knobs.processing?.receipt,
|
|
@@ -1327,7 +1320,7 @@ export class Orchestrator {
|
|
|
1327
1320
|
processing_allow_paid: knobs.processingAllowPaid,
|
|
1328
1321
|
};
|
|
1329
1322
|
const laneContinuity = runInput
|
|
1330
|
-
? await this.resolveContinuity(runInput, adapter.id, sessionFields?.credential_profile?.profile_id ?? runInput.credentialProfileId ?? null, inPlaceEnvelope && !!sessionFields?.resume_session_id, sessionFields, store, paths, envelope.repo_root, log, capturedProcessing, processingAdmission, () => ledger.markPhysicalDispatchStarted(processingLease.
|
|
1323
|
+
? await this.resolveContinuity(runInput, adapter.id, sessionFields?.credential_profile?.profile_id ?? runInput.credentialProfileId ?? null, inPlaceEnvelope && !!sessionFields?.resume_session_id, sessionFields, store, paths, envelope.repo_root, log, capturedProcessing, processingAdmission, () => ledger.markPhysicalDispatchStarted(processingLease.lease.lease_id))
|
|
1331
1324
|
: null;
|
|
1332
1325
|
const artifactRelativeDir = routed.browserRequirement.effective
|
|
1333
1326
|
? (wsm.ensureArtifactDirectory(envelope), wsm.ownedArtifactRelativeDirectory(envelope))
|
|
@@ -1372,16 +1365,12 @@ export class Orchestrator {
|
|
|
1372
1365
|
});
|
|
1373
1366
|
if (runInput)
|
|
1374
1367
|
this.credentials.stampProfileSelection(spec, runInput, adapter.id);
|
|
1375
|
-
bindProcessingAdmission(spec, ledger, processingLease.
|
|
1376
|
-
|
|
1377
|
-
//
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
? "metered"
|
|
1382
|
-
: actual.credential_profile
|
|
1383
|
-
? "subscription_entitlement"
|
|
1384
|
-
: this.routeBillingKnowledge(billingInput, adapter.id);
|
|
1368
|
+
bindProcessingAdmission(spec, ledger, processingLease.lease, adapter.id, attemptId, processingLease.onDenied, processingAdmission);
|
|
1369
|
+
// Profile-less processing keeps its existing route estimate. Named rows
|
|
1370
|
+
// receive their own verification at the shared physical-dispatch gate.
|
|
1371
|
+
spec.extra["routeBillingKnowledge"] = (actual) => actual.credential_profile
|
|
1372
|
+
? "unknown"
|
|
1373
|
+
: this.routeBillingKnowledge(runInput ?? { repoRoot: contract.repo.root }, adapter.id);
|
|
1385
1374
|
if (interaction)
|
|
1386
1375
|
spec.extra["interactionChannel"] = interaction;
|
|
1387
1376
|
const workEnvelope = this.workReportEnvelopeFor(routed, contract, Boolean(interaction));
|
|
@@ -1469,17 +1458,19 @@ export class Orchestrator {
|
|
|
1469
1458
|
suspensionVersion: () => interaction?.suspensionVersion?.() ?? 0,
|
|
1470
1459
|
});
|
|
1471
1460
|
for await (const ev of watched) {
|
|
1472
|
-
if (signal?.aborted)
|
|
1473
|
-
break;
|
|
1474
1461
|
rawPatch = captureRawPatchEnvelope(rawContextPacket !== null, rawPatch, ev);
|
|
1475
1462
|
if (ev.type === "patch_produced")
|
|
1476
1463
|
continue;
|
|
1477
1464
|
const safeEv = redactHarnessEvent(ev);
|
|
1478
1465
|
if (directory)
|
|
1479
1466
|
observeDirectoryPaths(observedPaths, safeEv, envelope.worktree_path);
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1467
|
+
const capped = dropDeltaPastBudget(safeEv, deltaFlood, Orchestrator.MAX_DELTAS_PER_ATTEMPT, (t, p) => log?.emit(t, p), adapter.id, attemptId);
|
|
1468
|
+
const display = !capped && safeEv.payload?.["buffered"] !== true;
|
|
1469
|
+
log?.emit("harness.event", harnessEventPayload(adapter.id, attemptId, safeEv), display);
|
|
1470
|
+
if (signal?.aborted)
|
|
1471
|
+
break;
|
|
1472
|
+
if (display)
|
|
1473
|
+
safeInvoke(onHarnessEvent, safeEv);
|
|
1483
1474
|
// In-place turns run in the live tree under the native environment, so
|
|
1484
1475
|
// the session they emit IS reachable for the next turn: record it. An
|
|
1485
1476
|
// ISOLATED envelope-born session lives in the scoped home that dispose()
|
|
@@ -1554,7 +1545,8 @@ export class Orchestrator {
|
|
|
1554
1545
|
// gate and required-actions read a typed category, not a bare boolean.
|
|
1555
1546
|
harnessErrored = true;
|
|
1556
1547
|
errors.push(safeErrorMessage(err));
|
|
1557
|
-
if (err instanceof ProcessingBudgetAdmissionError
|
|
1548
|
+
if (err instanceof ProcessingBudgetAdmissionError ||
|
|
1549
|
+
err instanceof RoutingPreflightError) {
|
|
1558
1550
|
processingRefusal = err;
|
|
1559
1551
|
break;
|
|
1560
1552
|
}
|
|
@@ -1778,6 +1770,12 @@ export class Orchestrator {
|
|
|
1778
1770
|
estimated: costEstimated,
|
|
1779
1771
|
settlement: attemptUsageCostSettlement(cost, costEstimated, attemptId, adapter.id, telemetry.authMode, telemetry.usageCost),
|
|
1780
1772
|
});
|
|
1773
|
+
for (const path of producedFiles)
|
|
1774
|
+
log?.emit("output.ready", {
|
|
1775
|
+
kind: "artifact",
|
|
1776
|
+
path: `attempts/${attemptId}/produced/${path}`,
|
|
1777
|
+
state: "diagnostic",
|
|
1778
|
+
});
|
|
1781
1779
|
return {
|
|
1782
1780
|
attemptId,
|
|
1783
1781
|
harnessId: adapter.id,
|
|
@@ -1948,7 +1946,7 @@ export class Orchestrator {
|
|
|
1948
1946
|
attemptId,
|
|
1949
1947
|
intent: this.candidateIntent(input),
|
|
1950
1948
|
harnessId: routed.adapter.id,
|
|
1951
|
-
cost:
|
|
1949
|
+
cost: processingAttemptCostEvidence(routed.adapter.id, attemptId, this.reservationEstimateUsd(input, i > 0), this.routeBillingKnowledge(input, routed.adapter.id, routed), routed.processing),
|
|
1952
1950
|
});
|
|
1953
1951
|
log.emit("budget.lease.created", {
|
|
1954
1952
|
granted: lease.granted,
|
|
@@ -1973,7 +1971,7 @@ export class Orchestrator {
|
|
|
1973
1971
|
routed,
|
|
1974
1972
|
attemptId,
|
|
1975
1973
|
label: `Candidate ${LABELS[i] ?? i + 1}`,
|
|
1976
|
-
|
|
1974
|
+
lease: lease.lease,
|
|
1977
1975
|
});
|
|
1978
1976
|
}
|
|
1979
1977
|
const runsBySlot = new Array(slots.length);
|
|
@@ -1984,14 +1982,14 @@ export class Orchestrator {
|
|
|
1984
1982
|
let candidateContinuationCount = 0;
|
|
1985
1983
|
const runSlot = async (slot, slotIdx) => {
|
|
1986
1984
|
if (input.signal?.aborted) {
|
|
1987
|
-
ledger.cancel(slot.
|
|
1985
|
+
ledger.cancel(slot.lease.lease_id);
|
|
1988
1986
|
return;
|
|
1989
1987
|
}
|
|
1990
1988
|
// Leases are granted upfront (before spend exists); a worker still
|
|
1991
1989
|
// re-checks the circuit breaker so queued slots beyond the parallel wave
|
|
1992
1990
|
// do not start after earlier candidates already blew the hard cap.
|
|
1993
1991
|
if (budgetStopped || ledger.tier() === "hard") {
|
|
1994
|
-
ledger.cancel(slot.
|
|
1992
|
+
ledger.cancel(slot.lease.lease_id);
|
|
1995
1993
|
log.emit("budget.lease.created", {
|
|
1996
1994
|
granted: false,
|
|
1997
1995
|
reason: "budget exhausted (hard cap reached)",
|
|
@@ -2055,24 +2053,20 @@ export class Orchestrator {
|
|
|
2055
2053
|
});
|
|
2056
2054
|
harnessHome = this.harnessHomeFor(wsm, envelope, slot.routed, input);
|
|
2057
2055
|
const run = await this.runCandidateInEnvelope(slot.routed, envelope, slot.attemptId, slot.label, contract, input.prompt, store, paths, wsm, ledger, {
|
|
2058
|
-
|
|
2056
|
+
lease: slot.lease,
|
|
2059
2057
|
onDenied: (denial) => {
|
|
2060
2058
|
budgetStopped = true;
|
|
2061
2059
|
budgetDenial ??= denial;
|
|
2062
2060
|
},
|
|
2063
|
-
}, candidateAccess, (
|
|
2064
|
-
|
|
2065
|
-
safeInvoke(input.onHarnessEvent, safeEv);
|
|
2066
|
-
log.emit("harness.event", harnessEventPayload(adapter.id, slot.attemptId, safeEv));
|
|
2067
|
-
}, input.signal, downgradeModel ?? undefined, input.effort, this.candidateIntent(input), log, effectiveWeb, this.interactionChannelFor(input, log, runId, taskId, slot.attemptId, adapter.id, slot.routed.supportsInteractive), (streamedUsd) => {
|
|
2068
|
-
ledger.updateHold(slot.leaseId, streamedUsd);
|
|
2061
|
+
}, candidateAccess, input.onHarnessEvent, input.signal, downgradeModel ?? undefined, input.effort, this.candidateIntent(input), log, effectiveWeb, this.interactionChannelFor(input, log, runId, taskId, slot.attemptId, adapter.id, slot.routed.supportsInteractive), (streamedUsd) => {
|
|
2062
|
+
ledger.updateHold(slot.lease.lease_id, streamedUsd);
|
|
2069
2063
|
if (ledger.tier() !== "hard")
|
|
2070
2064
|
return false;
|
|
2071
2065
|
budgetStopped = true;
|
|
2072
2066
|
return true;
|
|
2073
2067
|
}, input, requestedSingleCandidate, // W-C4 deltas: single-candidate chat lane only (racing = noise x N)
|
|
2074
2068
|
undefined, undefined, harnessHome);
|
|
2075
|
-
ledger.settle(slot.
|
|
2069
|
+
ledger.settle(slot.lease.lease_id, attemptUsageCostSettlement(run.cost, run.costEstimated, run.attemptId, run.harnessId, run.telemetry.authMode, run.telemetry.usageCost));
|
|
2076
2070
|
log.emit("harness.completed", {
|
|
2077
2071
|
harness_id: adapter.id,
|
|
2078
2072
|
attempt_id: slot.attemptId,
|
|
@@ -2118,7 +2112,7 @@ export class Orchestrator {
|
|
|
2118
2112
|
attemptId: contAttemptId,
|
|
2119
2113
|
intent: this.candidateIntent(input),
|
|
2120
2114
|
harnessId: adapter.id,
|
|
2121
|
-
cost:
|
|
2115
|
+
cost: processingAttemptCostEvidence(adapter.id, contAttemptId, this.estimateUsdFloor(input.repoRoot), this.routeBillingKnowledge(input, adapter.id, slot.routed), slot.routed.processing),
|
|
2122
2116
|
});
|
|
2123
2117
|
if (contLease.granted) {
|
|
2124
2118
|
candidateContinuationCount += 1; // claim the one-shot only once it launches
|
|
@@ -2138,16 +2132,12 @@ export class Orchestrator {
|
|
|
2138
2132
|
const contLeaseId = contLease.lease?.lease_id ?? "";
|
|
2139
2133
|
try {
|
|
2140
2134
|
const contRun = await this.runCandidateInEnvelope(slot.routed, envelope, contAttemptId, slot.label, contract, input.prompt, store, paths, wsm, ledger, {
|
|
2141
|
-
|
|
2135
|
+
lease: contLease.lease,
|
|
2142
2136
|
onDenied: (denial) => {
|
|
2143
2137
|
budgetStopped = true;
|
|
2144
2138
|
budgetDenial ??= denial;
|
|
2145
2139
|
},
|
|
2146
|
-
}, candidateAccess, (
|
|
2147
|
-
const safeEv = redactHarnessEvent(ev);
|
|
2148
|
-
safeInvoke(input.onHarnessEvent, safeEv);
|
|
2149
|
-
log.emit("harness.event", harnessEventPayload(adapter.id, contAttemptId, safeEv));
|
|
2150
|
-
}, input.signal, downgradeModel ?? undefined, input.effort, this.candidateIntent(input), log, effectiveWeb, this.interactionChannelFor(input, log, runId, taskId, contAttemptId, adapter.id, slot.routed.supportsInteractive), (streamedUsd) => {
|
|
2140
|
+
}, candidateAccess, input.onHarnessEvent, input.signal, downgradeModel ?? undefined, input.effort, this.candidateIntent(input), log, effectiveWeb, this.interactionChannelFor(input, log, runId, taskId, contAttemptId, adapter.id, slot.routed.supportsInteractive), (streamedUsd) => {
|
|
2151
2141
|
ledger.updateHold(contLeaseId, streamedUsd);
|
|
2152
2142
|
if (ledger.tier() !== "hard")
|
|
2153
2143
|
return false;
|
|
@@ -2197,7 +2187,7 @@ export class Orchestrator {
|
|
|
2197
2187
|
}
|
|
2198
2188
|
catch (err) {
|
|
2199
2189
|
const failureCost = AC.attemptFailureCost(err, "post-stream-error", 0);
|
|
2200
|
-
ledger.settle(slot.
|
|
2190
|
+
ledger.settle(slot.lease.lease_id, failureCost.settlement);
|
|
2201
2191
|
const message = safeErrorMessage(err);
|
|
2202
2192
|
const declared = declaredFailure(err);
|
|
2203
2193
|
const infraPhase = envelope === undefined ? "workspace" : "harness";
|
|
@@ -2251,6 +2241,16 @@ export class Orchestrator {
|
|
|
2251
2241
|
mode,
|
|
2252
2242
|
ledger,
|
|
2253
2243
|
runs,
|
|
2244
|
+
git: input.workspaceKind !== "directory"
|
|
2245
|
+
? {
|
|
2246
|
+
live: input.inPlace === true &&
|
|
2247
|
+
requestedSingleCandidate &&
|
|
2248
|
+
runs[0]?.reviewCwd === execRoot,
|
|
2249
|
+
execRoot,
|
|
2250
|
+
preTurnSha,
|
|
2251
|
+
postTurnSha: earlyPostTurnSha,
|
|
2252
|
+
}
|
|
2253
|
+
: undefined,
|
|
2254
2254
|
signal: input.signal,
|
|
2255
2255
|
writeTelemetry: () => this.writeRunTelemetry(store, paths, contract, runId, taskId, mode, candidateRoster(runs), null),
|
|
2256
2256
|
});
|
|
@@ -2404,7 +2404,7 @@ export class Orchestrator {
|
|
|
2404
2404
|
attemptId: "synth",
|
|
2405
2405
|
intent: "synthesize",
|
|
2406
2406
|
harnessId: synthRouted.adapter.id,
|
|
2407
|
-
cost:
|
|
2407
|
+
cost: processingAttemptCostEvidence(synthRouted.adapter.id, "synth", this.reservationEstimateUsd(input), this.routeBillingKnowledge(input, synthRouted.adapter.id, synthRouted), synthRouted.processing),
|
|
2408
2408
|
});
|
|
2409
2409
|
if (lease.granted) {
|
|
2410
2410
|
let envelope;
|
|
@@ -2431,16 +2431,12 @@ export class Orchestrator {
|
|
|
2431
2431
|
});
|
|
2432
2432
|
const synthHome = this.harnessHomeFor(wsm, envelope, synthRouted, input);
|
|
2433
2433
|
const run = await this.runCandidateInEnvelope(synthRouted, envelope, "synth", "Synthesis", contract, synthesisInput.prompt, store, paths, wsm, ledger, {
|
|
2434
|
-
|
|
2434
|
+
lease: lease.lease,
|
|
2435
2435
|
onDenied: (denial) => {
|
|
2436
2436
|
budgetStopped = true;
|
|
2437
2437
|
budgetDenial ??= denial;
|
|
2438
2438
|
},
|
|
2439
|
-
}, candidateAccess, (
|
|
2440
|
-
const safeEv = redactHarnessEvent(ev);
|
|
2441
|
-
safeInvoke(input.onHarnessEvent, safeEv);
|
|
2442
|
-
log.emit("harness.event", harnessEventPayload(synthAdapter.id, "synth", safeEv));
|
|
2443
|
-
}, input.signal, undefined, input.effort, "synthesize", log, effectiveWeb, this.interactionChannelFor(input, log, runId, taskId, "synth", synthAdapter.id, synthRouted.supportsInteractive), undefined, input, false, synthesisInput.content, undefined, synthHome);
|
|
2439
|
+
}, candidateAccess, input.onHarnessEvent, input.signal, undefined, input.effort, "synthesize", log, effectiveWeb, this.interactionChannelFor(input, log, runId, taskId, "synth", synthAdapter.id, synthRouted.supportsInteractive), undefined, input, false, synthesisInput.content, undefined, synthHome);
|
|
2444
2440
|
ledger.settle(lease.lease?.lease_id ?? "", attemptUsageCostSettlement(run.cost, run.costEstimated, run.attemptId, run.harnessId, run.telemetry.authMode, run.telemetry.usageCost));
|
|
2445
2441
|
reviewEnvelopes.push(envelope);
|
|
2446
2442
|
envelope = undefined;
|
|
@@ -2744,6 +2740,7 @@ export class Orchestrator {
|
|
|
2744
2740
|
pre_turn_sha: preTurnSha,
|
|
2745
2741
|
post_turn_sha: postTurnSha,
|
|
2746
2742
|
revert_anchor_id: revertAnchorId,
|
|
2743
|
+
execution_root: adopted === true ? execRoot : null,
|
|
2747
2744
|
},
|
|
2748
2745
|
});
|
|
2749
2746
|
}
|
|
@@ -2923,6 +2920,7 @@ export class Orchestrator {
|
|
|
2923
2920
|
reviewScoped(input) {
|
|
2924
2921
|
return reviewCandidate({
|
|
2925
2922
|
...input,
|
|
2923
|
+
credentialObserverFactory: this.deps.credentialObserverFactory,
|
|
2926
2924
|
reviewerTimeoutMs: input.reviewerTimeoutMs ?? reviewerTimeoutMs(this.config(input.cwd)),
|
|
2927
2925
|
transientRetryPolicy: input.transientRetryPolicy ?? transientRetryPolicy(this.config(input.cwd)),
|
|
2928
2926
|
});
|
|
@@ -3211,7 +3209,7 @@ export class Orchestrator {
|
|
|
3211
3209
|
attemptId,
|
|
3212
3210
|
intent: "repair",
|
|
3213
3211
|
harnessId: adapter.id,
|
|
3214
|
-
cost:
|
|
3212
|
+
cost: processingAttemptCostEvidence(adapter.id, attemptId, this.reservationEstimateUsd(input), this.routeBillingKnowledge(input, adapter.id, routed), routed.processing),
|
|
3215
3213
|
});
|
|
3216
3214
|
if (!lease.granted) {
|
|
3217
3215
|
exhausted = true;
|
|
@@ -3230,16 +3228,12 @@ export class Orchestrator {
|
|
|
3230
3228
|
...(knobs.ignored.length > 0 ? { ignored_settings: knobs.ignored } : {}),
|
|
3231
3229
|
});
|
|
3232
3230
|
run = await this.runCandidateInEnvelope(routed, envelope, attemptId, `Attempt ${attempt}`, contract, prompt, store, paths, wsm, ledger, {
|
|
3233
|
-
|
|
3231
|
+
lease: lease.lease,
|
|
3234
3232
|
onDenied: (denial) => {
|
|
3235
3233
|
exhausted = true;
|
|
3236
3234
|
processingBudgetDenial ??= denial;
|
|
3237
3235
|
},
|
|
3238
|
-
}, convergenceAccess, (
|
|
3239
|
-
const safeEv = redactHarnessEvent(ev);
|
|
3240
|
-
safeInvoke(input.onHarnessEvent, safeEv);
|
|
3241
|
-
log.emit("harness.event", harnessEventPayload(adapter.id, attemptId, safeEv));
|
|
3242
|
-
}, input.signal, undefined, input.effort, "repair", log, effectiveWeb, this.interactionChannelFor(input, log, runId, taskId, attemptId, adapter.id, routed.supportsInteractive), (streamedUsd) => {
|
|
3236
|
+
}, convergenceAccess, input.onHarnessEvent, input.signal, undefined, input.effort, "repair", log, effectiveWeb, this.interactionChannelFor(input, log, runId, taskId, attemptId, adapter.id, routed.supportsInteractive), (streamedUsd) => {
|
|
3243
3237
|
ledger.updateHold(lease.lease?.lease_id ?? "", streamedUsd);
|
|
3244
3238
|
return ledger.tier() === "hard";
|
|
3245
3239
|
}, input, true, // convergence runs one candidate: live deltas on (W-C4)
|
|
@@ -3300,6 +3294,20 @@ export class Orchestrator {
|
|
|
3300
3294
|
// per attempt, so the proof is spent per attempt.
|
|
3301
3295
|
assertDelegatedEvidence(input.delegated === true, convergenceAccess, [run]);
|
|
3302
3296
|
attemptTelemetries.push({ attemptId, harnessId: adapter.id, telemetry: run.telemetry });
|
|
3297
|
+
lastPostTurnSha = null;
|
|
3298
|
+
// Post-mutation fence for in-place: snapshot the live tree NOW (after the
|
|
3299
|
+
// harness mutated it, before this attempt's review). The last attempt's
|
|
3300
|
+
// value is the revert target persisted into work_product.yaml.
|
|
3301
|
+
if (input.inPlace === true &&
|
|
3302
|
+
input.workspaceKind !== "directory" &&
|
|
3303
|
+
!run.secretDiffRefusal) {
|
|
3304
|
+
try {
|
|
3305
|
+
lastPostTurnSha = await snapshotTree(execRoot);
|
|
3306
|
+
}
|
|
3307
|
+
catch {
|
|
3308
|
+
lastPostTurnSha = null;
|
|
3309
|
+
}
|
|
3310
|
+
}
|
|
3303
3311
|
// Cancellation/deadline keeps priority over a belt failure finalized concurrently.
|
|
3304
3312
|
if (input.signal?.aborted || processingBudgetDenial)
|
|
3305
3313
|
break;
|
|
@@ -3351,17 +3359,6 @@ export class Orchestrator {
|
|
|
3351
3359
|
interrupted = true;
|
|
3352
3360
|
break;
|
|
3353
3361
|
}
|
|
3354
|
-
// Post-mutation fence for in-place: snapshot the live tree NOW (after the
|
|
3355
|
-
// harness mutated it, before this attempt's review). The last attempt's
|
|
3356
|
-
// value is the revert target persisted into work_product.yaml.
|
|
3357
|
-
if (input.inPlace === true && input.workspaceKind !== "directory") {
|
|
3358
|
-
try {
|
|
3359
|
-
lastPostTurnSha = await snapshotTree(execRoot);
|
|
3360
|
-
}
|
|
3361
|
-
catch {
|
|
3362
|
-
lastPostTurnSha = null;
|
|
3363
|
-
}
|
|
3364
|
-
}
|
|
3365
3362
|
// The review round is wrapped so a preflight/revalidation throw ends the
|
|
3366
3363
|
// run TERMINALLY with artifacts instead of orphaning the run dir.
|
|
3367
3364
|
let conv;
|
|
@@ -3644,6 +3641,7 @@ export class Orchestrator {
|
|
|
3644
3641
|
pre_turn_sha: convAdopted === true ? preTurnSha : null,
|
|
3645
3642
|
post_turn_sha: convAdopted === true ? lastPostTurnSha : null,
|
|
3646
3643
|
revert_anchor_id: revertAnchorId,
|
|
3644
|
+
execution_root: convAdopted === true ? execRoot : null,
|
|
3647
3645
|
},
|
|
3648
3646
|
});
|
|
3649
3647
|
}
|
|
@@ -3796,17 +3794,17 @@ export class Orchestrator {
|
|
|
3796
3794
|
/** Bind private route/session preparation to the planner-attempt owner. */
|
|
3797
3795
|
plannerAttemptDeps() {
|
|
3798
3796
|
return {
|
|
3799
|
-
billingKnowledge: (input, harnessId) => this.routeBillingKnowledge(input, harnessId),
|
|
3797
|
+
billingKnowledge: (input, harnessId, routed) => this.routeBillingKnowledge(input, harnessId, routed),
|
|
3800
3798
|
inactivityTimeoutMs: (repoRoot) => harnessInactivityTimeoutMs(this.config(repoRoot)),
|
|
3801
3799
|
quotaEventSink: this.deps.quotaEventSink,
|
|
3802
|
-
prepare: async (args) => {
|
|
3800
|
+
prepare: async (args, processingAdmission, physicalDispatchStarted) => {
|
|
3803
3801
|
const { input, contract, taskId, runId, log, store, paths, routed, attemptId } = args;
|
|
3804
3802
|
const adapter = routed.adapter;
|
|
3805
3803
|
const knobs = this.routeSpecKnobs(routed, contract, undefined, input.effort);
|
|
3806
3804
|
const effectiveWeb = this.discloseWebUpgrade(log, routed, knobs.webPolicy, attemptId);
|
|
3807
3805
|
const sessionFields = await this.sessionSpecFields(input, adapter.id, knobs.model, log, routed.authRouteEstimate, routed.quotaAdmission);
|
|
3808
3806
|
const laneContinuity = args.laneRun
|
|
3809
|
-
? await this.resolveContinuity(input, adapter.id, sessionFields.credential_profile?.profile_id ?? input.credentialProfileId ?? null, sessionFields.resume_session_id !== null, sessionFields, store, paths, this.execRootOf(input), log)
|
|
3807
|
+
? await this.resolveContinuity(input, adapter.id, sessionFields.credential_profile?.profile_id ?? input.credentialProfileId ?? null, sessionFields.resume_session_id !== null, sessionFields, store, paths, this.execRootOf(input), log, this.harnessSpecKnobs(contract, knobs, args.intent), processingAdmission, physicalDispatchStarted)
|
|
3810
3808
|
: null;
|
|
3811
3809
|
const spec = HarnessRunSpec.parse({
|
|
3812
3810
|
session_id: newId("ses"),
|
|
@@ -3995,13 +3993,7 @@ export class Orchestrator {
|
|
|
3995
3993
|
// terminal names the refused route and does not read "all planners
|
|
3996
3994
|
// failed"; capture the typed denial for the budget classifier.
|
|
3997
3995
|
planBudgetDenial ??= outcome.budgetDenial ?? null;
|
|
3998
|
-
planAttempts.push(
|
|
3999
|
-
attemptId,
|
|
4000
|
-
harnessId: outcome.harnessId,
|
|
4001
|
-
status: outcome.status,
|
|
4002
|
-
outcomeClass: outcome.outcomeClass,
|
|
4003
|
-
error: outcome.error,
|
|
4004
|
-
});
|
|
3996
|
+
planAttempts.push(plannerAttemptSummary(outcome));
|
|
4005
3997
|
break;
|
|
4006
3998
|
}
|
|
4007
3999
|
if (outcome.telemetry)
|
|
@@ -4010,13 +4002,7 @@ export class Orchestrator {
|
|
|
4010
4002
|
harnessId: outcome.harnessId,
|
|
4011
4003
|
telemetry: outcome.telemetry,
|
|
4012
4004
|
});
|
|
4013
|
-
planAttempts.push(
|
|
4014
|
-
attemptId,
|
|
4015
|
-
harnessId: outcome.harnessId,
|
|
4016
|
-
status: outcome.status,
|
|
4017
|
-
outcomeClass: outcome.outcomeClass,
|
|
4018
|
-
error: outcome.error,
|
|
4019
|
-
});
|
|
4005
|
+
planAttempts.push(plannerAttemptSummary(outcome));
|
|
4020
4006
|
if (outcome.status !== "success") {
|
|
4021
4007
|
if (outcome.telemetry?.effortResolution?.resolution === "rejected")
|
|
4022
4008
|
break;
|
|
@@ -4141,7 +4127,13 @@ export class Orchestrator {
|
|
|
4141
4127
|
quotaSnapshotPreflight() {
|
|
4142
4128
|
return [...(this.deps.quotaSnapshots?.() ?? [])].map((snapshot) => QuotaSnapshotSchema.parse(snapshot));
|
|
4143
4129
|
}
|
|
4144
|
-
routeBillingKnowledge(input, harnessId) {
|
|
4130
|
+
routeBillingKnowledge(input, harnessId, routed) {
|
|
4131
|
+
if (routed?.quotaAdmission.profile) {
|
|
4132
|
+
return billingKnowledgeForAuthRoute({
|
|
4133
|
+
route: routed.quotaAdmission.route,
|
|
4134
|
+
verification: routed.quotaAdmission.profileVerification ?? "not_run",
|
|
4135
|
+
});
|
|
4136
|
+
}
|
|
4145
4137
|
// A selected profile's credential_kind decides billing (round-18 #2).
|
|
4146
4138
|
const profileRoute = this.credentials.profileAuthRoute(input, harnessId);
|
|
4147
4139
|
if (profileRoute)
|
|
@@ -4173,9 +4165,7 @@ export class Orchestrator {
|
|
|
4173
4165
|
// The reducer admits under a finite estimate floor (mirror of the n>1
|
|
4174
4166
|
// scout reserve) so a subscription route is not refused for lacking a
|
|
4175
4167
|
// cash quote.
|
|
4176
|
-
|
|
4177
|
-
`harness:${harnessId}`,
|
|
4178
|
-
])),
|
|
4168
|
+
processingAttemptCostEvidence(harnessId, attemptId, this.estimateUsdFloor(input.repoRoot), this.routeBillingKnowledge(input, harnessId, routed), routed?.processing),
|
|
4179
4169
|
buildSpec: async (routed, homeEnv, prompt, attemptId) => {
|
|
4180
4170
|
const knobs = this.routeSpecKnobs(routed, contract, undefined, input.effort);
|
|
4181
4171
|
const effectiveWeb = this.discloseWebUpgrade(log, routed, knobs.webPolicy, attemptId);
|
|
@@ -4349,7 +4339,7 @@ export class Orchestrator {
|
|
|
4349
4339
|
// (mirror of the candidate loop): the first top-level scout reserves
|
|
4350
4340
|
// without a floor; later scouts and every real Delegate child pass the
|
|
4351
4341
|
// repo floor because they overlap an existing family unit.
|
|
4352
|
-
cost:
|
|
4342
|
+
cost: processingAttemptCostEvidence(adapter.id, attemptId, this.reservationEstimateUsd(input, opts.deepScan && idx > 0), this.routeBillingKnowledge(input, adapter.id, routed), routed.processing),
|
|
4353
4343
|
});
|
|
4354
4344
|
if (!lease.granted) {
|
|
4355
4345
|
log.emit("budget.lease.created", {
|
|
@@ -4378,6 +4368,10 @@ export class Orchestrator {
|
|
|
4378
4368
|
}
|
|
4379
4369
|
return { status: "budget_denied", reason: lease.reason ?? "budget lease denied" };
|
|
4380
4370
|
}
|
|
4371
|
+
const processingAdmission = processingAdmissionForLease(ledger, lease.lease, adapter.id, attemptId, (denial) => {
|
|
4372
|
+
budgetStopped = true;
|
|
4373
|
+
budgetDenial ??= denial;
|
|
4374
|
+
});
|
|
4381
4375
|
// As with planners, the granted lease owns profile/continuity/spec
|
|
4382
4376
|
// preparation. Contain a pre-stream rejection as this attempt's failure;
|
|
4383
4377
|
// parallel siblings can then finish before the shared HOME is disposed.
|
|
@@ -4398,7 +4392,7 @@ export class Orchestrator {
|
|
|
4398
4392
|
// scouts are excluded from laneRun); native resume is available only when
|
|
4399
4393
|
// this slot was granted the lane's recorded session.
|
|
4400
4394
|
const laneContinuity = laneRun
|
|
4401
|
-
? await this.resolveContinuity(input, adapter.id, sessionFields.credential_profile?.profile_id ?? input.credentialProfileId ?? null, grantResume, sessionFields, store, paths, this.execRootOf(input), log)
|
|
4395
|
+
? await this.resolveContinuity(input, adapter.id, sessionFields.credential_profile?.profile_id ?? input.credentialProfileId ?? null, grantResume, sessionFields, store, paths, this.execRootOf(input), log, this.harnessSpecKnobs(contract, knobs, opts.intent), processingAdmission, () => ledger.markPhysicalDispatchStarted(lease.lease.lease_id))
|
|
4402
4396
|
: null;
|
|
4403
4397
|
// D-16d: the continuation packet pointer rides after the lane pointer so
|
|
4404
4398
|
// the fresh session is re-grounded in the exhausted attempt's work.
|
|
@@ -4457,7 +4451,7 @@ export class Orchestrator {
|
|
|
4457
4451
|
const message = `read-only attempt setup failed: ${safeErrorMessage(preparation.error)}`;
|
|
4458
4452
|
AC.settleGrantedAttemptLease({
|
|
4459
4453
|
ledger,
|
|
4460
|
-
leaseId: lease.lease
|
|
4454
|
+
leaseId: lease.lease.lease_id,
|
|
4461
4455
|
attemptId,
|
|
4462
4456
|
harnessId: adapter.id,
|
|
4463
4457
|
costUsd: 0,
|
|
@@ -4490,10 +4484,7 @@ export class Orchestrator {
|
|
|
4490
4484
|
const { knobs, spec: preparedSpec, reportAbort, reportInteraction, readonlyWorkMode, attemptEventsPath, telemetry, } = preparation.value;
|
|
4491
4485
|
let { answer } = preparation.value;
|
|
4492
4486
|
let spec = preparedSpec;
|
|
4493
|
-
bindProcessingAdmission(spec, ledger, lease.lease
|
|
4494
|
-
budgetStopped = true;
|
|
4495
|
-
budgetDenial ??= denial;
|
|
4496
|
-
});
|
|
4487
|
+
bindProcessingAdmission(spec, ledger, lease.lease, adapter.id, attemptId, undefined, processingAdmission);
|
|
4497
4488
|
const retryPolicy = transientRetryPolicy(this.config(input.repoRoot));
|
|
4498
4489
|
let activeSessionId = spec.session_id;
|
|
4499
4490
|
const live = liveAttempt(input, routed, paths, contract, attemptId, () => activeSessionId);
|
|
@@ -4552,10 +4543,9 @@ export class Orchestrator {
|
|
|
4552
4543
|
suspensionVersion: () => reportInteraction?.suspensionVersion?.() ?? 0,
|
|
4553
4544
|
});
|
|
4554
4545
|
for await (const ev of watchedReport) {
|
|
4555
|
-
if (input.signal?.aborted)
|
|
4556
|
-
break;
|
|
4557
4546
|
const safeEv = redactHarnessEvent(ev);
|
|
4558
|
-
|
|
4547
|
+
if (safeEv.payload?.["buffered"] !== true)
|
|
4548
|
+
safeInvoke(input.onHarnessEvent, safeEv);
|
|
4559
4549
|
// A thread ASK turn IS a chat turn now (INV-034): its native
|
|
4560
4550
|
// session lives in the DURABLE per-lane home, so record it for the
|
|
4561
4551
|
// next lane turn's resume. The read-only fallback chain is
|
|
@@ -4565,8 +4555,10 @@ export class Orchestrator {
|
|
|
4565
4555
|
if (laneRun)
|
|
4566
4556
|
observeNativeSessionEvent(input, adapter.id, safeEv);
|
|
4567
4557
|
observeAuthSwitch(log, adapter.id, attemptId, safeEv);
|
|
4568
|
-
log.emit("harness.event", harnessEventPayload(adapter.id, attemptId, safeEv));
|
|
4558
|
+
log.emit("harness.event", harnessEventPayload(adapter.id, attemptId, safeEv), safeEv.payload?.["buffered"] !== true);
|
|
4569
4559
|
appendLine(attemptEventsPath, JSON.stringify(safeEv));
|
|
4560
|
+
if (input.signal?.aborted)
|
|
4561
|
+
break;
|
|
4570
4562
|
observeAttemptTelemetry(telemetry, safeEv);
|
|
4571
4563
|
emitPlanProgress((t, p) => log.emit(t, p), adapter.id, attemptId, safeEv);
|
|
4572
4564
|
// read-only routes burn quota too (the orchestrate PLANNER is
|
|
@@ -4595,7 +4587,8 @@ export class Orchestrator {
|
|
|
4595
4587
|
}
|
|
4596
4588
|
catch (err) {
|
|
4597
4589
|
harnessError = safeErrorMessage(err);
|
|
4598
|
-
if (err instanceof ProcessingBudgetAdmissionError
|
|
4590
|
+
if (err instanceof ProcessingBudgetAdmissionError ||
|
|
4591
|
+
err instanceof RoutingPreflightError) {
|
|
4599
4592
|
processingRefusal = err;
|
|
4600
4593
|
break;
|
|
4601
4594
|
}
|
|
@@ -4676,7 +4669,7 @@ export class Orchestrator {
|
|
|
4676
4669
|
input.signal?.removeEventListener("abort", onAbort);
|
|
4677
4670
|
AC.settleGrantedAttemptLease({
|
|
4678
4671
|
ledger,
|
|
4679
|
-
leaseId: lease.lease
|
|
4672
|
+
leaseId: lease.lease.lease_id,
|
|
4680
4673
|
attemptId,
|
|
4681
4674
|
harnessId: adapter.id,
|
|
4682
4675
|
costUsd: cost,
|
|
@@ -4962,14 +4955,6 @@ export class Orchestrator {
|
|
|
4962
4955
|
fallbackOpen = false;
|
|
4963
4956
|
}
|
|
4964
4957
|
const partialReport = [...attempts].reverse().find((a) => a.report)?.report ?? "";
|
|
4965
|
-
if (partialReport) {
|
|
4966
|
-
store.writeText(join(paths.finalDir, opts.artifactName), `# ${opts.title}\n\n> Unverified partial output. The run is ${webBlocked ? "blocked" : "failed"} because a required/attempted tool failed.\n\n${partialReport}\n`);
|
|
4967
|
-
log.emit("output.ready", {
|
|
4968
|
-
kind: opts.mode === "ask" ? "answer" : "report",
|
|
4969
|
-
path: `final/${opts.artifactName}`,
|
|
4970
|
-
state: "diagnostic",
|
|
4971
|
-
});
|
|
4972
|
-
}
|
|
4973
4958
|
this.writeRunTelemetry(store, paths, contract, runId, taskId, opts.mode, attemptTelemetries, null);
|
|
4974
4959
|
store.writeText(join(paths.contextDir, "context_error.md"), `# ${budgetMapping ? "Budget Denied" : "Harness Error"}\n\n${singleError}\n`);
|
|
4975
4960
|
const roEventRefs = attempts.map((a) => `attempts/${a.attemptId}/events.jsonl`);
|