Skip to content

doctor falsely flags live *.trajectory.jsonl files as orphan transcripts #70680

@editbyjunior

Description

@editbyjunior

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:upgrade69d8482d-2321-4cb0-bd7d-b59132b6f382.jsonl
  • agent:main:upgrade:heartbeat67553e3e-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:

  1. the matcher was already too broad
  2. 2026.4.22 introduced *.trajectory.jsonl artifacts
  3. doctor now misclassifies them as orphan transcripts

Suggested fix

Narrow isPrimarySessionTranscriptFileName() so it excludes structured secondary artifacts such as:

  • *.trajectory.jsonl

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions