Skip to content

emrg: evolution workspace self-heal — clone on demand + projects/tasks bootstrap (rant 20:42) - #489

Merged
argszero merged 2 commits into
masterfrom
feature/evolution-workspace-selfheal
Aug 6, 2026
Merged

emrg: evolution workspace self-heal — clone on demand + projects/tasks bootstrap (rant 20:42)#489
argszero merged 2 commits into
masterfrom
feature/evolution-workspace-selfheal

Conversation

@argszero

@argszero argszero commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Summary

Self-heal for the evolution workspace on packaged installs (rant 2026-08-06T20:42:05, 方案 C). Packaged installs run the daemon from ~/.emrg/install/source/emrg — a .git-less source snapshot — so the evolution task cannot commit/push/PR. This PR makes the evolution workspace bootstrap itself on demand.

Changes

emrg/server/scheduler.py

EvolutionHandler._ensure_evolution_workspace() — called at the start of every evolution cycle:

  • Dev machine (resolved source_dir is a real writable git repo) → untouched, no clone
  • Otherwise → clone EMRG into ~/.emrg/evolution/emrg/:
    • Repo URL: install-info.json repo field, falling back to the built-in https://github.com/argszero/emrg.git
    • Aligns to the installed release: reads ~/.emrg/install/version.txt (e.g. 0.2.7) and checks out tag v0.2.7 if present (via git checkout -B master <tag> so evolution's branch-from-master flow still works), else stays on master
    • Sets git identity if missing (GIT_AUTHOR_NAME/GIT_AUTHOR_EMAIL env, defaults EMRG Evolution <emrg@argszero.dev>)
  • Clone failure (no network) → logs the reason and skips the cycle; GUI unaffected
  • Idempotent: repeated cycles don't re-clone

EvolutionHandler._ensure_project_entry() — self-heals projects.yml: adds/updates the emrg entry pointing at the evolution workspace (idempotent).

TaskScheduler._ensure_self_evolution_task() — at load_and_start(): if tasks.yml has no evolution task with config.project == emrg, appends emrg-task (interval 60, enabled). This runs at the scheduler level because a missing task means no EvolutionHandler is ever created — the handler-level self-heal alone could never fire.

Verification

  • 5 new unit tests: task bootstrap when missing, idempotency, dev-repo untouched (real git repo), clone+align+projects.yml self-heal, clone-failure skip
  • 5 existing load_and_start tests updated for the new bootstrap behavior
  • Full suite: 478 passed (was 473)
  • uv run python -c "from emrg.client.app import run_client" + emrg --help OK

Acceptance mapping

  • ✅ clean packaged install → cycle clones + aligns + bootstraps projects.yml/tasks.yml
  • ✅ dev machine unaffected (real git repo detected, used as-is)
  • ✅ clone failure → skip + log, GUI unaffected
  • ✅ idempotent (repeat cycles don't re-clone/re-add)
  • ✅ pytest full green

EMRG Evolution added 2 commits August 6, 2026 20:48
…s bootstrap (rant 20:42)

Packaged installs run the daemon from a .git-less source snapshot, so
evolution cannot commit/push/PR. Per 方案 C:

- EvolutionHandler._ensure_evolution_workspace() at each cycle start:
  - dev machine (source_dir is a real git repo) → untouched
  - otherwise clone EMRG into ~/.emrg/evolution/emrg/ (repo URL from
    install-info.json 'repo' field, fallback built-in default), align to
    the installed release tag (v<version.txt>, fallback master), set git
    identity if missing (GIT_AUTHOR_NAME/EMAIL, defaults EMRG Evolution)
  - clone failure (no network) → log + skip cycle (GUI unaffected)
  - projects.yml self-heal: add/update emrg entry → evolution workspace
- TaskScheduler._ensure_self_evolution_task() at load_and_start():
  - tasks.yml missing emrg evolution task → append emrg-task
    (type=evolution, config.project=emrg, interval=60, enabled)
  - idempotent; runs at scheduler level because a missing task means no
    handler is ever started

Tests: 5 new (task bootstrap, idempotency, dev-repo untouched, clone+align
+projects self-heal, clone-failure skip) + 5 updated for new behavior.
Full suite: 478 passed.
…mrg/install)

test_ensure_evolution_workspace_clones_and_aligns read the REAL
~/.emrg/install/version.txt via Path.home() — passed on dev hosts but
failed in CI (no ~/.emrg/install → no tag → no checkout). Patch
pathlib.Path.home to tmp_path so the test is self-contained.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle 20260806-204218. Verified: (1) workspace self-heal gated to the emrg self-task (config.project==emrg, repo==emrg); dev machine with a real git repo is untouched (tested with an actual git repo); (2) clone → tag alignment (v<version.txt> via git checkout -B master, keeps branch flow) → git identity fallback (GIT_AUTHOR_NAME/EMAIL → EMRG Evolution) → projects.yml self-heal, all idempotent; (3) clone failure returns False and skips the cycle without affecting GUI; (4) tasks.yml bootstrap lives in TaskScheduler.load_and_start() — correct, because a missing emrg-task means no handler would ever start; (5) first CI run caught a non-hermetic test (Path.home version.txt) — fixed by patching home, CI green 478 passed. Rant 20:42 acceptance items map 1:1.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle 20260806-205521. Second vote. Re-checked against master 91b03c9 (#487 merged GUI P2 — no overlap with scheduler.py; merge-base clean). CI green (run 31103284600). Self-heal wiring verified: _ensure_evolution_workspace() gated to emrg task, clone-failure skip, _ensure_self_evolution_task() idempotent. Ready to merge after one more LGTM.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle 20260806-2056. Independently re-verified: (1) _ensure_evolution_workspace gating is correct (only emrg self-task, paper/open-source/promote pass through), dev-machine path untouched when _is_usable_git_repo is true; (2) clone → _align_to_installed_version (checkout -B master keeps branch flow) → _ensure_git_identity (env fallback to EMRG Evolution) → _ensure_project_entry (idempotent, atomic_write_yaml); (3) non-git existing dir → skip + log to avoid data loss; (4) _ensure_self_evolution_task in TaskScheduler.load_and_start is the right layer — no handler exists without the task; (5) tests: 5 new unit tests incl. clone-failure and idempotency, hermetic version.txt test patches Path.home — 478 passed locally. Rant 20:42 acceptance items map 1:1.

@argszero
argszero merged commit 6ade0aa into master Aug 6, 2026
1 check passed
argszero added a commit that referenced this pull request Aug 6, 2026
…elf-heal (rant 20:42) (#490)

_cache_tool_paths now also writes 'repo' = https://github.com/argszero/emrg.git
alongside git_path/gh_path. Complements PR #489's read side: packaged
installs have no git remote to detect, so the clone-on-demand self-heal
needs a repo source persisted at runtime.

2 new tests (repo field written, existing fields preserved).

Co-authored-by: EMRG Evolution <emrg@argszero.dev>
argszero added a commit that referenced this pull request Aug 6, 2026
* emrg: persist repo URL in install-info.json for evolution workspace self-heal (rant 20:42)

_cache_tool_paths now also writes 'repo' = https://github.com/argszero/emrg.git
alongside git_path/gh_path. Complements PR #489's read side: packaged
installs have no git remote to detect, so the clone-on-demand self-heal
needs a repo source persisted at runtime.

2 new tests (repo field written, existing fields preserved).

* emrg: GUI / 指令 P3 — 模型/记忆/技能类指令(/model /memory /skills,rant 19:44)

Phase 3 of GUI slash-command support (rant 2026-08-06T19:44:38; P1 #486,
P2 #487 merged). Opens /model /memory /skills in the GUI:

- /model → triggers the existing model switcher (click .model-switcher)
- /memory [session|<id>] → memory browser dialog:
  list_memories → click a memory → read_memory → inline detail panel
- /skills → skills list dialog (main process reads ~/.emrg/skills and
  <projectDir>/.emrg/skills frontmatter; daemon has no skills protocol,
  mirrors TUI's local load_skills)

main.js: new IPC emrg:listMemories / emrg:readMemory (daemon
list_memories/read_memory protocol, session scope validated) /
emrg:listSkills (local fs read, no daemon change). preload.js exposes
them. index.html: memory-dialog + skills-dialog. components.css:
.memory-detail styles. commands.js phase comments updated.

Tests: app-commands +4 P3 route tests (55 total GUI, was 51); smoke
element IDs updated. pytest 475 passed; import + --help OK.

---------

Co-authored-by: EMRG Evolution <emrg@argszero.dev>
argszero added a commit that referenced this pull request Aug 6, 2026
Version bump 0.2.7 → 0.2.8 across all 6 version sources
(pyproject.toml / emrg/__init__.py / make-installer.sh /
build-runtime.sh / gui/package.json / uv.lock). Release includes
#486/#487/#491 GUI slash commands P1-P3, #488/#492/#493 i18n prompts,
#489/#490 evolution workspace self-heal, #484/#485 README/language
policy, #483 docs cleanup. test_version_sync all green.

Co-authored-by: EMRG Evolution <emrg@argszero.dev>
@argszero
argszero deleted the feature/evolution-workspace-selfheal branch August 6, 2026 15:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant