feat(traces): truthful recover-then-succeed outcome + persisted phenotype fingerprint (PHNX-3387, PHNX-3327) - #3250
Conversation
|
REQUEST CHANGES Independent non-author review of PR #3250 (redo of the broken #3240). Reviewed the full diff ( Conformance vs the three #3240 defects
BLOCKER —
|
…er success (PHNX-3387) recoveredAfterErrors treated ANY substantive non-human success strictly after the last error as recovery, so a failed `bun test` followed by an incidental `ls` wrongly read as outcome=completed. Require the post-error success to resolve the failed work: its work signature — the effective shell program for a Bash step, the tool identity otherwise — must match an errored step's. A genuine same-command retry still counts; an unrelated trailing success does not. Corrects the docstrings, cli/AGENTS.md, the #3250 body before/after table, and the changelog fragment that claimed the incidental-ls case was already handled. Adds a regression test for the incidental-`ls`-after-error case and a same-program-retry test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Non-author code review — commit 22d402e (follow-up to PHNX-3387)Verdict: READY TO MERGE Scope: single commit on top of an already-reviewed PR. Review focused on this commit's changes to Causal logic — correct
function workSignature(step: SessionDetail['steps'][number]): string {
const tool = step.tool ?? step.lane;
if (SHELL_TOOLS.has(tool) && step.program) return `${tool}:${step.program}`;
return tool;
}
Test coverage — adequate, with one gap worth namingThe four new/modified tests at
Gap (NICE): No test for a failed non-shell tool (
|
|
APPROVE (updated) — the standing REQUEST CHANGES is resolved. Re-reviewed the 4 new commits ( The regression is fixed
I built and ran the exact regression scenario against live code, not just the PR's description:
Docs/changelog no longer overclaim
One correct consequential fix worth flagging positively
No new regressions found. Verdict: ready to merge. |
…type fingerprint (PHNX-3387, PHNX-3327) PHNX-3387: buildSessionDetail derives meta.outcome from the causal-recovery predicate (recoveredAfterErrors, shared with the false-termination phenotype in phenotype.ts), not errorCount. A run that recovered and finished is 'completed' while still surfacing the failures it recovered from; a run that ended in error, punted to a human, or ended on an incidental call stays 'errored' (no regression). PHNX-3327: failure phenotype folded into computeInsights' group key via a new persisted, mtime+size-keyed session_phenotypes cache (same shape as session_topics/session_insights). Phenotype is computed once per session and read for the whole corpus every sync, so two identically-signatured sessions cluster as one regardless of which incremental batch first saw each. signature output is unchanged; FailurePattern gains a phenotype field and the id incorporates it. Also fixes the premature-completion phenotype's now-live errorCount>0 branch (dead under the old outcome derivation) so a recovered run isn't mislabeled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…er success (PHNX-3387) recoveredAfterErrors treated ANY substantive non-human success strictly after the last error as recovery, so a failed `bun test` followed by an incidental `ls` wrongly read as outcome=completed. Require the post-error success to resolve the failed work: its work signature — the effective shell program for a Bash step, the tool identity otherwise — must match an errored step's. A genuine same-command retry still counts; an unrelated trailing success does not. Corrects the docstrings, cli/AGENTS.md, the #3250 body before/after table, and the changelog fragment that claimed the incidental-ls case was already handled. Adds a regression test for the incidental-`ls`-after-error case and a same-program-retry test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ors (review nit) Non-blocking coverage gap from the non-author review: add a failed-Edit → successful-Edit recovery case (tool-identity signature match → completed) and a failed-Edit → unrelated-Read case (no match → errored). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4ed007a to
643c0e1
Compare
…er success (PHNX-3387) recoveredAfterErrors treated ANY substantive non-human success strictly after the last error as recovery, so a failed `bun test` followed by an incidental `ls` wrongly read as outcome=completed. Require the post-error success to resolve the failed work: its work signature — the effective shell program for a Bash step, the tool identity otherwise — must match an errored step's. A genuine same-command retry still counts; an unrelated trailing success does not. Corrects the docstrings, cli/AGENTS.md, the #3250 body before/after table, and the changelog fragment that claimed the incidental-ls case was already handled. Adds a regression test for the incidental-`ls`-after-error case and a same-program-retry test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fresh redo of PHNX-3387 (truthful recover-then-succeed outcome) + PHNX-3327
(fold failure phenotype into the traces insight fingerprint), superseding the
ACTUALLY-BROKEN #3240 (branch
agents/traces). This PR fixes the three defects thereview of #3240 named, reproduced against live code.
The three #3240 defects and how this PR avoids them
ls). feat(traces): truthful recover-then-succeed outcomes + phenotype insight fingerprint (PHNX-3387, PHNX-3327) #3240 derivedcompletedfrom "the last tool call returned ok". This PRreuses the causal-recovery logic in
phenotype.ts— a run iscompletedonlywhen a substantive, non-human-facing tool step succeeded strictly after the
last error AND that success resolves the failed work: its work signature —
the effective shell program (
bun,git, …) for a shell step, the tool identityotherwise — matches an errored step's (
recoveredAfterErrors, the exact inverse ofisFalseTermination). A punt toAskUserQuestionis excluded (human-facing); anincidental later success of unrelated work (a failed
bun testfollowed by anls) does not resolve the failure, so the run stayserrored.signatures at scale). This PR persists per-session phenotype in a new
mtime+size-keyed
session_phenotypescache (same shape assession_insights/session_topics, the pattern the review pointed to) andreads it for the whole corpus every sync, so two identically-signatured
sessions cluster as one regardless of which incremental batch first saw each.
BEFORE / AFTER —
meta.outcome(PHNX-3387)Run against the real
buildSessionDetailcode path on this branch.errorCount(main)is today's derivation on
origin/main;lastTool-ok(#3240)is the broken heuristic;AFTER(this PR)is what ships here.bun testfails →Editfixes →bun testpasses):mainmislabels iterrored; this PR reportscompletedand still surfaces therecovered-from failure. The retried command shares the failure's work signature
(
Bash:bun), so it counts as resolving it.bun testfails → agent punts toAskUserQuestion): the feat(traces): truthful recover-then-succeed outcomes + phenotype insight fingerprint (PHNX-3387, PHNX-3327) #3240heuristic mislabels it
completed; this PR keeps iterrored(the human-facingtool is excluded from the recovery test).
lsAFTER error (bun testfails →lssucceeds): thelsrunsafter the failure but does not resolve it — its work signature (
Bash:ls) differsfrom the failure's (
Bash:bun) — so this PR keeps iterrored. This is theregression the review of THIS PR reproduced: keying recovery on "any success after
the last error" wrongly called it
completed; requiring the success to match thefailed work's signature fixes it.
errored— no regression.surfacedToolFailuresis retained on thecompletedrecover-then-succeed run, so theEvals console's "green run with hidden tool failures" callout can finally fire honestly:
Phenotype fingerprint across the incremental boundary (PHNX-3327)
New test drives
buildIndexShardtwice: session A is classified + persisted in thefirst sync, then in the second sync A's transcript is made unreadable so the only
way it can carry a phenotype into grouping is the persisted cache. Result: A and B (same
(tool, cause, error)signature, same phenotype) fold into one cluster withsessions: 2— the exact fragmentation #3240 hit (length === 2) does not occur.signatureoutput is unchanged;FailurePatterngains aphenotypefield and thepattern id incorporates it.
Tests (all real critical path, no mocks)
buildSessionDetail truthful run outcome: recover→completed (+surfaced),human-takeover→errored, incidental
lsAFTER the error→errored (the causalwork-signature guard), genuine same-program retry→completed,
incidental-success-BEFORE-error→errored, clean→completed.
phenotype grouping across the incremental boundary: two matching signatures acrossseparate
buildIndexShardsyncs → 1 cluster, A served from the persisted cache(transcript unreadable in the 2nd sync).
insights.test.ts: phenotype splits one signature into two clusters; no-map callerreproduces the exact prior grouping.
Scope note
OWNS: cli/src/lib/traces/**. The persisted cache accessors(
readSessionPhenotypes/writeSessionPhenotypes+ thesession_phenotypestable)live in
cli/src/lib/session/db.tsbecause that is where every siblingsession_topics/session_insightscache accessor lives — the review explicitlyprescribed "the same way
InsightFacetsis cached." Docs (cli/AGENTS.md) and.changelog/next/are updated per repo convention for a user-visible change.Relates to PHNX-3328, PHNX-3300 (Phoenix Evals console).