Skip to content

fix(cron): preserve dashboard repeat counts - #68022

Open
tynamite wants to merge 1 commit into
NousResearch:mainfrom
tynamite:tynamite/fix-dashboard-cron-repeat
Open

fix(cron): preserve dashboard repeat counts#68022
tynamite wants to merge 1 commit into
NousResearch:mainfrom
tynamite:tynamite/fix-dashboard-cron-repeat

Conversation

@tynamite

Copy link
Copy Markdown

What does this PR do?

The dashboard POST /api/cron/jobs endpoint accepted payloads containing a finite repeat count but silently stripped the field during Pydantic parsing. The resulting job used the core default repeat=None and ran forever.

This change declares repeat as an optional strict positive integer and forwards it to cron.jobs.create_job(). Omitting the field keeps the existing unlimited behavior. Invalid values are rejected before a job is stored.

Related Issue

Fixes #68012

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • hermes_cli/web_server.py: validate and forward finite dashboard cron repeat counts.
  • tests/hermes_cli/test_web_server_cron_repeat.py: cover finite, omitted, non-positive, boolean, fractional, and string values; verify invalid requests create no job.

How to Test

  1. POST a job with repeat: 2; verify the response contains {"times": 2, "completed": 0}.
  2. Omit repeat; verify times remains null.
  3. Submit invalid values; verify HTTP 422 identifies repeat and no job is stored.
python -m pytest   tests/cron/test_jobs.py   tests/hermes_cli/test_web_server_cron_repeat.py   tests/hermes_cli/test_web_server_cron_profiles.py   tests/hermes_cli/test_web_server_skill_editor.py   -q -o addopts=
# 189 passed

python -m ruff check   hermes_cli/web_server.py   tests/hermes_cli/test_web_server_cron_repeat.py
# All checks passed

The exact commit was also reviewed on the contributor fork by both an independent Codex pass and GitHub Codex; neither found an actionable issue.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass (focused affected suites pass locally; full CI is left to Actions)
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 15.6.1 arm64

Documentation & Housekeeping

  • Documentation update: N/A — no user-facing configuration or workflow changed
  • cli-config.yaml.example update: N/A — no config key changed
  • CONTRIBUTING.md / AGENTS.md update: N/A — no architecture or workflow changed
  • Cross-platform impact considered: request validation and forwarding are platform-independent
  • Tool descriptions/schemas update: N/A — no agent tool contract changed

Screenshots / Logs

Not applicable; this is an HTTP request-contract fix with regression coverage.

@alt-glitch alt-glitch added type/bug Something isn't working comp/cron Cron scheduler and job management comp/dashboard Web dashboard / control panel UI (dashboard/, landing) P2 Medium — degraded but workaround exists sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Jul 20, 2026
@PRATHAMESH75

Copy link
Copy Markdown
Contributor

Reviewed against issue #68012. This fully closes the issue as written.

  • repeat: Optional[int] = Field(default=None, ge=1, strict=True) on CronJobCreate (hermes_cli/web_server.py) is the right root-cause fix: the missing field was being dropped by Pydantic's extra-field handling. ge=1 makes a non-positive value a clean 422 (acceptance criterion "invalid counts return a clear 4xx"), and strict=True blocks float/string coercion so 2.9 or "2" can't sneak through.
  • _create_cron_job_sync() now forwards repeat=body.repeat to create_job() — the second half of the drop.
  • tests/hermes_cli/test_web_server_cron_repeat.py posts repeat: 2 and asserts storage — this is exactly the endpoint coverage the issue asks for, and the piece the sibling PR fix(web_server): preserve repeat count when creating cron jobs from dashboard #68025 lacks.

Verifies against all four acceptance criteria (finite preserved, omit → default, invalid → 4xx, gateway API untouched). Note there's a competing PR #68025 that also adds the desktop CronJobCreatePayload.repeat?: number TS type — maintainers may want to cherry that one-line type add on top of this, since it's the only thing here that doesn't cover. LGTM on the backend fix. (Automated triage review.)

@tynamite
tynamite force-pushed the tynamite/fix-dashboard-cron-repeat branch from b541549 to 2fd6e37 Compare July 28, 2026 10:58
@tynamite

Copy link
Copy Markdown
Author

Rebased onto current upstream main to resolve the merge conflict. The PR now points to 2fd6e37db6; the diff remains limited to hermes_cli/web_server.py plus the targeted dashboard-cron regression tests. Fork CI is green, and Codex completed a fresh review of this exact commit with no major issues.

@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 the focused regression coverage. The underlying dashboard endpoint defect remains on current main: CronJobCreate lacks repeat at hermes_cli/web_models.py:361, and _create_cron_job_sync() does not forward it at hermes_cli/web_server.py:12462.

Problems

  • Current main commit 9179fb72ea moved CronJobCreate out of hermes_cli/web_server.py into hermes_cli/web_models.py. The PR’s schema hunk therefore targets the old location and will not change the active request model.

Suggested changes

  • Transplant the Field import and repeat: Optional[int] = Field(default=None, ge=1, strict=True) declaration into hermes_cli/web_models.py, while retaining the forwarding change in hermes_cli/web_server.py and the focused endpoint tests.

The core approach matches the existing gateway API behavior in gateway/platforms/api_server.py:5276-5309. This is an automated hermes-sweeper review.

Comment thread hermes_cli/web_server.py Outdated
@teknium1 teknium1 added the sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform label Jul 30, 2026
@tynamite
tynamite force-pushed the tynamite/fix-dashboard-cron-repeat branch from 2fd6e37 to a15b61b Compare July 30, 2026 13:11
@tynamite
tynamite force-pushed the tynamite/fix-dashboard-cron-repeat branch from a15b61b to eeee395 Compare July 30, 2026 13:26
@GottZ

GottZ commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

This was generated by AI during triage.

Summary

Two PRs address #68012 by adding the missing dashboard cron repeat field and forwarding it to create_job(). #68022 applies strict validation to the active request model and adds endpoint/storage regression coverage, while #68025 edits the superseded model location, uses coercible validation without tests, and uniquely adds the desktop TypeScript payload field.

Related pull requests

Duplicates

#68022 and #68025 substantially duplicate the request-model and create_job() forwarding changes for #68012; only #68025's desktop repeat?: number type is materially unique.

Suggested consolidation

Keep #68022 open with a salvage path: retain its active-model strict constraint, direct forwarding, and focused endpoint/storage tests, which address the contributor review's stated blocker. Close #68025 as a duplicate of #68022 despite its keep-open review because its visible core diff remains stale and less complete; preserve its one-line desktop TypeScript payload addition by splitting it into a focused follow-up or porting it during #68022 author work.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    I68012(["issue #68012 (open)"])
    subgraph Dup68022 ["PRs duplicating each other"]
        P68022["PR #68022 (open)"]
        P68025["PR #68025 (open)"]
    end
    P68022 -->|best fix| I68012
    class I68012 open
    class P68022 open
    class P68025 open
    class P68022 best
    class P68022 target
    click I68012 "https://github.com/NousResearch/hermes-agent/issues/68012"
    click P68022 "https://github.com/NousResearch/hermes-agent/pull/68022"
    click P68025 "https://github.com/NousResearch/hermes-agent/pull/68025"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label).

Cross-PR triage: Reviewed 2 pull requests and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 8 kB of PR diffs, 7 kB of issue/PR text, 7 kB of discussion (11 comments), 4 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cron Cron scheduler and job management comp/dashboard Web dashboard / control panel UI (dashboard/, landing) P2 Medium — degraded but workaround exists 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 type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dashboard cron create silently drops finite repeat counts

5 participants