You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As someone writing a skill that reports on AIDD work I want one machine-readable shape, the same whatever tool ran, that says what each tool could and could not supply So that a skill branches on a declared capability instead of guessing from a missing number, and two identical calls give two identical answers
Why now
#629 shipped aidd telemetry report. Its figures are right and proven across three tools end to end. But nothing about it is consumable by a program, and the flow that feeds it cannot be followed by a person.
Four things block a skill today, all measured
1. There is no flow.aidd telemetry read takes --session <uuid> as a required option, and nothing tells a user their session id. The journal has known every session id all along; RunJournalReader.list() has existed since #629 phase 1 and nothing calls it.
2. --days resolves against Date.now(). The same command run twice covers two different periods. A skill cannot cite a figure it cannot reproduce.
3. The attribution block's order is whatever order the records arrived in. Real output from the multi-tool e2e:
attribution of tokens
stated by the tool 3%
unattributed 74%
from a journal interval 24%
Three rows, arbitrary order, and a strength with no records vanishes from the list entirely — though zero really is the measurement there, not an absence.
4. The output is aligned text. A skill scraping columns breaks the first time one gets wider.
The decision this rests on
A skill reads the report's output, never the stored records. The two double-count rules, the split between the two record kinds, and the turn_id dedup would otherwise be re-implemented by every consumer, differently — the same failure the decision table in #687 names for vendor_field. One computation, in one place.
Equivalent information, per tool
The second half of this ticket. What each tool can supply is currently spread across document prose, source comments and a table inside the hook. A consumer cannot read any of it, so it has to infer capability from whether a number happened to be present — which is exactly the inference that turns a limit into a zero.
Measured today:
Tool
Route
Tokens
Amount
Step, stated by the tool
Step, from the journal
Task
Claude Code
local
yes
no
yes (attributionSkill)
yes
yes
Claude Code
export
yes
yes
no — the vendor attribute reads third-party
no — the mapper runs while the journal is still open
no
Codex
local
yes
no
no
yes
no — writes through apply_patch, no readable path
Codex
export
unmeasured
unmeasured
—
—
—
OpenCode
local
yes
no — info.cost is 0 everywhere and its denomination was never established
no
no — no captured payload carries its session id, so nothing joins
no
Copilot
local
unsupported — outputTokens per turn, nothing else per request
unmeasured — an Enterprise team setting nobody here can enable
—
—
—
—
Two readings of that table:
No locally-read tool carries an amount. None. Claude Code's cost_usd reaches the sink only through its OTLP export. Proven by the multi-tool e2e, which asserts the report contains no $ at all. Equivalence on money is not reached here and is not meant to be: the rates live in the governor, and this repository's job is to emit tokens complete enough to price.
So the field is uniform, the presence is not, and forcing the second would be lying. What this ticket adds is that presence becomes declared rather than discovered — each tool states what it can supply, and the report emits that beside the figures.
Acceptance
aidd telemetry report --json prints one object, carrying a version a consumer can refuse.
The period is reported as it resolved, absolutely, never as it was asked.
--from and --to take absolute days; --days stays as the human shorthand and is defined in terms of them.
The same files and the same absolute period produce byte-identical output, twice.
All three attribution strengths always appear, in a fixed order, zero where zero is the measurement.
Every declared tool carries a capability block: readable by which route, carries an amount or not, states its own step or not, journal-attributable or not, task-attributable or not — from declarations, never inferred from whether a figure is present.
Adding a tool changes a declaration; neither the report nor the printer is touched.
aidd telemetry read with no --session reads every session the journal knows and has not already stored, and says how many it read.
--session still works, unchanged, for one session by name.
Records the read could not place, and lines it could not parse, are carried into the output so a partial read cannot read as a complete one.
The human output keeps every guarantee it has today; the JSON is a second rendering of one computation, never a second computation.
As someone writing a skill that reports on AIDD work
I want one machine-readable shape, the same whatever tool ran, that says what each tool could and could not supply
So that a skill branches on a declared capability instead of guessing from a missing number, and two identical calls give two identical answers
Why now
#629 shipped
aidd telemetry report. Its figures are right and proven across three tools end to end. But nothing about it is consumable by a program, and the flow that feeds it cannot be followed by a person.Four things block a skill today, all measured
1. There is no flow.
aidd telemetry readtakes--session <uuid>as a required option, and nothing tells a user their session id. The journal has known every session id all along;RunJournalReader.list()has existed since #629 phase 1 and nothing calls it.2.
--daysresolves againstDate.now(). The same command run twice covers two different periods. A skill cannot cite a figure it cannot reproduce.3. The attribution block's order is whatever order the records arrived in. Real output from the multi-tool e2e:
Three rows, arbitrary order, and a strength with no records vanishes from the list entirely — though zero really is the measurement there, not an absence.
4. The output is aligned text. A skill scraping columns breaks the first time one gets wider.
The decision this rests on
A skill reads the report's output, never the stored records. The two double-count rules, the split between the two record kinds, and the
turn_iddedup would otherwise be re-implemented by every consumer, differently — the same failure the decision table in #687 names forvendor_field. One computation, in one place.Equivalent information, per tool
The second half of this ticket. What each tool can supply is currently spread across document prose, source comments and a table inside the hook. A consumer cannot read any of it, so it has to infer capability from whether a number happened to be present — which is exactly the inference that turns a limit into a zero.
Measured today:
attributionSkill)third-partyapply_patch, no readable pathinfo.costis0everywhere and its denomination was never establishedoutputTokensper turn, nothing else per request/v1/logsand/v1/metricsonlyTwo readings of that table:
cost_usdreaches the sink only through its OTLP export. Proven by the multi-tool e2e, which asserts the report contains no$at all. Equivalence on money is not reached here and is not meant to be: the rates live in the governor, and this repository's job is to emit tokens complete enough to price.So the field is uniform, the presence is not, and forcing the second would be lying. What this ticket adds is that presence becomes declared rather than discovered — each tool states what it can supply, and the report emits that beside the figures.
Acceptance
aidd telemetry report --jsonprints one object, carrying a version a consumer can refuse.--fromand--totake absolute days;--daysstays as the human shorthand and is defined in terms of them.aidd telemetry readwith no--sessionreads every session the journal knows and has not already stored, and says how many it read.--sessionstill works, unchanged, for one session by name.Out of scope
Relations