tledger 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +283 -155
- package/bin/token-ledger-cache-data.mjs +492 -0
- package/bin/token-ledger-cache-image.mjs +7 -1147
- package/bin/token-ledger-cache-sections.mjs +848 -0
- package/bin/token-ledger-cost-terminal.mjs +234 -0
- package/bin/token-ledger-image-layout.mjs +20 -0
- package/bin/token-ledger-image-primitives.mjs +192 -0
- package/bin/token-ledger-report-data.mjs +1159 -0
- package/bin/token-ledger-source-status.mjs +31 -0
- package/bin/token-ledger-terminal.mjs +245 -69
- package/bin/token-ledger-trend-image.mjs +2039 -1599
- package/bin/token-ledger-trend-terminal.mjs +273 -150
- package/bin/token-ledger-trend.mjs +262 -210
- package/bin/token-ledger-tui.mjs +180 -51
- package/bin/token-ledger.mjs +747 -194
- package/docs/durable-ledger-operations.md +198 -0
- package/docs/release-notes-0.4.0.md +41 -0
- package/docs/token-ledger-report-7-day.png +0 -0
- package/lib/token-ledger-calendar.mjs +225 -0
- package/lib/token-ledger-collection.mjs +100 -0
- package/lib/token-ledger-importer.mjs +3334 -480
- package/lib/token-ledger-labels.mjs +66 -0
- package/lib/token-ledger-ledger.mjs +6056 -0
- package/lib/token-ledger-quota-contract.mjs +38 -0
- package/lib/token-ledger-range-analysis.mjs +120 -0
- package/lib/token-ledger-rates.mjs +330 -0
- package/lib/token-ledger-snapshot.mjs +336 -35
- package/lib/token-ledger-terminal-text.mjs +11 -0
- package/lib/token-ledger-usage.mjs +339 -33
- package/package.json +13 -10
- package/bin/token-ledger-rates.mjs +0 -65
package/README.md
CHANGED
|
@@ -1,193 +1,321 @@
|
|
|
1
1
|
# Token Ledger
|
|
2
2
|
|
|
3
|
-
Token Ledger is a local-only
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
context;
|
|
7
|
-
- a terminal dashboard for a fast project and token summary.
|
|
8
|
-
|
|
9
|
-
This README describes the local checkout. It does not assume a hosted report
|
|
10
|
-
or a published npm package.
|
|
3
|
+
Token Ledger is a small, local-only terminal dashboard for Codex usage. It
|
|
4
|
+
shows ranked project bars, model mix, usage type, cache coverage, and reset
|
|
5
|
+
cycle context without sending your data anywhere.
|
|
11
6
|
|
|
12
7
|
## Install
|
|
13
8
|
|
|
14
|
-
Requires Node.js 22.13 or newer.
|
|
9
|
+
Requires Node.js 22.13 or newer.
|
|
10
|
+
|
|
11
|
+
Install the published CLI with:
|
|
15
12
|
|
|
16
13
|
```bash
|
|
17
|
-
npm install
|
|
18
|
-
npm install -g .
|
|
14
|
+
npm install -g tledger
|
|
19
15
|
```
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
use `npx tledger` instead.
|
|
23
|
-
|
|
24
|
-
## Basics
|
|
25
|
-
|
|
26
|
-
| What you need | Command |
|
|
27
|
-
| --- | --- |
|
|
28
|
-
| Quick guide | `tledger` |
|
|
29
|
-
| Last 24 hours | `tledger 1d` |
|
|
30
|
-
| Last 7 calendar days | `tledger week` |
|
|
31
|
-
| Rolling 30 days | `tledger 30d` |
|
|
32
|
-
| 7-day PNG report | `tledger report 7d` |
|
|
33
|
-
| Cache-only PNG report | `tledger report 7d --cache-rate` |
|
|
34
|
-
|
|
35
|
-
The main options are:
|
|
36
|
-
|
|
37
|
-
- `--static` prints once instead of opening the terminal dashboard.
|
|
38
|
-
- `--refresh` rebuilds the local usage cache.
|
|
39
|
-
- `--image-output <file>` chooses where to save a PNG.
|
|
40
|
-
- `--no-open` writes a PNG without opening it.
|
|
41
|
-
- `--help-all` shows the complete command and option reference.
|
|
42
|
-
|
|
43
|
-
`week` covers seven local calendar days ending on the selected day. `1d` is a
|
|
44
|
-
rolling 24-hour view ending when the command starts. In a TTY, the project
|
|
45
|
-
dashboard is interactive. `j`/`k` select a project; `q`, `Q`, `Esc`, or
|
|
46
|
-
`Ctrl-C` exits. Enter does not inspect a project, and `d` / `w` / `m` do not
|
|
47
|
-
change the range; choose the range in the command.
|
|
48
|
-
|
|
49
|
-
## Cache and input controls
|
|
50
|
-
|
|
51
|
-
`tledger report [Nd|Nw] --cache-rate` writes a separate, purpose-built cache
|
|
52
|
-
report to `token-ledger-cache-report-<period>.png`. Its primary view is the
|
|
53
|
-
input-token-weighted cache rate (`cached input / measured input`), shown
|
|
54
|
-
across the selected period with input-volume context. A smaller model breakout
|
|
55
|
-
shows which models account for that input and their individual cache rates.
|
|
56
|
-
The cache report intentionally omits the general report's project, quota-meter,
|
|
57
|
-
runway, and output-token sections. Cached input is clamped to input per event,
|
|
58
|
-
and the report states how much token volume had a usable component breakdown.
|
|
59
|
-
Use `--image-output`, `--image-width`, `--date`, `--tz`, and `--no-open` the
|
|
60
|
-
same way as on the standard report.
|
|
61
|
-
|
|
62
|
-
The default privacy-reduced snapshot is
|
|
63
|
-
`~/.token-ledger/token-ledger-snapshot-v2.json.gz`. It is gzip-compressed,
|
|
64
|
-
written atomically with mode `0600`, targets 12 MiB, and has a hard 16 MiB
|
|
65
|
-
on-disk limit. Its expanded JSON representation also targets 48 MiB and has a
|
|
66
|
-
64 MiB safety limit, so the old 93 MiB raw-cache behavior cannot recur on the
|
|
67
|
-
default production path. Reads check the compressed size before loading and
|
|
68
|
-
bound gzip expansion to the same 64 MiB JSON limit. The collector de-duplicates
|
|
69
|
-
through a private temporary SQLite spool, then keeps exact recent calls while
|
|
70
|
-
rolling older history into minute, hour, and day buckets. If a dense history
|
|
71
|
-
approaches the target, it increases the bucket resolution automatically while
|
|
72
|
-
preserving additive token, model, project, cache, tool-call, and thread totals.
|
|
73
|
-
When a compacted bucket crosses a requested range or chart boundary, Token
|
|
74
|
-
Ledger allocates its additive values proportionally across the overlap and
|
|
75
|
-
marks the terminal result as estimated; exact recent calls remain exact. The
|
|
76
|
-
temporary spool is removed when collection completes or exits with a handled
|
|
77
|
-
error.
|
|
78
|
-
|
|
79
|
-
If even the coarsest bounded representation exceeds the hard limit, Token
|
|
80
|
-
Ledger preserves the previous cache and asks you to reduce the source with
|
|
81
|
-
`--no-archived` or the collector's `--since` option. It never replaces the
|
|
82
|
-
production cache with an oversized or partial file. On a normal default-path
|
|
83
|
-
run, a snapshot whose mtime is in the past and less than one hour old skips the
|
|
84
|
-
source walk. An exact-hour or future mtime is not fresh; an older snapshot is
|
|
85
|
-
checked against local source mtimes before it is reused or rebuilt.
|
|
17
|
+
For a one-time run without a permanent global install:
|
|
86
18
|
|
|
87
19
|
```bash
|
|
88
|
-
|
|
89
|
-
tledger week --refresh
|
|
90
|
-
|
|
91
|
-
# Read the existing default snapshot without a source-freshness check
|
|
92
|
-
tledger week --no-refresh
|
|
93
|
-
|
|
94
|
-
# Read an explicit snapshot without automatic freshness checks
|
|
95
|
-
tledger week --input /path/to/token-ledger-snapshot-v2.json.gz
|
|
20
|
+
npx tledger week
|
|
96
21
|
```
|
|
97
22
|
|
|
98
|
-
|
|
99
|
-
`--input` in this checkout. `--no-archived` excludes `archived_sessions` when a
|
|
100
|
-
refresh occurs. The collector can also be run directly:
|
|
23
|
+
To install the development version from this repository:
|
|
101
24
|
|
|
102
25
|
```bash
|
|
103
|
-
|
|
26
|
+
git clone https://github.com/jskoiz/token-ledger.git
|
|
27
|
+
cd token-ledger
|
|
28
|
+
npm install -g .
|
|
104
29
|
```
|
|
105
30
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
new cache does not read or delete schema-v1 cache files; remove an old generated
|
|
109
|
-
cache separately once the v2 cache is proven.
|
|
31
|
+
The package uses a small runtime image encoder for PNG report output, Node's
|
|
32
|
+
built-in SQLite support, and reads Codex data directly from the local machine.
|
|
110
33
|
|
|
111
|
-
##
|
|
34
|
+
## Run
|
|
112
35
|
|
|
113
|
-
|
|
114
|
-
| --- | --- | --- |
|
|
115
|
-
| Command | `tledger report 7d` or `tledger trend 7d --image` | `tledger week`, `tledger 1d`, or `tledger day <date>` |
|
|
116
|
-
| Output | One PNG with a stat quad, weekly-meter pace/runway, daily token columns, an aligned cache-rate strip, top projects, and per-model cache rates | Interactive or static project rows with totals, shares, thread counts, model mix, usage type, cache split, and reset-cycle context |
|
|
117
|
-
| Range | A selected local-calendar-day trend window, such as 7d or 2w | A calendar day/week or a rolling 24-hour/`Nd`/`Nw` window |
|
|
118
|
-
| Estimate surface | Meter-derived burn and runway are called out; cache coverage comes from measured token breakdowns | The sidebar can show derived `View burn`; project detail includes rate-card credit shares when available |
|
|
36
|
+
The shortest useful command is:
|
|
119
37
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
## Examples
|
|
38
|
+
```bash
|
|
39
|
+
tledger week
|
|
40
|
+
```
|
|
124
41
|
|
|
125
|
-
|
|
42
|
+
It defaults to today's seven-day window, the computer's local timezone, the
|
|
43
|
+
top 10 projects, and the local Codex data directory. The default terminal view
|
|
44
|
+
is interactive; press `q` or `esc` to exit.
|
|
126
45
|
|
|
127
|
-
|
|
46
|
+
Other common views:
|
|
128
47
|
|
|
129
|
-
|
|
48
|
+
```bash
|
|
49
|
+
tledger 1d
|
|
50
|
+
tledger 1d --static
|
|
51
|
+
tledger 2d
|
|
52
|
+
tledger 1w
|
|
53
|
+
tledger 3w --static
|
|
54
|
+
tledger day 2026-08-05
|
|
55
|
+
tledger week --top 5
|
|
56
|
+
tledger week --static
|
|
57
|
+
tledger trend 7d --static
|
|
58
|
+
tledger trend 7d --image --image-output artifacts/token-ledger-trend-7d.png
|
|
59
|
+
tledger report 7d
|
|
60
|
+
```
|
|
130
61
|
|
|
131
|
-
|
|
62
|
+
Bare duration aliases such as `tledger 1d`, `tledger 2d`, `tledger 3d`,
|
|
63
|
+
`tledger 1w`, `tledger 2w`, and `tledger 3w` show the `TOKENS BY PROJECT`
|
|
64
|
+
breakdown for a rolling window ending when the command starts. Day and week
|
|
65
|
+
aliases accept any positive `Nd` or `Nw` value up to 3,650 days. `tledger 1d`
|
|
66
|
+
is the existing rolling 24-hour view; `tledger 1w` is a rolling seven-day
|
|
67
|
+
window. This is different from `tledger day today`, which covers the current
|
|
68
|
+
calendar day from local midnight, and `tledger week`, which covers seven local
|
|
69
|
+
calendar days.
|
|
70
|
+
|
|
71
|
+
`tledger report [Nd|Nw]` is the one-step report output: it writes the
|
|
72
|
+
dashboard PNG (identical to `trend --image`) to
|
|
73
|
+
`token-ledger-report-<period>.png` in the current directory. It accepts the
|
|
74
|
+
same flags as the trend view (`--drain`, `--date`, `--tz`, `--image-output`,
|
|
75
|
+
`--image-width`) and prints progress while rendering and encoding the image.
|
|
76
|
+
|
|
77
|
+
`tledger report 1d` shows the selected local calendar day in hourly columns,
|
|
78
|
+
including hourly cache efficiency. The current hour is marked partial; future
|
|
79
|
+
hours are not treated as observed zero usage. Use `--date yesterday` for a
|
|
80
|
+
completed day. This differs from the rolling 24-hour `tledger 1d` terminal view.
|
|
81
|
+
|
|
82
|
+
Use `tledger report 1d --private` to replace project names with `Project 1`,
|
|
83
|
+
`Project 2`, and so on, ranked by usage within that report. Counts and usage
|
|
84
|
+
remain visible; the local snapshot is unchanged. The default filename ends
|
|
85
|
+
in `-private.png` so the named report is preserved.
|
|
86
|
+
|
|
87
|
+
The terminal trend view is a compact approximation of the image view. For the
|
|
88
|
+
full chart grammar, use `--image`: it writes a single shareable report card as
|
|
89
|
+
a PNG. The report leads with a total-usage KPI (with a delta against the prior
|
|
90
|
+
equivalent period), input-weighted cache efficiency, the fast-mode share of
|
|
91
|
+
actual tokens, and the active-project count, beside the latest observed
|
|
92
|
+
weekly-limit state. Below that sit a model-mix strip, calendar-day columns of
|
|
93
|
+
local token volume stacked by model, daily cache efficiency with input
|
|
94
|
+
volumes, top projects, and a per-model cache table.
|
|
95
|
+
|
|
96
|
+

