app

package
v0.2.0 Latest Latest
Warning

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

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

Documentation

Overview

Package app holds the dependency-injection builders and config predicates that assemble the RunLore agent. They live here (instead of in cmd/lore behind main()) so the wiring that decides what ships is unit-testable.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildApprovals

func BuildApprovals(cfg *config.Config, exec action.Executor, aud audit.Auditor, log *slog.Logger) *action.Approvals

BuildApprovals enables rung-2 approval-gated execution for action mode "approve" (requires a reachable cluster).

func BuildAuditor

func BuildAuditor(cfg *config.Config) (audit.Auditor, func(), error)

BuildAuditor opens the append-only action audit log when configured, else a no-op. Validate already requires AuditLogPath when actions.mode=auto.

func BuildAuto

func BuildAuto(cfg *config.Config, exec action.Executor, aud audit.Auditor, log *slog.Logger) *action.Auto

BuildAuto enables rung-3 unattended execution for action mode "auto" (requires a reachable cluster). Heavily gated: reversible-only, confidence-floored, rate- limited, kill-switchable, and audited. The rung is EXPERIMENTAL and FROZEN (FEAT-1): unattended execution contradicts the read-only-first posture and is the only path that turns a prompt-injected finding into a cluster mutation, so it gets no further investment and may be removed — prefer "approve", which captures nearly all the value. Recommend dry_run if you evaluate it.

func BuildCatalog

func BuildCatalog(ctx context.Context, cfg *config.Config, forgeTok ForgeToken, metrics *telemetry.Metrics, log *slog.Logger) *catalog.Catalog

BuildCatalog returns the kb_search backing store, or nil when no catalog is configured. With a Git URL it starts a background syncer (running on every replica, so a failover standby is already warm) that re-indexes after each pull; otherwise it loads a static mounted directory once.

func BuildCurator

func BuildCurator(cfg *config.Config, token ForgeToken, cat *catalog.Catalog, metrics *telemetry.Metrics, log *slog.Logger) *curator.Curator

BuildCurator returns a Curator when the GitHub App token + KB repo are configured, else nil.

func BuildFailureDebouncer

func BuildFailureDebouncer(cfg *config.Config, gp providers.GitOpsProvider, metrics *telemetry.Metrics, log *slog.Logger) *investigate.Debouncer

BuildFailureDebouncer wires a Debouncer whose "still failing?" re-check reads the workload's CURRENT Ready condition via GitOpsInspector.ResourceStatus. When the engine offers no inspector, the predicate is nil and the debouncer just waits out the window before enqueuing (still filtering instantly-clearing flaps). A zero window makes Debounce enqueue immediately.

func BuildGitOps

func BuildGitOps(cfg *config.Config, dc dynamic.Interface, log *slog.Logger) providers.GitOpsProvider

BuildGitOps builds the GitOps provider for the configured engine (flux default). The differ clones the GitOps source repo over HTTPS; it authenticates private repos with the shared GitHub App installation token (the App needs contents:read on the source repo). A nil token source (no App configured) means public/local repos only.

func BuildInvestigator

func BuildInvestigator(ctx context.Context, cfg *config.Config, gp providers.GitOpsProvider, approvals *action.Approvals, auto *action.Auto, metrics *telemetry.Metrics, ledger *outcome.Ledger, log *slog.Logger) (investigate.Investigator, *catalog.Catalog, error)

BuildInvestigator returns the LLM ReAct investigator when a model is configured, otherwise the read-only LogInvestigator. It also returns the catalog (nil when no model is configured or no catalog is wired).

func BuildJudgeModel

func BuildJudgeModel(cfg *config.Config, provider, baseURL, model, apiKeyEnv string) providers.ModelProvider

BuildJudgeModel builds the (stronger) grader model from --judge-* flags, falling back to the configured investigation model when unset.

func BuildModel

func BuildModel(cfg *config.Config, apiKey string) providers.ModelProvider

BuildModel builds the ModelProvider for the configured provider.

func BuildModelAndTools

BuildModelAndTools assembles the model, investigation tools, and the instant-recall short-circuit from config + the GitOps provider. Shared by serve and investigate.

func BuildNotifier

func BuildNotifier(cfg *config.Config, log *slog.Logger) (*notify.Multi, error)

BuildNotifier assembles the configured chat notifiers (best-effort fan-out) via the notifier registry. Slack/Matrix (and any registered sink, e.g. the generic webhook) self-register; each Build reads its own config.

