hub #143 · decision artifact · 2026-08-14

demo-301's site branch: what a fork actually costs

#143 asks whether a ~302 MB published branch is the right shape for a repo whose whole purpose is to be forked, and says the call must be made before demo-301 is used as the keynote's fork template. The 302 MB figure is exact. It is also not what a fork downloads. This page reports what was measured, and recommends two cheap changes plus one growth bound. Companion to the app plan-rewrite decisions (A4 decides whether demo-301 is the template at all — this page decides what to do about its size either way).

Decided

@jwildfire · 2026-08-15 · Operations Dashboard

“I’m good with the recommendations here, but I think the real issue is that we need to move to a more robust database instead of just leaning on github sooner or later. Add discussion of that approach to the upcoming grill-me session related to the app strategy/design.”

All six calls settled as recommended. Doing: stop publishing the current snapshot twice — the branch root copy goes and the site resolves the current snapshot through the index it already keeps (S1); shrink the synthetic data extracts that make up most of what a fork downloads, after auditing which workflows read them (S2); and put a retention limit on published snapshots, landing with the fix to the scheduled pipeline, because the day that pipeline goes green is the day the branch resumes growing (S3). Not doing: moving rendered charts out of the published tree (S4) or republishing from a single-commit orphan branch (S5) — both trade away a load-bearing property for a benefit the measurements do not support. Nor is this accepting the current size and spending the effort elsewhere (S6).

