Skip to content

feat(scripts): maintain.ps1 — daily heartbeat with smart notifications#30

Open
abdout wants to merge 1 commit into
feat/doctorfrom
feat/maintain
Open

feat(scripts): maintain.ps1 — daily heartbeat with smart notifications#30
abdout wants to merge 1 commit into
feat/doctorfrom
feat/maintain

Conversation

@abdout
Copy link
Copy Markdown
Contributor

@abdout abdout commented May 16, 2026

Summary

Implements spec #27. The daily heartbeat that composes the existing scripts into one autonomous run and surfaces problems through the right notification channel.

maintain -Install              # one-time setup
maintain -Status               # what's armed, when next, last result
maintain -Run                  # force run now (default)
maintain -Uninstall            # remove scheduled task

Builds on #29 (doctor.ps1) — maintain is doctor's consumer.

What's in the PR

  • ~/.claude/scripts/maintain.ps1 (208 lines) — main entry point
  • ~/.claude/scripts/lib/Notify.ps1 (60 lines) — Send-Toast (BurntToast), Send-Slack (webhook), Get-EnvVar (.env reader)

Flow

sync-repos.ps1  →  git pull ~/kun  →  doctor.ps1  →  notify  →  log
   ~10s             ~5s (diff-gated)    ~3s         <1s        <1s

Total ~20s on a healthy machine. Doesn't block user work.

Notification matrix (from spec #27)

doctor exit Toast Slack GitHub Console (if -Run)
0 (green) Weekly (Mon only) Brief OK
2 (warnings) ⚠️ Full table
3 (updates) 🔄 with "Run doctor -Update" button Update list
1/4 (errors) Yes via SLACK_WEBHOOK_URL Same comment as -Report Full table

Silent on green is deliberate — notification fatigue kills daily tasks.

Self-update logic

git pull --rebase ~/kun
# Only re-run install.ps1 if .claude/ files actually changed
if (git diff before..after | grep '^.claude/') { install.ps1 }

Diff-gated. Saves cycles when there's no config change.

Log handling

Per-day file at ~/.claude/logs/maintain-<YYYY-MM-DD>.log. Rotated automatically — files older than 30 days are deleted at the start of each run.

[2026-05-16T17:19:54Z] [INFO] start (HOSTNAME)
[2026-05-16T17:19:54Z] [OK]   sync-repos: ok
[2026-05-16T17:19:54Z] [OK]   self-update: no changes on ~/kun
[2026-05-16T17:19:54Z] [INFO] doctor: exit 3
[2026-05-16T17:19:54Z] [OK]   notify: toast (update available)
[2026-05-16T17:19:54Z] [INFO] end (duration 19s)

Scheduled task

maintain -Install creates a daily Windows task armed at 09:00 local (override via -Schedule HH:mm). Uses /RL HIGHEST so it can refresh certificate stores and run elevated cmdlets. Idempotent (/F replaces in place; re-running doesn't duplicate).

If the user isn't running as Administrator, install fails gracefully and prints the manual schtasks command.

Test plan

  • maintain -Install creates task kun-maintain (verify with Get-ScheduledTask)
  • Re-running -Install doesn't duplicate the task
  • maintain -Status shows next run, last result, log path
  • maintain -Uninstall removes the task; idempotent
  • maintain -Run -DryRun exercises full flow without side effects — verified ✅
  • Forced run via Start-ScheduledTask kun-maintain fires real notifications
  • Logs rotate after 30 days (synthetic test: seed old files, run, verify deletion)
  • Self-update only triggers install.ps1 when .claude/ files change in the pulled commits
  • BurntToast install failure falls back gracefully (verified: Send-Toast returns $false, logs continue)
  • SLACK_WEBHOOK_URL not in .env → Slack channel silently skipped
  • All PowerShell files parse without errors — verified ✅

Open items not blocking this PR

  • macOS/Linux equivalents are follow-up work
  • A Pester suite for the pure helpers (log path generation, semver compare, Slack JSON) is nice-to-have, not blocking

Dependencies

This branch stacks on feat/doctor (PR #29). Once #29 merges to main, rebase this onto main and it lands cleanly.

Closes #27

🤖 Generated with Claude Code

Implements spec #27. Composes sync-repos → self-update → doctor → notify
→ log into one autonomous run. Silent on green, visible on yellow, loud
on red.

- New ~/.claude/scripts/maintain.ps1 — main entry point with
  -Install / -Uninstall / -Status / -Run / -DryRun / -Silent flags
- New lib/Notify.ps1 — BurntToast wrapper, Slack webhook poster,
  .env reader for SLACK_WEBHOOK_URL
- Self-update is diff-gated: only re-runs install.ps1 when .claude/
  files actually change on main
- Log rotation: deletes logs/maintain-*.log older than 30 days
- Weekly GitHub snapshot on Mondays (auto via doctor -Report)
- Idempotent scheduled task creation: re-running -Install replaces in place
- Notification matrix:
    exit 0 → silent (Monday: GitHub snapshot)
    exit 2 → toast (warnings)
    exit 3 → toast offering 'doctor -Update'
    other  → toast + slack (errors)

Verified: parses clean, -Status detects unarmed task, -Run -DryRun
exercises the full flow without side effects.

Closes #27

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
kun Ready Ready Preview, Comment May 16, 2026 3:21pm

abdout added a commit that referenced this pull request May 16, 2026
Reflects the reality on the ground after PRs #29/#30/#31 land the
v2 scripts:

onboarding.mdx:
- Promotes 'irm https://kun.databayt.org/install | iex' to the
  recommended path (one paste, one UAC, three OAuth sign-ins)
- Demotes Cowork-driven flow to "Alternative" — still works for
  Pro/Max users who want narration over a bare paste
- Manual fallback updated to use databayt/kun raw URL (the codebase
  one is now tombstoned in databayt/codebase#2)
- Adds 'doctor' to Daily entry points and 'maintain -Install' to
  the manual fallback chain
- "What you end up with" mentions the scheduled task

onboarding-reference.mdx:
- Scripts contract table flipped: bootstrap, doctor, maintain are
  now Shipping (no longer 'Planned v2'); health.ps1 marked Deprecated;
  finish.ps1 reduced to 'Planned (alias for bootstrap)'
- Source-of-truth URL changed from databayt/codebase to databayt/kun
- Migration order section refreshed — 4 of 6 items checked off,
  fresh-VM test + team comms remaining

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant