health

package
v0.5.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Overview

Package health answers "is this actually working", and is careful about the difference between a thing that is fine and a thing nobody looked at.

The old `logos doctor` listed runtimes, tiers and voice engines. It never looked at the vault, the index, or whether any host was wired — so a user with an empty vault and a stale index got a clean bill of health, and the first sign of trouble was an agent answering as though it knew nothing.

That is the same class of failure the hardening pass was built to find: silence presented as success. So every check here resolves to one of three states, and Unknown is a first-class answer rather than something folded into OK. "I could not check the index because there is no index" is useful; "ok" in its place is a lie that costs an afternoon.

Index

Constants

This section is empty.

Variables

View Source
var HomebrewPrefixes = func() []string {
	prefixes := []string{"/opt/homebrew", "/usr/local", "/home/linuxbrew/.linuxbrew"}
	if p := os.Getenv("HOMEBREW_PREFIX"); p != "" {
		prefixes = append([]string{p}, prefixes...)
	}
	return prefixes
}

HomebrewPrefixes are where a Homebrew logos is looked for: HOMEBREW_PREFIX, which `brew shellenv` sets, then brew's defaults on Apple silicon, Intel macOS and Linux. A variable so a test never finds the machine's real brew.

Functions

func HomebrewInstall added in v0.4.6

func HomebrewInstall(self string) (path, version string)

HomebrewInstall is the logos Homebrew has installed, and its version, or "" when there is none other than self. The opt path is returned rather than the Cellar one it links to: that link is what survives an upgrade, so it is the path a host config should name.

func UnderTempDir

func UnderTempDir(path string) bool

UnderTempDir reports whether path sits inside a system temporary directory.

Every well-known temp root is checked, not just os.TempDir(). os.TempDir() answers $TMPDIR, which on macOS is a per-user directory under /var/folders — and the directory that actually repointed a real installation was under /tmp, which shares no prefix with it. Agent scratchpads, mktemp -d scripts and half the shell in this repository use /tmp; a guard that cannot see it is a guard against the one case that has never happened.

Both sides are resolved through symlinks first: /tmp answers to /private/tmp and /var/folders/... to /private/var/folders/..., and a string compare of the two forms says they are unrelated.

Types

type Check

type Check struct {
	Name   string
	State  State
	Detail string
	// Fix is what the user should do, when there is something to do. Empty for
	// checks that pass or that the user cannot act on.
	Fix string
}

A Check is one question and its answer.

func CheckOtherInstall added in v0.4.4

func CheckOtherInstall(self, version string) Check

CheckOtherInstall finds a second logos that runs instead of this one. An npx setup pins a copy in ~/.local/bin, which Claude Code's installer puts ahead of Homebrew on PATH, so after a later `brew install` the shell, setup and so every host kept running the old copy, `brew upgrade` reached nothing that ran, and nothing said there were two. A zero Check means none was found.

func CheckPlugin added in v0.4.4

func CheckPlugin(version string) (c Check)

CheckPlugin is checkPlugin for setup, which skips Claude Code on the plugin's account and so owes the same warning. A zero Check means no plugin connects Claude Code.

func Integration

func Integration(bin string, args []string, vault string) []Check

Integration proves the wiring end to end, by being the host.

Registering a server and having a working integration are not the same thing, and until now nothing checked the difference: setup wrote config files, said four hosts were connected, and the first evidence to the contrary arrived inside Claude or Cursor as an unhelpful connection error.

The obvious probe — initialize, then tools/list — is not enough. A server pointed at the *wrong vault* passes both perfectly while knowing nothing about the user's work, and that is the failure most worth catching, because it looks exactly like logos being useless rather than logos being misconfigured. So this writes a disposable checkpoint, reads it back through resume, and confirms the file landed in the vault that was configured — then removes it.

Needs no model: every tool it exercises is markdown and SQL. args is the server's argument list rather than a hardcoded "mcp serve", because the command written into a host config is not always this binary: an npx install is wired as `npx -y @noeton/logos mcp serve`, and a probe that launched the running executable instead would pass while the thing the host will actually run was never tried.

type Input

type Input struct {
	Vault string
	// DB is an open index. Nil means the index could not be opened, so anything
	// derived from it is unknown rather than absent.
	DB *sql.DB
	// Runtime is the runtime the server would use, or nil if none answered.
	Runtime *provider.Provider
	// Configured is LOGOS_RUNTIME, when set. With Runtime nil it means the
	// runtime the user named is down, which is not the same as having none.
	Configured string
	EmbedModel string
	// Hosts drives the duplicate-registration check. Nil means "not asked" —
	// distinct from "asked and found nothing" — and reports Unknown, because
	// listing a host's real registrations means shelling out to another
	// application's CLI, which a caller should opt into rather than pay for on
	// every unrelated health check.
	Hosts []setup.Host
	// Version is this binary's release, for comparing against the Claude Code
	// plugin's. "dev" or empty means there is nothing to compare.
	Version string
	// Self is this binary's path with symlinks resolved, for finding another
	// logos that runs instead of it. Empty skips that check.
	Self string
}

Input is what the checks have to work with. Every field is optional: a nil DB or provider produces Unknown for the checks that need it, which is the whole point of the package.

type Report

type Report struct {
	Checks []Check
}

A Report is every check, in the order they were run.

func Run

func Run(in Input) Report

Run performs every check.

func (*Report) Add

func (r *Report) Add(c Check)

Add appends a check.

func (Report) Counts

func (r Report) Counts() (ok, warn, failed, unknown int)

Counts summarises the report, which is what a caller needs to decide an exit code or a headline.

func (Report) Healthy

func (r Report) Healthy() bool

Healthy reports whether nothing is broken. Unknowns do not make a system unhealthy — they make it unverified, which is a different sentence. Nor do warnings: a queue waiting to be reviewed is the product working, and a verdict that cannot tell that from a corrupt index is a verdict nobody reads.

type State

type State string

State is what a check concluded.

const (
	// OK means checked, and fine.
	OK State = "ok"
	// Failed means checked, and broken. Actionable.
	Failed State = "failed"
	// Warn means checked, working, and holding a backlog — a chore, not a
	// defect. Sessions nobody checkpointed, proposals nobody reviewed: work
	// waiting on the user, which has to be visible without being graded as
	// breakage. Without this tier the three chore checks each picked a side and
	// disagreed: one was Failed, so `logos doctor` exited 1 forever on a
	// perfectly healthy install, and the other two were OK, which hid them.
	Warn State = "warn"
	// Unknown means not checked — a precondition was missing, so no claim is
	// made either way. Never use this for "probably fine".
	Unknown State = "unknown"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL