Repository navigation
Description
opencode-usage-export: --window-hours / --fresh-hours are never validated — a junk window publishes a zero-filled status: "ok" document, a junk freshness reports a fresh store as moved
pm-stack/opencode-usage-export/opencode-usage-export.mjs (slice 1 of #2072, merged in PR #4680) parses its two numeric flags with a bare Number(...) and never checks the result:
parseArgs(:311-322):--window-hours→Number(argv[++i])(:317),--fresh-hours→Number(argv[++i])(:318). No finite/positive check; a missing value isNumber(undefined)=NaN; an unknown flag throws, but a known flag with a bad value does not.- The window flows unchecked into
sinceMs = now - args.windowHours * 3600000(:348) and the session queryWHERE time_updated >= ?(:221via:349). - The freshness flows unchecked into
freshMs: args.freshHours * 3600000(:343) and the liveness comparisonnow - p.newestUpdated <= freshMs(:165).
Verified this run (laptop probe, verbatim origin/main @ cf74b1e, file md5 13c24364)
Fixture store with one fresh session (updated 1 min before now) and one 48 h-old session, exporter extracted byte-identical from origin/main (~/git/fleet/probe-2026-11-02-laneA-usagewindow/ on the laptop):
| Invocation | Result |
|---|---|
| control (defaults) | exit 0, status: "ok", 1 session |
--window-hours banana |
exit 0, status: "ok", 0 sessions, windowHours: NaN |
--window-hours (value missing) |
exit 0, status: "ok", 0 sessions, windowHours: NaN |
--window-hours -5 |
exit 0, status: "ok", 0 sessions |
--window-hours Infinity |
exit 0, status: "ok", 2 sessions — the 48 h-old session outside any real window is included |
--fresh-hours banana |
exit 4, store-stale: "no candidate store has session_v2 activity within NaNh; newest activity [1 minute ago] — the live store may have moved" |
--fresh-hours -1 |
exit 4, store-stale, same misleading moved-store diagnosis for a store updated 1 minute ago |
Why it matters
The module's own contract is fail-closed: the header (:29-31) promises a tick that cannot read the live store "writes a failure document and exits non-zero — never a zero-filled success", and the README repeats that a failed tick can never look like a reading. An invalid --window-hours breaks exactly that promise: latest.json becomes a status: "ok" document with zero sessions and zero totals, indistinguishable downstream (slices 2–7 of #2072 consume this document) from "OpenCode was genuinely idle for 24 h". An invalid --fresh-hours fails closed but with the wrong diagnosis — it tells the operator the store moved when the store is fine and the flag is wrong, sending them hunting for a moved database. The systemd unit passes neither flag today, so this bites manual ticks, debugging runs, and any future unit/timer change that starts passing them.
Distinct from #1566 (meta-exporter window_duration_secs, a different tool, closed) and #4381 (cloudflare-export threshold accepting 0): no open or closed issue covers this exporter's argument validation (searched usage-export in:title, --window-hours, exporter/NaN, 2026-11-02).
Acceptance criteria
-
--window-hoursand--fresh-hoursvalues that are missing, non-numeric,NaN, infinite, zero, or negative are rejected before any store read: a failure document with a status/detail that names the invalid argument (notstore-stale), and a non-zero exit. - A valid positive finite value behaves exactly as today (existing tests green).
- New tests in
opencode-usage-export.test.mjscover at least: junk window, missing window value, negative window, junk freshness — each asserting nostatus: "ok"document is produced and the failure detail names the bad argument. - No
okdocument can ever carry a non-finite or non-positivewindowHours.
Activity
dezren39 commentedon Nov 3, 2026
🤖 Agent note · filed
52 remaining items
dezren39 commentedon Nov 4, 2026
agent-note:v1
task: 8444
stage: handed_off
lane: code-l
execution_lane: opencode
issue_state: open (verified fresh 2026-11-04)
next: claimant launches the bound opencode session
note: task 8444 attempts 15/16 — near cap; if the lease expires unlaunched a cap raise may be needed. Issue #4739 OPEN fresh via gh, no hard-stop labels.
dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 5, 2026
Picked up as task 8444 by lane code-c (repo-queue worker) and handed off to the opencode execution lane per the execution-lane assignment for task 8444. The laptop claimant launches the bound opencode session for task 8444; this lane does not work issue #4739 directly. Note: task 8444 is at attempts 19/32.
dezren39 commentedon Nov 5, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 5, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 5, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 5, 2026
🤖 Agent note · correction
gh pr list --search 4739in the same check returned open PR fix(usage-export): validate hours flags (#4739) #4790 "fix(usage-export): validate hours flags (opencode-usage-export: --window-hours / --fresh-hours are never validated — a junk window publishes a zero-filled status:ok document, a junk freshness reports a fresh store as moved #4739)", which appears to own this fix. The bound opencode session should evaluate/advance PR fix(usage-export): validate hours flags (#4739) #4790, not open a competing PR. The handoff itself stands.dezren39 commentedon Nov 5, 2026
agent-note:v1
state: handed off
task: 8444 (repo-health-code-pilot, worker repo-worker-code)
session: ses_e5e5589f378ffejE3h9MHlWsSx
found via: queue claim; execution lane opencode
launch: session created on the laptop OpenCode server at verified primary location /home/user/git/code, bound atomically before the prompt was sent.
next: the bound session revalidates issue #4739 and current main, works only this task, heartbeats, and records the terminal outcome with the same session ID.
links: task 8444 · issue #4739