audit-tools 0.28.8 → 0.28.10

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.
Files changed (188) hide show
  1. package/audit-code-wrapper-install-hosts.mjs +133 -27
  2. package/dist/audit/cli/confirmIntentStep.d.ts +1 -0
  3. package/dist/audit/cli/confirmIntentStep.d.ts.map +1 -1
  4. package/dist/audit/cli/confirmIntentStep.js +14 -10
  5. package/dist/audit/cli/confirmIntentStep.js.map +1 -1
  6. package/dist/audit/cli/dispatch/quotaPool.d.ts.map +1 -1
  7. package/dist/audit/cli/dispatch/quotaPool.js +47 -39
  8. package/dist/audit/cli/dispatch/quotaPool.js.map +1 -1
  9. package/dist/audit/cli/dispatch.d.ts +15 -1
  10. package/dist/audit/cli/dispatch.d.ts.map +1 -1
  11. package/dist/audit/cli/dispatch.js +54 -19
  12. package/dist/audit/cli/dispatch.js.map +1 -1
  13. package/dist/audit/cli/hybridDispatch.d.ts +46 -0
  14. package/dist/audit/cli/hybridDispatch.d.ts.map +1 -0
  15. package/dist/audit/cli/hybridDispatch.js +77 -0
  16. package/dist/audit/cli/hybridDispatch.js.map +1 -0
  17. package/dist/audit/cli/nextStepHelpers.d.ts.map +1 -1
  18. package/dist/audit/cli/nextStepHelpers.js +119 -2
  19. package/dist/audit/cli/nextStepHelpers.js.map +1 -1
  20. package/dist/audit/cli/reviewRun.d.ts +19 -0
  21. package/dist/audit/cli/reviewRun.d.ts.map +1 -1
  22. package/dist/audit/cli/reviewRun.js +2 -2
  23. package/dist/audit/cli/reviewRun.js.map +1 -1
  24. package/dist/audit/cli/rollingAuditDispatch.d.ts +57 -4
  25. package/dist/audit/cli/rollingAuditDispatch.d.ts.map +1 -1
  26. package/dist/audit/cli/rollingAuditDispatch.js +137 -10
  27. package/dist/audit/cli/rollingAuditDispatch.js.map +1 -1
  28. package/dist/audit/cli/scoreAuditCommand.d.ts +16 -0
  29. package/dist/audit/cli/scoreAuditCommand.d.ts.map +1 -0
  30. package/dist/audit/cli/scoreAuditCommand.js +82 -0
  31. package/dist/audit/cli/scoreAuditCommand.js.map +1 -0
  32. package/dist/audit/cli.d.ts.map +1 -1
  33. package/dist/audit/cli.js +5 -1
  34. package/dist/audit/cli.js.map +1 -1
  35. package/dist/audit/orchestrator/designReviewProjection.d.ts +9 -1
  36. package/dist/audit/orchestrator/designReviewProjection.d.ts.map +1 -1
  37. package/dist/audit/orchestrator/designReviewProjection.js +19 -1
  38. package/dist/audit/orchestrator/designReviewProjection.js.map +1 -1
  39. package/dist/audit/orchestrator/designReviewPrompt.d.ts +2 -0
  40. package/dist/audit/orchestrator/designReviewPrompt.d.ts.map +1 -1
  41. package/dist/audit/orchestrator/designReviewPrompt.js +11 -1
  42. package/dist/audit/orchestrator/designReviewPrompt.js.map +1 -1
  43. package/dist/audit/orchestrator/executorRunners.js +1 -1
  44. package/dist/audit/orchestrator/executorRunners.js.map +1 -1
  45. package/dist/audit/orchestrator/intakeExecutors.d.ts +9 -1
  46. package/dist/audit/orchestrator/intakeExecutors.d.ts.map +1 -1
  47. package/dist/audit/orchestrator/intakeExecutors.js +16 -3
  48. package/dist/audit/orchestrator/intakeExecutors.js.map +1 -1
  49. package/dist/audit/orchestrator/intentCheckpointExecutor.d.ts.map +1 -1
  50. package/dist/audit/orchestrator/intentCheckpointExecutor.js +3 -0
  51. package/dist/audit/orchestrator/intentCheckpointExecutor.js.map +1 -1
  52. package/dist/audit/orchestrator/intentInterpreter.d.ts +21 -7
  53. package/dist/audit/orchestrator/intentInterpreter.d.ts.map +1 -1
  54. package/dist/audit/orchestrator/intentInterpreter.js +30 -11
  55. package/dist/audit/orchestrator/intentInterpreter.js.map +1 -1
  56. package/dist/audit/orchestrator/intentScopeDisposition.d.ts +49 -0
  57. package/dist/audit/orchestrator/intentScopeDisposition.d.ts.map +1 -0
  58. package/dist/audit/orchestrator/intentScopeDisposition.js +57 -0
  59. package/dist/audit/orchestrator/intentScopeDisposition.js.map +1 -0
  60. package/dist/audit/orchestrator/rollingDispatch.d.ts +9 -0
  61. package/dist/audit/orchestrator/rollingDispatch.d.ts.map +1 -1
  62. package/dist/audit/orchestrator/rollingDispatch.js +10 -0
  63. package/dist/audit/orchestrator/rollingDispatch.js.map +1 -1
  64. package/dist/audit/orchestrator/scope.d.ts +1 -0
  65. package/dist/audit/orchestrator/scope.d.ts.map +1 -1
  66. package/dist/audit/orchestrator/scope.js +2 -7
  67. package/dist/audit/orchestrator/scope.js.map +1 -1
  68. package/dist/audit/quota/index.d.ts +5 -0
  69. package/dist/audit/quota/index.d.ts.map +1 -1
  70. package/dist/audit/reporting/scoreAudit.d.ts +161 -0
  71. package/dist/audit/reporting/scoreAudit.d.ts.map +1 -0
  72. package/dist/audit/reporting/scoreAudit.js +224 -0
  73. package/dist/audit/reporting/scoreAudit.js.map +1 -0
  74. package/dist/audit/types/activeDispatch.d.ts +29 -1
  75. package/dist/audit/types/activeDispatch.d.ts.map +1 -1
  76. package/dist/audit/types/activeDispatch.js.map +1 -1
  77. package/dist/audit/types/analyzerCapability.d.ts +6 -6
  78. package/dist/remediate/contractPipeline/changeClassification.d.ts +146 -0
  79. package/dist/remediate/contractPipeline/changeClassification.d.ts.map +1 -0
  80. package/dist/remediate/contractPipeline/changeClassification.js +398 -0
  81. package/dist/remediate/contractPipeline/changeClassification.js.map +1 -0
  82. package/dist/remediate/contractPipeline/derive.d.ts.map +1 -1
  83. package/dist/remediate/contractPipeline/derive.js +9 -0
  84. package/dist/remediate/contractPipeline/derive.js.map +1 -1
  85. package/dist/remediate/intent/intentOrdering.d.ts +51 -0
  86. package/dist/remediate/intent/intentOrdering.d.ts.map +1 -0
  87. package/dist/remediate/intent/intentOrdering.js +150 -0
  88. package/dist/remediate/intent/intentOrdering.js.map +1 -0
  89. package/dist/remediate/phases/plan.d.ts.map +1 -1
  90. package/dist/remediate/phases/plan.js +14 -1
  91. package/dist/remediate/phases/plan.js.map +1 -1
  92. package/dist/remediate/providers/index.d.ts +32 -0
  93. package/dist/remediate/providers/index.d.ts.map +1 -1
  94. package/dist/remediate/providers/index.js +28 -1
  95. package/dist/remediate/providers/index.js.map +1 -1
  96. package/dist/remediate/steps/contractPipeline.d.ts +15 -1
  97. package/dist/remediate/steps/contractPipeline.d.ts.map +1 -1
  98. package/dist/remediate/steps/contractPipeline.js +282 -14
  99. package/dist/remediate/steps/contractPipeline.js.map +1 -1
  100. package/dist/remediate/steps/dispatch.d.ts +75 -1
  101. package/dist/remediate/steps/dispatch.d.ts.map +1 -1
  102. package/dist/remediate/steps/dispatch.js +159 -43
  103. package/dist/remediate/steps/dispatch.js.map +1 -1
  104. package/dist/remediate/steps/nextStep.d.ts +53 -2
  105. package/dist/remediate/steps/nextStep.d.ts.map +1 -1
  106. package/dist/remediate/steps/nextStep.js +255 -81
  107. package/dist/remediate/steps/nextStep.js.map +1 -1
  108. package/dist/remediate/steps/providerNodeDispatch.d.ts +8 -1
  109. package/dist/remediate/steps/providerNodeDispatch.d.ts.map +1 -1
  110. package/dist/remediate/steps/providerNodeDispatch.js +7 -2
  111. package/dist/remediate/steps/providerNodeDispatch.js.map +1 -1
  112. package/dist/remediate/steps/rollingSession.d.ts +55 -1
  113. package/dist/remediate/steps/rollingSession.d.ts.map +1 -1
  114. package/dist/remediate/steps/rollingSession.js +132 -21
  115. package/dist/remediate/steps/rollingSession.js.map +1 -1
  116. package/dist/remediate/validation/contractPipelineGates.d.ts +23 -8
  117. package/dist/remediate/validation/contractPipelineGates.d.ts.map +1 -1
  118. package/dist/remediate/validation/contractPipelineGates.js +43 -38
  119. package/dist/remediate/validation/contractPipelineGates.js.map +1 -1
  120. package/dist/shared/dispatch/coordinator.d.ts +170 -0
  121. package/dist/shared/dispatch/coordinator.d.ts.map +1 -0
  122. package/dist/shared/dispatch/coordinator.js +177 -0
  123. package/dist/shared/dispatch/coordinator.js.map +1 -0
  124. package/dist/shared/dispatch/hybridDispatch.d.ts +74 -0
  125. package/dist/shared/dispatch/hybridDispatch.d.ts.map +1 -0
  126. package/dist/shared/dispatch/hybridDispatch.js +54 -0
  127. package/dist/shared/dispatch/hybridDispatch.js.map +1 -0
  128. package/dist/shared/dispatch/settledPools.d.ts +21 -0
  129. package/dist/shared/dispatch/settledPools.d.ts.map +1 -0
  130. package/dist/shared/dispatch/settledPools.js +34 -0
  131. package/dist/shared/dispatch/settledPools.js.map +1 -0
  132. package/dist/shared/index.d.ts +15 -5
  133. package/dist/shared/index.d.ts.map +1 -1
  134. package/dist/shared/index.js +14 -2
  135. package/dist/shared/index.js.map +1 -1
  136. package/dist/shared/intent/clauseInterpreter.d.ts +19 -0
  137. package/dist/shared/intent/clauseInterpreter.d.ts.map +1 -1
  138. package/dist/shared/intent/clauseInterpreter.js +19 -0
  139. package/dist/shared/intent/clauseInterpreter.js.map +1 -1
  140. package/dist/shared/providers/sharedProviderConfirmation.d.ts +134 -0
  141. package/dist/shared/providers/sharedProviderConfirmation.d.ts.map +1 -0
  142. package/dist/shared/providers/sharedProviderConfirmation.js +244 -0
  143. package/dist/shared/providers/sharedProviderConfirmation.js.map +1 -0
  144. package/dist/shared/quota/apiPool.d.ts +109 -0
  145. package/dist/shared/quota/apiPool.d.ts.map +1 -0
  146. package/dist/shared/quota/apiPool.js +183 -0
  147. package/dist/shared/quota/apiPool.js.map +1 -0
  148. package/dist/shared/quota/capacity.d.ts +29 -1
  149. package/dist/shared/quota/capacity.d.ts.map +1 -1
  150. package/dist/shared/quota/capacity.js +5 -0
  151. package/dist/shared/quota/capacity.js.map +1 -1
  152. package/dist/shared/quota/claimRegistry.d.ts +64 -0
  153. package/dist/shared/quota/claimRegistry.d.ts.map +1 -0
  154. package/dist/shared/quota/claimRegistry.js +157 -0
  155. package/dist/shared/quota/claimRegistry.js.map +1 -0
  156. package/dist/shared/quota/compositeQuotaSource.d.ts +10 -1
  157. package/dist/shared/quota/compositeQuotaSource.d.ts.map +1 -1
  158. package/dist/shared/quota/compositeQuotaSource.js +34 -6
  159. package/dist/shared/quota/compositeQuotaSource.js.map +1 -1
  160. package/dist/shared/quota/fileLock.d.ts.map +1 -1
  161. package/dist/shared/quota/fileLock.js +7 -1
  162. package/dist/shared/quota/fileLock.js.map +1 -1
  163. package/dist/shared/quota/httpQuotaSource.d.ts +9 -1
  164. package/dist/shared/quota/httpQuotaSource.d.ts.map +1 -1
  165. package/dist/shared/quota/httpQuotaSource.js +33 -8
  166. package/dist/shared/quota/httpQuotaSource.js.map +1 -1
  167. package/dist/shared/quota/learnedQuotaSource.d.ts +7 -1
  168. package/dist/shared/quota/learnedQuotaSource.d.ts.map +1 -1
  169. package/dist/shared/quota/learnedQuotaSource.js +18 -7
  170. package/dist/shared/quota/learnedQuotaSource.js.map +1 -1
  171. package/dist/shared/quota/quotaSource.d.ts +41 -0
  172. package/dist/shared/quota/quotaSource.d.ts.map +1 -1
  173. package/dist/shared/quota/quotaSource.js +19 -0
  174. package/dist/shared/quota/quotaSource.js.map +1 -1
  175. package/dist/shared/types/contractPipeline/obligations.d.ts +42 -0
  176. package/dist/shared/types/contractPipeline/obligations.d.ts.map +1 -1
  177. package/dist/shared/types/contractPipeline.d.ts +1 -1
  178. package/dist/shared/types/contractPipeline.d.ts.map +1 -1
  179. package/dist/shared/types/contractPipeline.js.map +1 -1
  180. package/dist/shared/types/intentCheckpoint.d.ts +14 -0
  181. package/dist/shared/types/intentCheckpoint.d.ts.map +1 -1
  182. package/dist/shared/types/intentCheckpoint.js +10 -0
  183. package/dist/shared/types/intentCheckpoint.js.map +1 -1
  184. package/dist/shared/types/sessionConfig.d.ts +60 -0
  185. package/dist/shared/types/sessionConfig.d.ts.map +1 -1
  186. package/dist/shared/types/sessionConfig.js +13 -0
  187. package/dist/shared/types/sessionConfig.js.map +1 -1
  188. package/package.json +3 -2
