Summary
Two bugs in PAI 5.0.0 combine to make the installer report failure even when Pulse starts successfully, and to flood the error log with cron failures on every run.
Bug 1 — manage.sh install timeout too short for launchd startup
File: PAI/Pulse/manage.sh (install case)
Symptom: Installer reports "Pulse install command failed." after upgrading from 4.0.3. Pulse IS running correctly (port 31337 responds 200 OK) — but the report is a false negative.
Root cause: The install verification loop polls port 31337 for only 10 seconds (seq 1 20, 0.5s sleep each):
for _ in $(seq 1 20); do
sleep 0.5
if curl -sS --max-time 1 -o /dev/null -X POST http://localhost:31337/notify ...; then
echo "PAI Pulse installed and verified on port 31337 (bun: $BUN_PATH)"
exit 0
fi
done
echo "ERROR: PAI Pulse plist installed but port 31337 did not bind within 10s." >&2
exit 1
The plist has ThrottleInterval=30. On an upgrade where the previous Pulse was recently active, launchd tracks the label (com.pai.pulse) history even across unload/reload cycles. In this case, launchd can take longer than 10s to dispatch the new process — the window closes before port binds, manage.sh exits 1, and the installer surfaces the failure message. Pulse then starts successfully ~10–30 seconds later.
Proposed fix: Extend the loop to 50 iterations (25s) — well above any realistic launchd dispatch delay, and safely under the installer's 30s hard kill (actions.ts:1596):
# Verify pulse actually binds :31337 within 25s. Fail loud if not — prior
# behavior was silent success even when the daemon never came up.
# 25s > launchd ThrottleInterval=30 edge case on upgrade; fits installer's 30s hard kill.
for _ in $(seq 1 50); do
sleep 0.5
if curl -sS --max-time 1 -o /dev/null -X POST http://localhost:31337/notify ...; then
echo "PAI Pulse installed and verified on port 31337 (bun: $BUN_PATH)"
exit 0
fi
done
echo "ERROR: PAI Pulse plist installed but port 31337 did not bind within 25s." >&2
exit 1
Bug 2 — PULSE.toml DA subsystem jobs reference non-existent scripts
File: PAI/Pulse/PULSE.toml
Symptom: assistant-tasks fails every minute with Module not found "Assistant/checks/tasks.ts". After 3 consecutive failures the job is auto-disabled. assistant-heartbeat fails on its first 30-minute tick. assistant-diary and assistant-growth will fail on their next scheduled runs.
Root cause: PULSE.toml ships four DA subsystem jobs with enabled = true, but the scripts they reference (Assistant/checks/*.ts) do not exist in the release. Per PAI/DOCUMENTATION/Pulse/DaSubsystem.md, the DA subsystem is "architecture complete, pending implementation."
The four affected jobs:
| Job |
Schedule |
Script |
assistant-heartbeat |
*/30 * * * * |
Assistant/checks/heartbeat.ts |
assistant-tasks |
* * * * * |
Assistant/checks/tasks.ts |
assistant-diary |
0 23 * * * |
Assistant/checks/diary.ts |
assistant-growth |
0 4 * * 0 |
Assistant/checks/growth.ts |
Additionally, pulse.ts attempts import('./Assistant/module') at startup. This is caught with try/catch and degrades gracefully (WARN-level log, non-fatal), so Pulse runs fine — but the startup warning is noisy until the module ships.
Proposed fix: Set enabled = false on all four jobs until Assistant/checks/ is implemented. The command and schedule fields should be preserved so re-enabling is a one-line change when the implementation ships.
[[job]]
name = "assistant-heartbeat"
schedule = "*/30 * * * *"
type = "script"
command = "bun run Assistant/checks/heartbeat.ts"
output = "voice"
enabled = false # DA subsystem pending implementation — see DaSubsystem.md
[[job]]
name = "assistant-tasks"
schedule = "* * * * *"
type = "script"
command = "bun run Assistant/checks/tasks.ts"
output = "voice"
enabled = false
# ... same for assistant-diary and assistant-growth
Reproduction
Both bugs reproduce on a fresh upgrade from 4.0.3 → 5.0.0 on macOS with an existing Pulse installation:
- Run the 5.0.0 installer over an existing PAI 4.0.3 install
- Observe installer output: "Pulse install command failed."
- Wait 30–60 seconds; confirm Pulse is actually running:
curl -X POST http://localhost:31337/notify -H 'Content-Type: application/json' -d '{"message":"","voice_enabled":false}' → 200
- Check
PAI/Pulse/logs/pulse-stderr.log → Module not found "Assistant/checks/tasks.ts" repeated until auto-disabled
Environment
- macOS (Darwin) with APFS case-insensitive filesystem
- PAI upgraded from 4.0.3 → 5.0.0
- Pulse previously running as launchd agent (
com.pai.pulse)
Summary
Two bugs in PAI 5.0.0 combine to make the installer report failure even when Pulse starts successfully, and to flood the error log with cron failures on every run.
Bug 1 —
manage.sh installtimeout too short for launchd startupFile:
PAI/Pulse/manage.sh(install case)Symptom: Installer reports
"Pulse install command failed."after upgrading from 4.0.3. Pulse IS running correctly (port 31337 responds 200 OK) — but the report is a false negative.Root cause: The install verification loop polls port 31337 for only 10 seconds (
seq 1 20, 0.5s sleep each):The plist has
ThrottleInterval=30. On an upgrade where the previous Pulse was recently active, launchd tracks the label (com.pai.pulse) history even across unload/reload cycles. In this case, launchd can take longer than 10s to dispatch the new process — the window closes before port binds, manage.sh exits 1, and the installer surfaces the failure message. Pulse then starts successfully ~10–30 seconds later.Proposed fix: Extend the loop to 50 iterations (25s) — well above any realistic launchd dispatch delay, and safely under the installer's 30s hard kill (
actions.ts:1596):Bug 2 —
PULSE.tomlDA subsystem jobs reference non-existent scriptsFile:
PAI/Pulse/PULSE.tomlSymptom:
assistant-tasksfails every minute withModule not found "Assistant/checks/tasks.ts". After 3 consecutive failures the job is auto-disabled.assistant-heartbeatfails on its first 30-minute tick.assistant-diaryandassistant-growthwill fail on their next scheduled runs.Root cause:
PULSE.tomlships four DA subsystem jobs withenabled = true, but the scripts they reference (Assistant/checks/*.ts) do not exist in the release. PerPAI/DOCUMENTATION/Pulse/DaSubsystem.md, the DA subsystem is "architecture complete, pending implementation."The four affected jobs:
assistant-heartbeat*/30 * * * *Assistant/checks/heartbeat.tsassistant-tasks* * * * *Assistant/checks/tasks.tsassistant-diary0 23 * * *Assistant/checks/diary.tsassistant-growth0 4 * * 0Assistant/checks/growth.tsAdditionally,
pulse.tsattemptsimport('./Assistant/module')at startup. This is caught with try/catch and degrades gracefully (WARN-level log, non-fatal), so Pulse runs fine — but the startup warning is noisy until the module ships.Proposed fix: Set
enabled = falseon all four jobs untilAssistant/checks/is implemented. Thecommandandschedulefields should be preserved so re-enabling is a one-line change when the implementation ships.Reproduction
Both bugs reproduce on a fresh upgrade from 4.0.3 → 5.0.0 on macOS with an existing Pulse installation:
curl -X POST http://localhost:31337/notify -H 'Content-Type: application/json' -d '{"message":"","voice_enabled":false}'→ 200PAI/Pulse/logs/pulse-stderr.log→Module not found "Assistant/checks/tasks.ts"repeated until auto-disabledEnvironment
com.pai.pulse)