Skip to content

fix(cli): keep cron's state inside --cache-dir and quiet its first run - #39

Merged
zz-plant merged 3 commits into
mainfrom
fix/cron-cache-dir
Oct 13, 2026
Merged

zz-plant merged 3 commits into
mainfrom
fix/cron-cache-dir

Conversation

@zz-plant

Copy link
Copy Markdown
Collaborator

Two refract cron bugs, confirmed against @refract-org/cli@0.5.17 from npm and present on main.

1. --cache-dir did not isolate cron

Cron called runAnalyze without its cache dir. The analysis's --since path then read and overwrote ~/.wikihistory/observations/<page>.json and printed a "Re-observation delta" against that file. On a first run into an empty --cache-dir, it reported e.g. "New events: 66, Resolved: 8, Unchanged: 87" from an unrelated earlier run. That delta also counted prior events outside the lookback window as resolved, which cron's own count does not, so the two numbers could disagree.

Cron now passes its cache dir through and asks analysis not to record an observation, via a new optional trailing argument to runAnalyze: { recordObservation: false }. Cron keeps the only observation, under its cache dir. refract analyze --since is unchanged.

2. A page's first run printed a stack trace

reports/<page>.json does not exist until the first run finishes, and reading it was logged as a failure with the ENOENT and its full stack. refract analyze --since did the same for its first observation file. A new readPriorJson helper is silent on a missing file. It reports any other read or parse failure in one line, naming the path and the reason. All three readers use it.

Tests

  • cron.test.ts:
    • a first run writes nothing to stderr
    • a corrupt report is logged as one line with no stack
    • the call-shape assertion now expects the cache dir and { recordObservation: false }
    • two tests whose mocks simulated analysis writing cron's file were reworded or simplified
  • cron-cache-dir.test.ts runs cron twice over the real analysis pipeline against fake-mediawiki, with homedir() mocked to an empty temp dir. It asserts:
    • nothing is created under the home dir
    • stderr has no "Re-observation delta" and no ENOENT
    • the state files land in the cache dir
  • analyze-helpers.test.ts:
    • analyze --since's first observation is silent
    • the opt-out neither prints nor writes anything

With the original cron.ts swapped back in, all four new or changed cron tests fail. The real-pipeline test fails because .wikihistory appears in the fake home.

Verification

  • bun run build, typecheck, biome ci packages/, check:boundaries and bun run test pass: 380 passed, 9 skipped. The skips are the REFRACT_TEST_LIVE contract tests; mediawiki-client.ts is untouched.
  • Ran the repro against live Wikipedia with the built CLI, twice: refract cron pages.txt --interval 720 --cache-dir <scratch> with Earth.
    • No stack trace and no inner delta.
    • The mtimes in ~/.wikihistory/observations did not change.
    • Only observations/Earth.json and reports/Earth.json were written in the cache dir.

Not changed

  • On a first run, cron prints "No changes" while its report says "baseline established".
  • analyze --since --cache-dir D stores its observation at D/<page>.json, not D/observations/<page>.json.

🤖 Generated with Claude Code

zz-plant and others added 3 commits October 12, 2026 20:19
cron ran analysis without its cache dir, so the inner --since path read and
overwrote ~/.wikihistory/observations/<page>.json and printed a
"Re-observation delta" against it — outside --cache-dir, and counting prior
events outside the lookback window as resolved, which cron's own count does
not. Cron now passes its cache dir through and asks analysis not to record an
observation (runAnalyze's new { recordObservation: false }); cron keeps the
only one.

A page's first run logged the not-yet-written report with its ENOENT and full
stack; analyze --since did the same for its first observation. readPriorJson
is silent on a missing file and reports any other read or parse failure in
one line, path and reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
packages/cli/src/commands/analyze.ts conflicted on runAnalyze's signature:
#38 widened its return type with `coverage`, this branch added the
`{ recordObservation }` option. Kept both.

CHANGELOG.md had two "## Unreleased" headings on main, from #38's section
merging beside the existing one without a conflict. Folded them into one,
entries unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zz-plant
zz-plant merged commit 8030b6b into main Oct 13, 2026
3 checks passed
@zz-plant
zz-plant deleted the fix/cron-cache-dir branch October 13, 2026 01:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant