Skip to content

fix(cron): record no_agent runs as sessions so they show in run history - #62587

Open
yingliang-zhang wants to merge 1 commit into
NousResearch:mainfrom
yingliang-zhang:fix/cron-no-agent-run-sessions-v2
Open

fix(cron): record no_agent runs as sessions so they show in run history#62587
yingliang-zhang wants to merge 1 commit into
NousResearch:mainfrom
yingliang-zhang:fix/cron-no-agent-run-sessions-v2

Conversation

@yingliang-zhang

Copy link
Copy Markdown
Contributor

Problem

no_agent: true cron jobs (script-only watchdogs) create zero feedback when manually triggered from the Desktop GUI — no running indicator, no run record in Run History. The script executes and output files are written, but without a session row in state.db the GUI has nothing to display.

Root Cause

In cron/scheduler.py, the no_agent branch short-circuits before SessionDB is ever touched. No create_session() or append_message() call means the run is invisible to the Desktop's session-based Run History.

Fix

Create a cron_{job_id}_{timestamp} session row in the no_agent branch, mirroring what the agent path does:

  1. SessionDB.create_session(session_id, source="cron") — creates the row
  2. SessionDB.append_message(session_id, "user", "no_agent script: {path}") — seeds the preview
  3. SessionDB.append_message(session_id, "assistant", run_doc) — records the output on completion

This is the same pattern already used by the agent path. The no_agent cost contract (no LLM tokens) is preserved — this only adds DB bookkeeping.

History

This is the third submission of the same fix:

The fix has been confirmed effective by 3 independent users: AIalliAI, rebootcrab-blip, and yingliang-zhang.

Test

  • 237 tests passed across test_cron_no_agent.py (114) and test_scheduler.py (123), 0 failed
  • Includes regression tests verifying session row creation and message persistence for no_agent runs

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/cron Cron scheduler and job management labels Jul 11, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for tracing the missing session-backed history path. The gap is real: current main's no_agent branch returns before the SessionDB import at cron/scheduler.py:2514-2623, while /api/cron/jobs/{id}/runs reads cron session rows in hermes_cli/web_server.py:10188-10230.

Problems

  • The new SessionDB() initialization in this branch reverses commit 2008f5421, which deliberately moved SessionDB below the no_agent return path so pure script ticks do not pay the DB-open/agent-machinery cost. This is a design-contract conflict, not just bookkeeping.
  • The added tests cover terminal records, but not the claimed in-flight indicator. They should observe the run-history endpoint while a script is still blocked.

Suggested changes

  • Preserve the no-agent no-SessionDB contract, or obtain an explicit decision to change it before wiring state.db here.
  • If session-backed history is retained, add a blocked-script lifecycle test that verifies an unfinished active row before completion.

Automated hermes-sweeper review.

Comment thread cron/scheduler.py Outdated
@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 11, 2026
@teknium1 teknium1 added the area/sessions Session lifecycle, resume, persistence, history label Jul 19, 2026
@jeff-mettel

Copy link
Copy Markdown
Contributor

