You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adds an additive, aggregate-only worker-evidence projection to hermes kanban stats --json so consumers can distinguish a recorded running row from a host-locally verified live worker.
The projection reports:
per-assignee and total running/live/stale/unverified row counts;
unassigned running totals;
the latest aggregate heartbeat timestamp per assignee.
A live worker requires both a host-local live PID and a recent heartbeat. Remote-host rows and insufficient evidence remain unverified. A stale heartbeat or a dead host-local PID is reported stale.
All aggregate queries are read from one SQLite snapshot so by_status.running, by_assignee[*].running, and the new activity totals cannot describe different moments during concurrent worker updates.
No task ID, title, body, result, comment, claim lock, worker PID, hostname, path, or email is added to the JSON contract.
Related Issue
No linked issue.
Type of Change
✨ New feature (non-breaking change that adds functionality)
✅ Tests (adding or improving test coverage)
Changes Made
Add activity_by_assignee and activity_totals to board stats.
Classify live, stale, and unverified evidence without promoting running alone to live.
Preserve existing by_status, by_assignee, age, and JSON behavior.
Hold one SQLite read snapshot across all aggregate queries.
Add behavioral coverage for live/dead/stale-heartbeat/remote/unassigned rows, privacy, legacy-count invariants, latest-heartbeat selection, and a concurrent writer race.
Tool descriptions/schemas: N/A; no model tool schema change.
Runtime compatibility evidence
Against the reviewed commit, the dashboard adapter reported connected freshness, 20/20 worker-evidence contract profiles, 0 fallback profiles, true evidence invariants, and no prohibited key paths. The clean upstream base reported 0/20 contract profiles and 20/20 safe legacy fallback profiles. Current runtime had zero running rows, so this evidence does not claim any worker was active.
The PR workflows are currently blocked with conclusion action_required, consistent with a first-time fork contribution. Could a maintainer approve and run the workflows? The focused Kanban DB/CLI suite is green (57 passed, 0 failed, 2 skipped), and the full-suite checklist remains intentionally unchecked until upstream CI reports.
Independent validation on current origin/main (165c889e5b4277b56dadd42949a4112c1e6175a6): the PR patch from 58b0944553 applies cleanly (including the kanban_db.py overlap), git diff --check passes, and the full targeted file passes through the repository runner:
I also reviewed the aggregate contract: remote-host rows remain unverified, local liveness requires both a live PID and a fresh heartbeat, task IDs/content/claim locks/PIDs are excluded, and all aggregate queries are held in one SQLite read snapshot. I did not find a counterexample in that scope.
Compatibility note for the worker-lifecycle work in #86609/#86610: their kanban_db.py patch hunks apply after this PR's patch without a content conflict. #86609 currently has a separate env_loader.py rebase conflict against today's main, unrelated to this PR.
AI code review — automated review for reference, author can ignore or act on any point.
feat(kanban): expose aggregate worker evidence
hermes_cli/kanban_db.py:53 — _pid_alive(int(pid)): if worker_pid ever holds non-numeric garbage (older rows, manual edits, recovered checkpoints), int(pid) raises ValueError and board_stats() crashes for the whole board. Guarding the conversion (try/except or an isdigit() check) would make the aggregation robust to dirty rows.
hermes_cli/kanban_db.py:24 — host-locality is decided by claim_lock.startswith(f"{_claimer_id().split(':', 1)[0]}:"). In container/VM setups where hosts share a hostname, a remote claim could be misclassified as host-local, flipping its evidence from "unverified" to "live"/"stale" incorrectly. It's a reasonable heuristic — a fallback that also requires the claimer id to match (not just the host prefix) or a comment documenting the assumption would harden it.
hermes_cli/kanban_db.py:111-126 — wrapping the aggregation in BEGIN/rollback gives a consistent read snapshot when the caller isn't already in a transaction; when it is (owns_snapshot=False) the halves read the caller's transaction snapshot, so consistency holds either way. Good.
The no-leak test (asserting task ids/titles/bodies never appear in the serialized payload) is exactly the right invariant for an aggregate endpoint that routers consume.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
comp/cronCron scheduler and job managementP3Low — cosmetic, nice to havetype/featureNew feature or request
4 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds an additive, aggregate-only worker-evidence projection to
hermes kanban stats --jsonso consumers can distinguish a recordedrunningrow from a host-locally verified live worker.The projection reports:
A live worker requires both a host-local live PID and a recent heartbeat. Remote-host rows and insufficient evidence remain unverified. A stale heartbeat or a dead host-local PID is reported stale.
All aggregate queries are read from one SQLite snapshot so
by_status.running,by_assignee[*].running, and the new activity totals cannot describe different moments during concurrent worker updates.No task ID, title, body, result, comment, claim lock, worker PID, hostname, path, or email is added to the JSON contract.
Related Issue
No linked issue.
Type of Change
Changes Made
activity_by_assigneeandactivity_totalsto board stats.runningalone to live.by_status,by_assignee, age, and JSON behavior.How to Test
scripts/run_tests.sh tests/hermes_cli/test_kanban_core_functionality.py tests/hermes_cli/test_kanban_db.py tests/hermes_cli/test_kanban_cli.pyruff check hermes_cli/kanban_db.py tests/hermes_cli/test_kanban_core_functionality.pyhermes kanban stats --jsonand verify the three count invariants documented above.Local result: 57 passed, 0 failed, 2 skipped; Ruff passed.
Checklist
Code
Documentation & Housekeeping
cli-config.yaml.example: N/A; no config keys.CONTRIBUTING.md/AGENTS.md: N/A; no workflow or architecture change._pid_alive.Runtime compatibility evidence
Against the reviewed commit, the dashboard adapter reported connected freshness, 20/20 worker-evidence contract profiles, 0 fallback profiles, true evidence invariants, and no prohibited key paths. The clean upstream base reported 0/20 contract profiles and 20/20 safe legacy fallback profiles. Current runtime had zero running rows, so this evidence does not claim any worker was active.