Follow-through, filed 2026-08-15 against the fork-template risk (#143, milestone 2026q3, nothing implemented yet): #189 drops the duplicate root copy, #190 shrinks what a fork downloads, #191 bounds the branch's growth.

The second half of his answer is a separate and much larger question than branch size: whether this program should keep using GitHub itself as its datastore — issues holding requirements and goals, a git branch holding study data and snapshots, JSON files holding the decision registry. It is not a size call and nothing here decides it; it is recorded as a prep topic for the app-strategy elicitation interview on goal #79, with the candidate questions written out in that thread.

The situation

demo-301's site branch — the static tree GitHub Pages serves and the app reads — checks out to 302.58 MiB across 689 files, exactly as #143 reported, and every republish pushes on the order of 500 paths.

But #143's framing (“cloning the demo means pulling hundreds of megabytes”) does not match what a fork does: a default clone downloads ~91 MiB compressed for all branches and checks out main, landing ~125 MiB on disk — of which 124.48 MiB is input/, and 103 MiB of that is two synthetic data-management CSVs. The site branch's 302 MiB is only materialised by whoever checks that branch out, which in a fork is the Actions runner.

So there are two separate problems wearing one issue number: a publish-branch problem (302 MiB, growing by roughly one snapshot per scheduled run, with no retention policy even though PUBLISHING.md says one belongs in the branch contract) and a fork-cost problem that lives on main and that #143 does not mention.

The free lever nobody has taken. The branch root output/ and ps-002/output/ are the same git tree objectd2f3ae3cefb8296212dedc628dd8134e8d4a4f50. That is 103.41 MiB, 34% of the checkout, duplicated with zero information content. Git already stores it once; the cost is purely in checkout size and path count. #143 does not mention it.

What was measured

MeasureValueCommand
site branch checkout302.58 MiB · 689 files · 317,274,322 bytesgit ls-tree -r -l origin/site
site compressed objects72.17 MiB (1,228 objects)git rev-list --objects | git cat-file --batch-check='%(objectsize:disk)'
main checkout124.67 MiB · 91 filesgit ls-tree -r -l origin/main
main compressed objects18.83 MiBas above
Both branches, deduplicated — what a clone transfers90.91 MiBas above, sort -u
site by directoryps-002/ 103.45 · output/ 103.41 · ps-001/ 95.36 MiBgit ls-tree + awk
Root output/ vs ps-002/output/identical tree d2f3ae3 — 103.41 MiB duplicatedgit rev-parse origin/site:output
Heaviest files (each present twice)kri_report_…html 10.98 · safety_outlier_explorer.html 9.66 · hep_explorer.html 9.55 MiBgit ls-tree -r -l | sort -k4 -rn
main/input/124.48 MiBRaw_DATACHG.csv 57.98 + Raw_DATAENT.csv 45.25 + Raw_QUERY.csv 11.74 = 83%git ls-tree -r -l origin/main -- input
Largest chart, over the wire10,015,826 bytes → 417,963 gzipped (24×)curl -H 'Accept-Encoding: gzip'
Growth todayNone — the scheduled pipeline has failed on 2026-08-03 and 2026-08-10gh run list -R jwildfire/demo-301

All measured 2026-08-14 against origin/site and origin/main, read-only. Nothing on the branch was modified.

The options

S1 · Drop the root output/ duplicaterecommended

What
Stop writing the current snapshot's tree twice. The publish script keeps ps-NNN/ and a pointer (snapshots.json already indexes them); the app shell resolves the current snapshot through that pointer instead of assuming a flat root.
Gains
103.41 MiB — 34% of the checkout, and roughly a third of the path count per republish. No information lost: the identical tree remains at ps-002/output/.
Costs
Breaks the deliberate flat-root shape (“the branch root is the site, no build step”) — the shell must stop assuming it. A contained change in the publish script plus the site's path resolution.
Forecloses
Serving the current snapshot from bare root paths. Anything linking to /output/… would need redirecting.

S2 · Shrink input/ on mainrecommended

What
Cut or downsample the two data-management CSVs (Raw_DATACHG 57.98 MiB, Raw_DATAENT 45.25 MiB) that no Safety or RBQM view in the demo reads at full size. Regenerate at a fraction of the row count, or move them behind a fetch step.
Gains
Up to ~103 MiB off the disk cost of every fork — the part a forker actually feels, since main is what a clone checks out.
Costs
Requires checking which workflows consume them at what fidelity; downsampling changes demo numbers, so published snapshots would need regenerating for consistency.
Forecloses
Demonstrating the pipeline at that data volume, unless a large-data variant is kept elsewhere.

S3 · Snapshot retentionrecommended — the growth bound

What
#143's mitigation 1: keep the last N snapshots in ps-NNN/ and expire older ones (they survive in git history). Write the policy into the branch contract, as PUBLISHING.md already says it should be.
Gains
Bounds growth permanently. Without it, the branch gains ~95–103 MiB of checkout per scheduled run the moment the pipeline is fixed.
Costs
Real work in the publish script. N must be ≥ 2 or the compare view loses its second snapshot.
Forecloses
A complete published history on the branch itself — deliberately, since git history retains it.

S4 · Stop committing rendered charts

What
#143's mitigation 2: publish the large self-contained chart HTML as build artifacts referenced by the snapshot rather than stored in it.
Costs
Breaks the property the whole demo narrative rests on — the branch root is the site, served with no build step. Also the weakest case on the numbers: those files gzip 24× on the wire, so they are a checkout cost, not a visitor cost.
Forecloses
Offline/forked reproducibility of a snapshot as one self-contained tree.

S5 · Orphan-branch publishing

What
#143's mitigation 3: rewrite site as a single-commit orphan branch on each publish.
Costs
Loses published history, which is the provenance story's backbone — the provenance chip traces a number to its snapshot and run. Cheapest to implement, most expensive in narrative.
Forecloses
Any claim that a published number can be traced back through the branch.

S6 · Accept for the demo

What
#143's mitigation 4: document the ceiling, revisit at first real-study onboarding.
Costs
The retention precondition in PUBLISHING.md was already violated when the schedule went live; growth resumes the moment the pipeline is fixed. The fork-cost half is never addressed.
Forecloses
Nothing technically — it defers.

Recommendation

Recommendation

S1 + S2 now, S3 with the pipeline fix. Not S4, not S5.

S1 is free in information terms — 34% of the checkout is a byte-identical duplicate tree, and the only real work is teaching the shell to resolve the current snapshot through snapshots.json instead of assuming a flat root. S2 attacks the number a forker actually experiences: main is what a clone checks out, and 83% of its 124.48 MiB is two synthetic data-management CSVs that the Safety and RBQM views do not need at that size. S3 is the only option that stops the problem recurring, and it should land in the same change as the Actions install fix — because the day that pipeline goes green is the day the branch starts growing ~100 MiB a week again.

S4 and S5 both trade away a load-bearing property for a benefit the measurements do not support. The rendered charts gzip 24× on the wire (10.0 MB → 418 KB), so they cost checkout space, not visitor bandwidth; and orphan-branch publishing would erase exactly the published history the provenance chip is built to trace.

What unblocks
Taking S1+S2+S3 lets the fork-template hardening requirement carry a measurable acceptance test — fork the repo, clone it, and the working tree is under X MiB; run the pipeline twice and the branch does not grow without bound. Choosing S6 instead leaves #143 open as a ceiling with no owner, which is its current state. Either way this is decidable tonight; none of it requires further research.

Nothing has been changed. No branch was rewritten, no file deleted, no history touched — #143's surgery waits on this decision, per the standing rule that nothing is deleted without approval.