feat(forecast): the night is not runway — an hour shape for the walk - #33
Merged
Conversation
Claude Code can work around the clock; the human cannot, and every projection this script made burned flat through the night. Four measured consequences: `7d dry ~Thu 03:00`, which is a false alarm at 23:00 and a missed warning at 09:00; an L1 blend projecting a hot day's rate through eight idle hours; "spend it" at 23:00 for a surplus no waking hour can reach; and a ration dividing the week by windows you sleep through. The corpus already held the answer — burn credited by the envelope pass carries a timestamp, and hours that never burn across weeks are rest. `forecast.cache` gains `hour_profile`: 24 burn multipliers, local hour "0".."23", mean 1, so the rate at hour h is `weekday_rate x mult[h]` and integrating any whole day reproduces the weekday total exactly. Same envelope pass, same 14-day EWMA half-life, today excluded (a day that has only reached noon reports every evening hour as rest). Floored at 0.1 and renormalized at BUILD time so every reader sees the same numbers: a rest hour projects a tenth of a uniform hour, never zero, which is what the occasional overnight autonomous run costs. Additive, so `schema` stays 2; ccpace v0.4.0 implements the identical model and `docs/api/state-dir.md` is the contract, down to REST_MULT_MAX = 0.25. Read under one validation — 24 keys, each numeric in [0, 24], mean in [0.9, 1.1], days_history >= 14 — and anything else walks flat. A bad hour shape narrows no clause and silences nothing; only the weekday guards take the walk's voice away. The walk steps local hours now (<= 169 of them), because a rate that changes at 08:00 cannot be integrated a day at a time. That also ends the L1 blend at exactly 24h: day-sized steps let a blend starting mid-day run to the end of the day holding now+24h, up to 47 hours of a hot rate on a sentence claiming 24. On a calm 10%/day profile with a 40% trailing day, `lands ~70%` where it used to be ~73%. Surfaced in three places. The budget long form gains `~6 awake` — the windows falling in hours you have actually burned in — shown only when it cuts the calendar count, and `even` then divides by it, because a ration you can only hit by not sleeping is not a ration; at zero awake windows both clauses go and the landing stands alone. The surplus feasibility check counts awake seconds per leg, so `~35% expires even at full burn` replaces `spend it` on a night. `report` states the rhythm it walks: the longest circular run of rest hours, three or more, else "no rest learned". Row 2, the strip fold and the windows-ahead countdown are untouched. Dry warnings need no new words: the shaped walk moves the dry TIME out of sleep by itself, which was the early-warning fix all along. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
forecast.cachegainshour_profile: 24 local-hour burn multipliers (mean 1, floor 0.1, same envelope pass + 14d EWMA, today excluded). The learned walk steps hour-by-hour, so dry-outs land where the reader can act on them instead of mid-sleep; the surplus feasibility check counts awake seconds only; the budget line gains~N awakeand rations by it;reportstates the learned rhythm.REST_MULT_MAX=0.25is part of the cache contract (docs/api/state-dir.md); ccpace v0.4.0 implements the same build/read rules — cross-writer parity verified exact on a shared fixture.Smoked on a 259-day real corpus (26,770 samples, 1.1s build): learned
rhythm: rest ~12:00-19:00 · 17h awake/day; at 85% with 25h left the dry-out moves Tue 16:40 (mid-rest) → Tue 12:40 (end of active morning).🤖 Generated with Claude Code