Skip to content

Split retrospective analysis into main first-pass and Fable review#284

Open
ikuwow wants to merge 8 commits into
mainfrom
retrospective-review
Open

Split retrospective analysis into main first-pass and Fable review#284
ikuwow wants to merge 8 commits into
mainfrom
retrospective-review

Conversation

@ikuwow

@ikuwow ikuwow commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

PR 1 (#283) kept the original executor: a Fable subagent reads the whole session jsonl from disk and produces findings one-shot. That duplicates work — the main session already has the same context in memory — and re-pays the read cost on every session end even though the jsonl is typically several MB. This PR flips the executor so main does the first pass in-memory, and Fable reviews the resulting findings against a small mandatory sample of transcript slices instead of the whole file.

Why the shape it took

Splitting analyst from reviewer moves total transcript I/O from "whole file every time" to "a few slices plus targeted spot-checks", while keeping an outside perspective that catches motivated severity-downgrading. Main owns the initial slate and the final decision; Fable is the challenger with a hard 2-round cap and delta-only round 2 (Fable's "add missing" proposals get one defense pass, not a full re-review).

Self-bias mitigation: any finding where main overrides Fable's reject or adjust carries Fable's dissent into Step 4's AskUserQuestion, so the user arbitrates disputed cases explicitly. The rubber-stamp path stays only on confirm.

Compaction handling: an earlier reviewer suggestion to detect compaction via an isCompactSummary jsonl field was dropped after grep across all local ~/.claude/projects/**/*.jsonl returned zero matches for that field name. Instead Fable's slice sample is mandatory every session, so the coverage check runs whether the digest is complete or lossy.

Verification

Static:

  • pre-commit run --files claude/skills/retrospective/SKILL.md claude/skills/retrospective/analysis.md → all applicable hooks Passed; JSON/YAML/line-count budget hooks Skipped as N/A
  • git grep -n 'Step 1\|Step 2\|Step 3\|Step 4' claude/skills/retrospective/SKILL.md → step cross-references all consistent, no dangling references to the deleted old Step 1 delegation template
  • SendMessage tool schema verified against the current session's ToolSearch select:SendMessage result — the round-2 continuation mechanism exists at time of writing

End-to-end:

  • Run /retrospective once from a throwaway session with all findings routed as skip, and confirm (a) the 2-round cap fires when Fable emits add missing, (b) Fable's mandatory slice sample actually happens, (c) dissent surfaces to AskUserQuestion when main overrides a Fable verdict. Deferred out of this PR because claude/skills/retrospective/* is symlinked into ~/.claude/, so any real invocation mutates the live skill for every concurrent Claude Code session on this host, and non-skip paths would open real GitHub issues

Base branch

Stacked on retrospective-routing (PR #283) — merge #283 first, then this. GitHub will re-target the base to main automatically after #283 lands.

ikuwow and others added 6 commits July 10, 2026 19:34
Replace the asymmetric global-auto-issue / project-AskUserQuestion
routing with per-finding AskUserQuestion for both scopes, and replace
the 4-step countermeasure priority list with a 5-destination taxonomy
(existing-rule-edit, existing-skill-update, mechanize, new-rule,
new-skill) tagged explicitly on each finding. Preserve the sanitize
rule for global issues (now stated up front in Step 2) and add a
prompt-fatigue split for sessions with many findings.

Co-authored-by: Claude <Opus 4.7 (1M context)> <[email protected]>
Resolve gaps flagged by an outside review of the routing rewrite: the
apply-now branch context was unspecified (session end could be on the
default branch or an unrelated feature branch), and the create-issue
granularity was ambiguous between per-finding and per-session issues.
Add a branch gate that refuses apply-now on the default branch and
leaves feature-branch writes uncommitted, batch approved findings by
scope into one session-level issue each, and note that the dotfiles
cwd edge case still uses Other rather than lifting the global
apply-now ban.

Co-authored-by: Claude <Opus 4.7 (1M context)> <[email protected]>
Code review flagged three issues. The branch-gate detection compared
`git symbolic-ref refs/remotes/origin/HEAD` (which returns
`refs/remotes/origin/main`) to `git rev-parse --abbrev-ref HEAD`
(which returns `main`), so the two strings never matched and the
gate silently failed open. Normalize both to short branch names and
show the shell one-liner explicitly. Also split the "Global finding"
multi-clause bullet into parent + rationale/exception children per
the bullet-per-sentence rule, and restructure the `skip` / `Other`
outcome lines as prose so they no longer sit as trailing bullets
under the `create issue` list.

Co-authored-by: Claude <Opus 4.7 (1M context)> <[email protected]>
Main session now produces first-pass findings plus a factual digest
from in-memory context (no transcript read), and a Fable subagent
reviews them against a mandatory small sample of transcript slices,
returning per-finding confirm/adjust/reject verdicts. Additions Fable
proposes go through a delta-only round 2 (2-round hard cap), and any
dissent from an overridden Fable verdict is preserved for Step 4's
routing so the user can arbitrate. This cuts the transcript read
volume from the whole jsonl to targeted slices while keeping an
outside-perspective check on main's self-analysis.

Co-authored-by: Claude <Opus 4.7 (1M context)> <[email protected]>
Implementer preserved Step 4 content byte-for-byte on instruction,
which left the intro line referring to "the subagent's output" and
tags "from Step 1" — both stale under the new pipeline where Step 3
finalizes findings that may carry tag adjustments from Step 2/3.
Retarget the intro at Step 3's output and note the dissent-surfacing
path so the routing step matches the flow above it.

Co-authored-by: Claude <Opus 4.7 (1M context)> <[email protected]>
…nc intro

Code review flagged three consistency issues. Fable's Step 2 prompt
mandated slice-sampling and forbade whole-file reads, but analysis.md's
Reading-the-transcript still offered a whole-file shortcut for small
files — align by dropping the shortcut. Findings about the currently-
in-progress turn (not yet in the transcript) were falling through to
reject on missing evidence — add a fourth unverifiable verdict Fable
returns in that case, and route it in Step 3 as kept-with-caveat, not
dissent. Rewrite analysis.md's opening line so it addresses both
consumers named in Reader context instead of assuming a single
transcript reader.

Co-authored-by: Claude <Opus 4.7 (1M context)> <[email protected]>
Base automatically changed from retrospective-routing to main July 10, 2026 11:34
# Conflicts:
#	claude/skills/retrospective/SKILL.md
@ikuwow ikuwow marked this pull request as ready for review July 10, 2026 11:38
Only recorded dissent was being shown to the user, so when main
accepted Fable's verdict the outside review disappeared from the
routing choice — the user picked a route without seeing what Fable
concluded. Require every AskUserQuestion to include a compact Fable
summary line (verdict plus one-line reason) regardless of acceptance,
and keep the extra dissent display for disagreements.

Co-authored-by: Claude <Opus 4.7 (1M context)> <[email protected]>
@ikuwow

ikuwow commented Jul 10, 2026

Copy link
Copy Markdown
Owner Author

Agent Teams direction — investigation notes (for tomorrow)

Merge held. Retrospective didn't converge into real dialogue with the SendMessage-based subagent design (Fable review is one-shot plus optional defense round; main is the only decision-maker; no severity negotiation or counter-argument exchange). Agent Teams looked worth investigating as a replacement.

What's already available in Claude Code (verified against ~/.claude/cache/changelog.md)

  • CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 enables agent teams. Every session has one implicit team once enabled; TeamCreate / TeamDelete were removed.
  • Teammate spawn: Agent tool with a name parameter. team_name is accepted but ignored (implicit team).
  • Communication: SendMessage for peer-to-peer; teammates get their own context, inbox, shared task queue; idle between turns, wake on message.
  • --effort and CLAUDE_CODE_SUBAGENT_MODEL inheritance was fixed in a past release, so the leader's model/effort propagate to teammates.
  • Constraint: teammates cannot spawn nested teammates (Agent name param is blocked in teammate processes).

What a retro-only agent-teams version would need to decide

  • Env-var precondition: hard-require CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1, or keep the subagent-based path as a fallback.
  • Teammate lifecycle: teammates persist until stopped. Skill must explicitly stop the reviewer at end (otherwise it lingers in the session).
  • User-visible mode: teammateMode: "iterm2" etc. controls whether the dialogue shows as a separate pane, tmux window, or in-process. UX shifts significantly by mode.
  • Dialogue schema: this is the biggest design question. What do main and Fable actually argue about? Concrete options — severity negotiation loop, counter-argument round on Fable's rejects, findings-revision handshake, all three. Need explicit round definitions and a hard cap, or it can run away.

Suggested next step for tomorrow

Prototype in a sibling skill (e.g., retrospective-team) rather than mutating this one, so the current subagent-based flow stays intact for comparison. Run both against the same session and see whether the dialogue version actually surfaces disagreements the review-only version missed.

Immediate merge decision

Keep #284 open, do not merge. Revisit after prototyping the team version and comparing outputs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant