Skip to content

Fix codex subagent indexing, search cwd, and broken-pipe exits - #2

Open
caffeinum wants to merge 4 commits into
buildoak:masterfrom
caffeinum:fix/codex-parent-links-search-cwd-sigpipe
Open

Fix codex subagent indexing, search cwd, and broken-pipe exits#2
caffeinum wants to merge 4 commits into
buildoak:masterfrom
caffeinum:fix/codex-parent-links-search-cwd-sigpipe

Conversation

@caffeinum

Copy link
Copy Markdown

Three reported bugs, plus the test failures that were blocking the verification gate.

1. Codex subagents failed to index behind their parent

[6/10] error 9767dfaf (...): FOREIGN KEY constraint failed
[7/10] error 1abb4461 (...): FOREIGN KEY constraint failed
[8/10] error 0cd2d771 (...): FOREIGN KEY constraint failed
[9/10] indexed 4105a92a (...)

All three are subagents of 4105a92a — indexed at position 9, after its own
children. Discovery is newest-first and a fork always starts after the session
that spawned it, so children reached the indexer first; sessions.parent_id is
a foreign key, so the insert aborted and the session was dropped entirely.

  • Discovery sorts linked sessions after their potential parents (the existing
    Hermes-only rule, generalized — Codex needed it for the same reason).
  • The indexer writes the link only when the parent row exists.
  • Anything still unresolved is applied after the pass, which also covers nesting.
  • A parent that is never indexed leaves the child indexed and typed as a
    subagent with the link unset, and says so:
    -> session 9767dfaf: parent 4105a92a is not indexed; link left unset

Losing the whole session to keep a foreign key was the wrong trade.

2. gaal search did not report cwd

A hit named the session but not where it ran, so getting back to the repo took a
second inspect per session. The enrichment pass already loads the session row;
cwd now rides along in JSON and in the -H table.

3. gaal ... | head reported a failure

{"error":"The command failed: Broken pipe (os error 32)", ... "exit_code":1}

Rust ignores SIGPIPE at startup, so a closed downstream pipe surfaced as an
EPIPE write error — an error payload and non-zero exit for JSON commands, a
println! panic for human output. Gaal now restores the default disposition and
dies on SIGPIPE (141) with clean stderr, like every other CLI.

Test failures that were already red on master

cargo test fails on master before any of the above:

  • handoff_frontmatter_uses_local_date hardcoded the local date of a 23:43 UTC
    timestamp — true only at UTC+1 or east, false in US timezones.
  • The agy batch-handoff and grok search tests used a relative --since 30d (or
    the search default) against fixtures with fixed dates, and those fixtures aged
    past the window. Pinned to absolute bounds, matching the surrounding agy
    assertions.

Verification

  • New tests/integration/codex.rs with a sanitized fixture (coordinator +
    two subagents + one subagent whose parent has no trace). Each test was
    confirmed to fail with the fix reverted and pass with it.
  • cargo fmt --check, cargo clippy --all-targets, cargo test (203 tests),
    ./tests/run-all.sh — all green.
  • Checked against the real traces that produced the report: the same window that
    gave "errors": 3 now indexes 9/9 with the three subagents linked to
    4105a92a and that parent promoted to coordinator.

Opened from a fork — the account on this machine has read-only access to
buildoak/gaal.

🤖 Generated with Claude Code

caffeinum and others added 4 commits August 12, 2026 14:52
Discovery returns sessions newest-first, and a forked subagent always
starts after the session that spawned it. sessions.parent_id is a foreign
key, so linking a child that reached the indexer first aborted the insert
with FOREIGN KEY constraint failed and dropped the session entirely — a
backfill of one coordinator plus three subagents lost all three.

Sort linked sessions after their parents, write the link only when the
parent row exists, and apply the rest after the pass so nesting resolves
too. A parent that is never indexed now leaves the child indexed and
unlinked with a reported reason instead of failing the session.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A search hit named the session but not where it ran, so following a
result back to the repo it came from needed a second inspect call per
session. The enrichment pass already loads the session row; carry cwd
through to JSON and the human table.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Rust ignores SIGPIPE at startup, so `gaal inspect ... | head` turned a
closed downstream pipe into an EPIPE write error: JSON commands reported
"The command failed: Broken pipe (os error 32)" and exited non-zero,
human output panicked out of println!.

Restore the default SIGPIPE disposition so gaal dies on a closed pipe
like every other CLI, and treat a broken pipe that still reaches the
error path as a silent exit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three failures unrelated to any code change:

handoff_frontmatter_uses_local_date hardcoded the local date of a
23:43 UTC timestamp, which only holds at UTC+1 or east. Derive the
expectation from the fixture instead.

The agy batch-handoff and grok search tests passed a relative `--since
30d` (or relied on the search default) against fixtures with fixed
dates, so they started failing once the fixtures aged past the window.
Pin absolute lower bounds, as the surrounding agy assertions already do.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.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