fix(attribution): honest why prompts + unified blame/why line syntax#1535
Conversation
blackgirlbytes
left a comment
There was a problem hiding this comment.
this PR is based on feedback we received from Insiders. Tested and it looks like it addresses the issues Insiders pointed out.
blackgirlbytes
left a comment
There was a problem hiding this comment.
hmm failing tests
`entire why <file>:<line>` printed a "Prompt:" that did not appear in `entire checkpoint explain <id>`. The prompt came from the session's seed prompt (empty prompt.txt -> meta.ReviewPrompt), which is a session-level artifact, while `explain` derives prompts from the checkpoint-scoped transcript. Track that provenance (PromptSessionLevel) and render it as "Session prompt:" with a caveat pointing at `checkpoint explain`, so the output no longer implies the seed prompt lives in this checkpoint's transcript. Also flag single-session path mismatches with SessionFallback (it was gated on >1 session), but only when the chosen session actually recorded paths that exclude the file -- an empty FilesTouched means "unknown", not "renamed", so it must not print the misleading rename caveat. Unify line selection so blame and why accept the same forms: - blame now accepts a positional <file>:N[-M] in addition to --line - why now accepts --line in addition to <file>:line Both share splitFileLineSpec; why's positional parser is migrated onto it so a colon-then-non-numeric suffix is treated as a filename (matching blame) and ranges get a friendly "use entire blame" message. Conflicting positional+flag line specs error with "not both". Tests: new attribution_consistency_test.go covers provenance, the single-session fallback (including the empty-paths non-flag case), the why/blame syntax forms, conflicts, and range rejection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013zxz8rDq24LPbY7E42vYdG
e8758fa to
0dd9b98
Compare
|
@blackgirlbytes try the tests now |
… disclose approximate/ambiguous blame lines
Completes the two follow-ups from the blame/why review.
1. why prompt provenance (general case): prompt.txt is session-wide
(extracted from transcript offset 0; `checkpoint explain` re-derives a
checkpoint-scoped prompt and only falls back to it). So on a LATER
checkpoint (GetTranscriptStart() > 0) the prompt `why` shows is
session-level, not this checkpoint's. Flag PromptSessionLevel there too
— not just the empty-prompt.txt -> ReviewPrompt seed case — so `why`
renders "Session prompt:" + the caveat + `checkpoint explain` pointer
whenever the prompt cannot be scoped to this checkpoint. The first
checkpoint (start 0) stays exact.
2. blame disclosure parity with why: the compact and long blame tables now
show a one-char marker ("~" best-effort attribution when SessionFallback
or MetadataMissing; "?" multiple candidate checkpoints) plus a legend,
matching what `why` shows in prose. The marker sits after the Checkpoint
column so Tag/Agent/Author/Checkpoint alignment is unchanged (only
Content shifts); JSON output is untouched.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013zxz8rDq24LPbY7E42vYdG
…sing; refine session-fallback caveat Addresses review feedback on entireio#1535. Karthik's report (community Discord + karthik-rameshkumar#1): `entire why` on a line whose checkpoint metadata is missing printed "Full context: entire checkpoint explain <id>", but running that command fails identically ("no checkpoint or commit found matching <id>") because the same remote fetch `why` attempts has already failed. The hint pointed at a command that immediately errors. - Resolve metadata-missing during attribution (resolveFileAttribution with fetchOnMiss) and record a MetadataMissingReason that states the cause and the actionable remedy: `git fetch <remote> entire/checkpoints/v1:...`, then re-run `entire checkpoint explain <id>`. Surfaced in the line and file `why` views and in JSON. Also drops the separate post-resolution enrich step, which left the checkpoint map non-deterministic across calls. (Mechanism and tests adapted from Karthik's PR.) - Suppress the bare "Full context: entire checkpoint explain <id>" hint when metadata is missing: it would fail the same way, and the reason line above now gives the fetch-then-explain sequence. - Refine the session-fallback caveat (Soph's review): flag the multi-session fallback whose chosen session has empty FilesTouched (one of several sessions, no path evidence) via `sessionsRead > 1 || len(FilesTouched) > 0`, while still suppressing the single-session empty-paths false positive. Tests for both. Co-authored-by: karthik-rameshkumar <6728802+karthik-rameshkumar@users.noreply.github.com>
|
Pushed dd47f15 — this now addresses Karthik's issue as well as @Soph's review. Karthik's bug (Discord + karthik-rameshkumar#1): Fix (mechanism + tests adapted from Karthik's PR, credited as co-author):
@Soph's feedback: applied the union New tests: |
…sing; refine session-fallback caveat Addresses review feedback on entireio#1535. Karthik's report (community Discord + karthik-rameshkumar#1): `entire why` on a line whose checkpoint metadata is missing printed "Full context: entire checkpoint explain <id>", but running that command fails identically ("no checkpoint or commit found matching <id>") because the same remote fetch `why` attempts has already failed. The hint pointed at a command that immediately errors. - Resolve metadata-missing during attribution (resolveFileAttribution with fetchOnMiss) and record a MetadataMissingReason that states the cause and the actionable remedy: `git fetch <remote> entire/checkpoints/v1:...`, then re-run `entire checkpoint explain <id>`. Surfaced in the line and file `why` views and in JSON. Also drops the separate post-resolution enrich step, which left the checkpoint map non-deterministic across calls. (Mechanism and tests adapted from Karthik's PR.) - Suppress the bare "Full context: entire checkpoint explain <id>" hint when metadata is missing: it would fail the same way, and the reason line above now gives the fetch-then-explain sequence. - Refine the session-fallback caveat (Soph's review): flag the multi-session fallback whose chosen session has empty FilesTouched (one of several sessions, no path evidence) via `sessionsRead > 1 || len(FilesTouched) > 0`, while still suppressing the single-session empty-paths false positive. Tests for both. Co-authored-by: karthik-rameshkumar <6728802+karthik-rameshkumar@users.noreply.github.com>
dd47f15 to
4f43538
Compare
|
Pushed |
There was a problem hiding this comment.
Pull request overview
This PR improves the usability and correctness of the labs attribution commands (entire blame / entire why) by aligning their line-spec syntax, making why’s prompt output more honest about provenance, and improving missing-metadata diagnostics.
Changes:
- Unified
blame/whyline targeting by introducing a shared<file>:N[-M]splitter and addingwhy --line. - Added prompt provenance tracking (
prompt_session_level) and improved missing-metadata messaging (metadata_missing_reason) for clearerwhyoutput. - Expanded tests to cover the new parsing/provenance behavior, missing-metadata reasons, and blame-table markers.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| cmd/entire/cli/attribution.go | Unifies line-spec parsing across commands, adds prompt provenance + missing-reason fields, and improves blame/why rendering. |
| cmd/entire/cli/attribution_test.go | Updates/extends unit tests for new why options and missing-metadata reason behavior. |
| cmd/entire/cli/attribution_consistency_test.go | New focused tests covering blame/why syntax parity and prompt provenance semantics. |
…ble divider width - `blame` Use string now shows range support: `<file>[:line[-line]]`, matching the Long help and parser (which accept `<file>:12` and `<file>:12-20`). - The `--long` blame-table dividers used `lineWidth+94` dashes but print with a 2-space indent, making them 2 chars wider than the header (whose content width after the indent is `lineWidth+92`). Both dividers reduced to `lineWidth+92` so the separators align with the header row.
…lame) why's Use/Long didn't mention the --line flag while blame's did, leaving the two commands asymmetric in their self-documentation. (Soph review nit)
Summary
Fixes two reported issues with
entire blame/entire why(labs) plus a related latent bug found while auditing.1.
entire whyprinted a "Prompt:" that doesn't exist inentire checkpoint explainwhysurfaced the session's seed prompt whileexplainshows the checkpoint-scoped transcript, so they disagreed (most visibly for attach/trail sessions, where the prompt iswork on this trail …).Root cause: when a session's
prompt.txtis empty, attribution falls back tometa.ReviewPrompt— a session-level seed, not a prompt recorded for this checkpoint — and rendered it as a plainPrompt:.Fix: track that provenance (
PromptSessionLevel) and render it asSession prompt:with a dim caveat and a pointer toentire checkpoint explain, so the output no longer implies the seed prompt lives in this checkpoint's transcript.2.
entire blameandentire whyused different line syntaxblametook--line N|N-M;whytook positional<file>:line. Now unified — both accept both forms:blame <file>:N,blame <file>:N-M(in addition to--line)why <file> --line N(in addition to<file>:line)They share a single
splitFileLineSpec;why's positional parser is migrated onto it, so a colon-then-non-numeric suffix is treated as a filename (matchingblame) and ranges get a friendly "useentire blamefor a range" message. Conflicting positional +--lineerrors withnot both.3. Latent:
SessionFallbackcaveat (found + fixed during audit)Relaxed
SessionFallbackto flag single-session path mismatches (was gated on>1session), but only when the session actually recorded paths that exclude the file — an emptyFilesTouchedmeans "unknown", not "renamed", so it must not print the misleading "may have been renamed" caveat (common for older metadata / attach sessions).Not changed (deliberate)
blameshowingpythonas the author on[HU]lines is faithfulgit blamecommitter data, not a bug — no code change.Test plan
attribution_consistency_test.go(TDD, red→green): prompt provenance, single-session fallback incl. the empty-paths non-flag case, unifiedblame/whysyntax forms, conflict + range-rejection, and the sharedsplitFileLineSpec.go test ./cmd/entire/cli/— pass (incl. existing JSON-stability and 2-session fallback tests; newprompt_session_levelfield isomitempty).mise run test:integration— 378 tests pass.mise run lint— 0 issues;gofmt/go vetclean.blame <file>:N,:N-M,--line,why <file>:N,--line, conflict errors, range rejection).Credits: the missing-metadata fix (the
MetadataMissingReasonguidance + determinism cleanup) is @karthik-rameshkumar's work from karthik-rameshkumar/cli#1, integrated here and credited as co-author on commitdd47f15. The session-fallback refinement is from @Soph's review.🤖 Generated with Claude Code