diff --git a/.gitignore b/.gitignore index a3bca706..66725dc6 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,9 @@ web/src/sample/ .env.local # Migration fixtures are fake homes of other agents; their .env files hold fake keys. !internal/migrate/testdata/**/.env +# OpenHuman keeps its memory in a SQLite file; the fixture needs it present so +# the planner reports the "memory.db is not imported" warning. +!internal/migrate/testdata/**/memory.db /tuishot # Local agent/editor tooling (not part of the project) @@ -32,7 +35,10 @@ web/src/sample/ .opencode/ .mcp.json opencode.json -AGENTS.md +# Anchored: the migration fixtures are fake homes of other agents and include +# AGENTS.md/CLAUDE.local.md files. An unanchored rule here once kept them out of +# every checkout, so the migrate golden tests failed on CI and nowhere local. +/AGENTS.md .worktrees/ .superpowers/ .codegraph/ diff --git a/internal/config/load.go b/internal/config/load.go index 2084c170..ed0629a6 100644 --- a/internal/config/load.go +++ b/internal/config/load.go @@ -15,6 +15,13 @@ import ( var ( mu sync.RWMutex loaded *Config + // loadedHome and loadedPath record the state directory and config file the + // cached config was read from. Load only serves the cache while both still + // match, so a process (or a test) that moves ANTARES_HOME gets its own + // configuration instead of the previous directory's — the stale port from + // one test's config used to leak into the next. + loadedHome string + loadedPath string // saveMu serialises writes to the config file. Concurrent saves (e.g. a // rapid run of model switches, or a model switch overlapping a raw config // save) would otherwise race on the temp file and the rename, corrupting @@ -25,8 +32,9 @@ var ( // Load reads defaults, merges the profile YAML file, then applies env overrides. // It is safe to call repeatedly; the result is cached until Reload or Save. func Load() (*Config, error) { + home, path := Home(), ConfigFile() mu.RLock() - if loaded != nil { + if loaded != nil && loadedHome == home && loadedPath == path { c := loaded.Clone() mu.RUnlock() return c, nil @@ -61,6 +69,7 @@ func Reload() (*Config, error) { mu.Lock() loaded = cfg.Clone() + loadedHome, loadedPath = Home(), path mu.Unlock() return cfg, nil } @@ -90,6 +99,7 @@ func SaveNormalizedAt(path string, cfg *Config) error { } mu.Lock() loaded = cfg.Clone() + loadedHome, loadedPath = Home(), path mu.Unlock() return nil } diff --git a/internal/migrate/testdata/golden/openclaw_plan.txt b/internal/migrate/testdata/golden/openclaw_plan.txt index cc681380..3c4fb95e 100644 --- a/internal/migrate/testdata/golden/openclaw_plan.txt +++ b/internal/migrate/testdata/golden/openclaw_plan.txt @@ -49,7 +49,7 @@ summary: 9 providers · model · soul · instructions · user profile · 3 memor [agents_md] agents_md:file "AGENTS.md" status=conflict selected=false detail: from AGENTS.md + BOOT.md · 68 chars reason: Antares already has a custom AGENTS.md (replace or append) - text: from=AGENTS.md + BOOT.md sha=8bff4f1541f6 + text: from=AGENTS.md + BOOT.md sha=c43c7bdeeac0 [user_md] user_md:file "USER.md" status=ready selected=true detail: from USER.md · 41 chars @@ -139,4 +139,4 @@ summary: 9 providers · model · soul · instructions · user profile · 3 memor [role] role:work "Work" status=ready selected=true detail: OpenClaw agent work - role: name=work title="Work" model=openai/gpt-5 prompt_sha=db747aabfa12 + role: name=work title="Work" model=openai/gpt-5 prompt_sha=632c27a4a321 diff --git a/internal/migrate/testdata/nanobot/home/.nanobot/workspace/AGENTS.md b/internal/migrate/testdata/nanobot/home/.nanobot/workspace/AGENTS.md new file mode 100644 index 00000000..7131bad6 --- /dev/null +++ b/internal/migrate/testdata/nanobot/home/.nanobot/workspace/AGENTS.md @@ -0,0 +1,5 @@ +# Instructions + +- Reply in the user's language. +- Keep answers short and clear. +- Ask before running any command. diff --git a/internal/migrate/testdata/nanobot/plan.golden b/internal/migrate/testdata/nanobot/plan.golden index c5129f69..1b774118 100644 --- a/internal/migrate/testdata/nanobot/plan.golden +++ b/internal/migrate/testdata/nanobot/plan.golden @@ -29,7 +29,7 @@ summary: 5 providers · model · soul · instructions · 3 memories · 2 skills [agents_md] agents_md:file "AGENTS.md" status=ready selected=true detail: from nanobot AGENTS.md · 113 chars - text: from=nanobot AGENTS.md sha=99814a105bc2 + text: from=nanobot AGENTS.md sha=503636a3a5dc [memory] memory:99e8d1ee7047 "The user's name is Eno." status=ready selected=true memory: scope=global key=the-user-s-name-is-eno tags=[import:nanobot user-information] diff --git a/internal/migrate/testdata/nanoclaw/v2/groups/main/CLAUDE.local.md b/internal/migrate/testdata/nanoclaw/v2/groups/main/CLAUDE.local.md new file mode 100644 index 00000000..1cb659a5 --- /dev/null +++ b/internal/migrate/testdata/nanoclaw/v2/groups/main/CLAUDE.local.md @@ -0,0 +1 @@ +Rina works at Example Corp. diff --git a/internal/migrate/testdata/openclaw/home/.openclaw/work-ws/AGENTS.md b/internal/migrate/testdata/openclaw/home/.openclaw/work-ws/AGENTS.md new file mode 100644 index 00000000..32895eb1 --- /dev/null +++ b/internal/migrate/testdata/openclaw/home/.openclaw/work-ws/AGENTS.md @@ -0,0 +1,3 @@ +# Work + +Reply briefly, and never miss a deadline. diff --git a/internal/migrate/testdata/openclaw/home/.openclaw/workspace/AGENTS.md b/internal/migrate/testdata/openclaw/home/.openclaw/workspace/AGENTS.md new file mode 100644 index 00000000..27ba5bd5 --- /dev/null +++ b/internal/migrate/testdata/openclaw/home/.openclaw/workspace/AGENTS.md @@ -0,0 +1,3 @@ +# Rules + +Always cite sources. Never guess. diff --git a/internal/migrate/testdata/openhuman/home/.openhuman/users/u_123/workspace/AGENTS.md b/internal/migrate/testdata/openhuman/home/.openhuman/users/u_123/workspace/AGENTS.md new file mode 100644 index 00000000..9e102a49 --- /dev/null +++ b/internal/migrate/testdata/openhuman/home/.openhuman/users/u_123/workspace/AGENTS.md @@ -0,0 +1,3 @@ +# Instructions + +Never guess at file paths. diff --git a/internal/migrate/testdata/openhuman/home/.openhuman/users/u_123/workspace/memory/memory.db b/internal/migrate/testdata/openhuman/home/.openhuman/users/u_123/workspace/memory/memory.db new file mode 100644 index 00000000..e69de29b diff --git a/internal/migrate/testdata/openhuman/plan.golden b/internal/migrate/testdata/openhuman/plan.golden index 93d9ef41..6922625c 100644 --- a/internal/migrate/testdata/openhuman/plan.golden +++ b/internal/migrate/testdata/openhuman/plan.golden @@ -29,7 +29,7 @@ warning: OpenHuman's memory database (memory/memory.db) is not imported; MEMORY. [agents_md] agents_md:file "AGENTS.md" status=ready selected=true detail: from AGENTS.md · 42 chars - text: from=AGENTS.md sha=fd6819395b8e + text: from=AGENTS.md sha=7fd3521d178e [user_md] user_md:file "USER.md" status=ready selected=true detail: from PROFILE.md · 71 chars diff --git a/internal/migrate/testdata/zeroclaw/plan_v3.golden b/internal/migrate/testdata/zeroclaw/plan_v3.golden index b346a248..87f635b0 100644 --- a/internal/migrate/testdata/zeroclaw/plan_v3.golden +++ b/internal/migrate/testdata/zeroclaw/plan_v3.golden @@ -27,7 +27,7 @@ warning: ZeroClaw is running — stop it before importing its chat channels, or [agents_md] agents_md:file "AGENTS.md" status=ready selected=true detail: from AGENTS.md · 80 chars - text: from=AGENTS.md sha=271cc46a7c77 + text: from=AGENTS.md sha=5cf54a5943bf [user_md] user_md:file "USER.md" status=ready selected=true detail: from USER.md · 48 chars @@ -102,4 +102,4 @@ warning: ZeroClaw is running — stop it before importing its chat channels, or [role] role:coder "coder" status=ready selected=true detail: ZeroClaw agent - role: name=coder title="coder" model=anthropic/claude-sonnet-4-5 prompt_sha=9faf3f252ee0 + role: name=coder title="coder" model=anthropic/claude-sonnet-4-5 prompt_sha=b854746dce1b diff --git a/internal/migrate/testdata/zeroclaw/v3/agents/coder/workspace/AGENTS.md b/internal/migrate/testdata/zeroclaw/v3/agents/coder/workspace/AGENTS.md new file mode 100644 index 00000000..763bd2eb --- /dev/null +++ b/internal/migrate/testdata/zeroclaw/v3/agents/coder/workspace/AGENTS.md @@ -0,0 +1,4 @@ +# Instructions + +- Write small commits. +- Test before you push. diff --git a/internal/migrate/testdata/zeroclaw/v3/agents/default/workspace/AGENTS.md b/internal/migrate/testdata/zeroclaw/v3/agents/default/workspace/AGENTS.md new file mode 100644 index 00000000..849fb623 --- /dev/null +++ b/internal/migrate/testdata/zeroclaw/v3/agents/default/workspace/AGENTS.md @@ -0,0 +1,5 @@ +# Instructions + +- Use metric units. +- Ask before you deploy. +- Keep a changelog.