Repository navigation
fix: 数え直し直後に主なモデルが載らない累積を取りこぼさない(欠落したモデルが支配的なら数え直し) - #5406
Merged
Merged
Conversation
#5402 の続き。数え直し直後の最初の累積に主なモデル(opus)が載らず、別のモデル(haiku)だけが載り、 それが前回以上だと reset にならず、基準に残った前回の opus に追いつくまでの消費が台帳に積まれなかった。 detectReset に「基準の全モデルの合計 cost より今回の合計 cost が小さい(厳密な <)」を足した。 等しい(再送)は数え直しにしない。今回に cost の読めなかった欄が在るときは合計を見ない。 既存の試験 1 本(基準 opus 5 に対し今回 sonnet 1)は合計が減る形で、数え直し直後の形と区別できないため、sonnet を 6 に改めた。
合計 cost の減少で数え直しとみなすと、#5402 の本番事象の形(haiku が載った直後に haiku の無い累積が来て、 opus がほぼ増えない)で合計が haiku の cost ぶん減り、opus 約 108 億の二重計上が再発しうる。 今回に無い基準のモデルの前回 cost の合計(欠落ぶん)が、今回の全モデルの cost 合計より大きい(厳密な >)ときだけ 数え直しとする。haiku のような小さな欠落は reset にならず、主なモデルが丸ごと欠けて別のモデルだけが載る 数え直し直後の形は reset になる。欠落が無ければ働かない。cost の unreadable が在れば判定しない。
This was referenced Oct 28, 2026
takecchi
added a commit
that referenced
this pull request
Oct 28, 2026
コメントだけの変更(挙動は変えない)。#5405・#5406 の続き。 - `usage.ts` の `detectReset` の上のコメントを、今の条件(欠落ぶんの前回 cost が今回の全モデルの cost 合計より大きいときだけ reset。小さな欠落は変化なし)に合わせた。 - 同じコメントに、両向きの危険を書いた。過大に数える側: 数え直しでない読みで opus が丸ごと欠け他のモデルだけが載ると誤って reset になり、基準が今回だけになるので、次の累積で opus が戻ると opus の全量が二重計上される(#5402 と同じ規模)。少なく数える側: 欠落が支配的でない数え直しは拾えない。台帳は推定値であること、reset は日誌(`turn_usage` 行の `reset` と gauge の exchange)で見張れることも書いた。 - `clone.ts` の `INBOX_SETTLE_MS` のコメントを外部の窓(と合成した報告の窓)の説明に絞り、報告の窓は `REPORT_SETTLE_MS` と書いた。 - `clone.ts` の `#pump` の待ちの前のコメントを、`settleWaitFor` の実装に合わせた(報告の窓は合成していない報告以外が届くと切れ、外部の窓は人間起点だけで切れる。`Inbox#settle` は待ちに入る前に積まれていた割り込みも見る)。 検証: prettier・eslint・tsc・usage/inbox の vitest が通った。
takecchi
added a commit
that referenced
this pull request
Oct 28, 2026
Issue #5409 を参照(案 A。#5402・#5406・#5407 の続き)。 ## 内容 reset の発生を、日誌を引かずに見張れるようにする。読み取りだけで、書き込みと基準の保存は変えない。 - `UsageAggregate`(`aggregate()` の戻り、`GET /usage` の応答)に、任意の `resets: [{layer, managerId, resets, lastResetAt?}]` を足した。基準(層 × 担当)ごとの回数と最終時刻。 - 基準が1件でもあるときだけ欄を載せる(無ければ欄ごと無い)。reset の無い基準は回数 0・`lastResetAt` 無し(「数え直しが無い」と「基準が無い」を区別するため)。 - 日付に依らない現在値: `from` / `to` / `site` / `tokenId` では絞らず、`layer` / `managerId` だけで絞る(基準は日付を持たないため)。並びは層、managerId の順。 - インメモリ / fs / pg の3実装の `aggregate()` が、同じ関数(`resetRowsOfBaselines`)で作る。pg は `usage_baseline` を(絞り込み付きで)select。 - `alteroid usage` は、1回以上ある基準だけ 1 行ずつ出す(0 回は出さない。0 回だけ・欄なしなら出力は 1 文字も変わらない)。`--json` は無い現状のまま。 - `apps/daemon/openapi.json` を再生成した(`pnpm -C apps/daemon build`)。 ## 既存クライアントへの影響 任意欄の追加だけで、既存の欄は変えていない。欄を知らないクライアントは無視でき、`resets` を読まない CLI の出力も変わらない。ただし基準が1件でもある台帳の応答には `resets` が載る(pg の「既存の応答を変えない」試験の鍵の一覧に `resets` を足した)。 ## 案 B(`reset` の行へ「欠落ぶんで判定した」印を足す案)は入れない schema を増やすので、A で足りるかを見てから。 ## 試験 - 契約(`verifyUsageResetsContract`)を3実装に当てた: 数え直しの後に回数・最終時刻が読める、基準に reset が無ければ 0 回で最終時刻なし、layer / managerId で絞れる、日付で絞っても変わらない、該当が無ければ欄ごと無い。 - `GET /usage` の応答(絞り込み・日付に依らない)と、`alteroid usage` の表示(1 回以上だけ・0 回は出さない・導入前と出力が変わらない)。 ## 変異の確認 - 基準の列挙(`resetRowsOfBaselines` が空を返す)にすると、契約の3実装(インメモリ・fs・pg)と `GET /usage` の試験が落ちた。 - CLI の表示(`describeUsageResets` を外す)にすると、CLI の表示の試験 2 本が落ちた。 - どちらも戻して全緑。 ## 限界 判定そのものは推定で、誤って数え直しとみなす(過大)も拾えない(過少)もありうる。この口は、回数が増え続けていないかを見張るためのもの。過去分の台帳は補正しない。
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.
Issue #5405 を参照(#5402 の続き)。
弱点
#5402 で reset は「今回にもあるモデルの値が前回より減ったとき」だけになり、基準は
{...prev, ...next}。本当の数え直し(resume //clear)の直後の最初の累積に主なモデル(opus)が載らず別のモデル(haiku)だけが載り、それが前回以上だと reset にならない。基準には前回の opus が残るので、新しい opus が追いつくまでの消費は差分 0 で台帳に積まれない(少なく数える)。直し方と判定の理由
detectResetに、今回に無い基準のモデルの前回 cost の合計(欠落ぶん)が、今回の全モデルの cost 合計より大きい(厳密な>)とき reset とみなす判定を足した。reset なら全量が増分、基準は今回だけ。今回に無いモデルが無ければ働かない。今回に cost の読めなかった欄(unreadable.costUsd)が在るときは判定しない(読めない cost は 0 で書かれ、今回の合計が小さく見えるため)。foldRecordForStoreは reset の旗をそのまま使うので、現役 runner(控えが今回だけになる)と superseded(skipped: decreased)に波及する。インメモリ / fs / pg は同じ関数を通る。「合計 cost が減った」を判定にしない理由: #5402 の本番事象は、haiku が載った直後(約 0.2 秒)に haiku の無い累積が来る形で、その間 opus がほぼ増えない。合計は haiku の cost ぶん減るので、合計の減少で reset にすると opus 約 108 億の二重計上が再発する。欠落ぶんが今回の合計より大きいときだけにすれば、haiku のような小さな欠落は reset にならず、主なモデルが丸ごと欠けた数え直し直後の形だけが reset になる。
案 1・3 を採らない理由
usage.tsのコメントの理由)。変えた既存の試験
「基準にあったモデルが今回に無いことは数え直しではない」は、基準 opus 5・今回 sonnet 1 だった。この元の形は、欠けた opus(5)が今回の合計(1)より大きく、数え直し直後に主なモデルが載らない形そのもの(reset になる)で、新しい判定と矛盾する。そのため sonnet を 6(欠落ぶん 5 が今回の合計 6 以下)に改め、「欠落ぶんが支配的でなければ reset にならない」を確かめる試験にした。理由は試験のコメントにも書いた。
試験
foldRecordForStoreの現役 runner・superseded に 1 本ずつ。変異の確認
限界