fix(attribution): deterministic why metadata + interactive viewer + honest tag legend#1613
Open
suhaanthayyil wants to merge 19 commits into
Open
fix(attribution): deterministic why metadata + interactive viewer + honest tag legend#1613suhaanthayyil wants to merge 19 commits into
suhaanthayyil wants to merge 19 commits into
Conversation
… clones Three clones of the same repo at the same commit could see three different 'entire why' outputs (#1551). Two residual causes after the earlier actionable-guidance work: - When the checkpoint summary resolved but the per-session records were unreadable (treeless/partial clone, gc-pruned objects), the resolver marked the metadata missing with NO reason and never attempted the remote refresh — so clones with different local blob availability silently diverged, and a multi-session checkpoint could even pick a different fallback session per clone. - Each missing checkpoint ran its own remote-fetch chain and discarded the fetch error: a file with many misses paid one network timeout per checkpoint, and the reason could not distinguish 'fetch failed' from 'the remote genuinely lacks this checkpoint'. Restructure the resolver around a memoized once-per-resolver refresh: - Any incomplete local read (summary unreadable OR session records partially/ wholly unreadable) triggers ONE durable metadata fetch; on success the store is re-pointed at a fresh repo handle and the read retried, so every clone of the same remote converges on the same answer. - The refresh outcome is memoized: many misses share one fetch (or one failure), making a single run internally consistent and bounding network attempts to one. - A retry that reads worse than the local pass (an unpushed local-only checkpoint vanishing from the remote view) keeps the local data. - MetadataMissingReason now distinguishes the three recovery situations: no fetch attempted (run this git fetch), refresh failed (the underlying error), and refresh succeeded but the remote lacks the checkpoint (ask its author to push entire/checkpoints/v1) — the last no longer suggests a pointless fetch. - The sessions-unreadable case now carries a reason on the blame (no-fetch) path too, and the resolution path emits debug logs (summary miss, sessions read x/y, refresh outcome) for field diagnosis. Closes #1551
…round 1) An adversarial audit of the determinism fix confirmed four defects; all fixed: - The refresh seam wrapped getMetadataTree, whose local-branch fallback reports success when every actual remote fetch failed (offline, no remote, auth). The resolver then confidently claimed 'the remote does not contain this checkpoint — it may not have been pushed' and suppressed the git fetch suggestion, in exactly the field conditions of #1551. The seam now calls the fetch primitives directly (checkpoint remote, then the full-content origin fetch — attribution needs session blobs, so the tree-only probe is not enough) and returns success ONLY when a remote fetch genuinely succeeded. - The sessions-unreadable-after-refresh reason reused the whole-checkpoint wording, producing the self-contradiction 'checkpoint found, but … the remote does not contain it … or it predates checkpointing'. The refreshed wording now matches the miss kind: session records still unavailable after the refresh, without claiming the just-resolved checkpoint is missing. - After one successful refresh, every later incomplete checkpoint re-read the same store twice (memoized nil triggered an identical retry). A store generation counter gates the retry on the store actually changing during the call. - Test gaps: per-index session stubbing (a multi-session checkpoint with only some records readable now provably refreshes and resolves the file-matching session); the determinism test now converges two differently-damaged clones instead of two identical ones; the success path pins one-fetch-one-reopen across misses; and a real-seam regression test (local metadata branch, no remote) fails on the pre-fix seam and passes on the fixed one.
…fetch (audit round 2) Second audit pass confirmed six diagnostic-accuracy issues; all fixed: - A configured checkpoint remote is the source of truth: its fetch failure is no longer masked by an origin fallback that may hold a stale copy (which would let a miss claim 'not pushed' about a remote we never reached). The origin leg now runs only when no checkpoint remote is configured, which also removes the 'checkpoint remote: not configured' noise from every error. - The 'not pushed' claim now requires evidence: the refreshed store must report the genuine-absence sentinel. A summary read that fails for any other reason (storage error, cancellation) after a successful refresh makes no claim about the remote. - A retry rejected as worse no longer discards what it proved: when the refreshed store reports the checkpoint absent while local data survives (an unpushed local-only checkpoint with damaged session records), the reason says the checkpoint is not on the remote instead of speculating that the metadata branch 'may have been pushed without' the session records. - Reasons are collapsed to one line (git fetch errors embed multi-line output that would break the renderer). - Stale comment still attributing the fetch to getMetadataTree reworded. Tests updated to present genuine absence via the sentinel where 'not pushed' is asserted, plus new pins: non-absence errors make no remote claim; the worse-retry reason uses the retry's proof; multi-line fetch errors collapse.
Third audit pass confirmed three residual issues; all fixed: - The refreshed-but-unreadable reason pointed users at .entire/logs, which is empty for this path at the default log level (all entries are debug-only and the post-refresh read failure was never logged at all). The pointer is dropped — the cause is already embedded in the reason — and the post-refresh outcome now gets a debug log for field diagnosis. - The resolver comments overclaimed: readCheckpointContextOnce is not 'side-effect-free / never fetches' and the memoized refresh does not bound ALL network attempts — the underlying store's on-demand BlobFetcher (pre-existing behavior shared with blame, unchanged at runtime) may still attempt per-blob fetches. Comments now state the bound covers the refresh path only, and openAttributionStore documents that keeping the fetcher is deliberate (straggler healing after a genuine refresh). - The authoritative-checkpoint-remote rule had no test on the real seam: a configured checkpoint remote whose resolution fails (no network needed) now pins that its failure surfaces as 'checkpoint remote fetch failed' with no origin fallback masking and no unfounded 'not pushed' claim.
…emote tests (audit round 4) - remote.FetchURL silently returns the ORIGIN URL when the configured checkpoint remote's URL cannot be derived (unparseable origin, unknown provider) — a 'successful' refresh could then have hit origin, faking the evidence behind the not-pushed wording. fetchAttributionMetadata now detects that resolution fallback (resolved URL == origin URL) and treats it as a refresh failure, so no claim is made about a remote never reached. - The real-seam tests cleared of environment dependence: with ENTIRE_CHECKPOINT_TOKEN set, FetchURL derives a live github.com URL with no git remote and the tests would fetch over the network with the environment's token. Both now clear the token (t.Setenv), keeping them fast and hermetic.
…nd 5) The round-4 guard inferred FetchURL's origin fallback from string equality with the origin URL — unsound in both directions: the token path rewrites the origin URL to its HTTPS form before falling back (so the fallback never string-matches and a token-based CI run could still fabricate not-pushed evidence from an origin fetch), and a checkpoint_remote legitimately naming the origin repo derives a byte-identical URL (so a genuine derivation was misreported as a fallback, permanently disabling the refresh for that configuration). Replace the heuristic with an explicit signal: FetchURLWithSource returns whether the URL was derived from the configured checkpoint_remote (mirroring PushURL's boolean); FetchURL delegates. fetchAttributionMetadata now requires usedCheckpointRemote=true before treating a configured-remote refresh as authoritative. Pins: remote-package table test for the source bool (derived, equal-URLs- legit, token-fallback, no-config, token-derived); attribution-level hermetic test that the token-path origin fallback surfaces as a refresh failure rather than fake not-pushed evidence.
…(audit round 6)
- fetchAttributionMetadata resolved the authority up to four times (Configured,
FetchURLWithSource, then the fetch helper's own Configured + FetchURL): any
divergence between reads — a transient settings failure, a concurrent
settings write — could route the fetch to origin while attribution recorded
an authoritative checkpoint-remote refresh. Now: load settings once, branch
on GetCheckpointRemote from that load, resolve the URL once via
FetchURLWithSource, and fetch THAT verified URL directly
(strategy.FetchMetadataBranch), so the fetched URL is by construction the
one whose source was verified.
- A settings-load failure is now a refresh failure (honest 'remote refresh
failed' wording) instead of being silently mapped to 'no checkpoint remote',
which would have promoted origin to the evidence source.
- Stale render comment ('the remote fetch has failed') updated: the refresh
may also have succeeded against a remote that lacks the data.
…ch suggestion (audit round 7) - A retry rejected as worse whose failure is NOT genuine absence (corrupt fetched pack, cancellation) proves nothing about the remote — the reason no longer speculates that the metadata branch 'may have been pushed without' the session records, and the retry's error is surfaced instead of dropped (mirroring the evidence-gating the whole-checkpoint miss already had). - suggestCheckpointFetchCommand no longer tells the user to fetch from origin when a configured checkpoint remote's URL could not be derived — the exact contradiction of the authoritative-remote policy the refresh just refused. It uses the explicit source signal and points at the checkpoint_remote configuration instead.
…audit round 8) suggestCheckpointFetchCommand gated on remote.Configured, which collapses a settings-load failure to 'not configured' — so a corrupt .entire/settings.json produced a reason that simultaneously said the refresh refused origin (the authoritative remote is unknowable) and told the user to 'git fetch origin'. Load settings directly: on failure, point at the unreadable settings file (whose checkpoint_remote determines the correct remote) instead of recommending origin.
…prose (audit round 9) - Two reason tests resolved the fetch suggestion against the developer's real CWD (settings.json + git remotes) — a corrupt local settings.local.json made one fail spuriously. Both now run in a hermetic temp repo, matching the file's own conventions. - suggestCheckpointFetchCommand now returns (suggestion, isCommand): the prose fallbacks (unreadable settings, underivable checkpoint-remote URL) are no longer rendered behind a 'Run:' prefix or inside a pasteable command block, which produced 'Run: fix .entire/settings.json …, then re-run; … Then re-run …' style output. Prose composes as prose; commands keep the Run:/command-block rendering.
…ility parity (audit round 10)
Rebased onto main, which added the git-refs per-checkpoint backend. Two
integration hazards fixed:
- openAttributionStore now opens the refreshed store with the same RefFetcher
the initial store has (plus the BlobFetcher) — without it, a post-refresh
retry on a git-refs-backend repo silently lost on-demand per-checkpoint ref
fetching and could read strictly worse than the first pass.
- The strong miss evidence ('the remote's entire/checkpoints/v1 does not
contain it' / 'not on the remote') is now gated on the primary backend being
the git-branch backend: the v1-branch refresh proves nothing about
per-checkpoint refs, so refs-backend misses get neutral wording that says
why the evidence is weaker. Backend topology is memoized per resolver.
Also: TestRefreshMetadataStoreRunsAtMostOnce gets the same hermetic-CWD
treatment its sibling suggestion-path tests received in round 9.
…audit round 11) Round 10's backend gate made missReason consult the checkpoint topology (ENTIRE_CHECKPOINTS_PRIMARY env, else CWD settings), which the evidence-wording tests inherited from the ambient environment: under ENTIRE_CHECKPOINTS_PRIMARY=git-refs, KeepsLocalWhenRefreshReadsWorse failed deterministically (neutral refs wording instead of the asserted git-branch claim) and siblings silently pinned a different branch than their names claim. Pin t.Setenv(EnvCheckpointsPrimary, "git-branch") in every test that asserts backend-gated wording, and add the refs-backend twin of the worse-retry case (neutral wording, no 'not on the remote' claim), which had no coverage.
…ls to neutral (audit round 12) - primaryBackendIsRefs now distinguishes 'config unreadable' from a known backend: an unreadable checkpoints config supports neither backend's claim, so such misses get generic neutral wording instead of the strongest git-branch claim (the previous failure direction overclaimed — inconsistent with the branch's own evidence discipline). The v1-speculation catch-all is likewise gated on a KNOWN git-branch backend. - On a KNOWN git-refs-primary repo, a failing v1-branch fetch is now a soft outcome: the branch is not that backend's primary mechanism (a refs-only remote may not carry it), and the reopened store's per-checkpoint RefFetcher does the real work — previously every miss in the run surfaced 'remote refresh failed: … entire/checkpoints/v1 …' plus a suggestion guaranteed to fail for the same reason. Pins: refs-primary + failing branch fetch (real fetch seam, hermetic repo with no origin) yields the refs wording with no 'remote refresh failed'; an invalid checkpoints block yields neutral wording with neither backend's claim.
…audit round 13) The round-12 commit accidentally swept in-progress why-TUI wiring into this branch while its defining file stayed untracked — the committed tree did not compile (undefined: runWhyTUI / whyMarkerLegend); local builds passed only via the untracked working-tree file. The TUI belongs to its own branch: the --tui flag, dispatch, repo-name helper, and legend line are removed here. Also, softened refreshes now stay honest: the soften decision moved out of the fetch seam into refreshMetadataStore, deciding via the SAME memoized backend gate missReason uses (one config resolution — no TOCTOU between the soften and evidence gates), and a soft refresh records refreshSoft so every wording says 'a metadata refresh was attempted (the v1 branch could not be fetched...)' instead of claiming the branch was refreshed. Pinned in the refs-primary soft-fetch test.
…atch-all (audit round 14)
Round 13's move of the soften decision into refreshMetadataStore accidentally
widened its scope to EVERY refresh error: on a refs-primary repo, settings-read
failures, URL-derivation failures, and the authority-guard rejection (the
token-path evasion this branch hardened against) were silently softened behind
a false 'the v1 branch could not be fetched' description. A sentinel now marks
the genuine v1-branch fetch step; only errors carrying it are softened —
config and policy failures stay hard on every backend, pinned by a refs-primary
authority-guard test.
The sessions-miss catch-all also now words a soft refresh honestly
('refresh was attempted', never 'after refreshing'), pinned by a soft-refresh
sessions-miss test on the real fetch seam.
…fs-aware suggestion, env-hermetic tests (audit round 15) An exhaustive 8-lens, loop-until-dry audit (full missReason state-machine enumeration, adversarial scenario construction, both-backend test matrix) confirmed the following; all fixed: - Soft-refresh honesty completed: the rejected-retry wording no longer calls the store 'refreshed' in the same sentence that admits the v1 branch was not fetched; the reopen debug log is soft-aware; and a soft refresh whose store reopen ALSO fails keeps the swallowed fetch error as diagnostic context. - Refs-aware recovery: a refs-primary no-refresh miss now suggests fetching the per-checkpoint refs namespace instead of the v1 branch that cannot heal it (suggestCheckpointFetchCommandForRefspec; the v1 wording is unchanged for the git-branch backend and for attach). - Env hermeticity closed: newAttributionRepo pins the git-branch backend by default (tests wanting git-refs override after the call), the two remaining backend-sensitive tests pin explicitly, and the blame no-fetch contract is now non-vacuous (seam traps fail the test if fetchOnMiss=false ever fetches). - suggestCheckpointFetchCommand's four outcomes pinned directly (derived command / origin command / unreadable-settings prose / underivable-URL prose); overstated 'exactly once' comment corrected; misleading pin-rationale comment fixed. Verified under hostile environments: full attribution suite green with ENTIRE_CHECKPOINTS_PRIMARY=git-refs and with a leaked ENTIRE_CHECKPOINT_TOKEN.
Adds an opt-in TUI for 'entire why <file>' and the readability fixes insiders asked for, built under the Agent-Safe CLI Fallbacks rules: - --tui opens a master-detail Bubble Tea viewer over the already-resolved attribution (no git/network I/O inside the TUI): file lines with [AI]/[MX]/[HU] tags on the left; the selected line's full explanation on the right (authorship sentence, commit, agent/model, session with an OSC 8 entire.io hyperlink when origin resolves, checkpoint, prompt with the session-level caveat, intent, metadata-missing reason, candidates, explain hint). n/p jump to the next/previous agent-attributed line; enter expands the full prompt; why <file>:12 --tui opens positioned at line 12. - Agent-safe: the TUI is opt-in AND TTY-gated (IsTerminalWriter) and skipped in accessible mode; non-TTY --tui falls through to the identical plain output, and --json always wins — both pinned by tests against a non-TTY writer. Nothing is TUI-only. - Tag legend on blame, the why file view, and the TUI footer: [AI] all agent, [MX] agent+human mixed, [HU] no agent, [??] uncommitted — kept within the blame table's 80-column budget; full sentences in the detail views. Model-level TUI tests cover rendering, navigation, agent-line jumps, expand, missing-metadata handling, quit keys, empty files, and tiny windows. Paging is bound to pgup/pgdn because the shared keymap claims n/p.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a non-determinism bug in entire why <file>[:<line>] where equivalent clones could resolve different checkpoint context depending on which metadata/session blobs were locally available. It restructures attribution’s checkpoint metadata resolution to perform a memoized, once-per-run remote refresh when local metadata reads are incomplete, and improves miss reasons so users can distinguish “not fetched”, “fetch failed”, and “remote lacks checkpoint”.
Changes:
- Added an explicit
FetchURLWithSourceAPI so callers can reliably tell whether the fetch URL came fromcheckpoint_remotevs an origin fallback. - Reworked attribution checkpoint context reads to detect incomplete local reads (including partially/fully unreadable session records), perform at-most-once durable refresh + repo reopen, and emit deterministic
MetadataMissingReason. - Updated attach/error guidance to treat fetch suggestions as either a pasteable command or prose (when settings/URL derivation prevents a safe command), and added a comprehensive regression test suite for the refresh behavior.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| cmd/entire/cli/checkpoint/remote/util.go | Adds FetchURLWithSource and routes FetchURL through it to expose a sound “source” signal. |
| cmd/entire/cli/checkpoint/remote/util_test.go | Adds coverage for the new source-signal behavior, including token rewrite and “checkpoint remote equals origin” cases. |
| cmd/entire/cli/attribution.go | Implements memoized remote refresh + store reopen, stronger evidence-gated miss reasons, and debug logging for diagnosis. |
| cmd/entire/cli/attribution_test.go | Extends reader stubs and pins default backend env to keep attribution tests hermetic. |
| cmd/entire/cli/attribution_refresh_test.go | Adds a comprehensive suite validating determinism, refresh semantics, evidence gating, and error messaging. |
| cmd/entire/cli/attach.go | Improves missing-checkpoint guidance by distinguishing command vs prose suggestions and introduces branch-vs-refs refspec suggestions. |
The [AI]/[MX]/[HU] tags are a per-commit inference, not a per-line truth: [AI] means the commit's checkpointed work was fully agent-authored, [MX] means the commit mixed agent and human edits (any given line may be either), [HU] means no agent checkpoint. The legend now says so explicitly — 'per commit: [AI] all agent · [MX] mixed — line may be either · [HU] no agent' — instead of reading like per-line labels. [??] moved to the conditional marker legend line (shown only when uncommitted lines exist), keeping the main legend inside the blame table's 80-column budget.
The rule people do not guess: a single human edit anywhere in a commit turns every line of it [MX] — [AI] appears only for fully agent-authored commits. The blame and why legends now carry an explicit second note line saying so: 'note: [AI] requires a fully agent commit; one human edit turns all lines [MX]'. Within the blame table's 80-column budget.
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.
Trail: https://entire.io/gh/entireio/cli/trails/737
What
entire why <file>[:<line>]could show three different answers on three equivalent clones of the same repo at the same commit — full metadata on one, partial on another, bareCheckpointIDon a third. This makes the resolution deterministic: given the same remote state, every clone converges on the same output, and when it can't, the miss reason says exactly why and how to recover.Root cause (what remained after #1535 /
4f435384d)Earlier work already added
MetadataMissingReason, file-level enrichment, and the fetch suggestion. Two residual defects kept the issue alive:git gc-pruned objects — see KNOWN_LIMITATIONS ENT-241), the resolver setMetadataMissingwith no reason and no remote refresh. Worse, on multi-session checkpoints the session loop silentlycontinued over unreadable records, so which fallback session got picked depended on which blobs a clone happened to have — different agent/model/prompt per clone, unflagged.fetchCheckpointContext→ fresh lookup →getMetadataTree) and discarded the fetch error. A file with N missing checkpoints paid up to N network timeouts, and the reason couldn't distinguish "fetch failed (offline/auth/no remote)" from "the remote genuinely lacks this checkpoint".Fix
Restructured the resolver around a memoized once-per-resolver refresh:
entire/checkpoints/v1; on success the store is re-pointed at a fresh repo handle (post-fetch packfiles are invisible to the already-open handle) and the read retried. Retries are gated on the store having actually changed during the call (no wasted double reads), and a retry that reads worse than the local pass (an unpushed local-only checkpoint) keeps the local data.getMetadataTree, whose local-branch fallback reports success when every actual fetch failed — that would have made an offline run claim "the remote doesn't have this checkpoint" (found by the audit; regression-pinned by a test that fails on that seam).MetadataMissingReasonnow distinguishes all the recovery situations the issue reporters couldn't tell apart:git fetch … entire/checkpoints/v1to run;entire/checkpoints/v1" (no pointless fetch suggestion);.entire/logs/for field diagnosis (issue ask Improved entire enable messaging #6).entire blamestays local-only/fast by design (unchanged semantics; it now also gets a reason for the sessions-unreadable case). File-level and line-levelwhyshare the same resolution path (both enrich).Audit
Adversarially audited in a fix-until-clean loop (multi-lens review; every finding independently adversarially verified before being acted on; exit = two consecutive clean passes). Eleven fix rounds landed; highlights of what the loop caught in my own cuts, all fixed and regression-pinned:
getMetadataTree's local-branch fallback reported success while offline (an offline run would claim "not pushed"); an origin fallback masked a configured checkpoint remote's failure; a URL-string-equality guard was evadable by token rewrites and false-positived on legitimately-equal URLs → replaced with an explicitFetchURLWithSourcesource signal (mirrorsPushURL).RefFetchercapability parity with the initial store, and the strong "the remote's entire/checkpoints/v1 does not contain it" evidence is gated on the git-branch backend (the v1 refresh proves nothing about per-checkpoint refs — refs-backend misses get neutral wording).ENTIRE_CHECKPOINTS_PRIMARY), and the real-seam tests clearENTIRE_CHECKPOINT_TOKENso no developer/CI environment leaks in (one test provably failed under a refs-backend env before the pin).Testing
attribution_refresh_test.go: unreadable-session reason on the no-fetch path; refresh restores unreadable sessions; refreshed-but-absent says "not pushed" (and does not suggest a fetch); at-most-once refresh on both the failure and success paths (fetch/reopen counted across misses); local-data-kept when the refreshed read is worse; differently-damaged clones converge on the identical context; partial multi-session reads trigger refresh and resolve the file-matching session; real-seam regression test (local metadata branch + no remote → "remote refresh failed", not "not pushed") — verified to fail on the pre-fix seam.mise run lint— 0 issues;mise run test:ci— unit + integration + Vogon canary green on the committed tree.Related
entire whydeterministic across clones and surface actionable checkpoint-metadata miss reasons karthik-rameshkumar/cli#1 (thanks — the fetchOnMiss-parity and reason-propagation direction was right and much of it had landed via4f435384d); this PR fixes the deeper residual non-determinism it didn't reach: the partial-blob/session-selection divergence, the per-miss fetch churn, and the unsound refresh-success signal.Part 2: interactive viewer + insider-feedback fixes
An interactive viewer for
entire why <file>plus the readability fixes insiders asked for — built strictly under the new Agent-Safe CLI Fallbacks rules (#1596).entire why <file> --tuiMaster-detail Bubble Tea viewer over the already-resolved attribution (no git/network I/O inside the TUI):
[AI]/[MX]/[HU]/[??]tags and~/?markers, windowed scrolling for large files.Session promptcaveat), intent, metadata-missing reason, candidate checkpoints, and thecheckpoint explainhint (suppressed when metadata is missing, matching the text view).n/pnext/previous agent-attributed line (jump straight to the interesting lines), enter expands the full prompt/candidates, pgup/pgdn, g/G, q.why <file>:12 --tuiopens positioned at line 12.Agent-safe by construction
--tui) and TTY-gated (interactive.IsTerminalWriter) and skipped in accessible mode — the exactexperts --tuipattern the guidelines cite as good.--tuifalls through to the same deterministic plain output;--jsonalways wins over--tuiso scripted callers never block. Both pinned by tests against a non-TTY writer.Insider-feedback fixes (text output)
blame, why file view, TUI footer):[AI] all agent · [MX] agent+human mixed · [HU] no agent · [??] uncommitted— wording per soph's correction (AI = 100% agent-authored checkpoint work; MX = agent + human edits; careful not to overclaim). Full sentences in the TUI detail pane.Testing
Update/View, color off): render + summary, navigation → prompt detail, start-line positioning,n/pagent-line jumps (including exhaustion + status message), expand toggle, missing-metadata reason + suppressed explain hint, quit keys, empty file, tiny window.--tuion a non-TTY writer produces the plain file summary;--tui --jsonproduces JSON.n/pfor paging — the viewer rebinds paging to pgup/pgdn son/pcan do agent-line jumps (commented).mise run lint0 issues; fullcmd/entire/clisuite green;mise run test:cigreen.Notes
entire whystays hidden/labs. The TUI addresses the insiders' "why is hard to read" feedback and pfleidi's browse-the-file/summit-linking ideas without touching the default output contract.Part 3:
entire blame— what actually changes (and what doesn't)To be explicit about the two commands, since they share the resolver:
entire blamebehavior is unchanged: local-only and fast, never fetches (now pinned by seam-trap tests that fail if the blame path ever refreshes). It gains only diagnostics + the legend:MetadataMissingReason(before: flagged missing with no reason and no recovery hint);entire whyis where the behavior changes live: remote enrichment on miss (Part 1) and the opt-in TUI (Part 2).Tag legend — per-commit inference, spelled out
Per the internal wording guidance: the
[AI]/[MX]/[HU]tags are a per-commit inference, not a per-line truth. It shows[AI]only when 100% of the commit's checkpointed work was agent-authored; otherwise[MX];[HU]when the commit had no agent checkpoint. Shown inblame, thewhyfile view, and the TUI footer:The note line exists because the rule is not what people infer on their own (a mostly-agent commit with one human tweak renders every line
[MX], including the purely agent-written ones).[??]appears on a conditional marker line only when uncommitted lines exist.