|
|
97
|
+
|
|
98
|
+
The weekly-limit line is drawn from sampled OpenAI observations, never
|
|
99
|
+
continuous telemetry: solid runs mark spans confirmed by repeated equal
|
|
100
|
+
readings, dashed runs bridge unobserved gaps, and the line never extends past
|
|
101
|
+
the latest reading. When the report is generated partway
|
|
102
|
+
through the final day, that column is marked `PARTIAL` with the actual cutoff
|
|
103
|
+
time, and the prior-period delta compares an equally long partial window.
|
|
104
|
+
Values allocated from compacted history or placed using an estimated event
|
|
105
|
+
time are marked with `≈`. Splitting usage between meter readings does not by
|
|
106
|
+
itself make the daily token total approximate. Reports built from an explicit
|
|
107
|
+
or stale snapshot say `Snapshot generated …` (with a `STALE SNAPSHOT` badge on
|
|
108
|
+
fallback).
|
|
109
|
+
Detailed source and integrity diagnostics remain in the generated snapshot's
|
|
110
|
+
coverage metadata.
|
|
111
|
+
|
|
112
|
+
When run from a terminal, the finished PNG opens in the default image viewer
|
|
113
|
+
automatically so the report lands on screen instead of in a file browser.
|
|
114
|
+
Pass `--no-open` to skip that; piped or scripted runs never open a window.
|
|
115
|
+
|
|
116
|
+
Turns run in fast mode (service tiers "priority" and "fast") are drawn with a
|
|
117
|
+
diagonal hatch inside their model's segment — fast mode is a property of usage,
|
|
118
|
+
not a separate model, so the hatch never adds bar height and stays legible in
|
|
119
|
+
grayscale.
|
|
120
|
+
|
|
121
|
+
The fast-mode KPI counts only usage explicitly recorded as `priority` or
|
|
122
|
+
`fast`. Missing or unrecognized service tiers are shown separately as unknown;
|
|
123
|
+
they are included in total usage but cannot be classified as fast or normal.
|
|
124
|
+
Input and cache metrics use only records with the necessary component counts.
|
|
125
|
+
Total-only records still contribute their reported tokens to total usage.
|
|
126
|
+
|
|
127
|
+
Pass `--drain` to flip the columns into limit-drain units instead: each column
|
|
128
|
+
becomes the weekly limit percentage the meter dropped, stacked by model using
|
|
129
|
+
rate-card credit weights (an estimate — the official card is the best
|
|
130
|
+
available proxy for per-model debit, but subscription limits are not billed
|
|
131
|
+
per token), on the same percent scale as the meter line.
|
|
132
|
+
|
|
133
|
+
Meter windows are keyed by their server-reported reset timestamp, so a fresh
|
|
134
|
+
window that starts days early (a provider-initiated limit restart) is drawn as
|
|
135
|
+
its own cycle and labeled `restart`, while a true weekly expiry is labeled
|
|
136
|
+
`reset`.
|
|
137
|
+
Stale readings from sessions still reporting a superseded window are dropped
|
|
138
|
+
instead of being fused into the line as phantom drain. Drops observed after a
|
|
139
|
+
sparse meter gap (over 36 hours) are spread across the covered days and marked
|
|
140
|
+
with `≈`. When a range has no usable meter drain, columns fall back to raw
|
|
141
|
+
local token counts and the chart says so.
|
|
142
|
+
|
|
143
|
+
`--image` defaults to `token-ledger-trend-7d.png` in the current directory.
|
|
144
|
+
Use `--image-output <file.png>` to choose the path and `--image-width <px>` to
|
|
145
|
+
choose a width from 900 to 2400 pixels.
|
|
146
|
+
|
|
147
|
+
Use `trend 14d` for daily columns across two weeks. At 30 days, the terminal
|
|
148
|
+
uses readable multi-day bins: three-day bins at ordinary widths and two-day
|
|
149
|
+
bins on wider terminals. The image view keeps daily columns while they stay
|
|
150
|
+
legible and falls back to the same readable multi-day binning for longer
|
|
151
|
+
windows. Meter-drain weighting uses the rate card bundled with this release;
|
|
152
|
+
subscription limits are not billed per token.
|
|
153
|
+
|
|
154
|
+
Models without a bundled price remain explicitly unrated in cost estimates.
|
|
155
|
+
Astra is recognized in usage reports but is unrated in this release's
|
|
156
|
+
purchased-credit and API-dollar estimates.
|
|
157
|
+
|
|
158
|
+
The CLI checks the local Codex source manifest on every automatic load. If it
|
|
159
|
+
differs from the cached watermark, the CLI rebuilds the privacy-reduced
|
|
160
|
+
snapshot; otherwise it reuses the cache immediately. The first refresh may
|
|
161
|
+
scan historical rollout files. The one-hour threshold affects only the
|
|
162
|
+
displayed freshness label, not source validation. Use `--refresh` to force a
|
|
163
|
+
rebuild even when the manifest is unchanged.
|
|
164
|
+
|
|
165
|
+
The `1d` project dashboard shows a compact snapshot-age line such as
|
|
166
|
+
`SNAPSHOT · fresh · 12m old`. `fresh` means the snapshot is within the
|
|
167
|
+
one-hour cache window, `stale` means it is older, and `age unknown` means the
|
|
168
|
+
snapshot has no usable capture-time metadata. The indicator does not print a
|
|
169
|
+
local path or trigger another source scan. Terminal reports also show a
|
|
170
|
+
separate provenance status: `VERIFIED CURRENT`, `STALE FALLBACK`,
|
|
171
|
+
`UNCHECKED CACHE`, or `EXPLICIT SNAPSHOT`. The standard PNG report communicates
|
|
172
|
+
freshness through its generation timestamp and stale/partial labels. Snapshot
|
|
173
|
+
age describes capture time; it never implies that the local source was checked
|
|
174
|
+
successfully.
|
|
175
|
+
|
|
176
|
+
Useful overrides:
|
|
132
177
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
178
|
+
```bash
|
|
179
|
+
# Use another timezone instead of the computer's local timezone
|
|
180
|
+
tledger week --tz America/New_York
|
|
136
181
|
|
|
137
|
-
|
|
182
|
+
# Force a complete local refresh
|
|
183
|
+
tledger week --refresh
|
|
138
184
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
metadata. It retains positive `last_token_usage` model-call events and their
|
|
142
|
-
timestamps, turn IDs, model/source attribution, and token categories.
|
|
185
|
+
# Skip the freshness check and use the existing cache
|
|
186
|
+
tledger week --no-refresh
|
|
143
187
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
marked as heuristic. State database token counters are kept as non-additive
|
|
148
|
-
reference values because forks and subagents inherit cumulative history.
|
|
188
|
+
# Read a specific privacy-reduced snapshot
|
|
189
|
+
tledger week --input /path/to/token-ledger-snapshot.json
|
|
190
|
+
```
|
|
149
191
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
double counting. Models are attributed from turn context/settings and local
|
|
154
|
-
thread metadata, then normalized for display.
|
|
192
|
+
`--static` prints once for pipes, logs, or terminals without interactive input.
|
|
193
|
+
`--plain` or `NO_COLOR=1` disables ANSI color. `--youplot` is an optional
|
|
194
|
+
legacy renderer and is not required for the default dashboard.
|
|
155
195
|
|
|
156
|
-
|
|
157
|
-
weekly window. Reset timestamps identify windows; stale readings and separate
|
|
158
|
-
named pools are not stitched into that meter. Remaining percentage,
|
|
159
|
-
observation time, and the selected window are local observations; the reset
|
|
160
|
-
type (weekly expiry versus restart) is derived by comparing the prior window's
|
|
161
|
-
reset timestamp with the first reading of the new window. None of this is an
|
|
162
|
-
official account-wide quota or billing record.
|
|
196
|
+
## Local data and privacy
|
|
163
197
|
|
|
164
|
-
The
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
project labels are user-written or local metadata and should be reviewed before
|
|
168
|
-
sharing. Normal successful dashboard output is privacy-reduced, but diagnostics
|
|
169
|
-
or explicit PNG writes may echo configured snapshot, Codex, or output path
|
|
170
|
-
labels.
|
|
198
|
+
The CLI reads from `CODEX_HOME` when set, otherwise `~/.codex`. It uses local
|
|
199
|
+
Codex rollout JSONL files, the session index, and local state metadata. It
|
|
200
|
+
writes a replaceable, privacy-reduced report snapshot to:
|
|
171
201
|
|
|
172
|
-
|
|
202
|
+
```text
|
|
203
|
+
~/.token-ledger/token-ledger-snapshot-v3.json.gz
|
|
204
|
+
```
|
|
173
205
|
|
|
174
|
-
|
|
175
|
-
priced separately, priority/fast-mode events use the 1.5× multiplier, and
|
|
176
|
-
events without a detailed breakdown or known model rate are unrated. These are
|
|
177
|
-
rate-card estimates, not provider billing totals.
|
|
206
|
+
It also maintains the durable local ledger separately at:
|
|
178
207
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
spread across local calendar days as estimates. Tokens-per-meter-point,
|
|
183
|
-
model-split burn, runway, and CLI `View burn` are derived estimates. None is
|
|
184
|
-
official billing, quota, or account-completeness truth.
|
|
208
|
+
```text
|
|
209
|
+
~/.token-ledger/token-ledger-ledger.sqlite
|
|
210
|
+
```
|
|
185
211
|
|
|
186
|
-
|
|
212
|
+
The ledger is the append-and-deduplicate source of truth for committed token
|
|
213
|
+
events, quota samples, source state, and useful thread metadata. The snapshot
|
|
214
|
+
is a generated export and can be replaced or rebuilt without deleting ledger
|
|
215
|
+
history. Refreshes scan both `sessions` and `archived_sessions`; a source that
|
|
216
|
+
is removed is recorded as missing or tombstoned, and its committed observations
|
|
217
|
+
remain available. A file replacement or truncation is recorded as a mutable
|
|
218
|
+
source change and does not re-add earlier observations.
|
|
219
|
+
|
|
220
|
+
When a token event is timestamped before its own recorded turn began, refresh
|
|
221
|
+
can use the turn's time as an estimated placement and retain the original
|
|
222
|
+
timestamp as provenance. The same repair applies to previously stored events.
|
|
223
|
+
This changes their date attribution, not their token counts; it cannot recover
|
|
224
|
+
the exact event time from a malformed source record.
|
|
225
|
+
|
|
226
|
+
Exact observations are retained for 3,650 days. Older observations are
|
|
227
|
+
compacted into UTC daily buckets with additive totals and source membership;
|
|
228
|
+
the supported report window is never silently compacted away. Existing v3
|
|
229
|
+
snapshots are migrated once, when readable, into explicitly marked
|
|
230
|
+
`migrated_compacted` rows. Those rows preserve totals and ranges but do not
|
|
231
|
+
invent exact event or turn identities, and remain marked as estimated in
|
|
232
|
+
coverage. A missing legacy snapshot is also recorded as checked so a later
|
|
233
|
+
refresh cannot unexpectedly migrate a different file into the same ledger.
|
|
234
|
+
An existing snapshot with malformed usage/thread history, or one that is
|
|
235
|
+
unreadable, oversized, non-regular, or non-v3, instead stops with
|
|
236
|
+
`ERR_DURABLE_LEDGER_LEGACY_SNAPSHOT` before the ledger
|
|
237
|
+
revision advances. Its bytes and the one-shot migration opportunity are
|
|
238
|
+
preserved so the snapshot can be privately backed up, repaired or replaced,
|
|
239
|
+
and retried.
|
|
240
|
+
|
|
241
|
+
Legacy quota samples are imported only when the snapshot explicitly carries
|
|
242
|
+
the current quota-identity contract. Older or markerless snapshots may have
|
|
243
|
+
keyed unnamed limits by a display label or an anonymous placeholder, so their
|
|
244
|
+
quota samples are skipped while safe usage and thread history still migrate.
|
|
245
|
+
Current-contract quota claims that fail identity or measurement validation are
|
|
246
|
+
also skipped independently instead of blocking otherwise valid usage history.
|
|
247
|
+
The generated snapshot reports this separately as `legacyQuotaStatus` and
|
|
248
|
+
`legacyQuotaRowsSkipped`.
|
|
249
|
+
|
|
250
|
+
Compacted rows are retained for 7,300 days (20 years) before retirement.
|
|
251
|
+
Source, quota, tool, and state-only thread metadata are pruned only after they
|
|
252
|
+
are outside the applicable retention horizon; the supported report window is
|
|
253
|
+
never silently dropped.
|
|
254
|
+
Compacted usage buckets retain their deduplicated source-association scope, so
|
|
255
|
+
`--no-archived` can exclude archived-only history without including it through
|
|
256
|
+
an aggregate that also contains active usage.
|
|
257
|
+
|
|
258
|
+
Legacy snapshot history is imported only when its collection scope and hashed
|
|
259
|
+
Codex-home identity are both provable. If either check fails, exact rollout
|
|
260
|
+
collection continues without that legacy history. The reason is recorded as
|
|
261
|
+
`coverage.legacySnapshotStatus` in the generated snapshot.
|
|
262
|
+
|
|
263
|
+
Codex quota records do not contain a ChatGPT account identifier. Token Ledger
|
|
264
|
+
therefore treats one `CODEX_HOME` and its durable ledger as one account boundary
|
|
265
|
+
and keys pools only by the canonical provider limit id; omitted or blank ids
|
|
266
|
+
mean the default `codex` pool. If different ChatGPT accounts share a
|
|
267
|
+
`CODEX_HOME`, their equal provider ids cannot be separated. Use distinct Codex
|
|
268
|
+
homes under separate OS user profiles when account isolation matters.
|
|
269
|
+
|
|
270
|
+
Raw provider limit ids are normalized and then hash-derived into stored pool
|
|
271
|
+
keys; the raw ids are not written to the ledger or generated snapshot.
|
|
272
|
+
Sanitized optional display labels are not identity, but may remain in the
|
|
273
|
+
ledger, generated snapshot, terminal report, and image report.
|
|
274
|
+
|
|
275
|
+
The application state directory is private (`0700`), and its ledger, lock, and
|
|
276
|
+
SQLite transient files are private (`0600`). The durable database location is
|
|
277
|
+
fixed at `~/.token-ledger/token-ledger-ledger.sqlite`; custom snapshot outputs
|
|
278
|
+
never relocate it. An explicit `--input` reads only that deliberate snapshot
|
|
279
|
+
input and does not use the durable ledger as a hidden data source.
|
|
280
|
+
|
|
281
|
+
The collector does not export message bodies, reasoning text, tool arguments or
|
|
282
|
+
results, credentials, file contents, or full local paths. Display titles may
|
|
283
|
+
contain user-written text. CLI errors and empty-state source labels show only a
|
|
284
|
+
safe filename label, not an absolute input or source path. When a PNG or report
|
|
285
|
+
is written, the explicit output path is reported so you can find the file. The
|
|
286
|
+
CLI makes no network requests.
|
|
287
|
+
|
|
288
|
+
For schema health signals, crash-safety guidance, cache/ledger
|
|
289
|
+
coherence, and the repeatable scaling benchmark, see
|
|
290
|
+
[Durable ledger operations](docs/durable-ledger-operations.md).
|
|
291
|
+
|
|
292
|
+
## Keyboard controls
|
|
293
|
+
|
|
294
|
+
In the interactive dashboard:
|
|
295
|
+
|
|
296
|
+
- `↑` / `↓` or `j` / `k` moves between projects.
|
|
297
|
+
- `q`, `Q`, `Esc`, or `Ctrl-C` exits.
|
|
298
|
+
- Enter does not inspect a project, and `d` / `w` / `m` do not
|
|
299
|
+
change the range; choose the desired range in the command instead.
|
|
300
|
+
|
|
301
|
+
## Verify from source
|
|
187
302
|
|
|
188
303
|
```bash
|
|
189
|
-
npm
|
|
190
|
-
npm run
|
|
191
|
-
npm run
|
|
192
|
-
npm
|
|
304
|
+
npm ci
|
|
305
|
+
npm run test:fast # quick contract feedback while editing
|
|
306
|
+
npm run check # all regular tests plus lint, before committing
|
|
307
|
+
npm run prepublishOnly # full suite, stress, lint, and installed-package checks
|
|
193
308
|
```
|
|
309
|
+
|
|
310
|
+
`npm run verify:release` packs the allowlisted artifact, installs that tarball
|
|
311
|
+
in a clean temporary directory with no network or Codex data access, and runs
|
|
312
|
+
the installed help commands, a synthetic `tledger 1d --static` dashboard, and
|
|
313
|
+
both standard and cache-rate PNG report smoke checks.
|
|
314
|
+
|
|
315
|
+
New top-level test files are included automatically. `npm test` retains the full
|
|
316
|
+
regular suite; `npm run test:integration` selects the CLI, importer subprocess,
|
|
317
|
+
and durable-ledger suites omitted by `test:fast`. `npm run test:all` runs regular
|
|
318
|
+
and stress tests together in one test-runner invocation. PR and main CI run all
|
|
319
|
+
regular tests; stress tests also run for release tags and before publication.
|
|
320
|
+
Superseded PR runs are cancelled automatically. Run the full gate once for the
|
|
321
|
+
final source state, rather than repeating its constituent commands.
|