Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion docs/knowledgebase/Agent-Cost-Telemetry-Surfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,10 @@ The hook projects:
- observed operator-equivalent labor
- observed blended lower-bound spend
- operator budget cap / remaining lower bound
- operational invoice-turn remainder
- operator budget spendable status
- active invoice-turn remainder
- whole-account remaining USD estimate from the latest credit snapshot
- operational headroom after protected reserve
- reserved calibration funding window state
- live/background/total turn counts

Expand All @@ -296,6 +299,11 @@ consuming it. The current intent is:
- operational invoice turn may spend
- calibration invoice turn remains on hold

When operator labor timing is incomplete, the hook still records the lower-bound
cap math but marks spendable operator remaining as unreconciled. That prevents
the comment trail from implying the full configured operator cap is immediately
safe to spend.

Use the wrappers by default so GitHub issue and PR comments pick up the durable
budget hook automatically. Pass `-SkipBudgetHook` only for narrow test or
break-glass cases where the attestation must be suppressed deliberately.
Expand Down
33 changes: 30 additions & 3 deletions docs/schemas/github-comment-budget-hook-report-v1.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@
"knownBlendedUsd",
"operatorBudgetCapUsd",
"operatorBudgetRemainingLowerBoundUsd",
"operatorBudgetRemainingStatus"
"operatorBudgetRemainingStatus",
"operatorBudgetSpendableUsd",
"operatorBudgetSpendableStatus",
"accountRemainingUsdEstimate",
"operationalHeadroomUsd",
"operationalHeadroomStatus",
"budgetPressureState"
],
"properties": {
"status": { "type": "string", "enum": ["pass", "warn", "blocked"] },
Expand All @@ -53,7 +59,13 @@
"knownBlendedUsd": { "type": ["number", "null"], "minimum": 0 },
"operatorBudgetCapUsd": { "type": ["number", "null"], "minimum": 0 },
"operatorBudgetRemainingLowerBoundUsd": { "type": ["number", "null"], "minimum": 0 },
"operatorBudgetRemainingStatus": { "type": "string", "enum": ["observed", "lower-bound", "unknown"] }
"operatorBudgetRemainingStatus": { "type": "string", "enum": ["observed", "lower-bound", "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"] },
"budgetPressureState": { "type": "string", "enum": ["healthy", "cautious", "tight", "stop-nonessential-spend", "blocked"] }
}
},
"turns": {
Expand All @@ -69,7 +81,7 @@
"funding": {
"type": "object",
"additionalProperties": false,
"required": ["billingWindow", "reservedFunding"],
"required": ["billingWindow", "accountBalance", "reservedFunding"],
"properties": {
"billingWindow": {
"type": ["object", "null"],
Expand All @@ -88,6 +100,21 @@
"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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,21 @@ test('github-comment-budget-hook report and policy validate against checked-in s
operatorLaborUsd: 4,
operatorLaborMissingTurnCount: 0,
blendedTotalUsd: 5.5,
estimatedPrepaidUsdRemaining: 398.5
estimatedPrepaidUsdRemaining: 398.5,
accountBalanceTotalCredits: 28750,
accountBalanceUsedCredits: 24600,
accountBalanceRemainingCredits: 4150
},
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: []
}
},
Expand Down
24 changes: 23 additions & 1 deletion tools/priority/__tests__/github-comment-budget-hook.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,25 @@ function createRollupFixture() {
operatorLaborUsd: 30,
operatorLaborMissingTurnCount: 1,
blendedTotalUsd: null,
estimatedPrepaidUsdRemaining: 387.5
estimatedPrepaidUsdRemaining: 387.5,
accountBalanceTotalCredits: 28750,
accountBalanceUsedCredits: 24600,
accountBalanceRemainingCredits: 4150
},
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',
Expand Down Expand Up @@ -134,12 +145,23 @@ test('runGitHubCommentBudgetHook emits a durable lower-bound budget hook with re
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.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.budgetPressureState, 'tight');
assert.equal(result.report.turns.backgroundTurnCount, 2);
assert.equal(result.report.funding.accountBalance.remainingCredits, 4150);
assert.equal(result.report.funding.accountBalance.remainingUsdEstimate, 166);
assert.equal(result.report.funding.reservedFunding.count, 1);
assert.equal(result.report.funding.reservedFunding.totalReservedUsd, 100);
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, /calibration reserve \$100\.000000/);
});
26 changes: 26 additions & 0 deletions tools/priority/__tests__/materialize-agent-cost-rollup.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,13 @@ function setupMaterializationFixture() {
path.join(donorRoot, 'tests', 'results', '_agent', 'cost', 'invoice-turns', 'HQ1VJLMV-0027.local.json'),
createInvoiceTurnPayload()
);
writeJson(
path.join(donorRoot, 'tests', 'results', '_agent', 'cost', 'invoice-turns', 'HQ1VJLMV-0027.metadata.local.json'),
{
schema: 'priority/agent-cost-private-invoice-metadata@v1',
invoiceId: 'HQ1VJLMV-0027'
}
);
writeJson(
path.join(donorRoot, 'tests', 'results', '_agent', 'cost', 'usage-exports', 'usage-export-2026-03-15.json'),
createUsageExportPayload()
Expand All @@ -224,6 +231,17 @@ function setupMaterializationFixture() {
path.join(donorRoot, 'tests', 'results', '_agent', 'cost', 'account-balances', 'account-balance-2026-03-21.json'),
createAccountBalancePayload()
);
writeJson(
path.join(donorRoot, 'tests', 'results', '_agent', 'cost', 'account-balances', 'account-balance-2026-03-21.private.local.json'),
{
schema: 'priority/agent-cost-private-account-balance@v1',
balances: {
totalCredits: 27500,
usedCredits: 15800,
remainingCredits: 11700
}
}
);

return { repoRoot };
}
Expand All @@ -245,6 +263,14 @@ test('runMaterializeAgentCostRollup materializes a heuristic turn and rollup in
assert.equal(result.report.syncedReceipts.invoiceTurns.materializedCount, 1);
assert.equal(result.report.syncedReceipts.usageExports.materializedCount, 1);
assert.equal(result.report.syncedReceipts.accountBalances.materializedCount, 1);
assert.equal(
result.report.syncedReceipts.invoiceTurns.files.some((entry) => entry.fileName.includes('.metadata.')),
false
);
assert.equal(
result.report.syncedReceipts.accountBalances.files.some((entry) => entry.fileName.includes('.private.')),
false
);
assert.equal(result.report.heuristicTurn.requestedModel, 'gpt-5.4');
assert.equal(fs.existsSync(result.outputPath), true);
assert.equal(fs.existsSync(result.costRollupPath), true);
Expand Down
Loading
Loading