sigrank 0.15.5 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/tokenpull.mjs CHANGED
@@ -164,6 +164,14 @@ export async function tokenpull({ adapter = claudeAdapter, root, now } = {}) {
164
164
 
165
165
  const windows = WINDOWS.map((w) => {
166
166
  const cutoff = w.days === Infinity ? -Infinity : nowMs - w.days * DAY_MS
167
+ // NULL-TIMESTAMP WINDOW ASYMMETRY: the `all` window returns true unconditionally,
168
+ // so records whose adapter cannot supply a timestamp (ts: null or unparseable)
169
+ // appear in all-time but disappear from 7d/30d/90d. This is intentional — we do
170
+ // not fabricate timestamps. Session-granularity adapters (goose/droid/hermes)
171
+ // typically have created_at/updated_at, but if those columns are absent the row
172
+ // is all-time-only. A file-mtime fallback was considered but rejected: mtime
173
+ // reflects the log file, not the session, and would misattribute old sessions
174
+ // to recent file-touch times.
167
175
  const inWin = msgs.filter((m) => {
168
176
  if (w.days === Infinity) return true
169
177
  const t = m.ts ? Date.parse(m.ts) : NaN
@@ -250,6 +258,8 @@ export async function tokenpullCodex({ adapter = codexAdapter, root, now, ioRati
250
258
 
251
259
  const windows = WINDOWS.map((w) => {
252
260
  const cutoff = w.days === Infinity ? -Infinity : nowMs - w.days * DAY_MS
261
+ // NULL-TIMESTAMP WINDOW ASYMMETRY: see tokenpull() above — same behavior.
262
+ // Records without a parseable ts appear in `all` only, not in 7d/30d/90d.
253
263
  const inWin = recs.filter((m) => {
254
264
  if (w.days === Infinity) return true
255
265
  const t = m.ts ? Date.parse(m.ts) : NaN
@@ -284,7 +294,9 @@ export async function tokenpullAny(platform, opts = {}) {
284
294
  let ioRatio = opts.ioRatio || 2.0
285
295
  if (!opts.ioRatio) {
286
296
  try {
287
- const c = await tokenpull({ adapter: claudeAdapter })
297
+ // Forward root/now from opts so the Beta-ratio derivation is testable
298
+ // (without this, it always reads the real ~/.claude and can't be injected).
299
+ const c = await tokenpull({ adapter: claudeAdapter, root: opts.root, now: opts.now })
288
300
  const all = c.windows.find((w) => w.window === 'all')
289
301
  if (all && all.pillars.output > 0) ioRatio = all.pillars.input / all.pillars.output
290
302
  } catch { /* no Claude data → Alpha 2.0 */ }