Summary
On OpenClaw 2026.4.22, openclaw doctor --non-interactive falsely reports live *.trajectory.jsonl session artifacts as orphan transcript files and suggests archiving them via --fix, even when the owning sessions are still present in sessions.json and one may have a live lock.
Observed behavior
- Doctor reports orphan transcript files in
~/.openclaw/agents/main/sessions
- Reported examples are
*.trajectory.jsonl
- At least one matching session may still be active and locked
openclaw doctor --fix appears willing to rename valid trajectory logs to *.deleted.<timestamp>
Example doctor output:
2b549cee-6e59-454d-8bb6-94c08d20bcbb.trajectory.jsonl
67553e3e-f24d-4018-bb38-a9abc43b9d23.trajectory.jsonl
69d8482d-2321-4cb0-bd7d-b59132b6f382.trajectory.jsonl
Expected behavior
Doctor should only consider primary session transcript files as orphan candidates. *.trajectory.jsonl should not be treated as orphanable primary transcripts unless they are explicitly tracked and cross-checked as trajectory artifacts.
Why this happens
isPrimarySessionTranscriptFileName(fileName) currently matches any non-archived *.jsonl, which incorrectly includes *.trajectory.jsonl.
Current matcher in dist/artifacts-Czkc6wYi.js:
function isPrimarySessionTranscriptFileName(fileName) {
if (fileName === "sessions.json") return false;
if (!fileName.endsWith(".jsonl")) return false;
return !isSessionArchiveArtifactName(fileName);
}
Doctor then builds orphan candidates from that matcher in dist/doctor-state-integrity-CLk7YYo-.js:
const orphanTranscriptPaths = fs.readdirSync(sessionsDir, { withFileTypes: true })
.filter((entry) => entry.isFile() && isPrimarySessionTranscriptFileName(entry.name))
.map((entry) => path.resolve(path.join(sessionsDir, entry.name)))
.filter((filePath) => !referencedTranscriptPaths.has(filePath));
But referencedTranscriptPaths is built from entry.sessionFile values from sessions.json, which point to <sessionId>.jsonl, not <sessionId>.trajectory.jsonl.
So the candidate set includes trajectory logs, while the reference set does not, creating false orphan reports.
Evidence
Live references in ~/.openclaw/agents/main/sessions/sessions.json included:
agent:main:upgrade → 69d8482d-2321-4cb0-bd7d-b59132b6f382.jsonl
agent:main:upgrade:heartbeat → 67553e3e-f24d-4018-bb38-a9abc43b9d23.jsonl
agent:main:cron:... / run entry → 2b549cee-6e59-454d-8bb6-94c08d20bcbb.jsonl
Corresponding trajectory files were flagged as orphan:
69d8482d-2321-4cb0-bd7d-b59132b6f382.trajectory.jsonl
67553e3e-f24d-4018-bb38-a9abc43b9d23.trajectory.jsonl
2b549cee-6e59-454d-8bb6-94c08d20bcbb.trajectory.jsonl
A live lock was also present:
69d8482d-2321-4cb0-bd7d-b59132b6f382.jsonl.lock
- lock pid matched the running gateway process at the time of inspection
Regression shape
I checked the 2026.4.21 package as well:
- the broad
isPrimarySessionTranscriptFileName() matcher already existed
- the orphan-detection logic already existed
- but I could not find trajectory artifact strings in that older dist bundle
So the likely regression shape is:
- the matcher was already too broad
2026.4.22 introduced *.trajectory.jsonl artifacts
- doctor now misclassifies them as orphan transcripts
Suggested fix
Narrow isPrimarySessionTranscriptFileName() so it excludes structured secondary artifacts such as:
For example, require a bare primary transcript filename shape, or explicitly exclude known suffix families before .jsonl.
Safety note
Users should avoid running openclaw doctor --fix on this finding until the matcher is corrected, because it may rename valid trajectory logs for live or still-referenced sessions.
Summary
On OpenClaw
2026.4.22,openclaw doctor --non-interactivefalsely reports live*.trajectory.jsonlsession artifacts as orphan transcript files and suggests archiving them via--fix, even when the owning sessions are still present insessions.jsonand one may have a live lock.Observed behavior
~/.openclaw/agents/main/sessions*.trajectory.jsonlopenclaw doctor --fixappears willing to rename valid trajectory logs to*.deleted.<timestamp>Example doctor output:
2b549cee-6e59-454d-8bb6-94c08d20bcbb.trajectory.jsonl67553e3e-f24d-4018-bb38-a9abc43b9d23.trajectory.jsonl69d8482d-2321-4cb0-bd7d-b59132b6f382.trajectory.jsonlExpected behavior
Doctor should only consider primary session transcript files as orphan candidates.
*.trajectory.jsonlshould not be treated as orphanable primary transcripts unless they are explicitly tracked and cross-checked as trajectory artifacts.Why this happens
isPrimarySessionTranscriptFileName(fileName)currently matches any non-archived*.jsonl, which incorrectly includes*.trajectory.jsonl.Current matcher in
dist/artifacts-Czkc6wYi.js:Doctor then builds orphan candidates from that matcher in
dist/doctor-state-integrity-CLk7YYo-.js:But
referencedTranscriptPathsis built fromentry.sessionFilevalues fromsessions.json, which point to<sessionId>.jsonl, not<sessionId>.trajectory.jsonl.So the candidate set includes trajectory logs, while the reference set does not, creating false orphan reports.
Evidence
Live references in
~/.openclaw/agents/main/sessions/sessions.jsonincluded:agent:main:upgrade→69d8482d-2321-4cb0-bd7d-b59132b6f382.jsonlagent:main:upgrade:heartbeat→67553e3e-f24d-4018-bb38-a9abc43b9d23.jsonlagent:main:cron:.../ run entry →2b549cee-6e59-454d-8bb6-94c08d20bcbb.jsonlCorresponding trajectory files were flagged as orphan:
69d8482d-2321-4cb0-bd7d-b59132b6f382.trajectory.jsonl67553e3e-f24d-4018-bb38-a9abc43b9d23.trajectory.jsonl2b549cee-6e59-454d-8bb6-94c08d20bcbb.trajectory.jsonlA live lock was also present:
69d8482d-2321-4cb0-bd7d-b59132b6f382.jsonl.lockRegression shape
I checked the
2026.4.21package as well:isPrimarySessionTranscriptFileName()matcher already existedSo the likely regression shape is:
2026.4.22introduced*.trajectory.jsonlartifactsSuggested fix
Narrow
isPrimarySessionTranscriptFileName()so it excludes structured secondary artifacts such as:*.trajectory.jsonlFor example, require a bare primary transcript filename shape, or explicitly exclude known suffix families before
.jsonl.Safety note
Users should avoid running
openclaw doctor --fixon this finding until the matcher is corrected, because it may rename valid trajectory logs for live or still-referenced sessions.