--- id: FIN-WP-0007 type: workplan title: "AI plan cost, token estimates, and effectiveness" domain: financials repo: fin-hub status: finished owner: grok topic_slug: financials created: "2026-08-15" updated: "2026-08-15" related: - FIN-WP-0002 - FIN-WP-0004 - FIN-WP-0006 - STATE-WP-0045 - RESOURCE-WP-0003 - ITC-CAP-0.2.0 origin: assessment origin_ref: "info-tech-canon 0.3.0 review — AI token data-gap" state_hub_workstream_id: "88de5e03-a53f-4b62-a0a7-1365756da2d7" --- # FIN-WP-0007 — AI plan cost, token estimates, and effectiveness ## Goal Build a provenance-bearing dataset that lets fin-hub compare **what AI plans cost**, **what token capacity they entitle**, **what was actually or estimably consumed**, and **what work was delivered**, without treating missing session usage as zero and without turning estimates into booked spend. The motivating failure is operational, not theoretical: most coding-agent sessions do not emit trustworthy token counts or token costs. The facts that *do* exist are monthly plan invoices, plan entitlements, occasional provider or State Hub measurements, and independent work outcomes. Those must stay distinct and joinable so effectiveness can be watched over time. This workplan applies the InfoTechCanon 0.3.0 / ITC-CAP 0.2.0 split already used for infrastructure in `FIN-WP-0004`: booked euros are not usage; usage is recorded in native units (`token` for class `I`); `unknown` is never stored as `0`; currency is an overlay. It does **not** wait for a new commerce or intelligence domain model. ## Boundaries Checked 2026-08-15 against resource-control SCOPE, INTENT, procurement terms §4.1/§6, their v0.1 ratification, evidence-basis vocabulary, and the backup capability restatement. Design note: `docs/ai-plan-token-effectiveness.md`. Contract v0.1 is not silently amended; the addendum in that note is offered, not assumed. | Concept | Authoritative writer | Fin-hub role | | --- | --- | --- | | Provider invoice / plan subscription charge | fin-hub | Book once as `booked_cost` | | Recurring plan as a financial commitment | fin-hub | Record cadence and amount; not usage | | Plan entitlement (included tokens or plan capacity) | fin-hub | Commercial fact, same discipline as engagement prices | | Intelligence / infrastructure `resource_id` | resource-control | Join when they publish one; never invent | | Provision-level class `I` usage | resource-control (gap they already own) | Consume via `FIN-WP-0004` when emitted | | Session token evidence (`measured` / `allocated` / `estimated` / `superseded`) | State Hub (`STATE-WP-0045`) | Join as session-token evidence; do not store as `usage_observation` | | Technical allocation of a portfolio resource | resource-control | Consume `AllocationEvidence`; do not emit it | | Work done (tasks, progress, outcomes) | State Hub / domain repos | Join key for effectiveness; not a cost driver | | Reporting allocation of a plan invoice across work | fin-hub | Local `FIN-WP-0002`-family derivation | | Implied €/token and work-per-token / work-per-euro | fin-hub | Reporting overlay; never a booked price | | Vendor parsers, transcripts, model names, list prices | State Hub / llm-connect / operators | Not invented here | Reuse the *discipline* of contract v0.1 (unknown is not zero, residual visible, estimates are not booked). Do not impersonate resource-control record types for agent-session telemetry or work-effectiveness shares. Founder-private AI plans may be booked for runway. They stay `resource_id=null` and must not silent-default `financial_entity_id` until the spend is booked to an entity and, if Railiance-procured, a resource. ## Non-goals - Legal invoices, DATEV postings, or payment execution (`FIN-WP-0005`). - Completing the Scaleway `platform:audit-storage` booked-cost round trip (`FIN-WP-0004-T05`). That is class `S`, not class `I`. - Owning session parsers or storing transcripts. - Inventing a `resource_id` or metering tokens against a provision. - Emitting `usage_observation` or `AllocationEvidence` as if this repo were resource-control. - A canonical token↔hour or token↔euro exchange rate (ITC-CAP forbids asserting one; substitution is observed from the time series). - A new definition of “work” beyond joining to existing task / progress outcomes. - Editing InfoTechCanon inline. Canon pressure is a demand message, not a kernel patch from this repo. ## Measurement layers Keep these four quantities in separate records, joined by period, provider/plan, and optional workplan/repo: 1. **Booked plan cost** — euros for the subscription month. 2. **Entitlement** — included tokens or declared plan capacity. 3. **Consumption of class `I`** — tokens, each row marked `measured` | `inferred` | `unknown`. Missing is `unknown`, never `0`. 4. **Work done** — tasks or accepted outcomes in the same period. Derived overlays, never booked facts: - implied €/token = booked ÷ (measured + estimated + residual) - effectiveness = work / measured tokens, work / (measured+estimated) tokens, and work / euro - coverage = measured / (measured + estimated + residual) A month with worse coverage must not look more efficient. Changing an estimator method starts a new series. ## Record the authority and measurement split ```task id: FIN-WP-0007-T00 status: done priority: high state_hub_task_id: "5e9bccfd-569a-43a2-b016-afed760add49" ``` Write a short design note in `docs/` that records the four-layer split, the authority table above, reuse of the v0.1 exchange envelopes, and the State Hub join (token aggregates by `measurement_kind`, period, repo/workplan). Confirm `SCOPE.md` already covers token-spend models; if the current wording implies session-metered CSV rows are the only token surface, update it so plan invoices, entitlements, estimated usage, and effectiveness reports are in scope while session parsing stays out. Done when the note is committed, `SCOPE.md` matches the boundary, and no task below has an ambiguous owner for booked cost, entitlement, session tokens, or work. Completed 2026-08-15: boundary-checked against resource-control SCOPE, INTENT, Terms §4.1/§6, their contract ratification, evidence-basis, and the backup restatement. They own intelligence *resource* identity and provision-level class `I` metering (not yet implemented). Session telemetry and work-effectiveness stay outside that. Note: `docs/ai-plan-token-effectiveness.md`. `SCOPE.md` and `INTENT.md` updated. T04/T05 rewritten so fin-hub does not impersonate `usage_observation` or `AllocationEvidence`. Proposed v0.1 addendum offered to resource-control; not assumed. ## Stop treating missing tokens as zero ```task id: FIN-WP-0007-T01 status: done priority: high state_hub_task_id: "aefa287e-0e4d-40b1-adf6-a8e6df7caeb2" ``` After T00, fix `TokenSpend` and `parse_anthropic_billing_csv` so absent token fields are `null` / omitted, not `0`. `0` means measured and none. Align ledger import: token quantities that are unknown must not become zero ledger attributes, and a cost-only row must remain a cost-only row. Add regression tests for missing `input_tokens` / `output_tokens`, cost-only provider exports, and the invariant that incomplete months cannot under-report consumption as zero. Done when the existing fixture still parses, a missing-token fixture does not emit zeros, and CAP-R8 (`unknown` never stored as zero) holds on the token path. Completed 2026-08-15: `parse_optional_token_count` treats empty as unknown and `0` as measured none. `TokenSpend.tokens_in/out` are nullable with no zero default. Ledger import of a cost-only Anthropic row still books the amount and does not invent token quantities. ## Book AI-plan invoices as facts and commitments ```task id: FIN-WP-0007-T02 status: done priority: high state_hub_task_id: "216aac44-f712-483c-a402-7db39c5967dd" ``` After T00, ingest monthly AI-plan / subscription charges as `booked_cost` facts (one current fact per provider-account × plan × accounting period) and as recurring `Commitment` rows where the plan is ongoing. Use the existing financial-fact identity, fingerprint, correction, and unknown-tax rules from `FIN-WP-0004`. Do not explode a flat monthly invoice into synthetic per-session costs. Session-level euros, if shown at all, come from a later allocation (T05), not from the booked ledger. Done when a fixture for at least two providers (for example a flat subscription and a usage-top-up) books exactly once per period, corrects append-only, and appears on burn/runway like any other commitment. Completed 2026-08-15: `import-ai-plan` / `ledger import ai-plan` books one current fact per provider-account × plan × period. Session-level columns are rejected. Subscriptions upsert a monthly commitment; usage top-ups do not. Corrections stay append-only. `booked_cost` projection keeps `resource_id` null and tax unknown. Booked invoices drive burn; a commitment-only month can still produce a runway figure without double-counting the same euros. ## Record plan entitlements ```task id: FIN-WP-0007-T03 status: done priority: high state_hub_task_id: "51c1b86f-c137-4b5d-9719-cd2ae60fe857" ``` After T02, add an append-only plan-entitlement record: provider, plan identity, period, entitled quantity, unit (`token` or a declared plan capacity such as a multiplier), source provenance, and revision link. Follow the engagement-price discipline from `FIN-WP-0002-T02`: a revision supersedes, a price or capacity is not an invoice, currency mismatches cannot silently join. When entitled tokens are themselves unknown (common for “Max 20×” style plans), store `unknown` plus the declared plan label. Do not invent a token ceiling. Done when a plan month can be reported as booked euros + entitled capacity (or explicit unknown) without reading session logs. Completed 2026-08-15: `ledger set-entitlement` / `plan-month` record append-only capacity (`token`, `multiplier`, or `plan`). Unknown tokens require a plan label and never become zero. Revisions supersede. Booked euros join entitlement on provider/account/plan/ period; a currency mismatch stays visible and is not treated as a matched series. No session logs are read. ## Join State Hub session-token aggregates ```task id: FIN-WP-0007-T04 status: done priority: high state_hub_task_id: "29f1804f-a5ad-46b6-b9d7-8f074e31b04e" ``` After T00, ingest State Hub token summaries as **fin-hub session-token evidence**, not as resource-control `usage_observation`. Preserve `measurement_kind` (`measured`, `allocated`, `estimated`, `superseded`), period, model, repo/workplan association, confidence, and coverage. Map kinds onto the resource-control evidence-basis vocabulary (`measured` / `derived` / `estimated` / excluded / `unknown`). Do not re-parse Codex, Claude, Cursor, or Grok session files. Do not invent a `resource_id`. If resource-control later inventories a Railiance-procured intelligence resource and emits `usage_observation` for it, consume that through the existing `FIN-WP-0004` planning-evidence path. Superseded rows must not enter totals. Estimated and measured must remain separable. Months with no State Hub events produce an explicit unknown residual, not a zero-consumption observation. Done when a recorded fixture of mixed measured/estimated/superseded aggregates stores as session-token evidence, reconciles by kind, and cannot be posted as booked spend or as resource-control usage. Completed 2026-08-15: `ledger ingest-session-tokens` stores a State Hub aggregate snapshot in `session_token_evidence`. Kinds map to measured/derived/estimated; superseded is excluded. Empty months are `unknown_residual`, not zero. The snapshot cannot be posted as `booked_cost` or as resource-control `usage_observation`. Allocated slices require a method. No session files are parsed and no `resource_id` is minted. ## Reporting-allocate booked plan cost across work ```task id: FIN-WP-0007-T05 status: done priority: medium state_hub_task_id: "db098143-90b7-475c-8846-e4c274e50b4a" ``` After T02 and T04, allocate each AI-plan `financial_fact_id` across repos/workplans as a **fin-hub reporting allocation** (same family as `FIN-WP-0002` billing basis). This is not resource-control `AllocationEvidence` and must not be posted as technical allocation. Allowed first methods: measured-token share, measured+estimated-token share, session-count share, even split. Method and estimator version are part of the record identity. Shares plus residual must equal 1. Unattributed and unmeasured shares stay visible. Allocation never writes a new booked fact. Technical allocation of a portfolio resource remains resource-control's job and only applies when they have published a `resource_id`. Done when a one-plan, two-workplan fixture reconciles to the booked effective amount, names its method, keeps residual when coverage is incomplete, and is not stored as `AllocationEvidence`. Completed 2026-08-15: `ledger allocate-plan` writes a reporting allocation for an `ai-plan` fact. One plan / two workplans at 100 and 50 measured tokens of a 200-token pool leaves a 0.25 unmeasured residual and still sums to the booked €200. The record is not stored as `AllocationEvidence` and does not change booked totals. ## Publish an effectiveness report ```task id: FIN-WP-0007-T06 status: done priority: medium state_hub_task_id: "cea14702-faca-4024-b6f8-1ad221b70624" ``` After T03–T05, add a period report (CLI and, if cheap, the existing read API) that emits, per plan and currency: - booked effective amount - entitled capacity (or unknown) - tokens measured / estimated / residual-unknown - coverage ratio - implied €/token, labelled inferred - work joined (task counts or accepted outcomes) for the same period - work per measured token, work per (measured+estimated) token, work per euro — three series, not one blend Refuse to present a single blended “efficiency” number. A month whose coverage is below a documented threshold is marked unfit for trend comparison, not interpolated. Done when two fixture months with different coverage cannot produce a chart in which the worse-measured month looks cheaper per unit of work unless that is also true on the measured-only series. Completed 2026-08-15: `ledger effectiveness` and `GET /effectiveness` publish the three series and mark coverage below 0.50 as `unfit`. Implied €/token is labelled inferred. A low-coverage month cannot be ranked cheaper on a token series; there is no blended efficiency field. ## Send canon feedback ```task id: FIN-WP-0007-T07 status: done priority: low state_hub_task_id: "42aeae80-4d7c-4f79-b5b3-d42b3d205762" ``` After T00, send a demand signal to `info-tech-canon` (State Hub message and/or a `demand/` note they can assimilate). Ask for: - a `measured | inferred | declared | unknown` qualifier on `CapabilityConsumption` (reuse ITC-DATA lineage states; do not invent a local dialect); - enough `commerce.entitlement` / `commerce.metering` structure for plan capacity and incomplete meters (OQ-5 still open for invoices and entitlements); - dropping or re-homing the `cost` quality dimension on `intelligence.generation` so it does not fight ITC-CAP §4.12. Do not patch the canon from this repo. Done when the demand is sent, referenced from this workplan, and explicitly does not block T01–T06. Completed 2026-08-15: demand filed at `info-tech-canon/demand/CapabilityConsumptionLineage.md` (inbound, un-reviewed) with consumer copy `docs/demand-capability-consumption-lineage.md`. State Hub message `8b0fd492-dac1-4fbe-bebb-efd52c601773` to `info-tech-canon`. No canon models were edited. T01–T06 remain done.