Add Program to the process package as a lightweight tool-finder and runner.
Find() resolves a binary via exec.LookPath (wrapping ErrProgramNotFound),
Run() and RunDir() execute the binary and return trimmed combined output.
Includes 7 tests covering happy paths, error paths, and the errors.Is contract.
Co-Authored-By: Virgil <virgil@lethean.io>
- RunOptions.Timeout: auto-kills after duration (SIGTERM → SIGKILL)
- RunOptions.GracePeriod: time between SIGTERM and SIGKILL
- RunOptions.KillGroup: kills entire process group (child processes too)
- Process.Shutdown(): graceful SIGTERM → wait → SIGKILL
- OnShutdown uses Shutdown() instead of Kill() for graceful stops
- Runner circular deps now count as Failed, not Skipped
- Tests for all new features
Co-Authored-By: Virgil <virgil@lethean.io>
- Assert SetDefault error return in tests instead of ignoring it
- Pass caller location to wrapError for accurate error traces
- daemon.go reviewed: no actionable finding
Co-Authored-By: Virgil <virgil@lethean.io>
Replace all 27 instances of fmt.Errorf/errors.New in production code
with coreerr.E() from forge.lthn.ai/core/go-log for structured error
context (op, message, cause). Promote go-log from indirect to direct
dependency in go.mod.
Co-Authored-By: Virgil <virgil@lethean.io>
Replace all os.ReadFile, os.WriteFile, os.MkdirAll, os.Remove calls in
pidfile.go and registry.go with coreio.Local equivalents (Read, Write,
EnsureDir, Delete). Add forge.lthn.ai/core/go-io v0.1.2 as a direct dependency.
Co-Authored-By: Virgil <virgil@lethean.io>
RunOptions.Detach creates the process in its own process group
(Setpgid) and uses context.Background() instead of the parent
context. Detached processes survive parent death.
Co-Authored-By: Virgil <virgil@lethean.io>
Resolve stale forge.lthn.ai/core/cli v0.1.0 references (tag never existed,
earliest is v0.0.1) and regenerate go.sum via workspace-aware go mod tidy.
Co-Authored-By: Virgil <virgil@lethean.io>
Five Lit custom elements following the go-scm UI pattern:
- <core-process-panel> tabbed container (Daemons/Processes/Pipelines)
- <core-process-daemons> daemon registry with health checks and stop
- <core-process-list> managed processes with status badges
- <core-process-output> live stdout/stderr WS stream viewer
- <core-process-runner> pipeline execution results display
Also adds provider.Renderable interface to ProcessProvider with
Element() returning core-process-panel tag, extends WS channels
with process-level events, and embeds the built UI bundle via
go:embed.
Co-Authored-By: Virgil <virgil@lethean.io>
Wraps the daemon Registry as a provider.Provider with REST endpoints for
list, get, stop, and health check. Implements Streamable and Describable
for WS event streaming and OpenAPI generation. Adds go-api, go-ws, and
gin as direct dependencies for the pkg/api sub-package.
Co-Authored-By: Virgil <virgil@lethean.io>
When Registry is set on DaemonOptions, Start() auto-registers the daemon
(filling PID and Health address) and Stop() auto-unregisters it. Consumers
without a registry are completely unaffected.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- WaitForHealth: use http.Client with 2s timeout instead of DefaultClient
- Daemon.Stop: use errors.Join for proper error unwrapping
- Remove unused OnReload field from DaemonOptions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>