Skip to content

A session's directory has ten spellings and one rule #2473

Description

@argszero

A session's directory has ten spellings and one rule

What is observed, and where

A session's state lives in <cwd>/.emrg/sessions/<session_id>. Ten pieces of code build that path
for themselves. One of them is the rule — Session in emrg/session.py, which computes self._dir
and then fills it with meta.json, history.jsonl, memory/ and images/. The other nine are
copies:

  • emrg/session.py — Session.delete, which has an id and a cwd but no handle of its own.
  • emrg/server/daemon.py, five sites — delete_session; _get_or_create_session;
    _handle_resume_session's ghost check; and the two memory handlers, memories_list and
    memory_content, which each place a SessionMemoryStore inside it.
  • emrg/client/app.py, two sites — the paste and /image paths, which build
    <cwd>/.emrg/sessions/<id>/images to drop a clipboard image into.
  • emrg/gui/main.js, one site — the Electron main process builds the same images/ directory
    when the host pastes an image into the GUI, so the daemon finds it where it expects.

Two of the Python copies arrived with the delegation features (#2454, #2470), which build a
parent's directory to place a child's cwd inside it. The rest are older, and the JavaScript one is
the newest: it sits in another language, in another process, and no Python reading of the package
can see it. Each is correct today, and that is the problem: they agree, so nothing looks wrong, and
no behavioural test can see a copy that computes the right answer.

What is expected instead

One producer for the rule, and every reader going through it. Session owns what a session
directory is, so the function that computes it belongs beside it, and a caller that has an id and a
cwd without a handle — the daemon deriving a parent's directory, the client building its own
images/ subdirectory, Session.delete — should ask that same function.

The Electron main process cannot follow that rule, and the reason is structural: it shares a
filesystem with the daemon, not a runtime, so it cannot call a Python function. On that side the
requirement is weaker and different — the copy stays one copy, in one file, and a second one is
refused.

Concretely: a layout change (a per-project sessions root, a different separator, a nested namespace
for delegated children) must be a one-place edit in the package and a two-file edit counting the
client. Today both halves are search-and-hope, and every copy is silent if missed: a child cwd
simply points at a directory no Session ever wrote, a memory panel reads a store that does not
exist, and a pasted image lands where the daemon never looks. A test that compares the copies would
notice only that they still spell the same letters.

What the fix must satisfy

  • A module-level function in emrg/session.py returns <cwd>/.emrg/sessions/<id>.
  • Session.__init__ uses it, so the rule and the class cannot disagree.
  • Every other Python site above uses it instead of its own expression, with its existing callers and
    behaviour unchanged: a subagent's slot cwd, the boss's cwd and the clipboard image directory stay
    exactly where they are.
  • A guard makes an eleventh copy impossible to add quietly in the package, and it must survive a
    copy spelled with a different local name — scanning for one spelling guards one spelling, not the
    rule. Reading the syntax tree, not the text, is what buys that.
  • A second guard covers the half the first cannot reach: exactly one code site in the Electron client
    builds that path, counted with comments blanked so that prose about the path is not mistaken for a
    producer of it.
  • A scan that decides by walking a tree must compare each path against the root it walked from, not
    against the machine's absolute path: an ancestor directory named node_modules, .venv or
    __pycache__ otherwise silences the walk, and a guard that reports a clean reading of nothing is
    worse than no guard.
  • The sessions directory itself (without an id) is a different value with its own small set of
    sites; this issue is about the directory a session lives in, and does not claim it.
  • No behaviour change anywhere: this is one expression moved to one place, plus one guard on the
    side that cannot delegate.
  • The end-to-end guards that already pin the resulting paths keep passing unchanged
    (tests/test_boss_tool.py, tests/test_subagent_tool.py, tests/test_session.py).

Activity

  1. argszero commented on Oct 22, 2026

    @argszero
    OwnerAuthor

    Handled by #2474

  2. changed the title [-]emrg: the sessions directory is derived in two places, and only one of them is the rule[/-] [+]emrg: a session's directory has nine spellings and one rule[/+] on Oct 22, 2026
  3. changed the title [-]emrg: a session's directory has nine spellings and one rule[/-] [+]A session's directory has ten spellings and one rule[/+] on Oct 22, 2026
  4. pm25coder commented on Oct 22, 2026

    @pm25coder
    Collaborator

    Handled by #2494

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