diff --git a/docs/documentation-manifest.json b/docs/documentation-manifest.json index 6752ef824..2d8cb500f 100644 --- a/docs/documentation-manifest.json +++ b/docs/documentation-manifest.json @@ -153,7 +153,7 @@ "name": "Agent Cost Telemetry Contracts", "category": "supporting", "status": "reference", - "description": "Checked-in invoice-turn, per-turn, rollup, operator labor, and blended autonomy cost telemetry contracts, fixtures, helper CLIs, and focused tests used to anchor spend reporting in repo-visible evidence.", + "description": "Checked-in invoice-turn, per-turn, rollup, treasury control-plane, operator labor, and blended autonomy cost telemetry contracts, fixtures, helper CLIs, and focused tests used to anchor spend reporting in repo-visible evidence.", "files": [ "docs/knowledgebase/Agent-Cost-Telemetry-Surfaces.md", "docs/schemas/agent-cost-private-invoice-metadata-v1.schema.json", @@ -165,6 +165,8 @@ "docs/schemas/github-comment-budget-hook-report-v1.schema.json", "docs/schemas/operator-cost-profile-v1.schema.json", "docs/schemas/pr-spend-projection-v1.schema.json", + "docs/schemas/treasury-control-plane-policy-v2.schema.json", + "docs/schemas/treasury-control-plane-report-v2.schema.json", "tools/priority/__fixtures__/agent-cost-rollup/live-turn-estimated.json", "tools/priority/__fixtures__/agent-cost-rollup/background-turn-exact.json", "tools/priority/__fixtures__/agent-cost-rollup/invoice-turn-baseline.json", @@ -173,6 +175,7 @@ "tools/priority/__fixtures__/agent-cost-rollup/private-invoice-metadata-sample.json", "tools/policy/github-comment-budget-hook.json", "tools/policy/operator-cost-profile.json", + "tools/policy/treasury-control-plane.json", "tools/priority/agent-cost-invoice-normalize.mjs", "tools/priority/agent-cost-invoice-turn.mjs", "tools/priority/agent-cost-turn.mjs", @@ -180,6 +183,7 @@ "tools/priority/average-issue-cost-scorecard.mjs", "tools/priority/github-comment-budget-hook.mjs", "tools/priority/pr-spend-projection.mjs", + "tools/priority/treasury-control-plane.mjs", "tools/priority/__tests__/github-comment-budget-hook.test.mjs", "tools/priority/__tests__/github-comment-budget-hook-schema.test.mjs", "tools/priority/__tests__/average-issue-cost-scorecard.test.mjs", @@ -192,7 +196,9 @@ "tools/priority/__tests__/operator-cost-profile-schema.test.mjs", "tools/priority/__tests__/pr-spend-projection.test.mjs", "tools/priority/__tests__/pr-spend-projection-schema.test.mjs", - "tools/priority/__tests__/agent-cost-telemetry-surfaces.test.mjs" + "tools/priority/__tests__/agent-cost-telemetry-surfaces.test.mjs", + "tools/priority/__tests__/treasury-control-plane.test.mjs", + "tools/priority/__tests__/treasury-control-plane-schema.test.mjs" ] }, { diff --git a/docs/knowledgebase/Agent-Cost-Telemetry-Surfaces.md b/docs/knowledgebase/Agent-Cost-Telemetry-Surfaces.md index 3f03b19fb..11b91bc60 100644 --- a/docs/knowledgebase/Agent-Cost-Telemetry-Surfaces.md +++ b/docs/knowledgebase/Agent-Cost-Telemetry-Surfaces.md @@ -265,6 +265,33 @@ Automation-authored GitHub comments now have a checked-in budget attestation surface so cost state survives session compaction and comment history remains a durable breadcrumb for later agents. +## Treasury Control Plane + +The budget hook is now a projection layer, not the authority. + +The authoritative spend-governance surface is the treasury control plane: + +- schema: `docs/schemas/treasury-control-plane-policy-v2.schema.json` +- schema: `docs/schemas/treasury-control-plane-report-v2.schema.json` +- policy: `tools/policy/treasury-control-plane.json` +- helper: `tools/priority/treasury-control-plane.mjs` +- npm surface: `priority:cost:treasury` + +This surface separates: + +- whole-account remaining USD estimate +- protected reserve USD +- operational headroom +- safe spendable lower bound +- possible spendable upper bound +- operator budget observed upper bound +- operator budget spendable status +- premium/background/non-essential execution controls + +The treasury control plane is what governor, portfolio, and handoff surfaces +should read when deciding whether work is allowed. The GitHub comment hook +exists to persist that decision visibly on issue and PR history. + - schema: `docs/schemas/github-comment-budget-hook-policy-v1.schema.json` - schema: `docs/schemas/github-comment-budget-hook-report-v1.schema.json` - policy: `tools/policy/github-comment-budget-hook.json` diff --git a/docs/schemas/autonomous-governor-portfolio-summary-report-v1.schema.json b/docs/schemas/autonomous-governor-portfolio-summary-report-v1.schema.json index cea473f9e..b651fc87a 100644 --- a/docs/schemas/autonomous-governor-portfolio-summary-report-v1.schema.json +++ b/docs/schemas/autonomous-governor-portfolio-summary-report-v1.schema.json @@ -52,6 +52,7 @@ "queueHandoffNextWakeCondition", "queueHandoffPrUrl", "queueAuthoritySource", + "treasury", "executionTopology", "executionBundleStatus", "executionBundlePlaneBinding", @@ -71,6 +72,7 @@ "queueHandoffNextWakeCondition": { "type": ["string", "null"] }, "queueHandoffPrUrl": { "type": ["string", "null"] }, "queueAuthoritySource": { "type": ["string", "null"] }, + "treasury": { "$ref": "#/$defs/treasury" }, "executionTopology": { "$ref": "#/$defs/executionTopology" }, "executionBundleStatus": { "type": ["string", "null"] }, "executionBundlePlaneBinding": { "type": ["string", "null"] }, @@ -280,6 +282,27 @@ "executionBundlePremiumSaganMode", "executionBundleReciprocalLinkReady", "executionBundleEffectiveBillableRateUsdPerHour", + "treasuryStatus", + "treasuryConfidence", + "treasurySpendPolicyState", + "treasuryBudgetPressureState", + "treasuryProtectedReserveUsd", + "treasuryAccountRemainingUsdEstimate", + "treasuryOperationalHeadroomUsd", + "treasurySafeSpendableUsd", + "treasuryPossibleSpendableUpperBoundUsd", + "treasuryOperatorBudgetObservedRemainingUpperBoundUsd", + "treasuryOperatorBudgetObservedRemainingStatus", + "treasuryOperatorBudgetSpendableStatus", + "treasuryCoreDeliveryAllowed", + "treasuryQueueAuthorityAllowed", + "treasuryReleaseApplyAllowed", + "treasuryPremiumSaganAllowed", + "treasuryPremiumAuthorizationPromptRequired", + "treasuryPremiumAuthorizationFollowupEstimate", + "treasuryBackgroundFanoutAllowed", + "treasuryMaxBackgroundSubagents", + "treasuryNonEssentialWorkAllowed", "viHistoryDistributorDependencyStatus", "viHistoryDistributorDependencyTargetRepository", "viHistoryDistributorDependencyExternalBlocker", @@ -327,6 +350,27 @@ "executionBundlePremiumSaganMode": { "type": "boolean" }, "executionBundleReciprocalLinkReady": { "type": "boolean" }, "executionBundleEffectiveBillableRateUsdPerHour": { "type": ["number", "null"], "minimum": 0 }, + "treasuryStatus": { "type": "string", "enum": ["pass", "warn", "blocked", "missing"] }, + "treasuryConfidence": { "type": "string", "enum": ["observed", "lower-bound-only", "conflicted", "blocked", "unknown"] }, + "treasurySpendPolicyState": { "type": "string", "enum": ["healthy", "cautious-delivery", "core-delivery-only", "reserve-protected-only", "blocked"] }, + "treasuryBudgetPressureState": { "type": "string", "enum": ["healthy", "cautious", "tight", "stop-nonessential-spend", "blocked"] }, + "treasuryProtectedReserveUsd": { "type": ["number", "null"], "minimum": 0 }, + "treasuryAccountRemainingUsdEstimate": { "type": ["number", "null"], "minimum": 0 }, + "treasuryOperationalHeadroomUsd": { "type": ["number", "null"], "minimum": 0 }, + "treasurySafeSpendableUsd": { "type": ["number", "null"], "minimum": 0 }, + "treasuryPossibleSpendableUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "treasuryOperatorBudgetObservedRemainingUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "treasuryOperatorBudgetObservedRemainingStatus": { "type": "string", "enum": ["observed", "upper-bound", "unknown"] }, + "treasuryOperatorBudgetSpendableStatus": { "type": "string", "enum": ["observed", "unreconciled", "unknown"] }, + "treasuryCoreDeliveryAllowed": { "type": "boolean" }, + "treasuryQueueAuthorityAllowed": { "type": "boolean" }, + "treasuryReleaseApplyAllowed": { "type": "boolean" }, + "treasuryPremiumSaganAllowed": { "type": "boolean" }, + "treasuryPremiumAuthorizationPromptRequired": { "type": "boolean" }, + "treasuryPremiumAuthorizationFollowupEstimate": { "type": "integer", "minimum": 0 }, + "treasuryBackgroundFanoutAllowed": { "type": "boolean" }, + "treasuryMaxBackgroundSubagents": { "type": "integer", "minimum": 0 }, + "treasuryNonEssentialWorkAllowed": { "type": "boolean" }, "viHistoryDistributorDependencyStatus": { "type": "string", "enum": ["ready", "blocked", "unknown"] }, "viHistoryDistributorDependencyTargetRepository": { "type": ["string", "null"] }, "viHistoryDistributorDependencyExternalBlocker": { "type": ["string", "null"] }, @@ -345,6 +389,56 @@ } }, "$defs": { + "treasury": { + "type": "object", + "additionalProperties": false, + "required": [ + "status", + "confidence", + "spendPolicyState", + "budgetPressureState", + "protectedReserveUsd", + "accountRemainingUsdEstimate", + "operationalHeadroomUsd", + "safeSpendableUsd", + "possibleSpendableUpperBoundUsd", + "operatorBudgetObservedRemainingUpperBoundUsd", + "operatorBudgetObservedRemainingStatus", + "operatorBudgetSpendableStatus", + "coreDeliveryAllowed", + "queueAuthorityAllowed", + "releaseApplyAllowed", + "premiumSaganAllowed", + "premiumAuthorizationPromptRequired", + "premiumAuthorizationFollowupEstimate", + "backgroundFanoutAllowed", + "maxBackgroundSubagents", + "nonEssentialWorkAllowed" + ], + "properties": { + "status": { "type": "string", "enum": ["pass", "warn", "blocked", "missing"] }, + "confidence": { "type": "string", "enum": ["observed", "lower-bound-only", "conflicted", "blocked", "unknown"] }, + "spendPolicyState": { "type": "string", "enum": ["healthy", "cautious-delivery", "core-delivery-only", "reserve-protected-only", "blocked"] }, + "budgetPressureState": { "type": "string", "enum": ["healthy", "cautious", "tight", "stop-nonessential-spend", "blocked"] }, + "protectedReserveUsd": { "type": ["number", "null"], "minimum": 0 }, + "accountRemainingUsdEstimate": { "type": ["number", "null"], "minimum": 0 }, + "operationalHeadroomUsd": { "type": ["number", "null"], "minimum": 0 }, + "safeSpendableUsd": { "type": ["number", "null"], "minimum": 0 }, + "possibleSpendableUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetObservedRemainingUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetObservedRemainingStatus": { "type": "string", "enum": ["observed", "upper-bound", "unknown"] }, + "operatorBudgetSpendableStatus": { "type": "string", "enum": ["observed", "unreconciled", "unknown"] }, + "coreDeliveryAllowed": { "type": "boolean" }, + "queueAuthorityAllowed": { "type": "boolean" }, + "releaseApplyAllowed": { "type": "boolean" }, + "premiumSaganAllowed": { "type": "boolean" }, + "premiumAuthorizationPromptRequired": { "type": "boolean" }, + "premiumAuthorizationFollowupEstimate": { "type": "integer", "minimum": 0 }, + "backgroundFanoutAllowed": { "type": "boolean" }, + "maxBackgroundSubagents": { "type": "integer", "minimum": 0 }, + "nonEssentialWorkAllowed": { "type": "boolean" } + } + }, "executionBundle": { "type": "object", "additionalProperties": false, diff --git a/docs/schemas/autonomous-governor-summary-report-v1.schema.json b/docs/schemas/autonomous-governor-summary-report-v1.schema.json index f5f0180f5..1c6be1202 100644 --- a/docs/schemas/autonomous-governor-summary-report-v1.schema.json +++ b/docs/schemas/autonomous-governor-summary-report-v1.schema.json @@ -38,7 +38,8 @@ "wakeLifecyclePath", "wakeInvestmentAccountingPath", "deliveryRuntimeStatePath", - "releaseSigningReadinessPath" + "releaseSigningReadinessPath", + "treasuryControlPlanePath" ], "properties": { "queueEmptyReportPath": { "type": "string", "minLength": 1 }, @@ -47,7 +48,8 @@ "wakeLifecyclePath": { "type": "string", "minLength": 1 }, "wakeInvestmentAccountingPath": { "type": "string", "minLength": 1 }, "deliveryRuntimeStatePath": { "type": "string", "minLength": 1 }, - "releaseSigningReadinessPath": { "type": "string", "minLength": 1 } + "releaseSigningReadinessPath": { "type": "string", "minLength": 1 }, + "treasuryControlPlanePath": { "type": "string", "minLength": 1 } } }, "compare": { @@ -57,6 +59,7 @@ "queueState", "continuity", "monitoringMode", + "treasury", "releaseSigningReadiness", "deliveryRuntime", "queueAuthority" @@ -65,6 +68,7 @@ "queueState": { "$ref": "#/$defs/queueState" }, "continuity": { "$ref": "#/$defs/continuity" }, "monitoringMode": { "$ref": "#/$defs/monitoringMode" }, + "treasury": { "$ref": "#/$defs/treasury" }, "releaseSigningReadiness": { "$ref": "#/$defs/releaseSigningReadiness" }, "deliveryRuntime": { "$ref": "#/$defs/deliveryRuntime" }, "queueAuthority": { "$ref": "#/$defs/queueAuthority" } @@ -313,6 +317,56 @@ "netPaybackUsd": { "type": ["number", "null"] } } }, + "treasury": { + "type": "object", + "additionalProperties": false, + "required": [ + "status", + "confidence", + "spendPolicyState", + "budgetPressureState", + "protectedReserveUsd", + "accountRemainingUsdEstimate", + "operationalHeadroomUsd", + "safeSpendableUsd", + "possibleSpendableUpperBoundUsd", + "operatorBudgetObservedRemainingUpperBoundUsd", + "operatorBudgetObservedRemainingStatus", + "operatorBudgetSpendableStatus", + "coreDeliveryAllowed", + "queueAuthorityAllowed", + "releaseApplyAllowed", + "premiumSaganAllowed", + "premiumAuthorizationPromptRequired", + "premiumAuthorizationFollowupEstimate", + "backgroundFanoutAllowed", + "maxBackgroundSubagents", + "nonEssentialWorkAllowed" + ], + "properties": { + "status": { "type": "string", "enum": ["pass", "warn", "blocked", "missing"] }, + "confidence": { "type": "string", "enum": ["observed", "lower-bound-only", "conflicted", "blocked", "unknown"] }, + "spendPolicyState": { "type": "string", "enum": ["healthy", "cautious-delivery", "core-delivery-only", "reserve-protected-only", "blocked"] }, + "budgetPressureState": { "type": "string", "enum": ["healthy", "cautious", "tight", "stop-nonessential-spend", "blocked"] }, + "protectedReserveUsd": { "type": ["number", "null"], "minimum": 0 }, + "accountRemainingUsdEstimate": { "type": ["number", "null"], "minimum": 0 }, + "operationalHeadroomUsd": { "type": ["number", "null"], "minimum": 0 }, + "safeSpendableUsd": { "type": ["number", "null"], "minimum": 0 }, + "possibleSpendableUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetObservedRemainingUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetObservedRemainingStatus": { "type": "string", "enum": ["observed", "upper-bound", "unknown"] }, + "operatorBudgetSpendableStatus": { "type": "string", "enum": ["observed", "unreconciled", "unknown"] }, + "coreDeliveryAllowed": { "type": "boolean" }, + "queueAuthorityAllowed": { "type": "boolean" }, + "releaseApplyAllowed": { "type": "boolean" }, + "premiumSaganAllowed": { "type": "boolean" }, + "premiumAuthorizationPromptRequired": { "type": "boolean" }, + "premiumAuthorizationFollowupEstimate": { "type": "integer", "minimum": 0 }, + "backgroundFanoutAllowed": { "type": "boolean" }, + "maxBackgroundSubagents": { "type": "integer", "minimum": 0 }, + "nonEssentialWorkAllowed": { "type": "boolean" } + } + }, "summary": { "type": "object", "additionalProperties": false, @@ -353,6 +407,27 @@ "executionBundlePremiumSaganMode", "executionBundleReciprocalLinkReady", "executionBundleEffectiveBillableRateUsdPerHour", + "treasuryStatus", + "treasuryConfidence", + "treasurySpendPolicyState", + "treasuryBudgetPressureState", + "treasuryProtectedReserveUsd", + "treasuryAccountRemainingUsdEstimate", + "treasuryOperationalHeadroomUsd", + "treasurySafeSpendableUsd", + "treasuryPossibleSpendableUpperBoundUsd", + "treasuryOperatorBudgetObservedRemainingUpperBoundUsd", + "treasuryOperatorBudgetObservedRemainingStatus", + "treasuryOperatorBudgetSpendableStatus", + "treasuryCoreDeliveryAllowed", + "treasuryQueueAuthorityAllowed", + "treasuryReleaseApplyAllowed", + "treasuryPremiumSaganAllowed", + "treasuryPremiumAuthorizationPromptRequired", + "treasuryPremiumAuthorizationFollowupEstimate", + "treasuryBackgroundFanoutAllowed", + "treasuryMaxBackgroundSubagents", + "treasuryNonEssentialWorkAllowed", "queueHandoffStatus", "queueHandoffNextWakeCondition", "queueHandoffPrUrl", @@ -426,6 +501,27 @@ "executionBundlePremiumSaganMode": { "type": "boolean" }, "executionBundleReciprocalLinkReady": { "type": "boolean" }, "executionBundleEffectiveBillableRateUsdPerHour": { "type": ["number", "null"], "minimum": 0 }, + "treasuryStatus": { "type": "string", "enum": ["pass", "warn", "blocked", "missing"] }, + "treasuryConfidence": { "type": "string", "enum": ["observed", "lower-bound-only", "conflicted", "blocked", "unknown"] }, + "treasurySpendPolicyState": { "type": "string", "enum": ["healthy", "cautious-delivery", "core-delivery-only", "reserve-protected-only", "blocked"] }, + "treasuryBudgetPressureState": { "type": "string", "enum": ["healthy", "cautious", "tight", "stop-nonessential-spend", "blocked"] }, + "treasuryProtectedReserveUsd": { "type": ["number", "null"], "minimum": 0 }, + "treasuryAccountRemainingUsdEstimate": { "type": ["number", "null"], "minimum": 0 }, + "treasuryOperationalHeadroomUsd": { "type": ["number", "null"], "minimum": 0 }, + "treasurySafeSpendableUsd": { "type": ["number", "null"], "minimum": 0 }, + "treasuryPossibleSpendableUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "treasuryOperatorBudgetObservedRemainingUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "treasuryOperatorBudgetObservedRemainingStatus": { "type": "string", "enum": ["observed", "upper-bound", "unknown"] }, + "treasuryOperatorBudgetSpendableStatus": { "type": "string", "enum": ["observed", "unreconciled", "unknown"] }, + "treasuryCoreDeliveryAllowed": { "type": "boolean" }, + "treasuryQueueAuthorityAllowed": { "type": "boolean" }, + "treasuryReleaseApplyAllowed": { "type": "boolean" }, + "treasuryPremiumSaganAllowed": { "type": "boolean" }, + "treasuryPremiumAuthorizationPromptRequired": { "type": "boolean" }, + "treasuryPremiumAuthorizationFollowupEstimate": { "type": "integer", "minimum": 0 }, + "treasuryBackgroundFanoutAllowed": { "type": "boolean" }, + "treasuryMaxBackgroundSubagents": { "type": "integer", "minimum": 0 }, + "treasuryNonEssentialWorkAllowed": { "type": "boolean" }, "queueHandoffStatus": { "type": "string", "enum": [ diff --git a/docs/schemas/execution-cell-bundle-report-v1.schema.json b/docs/schemas/execution-cell-bundle-report-v1.schema.json index 3e9543b1e..65cb155c0 100644 --- a/docs/schemas/execution-cell-bundle-report-v1.schema.json +++ b/docs/schemas/execution-cell-bundle-report-v1.schema.json @@ -154,8 +154,14 @@ "windowsNativeTestStand", "effectiveBillableRateMultiplier", "effectiveBillableRateUsdPerHour", + "premiumSaganRequested", "premiumSaganMode", + "operatorAuthorizationRequired", + "operatorAuthorizationPromptRequired", + "estimatedFollowupAuthorizationsNeeded", "operatorAuthorizationRef", + "treasuryDecisionCode", + "treasuryControlPlanePath", "isolatedLaneGroupId", "fingerprintSha256", "capabilities", @@ -267,15 +273,40 @@ ], "minimum": 0 }, + "premiumSaganRequested": { + "type": "boolean" + }, "premiumSaganMode": { "type": "boolean" }, + "operatorAuthorizationRequired": { + "type": "boolean" + }, + "operatorAuthorizationPromptRequired": { + "type": "boolean" + }, + "estimatedFollowupAuthorizationsNeeded": { + "type": "integer", + "minimum": 0 + }, "operatorAuthorizationRef": { "type": [ "string", "null" ] }, + "treasuryDecisionCode": { + "type": [ + "string", + "null" + ] + }, + "treasuryControlPlanePath": { + "type": [ + "string", + "null" + ] + }, "isolatedLaneGroupId": { "type": [ "string", diff --git a/docs/schemas/github-comment-budget-hook-policy-v1.schema.json b/docs/schemas/github-comment-budget-hook-policy-v1.schema.json index 5eb2d3dc4..1e30d6cc0 100644 --- a/docs/schemas/github-comment-budget-hook-policy-v1.schema.json +++ b/docs/schemas/github-comment-budget-hook-policy-v1.schema.json @@ -6,6 +6,7 @@ "additionalProperties": false, "required": [ "schema", + "treasuryPolicyPath", "costRollupPath", "materializationPolicyPath", "materializationReportPath", @@ -18,6 +19,7 @@ ], "properties": { "schema": { "const": "priority/github-comment-budget-hook-policy@v1" }, + "treasuryPolicyPath": { "type": "string", "minLength": 1 }, "costRollupPath": { "type": "string", "minLength": 1 }, "materializationPolicyPath": { "type": "string", "minLength": 1 }, "materializationReportPath": { "type": "string", "minLength": 1 }, diff --git a/docs/schemas/github-comment-budget-hook-report-v1.schema.json b/docs/schemas/github-comment-budget-hook-report-v1.schema.json index 6674a11e8..c01bf99d7 100644 --- a/docs/schemas/github-comment-budget-hook-report-v1.schema.json +++ b/docs/schemas/github-comment-budget-hook-report-v1.schema.json @@ -40,6 +40,8 @@ "observedBlendedLowerBoundUsd", "knownBlendedUsd", "operatorBudgetCapUsd", + "operatorBudgetObservedRemainingUpperBoundUsd", + "operatorBudgetObservedRemainingStatus", "operatorBudgetRemainingLowerBoundUsd", "operatorBudgetRemainingStatus", "operatorBudgetSpendableUsd", @@ -47,6 +49,19 @@ "accountRemainingUsdEstimate", "operationalHeadroomUsd", "operationalHeadroomStatus", + "safeSpendableUsd", + "possibleSpendableUpperBoundUsd", + "treasuryConfidence", + "treasurySpendPolicyState", + "coreDeliveryAllowed", + "queueAuthorityAllowed", + "releaseApplyAllowed", + "premiumSaganAllowed", + "premiumAuthorizationPromptRequired", + "premiumAuthorizationFollowupEstimate", + "backgroundFanoutAllowed", + "maxBackgroundSubagents", + "nonEssentialWorkAllowed", "budgetPressureState" ], "properties": { @@ -58,13 +73,28 @@ "observedBlendedLowerBoundUsd": { "type": "number", "minimum": 0 }, "knownBlendedUsd": { "type": ["number", "null"], "minimum": 0 }, "operatorBudgetCapUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetObservedRemainingUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetObservedRemainingStatus": { "type": "string", "enum": ["observed", "upper-bound", "unknown"] }, "operatorBudgetRemainingLowerBoundUsd": { "type": ["number", "null"], "minimum": 0 }, - "operatorBudgetRemainingStatus": { "type": "string", "enum": ["observed", "lower-bound", "unknown"] }, + "operatorBudgetRemainingStatus": { "type": "string", "enum": ["observed", "unknown"] }, "operatorBudgetSpendableUsd": { "type": ["number", "null"], "minimum": 0 }, "operatorBudgetSpendableStatus": { "type": "string", "enum": ["observed", "unreconciled", "unknown"] }, "accountRemainingUsdEstimate": { "type": ["number", "null"], "minimum": 0 }, "operationalHeadroomUsd": { "type": ["number", "null"], "minimum": 0 }, "operationalHeadroomStatus": { "type": "string", "enum": ["healthy", "reserve-near", "reserve-protected-only", "unknown"] }, + "safeSpendableUsd": { "type": ["number", "null"], "minimum": 0 }, + "possibleSpendableUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "treasuryConfidence": { "type": "string", "enum": ["observed", "lower-bound-only", "conflicted", "blocked", "unknown"] }, + "treasurySpendPolicyState": { "type": "string", "enum": ["healthy", "cautious-delivery", "core-delivery-only", "reserve-protected-only", "blocked"] }, + "coreDeliveryAllowed": { "type": "boolean" }, + "queueAuthorityAllowed": { "type": "boolean" }, + "releaseApplyAllowed": { "type": "boolean" }, + "premiumSaganAllowed": { "type": "boolean" }, + "premiumAuthorizationPromptRequired": { "type": "boolean" }, + "premiumAuthorizationFollowupEstimate": { "type": "integer", "minimum": 0 }, + "backgroundFanoutAllowed": { "type": "boolean" }, + "maxBackgroundSubagents": { "type": "integer", "minimum": 0 }, + "nonEssentialWorkAllowed": { "type": "boolean" }, "budgetPressureState": { "type": "string", "enum": ["healthy", "cautious", "tight", "stop-nonessential-spend", "blocked"] } } }, @@ -145,13 +175,11 @@ "source": { "type": "object", "additionalProperties": false, - "required": ["policyPath", "costRollupPath", "costRollupMaterialized", "costRollupMaterializationReportPath", "operatorCostProfilePath", "outputPath", "markdownOutputPath"], + "required": ["policyPath", "treasuryPolicyPath", "treasuryControlPlanePath", "outputPath", "markdownOutputPath"], "properties": { "policyPath": { "type": ["string", "null"] }, - "costRollupPath": { "type": ["string", "null"] }, - "costRollupMaterialized": { "type": "boolean" }, - "costRollupMaterializationReportPath": { "type": ["string", "null"] }, - "operatorCostProfilePath": { "type": ["string", "null"] }, + "treasuryPolicyPath": { "type": ["string", "null"] }, + "treasuryControlPlanePath": { "type": ["string", "null"] }, "outputPath": { "type": ["string", "null"] }, "markdownOutputPath": { "type": ["string", "null"] } } diff --git a/docs/schemas/treasury-control-plane-policy-v1.schema.json b/docs/schemas/treasury-control-plane-policy-v1.schema.json new file mode 100644 index 000000000..1f9a5e07b --- /dev/null +++ b/docs/schemas/treasury-control-plane-policy-v1.schema.json @@ -0,0 +1,69 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://labview-community-ci-cd.github.io/compare-vi-cli-action/schemas/treasury-control-plane-policy-v1.schema.json", + "title": "Treasury Control Plane Policy v1", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "costRollupPath", + "materializationPolicyPath", + "materializationReportPath", + "outputPath", + "operatorBudgetCapUsd", + "materializeCostRollup", + "reservedFundingPurposes", + "reservedActivationStates", + "thresholds", + "limits" + ], + "properties": { + "schema": { "const": "priority/treasury-control-plane-policy@v1" }, + "costRollupPath": { "type": "string", "minLength": 1 }, + "materializationPolicyPath": { "type": "string", "minLength": 1 }, + "materializationReportPath": { "type": "string", "minLength": 1 }, + "outputPath": { "type": "string", "minLength": 1 }, + "operatorBudgetCapUsd": { "type": "number", "minimum": 0 }, + "materializeCostRollup": { "type": "boolean" }, + "reservedFundingPurposes": { + "type": "array", + "minItems": 1, + "items": { "type": "string", "minLength": 1 } + }, + "reservedActivationStates": { + "type": "array", + "minItems": 1, + "items": { "type": "string", "minLength": 1 } + }, + "thresholds": { + "type": "object", + "additionalProperties": false, + "required": [ + "reserveNearOperationalHeadroomUsd", + "healthyOperationalHeadroomUsd", + "premiumSaganMinimumOperationalHeadroomUsd", + "backgroundFanoutMinimumOperationalHeadroomUsd", + "nonEssentialWorkMinimumOperationalHeadroomUsd" + ], + "properties": { + "reserveNearOperationalHeadroomUsd": { "type": "number", "minimum": 0 }, + "healthyOperationalHeadroomUsd": { "type": "number", "minimum": 0 }, + "premiumSaganMinimumOperationalHeadroomUsd": { "type": "number", "minimum": 0 }, + "backgroundFanoutMinimumOperationalHeadroomUsd": { "type": "number", "minimum": 0 }, + "nonEssentialWorkMinimumOperationalHeadroomUsd": { "type": "number", "minimum": 0 } + } + }, + "limits": { + "type": "object", + "additionalProperties": false, + "required": [ + "healthyBackgroundSubagentsMax", + "cautiousBackgroundSubagentsMax" + ], + "properties": { + "healthyBackgroundSubagentsMax": { "type": "integer", "minimum": 0 }, + "cautiousBackgroundSubagentsMax": { "type": "integer", "minimum": 0 } + } + } + } +} diff --git a/docs/schemas/treasury-control-plane-policy-v2.schema.json b/docs/schemas/treasury-control-plane-policy-v2.schema.json new file mode 100644 index 000000000..c272e0f82 --- /dev/null +++ b/docs/schemas/treasury-control-plane-policy-v2.schema.json @@ -0,0 +1,73 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://labview-community-ci-cd.github.io/compare-vi-cli-action/schemas/treasury-control-plane-policy-v2.schema.json", + "title": "Treasury Control Plane Policy v2", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "costRollupPath", + "materializationPolicyPath", + "materializationReportPath", + "outputPath", + "operatorBudgetCapUsd", + "materializeCostRollup", + "reservedFundingPurposes", + "reservedActivationStates", + "thresholds", + "limits" + ], + "properties": { + "schema": { "const": "priority/treasury-control-plane-policy@v2" }, + "costRollupPath": { "type": "string", "minLength": 1 }, + "materializationPolicyPath": { "type": "string", "minLength": 1 }, + "materializationReportPath": { "type": "string", "minLength": 1 }, + "outputPath": { "type": "string", "minLength": 1 }, + "operatorBudgetCapUsd": { "type": "number", "minimum": 0 }, + "materializeCostRollup": { "type": "boolean" }, + "reservedFundingPurposes": { + "type": "array", + "minItems": 1, + "items": { "type": "string", "minLength": 1 } + }, + "reservedActivationStates": { + "type": "array", + "minItems": 1, + "items": { "type": "string", "minLength": 1 } + }, + "thresholds": { + "type": "object", + "additionalProperties": false, + "required": [ + "accountBalanceMaxAgeHours", + "reserveNearOperationalHeadroomUsd", + "healthyOperationalHeadroomUsd", + "premiumSaganMinimumOperationalHeadroomUsd", + "backgroundFanoutMinimumOperationalHeadroomUsd", + "nonEssentialWorkMinimumOperationalHeadroomUsd" + ], + "properties": { + "accountBalanceMaxAgeHours": { "type": "integer", "minimum": 1 }, + "reserveNearOperationalHeadroomUsd": { "type": "number", "minimum": 0 }, + "healthyOperationalHeadroomUsd": { "type": "number", "minimum": 0 }, + "premiumSaganMinimumOperationalHeadroomUsd": { "type": "number", "minimum": 0 }, + "backgroundFanoutMinimumOperationalHeadroomUsd": { "type": "number", "minimum": 0 }, + "nonEssentialWorkMinimumOperationalHeadroomUsd": { "type": "number", "minimum": 0 } + } + }, + "limits": { + "type": "object", + "additionalProperties": false, + "required": [ + "healthyBackgroundSubagentsMax", + "cautiousBackgroundSubagentsMax", + "premiumSaganFollowupAuthorizationsEstimate" + ], + "properties": { + "healthyBackgroundSubagentsMax": { "type": "integer", "minimum": 0 }, + "cautiousBackgroundSubagentsMax": { "type": "integer", "minimum": 0 }, + "premiumSaganFollowupAuthorizationsEstimate": { "type": "integer", "minimum": 0 } + } + } + } +} diff --git a/docs/schemas/treasury-control-plane-report-v1.schema.json b/docs/schemas/treasury-control-plane-report-v1.schema.json new file mode 100644 index 000000000..20d4fe030 --- /dev/null +++ b/docs/schemas/treasury-control-plane-report-v1.schema.json @@ -0,0 +1,280 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://labview-community-ci-cd.github.io/compare-vi-cli-action/schemas/treasury-control-plane-report-v1.schema.json", + "title": "Treasury Control Plane Report v1", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "generatedAt", + "repository", + "summary", + "turns", + "funding", + "controls", + "source", + "blockers" + ], + "properties": { + "schema": { "const": "priority/treasury-control-plane@v1" }, + "generatedAt": { "type": "string", "format": "date-time" }, + "repository": { "type": ["string", "null"] }, + "summary": { + "type": "object", + "additionalProperties": false, + "required": [ + "status", + "recommendation", + "confidence", + "spendPolicyState", + "budgetPressureState", + "tokenSpendUsd", + "operatorLaborObservedUsd", + "operatorLaborMissingTurnCount", + "observedBlendedLowerBoundUsd", + "knownBlendedUsd", + "protectedReserveUsd", + "accountRemainingUsdEstimate", + "operationalHeadroomUsd", + "operationalHeadroomStatus", + "safeSpendableUsd", + "possibleSpendableUpperBoundUsd", + "sourceConflictCount", + "operatorBudgetCapUsd", + "operatorBudgetObservedRemainingUpperBoundUsd", + "operatorBudgetObservedRemainingStatus", + "operatorBudgetRemainingLowerBoundUsd", + "operatorBudgetRemainingStatus", + "operatorBudgetSpendableUsd", + "operatorBudgetSpendableStatus", + "premiumSaganAllowed", + "backgroundFanoutAllowed", + "maxBackgroundSubagents", + "nonEssentialWorkAllowed", + "calibrationReserveProtected" + ], + "properties": { + "status": { "type": "string", "enum": ["pass", "warn", "blocked"] }, + "recommendation": { "type": "string", "minLength": 1 }, + "confidence": { "type": "string", "enum": ["observed", "lower-bound-only", "conflicted", "blocked"] }, + "spendPolicyState": { + "type": "string", + "enum": ["healthy", "cautious-delivery", "core-delivery-only", "reserve-protected-only", "blocked"] + }, + "budgetPressureState": { + "type": "string", + "enum": ["healthy", "cautious", "tight", "stop-nonessential-spend", "blocked"] + }, + "tokenSpendUsd": { "type": "number", "minimum": 0 }, + "operatorLaborObservedUsd": { "type": "number", "minimum": 0 }, + "operatorLaborMissingTurnCount": { "type": "integer", "minimum": 0 }, + "observedBlendedLowerBoundUsd": { "type": "number", "minimum": 0 }, + "knownBlendedUsd": { "type": ["number", "null"], "minimum": 0 }, + "protectedReserveUsd": { "type": "number", "minimum": 0 }, + "accountRemainingUsdEstimate": { "type": ["number", "null"], "minimum": 0 }, + "operationalHeadroomUsd": { "type": ["number", "null"], "minimum": 0 }, + "operationalHeadroomStatus": { + "type": "string", + "enum": ["healthy", "reserve-near", "reserve-protected-only", "unknown"] + }, + "safeSpendableUsd": { "type": ["number", "null"], "minimum": 0 }, + "possibleSpendableUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "sourceConflictCount": { "type": "integer", "minimum": 0 }, + "operatorBudgetCapUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetObservedRemainingUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetObservedRemainingStatus": { + "type": "string", + "enum": ["observed", "upper-bound", "unknown"] + }, + "operatorBudgetRemainingLowerBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetRemainingStatus": { + "type": "string", + "enum": ["observed", "unknown"] + }, + "operatorBudgetSpendableUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetSpendableStatus": { + "type": "string", + "enum": ["observed", "unreconciled", "unknown"] + }, + "premiumSaganAllowed": { "type": "boolean" }, + "backgroundFanoutAllowed": { "type": "boolean" }, + "maxBackgroundSubagents": { "type": "integer", "minimum": 0 }, + "nonEssentialWorkAllowed": { "type": "boolean" }, + "calibrationReserveProtected": { "type": "boolean" } + } + }, + "turns": { + "type": "object", + "additionalProperties": false, + "required": ["totalTurns", "liveTurnCount", "backgroundTurnCount"], + "properties": { + "totalTurns": { "type": "integer", "minimum": 0 }, + "liveTurnCount": { "type": "integer", "minimum": 0 }, + "backgroundTurnCount": { "type": "integer", "minimum": 0 } + } + }, + "funding": { + "type": "object", + "additionalProperties": false, + "required": ["billingWindow", "accountBalance", "reservedFunding"], + "properties": { + "billingWindow": { + "type": ["object", "null"], + "additionalProperties": false, + "required": [ + "invoiceTurnId", + "invoiceId", + "fundingPurpose", + "activationState", + "prepaidUsd", + "tokenSpendUsd", + "remainingUsd", + "pricingBasis", + "selectionMode", + "selectionReason" + ], + "properties": { + "invoiceTurnId": { "type": ["string", "null"] }, + "invoiceId": { "type": ["string", "null"] }, + "fundingPurpose": { "type": ["string", "null"] }, + "activationState": { "type": ["string", "null"] }, + "prepaidUsd": { "type": ["number", "null"], "minimum": 0 }, + "tokenSpendUsd": { "type": ["number", "null"], "minimum": 0 }, + "remainingUsd": { "type": ["number", "null"], "minimum": 0 }, + "pricingBasis": { "type": ["string", "null"] }, + "selectionMode": { "type": ["string", "null"] }, + "selectionReason": { "type": ["string", "null"] } + } + }, + "accountBalance": { + "type": ["object", "null"], + "additionalProperties": false, + "required": [ + "totalCredits", + "usedCredits", + "remainingCredits", + "unitPriceUsd", + "remainingUsdEstimate", + "sourceKind", + "sourcePathEvidence", + "operatorNote" + ], + "properties": { + "totalCredits": { "type": ["number", "null"], "minimum": 0 }, + "usedCredits": { "type": ["number", "null"], "minimum": 0 }, + "remainingCredits": { "type": ["number", "null"], "minimum": 0 }, + "unitPriceUsd": { "type": ["number", "null"], "minimum": 0 }, + "remainingUsdEstimate": { "type": ["number", "null"], "minimum": 0 }, + "sourceKind": { "type": ["string", "null"] }, + "sourcePathEvidence": { "type": ["string", "null"] }, + "operatorNote": { "type": ["string", "null"] } + } + }, + "reservedFunding": { + "type": "object", + "additionalProperties": false, + "required": ["count", "totalReservedUsd", "windows"], + "properties": { + "count": { "type": "integer", "minimum": 0 }, + "totalReservedUsd": { "type": "number", "minimum": 0 }, + "windows": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "invoiceTurnId", + "invoiceId", + "fundingPurpose", + "activationState", + "prepaidUsd", + "operatorNote" + ], + "properties": { + "invoiceTurnId": { "type": ["string", "null"] }, + "invoiceId": { "type": ["string", "null"] }, + "fundingPurpose": { "type": ["string", "null"] }, + "activationState": { "type": ["string", "null"] }, + "prepaidUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorNote": { "type": ["string", "null"] } + } + } + } + } + } + } + }, + "controls": { + "type": "object", + "additionalProperties": false, + "required": ["premiumSaganMode", "backgroundFanout", "nonEssentialWork"], + "properties": { + "premiumSaganMode": { + "type": "object", + "additionalProperties": false, + "required": ["allowed", "requiresOperatorAuthorization", "minimumOperationalHeadroomUsd", "reason"], + "properties": { + "allowed": { "type": "boolean" }, + "requiresOperatorAuthorization": { "type": "boolean" }, + "minimumOperationalHeadroomUsd": { "type": ["number", "null"], "minimum": 0 }, + "reason": { "type": ["string", "null"] } + } + }, + "backgroundFanout": { + "type": "object", + "additionalProperties": false, + "required": ["allowed", "minimumOperationalHeadroomUsd", "maximumConcurrentSubagents", "reason"], + "properties": { + "allowed": { "type": "boolean" }, + "minimumOperationalHeadroomUsd": { "type": ["number", "null"], "minimum": 0 }, + "maximumConcurrentSubagents": { "type": "integer", "minimum": 0 }, + "reason": { "type": ["string", "null"] } + } + }, + "nonEssentialWork": { + "type": "object", + "additionalProperties": false, + "required": ["allowed", "minimumOperationalHeadroomUsd", "reason"], + "properties": { + "allowed": { "type": "boolean" }, + "minimumOperationalHeadroomUsd": { "type": ["number", "null"], "minimum": 0 }, + "reason": { "type": ["string", "null"] } + } + } + } + }, + "source": { + "type": "object", + "additionalProperties": false, + "required": [ + "policyPath", + "costRollupPath", + "costRollupMaterialized", + "costRollupMaterializationReportPath", + "operatorCostProfilePath", + "outputPath" + ], + "properties": { + "policyPath": { "type": ["string", "null"] }, + "costRollupPath": { "type": ["string", "null"] }, + "costRollupMaterialized": { "type": "boolean" }, + "costRollupMaterializationReportPath": { "type": ["string", "null"] }, + "operatorCostProfilePath": { "type": ["string", "null"] }, + "outputPath": { "type": ["string", "null"] } + } + }, + "blockers": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["code", "message", "details"], + "properties": { + "code": { "type": "string", "minLength": 1 }, + "message": { "type": "string", "minLength": 1 }, + "details": { "type": ["string", "null"] } + } + } + } + } +} diff --git a/docs/schemas/treasury-control-plane-report-v2.schema.json b/docs/schemas/treasury-control-plane-report-v2.schema.json new file mode 100644 index 000000000..55b42d69a --- /dev/null +++ b/docs/schemas/treasury-control-plane-report-v2.schema.json @@ -0,0 +1,376 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://labview-community-ci-cd.github.io/compare-vi-cli-action/schemas/treasury-control-plane-report-v2.schema.json", + "title": "Treasury Control Plane Report v2", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "generatedAt", + "repository", + "summary", + "turns", + "funding", + "controls", + "source", + "blockers" + ], + "properties": { + "schema": { "const": "priority/treasury-control-plane@v2" }, + "generatedAt": { "type": "string", "format": "date-time" }, + "repository": { "type": ["string", "null"] }, + "summary": { + "type": "object", + "additionalProperties": false, + "required": [ + "status", + "recommendation", + "confidence", + "spendPolicyState", + "budgetPressureState", + "tokenSpendUsd", + "operatorLaborObservedUsd", + "operatorLaborMissingTurnCount", + "observedBlendedLowerBoundUsd", + "knownBlendedUsd", + "protectedReserveUsd", + "accountRemainingUsdEstimate", + "operationalHeadroomUsd", + "operationalHeadroomStatus", + "safeSpendableUsd", + "possibleSpendableUpperBoundUsd", + "sourceConflictCount", + "operatorBudgetCapUsd", + "operatorBudgetObservedRemainingUpperBoundUsd", + "operatorBudgetObservedRemainingStatus", + "operatorBudgetRemainingLowerBoundUsd", + "operatorBudgetRemainingStatus", + "operatorBudgetSpendableUsd", + "operatorBudgetSpendableStatus", + "coreDeliveryAllowed", + "queueAuthorityAllowed", + "releaseApplyAllowed", + "premiumSaganAllowed", + "premiumAuthorizationPromptRequired", + "premiumAuthorizationFollowupEstimate", + "backgroundFanoutAllowed", + "maxBackgroundSubagents", + "nonEssentialWorkAllowed", + "calibrationReserveProtected" + ], + "properties": { + "status": { "type": "string", "enum": ["pass", "warn", "blocked"] }, + "recommendation": { "type": "string", "minLength": 1 }, + "confidence": { "type": "string", "enum": ["observed", "lower-bound-only", "conflicted", "blocked"] }, + "spendPolicyState": { + "type": "string", + "enum": ["healthy", "cautious-delivery", "core-delivery-only", "reserve-protected-only", "blocked"] + }, + "budgetPressureState": { + "type": "string", + "enum": ["healthy", "cautious", "tight", "stop-nonessential-spend", "blocked"] + }, + "tokenSpendUsd": { "type": "number", "minimum": 0 }, + "operatorLaborObservedUsd": { "type": "number", "minimum": 0 }, + "operatorLaborMissingTurnCount": { "type": "integer", "minimum": 0 }, + "observedBlendedLowerBoundUsd": { "type": "number", "minimum": 0 }, + "knownBlendedUsd": { "type": ["number", "null"], "minimum": 0 }, + "protectedReserveUsd": { "type": "number", "minimum": 0 }, + "accountRemainingUsdEstimate": { "type": ["number", "null"], "minimum": 0 }, + "operationalHeadroomUsd": { "type": ["number", "null"], "minimum": 0 }, + "operationalHeadroomStatus": { + "type": "string", + "enum": ["healthy", "reserve-near", "reserve-protected-only", "unknown"] + }, + "safeSpendableUsd": { "type": ["number", "null"], "minimum": 0 }, + "possibleSpendableUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "sourceConflictCount": { "type": "integer", "minimum": 0 }, + "operatorBudgetCapUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetObservedRemainingUpperBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetObservedRemainingStatus": { + "type": "string", + "enum": ["observed", "upper-bound", "unknown"] + }, + "operatorBudgetRemainingLowerBoundUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetRemainingStatus": { + "type": "string", + "enum": ["observed", "unknown"] + }, + "operatorBudgetSpendableUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorBudgetSpendableStatus": { + "type": "string", + "enum": ["observed", "unreconciled", "unknown"] + }, + "coreDeliveryAllowed": { "type": "boolean" }, + "queueAuthorityAllowed": { "type": "boolean" }, + "releaseApplyAllowed": { "type": "boolean" }, + "premiumSaganAllowed": { "type": "boolean" }, + "premiumAuthorizationPromptRequired": { "type": "boolean" }, + "premiumAuthorizationFollowupEstimate": { "type": "integer", "minimum": 0 }, + "backgroundFanoutAllowed": { "type": "boolean" }, + "maxBackgroundSubagents": { "type": "integer", "minimum": 0 }, + "nonEssentialWorkAllowed": { "type": "boolean" }, + "calibrationReserveProtected": { "type": "boolean" } + } + }, + "turns": { + "type": "object", + "additionalProperties": false, + "required": ["totalTurns", "liveTurnCount", "backgroundTurnCount"], + "properties": { + "totalTurns": { "type": "integer", "minimum": 0 }, + "liveTurnCount": { "type": "integer", "minimum": 0 }, + "backgroundTurnCount": { "type": "integer", "minimum": 0 } + } + }, + "funding": { + "type": "object", + "additionalProperties": false, + "required": ["billingWindow", "accountBalance", "reservedFunding"], + "properties": { + "billingWindow": { + "type": ["object", "null"], + "additionalProperties": false, + "required": [ + "invoiceTurnId", + "invoiceId", + "fundingPurpose", + "activationState", + "prepaidUsd", + "tokenSpendUsd", + "remainingUsd", + "pricingBasis", + "selectionMode", + "selectionReason" + ], + "properties": { + "invoiceTurnId": { "type": ["string", "null"] }, + "invoiceId": { "type": ["string", "null"] }, + "fundingPurpose": { "type": ["string", "null"] }, + "activationState": { "type": ["string", "null"] }, + "prepaidUsd": { "type": ["number", "null"], "minimum": 0 }, + "tokenSpendUsd": { "type": ["number", "null"], "minimum": 0 }, + "remainingUsd": { "type": ["number", "null"], "minimum": 0 }, + "pricingBasis": { "type": ["string", "null"] }, + "selectionMode": { "type": ["string", "null"] }, + "selectionReason": { "type": ["string", "null"] } + } + }, + "accountBalance": { + "type": ["object", "null"], + "additionalProperties": false, + "required": [ + "totalCredits", + "usedCredits", + "remainingCredits", + "unitPriceUsd", + "remainingUsdEstimate", + "sourceKind", + "sourcePathEvidence", + "operatorNote" + ], + "properties": { + "totalCredits": { "type": ["number", "null"], "minimum": 0 }, + "usedCredits": { "type": ["number", "null"], "minimum": 0 }, + "remainingCredits": { "type": ["number", "null"], "minimum": 0 }, + "unitPriceUsd": { "type": ["number", "null"], "minimum": 0 }, + "remainingUsdEstimate": { "type": ["number", "null"], "minimum": 0 }, + "sourceKind": { "type": ["string", "null"] }, + "sourcePathEvidence": { "type": ["string", "null"] }, + "operatorNote": { "type": ["string", "null"] } + } + }, + "reservedFunding": { + "type": "object", + "additionalProperties": false, + "required": ["count", "totalReservedUsd", "windows"], + "properties": { + "count": { "type": "integer", "minimum": 0 }, + "totalReservedUsd": { "type": "number", "minimum": 0 }, + "windows": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "invoiceTurnId", + "invoiceId", + "fundingPurpose", + "activationState", + "prepaidUsd", + "operatorNote" + ], + "properties": { + "invoiceTurnId": { "type": ["string", "null"] }, + "invoiceId": { "type": ["string", "null"] }, + "fundingPurpose": { "type": ["string", "null"] }, + "activationState": { "type": ["string", "null"] }, + "prepaidUsd": { "type": ["number", "null"], "minimum": 0 }, + "operatorNote": { "type": ["string", "null"] } + } + } + } + } + } + } + }, + "controls": { + "type": "object", + "additionalProperties": false, + "required": ["premiumSaganMode", "backgroundFanout", "nonEssentialWork", "operations"], + "properties": { + "premiumSaganMode": { + "type": "object", + "additionalProperties": false, + "required": [ + "allowed", + "requiresOperatorAuthorization", + "requiresExplicitOperatorPrompt", + "estimatedFollowupAuthorizationsNeeded", + "minimumOperationalHeadroomUsd", + "reason" + ], + "properties": { + "allowed": { "type": "boolean" }, + "requiresOperatorAuthorization": { "type": "boolean" }, + "requiresExplicitOperatorPrompt": { "type": "boolean" }, + "estimatedFollowupAuthorizationsNeeded": { "type": "integer", "minimum": 0 }, + "minimumOperationalHeadroomUsd": { "type": ["number", "null"], "minimum": 0 }, + "reason": { "type": ["string", "null"] } + } + }, + "backgroundFanout": { + "type": "object", + "additionalProperties": false, + "required": ["allowed", "minimumOperationalHeadroomUsd", "maximumConcurrentSubagents", "reason"], + "properties": { + "allowed": { "type": "boolean" }, + "minimumOperationalHeadroomUsd": { "type": ["number", "null"], "minimum": 0 }, + "maximumConcurrentSubagents": { "type": "integer", "minimum": 0 }, + "reason": { "type": ["string", "null"] } + } + }, + "nonEssentialWork": { + "type": "object", + "additionalProperties": false, + "required": ["allowed", "minimumOperationalHeadroomUsd", "reason"], + "properties": { + "allowed": { "type": "boolean" }, + "minimumOperationalHeadroomUsd": { "type": ["number", "null"], "minimum": 0 }, + "reason": { "type": ["string", "null"] } + } + }, + "operations": { + "type": "object", + "additionalProperties": false, + "required": [ + "core-delivery", + "queue-authority", + "release-apply", + "background-fanout", + "non-essential-work", + "premium-sagan" + ], + "properties": { + "core-delivery": { + "type": "object", + "additionalProperties": false, + "required": ["allowed", "reason"], + "properties": { + "allowed": { "type": "boolean" }, + "reason": { "type": ["string", "null"] } + } + }, + "queue-authority": { + "type": "object", + "additionalProperties": false, + "required": ["allowed", "reason"], + "properties": { + "allowed": { "type": "boolean" }, + "reason": { "type": ["string", "null"] } + } + }, + "release-apply": { + "type": "object", + "additionalProperties": false, + "required": ["allowed", "reason"], + "properties": { + "allowed": { "type": "boolean" }, + "reason": { "type": ["string", "null"] } + } + }, + "background-fanout": { + "type": "object", + "additionalProperties": false, + "required": ["allowed", "reason"], + "properties": { + "allowed": { "type": "boolean" }, + "reason": { "type": ["string", "null"] } + } + }, + "non-essential-work": { + "type": "object", + "additionalProperties": false, + "required": ["allowed", "reason"], + "properties": { + "allowed": { "type": "boolean" }, + "reason": { "type": ["string", "null"] } + } + }, + "premium-sagan": { + "type": "object", + "additionalProperties": false, + "required": [ + "allowed", + "reason", + "requiresOperatorAuthorization", + "requiresExplicitOperatorPrompt", + "estimatedFollowupAuthorizationsNeeded" + ], + "properties": { + "allowed": { "type": "boolean" }, + "reason": { "type": ["string", "null"] }, + "requiresOperatorAuthorization": { "type": "boolean" }, + "requiresExplicitOperatorPrompt": { "type": "boolean" }, + "estimatedFollowupAuthorizationsNeeded": { "type": "integer", "minimum": 0 } + } + } + } + } + } + }, + "source": { + "type": "object", + "additionalProperties": false, + "required": [ + "policyPath", + "costRollupPath", + "costRollupMaterialized", + "costRollupMaterializationReportPath", + "operatorCostProfilePath", + "outputPath" + ], + "properties": { + "policyPath": { "type": ["string", "null"] }, + "costRollupPath": { "type": ["string", "null"] }, + "costRollupMaterialized": { "type": "boolean" }, + "costRollupMaterializationReportPath": { "type": ["string", "null"] }, + "operatorCostProfilePath": { "type": ["string", "null"] }, + "outputPath": { "type": ["string", "null"] } + } + }, + "blockers": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["code", "message", "details"], + "properties": { + "code": { "type": "string", "minLength": 1 }, + "message": { "type": "string", "minLength": 1 }, + "details": { "type": ["string", "null"] } + } + } + } + } +} diff --git a/package.json b/package.json index f97259164..d123fc7f3 100644 --- a/package.json +++ b/package.json @@ -147,6 +147,7 @@ "priority:cost:turn": "node tools/priority/agent-cost-turn.mjs", "priority:cost:rollup": "node tools/priority/agent-cost-rollup.mjs", "priority:cost:rollup:materialize": "node tools/priority/materialize-agent-cost-rollup.mjs", + "priority:cost:treasury": "node tools/priority/treasury-control-plane.mjs", "priority:cost:comment-hook": "node tools/priority/github-comment-budget-hook.mjs", "priority:cost:pr-spend": "node tools/priority/pr-spend-projection.mjs", "priority:model:select": "node tools/priority/live-agent-model-selection.mjs", diff --git a/tests/AgentHandoff.Local.Tests.ps1 b/tests/AgentHandoff.Local.Tests.ps1 index 1767330d3..10ed90e25 100644 --- a/tests/AgentHandoff.Local.Tests.ps1 +++ b/tests/AgentHandoff.Local.Tests.ps1 @@ -51,5 +51,17 @@ Describe 'Local Agent Handoff' -Tag 'Unit' { $content | Should -Match 'harnessInstanceId' $content | Should -Match 'execHLease\s*:' $content | Should -Match 'harnessInstanceLeaseId' + $content | Should -Match 'treas\s*:' + $content | Should -Match 'treasuryStatus' + $content | Should -Match 'treasPol\s*:' + $content | Should -Match 'treasurySpendPolicyState' + $content | Should -Match 'treasConf\s*:' + $content | Should -Match 'treasuryConfidence' + $content | Should -Match 'treasSafe\s*:' + $content | Should -Match 'treasurySafeSpendableUsd' + $content | Should -Match 'treasPrem\s*:' + $content | Should -Match 'treasuryPremiumSaganAllowed' + $content | Should -Match 'treasFan\s*:' + $content | Should -Match 'treasuryMaxBackgroundSubagents' } } diff --git a/tools/Print-AgentHandoff.ps1 b/tools/Print-AgentHandoff.ps1 index f4b3f8bbb..11a4ad412 100644 --- a/tools/Print-AgentHandoff.ps1 +++ b/tools/Print-AgentHandoff.ps1 @@ -1629,6 +1629,19 @@ try { Write-Host (" execLink : {0}" -f (Format-NullableValue $governor.summary.executionBundleReciprocalLinkReady)) Write-Host (" execRate : {0}" -f (Format-NullableValue $governor.summary.executionBundleEffectiveBillableRateUsdPerHour)) } + if ($governor.summary.PSObject.Properties['treasuryStatus'] -and $governor.summary.treasuryStatus) { + Write-Host (" treas : {0}" -f (Format-NullableValue $governor.summary.treasuryStatus)) + Write-Host (" treasPol : {0}" -f (Format-NullableValue $governor.summary.treasurySpendPolicyState)) + Write-Host (" treasConf: {0}" -f (Format-NullableValue $governor.summary.treasuryConfidence)) + Write-Host (" treasSafe: {0}" -f (Format-NullableValue $governor.summary.treasurySafeSpendableUsd)) + Write-Host (" treasCore: {0}" -f (Format-NullableValue $governor.summary.treasuryCoreDeliveryAllowed)) + Write-Host (" treasQ : {0}" -f (Format-NullableValue $governor.summary.treasuryQueueAuthorityAllowed)) + Write-Host (" treasRel : {0}" -f (Format-NullableValue $governor.summary.treasuryReleaseApplyAllowed)) + Write-Host (" treasPrem: {0}" -f (Format-NullableValue $governor.summary.treasuryPremiumSaganAllowed)) + Write-Host (" treasAuth: {0}" -f (Format-NullableValue $governor.summary.treasuryPremiumAuthorizationPromptRequired)) + Write-Host (" treasAuth+: {0}" -f (Format-NullableValue $governor.summary.treasuryPremiumAuthorizationFollowupEstimate)) + Write-Host (" treasFan : {0}" -f (Format-NullableValue $governor.summary.treasuryMaxBackgroundSubagents)) + } if ($env:GITHUB_STEP_SUMMARY) { $governorLines = @( '### Autonomous Governor', @@ -1715,6 +1728,19 @@ try { $governorLines += ('- Execution reciprocal link: {0}' -f (Format-NullableValue $governor.summary.executionBundleReciprocalLinkReady)) $governorLines += ('- Execution effective rate USD/hr: {0}' -f (Format-NullableValue $governor.summary.executionBundleEffectiveBillableRateUsdPerHour)) } + if ($governor.summary.PSObject.Properties['treasuryStatus'] -and $governor.summary.treasuryStatus) { + $governorLines += ('- Treasury status: {0}' -f (Format-NullableValue $governor.summary.treasuryStatus)) + $governorLines += ('- Treasury policy: {0}' -f (Format-NullableValue $governor.summary.treasurySpendPolicyState)) + $governorLines += ('- Treasury confidence: {0}' -f (Format-NullableValue $governor.summary.treasuryConfidence)) + $governorLines += ('- Treasury safe spendable USD: {0}' -f (Format-NullableValue $governor.summary.treasurySafeSpendableUsd)) + $governorLines += ('- Treasury core delivery allowed: {0}' -f (Format-NullableValue $governor.summary.treasuryCoreDeliveryAllowed)) + $governorLines += ('- Treasury queue authority allowed: {0}' -f (Format-NullableValue $governor.summary.treasuryQueueAuthorityAllowed)) + $governorLines += ('- Treasury release apply allowed: {0}' -f (Format-NullableValue $governor.summary.treasuryReleaseApplyAllowed)) + $governorLines += ('- Treasury premium Sagan allowed: {0}' -f (Format-NullableValue $governor.summary.treasuryPremiumSaganAllowed)) + $governorLines += ('- Treasury premium operator prompt required: {0}' -f (Format-NullableValue $governor.summary.treasuryPremiumAuthorizationPromptRequired)) + $governorLines += ('- Treasury premium follow-up authorization estimate: {0}' -f (Format-NullableValue $governor.summary.treasuryPremiumAuthorizationFollowupEstimate)) + $governorLines += ('- Treasury max background subagents: {0}' -f (Format-NullableValue $governor.summary.treasuryMaxBackgroundSubagents)) + } ($governorLines -join "`n") | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8 } } @@ -1802,6 +1828,19 @@ try { Write-Host (" execLink : {0}" -f (Format-NullableValue $portfolio.summary.executionBundleReciprocalLinkReady)) Write-Host (" execRate : {0}" -f (Format-NullableValue $portfolio.summary.executionBundleEffectiveBillableRateUsdPerHour)) } + if ($portfolio.summary.PSObject.Properties['treasuryStatus'] -and $portfolio.summary.treasuryStatus) { + Write-Host (" treas : {0}" -f (Format-NullableValue $portfolio.summary.treasuryStatus)) + Write-Host (" treasPol : {0}" -f (Format-NullableValue $portfolio.summary.treasurySpendPolicyState)) + Write-Host (" treasConf: {0}" -f (Format-NullableValue $portfolio.summary.treasuryConfidence)) + Write-Host (" treasSafe: {0}" -f (Format-NullableValue $portfolio.summary.treasurySafeSpendableUsd)) + Write-Host (" treasCore: {0}" -f (Format-NullableValue $portfolio.summary.treasuryCoreDeliveryAllowed)) + Write-Host (" treasQ : {0}" -f (Format-NullableValue $portfolio.summary.treasuryQueueAuthorityAllowed)) + Write-Host (" treasRel : {0}" -f (Format-NullableValue $portfolio.summary.treasuryReleaseApplyAllowed)) + Write-Host (" treasPrem: {0}" -f (Format-NullableValue $portfolio.summary.treasuryPremiumSaganAllowed)) + Write-Host (" treasAuth: {0}" -f (Format-NullableValue $portfolio.summary.treasuryPremiumAuthorizationPromptRequired)) + Write-Host (" treasAuth+: {0}" -f (Format-NullableValue $portfolio.summary.treasuryPremiumAuthorizationFollowupEstimate)) + Write-Host (" treasFan : {0}" -f (Format-NullableValue $portfolio.summary.treasuryMaxBackgroundSubagents)) + } if ($env:GITHUB_STEP_SUMMARY) { $portfolioLines = @( '### Governor Portfolio', @@ -1881,6 +1920,19 @@ try { $portfolioLines += ('- Execution reciprocal link: {0}' -f (Format-NullableValue $portfolio.summary.executionBundleReciprocalLinkReady)) $portfolioLines += ('- Execution effective rate USD/hr: {0}' -f (Format-NullableValue $portfolio.summary.executionBundleEffectiveBillableRateUsdPerHour)) } + if ($portfolio.summary.PSObject.Properties['treasuryStatus'] -and $portfolio.summary.treasuryStatus) { + $portfolioLines += ('- Treasury status: {0}' -f (Format-NullableValue $portfolio.summary.treasuryStatus)) + $portfolioLines += ('- Treasury policy: {0}' -f (Format-NullableValue $portfolio.summary.treasurySpendPolicyState)) + $portfolioLines += ('- Treasury confidence: {0}' -f (Format-NullableValue $portfolio.summary.treasuryConfidence)) + $portfolioLines += ('- Treasury safe spendable USD: {0}' -f (Format-NullableValue $portfolio.summary.treasurySafeSpendableUsd)) + $portfolioLines += ('- Treasury core delivery allowed: {0}' -f (Format-NullableValue $portfolio.summary.treasuryCoreDeliveryAllowed)) + $portfolioLines += ('- Treasury queue authority allowed: {0}' -f (Format-NullableValue $portfolio.summary.treasuryQueueAuthorityAllowed)) + $portfolioLines += ('- Treasury release apply allowed: {0}' -f (Format-NullableValue $portfolio.summary.treasuryReleaseApplyAllowed)) + $portfolioLines += ('- Treasury premium Sagan allowed: {0}' -f (Format-NullableValue $portfolio.summary.treasuryPremiumSaganAllowed)) + $portfolioLines += ('- Treasury premium operator prompt required: {0}' -f (Format-NullableValue $portfolio.summary.treasuryPremiumAuthorizationPromptRequired)) + $portfolioLines += ('- Treasury premium follow-up authorization estimate: {0}' -f (Format-NullableValue $portfolio.summary.treasuryPremiumAuthorizationFollowupEstimate)) + $portfolioLines += ('- Treasury max background subagents: {0}' -f (Format-NullableValue $portfolio.summary.treasuryMaxBackgroundSubagents)) + } ($portfolioLines -join "`n") | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8 } } diff --git a/tools/policy/github-comment-budget-hook.json b/tools/policy/github-comment-budget-hook.json index 8fe08f642..ae4198eb6 100644 --- a/tools/policy/github-comment-budget-hook.json +++ b/tools/policy/github-comment-budget-hook.json @@ -1,5 +1,6 @@ { "schema": "priority/github-comment-budget-hook-policy@v1", + "treasuryPolicyPath": "tools/policy/treasury-control-plane.json", "costRollupPath": "tests/results/_agent/cost/agent-cost-rollup.json", "materializationPolicyPath": "tools/policy/agent-cost-rollup-materialization.json", "materializationReportPath": "tests/results/_agent/cost/agent-cost-rollup-materialization.json", diff --git a/tools/policy/treasury-control-plane.json b/tools/policy/treasury-control-plane.json new file mode 100644 index 000000000..7a83eab27 --- /dev/null +++ b/tools/policy/treasury-control-plane.json @@ -0,0 +1,28 @@ +{ + "schema": "priority/treasury-control-plane-policy@v2", + "costRollupPath": "tests/results/_agent/cost/agent-cost-rollup.json", + "materializationPolicyPath": "tools/policy/agent-cost-rollup-materialization.json", + "materializationReportPath": "tests/results/_agent/cost/agent-cost-rollup-materialization.json", + "outputPath": "tests/results/_agent/cost/treasury-control-plane.json", + "operatorBudgetCapUsd": 50000, + "materializeCostRollup": true, + "reservedFundingPurposes": [ + "calibration" + ], + "reservedActivationStates": [ + "hold" + ], + "thresholds": { + "accountBalanceMaxAgeHours": 24, + "reserveNearOperationalHeadroomUsd": 100, + "healthyOperationalHeadroomUsd": 250, + "premiumSaganMinimumOperationalHeadroomUsd": 150, + "backgroundFanoutMinimumOperationalHeadroomUsd": 125, + "nonEssentialWorkMinimumOperationalHeadroomUsd": 100 + }, + "limits": { + "healthyBackgroundSubagentsMax": 2, + "cautiousBackgroundSubagentsMax": 1, + "premiumSaganFollowupAuthorizationsEstimate": 1 + } +} diff --git a/tools/priority/__tests__/autonomous-governor-portfolio-summary-schema.test.mjs b/tools/priority/__tests__/autonomous-governor-portfolio-summary-schema.test.mjs index 89d3ef601..25420901e 100644 --- a/tools/priority/__tests__/autonomous-governor-portfolio-summary-schema.test.mjs +++ b/tools/priority/__tests__/autonomous-governor-portfolio-summary-schema.test.mjs @@ -61,12 +61,36 @@ test('autonomous governor portfolio summary schema validates a generated report' continuitySummaryPath: 'tests/results/_agent/handoff/continuity-summary.json', monitoringModePath: 'tests/results/_agent/handoff/monitoring-mode.json', wakeLifecyclePath: 'tests/results/_agent/issue/wake-lifecycle.json', - wakeInvestmentAccountingPath: 'tests/results/_agent/capital/wake-investment-accounting.json' + wakeInvestmentAccountingPath: 'tests/results/_agent/capital/wake-investment-accounting.json', + treasuryControlPlanePath: 'tests/results/_agent/cost/treasury-control-plane.json' }, compare: { queueState: { status: 'queue-empty', reason: 'queue-empty', openIssueCount: 0, ready: true }, continuity: { status: 'maintained', turnBoundary: 'safe-idle', supervisionState: 'idle-monitoring', operatorPromptRequiredToResume: false }, monitoringMode: { status: 'active', futureAgentAction: 'future-agent-may-pivot', wakeConditionCount: 0 }, + treasury: { + status: 'warn', + confidence: 'lower-bound-only', + spendPolicyState: 'core-delivery-only', + budgetPressureState: 'tight', + protectedReserveUsd: 100, + accountRemainingUsdEstimate: 166, + operationalHeadroomUsd: 66, + safeSpendableUsd: 66, + possibleSpendableUpperBoundUsd: 66, + operatorBudgetObservedRemainingUpperBoundUsd: 49970, + operatorBudgetObservedRemainingStatus: 'upper-bound', + operatorBudgetSpendableStatus: 'unreconciled', + coreDeliveryAllowed: true, + queueAuthorityAllowed: true, + releaseApplyAllowed: true, + premiumSaganAllowed: false, + premiumAuthorizationPromptRequired: true, + premiumAuthorizationFollowupEstimate: 1, + backgroundFanoutAllowed: false, + maxBackgroundSubagents: 0, + nonEssentialWorkAllowed: false + }, releaseSigningReadiness: { status: 'missing', codePathState: null, @@ -141,7 +165,28 @@ test('autonomous governor portfolio summary schema validates a generated report' queueHandoffStatus: 'checks-pending', queueHandoffNextWakeCondition: 'checks-green', queueHandoffPrUrl: 'https://github.com/LabVIEW-Community-CI-CD/compare-vi-cli-action/pull/1864', - queueAuthoritySource: 'delivery-runtime' + queueAuthoritySource: 'delivery-runtime', + treasuryStatus: 'warn', + treasuryConfidence: 'lower-bound-only', + treasurySpendPolicyState: 'core-delivery-only', + treasuryBudgetPressureState: 'tight', + treasuryProtectedReserveUsd: 100, + treasuryAccountRemainingUsdEstimate: 166, + treasuryOperationalHeadroomUsd: 66, + treasurySafeSpendableUsd: 66, + treasuryPossibleSpendableUpperBoundUsd: 66, + treasuryOperatorBudgetObservedRemainingUpperBoundUsd: 49970, + treasuryOperatorBudgetObservedRemainingStatus: 'upper-bound', + treasuryOperatorBudgetSpendableStatus: 'unreconciled', + treasuryCoreDeliveryAllowed: true, + treasuryQueueAuthorityAllowed: true, + treasuryReleaseApplyAllowed: true, + treasuryPremiumSaganAllowed: false, + treasuryPremiumAuthorizationPromptRequired: true, + treasuryPremiumAuthorizationFollowupEstimate: 1, + treasuryBackgroundFanoutAllowed: false, + treasuryMaxBackgroundSubagents: 0, + treasuryNonEssentialWorkAllowed: false } }); @@ -247,4 +292,5 @@ test('autonomous governor portfolio summary schema validates a generated report' runSchemaValidate(repoRoot, path.join(repoRoot, 'docs', 'schemas', 'autonomous-governor-portfolio-summary-report-v1.schema.json'), outputPath); assert.equal(report.schema, 'priority/autonomous-governor-portfolio-summary-report@v1'); + assert.equal(report.summary.treasurySafeSpendableUsd, 66); }); diff --git a/tools/priority/__tests__/autonomous-governor-portfolio-summary.test.mjs b/tools/priority/__tests__/autonomous-governor-portfolio-summary.test.mjs index 3161183cb..f714b9596 100644 --- a/tools/priority/__tests__/autonomous-governor-portfolio-summary.test.mjs +++ b/tools/priority/__tests__/autonomous-governor-portfolio-summary.test.mjs @@ -28,7 +28,8 @@ function createCompareGovernorSummary(overrides = {}) { continuitySummaryPath: 'tests/results/_agent/handoff/continuity-summary.json', monitoringModePath: 'tests/results/_agent/handoff/monitoring-mode.json', wakeLifecyclePath: 'tests/results/_agent/issue/wake-lifecycle.json', - wakeInvestmentAccountingPath: 'tests/results/_agent/capital/wake-investment-accounting.json' + wakeInvestmentAccountingPath: 'tests/results/_agent/capital/wake-investment-accounting.json', + treasuryControlPlanePath: 'tests/results/_agent/cost/treasury-control-plane.json' }, compare: { queueState: { status: 'not-queue-empty', reason: 'standing-open', openIssueCount: 1, ready: false }, @@ -43,6 +44,29 @@ function createCompareGovernorSummary(overrides = {}) { futureAgentAction: 'stay-in-compare-monitoring', wakeConditionCount: 3 }, + treasury: { + status: 'warn', + confidence: 'lower-bound-only', + spendPolicyState: 'core-delivery-only', + budgetPressureState: 'tight', + protectedReserveUsd: 100, + accountRemainingUsdEstimate: 166, + operationalHeadroomUsd: 66, + safeSpendableUsd: 66, + possibleSpendableUpperBoundUsd: 66, + operatorBudgetObservedRemainingUpperBoundUsd: 49970, + operatorBudgetObservedRemainingStatus: 'upper-bound', + operatorBudgetSpendableStatus: 'unreconciled', + coreDeliveryAllowed: true, + queueAuthorityAllowed: true, + releaseApplyAllowed: true, + premiumSaganAllowed: false, + premiumAuthorizationPromptRequired: true, + premiumAuthorizationFollowupEstimate: 1, + backgroundFanoutAllowed: false, + maxBackgroundSubagents: 0, + nonEssentialWorkAllowed: false + }, releaseSigningReadiness: { status: 'warn', codePathState: 'ready', @@ -177,6 +201,27 @@ function createCompareGovernorSummary(overrides = {}) { executionBundlePremiumSaganMode: true, executionBundleReciprocalLinkReady: true, executionBundleEffectiveBillableRateUsdPerHour: 375, + treasuryStatus: 'warn', + treasuryConfidence: 'lower-bound-only', + treasurySpendPolicyState: 'core-delivery-only', + treasuryBudgetPressureState: 'tight', + treasuryProtectedReserveUsd: 100, + treasuryAccountRemainingUsdEstimate: 166, + treasuryOperationalHeadroomUsd: 66, + treasurySafeSpendableUsd: 66, + treasuryPossibleSpendableUpperBoundUsd: 66, + treasuryOperatorBudgetObservedRemainingUpperBoundUsd: 49970, + treasuryOperatorBudgetObservedRemainingStatus: 'upper-bound', + treasuryOperatorBudgetSpendableStatus: 'unreconciled', + treasuryCoreDeliveryAllowed: true, + treasuryQueueAuthorityAllowed: true, + treasuryReleaseApplyAllowed: true, + treasuryPremiumSaganAllowed: false, + treasuryPremiumAuthorizationPromptRequired: true, + treasuryPremiumAuthorizationFollowupEstimate: 1, + treasuryBackgroundFanoutAllowed: false, + treasuryMaxBackgroundSubagents: 0, + treasuryNonEssentialWorkAllowed: false, releaseSigningStatus: 'warn', releaseSigningAuthorityState: 'scope-missing', releaseConductorApplyState: 'disabled', @@ -424,6 +469,35 @@ test('runAutonomousGovernorPortfolioSummary keeps compare as owner during active assert.equal(report.summary.executionBundlePremiumSaganMode, true); assert.equal(report.summary.executionBundleReciprocalLinkReady, true); assert.equal(report.summary.executionBundleEffectiveBillableRateUsdPerHour, 375); + assert.equal(report.compare.treasury.status, 'warn'); + assert.equal(report.compare.treasury.confidence, 'lower-bound-only'); + assert.equal(report.compare.treasury.spendPolicyState, 'core-delivery-only'); + assert.equal(report.compare.treasury.safeSpendableUsd, 66); + assert.equal(report.compare.treasury.operatorBudgetObservedRemainingUpperBoundUsd, 49970); + assert.equal(report.compare.treasury.operatorBudgetSpendableStatus, 'unreconciled'); + assert.equal(report.compare.treasury.coreDeliveryAllowed, true); + assert.equal(report.compare.treasury.queueAuthorityAllowed, true); + assert.equal(report.compare.treasury.releaseApplyAllowed, true); + assert.equal(report.compare.treasury.premiumAuthorizationPromptRequired, true); + assert.equal(report.compare.treasury.premiumAuthorizationFollowupEstimate, 1); + assert.equal(report.summary.treasuryStatus, 'warn'); + assert.equal(report.summary.treasuryConfidence, 'lower-bound-only'); + assert.equal(report.summary.treasurySpendPolicyState, 'core-delivery-only'); + assert.equal(report.summary.treasuryBudgetPressureState, 'tight'); + assert.equal(report.summary.treasuryProtectedReserveUsd, 100); + assert.equal(report.summary.treasuryAccountRemainingUsdEstimate, 166); + assert.equal(report.summary.treasuryOperationalHeadroomUsd, 66); + assert.equal(report.summary.treasurySafeSpendableUsd, 66); + assert.equal(report.summary.treasuryPossibleSpendableUpperBoundUsd, 66); + assert.equal(report.summary.treasuryOperatorBudgetObservedRemainingUpperBoundUsd, 49970); + assert.equal(report.summary.treasuryOperatorBudgetObservedRemainingStatus, 'upper-bound'); + assert.equal(report.summary.treasuryOperatorBudgetSpendableStatus, 'unreconciled'); + assert.equal(report.summary.treasuryPremiumSaganAllowed, false); + assert.equal(report.summary.treasuryPremiumAuthorizationPromptRequired, true); + assert.equal(report.summary.treasuryPremiumAuthorizationFollowupEstimate, 1); + assert.equal(report.summary.treasuryBackgroundFanoutAllowed, false); + assert.equal(report.summary.treasuryMaxBackgroundSubagents, 0); + assert.equal(report.summary.treasuryNonEssentialWorkAllowed, false); assert.equal(report.summary.viHistoryDistributorDependencyStatus, 'blocked'); assert.equal( report.summary.viHistoryDistributorDependencyExternalBlocker, diff --git a/tools/priority/__tests__/autonomous-governor-summary-schema.test.mjs b/tools/priority/__tests__/autonomous-governor-summary-schema.test.mjs index 47432f5e4..97c1ce3fc 100644 --- a/tools/priority/__tests__/autonomous-governor-summary-schema.test.mjs +++ b/tools/priority/__tests__/autonomous-governor-summary-schema.test.mjs @@ -99,10 +99,138 @@ test('autonomous governor summary report matches schema', async () => { reason: 'Waiting for hosted checks to finish before merge queue advances.' } }); + writeJson(path.join(tmpDir, 'tests', 'results', '_agent', 'cost', 'treasury-control-plane.json'), { + schema: 'priority/treasury-control-plane@v2', + repository: 'LabVIEW-Community-CI-CD/compare-vi-cli-action', + summary: { + status: 'warn', + recommendation: 'constrain-spend-to-core-delivery', + confidence: 'lower-bound-only', + spendPolicyState: 'core-delivery-only', + budgetPressureState: 'tight', + tokenSpendUsd: 12.5, + operatorLaborObservedUsd: 30, + operatorLaborMissingTurnCount: 1, + observedBlendedLowerBoundUsd: 42.5, + knownBlendedUsd: null, + protectedReserveUsd: 100, + accountRemainingUsdEstimate: 166, + operationalHeadroomUsd: 66, + operationalHeadroomStatus: 'reserve-near', + safeSpendableUsd: 66, + possibleSpendableUpperBoundUsd: 66, + sourceConflictCount: 0, + operatorBudgetCapUsd: 50000, + operatorBudgetObservedRemainingUpperBoundUsd: 49970, + operatorBudgetObservedRemainingStatus: 'upper-bound', + operatorBudgetRemainingLowerBoundUsd: null, + operatorBudgetRemainingStatus: 'unknown', + operatorBudgetSpendableUsd: null, + operatorBudgetSpendableStatus: 'unreconciled', + coreDeliveryAllowed: true, + queueAuthorityAllowed: true, + releaseApplyAllowed: true, + premiumSaganAllowed: false, + premiumAuthorizationPromptRequired: true, + premiumAuthorizationFollowupEstimate: 1, + backgroundFanoutAllowed: false, + maxBackgroundSubagents: 0, + nonEssentialWorkAllowed: false, + calibrationReserveProtected: true + }, + turns: { + totalTurns: 3, + liveTurnCount: 1, + backgroundTurnCount: 2 + }, + funding: { + billingWindow: { + invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0027', + invoiceId: 'HQ1VJLMV-0027', + fundingPurpose: 'operational', + activationState: 'active', + prepaidUsd: 400, + tokenSpendUsd: 12.5, + remainingUsd: 387.5, + pricingBasis: 'prepaid-credit', + selectionMode: 'hold', + selectionReason: 'Calibration funding window remains on hold before activation.' + }, + accountBalance: { + totalCredits: 28750, + usedCredits: 24600, + remainingCredits: 4150, + unitPriceUsd: 0.04, + remainingUsdEstimate: 166, + sourceKind: 'operator-account-state', + sourcePathEvidence: 'operator-account-state.json', + operatorNote: 'Latest operator-provided balance snapshot.' + }, + reservedFunding: { + count: 1, + totalReservedUsd: 100, + windows: [ + { + invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0028', + invoiceId: 'HQ1VJLMV-0028', + fundingPurpose: 'calibration', + activationState: 'hold', + prepaidUsd: 100, + operatorNote: 'Reserved calibration window.' + } + ] + } + }, + controls: { + premiumSaganMode: { + allowed: false, + requiresOperatorAuthorization: true, + requiresExplicitOperatorPrompt: true, + estimatedFollowupAuthorizationsNeeded: 1, + minimumOperationalHeadroomUsd: 150, + reason: 'budget-tight' + }, + backgroundFanout: { + allowed: false, + minimumOperationalHeadroomUsd: 125, + maximumConcurrentSubagents: 0, + reason: 'budget-tight' + }, + nonEssentialWork: { + allowed: false, + minimumOperationalHeadroomUsd: 100, + reason: 'budget-tight' + }, + operations: { + 'core-delivery': { allowed: true, reason: 'policy-core-delivery-only' }, + 'queue-authority': { allowed: true, reason: 'policy-core-delivery-only' }, + 'release-apply': { allowed: true, reason: 'policy-core-delivery-only' }, + 'background-fanout': { allowed: false, reason: 'budget-tight' }, + 'non-essential-work': { allowed: false, reason: 'budget-tight' }, + 'premium-sagan': { + allowed: false, + reason: 'budget-tight', + requiresOperatorAuthorization: true, + requiresExplicitOperatorPrompt: true, + estimatedFollowupAuthorizationsNeeded: 1 + } + } + }, + source: { + policyPath: 'tools/policy/treasury-control-plane.json', + costRollupPath: 'tests/results/_agent/cost/agent-cost-rollup.json', + costRollupMaterialized: true, + costRollupMaterializationReportPath: 'tests/results/_agent/cost/agent-cost-rollup-materialization.json', + operatorCostProfilePath: 'tools/policy/operator-cost-profile.json', + outputPath: 'tests/results/_agent/cost/treasury-control-plane.json' + }, + blockers: [] + }); const outputPath = path.join(tmpDir, 'tests', 'results', '_agent', 'handoff', 'autonomous-governor-summary.json'); const { report } = await runAutonomousGovernorSummary({ repoRoot: tmpDir, outputPath }); runSchemaValidate(repoRoot, path.join(repoRoot, 'docs', 'schemas', 'autonomous-governor-summary-report-v1.schema.json'), outputPath); assert.equal(report.schema, 'priority/autonomous-governor-summary-report@v1'); + assert.equal(report.summary.treasurySafeSpendableUsd, 66); }); diff --git a/tools/priority/__tests__/autonomous-governor-summary.test.mjs b/tools/priority/__tests__/autonomous-governor-summary.test.mjs index 22de60bc3..01f13bd9d 100644 --- a/tools/priority/__tests__/autonomous-governor-summary.test.mjs +++ b/tools/priority/__tests__/autonomous-governor-summary.test.mjs @@ -102,6 +102,137 @@ function createWakeInvestmentAccounting() { }; } +function createTreasuryControlPlane(overrides = {}) { + return { + schema: 'priority/treasury-control-plane@v2', + repository: 'LabVIEW-Community-CI-CD/compare-vi-cli-action', + summary: { + status: 'warn', + recommendation: 'constrain-spend-to-core-delivery', + confidence: 'lower-bound-only', + spendPolicyState: 'core-delivery-only', + budgetPressureState: 'tight', + tokenSpendUsd: 12.5, + operatorLaborObservedUsd: 30, + operatorLaborMissingTurnCount: 1, + observedBlendedLowerBoundUsd: 42.5, + knownBlendedUsd: null, + protectedReserveUsd: 100, + accountRemainingUsdEstimate: 166, + operationalHeadroomUsd: 66, + operationalHeadroomStatus: 'reserve-near', + safeSpendableUsd: 66, + possibleSpendableUpperBoundUsd: 66, + sourceConflictCount: 0, + operatorBudgetCapUsd: 50000, + operatorBudgetObservedRemainingUpperBoundUsd: 49970, + operatorBudgetObservedRemainingStatus: 'upper-bound', + operatorBudgetRemainingLowerBoundUsd: null, + operatorBudgetRemainingStatus: 'unknown', + operatorBudgetSpendableUsd: null, + operatorBudgetSpendableStatus: 'unreconciled', + coreDeliveryAllowed: true, + queueAuthorityAllowed: true, + releaseApplyAllowed: true, + premiumSaganAllowed: false, + premiumAuthorizationPromptRequired: true, + premiumAuthorizationFollowupEstimate: 1, + backgroundFanoutAllowed: false, + maxBackgroundSubagents: 0, + nonEssentialWorkAllowed: false, + calibrationReserveProtected: true + }, + turns: { + totalTurns: 3, + liveTurnCount: 1, + backgroundTurnCount: 2 + }, + funding: { + billingWindow: { + invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0027', + invoiceId: 'HQ1VJLMV-0027', + fundingPurpose: 'operational', + activationState: 'active', + prepaidUsd: 400, + tokenSpendUsd: 12.5, + remainingUsd: 387.5, + pricingBasis: 'prepaid-credit', + selectionMode: 'hold', + selectionReason: 'Calibration funding window remains on hold before activation.' + }, + accountBalance: { + totalCredits: 28750, + usedCredits: 24600, + remainingCredits: 4150, + unitPriceUsd: 0.04, + remainingUsdEstimate: 166, + sourceKind: 'operator-account-state', + sourcePathEvidence: 'operator-account-state.json', + operatorNote: 'Latest operator-provided balance snapshot.' + }, + reservedFunding: { + count: 1, + totalReservedUsd: 100, + windows: [ + { + invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0028', + invoiceId: 'HQ1VJLMV-0028', + fundingPurpose: 'calibration', + activationState: 'hold', + prepaidUsd: 100, + operatorNote: 'Reserved calibration window.' + } + ] + } + }, + controls: { + premiumSaganMode: { + allowed: false, + requiresOperatorAuthorization: true, + requiresExplicitOperatorPrompt: true, + estimatedFollowupAuthorizationsNeeded: 1, + minimumOperationalHeadroomUsd: 150, + reason: 'budget-tight' + }, + backgroundFanout: { + allowed: false, + minimumOperationalHeadroomUsd: 125, + maximumConcurrentSubagents: 0, + reason: 'budget-tight' + }, + nonEssentialWork: { + allowed: false, + minimumOperationalHeadroomUsd: 100, + reason: 'budget-tight' + }, + operations: { + 'core-delivery': { allowed: true, reason: 'policy-core-delivery-only' }, + 'queue-authority': { allowed: true, reason: 'policy-core-delivery-only' }, + 'release-apply': { allowed: true, reason: 'policy-core-delivery-only' }, + 'background-fanout': { allowed: false, reason: 'budget-tight' }, + 'non-essential-work': { allowed: false, reason: 'budget-tight' }, + 'premium-sagan': { + allowed: false, + reason: 'budget-tight', + requiresOperatorAuthorization: true, + requiresExplicitOperatorPrompt: true, + estimatedFollowupAuthorizationsNeeded: 1 + } + } + }, + source: { + policyPath: 'tools/policy/treasury-control-plane.json', + costRollupPath: 'tests/results/_agent/cost/agent-cost-rollup.json', + costRollupMaterialized: true, + costRollupMaterializationReportPath: 'tests/results/_agent/cost/agent-cost-rollup-materialization.json', + operatorCostProfilePath: 'tools/policy/operator-cost-profile.json', + outputPath: 'tests/results/_agent/cost/treasury-control-plane.json' + }, + blockers: [], + ...overrides + }; +} + function createReleaseSigningReadiness(overrides = {}) { return { schema: 'priority/release-signing-readiness-report@v1', @@ -389,6 +520,10 @@ test('runAutonomousGovernorSummary reports compare governance work when the late path.join(tmpDir, 'tests', 'results', '_agent', 'capital', 'wake-investment-accounting.json'), createWakeInvestmentAccounting() ); + writeJson( + path.join(tmpDir, 'tests', 'results', '_agent', 'cost', 'treasury-control-plane.json'), + createTreasuryControlPlane() + ); const { report } = await runAutonomousGovernorSummary({ repoRoot: tmpDir }); @@ -399,6 +534,40 @@ test('runAutonomousGovernorSummary reports compare governance work when the late assert.equal(report.summary.signalQuality, 'validated-governance-work'); assert.equal(report.funding.invoiceTurnId, 'invoice-turn-2026-03-HQ1VJLMV-0027'); assert.equal(report.compare.releaseSigningReadiness.status, 'missing'); + assert.equal(report.compare.treasury.status, 'warn'); + assert.equal(report.compare.treasury.confidence, 'lower-bound-only'); + assert.equal(report.compare.treasury.spendPolicyState, 'core-delivery-only'); + assert.equal(report.compare.treasury.operationalHeadroomUsd, 66); + assert.equal(report.compare.treasury.safeSpendableUsd, 66); + assert.equal(report.compare.treasury.operatorBudgetObservedRemainingUpperBoundUsd, 49970); + assert.equal(report.compare.treasury.operatorBudgetSpendableStatus, 'unreconciled'); + assert.equal(report.compare.treasury.coreDeliveryAllowed, true); + assert.equal(report.compare.treasury.queueAuthorityAllowed, true); + assert.equal(report.compare.treasury.releaseApplyAllowed, true); + assert.equal(report.compare.treasury.premiumSaganAllowed, false); + assert.equal(report.compare.treasury.premiumAuthorizationPromptRequired, true); + assert.equal(report.compare.treasury.premiumAuthorizationFollowupEstimate, 1); + assert.equal(report.compare.treasury.backgroundFanoutAllowed, false); + assert.equal(report.compare.treasury.maxBackgroundSubagents, 0); + assert.equal(report.compare.treasury.nonEssentialWorkAllowed, false); + assert.equal(report.summary.treasuryStatus, 'warn'); + assert.equal(report.summary.treasuryConfidence, 'lower-bound-only'); + assert.equal(report.summary.treasurySpendPolicyState, 'core-delivery-only'); + assert.equal(report.summary.treasuryBudgetPressureState, 'tight'); + assert.equal(report.summary.treasuryProtectedReserveUsd, 100); + assert.equal(report.summary.treasuryAccountRemainingUsdEstimate, 166); + assert.equal(report.summary.treasuryOperationalHeadroomUsd, 66); + assert.equal(report.summary.treasurySafeSpendableUsd, 66); + assert.equal(report.summary.treasuryPossibleSpendableUpperBoundUsd, 66); + assert.equal(report.summary.treasuryOperatorBudgetObservedRemainingUpperBoundUsd, 49970); + assert.equal(report.summary.treasuryOperatorBudgetObservedRemainingStatus, 'upper-bound'); + assert.equal(report.summary.treasuryOperatorBudgetSpendableStatus, 'unreconciled'); + assert.equal(report.summary.treasuryPremiumSaganAllowed, false); + assert.equal(report.summary.treasuryPremiumAuthorizationPromptRequired, true); + assert.equal(report.summary.treasuryPremiumAuthorizationFollowupEstimate, 1); + assert.equal(report.summary.treasuryBackgroundFanoutAllowed, false); + assert.equal(report.summary.treasuryMaxBackgroundSubagents, 0); + assert.equal(report.summary.treasuryNonEssentialWorkAllowed, false); assert.equal(report.summary.releaseSigningStatus, 'missing'); assert.equal(report.summary.releaseSigningExternalBlocker, null); }); @@ -424,6 +593,12 @@ test('runAutonomousGovernorSummary reports monitoring-active when no wake lifecy assert.equal(report.summary.queueHandoffStatus, 'none'); assert.equal(report.summary.queueAuthoritySource, 'none'); assert.equal(report.summary.releaseSigningStatus, 'missing'); + assert.equal(report.compare.treasury.status, 'missing'); + assert.equal(report.summary.treasuryStatus, 'missing'); + assert.equal(report.summary.treasurySpendPolicyState, 'blocked'); + assert.equal(report.summary.treasuryPremiumSaganAllowed, false); + assert.equal(report.summary.treasuryBackgroundFanoutAllowed, false); + assert.equal(report.summary.treasuryMaxBackgroundSubagents, 0); }); test('runAutonomousGovernorSummary carries explicit release signing blocker state into the governor summary', async () => { diff --git a/tools/priority/__tests__/delivery-agent-pr-sync.test.mjs b/tools/priority/__tests__/delivery-agent-pr-sync.test.mjs index ea4b275b1..3497b4090 100644 --- a/tools/priority/__tests__/delivery-agent-pr-sync.test.mjs +++ b/tools/priority/__tests__/delivery-agent-pr-sync.test.mjs @@ -117,6 +117,78 @@ test('runDeliveryTurnBroker updates a behind PR branch before waiting on review' assert.equal(brokerResult.details.nextWakeCondition, 'checks-green'); }); +test('runDeliveryTurnBroker fails closed when treasury denies sync-pr-branch core delivery', async (t) => { + const repoRoot = await mkdtemp(path.join(os.tmpdir(), 'delivery-agent-pr-sync-treasury-')); + t.after(async () => { + await rm(repoRoot, { recursive: true, force: true }); + }); + + let branchUpdateCalled = false; + const brokerResult = await runDeliveryTurnBroker({ + repoRoot, + taskPacket: { + repository: 'LabVIEW-Community-CI-CD/compare-vi-cli-action', + status: 'waiting-review', + objective: { + summary: 'Advance issue #959' + }, + evidence: { + delivery: { + laneLifecycle: 'waiting-review', + pullRequest: { + number: 1017, + url: 'https://github.com/LabVIEW-Community-CI-CD/compare-vi-cli-action/pull/1017', + mergeStateStatus: 'BEHIND', + syncRequired: true, + checks: { + blockerClass: 'ci' + } + } + } + } + }, + deps: { + loadDeliveryAgentPolicyFn: async () => ({ + schema: 'priority/delivery-agent-policy@v1', + backlogAuthority: 'issues', + implementationRemote: 'origin', + copilotReviewStrategy: 'off', + autoSlice: true, + autoMerge: true, + maxActiveCodingLanes: 1, + allowPolicyMutations: false, + allowReleaseAdmin: false, + stopWhenNoOpenEpics: true, + codingTurnCommand: [] + }), + runTreasuryOperationGuardFn: () => ({ + decision: { + allowed: false, + code: 'treasury-operation-denied', + reason: 'Treasury denied core-delivery: reserve-protected-only.', + authorization: { + requiresOperatorAuthorization: false, + requiresExplicitOperatorPrompt: false, + estimatedFollowupAuthorizationsNeeded: 0 + } + } + }), + updatePullRequestBranchFn: async () => { + branchUpdateCalled = true; + return { + status: 'completed', + outcome: 'branch-updated' + }; + } + } + }); + + assert.equal(brokerResult.status, 'blocked'); + assert.equal(brokerResult.outcome, 'treasury-core-delivery-denied'); + assert.equal(brokerResult.details.treasuryDecisionCode, 'treasury-operation-denied'); + assert.equal(branchUpdateCalled, false); +}); + test('runDeliveryTurnBroker refreshes queue authority during waiting-ci watch turns', async (t) => { const repoRoot = await mkdtemp(path.join(os.tmpdir(), 'delivery-agent-watch-pr-queue-refresh-')); t.after(async () => { diff --git a/tools/priority/__tests__/execution-cell-bundle-schema.test.mjs b/tools/priority/__tests__/execution-cell-bundle-schema.test.mjs index 4a190392d..9f719a2d5 100644 --- a/tools/priority/__tests__/execution-cell-bundle-schema.test.mjs +++ b/tools/priority/__tests__/execution-cell-bundle-schema.test.mjs @@ -233,8 +233,14 @@ test('execution cell bundle report schema validates a premium Sagan kernel recei windowsNativeTestStand: true, effectiveBillableRateMultiplier: 1.5, effectiveBillableRateUsdPerHour: 375, + premiumSaganRequested: true, premiumSaganMode: true, + operatorAuthorizationRequired: true, + operatorAuthorizationPromptRequired: true, + estimatedFollowupAuthorizationsNeeded: 1, operatorAuthorizationRef: 'budget-auth://operator/session-2026-03-24', + treasuryDecisionCode: 'treasury-operation-allowed', + treasuryControlPlanePath: 'tests/results/_agent/cost/treasury-control-plane.json', isolatedLaneGroupId: 'host-os-fingerprint:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', fingerprintSha256: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', capabilities: ['teststand-harness', 'docker-lane', 'native-labview-2026-32'], diff --git a/tools/priority/__tests__/execution-cell-bundle.test.mjs b/tools/priority/__tests__/execution-cell-bundle.test.mjs index d96d89794..c41b1e07b 100644 --- a/tools/priority/__tests__/execution-cell-bundle.test.mjs +++ b/tools/priority/__tests__/execution-cell-bundle.test.mjs @@ -112,7 +112,12 @@ test('execution-cell bundle grants coordinated worker cell and docker lane at or assert.equal(granted.executionCell.status, 'granted'); assert.equal(granted.dockerLane.status, 'granted'); assert.equal(granted.summary.effectiveBillableRateUsdPerHour, 250); + assert.equal(granted.summary.premiumSaganRequested, false); assert.equal(granted.summary.premiumSaganMode, false); + assert.equal(granted.summary.operatorAuthorizationRequired, false); + assert.equal(granted.summary.operatorAuthorizationPromptRequired, false); + assert.equal(granted.summary.estimatedFollowupAuthorizationsNeeded, 0); + assert.equal(granted.summary.treasuryDecisionCode, null); assert.equal(granted.summary.windowsNativeTestStand, true); assert.equal(granted.summary.reciprocalLinkReady, false); }); @@ -172,7 +177,11 @@ test('execution-cell bundle infers premium Sagan dual-lane mode for dual-plane p assert.equal(granted.status, 'granted'); assert.equal(granted.executionCell.status, 'granted'); assert.equal(granted.dockerLane.status, 'granted'); + assert.equal(granted.summary.premiumSaganRequested, true); assert.equal(granted.summary.premiumSaganMode, true); + assert.equal(granted.summary.operatorAuthorizationRequired, true); + assert.equal(granted.summary.operatorAuthorizationPromptRequired, true); + assert.equal(granted.summary.estimatedFollowupAuthorizationsNeeded, 1); assert.equal(granted.summary.effectiveBillableRateUsdPerHour, 375); assert.equal(granted.summary.reciprocalLinkReady, false); assert.deepEqual( @@ -182,6 +191,99 @@ test('execution-cell bundle infers premium Sagan dual-lane mode for dual-plane p }); }); +test('execution-cell bundle fails closed when treasury denies premium Sagan mode', async () => { + await withTempDir('execution-cell-bundle-premium-treasury-denied', async (root) => { + const hostPlaneReportPath = path.join(root, 'host-plane.json'); + const operatorCostProfilePath = path.join(root, 'operator-cost-profile.json'); + await writeJson(hostPlaneReportPath, createHostPlaneReport()); + await writeJson(operatorCostProfilePath, createOperatorCostProfile()); + + const denied = await runExecutionCellBundle({ + action: 'request', + cellId: 'exec-cell-sagan-kernel-03', + laneId: 'docker-agent-sagan-kernel-03', + agentId: 'sagan', + agentClass: 'sagan', + cellClass: 'kernel-coordinator', + suiteClass: 'dual-plane-parity', + planeBinding: 'dual-plane-parity', + harnessKind: 'teststand-compare-harness', + capabilities: ['teststand-harness', 'docker-lane'], + operatorAuthorizationRef: 'budget-auth://operator/session-2026-03-24', + repoRoot: root, + runTreasuryOperationGuardFn: () => ({ + outputPath: path.join(root, 'tests', 'results', '_agent', 'cost', 'treasury-control-plane.json'), + decision: { + allowed: false, + code: 'treasury-operation-denied', + reason: 'Treasury denied premium-sagan: budget-tight.', + authorization: { + requiresOperatorAuthorization: true, + requiresExplicitOperatorPrompt: true, + estimatedFollowupAuthorizationsNeeded: 2 + } + } + }) + }); + + assert.equal(denied.status, 'denied'); + assert.equal(denied.executionCell, null); + assert.equal(denied.dockerLane, null); + assert.equal(denied.summary.premiumSaganRequested, true); + assert.equal(denied.summary.premiumSaganMode, false); + assert.equal(denied.summary.operatorAuthorizationRequired, true); + assert.equal(denied.summary.operatorAuthorizationPromptRequired, true); + assert.equal(denied.summary.estimatedFollowupAuthorizationsNeeded, 2); + assert.equal(denied.summary.treasuryDecisionCode, 'treasury-operation-denied'); + assert.match(denied.summary.treasuryControlPlanePath, /treasury-control-plane\.json$/); + assert.match(denied.summary.denialReasons.join('\n'), /treasury-operation-denied/); + }); +}); + +test('execution-cell bundle surfaces an explicit operator authorization prompt when premium mode lacks authorization', async () => { + await withTempDir('execution-cell-bundle-premium-auth-required', async (root) => { + const hostPlaneReportPath = path.join(root, 'host-plane.json'); + const operatorCostProfilePath = path.join(root, 'operator-cost-profile.json'); + await writeJson(hostPlaneReportPath, createHostPlaneReport()); + await writeJson(operatorCostProfilePath, createOperatorCostProfile()); + + const denied = await runExecutionCellBundle({ + action: 'request', + cellId: 'exec-cell-sagan-kernel-04', + laneId: 'docker-agent-sagan-kernel-04', + agentId: 'sagan', + agentClass: 'sagan', + cellClass: 'kernel-coordinator', + suiteClass: 'dual-plane-parity', + planeBinding: 'dual-plane-parity', + harnessKind: 'teststand-compare-harness', + capabilities: ['teststand-harness', 'docker-lane'], + repoRoot: root, + runTreasuryOperationGuardFn: () => ({ + outputPath: path.join(root, 'tests', 'results', '_agent', 'cost', 'treasury-control-plane.json'), + decision: { + allowed: true, + code: 'treasury-operation-allowed', + reason: 'budget-healthy', + authorization: { + requiresOperatorAuthorization: true, + requiresExplicitOperatorPrompt: true, + estimatedFollowupAuthorizationsNeeded: 1 + } + } + }) + }); + + assert.equal(denied.status, 'denied'); + assert.equal(denied.summary.premiumSaganRequested, true); + assert.equal(denied.summary.operatorAuthorizationRequired, true); + assert.equal(denied.summary.operatorAuthorizationPromptRequired, true); + assert.equal(denied.summary.estimatedFollowupAuthorizationsNeeded, 1); + assert.match(denied.summary.denialReasons.join('\n'), /operator-authorization-required/); + assert.match(denied.summary.observations.join('\n'), /premium-operator-prompt-required/); + }); +}); + test('execution-cell bundle denies linux-bound TestStand cells and rolls back requested docker lanes', async () => { await withTempDir('execution-cell-bundle-linux-teststand', async (root) => { const hostPlaneReportPath = path.join(root, 'host-plane.json'); diff --git a/tools/priority/__tests__/github-comment-budget-hook-schema.test.mjs b/tools/priority/__tests__/github-comment-budget-hook-schema.test.mjs index 91bc6b216..055969099 100644 --- a/tools/priority/__tests__/github-comment-budget-hook-schema.test.mjs +++ b/tools/priority/__tests__/github-comment-budget-hook-schema.test.mjs @@ -26,6 +26,7 @@ test('github-comment-budget-hook report and policy validate against checked-in s const policyPath = path.join(repo, 'tools', 'policy', 'github-comment-budget-hook.json'); writeJson(policyPath, { schema: 'priority/github-comment-budget-hook-policy@v1', + treasuryPolicyPath: 'tools/policy/treasury-control-plane.json', costRollupPath: 'tests/results/_agent/cost/agent-cost-rollup.json', materializationPolicyPath: 'tools/policy/agent-cost-rollup-materialization.json', materializationReportPath: 'tests/results/_agent/cost/agent-cost-rollup-materialization.json', @@ -45,50 +46,126 @@ test('github-comment-budget-hook report and policy validate against checked-in s targetNumber: 1908 }, { - runMaterializeAgentCostRollupFn: ({ costRollupPath, outputPath }) => { - writeJson(costRollupPath, { - schema: 'priority/agent-cost-rollup@v1', + runTreasuryControlPlaneFn: () => ({ + report: { + schema: 'priority/treasury-control-plane@v2', repository: 'LabVIEW-Community-CI-CD/compare-vi-cli-action', summary: { - metrics: { - totalTurns: 1, - liveTurnCount: 0, - backgroundTurnCount: 1, - totalUsd: 1.5, - operatorLaborUsd: 4, - operatorLaborMissingTurnCount: 0, - blendedTotalUsd: 5.5, - estimatedPrepaidUsdRemaining: 398.5, - accountBalanceTotalCredits: 28750, - accountBalanceUsedCredits: 24600, - accountBalanceRemainingCredits: 4150 + status: 'pass', + recommendation: 'treasury-control-plane-ready', + confidence: 'observed', + spendPolicyState: 'healthy', + budgetPressureState: 'healthy', + tokenSpendUsd: 1.5, + operatorLaborObservedUsd: 4, + operatorLaborMissingTurnCount: 0, + observedBlendedLowerBoundUsd: 5.5, + knownBlendedUsd: 5.5, + protectedReserveUsd: 0, + accountRemainingUsdEstimate: 400, + operationalHeadroomUsd: 400, + operationalHeadroomStatus: 'healthy', + safeSpendableUsd: 400, + possibleSpendableUpperBoundUsd: 400, + sourceConflictCount: 0, + operatorBudgetCapUsd: 50000, + operatorBudgetObservedRemainingUpperBoundUsd: 49996, + operatorBudgetObservedRemainingStatus: 'observed', + operatorBudgetRemainingLowerBoundUsd: 49996, + operatorBudgetRemainingStatus: 'observed', + operatorBudgetSpendableUsd: 49996, + operatorBudgetSpendableStatus: 'observed', + coreDeliveryAllowed: true, + queueAuthorityAllowed: true, + releaseApplyAllowed: true, + premiumSaganAllowed: true, + premiumAuthorizationPromptRequired: true, + premiumAuthorizationFollowupEstimate: 1, + backgroundFanoutAllowed: true, + maxBackgroundSubagents: 2, + nonEssentialWorkAllowed: true, + calibrationReserveProtected: false + }, + turns: { + totalTurns: 1, + liveTurnCount: 0, + backgroundTurnCount: 1 + }, + funding: { + billingWindow: { + invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0027', + invoiceId: 'HQ1VJLMV-0027', + fundingPurpose: 'operational', + activationState: 'active', + prepaidUsd: 400, + tokenSpendUsd: 1.5, + remainingUsd: 398.5, + pricingBasis: 'prepaid-credit', + selectionMode: 'hold', + selectionReason: null + }, + accountBalance: { + totalCredits: 28750, + usedCredits: 18750, + remainingCredits: 10000, + unitPriceUsd: 0.04, + remainingUsdEstimate: 400, + sourceKind: 'operator-account-state', + sourcePathEvidence: 'operator-account-state.json', + operatorNote: 'Latest operator-provided balance snapshot.' }, - provenance: { - operatorProfiles: [{ operatorProfilePath: 'tools/policy/operator-cost-profile.json' }], - invoiceTurn: { - unitPriceUsd: 0.04 - }, - accountBalance: { - sourceKind: 'operator-account-state', - sourcePathEvidence: 'operator-account-state.json', - operatorNote: 'Latest operator-provided balance snapshot.' - }, - invoiceTurns: [] + reservedFunding: { + count: 0, + totalReservedUsd: 0, + windows: [] } }, - billingWindow: { - invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0027', - invoiceId: 'HQ1VJLMV-0027', - fundingPurpose: 'operational', - activationState: 'active', - prepaidUsd: 400, - pricingBasis: 'prepaid-credit', - selection: { mode: 'hold', reason: null } - } - }); - writeJson(outputPath, { schema: 'priority/agent-cost-rollup-materialization@v1', summary: { status: 'pass' } }); - return { costRollupPath, outputPath }; - } + controls: { + premiumSaganMode: { + allowed: true, + requiresOperatorAuthorization: true, + requiresExplicitOperatorPrompt: true, + estimatedFollowupAuthorizationsNeeded: 1, + minimumOperationalHeadroomUsd: 150, + reason: 'budget-healthy' + }, + backgroundFanout: { + allowed: true, + minimumOperationalHeadroomUsd: 125, + maximumConcurrentSubagents: 2, + reason: 'budget-healthy' + }, + nonEssentialWork: { + allowed: true, + minimumOperationalHeadroomUsd: 100, + reason: 'budget-healthy' + }, + operations: { + 'core-delivery': { allowed: true, reason: 'policy-healthy' }, + 'queue-authority': { allowed: true, reason: 'policy-healthy' }, + 'release-apply': { allowed: true, reason: 'policy-healthy' }, + 'background-fanout': { allowed: true, reason: 'budget-healthy' }, + 'non-essential-work': { allowed: true, reason: 'budget-healthy' }, + 'premium-sagan': { + allowed: true, + reason: 'budget-healthy', + requiresOperatorAuthorization: true, + requiresExplicitOperatorPrompt: true, + estimatedFollowupAuthorizationsNeeded: 1 + } + } + }, + source: { + policyPath: 'tools/policy/treasury-control-plane.json', + costRollupPath: 'tests/results/_agent/cost/agent-cost-rollup.json', + costRollupMaterialized: true, + costRollupMaterializationReportPath: 'tests/results/_agent/cost/agent-cost-rollup-materialization.json', + operatorCostProfilePath: 'tools/policy/operator-cost-profile.json', + outputPath: 'tests/results/_agent/cost/treasury-control-plane.json' + }, + blockers: [] + } + }) } ); diff --git a/tools/priority/__tests__/github-comment-budget-hook.test.mjs b/tools/priority/__tests__/github-comment-budget-hook.test.mjs index a3193f269..6d1647e2c 100644 --- a/tools/priority/__tests__/github-comment-budget-hook.test.mjs +++ b/tools/priority/__tests__/github-comment-budget-hook.test.mjs @@ -17,47 +17,78 @@ function writeJson(filePath, payload) { fs.writeFileSync(filePath, `${JSON.stringify(payload, null, 2)}\n`, 'utf8'); } -function createRollupFixture() { +function createTreasuryReportFixture() { return { - schema: 'priority/agent-cost-rollup@v1', + schema: 'priority/treasury-control-plane@v2', repository: 'LabVIEW-Community-CI-CD/compare-vi-cli-action', summary: { - metrics: { - totalTurns: 3, - liveTurnCount: 1, - backgroundTurnCount: 2, - totalUsd: 12.5, - operatorLaborUsd: 30, - operatorLaborMissingTurnCount: 1, - blendedTotalUsd: null, - estimatedPrepaidUsdRemaining: 387.5, - accountBalanceTotalCredits: 28750, - accountBalanceUsedCredits: 24600, - accountBalanceRemainingCredits: 4150 + status: 'warn', + recommendation: 'constrain-spend-to-core-delivery', + confidence: 'lower-bound-only', + spendPolicyState: 'core-delivery-only', + budgetPressureState: 'tight', + tokenSpendUsd: 12.5, + operatorLaborObservedUsd: 30, + operatorLaborMissingTurnCount: 1, + observedBlendedLowerBoundUsd: 42.5, + knownBlendedUsd: null, + protectedReserveUsd: 100, + accountRemainingUsdEstimate: 166, + operationalHeadroomUsd: 66, + operationalHeadroomStatus: 'reserve-near', + safeSpendableUsd: 66, + possibleSpendableUpperBoundUsd: 66, + sourceConflictCount: 0, + operatorBudgetCapUsd: 50000, + operatorBudgetObservedRemainingUpperBoundUsd: 49970, + operatorBudgetObservedRemainingStatus: 'upper-bound', + operatorBudgetRemainingLowerBoundUsd: null, + operatorBudgetRemainingStatus: 'unknown', + operatorBudgetSpendableUsd: null, + operatorBudgetSpendableStatus: 'unreconciled', + coreDeliveryAllowed: true, + queueAuthorityAllowed: true, + releaseApplyAllowed: true, + premiumSaganAllowed: false, + premiumAuthorizationPromptRequired: true, + premiumAuthorizationFollowupEstimate: 1, + backgroundFanoutAllowed: false, + maxBackgroundSubagents: 0, + nonEssentialWorkAllowed: false, + calibrationReserveProtected: true + }, + turns: { + totalTurns: 3, + liveTurnCount: 1, + backgroundTurnCount: 2 + }, + funding: { + billingWindow: { + invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0027', + invoiceId: 'HQ1VJLMV-0027', + fundingPurpose: 'operational', + activationState: 'active', + prepaidUsd: 400, + tokenSpendUsd: 12.5, + remainingUsd: 387.5, + pricingBasis: 'prepaid-credit', + selectionMode: 'hold', + selectionReason: 'Calibration funding window remains on hold before activation.' }, - provenance: { - operatorProfiles: [ - { - operatorProfilePath: 'tools/policy/operator-cost-profile.json' - } - ], - invoiceTurn: { - unitPriceUsd: 0.04 - }, - accountBalance: { - sourceKind: 'operator-account-state', - sourcePathEvidence: 'operator-account-state.json', - operatorNote: 'Latest operator-provided balance snapshot.' - }, - invoiceTurns: [ - { - invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0027', - invoiceId: 'HQ1VJLMV-0027', - fundingPurpose: 'operational', - activationState: 'active', - prepaidUsd: 400, - operatorNote: 'Operational window.' - }, + accountBalance: { + totalCredits: 28750, + usedCredits: 24600, + remainingCredits: 4150, + unitPriceUsd: 0.04, + remainingUsdEstimate: 166, + sourceKind: 'operator-account-state', + sourcePathEvidence: 'operator-account-state.json', + operatorNote: 'Latest operator-provided balance snapshot.' + }, + reservedFunding: { + count: 1, + totalReservedUsd: 100, + windows: [ { invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0028', invoiceId: 'HQ1VJLMV-0028', @@ -69,18 +100,50 @@ function createRollupFixture() { ] } }, - billingWindow: { - invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0027', - invoiceId: 'HQ1VJLMV-0027', - fundingPurpose: 'operational', - activationState: 'active', - prepaidUsd: 400, - pricingBasis: 'prepaid-credit', - selection: { - mode: 'hold', - reason: 'Calibration funding window remains on hold before activation.' + controls: { + premiumSaganMode: { + allowed: false, + requiresOperatorAuthorization: true, + requiresExplicitOperatorPrompt: true, + estimatedFollowupAuthorizationsNeeded: 1, + minimumOperationalHeadroomUsd: 150, + reason: 'budget-tight' + }, + backgroundFanout: { + allowed: false, + minimumOperationalHeadroomUsd: 125, + maximumConcurrentSubagents: 0, + reason: 'budget-tight' + }, + nonEssentialWork: { + allowed: false, + minimumOperationalHeadroomUsd: 100, + reason: 'budget-tight' + }, + operations: { + 'core-delivery': { allowed: true, reason: 'policy-core-delivery-only' }, + 'queue-authority': { allowed: true, reason: 'policy-core-delivery-only' }, + 'release-apply': { allowed: true, reason: 'policy-core-delivery-only' }, + 'background-fanout': { allowed: false, reason: 'budget-tight' }, + 'non-essential-work': { allowed: false, reason: 'budget-tight' }, + 'premium-sagan': { + allowed: false, + reason: 'budget-tight', + requiresOperatorAuthorization: true, + requiresExplicitOperatorPrompt: true, + estimatedFollowupAuthorizationsNeeded: 1 + } } - } + }, + source: { + policyPath: 'tools/policy/treasury-control-plane.json', + costRollupPath: 'tests/results/_agent/cost/agent-cost-rollup.json', + costRollupMaterialized: true, + costRollupMaterializationReportPath: 'tests/results/_agent/cost/agent-cost-rollup-materialization.json', + operatorCostProfilePath: 'tools/policy/operator-cost-profile.json', + outputPath: 'tests/results/_agent/cost/treasury-control-plane.json' + }, + blockers: [] }; } @@ -98,17 +161,17 @@ test('appendBudgetHook appends exactly one hook block', () => { assert.match(twice, new RegExp(COMMENT_HOOK_START_MARKER.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))); }); -test('runGitHubCommentBudgetHook emits a durable lower-bound budget hook with reserved calibration context', () => { +test('runGitHubCommentBudgetHook projects the treasury control plane into a durable comment hook', () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'github-comment-budget-hook-')); const repoRoot = path.join(tempDir, 'repo'); fs.mkdirSync(repoRoot, { recursive: true }); const policyPath = path.join(repoRoot, 'tools', 'policy', 'github-comment-budget-hook.json'); const outputPath = path.join(repoRoot, 'tests', 'results', '_agent', 'cost', 'github-comment-budget-hook.json'); const markdownOutputPath = path.join(repoRoot, 'tests', 'results', '_agent', 'cost', 'github-comment-budget-hook.md'); - const rollupPath = path.join(repoRoot, 'tests', 'results', '_agent', 'cost', 'agent-cost-rollup.json'); writeJson(policyPath, { schema: 'priority/github-comment-budget-hook-policy@v1', + treasuryPolicyPath: 'tools/policy/treasury-control-plane.json', costRollupPath: 'tests/results/_agent/cost/agent-cost-rollup.json', materializationPolicyPath: 'tools/policy/agent-cost-rollup-materialization.json', materializationReportPath: 'tests/results/_agent/cost/agent-cost-rollup-materialization.json', @@ -128,29 +191,35 @@ test('runGitHubCommentBudgetHook emits a durable lower-bound budget hook with re targetNumber: 1907 }, { - runMaterializeAgentCostRollupFn: ({ costRollupPath, outputPath: materializationPath }) => { - writeJson(costRollupPath, createRollupFixture()); - writeJson(materializationPath, { - schema: 'priority/agent-cost-rollup-materialization@v1', - summary: { status: 'pass' } - }); - return { - costRollupPath, - outputPath: materializationPath - }; - } + runTreasuryControlPlaneFn: () => ({ + report: createTreasuryReportFixture() + }) } ); assert.equal(result.report.summary.status, 'warn'); assert.equal(result.report.summary.operatorBudgetCapUsd, 50000); - assert.equal(result.report.summary.operatorBudgetRemainingStatus, 'lower-bound'); + assert.equal(result.report.summary.operatorBudgetObservedRemainingUpperBoundUsd, 49970); + assert.equal(result.report.summary.operatorBudgetObservedRemainingStatus, 'upper-bound'); + assert.equal(result.report.summary.operatorBudgetRemainingLowerBoundUsd, null); + assert.equal(result.report.summary.operatorBudgetRemainingStatus, 'unknown'); assert.equal(result.report.summary.operatorBudgetSpendableStatus, 'unreconciled'); assert.equal(result.report.summary.operatorBudgetSpendableUsd, null); assert.equal(result.report.summary.observedBlendedLowerBoundUsd, 42.5); assert.equal(result.report.summary.accountRemainingUsdEstimate, 166); assert.equal(result.report.summary.operationalHeadroomUsd, 66); - assert.equal(result.report.summary.operationalHeadroomStatus, 'reserve-near'); + assert.equal(result.report.summary.safeSpendableUsd, 66); + assert.equal(result.report.summary.treasuryConfidence, 'lower-bound-only'); + assert.equal(result.report.summary.treasurySpendPolicyState, 'core-delivery-only'); + assert.equal(result.report.summary.coreDeliveryAllowed, true); + assert.equal(result.report.summary.queueAuthorityAllowed, true); + assert.equal(result.report.summary.releaseApplyAllowed, true); + assert.equal(result.report.summary.premiumSaganAllowed, false); + assert.equal(result.report.summary.premiumAuthorizationPromptRequired, true); + assert.equal(result.report.summary.premiumAuthorizationFollowupEstimate, 1); + assert.equal(result.report.summary.backgroundFanoutAllowed, false); + assert.equal(result.report.summary.maxBackgroundSubagents, 0); + assert.equal(result.report.summary.nonEssentialWorkAllowed, false); assert.equal(result.report.summary.budgetPressureState, 'tight'); assert.equal(result.report.turns.backgroundTurnCount, 2); assert.equal(result.report.funding.accountBalance.remainingCredits, 4150); @@ -160,8 +229,10 @@ test('runGitHubCommentBudgetHook emits a durable lower-bound budget hook with re assert.equal(fs.existsSync(outputPath), true); assert.equal(fs.existsSync(markdownOutputPath), true); assert.match(result.markdown, /blended lower bound \$42\.500000/); - assert.match(result.markdown, /account est \$166\.000000 remaining/); - assert.match(result.markdown, /operational headroom \$66\.000000 \(reserve-near\)/); - assert.match(result.markdown, /pressure tight/); + assert.match(result.markdown, /observed upper bound \$49970\.000000/); + assert.match(result.markdown, /safe spend \$66\.000000/); + assert.match(result.markdown, /treasury core-delivery-only \(lower-bound-only\)/); + assert.match(result.markdown, /ops core=true queue=true release=true/); + assert.match(result.markdown, /premium requires explicit operator authorization \(follow-up estimate 1\)/); assert.match(result.markdown, /calibration reserve \$100\.000000/); }); diff --git a/tools/priority/__tests__/queue-supervisor.test.mjs b/tools/priority/__tests__/queue-supervisor.test.mjs index 94aa3664b..de7c538f7 100644 --- a/tools/priority/__tests__/queue-supervisor.test.mjs +++ b/tools/priority/__tests__/queue-supervisor.test.mjs @@ -1881,3 +1881,67 @@ test('runQueueSupervisor applies governor stabilize cap when queue is healthy', assert.equal(report.effectiveMaxInflight, 2); assert.equal(report.paused, false); }); + +test('runQueueSupervisor fails closed when treasury denies queue authority', async () => { + const runGhJsonFn = (args) => { + if (args[0] === 'pr' && args[1] === 'list') { + return []; + } + if (args[0] === 'api' && String(args[1]).includes('validate.yml')) return { workflow_runs: [] }; + if (args[0] === 'api' && String(args[1]).includes('policy-guard-upstream.yml')) return { workflow_runs: [] }; + if (args[0] === 'api' && String(args[1]).includes('fixture-drift.yml')) return { workflow_runs: [] }; + if (args[0] === 'api' && String(args[1]).includes('commit-integrity.yml')) return { workflow_runs: [] }; + throw new Error(`Unexpected gh args: ${args.join(' ')}`); + }; + + const readJsonFileFn = async (filePath) => { + if (String(filePath).endsWith('branch-required-checks.json')) { + return { branches: { develop: ['lint'] } }; + } + if (String(filePath).endsWith('policy.json')) { + return { rulesets: {} }; + } + throw new Error(`Unexpected read path: ${filePath}`); + }; + + let commandCalls = 0; + const { report } = await runQueueSupervisor({ + repoRoot: process.cwd(), + args: { + apply: true, + dryRun: false, + reportPath: 'tests/results/_agent/queue/queue-supervisor-report.json', + maxInflight: 5, + minInflight: 1, + adaptiveCap: false, + maxQueuedRuns: 6, + maxInProgressRuns: 8, + stallThresholdMinutes: 45, + repo: 'owner/repo', + baseBranches: ['develop', 'main'], + healthBranch: 'develop', + help: false + }, + now: new Date('2026-03-05T21:30:00.000Z'), + runGhJsonFn, + runCommandFn: () => { + commandCalls += 1; + return { status: 0, stdout: '', stderr: '' }; + }, + readJsonFileFn, + readOptionalJsonFn: async () => null, + writeReportFn: async (reportPath) => reportPath, + runTreasuryOperationGuardFn: () => ({ + decision: { + allowed: false, + code: 'treasury-operation-denied', + reason: 'Treasury denied queue-authority: policy-core-delivery-only.' + } + }) + }); + + assert.equal(report.paused, true); + assert.ok(report.pausedReasons.includes('treasury-queue-authority-denied')); + assert.ok(report.pausedReasons.includes('treasury-operation-denied')); + assert.equal(commandCalls, 0); +}); diff --git a/tools/priority/__tests__/release-conductor.test.mjs b/tools/priority/__tests__/release-conductor.test.mjs index 4878089a1..9dc9eb84e 100644 --- a/tools/priority/__tests__/release-conductor.test.mjs +++ b/tools/priority/__tests__/release-conductor.test.mjs @@ -239,6 +239,87 @@ test('runReleaseConductor blocks apply when release conductor flag is disabled', assert.equal(commandCalls.some((entry) => entry.command === 'git' && entry.args[0] === 'tag'), false); }); +test('runReleaseConductor fails closed when treasury denies release apply', async () => { + const readJsonOptionalFn = async (filePath) => { + const normalized = String(filePath); + if (normalized.includes('queue-supervisor-report.json')) { + return { + exists: true, + error: null, + path: filePath, + payload: { + paused: false, + throughputController: { mode: 'healthy' }, + retryHistory: {} + } + }; + } + return { + exists: true, + error: null, + path: filePath, + payload: { + schema: 'priority/policy-live-state@v1', + generatedAt: '2026-03-06T10:00:00Z', + state: {} + } + }; + }; + + const runGhJsonFn = (args) => { + if (args[0] === 'api') { + return makeWorkflowRunsResponse(String(args[1])); + } + throw new Error(`unexpected gh args: ${args.join(' ')}`); + }; + + const commandCalls = []; + const { report, exitCode } = await runReleaseConductor({ + repoRoot: process.cwd(), + now: new Date('2026-03-06T12:00:00.000Z'), + args: { + apply: true, + dryRun: false, + reportPath: 'tests/results/_agent/release/release-conductor-report.json', + queueReportPath: 'tests/results/_agent/queue/queue-supervisor-report.json', + policySnapshotPath: 'tests/results/_agent/policy/policy-state-snapshot.json', + repo: 'owner/repo', + stream: 'comparevi-cli', + channel: 'stable', + version: '0.8.0', + dwellMinutes: 60, + quarantineStaleHours: 24, + help: false + }, + environment: { + GITHUB_REPOSITORY: 'owner/repo', + RELEASE_CONDUCTOR_ENABLED: '1' + }, + runGhJsonFn, + runCommandFn: (command, args) => { + commandCalls.push({ command, args }); + if (command === 'git' && args[0] === 'config') { + return { status: 0, stdout: 'ABC123', stderr: '' }; + } + return { status: 0, stdout: '', stderr: '' }; + }, + readJsonOptionalFn, + writeReportFn: async (reportPath) => reportPath, + runTreasuryOperationGuardFn: () => ({ + decision: { + allowed: false, + code: 'treasury-operation-denied', + reason: 'Treasury denied release-apply: policy-core-delivery-only.' + } + }) + }); + + assert.equal(exitCode, 1); + assert.equal(report.decision.status, 'fail'); + assert.ok(report.decision.blockers.some((entry) => entry.code === 'treasury-release-apply-denied')); + assert.equal(commandCalls.some((entry) => entry.command === 'git' && entry.args[0] === 'tag'), false); +}); + test('runReleaseConductor keeps dry-run proposal-only when queue evidence is missing and no recent success exists', async () => { const readJsonOptionalFn = async (filePath) => { const normalized = String(filePath); diff --git a/tools/priority/__tests__/runtime-supervisor.test.mjs b/tools/priority/__tests__/runtime-supervisor.test.mjs index cd29915a5..716e191b4 100644 --- a/tools/priority/__tests__/runtime-supervisor.test.mjs +++ b/tools/priority/__tests__/runtime-supervisor.test.mjs @@ -3703,6 +3703,81 @@ test('comparevi canonical execution delegates to the delivery broker instead of assert.equal(execution.details.actionType, 'execute-coding-turn'); }); +test('comparevi canonical execution fails closed when treasury denies core delivery', async () => { + let brokerCalled = false; + const execution = await compareviRuntimeTest.executeCompareviTurn({ + options: { + repo: 'LabVIEW-Community-CI-CD/compare-vi-cli-action' + }, + env: { + AGENT_PRIORITY_UPSTREAM_REPOSITORY: 'LabVIEW-Community-CI-CD/compare-vi-cli-action' + }, + repoRoot: '/tmp/repo', + repository: 'LabVIEW-Community-CI-CD/compare-vi-cli-action', + schedulerDecision: { + activeLane: { + laneId: 'origin-1012', + issue: 1012, + forkRemote: 'origin', + branch: 'issue/origin-1012-wire-canonical-delivery-broker' + }, + artifacts: { + standingRepository: 'LabVIEW-Community-CI-CD/compare-vi-cli-action', + standingIssueNumber: 1010, + laneLifecycle: 'coding', + selectedActionType: 'advance-child-issue' + } + }, + taskPacket: { + repository: 'LabVIEW-Community-CI-CD/compare-vi-cli-action', + objective: { summary: 'Advance issue #1012' }, + evidence: { + delivery: { + laneLifecycle: 'coding', + selectedActionType: 'advance-child-issue', + planeTransition: { + from: 'origin', + to: 'upstream', + action: 'promote', + via: 'pull-request', + branchClass: 'lane', + sourceRepository: 'labview-community-ci-cd/compare-vi-cli-action-fork', + targetRepository: 'labview-community-ci-cd/compare-vi-cli-action' + } + } + } + }, + taskPacketArtifacts: { + latestPath: '/tmp/repo/tests/results/_agent/runtime/task-packet.json' + }, + runtimeArtifactPaths: { + runtimeDir: '/tmp/repo/tests/results/_agent/runtime' + }, + deps: { + runTreasuryOperationGuardFn: () => ({ + outputPath: '/tmp/repo/tests/results/_agent/cost/treasury-control-plane.json', + decision: { + allowed: false, + code: 'treasury-operation-denied', + reason: 'Treasury denied core-delivery: reserve-protected-only.' + } + }), + invokeDeliveryTurnBrokerFn: async () => { + brokerCalled = true; + return { + status: 'completed', + outcome: 'coding-command-finished' + }; + } + } + }); + + assert.equal(execution.status, 'blocked'); + assert.equal(execution.outcome, 'treasury-core-delivery-denied'); + assert.equal(execution.details.treasuryDecisionCode, 'treasury-operation-denied'); + assert.equal(brokerCalled, false); +}); + test('comparevi runtime executes repo-context pivot when queue-empty portfolio handoff targets canonical template', async () => { const runtimeDir = await mkdtemp(path.join(os.tmpdir(), 'comparevi-runtime-portfolio-pivot-')); const execution = await compareviRuntimeTest.executeCompareviTurn({ diff --git a/tools/priority/__tests__/treasury-control-plane-schema.test.mjs b/tools/priority/__tests__/treasury-control-plane-schema.test.mjs new file mode 100644 index 000000000..2ae656371 --- /dev/null +++ b/tools/priority/__tests__/treasury-control-plane-schema.test.mjs @@ -0,0 +1,124 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; + +import { Ajv2020 } from 'ajv/dist/2020.js'; +import addFormats from 'ajv-formats'; + +import { runTreasuryControlPlane } from '../treasury-control-plane.mjs'; + +const repoRoot = path.resolve(process.cwd()); + +function readJson(filePath) { + return JSON.parse(fs.readFileSync(filePath, 'utf8')); +} + +function writeJson(filePath, payload) { + fs.mkdirSync(path.dirname(filePath), { recursive: true }); + fs.writeFileSync(filePath, `${JSON.stringify(payload, null, 2)}\n`, 'utf8'); +} + +test('treasury-control-plane policy and report validate against checked-in schemas', () => { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'treasury-control-plane-schema-')); + const repo = path.join(tempDir, 'repo'); + const policyPath = path.join(repo, 'tools', 'policy', 'treasury-control-plane.json'); + + writeJson(policyPath, { + schema: 'priority/treasury-control-plane-policy@v2', + costRollupPath: 'tests/results/_agent/cost/agent-cost-rollup.json', + materializationPolicyPath: 'tools/policy/agent-cost-rollup-materialization.json', + materializationReportPath: 'tests/results/_agent/cost/agent-cost-rollup-materialization.json', + outputPath: 'tests/results/_agent/cost/treasury-control-plane.json', + operatorBudgetCapUsd: 50000, + materializeCostRollup: true, + reservedFundingPurposes: ['calibration'], + reservedActivationStates: ['hold'], + thresholds: { + accountBalanceMaxAgeHours: 24, + reserveNearOperationalHeadroomUsd: 100, + healthyOperationalHeadroomUsd: 250, + premiumSaganMinimumOperationalHeadroomUsd: 150, + backgroundFanoutMinimumOperationalHeadroomUsd: 125, + nonEssentialWorkMinimumOperationalHeadroomUsd: 100 + }, + limits: { + healthyBackgroundSubagentsMax: 2, + cautiousBackgroundSubagentsMax: 1, + premiumSaganFollowupAuthorizationsEstimate: 1 + } + }); + + const { report } = runTreasuryControlPlane( + { + repoRoot: repo, + policyPath + }, + { + runMaterializeAgentCostRollupFn: ({ costRollupPath, outputPath }) => { + writeJson(costRollupPath, { + schema: 'priority/agent-cost-rollup@v1', + repository: 'LabVIEW-Community-CI-CD/compare-vi-cli-action', + summary: { + metrics: { + totalTurns: 1, + liveTurnCount: 1, + backgroundTurnCount: 0, + totalUsd: 1.5, + operatorLaborUsd: 4, + operatorLaborMissingTurnCount: 0, + blendedTotalUsd: 5.5, + estimatedPrepaidUsdRemaining: 398.5, + accountBalanceTotalCredits: 28750, + accountBalanceUsedCredits: 18750, + accountBalanceRemainingCredits: 10000 + }, + provenance: { + operatorProfiles: [{ operatorProfilePath: 'tools/policy/operator-cost-profile.json' }], + invoiceTurn: { + unitPriceUsd: 0.04 + }, + accountBalance: { + snapshotAt: '2026-03-24T08:00:00.000Z', + sourceKind: 'operator-account-state', + sourcePathEvidence: 'operator-account-state.json', + operatorNote: 'Latest operator-provided balance snapshot.' + }, + invoiceTurns: [ + { + invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0027', + invoiceId: 'HQ1VJLMV-0027', + fundingPurpose: 'operational', + activationState: 'active', + prepaidUsd: 400, + operatorNote: 'Operational window.' + } + ] + } + }, + billingWindow: { + invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0027', + invoiceId: 'HQ1VJLMV-0027', + fundingPurpose: 'operational', + activationState: 'active', + prepaidUsd: 400, + pricingBasis: 'prepaid-credit', + selection: { mode: 'hold', reason: null } + } + }); + writeJson(outputPath, { schema: 'priority/agent-cost-rollup-materialization@v1', summary: { status: 'pass' } }); + return { costRollupPath, outputPath }; + }, + now: new Date('2026-03-24T12:00:00.000Z') + } + ); + + const ajv = new Ajv2020({ allErrors: true, strict: false }); + addFormats(ajv); + const validatePolicy = ajv.compile(readJson(path.join(repoRoot, 'docs', 'schemas', 'treasury-control-plane-policy-v2.schema.json'))); + const validateReport = ajv.compile(readJson(path.join(repoRoot, 'docs', 'schemas', 'treasury-control-plane-report-v2.schema.json'))); + + assert.equal(validatePolicy(readJson(policyPath)), true, JSON.stringify(validatePolicy.errors, null, 2)); + assert.equal(validateReport(report), true, JSON.stringify(validateReport.errors, null, 2)); +}); diff --git a/tools/priority/__tests__/treasury-control-plane.test.mjs b/tools/priority/__tests__/treasury-control-plane.test.mjs new file mode 100644 index 000000000..ec66ab2c9 --- /dev/null +++ b/tools/priority/__tests__/treasury-control-plane.test.mjs @@ -0,0 +1,416 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; + +import { + TREASURY_OPERATION, + evaluateTreasuryOperation, + runTreasuryControlPlane, + runTreasuryOperationGuard +} from '../treasury-control-plane.mjs'; + +function writeJson(filePath, payload) { + fs.mkdirSync(path.dirname(filePath), { recursive: true }); + fs.writeFileSync(filePath, `${JSON.stringify(payload, null, 2)}\n`, 'utf8'); +} + +function createRollupFixture({ operatorLaborMissingTurnCount = 1 } = {}) { + return { + schema: 'priority/agent-cost-rollup@v1', + repository: 'LabVIEW-Community-CI-CD/compare-vi-cli-action', + summary: { + metrics: { + totalTurns: 3, + liveTurnCount: 1, + backgroundTurnCount: 2, + totalUsd: 12.5, + operatorLaborUsd: 30, + operatorLaborMissingTurnCount, + blendedTotalUsd: null, + estimatedPrepaidUsdRemaining: 387.5, + accountBalanceTotalCredits: 28750, + accountBalanceUsedCredits: 24600, + accountBalanceRemainingCredits: 4150 + }, + provenance: { + operatorProfiles: [ + { + operatorProfilePath: 'tools/policy/operator-cost-profile.json' + } + ], + invoiceTurn: { + unitPriceUsd: 0.04 + }, + accountBalance: { + snapshotAt: '2026-03-24T08:00:00.000Z', + sourceKind: 'operator-account-state', + sourcePathEvidence: 'operator-account-state.json', + operatorNote: 'Latest operator-provided balance snapshot.' + }, + invoiceTurns: [ + { + invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0027', + invoiceId: 'HQ1VJLMV-0027', + fundingPurpose: 'operational', + activationState: 'active', + prepaidUsd: 400, + operatorNote: 'Operational window.' + }, + { + invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0028', + invoiceId: 'HQ1VJLMV-0028', + fundingPurpose: 'calibration', + activationState: 'hold', + prepaidUsd: 100, + operatorNote: 'Reserved calibration window.' + } + ] + } + }, + billingWindow: { + invoiceTurnId: 'invoice-turn-2026-03-HQ1VJLMV-0027', + invoiceId: 'HQ1VJLMV-0027', + fundingPurpose: 'operational', + activationState: 'active', + prepaidUsd: 400, + pricingBasis: 'prepaid-credit', + selection: { + mode: 'hold', + reason: 'Calibration funding window remains on hold before activation.' + } + } + }; +} + +test('runTreasuryControlPlane produces a governed lower-bound treasury state when operator timing is incomplete', () => { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'treasury-control-plane-')); + const repoRoot = path.join(tempDir, 'repo'); + fs.mkdirSync(repoRoot, { recursive: true }); + + const policyPath = path.join(repoRoot, 'tools', 'policy', 'treasury-control-plane.json'); + writeJson(policyPath, { + schema: 'priority/treasury-control-plane-policy@v2', + costRollupPath: 'tests/results/_agent/cost/agent-cost-rollup.json', + materializationPolicyPath: 'tools/policy/agent-cost-rollup-materialization.json', + materializationReportPath: 'tests/results/_agent/cost/agent-cost-rollup-materialization.json', + outputPath: 'tests/results/_agent/cost/treasury-control-plane.json', + operatorBudgetCapUsd: 50000, + materializeCostRollup: true, + reservedFundingPurposes: ['calibration'], + reservedActivationStates: ['hold'], + thresholds: { + accountBalanceMaxAgeHours: 24, + reserveNearOperationalHeadroomUsd: 100, + healthyOperationalHeadroomUsd: 250, + premiumSaganMinimumOperationalHeadroomUsd: 150, + backgroundFanoutMinimumOperationalHeadroomUsd: 125, + nonEssentialWorkMinimumOperationalHeadroomUsd: 100 + }, + limits: { + healthyBackgroundSubagentsMax: 2, + cautiousBackgroundSubagentsMax: 1, + premiumSaganFollowupAuthorizationsEstimate: 1 + } + }); + + const result = runTreasuryControlPlane( + { + repoRoot, + policyPath + }, + { + runMaterializeAgentCostRollupFn: ({ costRollupPath, outputPath }) => { + writeJson(costRollupPath, createRollupFixture()); + writeJson(outputPath, { + schema: 'priority/agent-cost-rollup-materialization@v1', + summary: { status: 'pass' } + }); + return { + costRollupPath, + outputPath + }; + } + , + now: new Date('2026-03-24T12:00:00.000Z') + } + ); + + assert.equal(result.report.summary.status, 'warn'); + assert.equal(result.report.summary.confidence, 'lower-bound-only'); + assert.equal(result.report.summary.spendPolicyState, 'core-delivery-only'); + assert.equal(result.report.summary.budgetPressureState, 'tight'); + assert.equal(result.report.summary.protectedReserveUsd, 100); + assert.equal(result.report.summary.accountRemainingUsdEstimate, 166); + assert.equal(result.report.summary.operationalHeadroomUsd, 66); + assert.equal(result.report.summary.safeSpendableUsd, 66); + assert.equal(result.report.summary.operatorBudgetObservedRemainingUpperBoundUsd, 49970); + assert.equal(result.report.summary.operatorBudgetObservedRemainingStatus, 'upper-bound'); + assert.equal(result.report.summary.operatorBudgetRemainingLowerBoundUsd, null); + assert.equal(result.report.summary.operatorBudgetRemainingStatus, 'unknown'); + assert.equal(result.report.summary.operatorBudgetSpendableUsd, null); + assert.equal(result.report.summary.operatorBudgetSpendableStatus, 'unreconciled'); + assert.equal(result.report.summary.coreDeliveryAllowed, true); + assert.equal(result.report.summary.queueAuthorityAllowed, true); + assert.equal(result.report.summary.releaseApplyAllowed, true); + assert.equal(result.report.summary.premiumSaganAllowed, false); + assert.equal(result.report.summary.premiumAuthorizationPromptRequired, true); + assert.equal(result.report.summary.premiumAuthorizationFollowupEstimate, 1); + assert.equal(result.report.summary.backgroundFanoutAllowed, false); + assert.equal(result.report.summary.maxBackgroundSubagents, 0); + assert.equal(result.report.summary.nonEssentialWorkAllowed, false); + assert.equal(result.report.controls.premiumSaganMode.requiresOperatorAuthorization, true); + assert.equal(result.report.controls.premiumSaganMode.requiresExplicitOperatorPrompt, true); + assert.equal(result.report.controls.operations['core-delivery'].allowed, true); + assert.equal(result.report.controls.operations['queue-authority'].allowed, true); + assert.equal(result.report.controls.operations['release-apply'].allowed, true); + assert.equal(result.report.controls.operations['background-fanout'].allowed, false); + assert.equal(result.report.controls.operations['non-essential-work'].allowed, false); + assert.equal(result.report.controls.operations['premium-sagan'].allowed, false); + assert.equal(result.report.funding.reservedFunding.totalReservedUsd, 100); +}); + +test('runTreasuryControlPlane allows healthier expansion only when operator timing is fully observed', () => { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'treasury-control-plane-healthy-')); + const repoRoot = path.join(tempDir, 'repo'); + fs.mkdirSync(repoRoot, { recursive: true }); + + const policyPath = path.join(repoRoot, 'tools', 'policy', 'treasury-control-plane.json'); + writeJson(policyPath, { + schema: 'priority/treasury-control-plane-policy@v2', + costRollupPath: 'tests/results/_agent/cost/agent-cost-rollup.json', + materializationPolicyPath: 'tools/policy/agent-cost-rollup-materialization.json', + materializationReportPath: 'tests/results/_agent/cost/agent-cost-rollup-materialization.json', + outputPath: 'tests/results/_agent/cost/treasury-control-plane.json', + operatorBudgetCapUsd: 50000, + materializeCostRollup: true, + reservedFundingPurposes: ['calibration'], + reservedActivationStates: ['hold'], + thresholds: { + accountBalanceMaxAgeHours: 24, + reserveNearOperationalHeadroomUsd: 100, + healthyOperationalHeadroomUsd: 250, + premiumSaganMinimumOperationalHeadroomUsd: 150, + backgroundFanoutMinimumOperationalHeadroomUsd: 125, + nonEssentialWorkMinimumOperationalHeadroomUsd: 100 + }, + limits: { + healthyBackgroundSubagentsMax: 2, + cautiousBackgroundSubagentsMax: 1, + premiumSaganFollowupAuthorizationsEstimate: 1 + } + }); + + const result = runTreasuryControlPlane( + { + repoRoot, + policyPath + }, + { + runMaterializeAgentCostRollupFn: ({ costRollupPath, outputPath }) => { + const rollup = createRollupFixture({ operatorLaborMissingTurnCount: 0 }); + rollup.summary.metrics.accountBalanceRemainingCredits = 10000; + writeJson(costRollupPath, rollup); + writeJson(outputPath, { + schema: 'priority/agent-cost-rollup-materialization@v1', + summary: { status: 'pass' } + }); + return { + costRollupPath, + outputPath + }; + } + , + now: new Date('2026-03-24T12:00:00.000Z') + } + ); + + assert.equal(result.report.summary.status, 'pass'); + assert.equal(result.report.summary.confidence, 'observed'); + assert.equal(result.report.summary.budgetPressureState, 'healthy'); + assert.equal(result.report.summary.spendPolicyState, 'healthy'); + assert.equal(result.report.summary.operationalHeadroomUsd, 300); + assert.equal(result.report.summary.safeSpendableUsd, 300); + assert.equal(result.report.summary.operatorBudgetRemainingLowerBoundUsd, 49970); + assert.equal(result.report.summary.operatorBudgetRemainingStatus, 'observed'); + assert.equal(result.report.summary.operatorBudgetSpendableUsd, 49970); + assert.equal(result.report.summary.operatorBudgetSpendableStatus, 'observed'); + assert.equal(result.report.summary.premiumSaganAllowed, true); + assert.equal(result.report.summary.backgroundFanoutAllowed, true); + assert.equal(result.report.summary.maxBackgroundSubagents, 2); + assert.equal(result.report.summary.nonEssentialWorkAllowed, true); +}); + +test('runTreasuryOperationGuard allows core delivery but denies premium and fanout under tight lower-bound-only posture', () => { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'treasury-operation-guard-')); + const repoRoot = path.join(tempDir, 'repo'); + fs.mkdirSync(repoRoot, { recursive: true }); + + const policyPath = path.join(repoRoot, 'tools', 'policy', 'treasury-control-plane.json'); + writeJson(policyPath, { + schema: 'priority/treasury-control-plane-policy@v2', + costRollupPath: 'tests/results/_agent/cost/agent-cost-rollup.json', + materializationPolicyPath: 'tools/policy/agent-cost-rollup-materialization.json', + materializationReportPath: 'tests/results/_agent/cost/agent-cost-rollup-materialization.json', + outputPath: 'tests/results/_agent/cost/treasury-control-plane.json', + operatorBudgetCapUsd: 50000, + materializeCostRollup: true, + reservedFundingPurposes: ['calibration'], + reservedActivationStates: ['hold'], + thresholds: { + accountBalanceMaxAgeHours: 24, + reserveNearOperationalHeadroomUsd: 100, + healthyOperationalHeadroomUsd: 250, + premiumSaganMinimumOperationalHeadroomUsd: 150, + backgroundFanoutMinimumOperationalHeadroomUsd: 125, + nonEssentialWorkMinimumOperationalHeadroomUsd: 100 + }, + limits: { + healthyBackgroundSubagentsMax: 2, + cautiousBackgroundSubagentsMax: 1, + premiumSaganFollowupAuthorizationsEstimate: 2 + } + }); + + const makeGuard = (operation) => + runTreasuryOperationGuard( + { + repoRoot, + policyPath, + operation + }, + { + runTreasuryControlPlaneFn: ({ repoRoot: guardRepoRoot, policyPath: guardPolicyPath }) => + runTreasuryControlPlane( + { + repoRoot: guardRepoRoot, + policyPath: guardPolicyPath + }, + { + runMaterializeAgentCostRollupFn: ({ costRollupPath, outputPath }) => { + writeJson(costRollupPath, createRollupFixture()); + writeJson(outputPath, { + schema: 'priority/agent-cost-rollup-materialization@v1', + summary: { status: 'pass' } + }); + return { + costRollupPath, + outputPath + }; + } + , + now: new Date('2026-03-24T12:00:00.000Z') + } + ) + } + ); + + const coreDelivery = makeGuard(TREASURY_OPERATION.CORE_DELIVERY); + const queueAuthority = makeGuard(TREASURY_OPERATION.QUEUE_AUTHORITY); + const releaseApply = makeGuard(TREASURY_OPERATION.RELEASE_APPLY); + const backgroundFanout = makeGuard(TREASURY_OPERATION.BACKGROUND_FANOUT); + const premiumSagan = makeGuard(TREASURY_OPERATION.PREMIUM_SAGAN); + + assert.equal(coreDelivery.decision.allowed, true); + assert.equal(queueAuthority.decision.allowed, true); + assert.equal(releaseApply.decision.allowed, true); + assert.equal(backgroundFanout.decision.allowed, false); + assert.equal(premiumSagan.decision.allowed, false); + assert.equal(premiumSagan.decision.authorization.requiresOperatorAuthorization, true); + assert.equal(premiumSagan.decision.authorization.requiresExplicitOperatorPrompt, true); + assert.equal(premiumSagan.decision.authorization.estimatedFollowupAuthorizationsNeeded, 2); +}); + +test('runTreasuryControlPlane blocks automation when account-balance evidence is stale', () => { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'treasury-control-plane-stale-balance-')); + const repoRoot = path.join(tempDir, 'repo'); + fs.mkdirSync(repoRoot, { recursive: true }); + + const policyPath = path.join(repoRoot, 'tools', 'policy', 'treasury-control-plane.json'); + writeJson(policyPath, { + schema: 'priority/treasury-control-plane-policy@v2', + costRollupPath: 'tests/results/_agent/cost/agent-cost-rollup.json', + materializationPolicyPath: 'tools/policy/agent-cost-rollup-materialization.json', + materializationReportPath: 'tests/results/_agent/cost/agent-cost-rollup-materialization.json', + outputPath: 'tests/results/_agent/cost/treasury-control-plane.json', + operatorBudgetCapUsd: 50000, + materializeCostRollup: true, + reservedFundingPurposes: ['calibration'], + reservedActivationStates: ['hold'], + thresholds: { + accountBalanceMaxAgeHours: 24, + reserveNearOperationalHeadroomUsd: 100, + healthyOperationalHeadroomUsd: 250, + premiumSaganMinimumOperationalHeadroomUsd: 150, + backgroundFanoutMinimumOperationalHeadroomUsd: 125, + nonEssentialWorkMinimumOperationalHeadroomUsd: 100 + }, + limits: { + healthyBackgroundSubagentsMax: 2, + cautiousBackgroundSubagentsMax: 1, + premiumSaganFollowupAuthorizationsEstimate: 1 + } + }); + + const result = runTreasuryControlPlane( + { + repoRoot, + policyPath + }, + { + runMaterializeAgentCostRollupFn: ({ costRollupPath, outputPath }) => { + const rollup = createRollupFixture(); + rollup.summary.provenance.accountBalance.snapshotAt = '2026-03-21T12:00:00.000Z'; + writeJson(costRollupPath, rollup); + writeJson(outputPath, { + schema: 'priority/agent-cost-rollup-materialization@v1', + summary: { status: 'pass' } + }); + return { + costRollupPath, + outputPath + }; + }, + now: new Date('2026-03-24T16:00:00.000Z') + } + ); + + assert.equal(result.report.summary.status, 'blocked'); + assert.equal(result.report.summary.recommendation, 'repair-treasury-inputs'); + assert.equal(result.report.summary.confidence, 'blocked'); + assert.equal(result.report.summary.safeSpendableUsd, 0); + assert.equal(result.report.summary.coreDeliveryAllowed, false); + assert.equal(result.report.summary.queueAuthorityAllowed, false); + assert.equal(result.report.summary.releaseApplyAllowed, false); + assert.match( + result.report.blockers.map((entry) => entry.code).join('\n'), + /account-balance-stale/ + ); +}); + +test('evaluateTreasuryOperation fails closed when only reserve funding remains', () => { + const report = { + schema: 'priority/treasury-control-plane@v2', + controls: { + operations: { + 'core-delivery': { allowed: false, reason: 'policy-reserve-protected-only' }, + 'queue-authority': { allowed: false, reason: 'policy-reserve-protected-only' }, + 'release-apply': { allowed: false, reason: 'policy-reserve-protected-only' }, + 'background-fanout': { allowed: false, reason: 'budget-stop-nonessential-spend' }, + 'non-essential-work': { allowed: false, reason: 'budget-stop-nonessential-spend' }, + 'premium-sagan': { + allowed: false, + reason: 'budget-stop-nonessential-spend', + requiresOperatorAuthorization: true, + requiresExplicitOperatorPrompt: true, + estimatedFollowupAuthorizationsNeeded: 1 + } + } + } + }; + + const decision = evaluateTreasuryOperation(report, TREASURY_OPERATION.CORE_DELIVERY); + assert.equal(decision.allowed, false); + assert.equal(decision.code, 'treasury-operation-denied'); +}); diff --git a/tools/priority/autonomous-governor-portfolio-summary.mjs b/tools/priority/autonomous-governor-portfolio-summary.mjs index 9fb30013c..c7f7e4a0d 100644 --- a/tools/priority/autonomous-governor-portfolio-summary.mjs +++ b/tools/priority/autonomous-governor-portfolio-summary.mjs @@ -365,6 +365,97 @@ function deriveExecutionTopology(compareGovernorSummary) { }; } +function deriveTreasury(compareGovernorSummary) { + const treasury = compareGovernorSummary?.compare?.treasury; + if (treasury && typeof treasury === 'object' && !Array.isArray(treasury)) { + return { + status: asOptional(treasury.status) || 'missing', + confidence: asOptional(treasury.confidence) || 'unknown', + spendPolicyState: asOptional(treasury.spendPolicyState) || 'blocked', + budgetPressureState: asOptional(treasury.budgetPressureState) || 'cautious', + protectedReserveUsd: Number.isFinite(treasury.protectedReserveUsd) ? treasury.protectedReserveUsd : null, + accountRemainingUsdEstimate: Number.isFinite(treasury.accountRemainingUsdEstimate) + ? treasury.accountRemainingUsdEstimate + : null, + operationalHeadroomUsd: Number.isFinite(treasury.operationalHeadroomUsd) ? treasury.operationalHeadroomUsd : null, + safeSpendableUsd: Number.isFinite(treasury.safeSpendableUsd) ? treasury.safeSpendableUsd : null, + possibleSpendableUpperBoundUsd: Number.isFinite(treasury.possibleSpendableUpperBoundUsd) + ? treasury.possibleSpendableUpperBoundUsd + : null, + operatorBudgetObservedRemainingUpperBoundUsd: Number.isFinite( + treasury.operatorBudgetObservedRemainingUpperBoundUsd + ) + ? treasury.operatorBudgetObservedRemainingUpperBoundUsd + : null, + operatorBudgetObservedRemainingStatus: + asOptional(treasury.operatorBudgetObservedRemainingStatus) || 'unknown', + operatorBudgetSpendableStatus: asOptional(treasury.operatorBudgetSpendableStatus) || 'unknown', + coreDeliveryAllowed: treasury.coreDeliveryAllowed === true, + queueAuthorityAllowed: treasury.queueAuthorityAllowed === true, + releaseApplyAllowed: treasury.releaseApplyAllowed === true, + premiumSaganAllowed: treasury.premiumSaganAllowed === true, + premiumAuthorizationPromptRequired: treasury.premiumAuthorizationPromptRequired === true, + premiumAuthorizationFollowupEstimate: Number.isInteger(treasury.premiumAuthorizationFollowupEstimate) + ? treasury.premiumAuthorizationFollowupEstimate + : 0, + backgroundFanoutAllowed: treasury.backgroundFanoutAllowed === true, + maxBackgroundSubagents: Number.isInteger(treasury.maxBackgroundSubagents) + ? treasury.maxBackgroundSubagents + : 0, + nonEssentialWorkAllowed: treasury.nonEssentialWorkAllowed === true + }; + } + + return { + status: asOptional(compareGovernorSummary?.summary?.treasuryStatus) || 'missing', + confidence: asOptional(compareGovernorSummary?.summary?.treasuryConfidence) || 'unknown', + spendPolicyState: asOptional(compareGovernorSummary?.summary?.treasurySpendPolicyState) || 'blocked', + budgetPressureState: asOptional(compareGovernorSummary?.summary?.treasuryBudgetPressureState) || 'cautious', + protectedReserveUsd: Number.isFinite(compareGovernorSummary?.summary?.treasuryProtectedReserveUsd) + ? compareGovernorSummary.summary.treasuryProtectedReserveUsd + : null, + accountRemainingUsdEstimate: Number.isFinite(compareGovernorSummary?.summary?.treasuryAccountRemainingUsdEstimate) + ? compareGovernorSummary.summary.treasuryAccountRemainingUsdEstimate + : null, + operationalHeadroomUsd: Number.isFinite(compareGovernorSummary?.summary?.treasuryOperationalHeadroomUsd) + ? compareGovernorSummary.summary.treasuryOperationalHeadroomUsd + : null, + safeSpendableUsd: Number.isFinite(compareGovernorSummary?.summary?.treasurySafeSpendableUsd) + ? compareGovernorSummary.summary.treasurySafeSpendableUsd + : null, + possibleSpendableUpperBoundUsd: Number.isFinite( + compareGovernorSummary?.summary?.treasuryPossibleSpendableUpperBoundUsd + ) + ? compareGovernorSummary.summary.treasuryPossibleSpendableUpperBoundUsd + : null, + operatorBudgetObservedRemainingUpperBoundUsd: Number.isFinite( + compareGovernorSummary?.summary?.treasuryOperatorBudgetObservedRemainingUpperBoundUsd + ) + ? compareGovernorSummary.summary.treasuryOperatorBudgetObservedRemainingUpperBoundUsd + : null, + operatorBudgetObservedRemainingStatus: + asOptional(compareGovernorSummary?.summary?.treasuryOperatorBudgetObservedRemainingStatus) || 'unknown', + operatorBudgetSpendableStatus: + asOptional(compareGovernorSummary?.summary?.treasuryOperatorBudgetSpendableStatus) || 'unknown', + coreDeliveryAllowed: compareGovernorSummary?.summary?.treasuryCoreDeliveryAllowed === true, + queueAuthorityAllowed: compareGovernorSummary?.summary?.treasuryQueueAuthorityAllowed === true, + releaseApplyAllowed: compareGovernorSummary?.summary?.treasuryReleaseApplyAllowed === true, + premiumSaganAllowed: compareGovernorSummary?.summary?.treasuryPremiumSaganAllowed === true, + premiumAuthorizationPromptRequired: + compareGovernorSummary?.summary?.treasuryPremiumAuthorizationPromptRequired === true, + premiumAuthorizationFollowupEstimate: Number.isInteger( + compareGovernorSummary?.summary?.treasuryPremiumAuthorizationFollowupEstimate + ) + ? compareGovernorSummary.summary.treasuryPremiumAuthorizationFollowupEstimate + : 0, + backgroundFanoutAllowed: compareGovernorSummary?.summary?.treasuryBackgroundFanoutAllowed === true, + maxBackgroundSubagents: Number.isInteger(compareGovernorSummary?.summary?.treasuryMaxBackgroundSubagents) + ? compareGovernorSummary.summary.treasuryMaxBackgroundSubagents + : 0, + nonEssentialWorkAllowed: compareGovernorSummary?.summary?.treasuryNonEssentialWorkAllowed === true + }; +} + function deriveOwners(compareGovernorSummary, monitoringMode, portfolioMode, viHistoryDistributorDependency) { const compareRepository = asOptional(compareGovernorSummary?.summary?.currentOwnerRepository) || @@ -539,6 +630,7 @@ function buildReport({ ? monitoringMode.summary.triggeredWakeConditions : []; const executionTopology = deriveExecutionTopology(compareGovernorSummary); + const treasury = deriveTreasury(compareGovernorSummary); return { schema: 'priority/autonomous-governor-portfolio-summary-report@v1', @@ -562,6 +654,7 @@ function buildReport({ queueHandoffNextWakeCondition: asOptional(compareGovernorSummary?.summary?.queueHandoffNextWakeCondition), queueHandoffPrUrl: asOptional(compareGovernorSummary?.summary?.queueHandoffPrUrl), queueAuthoritySource: asOptional(compareGovernorSummary?.summary?.queueAuthoritySource), + treasury, executionTopology, executionBundleStatus: asOptional(compareGovernorSummary?.summary?.executionBundleStatus), executionBundlePlaneBinding: asOptional(compareGovernorSummary?.summary?.executionBundlePlaneBinding), @@ -572,7 +665,28 @@ function buildReport({ compareGovernorSummary?.summary?.executionBundleEffectiveBillableRateUsdPerHour ) ? compareGovernorSummary.summary.executionBundleEffectiveBillableRateUsdPerHour - : null + : null, + treasuryStatus: treasury.status, + treasuryConfidence: treasury.confidence, + treasurySpendPolicyState: treasury.spendPolicyState, + treasuryBudgetPressureState: treasury.budgetPressureState, + treasuryProtectedReserveUsd: treasury.protectedReserveUsd, + treasuryAccountRemainingUsdEstimate: treasury.accountRemainingUsdEstimate, + treasuryOperationalHeadroomUsd: treasury.operationalHeadroomUsd, + treasurySafeSpendableUsd: treasury.safeSpendableUsd, + treasuryPossibleSpendableUpperBoundUsd: treasury.possibleSpendableUpperBoundUsd, + treasuryOperatorBudgetObservedRemainingUpperBoundUsd: treasury.operatorBudgetObservedRemainingUpperBoundUsd, + treasuryOperatorBudgetObservedRemainingStatus: treasury.operatorBudgetObservedRemainingStatus, + treasuryOperatorBudgetSpendableStatus: treasury.operatorBudgetSpendableStatus, + treasuryCoreDeliveryAllowed: treasury.coreDeliveryAllowed, + treasuryQueueAuthorityAllowed: treasury.queueAuthorityAllowed, + treasuryReleaseApplyAllowed: treasury.releaseApplyAllowed, + treasuryPremiumSaganAllowed: treasury.premiumSaganAllowed, + treasuryPremiumAuthorizationPromptRequired: treasury.premiumAuthorizationPromptRequired, + treasuryPremiumAuthorizationFollowupEstimate: treasury.premiumAuthorizationFollowupEstimate, + treasuryBackgroundFanoutAllowed: treasury.backgroundFanoutAllowed, + treasuryMaxBackgroundSubagents: treasury.maxBackgroundSubagents, + treasuryNonEssentialWorkAllowed: treasury.nonEssentialWorkAllowed }, portfolio: { repositoryCount: repositoryEntries.length, @@ -623,6 +737,27 @@ function buildReport({ ) ? compareGovernorSummary.summary.executionBundleEffectiveBillableRateUsdPerHour : null, + treasuryStatus: treasury.status, + treasuryConfidence: treasury.confidence, + treasurySpendPolicyState: treasury.spendPolicyState, + treasuryBudgetPressureState: treasury.budgetPressureState, + treasuryProtectedReserveUsd: treasury.protectedReserveUsd, + treasuryAccountRemainingUsdEstimate: treasury.accountRemainingUsdEstimate, + treasuryOperationalHeadroomUsd: treasury.operationalHeadroomUsd, + treasurySafeSpendableUsd: treasury.safeSpendableUsd, + treasuryPossibleSpendableUpperBoundUsd: treasury.possibleSpendableUpperBoundUsd, + treasuryOperatorBudgetObservedRemainingUpperBoundUsd: treasury.operatorBudgetObservedRemainingUpperBoundUsd, + treasuryOperatorBudgetObservedRemainingStatus: treasury.operatorBudgetObservedRemainingStatus, + treasuryOperatorBudgetSpendableStatus: treasury.operatorBudgetSpendableStatus, + treasuryCoreDeliveryAllowed: treasury.coreDeliveryAllowed, + treasuryQueueAuthorityAllowed: treasury.queueAuthorityAllowed, + treasuryReleaseApplyAllowed: treasury.releaseApplyAllowed, + treasuryPremiumSaganAllowed: treasury.premiumSaganAllowed, + treasuryPremiumAuthorizationPromptRequired: treasury.premiumAuthorizationPromptRequired, + treasuryPremiumAuthorizationFollowupEstimate: treasury.premiumAuthorizationFollowupEstimate, + treasuryBackgroundFanoutAllowed: treasury.backgroundFanoutAllowed, + treasuryMaxBackgroundSubagents: treasury.maxBackgroundSubagents, + treasuryNonEssentialWorkAllowed: treasury.nonEssentialWorkAllowed, viHistoryDistributorDependencyStatus: viHistoryDistributorDependency.status, viHistoryDistributorDependencyTargetRepository: viHistoryDistributorDependency.dependentRepository, viHistoryDistributorDependencyExternalBlocker: viHistoryDistributorDependency.externalBlocker, diff --git a/tools/priority/autonomous-governor-summary.mjs b/tools/priority/autonomous-governor-summary.mjs index 556957acb..5669344b8 100644 --- a/tools/priority/autonomous-governor-summary.mjs +++ b/tools/priority/autonomous-governor-summary.mjs @@ -63,6 +63,13 @@ export const DEFAULT_RELEASE_SIGNING_READINESS_PATH = path.join( 'release', 'release-signing-readiness.json' ); +export const DEFAULT_TREASURY_CONTROL_PLANE_PATH = path.join( + 'tests', + 'results', + '_agent', + 'cost', + 'treasury-control-plane.json' +); function asOptional(value) { if (value == null) { @@ -531,6 +538,7 @@ export function parseArgs(argv = process.argv) { wakeInvestmentAccountingPath: DEFAULT_WAKE_INVESTMENT_ACCOUNTING_PATH, deliveryRuntimeStatePath: DEFAULT_DELIVERY_RUNTIME_STATE_PATH, releaseSigningReadinessPath: DEFAULT_RELEASE_SIGNING_READINESS_PATH, + treasuryControlPlanePath: DEFAULT_TREASURY_CONTROL_PLANE_PATH, outputPath: DEFAULT_OUTPUT_PATH, help: false }; @@ -544,6 +552,7 @@ export function parseArgs(argv = process.argv) { ['--wake-investment-accounting', 'wakeInvestmentAccountingPath'], ['--delivery-runtime-state', 'deliveryRuntimeStatePath'], ['--release-signing-readiness', 'releaseSigningReadinessPath'], + ['--treasury-control-plane', 'treasuryControlPlanePath'], ['--output', 'outputPath'] ]); @@ -581,6 +590,7 @@ function printHelp() { ` --wake-investment-accounting Wake investment accounting path (default: ${DEFAULT_WAKE_INVESTMENT_ACCOUNTING_PATH}).`, ` --delivery-runtime-state Delivery runtime state path (default: ${DEFAULT_DELIVERY_RUNTIME_STATE_PATH}).`, ` --release-signing-readiness Release signing readiness path (default: ${DEFAULT_RELEASE_SIGNING_READINESS_PATH}).`, + ` --treasury-control-plane Treasury control-plane path (default: ${DEFAULT_TREASURY_CONTROL_PLANE_PATH}).`, ` --output Output path (default: ${DEFAULT_OUTPUT_PATH}).`, ' -h, --help Show help.' ].forEach((line) => console.log(line)); @@ -672,6 +682,85 @@ function deriveFunding(wakeInvestmentAccounting) { }; } +function deriveTreasury(treasuryControlPlaneReport) { + if (treasuryControlPlaneReport?.schema !== 'priority/treasury-control-plane@v2') { + return { + status: 'missing', + confidence: 'unknown', + spendPolicyState: 'blocked', + budgetPressureState: 'cautious', + protectedReserveUsd: null, + accountRemainingUsdEstimate: null, + operationalHeadroomUsd: null, + safeSpendableUsd: null, + possibleSpendableUpperBoundUsd: null, + operatorBudgetObservedRemainingUpperBoundUsd: null, + operatorBudgetObservedRemainingStatus: 'unknown', + operatorBudgetSpendableStatus: 'unknown', + coreDeliveryAllowed: false, + queueAuthorityAllowed: false, + releaseApplyAllowed: false, + premiumSaganAllowed: false, + premiumAuthorizationPromptRequired: false, + premiumAuthorizationFollowupEstimate: 0, + backgroundFanoutAllowed: false, + maxBackgroundSubagents: 0, + nonEssentialWorkAllowed: false + }; + } + + return { + status: asOptional(treasuryControlPlaneReport?.summary?.status) || 'missing', + confidence: asOptional(treasuryControlPlaneReport?.summary?.confidence) || 'unknown', + spendPolicyState: asOptional(treasuryControlPlaneReport?.summary?.spendPolicyState) || 'blocked', + budgetPressureState: asOptional(treasuryControlPlaneReport?.summary?.budgetPressureState) || 'cautious', + protectedReserveUsd: + typeof treasuryControlPlaneReport?.summary?.protectedReserveUsd === 'number' + ? treasuryControlPlaneReport.summary.protectedReserveUsd + : null, + accountRemainingUsdEstimate: + typeof treasuryControlPlaneReport?.summary?.accountRemainingUsdEstimate === 'number' + ? treasuryControlPlaneReport.summary.accountRemainingUsdEstimate + : null, + operationalHeadroomUsd: + typeof treasuryControlPlaneReport?.summary?.operationalHeadroomUsd === 'number' + ? treasuryControlPlaneReport.summary.operationalHeadroomUsd + : null, + safeSpendableUsd: + typeof treasuryControlPlaneReport?.summary?.safeSpendableUsd === 'number' + ? treasuryControlPlaneReport.summary.safeSpendableUsd + : null, + possibleSpendableUpperBoundUsd: + typeof treasuryControlPlaneReport?.summary?.possibleSpendableUpperBoundUsd === 'number' + ? treasuryControlPlaneReport.summary.possibleSpendableUpperBoundUsd + : null, + operatorBudgetObservedRemainingUpperBoundUsd: + typeof treasuryControlPlaneReport?.summary?.operatorBudgetObservedRemainingUpperBoundUsd === 'number' + ? treasuryControlPlaneReport.summary.operatorBudgetObservedRemainingUpperBoundUsd + : null, + operatorBudgetObservedRemainingStatus: + asOptional(treasuryControlPlaneReport?.summary?.operatorBudgetObservedRemainingStatus) || 'unknown', + operatorBudgetSpendableStatus: + asOptional(treasuryControlPlaneReport?.summary?.operatorBudgetSpendableStatus) || 'unknown', + coreDeliveryAllowed: parseBoolean(treasuryControlPlaneReport?.summary?.coreDeliveryAllowed), + queueAuthorityAllowed: parseBoolean(treasuryControlPlaneReport?.summary?.queueAuthorityAllowed), + releaseApplyAllowed: parseBoolean(treasuryControlPlaneReport?.summary?.releaseApplyAllowed), + premiumSaganAllowed: parseBoolean(treasuryControlPlaneReport?.summary?.premiumSaganAllowed), + premiumAuthorizationPromptRequired: + parseBoolean(treasuryControlPlaneReport?.summary?.premiumAuthorizationPromptRequired), + premiumAuthorizationFollowupEstimate: Number.isInteger( + treasuryControlPlaneReport?.summary?.premiumAuthorizationFollowupEstimate + ) + ? treasuryControlPlaneReport.summary.premiumAuthorizationFollowupEstimate + : 0, + backgroundFanoutAllowed: parseBoolean(treasuryControlPlaneReport?.summary?.backgroundFanoutAllowed), + maxBackgroundSubagents: Number.isInteger(treasuryControlPlaneReport?.summary?.maxBackgroundSubagents) + ? treasuryControlPlaneReport.summary.maxBackgroundSubagents + : 0, + nonEssentialWorkAllowed: parseBoolean(treasuryControlPlaneReport?.summary?.nonEssentialWorkAllowed) + }; +} + function deriveReleaseSigningReadiness(releaseSigningReadinessReport) { if (releaseSigningReadinessReport?.schema !== 'priority/release-signing-readiness-report@v1') { return { @@ -1015,6 +1104,8 @@ function buildReport({ deliveryRuntimeState, releaseSigningReadinessPath, releaseSigningReadinessReport, + treasuryControlPlanePath, + treasuryControlPlaneReport, readOptionalJsonFn, now }) { @@ -1028,6 +1119,7 @@ function buildReport({ const continuity = deriveContinuity(continuitySummary, monitoringMode); const wake = deriveWake(wakeLifecycle); const funding = deriveFunding(wakeInvestmentAccounting); + const treasury = deriveTreasury(treasuryControlPlaneReport); const releaseSigningReadiness = deriveReleaseSigningReadiness(releaseSigningReadinessReport); const deliveryRuntime = deriveDeliveryRuntime(deliveryRuntimeState); const queueAuthority = deriveQueueAuthority({ @@ -1052,7 +1144,8 @@ function buildReport({ wakeLifecyclePath: toRelative(repoRoot, wakeLifecyclePath), wakeInvestmentAccountingPath: toRelative(repoRoot, wakeInvestmentAccountingPath), deliveryRuntimeStatePath: toRelative(repoRoot, deliveryRuntimeStatePath), - releaseSigningReadinessPath: toRelative(repoRoot, releaseSigningReadinessPath) + releaseSigningReadinessPath: toRelative(repoRoot, releaseSigningReadinessPath), + treasuryControlPlanePath: toRelative(repoRoot, treasuryControlPlanePath) }, compare: { queueState, @@ -1064,6 +1157,7 @@ function buildReport({ ? monitoringMode.summary.wakeConditionCount : null }, + treasury, releaseSigningReadiness, deliveryRuntime, queueAuthority @@ -1107,6 +1201,27 @@ function buildReport({ executionBundlePremiumSaganMode: deliveryRuntime.executionBundle.premiumSaganMode, executionBundleReciprocalLinkReady: deliveryRuntime.executionBundle.reciprocalLinkReady, executionBundleEffectiveBillableRateUsdPerHour: deliveryRuntime.executionBundle.effectiveBillableRateUsdPerHour, + treasuryStatus: treasury.status, + treasuryConfidence: treasury.confidence, + treasurySpendPolicyState: treasury.spendPolicyState, + treasuryBudgetPressureState: treasury.budgetPressureState, + treasuryProtectedReserveUsd: treasury.protectedReserveUsd, + treasuryAccountRemainingUsdEstimate: treasury.accountRemainingUsdEstimate, + treasuryOperationalHeadroomUsd: treasury.operationalHeadroomUsd, + treasurySafeSpendableUsd: treasury.safeSpendableUsd, + treasuryPossibleSpendableUpperBoundUsd: treasury.possibleSpendableUpperBoundUsd, + treasuryOperatorBudgetObservedRemainingUpperBoundUsd: treasury.operatorBudgetObservedRemainingUpperBoundUsd, + treasuryOperatorBudgetObservedRemainingStatus: treasury.operatorBudgetObservedRemainingStatus, + treasuryOperatorBudgetSpendableStatus: treasury.operatorBudgetSpendableStatus, + treasuryCoreDeliveryAllowed: treasury.coreDeliveryAllowed, + treasuryQueueAuthorityAllowed: treasury.queueAuthorityAllowed, + treasuryReleaseApplyAllowed: treasury.releaseApplyAllowed, + treasuryPremiumSaganAllowed: treasury.premiumSaganAllowed, + treasuryPremiumAuthorizationPromptRequired: treasury.premiumAuthorizationPromptRequired, + treasuryPremiumAuthorizationFollowupEstimate: treasury.premiumAuthorizationFollowupEstimate, + treasuryBackgroundFanoutAllowed: treasury.backgroundFanoutAllowed, + treasuryMaxBackgroundSubagents: treasury.maxBackgroundSubagents, + treasuryNonEssentialWorkAllowed: treasury.nonEssentialWorkAllowed, queueHandoffStatus: queueAuthority.status, queueHandoffNextWakeCondition: queueAuthority.nextWakeCondition, queueHandoffPrUrl: queueAuthority.prUrl, @@ -1133,6 +1248,10 @@ export async function runAutonomousGovernorSummary(options = {}, deps = {}) { repoRoot, options.releaseSigningReadinessPath || DEFAULT_RELEASE_SIGNING_READINESS_PATH ); + const treasuryControlPlanePath = path.resolve( + repoRoot, + options.treasuryControlPlanePath || DEFAULT_TREASURY_CONTROL_PLANE_PATH + ); const outputPath = path.resolve(repoRoot, options.outputPath || DEFAULT_OUTPUT_PATH); const readOptionalJsonFn = deps.readOptionalJsonFn || readOptionalJson; @@ -1146,6 +1265,7 @@ export async function runAutonomousGovernorSummary(options = {}, deps = {}) { const wakeInvestmentAccounting = readOptionalJsonFn(wakeInvestmentAccountingPath); const deliveryRuntimeState = readOptionalJsonFn(deliveryRuntimeStatePath); const releaseSigningReadinessReport = readOptionalJsonFn(releaseSigningReadinessPath); + const treasuryControlPlaneReport = readOptionalJsonFn(treasuryControlPlanePath); if (queueEmptyReport) { ensureSchema(queueEmptyReport, queueEmptyReportPath, 'standing-priority/no-standing@v1'); @@ -1172,6 +1292,13 @@ export async function runAutonomousGovernorSummary(options = {}, deps = {}) { 'priority/release-signing-readiness-report@v1' ); } + if (treasuryControlPlaneReport) { + ensureSchema( + treasuryControlPlaneReport, + treasuryControlPlanePath, + 'priority/treasury-control-plane@v2' + ); + } const report = buildReport({ repoRoot, @@ -1189,6 +1316,8 @@ export async function runAutonomousGovernorSummary(options = {}, deps = {}) { deliveryRuntimeState, releaseSigningReadinessPath, releaseSigningReadinessReport, + treasuryControlPlanePath, + treasuryControlPlaneReport, readOptionalJsonFn, now }); diff --git a/tools/priority/delivery-agent.mjs b/tools/priority/delivery-agent.mjs index ea95a71a4..929d7c676 100644 --- a/tools/priority/delivery-agent.mjs +++ b/tools/priority/delivery-agent.mjs @@ -17,6 +17,11 @@ import { DEFAULT_STATUS_OUTPUT_PATH as DEFAULT_CONCURRENT_LANE_STATUS_RECEIPT_PATH, observeConcurrentLaneStatus } from './concurrent-lane-status.mjs'; +import { + DEFAULT_POLICY_PATH as DEFAULT_TREASURY_POLICY_PATH, + TREASURY_OPERATION, + runTreasuryOperationGuard +} from './treasury-control-plane.mjs'; import { loadBranchClassContract, resolveBranchPlaneTransition } from './lib/branch-classification.mjs'; import { resolveRequiredLaneBranchPrefix } from './lib/runtime-lane-branch-contract.mjs'; import { @@ -5531,6 +5536,7 @@ export async function runDeliveryTurnBroker({ taskPacketPath = '', repoRoot, policyPath, + enforceTreasuryGuard = false, now = new Date(), deps = {} }) { @@ -5548,6 +5554,46 @@ export async function runDeliveryTurnBroker({ }; const executionRoot = resolveExecutionRoot(repoRoot, enrichedPacket); const planned = planDeliveryBrokerAction(enrichedPacket); + const treasuryPolicyPath = path.resolve(repoRoot, DEFAULT_TREASURY_POLICY_PATH); + const shouldRunTreasuryGuard = + typeof deps.runTreasuryOperationGuardFn === 'function' || enforceTreasuryGuard === true; + const guardBrokerOperation = (operation, actionType, outcome, nextWakeCondition = 'treasury-reconciled') => { + if (!shouldRunTreasuryGuard) { + return null; + } + const runTreasuryOperationGuardFn = deps.runTreasuryOperationGuardFn ?? runTreasuryOperationGuard; + const treasuryGuard = runTreasuryOperationGuardFn({ + repoRoot, + repo: normalizeText(taskPacket?.repository) || null, + policyPath: treasuryPolicyPath, + operation + }); + if (treasuryGuard?.decision?.allowed === true) { + return null; + } + return withWorkerProviderDispatch({ + status: 'blocked', + outcome, + reason: treasuryGuard?.decision?.reason || `Treasury denied ${operation}.`, + source: 'delivery-agent-broker', + details: { + actionType, + laneLifecycle: 'blocked', + blockerClass: 'budget', + retryable: true, + nextWakeCondition, + helperCallsExecuted: [], + filesTouched: [], + treasuryOperation: operation, + treasuryDecisionCode: treasuryGuard?.decision?.code || 'treasury-operation-denied', + operatorAuthorizationRequired: treasuryGuard?.decision?.authorization?.requiresOperatorAuthorization === true, + operatorAuthorizationPromptRequired: + treasuryGuard?.decision?.authorization?.requiresExplicitOperatorPrompt === true, + estimatedFollowupAuthorizationsNeeded: + Number(treasuryGuard?.decision?.authorization?.estimatedFollowupAuthorizationsNeeded ?? 0) || 0 + } + }, enrichedPacket); + }; if (planned.actionType === 'idle') { return withWorkerProviderDispatch({ @@ -5640,6 +5686,14 @@ export async function runDeliveryTurnBroker({ } if (planned.actionType === 'dispatch-concurrent-lanes') { + const treasuryDenied = guardBrokerOperation( + TREASURY_OPERATION.BACKGROUND_FANOUT, + 'dispatch-concurrent-lanes', + 'treasury-background-fanout-denied' + ); + if (treasuryDenied) { + return treasuryDenied; + } const dispatchResult = await dispatchConcurrentLanes({ taskPacket: enrichedPacket, repoRoot, @@ -5650,6 +5704,14 @@ export async function runDeliveryTurnBroker({ } if (planned.actionType === 'sync-pr-branch') { + const treasuryDenied = guardBrokerOperation( + TREASURY_OPERATION.CORE_DELIVERY, + 'sync-pr-branch', + 'treasury-core-delivery-denied' + ); + if (treasuryDenied) { + return treasuryDenied; + } return withWorkerProviderDispatch(await updatePullRequestBranch({ taskPacket: enrichedPacket, repoRoot, @@ -5659,6 +5721,14 @@ export async function runDeliveryTurnBroker({ } if (planned.actionType === 'merge-pr') { + const treasuryDenied = guardBrokerOperation( + TREASURY_OPERATION.QUEUE_AUTHORITY, + 'merge-pr', + 'treasury-queue-authority-denied' + ); + if (treasuryDenied) { + return treasuryDenied; + } const mergeResult = await mergePullRequest({ taskPacket: enrichedPacket, repoRoot, @@ -5743,6 +5813,14 @@ export async function runDeliveryTurnBroker({ } if (planned.actionType === 'reshape-backlog') { + const treasuryDenied = guardBrokerOperation( + TREASURY_OPERATION.NON_ESSENTIAL_WORK, + 'reshape-backlog', + 'treasury-non-essential-work-denied' + ); + if (treasuryDenied) { + return treasuryDenied; + } if (policy.autoSlice !== true) { return withWorkerProviderDispatch({ status: 'blocked', @@ -5768,6 +5846,15 @@ export async function runDeliveryTurnBroker({ }), enrichedPacket); } + const treasuryDenied = guardBrokerOperation( + TREASURY_OPERATION.CORE_DELIVERY, + 'execute-coding-turn', + 'treasury-core-delivery-denied' + ); + if (treasuryDenied) { + return treasuryDenied; + } + return withWorkerProviderDispatch(await invokeCodingTurnCommand({ taskPacket: enrichedPacket, policy, diff --git a/tools/priority/execution-cell-bundle.mjs b/tools/priority/execution-cell-bundle.mjs index 7ae7a3a45..f3b2f6ce7 100644 --- a/tools/priority/execution-cell-bundle.mjs +++ b/tools/priority/execution-cell-bundle.mjs @@ -1,5 +1,6 @@ #!/usr/bin/env node +import { existsSync } from 'node:fs'; import fs from 'node:fs/promises'; import path from 'node:path'; import process from 'node:process'; @@ -16,6 +17,11 @@ import { DEFAULT_OUTPUT_PATH as DEFAULT_EXECUTION_CELL_REPORT_PATH, runExecutionCellLease } from './execution-cell-lease.mjs'; +import { + DEFAULT_POLICY_PATH as DEFAULT_TREASURY_POLICY_PATH, + TREASURY_OPERATION, + runTreasuryOperationGuard +} from './treasury-control-plane.mjs'; const MODULE_DIR = path.dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = path.resolve(MODULE_DIR, '..', '..'); @@ -75,6 +81,11 @@ function wantsDockerLane(options = {}) { return Boolean(toOptionalText(options.laneId)) || normalizeCapabilities(options.capabilities).includes(DOCKER_LANE_CAPABILITY); } +function isPremiumSaganRequested(capabilities = []) { + const normalized = new Set(normalizeCapabilities(capabilities)); + return normalized.has(DOCKER_LANE_CAPABILITY) && normalized.has(NATIVE_LV32_CAPABILITY); +} + function inferBundleCapabilities(capabilities = [], planeBinding, dockerRequested) { const normalized = new Set(normalizeCapabilities(capabilities)); const normalizedPlaneBinding = normalizeText(planeBinding).toLowerCase(); @@ -265,14 +276,27 @@ function buildReport({ outputPath, dockerRequested, capabilities, + premiumSaganRequested = false, + premiumAuthorization = {}, executionCell, dockerLane, - rollbacks + rollbacks, + overrideStatus = null, + extraDenialReasons = [] }) { const reports = [executionCell, dockerLane].filter(Boolean); const effectiveRate = summarizeEffectiveRate(reports); const premiumSaganMode = executionCell?.summary?.premiumSaganMode === true || dockerLane?.summary?.premiumSaganMode === true; + const operatorAuthorizationRequired = + premiumAuthorization.operatorAuthorizationRequired === true || + (premiumSaganRequested && premiumSaganMode === true); + const operatorAuthorizationPromptRequired = + premiumAuthorization.operatorAuthorizationPromptRequired === true; + const estimatedFollowupAuthorizationsNeeded = + operatorAuthorizationRequired + ? Number(premiumAuthorization.estimatedFollowupAuthorizationsNeeded ?? 1) || 1 + : 0; const observations = collectSummaryStrings(reports, 'observations'); if (reports.length > 1 && effectiveRate.usdPerHour != null) { observations.push('agent-billed-once-at-effective-rate'); @@ -283,12 +307,13 @@ function buildReport({ if (rollbacks.dockerLane) { observations.push(`docker-lane-rollback-${rollbacks.dockerLane.status}`); } + observations.push(...(Array.isArray(premiumAuthorization.observations) ? premiumAuthorization.observations : [])); return { schema: EXECUTION_CELL_BUNDLE_REPORT_SCHEMA, generatedAt, action, - status: resolveBundleStatus(action, executionCell, dockerLane, rollbacks), + status: overrideStatus || resolveBundleStatus(action, executionCell, dockerLane, rollbacks), cellId, laneId: toOptionalText(laneId), outputPath, @@ -323,10 +348,16 @@ function buildReport({ ), effectiveBillableRateMultiplier: effectiveRate.multiplier, effectiveBillableRateUsdPerHour: effectiveRate.usdPerHour, + premiumSaganRequested, premiumSaganMode, + operatorAuthorizationRequired, + operatorAuthorizationPromptRequired, + estimatedFollowupAuthorizationsNeeded, operatorAuthorizationRef: toOptionalText(executionCell?.summary?.operatorAuthorizationRef) || toOptionalText(dockerLane?.summary?.operatorAuthorizationRef), + treasuryDecisionCode: toOptionalText(premiumAuthorization.treasuryDecisionCode), + treasuryControlPlanePath: toOptionalText(premiumAuthorization.treasuryControlPlanePath), isolatedLaneGroupId: toOptionalText(executionCell?.summary?.isolatedLaneGroupId) || toOptionalText(dockerLane?.summary?.isolatedLaneGroupId), @@ -334,7 +365,14 @@ function buildReport({ toOptionalText(executionCell?.summary?.fingerprintSha256) || toOptionalText(dockerLane?.summary?.fingerprintSha256), capabilities, - denialReasons: collectSummaryStrings([...reports, rollbacks.executionCell, rollbacks.dockerLane], 'denialReasons'), + denialReasons: [ + ...new Set( + [ + ...collectSummaryStrings([...reports, rollbacks.executionCell, rollbacks.dockerLane], 'denialReasons'), + ...extraDenialReasons + ].filter(Boolean) + ) + ], observations: [...new Set(observations.filter(Boolean))] } }; @@ -489,16 +527,28 @@ export async function runExecutionCellBundle(options = {}) { const outputPath = path.resolve(repoRoot, options.outputPath || DEFAULT_OUTPUT_PATH); const dockerRequested = wantsDockerLane(options); const capabilities = inferBundleCapabilities(options.capabilities, options.planeBinding, dockerRequested); + const action = normalizeText(options.action).toLowerCase(); + const premiumSaganRequested = isPremiumSaganRequested(capabilities); + let premiumAuthorization = { + operatorAuthorizationRequired: premiumSaganRequested, + operatorAuthorizationPromptRequired: premiumSaganRequested, + estimatedFollowupAuthorizationsNeeded: premiumSaganRequested ? 1 : 0, + treasuryDecisionCode: null, + treasuryControlPlanePath: null, + observations: [] + }; if (!toOptionalText(options.cellId)) { const report = buildReport({ - action: options.action, + action, generatedAt, cellId: '', laneId: options.laneId, outputPath, dockerRequested, capabilities, + premiumSaganRequested, + premiumAuthorization, executionCell: null, dockerLane: null, rollbacks: {} @@ -511,13 +561,15 @@ export async function runExecutionCellBundle(options = {}) { if (dockerRequested && !toOptionalText(options.laneId)) { const report = buildReport({ - action: options.action, + action, generatedAt, cellId: options.cellId, laneId: '', outputPath, dockerRequested, capabilities, + premiumSaganRequested, + premiumAuthorization, executionCell: null, dockerLane: null, rollbacks: {} @@ -534,6 +586,84 @@ export async function runExecutionCellBundle(options = {}) { ); const dockerLaneReportPath = path.resolve(repoRoot, options.dockerLaneReportPath || DEFAULT_DOCKER_REPORT_PATH); + if (premiumSaganRequested && !['inspect', 'release'].includes(action)) { + const treasuryPolicyPath = path.resolve(repoRoot, DEFAULT_TREASURY_POLICY_PATH); + const shouldRunTreasuryGuard = + typeof options.runTreasuryOperationGuardFn === 'function' + || options.enforceTreasuryGuard === true + || existsSync(treasuryPolicyPath); + if (shouldRunTreasuryGuard) { + const treasuryGuard = (options.runTreasuryOperationGuardFn ?? runTreasuryOperationGuard)({ + repoRoot, + repo: options.repository || null, + policyPath: treasuryPolicyPath, + operation: TREASURY_OPERATION.PREMIUM_SAGAN + }); + premiumAuthorization = { + operatorAuthorizationRequired: treasuryGuard?.decision?.authorization?.requiresOperatorAuthorization === true, + operatorAuthorizationPromptRequired: + treasuryGuard?.decision?.authorization?.requiresExplicitOperatorPrompt === true, + estimatedFollowupAuthorizationsNeeded: + Number(treasuryGuard?.decision?.authorization?.estimatedFollowupAuthorizationsNeeded ?? 0) || 0, + treasuryDecisionCode: treasuryGuard?.decision?.code || null, + treasuryControlPlanePath: treasuryGuard?.outputPath || null, + observations: + treasuryGuard?.decision?.authorization?.requiresExplicitOperatorPrompt === true + ? ['premium-operator-prompt-required'] + : [] + }; + if (treasuryGuard?.decision?.allowed !== true) { + const report = buildReport({ + action, + generatedAt, + cellId: options.cellId, + laneId: options.laneId, + outputPath, + dockerRequested, + capabilities, + premiumSaganRequested, + premiumAuthorization, + executionCell: null, + dockerLane: null, + rollbacks: {}, + overrideStatus: STATUS.denied, + extraDenialReasons: [ + treasuryGuard?.decision?.code || 'treasury-operation-denied' + ] + }); + await writeReport(outputPath, report); + return report; + } + } + if (!toOptionalText(options.operatorAuthorizationRef)) { + const report = buildReport({ + action, + generatedAt, + cellId: options.cellId, + laneId: options.laneId, + outputPath, + dockerRequested, + capabilities, + premiumSaganRequested, + premiumAuthorization: { + ...premiumAuthorization, + operatorAuthorizationRequired: true, + operatorAuthorizationPromptRequired: true, + estimatedFollowupAuthorizationsNeeded: + Number(premiumAuthorization.estimatedFollowupAuthorizationsNeeded ?? 0) || 1, + observations: [...new Set([...(premiumAuthorization.observations || []), 'premium-operator-prompt-required'])] + }, + executionCell: null, + dockerLane: null, + rollbacks: {}, + overrideStatus: STATUS.denied, + extraDenialReasons: ['operator-authorization-required'] + }); + await writeReport(outputPath, report); + return report; + } + } + const executionCellOptions = { action: options.action, cellId: options.cellId, @@ -652,13 +782,15 @@ export async function runExecutionCellBundle(options = {}) { } const report = buildReport({ - action: normalizeText(options.action).toLowerCase(), + action, generatedAt, cellId: options.cellId, laneId: options.laneId, outputPath, dockerRequested, capabilities, + premiumSaganRequested, + premiumAuthorization, executionCell, dockerLane, rollbacks @@ -686,7 +818,8 @@ export async function main(argv = process.argv) { const report = await runExecutionCellBundle({ ...options, - repoRoot: process.cwd() + repoRoot: process.cwd(), + enforceTreasuryGuard: true }); console.log( `[execution-cell-bundle] report: ${path.resolve(process.cwd(), options.outputPath || DEFAULT_OUTPUT_PATH)} status=${report.status} cell=${report.cellId} lane=${report.laneId ?? 'none'}` diff --git a/tools/priority/github-comment-budget-hook.mjs b/tools/priority/github-comment-budget-hook.mjs index d6b02093e..e8a64383c 100644 --- a/tools/priority/github-comment-budget-hook.mjs +++ b/tools/priority/github-comment-budget-hook.mjs @@ -3,7 +3,10 @@ import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; -import { runMaterializeAgentCostRollup } from './materialize-agent-cost-rollup.mjs'; +import { + DEFAULT_POLICY_PATH as DEFAULT_TREASURY_POLICY_PATH, + runTreasuryControlPlane +} from './treasury-control-plane.mjs'; export const REPORT_SCHEMA = 'priority/github-comment-budget-hook@v1'; export const POLICY_SCHEMA = 'priority/github-comment-budget-hook-policy@v1'; @@ -96,6 +99,7 @@ function parseArgs(argv = process.argv) { targetKind: 'unknown', targetNumber: null, policyPath: DEFAULT_POLICY_PATH, + treasuryPolicyPath: null, costRollupPath: null, outputPath: null, markdownOutputPath: null, @@ -118,7 +122,7 @@ function parseArgs(argv = process.argv) { options.materialize = false; continue; } - if (['--repo-root', '--repo', '--target-kind', '--target-number', '--policy', '--cost-rollup', '--output', '--markdown-output'].includes(token)) { + if (['--repo-root', '--repo', '--target-kind', '--target-number', '--policy', '--treasury-policy', '--cost-rollup', '--output', '--markdown-output'].includes(token)) { if (!next || next.startsWith('-')) { throw new Error(`Missing value for ${token}.`); } @@ -128,6 +132,7 @@ function parseArgs(argv = process.argv) { if (token === '--target-kind') options.targetKind = next; if (token === '--target-number') options.targetNumber = toPositiveInteger(next); if (token === '--policy') options.policyPath = next; + if (token === '--treasury-policy') options.treasuryPolicyPath = next; if (token === '--cost-rollup') options.costRollupPath = next; if (token === '--output') options.outputPath = next; if (token === '--markdown-output') options.markdownOutputPath = next; @@ -281,6 +286,8 @@ function buildJsonHookPayload(report) { operatorLaborObservedUsd: report.summary.operatorLaborObservedUsd, operatorLaborMissingTurnCount: report.summary.operatorLaborMissingTurnCount, operatorBudgetCapUsd: report.summary.operatorBudgetCapUsd, + operatorBudgetObservedRemainingUpperBoundUsd: report.summary.operatorBudgetObservedRemainingUpperBoundUsd, + operatorBudgetObservedRemainingStatus: report.summary.operatorBudgetObservedRemainingStatus, operatorBudgetRemainingLowerBoundUsd: report.summary.operatorBudgetRemainingLowerBoundUsd, operatorBudgetRemainingStatus: report.summary.operatorBudgetRemainingStatus, operatorBudgetSpendableUsd: report.summary.operatorBudgetSpendableUsd, @@ -288,6 +295,19 @@ function buildJsonHookPayload(report) { accountRemainingUsdEstimate: report.summary.accountRemainingUsdEstimate, operationalHeadroomUsd: report.summary.operationalHeadroomUsd, operationalHeadroomStatus: report.summary.operationalHeadroomStatus, + safeSpendableUsd: report.summary.safeSpendableUsd, + possibleSpendableUpperBoundUsd: report.summary.possibleSpendableUpperBoundUsd, + treasuryConfidence: report.summary.treasuryConfidence, + treasurySpendPolicyState: report.summary.treasurySpendPolicyState, + coreDeliveryAllowed: report.summary.coreDeliveryAllowed, + queueAuthorityAllowed: report.summary.queueAuthorityAllowed, + releaseApplyAllowed: report.summary.releaseApplyAllowed, + premiumSaganAllowed: report.summary.premiumSaganAllowed, + premiumAuthorizationPromptRequired: report.summary.premiumAuthorizationPromptRequired, + premiumAuthorizationFollowupEstimate: report.summary.premiumAuthorizationFollowupEstimate, + backgroundFanoutAllowed: report.summary.backgroundFanoutAllowed, + maxBackgroundSubagents: report.summary.maxBackgroundSubagents, + nonEssentialWorkAllowed: report.summary.nonEssentialWorkAllowed, budgetPressureState: report.summary.budgetPressureState, billingWindow: report.funding.billingWindow, accountBalance: report.funding.accountBalance, @@ -316,7 +336,7 @@ function buildMarkdown(report) { ? 'operator cap unknown' : report.summary.operatorBudgetSpendableStatus === 'observed' ? `operator ${formatUsd(report.summary.operatorLaborObservedUsd)} of ${formatUsd(report.summary.operatorBudgetCapUsd)} cap (spendable remaining ${formatUsd(report.summary.operatorBudgetSpendableUsd)})` - : `operator ${formatUsd(report.summary.operatorLaborObservedUsd)} of ${formatUsd(report.summary.operatorBudgetCapUsd)} cap (spendable remaining unreconciled; lower bound ${report.summary.operatorBudgetRemainingStatus === 'lower-bound' ? '>=' : ''}${formatUsd(report.summary.operatorBudgetRemainingLowerBoundUsd)})`; + : `operator ${formatUsd(report.summary.operatorLaborObservedUsd)} of ${formatUsd(report.summary.operatorBudgetCapUsd)} cap (spendable remaining unreconciled; observed upper bound ${formatUsd(report.summary.operatorBudgetObservedRemainingUpperBoundUsd)})`; const billingWindowText = billingWindow?.invoiceTurnId ? `window \`${billingWindow.invoiceTurnId}\` spent ${formatUsd(billingWindow.tokenSpendUsd)} remaining ${formatUsd(billingWindow.remainingUsd)}` : 'window unavailable'; @@ -324,15 +344,21 @@ function buildMarkdown(report) { ? `account est ${formatUsd(accountBalance.remainingUsdEstimate)} remaining from ${accountBalance.remainingCredits} credits @ ${formatUsd(accountBalance.unitPriceUsd)} per credit` : 'account headroom unavailable'; const headroomText = report.summary.operationalHeadroomUsd != null - ? `operational headroom ${formatUsd(report.summary.operationalHeadroomUsd)} (${report.summary.operationalHeadroomStatus})` + ? `operational headroom ${formatUsd(report.summary.operationalHeadroomUsd)} (${report.summary.operationalHeadroomStatus}); safe spend ${formatUsd(report.summary.safeSpendableUsd)}` : `operational headroom unavailable (${report.summary.operationalHeadroomStatus})`; + const treasuryText = `treasury ${report.summary.treasurySpendPolicyState} (${report.summary.treasuryConfidence})`; + const treasuryOperationsText = + `ops core=${report.summary.coreDeliveryAllowed} queue=${report.summary.queueAuthorityAllowed} release=${report.summary.releaseApplyAllowed}`; + const premiumPromptText = report.summary.premiumAuthorizationPromptRequired + ? `; premium requires explicit operator authorization (follow-up estimate ${report.summary.premiumAuthorizationFollowupEstimate})` + : ''; const reserveText = reservedFunding.count > 0 ? `; calibration reserve ${formatUsd(reservedFunding.totalReservedUsd)} across ${reservedFunding.count} held window(s)` : ''; const timingText = report.summary.operatorLaborMissingTurnCount > 0 ? `; ${report.summary.operatorLaborMissingTurnCount} turn(s) still pending labor timing` : ''; - lines.push(`_Budget hook_: blended lower bound ${formatUsd(report.summary.observedBlendedLowerBoundUsd)}; ${operatorBudgetText}; ${billingWindowText}; ${accountText}; ${headroomText}; pressure ${report.summary.budgetPressureState}; turns ${report.turns.totalTurns} total (${report.turns.liveTurnCount} live, ${report.turns.backgroundTurnCount} background)${timingText}${reserveText}. Receipt: \`${report.source.outputPath}\`.`); + lines.push(`_Budget hook_: blended lower bound ${formatUsd(report.summary.observedBlendedLowerBoundUsd)}; ${operatorBudgetText}; ${billingWindowText}; ${accountText}; ${headroomText}; ${treasuryText}; ${treasuryOperationsText}; pressure ${report.summary.budgetPressureState}${premiumPromptText}; turns ${report.turns.totalTurns} total (${report.turns.liveTurnCount} live, ${report.turns.backgroundTurnCount} background)${timingText}${reserveText}. Receipt: \`${report.source.outputPath}\`.`); } lines.push(COMMENT_HOOK_END_MARKER, ''); @@ -369,56 +395,27 @@ export function appendBudgetHook(body, hookMarkdown) { return `${cleanBody}\n\n${hook}\n`; } -export function buildGitHubCommentBudgetHookReport({ rollup, repository, targetKind, targetNumber, operatorBudgetCapUsd, reservedFunding, billingWindow, source, blockers, now }) { - const metrics = rollup?.summary?.metrics ?? {}; - const tokenSpendUsd = toNonNegativeNumber(metrics.totalUsd) ?? 0; - const operatorLaborObservedUsd = toNonNegativeNumber(metrics.operatorLaborUsd) ?? 0; - const operatorLaborMissingTurnCount = Number(metrics.operatorLaborMissingTurnCount ?? 0) || 0; - const observedBlendedLowerBoundUsd = roundUsd(tokenSpendUsd + operatorLaborObservedUsd) ?? 0; - const knownBlendedUsd = toNonNegativeNumber(metrics.blendedTotalUsd); - const accountBalance = summarizeAccountBalance(rollup); - const operationalHeadroom = summarizeOperationalHeadroom(accountBalance, reservedFunding); - const operatorBudgetRemainingLowerBoundUsd = - operatorBudgetCapUsd == null ? null : roundUsd(Math.max(0, operatorBudgetCapUsd - operatorLaborObservedUsd)); - const operatorBudgetRemainingStatus = - operatorBudgetCapUsd == null ? 'unknown' : operatorLaborMissingTurnCount > 0 ? 'lower-bound' : 'observed'; - const operatorBudgetSpendableStatus = - operatorBudgetCapUsd == null ? 'unknown' : operatorLaborMissingTurnCount > 0 ? 'unreconciled' : 'observed'; - const operatorBudgetSpendableUsd = - operatorBudgetSpendableStatus === 'observed' ? operatorBudgetRemainingLowerBoundUsd : null; - - const blocking = Array.isArray(blockers) ? blockers.filter(Boolean) : []; - const budgetPressureState = - blocking.length > 0 - ? 'blocked' - : operationalHeadroom.status === 'reserve-protected-only' - ? 'stop-nonessential-spend' - : operationalHeadroom.status === 'reserve-near' - ? 'tight' - : operationalHeadroom.status === 'unknown' || operatorBudgetSpendableStatus !== 'observed' - ? 'cautious' - : 'healthy'; - const status = - blocking.length > 0 - ? 'blocked' - : budgetPressureState === 'healthy' - ? 'pass' - : 'warn'; - const recommendation = - status === 'blocked' - ? 'repair-comment-budget-hook-inputs' - : budgetPressureState === 'stop-nonessential-spend' - ? 'protect-calibration-reserve' - : budgetPressureState === 'tight' - ? 'constrain-spend' - : operatorLaborMissingTurnCount > 0 - ? 'reconcile-operator-labor-before-assuming-headroom' - : 'comment-budget-hook-ready'; +export function buildGitHubCommentBudgetHookReport({ treasuryReport, repository, targetKind, targetNumber, source, blockers, now }) { + const treasurySummary = treasuryReport?.summary ?? {}; + const treasuryTurns = treasuryReport?.turns ?? {}; + const treasuryFunding = treasuryReport?.funding ?? { + billingWindow: null, + accountBalance: null, + reservedFunding: { count: 0, totalReservedUsd: 0, windows: [] } + }; + const combinedBlockers = [ + ...(Array.isArray(treasuryReport?.blockers) ? treasuryReport.blockers : []), + ...(Array.isArray(blockers) ? blockers : []) + ].filter(Boolean); + const status = combinedBlockers.length > 0 ? 'blocked' : asOptional(treasurySummary.status) || 'blocked'; + const recommendation = combinedBlockers.length > 0 + ? 'repair-comment-budget-hook-inputs' + : asOptional(treasurySummary.recommendation) || 'comment-budget-hook-ready'; return { schema: REPORT_SCHEMA, generatedAt: now.toISOString(), - repository, + repository: repository || treasuryReport?.repository || null, target: { kind: asOptional(targetKind) || 'unknown', number: targetNumber ?? null @@ -426,33 +423,50 @@ export function buildGitHubCommentBudgetHookReport({ rollup, repository, targetK summary: { status, recommendation, - tokenSpendUsd, - operatorLaborObservedUsd, - operatorLaborMissingTurnCount, - observedBlendedLowerBoundUsd, - knownBlendedUsd, - operatorBudgetCapUsd, - operatorBudgetRemainingLowerBoundUsd, - operatorBudgetRemainingStatus, - operatorBudgetSpendableUsd, - operatorBudgetSpendableStatus, - accountRemainingUsdEstimate: operationalHeadroom.accountRemainingUsdEstimate, - operationalHeadroomUsd: operationalHeadroom.operationalHeadroomUsd, - operationalHeadroomStatus: operationalHeadroom.status, - budgetPressureState + tokenSpendUsd: toNonNegativeNumber(treasurySummary.tokenSpendUsd) ?? 0, + operatorLaborObservedUsd: toNonNegativeNumber(treasurySummary.operatorLaborObservedUsd) ?? 0, + operatorLaborMissingTurnCount: Number(treasurySummary.operatorLaborMissingTurnCount ?? 0) || 0, + observedBlendedLowerBoundUsd: toNonNegativeNumber(treasurySummary.observedBlendedLowerBoundUsd) ?? 0, + knownBlendedUsd: toNonNegativeNumber(treasurySummary.knownBlendedUsd), + operatorBudgetCapUsd: toNonNegativeNumber(treasurySummary.operatorBudgetCapUsd), + operatorBudgetObservedRemainingUpperBoundUsd: toNonNegativeNumber( + treasurySummary.operatorBudgetObservedRemainingUpperBoundUsd + ), + operatorBudgetObservedRemainingStatus: asOptional(treasurySummary.operatorBudgetObservedRemainingStatus) || 'unknown', + operatorBudgetRemainingLowerBoundUsd: toNonNegativeNumber(treasurySummary.operatorBudgetRemainingLowerBoundUsd), + operatorBudgetRemainingStatus: asOptional(treasurySummary.operatorBudgetRemainingStatus) || 'unknown', + operatorBudgetSpendableUsd: toNonNegativeNumber(treasurySummary.operatorBudgetSpendableUsd), + operatorBudgetSpendableStatus: asOptional(treasurySummary.operatorBudgetSpendableStatus) || 'unknown', + accountRemainingUsdEstimate: toNonNegativeNumber(treasurySummary.accountRemainingUsdEstimate), + operationalHeadroomUsd: toNonNegativeNumber(treasurySummary.operationalHeadroomUsd), + operationalHeadroomStatus: asOptional(treasurySummary.operationalHeadroomStatus) || 'unknown', + safeSpendableUsd: toNonNegativeNumber(treasurySummary.safeSpendableUsd), + possibleSpendableUpperBoundUsd: toNonNegativeNumber(treasurySummary.possibleSpendableUpperBoundUsd), + treasuryConfidence: asOptional(treasurySummary.confidence) || 'unknown', + treasurySpendPolicyState: asOptional(treasurySummary.spendPolicyState) || 'blocked', + coreDeliveryAllowed: treasurySummary.coreDeliveryAllowed === true, + queueAuthorityAllowed: treasurySummary.queueAuthorityAllowed === true, + releaseApplyAllowed: treasurySummary.releaseApplyAllowed === true, + premiumSaganAllowed: treasurySummary.premiumSaganAllowed === true, + premiumAuthorizationPromptRequired: treasurySummary.premiumAuthorizationPromptRequired === true, + premiumAuthorizationFollowupEstimate: Number(treasurySummary.premiumAuthorizationFollowupEstimate ?? 0) || 0, + backgroundFanoutAllowed: treasurySummary.backgroundFanoutAllowed === true, + maxBackgroundSubagents: Number(treasurySummary.maxBackgroundSubagents ?? 0) || 0, + nonEssentialWorkAllowed: treasurySummary.nonEssentialWorkAllowed === true, + budgetPressureState: asOptional(treasurySummary.budgetPressureState) || 'blocked' }, turns: { - totalTurns: Number(metrics.totalTurns ?? 0) || 0, - liveTurnCount: Number(metrics.liveTurnCount ?? 0) || 0, - backgroundTurnCount: Number(metrics.backgroundTurnCount ?? 0) || 0 + totalTurns: Number(treasuryTurns.totalTurns ?? 0) || 0, + liveTurnCount: Number(treasuryTurns.liveTurnCount ?? 0) || 0, + backgroundTurnCount: Number(treasuryTurns.backgroundTurnCount ?? 0) || 0 }, funding: { - billingWindow, - accountBalance, - reservedFunding + billingWindow: treasuryFunding.billingWindow ?? null, + accountBalance: treasuryFunding.accountBalance ?? null, + reservedFunding: treasuryFunding.reservedFunding ?? { count: 0, totalReservedUsd: 0, windows: [] } }, source, - blockers: blocking + blockers: combinedBlockers }; } @@ -460,72 +474,44 @@ export function runGitHubCommentBudgetHook( options, { now = new Date(), - readJsonFn = readJson, writeJsonFn = writeJson, writeTextFn = writeText, - runMaterializeAgentCostRollupFn = runMaterializeAgentCostRollup + runTreasuryControlPlaneFn = runTreasuryControlPlane } = {} ) { const repoRoot = path.resolve(options.repoRoot || process.cwd()); const { resolvedPolicyPath, policy } = loadPolicy(repoRoot, options.policyPath || DEFAULT_POLICY_PATH); - let costRollupPath = path.resolve(repoRoot, options.costRollupPath || asOptional(policy.costRollupPath) || DEFAULT_OUTPUT_PATH.replace('github-comment-budget-hook', 'agent-cost-rollup')); - let costRollupMaterialized = false; - let costRollupMaterializationReportPath = null; const blockers = []; - - const shouldMaterialize = options.materialize ?? Boolean(policy.materializeCostRollup); - if (shouldMaterialize) { - try { - const materializeResult = runMaterializeAgentCostRollupFn({ - repoRoot, - repo: options.repo, - policyPath: asOptional(policy.materializationPolicyPath) || undefined, - costRollupPath, - outputPath: asOptional(policy.materializationReportPath) || undefined - }); - costRollupMaterialized = true; - costRollupPath = path.resolve(materializeResult.costRollupPath || costRollupPath); - costRollupMaterializationReportPath = safeRelative(repoRoot, materializeResult.outputPath); - } catch (error) { - blockers.push(createBlocker('cost-rollup-materialization-failed', error?.message || String(error))); - } - } - - let rollup = null; - if (!fs.existsSync(costRollupPath)) { - blockers.push(createBlocker('cost-rollup-missing', 'Agent cost rollup is missing.', safeRelative(repoRoot, costRollupPath))); - } else { - try { - rollup = readJsonFn(costRollupPath); - if (normalizeText(rollup?.schema) !== 'priority/agent-cost-rollup@v1') { - blockers.push(createBlocker('cost-rollup-schema-mismatch', 'Agent cost rollup schema must remain priority/agent-cost-rollup@v1.', safeRelative(repoRoot, costRollupPath))); - } - } catch (error) { - blockers.push(createBlocker('cost-rollup-unreadable', error?.message || String(error), safeRelative(repoRoot, costRollupPath))); - } - } - - const billingWindow = summarizeBillingWindow(rollup); - const reservedFunding = summarizeReservedFundingWindows(rollup, policy, billingWindow?.invoiceTurnId ?? null); - const repository = chooseTargetRepository(options.repo, rollup); - const operatorBudgetCapUsd = toNonNegativeNumber(policy.operatorBudgetCapUsd); + const treasuryPolicyPath = path.resolve( + repoRoot, + options.treasuryPolicyPath || asOptional(policy.treasuryPolicyPath) || DEFAULT_TREASURY_POLICY_PATH + ); const outputPath = path.resolve(repoRoot, options.outputPath || asOptional(policy.outputPath) || DEFAULT_OUTPUT_PATH); const markdownOutputPath = path.resolve(repoRoot, options.markdownOutputPath || asOptional(policy.markdownOutputPath) || DEFAULT_MARKDOWN_OUTPUT_PATH); + let treasuryReport = null; + + try { + const treasuryResult = runTreasuryControlPlaneFn({ + repoRoot, + repo: options.repo, + policyPath: treasuryPolicyPath, + costRollupPath: options.costRollupPath, + materialize: options.materialize + }); + treasuryReport = treasuryResult.report; + } catch (error) { + blockers.push(createBlocker('treasury-control-plane-failed', error?.message || String(error))); + } const report = buildGitHubCommentBudgetHookReport({ - rollup, - repository, + treasuryReport, + repository: chooseTargetRepository(options.repo, treasuryReport), targetKind: options.targetKind, targetNumber: options.targetNumber, - operatorBudgetCapUsd, - reservedFunding, - billingWindow, source: { policyPath: safeRelative(repoRoot, resolvedPolicyPath), - costRollupPath: safeRelative(repoRoot, costRollupPath), - costRollupMaterialized, - costRollupMaterializationReportPath, - operatorCostProfilePath: asOptional(rollup?.summary?.provenance?.operatorProfiles?.[0]?.operatorProfilePath) || 'tools/policy/operator-cost-profile.json', + treasuryPolicyPath: safeRelative(repoRoot, treasuryPolicyPath), + treasuryControlPlanePath: asOptional(treasuryReport?.source?.outputPath), outputPath: safeRelative(repoRoot, outputPath), markdownOutputPath: safeRelative(repoRoot, markdownOutputPath) }, @@ -556,6 +542,7 @@ function printUsage() { ' --repo Repository slug override.', ' --target-kind Comment target kind.', ' --target-number Comment target number.', + ' --treasury-policy Treasury policy path override.', ' --cost-rollup Cost rollup path override.', ` --output JSON report path (default: ${DEFAULT_OUTPUT_PATH}).`, ` --markdown-output Markdown hook path (default: ${DEFAULT_MARKDOWN_OUTPUT_PATH}).`, diff --git a/tools/priority/queue-supervisor.mjs b/tools/priority/queue-supervisor.mjs index 1337cd969..318db65f1 100644 --- a/tools/priority/queue-supervisor.mjs +++ b/tools/priority/queue-supervisor.mjs @@ -2,7 +2,6 @@ import { spawnSync } from 'node:child_process'; import { readFile, writeFile, mkdir, readdir } from 'node:fs/promises'; -import { existsSync } from 'node:fs'; import path from 'node:path'; import process from 'node:process'; import { fileURLToPath } from 'node:url'; @@ -10,6 +9,7 @@ import { parseRemoteUrl, runGhGraphql } from './lib/remote-utils.mjs'; import { getRepoRoot } from './lib/branch-utils.mjs'; import { buildQueueReadinessReport, DEFAULT_READINESS_REPORT_PATH } from './queue-readiness.mjs'; import { hasDeferredPostMergeBranchCleanup, reconcileDeferredBranchCleanup } from './merge-sync-pr.mjs'; +import { DEFAULT_POLICY_PATH as DEFAULT_TREASURY_POLICY_PATH, TREASURY_OPERATION, runTreasuryOperationGuard } from './treasury-control-plane.mjs'; const REPORT_SCHEMA = 'priority/queue-supervisor-report@v1'; const DEFAULT_REPORT_PATH = path.join('tests', 'results', '_agent', 'queue', 'queue-supervisor-report.json'); @@ -1587,6 +1587,7 @@ export async function runQueueSupervisor(options = {}) { const writeReportFn = options.writeReportFn ?? writeReport; const reconcileDeferredBranchCleanupFn = options.reconcileDeferredBranchCleanupFn ?? reconcileDeferredBranchCleanup; const runGhGraphqlFn = options.runGhGraphqlFn ?? (options.runGhJsonFn ? null : runGhGraphql); + const runTreasuryOperationGuardFn = options.runTreasuryOperationGuardFn ?? runTreasuryOperationGuard; const repository = resolveRepositorySlug(repoRoot, args.repo); const repositoryOwner = String(repository).split('/')[0]?.trim().toLowerCase() ?? ''; @@ -1915,6 +1916,27 @@ export async function runQueueSupervisor(options = {}) { reconcileDeferredBranchCleanupFn }); + const treasuryPolicyPath = path.resolve(repoRoot, DEFAULT_TREASURY_POLICY_PATH); + const shouldRunTreasuryGuard = + Boolean(args.apply && !args.dryRun) + && (options.enforceTreasuryGuard === true || typeof options.runTreasuryOperationGuardFn === 'function'); + if (shouldRunTreasuryGuard) { + const treasuryGuard = runTreasuryOperationGuardFn({ + repoRoot, + repo: repository, + policyPath: treasuryPolicyPath, + operation: TREASURY_OPERATION.QUEUE_AUTHORITY + }); + if (treasuryGuard?.decision?.allowed !== true) { + report.paused = true; + report.pausedReasons = [...new Set([ + ...(Array.isArray(report.pausedReasons) ? report.pausedReasons : []), + 'treasury-queue-authority-denied', + treasuryGuard?.decision?.code || 'treasury-operation-denied' + ])]; + } + } + if (report.paused || args.dryRun || !args.apply) { report.retryHistory = retryHistory; const resolvedPath = await writeReportFn(args.reportPath, report); @@ -2050,7 +2072,10 @@ export async function main(argv = process.argv) { return 0; } - const { report, reportPath, controllerState, controllerStatePath, readinessPath } = await runQueueSupervisor({ args }); + const { report, reportPath, controllerState, controllerStatePath, readinessPath } = await runQueueSupervisor({ + args, + enforceTreasuryGuard: true + }); console.log(`[queue-supervisor] report written: ${reportPath}`); if (controllerStatePath) { console.log( diff --git a/tools/priority/release-conductor.mjs b/tools/priority/release-conductor.mjs index 5dea1b441..3c9d0b8c8 100644 --- a/tools/priority/release-conductor.mjs +++ b/tools/priority/release-conductor.mjs @@ -6,6 +6,7 @@ import { spawnSync } from 'node:child_process'; import path from 'node:path'; import process from 'node:process'; import { fileURLToPath } from 'node:url'; +import { DEFAULT_POLICY_PATH as DEFAULT_TREASURY_POLICY_PATH, TREASURY_OPERATION, runTreasuryOperationGuard } from './treasury-control-plane.mjs'; export const REPORT_SCHEMA = 'release/release-conductor-report@v1'; export const DEFAULT_REPORT_PATH = path.join('tests', 'results', '_agent', 'release', 'release-conductor-report.json'); @@ -664,6 +665,7 @@ export async function runReleaseConductor(options = {}) { const readJsonOptionalFn = options.readJsonOptionalFn ?? readJsonOptional; const writeReportFn = options.writeReportFn ?? writeReport; const environment = options.environment ?? process.env; + const runTreasuryOperationGuardFn = options.runTreasuryOperationGuardFn ?? runTreasuryOperationGuard; const repository = resolveRepositorySlug(repoRoot, args.repo, environment); const queueReportEnvelope = await readJsonOptionalFn(path.resolve(repoRoot, args.queueReportPath)); @@ -692,6 +694,23 @@ export async function runReleaseConductor(options = {}) { const applyRequested = Boolean(args.apply && !args.dryRun); const blockers = []; const advisories = []; + const treasuryPolicyPath = path.resolve(repoRoot, DEFAULT_TREASURY_POLICY_PATH); + const shouldRunTreasuryGuard = + applyRequested && (options.enforceTreasuryGuard === true || typeof options.runTreasuryOperationGuardFn === 'function'); + if (shouldRunTreasuryGuard) { + const treasuryGuard = runTreasuryOperationGuardFn({ + repoRoot, + repo: repository, + policyPath: treasuryPolicyPath, + operation: TREASURY_OPERATION.RELEASE_APPLY + }); + if (treasuryGuard?.decision?.allowed !== true) { + blockers.push({ + code: 'treasury-release-apply-denied', + message: treasuryGuard?.decision?.reason || 'Treasury denied release apply.' + }); + } + } if (fetchErrors.length > 0) { blockers.push({ code: 'workflow-fetch-failed', @@ -1052,7 +1071,10 @@ export async function main(argv = process.argv) { return 0; } - const { report, reportPath, exitCode } = await runReleaseConductor({ args }); + const { report, reportPath, exitCode } = await runReleaseConductor({ + args, + enforceTreasuryGuard: true + }); console.log( `[release-conductor] report: ${reportPath} status=${report.decision.status} blockers=${report.decision.blockerCount} advisories=${report.decision.advisoryCount}` ); diff --git a/tools/priority/runtime-supervisor.mjs b/tools/priority/runtime-supervisor.mjs index 44a62a304..9957a94d2 100644 --- a/tools/priority/runtime-supervisor.mjs +++ b/tools/priority/runtime-supervisor.mjs @@ -83,6 +83,11 @@ import { DEFAULT_OUTPUT_PATH as DEFAULT_MONITORING_WORK_INJECTION_PATH, runMonitoringWorkInjection } from './monitoring-work-injection.mjs'; +import { + DEFAULT_POLICY_PATH as DEFAULT_TREASURY_POLICY_PATH, + TREASURY_OPERATION, + runTreasuryOperationGuard +} from './treasury-control-plane.mjs'; export { ACTIONS, @@ -1912,6 +1917,50 @@ async function executeCompareviTurn({ } if (standingRepository === upstreamRepository || !Number.isInteger(mirrorOf?.number) || !normalizeText(mirrorOf?.url)) { + const treasuryPolicyPath = path.resolve(repoRoot, DEFAULT_TREASURY_POLICY_PATH); + const shouldRunTreasuryGuard = + typeof deps.runTreasuryOperationGuardFn === 'function' || options.enforceTreasuryGuard === true; + if (shouldRunTreasuryGuard) { + const runTreasuryOperationGuardFn = deps.runTreasuryOperationGuardFn ?? runTreasuryOperationGuard; + const treasuryGuard = runTreasuryOperationGuardFn({ + repoRoot, + repo: repository || standingRepository, + policyPath: treasuryPolicyPath, + operation: TREASURY_OPERATION.CORE_DELIVERY + }); + if (treasuryGuard?.decision?.allowed !== true) { + const receipt = { + status: 'blocked', + outcome: 'treasury-core-delivery-denied', + reason: treasuryGuard?.decision?.reason || 'Treasury denied core delivery.', + source: 'comparevi-runtime', + details: { + laneLifecycle: 'blocked', + blockerClass: 'budget', + actionType: 'treasury-guard', + retryable: true, + nextWakeCondition: 'treasury-reconciled', + treasuryOperation: TREASURY_OPERATION.CORE_DELIVERY, + treasuryDecisionCode: treasuryGuard?.decision?.code || 'treasury-operation-denied' + }, + artifacts: { + treasuryControlPlanePath: treasuryGuard?.outputPath || null + } + }; + await persistCompareviDeliveryRuntime({ + repository: repository || standingRepository, + runtimeArtifactPaths, + schedulerDecision, + taskPacket, + executionReceipt: receipt, + repoRoot, + deps, + now + }); + return receipt; + } + } + const receipt = await invokeCanonicalDeliveryTurn({ repoRoot, deps, @@ -2100,7 +2149,13 @@ export const compareviRuntimeAdapter = createRuntimeAdapter({ bootstrapWorker: (context) => bootstrapCompareviWorkerCheckout(context), activateWorker: (context) => activateCompareviWorkerLane(context), buildTaskPacket: (context) => buildCompareviTaskPacket(context), - executeTurn: (context) => executeCompareviTurn(context) + executeTurn: (context) => executeCompareviTurn({ + ...context, + options: { + ...(context?.options || {}), + enforceTreasuryGuard: true + } + }) }); export const compareviRuntimeTest = { diff --git a/tools/priority/runtime-turn-broker.mjs b/tools/priority/runtime-turn-broker.mjs index 27ed8bd47..afc590275 100644 --- a/tools/priority/runtime-turn-broker.mjs +++ b/tools/priority/runtime-turn-broker.mjs @@ -103,7 +103,8 @@ async function main(argv = process.argv) { taskPacket, taskPacketPath, repoRoot, - policyPath: options.policyPath + policyPath: options.policyPath, + enforceTreasuryGuard: true }) ); diff --git a/tools/priority/treasury-control-plane.mjs b/tools/priority/treasury-control-plane.mjs new file mode 100644 index 000000000..c21c83572 --- /dev/null +++ b/tools/priority/treasury-control-plane.mjs @@ -0,0 +1,898 @@ +#!/usr/bin/env node + +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +import { runMaterializeAgentCostRollup } from './materialize-agent-cost-rollup.mjs'; + +export const REPORT_SCHEMA = 'priority/treasury-control-plane@v2'; +export const POLICY_SCHEMA = 'priority/treasury-control-plane-policy@v2'; +export const DEFAULT_POLICY_PATH = path.join('tools', 'policy', 'treasury-control-plane.json'); +export const DEFAULT_OUTPUT_PATH = path.join( + 'tests', + 'results', + '_agent', + 'cost', + 'treasury-control-plane.json' +); +export const TREASURY_OPERATION = Object.freeze({ + CORE_DELIVERY: 'core-delivery', + QUEUE_AUTHORITY: 'queue-authority', + RELEASE_APPLY: 'release-apply', + BACKGROUND_FANOUT: 'background-fanout', + NON_ESSENTIAL_WORK: 'non-essential-work', + PREMIUM_SAGAN: 'premium-sagan' +}); + +function normalizeText(value) { + if (value == null) { + return ''; + } + return String(value).trim(); +} + +function asOptional(value) { + const normalized = normalizeText(value); + return normalized.length > 0 ? normalized : null; +} + +function toNonNegativeNumber(value) { + if (value == null || value === '') { + return null; + } + const parsed = Number(value); + return Number.isFinite(parsed) && parsed >= 0 ? parsed : null; +} + +function toPositiveInteger(value) { + const parsed = Number(value); + return Number.isInteger(parsed) && parsed > 0 ? parsed : null; +} + +function roundUsd(value) { + const parsed = Number(value); + if (!Number.isFinite(parsed)) { + return null; + } + return Number(parsed.toFixed(6)); +} + +function toTimestamp(value) { + const normalized = asOptional(value); + if (!normalized) { + return null; + } + const parsed = Date.parse(normalized); + return Number.isFinite(parsed) ? parsed : null; +} + +function safeRelative(repoRoot, targetPath) { + if (!targetPath) { + return null; + } + return path.relative(repoRoot, path.resolve(targetPath)).replace(/\\/g, '/'); +} + +function readJson(filePath) { + return JSON.parse(fs.readFileSync(path.resolve(filePath), 'utf8')); +} + +function writeJson(filePath, payload) { + const resolved = path.resolve(filePath); + fs.mkdirSync(path.dirname(resolved), { recursive: true }); + fs.writeFileSync(resolved, `${JSON.stringify(payload, null, 2)}\n`, 'utf8'); + return resolved; +} + +function createBlocker(code, message, details = null) { + return { + code, + message, + details: asOptional(details) + }; +} + +function parseArgs(argv = process.argv) { + const args = argv.slice(2); + const options = { + repoRoot: process.cwd(), + repo: null, + policyPath: DEFAULT_POLICY_PATH, + costRollupPath: null, + outputPath: null, + materialize: null, + help: false + }; + + for (let index = 0; index < args.length; index += 1) { + const token = args[index]; + const next = args[index + 1]; + if (token === '-h' || token === '--help') { + options.help = true; + continue; + } + if (token === '--materialize') { + options.materialize = true; + continue; + } + if (token === '--no-materialize') { + options.materialize = false; + continue; + } + if (['--repo-root', '--repo', '--policy', '--cost-rollup', '--output'].includes(token)) { + if (!next || next.startsWith('-')) { + throw new Error(`Missing value for ${token}.`); + } + index += 1; + if (token === '--repo-root') options.repoRoot = next; + if (token === '--repo') options.repo = next; + if (token === '--policy') options.policyPath = next; + if (token === '--cost-rollup') options.costRollupPath = next; + if (token === '--output') options.outputPath = next; + continue; + } + throw new Error(`Unknown option: ${token}`); + } + + return options; +} + +function loadPolicy(repoRoot, policyPath) { + const resolvedPolicyPath = path.resolve(repoRoot, policyPath || DEFAULT_POLICY_PATH); + const payload = readJson(resolvedPolicyPath); + if (normalizeText(payload?.schema) !== POLICY_SCHEMA) { + throw new Error(`Treasury control plane policy must remain ${POLICY_SCHEMA}.`); + } + return { + resolvedPolicyPath, + policy: payload + }; +} + +function chooseTargetRepository(repo, rollup) { + return asOptional(repo) || asOptional(rollup?.repository) || null; +} + +function summarizeBillingWindow(rollup) { + const billingWindow = rollup?.billingWindow; + const invoiceTurn = rollup?.summary?.provenance?.invoiceTurn; + if (!billingWindow || typeof billingWindow !== 'object') { + return null; + } + const prepaidUsd = toNonNegativeNumber(billingWindow.prepaidUsd) ?? toNonNegativeNumber(invoiceTurn?.prepaidUsd); + const tokenSpendUsd = toNonNegativeNumber(rollup?.summary?.metrics?.totalUsd) ?? 0; + const remainingUsd = + toNonNegativeNumber(rollup?.summary?.metrics?.estimatedPrepaidUsdRemaining) ?? + (prepaidUsd != null ? roundUsd(prepaidUsd - tokenSpendUsd) : null); + return { + invoiceTurnId: asOptional(billingWindow.invoiceTurnId) ?? asOptional(invoiceTurn?.invoiceTurnId), + invoiceId: asOptional(billingWindow.invoiceId) ?? asOptional(invoiceTurn?.invoiceId), + fundingPurpose: asOptional(billingWindow.fundingPurpose) ?? asOptional(invoiceTurn?.fundingPurpose), + activationState: asOptional(billingWindow.activationState) ?? asOptional(invoiceTurn?.activationState), + prepaidUsd, + tokenSpendUsd, + remainingUsd, + pricingBasis: asOptional(billingWindow.pricingBasis) ?? asOptional(invoiceTurn?.pricingBasis), + selectionMode: asOptional(billingWindow?.selection?.mode), + selectionReason: asOptional(billingWindow?.selection?.reason) + }; +} + +function summarizeReservedFundingWindows(rollup, policy, billingWindowInvoiceTurnId) { + const reservedPurposes = Array.isArray(policy.reservedFundingPurposes) + ? policy.reservedFundingPurposes.map((entry) => normalizeText(entry).toLowerCase()).filter(Boolean) + : ['calibration']; + const reservedActivationStates = Array.isArray(policy.reservedActivationStates) + ? policy.reservedActivationStates.map((entry) => normalizeText(entry).toLowerCase()).filter(Boolean) + : ['hold']; + const invoiceTurns = Array.isArray(rollup?.summary?.provenance?.invoiceTurns) + ? rollup.summary.provenance.invoiceTurns + : []; + const reservedWindows = invoiceTurns + .filter((entry) => { + const fundingPurpose = normalizeText(entry?.fundingPurpose).toLowerCase(); + const activationState = normalizeText(entry?.activationState).toLowerCase(); + const invoiceTurnId = asOptional(entry?.invoiceTurnId); + return reservedPurposes.includes(fundingPurpose) + && reservedActivationStates.includes(activationState) + && invoiceTurnId + && invoiceTurnId !== billingWindowInvoiceTurnId; + }) + .map((entry) => ({ + invoiceTurnId: asOptional(entry.invoiceTurnId), + invoiceId: asOptional(entry.invoiceId), + fundingPurpose: asOptional(entry.fundingPurpose), + activationState: asOptional(entry.activationState), + prepaidUsd: toNonNegativeNumber(entry.prepaidUsd), + operatorNote: asOptional(entry.operatorNote) + })); + + return { + count: reservedWindows.length, + totalReservedUsd: + roundUsd(reservedWindows.reduce((sum, entry) => sum + (Number(entry.prepaidUsd ?? 0) || 0), 0)) ?? 0, + windows: reservedWindows + }; +} + +function summarizeAccountBalance(rollup) { + const metrics = rollup?.summary?.metrics ?? {}; + const accountBalance = rollup?.summary?.provenance?.accountBalance ?? {}; + const totalCredits = toNonNegativeNumber(metrics.accountBalanceTotalCredits ?? accountBalance?.totalCredits); + const usedCredits = toNonNegativeNumber(metrics.accountBalanceUsedCredits ?? accountBalance?.usedCredits); + const remainingCredits = toNonNegativeNumber( + metrics.accountBalanceRemainingCredits ?? accountBalance?.remainingCredits + ); + const unitPriceUsd = + toNonNegativeNumber(rollup?.summary?.provenance?.invoiceTurn?.unitPriceUsd) ?? + toNonNegativeNumber(rollup?.billingWindow?.credits?.unitPriceUsd); + const remainingUsdEstimate = + remainingCredits != null && unitPriceUsd != null ? roundUsd(remainingCredits * unitPriceUsd) : null; + + if (totalCredits == null && usedCredits == null && remainingCredits == null && remainingUsdEstimate == null) { + return null; + } + + return { + totalCredits, + usedCredits, + remainingCredits, + unitPriceUsd, + remainingUsdEstimate, + sourceKind: asOptional(accountBalance?.sourceKind), + sourcePathEvidence: asOptional(accountBalance?.sourcePathEvidence), + operatorNote: asOptional(accountBalance?.operatorNote) + }; +} + +function evaluateAccountBalanceFreshness(rollup, policy, now) { + const accountBalance = rollup?.summary?.provenance?.accountBalance ?? {}; + const snapshotAt = asOptional(accountBalance?.snapshotAt); + const snapshotTimestamp = toTimestamp(snapshotAt); + const maxAgeHours = toPositiveInteger(policy?.thresholds?.accountBalanceMaxAgeHours) ?? 24; + if (snapshotTimestamp == null) { + return { + status: 'unknown', + blocker: createBlocker( + 'account-balance-snapshot-missing', + 'Treasury requires account-balance snapshotAt evidence to enforce safe spend.', + asOptional(accountBalance?.sourcePathEvidence) + ) + }; + } + + const ageHours = Math.max(0, (now.getTime() - snapshotTimestamp) / (60 * 60 * 1000)); + if (ageHours > maxAgeHours) { + return { + status: 'stale', + ageHours: roundUsd(ageHours), + maxAgeHours, + blocker: createBlocker( + 'account-balance-stale', + `Treasury requires account-balance evidence no older than ${maxAgeHours}h; current snapshot age is ${roundUsd(ageHours)}h.`, + asOptional(accountBalance?.sourcePathEvidence) || snapshotAt + ) + }; + } + + return { + status: 'fresh', + ageHours: roundUsd(ageHours), + maxAgeHours, + blocker: null + }; +} + +function summarizeOperationalHeadroom(accountBalance, reservedFunding, policy) { + const reservedUsd = toNonNegativeNumber(reservedFunding?.totalReservedUsd) ?? 0; + const accountRemainingUsdEstimate = toNonNegativeNumber(accountBalance?.remainingUsdEstimate); + const reserveNearOperationalHeadroomUsd = + toNonNegativeNumber(policy?.thresholds?.reserveNearOperationalHeadroomUsd) ?? 100; + + if (accountRemainingUsdEstimate == null) { + return { + accountRemainingUsdEstimate: null, + operationalHeadroomUsd: null, + operationalHeadroomStatus: 'unknown', + possibleOperationalHeadroomUpperBoundUsd: null, + basis: 'missing-account-balance' + }; + } + + const operationalHeadroomUsd = roundUsd(Math.max(accountRemainingUsdEstimate - reservedUsd, 0)) ?? 0; + const operationalHeadroomStatus = + operationalHeadroomUsd <= 0 + ? 'reserve-protected-only' + : operationalHeadroomUsd <= reserveNearOperationalHeadroomUsd + ? 'reserve-near' + : 'healthy'; + + return { + accountRemainingUsdEstimate, + operationalHeadroomUsd, + operationalHeadroomStatus, + possibleOperationalHeadroomUpperBoundUsd: operationalHeadroomUsd, + basis: 'account-balance-minus-reserve' + }; +} + +function deriveOperatorBudgetState({ operatorBudgetCapUsd, operatorLaborObservedUsd, operatorLaborMissingTurnCount }) { + const observedRemainingUpperBoundUsd = + operatorBudgetCapUsd == null ? null : roundUsd(Math.max(0, operatorBudgetCapUsd - operatorLaborObservedUsd)); + const observedRemainingStatus = + operatorBudgetCapUsd == null ? 'unknown' : operatorLaborMissingTurnCount > 0 ? 'upper-bound' : 'observed'; + const spendableStatus = + operatorBudgetCapUsd == null ? 'unknown' : operatorLaborMissingTurnCount > 0 ? 'unreconciled' : 'observed'; + const spendableUsd = spendableStatus === 'observed' ? observedRemainingUpperBoundUsd : null; + + return { + operatorBudgetCapUsd, + operatorBudgetObservedRemainingUpperBoundUsd: observedRemainingUpperBoundUsd, + operatorBudgetObservedRemainingStatus: observedRemainingStatus, + operatorBudgetRemainingLowerBoundUsd: spendableStatus === 'observed' ? observedRemainingUpperBoundUsd : null, + operatorBudgetRemainingStatus: spendableStatus === 'observed' ? 'observed' : 'unknown', + operatorBudgetSpendableUsd: spendableUsd, + operatorBudgetSpendableStatus: spendableStatus + }; +} + +function deriveBudgetPressureState({ + blockers, + operationalHeadroomStatus, + operationalHeadroomUsd, + operatorBudgetSpendableStatus, + policy +}) { + const healthyOperationalHeadroomUsd = + toNonNegativeNumber(policy?.thresholds?.healthyOperationalHeadroomUsd) ?? 250; + if (Array.isArray(blockers) && blockers.length > 0) { + return 'blocked'; + } + if (operationalHeadroomStatus === 'reserve-protected-only') { + return 'stop-nonessential-spend'; + } + if (operationalHeadroomStatus === 'reserve-near') { + return 'tight'; + } + if (operationalHeadroomUsd == null || operatorBudgetSpendableStatus !== 'observed') { + return 'cautious'; + } + if (operationalHeadroomUsd < healthyOperationalHeadroomUsd) { + return 'cautious'; + } + return 'healthy'; +} + +function deriveSpendPolicyState(budgetPressureState) { + switch (budgetPressureState) { + case 'healthy': + return 'healthy'; + case 'cautious': + return 'cautious-delivery'; + case 'tight': + return 'core-delivery-only'; + case 'stop-nonessential-spend': + return 'reserve-protected-only'; + default: + return 'blocked'; + } +} + +function deriveControls({ + budgetPressureState, + operationalHeadroomUsd, + operatorBudgetSpendableStatus, + policy +}) { + const premiumThreshold = toNonNegativeNumber(policy?.thresholds?.premiumSaganMinimumOperationalHeadroomUsd) ?? 150; + const backgroundThreshold = + toNonNegativeNumber(policy?.thresholds?.backgroundFanoutMinimumOperationalHeadroomUsd) ?? 125; + const nonEssentialThreshold = + toNonNegativeNumber(policy?.thresholds?.nonEssentialWorkMinimumOperationalHeadroomUsd) ?? 100; + const healthyBackgroundMax = toPositiveInteger(policy?.limits?.healthyBackgroundSubagentsMax) ?? 2; + const cautiousBackgroundMax = toPositiveInteger(policy?.limits?.cautiousBackgroundSubagentsMax) ?? 1; + + const premiumEligible = + budgetPressureState === 'healthy' + && operatorBudgetSpendableStatus === 'observed' + && operationalHeadroomUsd != null + && operationalHeadroomUsd >= premiumThreshold; + const backgroundEligible = + (budgetPressureState === 'healthy' || budgetPressureState === 'cautious') + && operatorBudgetSpendableStatus === 'observed' + && operationalHeadroomUsd != null + && operationalHeadroomUsd >= backgroundThreshold; + const backgroundMax = !backgroundEligible + ? 0 + : budgetPressureState === 'healthy' + ? healthyBackgroundMax + : cautiousBackgroundMax; + const nonEssentialAllowed = + budgetPressureState === 'healthy' + && operationalHeadroomUsd != null + && operationalHeadroomUsd >= nonEssentialThreshold; + + return { + premiumSaganMode: { + allowed: premiumEligible, + requiresOperatorAuthorization: true, + requiresExplicitOperatorPrompt: true, + minimumOperationalHeadroomUsd: premiumThreshold, + estimatedFollowupAuthorizationsNeeded: + toPositiveInteger(policy?.limits?.premiumSaganFollowupAuthorizationsEstimate) ?? 1, + reason: premiumEligible ? 'budget-healthy' : `budget-${budgetPressureState}` + }, + backgroundFanout: { + allowed: backgroundEligible, + minimumOperationalHeadroomUsd: backgroundThreshold, + maximumConcurrentSubagents: backgroundMax, + reason: backgroundEligible ? `budget-${budgetPressureState}` : `budget-${budgetPressureState}` + }, + nonEssentialWork: { + allowed: nonEssentialAllowed, + minimumOperationalHeadroomUsd: nonEssentialThreshold, + reason: nonEssentialAllowed ? 'budget-healthy' : `budget-${budgetPressureState}` + } + }; +} + +function deriveOperationControls({ spendPolicyState, budgetPressureState, controls }) { + const coreDeliveryAllowed = + ['healthy', 'cautious-delivery', 'core-delivery-only'].includes(spendPolicyState) + && budgetPressureState !== 'blocked'; + const coreDeliveryReason = coreDeliveryAllowed + ? `policy-${spendPolicyState}` + : budgetPressureState === 'blocked' + ? 'treasury-blocked' + : `policy-${spendPolicyState}`; + + return { + [TREASURY_OPERATION.CORE_DELIVERY]: { + allowed: coreDeliveryAllowed, + reason: coreDeliveryReason + }, + [TREASURY_OPERATION.QUEUE_AUTHORITY]: { + allowed: coreDeliveryAllowed, + reason: coreDeliveryReason + }, + [TREASURY_OPERATION.RELEASE_APPLY]: { + allowed: coreDeliveryAllowed, + reason: coreDeliveryReason + }, + [TREASURY_OPERATION.BACKGROUND_FANOUT]: { + allowed: controls.backgroundFanout.allowed === true, + reason: controls.backgroundFanout.reason + }, + [TREASURY_OPERATION.NON_ESSENTIAL_WORK]: { + allowed: controls.nonEssentialWork.allowed === true, + reason: controls.nonEssentialWork.reason + }, + [TREASURY_OPERATION.PREMIUM_SAGAN]: { + allowed: controls.premiumSaganMode.allowed === true, + reason: controls.premiumSaganMode.reason, + requiresOperatorAuthorization: controls.premiumSaganMode.requiresOperatorAuthorization === true, + requiresExplicitOperatorPrompt: controls.premiumSaganMode.requiresExplicitOperatorPrompt === true, + estimatedFollowupAuthorizationsNeeded: + toPositiveInteger(controls.premiumSaganMode.estimatedFollowupAuthorizationsNeeded) ?? 1 + } + }; +} + +function normalizeTreasuryOperation(value) { + const normalized = asOptional(value)?.toLowerCase(); + return Object.values(TREASURY_OPERATION).includes(normalized) ? normalized : null; +} + +function buildAuthorizationEstimate(operationControl = {}) { + const requiresOperatorAuthorization = operationControl.requiresOperatorAuthorization === true; + const requiresExplicitOperatorPrompt = operationControl.requiresExplicitOperatorPrompt === true; + const estimatedFollowupAuthorizationsNeeded = + requiresOperatorAuthorization + ? toPositiveInteger(operationControl.estimatedFollowupAuthorizationsNeeded) ?? 1 + : 0; + + return { + requiresOperatorAuthorization, + requiresExplicitOperatorPrompt, + estimatedFollowupAuthorizationsNeeded + }; +} + +export function evaluateTreasuryOperation(report, operation) { + const normalizedOperation = normalizeTreasuryOperation(operation); + if (!normalizedOperation) { + return { + allowed: false, + operation: operation ?? null, + code: 'treasury-operation-unknown', + reason: 'Unknown treasury operation request.', + operationControl: null, + authorization: buildAuthorizationEstimate() + }; + } + + if (!report || typeof report !== 'object') { + return { + allowed: false, + operation: normalizedOperation, + code: 'treasury-report-missing', + reason: 'Treasury control plane report is missing.', + operationControl: null, + authorization: buildAuthorizationEstimate() + }; + } + + if (normalizeText(report.schema) !== REPORT_SCHEMA) { + return { + allowed: false, + operation: normalizedOperation, + code: 'treasury-schema-mismatch', + reason: `Treasury control plane report must remain ${REPORT_SCHEMA}.`, + operationControl: null, + authorization: buildAuthorizationEstimate() + }; + } + + const operationControl = report?.controls?.operations?.[normalizedOperation]; + const authorization = buildAuthorizationEstimate(operationControl); + if (!operationControl || typeof operationControl !== 'object') { + return { + allowed: false, + operation: normalizedOperation, + code: 'treasury-operation-missing', + reason: `Treasury control plane did not publish an operation control for ${normalizedOperation}.`, + operationControl: null, + authorization + }; + } + + if (operationControl.allowed !== true) { + return { + allowed: false, + operation: normalizedOperation, + code: 'treasury-operation-denied', + reason: + operationControl.reason + ? `Treasury denied ${normalizedOperation}: ${operationControl.reason}.` + : `Treasury denied ${normalizedOperation}.`, + operationControl, + authorization + }; + } + + return { + allowed: true, + operation: normalizedOperation, + code: 'treasury-operation-allowed', + reason: operationControl.reason || 'treasury-allowed', + operationControl, + authorization + }; +} + +function deriveConfidence({ blockers, sourceConflictCount, operationalHeadroomStatus, operatorBudgetSpendableStatus }) { + if (Array.isArray(blockers) && blockers.length > 0) { + return 'blocked'; + } + if ((sourceConflictCount ?? 0) > 0) { + return 'conflicted'; + } + if (operationalHeadroomStatus === 'unknown' || operatorBudgetSpendableStatus !== 'observed') { + return 'lower-bound-only'; + } + return 'observed'; +} + +function determineStatus(budgetPressureState) { + if (budgetPressureState === 'blocked') { + return 'blocked'; + } + return budgetPressureState === 'healthy' ? 'pass' : 'warn'; +} + +function determineRecommendation({ budgetPressureState, confidence }) { + switch (budgetPressureState) { + case 'blocked': + return 'repair-treasury-inputs'; + case 'stop-nonessential-spend': + return 'protect-calibration-reserve'; + case 'tight': + return 'constrain-spend-to-core-delivery'; + case 'cautious': + return confidence === 'lower-bound-only' + ? 'reconcile-budget-before-expanding-spend' + : 'stay-budget-cautious'; + default: + return 'treasury-control-plane-ready'; + } +} + +export function buildTreasuryControlPlaneReport({ + rollup, + repository, + operatorBudgetCapUsd, + reservedFunding, + billingWindow, + source, + blockers, + policy, + now +}) { + const metrics = rollup?.summary?.metrics ?? {}; + const tokenSpendUsd = toNonNegativeNumber(metrics.totalUsd) ?? 0; + const operatorLaborObservedUsd = toNonNegativeNumber(metrics.operatorLaborUsd) ?? 0; + const operatorLaborMissingTurnCount = Number(metrics.operatorLaborMissingTurnCount ?? 0) || 0; + const observedBlendedLowerBoundUsd = roundUsd(tokenSpendUsd + operatorLaborObservedUsd) ?? 0; + const knownBlendedUsd = toNonNegativeNumber(metrics.blendedTotalUsd); + const accountBalance = summarizeAccountBalance(rollup); + const operationalHeadroom = summarizeOperationalHeadroom(accountBalance, reservedFunding, policy); + const operatorBudget = deriveOperatorBudgetState({ + operatorBudgetCapUsd, + operatorLaborObservedUsd, + operatorLaborMissingTurnCount + }); + const sourceConflictCount = 0; + const confidence = deriveConfidence({ + blockers, + sourceConflictCount, + operationalHeadroomStatus: operationalHeadroom.operationalHeadroomStatus, + operatorBudgetSpendableStatus: operatorBudget.operatorBudgetSpendableStatus + }); + const budgetPressureState = deriveBudgetPressureState({ + blockers, + operationalHeadroomStatus: operationalHeadroom.operationalHeadroomStatus, + operationalHeadroomUsd: operationalHeadroom.operationalHeadroomUsd, + operatorBudgetSpendableStatus: operatorBudget.operatorBudgetSpendableStatus, + policy + }); + const spendPolicyState = deriveSpendPolicyState(budgetPressureState); + const controls = deriveControls({ + budgetPressureState, + operationalHeadroomUsd: operationalHeadroom.operationalHeadroomUsd, + operatorBudgetSpendableStatus: operatorBudget.operatorBudgetSpendableStatus, + policy + }); + const operationControls = deriveOperationControls({ + spendPolicyState, + budgetPressureState, + controls + }); + const safeSpendableUsd = Array.isArray(blockers) && blockers.length > 0 ? 0 : operationalHeadroom.operationalHeadroomUsd; + const possibleSpendableUpperBoundUsd = operationalHeadroom.possibleOperationalHeadroomUpperBoundUsd; + const protectedReserveUsd = toNonNegativeNumber(reservedFunding?.totalReservedUsd) ?? 0; + + return { + schema: REPORT_SCHEMA, + generatedAt: now.toISOString(), + repository, + summary: { + status: determineStatus(budgetPressureState), + recommendation: determineRecommendation({ budgetPressureState, confidence }), + confidence, + spendPolicyState, + budgetPressureState, + tokenSpendUsd, + operatorLaborObservedUsd, + operatorLaborMissingTurnCount, + observedBlendedLowerBoundUsd, + knownBlendedUsd, + protectedReserveUsd, + accountRemainingUsdEstimate: operationalHeadroom.accountRemainingUsdEstimate, + operationalHeadroomUsd: operationalHeadroom.operationalHeadroomUsd, + operationalHeadroomStatus: operationalHeadroom.operationalHeadroomStatus, + safeSpendableUsd, + possibleSpendableUpperBoundUsd, + sourceConflictCount, + operatorBudgetCapUsd: operatorBudget.operatorBudgetCapUsd, + operatorBudgetObservedRemainingUpperBoundUsd: operatorBudget.operatorBudgetObservedRemainingUpperBoundUsd, + operatorBudgetObservedRemainingStatus: operatorBudget.operatorBudgetObservedRemainingStatus, + operatorBudgetRemainingLowerBoundUsd: operatorBudget.operatorBudgetRemainingLowerBoundUsd, + operatorBudgetRemainingStatus: operatorBudget.operatorBudgetRemainingStatus, + operatorBudgetSpendableUsd: operatorBudget.operatorBudgetSpendableUsd, + operatorBudgetSpendableStatus: operatorBudget.operatorBudgetSpendableStatus, + coreDeliveryAllowed: operationControls[TREASURY_OPERATION.CORE_DELIVERY].allowed, + queueAuthorityAllowed: operationControls[TREASURY_OPERATION.QUEUE_AUTHORITY].allowed, + releaseApplyAllowed: operationControls[TREASURY_OPERATION.RELEASE_APPLY].allowed, + premiumSaganAllowed: controls.premiumSaganMode.allowed, + premiumAuthorizationPromptRequired: controls.premiumSaganMode.requiresExplicitOperatorPrompt === true, + premiumAuthorizationFollowupEstimate: + toPositiveInteger(controls.premiumSaganMode.estimatedFollowupAuthorizationsNeeded) ?? 1, + backgroundFanoutAllowed: controls.backgroundFanout.allowed, + maxBackgroundSubagents: controls.backgroundFanout.maximumConcurrentSubagents, + nonEssentialWorkAllowed: controls.nonEssentialWork.allowed, + calibrationReserveProtected: protectedReserveUsd > 0 + }, + turns: { + totalTurns: Number(metrics.totalTurns ?? 0) || 0, + liveTurnCount: Number(metrics.liveTurnCount ?? 0) || 0, + backgroundTurnCount: Number(metrics.backgroundTurnCount ?? 0) || 0 + }, + funding: { + billingWindow, + accountBalance, + reservedFunding + }, + controls: { + ...controls, + operations: operationControls + }, + source, + blockers: Array.isArray(blockers) ? blockers.filter(Boolean) : [] + }; +} + +export function runTreasuryControlPlane( + options, + { + now = new Date(), + readJsonFn = readJson, + writeJsonFn = writeJson, + runMaterializeAgentCostRollupFn = runMaterializeAgentCostRollup + } = {} +) { + const repoRoot = path.resolve(options.repoRoot || process.cwd()); + const { resolvedPolicyPath, policy } = loadPolicy(repoRoot, options.policyPath || DEFAULT_POLICY_PATH); + let costRollupPath = path.resolve( + repoRoot, + options.costRollupPath || asOptional(policy.costRollupPath) || path.join('tests', 'results', '_agent', 'cost', 'agent-cost-rollup.json') + ); + let costRollupMaterialized = false; + let costRollupMaterializationReportPath = null; + const blockers = []; + + const shouldMaterialize = options.materialize ?? Boolean(policy.materializeCostRollup); + if (shouldMaterialize) { + try { + const materializeResult = runMaterializeAgentCostRollupFn({ + repoRoot, + repo: options.repo, + policyPath: asOptional(policy.materializationPolicyPath) || undefined, + costRollupPath, + outputPath: asOptional(policy.materializationReportPath) || undefined + }); + costRollupMaterialized = true; + costRollupPath = path.resolve(materializeResult.costRollupPath || costRollupPath); + costRollupMaterializationReportPath = safeRelative(repoRoot, materializeResult.outputPath); + } catch (error) { + blockers.push(createBlocker('cost-rollup-materialization-failed', error?.message || String(error))); + } + } + + let rollup = null; + if (!fs.existsSync(costRollupPath)) { + blockers.push( + createBlocker('cost-rollup-missing', 'Agent cost rollup is missing.', safeRelative(repoRoot, costRollupPath)) + ); + } else { + try { + rollup = readJsonFn(costRollupPath); + if (normalizeText(rollup?.schema) !== 'priority/agent-cost-rollup@v1') { + blockers.push( + createBlocker( + 'cost-rollup-schema-mismatch', + 'Agent cost rollup schema must remain priority/agent-cost-rollup@v1.', + safeRelative(repoRoot, costRollupPath) + ) + ); + } + } catch (error) { + blockers.push( + createBlocker('cost-rollup-unreadable', error?.message || String(error), safeRelative(repoRoot, costRollupPath)) + ); + } + } + + if (rollup && typeof rollup === 'object') { + const accountBalanceFreshness = evaluateAccountBalanceFreshness(rollup, policy, now); + if (accountBalanceFreshness.blocker) { + blockers.push(accountBalanceFreshness.blocker); + } + } + + const billingWindow = summarizeBillingWindow(rollup); + const reservedFunding = summarizeReservedFundingWindows(rollup, policy, billingWindow?.invoiceTurnId ?? null); + const repository = chooseTargetRepository(options.repo, rollup); + const operatorBudgetCapUsd = toNonNegativeNumber(policy.operatorBudgetCapUsd); + const outputPath = path.resolve(repoRoot, options.outputPath || asOptional(policy.outputPath) || DEFAULT_OUTPUT_PATH); + + const report = buildTreasuryControlPlaneReport({ + rollup, + repository, + operatorBudgetCapUsd, + reservedFunding, + billingWindow, + source: { + policyPath: safeRelative(repoRoot, resolvedPolicyPath), + costRollupPath: safeRelative(repoRoot, costRollupPath), + costRollupMaterialized, + costRollupMaterializationReportPath, + operatorCostProfilePath: + asOptional(rollup?.summary?.provenance?.operatorProfiles?.[0]?.operatorProfilePath) || + 'tools/policy/operator-cost-profile.json', + outputPath: safeRelative(repoRoot, outputPath) + }, + blockers, + policy, + now + }); + + writeJsonFn(outputPath, report); + return { + report, + outputPath + }; +} + +export function runTreasuryOperationGuard( + options, + { + runTreasuryControlPlaneFn = runTreasuryControlPlane + } = {} +) { + const repoRoot = path.resolve(options?.repoRoot || process.cwd()); + let report = null; + let outputPath = null; + let decision = null; + + try { + const treasuryResult = runTreasuryControlPlaneFn({ + repoRoot, + repo: options?.repo, + policyPath: options?.policyPath, + costRollupPath: options?.costRollupPath, + outputPath: options?.outputPath, + materialize: options?.materialize + }); + report = treasuryResult?.report ?? null; + outputPath = treasuryResult?.outputPath ?? null; + decision = evaluateTreasuryOperation(report, options?.operation); + } catch (error) { + decision = { + allowed: false, + operation: normalizeTreasuryOperation(options?.operation), + code: 'treasury-control-plane-unavailable', + reason: error?.message || String(error), + operationControl: null, + authorization: buildAuthorizationEstimate() + }; + } + + return { + report, + outputPath, + decision + }; +} + +function printUsage() { + [ + 'Usage: node tools/priority/treasury-control-plane.mjs [options]', + '', + 'Builds the governed treasury control-plane receipt used by governor and comment projections.', + '', + ` --policy Treasury policy path (default: ${DEFAULT_POLICY_PATH}).`, + ' --repo-root Repository root (default: cwd).', + ' --repo Repository slug override.', + ' --cost-rollup Cost rollup path override.', + ` --output JSON report path (default: ${DEFAULT_OUTPUT_PATH}).`, + ' --materialize Force cost-rollup materialization before read.', + ' --no-materialize Skip cost-rollup materialization.', + ' -h, --help Show this message.' + ].forEach((line) => console.log(line)); +} + +if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { + try { + const options = parseArgs(process.argv); + if (options.help) { + printUsage(); + process.exit(0); + } + const result = runTreasuryControlPlane(options); + console.log(`[treasury-control-plane] wrote ${result.outputPath}`); + } catch (error) { + console.error(`[treasury-control-plane] ${error.message}`); + process.exit(1); + } +}