func BuildReinvestigator

func BuildReinvestigator(ctx context.Context, cfg *config.Config, gp providers.GitOpsProvider, metrics *telemetry.Metrics, log *slog.Logger) *investigate.Reinvestigator

BuildReinvestigator returns a poller that re-runs KB issues labelled "reinvestigate" and posts the fresh findings back, or nil when the forge isn't configured. RunLore polls the forge (outbound) — it has no inbound webhooks.

func BuildVerifyModel

func BuildVerifyModel(cfg *config.Config) providers.ModelProvider

BuildVerifyModel builds the optional cheaper model for the adversarial verify pass, inheriting any unset field from the main model. Returns nil when no model.verify override is configured (verify then runs on the main model).

func CatalogConfigured

func CatalogConfigured(cfg *config.Config) bool

CatalogConfigured reports whether the operator asked for a knowledge catalog (a mounted dir or a git-sync repo). It is independent of whether the load succeeded: ReadyFunc uses it to keep a configured-but-failed catalog (which BuildCatalog returns as nil) from collapsing readiness to pure leadership and serving incident traffic with no knowledge base.

func GitOpsFromKube

func GitOpsFromKube(cfg *config.Config, log *slog.Logger) providers.GitOpsProvider

GitOpsFromKube builds the GitOps provider from the ambient kubeconfig (best-effort).

func GitopsEngine

func GitopsEngine(cfg *config.Config) string

GitopsEngine returns the configured GitOps engine, defaulting to flux.

func KubeClientset

func KubeClientset(log *slog.Logger) *kubernetes.Clientset

KubeClientset builds a read-only clientset for pod-log access, or nil when no cluster is reachable (e.g. local runs without a kubeconfig).

func LogLedgerStartup

func LogLedgerStartup(log *slog.Logger, s outcome.Status)

LogLedgerStartup reports, at the right level, what the outcome ledger looks like to this `lore curate` process — turning the previously-silent no-op into a visible warning. The Queue + Recurrence passes read the ledger, but outcome.New succeeds even when the file is absent, so a misconfigured mount (the ledger lives on a volume the CronJob doesn't see — e.g. persistence not enabled, the path not under catalog.mountPath, or a fresh per-Job emptyDir) would silently produce zero work. We still run the passes; we just make the likely misconfiguration loud.

func ModelConfigured

func ModelConfigured(cfg *config.Config) bool

ModelConfigured reports whether a usable model is configured: a provider with a built-in default endpoint (anthropic, gemini), or any provider with a base_url.

func ModelProvider

func ModelProvider(cfg *config.Config) string

ModelProvider returns the configured model provider name (default "openai").

func NewHTTPServer

func NewHTTPServer(addr string, h http.Handler) *http.Server

NewHTTPServer builds the serving http.Server with every inbound bound set. Go's zero defaults leave each of these unlimited, exposing the long-lived server to Slowloris (slow header/body), unbounded idle keep-alives, and oversized headers. Payloads (Alertmanager/Slack) are small and synchronous, so 30s read/write is generous while still cutting off slow attackers; the body itself is capped per handler (1 MiB).

func NewModelClient

func NewModelClient(provider, baseURL, model, apiKey string) providers.ModelProvider

NewModelClient builds a ModelProvider for a wire protocol + endpoint.

func OutcomeKind

func OutcomeKind(recalled bool) string

OutcomeKind labels an outcome-ledger open as a recall (cache hit) or a fresh finding.

func PodName

func PodName() string

PodName returns this pod's identity for leader election.

func PodNamespace

func PodNamespace() string

PodNamespace resolves the namespace from the downward API or the service-account mount.

func ReadyFunc

func ReadyFunc(leader func() bool, cat *catalog.Catalog, configured bool) func() bool

ReadyFunc gates readiness on leadership AND a warm catalog. When a catalog is configured, the leader must NOT advertise ready until its knowledge base is loaded and warm — otherwise it would serve incident traffic blind. This distinguishes the two ways BuildCatalog returns a nil catalog:

  • configured but the load failed (configured=true, cat=nil): stay 503. A static catalog has no syncer to recover, so the pod stays not-ready and the misconfiguration surfaces loudly instead of silently serving with no KB.
  • not configured at all (configured=false, cat=nil): no catalog gate; readiness is pure leadership.

A configured-but-not-yet-warm catalog (git-sync NewEmpty, cat!=nil && !Ready()) is also held at 503 until its first successful sync.

func RequireWebhookAuth

func RequireWebhookAuth(cfg *config.Config, webhookToken string) error

RequireWebhookAuth fails closed on the serve path when the LLM investigator is wired but the alert webhook is anonymous. The webhook's labels/annotations flow verbatim into the LLM prompt (and bill the model), so an unauthenticated caller must not reach it once a model is configured — regardless of actions.mode. This lives on the serve path, NOT in config.Validate: Validate is shared by every subcommand (e.g. `lore investigate` legitimately needs a model and has no webhook), so the requirement is scoped to where the webhook is actually served. It mirrors the approval-token fail-closed guard.

func RestConfig

func RestConfig() (*rest.Config, error)

RestConfig builds a Kubernetes REST config from in-cluster config, falling back to the local kubeconfig (respecting $KUBECONFIG, then ~/.kube/config).

func RunCatalog

func RunCatalog(args []string) error

RunCatalog dispatches catalog subcommands.

func RunCatalogSync

func RunCatalogSync(args []string) error

RunCatalogSync clones/pulls the catalog Git repo into the mirror and reports the indexed entry count — a one-shot of the background sync that serve runs.

func RunCurate

func RunCurate(args []string) error

RunCurate grooms the KB backlog (Phase-2 curation agent). It runs the backlog-dedup pass (collapses duplicate open PRs across history) and the lifecycle sweep (closes stale, unprotected PRs by forge age). When outcome.ledger_path is configured, it also runs the Queue pass (promotes solved→ready-to-merge when the incident resolves) and the Recurrence pass (opens a knowledge-gap issue for repeatedly-unresolved patterns).

func RunEval

func RunEval(args []string) error

RunEval replays recorded incident cases through the investigation loop and reports the RCA-identification rate. Requires a configured model.

func RunEvalLive

func RunEvalLive(cfg *config.Config, scnDir, recordDir, reportDir, prevReport, stamp string, n int,
	jProvider, jBaseURL, jModel, jKeyEnv string) error

RunEvalLive runs the live-fire campaign and writes a dated report.

func RunInvestigate

func RunInvestigate(args []string) error

RunInvestigate runs a single on-demand investigation and prints the findings.

func RunLeaderElection

func RunLeaderElection(ctx context.Context, cfg *config.Config, cs *kubernetes.Clientset, leader *atomic.Bool, log *slog.Logger, startWork func(context.Context))

RunLeaderElection blocks running Lease-based leader election; the leader runs startWork and reports ready. Lost leadership cancels the work context.

func RunMCP

func RunMCP(version string, args []string) error

RunMCP serves RunLore's GitOps what-changed capability over the Model Context Protocol (stdio JSON-RPC), so an MCP client (e.g. HolmesGPT) can call it as a toolset. stdout is the protocol channel; logs go to stderr. Read-only. version is injected at build time and stays in package main; it is passed through to the MCP server's advertised server info.

func RunServe

func RunServe(version string, args []string) error

RunServe runs the in-cluster agent: it loads config, builds the investigation pipeline (kube/GitOps/model/catalog/actions), runs leader election, and serves the webhook + readiness endpoints until SIGTERM, then drains gracefully. version is injected at build time and stays in package main; it is passed through for the build-info gauge.

func SetMemoryLimitFromCgroup

func SetMemoryLimitFromCgroup(log *slog.Logger)

SetMemoryLimitFromCgroup sets GOMEMLIMIT to ~90% of the cgroup v2 memory limit so the Go GC respects the container's memory cap — keeping the heap under a soft ceiling and returning memory to the OS under pressure — instead of letting RSS grow across investigations until the cgroup OOM-kills the process. No-op when GOMEMLIMIT is set explicitly, or there is no cgroup memory limit.

Types

type ForgeToken

type ForgeToken func(context.Context) (string, error)

ForgeToken mints GitHub App installation tokens.

func BuildForgeTokenSource

func BuildForgeTokenSource(cfg *config.Config, log *slog.Logger) ForgeToken

BuildForgeTokenSource builds the GitHub App installation-token source shared by the curator (issues/PRs) and catalog git-sync (clone auth) — one identity for both forge writes and reads. Returns nil when no App is configured.

Jump to

Keyboard shortcuts

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