Skip to content

plugin: show the user, after each turn, where an AxiomCode answer verifiably helped the agent (#1935) - #1936

Open
swapnilpaliwal-sd wants to merge 9 commits into
apps/integration-0.1.10from
feat/assist-receipts
Open

swapnilpaliwal-sd wants to merge 9 commits into
apps/integration-0.1.10from
feat/assist-receipts

Conversation

@swapnilpaliwal-sd

Copy link
Copy Markdown
Contributor

Closes #1935.

What

A Stop hook (plugins/axiomcode/hooks/assist.py) shows the user, under the agent's reply, where an AxiomCode answer verifiably led the work in that turn:

◆ AxiomCode this turn
  • Helped: `impact _proxy_to_logger` showed _base.py (first seen there); edited it, read _native.py, twisted.py; both picked test files pass
  • Helped: `tests` picked 7 test files; all 7 pass
  • Redirected: before the answer the agent was in other files. It left them (never touched again, not in the diff), and the change landed in a file the answer showed first.
  • Helped: a file first seen in the answer was edited and the edit is kept, or a test verb's picked tests ran and passed.
  • Useful: it was read, or its picked tests ran.

Every link is read from the transcript (tool calls and results) and the working-tree diff, never from the agent's text, which is already on screen when Stop runs. An unchecked link is not printed, and a turn where no query led anywhere prints nothing. Chains accumulate in .axiomcode/assists.jsonl; axiomcode report renders them as HTML. AXIOMCODE_ASSISTS=off disables it.

Validation

  • tests/assists.py: 32 checks on synthetic transcripts, a credit case and a near no-credit control per rule, plus the hook end to end.
  • Replay of 23 past agent sessions (TS/JS/Python/Java/C# app loops): 149 chains. An independent checker re-tests each link with raw-text search over the transcript JSON (answer names the file; nothing earlier names it; a later Edit/Write or shell write targets it; left-behind files are never named by a later call; tests passed): 0 failed links.
  • Live headless runs on real OSS issues, two rounds on pinned Python repos, with the plugin loaded via --plugin-dir:
    • Round 2 (code frozen): 11 tasks / 15 turns (bug fixes from real issues, a rename, a cross-caller refactor, two 3-turn sessions, one control). 10 chains, 68 links checked, 0 failed. The control task printed nothing.
    • Silences were correct. For the rename, grep had already found every caller before the graph was asked. On two bug fixes the answer's files were never acted on.
  • The live runs drove the rule fixes in this PR: batched shell lines credit only answer-shaped rows; a shell edit counts only for the file it writes (log appends that mention a file had produced false "edits"); a write-then-test line that fails still edits; impact-picked tests count only when first seen in the answer; one test run is credited once.

Also

  • The packaged copy skills/axiomcode/SKILL.md had drifted from its source on the base (tests/manifests.py failed there). packaging/copies.py resynced it.
  • tests/surfaces.py still fails on the base's README --fresh mention. That predates this PR and is unrelated.

…ifiably helped the agent (#1935)

Agents finish a task with and without the graph and rarely credit the answer they acted on. A Stop hook
(hooks/assist.py) now reads the session's transcript at the end of each turn and prints, under the reply,
one line per chain an answer started:

    ◆ AxiomCode this turn
      • Helped: `impact _proxy_to_logger` showed _base.py (first seen there); edited it, read _native.py,
        twisted.py; both picked test files pass

Labels, strongest first: Redirected (the work moved from files left behind to one the answer showed),
Helped (a file first seen in the answer was edited and the edit is kept, or a test verb's picked tests
passed), Useful (it was read, or its picked tests ran). "First seen" means no earlier prompt, tool call,
tool result or hook context named the file.

Nothing comes from the agent's text: its reply is on screen before a Stop hook runs. Every link is read
from tool calls and results and the working-tree diff, and an unchecked link is not printed. A shell line
that batches the query with grep or cat credits only rows shaped like an answer's. A shell edit counts
only for the file the line writes, and a test run is credited once. Turns where nothing came of a query
print nothing.

Chains go to .axiomcode/assists.jsonl, which only the hook writes. A chain prints once, and again only
when it gets stronger. `axiomcode report` renders them as .axiomcode/assists.html.
AXIOMCODE_ASSISTS=off turns it off.

tests/assists.py: 32 checks over synthetic transcripts, a case each rule must credit and a near case it
must not, plus the hook end to end.

Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com>
swapnilpaliwal-sd and others added 8 commits October 12, 2026 10:37
…e files and tests behind each (#1935)

Each chain now reads cause → action → effect with the concrete files edited or read and the picked test files that
passed. The header counts the answers that led the agent's work; answers that led nowhere are never counted or
shown, and a label no chain earned gets no tile in the report.

Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com>
…eipt (#1935)

Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com>
…s and from shell edits (#1935)

- A graph note the plugin's own hooks put in front of the agent (the callers an edit reaches, where a task
  lands) is an answer like a tool call's; its hook_success copy no longer marks its files seen first.
- A shell line that edits files and also runs axiomcode keeps its edits, and a helper the script defines and
  calls with a path (def sub(path, ...): ...write_text...) writes that path.
- A row about a name the task already gave is the task's lead, not the answer's (the name asked about is
  exempt: it is on every caller's line); a note credits a file:line, not a file summary.

Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com>
… with every action inspectable (#1935)

- The report opens on the outcome (sessions, answers acted on, previously unseen files edited, selected
  tests passing), then the three ways answers showed, featured timelines, every answer expandable to its
  recorded actions by sequence number, and the rules each label is assigned by.
- Receipts and report say what happened: the agent acted on N answers; an answer pointed the agent to a
  file directly, before it had come across it.
- camelCase names a task gives are the task's lead; a runner config under test/ is not a test file; a run
  that exits 0 but reports failures is not a pass.

Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com>
…record, and the receipt links it (#1935)

Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com>
…ent with a query are not credited to it (#1935)

The Stop hook hands the receipt back to the agent once (decision "block"), which ends its reply with it, so it is part of
the answer in every client. The second stop checks the reply carries every line and shows it as a message when it
does not. Gemini keeps the message.

A file the agent read in the same message as a query was named before the answer came back; it is no longer credited
to that answer.

Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com>
…est run (#1935)

A test line exits 0 when it ends in `| tail` or `; ruff check`, including a run that never started (a missing module,
a collection error, every test deselected), so exit 0 was counted as a pass. A pass now needs the runner's own pass
line with no failure or error beside it, and a test file passes when its latest run does.

Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com>
…ests (#1935)

A follow-up turn that asks `tests` again and runs what it picked was credited to the first turn's answer, so the turn
that acted on it printed nothing.

Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com>
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