Repository navigation
hermes profile update merges shipped cron jobs instead of replacing the store (#120823, salvage #120910) - #121264
Merged
kshitijk4poor merged 7 commits intoSep 24, 2026
Conversation
(cherry picked from commit 291dca0)
(cherry picked from commit b8b50f7)
…tion.py cron/jobs.py is already ~3400 lines; JOB_DEFINITION_FIELDS and merge_job_definition are only used by importers of a foreign cron store (profile distributions), so they live in a small dedicated module instead of growing the scheduler file. profile_distribution imports the new module directly; jobs.py is left byte-identical to main (no re-export shim). Refs NousResearch#120823 Co-authored-by: John Paul Soliva <soliva.johnpaul@icloud.com> Co-authored-by: JoaoMarcos44 <joaomarcosdias444@gmail.com>
load_jobs raises RuntimeError for an unreadable or unrepairable jobs.json; that is the only failure worth relabelling as DistributionError. Catching OSError/ValueError too hid the profile's own permission/disk errors behind "Could not merge cron jobs" and double-wrapped invalid-schedule ValueErrors the CLI already reports on its own. Refs NousResearch#120823 Co-authored-by: JoaoMarcos44 <joaomarcosdias444@gmail.com>
…le is replaced A shipped job whose authored schedule was a past one-shot (or an unparseable string) raised ValueError from _apply_schedule_update in the middle of _copy_dist_payload: SOUL.md and skills were already replaced, the cron store was not, and the message named no job. `hermes profile update` ended half-applied. - _copy_dist_payload merges the cron store first, so the one step that can reject shipped content runs while the profile is still whole; the merge itself only writes after every record merged. - merge_job_definition normalises string schedules via parse_schedule (a hand-authored store previously persisted the raw string, and `cron resume` then crashed on `.get`), and passes schedule_display only when the authored record has one so the helper's display fallback applies. - _merge_cron_store wraps the ValueError into a DistributionError naming the job. - Paused/created stamps use hermes_time.now() like every other cron record. The kept update test now covers the past-one-shot rejection (SOUL.md untouched, local schedule kept) and a corrupt target store surfacing as DistributionError, so dropping the error wrapper goes red.
hermes_cli still reached into cron's private _jobs_lock and hand-built the "created paused" record one function away from the module created so callers never duplicate cron's schema. import_job_definitions() now holds the lock, loads, merges and saves, and labels a merge ValueError with the job name; _merge_cron_store keeps only the temp-store parse and the DistributionError wrap, and takes the profile home instead of deriving it from dest.parent.parent. Also drops the dead `and key != "repeat"` (repeat is reassigned right after) and the comment that restated the module docstring.
Use the scheduler's own runnable predicate instead of a hand-rolled enabled/state check, so a contradictory half-paused record is treated the same way the scheduler treats it.
This was referenced Sep 24, 2026
teknium1
added a commit
that referenced
this pull request
Sep 24, 2026
teknium1
added a commit
that referenced
this pull request
Sep 24, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
hermes profile updateno longer replaces the profile's whole cron store with the shipped one (#120823). This salvages #120910 by @JoaoMarcos44.Why
A profile distribution that shipped
cron/jobs.jsonwas copied over the target profile's store on install and on every update. Jobs the user created locally were wiped. Shipped jobs lost their scheduler state and started unpaused on install. The livecron/runtime.locksibling was copied as well.Changes
cron/runtime.lockare never copied.JOB_DEFINITION_FIELDS,merge_job_definition,import_job_definitions) lives incron/job_definition.py.DistributionErrorbefore any file is replaced. Previously the update stopped halfway with SOUL.md already overwritten. String schedules are parsed up front, socron resumecan't hit a raw string later.jobs.jsonalso becomes aDistributionErrorinstead of a traceback.Validation
cron/runtime.locksiblingtests/hermes_cli/test_profile_distribution.pytogether withtests/cron: 1412 passed, 10 skipped. 12-file review map: 343 passed, 8 skipped.Credit
Supersedes #120910, #120824.