fix(executing-plans): ledger the test summary, not the trailing duration - #2348
Open
Navaneethp007 wants to merge 1 commit into
Open
Navaneethp007 wants to merge 1 commit into
Navaneethp007 wants to merge 1 commit into
Conversation
Navaneethp007
force-pushed
the
fix-task-done-tap-summary
branch
from
October 1, 2026 13:27
3213c15 to
916bf0a
Compare
2 tasks done
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.
Who is submitting this PR? (required)
claude-opus-5[1m]superpowers@claude-plugins-official6.3.0,skill-creator@claude-plugins-official,frontend-design@claude-plugins-official. No other plugins installed.What problem are you trying to solve?
Fixes #2342, reported by @koreankop with logs from a real
executing-planssession.scripts/task-donefills the ledger's result field with the last non-blank line of the test log. For TAP output the last line is the duration.task-donealways redirects the test command to a file, andnode --testemits TAP when stdout is not a TTY, so every completion line in such a run records the runtime instead of a result:This is not a correctness bug —
task-donegates on exit status, so a failing run still records nothing. The cost is that the field stops being evidence.SKILL.mdtells the executor to trust the ledger over its own recollection after compaction, and documents this field as→ 1/1 pass(line 343). Withnode --testit cannot distinguish a passing run from any other run, and it silently hides shortfalls: a run of 2 passing plus 1 skipped looked identical to a clean run.I did not hit this in my own work first. I reproduced it by following the reporter's steps on a throwaway repo (Windows 11 / Git Bash, Node v22.14.0) and got the output above, consistent with their report.
What does this PR change?
task-donenow reads the run's own TAP summary counts (# tests/# pass) and records them as<passed>/<total> pass, the shapeSKILL.mdalready documents. Runners that print no TAP summary fall back to the previous last-line behaviour. The exit-status gate is untouched. Adds a regression test totests/claude-code/test-executing-plans-scripts.sh.Relationship to #2388, which landed on the same line
#2388 changed the exact line this PR replaces, adding an empty-log guard so
grepexiting 1 underset -euo pipefailcan no longer aborttask-doneand drop the ledger line entirely:This PR is rebased onto that and deliberately carries the guard onto the fallback branch:
That is load-bearing, not cosmetic. Resolving the conflict the obvious way — keeping this PR's version of the line — silently reintroduces #2385, and none of this PR's own assertions would catch it. I verified that directly; see the third row of the verification table below. The two fixes are complementary: #2388 stops the fallback from aborting, this one makes the TAP path report an actual result.
Is this change appropriate for the core library?
Yes.
task-doneis coreexecuting-plansinfrastructure that Superpowers ships, and the ledger contract it writes is core to how execution survives compaction. The change is not tied to a project, team, or third-party tool: it reads TAP, a cross-language test output format, and leaves every non-TAP runner byte-identical. It adds no dependency.What alternatives did you consider?
→ exit 0; <last line>), as the issue suggested. I tried this first and it does not work:task-donereturns early on a non-zero status, sorcis always0by the time the result field is built. It would record a constant, not evidence.ok/not oklines and count them. Rejected as redundant and more fragile — TAP already prints the totals, and counting result lines has to handle subtests,# SKIPand# TODOdirectives correctly to avoid being wrong in exactly the cases that matter.node --test. Rejected as too narrow. Keying on TAP means any TAP-emitting runner benefits, and nothing is node-specific.task-done's interface and pushes work onto every caller to fix a default that can simply be correct. Worth revisiting only if TAP parsing proves insufficient.pass 4 fail 0. Rejected in favour of4/4 passto match the documented format.Does this PR contain multiple unrelated changes?
No. One problem, one behaviour change, plus the regression test covering it.
Existing PRs
tests: … → <result>field. I searched open and closed PRs forduration_ms,task-done,ledger, andtap.Environment tested
claude-opus-5[1m]Shell/OS for the runs: Windows 11, Git Bash (scripts ran under bash via their shebang), Node v22.14.0. I have not tested on macOS or Linux; the reporter's original session was macOS 26.6.2 / zsh.
New harness support
Not applicable — this PR does not add support for a new harness.
Evaluation
node --testruns record# duration_ms …instead of pass/fail #2342, and then asked it to fix it. The change is grounded in a reproduction that was actually run, not in reasoning from documentation.SKILL.mdprose changed, so there is nothing for a skill eval to measure. The appropriate verification here is deterministic, and that is what was run.Behaviour of the result field, measured on a throwaway repo:
node --test, 4 passing# duration_ms 117.72024/4 passechooutput)12 examples, 0 failures(no output)(no output)— unchanged# duration_ms …2/3 passThe skipped case is the most useful one:
2/3 passsurfaces a shortfall the duration line hid entirely.Each assertion was checked against the code it is meant to guard, so that none of them can pass vacuously:
task-doneuseddev|| last="(no output)"rc=1)The third row is why the guard is called out above: the naive conflict resolution passes every assertion this PR adds while re-breaking #2385, and only #2388's tests catch it.
Full suite is green, 14/14, with no pre-existing failures. (An earlier revision of this PR disclosed one unrelated Git Bash failure in
task-start prints the brief path; 49b1db5 fixed it upstream, so that no longer applies.) The siblingtests/claude-code/test-sdd-workspace.shalso passes.The regression test feeds a TAP fixture through
printf, so it adds no Node dependency and runs wherever the suite runs.Rigor
superpowers:writing-skillsand completed adversarial pressure testing — not applicable: this is a script + test change, no skill content modifiedHuman review