Skip to content

feat: run Gortex post-task diagnostics when the agent finishes - #57

Draft
vitaliyslion wants to merge 4 commits into
mainfrom
feat/post-task-diagnostics
Draft

vitaliyslion wants to merge 4 commits into
mainfrom
feat/post-task-diagnostics

Conversation

@vitaliyslion

@vitaliyslion vitaliyslion commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Runs Gortex's post-task diagnostics when the Pi agent finishes, matching Claude Code's Stop hook.

On agent_before_settle after a completed run, the extension sends gortex hook a stop with the last assistant reply. Gortex's diagnostics, or its claim-check block reason, go back as a displayed message and continue the run for one more model request, as a Stop hook's context does in Claude Code. Pi has no loop guard for a continuation, so the stop after the extension's own continuation is flagged stop_hook_active and never continues again. Aborted and failed runs skip the stop, and the stop gets a 10 s budget since Gortex runs its checks one after another. Esc cannot cut that wait short, because Pi gives agent_before_settle no abort signal, so the budget stays tight.

The diagnostics are scoped to the files this session wrote, which Gortex learns from forwarded tool calls. With enforcement off, tool calls are now still forwarded, marked record_only, and their decisions are ignored. Records run one at a time, since Gortex rewrites the session's state for each, and the stop waits for the last. Tool calls also read the session id through getSessionId() now.

Depends on zzet/gortex#1215, which adds the stop slot and write attribution to the bridge. Against a Gortex without it, a stop gets an empty answer and nothing happens, but record_only is ignored there, so an enforcement-off session would run every forwarded call through the full hook. Merge after a Gortex release ships #1215, with MIN_GORTEX_VERSION bumped to it.

Closes #44

Testing

  • npm run check passes
  • New behaviour has a suite that drives it through Pi's ExtensionRunner (see docs/tests.md)
  • Tried by hand in Pi (pi -e /path/to/checkout), if user-visible

test/post-task.test.ts covers the stop envelope and its budget, the continuation with diagnostics and with a block, the silent stop after the continuation, aborted and failed runs, a continuation that was aborted or cancelled by another extension, sessions without graph tools, record-only forwarding, its ordering and the wait on it, and the rendering. The harness's settle computes canContinue the way Pi does, which caught a guard that skipped every stop.

Also verified outside the harness: a real Pi AgentSession with a scripted model, the extension spawning a locally built Gortex with #1215 against a running daemon. The model edited an indexed file from a subdirectory cwd, received "Your edits this session: 2 symbol(s) across 1 file(s)" on finish, and the second stop was silent with no further model call, with enforcement on and off.

Tried by hand in Pi 1.4.0 with pi --no-extensions -e builtin:mcp -e <checkout>, a real model and the locally built Gortex. After the model edited src/runtime.ts, a "Gortex" box rendered the diagnostics as Markdown: the session's own edit, other dirty files listed as not attributed to the session, and the first lines with an expand hint that ctrl+o opens. The model acted on them by running the tests, and the run settled after that one continuation.

Checklist

  • No runtime dependencies added
  • README configuration table updated, if config changed
  • docs/architecture.md updated briefly, only if a design decision changed
  • Works on Windows paths and process spawning, if touching either

The hook call now passes its own timeout to the spawn. The full suite passes on windows-latest CI. Under Windows Node 24 in Wine it passes too, apart from known Wine gaps that fail the same way on main: libuv's process.title lookup crashes files that load Pi's TUI stack, and Wine's cmd.exe rejects cross-spawn's escaped bat path. With process.title stubbed, 209 of 210 pass, and the bat-path test is the one failure.

On agent_before_settle after a completed run, send `gortex hook` a stop
with the last assistant reply. Diagnostics or a block reason go back as a
displayed message and continue the run for one more request, matching
Claude Code's Stop hook. The stop after that continuation is flagged
stop_hook_active and never continues again, since Pi has no loop guard.

Tool calls are forwarded record-only when enforcement is off, so Gortex
can scope the diagnostics to files this session wrote, and the stop
waits for records still in flight. Tool calls now read the session id
through getSessionId().

Refs #44
Gortex writes its diagnostics in Markdown, which drew with its syntax showing. They now render through Pi's Markdown component inside the custom message box, under a short Gortex label, since the briefing brings its own heading.
With enforcement off, records were fire-and-forget, so parallel edits ran
concurrent hooks that each rewrite the session's state in Gortex and could
drop a file from the briefing. Records now run one at a time and the stop
waits for the last.

The loop guard is cleared on agent_settled, so a continuation another
extension cancelled no longer marks the next run's stop as a rerun.

The stop budget drops to 10 s: Esc cannot cut it short, since Pi gives
agent_before_settle no abort signal.

This branch has not been deployed

No deployments
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.

Run Gortex post-task diagnostics when the agent finishes

1 participant