Repository navigation
Weekly Pace: pick which weekly bucket it measures - #10
Conversation
The widget always measured the overall seven-day bucket. A new `source`
metadata value (weekly / sonnet / opus / fable) picks a per-model bucket
instead, derived from WEEKLY_MODEL_USAGE_BUCKETS so a new model bucket
gets a pace source without another table to update.
- `s` in the items editor cycles the source; the model name shows as
editor modifier text and prefixes the rendered label ("Fable Pace: ").
- usage-prefetch resolves Weekly Pace requirements per item, so a
fable-source widget fetches weeklyFableUsage instead of weeklyUsage,
and accepts the overall weekly reset when the model bucket has none.
- Omitting `source` keeps the previous fields, resolver, and labels, so
existing configs render unchanged.
Follow-up to the source option, plus a pre-existing bug it made reachable.
Conclusive-absence rule now covers every model bucket. It was hand-listed
for Fable only, directly under a comment saying per-model entries are
derived from WEEKLY_MODEL_USAGE_BUCKETS so they cannot drift. A required
weeklySonnetUsage/weeklyOpusUsage the account never reports could never
be satisfied, so clearUsageLock() was never reached and the 30-second
in-flight lock survived: every second render returned {error: 'timeout'},
and widgets that check data.error before their own field showed
[Timeout] indefinitely. Also fixes the existing weekly-sonnet-usage and
weekly-opus-usage widgets.
No phantom pace verdicts. A present-but-null legacy bucket parses to
utilization 0 with no resets_at (sirmalloc#343). Pace now applies the same
placeholder guard isPlaceholderUsageApiLimit already applies to limits[],
so it no longer states "Opus D4/7: Underusing -50%" about a bucket the
user may be actively burning. A per-model source with no usable reading
renders [No data] rather than hiding, so a mis-set source stays visible;
the overall bucket still hides itself, unchanged.
Stable source ids. The persisted `source` value came from
modelDisplayName.toLowerCase(). That string exists to match
limits[].scope.model.display_name and may be retuned when the API
changes, which would silently invalidate every saved config. It is now
an explicit paceSourceId on the bucket.
One code path. The overall source no longer branches around
resolveWeeklyPaceWindow, and the prefetch requirements have one shape for
every source. The branch existed only to keep existing test mocks alive;
those now spy on the resolver the widget actually calls.
Tests: resolveWeeklyPaceResetAt/resolveWeeklyPaceWindow are now executed
rather than mocked away, off-hours is covered with a per-model reset,
Sonnet and Opus render paths are covered, and the lock release is
asserted for all three buckets. The existing missing-required-fields lock
test keeps its coverage on extraUsageEnabled, which is still genuinely
non-conclusive.
d75dd47 to
18afe8d
Compare
|
Good catch on the lock bug. I traced it on Two things before this goes in. The resolvers didn't actually consolidate. The description says export function resolveWeeklyFableUsageWindow(usageData, nowMs = Date.now()) {
return getWeeklyUsageWindowFromResetAt(usageData.weeklyFableResetAt ?? usageData.weeklyResetAt, nowMs);
}
// ...and separately
export function resolveWeeklyPaceWindow(usageData, source, nowMs = Date.now()) {
return getWeeklyUsageWindowFromResetAt(resolveWeeklyPaceResetAt(usageData, source), nowMs);
}Collapsing the three into
Also worth a line in the notes: a real 0% early in the week on a bucket without its own Ignore the conflicts, they're our release churn. I'll rebase, retarget to 2.4.16, and move the comment block above |
Weekly Pace can measure one model's weekly bucket instead of only the overall seven day one.
sin the items editor cycles weekly / Sonnet / Opus / Fable. Sources derive fromWEEKLY_MODEL_USAGE_BUCKETS.Omitting
sourcerenders byte identical output to before.Also fixes two existing bugs
Usage lock held open.
FABLE_USAGE_FIELDSwas hand-listed, directly under the comment saying per-model entries derive fromWEEKLY_MODEL_USAGE_BUCKETSso they cannot drift. A requiredweeklySonnetUsageorweeklyOpusUsagethat the account never reports was never satisfiable, soclearUsageLock()never ran, the 30 second lock survived, and every second render returned{error: 'timeout'}. Widgets that checkdata.errorbefore their own field then showed[Timeout]permanently.weekly-sonnet-usageandweekly-opus-usagehit this today.Phantom verdict.
getUsageApiBucketUtilization(null)returns0, andusage-types.tswarns the flatseven_day_*keys return null even for models with real usage. Pace printedOpus D4/7: Underusing -50%off that. It now applies the rule fromisPlaceholderUsageApiLimit: 0% with no reset of its own is a placeholder, not a reading.Notes
[No data]rather than hiding, which would undo v2.4.9. The overall bucket still hides itself, unchanged.sourceid is an explicitpaceSourceId, notmodelDisplayName.toLowerCase(). That string tracks the API and would break saved configs if retuned.extraUsageEnabled, which is still genuinely unresolved.resolveWeekly{Sonnet,Opus,Fable}UsageWindoware now special cases ofresolveWeeklyPaceWindow.Checks
2154 tests, was 2123. Lint and
tsc --noEmitclean.scripts/test-inventory-gate.shreports no lost tests. New coverage: unmocked resolvers, off hours with a per-model reset, Sonnet and Opus render paths, placeholder zero, absent bucket, raw value mode, lock release for all three buckets.