Portfolio snapshot storage schema and delta engine
Parent: Cross-repo engagement radar epic
Milestone: v0.5.0
Goal
Define the storage format for cross-repo portfolio snapshots and build the delta computation logic that powers "what changed?" reports.
Storage design
Location options (in priority order):
~/.ghtraf/portfolio/snapshots/YYYY-MM-DD.json (local, default)
- Dedicated portfolio gist (cloud-backed, for dashboard access)
- Both (local primary, gist sync for dashboard)
Snapshot schema (one file per day):
{
"collectedAt": "2026-03-21T18:00:00Z",
"version": 1,
"repos": {
"djdarcy/github-traffic-tracker": {
"stars": 13,
"forks": 2,
"openIssues": 30,
"openPRs": 0,
"watchers": 5
},
"DazzleTools/Windows-No-Internet-Secured-BUGFIX": {
"stars": 144,
"forks": 15,
"openIssues": 3,
"openPRs": 1,
"watchers": 8
}
}
}
Delta computation:
- Compare two snapshots (today vs. yesterday, or today vs. N days ago)
- Per-repo:
delta = current[field] - previous[field] for each metric
- Flag repos with any non-zero delta
- Sort by largest positive delta (most attention first)
Merge-upward rule applies: same as traffic data -- never erase, always merge. If a repo disappears from the API (deleted, transferred, permissions changed), keep its last-known data with a lastSeen timestamp.
Relationship to existing gist storage
The portfolio gist is a separate gist from per-repo traffic gists. Naming convention: gtt-portfolio-<username>.json (following the gtt- prefix from #47).
Dependencies
- Prototype (#SUB1) informs the final schema
- Dashboard integration (#SUB3) needs this schema to be stable
Analysis
See 2026-03-21__17-57-11__dev-workflow-process_cross-repo-analytics-extend-vs-separate.md
Portfolio snapshot storage schema and delta engine
Parent: Cross-repo engagement radar epic
Milestone: v0.5.0
Goal
Define the storage format for cross-repo portfolio snapshots and build the delta computation logic that powers "what changed?" reports.
Storage design
Location options (in priority order):
~/.ghtraf/portfolio/snapshots/YYYY-MM-DD.json(local, default)Snapshot schema (one file per day):
{ "collectedAt": "2026-03-21T18:00:00Z", "version": 1, "repos": { "djdarcy/github-traffic-tracker": { "stars": 13, "forks": 2, "openIssues": 30, "openPRs": 0, "watchers": 5 }, "DazzleTools/Windows-No-Internet-Secured-BUGFIX": { "stars": 144, "forks": 15, "openIssues": 3, "openPRs": 1, "watchers": 8 } } }Delta computation:
delta = current[field] - previous[field]for each metricMerge-upward rule applies: same as traffic data -- never erase, always merge. If a repo disappears from the API (deleted, transferred, permissions changed), keep its last-known data with a
lastSeentimestamp.Relationship to existing gist storage
The portfolio gist is a separate gist from per-repo traffic gists. Naming convention:
gtt-portfolio-<username>.json(following thegtt-prefix from #47).Dependencies
Analysis
See
2026-03-21__17-57-11__dev-workflow-process_cross-repo-analytics-extend-vs-separate.md