Repository navigation
Conversation
Every journal entry in a context read now carries its age in whole UTC calendar days, shown next to its date in the digest and --layer reads. A project synthesis older than 30 days with at least 50 entries after it is labelled stale with a prompt to write a fresh wrap(project) and moves to the end of the digest, and a newer scoped wrap is shown beside it; a dormant project's synthesis keeps leading. Only active Changes contribute lineage keys, so retired Change lineage no longer appears as active. Ages and staleness are derived at read time; --json adds age_days, stale and entries_since. Fixes #419
Review of #426: the CLI read-clock test ages in UTC so daylight-saving changes cannot shift its exact age; the stamping test now covers synthesis, checkpoint, lineage, blockers, branch recency, BranchEntries and LatestWrap; negative ages from clock skew clamp to 0; the --layer blocker line is tested with its aged stamp; an existing context test pins its clock; comments and the changelog say exactly what is aged.
Owner
Author
|
Ship: request changes on 655e4bb (small). An independent reviewer found no product defects. It accepted the proposed stale rule: a synthesis is stale once it is more than 30 days old and at least 50 entries have followed it. Two tests needed fixing.
Agent notes
|
Review nits on #426: the pagination loop in the v2 active-truth test passes the same pinned clock as its first read; the stamping test asserts the scoped wrap and lineage decision come from their own layers; the changelog names the layers whose entries carry age_days.
Owner
Author
|
Ship: code approved on fc0c594; merge blocked on box 3. Every review finding is fixed, and the full local gate passes on this tree. Two things must happen before this lands:
Agent notes
|
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.
Summary
The continuity digest presented months-old entries as current truth, with nothing saying how old they were. In this repository the first thing an agent read was a project synthesis from 30 July ("Next: PR #143"), followed by a July lineage decision about a Change model that has since been retired.
[2026-07-30 17:25, 84 days ago].--layerreads show it too.wrap(project)when substantial work is finished, and moves it to the end. A fresh synthesis, or a dormant project's, keeps leading without a label.--jsonaddsage_daysto context entries, plusstaleandentries_sinceto the project synthesis.This PR is stacked on #424 (#420), so its base is that branch. Once #424 lands, it will be rebased onto
main.Native work
Implements #419.
Verification
Ran on fc0c594, which adds the review rounds' test and wording fixes to 655e4bb;
make verify-localpasses on that tree.Fixed-clock tests for the stale label and wrap prompt. Stale only when the synthesis is both old and overtaken: old with 50 entries after it is stale, while exactly 30 days old, old but dormant (49 entries) and fresh during a busy stretch are not. The renderer shows the stale label, the wrap prompt and the move to the end. A fresh synthesis leads with no label. Tests:
TestJournalContextMarksOnlyAnOldOvertakenSynthesisStale,TestJournalContextDigestShowsAgesAndDemotesAStaleSynthesis.TestJournalContextDefaultPathAgesTheSynthesisByTheReadClockdrives the real CLI default path. It logs a synthesis and 50 entries, moves the read clock a month on, and sees the stale label at the end. After a freshwrap(project), the new synthesis leads unlabelled.TestJournalContextShowsANewerScopedWrapBesideAStaleSynthesis).Ages across day boundaries. Calendar-day ages in UTC: one second before midnight is 1 day, midnight is today, and a reader in another timezone gets the same answer. Every layer's entries are stamped: synthesis, checkpoint, lineage, blockers, branch recency,
BranchEntriesandLatestWrap. An entry from a fast clock clamps to today, andjournal recentJSON carries no age (TestJournalContextStampsEveryEntryWithItsAge,TestJournalContextAgeDaysCountsUTCCalendarDays). The CLI read-clock test ages in UTC, so daylight-saving changes cannot move it.This repository, read-only so far. With 655e4bb, whose rendering f0dc53f does not change, the live digest:
stale, 2687 entries sinceand puts it last;lineage/change-model-hard-cutdecision;The second half of this check needs a genuine
wrap(project)in the live journal and is waiting on a decision.env -u LOAF_DB make verify-localpasses.Also ran:
loaf check issue-changelogpasses for Show how old digest items are and flag a stale project synthesis #419 against this PR's base.TestDiscoverActiveChangesUnionsHEADAndWorkingTreenow expects the clean, completedhistoricalChange'sfoo-extralineage to be left out; the rewritten-lineage case still keeps both keys of an active Change.Ship
Pending Ship review.
Migration / risks
internal/state/journal_context.go.--layer active-lineagereads.Out of scope
docs/changesfiles, and how the destination digest (Serve journal logging, search, and context from vNext facts and the ContextDigest #291) shows age.Fixes #419
Agent notes
JournalEntryRecord.AgeDays *int(age_days,omitempty) is set only bystampJournalContextAgesininternal/state/journal_context.go, so other readers' JSON is unchanged.JournalContextSynthesisStaleDays(30) andJournalContextSynthesisStaleEntries(50).entries_sincecounts every project entry after the synthesis, up to the watermark.discoverActiveChangesWithOutputininternal/cli/change_context.goretains lineage keys after computing active reasons, only for Changes that have one.formatJournalEntryStampserves both renderers. A stale synthesis is moved to the end ofjournalContextDigestLayerswithjournalContextStaleSynthesisHint;--layer project-synthesisprints the same hint.JournalContextOptions.Nowand theRunner.Nowseam added in feat: resolve journal blockers by entry id and stop listing stale ones #424.