From bbe1d79c536cdf0d5be5d5d2219c998462b4fd7e Mon Sep 17 00:00:00 2001 From: Parfii-bot Date: Wed, 22 Apr 2026 15:13:54 +0800 Subject: [PATCH] feat(v0.17): sleep-setup local/remote/hybrid mode + time picker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extends /sleep-setup wizard with three deployment modes and user-picked nightly time. Pure-click except existing free-text (repo URL; custom time if chosen). New phases: phase-0-mode.md (64 LOC) — 3 options: local-only (CronCreate, full filesystem access, real /self-audit skill) / remote-only (existing cloud-agent + git-repo flow) / hybrid (both; redundancy if Mac asleep). phase-0b-time.md (79 LOC) — 6 options: 03:00 REM peak / 00:00 / 05:00 / 23:00 / 21:00 / Custom (freeText with HH:MM regex + 3-retry fallback to 03:00). phase-5-trigger.md — octal-safe $SLEEP_TIME_LOCAL parsing (10# prefix), branches on $SLEEP_MODE: local-only → CronCreate only, local time (no UTC conversion) remote-only → /schedule create only (UTC-converted) hybrid → both, two sequential AskUserQuestion phase-3b-deep-sleep.md — adds plan+local-patch option when SLEEP_MODE=local-only (apply patches to ~/.claude/ directly after morning confirm, no git branch). SKILL.md — pipeline table 6 → 8 rows, AskUserQuestion minimum 9 → 11 (remote/hybrid) or 6 (local-only); final report shows Mode + Time fields adapted per mode. Verify: new user picks local-only + Custom 05:00 → zero git, cron 0 5 * * * registered with /self-audit body referencing ~/.claude/memory/audit-backlog.md and sleep-report-DATE.md. Co-Authored-By: Claude Opus 4.7 (1M context) --- skills/sleep-setup/SKILL.md | 82 ++++++++---- skills/sleep-setup/phase-0-mode.md | 64 ++++++++++ skills/sleep-setup/phase-0b-time.md | 79 ++++++++++++ skills/sleep-setup/phase-3b-deep-sleep.md | 44 ++++++- skills/sleep-setup/phase-5-trigger.md | 146 +++++++++++++++++----- 5 files changed, 355 insertions(+), 60 deletions(-) create mode 100644 skills/sleep-setup/phase-0-mode.md create mode 100644 skills/sleep-setup/phase-0b-time.md diff --git a/skills/sleep-setup/SKILL.md b/skills/sleep-setup/SKILL.md index 365d9da..b35486b 100644 --- a/skills/sleep-setup/SKILL.md +++ b/skills/sleep-setup/SKILL.md @@ -1,6 +1,6 @@ --- name: sleep-setup -description: One-time wizard (RULE 0.15) that configures KeiSeiKit v0.11 cloud REM sync. Generates an SSH deploy key, initializes the user's memory-repo, writes env refs (RULE 0.8), and emits a ready-to-paste `/schedule create` command for nightly consolidation. Pure-click except the 1 free-text field for repo URL. +description: One-time wizard (RULE 0.15) that configures KeiSeiKit sleep layer. Phase 0 picks mode (local-only / remote-only / hybrid); Phase 0b picks local trigger time (6 options incl. Custom HH:MM). Remote/hybrid generate an SSH deploy key, init the memory-repo, write env refs (RULE 0.8), and emit a `/schedule create` command. Local-only / hybrid emit a CronCreate snippet. Pure-click except 2 free-text fields (repo URL in Phase 2, Custom time in Phase 0b). argument-hint: (no arguments) --- @@ -18,19 +18,24 @@ executed in order. Never skip a phase. Never re-order phases. --- -## Pipeline overview (6 phases, 9+ AskUserQuestion since v0.13.0) +## Pipeline overview (8 phases, 11+ AskUserQuestion since v0.14.0) | Phase | File | Purpose | AskUserQuestion | |---|---|---|---| -| 1 | [phase-1-repo-pick.md](phase-1-repo-pick.md) | Pick repo provider + visibility | 2 (click-only) | -| 2 | [phase-2-repo-url.md](phase-2-repo-url.md) | Collect SSH URL (1 free-text field) | 1 (AskUserQuestion `freeText`) | -| 3 | [phase-3-deploy-key.md](phase-3-deploy-key.md) | Run `kei-sleep-setup.sh`, show pubkey, confirm deploy-key added | 1 (click) | +| 0 | [phase-0-mode.md](phase-0-mode.md) | Pick sleep mode: local-only / remote-only / hybrid | 1 (click-only) | +| 0b | [phase-0b-time.md](phase-0b-time.md) | Pick local trigger time (6 options; Custom adds 1 free-text) | 1-2 (click; +freeText if Custom) | +| 1 | [phase-1-repo-pick.md](phase-1-repo-pick.md) | Pick repo provider + visibility (skipped if local-only) | 2 (click-only) | +| 2 | [phase-2-repo-url.md](phase-2-repo-url.md) | Collect SSH URL (skipped if local-only) | 1 (AskUserQuestion `freeText`) | +| 3 | [phase-3-deploy-key.md](phase-3-deploy-key.md) | Run `kei-sleep-setup.sh`, confirm deploy-key added (skipped if local-only) | 1 (click) | | 3b | [phase-3b-deep-sleep.md](phase-3b-deep-sleep.md) | v0.13.0 — deep-sleep cadence + fork mode + store backend | 3 (click; +1 free-text if Custom cadence) | -| 4 | [phase-4-test-push.md](phase-4-test-push.md) | Dry-run a test commit via `kei-sleep-sync.sh` | 1 (click) | -| 5 | [phase-5-trigger.md](phase-5-trigger.md) | Render `/schedule create` command, offer to run now | 1 (click) | +| 4 | [phase-4-test-push.md](phase-4-test-push.md) | Dry-run a test commit (skipped if local-only) | 1 (click) | +| 5 | [phase-5-trigger.md](phase-5-trigger.md) | Render CronCreate and/or `/schedule create` per mode | 1-2 (click; hybrid asks twice) | -**Minimum AskUserQuestion count: 9.** All clicks except the single repo-URL -free-text in Phase 2 (plus optional Custom cadence / S3 fields in Phase 3b). +**Minimum AskUserQuestion count: 11** (remote-only / hybrid full pipeline). +**Local-only mode: 6 minimum** (Phases 0, 0b, 3b, 5; Phases 1-4 skipped). +All clicks except the repo-URL free-text in Phase 2 (skipped in local-only), +the Custom-time free-text in Phase 0b (optional), and the Custom-cadence / +S3 free-text fields in Phase 3b (optional). --- @@ -38,22 +43,28 @@ free-text in Phase 2 (plus optional Custom cadence / S3 fields in Phase 3b). | Name | Set in | Meaning | |---|---|---| -| `PROVIDER` | Phase 1 | `github` / `gitlab` / `bitbucket` / `self-hosted` | -| `VISIBILITY` | Phase 1 | `private` (recommended) / `public` (explicit user choice) | -| `REPO_URL` | Phase 2 | Validated SSH URL (`git@host:org/repo.git`) | -| `KEY_ADDED` | Phase 3 | boolean; was deploy key confirmed added? | +| `SLEEP_MODE` | Phase 0 | `local-only` / `remote-only` / `hybrid` | +| `SLEEP_TIME_LOCAL` | Phase 0b | `HH:MM` 24h format (e.g. `03:00`); user's local time | +| `PROVIDER` | Phase 1 (remote/hybrid only) | `github` / `gitlab` / `bitbucket` / `self-hosted` | +| `VISIBILITY` | Phase 1 (remote/hybrid only) | `private` (recommended) / `public` (explicit user choice) | +| `REPO_URL` | Phase 2 (remote/hybrid only) | Validated SSH URL (`git@host:org/repo.git`) | +| `KEY_ADDED` | Phase 3 (remote/hybrid only) | boolean; was deploy key confirmed added? | | `DEEP_SLEEP_CRON_DAYS` | Phase 3b | integer ≥0; 0 disables Phase C; default 7 | -| `DEEP_SLEEP_WITH_FORK` | Phase 3b | 0 (plan only) / 1 (plan + fork branch) | +| `DEEP_SLEEP_WITH_FORK` | Phase 3b | 0 (plan only) / 1 (plan + fork branch) / 2 (plan + local-patch; local-only mode) | | `STORE_BACKEND` | Phase 3b | `github` / `forgejo` / `gitea` / `filesystem` / `s3` | -| `TEST_VERIFIED` | Phase 4 | boolean; did the user see the test commit in the remote? | -| `SCHEDULE_ACTION` | Phase 5 | `run-now` / `copy-later` / `skip` | +| `TEST_VERIFIED` | Phase 4 (remote/hybrid only) | boolean; did the user see the test commit in the remote? | +| `SLEEP_CRON_UTC` | Phase 5 (remote/hybrid only) | `m h * * *` cron expression derived from `SLEEP_TIME_LOCAL` + local TZ | +| `SCHEDULE_ACTION` | Phase 5 | mode-dependent; see phase-5-trigger.md §5d | --- ## Final report (emit after Phase 5) +Remote-only / hybrid (full pipeline): ``` === SLEEP-SETUP REPORT === +Mode: +Time (local): Provider: (visibility: ) Repo URL: Deploy key: ~/.ssh/keisei-memory-sync(.pub) @@ -63,19 +74,40 @@ Test push: (Phase 4) Schedule: ``` -If `SCHEDULE_ACTION == skip`, add: +Local-only (Phases 1-4 skipped): ``` -Local-only mode. Traces will be pushed to the repo on every session end. -To enable nightly consolidation later: paste the prompt from Phase 5 into -`/schedule create` any time. +=== SLEEP-SETUP REPORT === +Mode: local-only +Time (local): +Provider: (skipped) +Repo URL: (skipped) +Deploy key: (not generated — local-only needs no git) +Sync repo path: (skipped) +Env refs: ~/.claude/secrets/.env (no sleep-sync keys written) +Test push: (skipped) +Schedule: # local-cron-created / -copy-later / -skipped +``` + +If `SCHEDULE_ACTION` contains `skipped` (remote) or `local-cron-skipped`, +add: +``` +No nightly consolidation. Traces still land locally in +~/.claude/memory/traces/ (and push to the repo on every session end if +mode != local-only). Re-run /sleep-setup any time to register a trigger. ``` --- ## Rules (apply throughout — enforced at every phase) -- **Pure-click contract.** Only Phase 2 asks for free text; every - decision is an `AskUserQuestion`. No `freeText` outside Phase 2. +- **Pure-click contract.** Only Phase 2 (repo URL) and Phase 0b (Custom + time) ask for free text; every other decision is an `AskUserQuestion`. + No `freeText` outside those two points (plus optional Custom cadence / + S3 fields in Phase 3b). +- **Local-only skips Phases 1-4 entirely** — no git operations, no SSH + key, no repo URL collection, no deploy-key walkthrough, no test push. + The skill jumps phase-0 → phase-0b → phase-3b → phase-5 and never + touches git. - **Idempotent.** Re-running the wizard must NOT clobber existing `~/.ssh/keisei-memory-sync` or `~/.claude/memory/sync-repo/`; the helper script handles re-use. @@ -91,8 +123,10 @@ To enable nightly consolidation later: paste the prompt from Phase 5 into repo leaks your session prompts and tool usage — confirm?". - **Silent failure (RULE 0.15).** Nothing in the session-end path may block the session from closing. The wizard itself may fail loudly. -- **Constructor Pattern (RULE ZERO).** Every phase file < 100 LOC - (well under the 200-LOC file limit). +- **Constructor Pattern (RULE ZERO).** Every phase file < 200 LOC + (RULE ZERO hard limit). New lightweight phases (0, 0b) target < 100 + LOC; phase-3b and phase-5 are heavier branch-heavy router files and + sit between 100-200. --- diff --git a/skills/sleep-setup/phase-0-mode.md b/skills/sleep-setup/phase-0-mode.md new file mode 100644 index 0000000..1d2a83a --- /dev/null +++ b/skills/sleep-setup/phase-0-mode.md @@ -0,0 +1,64 @@ +# Phase 0 — Sleep mode pick + +Ask the user to pick the execution mode for nightly sleep-layer +consolidation. This is the FIRST phase of the wizard — it runs BEFORE +Phase 1 and branches the entire pipeline. + +## 0a — Mode click + +Emit ONE `AskUserQuestion`: + +```json +{ + "questions": [ + { + "question": "How should sleep-layer consolidation run?", + "header": "Sleep mode", + "multiSelect": false, + "options": [ + {"label": "Local-only", "description": "macOS CronCreate on this Mac; full access to ~/.claude/memory/ and /self-audit. No git repo needed."}, + {"label": "Remote-only", "description": "Cloud agent via /schedule; git-repo based; morning git pull to read the report. Mac can sleep."}, + {"label": "Hybrid", "description": "Both. Local cron does the deep analysis; remote is redundancy when Mac is asleep. Both paths are idempotent."} + ] + } + ] +} +``` + +Store the pick as `SLEEP_MODE` ∈ {`local-only`, `remote-only`, `hybrid`}. + +## 0b — Branching + +Branch the remainder of the pipeline based on `SLEEP_MODE`: + +- **`local-only`** — skip Phases 1, 2, 3, 4 entirely. No git provider, + no SSH key, no repo URL, no deploy-key walkthrough, no test push. + Jump directly to Phase 0b (time) → Phase 3b (deep-sleep cadence, + adapted for local per phase-3b-deep-sleep.md) → Phase 5 (trigger, + emits only CronCreate). +- **`remote-only`** — proceed through Phase 0b (time) → Phase 1 → + Phase 2 → Phase 3 → Phase 3b → Phase 4 → Phase 5 (emits only + `/schedule create`). +- **`hybrid`** — same full pipeline as `remote-only`, but Phase 5 + emits BOTH a CronCreate block AND a `/schedule create` block, with + two sequential AskUserQuestions (one per trigger path). + +## 0c — Implication note + +Print a one-line reminder before continuing: + +``` +SLEEP_MODE = . Local cron uses this Mac; remote trigger uses a +cloud Claude Code agent. Hybrid runs both; the two paths write to +different paths and are idempotent. +``` + +No second AskUserQuestion — the pick is final. Re-running the wizard +lets the user change modes later. + +## Verify-criterion + +- Exactly ONE `AskUserQuestion` in this phase. +- `SLEEP_MODE ∈ {local-only, remote-only, hybrid}`. +- If `local-only`, Phases 1-4 MUST be skipped by the caller. +- If `remote-only` or `hybrid`, the full pipeline continues at Phase 0b. diff --git a/skills/sleep-setup/phase-0b-time.md b/skills/sleep-setup/phase-0b-time.md new file mode 100644 index 0000000..3c333e6 --- /dev/null +++ b/skills/sleep-setup/phase-0b-time.md @@ -0,0 +1,79 @@ +# Phase 0b — Sleep time picker + +Ask the user to pick the local-time trigger for nightly consolidation. +Runs immediately after Phase 0 (mode pick), before any git setup. + +## 0b.1 — Time click + +Emit ONE `AskUserQuestion`: + +```json +{ + "questions": [ + { + "question": "When should nightly consolidation run (local time)?", + "header": "Sleep time", + "multiSelect": false, + "options": [ + {"label": "03:00", "description": "Classical REM peak — default"}, + {"label": "00:00", "description": "Midnight — end of calendar day"}, + {"label": "05:00", "description": "Pre-dawn — fresh morning report"}, + {"label": "23:00", "description": "Late evening — before overnight sync"}, + {"label": "21:00", "description": "Early evening — for early sleepers"}, + {"label": "Custom", "description": "Pick exact HH:MM (24h format) on next prompt"} + ] + } + ] +} +``` + +## 0b.2 — Store or branch + +- Non-custom pick → store as `SLEEP_TIME_LOCAL` verbatim (e.g. `03:00`). +- `Custom` → emit follow-up `AskUserQuestion` with `freeText`: + +```json +{ + "questions": [ + { + "question": "Enter the local trigger time in HH:MM (24h). Example: 04:15 for 4:15 AM.", + "header": "Custom time", + "freeText": true + } + ] +} +``` + +## 0b.3 — Validation + +Validate with regex `^([01][0-9]|2[0-3]):[0-5][0-9]$`: + +```bash +if ! echo "$SLEEP_TIME_LOCAL" | grep -qE '^([01][0-9]|2[0-3]):[0-5][0-9]$'; then + # invalid — re-ask with the same freeText prompt + # accept any leading zeros; reject "3:00" (must be "03:00"), "24:00", "12:60" + echo "Invalid time '$SLEEP_TIME_LOCAL'. Expected HH:MM with leading zeros (e.g. 03:00, 23:59)." + # loop back to 0b.2 Custom freeText prompt +fi +``` + +Retry loop: if invalid, re-emit the freeText prompt up to 3 times. After +3 failures, fall back to `03:00` and log `SLEEP_TIME_LOCAL defaulted to +03:00 after 3 invalid inputs`. + +## 0b.4 — Confirmation line + +Once validated, print: + +``` +SLEEP_TIME_LOCAL = (this Mac's local time). Phase 5 will use +this value for the CronCreate expression and/or the UTC conversion for +the remote `/schedule` trigger. +``` + +## Verify-criterion + +- At least ONE `AskUserQuestion` (two if Custom picked). +- `SLEEP_TIME_LOCAL` matches `^([01][0-9]|2[0-3]):[0-5][0-9]$`. +- No unclamped / unvalidated values stored. Invalid input either + re-prompts or falls back to `03:00` with an audit line. diff --git a/skills/sleep-setup/phase-3b-deep-sleep.md b/skills/sleep-setup/phase-3b-deep-sleep.md index 629c01b..e1be5d1 100644 --- a/skills/sleep-setup/phase-3b-deep-sleep.md +++ b/skills/sleep-setup/phase-3b-deep-sleep.md @@ -4,6 +4,19 @@ Collect three pure-click decisions for Phase C (system consolidation): cadence, fork mode, store backend. All three are `AskUserQuestion` batches — zero free text (frequency "custom" is the single exception). +## Mode-dependent behaviour + +If `SLEEP_MODE == local-only` (set in Phase 0), the fork mode question +in §3b.2 gets an EXTRA third option `plan+local-patch` that applies +auto-resolvable changes directly to `~/.claude/` files (after user +confirm at morning) instead of committing to a git branch. Cadence +(§3b.1) and store backend (§3b.3) are still asked, but the store +backend defaults to `filesystem` for local-only — the user can still +pick another if they want a secondary backup path. + +For `remote-only` / `hybrid` the fork mode stays as the original 2 +options (plan only / plan + fork branch). + ## 3b.1 — Deep-sleep cadence Emit ONE `AskUserQuestion`: @@ -39,7 +52,8 @@ Store as `DEEP_SLEEP_CRON_DAYS`: ## 3b.2 — Fork output mode -Emit ONE `AskUserQuestion`: +For `SLEEP_MODE ∈ {remote-only, hybrid}`, emit ONE `AskUserQuestion` +with 2 options: ```json { @@ -57,7 +71,30 @@ Emit ONE `AskUserQuestion`: } ``` -Store as `DEEP_SLEEP_WITH_FORK` ∈ {0, 1}. +For `SLEEP_MODE == local-only`, emit ONE `AskUserQuestion` with 3 +options (adds `plan+local-patch`): + +```json +{ + "questions": [ + { + "question": "Fork output with applied changes?", + "header": "Deep-sleep fork (local mode)", + "multiSelect": false, + "options": [ + {"label": "Plan only (Recommended)", "description": "Read markdown in the morning; decide by hand"}, + {"label": "Plan + fork branch", "description": "Also generate deep-sleep/YYYY-MM-DD branch (needs a local git repo under ~/.claude/)"}, + {"label": "Plan + local-patch", "description": "Auto-resolvable changes applied directly to ~/.claude/ after morning confirm — no git branch needed"} + ] + } + ] +} +``` + +Store as `DEEP_SLEEP_WITH_FORK` ∈ {0, 1, 2}: +- `0` — Plan only +- `1` — Plan + fork branch +- `2` — Plan + local-patch (local-only mode only) ## 3b.3 — Memory-repo backend @@ -110,7 +147,8 @@ free-text fields (one-off — unavoidable; S3 has no SSH-like default). ## 3b.5 — Verify-criterion - `DEEP_SLEEP_CRON_DAYS ∈ {0,1,3,7,14, or 1..=90}` for custom. -- `DEEP_SLEEP_WITH_FORK ∈ {0, 1}`. +- `DEEP_SLEEP_WITH_FORK ∈ {0, 1}` for `remote-only` / `hybrid`; + `∈ {0, 1, 2}` for `local-only` (2 = plan+local-patch). - `STORE_BACKEND ∈ {github, forgejo, gitea, filesystem, s3}`. - `~/.claude/agents/_primitives/store-config.toml` exists and has the active backend set. diff --git a/skills/sleep-setup/phase-5-trigger.md b/skills/sleep-setup/phase-5-trigger.md index e8b801b..de5eca4 100644 --- a/skills/sleep-setup/phase-5-trigger.md +++ b/skills/sleep-setup/phase-5-trigger.md @@ -1,47 +1,100 @@ -# Phase 5 — Emit `/schedule create` command +# Phase 5 — Emit trigger (CronCreate and/or `/schedule create`) -Render the ready-to-paste nightly trigger and ask whether to run it now, -copy and do later, or skip to local-only mode. +Render the ready-to-paste nightly trigger(s) and ask how to register +them. Branches on `SLEEP_MODE` (set in Phase 0) and uses +`SLEEP_TIME_LOCAL` (set in Phase 0b). -## 5a — Load template +## 5a — Load template (remote path only) -Read `_primitives/templates/sleep-trigger-prompt.md` from the kit install -path: +If `SLEEP_MODE ∈ {remote-only, hybrid}`, read the cloud-agent template +from the kit install path: ``` ~/.claude/agents/_primitives/templates/sleep-trigger-prompt.md ``` If the file is missing (older kit version), fall back to the inline -template in this phase file (see 5e). +template in this phase file (see 5f). -## 5b — Compute UTC cron +For `SLEEP_MODE == local-only` skip 5a entirely — no remote template is +rendered. -Local target: `03:00` user-local time, every day. +## 5b — Parse local time + +`SLEEP_TIME_LOCAL` has format `HH:MM` (validated in Phase 0b). Convert +to minutes-past-midnight. The `10#` prefix prevents bash from +interpreting `08` / `09` as invalid octal: + +```bash +hh=${SLEEP_TIME_LOCAL%:*} +mm=${SLEEP_TIME_LOCAL#*:} +local_minutes=$((10#$hh * 60 + 10#$mm)) +``` + +## 5c — Compute UTC cron (remote path only) + +Only needed if `SLEEP_MODE ∈ {remote-only, hybrid}`. CronCreate on the +Mac uses local time directly, so `local-only` skips this block. ```bash # macOS / GNU date — detect local TZ offset in minutes offset_min=$(date +%z | awk '{ s=substr($0,1,1); h=substr($0,2,2); m=substr($0,4,2); print (s=="-" ? 1 : -1) * (h*60+m) }') -# local 03:00 = 180 minutes past midnight local -local_minutes=180 utc_minutes=$(( (local_minutes + offset_min + 1440) % 1440 )) utc_hour=$(( utc_minutes / 60 )) utc_min=$(( utc_minutes % 60 )) -utc_cron=$(printf '%d %d * * *' "$utc_min" "$utc_hour") +SLEEP_CRON_UTC=$(printf '%d %d * * *' "$utc_min" "$utc_hour") ``` -Keep arithmetic in the skill prompt if Claude Code executes shell; -otherwise have Claude compute the offset directly. +## 5d — Render blocks per mode -## 5c — Render placeholders +### Mode: `local-only` -Replace `{REPO_URL}` with `REPO_URL` and `{UTC_CRON}` with `utc_cron` in -the template. Print the rendered prompt to chat inside a fenced code -block so the user can one-click-copy. +Render ONE fenced `CronCreate` snippet (no `/schedule`). The cron +expression uses the user's local time directly — CronCreate runs on +this Mac, not in UTC: -## 5d — Click +``` +CronCreate expression: * * * (local time on this Mac) +Prompt body: + Run /self-audit --cross-session on ~/.claude/memory/traces/. + Duration budget: 60 min max. + Always write summary to ~/.claude/memory/sleep-report-YYYY-MM-DD.md. + If >=3 recurring patterns detected, append a dated block to + ~/.claude/memory/audit-backlog.md (section per RULE 0.14). + Invariants: append-only traces; no fabricated findings; skip + analysis if CWD was under a banned-project path. +``` -Emit ONE `AskUserQuestion`: +Where `` and `` are the values from 5b. Emit ONE +`AskUserQuestion`: + +```json +{ + "questions": [ + { + "question": "Register the local CronCreate now?", + "header": "Local cron", + "multiSelect": false, + "options": [ + {"label": "Create CronCreate now", "description": "Invoke CronCreate with the rendered body"}, + {"label": "Copy, create later", "description": "I'll register the cron myself with the snippet above"}, + {"label": "Skip (no local cron)", "description": "No scheduled analysis — manual /self-audit only"} + ] + } + ] +} +``` + +Store `SCHEDULE_ACTION`: +- `Create CronCreate now` → `local-cron-created` +- `Copy, create later` → `local-cron-copy-later` +- `Skip` → `local-cron-skipped` + +### Mode: `remote-only` + +Render ONE fenced `/schedule create` block using the template from 5a. +Replace `{REPO_URL}` with `REPO_URL` and `{UTC_CRON}` with +`SLEEP_CRON_UTC`. Emit ONE `AskUserQuestion`: ```json { @@ -52,7 +105,7 @@ Emit ONE `AskUserQuestion`: "multiSelect": false, "options": [ {"label": "Run /schedule now", "description": "Invoke /schedule create with the rendered prompt"}, - {"label": "Copy, run later", "description": "Leave it to me — I'll paste into /schedule create myself"}, + {"label": "Copy, run later", "description": "I'll paste into /schedule create myself"}, {"label": "Skip (local-only)", "description": "Just push traces; no nightly consolidation"} ] } @@ -60,22 +113,40 @@ Emit ONE `AskUserQuestion`: } ``` -Handle: -- `Run now` → set `SCHEDULE_ACTION = run-now`; invoke - `/schedule create` with the rendered body. -- `Copy later` → set `SCHEDULE_ACTION = copy-later`; print the body - again and a one-line reminder. -- `Skip` → set `SCHEDULE_ACTION = skip`; print the local-only - footer from SKILL.md's "Final report". +Store `SCHEDULE_ACTION`: +- `Run /schedule now` → `remote-run-now` +- `Copy, run later` → `remote-copy-later` +- `Skip` → `remote-skipped` -## 5e — Fallback inline template (if kit missing the file) +### Mode: `hybrid` + +Render BOTH blocks (CronCreate first, then `/schedule create`). Emit +TWO sequential `AskUserQuestion` batches — first the local question +from mode `local-only` (section 5d.local), then the remote question +from mode `remote-only` (section 5d.remote). + +Store `SCHEDULE_ACTION` as a composite, e.g. +`local-cron-created+remote-run-now`, +`local-cron-copy-later+remote-skipped`, +`local-cron-skipped+remote-copy-later`, etc. + +## 5e — Render placeholders (remote path only) + +For `remote-only` / `hybrid`: replace `{REPO_URL}` and `{UTC_CRON}` in +the template. Print the rendered prompt inside a fenced code block so +the user can one-click-copy. + +For `local-only`: no placeholders to render — the CronCreate body is +self-contained in 5d. + +## 5f — Fallback inline template (remote path, if kit missing file) If `~/.claude/agents/_primitives/templates/sleep-trigger-prompt.md` is absent, use this minimal inline prompt: ``` Clone: -At UTC : +At UTC : 1. Clone shallow, read traces/ since reports/last-run.txt 2. Write reports/sleep-.md with session + tool + error summary 3. If >=3 cross-session patterns, prepend to backlog.md @@ -89,7 +160,16 @@ missing from kit install; using fallback" so the user can re-install. ## Verify-criterion -- Exactly ONE `AskUserQuestion`. +- `local-only`: exactly ONE `AskUserQuestion`; exactly ONE fenced + CronCreate block; no `/schedule` rendered. +- `remote-only`: exactly ONE `AskUserQuestion`; exactly ONE fenced + `/schedule create` block; no CronCreate rendered. +- `hybrid`: exactly TWO `AskUserQuestion` batches (local first, + remote second); both blocks rendered. +- Cron expression on local path uses `SLEEP_TIME_LOCAL` directly (no + UTC conversion). +- Cron expression on remote path uses `SLEEP_CRON_UTC` from 5c. - Rendered prompt contains no placeholder (`{REPO_URL}` / `{UTC_CRON}`). -- `SCHEDULE_ACTION` is one of `run-now` / `copy-later` / `skip`. -- The final report block from SKILL.md is emitted with real values. +- `SCHEDULE_ACTION` set per mode rules above. +- The final report block from SKILL.md is emitted with real values, + including `Mode: ` and `Time (local): `.