spaces: doc.trail, doc.periods, and the three progress charts - #445
Open
nyblnet wants to merge 1 commit into
Open
spaces: doc.trail, doc.periods, and the three progress charts#445nyblnet wants to merge 1 commit into
nyblnet wants to merge 1 commit into
Conversation
A tracker could tell you what is open today and never what was open last
Tuesday, because the only artefact that ever knew was gone. A space now
records one small row per local day — issues per status option, summed
estimates, and the count that carried no estimate — and a new `chart` block
draws burndown, burnup and cumulative flow from it over a named period.
The format additions, both maps merged per key under collaboration so two
people working on one day cannot lose each other's row:
doc.trail "<YYYY-MM-DD>" | "<seriesId>/<YYYY-MM-DD>" -> { n, e?, x?, s?, cut? }
doc.periods id -> { label, from, to, source?, filter?, series?, base?, closed? }
A row holds counts and nothing else: no page ids, no assignee breakdown, no
per-issue anything. That is a budget rule and a privacy rule at once, and it
is why a reading copy and a page extract carry none of it — the aggregate is
dull, the cadence is not.
Three things the design turns on:
· A GAP IS DRAWN AS A GAP. No interpolation, no carry-forward, no zero;
the line breaks and the region is hatched. A thinned row stands for the
span it replaced and draws dashed, so a weekly sample is never mistaken
for a daily reading. Thinning selects an observation somebody made and
never averages two into a number nobody saw.
· TODAY IS DERIVED, every earlier day is read. Change an estimate now and
today's point moves; yesterday's row cannot, because no code path
addresses a past key.
· ONE RECORD BUDGET, proportional: 25% of the document's own content
between 64 KB and 256 KB, shared with version history when it lands, the
trail thinning first. The record never outweighs what it is a record of.
Charts draw their own SVG rather than calling kernel's charts-lite, which
coerces an absent datum to zero (num(v,0)), has no stacking, and has no
per-segment dash — the three things these charts are about. Reasoning in
docs/DECISIONS.md; no kernel file is touched.
scripts/test-spaces-trail.ts is behavioural throughout: it builds documents,
writes rows, draws charts and asserts on the numbers and the geometry. 157
checks under four timezones including UTC+14 and UTC-11. Verified in a real
browser on a uniquely-named build: the gap band sits between the two runs
with no point at zero, and a sample segment's computed stroke-dasharray is
5px,4px while its neighbour's is none.
Build size
Updated: |
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.
A tracker could always tell you what is open today and never what was open last
Tuesday, because the only artefact that ever knew was gone. This adds the two
format fields that fix that, and the three charts that read them.
Implements the approved
doc.trail/doc.periodsdesign, with themaintainer's three changes: status options rather than phase groups, the
trail stripped from published copies with no checkbox, and — the one
structural change — one shared, proportional record budget instead of two
absolute ceilings.
The shapes
Both are maps, declared in
DOC_MAPSand handed to the kernel'sshape(), sothe CRDT merges them per key: two people working on the same day cannot lose
each other's row. The same list drives a parse-time fold of
/^trail\./top-level keys, which is what an older peer writes when its shape does not know
the map — cheap, deterministic, self-healing, and no kernel change.
The parts that are the actual work
A gap draws as a gap. A missing key breaks the line and hatches the region,
labelled not recorded. No interpolation, no carry-forward, no zero — a carried
value looks exactly like data, and an interpolated weekend shows work happening
on Sunday. A day with nothing open is still a point at zero, and the two look
different. Thinned rows are a third state: dashed, so a weekly sample is never
mistaken for a daily reading.
Editing the past does not rewrite it. One code path writes one key —
today's. There is no "recompute the last 7 days" and no repair pass.
backfillrefuses to overwrite. The trail is excluded from undo snapshots (a row lands
outside any commit; an undo could otherwise restore a stale row over a newer
one) — but
doc.periodsis not excluded, because starting a period issomething a person did.
Timezones. A row key is a local day label, minted once from
journal.todayISO(). Everything after that is UTC ordinal arithmetic on thelabel, so no DST boundary or locale can move it. Run under UTC, Berlin,
Kiritimati (UTC+14) and Niue (UTC-11).
One budget, proportional.
clamp(25% of content bytes, 64 KB, 256 KB),where content is
title/home/theme/pages— notassets, since onephotograph would otherwise buy a document more room to record cadence in. Trail
and history tier independently inside it and the trail thins first: its
allowance is the budget less whatever
doc.revisionscurrently holds, readgenerically so neither side needs to know about the other. History is not
merged, so today the trail simply has the whole budget.
The one deviation from the brief, and why
The brief said to host these on
kernel/src/charts.ts. I read it and measuredit instead, and it cannot host these three:
renderCartesianmaps every datumthrough
num(v, 0), so an absent day would draw as zero — the one thingthese charts exist not to do; there is no
stacksupport anywhere in the file,and a CFD is stacked bands by definition; and
stroke-dasharrayis set only toanimate a sweep, so a sample could not be drawn distinguishably from a daily
reading. Kernel is serialized and this is not a kernel change, so spaces draws
its own SVG — as
graph.tsalready does rather than shipping d3. No kernelfile is touched. If the kernel zone would rather grow null-handling, stacking
and per-segment styling, that is a separate PR and this one can move onto it.
Verification
scripts/test-spaces-trail.ts— 157 behavioural checks, green under UTC,Europe/Berlin, Pacific/Kiritimati and Pacific/Niue. It builds documents, writes
rows, draws the charts and asserts on the numbers and the geometry; no
source-grep assertions, which this zone has twice measured passing straight
through a live regression.
Sabotaged, each restored after: carrying a value forward into a gap (7 fail),
rewriting yesterday from today (2), pruning that gives up instead of tiering
(5), thinning that averages two rows (1 — and this one passed vacuously first
time against a uniform fixture, which is why the fixture's counts now move),
dropping
trailfromDOC_MAPS(8, including both replica checks), ignoringhistory's bytes in the shared budget (1), erasing the sample/day distinction
(3), and removing the undo exclusion (1).
Browser-verified on a uniquely-named build over
127.0.0.1, marker checked onevery probe, DOM re-queried after every action. Measured there: the hatched band
sits between the two runs with no dot within 0.5px of the zero axis; the
segment arriving at a thinned sample has computed
stroke-dasharray: 5px, 4pxwhile its neighbour's is
none; a danglingperiodrenders "this chart'speriod is gone"; and starting a period from the block's own control writes
basefrom live state withbase.at= today, backfills today's row, andfabricates no past key.
Also green: the whole spaces suite (model, agent, journal, calc, trail, undo,
invite, roundtrip, size),
test-sync.ts(45,368 checks),test-sync-spaces,test-sync-spaces-session,test-sync-shape,tsc --noEmit,shell-gate,--manifest, andbuild-spaces-i18n --checkat 623 × 8 = 100%, with the newkeys grepped out of
packed.tsrather than trusted to the percentage.Byte cost. A year of full daily rows measures 61.5 KB (172 B/row);
counts-only 31.9 KB. The shell grows +30.9 KB to 289 KB — charts.ts, the
three record modules and 26 strings × 8 locales.
Not done, and deliberately
No UI for editing a period's label, dates or scope beyond "new two-week period
from today" — the scope selectors exist in the format and are frozen correctly,
but choosing them needs a form this PR does not add. No multi-series UI (the key
shape ships; the picker does not). No
bento.*agent verbs for the trail. Nobackfill from
doc.revisions— that is the migration to write the day historylands.