Skip to content

emrg: a register still at its pre-rename name reads as an empty register to every in-package reader #2545

Closed

Description

@argszero

What was observed

The register of agents lives at ~/.emrg/agents.yml since the rename from projects.yml, and emrg.config.agents_file() is its one derivation. emrg.config.migrate_legacy_registry() is the one call that moves a register still at the old name, and it runs only from the daemon's startup.

That leaves a state the readers do not handle. migrate_legacy_registry is documented to answer False and leave the legacy file exactly where it is when the move cannot happen — a read-only home, a permission boundary, a concurrent caller that got there first. A checkout also runs ahead of the daemon that still holds the register at the old name. In both states agents_file() names a file that does not exist, and every in-package reader that asks only agents_file() reads an empty register while the real one sits one filename away.

Measured on a host in exactly that state (~/.emrg/agents.yml absent, ~/.emrg/projects.yml holding 34 entries):

reader answers what the answer costs
SubmitRantTool._registered_agent_names() [] submit_rant's "this agent name is not registered, candidates are …" warning is gated on if registered and …, so it never fires: a mis-spelled agent name is accepted with no candidates listed
scheduler._resolve_agent_path("emrg") None an agent name does not resolve to its path
scheduler._load_agent_config("emrg", …) {} a task template's {{ agent.<field> }} renders empty
file_policy.protected_paths() contains agents.yml, not projects.yml the register that is actually live is not on the sandbox's protected list

Every one of them degrades silently: each answers "nothing there" where the truth is "the register is at the other name", and no reading distinguishes the two.

Why the existing tests do not catch it

tests/test_submit_rant_tool.py pins the candidate reader against absent, malformed, unparseable and FIFO agents.yml files, and every one of those cases creates agents.yml in a temporary directory. No test creates the legacy name, so the state above is not reachable from the suite: the requirement "a register at the old name is still read" is named nowhere.

What the fix must satisfy

  • One reading of "where the register is", for readers. A reader asks for the register's read path; it is agents.yml when that file exists and the legacy name while that is the one that holds it. agents_file() itself must stay a pure path that opens and moves nothing — and the fallback must not live inside it, because migrate_legacy_registry takes agents_file() as its move target: a fallback there would make the target exist (it is the legacy file), so the migration would answer "already at the new name" on every host, for ever.
  • Reading never moves the file. Asking where the register is must not rename, create or delete anything: the migration stays the one operation that moves it, from the one process that owns it.
  • The new name governs when both exist, so a legacy file left behind by an older daemon cannot shadow the current register.
  • Writers keep writing the new name. This changes readers only.
  • A test names the state: with only the legacy name present, each reader above answers what the register says, and the legacy file is still at its own name afterwards.

Activity

  1. argszero commented on Oct 23, 2026

    @argszero
    OwnerAuthor

    Handled by #2546

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