Repository navigation
P5: lazurio module start|stop|status|logs and /api/modules — the module lifecycle over the catalog, systemd user units with journal logs, hosted links only from the recorded entry (base-instructions-11) - #73
Conversation
…unded journalctl tail of one generated unit (launchpad-parity B6) The fixed unit policy changes one property pair: an application's output goes to the user journal instead of being discarded. readApplicationJournal reads the newest lines of one generated unit name (-o cat, at most 1000 lines) through the service-manager process adapter, which gains the read-only journalctl. A unit an older release started with null output is foreign (service-unrecognized) until it is stopped once; the ownership table now proves exactly that transition. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…older.ts writeOrganization and folderFixture are shared by the catalog tests and the module lifecycle tests of slice P5; unchanged otherwise. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…/…: the module lifecycle over the catalog, one core for the CLI and the Launchpad (launchpad-parity B3) - src/modules/module-operations.ts: names a module <Org>/<module> through the catalog's selection rule (an ambiguous slug is refused, a module that cannot run is refused with its catalog reason, an undeclared or invalid --app likewise) and runs its default app, or the named one, through the existing lifecycle, runners and localApplicationAdapters. No state: the running state is the service manager's (Linux) or the Launchpad session's (macOS). - Toolchain from the standard path: Bun is <home>/.local/bin/bun (B2); missing, start is refused as toolchain-missing before any effect. On Linux a started app gets the installed unit's PATH line, so the CLI and the Launchpad start identical units. - The link (runtime.url) only while the app reports healthy: locally the loopback address its owner observed; on a hosted Machine only the recorded entry's moduleOrigin(template, id) for the default app, never a loopback address; without a recorded entry no link (hosted-entry-missing). - CLI: runModuleCommand in src/modules/module-cli.ts; the CLI builds a lifecycle per call, so on a session platform it answers launchpad-required, and logs there logs-unavailable. - HTTP: GET /api/modules/<org>/<module>/status, POST …/start and …/stop behind the existing admission, answering the same objects (409 when refused). The Launchpad holds one lifecycle per Organization and closes them on shutdown (session apps end with it, service apps stay). - /api/apps/* and app-request are unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…d Open while it reports a link (slice P5) The module route /o/<org>/<module> of an executable module shows an Application card in the settings-row pattern: the status (running, starting, not ready, stopping, ended, stopped) with its dot, who keeps it running, why a healthy app has no link, the sentence after the last action (polite live region), and on the right Open (a new tab, only the root of an https hostname or a loopback port) and the one primary action. After Start the page reads the status until the app reports healthy (about half a minute at most); focus returns to the action. The requests are GET .../status and POST .../start|stop, the same core as lazurio module. Pure presentation in src/launchpad/module-view.ts; Czech and English copy; the catalog intro no longer says starting comes later. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ted link only from runtime.url (base-instructions-11) For every preset with Organizations a new section names the commands kept from the resident (root decision 0167): module list, start, stop, status with runtime.url, logs from the journal, the toolchain at ~/.local/bin/bun (toolchain-missing) and prerequisites-not-ready; hosted it says apps are transient user services that survive a Launchpad restart, locally it adds the macOS session rule (launchpad-required). The hosted "Application links" section keeps "never a localhost link", carries the interim sentence of launchpad-parity B14 (a localhost link works only for a process on this Machine) and now names the link as runtime.url, composed only from the recorded entry and never from a naming convention; a null runtime means no link. Generated output changes, so the template revision moves to base-instructions-11 and the existing snapshots are regenerated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…s it changes, and the marked seams of P6, P7 and P9 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ained the held ones Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… and workstations (base-instructions-11) The Recovery page (LazurioPlatform PR #72) offers the repair-agent prompt and the prepared issue; the manual says so and that nothing of it leaves the Machine automatically. Rides on the template revision this branch bumps. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ecycle Both slices add messages and a startLaunchpad parameter; the Recovery page's recovery use case keeps main's position and the module host comes last. The page routes moved to page.ts with #72; the module routes stay. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
agentrozjedemeai
left a comment
There was a problem hiding this comment.
Exact-head review of 81720e1 (P5). Verified the hosted runtime link derives only from the recorded machine.entry.moduleOriginTemplate, never from a hostname convention or a loopback URL; missing entry and non-default app have no hosted link. CLI --json and HTTP start/stop/status share the core and match on the fixture; ambiguous/non-executable/unknown app and missing-Bun starts refuse before spawning. The systemd transient unit has explicit PATH and journal stdout/stderr, journalctl reads a bounded tail, and another Launchpad can rediscover and stop the exact owned unit without changing foreign units. The macOS session ends with its Launchpad. base-instructions-11 snapshots and the Recovery sentence pass. Local bun run check: 897 pass, 4 skip, 0 fail; lint, typecheck, public guard, proof build and smoke pass. Both required GitHub checks (Ubuntu and macOS) succeeded on this exact head; zero unresolved review threads. No blocking findings. No merge performed.
Why
Slice P5 of the Launchpad parity program (root decision 0167 points 1–2, 0137 as amended; shaping #65 B3/B6): the resident Launchpad's module lifecycle, done properly in the Platform and CLI first, so an agent or an operator can run a module's application without the Launchpad, and the Launchpad composes the same core.
What changes
lazurio module start|stop|status|logs <Org>/<module> [--app <package>] [--json]over the catalog of Launchpad home is the catalog: organization list, module list, POST /api/catalog; execution admission variant B (H1 decided) #68: the module is named through the one selection rule (an ambiguous slug is refused), a module that cannot run is refused with its typed reason, unknown or invalid apps are refused. Start runs the module's default app (or the declared--app) from its own declaration with the operator's Bun (~/.local/bin/bun; missing →toolchain-missing, nothing happens); it does not install dependencies (prerequisites-not-readynames the fix). No new Folder state: what runs is what the OS service manager or the session reports.StandardOutput/Error=journal),logsis a boundedjournalctl --usertail of that unit. macOS: apps stay session-bound; the CLI answerslaunchpad-required/logs-unavailable.runtime.urlonly while healthy. Locally the loopback address the app's owner observed; on a hosted Machine onlymoduleOrigin(template, id)from the recorded entry (P3: the Platform reads the handover entry (Launchpad, T3 Code, module origins), schema re-pinned to Machines 0.12.93; module origins by the gateway's label rule #71), default app only, never a loopback address — no recorded entry, no link (hosted-entry-missing).GET /api/modules/<org>/<module>/status,POST …/start|stopbehind the existing admission, returning the same object as the CLI (tests compare; 409 on refusal)./api/apps/*andapp-requestare kept unchanged (their retirement is recorded as open in the docs).runtime.url), the hosted "never send a localhost link" rule now namesruntime.url, and the Recovery page sentence for PR Recovery page: Recovery mode serves the page, GET /api/recovery = lazurio recover, copy the prompt and the prepared issue; the issue names the start refusal (F21) #72 (hosted and workstation).ensure(P6), the T3 chat link (P7) andprepare/open/--source(P9); none implemented.What deliberately does NOT change
No content sync, no ensure, no T3 link, no doctor, nothing of the update core;
/api/apps/*,--organization-directory,--bun-executablestay.Verified
Author of the slice:
bun run check886 pass, exit 0, and the page driven in headless Chromium against the compiled executable (Start → healthy with Open → Stop, no action on a module that cannot run). Thread owner:bun run checkon 71cb9c4 (with the manual sentence added): exit 0.Not verified: a real Ubuntu systemd user manager and journal (whether
journalctl --user --unitreads without persistent per-user journal storage) — that is the C.5 qualification (M3) and the first hosted run.Risks / follow-ups
service-unrecognizeduntil stopped once withsystemctl --user stop— needs a release note.operation-failed(the first holds the module's lock) instead of a clearer "busy".mainafter Recovery page: Recovery mode serves the page, GET /api/recovery = lazurio recover, copy the prompt and the prepared issue; the issue names the start refusal (F21) #72 (Recovery page): messages of both slices kept,startLaunchpadkeeps main'srecoveryposition and takes the module host last, page routes stay inpage.ts. Thread owner'sbun run checkon 81720e1: 897 pass, 0 fail, exit 0.🤖 Generated with Claude Code