From cc887149ce29e8d484b8bca631c7ab471ea4a812 Mon Sep 17 00:00:00 2001 From: argszero Date: Thu, 27 Aug 2026 09:40:03 +0800 Subject: [PATCH 1/2] =?UTF-8?q?emrg:=20list=5Ftasks=20=E2=80=94=20merge=20?= =?UTF-8?q?static=20task=20config=20into=20status=20(type/enabled/config/s?= =?UTF-8?q?andbox)=20for=20GUI=20tasks=20panel=20+=20edit=20form?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Agent.md | 2 +- emrg/server/scheduler.py | 16 +++++++++++++- tests/test_scheduler.py | 48 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/Agent.md b/Agent.md index 20824d7f..6dbf91ab 100644 --- a/Agent.md +++ b/Agent.md @@ -119,7 +119,7 @@ Community needs voiced in HN agent-UI discussions map directly to EMRG's design: pkill -f "emrg.server"; rm -f ~/.emrg/emrgd.token; python -m emrg ``` -Python: `uv run pytest tests/ -v` (1119) — import check: `uv run python -c "from emrg.client.app import run_client"` +Python: `uv run pytest tests/ -v` (1121) — import check: `uv run python -c "from emrg.client.app import run_client"` GUI: `cd emrg/gui && npm test` (89: 45 daemon_client + 20 conn-manager + 8 integration + 6 build-config + 7 gui-state + 3 preload-api) — syntax: `node --check main.js preload.js daemon_client.js` Renderer: `cd emrg/gui/renderer && npm run typecheck && npm test` (426: 5 snapshot-store + 9 utils + 3 ErrorBoundary + 2 App smoke + 11 commands + 4 copywriting + 11 i18n + 11 markdown + 15 transcript + 7 TranscriptView + 15 history + 22 composer + 14 Composer + 12 sidebar + 17 Sidebar + 9 fileTree + 9 FileTree + 16 resultPanel + 8 ResultPanel + 29 workspaceView + 8 WorkspaceView + 10 dialog + 6 Dialog + 9 ConfirmDialog + 9 RenameDialog + 10 dialogLists + 3 HelpDialog + 9 MemoryDialog + 6 SkillsDialog + 9 openSession + 6 WelcomeDialog + 8 OpenSessionDialog + 7 NewSessionDialog + 7 rewind + 8 RewindDialog + 7 GithubDeviceDialog + 12 daemonBridge + 6 DaemonBridgeProvider + 19 Shell + 15 DialogHost + 19 SettingsPanel + 4 vendorMarkdown) + `npm run build` → `renderer/dist/` CI: `uv run pytest` (ubuntu + **windows-2025 matrix** — Windows pytest 回归在 PR CI 即失败,v0.2.29 教训 #725) + GUI tests + **actionlint workflow lint** (`rhysd/actionlint@v1.7.12` gate, #444 — workflow 解析错误在 PR CI 即失败,如 `if:` secrets 上下文) diff --git a/emrg/server/scheduler.py b/emrg/server/scheduler.py index 32b1b949..da2c549a 100644 --- a/emrg/server/scheduler.py +++ b/emrg/server/scheduler.py @@ -1362,7 +1362,21 @@ def list_tasks(self) -> list[dict]: per_handler: list[str] = [] for handler in self._handlers: h_start = time.monotonic() - results.append(handler.status()) + status = handler.status() + # Task config enrichment (R2245): handler.status() exposes only + # runtime state — the GUI tasks panel + edit form need the task's + # static config (type/enabled/config/sandbox) to render type + # badges, enabled hints, project links, and prefill the edit form + # (previously undefined → GUI fell back to "evolution"/defaults). + # Merged from _handler_cfgs (pure in-memory — keeps list_tasks + # I/O-free per rant 2026-08-18T20:48:45). + cfg = self._handler_cfgs.get(handler.name) + if cfg: + status["type"] = cfg.get("type", "evolution") + status["enabled"] = cfg.get("enabled", True) + status["config"] = cfg.get("config", {}) + status["sandbox"] = cfg.get("sandbox") + results.append(status) per_handler.append(f"{handler.name}={1000 * (time.monotonic() - h_start):.1f}ms") elapsed_ms = 1000 * (time.monotonic() - start) if elapsed_ms > 200: diff --git a/tests/test_scheduler.py b/tests/test_scheduler.py index eb55e023..127a3e97 100644 --- a/tests/test_scheduler.py +++ b/tests/test_scheduler.py @@ -2181,6 +2181,54 @@ def slow_status(): assert handler.name in msgs, "per-handler breakdown must name the slow handler" +def test_list_tasks_includes_static_task_config(tmp_path): + """list_tasks must merge the task's static config (type/enabled/config/ + sandbox) into the runtime status — the GUI tasks panel renders type + badges + enabled hints and the edit form prefills from these fields; + without them type falls back to "evolution" and project/repo/sandbox are + lost (R2245 data-shape gap: handler.status() only exposes runtime state). + """ + from emrg.server.scheduler import TaskScheduler + + handler = _make_handler(tmp_path, name="journal", project="sci") + sched = TaskScheduler(InstanceIdentity()) + sched._handlers = [handler] + sched._handler_cfgs[handler.name] = { + "name": "journal", + "type": "journal", + "config": {"project": "sci", "repo": "argszero/sci"}, + "interval": 3600, + "enabled": False, + "sandbox": "read-only", + } + tasks = sched.list_tasks() + assert len(tasks) == 1 + row = tasks[0] + assert row["name"] == "journal" + assert row["type"] == "journal" + assert row["enabled"] is False + assert row["config"] == {"project": "sci", "repo": "argszero/sci"} + assert row["sandbox"] == "read-only" + # runtime fields must survive the merge + assert "running" in row and "interval" in row and row["interval"] == 60 + + +def test_list_tasks_without_cfg_leaves_status_untouched(tmp_path): + """A handler not present in _handler_cfgs (edge: hot-reload race) must not + be decorated — status fields stay as-is.""" + from emrg.server.scheduler import TaskScheduler + + handler = _make_handler(tmp_path, name="plain", project="emrg") + sched = TaskScheduler(InstanceIdentity()) + sched._handlers = [handler] + # no _handler_cfgs entry for this handler + tasks = sched.list_tasks() + assert len(tasks) == 1 + assert tasks[0]["name"] == "plain" + assert "type" not in tasks[0] + assert "config" not in tasks[0] + + # ── Task CRUD + hot reload + templates (rant 2026-08-12T18:23:15 P2) ── From bb043c3dfc96bab6d8d7a50a3aa7f918717e47ad Mon Sep 17 00:00:00 2001 From: EMRG Evolution Date: Thu, 27 Aug 2026 09:58:35 +0800 Subject: [PATCH 2/2] emrg: sync Agent.md Python test count to 1123 (list_tasks config enrichment adds 2 tests) --- Agent.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Agent.md b/Agent.md index 6dbf91ab..ce63178d 100644 --- a/Agent.md +++ b/Agent.md @@ -119,7 +119,7 @@ Community needs voiced in HN agent-UI discussions map directly to EMRG's design: pkill -f "emrg.server"; rm -f ~/.emrg/emrgd.token; python -m emrg ``` -Python: `uv run pytest tests/ -v` (1121) — import check: `uv run python -c "from emrg.client.app import run_client"` +Python: `uv run pytest tests/ -v` (1123) — import check: `uv run python -c "from emrg.client.app import run_client"` GUI: `cd emrg/gui && npm test` (89: 45 daemon_client + 20 conn-manager + 8 integration + 6 build-config + 7 gui-state + 3 preload-api) — syntax: `node --check main.js preload.js daemon_client.js` Renderer: `cd emrg/gui/renderer && npm run typecheck && npm test` (426: 5 snapshot-store + 9 utils + 3 ErrorBoundary + 2 App smoke + 11 commands + 4 copywriting + 11 i18n + 11 markdown + 15 transcript + 7 TranscriptView + 15 history + 22 composer + 14 Composer + 12 sidebar + 17 Sidebar + 9 fileTree + 9 FileTree + 16 resultPanel + 8 ResultPanel + 29 workspaceView + 8 WorkspaceView + 10 dialog + 6 Dialog + 9 ConfirmDialog + 9 RenameDialog + 10 dialogLists + 3 HelpDialog + 9 MemoryDialog + 6 SkillsDialog + 9 openSession + 6 WelcomeDialog + 8 OpenSessionDialog + 7 NewSessionDialog + 7 rewind + 8 RewindDialog + 7 GithubDeviceDialog + 12 daemonBridge + 6 DaemonBridgeProvider + 19 Shell + 15 DialogHost + 19 SettingsPanel + 4 vendorMarkdown) + `npm run build` → `renderer/dist/` CI: `uv run pytest` (ubuntu + **windows-2025 matrix** — Windows pytest 回归在 PR CI 即失败,v0.2.29 教训 #725) + GUI tests + **actionlint workflow lint** (`rhysd/actionlint@v1.7.12` gate, #444 — workflow 解析错误在 PR CI 即失败,如 `if:` secrets 上下文)