@resolveio/server-lib 22.3.186 → 22.3.187

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.
@@ -124,6 +124,7 @@ export interface ResolveIOAICoderWorkflowProofReadiness {
124
124
  evaluatedAt: string;
125
125
  }
126
126
  export type ResolveIOAICoderV6ContinuationAction = 'continue' | 'retry_same_step' | 'switch_to_repair' | 'park' | 'budget_stop' | 'infra_retry' | 'ready_to_publish';
127
+ export type ResolveIOAICoderNextActionCostRisk = 'free_or_deterministic' | 'small_model_or_qa' | 'expensive_model' | 'release_or_customer_send' | 'manual_blocked';
127
128
  export type ResolveIOAICoderWorkflowReadinessStatus = 'journey_contract_required' | 'journey_contract_repair_required' | 'workflow_build_ready' | 'workflow_qa_required' | 'workflow_business_proof_ready' | 'release_repair_required' | 'infra_repair_only' | 'compile_repair_only' | 'collect_new_evidence' | 'budget_stopped' | 'parked';
128
129
  export type ResolveIOAICoderWorkflowReadinessGate = 'journey_contract' | 'build' | 'workflow_qa' | 'release' | 'infra' | 'compile' | 'evidence' | 'manual';
129
130
  export type ResolveIOAICoderWorkflowProofCheckpointStatus = 'waiting_for_journey_contract' | 'waiting_for_workflow_proof' | 'waiting_for_new_evidence' | 'waiting_for_release_gate' | 'waiting_for_infra_or_compile' | 'ready_to_continue';
@@ -172,6 +173,46 @@ export interface ResolveIOAICoderWorkflowReadiness {
172
173
  businessProofArtifacts: string[];
173
174
  workflowProofCheckpoint: ResolveIOAICoderWorkflowProofCheckpoint;
174
175
  }
