Ask the API whether an action persisted before failing on a missing record - #224
Merged
Merged
Conversation
DavertMik
force-pushed
the
pilot-askapi-persisted
branch
from
September 16, 2026 22:15
39fd9c4 to
c99c23b
Compare
… a missing record Both descriptions of askApi framed the tool purely as pre-action setup — "what data already exists", "before precondition()". Nothing told the model the same tool settles whether its own run's action persisted, so when a page reported success without rendering the result, Pilot had no route to the data layer and decided from the screenshot alone. In trace df450361562bbd7ef4dc36fba307c203 a suite copy submitted fine and the app showed a "copied to root" notification, but the copy was not visible in the tree. Pilot read that correctly, then returned text-only guidance naming a command the Tester has no tool for, and the run ended as a failure. askApi was in that call's tool list and went unused. askApi already writes its answer to task notes, which reviewVerdict reads, so a confirmed write reaches the verdict without new plumbing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
DavertMik
force-pushed
the
pilot-askapi-persisted
branch
from
September 16, 2026 22:34
c99c23b to
55ab797
Compare
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.
Problem
Trace
df450361562bbd7ef4dc36fba307c203(sessionRollingRemarkableCyan648), scenario "Copy an existing suite and verify the copied suite is added to the suites tree."The copy submitted successfully.
see()then reported:The app itself confirmed the write. Pilot read this correctly in its progress analysis — "Copy submission succeeded and the app reported it copied to root, but the copied suite is not yet visible" — then returned text-only guidance ("reload with
I.reloadPage()") and pre-authorised the fail. The Tester searched its tools forreloadPage, found none, and calledstop(). Final verdict:{"decision":"fail","reason":"Copy notification appeared, but no distinct copied suite is visible in the suites tree."}askApiwas in that call's tool list and went unused.Root cause
Both places the model reads about
askApiframed it as pre-action setup only:src/ai/pilot.ts:1160— "what data already exists", "before creating any"src/ai/fisherman/tools.ts:223(the tool's owndescription) — "Ask what data already exists", "Use it before precondition()", "a record that is already there"So with the page not rendering the result, Pilot had no route to the data layer and decided from the screenshot alone.
Fix
The tool's stated purpose, in both places it is stated. Pilot's paragraph, 3 lines → 4:
and the matching clause in the tool
description(plus its input-schemadescribe, which also said "data that already exists").Visibility stays a concern worth recording, but it stops being the thing that decides the verdict.
No plumbing needed:
askApialready doestask.addNote(...)on a successful lookup (fisherman/tools.ts:244), andreviewVerdictbuilds its<notes>block fromtask.notesToString()(pilot.ts:105). A confirmed write therefore reaches the verdict context on its own.Trade-off
Pilot spends a Fisherman round-trip at a moment that is common in async UIs. Where API access is not configured, behaviour is unchanged —
askApireturns "No API access is configured… Judge from the page instead" and absence still decides the verdict.Testing
bun test tests/unit/— 1436 pass, 0 failbun test tests/integration/— 148 pass, 1 skip, 0 fail (includespilot-ask-api.test.ts)bun run format,bun run check:fixcleanNo test added: this is a prompt clarification with no behavioural branch to pin, and
persistedalready appears in the shared evidence rules, so an assertion here would only restate the string it asserts.Worth a replay of the same scenario before merge — expected: one
askApicall in Pilot's progress analysis after the copy, guidance naming a check the Tester has a tool for, and a verdict that is notfail. Regression was not run; apply the label if you want it.Noted while tracing, not fixed here
src/ai/pilot.ts:128—requestVerification's description contradicts itself: "Also use when evidence is insufficient before deciding pass/fail" then "Leave null for 'continue', 'fail', or 'skipped'".pilot.ts:183gates execution ondecision === 'pass', so the first clause is dead text.src/ai/tools.ts:629—see()always returns "Visual confirmation is valid evidence for test results. Use record() to note the visual findings." True for a sighting, not for an absence, and it routes a negative straight torecord().verify()'sinexpressiblebranch already carries the right phrasing.I.reloadPage()without the mechanism its own prompt specifies atpilot.ts:1155("through form").🤖 Generated with Claude Code