Internal Packages
One section per internal/ package. Import paths are
github.com/koryph/koryph/internal/<name>.
account
Constructs the child environment for a dispatch and verifies the logged-in
Claude identity, fail-closed. Supports subscription (OAuth) and api-key
billing modes.
Profile— resolved account context (config dir, expected email)Identity—Email/Organization(subscription) orFingerprint/Label(api-key/oauth-token) established by verificationBillingMode—"subscription"|"api-key"(legacy billing-only fallback; seeAuthModefor the auth-mode-keyed identity path)ChildEnv(spec)— full[]stringchild env; scrubs/re-injects credentials, including the resolvedAuthModecredential under its canonical nameVerify(ctx, p)/VerifyExpected(ctx, p, email)— read and comparesubscription-mode identity (OAuth email), unchangedAuthMode—"subscription"(default) |"api-key"|"oauth-token"(koryph-i3b, design docs/designs/2026-07-api-key-auth.md); aliased fromauthmode's constants to avoid an import cycleVerifyAuth(ctx, p, AuthSpec)— auth-mode-keyed identity verification: delegates toVerifyExpectedforsubscription; forapi-key/oauth-token, resolves the credential, fingerprint-matches it against the enrolledidentity_fingerprint(fail closed on swap), then confirms liveness viaanthro.ProbeLivenessResolveCredential(ctx, mode, cred)— resolves a long-lived credential from a vault reference (signing.FetchSecret) or a purpose-named env var (never the canonicalANTHROPIC_API_KEY/CLAUDE_CODE_OAUTH_TOKENname); returns the canonical env var name to inject under plus the resolved valueFingerprint(credential)— non-secret"sha256:<prefix>"identity signal forapi-key/oauth-tokenaccountsDiscover(ctx)— enumerate candidate profiles (~/.claude.json,~/.claude-*/) with verified identity + provenance, for the adopt wizard's account proposal
adopt
Orchestration logic for the koryph adopt wizard (design:
docs/designs/2026-07-adopt.md): detect → plan → confirm → execute → verify,
sequencing the same primitives project add uses. The CLI glue (flags,
prompts, streaming) lives in cmd/koryph/adopt.go; everything here is pure
or unit-testable.
Detect(ctx, root)— read-onlySnapshot(tools, platform, beads state, account candidates, gate/forge/area_map proposals, registry/config state)BuildPlan(snap)— the ordered[]Stepplan (statesdone|needed|offer|blocked, each with a why)ResolveAccountNonInteractive/ResolveGateNonInteractive/ResolveForgeNonInteractive— fail-closed value resolvers for--yes/non-TTYExecuteBeads/RegisterAndConfigure/InstallAssets/CommitAdoption— idempotent execute-phase steps
agentjson
Helpers for parsing Claude CLI JSON-envelope output: the outer
{result, is_error} envelope whose result field carries the model's text,
which itself is expected to be strict JSON. The single authoritative
implementation shared by internal/review and internal/epicreview so
escape/is_error edge-case fixes propagate to every caller.
ParseEnvelope(out)— unwrap the CLI envelope, error onis_errorSelectJSON(s, requiredKeys...)— pick the first valid JSON block carrying the schema keys (skips non-JSON brace tokens the model quoted)JSONBlocks/FirstJSONBlock/FencedJSONBlocks— balanced-block extractionTail(s, n)— bound an error/log excerpt
agentsmd
Installs the koryph operating contract as AGENTS.md at a managed project's
root — the canonical, runtime-neutral instruction file read natively by Codex,
Cursor, Grok, Copilot, opencode, amp, and (as a fallback) Claude Code; the
cross-runtime counterpart of CLAUDE.md. Installed unconditionally during
project add with the same hash-aware overwrite policy as
scaffold.CopyEmbed (identical → no-op, differing → skipped unless force).
Install(root, force)— write<root>/AGENTS.md; returns ascaffold.Action*constantTemplate()— the embedded contract bytes
anthro
Thin wrapper around anthropic-sdk-go for the two operations koryph uses
directly: single-message inference and pre-flight cost estimation.
Client— holds SDK client;NewClient(keyEnvVar)resolves the key from envMsgReq— request envelope (model, messages, max tokens)Usage— input/output token counts;BatchResult— aggregate batch outcomeEstimateUSD(reqs)— cost estimate for a slice ofMsgReqProbeLiveness(ctx, credential, useBearer)— freeGET /v1/modelsliveness check for a resolved long-lived credential (koryph-i3b):x-api-keywhenuseBeareris false (api-key mode),Authorization: Bearer+anthropic-beta: oauth-2025-04-20when true (oauth-token mode); never logs the credential
authmode
Dependency-free leaf package holding the auth-mode/credential data shared by
registry, quota, and account (koryph-i3b, design
docs/designs/2026-07-api-key-auth.md §4-§6): registry imports quota
(registry/store.go) and quota imports account (quota/usage.go), so
account importing registry directly would cycle. Before this package
existed, the constants and Credential struct were hand-mirrored in all
three packages; each now re-exports these via a local alias so existing
call sites are unaffected.
Subscription/APIKey/OAuthToken— auth-mode string constantsCredentialSourceVault/CredentialSourceEnv— credential source kindsCredential— long-lived credential reference (Source,Provider,KeyRef,EnvVar); never the secret itself
beads
Adapts the bd CLI. The only package that shells out to bd; all other
packages consume its types.
Adapter— wraps a repo root;New(repoRoot)is the constructorIssue— parsed beads issue (ID, title, status, labels, …)ReadyOpts— filters forbd readyqueries
bot
Implements the GitHub App Manifest flow for the koryph bot command family:
app creation (the localhost-redirect manifest dance), credential persistence,
and installation URL generation. Credentials live at
~/.koryph/bots/<name>.json (mode 0600) in pointer mode (a vault
Provider + KeyRef; ResolveKey fetches the PEM at JWT-mint time) or
legacy inline mode (PEM in the file, opt-in via --plaintext). GitLab has
no App identity, so the *GitLab variants run a project/group access-token
flow instead.
Create/Attach/Check/List/Load— thekoryph botverbs (GitHub)CreateGitLab/AttachGitLab/CheckGitLab— the token-flow equivalentsResolveKey— fetch the private key from its vault pointer- State:
~/.koryph/bots/<name>.json
ciinstall
Forge-native CI asset installation shared by koryph ci setup and future
installers. Install renders an asset kind through a forge.CIService and
writes it to the forge-native path (gate → .github/workflows/koryph-gate.yml
on GitHub, .koryph/ci/koryph-gate.yml includable fragment on GitLab);
Check compares the on-disk asset against the current render and reports
drift. Both are idempotent.
Install(...)/Check(...)— the stable API; import, never copyKindPath(forgeName, kind)— forge-native destination for a kindAllKinds/ action constants (installed/…)
cockpit
The read-only data layer shared by the TUI and the VS Code extension:
assembles a per-project Snapshot from the run ledger, the beads adapter
(cached at a coarser TTL than the refresh tick), and the quota config —
file reads only, cheap enough to call every 100 ms. Also computes the
burndown, efficiency, and queue views, surfacing P50/P90 projections and an
explicit "insufficient history" state below MinSamples observations.
Provider—Refresh() (Snapshot, error);DetailProvider— optional per-bead detailNewLedgerProvider/NewGraphProvider— production constructorsSnapshot— slots, queue, burndown, efficiency, events for one project
commandguard
Coordinates cooperative single-flight execution of classified broad commands within one phase. Every owner passes a kernel-released signature lease through the real command and its descendants. The lease therefore covers the complete cohort even after wrapper death or direct-child exit. Completion transfers the lease to a fresh parent descriptor under the signature state lock before publishing terminal evidence. Durable, strictly decoded owner and result records bind the lease's command signature and generation to an authenticated start/lease identity, process group, role, and fixed log path. Worker duplicates wait for that exact generation; trusted post-rebase validation additionally carries a stable kernel process identity and is published by an engine-owned Go caller before its real tool is released.
ProcessGuard.Acquire— publish, reuse, or deny a classified commandOpenLog/Observe/Complete/Wait— generation-bound evidence lifecycleCommandRoleWorker/CommandRoleValidation— trusted caller roles, never environment or command-line authority- Codex uses non-login tool shells so login startup cannot replace the guarded PATH; owner leases remain authoritative even where its sandbox denies process table probes
- Hookless PATH shims enforce cooperative invocation only; worktree isolation and protected-path merge refusal remain the malicious same-UID boundary, including absolute/copied tools, shim relocation, and mutable phase- environment bypass
commands
Ships the koryph-* Claude slash commands (//go:embed koryph-*.md) and
installs them into a project's .claude/commands/. Installed at onboarding so
koryph semantics hold whether koryph is run explicitly or implied by a
prompt.
FS— embedded slash-command templatesInstall(root, force)— copy commands viascaffold.CopyEmbed
dispatch
Launches one bead as a detached, headless claude process inside its
worktree and tracks the resulting PID/stream.
Spec— everything needed to launch one agent (bead, env, paths)Handle— live process reference (PID, stream path, start time)Backend/CLIBackend— interface + production implementation over theclaudebinaryParseResultCost(streamPath)— extract USD spend from transcriptAlive(pid)/StopGraceful(pid)— process lifecycle helpers
doctor
Runs system-health checks against the ~/.koryph state tree (global mode)
and per-project checks (project mode). All I/O and OS interactions are
injected so checks are unit-testable without touching the real filesystem or
spawning processes. Checks include zombie leases, orphan worktrees, GC
footprint, CI-gate and posture drift, asset drift, proxy loopback safety,
bot credentials, and unvalidated epics; some support --fix.
Run(opts)/RunProject(opts)— execute checks, return a*ReportFinding— one result (Check,Level,Message,Fixed); levelsok/warn/errorMatrix— the integration-status matrix behindkoryph doctor --matrix
dns
Narrowly scoped DNS clients used by koryph. The Cloudflare client manages only
the GitHub Pages custom-domain record set: the published apex A/AAAA addresses
and a DNS-only www CNAME. Its API token is fetched in memory from a vault
reference; no raw token is accepted, persisted, or logged.
NewCloudflareClient(config)— construct the native Cloudflare v4 clientEnsureGitHubPages(ctx, domain, pagesDomain)— create missing Pages records and make matching records DNS-only with automatic TTL
engine
The wave loop: scan → batch → preflight → dispatch → poll → stages → review →
merge. Main orchestration entry point called by cmd/.
Options— full run config (project ID, wave width, dispatch mode, auto-merge, review flags, …)Outcome— summary counts (dispatched, merged, failed, blocked)Run(ctx, opts)— blocking entry point; returns when the run terminates
Internal files: poll.go (heartbeat/completion, rate-limit requeue, AIMD
signal forwarding), recover.go (resume logic), wave.go (engine-side wave
assembly, rolling-mode refill loop, in-flight footprint map), pipeline.go
(post-implement stage execution), govern.go (AIMD report-rate-limit helper).
Requeues refresh the worktree onto current main first (rebuild when no commits,
rebase when there are) so a retry never runs a stale checkout.
DispatchMode (from Options or project.Config.DispatchMode) selects
wave (wait-for-batch, default) or rolling (continuous-refill). Both modes
share poll primitives; rolling additionally passes active in-flight footprints
(sched.Opts.Active) to every BuildWave call so freshly-picked candidates
cannot clash with running beads. Poll interval is poll_seconds from project
config (default 10), overridden by KORYPH_POLL_SEC or Options.PollSec.
epicreview
Whole-epic implementation validation (see
docs/designs/2026-07-epic-validation.md): after the last child of an epic
closes, Validate runs the koryph-epic-validator persona (opus by default,
with exponential-backoff retries) over the union of the epic's merged work and
returns a Verdict — met, gaps, and/or structural findings. Act applies a
verdict deterministically: stamps validation:passed/parked/degraded
labels, files gap and structural follow-up beads with round labels, files the
docs-update bead, and closes the epic when appropriate. Both the engine hook
and koryph epic call this package so the two paths cannot drift.
Validate(ctx, Opts)— run the frontier validator, return aVerdictAct(ctx, BeadStore, ActOpts, Verdict)— deterministic verdict actuationBeadStore— the bd-verb subsetActneeds (*beads.Adaptersatisfies it)RoundLabel/DetectNextRound/LoadPriorVerdicts— round bookkeeping- Labels:
LabelPassed,LabelParked,LabelDegraded,LabelStructural,LabelDocs,LabelNoValidate
execx
Runs external commands with an explicit working directory and environment. All engine subprocess calls go through here.
Cmd— command spec (bin, args, dir, env, timeout);Result— exit code + outputRun(ctx, c)/MustSucceed(ctx, c)— execute; latter errors on non-zero exitBaseEnv(remove...)— current environment with named vars strippedLookPath(name)— reports whethernameis on$PATH
forge
The contract between koryph and hosted git forge services (GitHub, GitLab, …).
Contract-only: the Forge interface, Capabilities flags, and per-domain
service interfaces (RepoService, ProtectionService, PRService,
SecretsService, ReleaseService, CIService, BotService). Providers live
under internal/forge/github/ and internal/forge/gitlab/ and self-register
into Default via init(). Only the edges of the loop talk to a forge —
everything git-native (worktrees, merges, signing, the green gate) stays
forge-neutral.
Forge/Capabilities— provider identity + feature flags (DraftReleases,Rulesets,AppIdentity,WorkflowDispatch, …); callers branch on capabilities, never provider namesDefault— the globalRegistry;ErrUnsupported— operation absent on this forgeSniffRemote— detect the forge from a git remote URL
fsx
Small filesystem helpers shared across the engine. All writes are atomic (write-to-temp + rename) to prevent torn files on crash.
WriteAtomic/WriteJSONAtomic— atomic byte-slice and JSON writesReadJSON(path, v)— unmarshal file intovAppendLine(path, line)— append one newline-terminated record;Exists(path)— stat check
gc
Data lifecycle management for koryph outputs: remove terminal phase-local
compiler state, preserve compact durable evidence, age/prune eligible
transcripts and filed planning snapshots, bound project-scoped Go caches, and
size-rotate audit.jsonl/runs.jsonl (default retention: forever). Telemetry
remains with internal/obs; posture snapshots, canary reports, live runs, and
retained failures are exempt. Config lives in ~/.koryph/retention.json with
per-project overrides in <repo>/.koryph/retention.json. See the
gc user guide.
Run(Options)— apply the policy (honoursDryRun); returns per-classResultFootprint(repoRoot)— reclaimable bytes without deleting (health patrol input)LoadConfig(repoRoot)— global + project overlay with defaults appliedConfig/RunDirPolicy/RotatePolicy/ProjectBudgetPolicy— the retention.json schema (including the 2 GiB soft/5 GiB hard project defaults andGCAuto, the in-run health-patrol flag)- The binary-native loop calls
Runat terminal and idle boundaries; failures become structured supervisor alerts and never launch a model. - State:
~/.koryph/retention.json,<repo>/.koryph/retention.json
govern
Machine-global concurrency governor: a cross-process cap on concurrently running
agents (across all projects) so independent koryph run invocations cannot
collectively breach the Claude API rate limits. Coordinates via lease + demand
files under ~/.koryph/slots guarded by a flock — no daemon. See
global-governor.md.
Store—Acquire(cap-checked reserve) /Release/Prune/RefreshDemand/DropDemand/Snapshot/Cap/SetCap/SetAdaptiveCap/ReportRateLimit/EffectiveCap/AIMDStatusConfig— serialisedgovernor.json; includes AIMD overlay fields (Adaptive,HardMax,DynamicCap) and settle/breaker/smoothing fields (SettleSeconds,SettleUntil,BreakSeconds,BreakerState,MinDispatchIntervalSeconds, …)Lease/Demand— on-disk records- Fair-share:
floor(cap/n)per demander, rotating remainder (no starvation)
AIMD adaptive overlay (--adaptive). When enabled, EffectiveCap floats
between 1 and HardMax instead of pinning to MaxGlobalAgents: +1 every
5 minutes of quiet (additive probe) / halve on a rate-limit signal (multiplicative
decrease). Hardened by three koryph-2im.11 mechanisms — all Adaptive-gated:
- Settle window (
SettleSeconds, default 120 s): freezes further cap changes in either direction after anyDynamicCapchange; the probe clock anchors on settle expiry. - Burst-scaled decrease: ≥3 distinct
(project, bead)rate-limit events within 30 s → divide by 4 instead of 2. - Circuit breaker (
BreakerState): opens when the cap is already at the floor or on 3 decreases within 10 minutes; denies all new admission machine-wide forBreakSeconds(default 300 s, doubling per consecutive re-open up to 3600 s); transitions half-open → admits exactly one probe → closes on clean release / re-opens on probe rate-limit. - Dispatch smoothing (
MinDispatchIntervalSeconds, default 3 s): machine-wide minimum inter-dispatch spacing, jittered ±50%, to prevent thundering-herd refills.
intake
Polls a project's external issue tracker for trigger-labeled issues and files
one planning bead per issue, idempotently (a bead carrying the
gh-<owner>/<repo>#<number> external-ref is skipped). Every ingested bead is
labeled no-dispatch — an ingested issue is planning input a human or planner
must triage first; intake never mutates tracker state except the opt-in
comment-back. Sources: GitHub (via the gh CLI, never a raw token), Linear,
and JIRA, plus a multi-source runner.
Run(ctx, Options)— one GitHub intake pass;RunLinear/RunJIRA/RunMultiSource— the pluggable issue-tracker provider interface- Defaults: trigger label
triage, limit 20
ledger
Owns the per-run ledger (JSONL on disk) and per-slot checkpoints. Classifies live runs to recommend the next orchestrator action.
Store— ledger DB;NewStore(repoRoot)with per-slotLockRun/Slot— top-level run and per-agent recordsManifest— immutable dispatch record;PlanState— wave snapshotDecision— recommended action (merge, retry, abandon, …);Probe— current observationsTerminal(status)— true if status is a final stateClassify(run, probe)— returns[]Decisionfor the orchestrator
loop
Binary-native, model-free supervisor around the transactional engine. It observes ready/recovery state before starting an engine run, persists exact run/cohort/circuit state, applies fixed-cohort canary admission, and sleeps on bounded event-backed idle waits without creating empty ledgers.
Supervisor.Run— single-owner lifecycle with synchronous run-start durability, exact-run recovery, bounded crash/non-progress circuits, and drain handlingCanarySpec/RequiredCanaryHardStops— immutable cohort, authoritative width progression, required review/merge evidence, and typed tripwiresObserver/Engine/TripwireSource— narrow product seams; no log scraping or model-driven wrapper recoveryMaintainer— bounded model-free GC at terminal and idle boundaries- State:
<repo>/.koryph/loop/supervisor.json,control.json, andalerts.jsonl; immutable canary evidence remains under<repo>/.plan-logs/koryph/canary/
merge
Lands a finished agent branch on the default branch after running the configured green gate.
Opts/Result— merge configuration and outcomeSlotLocker— interface abstracting per-slot locking (for tests)Protected(diffPaths, extra)— returns protected paths hit by a diffMerge(ctx, o)— main entry: run gate → ff-merge (squash optional)RunGate(ctx, dir, cmds)— execute green-gate commands; returnsok, outputReconciler/reconcileRebase— auto-heal a pre-merge rebase conflict confined entirely to configured generated files (a migrations lockfile, a secrets baseline) by regenerating each from the post-merge tree and continuing, instead of aborting; all-or-nothing and gated (docs/user-guide/merge-reconcilers.md)runMergePrepare— post-rebase, pre-gate normalization of the rebased tree (renumber a migration to tip at merge time); koryph commits any change so it rides the ff-merge and is gated
metrics
Rolls up burn-rate and reliability baselines from the run ledger for reporting and quota decisions.
ModelStat/ProjectStat/Report— nested stats typesCollect(store, projectID)— read ledger, compute*Report; the per-model breakdown is keyed on the model that actually served (Slot.ModelActual, fallbackModel) so a mid-flight--fallback-modeldowngrade is charged to the tier that ran, matching cockpit's token rollupRender(r, w)— pretty-print report to anio.Writer
modellearn
Reads historical or explicitly typed escalation provenance from run ledgers,
aggregates it by the similarity features frozen on each slot (area label +
size bucket), and can recommend a starting tier for future beads sharing those
features. Retry count does not create escalation evidence. The actuator is a
bead label, not a routing-table entry: Apply stamps model:<tier> plus a
model-learned:<date> provenance marker; any pre-existing model:* label
wins, making re-apply idempotent and human overrides durable.
Collect/Recommend/Apply— mine evidence → propose tiers → label beadsDefaultMinEvidence(2) — minimum escalated-then-merged count per bucketProvenancePrefix—model-learned:
modelroute
Resolves a (stage, bead-labels, run-defaults, project-config) tuple to a
(model, effort) pair, with persona-file overrides.
Precedence (koryph-v8u.10): bead model:<tier> label > persona tier (via
the active runtime's model map, project-overridable) > persona model
(legacy pin) > hardcoded stage default — see agents/README.md's "Resolution
precedence" section.
Req/Resolution— request and resolved(model, effort);Req.RepoRoot/Req.ModelMapopt a caller into the persona-tier stepResolve(r)— main entry; consults label rules, then persona tier/ model, then defaultsPersonaFor(stage, stages)— picks persona name from stage mapTierForModelID(id)— normalizes a concrete model id (a result line'smodelUsagekey) to its tier for actual-model attribution (koryph-qf6.2)PersonaMeta(repoRoot, persona)— reads persona file →(model, effort, tier)
netx
Shared network-address predicates used across koryph's security gates. Centralised so independent copies cannot drift (design I4: loopback-only routing for dispatched-agent Anthropic traffic).
IsLoopbackHost(host)— the single authoritative loopback predicate (localhost,127.0.0.0/8,::1, IPv4-mapped forms); used by both the registry load-time validation and the doctor proxy check
obs
koryph's observability foundation: a custom TRACE slog level, per-component
loggers with independently-settable minimum levels, and a swappable handler
pipeline (console / JSON / text / multi / OTLP-HTTP). Configured by
~/.koryph/observability.json with on-demand reload (no restart) and env
overrides (KORYPH_LOG_LEVEL, KORYPH_LOG_FORMAT, KORYPH_OTEL_ENDPOINT).
A central RedactingHandler scrubs every record so no secret reaches a
handler; canonical attribute keys (run_id, bead_id, model_actual, …)
keep logs, spans, and metrics correlated. Also owns telemetry-file rotation
and pruning (PruneFromConfig).
Init(cfg, handler)/LoadConfig/ReloadConfig— startup + live reloadFor(component)— a component-scoped*slog.LoggerRunAttrs/BeadAttrs/ForgeAttrs/Err— canonical attribute helpersRedactAttr/RedactValue— exported for no-secret-leak assertions- State:
~/.koryph/observability.json,~/.koryph/telemetry/
onboard
Inspects a repository, registers it in the registry, and validates that all prerequisites (hooks, beads, account identity) are satisfied.
Inventory— survey result (remotes, hooks, beads status, worktrees)RegisterOpts— identity, billing, and flag overrides forRegisterValidation/Check— validate output (slice of named pass/fail checks)Inspect(ctx, root)— non-mutating surveyRegister(ctx, store, inv, opts)— writeregistry.Recordfrom inventoryValidate(ctx, store, projectID, w)— check all prerequisites, print results
paths
Resolves all koryph machine-local state locations from $KORYPH_HOME
(default: ~/.koryph). No exported types; all functions return string.
KoryphHome · RegistryDir · QuotaDir · AuditLog · RunsIndex ·
PlanLogs(repoRoot) · KoryphRoot(repoRoot)
personas
Installs the fallback Claude sub-agent persona files (embedded from
agents/ in the binary) into a project's .claude/agents using the shared
scaffold hash-aware, force-guarded copy policy — no network access at onboard
time. For non-Claude runtimes, InstallForRuntime rewrites each persona's
model: frontmatter through the target runtime's ModelMap, keyed by the
persona's tier: scalar, so a codex/cursor/grok project never receives a
Claude model name it cannot honor. (Rendering personas for those runtimes
works today; dispatching to them does not — the engine blocks non-Claude
runtimes fail-closed. See
AI runtimes: support status.)
Install(root, force)— byte-identical copy (equivalent to runtime"claude")InstallForRuntime(root, force, runtimeName)— tier-mapped render; also reports untiered personas
phasecontrol
Defines the versioned, file-based bridge between an isolated worker phase and the orchestrator that owns privileged host actions. Requests have explicit operation fields rather than arbitrary commands or payloads; responses are digest-bound, sanitized, replay-safe, and journaled outside worker-writable state.
Request/Response— portable protocol records forlabel-addandruntime-canarySubmit/WaitResponse— worker-side atomic request and authenticated response flowListRequests/PublishResponse— orchestrator-side polling and worker-visible response publicationValidateSchedulingLabel— permits onlyarea:*,fp:*, andres:*ValidateCapability— validates structured host-capability block tokens
plan
Corpus-level plan analysis. Audit performs a deterministic, read-only
conflict analysis of a project's open bead corpus under the current sched
rules (FootprintFor + Conflicts), surfacing unlabeled beads (the
domain:unknown serializers), non-dispatchable ready beads, dependency-
unordered conflicting pairs, and achievable vs. potential parallel width.
AuditReport— the JSON-marshalable result (behindkoryph plan)ConflictPair/WidthReport/ItemSummary/SkipSummary— report parts
posture
Desired-state checking and applying for repository hygiene: branch-protection
rulesets (.github/rulesets/*.json) and administrative settings
(repo-settings.json), delegated to gh api passthrough — no token
management in-package. Named posture profiles compile forge-neutral Intents
to forge-native files (CompileGitHub); fragments, org-level rulesets,
snapshots, and rollback round out the koryph posture/koryph repo surface.
Posture snapshots are never auto-deleted (exempt from gc by design).
CheckRulesets/ApplyRulesets/CheckSettings/ApplySettings— diff-first check/applyCheckOrgRulesets/ApplyOrgRulesets— org-level equivalentsCompileGitHub(intents, params, ghDir)— profile → GitHub-native desired stateCaptureSnapshot/Rollback— pre-apply state capture + restoreSource— desired-state provider seam (LocalSourcereads.github/)
project
Loads the per-project adapter configuration (koryph.project.json).
Config— wave width, green-gate commands, footprint rules, dispatch mode, poll interval (PollSeconds), and AIMD-adjacent knobsFootprintRule— path-pattern → conflict-scope mappingDefault(projectID)/Load(repoRoot)— sensible defaults or parse from disk
Key scheduler fields: DispatchMode ("wave" | "rolling", default "wave"),
PollSeconds (poll tick override; 0 → engine default 10 s), MaxConcurrentSlots
(wave-width cap per project), DispatchStaggerSeconds (inter-agent launch
spacing; 0/unset → the engine's 10s anti-stampede floor, koryph-4rk6.3).
promptc
Compiles the dispatch prompt in a cache-stable, deterministic order so prompt-cache hits are maximised across re-dispatches.
Input— all variable sections (task, plan, project context, …)Compile(in)— assemble final prompt stringPreamble(engineVersion)— static koryph-protocol preamble
pricing
Single source of truth for Anthropic Claude per-model list prices (koryph-fiv
finding #5). Before it, anthro, quota's usage accounting, and quota's
per-dispatch estimator each hand-maintained their own Claude price copy and had
silently drifted (anthro priced Opus at $5/$25 per MTok vs the real $15/$75).
Consumers now derive their base rates from here; a price change is a one-line
edit, not a three-way reconciliation.
Rate— one model's base list price (USD / MTok input + output)Claude— the ordered canonical Claude tier→rate list (order significant forquota's substring matching: opus, haiku, fable, sonnet)ClaudeRate(tier)/ClaudeFallbackRate()— exact-tier lookup and the sonnet fallback for an unrecognized model idCacheReadMultiplier/CacheWrite5MinMultiplier/CacheWrite1HourMultiplier— cache-TTL multipliers (fraction of input rate) each consumer applies on top of the shared base:quotaprices 5-minute writes (1.25x),anthroprices 1-hour writes (2x)
Only base in/out rates are shared; the cache-TTL choice legitimately differs by context. Reads/writes no files.
procx
Small OS-process primitives shared across the recovery, governor, and health paths — factored out so the signal-0 liveness probe has exactly one implementation instead of the four byte-identical copies that had accreted in ledger, govern, doctor, and dispatch.
Alive(pid)— is pid a live process? (POSIX kill(pid, 0): nil → alive, EPERM → alive but not ours, ESRCH/other → dead)
Reads/writes no files.
quota
Per-account usage governor. Estimates wave cost, tracks rolling-window spend, and gates or scales dispatch.
Config— daily/monthly caps and thresholds per accountUsage/Window/Level— spend snapshot, rolling measurement,"ok"|"warn"|"drain"|"stop"State(u, cfg)— deriveLevel;ScaleSlots(u, max)— reduce wave width under pressurePreflight(u, estimateUSD, cfg)— gate a wave before dispatchEstimateItemForRuntime/EstimateWaveForRuntime/DefaultConfigForRuntime— pre-flight USD estimates, namespaced by runtime name (koryph-v8u.12): each runtime gets its own default per-tier USD base table (onlyclaude's carries real numbers today), selected by the runtime a bead actually resolves under (modelroute.ResolveRuntimeName); an unrecognized runtime name degrades to claude's table rather than erroring (an estimate is advisory governor input, never a fail-closed dispatch gate). Calibration keys ("<tier>:<size>") are deliberately not runtime-namespaced — only claude dispatches have ever recorded calibration, so existing~/.koryph/quota/*.jsonfiles keep estimating exactly as before.Record/LoadConfig/SaveConfig— persist actual spend and config
registry
Central multi-project registry stored under paths.RegistryDir().
One JSON file per project.
Store— registry root;NewStore()/NewStoreAt(home)Record— full project registration (ID, root, account, billing, hooks, …)Event— audit-log entry written on every mutation
Key Store methods: Get, Put, Delete, List, All.
release
Implements koryph release setup — rendering and installing the
forge-specific release pipeline plus release-please config/manifest into a
target project — and koryph release kick, the bot-less fallback that
close+reopens the open Release PR so GitHub fires check workflows under the
user's real gh auth. The caller workflow is rendered via the project's
forge CI service (forge.CIService.Render("caller")); the release-please
config and manifest come from templates embedded in this package. The
manifest is written once and never overwritten.
Setup(repoRoot, rc, initialVersion)/SetupForge(..., ci)— install the pipeline filesKick(viaKickOptions/KickResult) — close+reopen the Release PR, optional--waitcheck pollingReleasePRLabel—autorelease: pending, the Release PR detection label
resmon
Samples the OS resource usage (CPU time, resident memory, and — where the
platform exposes it — disk I/O) of an agent process tree, so the engine can
record per-bead efficiency metrics and the cockpit can surface avg/peak memory
and CPU per bead. Callers take ONE process-table Snapshot per tick and
aggregate the subtree rooted at each slot's PID — one syscall sweep regardless
of slot count. Build-tagged backends: linux reads /proc, darwin shells out
to ps (no per-process disk I/O there), other platforms report unavailable.
Snapshot()— one whole-machine process table (ProcTable)ProcTable/Sample/Usage— table, per-process reading, per-slot aggregate
review
Runs a read-only post-implementation review pass before a branch is merged.
Opts— branch, project root, model, and the singleTimeoutSecFinding— one review comment (file, line, severity, message)Verdict— pass/fail +[]Finding(TimedOutflags a deadline kill)Review(ctx, o)— launch reviewer agent, collectVerdict
Timeout (koryph-w82i). Each attempt runs under one wall-clock deadline —
Opts.TimeoutSec, the caller-resolved bead > project > system > built-in winner
(see timeoutcfg). The former start/escalate two-tier pair and
the 20-minute hard cap were removed: there is no escalation and no ceiling. The
package resolves Opts.TimeoutSec <= 0 to review.DefaultTimeoutSec
(timeoutcfg.BuiltinDefaultSec, 1200) and lets the break-glass
KORYPH_REVIEW_TIMEOUT_SEC env override win at spawn time (resolveTimeout). A
persistent timeout degrades after all attempts; retries reuse the same deadline
with exponential backoff.
runtime
Defines the pluggable agent-runtime contract (koryph-v8u.1): the runtime
interface, Capabilities flags, a normalized event envelope, and a
Registry — as a pure addition that deliberately imports nothing from
internal/dispatch/internal/account. Every type is a small local mirror of
the corresponding dispatch/account field set (e.g. dispatch.Spec ↔
runtime.DispatchSpec, with the mapping documented in doc comments) so a
second adapter can exist without wiring the contract to Claude's shape. The
Claude adapter lives in internal/runtime/claude; runtimetest holds shared
conformance fixtures.
Capabilities— feature flags (Personas,ModelSelect,EffortFlag,Resume,BudgetFlag, …)DispatchSpec/Profile/BillingMode— runtime-neutral request mirrorsNewRegistry()— named-runtime registry; each runtime carries its own model map
runtimecanary
Runs the fixed authenticated cross-runtime capability probe used by phase control. The orchestrator supplies the target runtime's verified profile, standard-tier model, and scratch directory; requester-authored prompts, commands, environments, and expected output are not accepted.
Options— orchestrator-resolved runtime, profile, credential, model, identity verifier, and execution seamsRun(ctx, opts)— verifies target identity, executes the fixed headless tool contract, and checks an unpredictable phase-local proof fileResult— credential-free result classification safe for worker-visible output (ok,configuration,identity,spawn,transient,execution,tool, orprotocol)
runtimeconfig
Resolves a named runtime adapter with its process-local binary override. Engine and command entry points use this package instead of constructing Claude, Codex, or future registered adapters independently, so one runtime selection has the same executable configuration everywhere.
Get(name)— return the configured built-in or registered adapterEnvClaudeBin/EnvCodexBin— compatibility binary overrides, applied only inside this construction seam
sched
Builds conflict-free waves from the beads ready frontier, respecting footprint rules and the wave-width cap.
Item/Wave— selected issues + deferred/blocked explanationsFootprint— RW conflict surface (Reads []string,Writes []string);Reason— why deferred/blockedFootprintFor(issue, cfg)— deriveFootprintfrom labels + project rulesConflicts(a, b)— true iff footprints share a token and at least one side holds it as a write (RWMutex semantics: two readers co-run)Eligible(issue, activeIDs)— can this issue be dispatched now?BuildWave(...)— main entry: frontier →Wave; acceptsOpts.Active(in-flight footprints keyed by bead id) for rolling-mode in-flight gating
Dispatch shape. Eligible skips any bead whose issue_type is
epic/feature/decision/merge-request, or that carries a no-dispatch,
refactor-core, or gt:* label — so a bead filed with the wrong type sits in
bd ready forever. FootprintFor derives conflict tokens with the precedence:
fp:read:<token>labels → read tokens (two readers of the same token co-run);fp:<token>labels (any other suffix) → write tokens (existing grammar, unchanged);area:*labels resolved through the project'sarea_map→ write tokens;- else
domain:unknown(a write token) — conflicts with every other unlabeled bead, serializing them 1-per-wave.
BuildWave also accepts Opts.Active (in-flight footprint map for rolling mode): a candidate
whose footprint Conflicts with any entry here is deferred before intra-batch greedy coloring
even runs, so a rolling refill can never clash with already-running beads. Label implementable
beads (task/bug/chore) with one area:* per area they touch: over-broad labeling only costs
parallelism, under-broad labeling risks a false-parallel merge conflict.
rules
Installs the koryph enforcement rules into a project: the hook scripts
(hooks/*.sh) and their wiring in .claude/settings.json. Hook scripts install
like agents (whole-file, hash-idempotent). settings.json is merged
additively — koryph's hooks and permission allow/deny entries are added,
every other key is preserved, and only an unparseable file blocks the merge.
Install(root, force)— install hooks + merge settingsMergeSettings(root, force)— additive settings merge →created/merged/unchanged/skipped
scaffold
Shared, hash-aware installer for binary-embedded assets (personas, commands,
hooks) into a project. Identical content is a no-op (unchanged); differing
content is skipped (warned) unless force, then overwritten.
Result/ action constants (installed/overwritten/unchanged/skipped)CopyEmbed(fsys, destDir, force, perm)— copy every embedded file with permConflicts(results)/Count(results, action)— reporting helpers
schemaver
Single source of truth for the on-disk schema version of every persisted state
surface, and the forward-compatibility guard that stops an older binary from
silently corrupting state a newer koryph wrote. When the on-disk version is
newer than this build understands, load/save is refused with an "upgrade
koryph" error rather than misreading it (or field-stripping it on the next
read-modify-write save). Write paths stamp Current(surface); read paths guard
with CheckRead — so the number lives in exactly one place. Design:
docs/designs/2026-07-state-versioning.md.
Surface— a versioned state surface (Registry,Quota,SigningVault,Project,LedgerRun,LedgerManifest)Current(s)— the schema version this binary writes/understands forsCheckRead(s, onDisk)/CheckWrite(s, onDisk)— refuse newer-than-supportedTooNewError— the version-skew refusal (errors.As to distinguish from IO errors)
State files: reads/writes no files of its own — it gates the load/save paths in registry, quota, signing, project, and ledger.
signing
SSH commit signing and koryph's secret-vault layer. Configures a repo for
signed commits, moves the signing key from a vault into an SSH agent (memory
only — a fetched key is piped to ssh-add -t 3600 -, never written to disk),
and provides the scoped agent: a koryph-managed ssh-agent holding only the
commit-signing key, which is what dispatched agents receive instead of the
operator's ambient SSH_AUTH_SOCK. Vault providers (Proton Pass, 1Password,
KeePassXC, macOS Keychain, age-encrypted file, generic command) are argv
templates in ~/.koryph/vault.json, so CLI drift is a config edit, not a code
change. FetchSecret is the generic secret path other packages (bot keys,
GitLab PATs) reuse; cosign key handling and signing-posture checks also live
here.
ConfigureRepo(ctx, repoRoot, cfg)— write the repo's signing git configEnsureAgent/EnsureScopedAgent— key into the system / scoped agentFetchSecret(ctx, provider, ref)— resolve any secret through the vault seamVaultConfig/ProviderTemplates— thevault.jsonschema- State:
~/.koryph/vault.json,~/.koryph/signing/config.json
stage
Runs one post-implement pipeline stage: a write-capable persona agent executed synchronously in the implementer's worktree (before review/merge) under the same account/billing/identity guarantees as a dispatch.
Opts— worktree, branch, resolved persona + model, per-stage prompt, profile/billing, andTimeoutSec(the caller-resolved bead > project > system > built-in winner;<= 0→DefaultTimeoutSec, 1200)Result—Ran/OK/TimedOut/CostUSD/NoteRun(ctx, o)— verify identity, run thedontAskclaude one-shot, persist the envelope, report cost
strictjson
Strict JSON evidence decoding shared by the autonomous supervisor, metrics reports, and command lifecycle readers. It rejects duplicate or case-fold colliding object keys, noncanonical field spellings, unknown fields, and trailing values so Go's permissive last-wins and case-insensitive matching cannot rewrite persisted safety evidence.
Decode(raw, target)— recursively validate object keys, then decode with unknown-field and trailing-value rejectionRejectDuplicateKeys(raw)— reject exact duplicates and case-fold collisions in every nested object
sysdeps
Platform detection and consented install planning for koryph's external tool
dependencies (bd, claude, gh), plus the consumer-flake edit route
(design: docs/designs/2026-07-adopt.md §4). Planning is pure — this package
never executes an install; the adopt wizard shows the exact argv (sudo called
out) and runs it only on consent.
Detect()—Platform(GOOS,/etc/os-releasedistro, package managers on PATH in preference order)Plan(p, tool)—InstallPlan{Route, Argv, Manual, Verify, NeedsSudo}; data-driven tool spec table, manual fallback always availablePlanFlakeBeads(root)/ApplyFlakeEdit(ctx, root, e)— minimal structural flake.nix edit adding the beads input + devShell package, diff-first,nix flake lockafter
sysmem
Reports coarse system memory availability with no external dependencies and
no cgo, so the scheduler can refuse to admit another agent when the host is
under memory pressure (koryph-930). AvailableBytes is a deliberately
conservative estimate (Linux: /proc/meminfo MemAvailable; macOS:
reclaimable page classes from vm_stat) used as a soft admission floor, never
a hard accounting number. Callers MUST fail open on ErrUnsupported — the
gate is a safety rail, not a correctness dependency.
Available()— currentStat(TotalBytes,AvailableBytes)DefaultFloorMB(totalMB)— auto-floor sizing, clamped for small/large hostsErrUnsupported— platform has no probe; fail open
textx
Tiny, dependency-free string helpers shared so packages stop each keeping a byte-identical copy (koryph-fiv finding #6). Imports nothing outside the standard library, so even low-level packages (worktree) can depend on it.
Tail(s, n)— last n bytes of s (all when shorter); bounds captured command output and log tails. Previously copied intomerge,worktree, andagentjson(the last now re-exports it).
timeoutcfg
The single home for koryph's unified agent-facing wall timeout and its override hierarchy (koryph-w82i). One built-in default governs every agent koryph spawns on the operator's behalf — the post-implementation reviewer, each pipeline stage, and epic validation — overridable at three levels in strict precedence: bead > project > system > built-in (1200).
BuiltinDefaultSec— the built-in 20-minute (1200s) default;reviewandstageboth anchor theirDefaultTimeoutSecto it, and aninternal/enginedrift guard asserts they stay equal.BeadTimeout(labels)— parses a bead's baretimeout:<seconds>label (mirrorsmodelroute'smodel:<tier>grammar); returns(sec, ok).Resolve(bead, project, system)— the precedence walk; each arg<= 0means "unset at that level", always returns a positive value, and imposes no ceiling (an explicit override may exceed the default).
The system tier lives in signing.GlobalConfig.DefaultTimeoutSeconds
(~/.koryph/config.json); internal/engine loads it once and threads it,
alongside the bead label and the project config, into Resolve at each spawn.
tui
The koryph terminal cockpit (koryph tui), built on Bubble Tea. App is the
root model — tab framework, project switcher, help overlay, status bar, and
refresh loop; each tab is a TabModel registered once via tabRegistry
(adding a tab = one file with init()), and only the active tab receives
Update calls. Data comes from cockpit.Provider, polled every 100 ms while
agents run (1 s when idle). Minimum terminal floor: 80×24. User docs:
user-guide/tui.md.
NewApp— construct the root modelDefaultKeyMap/DefaultTheme— keybindings and styling defaults
version
Holds the engine's semantic version (set at build time via -ldflags) and
version-requirement checking. Single entry point: Satisfied(have, want)
reports whether have meets the want semver constraint.
worktree
Creates and manages per-bead git worktrees (one branch per active issue).
Info— metadata (path, branch, bead ID, dirty flag)EnsureOpts/RefreshOpts/RefreshResult— lifecycle options and resultsBranchFor(beadID)— returns"agent/<beadID>"List(ctx, repoRoot)— all worktrees for the repoEnsure(ctx, o)— create-or-reuse worktree for a beadBootstrap(ctx, path, cmds, env)— run bootstrap commands inside worktreeRefresh(ctx, o)— rebase or snapshot an existing worktreeRemove(ctx, path, force)— delete worktree and prune branchPatchSnapshot/DeleteBranch— export diff patch, remove remote-tracked branchConflictMarkdown(branch, base, output)— renders theCONFLICT.mdbreadcrumb for an aborted rebase-onto-base; shared withinternal/merge(koryph-fiv finding #6)