Skip to content

fix: keep thread-analysis log dirs available to resumed runs - #700

Merged
rianjs merged 2 commits into
mainfrom
fix/699-thread-analysis-log-dir
Oct 30, 2026
Merged

rianjs merged 2 commits into
mainfrom
fix/699-thread-analysis-log-dir

Conversation

@rianjs

@rianjs rianjs commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Closes #699

Problem

A cr review rerun on #698 failed in thread_analysis before the provider started (resume_llm, 0 ms). It couldn't open agent-logs/thread-analysis/<thread>.jsonl: no such file or directory.

The pipeline does create that directory (prepareSelectionContext), but only once, early in the run, while it is still empty. llm.LaunchProcess then opened the log with a bare os.Create, so a missing parent directory was fatal.

The run's artifact timestamps show the directory was removed between being created and the thread analysis running. In the failing run, agent-logs/ and dossier/ were created at 15:54:4x–50, and the thread-analysis task started at 15:55:03. The thread-analysis/ log dir on disk now was created later, at 15:55:48, by the --fresh-session rerun. The only code that deletes directories under the runs root is retention prune's removeEmptyParents, which removes every empty directory. Another cr review started on a different PR at the same time (15:55:09). I couldn't prove a prune got past the active-runs lock, so that part is a likely explanation, not a confirmed one.

Fix

Two changes, one per side of the failure:

  1. Opening the log. openSubprocessLog now runs MkdirAll on the log's parent (0700, the same mode the pipeline uses) before it creates the file. Every subprocess task, fresh or resumed, then works no matter what happened to the directory after setup.
  2. The empty-dir sweep. removeEmptyParents used to walk the whole runs root and remove every empty directory, including empty subdirs inside a live run's artifact tree. It now stops at attempt (run-*) dirs, so it removes only empty layout parents left behind by deleted runs. Unreferenced attempt dirs are still cleaned up by orphan removal, after its grace window.

Tests

  • New subtest TestSubprocessCodexSafetyModes/resume_creates_a_missing_log_directory: resumes a codex session with LogPath under a missing agent-logs/thread-analysis/. Without the fix it fails with the same open …: no such file or directory error as the issue. With the fix it passes.
  • New TestPruneKeepsEmptyArtifactSubdirsOfLiveRuns: a live run with an empty agent-logs/thread-analysis/ keeps it through Prune, and an empty layout parent is still removed. Without the fix the live run's dir is deleted.
  • go test ./... (3825 passed) and make lint (0 issues).

)

A resumed thread analysis failed before launching the provider when
agent-logs/thread-analysis/ no longer existed. The pipeline creates that
directory early, while it is still empty. LaunchProcess then opened the log
with a bare os.Create and treated the missing parent as fatal.

Create the parent directory where the log is opened, so every subprocess
task (fresh or resumed) works no matter what happened to the directory
after the run set it up.

@rianjs-bot rianjs-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated PR Review

Reviewed commit: d3d22eba7833
Profile: codex-rianjs-bot - Posting as: rianjs-bot[bot]

Summary

Reviewer Findings
go:implementation-tests 0

Reviewer Coverage

Complete coverage details are retained in the local coverage.json artifact.

  • go:implementation-tests — complete (broad); scope: 2 files; examples: internal/llm/subprocess.go, internal/llmadapters/subprocess_test.go; body-inspected: 2 files; examples: internal/llm/subprocess.go, internal/llmadapters/subprocess_test.go; skipped: none; constraints: none

0 PR discussion threads considered. 0 summarized; 0 resolved.


Completed in 24s | gpt-6.1-terra | cr 0.10.357
Field Value
Model gpt-6.1-terra
Reviewers go:implementation-tests
Engine codex_cli · gpt-6.1-terra
Reviewed by cr · rianjs-bot[bot]
Duration 24s wall · 15s compute
Cost unavailable
Tokens 128.7k in / 546 out

Per-workstream usage

  • orchestrator-selection — gpt-6.1-terra
    • In: 18.1k
    • Out: 110
    • Cache read: 15.1k
    • Cache create: unavailable
    • Cost: unavailable
    • Duration: 5s
  • go:implementation-tests — gpt-6.1-terra
    • In: 73.5k
    • Out: 282
    • Cache read: 53.4k
    • Cache create: unavailable
    • Cost: unavailable
    • Duration: 7s
  • orchestrator-rollup — gpt-6.1-terra
    • In: 37.1k
    • Out: 154
    • Cache read: 33.0k
    • Cache create: unavailable
    • Cost: unavailable
    • Duration: 3s

…#699)

removeEmptyParents walked the whole runs root and removed every empty
directory, including empty subdirs inside a live run's artifact tree. The
pipeline creates agent-logs/thread-analysis before writing to it, so a prune
could delete it out from under an in-flight run.

Stop the sweep at attempt dirs. It now removes only empty layout parents left
behind by deleted runs; unreferenced attempt dirs are still handled by orphan
removal.
@rianjs rianjs changed the title fix(llm): create the subprocess log's parent dir before opening it fix: keep thread-analysis log dirs available to resumed runs Oct 30, 2026

@rianjs-bot rianjs-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated PR Review

Reviewed commit: 93f66ff33628
Profile: codex-rianjs-bot - Posting as: rianjs-bot[bot]

Summary

Reviewer Findings
go:implementation-tests 0

Reviewer Coverage

Complete coverage details are retained in the local coverage.json artifact.

  • go:implementation-tests — complete (constrained); scope: 4 files; examples: internal/datalifecycle/datalifecycle.go, internal/datalifecycle/datalifecycle_test.go, internal/llm/subprocess.go, internal/llmadapters/subprocess_test.go; body-inspected: 4 files; examples: internal/datalifecycle/datalifecycle.go, internal/datalifecycle/datalifecycle_test.go, internal/llm/subprocess.go, internal/llmadapters/subprocess_test.go; skipped: none; constraints: Review was limited to static inspection; tests were not run in the read-only environment.

0 PR discussion threads considered. 0 summarized; 0 resolved.


Completed in 24s | gpt-6.1-terra | cr 0.10.357
Field Value
Model gpt-6.1-terra
Reviewers go:implementation-tests
Engine codex_cli · gpt-6.1-terra
Reviewed by cr · rianjs-bot[bot]
Duration 24s wall · 14s compute
Cost unavailable
Tokens 261.3k in / 889 out

Per-workstream usage

  • go:implementation-tests — gpt-6.1-terra
    • In: 203.7k
    • Out: 686
    • Cache read: 167.0k
    • Cache create: unavailable
    • Cost: unavailable
    • Duration: 11s
  • orchestrator-rollup — gpt-6.1-terra
    • In: 57.6k
    • Out: 203
    • Cache read: 51.8k
    • Cache create: unavailable
    • Cost: unavailable
    • Duration: 3s

@rianjs
rianjs marked this pull request as ready for review October 30, 2026 20:24
@rianjs
rianjs merged commit b51c566 into main Oct 30, 2026
12 checks passed
@rianjs
rianjs deleted the fix/699-thread-analysis-log-dir branch October 30, 2026 20:28
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.

cr review rerun fails in thread_analysis resume: agent-logs/thread-analysis log file not found

1 participant