Skip to content

feat(cron): profile-scoped cron listing for the Routines pane (#37) - #86803

Closed
BowmanStephen wants to merge 1 commit into
NousResearch:mainfrom
BowmanStephen:feat/cron-profile-scoped-list
Closed

feat(cron): profile-scoped cron listing for the Routines pane (#37)#86803
BowmanStephen wants to merge 1 commit into
NousResearch:mainfrom
BowmanStephen:feat/cron-profile-scoped-list

Conversation

@BowmanStephen

Copy link
Copy Markdown

Problem

The desktop Routines pane claims to follow the active bot, but cron.manage only ever read the connected gateway's own cron store. A bot whose profile runs its own gateway (separate HERMES_HOME) appeared to have 'no cron jobs' — its store was invisible (Hermes-Bot-Mode issue #37, cross-referenced from Hermes-Bot-Mode PR #62).

Change

  • cronjob(action='list', home=...) scopes the read to another profile's cron store via the existing use_cron_store() ContextVar (per-profile isolation [Bug]: cron under profile-scoped launchd gateway falls back to default ~/.hermes instead of profile HERMES_HOME #4707; override is context-local and restored on exit). Only list is scoped — mutating another profile's store through this tool stays deliberately unsupported.
  • cron.manage RPC accepts an optional profile param: resolves the profile to its HERMES_HOME and forwards it. Unknown profile → clean RPC error. Old UIs unaffected (param omitted).
  • The desktop plugin marks scoped reads (data.scoped) so untagged jobs are treated as the bot's own and the pane can drop its 'check with hermes -p <bot> cron list' empty state (companion plugin PR will follow).

Tests

2 new: foreign-store read + isolation (caller's own store untouched), missing store → empty. 717 cron/tool tests pass.

…search#37)

The desktop Routines pane claims to follow the active bot, but
cron.manage only ever read the connected gateway's own cron store. A
bot whose profile runs its own gateway (separate HERMES_HOME) appeared
to have 'no cron jobs' — its store was invisible.

- cronjob(action='list', home=...) scopes the read to another profile's
  cron store via the existing use_cron_store() ContextVar (per-profile
  isolation NousResearch#4707; override is context-local and restored on exit).
  Only 'list' is scoped — mutating another profile's store through this
  tool stays deliberately unsupported.
- cron.manage RPC accepts an optional profile param: resolves the
  profile to its HERMES_HOME and forwards it. Unknown profile -> clean
  RPC error. Old UIs unaffected (param omitted).
- The desktop plugin marks scoped reads (data.scoped) so untagged jobs
  are treated as the bot's own, and the pane can drop its
  'check with hermes -p <bot> cron list' empty state.

Tests: 2 new (foreign-store read + isolation, missing store -> empty).
717 cron/tool tests pass.
@alt-glitch alt-glitch added type/feature New feature or request comp/cron Cron scheduler and job management comp/tui Terminal UI (ui-tui/ + tui_gateway/) area/profiles Multi-profile isolation, HERMES_HOME scoping sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades P3 Low — cosmetic, nice to have labels Aug 15, 2026
@Enough1122

Copy link
Copy Markdown
Contributor

AI code review — automated review for reference, author can ignore or act on any point.

feat(cron): profile-scoped cron listing for the Routines pane (#37)

No blocking issues found. A few minor observations:

  1. tools/cronjob_tools.py — the new home parameter accepts an arbitrary path with no validation at the tool level. The RPC layer (tui_gateway/methods_tools.py) validates profile_exists before resolving the home, but the tool itself will happily list any directory a caller points at (e.g. another profile's store, or any path with a cron/jobs.json). Read-only and opt-in, so the risk is low, but consider enforcing at the tool layer that home resolves to a profile home (or at least documenting the trust boundary in the schema description), so the tool and the RPC enforce the same contract.

  2. tools/cronjob_tools.py — the if home is not None: / else: branches duplicate the jobs = [...] line; use_cron_store returns a context manager, so with use_cron_store(home) if home is not None else nullcontext(): would collapse the duplication. Style nit only.

  3. tui_gateway/methods_tools.py — error code 4017 is hardcoded for the missing-profile case. Worth a quick check that 4017 does not collide with an existing tui_gateway error code range (the surrounding handlers use _err(rid, <n>, ...)), so the RPC contract stays unambiguous.

  4. Tests cover the tool-level home scoping well (foreign store read + caller store isolation + missing store → empty). The RPC layer's profile param branch (missing profile → 4017, valid profile → home forwarded) has no direct test — a small RPC-level test would lock in the wiring.

@teknium1

Copy link
Copy Markdown
Contributor

Your backend approach (profile-scoped cron listing via a profile param on cron.manage) was the right design and you were the earliest submitter — main landed the same mechanism in #86796 while this PR was open, so no code could be cherry-picked, but #88731 (just merged) builds directly on that design and credits you as the earliest submitter in its description. Thank you for pioneering the approach! Closing as superseded by #86796 + #88731.

@teknium1 teknium1 closed this Aug 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/profiles Multi-profile isolation, HERMES_HOME scoping comp/cron Cron scheduler and job management comp/tui Terminal UI (ui-tui/ + tui_gateway/) P3 Low — cosmetic, nice to have sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants