From f8fc5db13e668d93aa990d20d78cb347bcfc895c Mon Sep 17 00:00:00 2001 From: ytnobody Date: Tue, 28 Jul 2026 16:10:02 +0900 Subject: [PATCH] docs(claude-md): cancel the recurring cron trigger on .hermit-quit, not just the current pass (Closes #192) Superintendent cycle step 2 previously only skipped the current pass when .hermit-quit was found, leaving any session-only cron job registered in step 1 to keep firing /hermit every tick indefinitely. Step 2 now instructs calling CronList/CronDelete to actually cancel the recurring job before ending the pass, and notes that hermit run (a separate OS process, internal/runloop/runloop.go) already watches .hermit-quit itself and is unaffected. Applied the same fix to the CLAUDE.md.tmpl scaffold template used by `hermit init`. --- CLAUDE.md | 5 ++++- cmd/hermit/templates/CLAUDE.md.tmpl | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 913063d..9239c14 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -30,7 +30,10 @@ Because this cycle now runs with the full tool access of the invoking context (n 1. Ensure the cycle keeps triggering on its own, without depending on the model remembering to do so: call `CronList` to check whether a recurring job invoking `/hermit` (or this cycle) is already scheduled. - If no such job is registered, call `CronCreate` to schedule one at the configured interval (e.g. `*/2 * * * *` for the default 120-second cadence; round to the nearest whole minute the cron expression can express) - If a matching job is already registered, do nothing -2. If a `.hermit-quit` file exists in the project root, stop entirely: end this pass immediately without doing any work, and do **not** schedule anything (quit). This is a terminal stop, unlike pause — it is not resumed by `hermit resume`; starting `/hermit` again is required to resume autonomous operation. +2. If a `.hermit-quit` file exists in the project root, stop entirely — and actually cancel the recurring trigger, not just this one pass: + - Call `CronList` to find the recurring job invoking `/hermit` (registered in step 1), and call `CronDelete` on it. Do **not** just skip scheduling and leave a previously-registered job in place — an existing session-only cron job keeps firing `/hermit` every tick regardless of what a given pass does, so leaving it running means every subsequent tick wastes a full pass re-detecting the same quit file until the job is explicitly deleted (or the session expires after 7 days). + - If instead this project is run via `hermit run` (the standalone OS-process loop from Issue #181/PR #189, not a Claude-session cron job), no action is needed here: `hermit run` already watches for `.hermit-quit` itself (`internal/runloop/runloop.go`) and stops its own tick loop when the file appears — it does not register or depend on session-only `CronCreate`/`CronList`/`CronDelete` jobs at all, so this step's `CronDelete` call is a no-op (or simply finds nothing) in that mode. To fully stop a `hermit run` process, use its own controls; `.hermit-quit` alone is sufficient because `hermit run` checks for it directly. + - Then end this pass immediately without doing any other work, and do **not** schedule a new job (quit). This is a terminal stop, unlike pause — it is not resumed by `hermit resume`; a human must delete `.hermit-quit` and then start `/hermit` again (which re-runs step 1 and re-registers the recurring job) to resume autonomous operation. 3. If a `.hermit-paused` file exists in the project root, end this pass immediately without doing any work (paused) — the recurring cron trigger re-checks on the next cycle 4. Retrieve open Issues with `list_issues` 5. Check open PRs for new review comments using `get_recent_pr_comments` with a `since` timestamp set to the last check time (store the current time before calling): diff --git a/cmd/hermit/templates/CLAUDE.md.tmpl b/cmd/hermit/templates/CLAUDE.md.tmpl index 2431c77..150c21f 100644 --- a/cmd/hermit/templates/CLAUDE.md.tmpl +++ b/cmd/hermit/templates/CLAUDE.md.tmpl @@ -13,7 +13,10 @@ 1. Ensure the cycle keeps triggering on its own, without depending on the model remembering to do so: call `CronList` to check whether a recurring job invoking `/hermit` (or this cycle) is already scheduled. - If no such job is registered, call `CronCreate` to schedule one at the configured interval (e.g. `*/2 * * * *` for the default 120-second cadence; round to the nearest whole minute the cron expression can express) - If a matching job is already registered, do nothing -2. If a `.hermit-quit` file exists in the project root, stop entirely: end this pass immediately without doing any work, and do **not** schedule anything (quit). This is a terminal stop, unlike pause — it is not resumed by `hermit resume`; starting `/hermit` again is required to resume autonomous operation. +2. If a `.hermit-quit` file exists in the project root, stop entirely — and actually cancel the recurring trigger, not just this one pass: + - Call `CronList` to find the recurring job invoking `/hermit` (registered in step 1), and call `CronDelete` on it. Do **not** just skip scheduling and leave a previously-registered job in place — an existing session-only cron job keeps firing `/hermit` every tick regardless of what a given pass does, so leaving it running means every subsequent tick wastes a full pass re-detecting the same quit file until the job is explicitly deleted (or the session expires after 7 days). + - If instead this project is run via `hermit run` (the standalone OS-process loop from Issue #181/PR #189, not a Claude-session cron job), no action is needed here: `hermit run` already watches for `.hermit-quit` itself (`internal/runloop/runloop.go`) and stops its own tick loop when the file appears — it does not register or depend on session-only `CronCreate`/`CronList`/`CronDelete` jobs at all, so this step's `CronDelete` call is a no-op (or simply finds nothing) in that mode. To fully stop a `hermit run` process, use its own controls; `.hermit-quit` alone is sufficient because `hermit run` checks for it directly. + - Then end this pass immediately without doing any other work, and do **not** schedule a new job (quit). This is a terminal stop, unlike pause — it is not resumed by `hermit resume`; a human must delete `.hermit-quit` and then start `/hermit` again (which re-runs step 1 and re-registers the recurring job) to resume autonomous operation. 3. If a `.hermit-paused` file exists in the project root, end this pass immediately without doing any work (paused) — the recurring cron trigger re-checks on the next cycle 4. Retrieve open Issues with `list_issues` 5. Treat any Issue labeled `requirements` (or whose title starts with `[Requirements]`) as a **standing requirements-hearing channel**, not a work item — this is where non-engineers converse with HERMIT to create/update the requirements document. Exclude these Issues from the Engineer-spawning steps below (steps 7–8), and instead: