|
|
|
|
@@ -1,5 +1,9 @@
|
|
|
|
|
# One-shot Job that seeds Hermes' built-in cron schedule on first install.
|
|
|
|
|
# Idempotent: skips job names that already exist.
|
|
|
|
|
# One-shot Job that seeds Hermes' built-in cron schedule.
|
|
|
|
|
# Reconciles: on every run it deletes any existing job with the same name and
|
|
|
|
|
# recreates it with the prompt/schedule below, so changes to this file (e.g.
|
|
|
|
|
# prompt wording) are applied to the live schedule on the next ArgoCD sync.
|
|
|
|
|
# Note: this means live `hermes cron edit` changes will be overwritten — edit
|
|
|
|
|
# the prompts here in Git instead and let ArgoCD reconcile.
|
|
|
|
|
#
|
|
|
|
|
# Cron prompts are deliberately written as plain-English instructions (no inline
|
|
|
|
|
# curl commands) to avoid tripping Hermes' threat-pattern scanner, which blocks
|
|
|
|
|
@@ -54,40 +58,44 @@ spec:
|
|
|
|
|
POD=$(kubectl -n home-manager get pod -l app=hermes -o jsonpath='{.items[0].metadata.name}')
|
|
|
|
|
echo "Using pod: $POD"
|
|
|
|
|
|
|
|
|
|
# Returns 0 if a cron job with this name already exists.
|
|
|
|
|
exists() { kubectl -n home-manager exec "$POD" -- hermes cron list 2>/dev/null | grep -qi " $1 "; }
|
|
|
|
|
|
|
|
|
|
# Reconcile a cron job to the desired state defined in Git: if a job
|
|
|
|
|
# with this name already exists, delete it first so the (re)create
|
|
|
|
|
# below picks up prompt/schedule changes instead of being skipped.
|
|
|
|
|
create() {
|
|
|
|
|
name="$1"; schedule="$2"; deliver="$3"; prompt="$4"
|
|
|
|
|
if exists "$name"; then
|
|
|
|
|
echo "cron job '$name' already exists — skipping"
|
|
|
|
|
else
|
|
|
|
|
echo "deleting existing cron job '$name' to apply updates ..."
|
|
|
|
|
kubectl -n home-manager exec "$POD" -- hermes cron delete "$name" || true
|
|
|
|
|
fi
|
|
|
|
|
echo "creating cron job '$name' ..."
|
|
|
|
|
kubectl -n home-manager exec "$POD" -- hermes cron create "$schedule" "$prompt" --name "$name" --deliver "$deliver"
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ---- Watchdog checks (silent unless something is wrong) ----
|
|
|
|
|
create "door-window-check" "every 15m" "discord" \
|
|
|
|
|
"Check the Home Assistant REST API as documented in your SOUL.md. List all door and window sensor entities (binary_sensor.* for doors, windows, contact sensors). If any are open and either no one is home (check zone.home or presence sensors) or it is between 23:00 and 06:00, notify Roger with which sensor is open. If all closed, reply with exactly [SILENT]."
|
|
|
|
|
"Check the Home Assistant REST API as documented in your SOUL.md. List all door and window sensor entities (binary_sensor.* for doors, windows, contact sensors). If any are open and it is between 23:00 and 06:00, notify Roger with which sensor is open. Note: this HA instance has NO presence sensors configured, so do NOT infer 'nobody is home' from missing/absent presence entities — only treat the house as empty if a real presence entity (zone.home / device_tracker / presence binary_sensor) exists AND reports away/off; otherwise occupancy is unknown and you must assume someone might be home. If all closed, reply with exactly [SILENT]."
|
|
|
|
|
|
|
|
|
|
create "leak-moisture-check" "every 10m" "discord" \
|
|
|
|
|
"Check the Home Assistant REST API as documented in your SOUL.md. Look for moisture, water leak, or flood sensor entities (binary_sensor.* moisture/water/leak, sensor.* moisture). If any report wet/active, alert Roger immediately with the sensor name and location. If all dry, reply with exactly [SILENT]."
|
|
|
|
|
|
|
|
|
|
create "energy-anomaly" "every 30m" "discord" \
|
|
|
|
|
"Check the Home Assistant REST API as documented in your SOUL.md. Read the current power draw sensor (sensor.* power, sensor.* current_power). If the total power draw is unusually high for the time of day (over 4000 W during the day, or over 800 W when no one is home at night), alert Roger with the reading. Otherwise reply with exactly [SILENT]."
|
|
|
|
|
"Check the Home Assistant REST API as documented in your SOUL.md. Read the current power draw sensor (sensor.* power, sensor.* current_power). If the total power draw is unusually high for the time of day (over 4000 W during the day, or over 800 W at night), alert Roger with the reading. Otherwise reply with exactly [SILENT]."
|
|
|
|
|
|
|
|
|
|
create "comfort-check" "every 1h" "discord" \
|
|
|
|
|
"Check the Home Assistant REST API as documented in your SOUL.md. Read indoor temperature and humidity sensors. If a room is outside a comfortable range (below 18C or above 26C, or humidity above 65 percent), you may toggle a fan entity in that room (safe). Do NOT change climate/HVAC settings yourself — if it is uncomfortable, propose a climate change to Roger on Discord and wait. If everything is comfortable, reply with exactly [SILENT]."
|
|
|
|
|
|
|
|
|
|
create "left-on-check" "every 1h" "discord" \
|
|
|
|
|
"Check the Home Assistant REST API as documented in your SOUL.md. If no one is home (zone.home is away or presence sensors all off), find any lights, media players, fans, or non-critical switches that are on. Turn off the safe non-essential ones (lights, media, fans) and report what you turned off. Do NOT touch anything security-critical. If someone is home, or nothing is left on, reply with exactly [SILENT]."
|
|
|
|
|
"Check the Home Assistant REST API as documented in your SOUL.md. IMPORTANT: this HA instance has NO presence sensors configured. Do NOT infer 'nobody is home' from missing/absent zone.home or presence entities. Only treat the house as empty if a real presence entity (zone.home / device_tracker / presence binary_sensor) exists AND reports away/off. If no such entity exists, occupancy is UNKNOWN — assume someone might be home and do NOT turn things off. Only when presence genuinely reports away/off: find any lights, media players, fans, or non-critical switches that are on, turn off the safe non-essential ones (lights, media, fans), and report what you turned off. Do NOT touch anything security-critical. If someone is home (or unknown), or nothing is left on, reply with exactly [SILENT]."
|
|
|
|
|
|
|
|
|
|
# ---- Routines (always delivered) ----
|
|
|
|
|
create "goodnight-routine" "0 23 * * *" "discord" \
|
|
|
|
|
"Run the goodnight routine via the Home Assistant REST API as documented in your SOUL.md. Turn off all non-essential lights and pause media players (safe actions). Then propose — but do NOT execute — locking the doors (lock.*), closing the garage (cover.* garage), and arming the alarm (alarm_control_panel.*). Ask Roger on Discord for confirmation before calling any of those security-critical services. Deliver a short summary of what you turned off and what you are waiting for confirmation on."
|
|
|
|
|
|
|
|
|
|
create "morning-briefing" "0 7 * * *" "discord" \
|
|
|
|
|
"Produce a morning home briefing for Roger using the Home Assistant REST API as documented in your SOUL.md. Include: (1) who is home (zone.home / presence), (2) any lights or media still on, (3) any doors or windows open, (4) indoor temperatures, (5) today's calendar events if a calendar entity exists, (6) overnight energy use if an energy sensor exists, (7) any sensors in an alert/unavailable state. Keep it under 1800 chars. Always deliver (no [SILENT])."
|
|
|
|
|
"Produce a morning home briefing for Roger using the Home Assistant REST API as documented in your SOUL.md. Include: (1) occupancy status from zone.home / presence sensors IF such entities exist — if they do not exist, state 'presence: no presence sensors configured (occupancy unknown)' rather than claiming no one is home; (2) any lights or media still on, (3) any doors or windows open, (4) indoor temperatures, (5) today's calendar events if a calendar entity exists, (6) overnight energy use if an energy sensor exists, (7) any sensors in an alert/unavailable state. Keep it under 1800 chars. Always deliver (no [SILENT])."
|
|
|
|
|
|
|
|
|
|
echo "Done. Listing all cron jobs:"
|
|
|
|
|
kubectl -n home-manager exec "$POD" -- hermes cron list
|
|
|
|
|
|