fix(session-flow): report retro chain coverage and split a comma-joined --sessions - #1981
Conversation
…ed --sessions Two ways a chain-scoped retrospective reported a wrong answer without an error. `parse_transcript.py --sessions` is declared nargs="+", so `--sessions a,b,c` — the shape a caller reaches for when the ids were just written into prose — was consumed as ONE token. It matched no transcript file, and the run reported "0 with transcript" for a chain whose transcripts all existed. Tokens are now split on ",": a session id never contains one, so the split cannot change the meaning of a correctly space-separated invocation. Empty fragments are dropped, and a value resolving to no ids reaches the existing usage error. Chain discovery walks `previous_handoff` pointers backwards and stops at the first session that wrote no handoff file, so a chain linked by hand-pasted continuation prompts terminates early — the reported case ran ten sessions and got a retrospective built from two, with nothing in the output signalling the gap. A two-session retro and a genuinely two-session chain read identically. Multi-session output now carries chain_coverage (requested / found / available / ratio). `available` counts the transcripts present for the project: the denominator the walk itself cannot see. The same ratio rides in the human-readable summary, and the skill must now state its discovery basis rather than silently scoping a chain retrospective to whatever the walk reached — below ~0.5 it names the counts and offers --sessions with the ids enumerated. Closes #1980 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
Claude finished @kyle-sexton's task in 3m 52s —— View job Review:
|
|
Claude finished @kyle-sexton's task in 1m 57s —— View job Security review
No security issues found. This PR is scoped to a local, stdlib-only Python CLI script (
No CI/workflow files are touched by this PR, so there's nothing in scope for the |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 55e41efc33
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Claude has reviewed this PR 2 times. The lane skips further automatic reviews after 5; deleting this comment resets the count. |
… id was named Every multi-session number is a sum over the requested id list, so a repeated id double-counted its transcript: the aggregate token and turn totals doubled, and `transcripts_present` could exceed `available` — which counts the file once — publishing chain_coverage.ratio 2.0 and a summary reading "covering 2 of 1 transcript(s)" against a field documented as a 0.0-1.0 coverage figure. The repeat is easy to produce now that a comma-joined list can be mixed with a space-separated one, which is what this PR added. build_multi_session_output deduplicates first-occurrence-wins, so the order the roles depend on survives (first id = current session). The rule lives in that one function rather than at the argument parser, so every entry point is covered and a new caller cannot reintroduce the defect. extract_chain_from_handoff keeps its own `seen` guard: a pointer cycle has to terminate the walk, not merely be cleaned up afterwards. chain_coverage.requested and the `pass` comparison now read the deduplicated list, so a run that named an id twice reports requested: 1 and still passes. Suite: 37 passed (2 new cases — repeat counts once, dedupe keeps first-seen order so roles are not relabelled). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 2m 43s —— View job Code review:
|
|
Claude finished @kyle-sexton's task in 1m 12s —— View job Security review
No security issues found. Reviewed the full diff against
Everything else (comma-splitting, |
…-reduction Resolves the version-line collisions this branch's 16-plugin lib bump has with three PRs that landed on main first (#1974 guardrails, #1981 session-flow, #1983 claude-ops). - guardrails: main released 0.19.1 (#1974's PowerShell sink fixes), so the shared-lib entry re-heads as 0.19.2. - claude-ops: main released 0.27.2 (#1983's $HOME spelling fix, which also escaped the manifest's em-dashes), so the shared-lib entry re-heads as 0.27.3 and the manifest keeps main's escaped description. - Both changelogs keep BOTH entries, each under its own version. Gates: sync-hook-utils.sh --check (all 16 copies match) and --check-bump origin/main (lib changed and every carrying plugin bumped) both pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Closes #1980
Summary
Two ways
retro's chain-scoped path produced a wrong answer with no error signal: a comma-joined--sessionslist resolved to nothing, and a chain walk that terminated early was indistinguishablefrom a genuinely short chain.
Fix
--sessionscomma splitting. The option is declarednargs="+", so--sessions a,b,cwasconsumed as one literal token that matched no transcript, and the run reported
0 with transcriptfor a chain whose transcripts all existed. Tokens are split on
,after parsing — a session idnever contains one, so the split cannot change the meaning of a correctly space-separated
invocation. Empty fragments (
a,,b, a trailing comma) are dropped rather than passed on as an idthat cannot exist; a value resolving to no ids at all reaches the existing usage error (exit 2).
chain_coverage. Multi-session output gainsrequested/found/available/ratio.availablecounts the transcripts present in the base directory — the per-project transcriptdirectory — which is the denominator the
previous_handoffwalk structurally cannot see. It iscoverage evidence for a reader, not a filter: some sibling transcripts will belong to other work,
which is exactly why the skill surfaces the ratio rather than the parser widening the chain. The
same ratio also rides in the human-readable
summary, so it is visible without reading thestructured field. An unreadable base directory degrades
availabletonullinstead of failingthe parse.
Skill contract.
retro's SKILL.md andcontext/session.mdnow require stating the discoverybasis, and forbid presenting a low-coverage chain retrospective silently: below a ratio of ~0.5,
name
foundandavailableand offer--sessionswith the ids enumerated.Verification
plugins/session-flow/skills/retro/scripts/test_parse_transcript.py— 35 passed (was 30). Newcases: comma-joined list resolves the same list as the space-separated form and keeps its order
(first id = current session); mixed separators with empty fragments; a
--sessions ,value thatyields no ids exits 2; coverage reported as 2-of-5 with
ratio0.4 and the ratio present insummary; full coverage reportsratio1.0.plugins/session-flow/skills/retro/scripts/parse-transcript.test.sh— passes.ruff checkandruff format --check— clean.scripts/check-changed-skills.sh origin/main—retroPASS, 0 errors.scripts/check-changelog-parity.sh --check-bump origin/mainand--check-order, andmarkdownlint-cli2on the three touched markdown files — clean.Fresh-docs mandate: no WebFetch was required and none was performed. This changes a script's own
CLI behavior, its JSON output shape, and skill prose — no plugin manifest field beyond the
versionbump, no hook contract, no documented harness behavior.
Related
session-flowcarries no copy of the shared hook library, so it is untouched by the 16-pluginversion bump in perf(hook-utils): cut three subprocess spawns per hook invocation #1979.
orchestrate)overlaps an audit item resolved separately and is deliberately out of scope here.