Skip to content

graphcode reap aborts on every workspace since #308: the Mailroom sidecar is read as a corrupt graph #315

Description

@scgopi

graphcode reap has been dead since #308 shipped in 0.1.64-beta3 today. It aborts on every workspace, permanently, and it fails closed behind a message that reads as caution rather than breakage — so it is unlikely to be reported by whoever hits it.

$ graphcode reap --dry-run
graphcode: a graph or terminal layout failed to decode — refusing to guess which sessions it owns

This is a stable blocker. reap is the on-demand recovery tool for a machine that has run out of PTYs (#197). It is broken precisely when someone needs it most.

Cause

OrphanedSessionReaper.liveSessionIDs treats every .json under a workspace's projects/ directory as a LoopGraph, and returns nil — refusing to reap — if any one of them fails to decode:

let graphFiles = (try? FileManager.default.contentsOfDirectory(at: projects, ...))?
  .filter { $0.pathExtension == "json" } ?? []
for file in graphFiles {
  guard let data = try? Data(contentsOf: file),
    let graph = try? JSONDecoder().decode(LoopGraph.self, from: data)
  else { return nil }
  ...
}

That assumption was true until #307/#308 moved the Mailroom out of the graph file and into <project>.mailroom.json in that same directory. The room file is a JSON array of posts, so it can never decode as a LoopGraph, and every reap now bails.

Refusing to guess is the right behaviour for a genuinely damaged graph — a graph this build cannot read still owns sessions, and reaping them would be a sweep rather than a reap. The defect is that a sidecar is not a damaged graph.

Evidence

Reproduced on 0.1.64-beta5 (build 255). To rule out a coincidentally corrupt graph, every .json under projects/ in all four workspaces on this machine (~/.graphcode, ~/.graphcode-opencode, ~/.graphcode-client, and the current override) was decoded individually:

Workspace projects/*.json Decodes as a graph
~/.graphcode 16 16
~/.graphcode-opencode 3 2
~/.graphcode-client 4 4

The single exception is _Volumes_SCG_wd_graphcode.mailroom.json — a JSON array of 386 posts. It is the only non-graph .json in any workspace, so it is the cause and not a coincidence.

The abort is also workspace-independent: liveSessionIDs scans every discovered workspace, so one room file anywhere disables reap everywhere, including from a support dir that has no room file of its own. Confirmed by running reap --dry-run against an isolated GRAPHCODE_SUPPORT_DIR holding only a valid graph — it still aborted.

Blast radius

  • Fails closed: nothing is killed, no data is lost. The tool is simply unavailable.
  • Workspace.contents() has the same "every .json in projects/ is a graph" assumption but continues instead of bailing, so it is not user-visible today — it is the next place this bites.

Fix direction

Not a filename blocklist in the reaper — that breaks again the next time a sidecar is added. The rule should be positive and owned by ProjectPersistence, which mints both names, and it must keep failing closed for a file that is genuinely corrupt.

Regression from #308 (11e33a3), shipped in 0.1.64-beta3.

Found while verifying #307's fix (mailroom split + GraphWriter) on beta5.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions