---
name: notification-config
description: ntfy.sh topic + escalation policy for the orchestrator handoff daemon. Read by `daemon/lfo_handoff_daemon.py` at startup.
authored_by: claude-code-orchestrator
created: 2026-05-08
---

# Notification configuration

## ntfy topic

topic: rocky-lfcs-in76m24d

This is a randomly-generated subscriber-only topic on the free public ntfy.sh service. It is effectively private (the topic name is the access secret — anyone who knows the topic can subscribe AND can publish, so don't share it).

## How Rocky subscribes from his phone

1. Install **ntfy** app from the App Store (iOS) or Play Store (Android). Free, open-source, no signup.
2. Open the app, tap **+**, choose "Subscribe to topic."
3. Enter topic name: `rocky-lfcs-in76m24d`
4. Leave server URL as default (`https://ntfy.sh`).
5. Save. Push notifications fire immediately when the daemon publishes.

Alternative: subscribe via web at `https://ntfy.sh/rocky-lfcs-in76m24d` (browser tab stays open as a real-time push receiver).

## Notification trigger pattern

| Trigger | Priority | Body |
|---|---|---|
| New orch-to-pricer message | high | "Phase {N}. Switch to lfp terminal and run 'check handoff'." |
| New pricer-to-orch message | high | "Phase {N}. Switch to lfo terminal and run 'check handoff'." |
| Rocky-gate idle 30 min | high | "Rocky input needed — {question}" (1st escalation) |
| Rocky-gate idle 60 min | urgent | "Rocky input needed — {question}" (2nd escalation) |
| Rocky-gate idle 90 min | urgent | "Rocky input needed — {question}" (3rd escalation; daemon also writes stall diagnostic block to pricer-to-orch.md) |
| Bid completed (Phase 7 close) | default | "Bid {id} ready for review. Open `assumptions-log-{id}.md` and `priced-take-off-{id}.md` in lfo terminal." |

After 3 escalations on the same Rocky-gate, daemon stops sending and writes a diagnostic block. No further notifications fire until the gate is resolved (rocky_gate_active set to false in state.json).

## Daemon startup

```powershell
# Start daemon in background (PowerShell)
Start-Process python -ArgumentList "C:\Users\mclou\rateright-growth-deploy\HQ-Vault\11_OpsMan_LFCS\Codebase\lfcs-orchestrator\daemon\lfo_handoff_daemon.py" -WindowStyle Hidden

# Or foreground (for debugging)
python "C:\Users\mclou\rateright-growth-deploy\HQ-Vault\11_OpsMan_LFCS\Codebase\lfcs-orchestrator\daemon\lfo_handoff_daemon.py"
```

Or register as Windows Task Scheduler entry to launch on user logon.

To stop: kill the python process (`Get-Process python | Stop-Process` or Ctrl+C if running foreground).

Daemon log lives at `C:/Users/mclou/lfcs-handoff/daemon.log`.

## Topic rotation

If the topic gets noisy (someone else subscribes / publishes spam), rotate:
1. Generate a new topic with `python -c "import secrets, string; print('rocky-lfcs-' + ''.join(secrets.choice(string.ascii_lowercase + string.digits) for _ in range(8)))"`
2. Update the `topic:` line above.
3. Restart the daemon.
4. Re-subscribe on phone with the new topic.

## Failure modes

- **Daemon offline (process not running):** notifications don't fire; handoff files still work via manual Rocky shepherding. Log: "no notifications sent — daemon offline."
- **No internet on the daemon's host:** ntfy POST returns connection error; daemon logs it but keeps polling. Local handoff state still updates correctly.
- **Topic config missing:** daemon logs "WARNING: no ntfy topic configured" and continues running with notifications disabled. State + handoff still works.
- **ntfy.sh service down:** rare but possible. Daemon's ntfy POST returns non-2xx; logs it; next escalation tries again. Self-heals when service returns.

## Privacy note

ntfy.sh is a public service. The topic name is the access control. Body content of notifications is sent over HTTPS but stored ephemerally on ntfy.sh servers (no end-to-end encryption). Therefore: NEVER include client names, contract values, rate sheets, or any external-confidential content in notification bodies. Generic phase + bid_id + "check handoff" wording only. Daemon enforces this via body-content rules in `lfo_handoff_daemon.py`.
