audit-tools 0.33.0 → 0.33.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.
- package/README.md +7 -0
- package/dist/audit/cli/args.d.ts.map +1 -1
- package/dist/audit/cli/args.js +3 -0
- package/dist/audit/cli/args.js.map +1 -1
- package/dist/audit/cli/hybridDispatch.d.ts.map +1 -1
- package/dist/audit/cli/hybridDispatch.js +5 -0
- package/dist/audit/cli/hybridDispatch.js.map +1 -1
- package/dist/audit/cli/nextStepCommand.d.ts.map +1 -1
- package/dist/audit/cli/nextStepCommand.js +23 -1
- package/dist/audit/cli/nextStepCommand.js.map +1 -1
- package/dist/audit/cli/rollingAuditDispatch.d.ts.map +1 -1
- package/dist/audit/cli/rollingAuditDispatch.js +14 -1
- package/dist/audit/cli/rollingAuditDispatch.js.map +1 -1
- package/dist/audit/cli.js +3 -3
- package/dist/audit/cli.js.map +1 -1
- package/dist/audit/orchestrator/rollingDispatch.d.ts.map +1 -1
- package/dist/audit/orchestrator/rollingDispatch.js +2 -0
- package/dist/audit/orchestrator/rollingDispatch.js.map +1 -1
- package/dist/audit/providers/claudeWorkerProvider.d.ts +10 -0
- package/dist/audit/providers/claudeWorkerProvider.d.ts.map +1 -0
- package/dist/audit/providers/claudeWorkerProvider.js +15 -0
- package/dist/audit/providers/claudeWorkerProvider.js.map +1 -0
- package/dist/audit/providers/index.d.ts.map +1 -1
- package/dist/audit/providers/index.js +2 -0
- package/dist/audit/providers/index.js.map +1 -1
- package/dist/audit/quota/index.d.ts +15 -10
- package/dist/audit/quota/index.d.ts.map +1 -1
- package/dist/remediate/index.d.ts.map +1 -1
- package/dist/remediate/index.js +2 -2
- package/dist/remediate/index.js.map +1 -1
- package/dist/remediate/providers/claudeWorkerProvider.d.ts +11 -0
- package/dist/remediate/providers/claudeWorkerProvider.d.ts.map +1 -0
- package/dist/remediate/providers/claudeWorkerProvider.js +16 -0
- package/dist/remediate/providers/claudeWorkerProvider.js.map +1 -0
- package/dist/remediate/providers/index.d.ts.map +1 -1
- package/dist/remediate/providers/index.js +2 -0
- package/dist/remediate/providers/index.js.map +1 -1
- package/dist/remediate/steps/dispatch/acceptNode.d.ts +1 -1
- package/dist/remediate/steps/dispatch/acceptNode.d.ts.map +1 -1
- package/dist/remediate/steps/dispatch/acceptNode.js.map +1 -1
- package/dist/remediate/steps/nextStep.d.ts +21 -0
- package/dist/remediate/steps/nextStep.d.ts.map +1 -1
- package/dist/remediate/steps/nextStep.js +21 -2
- package/dist/remediate/steps/nextStep.js.map +1 -1
- package/dist/remediate/steps/sessionConfigLoad.d.ts.map +1 -1
- package/dist/remediate/steps/sessionConfigLoad.js +8 -1
- package/dist/remediate/steps/sessionConfigLoad.js.map +1 -1
- package/dist/shared/config/resolveSessionConfig.d.ts +6 -3
- package/dist/shared/config/resolveSessionConfig.d.ts.map +1 -1
- package/dist/shared/config/resolveSessionConfig.js +21 -1
- package/dist/shared/config/resolveSessionConfig.js.map +1 -1
- package/dist/shared/dispatch/coordinator.d.ts.map +1 -1
- package/dist/shared/dispatch/coordinator.js +52 -6
- package/dist/shared/dispatch/coordinator.js.map +1 -1
- package/dist/shared/dispatch/hybridDispatch.d.ts +6 -0
- package/dist/shared/dispatch/hybridDispatch.d.ts.map +1 -1
- package/dist/shared/dispatch/hybridDispatch.js +6 -0
- package/dist/shared/dispatch/hybridDispatch.js.map +1 -1
- package/dist/shared/dispatch/providerLaunchFinalize.d.ts +2 -1
- package/dist/shared/dispatch/providerLaunchFinalize.d.ts.map +1 -1
- package/dist/shared/dispatch/providerLaunchFinalize.js +123 -68
- package/dist/shared/dispatch/providerLaunchFinalize.js.map +1 -1
- package/dist/shared/dispatch/rollingDispatch.d.ts +69 -2
- package/dist/shared/dispatch/rollingDispatch.d.ts.map +1 -1
- package/dist/shared/dispatch/rollingDispatch.js +177 -7
- package/dist/shared/dispatch/rollingDispatch.js.map +1 -1
- package/dist/shared/dispatch/unifiedRolling.d.ts +23 -0
- package/dist/shared/dispatch/unifiedRolling.d.ts.map +1 -1
- package/dist/shared/dispatch/unifiedRolling.js +2 -0
- package/dist/shared/dispatch/unifiedRolling.js.map +1 -1
- package/dist/shared/friction/stepBoundaryCapture.d.ts +31 -1
- package/dist/shared/friction/stepBoundaryCapture.d.ts.map +1 -1
- package/dist/shared/friction/stepBoundaryCapture.js +47 -0
- package/dist/shared/friction/stepBoundaryCapture.js.map +1 -1
- package/dist/shared/index.d.ts +8 -4
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +10 -2
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/io/stateDir.d.ts +27 -0
- package/dist/shared/io/stateDir.d.ts.map +1 -0
- package/dist/shared/io/stateDir.js +40 -0
- package/dist/shared/io/stateDir.js.map +1 -0
- package/dist/shared/providers/auditorSources.d.ts +94 -4
- package/dist/shared/providers/auditorSources.d.ts.map +1 -1
- package/dist/shared/providers/auditorSources.js +261 -8
- package/dist/shared/providers/auditorSources.js.map +1 -1
- package/dist/shared/providers/claudeWorkerProvider.d.ts +71 -0
- package/dist/shared/providers/claudeWorkerProvider.d.ts.map +1 -0
- package/dist/shared/providers/claudeWorkerProvider.js +133 -0
- package/dist/shared/providers/claudeWorkerProvider.js.map +1 -0
- package/dist/shared/providers/providerConfirmation.d.ts.map +1 -1
- package/dist/shared/providers/providerConfirmation.js +24 -3
- package/dist/shared/providers/providerConfirmation.js.map +1 -1
- package/dist/shared/providers/providerFactory.d.ts +7 -1
- package/dist/shared/providers/providerFactory.d.ts.map +1 -1
- package/dist/shared/providers/providerFactory.js +6 -0
- package/dist/shared/providers/providerFactory.js.map +1 -1
- package/dist/shared/providers/proxyCatalog.d.ts +95 -0
- package/dist/shared/providers/proxyCatalog.d.ts.map +1 -0
- package/dist/shared/providers/proxyCatalog.js +426 -0
- package/dist/shared/providers/proxyCatalog.js.map +1 -0
- package/dist/shared/quota/apiPool.d.ts.map +1 -1
- package/dist/shared/quota/apiPool.js +31 -0
- package/dist/shared/quota/apiPool.js.map +1 -1
- package/dist/shared/quota/capacity.d.ts +33 -4
- package/dist/shared/quota/capacity.d.ts.map +1 -1
- package/dist/shared/quota/capacity.js +40 -5
- package/dist/shared/quota/capacity.js.map +1 -1
- package/dist/shared/quota/errorParsing.d.ts +39 -0
- package/dist/shared/quota/errorParsing.d.ts.map +1 -1
- package/dist/shared/quota/errorParsing.js +76 -0
- package/dist/shared/quota/errorParsing.js.map +1 -1
- package/dist/shared/types/auditorDescriptor.d.ts +8 -0
- package/dist/shared/types/auditorDescriptor.d.ts.map +1 -1
- package/dist/shared/types/auditorDescriptor.js.map +1 -1
- package/dist/shared/types/rollingDispatch.d.ts +45 -1
- package/dist/shared/types/rollingDispatch.d.ts.map +1 -1
- package/dist/shared/types/sessionConfig.d.ts +77 -3
- package/dist/shared/types/sessionConfig.d.ts.map +1 -1
- package/dist/shared/types/sessionConfig.js +39 -2
- package/dist/shared/types/sessionConfig.js.map +1 -1
- package/dist/shared/validation/sessionConfig.d.ts.map +1 -1
- package/dist/shared/validation/sessionConfig.js +25 -1
- package/dist/shared/validation/sessionConfig.js.map +1 -1
- package/docs/audit-pkg/operator-guide.md +4 -4
- package/package.json +1 -1
|
@@ -87,7 +87,27 @@ export function resolveSessionConfig(intent, descriptor, options) {
|
|
|
87
87
|
// `declared ∩ ambient-verifiable`, resolved IN-PROCESS (G2.5). An explicit
|
|
88
88
|
// hand-authored `--auditor sources[]` still wins — it is the operator's escape
|
|
89
89
|
// hatch and the only way to force a lane this process cannot prove.
|
|
90
|
-
|
|
90
|
+
let sources;
|
|
91
|
+
if (descriptor.sources) {
|
|
92
|
+
sources = descriptor.sources;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
const ambient = resolveAmbientSources(options);
|
|
96
|
+
// A dropped lane must be LOUD at every draw — the reasons existed since G2.5
|
|
97
|
+
// but were discarded here, so a declared-but-unresolvable lane was silently
|
|
98
|
+
// absent (the [[silent-fail-closed-on-one-draw]] class). Default = stderr;
|
|
99
|
+
// callers with a better channel inject `onDroppedSources`.
|
|
100
|
+
if (ambient.dropped.length > 0) {
|
|
101
|
+
const report = options?.onDroppedSources ??
|
|
102
|
+
((dropped) => {
|
|
103
|
+
for (const d of dropped) {
|
|
104
|
+
process.stderr.write(`[audit-tools] declared source "${d.id}" not resolved: ${d.reason}\n`);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
report(ambient.dropped);
|
|
108
|
+
}
|
|
109
|
+
sources = ambient.sources;
|
|
110
|
+
}
|
|
91
111
|
if (sources.length > 0) {
|
|
92
112
|
effective.sources = sources;
|
|
93
113
|
if (self.provider && DISPATCHABLE_PROVIDER_SET.has(self.provider)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveSessionConfig.js","sourceRoot":"","sources":["../../../src/shared/config/resolveSessionConfig.ts"],"names":[],"mappings":"AACA,OAAO,EACL,6BAA6B,
|
|
1
|
+
{"version":3,"file":"resolveSessionConfig.js","sourceRoot":"","sources":["../../../src/shared/config/resolveSessionConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../../../src/shared/dispatch/coordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../../../src/shared/dispatch/coordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAMpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAM/D;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,sEAAsE;IACtE,EAAE,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC;IAC3C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,yBAAyB,GACjC;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,qBAAqB,CAAC;IAAC,QAAQ,EAAE,yBAAyB,CAAA;CAAE,CAAC;AAEzE,8DAA8D;AAC9D,MAAM,WAAW,6BAA6B;IAC5C,kEAAkE;IAClE,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,aAAa,EAAE,aAAa,CAAC;IAC7B;;;OAGG;IACH,aAAa,EAAE,aAAa,CAAC;IAC7B;;;;OAIG;IACH,WAAW,EAAE,MAAM,mBAAmB,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrD;AAiBD,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4B;IACxD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAA2C;gBAEzD,IAAI,EAAE,6BAA6B;IAQ/C,4EAA4E;IAC5E,OAAO,CAAC,WAAW;IAKnB;;;;;;;;;;;;;;;;;;OAkBG;IACG,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAyFvE;;;;;;;;OAQG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK/C;;;;;;OAMG;IACG,OAAO,CAAC,UAAU,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD;;;;;;OAMG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,yBAAyB;CASjE"}
|
|
@@ -43,7 +43,18 @@
|
|
|
43
43
|
* provider coupling, so it runs identically on win32 / darwin / linux and under
|
|
44
44
|
* either driver.
|
|
45
45
|
*/
|
|
46
|
-
import { computeDispatchCapacity, buildEmptyPoolTerminal } from "../quota/capacity.js";
|
|
46
|
+
import { computeDispatchCapacity, buildEmptyPoolTerminal, AGENTIC_WORKER_HARNESS_OVERHEAD_TOKENS, } from "../quota/capacity.js";
|
|
47
|
+
/**
|
|
48
|
+
* Whether a node fits a pool's declared per-request/context token cap, including
|
|
49
|
+
* the agentic-harness overhead a CLI worker adds on top of the packet prompt.
|
|
50
|
+
* A pool with no declared cap (null/absent — host pools, undeclared sources) is
|
|
51
|
+
* always admissible: unknown means no fit filtering, the status quo.
|
|
52
|
+
*/
|
|
53
|
+
function nodeContextFits(node, pool) {
|
|
54
|
+
if (pool.contextCapTokens == null)
|
|
55
|
+
return true;
|
|
56
|
+
return node.estimatedTokens + AGENTIC_WORKER_HARNESS_OVERHEAD_TOKENS <= pool.contextCapTokens;
|
|
57
|
+
}
|
|
47
58
|
// ---------------------------------------------------------------------------
|
|
48
59
|
// HybridSpillCoordinator
|
|
49
60
|
// ---------------------------------------------------------------------------
|
|
@@ -101,7 +112,13 @@ export class HybridSpillCoordinator {
|
|
|
101
112
|
});
|
|
102
113
|
const poolById = new Map(active.map((p) => [p.id, p]));
|
|
103
114
|
const assignments = [];
|
|
104
|
-
|
|
115
|
+
// Per-pool packet-fit gate (U2): the claim walk consumes a shared queue with a
|
|
116
|
+
// FIRST-FIT scan instead of a linear cursor, so a node too large for THIS pool's
|
|
117
|
+
// declared context cap stays available for a later (larger or cap-less) pool in
|
|
118
|
+
// the same walk — the claim itself is the fit guarantee (a node is never claimed
|
|
119
|
+
// to a pool it cannot fit; post-hoc repartitioning would strand the claim on the
|
|
120
|
+
// wrong pool id).
|
|
121
|
+
const unassigned = [...ordered];
|
|
105
122
|
for (const alloc of capacity.pools) {
|
|
106
123
|
const pool = poolById.get(alloc.pool_id);
|
|
107
124
|
// Defensive: the fold echoes the input pools, but never assign to a pool
|
|
@@ -109,9 +126,16 @@ export class HybridSpillCoordinator {
|
|
|
109
126
|
if (!pool)
|
|
110
127
|
continue;
|
|
111
128
|
let placed = 0;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
129
|
+
let scan = 0;
|
|
130
|
+
while (placed < alloc.slots && scan < unassigned.length) {
|
|
131
|
+
const node = unassigned[scan];
|
|
132
|
+
if (!nodeContextFits(node, pool)) {
|
|
133
|
+
// Too large for this pool — leave it queued for a later pool this walk
|
|
134
|
+
// (or unclaimed for the next cycle); the slot stays open for the next node.
|
|
135
|
+
scan += 1;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
unassigned.splice(scan, 1);
|
|
115
139
|
// Claim BEFORE returning the node in any assignment (CE-001). A node
|
|
116
140
|
// another driver already holds is skipped — it is theirs to run — and the
|
|
117
141
|
// slot is freed for the next node so capacity is not wasted on a contested id.
|
|
@@ -127,9 +151,31 @@ export class HybridSpillCoordinator {
|
|
|
127
151
|
});
|
|
128
152
|
placed += 1;
|
|
129
153
|
}
|
|
130
|
-
if (
|
|
154
|
+
if (unassigned.length === 0)
|
|
131
155
|
break;
|
|
132
156
|
}
|
|
157
|
+
// Loud never-fits surface (spec F1): a node whose size exceeds EVERY active
|
|
158
|
+
// pool's declared cap can never be claimed by this coordinator — re-offering
|
|
159
|
+
// is correct only while a cap-less (host) pool may appear; silent re-offer
|
|
160
|
+
// against a fixed all-capped pool set would look like an idle wedge. One
|
|
161
|
+
// structured line per plan so the caller/operator can see exactly which
|
|
162
|
+
// nodes are unplaceable and why.
|
|
163
|
+
const neverFits = unassigned.filter((n) => active.every((p) => !nodeContextFits(n, p)));
|
|
164
|
+
if (neverFits.length > 0) {
|
|
165
|
+
try {
|
|
166
|
+
process.stderr.write(JSON.stringify({
|
|
167
|
+
ts: new Date().toISOString(),
|
|
168
|
+
kind: "hybrid_dispatch_node_never_fits",
|
|
169
|
+
node_ids: neverFits.map((n) => n.id).sort(),
|
|
170
|
+
active_pool_caps: active
|
|
171
|
+
.map((p) => ({ pool_id: p.id, context_cap_tokens: p.contextCapTokens ?? null }))
|
|
172
|
+
.sort((a, b) => a.pool_id.localeCompare(b.pool_id)),
|
|
173
|
+
}) + "\n");
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// Observability must never abort a plan.
|
|
177
|
+
}
|
|
178
|
+
}
|
|
133
179
|
return assignments;
|
|
134
180
|
}
|
|
135
181
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coordinator.js","sourceRoot":"","sources":["../../../src/shared/dispatch/coordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"coordinator.js","sourceRoot":"","sources":["../../../src/shared/dispatch/coordinator.ts"],"names":[],"mappings":"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"}
|
|
@@ -61,6 +61,12 @@ export interface HybridDispatchInput {
|
|
|
61
61
|
* claiming each node to exactly one pool, and partition the claimed assignments by the
|
|
62
62
|
* caller's in-process classification.
|
|
63
63
|
*
|
|
64
|
+
* Per-pool packet-fit gate (U2): fit is enforced INSIDE the coordinator's claim walk
|
|
65
|
+
* (`nodeContextFits` in coordinator.ts) — a node is never CLAIMED to a pool whose
|
|
66
|
+
* declared context cap (plus agentic-harness overhead) it exceeds, so every assignment
|
|
67
|
+
* returned here is fit-guaranteed by construction. Repartitioning after the claim would
|
|
68
|
+
* strand the claim on the wrong pool id; that is why the gate is not here.
|
|
69
|
+
*
|
|
64
70
|
* Behaviour falls out of the pool set with no special-casing:
|
|
65
71
|
* - host-only pools → every node lands in `host`; `inProcess` empty.
|
|
66
72
|
* - backend-only pools → every node lands in `inProcess`; `host` empty.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hybridDispatch.d.ts","sourceRoot":"","sources":["../../../src/shared/dispatch/hybridDispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,sBAAsB,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,yFAAyF;AACzF,MAAM,WAAW,uBAAuB;IACtC,yEAAyE;IACzE,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,qEAAqE;IACrE,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB;;;;OAIG;IACH,WAAW,EAAE,sBAAsB,CAAC;CACrC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,aAAa,EAAE,aAAa,CAAC;IAC7B,aAAa,EAAE,aAAa,CAAC;IAC7B,gFAAgF;IAChF,WAAW,EAAE,MAAM,mBAAmB,CAAC;IACvC,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD;;;;OAIG;IACH,WAAW,EAAE,CAAC,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC;CAC1D;AAED
|
|
1
|
+
{"version":3,"file":"hybridDispatch.d.ts","sourceRoot":"","sources":["../../../src/shared/dispatch/hybridDispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,sBAAsB,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,yFAAyF;AACzF,MAAM,WAAW,uBAAuB;IACtC,yEAAyE;IACzE,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,qEAAqE;IACrE,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB;;;;OAIG;IACH,WAAW,EAAE,sBAAsB,CAAC;CACrC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,aAAa,EAAE,aAAa,CAAC;IAC7B,aAAa,EAAE,aAAa,CAAC;IAC7B,gFAAgF;IAChF,WAAW,EAAE,MAAM,mBAAmB,CAAC;IACvC,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD;;;;OAIG;IACH,WAAW,EAAE,CAAC,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC;CAC1D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAerG"}
|
|
@@ -26,6 +26,12 @@ import { HybridSpillCoordinator } from "./coordinator.js";
|
|
|
26
26
|
* claiming each node to exactly one pool, and partition the claimed assignments by the
|
|
27
27
|
* caller's in-process classification.
|
|
28
28
|
*
|
|
29
|
+
* Per-pool packet-fit gate (U2): fit is enforced INSIDE the coordinator's claim walk
|
|
30
|
+
* (`nodeContextFits` in coordinator.ts) — a node is never CLAIMED to a pool whose
|
|
31
|
+
* declared context cap (plus agentic-harness overhead) it exceeds, so every assignment
|
|
32
|
+
* returned here is fit-guaranteed by construction. Repartitioning after the claim would
|
|
33
|
+
* strand the claim on the wrong pool id; that is why the gate is not here.
|
|
34
|
+
*
|
|
29
35
|
* Behaviour falls out of the pool set with no special-casing:
|
|
30
36
|
* - host-only pools → every node lands in `host`; `inProcess` empty.
|
|
31
37
|
* - backend-only pools → every node lands in `inProcess`; `host` empty.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hybridDispatch.js","sourceRoot":"","sources":["../../../src/shared/dispatch/hybridDispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,sBAAsB,EAA0C,MAAM,kBAAkB,CAAC;AAqClG
|
|
1
|
+
{"version":3,"file":"hybridDispatch.js","sourceRoot":"","sources":["../../../src/shared/dispatch/hybridDispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,sBAAsB,EAA0C,MAAM,kBAAkB,CAAC;AAqClG;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAA0B;IACjE,MAAM,WAAW,GAAG,IAAI,sBAAsB,CAAC;QAC7C,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACtE,MAAM,SAAS,GAAqB,EAAE,CAAC;IACvC,MAAM,IAAI,GAAqB,EAAE,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAC1C,CAAC"}
|
|
@@ -33,7 +33,8 @@ export interface ProviderLaunchFinalizeContext<TPacket> {
|
|
|
33
33
|
* read-only-vs-git-mutating / AuditResult-vs-ImplementWorkerResult divergences.
|
|
34
34
|
*
|
|
35
35
|
* In order:
|
|
36
|
-
* 1. not-accepted →
|
|
36
|
+
* 1. not-accepted → classify the failure text via the shared `classifyFailureChannels`
|
|
37
|
+
* helper (mirrors the accepted-but-no-result-file branch so both cannot drift);
|
|
37
38
|
* 2. channel-isolated credit-exhaustion (TIER 1) then session-limit (TIER 1)
|
|
38
39
|
* detection on stderr (CE-003) → credit_exhausted / non-consuming
|
|
39
40
|
* rate_limited re-queue (the result file is never scanned for these strings);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providerLaunchFinalize.d.ts","sourceRoot":"","sources":["../../../src/shared/dispatch/providerLaunchFinalize.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"providerLaunchFinalize.d.ts","sourceRoot":"","sources":["../../../src/shared/dispatch/providerLaunchFinalize.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAEzF,MAAM,WAAW,6BAA6B,CAAC,OAAO;IACpD,4EAA4E;IAC5E,MAAM,EAAE,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACvC,kEAAkE;IAClE,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAiHD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,4BAA4B,CAAC,OAAO,EACxD,MAAM,EAAE,wBAAwB,EAChC,GAAG,EAAE,6BAA6B,CAAC,OAAO,CAAC,GAC1C,OAAO,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAyEzC"}
|
|
@@ -1,6 +1,103 @@
|
|
|
1
|
-
import { detectRateLimitFromChannel, detectCreditExhaustionFromChannel, detectQuotaSuspicious } from "../quota/errorParsing.js";
|
|
1
|
+
import { detectRateLimitFromChannel, detectCreditExhaustionFromChannel, detectModelUnavailableFromChannel, detectRequestTooLargeFromChannel, detectQuotaSuspicious, } from "../quota/errorParsing.js";
|
|
2
2
|
import { appendTokenUsageLine } from "../io/tokenUsageLedger.js";
|
|
3
3
|
import { readOptionalJsonFile, readOptionalTextFile } from "../io/json.js";
|
|
4
|
+
/**
|
|
5
|
+
* Classify a worker's failure text by scanning stderr and stdout in order for known
|
|
6
|
+
* quota/API-error patterns. Reused identically by both not-accepted (exit ≠ 0) and
|
|
7
|
+
* accepted-but-no-result-file branches so they cannot drift.
|
|
8
|
+
*
|
|
9
|
+
* **Scan order (load-bearing — F4 requires stderr request-too-large BEFORE rate-limit
|
|
10
|
+
* so a combined "413 ... retry rate limit" cannot cooldown-poison a healthy pool):**
|
|
11
|
+
* 1. stderr: credit-exhaustion (permanent, no reset timer)
|
|
12
|
+
* 2. stderr: request-too-large (per-packet sizing fault, no cooldown)
|
|
13
|
+
* 3. stderr: model-unavailable (404, permanent pool exclusion)
|
|
14
|
+
* 4. stderr: rate-limit (transient 429)
|
|
15
|
+
* 5. stdout: credit-exhaustion
|
|
16
|
+
* 6. stdout: request-too-large
|
|
17
|
+
* 7. stdout: model-unavailable
|
|
18
|
+
* 8. stdout: rate-limit
|
|
19
|
+
* 9. TIER 2 `detectQuotaSuspicious` over both channels combined (fallback pre-filter)
|
|
20
|
+
*
|
|
21
|
+
* Returns the corresponding RollingDispatchResult fragment or null if no match.
|
|
22
|
+
*/
|
|
23
|
+
function classifyFailureChannels(packet, stderrText, stdoutText) {
|
|
24
|
+
// Stderr TIER 1: credit exhaustion (permanent, checked first — must never fall through to rate-limit)
|
|
25
|
+
const stderrCreditCheck = detectCreditExhaustionFromChannel("error", stderrText);
|
|
26
|
+
if (stderrCreditCheck.isCreditExhausted) {
|
|
27
|
+
return {
|
|
28
|
+
outcome: "credit_exhausted",
|
|
29
|
+
creditExhaustion: { channel: "error", text: stderrText, rawMatch: stderrCreditCheck.rawMatch },
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// Stderr TIER 1: request-too-large (F4 — must be checked BEFORE rate-limit to prevent cooldown-poisoning)
|
|
33
|
+
const stderrTooLargeCheck = detectRequestTooLargeFromChannel("error", stderrText);
|
|
34
|
+
if (stderrTooLargeCheck.isRequestTooLarge) {
|
|
35
|
+
return {
|
|
36
|
+
outcome: "packet_too_large",
|
|
37
|
+
packetTooLarge: { channel: "error", text: stderrText, rawMatch: stderrTooLargeCheck.rawMatch },
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// Stderr TIER 1: model-unavailable (permanent pool exclusion, checked before rate-limit)
|
|
41
|
+
const stderrModelUnavailableCheck = detectModelUnavailableFromChannel("error", stderrText);
|
|
42
|
+
if (stderrModelUnavailableCheck.isModelUnavailable) {
|
|
43
|
+
return {
|
|
44
|
+
outcome: "model_unavailable",
|
|
45
|
+
modelUnavailable: { channel: "error", text: stderrText, rawMatch: stderrModelUnavailableCheck.rawMatch },
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// Stderr TIER 1: rate-limit (transient, applies cooldown)
|
|
49
|
+
const stderrLimitCheck = detectRateLimitFromChannel("error", stderrText);
|
|
50
|
+
if (stderrLimitCheck.isRateLimited) {
|
|
51
|
+
return {
|
|
52
|
+
outcome: "rate_limited",
|
|
53
|
+
rateLimit: { channel: "error", text: stderrText },
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// Stdout TIER 1: credit exhaustion (some providers report to stdout instead)
|
|
57
|
+
const stdoutCreditCheck = detectCreditExhaustionFromChannel("status", stdoutText);
|
|
58
|
+
if (stdoutCreditCheck.isCreditExhausted) {
|
|
59
|
+
return {
|
|
60
|
+
outcome: "credit_exhausted",
|
|
61
|
+
creditExhaustion: { channel: "status", text: stdoutText, rawMatch: stdoutCreditCheck.rawMatch },
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// Stdout TIER 1: request-too-large
|
|
65
|
+
const stdoutTooLargeCheck = detectRequestTooLargeFromChannel("status", stdoutText);
|
|
66
|
+
if (stdoutTooLargeCheck.isRequestTooLarge) {
|
|
67
|
+
return {
|
|
68
|
+
outcome: "packet_too_large",
|
|
69
|
+
packetTooLarge: { channel: "status", text: stdoutText, rawMatch: stdoutTooLargeCheck.rawMatch },
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Stdout TIER 1: model-unavailable
|
|
73
|
+
const stdoutModelUnavailableCheck = detectModelUnavailableFromChannel("status", stdoutText);
|
|
74
|
+
if (stdoutModelUnavailableCheck.isModelUnavailable) {
|
|
75
|
+
return {
|
|
76
|
+
outcome: "model_unavailable",
|
|
77
|
+
modelUnavailable: { channel: "status", text: stdoutText, rawMatch: stdoutModelUnavailableCheck.rawMatch },
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// Stdout TIER 1: rate-limit
|
|
81
|
+
const stdoutLimitCheck = detectRateLimitFromChannel("status", stdoutText);
|
|
82
|
+
if (stdoutLimitCheck.isRateLimited) {
|
|
83
|
+
return {
|
|
84
|
+
outcome: "rate_limited",
|
|
85
|
+
rateLimit: { channel: "status", text: stdoutText },
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// TIER 2 (Slice A2b): broad pre-filter on combined channels (fallback for unclassified quota-suspicious text)
|
|
89
|
+
const combinedText = [stderrText, stdoutText].filter((t) => t.length > 0).join("\n");
|
|
90
|
+
if (combinedText.length > 0 && detectQuotaSuspicious(combinedText)) {
|
|
91
|
+
return {
|
|
92
|
+
outcome: "quota_unclassified",
|
|
93
|
+
quotaUnclassified: {
|
|
94
|
+
channel: stderrText.length > 0 ? "error" : "status",
|
|
95
|
+
text: combinedText,
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
4
101
|
/**
|
|
5
102
|
* The shared launch-result finalize tail run by BOTH per-packet dispatchers
|
|
6
103
|
* (audit `makeAuditProviderPacketDispatcher`, remediate `makeProviderNodeDispatcher`)
|
|
@@ -11,7 +108,8 @@ import { readOptionalJsonFile, readOptionalTextFile } from "../io/json.js";
|
|
|
11
108
|
* read-only-vs-git-mutating / AuditResult-vs-ImplementWorkerResult divergences.
|
|
12
109
|
*
|
|
13
110
|
* In order:
|
|
14
|
-
* 1. not-accepted →
|
|
111
|
+
* 1. not-accepted → classify the failure text via the shared `classifyFailureChannels`
|
|
112
|
+
* helper (mirrors the accepted-but-no-result-file branch so both cannot drift);
|
|
15
113
|
* 2. channel-isolated credit-exhaustion (TIER 1) then session-limit (TIER 1)
|
|
16
114
|
* detection on stderr (CE-003) → credit_exhausted / non-consuming
|
|
17
115
|
* rate_limited re-queue (the result file is never scanned for these strings);
|
|
@@ -29,40 +127,31 @@ import { readOptionalJsonFile, readOptionalTextFile } from "../io/json.js";
|
|
|
29
127
|
*/
|
|
30
128
|
export async function finalizeProviderLaunchResult(launch, ctx) {
|
|
31
129
|
const { packet } = ctx;
|
|
130
|
+
// Read both channels for classification (reused by both not-accepted and accepted-but-no-result branches)
|
|
131
|
+
//
|
|
132
|
+
// DELIBERATE semantic change (2026-07-17, gap-fix lap): an ACCEPTED launch whose
|
|
133
|
+
// result file landed + parses is a SUCCESS even if a channel carries limit text —
|
|
134
|
+
// an agentic worker that retried through transient 429s and still delivered must
|
|
135
|
+
// not have its completed work discarded and re-run (the old order scanned stderr
|
|
136
|
+
// before the result read and re-queued such packets). Channel classification now
|
|
137
|
+
// applies only when the launch was rejected or no result landed; result CONTENT
|
|
138
|
+
// is still never scanned (CE-003) and is adjudicated by the merge downstream.
|
|
139
|
+
const stderrText = (await readOptionalTextFile(ctx.stderrPath)) ?? "";
|
|
140
|
+
const stdoutText = (await readOptionalTextFile(ctx.stdoutPath)) ?? "";
|
|
141
|
+
// The not-accepted branch NOW runs the channel classifier BEFORE returning error.
|
|
142
|
+
// This fixes the dogfood gap: a nonzero-exit worker's 429/404/413 text is now scanned.
|
|
32
143
|
if (!launch.accepted) {
|
|
144
|
+
const classification = classifyFailureChannels(packet, stderrText, stdoutText);
|
|
145
|
+
if (classification) {
|
|
146
|
+
return { packet, ...classification };
|
|
147
|
+
}
|
|
148
|
+
// No classification matched — return the original error
|
|
33
149
|
return {
|
|
34
150
|
packet,
|
|
35
151
|
outcome: "error",
|
|
36
152
|
error: new Error(launch.error ?? `provider ${ctx.providerName} rejected ${ctx.entityLabel}`),
|
|
37
153
|
};
|
|
38
154
|
}
|
|
39
|
-
// Channel-isolated session-limit detection (CE-003): only the error/status channel
|
|
40
|
-
// (stderr) is inspected — the result file is never scanned for limit strings, so a
|
|
41
|
-
// healthy result quoting a limit never triggers a re-queue.
|
|
42
|
-
const stderrText = (await readOptionalTextFile(ctx.stderrPath)) ?? "";
|
|
43
|
-
// Credit exhaustion (out of prepaid usage credits) is checked FIRST and is
|
|
44
|
-
// architecturally distinct from a rate limit: it carries no reset time, so a
|
|
45
|
-
// positive match here must never fall through to the resettable rate_limited
|
|
46
|
-
// path below. Same channel isolation (CE-003) applies — only stderr, never the
|
|
47
|
-
// consumed result file.
|
|
48
|
-
const creditCheck = detectCreditExhaustionFromChannel("error", stderrText);
|
|
49
|
-
if (creditCheck.isCreditExhausted) {
|
|
50
|
-
return {
|
|
51
|
-
packet,
|
|
52
|
-
outcome: "credit_exhausted",
|
|
53
|
-
creditExhaustion: { channel: "error", text: stderrText, rawMatch: creditCheck.rawMatch },
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
const limitCheck = detectRateLimitFromChannel("error", stderrText);
|
|
57
|
-
if (limitCheck.isRateLimited) {
|
|
58
|
-
// Non-consuming re-queue: the rolling engine drops the provider and puts this
|
|
59
|
-
// packet back into the pending pool so it retries once the cooldown passes.
|
|
60
|
-
return {
|
|
61
|
-
packet,
|
|
62
|
-
outcome: "rate_limited",
|
|
63
|
-
rateLimit: { channel: "error", text: stderrText },
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
155
|
// Reactive cost verification: relay the endpoint-reported cost (when the provider
|
|
67
156
|
// surfaced one) so `handleResult` can demote a declared-free pool that started
|
|
68
157
|
// charging. Absent for providers that report no cost.
|
|
@@ -71,45 +160,11 @@ export async function finalizeProviderLaunchResult(launch, ctx) {
|
|
|
71
160
|
// Contents are adjudicated by the deterministic merge downstream.
|
|
72
161
|
const result = await readOptionalJsonFile(ctx.resultPath);
|
|
73
162
|
if (!result) {
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return {
|
|
80
|
-
packet,
|
|
81
|
-
outcome: "credit_exhausted",
|
|
82
|
-
creditExhaustion: { channel: "status", text: stdoutText, rawMatch: stdoutCreditCheck.rawMatch },
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
const stdoutLimitCheck = detectRateLimitFromChannel("status", stdoutText);
|
|
86
|
-
if (stdoutLimitCheck.isRateLimited) {
|
|
87
|
-
return {
|
|
88
|
-
packet,
|
|
89
|
-
outcome: "rate_limited",
|
|
90
|
-
rateLimit: { channel: "status", text: stdoutText },
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
// TIER 2 (Slice A2b): neither channel matched a PRECISE credit/rate-limit
|
|
94
|
-
// pattern. Before falling through to a silent, unclassified raw `error` —
|
|
95
|
-
// the exact "worker AND dispatcher both die raw" failure mode
|
|
96
|
-
// credit-exhaustion detection fixed, but only for text it recognizes — run
|
|
97
|
-
// the deliberately broad `detectQuotaSuspicious` pre-filter across BOTH
|
|
98
|
-
// channels combined. A positive match here degrades CONSERVATIVELY
|
|
99
|
-
// (re-queue with a reversible cooldown, the pool is never permanently
|
|
100
|
-
// excluded — see the `quota_unclassified` branch in rollingDispatch.ts) and
|
|
101
|
-
// carries the verbatim text so the operator can classify it and improve the
|
|
102
|
-
// pattern set, instead of a silent death with no signal at all.
|
|
103
|
-
const combinedText = [stderrText, stdoutText].filter((t) => t.length > 0).join("\n");
|
|
104
|
-
if (combinedText.length > 0 && detectQuotaSuspicious(combinedText)) {
|
|
105
|
-
return {
|
|
106
|
-
packet,
|
|
107
|
-
outcome: "quota_unclassified",
|
|
108
|
-
quotaUnclassified: {
|
|
109
|
-
channel: stderrText.length > 0 ? "error" : "status",
|
|
110
|
-
text: combinedText,
|
|
111
|
-
},
|
|
112
|
-
};
|
|
163
|
+
// No result file landed — reuse the same channel classifier so both branches cannot drift.
|
|
164
|
+
// Channel isolation (CE-003) is preserved: result channel is never scanned.
|
|
165
|
+
const classification = classifyFailureChannels(packet, stderrText, stdoutText);
|
|
166
|
+
if (classification) {
|
|
167
|
+
return { packet, ...classification };
|
|
113
168
|
}
|
|
114
169
|
return {
|
|
115
170
|
packet,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providerLaunchFinalize.js","sourceRoot":"","sources":["../../../src/shared/dispatch/providerLaunchFinalize.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"providerLaunchFinalize.js","sourceRoot":"","sources":["../../../src/shared/dispatch/providerLaunchFinalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -81,7 +81,7 @@ export interface RollingDispatchPacket<TPacket> {
|
|
|
81
81
|
/** Outcome of dispatching a single packet. */
|
|
82
82
|
export interface RollingDispatchResult<TPacket> {
|
|
83
83
|
packet: RollingDispatchPacket<TPacket>;
|
|
84
|
-
outcome: "success" | "rate_limited" | "timeout" | "error" | "credit_exhausted" | "quota_unclassified";
|
|
84
|
+
outcome: "success" | "rate_limited" | "timeout" | "error" | "credit_exhausted" | "model_unavailable" | "packet_too_large" | "quota_unclassified";
|
|
85
85
|
/** Actual tokens consumed, if the provider reports it. */
|
|
86
86
|
actualTokens?: number;
|
|
87
87
|
/**
|
|
@@ -129,6 +129,28 @@ export interface RollingDispatchResult<TPacket> {
|
|
|
129
129
|
text: string;
|
|
130
130
|
rawMatch: string | null;
|
|
131
131
|
};
|
|
132
|
+
/**
|
|
133
|
+
* The worker ERROR/STATUS channel evidence that classified a `model_unavailable`
|
|
134
|
+
* outcome (HTTP 404, model not found — permanent pool exclusion, the model is not
|
|
135
|
+
* served by this provider). Carried so the consumer's `onModelUnavailable` hook can
|
|
136
|
+
* surface it as reviewable friction. Absent on non-model_unavailable outcomes.
|
|
137
|
+
*/
|
|
138
|
+
modelUnavailable?: {
|
|
139
|
+
channel: WorkerOutputChannel;
|
|
140
|
+
text: string;
|
|
141
|
+
rawMatch: string | null;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* The worker ERROR/STATUS channel evidence that classified a `packet_too_large`
|
|
145
|
+
* outcome (HTTP 413, request/payload too large — a per-packet sizing fault for
|
|
146
|
+
* this particular pool). Carried so the consumer's `onPacketTooLarge` hook can
|
|
147
|
+
* surface it as reviewable friction. Absent on non-packet_too_large outcomes.
|
|
148
|
+
*/
|
|
149
|
+
packetTooLarge?: {
|
|
150
|
+
channel: WorkerOutputChannel;
|
|
151
|
+
text: string;
|
|
152
|
+
rawMatch: string | null;
|
|
153
|
+
};
|
|
132
154
|
/**
|
|
133
155
|
* The worker ERROR/STATUS channel VERBATIM evidence that classified a
|
|
134
156
|
* `quota_unclassified` outcome (Slice A2b, TIER 2): the broad
|
|
@@ -224,6 +246,24 @@ export interface RollingDispatchState<TPacket> {
|
|
|
224
246
|
* documented follow-up (docs/backlog.md) — bounded efficiency only, not a safety gap.
|
|
225
247
|
*/
|
|
226
248
|
quotaUnclassifiedPoolIds: Set<string>;
|
|
249
|
+
/**
|
|
250
|
+
* Pool ids permanently excluded after a `model_unavailable` result (HTTP 404, the
|
|
251
|
+
* model is not served by this provider). Monotonic within a run — a pool is never
|
|
252
|
+
* re-added — mirrors `exhaustedPoolIds` behavior for credit exhaustion but carries
|
|
253
|
+
* availability semantics instead of billing semantics. Unlike exhausted-pool
|
|
254
|
+
* re-routing (a timed backoff), a 404 has no reset condition: once a model is
|
|
255
|
+
* unavailable, the pool is gone for the run.
|
|
256
|
+
*/
|
|
257
|
+
modelUnavailablePoolIds: Set<string>;
|
|
258
|
+
/**
|
|
259
|
+
* Packet id → set of pool ids that 413'd this packet. When a `packet_too_large`
|
|
260
|
+
* result lands, a pool is never permanently excluded from the whole run (unlike
|
|
261
|
+
* credit_exhausted or model_unavailable); instead, ONLY THIS PACKET is skipped for
|
|
262
|
+
* THIS POOL on the next selection pass. Other packets freely bind to the pool, and
|
|
263
|
+
* this packet retries on any other pool. Discriminator is (packetId, poolId) — each
|
|
264
|
+
* distinct pair is a separate sizing fault signal.
|
|
265
|
+
*/
|
|
266
|
+
oversizedPacketPools: Map<string, Set<string>>;
|
|
227
267
|
}
|
|
228
268
|
/** Consumer-provided configuration for the rolling dispatcher. */
|
|
229
269
|
export interface RollingDispatchConfig<TPacket> {
|
|
@@ -266,6 +306,33 @@ export interface RollingDispatchConfig<TPacket> {
|
|
|
266
306
|
poolId: string;
|
|
267
307
|
rawMatch: string | null;
|
|
268
308
|
}) => void;
|
|
309
|
+
/**
|
|
310
|
+
* Model unavailable (HTTP 404, model not found — permanent pool exclusion):
|
|
311
|
+
* invoked once per pool the FIRST time a `model_unavailable` result lands for it —
|
|
312
|
+
* the model is not served by this provider and the pool is permanently excluded from
|
|
313
|
+
* this run's admissible set (monotonic `modelUnavailablePoolIds` — never a timed
|
|
314
|
+
* cooldown). The consumer wires it to friction emission. Best-effort — a throwing
|
|
315
|
+
* hook never aborts dispatch. Omit to leave the exclusion silent (no friction
|
|
316
|
+
* emitted, exclusion still happens).
|
|
317
|
+
*/
|
|
318
|
+
onModelUnavailable?: (info: {
|
|
319
|
+
poolId: string;
|
|
320
|
+
rawMatch: string | null;
|
|
321
|
+
}) => void;
|
|
322
|
+
/**
|
|
323
|
+
* Packet too large (HTTP 413, payload/request too large — per-packet sizing fault):
|
|
324
|
+
* invoked every time a `packet_too_large` result lands — the pool is NOT permanently
|
|
325
|
+
* excluded (unlike model_unavailable or credit_exhausted); only THIS PACKET is
|
|
326
|
+
* skipped for THIS POOL on re-selection. Each (packet,pool) pair is distinct signal,
|
|
327
|
+
* so the hook fires per distinct pair, not per pool. The consumer wires it to
|
|
328
|
+
* friction emission. Best-effort — a throwing hook never aborts dispatch. Omit to
|
|
329
|
+
* leave the re-queue silent (no friction, re-queue still happens).
|
|
330
|
+
*/
|
|
331
|
+
onPacketTooLarge?: (info: {
|
|
332
|
+
poolId: string;
|
|
333
|
+
packetId: string;
|
|
334
|
+
rawMatch: string | null;
|
|
335
|
+
}) => void;
|
|
269
336
|
/**
|
|
270
337
|
* Quota-unclassified harvest (Slice A2b, TIER 2): invoked once per pool the
|
|
271
338
|
* FIRST time a `quota_unclassified` result lands for it — a worker death whose
|
|
@@ -417,7 +484,7 @@ export declare function scorePacketComplexity<TPacket>(packet: RollingDispatchPa
|
|
|
417
484
|
*
|
|
418
485
|
* Returns null if no eligible pool currently has quota headroom.
|
|
419
486
|
*/
|
|
420
|
-
export declare function selectProvider<TPacket>(packet: RollingDispatchPacket<TPacket>, confirmedPools: CapacityPool[], inFlightTracker: InFlightTokenTracker, quotaStateEntries: Record<string, QuotaStateEntry>, sessionConfig: SessionConfig, exhaustedPoolIds?: ReadonlySet<string>, pausedPoolResetAt?: ReadonlyMap<string, number>, costDemotedPoolIds?: ReadonlySet<string>, now?: number): ProviderSlot | null;
|
|
487
|
+
export declare function selectProvider<TPacket>(packet: RollingDispatchPacket<TPacket>, confirmedPools: CapacityPool[], inFlightTracker: InFlightTokenTracker, quotaStateEntries: Record<string, QuotaStateEntry>, sessionConfig: SessionConfig, exhaustedPoolIds?: ReadonlySet<string>, pausedPoolResetAt?: ReadonlyMap<string, number>, costDemotedPoolIds?: ReadonlySet<string>, oversizedPacketPools?: ReadonlyMap<string, ReadonlySet<string>>, now?: number): ProviderSlot | null;
|
|
421
488
|
/**
|
|
422
489
|
* Create a rolling dispatcher for the given configuration.
|
|
423
490
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rollingDispatch.d.ts","sourceRoot":"","sources":["../../../src/shared/dispatch/rollingDispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"rollingDispatch.d.ts","sourceRoot":"","sources":["../../../src/shared/dispatch/rollingDispatch.ts"],"names":[],"mappings":"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"}
|