176
+ export interface ResolveIOAICoderNextActionContract {
177
+ contractId: string;
178
+ action: ResolveIOAICoderV6ContinuationAction;
179
+ label: string;
180
+ primaryCommand: string;
181
+ lane: ResolveIOAICoderV6Lane;
182
+ stepType: ResolveIOAICoderV6StepType;
183
+ safeToAutoRun: boolean;
184
+ requiresHumanApproval: boolean;
185
+ canRunWithoutCodexMonitor: boolean;
186
+ codexFallbackRequired: boolean;
187
+ codexFallbackReason: string;
188
+ costRisk: ResolveIOAICoderNextActionCostRisk;
189
+ workflowFirstSatisfied: boolean;
190
+ decisionBasis: {
191
+ journeyContractReady: boolean;
192
+ workflowProofReady: boolean;
193
+ sampleDataReady: boolean;
194
+ releaseBlocked: boolean;
195
+ routeOnlyBlocked: boolean;
196
+ infraOnly: boolean;
197
+ compileOnly: boolean;
198
+ sameFailureParked: boolean;
199
+ canPublish: boolean;
200
+ canPolishWowUi: boolean;
201
+ workflowReadinessStatus: string;
202
+ workflowProofCheckpointStatus: string;
203
+ failureClass: string;
204
+ evidenceHash: string;
205
+ };
206
+ preconditions: string[];
207
+ expectedStateTransition: string;
208
+ successEvidence: string[];
209
+ stopConditions: string[];
210
+ forbiddenActions: string[];
211
+ nextCommands: string[];
212
+ blockers: string[];
213
+ ownerFiles?: string[];
214
+ createdAt: string;
215
+ }
175
216
  export interface ResolveIOAICoderV6SupervisorState {
176
217
  version: 'v6';
177
218
  runKind: ResolveIOAICoderV6RunKind;
@@ -296,6 +337,7 @@ export interface ResolveIOAICoderV6ContinuationDecision {
296
337
  budgetExceeded: boolean;
297
338
  workflowReadiness: ResolveIOAICoderWorkflowReadiness;
298
339
  workflowProofCheckpoint: ResolveIOAICoderWorkflowProofCheckpoint;
340
+ nextActionContract: ResolveIOAICoderNextActionContract;
299
341
  recoveryPlan: ResolveIOAIManagerRecoveryPlan;
300
342
  recoveryCheckpoint: ResolveIOAIManagerRecoveryCheckpoint;
301
343
  recoveryEvidenceProbe: ResolveIOAIManagerRecoveryEvidenceProbe;
@@ -339,6 +381,17 @@ export declare function buildResolveIOAICoderV6WorkflowReadiness(bundle: Resolve
339
381
  budgetExceeded?: boolean;
340
382
  repeatedNoProgressCount?: number;
341
383
  }): ResolveIOAICoderWorkflowReadiness;
384
+ export declare function buildResolveIOAICoderNextActionContract(input: {
385
+ bundle: ResolveIOAICoderV6StateBundle;
386
+ action: ResolveIOAICoderV6ContinuationAction;
387
+ reason: string;
388
+ nextLane: ResolveIOAICoderV6Lane;
389
+ nextStep: ResolveIOAICoderV6StepType;
390
+ budgetExceeded?: boolean;
391
+ workflowReadiness: ResolveIOAICoderWorkflowReadiness;
392
+ workflowProofCheckpoint: ResolveIOAICoderWorkflowProofCheckpoint;
393
+ now?: Date | string;
394
+ }): ResolveIOAICoderNextActionContract;
342
395
  export declare function buildResolveIOAICoderV6Budget(existing?: Partial<ResolveIOAICoderV6Budget>): ResolveIOAICoderV6Budget;
343
396
  export declare function initializeResolveIOAICoderV6State(input: ResolveIOAICoderV6InitializeInput): ResolveIOAICoderV6StateBundle;
344
397
  export declare function recordResolveIOAICoderV6Step(bundle: ResolveIOAICoderV6StateBundle, step: ResolveIOAICoderV6StepInput): ResolveIOAICoderV6StateBundle;
@@ -55,6 +55,7 @@ exports.evaluateResolveIOAICoderWorkflowProofReadiness = evaluateResolveIOAICode
55
55
  exports.fingerprintResolveIOAICoderV6Blocker = fingerprintResolveIOAICoderV6Blocker;
56
56
  exports.buildResolveIOAICoderWorkflowProofCheckpoint = buildResolveIOAICoderWorkflowProofCheckpoint;
57
57
  exports.buildResolveIOAICoderV6WorkflowReadiness = buildResolveIOAICoderV6WorkflowReadiness;
58
+ exports.buildResolveIOAICoderNextActionContract = buildResolveIOAICoderNextActionContract;
58
59
  exports.buildResolveIOAICoderV6Budget = buildResolveIOAICoderV6Budget;
59
60
  exports.initializeResolveIOAICoderV6State = initializeResolveIOAICoderV6State;
60
61
  exports.recordResolveIOAICoderV6Step = recordResolveIOAICoderV6Step;
@@ -1547,6 +1548,232 @@ function buildResolveIOAICoderV6WorkflowReadiness(bundle, context) {
1547
1548
  workflowProofCheckpoint: workflowProofCheckpoint
1548
1549
  };
1549
1550
  }