@@ -0,0 +1,157 @@
1
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
+ import { withFileLock, STALE_LOCK_MS } from "./fileLock.js";
4
+ function mintOwnerToken() {
5
+ return `${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
6
+ }
7
+ function isClaimRecord(value) {
8
+ if (value === null || typeof value !== "object" || Array.isArray(value))
9
+ return false;
10
+ const obj = value;
11
+ return (typeof obj.ownerToken === "string" &&
12
+ typeof obj.poolId === "string" &&
13
+ typeof obj.heartbeatAt === "number" &&
14
+ Number.isFinite(obj.heartbeatAt));
15
+ }
16
+ // Read the registry, degrading ANY malformed/absent state to an empty map. A
17
+ // corrupt registry must never throw into the dispatch loop — at worst a claim is
18
+ // re-granted, which the lock-serialized write then makes consistent again. Only
19
+ // well-formed individual records are retained; junk entries are dropped silently.
20
+ async function readClaimMap(registryPath) {
21
+ let raw;
22
+ try {
23
+ raw = await readFile(registryPath, "utf8");
24
+ }
25
+ catch {
26
+ return {};
27
+ }
28
+ let parsed;
29
+ try {
30
+ parsed = JSON.parse(raw);
31
+ }
32
+ catch {
33
+ return {};
34
+ }
35
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
36
+ return {};
37
+ const out = {};
38
+ for (const [nodeId, record] of Object.entries(parsed)) {
39
+ if (isClaimRecord(record))
40
+ out[nodeId] = record;
41
+ }
42
+ return out;
43
+ }
44
+ async function writeClaimMap(registryPath, claims) {
45
+ await mkdir(dirname(registryPath), { recursive: true });
46
+ await writeFile(registryPath, `${JSON.stringify(claims, null, 2)}\n`, "utf8");
47
+ }
48
+ function isStale(record, now) {
49
+ return now - record.heartbeatAt > STALE_LOCK_MS;
50
+ }
51
+ /**
52
+ * File-backed claim registry. The caller owns the path (and may point two
53
+ * coordinators at the same file — that is the whole point). Every mutating op
54
+ * runs its entire read-modify-write inside `withFileLock(registryPath + '.lock')`
55
+ * so concurrent loops are serialized and the single-grant invariant holds.
56
+ */
57
+ export class ClaimRegistry {
58
+ registryPath;
59
+ now;
60
+ lockPath;
61
+ constructor(registryPath, now = () => Date.now()) {
62
+ this.registryPath = registryPath;
63
+ this.now = now;
64
+ this.lockPath = `${registryPath}.lock`;
65
+ }
66
+ /**
67
+ * Attempt to claim `nodeId` for `poolId`. Granted when the node is unclaimed or
68
+ * the existing claim is stale (heartbeat older than STALE_LOCK_MS). Returns the
69
+ * fresh ownerToken on success, or `{ acquired: false, heldBy }` carrying the
70
+ * live owner's token when another loop holds it.
71
+ */
72
+ async claim(nodeId, poolId) {
73
+ return withFileLock(this.lockPath, async () => {
74
+ const claims = await readClaimMap(this.registryPath);
75
+ const now = this.now();
76
+ const existing = claims[nodeId];
77
+ if (existing && !isStale(existing, now)) {
78
+ return { acquired: false, heldBy: existing.ownerToken };
79
+ }
80
+ const ownerToken = mintOwnerToken();
81
+ claims[nodeId] = { ownerToken, poolId, heartbeatAt: now };
82
+ await writeClaimMap(this.registryPath, claims);
83
+ return { acquired: true, ownerToken };
84
+ });
85
+ }
86
+ /**
87
+ * Refresh the heartbeat on a claim we still hold. Token-checked: a no-op if the
88
+ * node is unclaimed or held under a different token. Returns whether the
89
+ * heartbeat was applied. This is how a long-running owner stays "live" and so
90
+ * survives a concurrent `reclaimStale()`.
91
+ */
92
+ async heartbeat(nodeId, ownerToken) {
93
+ return withFileLock(this.lockPath, async () => {
94
+ const claims = await readClaimMap(this.registryPath);
95
+ const existing = claims[nodeId];
96
+ if (!existing || existing.ownerToken !== ownerToken)
97
+ return false;
98
+ existing.heartbeatAt = this.now();
99
+ await writeClaimMap(this.registryPath, claims);
100
+ return true;
101
+ });
102
+ }
103
+ /**
104
+ * Release a claim we hold. Token-checked: only the owner can release, so a
105
+ * stale-observation racer can never drop a claim another loop legitimately
106
+ * holds. Returns whether a claim was removed.
107
+ */
108
+ async release(nodeId, ownerToken) {
109
+ return withFileLock(this.lockPath, async () => {
110
+ const claims = await readClaimMap(this.registryPath);
111
+ const existing = claims[nodeId];
112
+ if (!existing || existing.ownerToken !== ownerToken)
113
+ return false;
114
+ delete claims[nodeId];
115
+ await writeClaimMap(this.registryPath, claims);
116
+ return true;
117
+ });
118
+ }
119
+ /**
120
+ * Reclaim every claim whose heartbeat is older than STALE_LOCK_MS, returning
121
+ * the freed nodeIds. A claim that was re-heartbeated since the staleness check
122
+ * is — by the same single-lock serialization — observed fresh here and left
123
+ * intact, so a live owner is never clobbered.
124
+ */
125
+ async reclaimStale() {
126
+ return withFileLock(this.lockPath, async () => {
127
+ const claims = await readClaimMap(this.registryPath);
128
+ const now = this.now();
129
+ const reclaimed = [];
130
+ for (const [nodeId, record] of Object.entries(claims)) {
131
+ if (isStale(record, now)) {
132
+ delete claims[nodeId];
133
+ reclaimed.push(nodeId);
134
+ }
135
+ }
136
+ if (reclaimed.length > 0)
137
+ await writeClaimMap(this.registryPath, claims);
138
+ return reclaimed;
139
+ });
140
+ }
141
+ /** Snapshot of all current claims, keyed by nodeId. Read under the lock. */
142
+ async listClaims() {
143
+ return withFileLock(this.lockPath, async () => readClaimMap(this.registryPath));
144
+ }
145
+ /**
146
+ * Whether `nodeId` currently has a LIVE (non-stale) claim. A stale claim reads
147
+ * as not-claimed, since the next `claim()` would grant over it.
148
+ */
149
+ async isClaimed(nodeId) {
150
+ return withFileLock(this.lockPath, async () => {
151
+ const claims = await readClaimMap(this.registryPath);
152
+ const existing = claims[nodeId];
153
+ return existing !== undefined && !isStale(existing, this.now());
154
+ });
155
+ }
156
+ }
157
+ //# sourceMappingURL=claimRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claimRegistry.js","sourceRoot":"","sources":["../../../src/shared/quota/claimRegistry.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { QuotaSource, QuotaUsageSnapshot } from "./quotaSource.js";
1
+ import type { QuotaProbeResult, QuotaSource, QuotaUsageSnapshot } from "./quotaSource.js";
2
2
  import { RunLogger } from "../observability/runLog.js";
3
3
  export interface BuildQuotaSourceOptions {
4
4
  halfLifeHours?: number;
@@ -17,6 +17,15 @@ export declare class CompositeQuotaSource implements QuotaSource {
17
17
  private runLogger;
18
18
  constructor(sources: QuotaSource[], runLogger?: RunLogger);
19
19
  queryCurrentUsage(providerModelKey: string): Promise<QuotaUsageSnapshot | null>;
20
+ /**
21
+ * Probe the cascade with an aggregate status: the first source that returns a
22
+ * snapshot wins (`ok`); otherwise the result is `degraded` when any source
23
+ * that handles this provider was queried and silently degraded (or threw), and
24
+ * `not_applicable` only when no source ever applied. This is what lets a pool
25
+ * record that a live quota reading was expected but lost, instead of treating
26
+ * every empty cascade as "no source configured".
27
+ */
28
+ probeUsage(providerModelKey: string): Promise<QuotaProbeResult>;
20
29
  }
21
30
  /**
22
31
  * Builds the standard runtime quota snapshot cascade.
@@ -1 +1 @@
1
- {"version":3,"file":"compositeQuotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/compositeQuotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAOxE,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEvD,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,WAAW,EAAE,CAAC;IAClC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;CACnC;AAED,qBAAa,oBAAqB,YAAW,WAAW;IACtD,QAAQ,CAAC,IAAI,eAAe;IAC5B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,SAAS,CAAY;gBAEjB,OAAO,EAAE,WAAW,EAAE,EAAE,SAAS,CAAC,EAAE,SAAS;IAKnD,iBAAiB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;CAiBtF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B,GAAG,WAAW,CAmBnF"}
1
+ {"version":3,"file":"compositeQuotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/compositeQuotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAO1F,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEvD,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,WAAW,EAAE,CAAC;IAClC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;CACnC;AAED,qBAAa,oBAAqB,YAAW,WAAW;IACtD,QAAQ,CAAC,IAAI,eAAe;IAC5B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,SAAS,CAAY;gBAEjB,OAAO,EAAE,WAAW,EAAE,EAAE,SAAS,CAAC,EAAE,SAAS;IAKnD,iBAAiB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAIrF;;;;;;;OAOG;IACG,UAAU,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAgCtE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B,GAAG,WAAW,CAmBnF"}
@@ -14,15 +14,43 @@ export class CompositeQuotaSource {
14
14
  this.runLogger = runLogger ?? RunLogger.disabled();
15
15
  }
16
16
  async queryCurrentUsage(providerModelKey) {
17
+ return (await this.probeUsage(providerModelKey)).snapshot;
18
+ }
19
+ /**
20
+ * Probe the cascade with an aggregate status: the first source that returns a
21
+ * snapshot wins (`ok`); otherwise the result is `degraded` when any source
22
+ * that handles this provider was queried and silently degraded (or threw), and
23
+ * `not_applicable` only when no source ever applied. This is what lets a pool
24
+ * record that a live quota reading was expected but lost, instead of treating
25
+ * every empty cascade as "no source configured".
26
+ */
27
+ async probeUsage(providerModelKey) {
28
+ let sawDegraded = false;
17
29
  for (const source of this.sources) {
18
30
  try {
19
- const snapshot = await source.queryCurrentUsage(providerModelKey);
20
- if (snapshot)
21
- return snapshot;
31
+ // Invoke the source directly (not via the swallowing `probeQuotaSource`)
32
+ // so a throw propagates to the catch below, where it is BOTH logged and
33
+ // counted as a degrade — preserving the operator-visible failure event.
34
+ let result;
35
+ if (source.probeUsage) {
36
+ result = await source.probeUsage(providerModelKey);
37
+ }
38
+ else {
39
+ // A bare `queryCurrentUsage` source can't distinguish a silent degrade
40
+ // from a non-match, so a null result is `not_applicable`; a throw falls
41
+ // through to the catch and is recorded as a degrade there.
42
+ const snapshot = await source.queryCurrentUsage(providerModelKey);
43
+ result = { snapshot, status: snapshot ? "ok" : "not_applicable" };
44
+ }
45
+ if (result.snapshot)
46
+ return result;
47
+ if (result.status === "degraded")
48
+ sawDegraded = true;
22
49
  }
23
50
  catch (err) {
24
- // Skip failing sources, try next — but surface the failure so operators
25
- // can detect a persistently failing quota source.
51
+ // A throw is a degrade for that source — surface it so operators can
52
+ // detect a persistently failing quota source, then try the next one.
53
+ sawDegraded = true;
26
54
  this.runLogger.event({
27
55
  kind: "error",
28
56
  phase: "quota",
@@ -30,7 +58,7 @@ export class CompositeQuotaSource {
30
58
  });
31
59
  }
32
60
  }
33
- return null;
61
+ return { snapshot: null, status: sawDegraded ? "degraded" : "not_applicable" };
34
62
  }
35
63
  }
36
64
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"compositeQuotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/compositeQuotaSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAcvD,MAAM,OAAO,oBAAoB;IACtB,IAAI,GAAG,WAAW,CAAC;IACpB,OAAO,CAAgB;IACvB,SAAS,CAAY;IAE7B,YAAY,OAAsB,EAAE,SAAqB;QACvD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,gBAAwB;QAC9C,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;gBAClE,IAAI,QAAQ;oBAAE,OAAO,QAAQ,CAAC;YAChC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,wEAAwE;gBACxE,kDAAkD;gBAClD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;oBACnB,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,OAAO;oBACd,IAAI,EAAE,iBAAiB,MAAM,CAAC,IAAI,oBAAoB,gBAAgB,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;iBAC9H,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAmC,EAAE;IACpE,MAAM,SAAS,GAAkB,EAAE,CAAC;IACpC,IAAI,OAAO,CAAC,WAAW,KAAK,KAAK,EAAE,CAAC;QAClC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,IAAI,IAAI,sBAAsB,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,+EAA+E;IAC/E,8EAA8E;IAC9E,0EAA0E;IAC1E,SAAS,CAAC,IAAI,CACZ,IAAI,gBAAgB,EAAE,EACtB,IAAI,kBAAkB,EAAE,EACxB,IAAI,sBAAsB,EAAE,EAC5B,IAAI,mBAAmB,EAAE,CAC1B,CAAC;IACF,OAAO,IAAI,oBAAoB,CAAC;QAC9B,GAAG,SAAS;QACZ,GAAG,CAAC,OAAO,CAAC,iBAAiB,IAAI,EAAE,CAAC;QACpC,IAAI,kBAAkB,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;KACpD,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;AACxB,CAAC"}
1
+ {"version":3,"file":"compositeQuotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/compositeQuotaSource.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"fileLock.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/fileLock.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5D,eAAO,MAAM,aAAa,QAAS,CAAC;AASpC,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,QAAQ,EAAE,MAAM;CAI7B;AAkGD,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAA2B,EACtC,MAAM,CAAC,EAAE,SAAS,GACjB,OAAO,CAAC,MAAM,CAAC,CAmDjB;AAED,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYrF;AAED,wBAAsB,YAAY,CAAC,CAAC,EAClC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,SAAS,GACjB,OAAO,CAAC,CAAC,CAAC,CAkBZ"}
1
+ {"version":3,"file":"fileLock.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/fileLock.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5D,eAAO,MAAM,aAAa,QAAS,CAAC;AASpC,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,QAAQ,EAAE,MAAM;CAI7B;AAkGD,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAA2B,EACtC,MAAM,CAAC,EAAE,SAAS,GACjB,OAAO,CAAC,MAAM,CAAC,CAyDjB;AAED,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYrF;AAED,wBAAsB,YAAY,CAAC,CAAC,EAClC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,SAAS,GACjB,OAAO,CAAC,CAAC,CAAC,CAkBZ"}
@@ -1,4 +1,5 @@
1
- import { writeFile, unlink, stat, readFile } from "node:fs/promises";
1
+ import { writeFile, unlink, stat, readFile, mkdir } from "node:fs/promises";
2
+ import { dirname } from "node:path";
2
3
  export const STALE_LOCK_MS = 30_000;
3
4
  // Lock-acquire retry uses exponential backoff (initial → doubling → max) rather
4
5
  // than a fixed poll, so a long contention window costs far fewer wakeups. The
@@ -116,6 +117,11 @@ export async function acquireLock(lockPath, timeoutMs = DEFAULT_TIMEOUT_MS, logg
116
117
  const deadline = Date.now() + timeoutMs;
117
118
  let lastStaleCheckAt = 0;
118
119
  let retryInterval = RETRY_INTERVAL_INITIAL_MS;
120
+ // A lock cannot be created in a directory that does not exist — the `wx` create
121
+ // would ENOENT (not EEXIST), failing the whole acquisition. Ensure the parent dir
122
+ // exists so callers that lock a path before its run dir is materialized (e.g. the
123
+ // A-8 audit hybrid claiming before the review run is set up) just work. Idempotent.
124
+ await mkdir(dirname(lockPath), { recursive: true });
119
125
  while (true) {
120
126
  try {
121
127
  await writeFile(lockPath, token, { flag: "wx" });
@@ -1 +1 @@
1
- {"version":3,"file":"fileLock.js","sourceRoot":"","sources":["../../../src/shared/quota/fileLock.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fileLock.js","sourceRoot":"","sources":["../../../src/shared/quota/fileLock.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { QuotaSource, QuotaUsageSnapshot } from "./quotaSource.js";
1
+ import type { QuotaProbeResult, QuotaSource, QuotaUsageSnapshot } from "./quotaSource.js";
2
2
  /**
3
3
  * Shared scaffolding for PROACTIVE per-provider quota sources (Claude, Codex,
4
4
  * Copilot, Antigravity, OpenCode-broker). Each subclass only supplies the
@@ -62,6 +62,14 @@ export declare abstract class BaseHttpQuotaSource implements QuotaSource {
62
62
  */
63
63
  protected abstract fetchSnapshot(provider: string, model: string | null, nowMs: number): Promise<QuotaUsageSnapshot | null>;
64
64
  queryCurrentUsage(providerModelKey: string): Promise<QuotaUsageSnapshot | null>;
65
+ /**
66
+ * Probe with an explicit status (see {@link QuotaProbeResult}). A non-matching
67
+ * provider key or a network-skipped probe is `not_applicable`; a real query
68
+ * that yields no snapshot (missing creds, 401/5xx, bad payload) is `degraded`
69
+ * — the silent-degrade signal a bare `null` from `queryCurrentUsage` hides.
70
+ * Both paths return through here so the cache and the status stay consistent.
71
+ */
72
+ probeUsage(providerModelKey: string): Promise<QuotaProbeResult>;
65
73
  /** Context for the reusable `fetchXxxUsage` helpers. */
66
74
  protected fetchContext(): UsageFetchContext;
67
75
  protected shouldSkipNetwork(): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"httpQuotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/httpQuotaSource.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"httpQuotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/httpQuotaSource.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,9 @@
1
+ /** A handled provider with a snapshot is `ok`; attempted-but-empty is `degraded`. */
2
+ function classifyProbe(cached) {
3
+ if (cached.snapshot)
4
+ return "ok";
5
+ return cached.attempted ? "degraded" : "not_applicable";
6
+ }
1
7
  const DEFAULT_CACHE_TTL_MS = 45_000;
2
8
  export class BaseHttpQuotaSource {
3
9
  fetchImpl;
@@ -14,19 +20,38 @@ export class BaseHttpQuotaSource {
14
20
  this.userAgent = options.userAgent ?? defaultUserAgent;
15
21
  }
16
22
  async queryCurrentUsage(providerModelKey) {
23
+ return (await this.probeUsage(providerModelKey)).snapshot;
24
+ }
25
+ /**
26
+ * Probe with an explicit status (see {@link QuotaProbeResult}). A non-matching
27
+ * provider key or a network-skipped probe is `not_applicable`; a real query
28
+ * that yields no snapshot (missing creds, 401/5xx, bad payload) is `degraded`
29
+ * — the silent-degrade signal a bare `null` from `queryCurrentUsage` hides.
30
+ * Both paths return through here so the cache and the status stay consistent.
31
+ */
32
+ async probeUsage(providerModelKey) {
17
33
  const { provider, model } = parseProviderModelKey(providerModelKey);
18
- if (!this.handlesProvider(provider))
19
- return null;
34
+ // Gated out for this provider — no I/O, and no signal was ever expected.
35
+ if (!this.handlesProvider(provider)) {
36
+ return { snapshot: null, status: "not_applicable" };
37
+ }
20
38
  const nowMs = this.now();
21
39
  const cached = this.cache.get(providerModelKey);
22
40
  if (cached && nowMs - cached.fetchedAtMs < this.cacheTtlMs) {
23
- return cached.snapshot;
41
+ return { snapshot: cached.snapshot, status: classifyProbe(cached) };
42
+ }
43
+ // The live probe was intentionally skipped (hermeticity / disabled) — absent
44
+ // by design, not a degrade.
45
+ if (this.shouldSkipNetwork()) {
46
+ const result = { fetchedAtMs: nowMs, snapshot: null, attempted: false };
47
+ this.cache.set(providerModelKey, result);
48
+ return { snapshot: null, status: "not_applicable" };
24
49
  }
25
- const snapshot = this.shouldSkipNetwork()
26
- ? null
27
- : await this.fetchSnapshot(provider, model, nowMs);
28
- this.cache.set(providerModelKey, { fetchedAtMs: nowMs, snapshot });
29
- return snapshot;
50
+ // A real query for a handled provider: a null result is a silent degrade.
51
+ const snapshot = await this.fetchSnapshot(provider, model, nowMs);
52
+ const result = { fetchedAtMs: nowMs, snapshot, attempted: true };
53
+ this.cache.set(providerModelKey, result);
54
+ return { snapshot, status: classifyProbe(result) };
30
55
  }
31
56
  /** Context for the reusable `fetchXxxUsage` helpers. */
32
57
  fetchContext() {
@@ -1 +1 @@
1
- {"version":3,"file":"httpQuotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/httpQuotaSource.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"httpQuotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/httpQuotaSource.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,14 @@
1
- import type { QuotaSource, QuotaUsageSnapshot } from "./quotaSource.js";
1
+ import type { QuotaProbeResult, QuotaSource, QuotaUsageSnapshot } from "./quotaSource.js";
2
2
  export declare class LearnedQuotaSource implements QuotaSource {
3
3
  readonly name = "learned";
4
4
  private halfLifeHours;
5
5
  constructor(halfLifeHours?: number);
6
6
  queryCurrentUsage(providerModelKey: string): Promise<QuotaUsageSnapshot | null>;
7
+ /**
8
+ * No learned entry yet is `not_applicable`, never `degraded`: the learned
9
+ * source is the reactive fallback, so the absence of history is the normal
10
+ * cold-start state, not a lost signal.
11
+ */
12
+ probeUsage(providerModelKey: string): Promise<QuotaProbeResult>;
7
13
  }
8
14
  //# sourceMappingURL=learnedQuotaSource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"learnedQuotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/learnedQuotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGxE,qBAAa,kBAAmB,YAAW,WAAW;IACpD,QAAQ,CAAC,IAAI,aAAa;IAE1B,OAAO,CAAC,aAAa,CAAS;gBAElB,aAAa,SAAK;IAIxB,iBAAiB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;CAmBtF"}
1
+ {"version":3,"file":"learnedQuotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/learnedQuotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG1F,qBAAa,kBAAmB,YAAW,WAAW;IACpD,QAAQ,CAAC,IAAI,aAAa;IAE1B,OAAO,CAAC,aAAa,CAAS;gBAElB,aAAa,SAAK;IAIxB,iBAAiB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAIrF;;;;OAIG;IACG,UAAU,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAsBtE"}
@@ -6,20 +6,31 @@ export class LearnedQuotaSource {
6
6
  this.halfLifeHours = halfLifeHours;
7
7
  }
8
8
  async queryCurrentUsage(providerModelKey) {
9
+ return (await this.probeUsage(providerModelKey)).snapshot;
10
+ }
11
+ /**
12
+ * No learned entry yet is `not_applicable`, never `degraded`: the learned
13
+ * source is the reactive fallback, so the absence of history is the normal
14
+ * cold-start state, not a lost signal.
15
+ */
16
+ async probeUsage(providerModelKey) {
9
17
  const state = await readQuotaState();
10
18
  const entry = state.entries[providerModelKey];
11
19
  if (!entry)
12
- return null;
20
+ return { snapshot: null, status: "not_applicable" };
13
21
  const maxSafe = computeMaxSafeConcurrency(entry, this.halfLifeHours);
14
22
  const isInCooldown = entry.cooldown_until != null &&
15
23
  new Date(entry.cooldown_until).getTime() > Date.now();
16
24
  return {
17
- remaining_pct: isInCooldown ? 0 : null,
18
- reset_at: isInCooldown ? entry.cooldown_until : null,
19
- requests_remaining: maxSafe,
20
- tokens_remaining: null,
21
- captured_at: entry.updated_at,
22
- source: "learned",
25
+ snapshot: {
26
+ remaining_pct: isInCooldown ? 0 : null,
27
+ reset_at: isInCooldown ? entry.cooldown_until : null,
28
+ requests_remaining: maxSafe,
29
+ tokens_remaining: null,
30
+ captured_at: entry.updated_at,
31
+ source: "learned",
32
+ },
33
+ status: "ok",
23
34
  };
24
35
  }
25
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"learnedQuotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/learnedQuotaSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEvE,MAAM,OAAO,kBAAkB;IACpB,IAAI,GAAG,SAAS,CAAC;IAElB,aAAa,CAAS;IAE9B,YAAY,aAAa,GAAG,EAAE;QAC5B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,gBAAwB;QAC9C,MAAM,KAAK,GAAG,MAAM,cAAc,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAExB,MAAM,OAAO,GAAG,yBAAyB,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACrE,MAAM,YAAY,GAChB,KAAK,CAAC,cAAc,IAAI,IAAI;YAC5B,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAExD,OAAO;YACL,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;YACtC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI;YACpD,kBAAkB,EAAE,OAAO;YAC3B,gBAAgB,EAAE,IAAI;YACtB,WAAW,EAAE,KAAK,CAAC,UAAU;YAC7B,MAAM,EAAE,SAAS;SAClB,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"learnedQuotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/learnedQuotaSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEvE,MAAM,OAAO,kBAAkB;IACpB,IAAI,GAAG,SAAS,CAAC;IAElB,aAAa,CAAS;IAE9B,YAAY,aAAa,GAAG,EAAE;QAC5B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,gBAAwB;QAC9C,OAAO,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,UAAU,CAAC,gBAAwB;QACvC,MAAM,KAAK,GAAG,MAAM,cAAc,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QAEhE,MAAM,OAAO,GAAG,yBAAyB,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACrE,MAAM,YAAY,GAChB,KAAK,CAAC,cAAc,IAAI,IAAI;YAC5B,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAExD,OAAO;YACL,QAAQ,EAAE;gBACR,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;gBACtC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI;gBACpD,kBAAkB,EAAE,OAAO;gBAC3B,gBAAgB,EAAE,IAAI;gBACtB,WAAW,EAAE,KAAK,CAAC,UAAU;gBAC7B,MAAM,EAAE,SAAS;aAClB;YACD,MAAM,EAAE,IAAI;SACb,CAAC;IACJ,CAAC;CACF"}
@@ -22,8 +22,49 @@ export declare const QuotaUsageSnapshotSchema: z.ZodObject<{
22
22
  source: string;
23
23
  }>;
24
24
  export type QuotaUsageSnapshot = z.infer<typeof QuotaUsageSnapshotSchema>;
25
+ /**
26
+ * Outcome of probing a quota source for one provider/model key, disambiguating
27
+ * the two cases a bare `null` snapshot conflates:
28
+ *
29
+ * - `ok` — a live snapshot was mapped (`snapshot` is non-null).
30
+ * - `degraded` — the source HANDLES this provider and was actually queried,
31
+ * but produced no snapshot (missing/expired creds, 401/5xx,
32
+ * network error, or an unmappable payload). The signal that was
33
+ * *expected* was silently lost — the operator-visible failure
34
+ * mode that `queryCurrentUsage`'s `null` hides.
35
+ * - `not_applicable` — the source does not answer for this provider (gated out
36
+ * with no I/O), or the live probe was intentionally skipped
37
+ * (hermeticity guard / proactive-quota disabled). No signal was
38
+ * ever expected, so its absence is not a degrade.
39
+ *
40
+ * This is the contract behind the `CapacityPool.quotaSignalDegraded` marker: a
41
+ * pool whose probe is `degraded` is dispatching blind where it expected a live
42
+ * quota reading, and that fact is attached to the pool rather than swallowed.
43
+ */
44
+ export type QuotaProbeStatus = "ok" | "degraded" | "not_applicable";
45
+ export interface QuotaProbeResult {
46
+ snapshot: QuotaUsageSnapshot | null;
47
+ status: QuotaProbeStatus;
48
+ }
25
49
  export interface QuotaSource {
26
50
  readonly name: string;
27
51
  queryCurrentUsage(providerModelKey: string): Promise<QuotaUsageSnapshot | null>;
52
+ /**
53
+ * Like {@link queryCurrentUsage}, but reports WHY the snapshot is null: a
54
+ * source that was queried and silently degraded (`degraded`) vs. one that
55
+ * never applied (`not_applicable`). Optional on the interface so plain
56
+ * `{ name, queryCurrentUsage }` stubs remain valid; {@link probeQuotaSource}
57
+ * derives a best-effort result for sources that don't implement it.
58
+ */
59
+ probeUsage?(providerModelKey: string): Promise<QuotaProbeResult>;
28
60
  }
61
+ /**
62
+ * Probe a quota source, using its native {@link QuotaSource.probeUsage} when it
63
+ * has one and otherwise deriving a conservative result from
64
+ * {@link QuotaSource.queryCurrentUsage}: a snapshot is `ok`, a thrown error is
65
+ * `degraded` (it was attempted and failed), and a plain `null` is reported as
66
+ * `not_applicable` (a source without `probeUsage` cannot distinguish a silent
67
+ * degrade from a non-match, so it must not over-report a degrade).
68
+ */
69
+ export declare function probeQuotaSource(source: QuotaSource, providerModelKey: string): Promise<QuotaProbeResult>;
29
70
  //# sourceMappingURL=quotaSource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"quotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/quotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;EAS1B,CAAC;AACZ,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;CACjF"}
1
+ {"version":3,"file":"quotaSource.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/quotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;EAS1B,CAAC;AACZ,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,UAAU,GAAG,gBAAgB,CAAC;AAEpE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACpC,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IAChF;;;;;;OAMG;IACH,UAAU,CAAC,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAClE;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EACnB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAQ3B"}
@@ -9,4 +9,23 @@ export const QuotaUsageSnapshotSchema = z
9
9
  source: z.string(),
10
10
  })
11
11
  .strict();
12
+ /**
13
+ * Probe a quota source, using its native {@link QuotaSource.probeUsage} when it
14
+ * has one and otherwise deriving a conservative result from
15
+ * {@link QuotaSource.queryCurrentUsage}: a snapshot is `ok`, a thrown error is
16
+ * `degraded` (it was attempted and failed), and a plain `null` is reported as
17
+ * `not_applicable` (a source without `probeUsage` cannot distinguish a silent
18
+ * degrade from a non-match, so it must not over-report a degrade).
19
+ */
20
+ export async function probeQuotaSource(source, providerModelKey) {
21
+ if (source.probeUsage)
22
+ return source.probeUsage(providerModelKey);
23
+ try {
24
+ const snapshot = await source.queryCurrentUsage(providerModelKey);
25
+ return { snapshot, status: snapshot ? "ok" : "not_applicable" };
26
+ }
27
+ catch {
28
+ return { snapshot: null, status: "degraded" };
29
+ }
30
+ }
12
31
  //# sourceMappingURL=quotaSource.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"quotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/quotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC;KACtC,MAAM,CAAC;IACN,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC/C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC7C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;CACnB,CAAC;KACD,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"quotaSource.js","sourceRoot":"","sources":["../../../src/shared/quota/quotaSource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC;KACtC,MAAM,CAAC;IACN,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC/C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC7C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;CACnB,CAAC;KACD,MAAM,EAAE,CAAC;AA0CZ;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAmB,EACnB,gBAAwB;IAExB,IAAI,MAAM,CAAC,UAAU;QAAE,OAAO,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAClE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;QAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAChD,CAAC;AACH,CAAC"}