Repository navigation
Closed
Labels
effort/sSmall: expected under 2 hours of workSmall: expected under 2 hours of workkind/infrastructureInfrastructure / host-portability workInfrastructure / host-portability workmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)
Description
Gap
#1057 is implemented and live-verified (2026-10-29, queue task 2990): scripts/produce-charge-candidates.ts (Plaid + Gmail → charges-candidates.json) feeds the fleet-feed collector, which publishes the /quota charges strip. But nothing runs the producer on a schedule:
- The collector (
fleet-feed-collector.timer, ~5 min, from the~/git/pm-feedclone) consumes the candidates file fail-soft — a stale file silently means a stale charges strip. - The only producer runs so far were by hand from agent sessions (2026-10-29 06:45Z during PR feat(aggregator): wire charges auto-matcher into collector + Plaid/Gmail producer (#1057) #2149 development, and 09:11Z during task 2990 verification).
- No systemd timer, cron job, or Muse scheduled job references
produce-charge-candidates(checked 2026-10-29: systemd timers,~/tools, and the Muse cron list).
Fix options
- A systemd timer on the sandbox mirroring
fleet-feed-collector(the producer is non-interactive: it shells out to/opt/hatch/bin/plaidand/opt/hatch/bin/hatch_gws_cli, both already usable from the collector unit context), daily or a few times a day, before a collector cycle. - Or fold the producer run into an existing daily Muse job that already touches the hub.
Acceptance
charges-candidates.jsongeneratedAtis never more than ~24h old without an agent remembering to run the producer.- A stale-candidates condition is visible somewhere (collector log line at minimum) instead of silently publishing old charges.
Refs #1057, #1349 (pm-feed staleness class). Filed by queue worker Lane B from task 2990 verification.
Acceptance criteria
- A scheduled mechanism (systemd timer, Muse scheduled job, or OpenChamber scheduled task — the choice recorded on this issue) runs
scripts/produce-charge-candidates.tson a cadence at least as frequent as the fleet-feed collector's consumption, without any agent session involved. - A fresh producer run's output is observed landing in
charges-candidates.jsonon schedule (timestamp evidence), and the /quota charges strip reflects data no older than one cadence interval. - The producer's failure mode is visible somewhere (a failed run leaves a record a monitor can find), rather than the current silent fail-soft staleness.
Metadata
Metadata
Assignees
Labels
effort/sSmall: expected under 2 hours of workSmall: expected under 2 hours of workkind/infrastructureInfrastructure / host-portability workInfrastructure / host-portability workmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)
Activity
developing-today commentedon Oct 29, 2026
CODE-1087
dezren39 commentedon Oct 29, 2026
Intake review
queue/queued. Normalized:kind/infrastructure,status/needs-triage,priority/normal,effort/s,meta/enriched; AC appended. A triage task (queue task 3387) was enqueued by this same monitor run under Duty 1 — the issue carriedqueue/queuedwith no live task behind it.fleet-feed-collector) is the smallest step; whichever mechanism is chosen, verify by watching one unattended run land.dezren39 commentedon Nov 1, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 1, 2026
🤖 Agent note · triaged and handed off
dezren39 commentedon Nov 2, 2026
🤖 Agent note · picked up
scripts/produce-charge-candidates.ts) socharges-candidates.jsonrefreshes unattended; first verifying the current runtime scheduler state fresh.dezren39 commentedon Nov 2, 2026
🤖 Agent note · done
Deployment choice (recorded per acceptance): systemd timer on the sandbox.
fleet-feed-collector.timer(every 5 min, last runs successful), readingcharges-candidates.jsonfrom the laptop hatch-personal checkout. The producer cannot run there — the laptop has no/opt/hatch/bin/plaidor/opt/hatch/bin/hatch_gws_cli; those connector CLIs live only on the sandbox, which is also where the producer header says it runs. No existing scheduler referenced the producer on either host (checked systemd system+user timers, Muse cron list, crontab).charge-candidates-producer.service+charge-candidates-producer.timerin/etc/systemd/system(mirrors thefleet-fetchsystem-unit precedent), running wrapper~/tools/produce-charge-candidates-scheduled.shevery 30 min. The wrapper ff-pulls~/git/devtoday-code(fail-soft), runsbun run scripts/produce-charge-candidates.tsfrompm-stack/aggregator, and uses only the connectors' existing credential handling — no secrets copied or exposed.generatedAtnever more than ~24h old; 30 min gives a 48x margin and refreshes far more often than the collector can surface a stale strip, without hammering Plaid/Gmail on the collector's 5-min cycle.generatedAt2026-10-29T09:10:17Z on both hosts. The timer fired on its own at 2026-11-02T02:18:00Z (no agent session), service exited SUCCESS, file advanced togeneratedAt2026-11-02T02:18:01Z; next fire 02:48Z. The laptop copy synced within minutes and the collector's 02:17Z run consumed the refreshed file successfully. Producer health spot-check: an October-period run to a temp file produced 80 candidates (plaid 64, gmail 16), so the current month's 0 candidates is a genuinely empty Nov 1–2, not a silent failure.hidden_files/charges-producer-runs.jsonlin this goal's workspace, and a failed run exits non-zero into the systemd journal (journalctl -u charge-candidates-producer) — no longer silent fail-soft.