I3287 — A provider declares how it reports usage, with the evidence, beside its lifecycle
Extend share/providers.yaml `offers` with `usage` (otel | app-server | stream-json | none) and `usage_evidence`, so discovery, normalisation, tests and surfaces read one declaration instead of a ClaudeTelemetry/CodexTelemetry/GeminiTelemetry subsystem.
READY wave 0 · p2 · implementation profile · parallel safe
Ready. Every dependency is done, so majordomus plan start I3287 will be accepted.
Objective
Extend share/providers.yaml `offers` with `usage` (otel | app-server | stream-json | none) and `usage_evidence`, so discovery, normalisation, tests and surfaces read one declaration instead of a ClaudeTelemetry/CodexTelemetry/GeminiTelemetry subsystem.
Why
The owner ordered one generic fabric (c253#3); providers.yaml already carries `offers` with dated evidence for episodes and prompts, so the usage seam is a fourth key, not a new 'telemetry adapter descriptor' noun. Plan repair carried here (the intent's own criteria were repaired in the plan on 2026-10-18; what remains is the existing execution-telemetry milestone and I0301-I0304) because I3287 has no dependencies and is the first issue every telemetry issue waits on: ADR 0213 promises that execution-telemetry drops runtime-adapters, but no milestone file changed, so I0301 and everything depending on it was derived BLOCKED. It extends milestone execution-telemetry. Proposed in ADR 0213 (Usage is observed through each provider's official telemetry into one provider-neutral record, and reported, estimated and billed amounts are never merged) (proposed; it carries no authority until the owner accepts it). Sources: chatgpt-majordomus:c253#4.
Current state
share/providers.yaml declares episode and prompts per provider; nothing about usage.
Desired state
claude-code: otel and stream-json; codex: app-server; gemini: otel; agents/bb: none — each with a citation verified at implementation; product validate refuses a key without evidence.
Scope
- share/providers.yaml
- apps/majordomus-cli/src/commands/product.rs
- .ai/repo/project/milestones/execution-telemetry.yaml
- .ai/repo/project/issues/I0301.yaml
- .ai/repo/project/issues/I0302.yaml
- .ai/repo/project/issues/I0303.yaml
- .ai/repo/project/issues/I0304.yaml
- share/schemas/generated/providers.schema.json
- apps/majordomus-cli/src/share.rs
- apps/majordomus-cli/src/product.rs
- apps/majordomus-cli/src/capability/builtin/lifecycle.rs
- test/cases/170_provider_lifecycle_declared.sh
- docs/generated/providers.json
- docs/generated/providers.md
- docs/generated/providers.yaml
Dependencies
None. This issue is a root of the graph.
What waits on this
- I3288BLOCKED The shared server receives Claude Code's OpenTelemetry usage events over loopback and records them as reported
- I3290BLOCKED Codex usage is read from app-server increments, and a cumulative total is never summed
- I3292BLOCKED Reported tokens, a price-list estimate and a billed amount are three fields, and the billing mode says which account paid
Acceptance criteria
- Every provider row states usage and its evidence
- lifecycle providers and product validate report the usage seam
- A row with usage and no evidence is refused
- execution-telemetry no longer depends_on runtime-adapters (ADR 0213 Consequences) and depends on every-sessions-usage-is-observed, and `majordomus plan show I0301` no longer derives BLOCKED from its milestone
- I0301 is rescoped to apps/majordomus-cli/src/economics and share/schemas and defines the usage record (Option<u64> per category, an absence reason, a named reporter per field)
- I0302 is cancelled as superseded by I3288 with its criteria carried into I3288; I0303 is rescoped to test/cases over the Rust receiver; I0304 is rescoped to the Rust economics read surface with a declared retention bound
- No acceptance criterion is ranked by both execution-telemetry and every-sessions-usage-is-observed (`majordomus plan validate` passes)
- Codex's usage row cites dated evidence on whether its own OpenTelemetry export covers sessions the person starts, or declares that seam unadapted with the reason
- The intent's criteria stand as the plan declares them on 2026-10-18 (no-estimate-shown-as-spend-or-saving replaces no-unmeasured-claim; a-silent-provider-is-absent, gemini-usage-recorded, compaction-is-measured, over-budget-is-told, savings-are-measured-by-arm and own-overhead-is-measured are served), and `majordomus intent validate` reports no criterion of the intent unserved
Validation
- majordomus product validate
- majordomus generate --check
- bash test/run.sh 170_provider_lifecycle_declared
- majordomus plan validate
Evidence required
- case_a_provider_declares_its_usage_seam
Evidence
None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.
Timeline
- started
- —
- verified
- —
- completed
- —
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I3287.yaml. Read it back with majordomus plan show I3287.