feat: book monthly AI-plan invoices as facts and commitments

Add ai-plan ingest that stores one current booked fact per
provider-account × plan × period. Subscriptions become recurring
commitments; usage top-ups do not. Session-level rows are rejected.
This commit is contained in:
tegwick 2026-08-15 19:09:14 +02:00
parent 38d0bf21c9
commit ce4f791a63
11 changed files with 511 additions and 5 deletions

View file

@ -8,7 +8,11 @@ from pathlib import Path
from fin_hub.coupling.canon import emit_viability_alert
from fin_hub.coupling.dev_hub import emit_resource_pressure
from fin_hub.services.alerts import evaluate_budget_alerts
from fin_hub.services.ledger import get_opening_balance, monthly_burn_series
from fin_hub.services.ledger import (
get_opening_balance,
list_current_commitments,
monthly_burn_series,
)
from fin_hub.services.runway import compute_runway
@ -30,6 +34,13 @@ def evaluate_runway(
effective_currency = currency or stored_currency
burns = monthly_burn_series(ledger_path=ledger_path, currency=effective_currency)
commitments = list_current_commitments(
ledger_path=ledger_path, currency=effective_currency
)
if not burns:
committed = sum((float(item.amount) for item in commitments), 0.0)
if committed > 0:
burns = [committed]
runway = compute_runway(
current_balance=balance,
monthly_burns=burns,
@ -42,6 +53,7 @@ def evaluate_runway(
"runway": runway.as_dict(),
"alerts": [alert.as_dict() for alert in alerts],
"monthly_burns": burns,
"commitments": [item.as_dict() for item in commitments],
"ledger_path": str(ledger_path.resolve()),
}