Skip to content

fix(run-evidence): NONE-safe tool_call + selected ORDER BY idiom (unblocks ingest on SurrealDB 3.2.0)#676

Merged
Necmttn merged 1 commit into
mainfrom
fix/run-evidence-null-toolcall
Jul 9, 2026
Merged

fix(run-evidence): NONE-safe tool_call + selected ORDER BY idiom (unblocks ingest on SurrealDB 3.2.0)#676
Necmttn merged 1 commit into
mainfrom
fix/run-evidence-null-toolcall

Conversation

@Necmttn

@Necmttn Necmttn commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Deep-dive root cause of #671; also fixes finding #4 of #675.

What #671 actually is

I reproduced the reporter's setup on SurrealDB 3.2.0 (fresh DB, schema applied, small dataset). The ingest does not hang or loop — the pipeline is a single-pass DAG (deps are awaited before taking a semaphore permit, so no deadlock). It runs every stage and then crashes on the run-evidence derive stage:

ingest: FAILED - Incorrect arguments for function record::id().
Argument 1 was the wrong type. Expected `record` but found `NONE`

command_outcome and hook_command_invocation legitimately have tool_call = NONE (session-level hooks — UserPromptSubmit/Stop/… — and hook-less outcomes; 3,812 such rows in the repro). record::id(NONE) throws, which aborts the entire ingest. Before #673's heartbeat there was no per-stage signal, so a killed/aborting run reads as "never exits" — a strong match for the report.

Fixes

  1. NONE-safe tool_call in both projecting SQLs (commandOutcomeSql, policyDecisionSql):
    IF tool_call != NONE THEN record::id(tool_call) ELSE NONE END. The JS side already treats toolCall as nullable (row.toolCall ?? null).
  2. Selected ORDER BY idiom — a latent second bug found while verifying the read surface: ax runs evidence did SELECT kind, summary … ORDER BY ts, and SurrealDB rejects ordering by an unselected idiom (Missing order idiom \ts`). Masked on dev boxes where the run_evidence tables never existed. Now selects ts`.

Verified live on SurrealDB 3.2.0

  • run-evidence derive stage now completes: written=55,631 refsWritten=18,882 (previously crashed at 0).
  • ax runs evidence <id> renders the timeline correctly.
  • Regression test asserts both tool_call SQLs are NONE-guarded (builders exported). bun test on both run-evidence test files → 36 pass; typecheck clean.

Relationship to #671 / #673

#673 (merged, v0.37.1) makes a genuinely slow/stuck stage visible + non-fatal (heartbeat + watchdog). This PR removes the concrete crash that actually aborted ingest in the derive stages. Together they should resolve #671; I've left #671 open pending the reporter confirming on the next release.

🤖 Generated with Claude Code

…locks ingest on SurrealDB 3.2.0)

Root-caused #671 by reproducing on SurrealDB 3.2.0: the ingest does NOT hang or
loop - it runs every stage and then CRASHES on the run-evidence derive stage:

  ingest: FAILED - Incorrect arguments for function record::id().
  Argument 1 was the wrong type. Expected `record` but found `NONE`

`command_outcome` and `hook_command_invocation` legitimately have NONE
`tool_call` (session-level hooks: UserPromptSubmit/Stop/…; hook-less outcomes -
3,812 such rows in the repro), and `record::id(NONE)` throws. Both SQLs now guard
it: `IF tool_call != NONE THEN record::id(tool_call) ELSE NONE END`. The crash
aborts the whole ingest, so this is a strong candidate for the reporter's "never
exits" (a killed/aborting run with no per-stage signal before #673's heartbeat).

Also fixes a latent second bug found while verifying the read surface: `ax runs
evidence` ordered by `ts` without selecting it, which SurrealDB rejects
("Missing order idiom `ts`"). It was masked on dev boxes where the run_evidence
tables never existed. Now selects `ts`.

Verified live end-to-end on a fresh SurrealDB 3.2.0 DB: run-evidence stage
completes (written=55,631 refsWritten=18,882) and `ax runs evidence <id>` renders.
Regression test asserts both tool_call SQLs are NONE-guarded (builders exported).

Refs #671, #675.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying ax with  Cloudflare Pages  Cloudflare Pages

Latest commit: a3319ba
Status: ✅  Deploy successful!
Preview URL: https://ca68debb.ax-62d.pages.dev
Branch Preview URL: https://fix-run-evidence-null-toolca.ax-62d.pages.dev

View logs

@Necmttn Necmttn merged commit 5654fd7 into main Jul 9, 2026
3 checks passed
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.

ax ingest derive loop never exits on Linux (subagents → claude-sidecars → invoked-positions)

1 participant