Skip to content

fix: Fix Metrics History Destruction & Self-Exclusion Blind Spot#34

Merged
sahil-noon merged 2 commits into
mainfrom
260610-srmi-fix-metrics-history-destruction
Jun 10, 2026
Merged

fix: Fix Metrics History Destruction & Self-Exclusion Blind Spot#34
sahil-noon merged 2 commits into
mainfrom
260610-srmi-fix-metrics-history-destruction

Conversation

@sahil-noon

Copy link
Copy Markdown
Collaborator

Meta

ID Type Confidence Plan Review
srmi fix 3.5/5.0 10/10 tasks, 21/21 acceptance ✓ ✓ 1 cycle

Pipeline: intake ✓ → apply ✓ → review ✓ → hydrate ✓ → ship → review-pr

Impact: +849/−5 code (excluding fab/, docs/) · +1234/−9 total

Summary

Claude Code purges session transcripts older than 30 days, so a machine's live ccusage view of old dates collapses toward zero — and tu's multi-machine sync treated that live fetch as authoritative, unconditionally overwriting correct per-day JSONL snapshots in the shared metrics repo ($5,160 measured destroyed; e.g. 2026-04-24 went $308.12 → $9.46). A compounding self-exclusion bug meant a machine could not see its own synced history once local transcripts were purged. This change makes day-files true high-water marks via a never-shrink guard in writeMetrics, ships a one-time repair script that restores shrunk files from the repo's git history (run manually post-release), and max-merges own-machine snapshots back into the live local view (fixing --by-machine and watch mode too).

Changes

  • Never-shrink guard in writeMetrics (src/node/sync/sync.ts)
  • One-time repair script (scripts/repair-metrics.mjs, new)
  • Self-view max-merge (src/node/core/cli.ts + src/node/core/fetcher.ts)

sahil87 added 2 commits June 10, 2026 21:18
- Never-shrink guard in writeMetrics: skip the day-file write when the
  incoming entry's totalCost is below the existing snapshot's — Claude
  Code purges transcripts >30 days old, so every sync was overwriting
  correct per-day JSONL history with post-purge residue (~$5,160
  measured destroyed across machines)
- New standalone scripts/repair-metrics.mjs (dry-run default, --write)
  restoring shrunk day-files to their historical max from the metrics
  repo's git history; run manually post-release
- Self-view max-merge: own-machine repo snapshots are max-merged into
  the live local view via new pure maxMergeEntries in fetcher.ts, so a
  machine sees its own synced history after local transcript purge
  (fixes --by-machine and watch mode too)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR prevents multi-machine sync from silently destroying historical daily metrics after Claude Code transcript retention purges, and fixes a related “self-exclusion” blind spot where a machine could no longer see its own synced history once local transcripts were gone.

Changes:

  • Added a never-shrink guard in writeMetrics so per-day snapshot files act as high-water marks and are not overwritten by lower totalCost values.
  • Introduced a standalone one-time repair script (scripts/repair-metrics.mjs) to restore shrunk day-files from the metrics repo’s git history (dry-run by default, --write restores working tree only).
  • Fixed own-machine self-view by max-merging local live entries with the machine’s own repo snapshots before summing with other machines.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/node/sync/sync.ts Adds the never-shrink write guard to protect historical day-file snapshots.
src/node/sync/tests/sync.test.ts Adds coverage for shrink-skip, equal refresh, and corrupted/empty existing files.
scripts/repair-metrics.mjs Adds a standalone repair tool to detect and restore shrunk metrics files from git history.
src/node/sync/tests/repair-metrics.test.ts End-to-end tests for the repair script using a hermetic seeded git fixture repo.
src/node/core/fetcher.ts Adds maxMergeEntries helper (whole-entry per-label max by totalCost).
src/node/core/cli.ts Rewires merged fetch paths to max-merge own snapshots into the local view and read all machines in one pass.
src/node/core/tests/fetcher.test.ts Adds unit tests for maxMergeEntries semantics (ties, copies, ordering, non-mutation).
src/node/core/tests/self-view-merge.test.ts Composition test mirroring the multi-mode pipeline to validate corrected self-view behavior.
docs/memory/sync/multi-machine.md Documents high-water-mark semantics, guarded writes, self-view max-merge, and the repair script contract.
docs/memory/sync/index.md Updates sync memory index description/date to reflect new semantics.
docs/memory/cli/data-pipeline.md Documents the updated multi-mode pipeline including maxMergeEntries.
docs/memory/cli/index.md Updates CLI memory index date to reflect the pipeline update.
fab/changes/260610-srmi-fix-metrics-history-destruction/* Adds/updates change tracking artifacts (intake/plan/status/history).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@sahil-noon sahil-noon marked this pull request as ready for review June 10, 2026 18:18
@sahil-noon sahil-noon merged commit 01fe24e into main Jun 10, 2026
3 checks passed
@sahil-noon sahil-noon deleted the 260610-srmi-fix-metrics-history-destruction branch June 10, 2026 18:18
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.

3 participants