feat(linux): add systemd --user discovery to Services.ts status/doc - #1705
Open
takanorinishida wants to merge 1 commit into
Open
feat(linux): add systemd --user discovery to Services.ts status/doc#1705takanorinishida wants to merge 1 commit into
takanorinishida wants to merge 1 commit into
Conversation
Services.ts's own doc comment says status "reports reality, not a hand-maintained guess" — but loadedLabels()/findPlist()/cadenceOf() only ever looked at launchctl/~/Library/LaunchAgents, so on Linux every one of the 16 registered services reported "✗ missing" regardless of what's actually installed. After the systemd backends landed for WorkSweep (danielmiessler#1692) and DerivedSync/CommitmentSweep/UsageAggregator/CodexUpdate (this branch's prior commit upstream), that's no longer true — but Services.ts had no way to know it. Adds a process.platform branch to the three discovery functions: - loadedLabels(): darwin parses `launchctl list`; linux parses `systemctl --user list-units --all --type=service,timer,path`, stripping the .service/.timer/.path suffix so a label counts as loaded from any of its unit files (same "loaded, not necessarily running" semantics launchctl list already had). - findPlist(): darwin looks for an installed plist then a template in TOOLS/PULSE; linux looks for an installed unit (preferring .timer or .path over .service, since that's where the schedule lives) then a template, falling back to a bare .service for persistent daemons with no timer pairing (pulse — the systemd analog of a RunAtLoad-only launchd job) or a bare non-.template unit (pulse's own manage.sh keeps its systemd source that way, mirroring the plist side's existing dual lookup). - cadenceOf(): darwin parses StartInterval/StartCalendarInterval/ WatchPaths/RunAtLoad from XML; linux parses PathModified/OnCalendar/ OnUnitActiveSec/Type=simple from the ini-style unit file. install/uninstall need no branch — they just run each service's `install:` command, which is itself platform-dispatching inside the Install*.ts script; Services.ts never had to know how a service installs itself, only how to tell whether it did. Services with no Linux port yet (com.lifeos.pulse-menubar, com.lifeos.deriver — both launchd-only by design, deriver explicitly per its own manage-deriver.sh: "Linux/systemd analog is intentionally not implemented") correctly continue to report "✗ missing" on Linux. That's fact, not a regression — same as before this change, just now for the right reason instead of a systemic launchd-only blind spot. Every deletion in this diff is a function signature line whose body moved unchanged into a renamed *Darwin variant, with the original name now the platform-dispatching wrapper — same pattern used across InstallWorkSweep.ts and the four Install*.ts scripts this branch depends on. Verified on this host (Ubuntu 24.04, systemd 255) with all 6 currently- installed systemd services live (pulse, derivedsync, worksweep, commitmentsweep, usage-aggregator, codexupdate): bun Services.ts status ● running at load Pulse (dashboard server) ● running on file-change Derived-file sync ● running every 1h Work sweep ● running daily/scheduled Commitment sweep ● running daily/scheduled Codex update ● running daily/scheduled Usage aggregator Every cadence string matches the actual installed unit content (OnUnitActiveSec=60min → "every 1h", OnCalendar daily entries → "daily/scheduled", the derivedsync .path's PathModified → "on file-change", pulse's Type=simple with no timer/path → "at load"). The 10 not-yet-ported services (Conduit, healthsync, blogdiscovery, etc.) correctly show "✗ missing". `bun Services.ts doc` also verified — produces the same markdown table shape as the darwin-generated one, just reflecting Linux's currently-narrower coverage. darwin path unaffected: `bunx tsc --noEmit` shows only pre-existing @types/node-absence noise, no new errors; the 3 renamed *Darwin functions are byte-for-byte identical to their pre-change bodies.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's broken
Services.ts's own doc comment saysstatus"reports reality, not a hand-maintained guess" — butloadedLabels()/findPlist()/cadenceOf()only ever look atlaunchctl/~/Library/LaunchAgents, so on Linux every one of the 16 registered services reports "✗ missing" regardless of what's actually installed. After the systemd backends for WorkSweep (#1692) and DerivedSync/CommitmentSweep/UsageAggregator/CodexUpdate (#1704) land, that's no longer true — butServices.tshas no way to know it.Fix
Adds a
process.platformbranch to the three discovery functions:loadedLabels(): darwin parseslaunchctl list; linux parsessystemctl --user list-units --all --type=service,timer,path, stripping the.service/.timer/.pathsuffix so a label counts as loaded from any of its unit files (same "loaded, not necessarily running" semanticslaunchctl listalready had).findPlist(): darwin looks for an installed plist then a template inTOOLS/PULSE; linux looks for an installed unit (preferring.timeror.pathover.service, since that's where the schedule lives) then a template, falling back to a bare.servicefor persistent daemons with no timer pairing (pulse — the systemd analog of a RunAtLoad-only launchd job) or a bare non-.templateunit (pulse's ownmanage.shkeeps its systemd source that way, mirroring the plist side's existing dual lookup).cadenceOf(): darwin parsesStartInterval/StartCalendarInterval/WatchPaths/RunAtLoadfrom XML; linux parsesPathModified/OnCalendar/OnUnitActiveSec/Type=simplefrom the ini-style unit file.install/uninstallneed no branch — they just run each service'sinstall:command, which is itself platform-dispatching inside theInstall*.tsscript;Services.tsnever had to know how a service installs itself, only how to tell whether it did.Services with no Linux port yet (
com.lifeos.pulse-menubar,com.lifeos.deriver— both launchd-only by design, deriver explicitly per its ownmanage-deriver.sh: "Linux/systemd analog is intentionally not implemented") correctly continue to report "✗ missing" on Linux. That's fact, not a regression.Why this doesn't change macOS behavior
Every deletion in this diff is a function signature line whose body moved unchanged into a renamed
*Darwinvariant, with the original name now the platform-dispatching wrapper — same pattern used acrossInstallWorkSweep.tsand the fourInstall*.tsscripts this depends on.Verification
Tested on Ubuntu 24.04 / systemd 255 with all 6 currently-installed systemd services live (pulse, derivedsync, worksweep, commitmentsweep, usage-aggregator, codexupdate):
Every cadence string matches the actual installed unit content (
OnUnitActiveSec=60min→ "every 1h",OnCalendardaily entries → "daily/scheduled", derivedsync's.pathPathModified→ "on file-change", pulse'sType=simplewith no timer/path → "at load"). The 10 not-yet-ported services (Conduit, healthsync, blogdiscovery, etc.) correctly show "✗ missing".bun Services.ts docalso verified — produces the same markdown table shape as the darwin-generated one, reflecting Linux's currently-narrower coverage.darwin path unaffected:
bunx tsc --noEmitshows only pre-existing@types/node-absence noise, no new errors; the 3 renamed*Darwinfunctions are byte-for-byte identical to their pre-change bodies.Depends on: #1704 (the 4 installers whose systemd units this reads).
🤖 Generated with Claude Code