1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! **The branch's last usage** — the provider's token report on the
//! newest model entry of the read-state tree, and the `window_percent`
//! predicate over it (`docs/DESIGN_CONTEXT_ECONOMY.md` §5.1).
//!
//! Usage rides the transcript entry (ARCH §2.3 *Usage rides the entry*),
//! so the window trigger reads the tree the state derivation already
//! holds — `messages/NNN-<model-id>.json`, the same listing context
//! assembly walks — and never `steps/`, which is diagnostic-only (§2.3).
//!
//! **Both numbers are the provider's, recorded and never computed.** The
//! numerator is the entry's `input_total_tokens` — the call's WHOLE
//! prompt, cached slices included, which brazen seals per protocol
//! shape so no consumer has to learn which dialect puts the cached
//! slice inside the prompt counter and which puts it beside (brazen
//! `specs/canonical-protocol.md` §3.2, brazen bl-d192). Its documented
//! consumer rule is exactly this trigger's: `input_total_tokens /
//! context_window` is fullness.
//!
//! **A record that predates the counter is read the old way.** The
//! entry was written by whatever `bz` answered the call, so a pre-0.0.10
//! adapter's `usage` sibling carries no `input_total_tokens`; that entry
//! falls back to `input_tokens` plus `cache_read_tokens` plus
//! `cache_write_tokens`, each absent counter contributing nothing,
//! because a `0` for a counter the provider never stated would be
//! litany's arithmetic wearing brazen's voice
//! ([`crate::prompt::dispatch::entry`], brazen's zero-vs-unknown rule).
//! The fallback over-reports on the three dialects whose prompt counter
//! already contains the cached slice — it fires the trigger early, never
//! late, which is the safe direction for a compaction clock.
//!
//! The denominator is the `context_window` the same report carries —
//! brazen states it in band on the `Usage` event, and the transcript
//! writer folds it in beside the counters like any other field brazen
//! adds under `v=1`, so litany keeps no per-model table (ARCH §4.2).
//!
//! **An unknown window is declined, loudly.** A workflow that names
//! `window_percent` for a model whose report carries no window has asked
//! for a threshold nothing can be measured against; answering "not due"
//! would ship a trigger that silently never fires, so the boundary
//! refuses instead, naming the model (`docs/PRINCIPLES.md`, decline
//! illegal operations). A branch with **no model entry at all** — step 1,
//! before its first model call — is simply not due: that is the general
//! path with empty inputs, not an unknown window.
use Error;
use Value;
use Path;
/// Branch-scoped transcript directory (ARCH §2.3 — `messages/NNN-…`).
pub const MESSAGES_DIR: &str = "messages";
/// The one reserved `.json` origin token (§2.3): a `tool` entry is a
/// `tool_result`, not model output, and carries no usage report. Every
/// other `.json` token is the model id that authored the entry.
const TOOL_ORIGIN: &str = "tool";
/// The provider's report on the branch's newest model entry.
/// The `window_percent` predicate (§5.1): due when `last`'s prompt side
/// reaches `n` percent of its reported context window. No last usage is
/// not due; a last usage with no window is the decline.
pub
/// Read the branch's last usage out of `worktree`'s transcript: the
/// highest-numbered `messages/NNN-<model-id>.json`, ignoring the
/// reserved `tool` origin and every `.md` delivery. `None` when the
/// branch has no model entry yet, or when its newest one carries no
/// `usage` sibling — the bare-array shape is lawful (§2.3).
pub
/// `(NNN, model-id)` of a `messages/NNN-<model-id>.json` path, or `None`
/// for anything else the directory holds: a `.md` delivery, the reserved
/// `tool` origin, a name with no counter prefix.
pub
/// The `usage` sibling of one entry's bytes, folded into a [`LastUsage`].
/// A bare block array, or an object with no `usage`, reports nothing.
/// The prompt side prefers brazen's served `input_total_tokens` and
/// falls back to the three-counter sum only when the entry predates it
/// (module docs).
pub