1551
+ function aicoderNextActionLabel(command) {
1552
+ switch (command) {
1553
+ case 'repair_aicoder_journey_contract':
1554
+ return 'Repair Journey Contract';
1555
+ case 'run_aicoder_workflow_build':
1556
+ return 'Build North-Star Workflow';
1557
+ case 'run_aicoder_workflow_qa':
1558
+ return 'Run Workflow QA';
1559
+ case 'repair_aicoder_release_gate':
1560
+ return 'Repair Release Gate';
1561
+ case 'repair_aicoder_compile_gate':
1562
+ return 'Repair Compile Gate';
1563
+ case 'repair_aicoder_infra_gate':
1564
+ return 'Repair Infra Gate';
1565
+ case 'run_aicoder_owner_scoped_repair':
1566
+ return 'Run Scoped Repair';
1567
+ case 'publish_aicoder_after_workflow_proof':
1568
+ return 'Publish After Workflow Proof';
1569
+ case 'park_aicoder_until_new_evidence':
1570
+ return 'Park Until New Evidence';
1571
+ case 'park_aicoder_budget_stop':
1572
+ return 'Park Budget Stop';
1573
+ default:
1574
+ return 'Continue Workflow';
1575
+ }
1576
+ }
1577
+ function aicoderNextActionPrimaryCommand(action, readiness) {
1578
+ if (action === 'budget_stop') {
1579
+ return 'park_aicoder_budget_stop';
1580
+ }
1581
+ if (action === 'park') {
1582
+ return 'park_aicoder_until_new_evidence';
1583
+ }
1584
+ if (action === 'infra_retry') {
1585
+ return readiness.compileOnly ? 'repair_aicoder_compile_gate' : 'repair_aicoder_infra_gate';
1586
+ }
1587
+ if (readiness.status === 'journey_contract_required' || readiness.status === 'journey_contract_repair_required') {
1588
+ return 'repair_aicoder_journey_contract';
1589
+ }
1590
+ if (readiness.status === 'workflow_build_ready') {
1591
+ return 'run_aicoder_workflow_build';
1592
+ }
1593
+ if (readiness.status === 'workflow_qa_required') {
1594
+ return 'run_aicoder_workflow_qa';
1595
+ }
1596
+ if (readiness.status === 'release_repair_required') {
1597
+ return 'repair_aicoder_release_gate';
1598
+ }
1599
+ if (action === 'ready_to_publish') {
1600
+ return 'publish_aicoder_after_workflow_proof';
1601
+ }
1602
+ if (action === 'switch_to_repair' || action === 'retry_same_step') {
1603
+ return 'run_aicoder_owner_scoped_repair';
1604
+ }
1605
+ return 'continue_aicoder_workflow';
1606
+ }
1607
+ function aicoderNextActionCostRisk(action, command, readiness) {
1608
+ if (action === 'park' || action === 'budget_stop' || readiness.requiresHumanDecision) {
1609
+ return 'manual_blocked';
1610
+ }
1611
+ if (action === 'ready_to_publish' || command === 'repair_aicoder_release_gate' || readiness.nextGate === 'release') {
1612
+ return 'release_or_customer_send';
1613
+ }
1614
+ if (command === 'run_aicoder_workflow_qa' || command === 'repair_aicoder_compile_gate' || command === 'repair_aicoder_infra_gate') {
1615
+ return 'small_model_or_qa';
1616
+ }
1617
+ if (command === 'continue_aicoder_workflow') {
1618
+ return 'free_or_deterministic';
1619
+ }
1620
+ return 'expensive_model';
1621
+ }
1622
+ function aicoderNextActionExpectedTransition(command) {
1623
+ switch (command) {
1624
+ case 'repair_aicoder_journey_contract':
1625
+ return 'Missing or invalid journey contract becomes a validated first/next/last workflow graph with QA rows.';
1626
+ case 'run_aicoder_workflow_build':
1627
+ return 'Journey contract becomes implemented workflow screens, hub action, data story, and reachable completion state.';
1628
+ case 'run_aicoder_workflow_qa':
1629
+ return 'Route/browser evidence becomes AIQaBusinessAssertion proof for the north-star workflow.';
1630
+ case 'repair_aicoder_release_gate':
1631
+ return 'Publish/deploy/sample-data blocker becomes hotfix evidence, release-gate evidence, or one explicit force-deploy decision.';
1632
+ case 'repair_aicoder_compile_gate':
1633
+ return 'Compile failure becomes a passing build or a new compile blocker fingerprint.';
1634
+ case 'repair_aicoder_infra_gate':
1635
+ return 'Infra/preflight failure becomes a passing startup/browser/Mongo gate or a new infra blocker fingerprint.';
1636
+ case 'run_aicoder_owner_scoped_repair':
1637
+ return 'Current blocker changes to passed, a new evidence hash, or a parked manual decision.';
1638
+ case 'publish_aicoder_after_workflow_proof':
1639
+ return 'Workflow-proven artifact moves through the release gate exactly once with publish/deploy evidence recorded.';
1640
+ case 'park_aicoder_budget_stop':
1641
+ case 'park_aicoder_until_new_evidence':
1642
+ return 'Runner stops spending until an operator records new evidence or an explicit next action.';
1643
+ default:
1644
+ return 'Runner advances to the next workflow-first gate with evidence recorded.';
1645
+ }
1646
+ }
1647
+ function buildResolveIOAICoderNextActionStopConditions(readiness, command) {
1648
+ var stopConditions = [
1649
+ 'Do not accept scorecard, wow score, or route load as app success without AIQaBusinessAssertion workflow proof.'
1650
+ ];
1651
+ if (!readiness.journeyContractReady || command === 'repair_aicoder_journey_contract') {
1652
+ stopConditions.push('Do not run build tasks until docs/APP_JOURNEY_CONTRACT.md validates with first/next/last workflow steps.');
1653
+ }
1654
+ if (!readiness.businessProofReady || readiness.routeOnlyBlocked || command === 'run_aicoder_workflow_qa') {
1655
+ stopConditions.push('Do not publish or run wow UI polish until workflow business proof passes.');
1656
+ stopConditions.push('Route-only proof must stay labeled as route evidence, not acceptance.');
1657
+ }
1658
+ if (readiness.releaseBlocked || command === 'repair_aicoder_release_gate') {
1659
+ stopConditions.push('Do not repeat a full publish/deploy until release blocker evidence changes or hotfix/force evidence is recorded.');
1660
+ }
1661
+ if (readiness.infraOnly || readiness.compileOnly) {
1662
+ stopConditions.push('Infra, startup, Puppeteer, Chrome, Mongo, and compile failures stay in infra/compile repair; do not charge them as product workflow failure.');
1663
+ }
1664
+ if (readiness.sameFailureParked) {
1665
+ stopConditions.push('Do not retry the same model/code repair until the blocker fingerprint, evidence hash, or workflow proof artifact changes.');
1666
+ }
1667
+ if (readiness.requiresHumanDecision) {
1668
+ stopConditions.push('Do not spend additional model or release budget until an operator records the next bounded action.');
1669
+ }
1670
+ return Array.from(new Set(stopConditions)).slice(0, 12);
1671
+ }
1672
+ function buildResolveIOAICoderNextActionContract(input) {
1673
+ var workflowReadiness = input.workflowReadiness;
1674
+ var workflowProofCheckpoint = input.workflowProofCheckpoint;
1675
+ var history = Array.isArray(input.bundle.aiCoderV6StepHistory) ? input.bundle.aiCoderV6StepHistory : [];
1676
+ var last = history[history.length - 1];
1677
+ var command = aicoderNextActionPrimaryCommand(input.action, workflowReadiness);
1678
+ var costRisk = aicoderNextActionCostRisk(input.action, command, workflowReadiness);
1679
+ var requiresHumanApproval = input.action === 'park'
1680
+ || input.action === 'budget_stop'
1681
+ || input.action === 'ready_to_publish'
1682
+ || input.budgetExceeded === true
1683
+ || workflowReadiness.requiresHumanDecision === true;
1684
+ var workflowFirstSatisfied = workflowReadiness.journeyContractReady
1685
+ && workflowReadiness.businessProofReady
1686
+ && !workflowReadiness.releaseBlocked
1687
+ && !workflowReadiness.routeOnlyBlocked
1688
+ && !workflowReadiness.infraOnly
1689
+ && !workflowReadiness.compileOnly
1690
+ && !workflowReadiness.sameFailureParked;
1691
+ var safeToAutoRun = !requiresHumanApproval && (command === 'repair_aicoder_journey_contract'
1692
+ || command === 'run_aicoder_workflow_build'
1693
+ || command === 'run_aicoder_workflow_qa'
1694
+ || command === 'repair_aicoder_release_gate'
1695
+ || command === 'repair_aicoder_compile_gate'
1696
+ || command === 'repair_aicoder_infra_gate'
1697
+ || (command === 'run_aicoder_owner_scoped_repair' && workflowReadiness.canRunProductRepair)
1698
+ || (command === 'continue_aicoder_workflow' && !workflowReadiness.blockers.length));
1699
+ var canRunWithoutCodexMonitor = safeToAutoRun
1700
+ && workflowProofCheckpoint.requiredEvidence.length > 0
1701
+ && workflowProofCheckpoint.nextAction.length > 0;
1702
+ var blockers = Array.from(new Set(__spreadArray(__spreadArray([], __read(workflowReadiness.blockers), false), __read((workflowProofCheckpoint.status === 'waiting_for_new_evidence' ? workflowProofCheckpoint.requiredResetEvidence : [])), false))).slice(0, 12);
1703
+ var preconditions = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray(__spreadArray([
1704
+ workflowProofCheckpoint.nextAction
1705
+ ], __read(workflowProofCheckpoint.requiredEvidence), false), __read((workflowReadiness.journeyContractReady ? [] : ['validated APP_JOURNEY_CONTRACT.md journey_contract JSON'])), false), __read((workflowReadiness.canRunWorkflowQa ? ['workflow QA rows generated from the journey contract'] : [])), false), __read((workflowReadiness.releaseBlocked ? ['release blocker artifact or hotfix-first release evidence'] : [])), false).map(function (entry) { return cleanText(entry, 300); }).filter(Boolean))).slice(0, 12);
1706
+ var successEvidence = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(workflowProofCheckpoint.requiredEvidence), false), __read((workflowReadiness.businessProofReady ? ['retained AIQaBusinessAssertion artifact'] : [])), false), __read((workflowReadiness.canPublish ? ['release gate accepts the workflow-proven artifact'] : [])), false), __read((command === 'repair_aicoder_release_gate' ? ['hotfix evidence or explicit one-time force release decision'] : [])), false).map(function (entry) { return cleanText(entry, 300); }).filter(Boolean))).slice(0, 12);
1707
+ var stopConditions = buildResolveIOAICoderNextActionStopConditions(workflowReadiness, command);
1708
+ var forbiddenActions = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray(__spreadArray([
1709
+ 'accepting route-only proof as app success',
1710
+ 'accepting scorecard-only or wow-score-only proof as app success'
1711
+ ], __read((workflowReadiness.journeyContractReady ? [] : ['building product routes before the journey contract validates'])), false), __read((workflowReadiness.businessProofReady ? [] : ['publishing before north-star workflow business proof passes'])), false), __read((workflowReadiness.releaseBlocked ? ['rerunning full deploy/publish without changed release evidence'] : [])), false), __read((workflowReadiness.sameFailureParked ? ['retrying the same repair loop without new evidence'] : [])), false))).slice(0, 12);
1712
+ var nextCommands = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([
1713
+ command
1714
+ ], __read((command === 'repair_aicoder_journey_contract' ? ['validate_aicoder_journey_contract', 'generate_workflow_qa_rows'] : [])), false), __read((command === 'run_aicoder_workflow_qa' ? ['execute_contract_qa_assertions', 'record_aiqa_business_assertion'] : [])), false), __read((command === 'repair_aicoder_release_gate' ? ['collect_release_blocker_evidence', 'prefer_hotfix_before_full_deploy'] : [])), false), __read((command === 'repair_aicoder_compile_gate' ? ['rerun_compile_gate_only', 'record_compile_evidence_hash'] : [])), false), __read((command === 'repair_aicoder_infra_gate' ? ['rerun_preflight_gate_only', 'record_infra_evidence_hash'] : [])), false), [
1715
+ 'record_aicoder_next_action_result'
1716
+ ], false))).slice(0, 12);
1717
+ var contractBasis = {
1718
+ action: input.action,
1719
+ reason: cleanText(input.reason, 500),
1720
+ command: command,
1721
+ readinessStatus: workflowReadiness.status,
1722
+ checkpointStatus: workflowProofCheckpoint.status,
1723
+ failureClass: cleanText(last === null || last === void 0 ? void 0 : last.failureClass, 120),
1724
+ evidenceHash: (0, ai_runner_manager_policy_1.hashResolveIOAIManagerEvidence)(last)
1725
+ };
1726
+ return {
1727
+ contractId: "aicoder-next-".concat((0, ai_runner_manager_policy_1.hashResolveIOAIManagerEvidence)({
1728
+ failureClass: contractBasis.failureClass,
1729
+ summary: "".concat(contractBasis.reason, ":").concat(contractBasis.command, ":").concat(contractBasis.readinessStatus, ":").concat(contractBasis.checkpointStatus),
1730
+ evidenceHash: contractBasis.evidenceHash,
1731
+ changedFiles: last === null || last === void 0 ? void 0 : last.changedFiles,
1732
+ artifactPaths: last === null || last === void 0 ? void 0 : last.artifactPaths
1733
+ })),
1734
+ action: input.action,
1735
+ label: aicoderNextActionLabel(command),
1736
+ primaryCommand: command,
1737
+ lane: input.nextLane,
1738
+ stepType: input.nextStep,
1739
+ safeToAutoRun: safeToAutoRun,
1740
+ requiresHumanApproval: requiresHumanApproval,
1741
+ canRunWithoutCodexMonitor: canRunWithoutCodexMonitor,
1742
+ codexFallbackRequired: !canRunWithoutCodexMonitor && !requiresHumanApproval,
1743
+ codexFallbackReason: canRunWithoutCodexMonitor
1744
+ ? ''
1745
+ : requiresHumanApproval
1746
+ ? 'Operator approval is required before the next action.'
1747
+ : 'Next action needs stronger deterministic evidence before it can run unattended.',
1748
+ costRisk: costRisk,
1749
+ workflowFirstSatisfied: workflowFirstSatisfied,
1750
+ decisionBasis: {
1751
+ journeyContractReady: workflowReadiness.journeyContractReady,
1752
+ workflowProofReady: workflowReadiness.businessProofReady,
1753
+ sampleDataReady: workflowReadiness.businessProofReady && !workflowReadiness.releaseBlocked,
1754
+ releaseBlocked: workflowReadiness.releaseBlocked,
1755
+ routeOnlyBlocked: workflowReadiness.routeOnlyBlocked,
1756
+ infraOnly: workflowReadiness.infraOnly,
1757
+ compileOnly: workflowReadiness.compileOnly,
1758
+ sameFailureParked: workflowReadiness.sameFailureParked,
1759
+ canPublish: workflowReadiness.canPublish,
1760
+ canPolishWowUi: workflowReadiness.canPolishWowUi,
1761
+ workflowReadinessStatus: workflowReadiness.status,
1762
+ workflowProofCheckpointStatus: workflowProofCheckpoint.status,
1763
+ failureClass: contractBasis.failureClass,
1764
+ evidenceHash: cleanText((last === null || last === void 0 ? void 0 : last.evidenceHash) || contractBasis.evidenceHash, 160)
1765
+ },
1766
+ preconditions: preconditions,
1767
+ expectedStateTransition: aicoderNextActionExpectedTransition(command),
1768
+ successEvidence: successEvidence,
1769
+ stopConditions: stopConditions,
1770
+ forbiddenActions: forbiddenActions,
1771
+ nextCommands: nextCommands,
1772
+ blockers: blockers,
1773
+ ownerFiles: cleanList(last === null || last === void 0 ? void 0 : last.changedFiles, 20, 500),
1774
+ createdAt: isoNow(input.now)
1775
+ };
1776
+ }
1550
1777
  function buildResolveIOAICoderV6Budget(existing) {
1551
1778
  return {
1552
1779
  maxPromptTokensPerNonInitialStep: Number((existing === null || existing === void 0 ? void 0 : existing.maxPromptTokensPerNonInitialStep) || 4000),
@@ -1825,7 +2052,17 @@ function decideResolveIOAICoderV6Continuation(bundle) {
1825
2052
  budgetExceeded: decision.budgetExceeded,
1826
2053
  repeatedNoProgressCount: decision.repeatedNoProgressCount
1827
2054
  });
1828
- return __assign(__assign({}, decision), { workflowReadiness: workflowReadiness, workflowProofCheckpoint: workflowReadiness.workflowProofCheckpoint });
2055
+ var workflowProofCheckpoint = workflowReadiness.workflowProofCheckpoint;
2056
+ return __assign(__assign({}, decision), { workflowReadiness: workflowReadiness, workflowProofCheckpoint: workflowProofCheckpoint, nextActionContract: buildResolveIOAICoderNextActionContract({
2057
+ bundle: bundle,
2058
+ action: decision.action,
2059
+ reason: decision.reason,
2060
+ nextLane: decision.nextLane,
2061
+ nextStep: decision.nextStep,
2062
+ budgetExceeded: decision.budgetExceeded,
2063
+ workflowReadiness: workflowReadiness,
2064
+ workflowProofCheckpoint: workflowProofCheckpoint
2065
+ }) });
1829
2066
  };
1830
2067
  var budgetExceeded = (budget.loopCount >= budget.maxLoopsPerRun && !managerDecision.loopBudgetShouldReset)
1831
2068
  || budget.totalPromptTokenEstimate >= budget.maxTotalPromptTokens