Add shared cost allocation reporting
This commit is contained in:
parent
a28a40dfe9
commit
b75ad06b3a
9 changed files with 348 additions and 15 deletions
|
|
@ -2,7 +2,7 @@
|
|||
# Custodian Brief — fin-hub
|
||||
|
||||
**Domain:** financials
|
||||
**Last synced:** 2026-08-11 08:37 UTC
|
||||
**Last synced:** 2026-08-11 09:04 UTC
|
||||
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
|
||||
|
||||
## Active Workstreams
|
||||
|
|
@ -16,12 +16,11 @@ Progress: 6/9 done | workplan_id: `67b6de6c-4820-4478-9789-f50260204c27`
|
|||
- · T06 — Generalize and operate the contract `a1309d51`
|
||||
|
||||
### Client attribution and billing basis
|
||||
Progress: 3/6 done | workplan_id: `ebc1d2de-ae11-4cde-b860-047922fc74b9`
|
||||
Progress: 4/6 done | workplan_id: `ebc1d2de-ae11-4cde-b860-047922fc74b9`
|
||||
|
||||
**Open tasks:**
|
||||
- ! Export a per-client billing basis `b5886131`
|
||||
- ! Select the external invoicing system `d30b606f`
|
||||
- · Define shared-infrastructure allocation `899a5c29`
|
||||
- · Export a per-client billing basis `b5886131`
|
||||
|
||||
---
|
||||
## MCP Orientation (when available)
|
||||
|
|
|
|||
10
README.md
10
README.md
|
|
@ -24,6 +24,7 @@ uv run finhub runway --balance 12000 --monthly-burn 2100,2200,2000
|
|||
uv run finhub ledger import cloud tests/fixtures/cloud-costs.csv
|
||||
uv run finhub ledger set-price --client acme --application portal --instance prod-01 --period 2026-07 --amount 100 --source agreement-2026-01
|
||||
uv run finhub ledger margins
|
||||
uv run finhub ledger allocations
|
||||
uv run finhub evaluate
|
||||
uv run finhub evidence --seed-fixtures
|
||||
uv run finhub serve
|
||||
|
|
@ -68,6 +69,15 @@ allocations, optimization cases, and commitment candidates outside booked
|
|||
spend. `ingest_resource_forecast` adapts resource-control's v0.1 monthly backup
|
||||
forecast without inventing resource identity.
|
||||
|
||||
Shared-infrastructure allocation remains authoritative in resource-control.
|
||||
Fin-hub's `ledger allocations` command consumes current `AllocationEvidence`,
|
||||
requires every referenced financial fact to be current and uniquely claimed,
|
||||
checks period/environment/currency and booked totals, and calculates target and
|
||||
residual amounts in integer minor units. The producer-supplied versioned method
|
||||
and provenance remain visible. Deterministic largest-remainder rounding makes
|
||||
all target amounts plus the explicit unattributed residual reconcile exactly
|
||||
to booked cost.
|
||||
|
||||
## Related Workplans
|
||||
|
||||
- `the-custodian/workplans/CUST-WP-0025-fos-hub-bootstrap.md` — umbrella
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@
|
|||
| task | FIN-WP-0002-T00 | done | — | workplans/FIN-WP-0002-client-attribution-and-billing-basis.md |
|
||||
| task | FIN-WP-0002-T01 | done | — | workplans/FIN-WP-0002-client-attribution-and-billing-basis.md |
|
||||
| task | FIN-WP-0002-T02 | done | — | workplans/FIN-WP-0002-client-attribution-and-billing-basis.md |
|
||||
| task | FIN-WP-0002-T03 | todo | — | workplans/FIN-WP-0002-client-attribution-and-billing-basis.md |
|
||||
| task | FIN-WP-0002-T04 | wait | — | workplans/FIN-WP-0002-client-attribution-and-billing-basis.md |
|
||||
| task | FIN-WP-0002-T03 | done | — | workplans/FIN-WP-0002-client-attribution-and-billing-basis.md |
|
||||
| task | FIN-WP-0002-T04 | todo | — | workplans/FIN-WP-0002-client-attribution-and-billing-basis.md |
|
||||
| task | FIN-WP-0002-T05 | wait | — | workplans/FIN-WP-0002-client-attribution-and-billing-basis.md |
|
||||
| task | FIN-WP-0003-T01 | todo | — | workplans/FIN-WP-0003-fabric-authority-boundary.md |
|
||||
| task | FIN-WP-0003-T02 | todo | — | workplans/FIN-WP-0003-fabric-authority-boundary.md |
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
| task | FIN-WP-0004-T02 | done | — | workplans/FIN-WP-0004-resource-cost-evidence-contract.md |
|
||||
| task | FIN-WP-0004-T03 | done | — | workplans/FIN-WP-0004-resource-cost-evidence-contract.md |
|
||||
| task | FIN-WP-0004-T04 | todo | — | workplans/FIN-WP-0004-resource-cost-evidence-contract.md |
|
||||
| task | FIN-WP-0004-T05 | todo | — | workplans/FIN-WP-0004-resource-cost-evidence-contract.md |
|
||||
| task | FIN-WP-0004-T05 | wait | — | workplans/FIN-WP-0004-resource-cost-evidence-contract.md |
|
||||
| task | FIN-WP-0004-T06 | todo | — | workplans/FIN-WP-0004-resource-cost-evidence-contract.md |
|
||||
| task | FIN-WP-0004-T07 | done | — | workplans/FIN-WP-0004-resource-cost-evidence-contract.md |
|
||||
| task | FIN-WP-0004-T08 | done | — | workplans/FIN-WP-0004-resource-cost-evidence-contract.md |
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Fin-hub ↔ resource-control authority contract v0.1
|
||||
|
||||
Status: authority boundary reviewed; v0.1 implementation acceptance pending
|
||||
Status: v0.1 ratified; operational booked-cost round trip pending
|
||||
|
||||
Owners: `fin-hub` / `resource-control`
|
||||
|
||||
|
|
@ -176,8 +176,9 @@ reference the current record of the same type. Fin-hub stores these in
|
|||
|
||||
## Acceptance status
|
||||
|
||||
Resource-control accepted the authority boundary in principle on 2026-08-11.
|
||||
The review is preserved at
|
||||
Resource-control ratified the v0.1 authority and schema contract on 2026-08-11
|
||||
after cross-repository preflight matched and idempotently replayed all 12
|
||||
current backup forecast records. The review is preserved at
|
||||
`history/2026-08-11-resource-control-review-fin-wp-0004.md`. Contract v0.1 is
|
||||
not accepted until the implementation-integrity tasks and reconciled backup
|
||||
round trip pass.
|
||||
implemented; operational acceptance remains gated by the first real provider
|
||||
fact and reconciled backup round trip in `FIN-WP-0004-T05`.
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from fin_hub.ingest.anthropic import parse_anthropic_billing_csv
|
|||
from fin_hub.ingest.cloud import parse_cloud_cost_csv
|
||||
from fin_hub.ingest.hosteurope import parse_hosteurope_csv
|
||||
from fin_hub.services.alerts import evaluate_budget_alerts
|
||||
from fin_hub.services.allocation import shared_cost_allocations
|
||||
from fin_hub.services.evaluate import evaluate_runway
|
||||
from fin_hub.services.evidence import write_runway_evidence
|
||||
from fin_hub.services.ledger import (
|
||||
|
|
@ -149,6 +150,12 @@ def _cmd_ledger_margins(args: argparse.Namespace) -> int:
|
|||
return 0
|
||||
|
||||
|
||||
def _cmd_ledger_allocations(args: argparse.Namespace) -> int:
|
||||
reports = shared_cost_allocations(ledger_path=_ledger_path(args))
|
||||
print(json.dumps([report.as_dict() for report in reports], indent=2, default=str))
|
||||
return 0
|
||||
|
||||
|
||||
def _cmd_evaluate(args: argparse.Namespace) -> int:
|
||||
report = evaluate_runway(
|
||||
ledger_path=_ledger_path(args),
|
||||
|
|
@ -261,6 +268,13 @@ def build_parser() -> argparse.ArgumentParser:
|
|||
ledger_margins.add_argument("--ledger", help="Ledger database path")
|
||||
ledger_margins.set_defaults(func=_cmd_ledger_margins)
|
||||
|
||||
ledger_allocations = ledger_sub.add_parser(
|
||||
"allocations",
|
||||
help="Reconcile resource-control allocation evidence to booked facts",
|
||||
)
|
||||
ledger_allocations.add_argument("--ledger", help="Ledger database path")
|
||||
ledger_allocations.set_defaults(func=_cmd_ledger_allocations)
|
||||
|
||||
evaluate = sub.add_parser(
|
||||
"evaluate",
|
||||
help="Evaluate runway from ledger burns (cron/systemd friendly)",
|
||||
|
|
|
|||
162
src/fin_hub/services/allocation.py
Normal file
162
src/fin_hub/services/allocation.py
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
"""Consume authoritative technical allocation evidence for financial reporting."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from dataclasses import asdict, dataclass
|
||||
from datetime import date
|
||||
from decimal import Decimal, ROUND_FLOOR
|
||||
from pathlib import Path
|
||||
|
||||
from fin_hub.money import MONEY_QUANTUM, minor_money, money_minor
|
||||
from fin_hub.schemas.exchange import AllocationEvidence
|
||||
from fin_hub.services.exchange import _ensure_planning_schema
|
||||
from fin_hub.services.ledger import _connect, default_ledger_path
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AllocatedTarget:
|
||||
target_key: str
|
||||
share: Decimal
|
||||
amount: Decimal
|
||||
rounding_adjustment: Decimal
|
||||
|
||||
def as_dict(self) -> dict:
|
||||
return asdict(self)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AllocationReport:
|
||||
allocation_id: str
|
||||
method: str
|
||||
financial_fact_ids: tuple[str, ...]
|
||||
period_start: date
|
||||
period_end: date
|
||||
environment: str | None
|
||||
currency: str
|
||||
booked_amount: Decimal
|
||||
targets: tuple[AllocatedTarget, ...]
|
||||
residual_share: Decimal
|
||||
residual_amount: Decimal
|
||||
residual_rounding_adjustment: Decimal
|
||||
source_evidence: tuple[str, ...]
|
||||
|
||||
def as_dict(self) -> dict:
|
||||
return asdict(self)
|
||||
|
||||
|
||||
def _split_minor_units(
|
||||
total_minor: int,
|
||||
shares: list[tuple[str, Decimal]],
|
||||
) -> dict[str, tuple[int, Decimal]]:
|
||||
"""Allocate exact minor units with deterministic largest-remainder rounding."""
|
||||
|
||||
floors: dict[str, int] = {}
|
||||
fractions: list[tuple[Decimal, str]] = []
|
||||
for key, share in shares:
|
||||
exact = Decimal(total_minor) * share
|
||||
floor = int(exact.to_integral_value(rounding=ROUND_FLOOR))
|
||||
floors[key] = floor
|
||||
fractions.append((exact - Decimal(floor), key))
|
||||
remainder = total_minor - sum(floors.values())
|
||||
for _fraction, key in sorted(fractions, key=lambda item: (-item[0], item[1]))[:remainder]:
|
||||
floors[key] += 1
|
||||
return {
|
||||
key: (
|
||||
floors[key],
|
||||
Decimal(floors[key]) - (Decimal(total_minor) * share),
|
||||
)
|
||||
for key, share in shares
|
||||
}
|
||||
|
||||
|
||||
def shared_cost_allocations(*, ledger_path: Path | None = None) -> list[AllocationReport]:
|
||||
"""Reconcile current allocation evidence to current booked facts."""
|
||||
|
||||
ledger = ledger_path or default_ledger_path()
|
||||
with _connect(ledger) as conn:
|
||||
_ensure_planning_schema(conn)
|
||||
allocation_rows = conn.execute(
|
||||
"SELECT payload_json FROM planning_evidence "
|
||||
"WHERE record_type = 'allocation' AND is_current = 1 ORDER BY record_id"
|
||||
).fetchall()
|
||||
claimed_facts: dict[str, str] = {}
|
||||
reports: list[AllocationReport] = []
|
||||
for allocation_row in allocation_rows:
|
||||
allocation = AllocationEvidence.model_validate_json(
|
||||
allocation_row["payload_json"]
|
||||
)
|
||||
duplicate_ids = {
|
||||
fact_id
|
||||
for fact_id in allocation.financial_fact_ids
|
||||
if allocation.financial_fact_ids.count(fact_id) > 1
|
||||
}
|
||||
if duplicate_ids:
|
||||
raise ValueError(f"allocation repeats financial facts: {sorted(duplicate_ids)}")
|
||||
fact_rows = []
|
||||
for fact_id in allocation.financial_fact_ids:
|
||||
owner = claimed_facts.get(fact_id)
|
||||
if owner is not None:
|
||||
raise ValueError(
|
||||
f"financial fact {fact_id} is allocated by both {owner} "
|
||||
f"and {allocation.record_id}"
|
||||
)
|
||||
fact = conn.execute(
|
||||
"SELECT * FROM ledger_entries "
|
||||
"WHERE financial_fact_id = ? AND is_current = 1",
|
||||
(fact_id,),
|
||||
).fetchone()
|
||||
if fact is None:
|
||||
raise ValueError(f"allocation references missing/current fact {fact_id}")
|
||||
if fact["currency"] != allocation.currency:
|
||||
raise ValueError(f"allocation currency does not match fact {fact_id}")
|
||||
if allocation.environment and fact["environment"] != allocation.environment:
|
||||
raise ValueError(f"allocation environment does not match fact {fact_id}")
|
||||
fact_period = date.fromisoformat(f"{fact['period_month']}-01")
|
||||
if not (allocation.period_start <= fact_period <= allocation.period_end):
|
||||
raise ValueError(f"allocation period does not include fact {fact_id}")
|
||||
claimed_facts[fact_id] = allocation.record_id
|
||||
fact_rows.append(fact)
|
||||
|
||||
total_minor = sum(int(row["amount_minor"]) for row in fact_rows)
|
||||
if total_minor != money_minor(allocation.allocated_amount):
|
||||
raise ValueError(
|
||||
f"allocation {allocation.record_id} amount does not reconcile "
|
||||
"to its current booked facts"
|
||||
)
|
||||
shares = [(share.target_key, share.share) for share in allocation.shares]
|
||||
if len({key for key, _share in shares}) != len(shares):
|
||||
raise ValueError("allocation target keys must be unique")
|
||||
residual_key = "__residual__"
|
||||
split = _split_minor_units(
|
||||
total_minor,
|
||||
[*shares, (residual_key, allocation.residual_share)],
|
||||
)
|
||||
targets = tuple(
|
||||
AllocatedTarget(
|
||||
target_key=key,
|
||||
share=share,
|
||||
amount=minor_money(split[key][0]),
|
||||
rounding_adjustment=(split[key][1] * MONEY_QUANTUM),
|
||||
)
|
||||
for key, share in shares
|
||||
)
|
||||
residual_minor, residual_adjustment = split[residual_key]
|
||||
reports.append(
|
||||
AllocationReport(
|
||||
allocation_id=allocation.record_id,
|
||||
method=allocation.method,
|
||||
financial_fact_ids=tuple(allocation.financial_fact_ids),
|
||||
period_start=allocation.period_start,
|
||||
period_end=allocation.period_end,
|
||||
environment=allocation.environment,
|
||||
currency=allocation.currency,
|
||||
booked_amount=minor_money(total_minor),
|
||||
targets=targets,
|
||||
residual_share=allocation.residual_share,
|
||||
residual_amount=minor_money(residual_minor),
|
||||
residual_rounding_adjustment=residual_adjustment * MONEY_QUANTUM,
|
||||
source_evidence=tuple(allocation.source_evidence),
|
||||
)
|
||||
)
|
||||
return reports
|
||||
129
tests/test_allocation.py
Normal file
129
tests/test_allocation.py
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
import sqlite3
|
||||
from decimal import Decimal
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from fin_hub.services.allocation import shared_cost_allocations
|
||||
from fin_hub.services.exchange import ingest_planning_evidence
|
||||
from fin_hub.services.ledger import import_csv
|
||||
|
||||
|
||||
def _booked_fact(tmp_path: Path, *, amount: str = "100.01", currency: str = "EUR"):
|
||||
ledger = tmp_path / "ledger.db"
|
||||
source = tmp_path / "shared.csv"
|
||||
source.write_text(
|
||||
"product,amount,currency,invoice_date,environment\n"
|
||||
f"Shared cluster,{amount},{currency},2026-07-01,production\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
import_csv(source, "hosteurope", ledger_path=ledger)
|
||||
with sqlite3.connect(ledger) as conn:
|
||||
fact_id = conn.execute(
|
||||
"SELECT financial_fact_id FROM ledger_entries WHERE is_current = 1"
|
||||
).fetchone()[0]
|
||||
return ledger, fact_id
|
||||
|
||||
|
||||
def _allocation(fact_id: str, **overrides) -> dict:
|
||||
payload = {
|
||||
"schema_version": "0.1",
|
||||
"record_type": "allocation",
|
||||
"record_id": "allocation:shared-cluster:2026-07:v1",
|
||||
"revision_of": None,
|
||||
"resource_id": "resource:shared_cluster",
|
||||
"service_id": "shared-cluster",
|
||||
"workload_id": None,
|
||||
"tenant_id": None,
|
||||
"environment": "production",
|
||||
"cost_attribution_key": "platform:shared-cluster",
|
||||
"period_start": "2026-07-01",
|
||||
"period_end": "2026-07-31",
|
||||
"currency": "EUR",
|
||||
"source_evidence": ["resource-control:allocation:namespace-cpu-v1"],
|
||||
"created_at": "2026-08-11T09:00:00Z",
|
||||
"financial_fact_ids": [fact_id],
|
||||
"method": "namespace-cpu-v1",
|
||||
"allocated_amount": "100.01",
|
||||
"shares": [
|
||||
{"target_key": "client:acme|app:portal|instance:prod-01", "share": "0.3333"},
|
||||
{"target_key": "client:beta|app:portal|instance:prod-01", "share": "0.3333"},
|
||||
],
|
||||
"residual_share": "0.3334",
|
||||
}
|
||||
payload.update(overrides)
|
||||
return payload
|
||||
|
||||
|
||||
def test_shared_allocation_reconciles_targets_rounding_and_residual(tmp_path: Path):
|
||||
ledger, fact_id = _booked_fact(tmp_path)
|
||||
ingest_planning_evidence(_allocation(fact_id), ledger_path=ledger)
|
||||
|
||||
report = shared_cost_allocations(ledger_path=ledger)[0]
|
||||
|
||||
assert report.booked_amount == Decimal("100.01")
|
||||
assert sum((target.amount for target in report.targets), report.residual_amount) == Decimal(
|
||||
"100.01"
|
||||
)
|
||||
assert report.residual_amount > Decimal("0")
|
||||
assert report.method == "namespace-cpu-v1"
|
||||
assert report.source_evidence
|
||||
|
||||
|
||||
def test_revised_allocation_supersedes_prior_shares(tmp_path: Path):
|
||||
ledger, fact_id = _booked_fact(tmp_path)
|
||||
original = _allocation(fact_id)
|
||||
ingest_planning_evidence(original, ledger_path=ledger)
|
||||
revised = _allocation(
|
||||
fact_id,
|
||||
record_id="allocation:shared-cluster:2026-07:v2",
|
||||
revision_of=original["record_id"],
|
||||
shares=[
|
||||
{"target_key": "client:acme|app:portal|instance:prod-01", "share": "0.75"}
|
||||
],
|
||||
residual_share="0.25",
|
||||
)
|
||||
ingest_planning_evidence(revised, ledger_path=ledger)
|
||||
|
||||
reports = shared_cost_allocations(ledger_path=ledger)
|
||||
|
||||
assert len(reports) == 1
|
||||
assert reports[0].allocation_id == revised["record_id"]
|
||||
assert reports[0].targets[0].share == Decimal("0.75")
|
||||
|
||||
|
||||
def test_allocation_rejects_missing_fact(tmp_path: Path):
|
||||
ledger = tmp_path / "ledger.db"
|
||||
ingest_planning_evidence(
|
||||
_allocation("fact:missing"),
|
||||
ledger_path=ledger,
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match="missing/current fact"):
|
||||
shared_cost_allocations(ledger_path=ledger)
|
||||
|
||||
|
||||
def test_allocation_rejects_currency_or_amount_mismatch(tmp_path: Path):
|
||||
ledger, fact_id = _booked_fact(tmp_path)
|
||||
ingest_planning_evidence(
|
||||
_allocation(fact_id, currency="USD"),
|
||||
ledger_path=ledger,
|
||||
)
|
||||
with pytest.raises(ValueError, match="currency"):
|
||||
shared_cost_allocations(ledger_path=ledger)
|
||||
|
||||
|
||||
def test_fact_cannot_be_allocated_twice(tmp_path: Path):
|
||||
ledger, fact_id = _booked_fact(tmp_path)
|
||||
first = _allocation(fact_id)
|
||||
second = _allocation(
|
||||
fact_id,
|
||||
record_id="allocation:duplicate",
|
||||
shares=[{"target_key": "client:acme", "share": "1"}],
|
||||
residual_share="0",
|
||||
)
|
||||
ingest_planning_evidence(first, ledger_path=ledger)
|
||||
ingest_planning_evidence(second, ledger_path=ledger)
|
||||
|
||||
with pytest.raises(ValueError, match="allocated by both"):
|
||||
shared_cost_allocations(ledger_path=ledger)
|
||||
|
|
@ -116,7 +116,7 @@ prices remain auditable, and duplicate prices require an explicit revision.
|
|||
|
||||
```task
|
||||
id: FIN-WP-0002-T03
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "899a5c29-843c-481f-a63a-42d4d327af5d"
|
||||
```
|
||||
|
|
@ -130,11 +130,19 @@ where resource-control supplies it.
|
|||
Test allocation totals, rounding, missing evidence, shared overhead, revised
|
||||
allocations, and prevention of duplicate booked cost.
|
||||
|
||||
Completed 2026-08-11: added a reporting-only allocation consumer for current
|
||||
resource-control `AllocationEvidence`. It requires uniquely claimed current
|
||||
financial facts, validates period/environment/currency and producer totals,
|
||||
retains the versioned method and provenance, and uses deterministic
|
||||
largest-remainder minor-unit rounding. Per-instance targets plus the explicit
|
||||
unattributed residual reconcile exactly to booked cost. Tests cover rounding,
|
||||
missing facts, mismatches, evidence revisions, and duplicate allocation.
|
||||
|
||||
## Export a per-client billing basis
|
||||
|
||||
```task
|
||||
id: FIN-WP-0002-T04
|
||||
status: wait
|
||||
status: todo
|
||||
priority: medium
|
||||
state_hub_task_id: "b5886131-82f6-49fb-a7e3-ba47d5b627a8"
|
||||
```
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ without reproducing fin-hub's allocator or runway logic.
|
|||
|
||||
```task
|
||||
id: FIN-WP-0004-T05
|
||||
status: todo
|
||||
status: wait
|
||||
priority: high
|
||||
state_hub_task_id: "9a411734-76f6-4c8d-9a48-b5a08cf8fd1f"
|
||||
```
|
||||
|
|
@ -179,6 +179,16 @@ Done when the same cost is booked exactly once, projected to resource-control,
|
|||
joined to technical evidence, and returned as planning or variance evidence
|
||||
without becoming a second financial fact.
|
||||
|
||||
Preflight 2026-08-11: resource-control verified fin-hub commit `0034330`, and
|
||||
both implementations produced identical canonical payloads for all 12 live
|
||||
backup forecast rows. Replaying them retained exactly 12 planning-store rows.
|
||||
Evidence is in resource-control at
|
||||
`docs/evidence/RESOURCE-WP-0003-fin-hub-contract-preflight-2026-08-11.md`.
|
||||
|
||||
The task now waits on `RESOURCE-WP-0002` procurement and the first real
|
||||
provider fact attributable to `platform:audit-storage`. Synthetic records test
|
||||
the contract but do not satisfy the operational booked-cost round trip.
|
||||
|
||||
## T06 — Generalize and operate the contract
|
||||
|
||||
```task
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue