gabriel / muse public
Open #78 Bug
filed by gabriel human · 15 days ago

muse agent-config's canonical source file is never tracked by Muse, defeating its own purpose

0 Anchors
Blast radius
Churn 30d
0 Proposals

muse agent-config's canonical source file is never tracked by Muse, defeating its own purpose

Background

The entire premise of muse agent-config is: one canonical, versioned source file per repo/workspace, from which any developer on any tool (Claude, Codex, Cursor, Windsurf) can generate their adapter file via muse agent-config sync — enabling a new developer to clone the repo and get the right config for their setup automatically.

That promise is broken. The canonical source lives at .muse/agent.md (muse/core/paths.py::agent_md_path()), and .muse/ is unconditionally excluded from every snapshot:

# muse/plugins/code/plugin.py:157-166
# Directories that are never versioned regardless of .museignore.
# These are implicit ignores that apply to all code repositories.
_ALWAYS_IGNORE_DIRS: frozenset[str] = frozenset({
    ".git",
    ".muse",
    ...
})

Confirmed live, not assumed: editing ~/ecosystem/.muse/agent.md (the workspace-level rules file) produces zero change in muse status, and the file is absent from muse ls-files entirely. CLAUDE.md at the repo root is tracked, but it's just a one-line @.muse/agent.md include — the actual rules content is local-only and would not survive a fresh clone.

This is not a workspace misconfiguration — agent_md_path() is a single, hardcoded function every agent-config subcommand (init, sync, read, status, inspect) routes through, so every user of Muse who has ever run muse agent-config init has the identical problem: their canonical config only exists on the machine it was created on.

Goal

The canonical agent-config source file must be a normal tracked file — living outside .muse/ entirely — so it survives clone/push/pull like any other repo content, restoring the actual promise: clone, run muse agent-config sync, get your tool's adapter.

Decided (2026-07-07): the new canonical filename is .museagent.md at the repo/workspace root — matches the existing .museignore/.museattributes dotfile naming convention, and avoids the near-collision risk of AGENT.md vs. the existing AGENTS.md (the Codex adapter's generated output, not the source).

"Done" means: agent_md_path() returns <root>/.museagent.md; every existing .muse/agent.md in this workspace (muse, musehub, ~/ecosystem workspace root, and any other member repo that has one) is migrated; generated adapter files reference @.museagent.md not @.muse/agent.md; a one-time forward migration (not a permanent fallback) handles repos that still have the old file when init/sync runs.

Out of Scope

  • Any change to what content agent.md/.museagent.md holds — this is a location fix, not a content redesign.
  • Per-tool adapter rendering logic beyond the path string itself (the _render_adapter templates stay the same, just fed a different path).
  • Retroactively renaming the concept from "agent.md" to something else in prose/docstrings beyond what's needed for the new filename to make sense.

Phases

Phase 1 — Red: pin the bug and the target behavior

  • ACFG_01agent_md_path(root) currently returns a path whose parent directory name is .muse — assert this is no longer true after the fix (returns <root>/.museagent.md). Must fail against current code.
  • ACFG_02 — After muse agent-config init in a fresh repo, the created file must not be excluded by _ALWAYS_IGNORE_DIRS / must appear in muse ls-files after muse code add . + commit. Real integration test, not just a path-string assertion — this is the actual bug.
  • ACFG_03 — Generated CLAUDE.md content contains @.museagent.md, not @.muse/agent.md, for both standalone and workspace-member scope (the latter also covers the workspace-root relative path, ../.museagent.md).

Deliverable: all three red against current code, confirmed before any Phase 2 change.

Phase 2 — Fix: move the canonical path, migrate existing files

  • Change agent_md_path() in muse/core/paths.py to return root / ".museagent.md".
  • Update every literal .muse/agent.md / {rel}/.muse/agent.md string in muse/cli/commands/agent_config.py (path-building logic, docstrings, help text) to .museagent.md / {rel}/.museagent.md.
  • One-time forward migration: if init or sync finds .muse/agent.md present and .museagent.md absent, move the content across (not copy — the old location must not linger, per this workspace's "no legacy" convention) and log what happened. This is a migration step, not a permanent fallback path — no dual-read logic survives after the move.
  • Update _WORKSPACE_ROOT_TEMPLATE / _WORKSPACE_MEMBER_TEMPLATE / _STANDALONE_TEMPLATE if they reference the old path internally.

Deliverable: ACFG_01-03 green.

Phase 3 — Migrate this workspace's existing files

  • Run the migration (via muse agent-config sync or manually) in muse, musehub, ~/ecosystem (workspace root), and any other member repo with an existing .muse/agent.md.
  • Commit each migrated .museagent.md — verify with muse ls-files that it's genuinely tracked this time, not just present on disk.
  • Regenerate all adapters (muse agent-config sync --force) so every CLAUDE.md/AGENTS.md references @.museagent.md.

Deliverable: ACFG_04 — a fresh muse clone of each affected repo has .museagent.md present and correct, with no manual agent-config init required.

Phase 4 — Regression sweep

  • Full tests/test_cmd_agent_config.py and tests/test_agent_config_envelope.py green — expect many existing assertions to need updating from .muse/agent.md literals to .museagent.md, not just the new tests passing.
  • muse code test --json for downstream impact.
  • grep -rn '\.muse/agent\.md' muse/ (excluding this ticket's own historical references) returns zero remaining hits in source or tests.

Deliverable: zero regressions, zero remaining old-path references.


Acceptance Criteria

  • agent_md_path() never returns a path inside .muse/.
  • A fresh muse agent-config init + commit produces a file that survives muse clone — proven by an integration test, not inferred.
  • Every existing .muse/agent.md in this workspace has been migrated and is now genuinely tracked.
  • Zero remaining .muse/agent.md references in muse/'s source, tests, or docstrings.
  • docs/agent-guide.md and every workspace CLAUDE.md/AGENTS.md reflect the new path.

Implementation Order

Phase 1 → Phase 2 → Phase 3 → Phase 4. Phase 3 (migrating this workspace's real files) cannot start until Phase 2's migration logic exists and is tested — don't hand-migrate files before the tool that's supposed to do it is proven correct.

Activity1
gabriel opened this issue 15 days ago
gabriel 15 days ago

Phases 1-3 (migration tool + auto-migrate on init/sync + this workspace's muse and musehub repos) landed on dev/main tonight, part of v0.2.0-nightly.3. Leaving open — the workspace root's own CLAUDE.md still resolves via .muse/agent.md, and Phase 4 (docs/workspace-wide sweep) hasn't been verified complete across every member repo.