Lift whole forest by absolute repo staleness#107
Merged
Conversation
Tree height was normalized to a repo's own commit span, so a repo
untouched for years still showed "young" trees at its newest end.
Add a scan-time staleness lift so a stale repo's whole forest reads
old while keeping its internal oldest->newest spread.
staleness = clamp((scanned_at - newest commit) / STALE_HORIZON_DAYS,
0, STALENESS_CAP)
maturity = staleness + (1 - staleness) * relT // relT = 1 - ageT
height = MIN_HEIGHT + maturity * (MAX_HEIGHT - MIN_HEIGHT)
asOf is manifest.scanned_at (NOT Date.now): a live clock would drift
height over time and break the deterministic goldens. staleness lives
on AgeRange so the tree renderer and firefly orbits derive identical
heights from one computation. Omitting scanned_at keeps staleness 0,
i.e. byte-identical repo-relative sizing (the pre-feature behavior),
so the decoration golden bench is unchanged and needs no recapture.
Constants (hardcoded first pass): STALE_HORIZON_DAYS=730 (~2y),
STALENESS_CAP=0.85 (a forest never fully flattens).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Promote the two hardcoded absolute-age constants to Rebuild-routed TREES settings (Staleness horizon, Staleness cap) under Height by age. AgeRange now carries the raw settings-independent `daysIdle` (scanned_at − newest commit); treeHeight derives the staleness lift from the current cfg horizon/cap, so both the tree renderer and firefly field apply the identical, live-configured lift. A cap of 0 turns the lift off; the horizon is floored at 1 day so a mis-set 0 can't divide by zero. Golden decoration bench still passes no scanned_at → daysIdle 0 → digest unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Tree height is normalized to a repo's own commit span, so a repo untouched for years still shows "young" trees at its newest end. This adds a scan-time staleness lift: a stale repo's whole forest reads old, while keeping the intra-repo oldest→newest spread.
asOf=manifest.scanned_at, notDate.now()— a live clock would drift tree height over time and break the deterministic goldens.staleness ≈ 0→maturity == relT→ byte-identical to today's repo-relative sizing.staleness.Settings
The two tunables are Rebuild-routed TREES settings, in the Settings panel under Trees → Height by age:
Design notes
AgeRangecarries the raw, settings-independentdaysIdle;treeHeightderives the staleness lift from the current cfg horizon/cap. The tree renderer and the firefly orbit field both derive height from that one path (with the sameTREES.value), so orbs never drift off their trees and either slider re-runs the rebuild with no extra wiring.manifest.scanned_at→ treesrebuild→createTreeRenderer, and → firefliesrebuild→placeFireflies. Both forward it tocomputeAgeRange; omitting it keepsdaysIdle = 0.decorationGolden.bench.test.tscalls the renderer/placement withoutscanned_at, sodaysIdle = 0→ digest byte-identical, no recapture needed. The bench now guards the fresh-repo no-op invariant.Tests
TDD in
treeEncoding.test.ts:daysIdlecounting/clamp + ISO-datetimescanned_at; a fresh repo is unchanged; a stale repo lifts the whole forest while preserving ordering; the cap holds; the horizon/cap settings tune the lift (incl. cap 0 = off); a same-day (span 0) stale repo degrades sanely. Full suite green (2553), lint clean.🤖 Generated with Claude Code