Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ Community needs voiced in HN agent-UI discussions map directly to EMRG's design:
pkill -f "emrg.server"; rm -f ~/.emrg/emrgd.port; python -m emrg
```

Python: `uv run pytest tests/ -v` (572) — import check: `uv run python -c "from emrg.client.app import run_client"`
Python: `uv run pytest tests/ -v` (573) — import check: `uv run python -c "from emrg.client.app import run_client"`
GUI: `cd emrg/gui && npm test` (93: 22 daemon_client + 22 app-commands + 24 renderer smoke + 15 i18n + 7 integration + 3 commands) — syntax: `node --check main.js preload.js daemon_client.js renderer/js/*.js`
CI: `uv run pytest` + GUI tests + **actionlint workflow lint** (`rhysd/actionlint@v1.7.12` gate, #444 — workflow 解析错误在 PR CI 即失败,如 `if:` secrets 上下文)
Re-trigger: `scripts/re-trigger-ci.sh [branch]` (workflow_dispatch, #527 — 替代空 commit 重触发:Actions outage 会整段丢弃 push 事件,dispatch 走 API 路径不受影响)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ EMRG doesn't just keep up — it catches up on its own.
git clone https://github.com/argszero/emrg.git
cd emrg
uv sync # install deps
uv run pytest tests/ -v # run tests (currently 572 items)
uv run pytest tests/ -v # run tests (currently 573 items)
uv run python -m emrg # launch TUI
# CI includes actionlint workflow gate (#444): workflow parse errors fail PR CI

Expand Down
25 changes: 22 additions & 3 deletions emrg/server/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,25 @@ async def serve(self) -> None:
except OSError:
pass

def _evolution_count(self) -> int:
"""Total completed evolution cycles across scheduler handlers.

The daemon's own ``self.evolutions`` list is a legacy from the
pre-scheduler BackgroundThread design (#95) and is never appended;
the scheduler's handlers own the real per-cycle logs. Aggregate from
the scheduler, falling back to the legacy list only when the
scheduler is unavailable (e.g. test harnesses mock it away).
"""
sched = getattr(self, "_scheduler", None)
if sched is not None:
try:
total = sched.total_evolutions()
if isinstance(total, int):
return total
except Exception:
pass
return len(self.evolutions)

async def _handle_client(self, ws) -> None:
"""Handle a single WebSocket client connection.

Expand Down Expand Up @@ -907,7 +926,7 @@ async def _process_message(
"branch_id": self.identity.branch_id,
},
uptime_seconds=max(0, elapsed),
evolution_count=len(self.evolutions),
evolution_count=self._evolution_count(),
)
await self._send(ws, {
"type": "pong",
Expand Down Expand Up @@ -1165,13 +1184,13 @@ async def _process_message(
continue
await self._send(ws, {
"type": "evolution_summary",
"count": len(self.evolutions),
"count": self._evolution_count(),
"recent": recent,
})
except OSError:
await self._send(ws, {
"type": "evolution_summary",
"count": len(self.evolutions),
"count": self._evolution_count(),
"recent": [],
})

Expand Down
4 changes: 4 additions & 0 deletions emrg/server/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,10 @@ def list_tasks(self) -> list[dict]:
"""Return status for all running handlers."""
return [handler.status() for handler in self._handlers]

def total_evolutions(self) -> int:
"""Total completed evolution cycles across all running handlers."""
return sum(len(handler.evolutions) for handler in self._handlers)

async def wait_all(self) -> None:
"""Wait for all handler coroutines to finish (after cancel)."""
for coro in self._coros:
Expand Down
17 changes: 17 additions & 0 deletions tests/test_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,23 @@ def test_evolution_handler_default_owner():
assert handler._repo_url == "https://github.com/argszero/emrg.git"


def test_task_scheduler_total_evolutions():
"""total_evolutions sums per-handler evolution log counts."""
from emrg.protocol import EvolutionLog

sched = TaskScheduler(InstanceIdentity())
h1 = EvolutionHandler(name="a", config={}, interval=60, identity=InstanceIdentity())
h2 = EvolutionHandler(name="b", config={}, interval=60, identity=InstanceIdentity())
sched._handlers = [h1, h2]

assert sched.total_evolutions() == 0
h1.evolutions.append(EvolutionLog(timestamp="t1"))
h1.evolutions.append(EvolutionLog(timestamp="t2"))
assert sched.total_evolutions() == 2
h2.evolutions.append(EvolutionLog(timestamp="t3"))
assert sched.total_evolutions() == 3


def test_paper_template_renders_with_context():
"""paper_prompt.md renders without Jinja2 errors (seq/uptime placeholders)."""
import jinja2
Expand Down
Loading