Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,54 @@

## Unreleased

## v0.28.0 — 2026-08-19 — the notice engine

**New: a notice engine behind rows 2 and 3.** The advisor was one
sentence built by one function; it is now a set of readers that emit
*notices* — records carrying rank, voice, scope, a key for the
condition, the number worth bolding, and both a short and a long form.
Row 2 **pins** the top notice (compacted to the room the ledgers leave,
cut at the rightmost joint so it gives up as little as possible) and
keeps it while the condition holds. Row 3 **flashes** the same notice in
full, but only for ~90 s after that condition first appears in this
session: the explanation arrives once, then leaves the pin alone. A
later story takes row 3 next. `--notice off` (or `STATUSLINE_NOTICE=off`)
keeps row 3 quiet.

**New: notices that know which limit binds.**

- `fb 91% vs 7d 55% · go op` — the *model's* weekly limit caps before the
account's 7d does. Line 1 shows both numbers, never their relation,
and the relation is the whole decision: switch and the week's
remaining capacity comes back. The roomiest other `weekly_scoped`
limit in the payload gets named; with a projected wall it speaks in
the pressure voice and carries `dry ~Wed 18:00` in the long form.
- `7d rebased 53%→12%` — utilization fell *inside* one window instance.
Burn never runs backwards, so this is a plan change or an out-of-band
reset moving the denominator. Tracked per account, newsworthy for
30 min, and it mutes the underuse voice while the learned walk still
describes the old period.
- `last 5h of the week · 47% unused` — the 7d reset lands inside this 5h
window: no later window exists to spend the remainder through. Carries
the same feasibility tail as the surplus notice.
- `5h ~40m left · 70% unused` — throughput you cannot bank, said *only*
when the week is stranding capacity. An unspent 5h window is otherwise
headroom, not waste: the 5h window is a rate limit, not a budget.

**Shorter rows.** The pin drops what line 1 already prints
(`! 5h caps ~05:18`, not `..., 42m before reset`); the full sentence is
one row down, or on `--check` / `--week`, which have a line to spend.
The number you act on is **bold**. And the 5h strip no longer repeats
the reset the 5h badge carries — one badge per fact, in both directions;
the 7d strip keeps its own label until the 7d badge shows one.

**Fixed: a record with an empty field lost everything after it.** Notice
records were tab-separated, and tab is IFS whitespace — bash collapses
runs of it, so one empty field shifted every field after it. They use US
(0x1f) now. Also fixed a `{ printf; [ -f ] && tail; }` group whose exit
status came from the `[ -f ]` test, so a first-ever notice was never
stamped and the flash never faded.

## v0.27.0 — 2026-08-19 — row 2 mirrors line 1

**The advisor moves up beside the ledgers.** Row 2 now mirrors line 1:
Expand Down
72 changes: 57 additions & 15 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ change breaks a rule, the rule wins or the rule changes here first.
## Rows

```
line 1 where · what · how much is left (always)
row 2 what to do about it | where it went (advisor left, 5h + 7d ledgers right)
row 3 the advisor, full, when row 2 has no room (narrow terminals only)
line 1 where · what · how much is left (always)
row 2 the pin | where it went (top notice left, ledgers right)
row 3 the flash: that notice in full, fading (~90 s after it first appears)
```

Row 2 mirrors line 1: advice left, evidence right, the gap absorbs the
width, the right edge is line 1's edge (never `COLUMNS`). The advisor
sentence compacts to the room the ledgers leave — weakest joint first
(`;` voice, `·` clause, `,` sub-fact), leading fact last; under 16
columns it drops to row 3 instead, and the rows hang as a block: the
width, the right edge is line 1's edge (never `COLUMNS`). The pinned
sentence compacts to the room the ledgers leave, cutting at the
rightmost joint (`;` a voice, `·` a clause, `,` a sub-fact) so it gives
up as little as possible; under 16 columns it drops to its own row and
the rows hang as a block: the
widest meets line 1's edge, the rest share its left edge. A lone row is
the block. Line 1 must fit: Claude Code truncates or wraps a wider row
and every anchor beneath it goes wrong. Degrade in value order before
Expand All @@ -26,6 +27,13 @@ Claude Code trims each row it renders (`.trim()` per line, 2.1.234), so
a block's padding rides behind a zero-width `\e[0m`: not whitespace, so
it survives; not ink, so it costs nothing.

**A number line 1 prints is not printed again below.** The 5h badge
always carries its reset while the window is live, so the 5h strip drops
its `@HH:MM` and spends those columns on the message; the 7d badge
carries one only under pressure, so the 7d strip labels its own end
until it does. The test is what line 1 actually rendered, not a
re-derivation of its gates.

## Line 1, left → right

```
Expand Down Expand Up @@ -97,14 +105,48 @@ colored. `▮` moves at cell boundaries; every other cell is history — the
row is freeze-safe by construction. Same glyphs, same math as
[ccpace](https://github.com/thevibeworks/ccpace)'s ledger.

## Advisor (row 2 left, or row 3)
## The notice engine (row 2 left, row 3)

Readers turn the live numbers into **notices**. One record per thing
worth saying:

```
rank voice scope key hl short long
```

- **rank** — value order. The top record is the pin.
- **voice** — `!` pressure (yellow/red) · `+` opportunity (cyan) · `-`
budget (dim). Cyan can never mean pressure, so colour alone carries
the stance.
- **scope** — `5h` / `7d` / `fb` / `acct`. One voice per scope per
frame: two clauses about one window can never disagree.
- **key** — identity of the *condition*, not of the text. Row 3 shows a
notice only while its key is new to this session (~90 s), so a long
explanation arrives once and then gets out of the way.
- **hl** — the number the reader acts on: bold, then back to the voice.
- **short / long** — the pin, and the sentence for a surface with a
whole line (row 3, `--check`, `--week`).

The pin stays while its condition holds. The flash fades. `--notice off`
keeps row 3 quiet; `--advisor off` silences both.

What the readers know, beyond the badges:

Speaks when line 1's numbers don't mean what they look like, and — while
the ledgers are showing — says the calm numbers they imply, on their
left. Three voices,
one hue each: `!` pressure (yellow/red), `+` opportunity (cyan), `-`
budget (dim: windows left · even · heading). Every clause derives from a badge
already shown; max two clauses; the 7d window gets one voice per frame.
```
fb capped ~Thu 07:00 the running model is gone until then
5h caps ~05:18 this sitting hits the wall before its reset
7d dry ~Thu 09:00 the learned weekday forecast, not a straight line
7d rebased 53%→12% utilization fell INSIDE one window: a plan change or
an out-of-band reset moved the denominator, and the
ledger below still draws the old period
last 5h of the week no later window exists to spend the remainder through
fb 91% vs 7d 55% the MODEL caps first, not the account: switch, and the
week's remaining capacity comes back
5h ~40m left throughput you cannot bank — said only while the week
has slack, since an unspent 5h window is otherwise
headroom, not waste
~62% will expire on pace to strand a large chunk of the subscription
```

## Requests

Expand All @@ -127,7 +169,7 @@ The API is asked for what the protocol does not hand us, and no more.
## Words

Lowercase, terse, plain: `caps`, `dry`, `unused`, `expires`, `spend it`,
`go heavier`. No exclamation marks except the pressure sigil. Numbers
`go heavier`, `go op`. No exclamation marks except the pressure sigil. Numbers
first, verbs second, adjectives never. `,` joins facts, `·` joins
clauses, `;` joins voices. No em dash on the line: a cell wide, it reads
as a minus beside `-`/`+` and says less than `·`.
Loading
Loading