[2026-06-25] eagle: personal/projects/personal-os/eagle-dashboard.md
This commit is contained in:
@@ -270,6 +270,23 @@ When a launchd cron is created and `launchctl print gui/<uid>/<label>` shows `la
|
||||
1. **`~` not expanded in ProgramArguments.** launchd does not expand `~`. Use full path: `/Users/admin/scripts/foo.sh`
|
||||
2. **Script itself exits 78.** Check script logic: `exit 78` is `EX_CONFIG` (configuration error). Fix the script.
|
||||
|
||||
## Launchd status display — PID & exit code parsing
|
||||
|
||||
`_list_launchd_crons()` parses `launchctl list <label>` output to determine process state:
|
||||
|
||||
- **next-format plist** — macOS Sequoia returns `{ "PID" = 1234; "LastExitStatus" = 0; ... }` (not JSON, not tab-separated)
|
||||
- **PID** — parsed via regex `r'"PID"\s*=\s*(\d+)'`
|
||||
- **LastExitStatus** — parsed via regex `r'"LastExitStatus"\s*=\s*(-?\d+)'`
|
||||
- `state` logic:
|
||||
- `running` — if PID > 0 (process alive right now)
|
||||
- `scheduled` — if no PID but has StartInterval/StartCalendarInterval
|
||||
- `idle` — if no PID, no schedule, but enabled (KeepAlive daemon between ticks)
|
||||
- `stopped` — if disabled (unloaded)
|
||||
- `last_status`: `None` when process is `running` (exit code is meaningless); integer (exit code) when process is not running; `None` when no LastExitStatus field (never run)
|
||||
- **Frontend** displays: `· exit <code>` in green for 0, red for non-zero; `· never run` when `last_status` is None (grey text)
|
||||
|
||||
**Files changed:** `main.py` — `_list_launchd_crons()`, `templates/index.html` — cron card status line
|
||||
|
||||
## Troubleshooting — sync-vault appeared as "none (manual)"
|
||||
|
||||
**Root cause:** Launchd create accepted cron expression `*/5 * * * *` (pre-fix), couldn't parse it into StartInterval, wrote plist without schedule → `_list_launchd_crons()` (pre-fix) filtered it out. Fixed in two ways:
|
||||
@@ -282,6 +299,7 @@ When a launchd cron is created and `launchctl print gui/<uid>/<label>` shows `la
|
||||
|
||||
## History
|
||||
|
||||
|- 2026-06-25 (round 10): **Launchd status — PID/exit code from launchctl list.** Added PID parsing (next-format "PID" = N) and LastExitStatus parsing in `_list_launchd_crons()`. `last_status` is None for running processes, integer exit code otherwise. Frontend shows `· exit <code>` or `· never run`. Legacy tab-separated format no longer supported. macOS launchctl returns next-format plist (not JSON) — regex parsing, not json.loads.
|
||||
|- 2026-06-25 (round 9): **RunAtLoad checkbox for launchd crons.** Added `RunAtLoad` field to launchd plist creation. Backend: `main.py` line 636 changed from `pd["RunAtLoad"] = False` to `pd["RunAtLoad"] = body.get("run_at_load", False)`. Frontend: checkbox "Run on load" in cron modal, shown only for source=launchd via `x-show`; `openAddCron()`, `openCronEdit()`, `saveCronModal()` all wired. Backend `_list_launchd_crons()` returns `run_at_load` for edit modal. **Also fixed:** `_msg` auto-dismiss bug — stale object reference after `fetchCrons()` replaced with `find` in fresh array (both crons and services).
|
||||
- 2026-06-25 (round 7): **Launchd schedule — source-dependent validation.** `validateSchedule()` now takes `source` param. For `launchd`: only `every Ns/m/h/d` accepted; cron and ISO rejected with explicit message. For Eagle/Whale: all three formats. Hints, placeholders, and `prettySchedule()` also differ by source. `Query` import added to FastAPI.
|
||||
- 2026-06-25 (round 6): **Tab URL routing.** Each tab now persists in URL via `?tab=` query-param + `history.replaceState()`. Frontend initializes `activeTab` from URL. Backend accepts `?tab=` on `GET /`. Added `setUrlTab()` to Alpine.js data.
|
||||
|
||||
Reference in New Issue
Block a user