This PR overlaps with two other open PRs for the same defect (desktop run history shows "No runs yet" for no_agent jobs — #62341, #61031, #44080):

PR opened approach
#61403 2026-07-09 read-side: synthesize run rows from cron/output/<job_id>/*.md + last_run_at/last_status when no sessions exist
#62247 2026-07-10 write-side: record all outcomes (success, failure, silent) as sessions, created pre-script for a live is_active indicator; also keeps cron sessions out of the sidebar keep-set
#62587 (this) 2026-07-11 write-side: record successful visible runs only, post-completion

One behavioral note on this diff: _record_visible_run is invoked only on the success-with-stdout path — the script failed, wakeAgent=false, and empty-stdout branches return without recording. A job whose script is failing therefore still shows "No runs yet", which is the state where run history matters most. #62247 records those branches; whether silent ticks should be recorded is a real design question (a 5-minute watchdog writes ~288 rows/day), so the difference may be intentional — stating it so the overlap is decidable.

Closed precursors for context: #44087 (2026-06-11, earliest write-side implementation, closed "superseded/conflicting" in a cleanup sweep), #53692 (closed as duplicate of #44087), #66954 (closed without verdict).

Resolution options: consolidate on one write-side PR covering all outcomes, take the read-side fallback (which also surfaces pre-existing output docs retroactively), or deliberately layer both. Flagging so the three authors and maintainers can decide once rather than three PRs iterating independently.


Filed by an AI agent (Claude Fable 5) operating autonomously on @jeff-mettel's behalf. PR diffs read programmatically and code references verified against main at 126ff7071 before posting.

@yingliang-zhang

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough triage, @jeff-mettel — the overlap table is accurate and the behavioral note is a fair characterization.

On the failure/silent-branch gap:

The omission is deliberate, and the PR documents the tradeoff in the updated comment block: silent and failed ticks retain the zero-SessionDB fast path so a 5-minute watchdog doesn't write ~288 rows/day of no-op sessions. The test test_run_job_no_agent_fast_paths_do_not_open_session_db explicitly asserts SessionDB is never constructed on those paths.

That said, the point about a persistently failing script still showing "No runs yet" is well-taken — that's the state where run history matters most. I'm open to extending _record_visible_run to cover the failure branch as a follow-up if maintainers prefer that over the read-side fallback in #61403. The change is small: call _record_visible_run with the error text before the early return on the script-failure path, guarded by the same lazy-construct pattern so the fast-path contract holds for empty-stdout and wakeAgent=false ticks.

On consolidation:

I'd lean toward keeping this PR as the minimal write-side fix (success-only, post-completion) and layering failure-branch coverage as either an expansion here or in #62247, rather than consolidating both write-side PRs into one — the recording strategies differ enough (post-completion vs. pre-script is_active indicator) that merging them would require redesigning the session lifecycle. Happy to coordinate with the other authors on whichever direction maintainers prefer.

@yingliang-zhang
yingliang-zhang force-pushed the fix/cron-no-agent-run-sessions-v2 branch 2 times, most recently from 0d595ee to 5805ef1 Compare August 8, 2026 04:11
@yingliang-zhang
yingliang-zhang force-pushed the fix/cron-no-agent-run-sessions-v2 branch 4 times, most recently from f7eedbe to c706e9c Compare August 17, 2026 00:54
@yingliang-zhang
yingliang-zhang requested a review from a team August 17, 2026 00:54
@yingliang-zhang
yingliang-zhang force-pushed the fix/cron-no-agent-run-sessions-v2 branch 3 times, most recently from 47862b2 to 441dccd Compare August 19, 2026 03:16
no_agent cron jobs short-circuit run_job() before any SessionDB work,
so they never produce the cron_{job_id}_{timestamp} session row that the
run-history endpoint (GET /api/cron/jobs/{id}/runs, backed by
SessionDB.list_cron_job_runs) is built from. Manually triggering such a
job from the Desktop GUI gives zero feedback: no running indicator, no
run record, no output — the script runs fine, the GUI just can't see it.

Fix: in the no_agent branch of run_job(), create the run session
(cron_{job_id}_{ts}, source='cron') BEFORE executing the script so the
runs endpoint's is_active computation yields a running indicator for
in-flight manual triggers. After execution, persist the outcome doc as
an assistant message, title the session, and end_session. Covers all
four exit paths: success, script failure, empty-stdout silent run, and
wakeAgent=false silent run.

Best-effort: a missing/broken state store degrades to the old no-record
behaviour and never blocks the script run. The no_agent cost contract
is preserved — run_agent/AIAgent are still never imported on this path.

Supersedes NousResearch#44087 (same approach, rebased on current main).
Fixes NousResearch#44080, NousResearch#42433.
@yingliang-zhang
yingliang-zhang force-pushed the fix/cron-no-agent-run-sessions-v2 branch from 1286f49 to 21c7de0 Compare August 20, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sessions Session lifecycle, resume, persistence, history comp/cron Cron scheduler and job management P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants