Documentation
¶
Overview ¶
Package kit is the importable contract a HOST-COUPLED plugin candy implements to run against charly's live check engine — the seam that lets a check verb whose logic needs the running deployment (exec-in-container, host TCP dial, host-vantage HTTP) live in its own candy module instead of charly's module.
A host-coupled verb candy implements CheckVerbProvider; charly runs it in EITHER placement, invisibly above the registry: IN-PROCESS (compiled-in — charly passes the live *Runner as a CheckContext) OR OUT-OF-PROCESS (the CheckContext legs are served back to the candy over the host's reverse channel — ExecutorService for Exec + CheckContextService for HTTPDo/AddBackground, F2 — and the scalar legs ride the env_json snapshot). RunVerb is identical in both. This package imports only the stdlib + charly/spec (the generated param/Op types), so a candy module can import it without pulling charly's package main.
Index ¶
- Constants
- Variables
- func AddBox(dir, name, base string, layers []string) error
- func AddCandyDeployment(paths *LedgerPaths, candyName, deployID string, update func(*CandyRecord)) error
- func AddCandyDeploymentVia(exec spec.DeployExecutor, paths *LedgerPaths, candyName, deployID string, ...) error
- func AnnotateNeverHangKill(msg string, bound time.Duration) string
- func AnnotateNeverHangKillWithEvidence(msg string, ev KillEvidence) string
- func AppendUnique(dst []string, items ...string) []string
- func ApplyPortOverrides(ports []string, overrides []string) ([]string, error)
- func AtomicWriteFile(path string, data []byte, perm os.FileMode) error
- func BareVolumeName(volumeName, boxName, instance string) string
- func BuildActivityDir() (string, error)
- func BuildArchExports() string
- func BuildCommandLine(command string, sudo bool, marker string) string
- func BuilderCollectContext(word string, in spec.BuilderCollectInput) map[string]any
- func BuilderResolve(word string, in spec.BuilderResolveInput) (spec.BuilderResolveReply, error)
- func BuilderReverse(word string, in spec.BuilderReverseInput) []spec.ReverseOp
- func CargoLdConfPath(candy string) string
- func CargoLibDir(candy string) string
- func CloseHostCleanups(cleanups []func())
- func CloseTerminal(ctx context.Context, tr ConsoleTransport) (string, error)
- func CollectAnyStrings(v any) []string
- func CollectHostRefs(checks []spec.Op) []string
- func ConsolePreview(s string, n int) string
- func ContainerPortsFromMappings(mappings []string) []int
- func DecodeInput(in map[string]any, out any)
- func DeleteCandyRecord(paths *LedgerPaths, layer string) error
- func DeleteDeployRecord(paths *LedgerPaths, id string) error
- func DirectDeployMarkerDir() (string, error)
- func DirectDeployMarkerPath(box, instance string) (string, error)
- func DiscoverRemoteCandy(repoDir string) ([]string, error)
- func EffectiveStepID(s *spec.Step, origin string, stepIdx int) string
- func EffectiveTags(stepTags []string) []string
- func EnableUnit(ctx context.Context, exec DeployExecutor, unit string, scope spec.Scope) error
- func EnsureSshConfigInclude(home string) error
- func EnvPairsToMap(pairs []string) map[string]string
- func EnvdDir(home string) string
- func EnvdFilePath(home, candyName string) string
- func ExpandAnyVars(v any, env map[string]string) (any, []string)
- func ExpandOpVars(c *spec.Op, env map[string]string) []string
- func ExpandTestVars(s string, env map[string]string) (string, []string)
- func FillReverseUninstallCmds(ops []ReverseOp, renderUninstall func(format string, packages []string) string)
- func FilterHostVars(missing []string) []string
- func FindMappingValue(m *yaml.Node, key string) *yaml.Node
- func FindPortOwner(port int, engine string) (owner string, ownerType string)
- func FirstUnmetDepStep(s spec.Step, verdictByID map[string]string) string
- func FormatPortConflicts(conflicts []PortConflict, image string) string
- func HammingDistance(a, b ScreenSignature) int
- func HumanBytes(n int64) string
- func IsAutoPort(mapping string) bool
- func IsDirectDeploy(box, instance string) bool
- func IsGitSubmoduleDir(p, root string) bool
- func IsNotFound(err error) bool
- func IsRuntimeOnlyVar(key string) bool
- func KeywordOf(s *spec.Step) spec.StepKeyword
- func LUKSUnlock(ctx context.Context, tr ConsoleTransport, passphrase string, ...) (string, error)
- func LedgerTxLockPath(paths *LedgerPaths) string
- func ListCandyNames(paths *LedgerPaths) []string
- func ListCandyNamesStrict(paths *LedgerPaths) ([]string, error)
- func ListDeployIDs(paths *LedgerPaths) []string
- func ListDeployIDsStrict(paths *LedgerPaths) ([]string, error)
- func ListVmSshAliases(home string) ([]string, error)
- func ManagedBlockBody(shell ShellKind, home string) string
- func ManagedBody(text string) string
- func MapValue(m *yaml.Node, key string) *yaml.Node
- func MappingChild(m *yaml.Node, key string) *yaml.Node
- func MarkersForTag(marker string) (begin, end string)
- func MergeAnswers(envVars, secrets, authored map[string]string, ...) map[string]string
- func MergeReverseOps(existing, incoming []spec.ReverseOp) []spec.ReverseOp
- func MigrateCandidateYAMLFiles(dir string, treeSubdirs []string) []string
- func NodeShapedValue(val *yaml.Node) bool
- func NormalizeTag(t string) string
- func OCRBytes(pngBytes []byte) (string, error)
- func OCRBytesScaled(pngBytes []byte, scale int) (string, error)
- func OpUnifyCandidateFiles(dir string) []string
- func OpenTerminal(ctx context.Context, tr ConsoleTransport, o TerminalOpen) (string, error)
- func ParseContainerPort(mapping string) (int, error)
- func ParseHostPort(mapping string) (int, error)
- func ParseTaskMode(mode string, def uint32) uint32
- func PopulateSystemInfo() error
- func PosArtifact(c *spec.Op) []string
- func PosCommandFields(c *spec.Op) []string
- func PosKeyNameSplit(c *spec.Op) []string
- func PosLibvirtQmp(c *spec.Op) []string
- func PosTarget(c *spec.Op) []string
- func PosText(c *spec.Op) []string
- func ReadLedger(paths *LedgerPaths) (map[string]DeployRecord, map[string]CandyRecord, error)
- func ReloadDaemon(ctx context.Context, exec DeployExecutor, scope spec.Scope) error
- func RemoveEnvdFile(home, candyName string) error
- func RemoveImagesByReference(engineBin, reference string)
- func RemoveManagedBlockAt(path, marker string) error
- func RemoveSshConfigInclude(home string) error
- func RemoveVmSshStanza(home string, alias string) (remaining int, err error)
- func RenderDownloadScript(op *spec.Op, candyVars map[string]string) string
- func RenderEnvdBody(candyName string, envVars map[string]string, pathAdd []string) string
- func RenderFlowEvidence(res ConsoleFlowResult) string
- func RenderManagedBlockStrip(path, marker string) string
- func RenderOpCommand(op *spec.Op, ctxPath string, candyVars map[string]string) (string, bool)
- func ReplaceOrAppendManagedBlock(existing, body, marker string) string
- func ReplaceOrPrependManagedBlock(existing, body, marker string) string
- func ResolveDeployPorts(containerPorts []int, pins, prior []string, occupied map[int]bool) ([]string, error)
- func ResolveEntrypointFromMeta(meta *spec.BoxMetadata) []string
- func ResolveInitDefFromMeta(meta *spec.BoxMetadata) (*spec.ResolvedInit, error)
- func ResolveNetwork(configured, engine string) (string, error)
- func ResolveVmSshPort(vm *spec.ResolvedVm, vmName string, persistedPort int) (int, error)
- func RunAgentOnce(ctx context.Context, ai *spec.AgentExecSpec, prompt string, ...) (string, string, error)
- func RunBootOrder(ctx context.Context, tr ConsoleTransport, o BootOrder) (string, error)
- func RunCommands(ctx context.Context, tr ConsoleTransport, cmds []ConsoleCommand, ...) (string, error)
- func RunReverseOps(ops []ReverseOp, exec ReverseExecutor)
- func SameStringSlice(a, b []string) bool
- func SanitizeDeployName(s string) string
- func SaveYAMLNodeFile(path string, root *yaml.Node) error
- func ScaffoldCandy(dir, name string) error
- func ScaffoldProject(dir string) error
- func ScreenMatches(current, reference ScreenSignature, maxDistance int) bool
- func ScreenPreview(s ScreenSignature) string
- func SetByDotPath(path, dotpath, valueYAML string) error
- func SetMappingKey(m *yaml.Node, key string, val *yaml.Node)
- func ShDoubleQuote(v string) string
- func ShDoubleQuotePath(v string) string
- func ShQuoteArg(v string) string
- func ShQuoteEnv(v string) string
- func ShellInitFilePath(shell ShellKind, home string) string
- func SidecarConfigDir() (string, error)
- func SortStrings(s []string)
- func SplitHostKey(key string) (name, arg string, ok bool)
- func SshConfigPath(home string) string
- func SshFragmentPath(home string) string
- func StepDoMode(s *spec.Step) spec.DoMode
- func StepID(origin string, stepIdx int) string
- func StripManagedBlock(existing, marker string) string
- func SubstituteConsoleAnswers(s string, answers map[string]string) string
- func TaskShellPreamble(candyVars, opEnv map[string]string) string
- func TestVarRefs(s string) []string
- func TransferToRootful(imageRef string) error
- func UpscalePNG(pngBytes []byte, scale int) ([]byte, error)
- func ValidatePlanSteps(desc string, plan []spec.Step, eid string) []string
- func ValidateTagExpr(tag string) error
- func WalkPlans(ctx context.Context, exec DeployExecutor, plans []spec.InstallPlanView, ...) ([]spec.ReverseOp, error)
- func WrapUnlessExists(cmd, guard, verb string) string
- func WrapUnlessExistsBlock(cmd, guard, verb string) string
- func WriteCandyRecord(paths *LedgerPaths, rec *CandyRecord) error
- func WriteDeployRecord(paths *LedgerPaths, rec *DeployRecord) error
- func WriteDeployRecordVia(exec spec.DeployExecutor, paths *LedgerPaths, rec *DeployRecord) error
- func WriteVmSshStanza(home string, s VmSshStanza) error
- type AgentForwardMounts
- type AgentGrader
- type BootOrder
- type BuilderRunOpts
- type CalVer
- type CandyRecord
- type CharlyInstallStrategy
- type CheckContext
- type CheckEndpoint
- type CheckResult
- type CheckRunReply
- type CheckVarResolver
- func NewRuntimeCheckVarResolver(env map[string]string) *CheckVarResolver
- func ResolveCheckVarsBuild(meta *spec.BoxMetadata) *CheckVarResolver
- func ResolveCheckVarsRuntime(meta *spec.BoxMetadata, deploy *vmshared.DeployNode, ...) (*CheckVarResolver, error)
- func StampCharlyBin(res *CheckVarResolver) *CheckVarResolver
- type CheckVerbProvider
- type ConsoleCommand
- type ConsoleCommandResult
- type ConsoleFlow
- type ConsoleFlowAction
- type ConsoleFlowNode
- type ConsoleFlowOutcome
- type ConsoleFlowResult
- type ConsoleFlowSpec
- type ConsoleSession
- func (s *ConsoleSession) EnterPassphrase(ctx context.Context, passphrase string, ...) (string, bool, error)
- func (s *ConsoleSession) NextMarker() string
- func (s *ConsoleSession) RunCommand(ctx context.Context, c ConsoleCommand) (ConsoleCommandResult, error)
- func (s *ConsoleSession) RunCommands(ctx context.Context, cmds []ConsoleCommand) ([]ConsoleCommandResult, error)
- func (s *ConsoleSession) WaitForAny(ctx context.Context, wants []string, timeoutSec int, artifact string) (string, bool, error)
- type ConsoleStep
- type ConsoleStepPlan
- type ConsoleStepResult
- type ConsoleTransport
- type ConsoleWizard
- type ContainerInspection
- type DefaultDownloader
- type DeployExecutor
- type DeployRecord
- type DocShape
- type EmitOpts
- type EngineConfig
- type EnvConfig
- type Executor
- type FetchedImage
- type GraderRequest
- type GraphicsEndpoint
- type HTTPRequest
- type HTTPResponse
- type InspectConfig
- type InspectHostConfig
- type InspectMount
- type InspectNetwork
- type InspectNetworkBind
- type InspectPortBind
- type JumpKind
- type KillEvidence
- type LabelDescriptionSet
- type LabeledDescription
- type LedgerLock
- type LedgerPaths
- type LocalImageInfo
- type LocalImageResolution
- type MemberRun
- type MethodSpec
- type NestedExecutor
- type NestedJump
- type ParsedPortMapping
- type ParsedRef
- type PlanContext
- type PlanGrammar
- type PollCond
- type PollFunc
- type PortConflict
- type ProvisionActor
- type RefsDownloader
- type ResolvedRuntime
- type Result
- type ReverseExecutor
- type ReverseOp
- type ReverseOpKind
- type ReverseRunner
- type RunMode
- type Runner
- func (r *Runner) Box() string
- func (r *Runner) CandyDirs() map[string]string
- func (r *Runner) CandyScanErr() error
- func (r *Runner) ClassifyUnresolved(op *spec.Op, name string) UnresolvedClass
- func (r *Runner) ContextSkipReason(op *spec.Op) string
- func (r *Runner) DialTimeout() time.Duration
- func (r *Runner) Distros() []string
- func (r *Runner) EffectiveDo(op *spec.Op) spec.DoMode
- func (r *Runner) EffectiveEnv() map[string]string
- func (r *Runner) Exec() Executor
- func (r *Runner) Grader() StepGrader
- func (r *Runner) HTTPClient() *http.Client
- func (r *Runner) HasRuntime() bool
- func (r *Runner) Instance() string
- func (r *Runner) MCPProvide() []spec.CandyMCPProvide
- func (r *Runner) Mode() RunMode
- func (r *Runner) ProbeNeverHang(op *spec.Op) time.Duration
- func (r *Runner) Run(ctx context.Context, checks []spec.Op) []CheckResult
- func (r *Runner) Scenario() *ScenarioContext
- func (r *Runner) SetScenario(sc *ScenarioContext)
- func (r *Runner) SetUnresolvedClassifier(f func(op *spec.Op, name string) UnresolvedClass)
- func (r *Runner) SkipDeterministicRun() bool
- func (r *Runner) SwapVenue(op *spec.Op) (func(), string)
- func (r *Runner) Verbs() VerbResolver
- func (r *Runner) VerifyOnly() bool
- func (r *Runner) VmName() string
- func (r *Runner) VmTargetName() string
- type RunnerConfig
- type RuntimeConfig
- type RuntimeVmConfig
- type SSHArgs
- type SSHExecutor
- type SSHReverseRunner
- type ScenarioContext
- type Scope
- type ScreenSignature
- type ShellExecutor
- type ShellKind
- type Status
- type StepGrader
- type StepKind
- type StepPass
- type StepProvider
- type StepRecord
- type StepResult
- type TagExpr
- type TerminalOpen
- type UnresolvedClass
- type Venue
- type VenueResolver
- type VerbResolver
- type VmSource
- type VmSshStanza
- type WalkOpts
Constants ¶
const ( // CheckLevelNone — skip acceptance entirely. CheckLevelNone = spec.CheckLevelNone // CheckLevelBuild — build-context ops only (charly check box). CheckLevelBuild = spec.CheckLevelBuild // CheckLevelNoAgent — build + deploy + runtime act/assert, NO do: instruct (default). CheckLevelNoAgent = spec.CheckLevelNoAgent // CheckLevelAgent — also run do: instruct steps through the agent grader. CheckLevelAgent = spec.CheckLevelAgent )
const ( ScopeSystem = spec.ScopeSystem ScopeUser = spec.ScopeUser ScopeUserProfile = spec.ScopeUserProfile ReverseOpPackageRemove = spec.ReverseOpPackageRemove ReverseOpCargoUninstall = spec.ReverseOpCargoUninstall ReverseOpNpmUninstallG = spec.ReverseOpNpmUninstallG ReverseOpPixiEnvRemove = spec.ReverseOpPixiEnvRemove ReverseOpRmFileSystem = spec.ReverseOpRmFileSystem ReverseOpRmFileUser = spec.ReverseOpRmFileUser ReverseOpRmDirRecursive = spec.ReverseOpRmDirRecursive ReverseOpServiceDisable = spec.ReverseOpServiceDisable ReverseOpServiceRemove = spec.ReverseOpServiceRemove ReverseOpRemoveDropin = spec.ReverseOpRemoveDropin ReverseOpRestoreEnabled = spec.ReverseOpRestoreEnabled ReverseOpRemoveManaged = spec.ReverseOpRemoveManaged ReverseOpRemoveEnvdFile = spec.ReverseOpRemoveEnvdFile ReverseOpRemoveRepoFile = spec.ReverseOpRemoveRepoFile ReverseOpCoprDisable = spec.ReverseOpCoprDisable ReverseOpPluginScript = spec.ReverseOpPluginScript )
const ( VenueLocal = exec.VenueLocal SignalKillErrMarker = exec.SignalKillErrMarker PodmanInfraExitCode = exec.PodmanInfraExitCode ContainerInfraErrMarker = exec.ContainerInfraErrMarker // JumpContainerExec is the ONE container-exec jump arm; the ENGINE is DATA // (NestedJump.Engine, a podman/docker/nerdctl word), so there is no per-engine // arm (the former JumpPodmanExec/JumpDockerExec are removed — a new engine sets // NestedJump.Engine, it does not add a JumpKind). JumpContainerExec = exec.JumpContainerExec JumpSSH = exec.JumpSSH JumpVirshConsole = exec.JumpVirshConsole CharlyInstallAuto = exec.CharlyInstallAuto CharlyInstallScp = exec.CharlyInstallScp CharlyInstallSkip = exec.CharlyInstallSkip )
const ( // ModeLive — `charly check live`, against a running container/VM (in-container probes). ModeLive = spec.CheckModeLive // ModeBox — `charly check box`, against a disposable build container. ModeBox = spec.CheckModeBox )
const ( StatusPass = spec.StatusPass StatusFail = spec.StatusFail StatusSkip = spec.StatusSkip )
const ( // DocShapeEmpty — a scalar-null / empty mapping document (nothing to load). DocShapeEmpty = spec.DocShapeEmpty // DocShapeNode — the unified name-first node-form. See spec.DocShapeNode. DocShapeNode = spec.DocShapeNode )
const ( DefaultBoxDir = spec.DefaultBoxDir // discovered box/<name>/ directory DefaultCandyDir = spec.DefaultCandyDir // discovered candy/<name>/ directory )
Layout path constants shared by core and kit. The canonical values moved to spec (spec.DefaultBoxDir / spec.DefaultCandyDir, #55 import-purity cone-render) — loader-result DATA the types-only spec module owns, mirroring spec.UnifiedFileName; kit re-exports them via const alias so existing kit.DefaultBoxDir / kit.DefaultCandyDir call sites (plugins + sdk) are untouched (R3, one source).
const ( KwRun spec.StepKeyword = "run" KwCheck spec.StepKeyword = "check" KwAgentRun spec.StepKeyword = "agent-run" KwAgentCheck spec.StepKeyword = "agent-check" KwInclude spec.StepKeyword = "include" )
const CharlyNetworkName = "charly"
CharlyNetworkName is the shared bridge network used by all charly containers.
const ConsoleDefaultTimeoutSec = 120
ConsoleDefaultTimeoutSec bounds one step's wait for its anchor.
const ConsoleFlowDefaultMaxLoops = 50
ConsoleFlowDefaultMaxLoops bounds how many times one node may be entered.
const ConsoleFlowDefaultMaxSteps = 200
ConsoleFlowDefaultMaxSteps bounds total node executions.
const ConsoleMarkerMaxEditDistance = 2
ConsoleMarkerMaxEditDistance is how many OCR character errors a marker line may differ from the marker and still count as a match. MEASURED (RCA): tesseract misreads individual marker characters (`2`->`Z`, `b`->`h`, `q`->`g`), so an exact comparison never matches a marker that IS on screen and the wait times out non-deterministically on the same code. A small edit distance tolerates those substitutions.
const ConsoleMarkerPrefix = "CHARLY_DONE_"
ConsoleMarkerPrefix identifies a completion marker on screen. It is chosen to be OCR-distinguishable (letters + underscores, no symbols OCR confuses).
The full marker carries a FRESH PER-COMMAND nonce after the prefix (see NextMarker). WITHOUT the nonce, a marker from a PREVIOUS run (or an earlier command) left in the terminal scrollback is a line equal to the current marker, so the wait completes on the STALE echo before the command runs — the RCA behind a flow matching an old `CHARLY_DONE_1` line still on screen. A fresh token makes both a stale and an earlier-command marker unmatchable.
const ConsoleOCRPSM = "11"
ConsoleOCRPSM is tesseract's sparse-text page-segmentation mode. A framebuffer console is scattered short labels, not a page of prose, and the default model finds little in it — the same mode the artifact validator uses.
const ConsoleOCRScale = 2
ConsoleOCRScale is the upscale factor the console engines apply before OCR by default. It is 2, MEASURED against a real Omarchy console (R1/RDD): a GUI installer's form labels OCR as `Usernane>` / `Confirn>` / `Hostnane>` at 1x (tesseract confuses the word-final `m>` for `n>`), which desynchronises any recipe anchored on `Username>` / `Confirm>` / `Hostname>`; at 2x they read correctly. A framebuffer TTY also reads better at 2x (`Usernane`→`Username`) while its shell anchors (`~`, `#`, `$`, `login:`) survive — at 4x they do not (`~`→`R`, `#`→`™`), the same reason the artifact validator's separate ocrUpscale is not reused here. 2 is the sweet spot for BOTH console shapes.
const ConsoleSessionDefaultPollInterval = 3 * time.Second
ConsoleSessionDefaultPollInterval mirrors the wizard's poll cadence.
const ConsoleSessionDefaultPromptTimeoutSec = 30
ConsoleSessionDefaultPromptTimeoutSec bounds the preflight shell-prompt wait (how long to poll for a shell prompt before refusing to type).
const ConsoleSessionDefaultTimeoutSec = 120
ConsoleSessionDefaultTimeoutSec bounds one command's wait for its marker.
const ConsoleSudoPrompt = "password"
ConsoleSudoPrompt is the substring a sudo password prompt contains (both the classic `[sudo] password for user:` and the bare `Password:`). Matched case-insensitively against OCR text.
const DefaultBootManager = "efibootmgr"
DefaultBootManager is the EFI boot-manager binary `boot-order` drives.
const DefaultCheckLevel = spec.DefaultCheckLevel
DefaultCheckLevel is the rung applied when a box declares no check_level.
const DefaultTerminalCombo = "super+Return"
DefaultTerminalCombo is used when a TerminalOpen sets no Combo: Omarchy's terminal hotkey.
const DeployConfigEnv = spec.DeployConfigEnv
deployconfig.go — re-export of the per-host deploy-overlay path resolver, RELOCATED to spec/spec/deployconfig.go (#55 value extraction). A pure host-path resolver over the deploy-config E-envelope, so it homes in spec; kit re-exports it here so existing kit.DeployConfigEnv / kit.DefaultDeployConfigPath call sites (plugins + sdk) are untouched. New consumers should reference spec.DeployConfigEnv / spec.DefaultDeployConfigPath.
const GraderDefaultTimeout = 5 * time.Minute
GraderDefaultTimeout bounds a single grader invocation when neither the `charly check feature run --timeout` flag nor the AI entry's own `timeout:` is set. Unlike the plateau-bounded harness loop, a grader call MUST be wall-clock-bounded so one stuck prose step can't hang an acceptance run.
const HostVar = "HOST"
HostVar is the cross-member address variable name — ${HOST:<member>} (+ optional :port). An unresolved one means the member is UNREACHABLE (a real failure, never a skip).
const ScreenDefaultMaxDistance = 5
ScreenDefaultMaxDistance is the default Hamming threshold for a reference match — tolerant of small rendering differences without matching a different screen.
Variables ¶
var ( ResolveApkPath = checkhost.ResolveApkPath ResolveCommittedApk = checkhost.ResolveCommittedApk )
apk_path.go — ResolveApkPath + ResolveCommittedApk RELOCATED to the spec fabric slice github.com/opencharly/spec/checkhost (#55 CHECK-ENGINE cone Option A — the committed-APK candy-source anchoring the adb:/appium: check verbs + candy/plugin-adb's deploy:android collector share; a pure filesystem walk-up, homed in the check-host fabric slice so charly core reaches it importing zero kit). kit re-exports so existing kit.ResolveApkPath / kit.ResolveCommittedApk call sites (charly + candy/plugin-adb) are untouched.
var ( ContainerName = spec.ContainerName ContainerNameInstance = spec.ContainerNameInstance )
var ( StampDescent = spec.StampDescent DescentFromTraits = spec.DescentFromTraits )
descent.go — re-export of the descent stamper, RELOCATED to spec/spec/descent.go (#55 fabric-primitive/value extraction). StampDescent/DescentFromTraits are pure #Deploy-tree value transforms over the E-envelope, so they home in spec; kit re-exports them here so every existing kit.StampDescent / kit.DescentFromTraits call site (plugins + sdk) is untouched. New consumers should reference spec.StampDescent / spec.DescentFromTraits.
var ( EngineBinary = container.EngineBinary GPURunArgs = container.GPURunArgs DetectEngine = container.DetectEngine // EngineCapabilityFor / EngineRunModeFor / IsUnitRunMode expose the engine // capability DATA (the name→facts table) so kit consumers stop switching on // the engine name. The capability STRUCT TYPE is spec.EngineCapability (the // generated schema type) — consumers name it directly; no alias here. EngineCapabilityFor = container.EngineCapabilityFor EngineRunModeFor = container.EngineRunModeFor IsUnitRunMode = container.IsUnitRunMode )
engine.go — re-export of the container-engine helpers, RELOCATED to the spec/container fabric slice (#55 fabric-primitive extraction). EngineBinary/GPURunArgs/DetectEngine are host engine-resolution primitives (DetectEngine shells `LookPath`), homed in spec/container which carries os/exec in its own slice (Rule 2). kit re-exports them here so kit's own callers (container_image.go/container_probe.go/runtime_config.go's ResolveRuntime) and every existing kit.EngineBinary / kit.GPURunArgs / kit.DetectEngine call site are untouched.
var ( LoadProcessDotenv = hostenv.LoadProcessDotenv ParseEnvFile = hostenv.ParseEnvFile ParseEnvBytes = hostenv.ParseEnvBytes LoadWorkspaceEnv = hostenv.LoadWorkspaceEnv ResolveEnvVars = hostenv.ResolveEnvVars EnrichNoProxy = hostenv.EnrichNoProxy DotenvLoaded = hostenv.DotenvLoaded )
var ( RunCaptureCmd = exec.RunCaptureCmd NestedContainerName = exec.NestedContainerName WaitForSSH = exec.WaitForSSH WaitForCloudInit = exec.WaitForCloudInit WaitForPackageLock = exec.WaitForPackageLock VenueFromDescriptor = exec.VenueFromDescriptor ContainerChainFromDescriptor = exec.ContainerChainFromDescriptor DescriptorFromExecutor = exec.DescriptorFromExecutor ResolveCharlyInstallStrategy = exec.ResolveCharlyInstallStrategy HostCharlyIsNewer = exec.HostCharlyIsNewer EnsureCharlyInDeployVenue = exec.EnsureCharlyInDeployVenue EnsureCharlyInGuest = exec.EnsureCharlyInGuest BuilderRun = exec.BuilderRun BuildBuilderRunArgs = exec.BuildBuilderRunArgs UserScopeBindMounts = exec.UserScopeBindMounts UserScopeEnv = exec.UserScopeEnv ClassifyContainerInfraFailure = exec.ClassifyContainerInfraFailure IsContainerInfraResult = exec.IsContainerInfraResult ContainerInfraError = exec.ContainerInfraError )
var ( ErrLockBusy = lock.ErrLockBusy AcquireFileLock = lock.AcquireFileLock AcquireFileLockWithin = lock.AcquireFileLockWithin ImageBuildLockPath = lock.ImageBuildLockPath AcquireImageBuildLock = lock.AcquireImageBuildLock AcquireLocalPkgBuildLock = lock.AcquireLocalPkgBuildLock )
filelock.go — re-export of the advisory-flock primitive, RELOCATED to the spec/lock fabric slice (#55 fabric-primitive extraction). A file lock is a host primitive a plugin cannot hold, so it homes in spec/lock (carrying syscall in its own slice, Rule 2); kit re-exports the symbols here so the compiled-in candy/plugin-preempt and every existing kit.AcquireFileLock / kit.ErrLockBusy / … call site are untouched. New consumers should import spec/lock directly.
var ( StripPortSuffix = spec.StripPortSuffix ParsePortMapping = spec.ParsePortMapping FormatPortMapping = spec.FormatPortMapping )
var ( ServiceName = spec.ServiceName ServiceNameInstance = spec.ServiceNameInstance QuadletFilename = spec.QuadletFilename QuadletFilenameInstance = spec.QuadletFilenameInstance PodQuadletFilename = spec.PodQuadletFilename PodQuadletFilenameInstance = spec.PodQuadletFilenameInstance SidecarQuadletFilename = spec.SidecarQuadletFilename SidecarQuadletFilenameInstance = spec.SidecarQuadletFilenameInstance QuadletDir = spec.QuadletDir SystemdUserDir = spec.SystemdUserDir QuadletExists = spec.QuadletExists QuadletExistsInstance = spec.QuadletExistsInstance )
var ( RepoGitURL = refs.RepoGitURL // sdk/loaderkit GitDefaultBranch = refs.GitDefaultBranch // sdk/loaderkit CompareSemver = refs.CompareSemver // sdk/loaderkit + candy/plugin-box DownloadRepo = refs.DownloadRepo // kit refs_downloader.go DefaultDownloader )
refs_git.go — the kit tail of the remote-repo GIT primitives (P7). The pure git-exec + string primitives + cache-path helpers RELOCATED to the spec/refs fabric slice (#55 fabric-primitive extraction); charly core reaches them via spec/refs directly. This file keeps ONLY:
- DiscoverRemoteCandy, which needs the kit-local layout constant DefaultCandyDir; and
- thin re-export shims for the primitives with a remaining sdk/candy caller (sdk/loaderkit + candy/plugin-refs's DefaultDownloader), so those keep compiling unchanged. The shims are tracked residue that die when loaderkit + plugin-refs migrate onto spec/refs in their cones.
var ( StripURLScheme = spec.StripURLScheme IsRemoteImageRef = spec.IsRemoteImageRef ParseRemoteRef = spec.ParseRemoteRef ResolveBoxName = spec.ResolveBoxName )
var ( LoadRuntimeConfig = hostenv.LoadRuntimeConfig SaveRuntimeConfig = hostenv.SaveRuntimeConfig ResolveRuntime = hostenv.ResolveRuntime ResolveValue = hostenv.ResolveValue ValidateEngine = hostenv.ValidateEngine ValidateRunMode = hostenv.ValidateRunMode DetectRunMode = hostenv.DetectRunMode SystemdUserAvailable = hostenv.SystemdUserAvailable ValidateBindAddress = hostenv.ValidateBindAddress ResolveEncryptedStoragePath = hostenv.ResolveEncryptedStoragePath ResolveVolumesPath = hostenv.ResolveVolumesPath ExpandHostHome = hostenv.ExpandHostHome ResolveAutoEnable = hostenv.ResolveAutoEnable )
var ( PodName = spec.PodName PodNameInstance = spec.PodNameInstance SidecarContainerName = spec.SidecarContainerName SidecarContainerNameInstance = spec.SidecarContainerNameInstance )
var AcquireVmDomainLock = lock.AcquireVmDomainLock
AcquireVmDomainLock takes a BLOCKING, host-global advisory lock serializing every check bed that occupies the given libvirt domain. Re-exported from lock.AcquireVmDomainLock.
var AnchorScanSpecs = spec.AnchorScanSpecs
AnchorScanSpecs forwards to spec.AnchorScanSpecs — the ONE path-anchoring mechanism, now resident in the spec module. Kept as a var alias so kit's own walk.go caller stays terse and there is exactly one implementation.
var BedVmDomains = lock.BedVmDomains
BedVmDomains returns the sorted, deduped libvirt domain names (charly-<from>) a bed's VM(s) occupy. Re-exported from lock.BedVmDomains (the body lives there).
var CheckLevelReaches = spec.CheckLevelReaches
CheckLevelReaches reports whether a box resolved to `have` runs at least as deep as `want`.
var ClassifyDoc = spec.ClassifyDoc
ClassifyDoc inspects a document's top level and returns its shape. See spec.ClassifyDoc.
var ClassifyStepFailures = report.ClassifyStepFailures
ClassifyStepFailures splits FAIL results into genuine check failures vs. container-setup INFRA failures. Re-exported from report.ClassifyStepFailures.
var CompareCalVer = calver.CompareCalVer
calver_compare.go — re-export of the lenient dotted-string CalVer comparator, RELOCATED to spec/calver (#55 value extraction). kit re-exports it so every existing kit.CompareCalVer call site (charly image-tag logic + sdk/deploykit render engine) is unchanged.
var ContainerExists = defaultContainerExists
ContainerExists reports whether a container exists (RUNNING OR STOPPED) — a bare `container inspect` succeeds for any existing container, so its exit status is the signal. R3 consolidation (K-wave 2 cone R2 bank C): the shared home for the token-identical copies that used to travel per module (candy/plugin-pod's `container exists` form + the new candy/plugin-fleet del-resolve probe); charly core keeps its OWN copy (import purity — charly/ imports only spec, and spec/container.EngineBinary is the allowed equivalent). Package-level var for testability (tests inject a stub, same pattern as ContainerRunning).
var ContainerImage = container.ContainerImage
ContainerImage returns the image ref for a running container, best-effort ("" on error). Re-exported from container.ContainerImage.
var ContainerImageRef = container.ContainerImageRef
ContainerImageRef returns the image ref backing a running container (.Config.Image via `<engine> inspect`). Re-exported from container.ContainerImageRef (the body lives there).
var ContainerRunning = defaultContainerRunning
ContainerRunning reports whether a container is running. Package-level var for testability (tests inject a stub, same pattern as EnsureCharlyNetwork/InspectLabels).
var CurrentCharlyExecutable = os.Executable
CurrentCharlyExecutable is the executable that owns the current check/deploy-verify run. Keeping it a package var (not a direct os.Executable() call) lets a caller's test prove the resolver contract uses the ACTIVE binary rather than a stale PATH selection.
var DefaultDeployConfigPath = spec.DefaultDeployConfigPath
var DefaultLUKSFailureAnchors = []string{"No key available", "wrong password", "Failed to activate"}
DefaultLUKSFailureAnchors mean the passphrase was REJECTED.
var DefaultLUKSSuccessAnchors = []string{"login:", "Welcome", "succeeded", "Booting"}
DefaultLUKSSuccessAnchors mean the passphrase was ACCEPTED and boot proceeded.
var DefaultPromptAnchors = []string{"$", "#", ">"}
DefaultPromptAnchors are the substrings that mean a shell prompt is ready.
var DirExists = loader.DirExists
DirExists reports whether path exists and is a directory. See loader.DirExists.
var DiscoverSkipDir = loader.DiscoverSkipDir
DiscoverSkipDir reports whether a directory name is a VCS or build-artifact dir that never contains a discoverable charly.yml manifest. See loader.DiscoverSkipDir.
var DoHTTPRequest = http.DoHTTPRequest
DoHTTPRequest issues req from the HOST's network namespace. Re-exported from http.DoHTTPRequest (the body lives there).
var EndpointForVenue = checkhost.EndpointForVenue
var EnsureCharlyNetwork = defaultEnsureCharlyNetwork
EnsureCharlyNetwork creates the "charly" network if it does not exist. It is a package-level var for testability.
var EnvMapToPairs = proc.EnvMapToPairs
EnvMapToPairs converts the deploy schema's env map into sorted KEY=VALUE pairs (the OCI-label wire + env-resolution chain form). RELOCATED to the spec/spec fabric slice (#55 coneB build-render cone, Class A — github.com/opencharly/spec/spec/env_pairs_coneb.go); re-exported here so every existing kit.EnvMapToPairs call site (sdk/deploykit's deploy_file.go + read_labels.go, kit/box_metadata.go) is unchanged. New consumers reference proc.EnvMapToPairs directly.
var ErrImageNotLocal = spec.ErrImageNotLocal
ErrImageNotLocal is the canonical image-not-in-local-storage sentinel (spec/spec/image_errors.go).
var ErrStaleLocalImage = spec.ErrStaleLocalImage
ErrStaleLocalImage is the canonical stale-short-name-resolve sentinel (spec/spec/image_errors.go), returned by ResolveBuiltImageRef.
var ExpandPath = spec.ExpandPath
ExpandPath (a pure ~/${HOME}/$HOME path expander) now lives in spec (spec.ExpandPath, #55 import-purity cone-render); kit re-exports it via alias so every existing kit.ExpandPath call site (sdk) is untouched (R3, one source).
var ExtractCalVerTag = container.ExtractCalVerTag
ExtractCalVerTag returns the CalVer portion of a ref's tag, or "" if the tag is not a recognisable CalVer (`YYYY.DDD.HHMM`).
var ExtractMetadata = container.ExtractMetadata
ExtractMetadata reads OCI labels from a local image and returns parsed spec.BoxMetadata. Returns nil if the image has no ai.opencharly labels. Returns spec.ErrImageNotLocal wrapped with the image ref if the image is not in local storage.
var FileExists = loader.FileExists
FileExists reports whether path exists and is a regular (non-dir) file. See loader.FileExists.
var FindEntityDirs = loader.FindEntityDirs
FindEntityDirs walks a scan root and returns every directory that contains the given canonical filename. See loader.FindEntityDirs.
var FirstYAMLVersionLine = spec.FirstYAMLVersionLine
FirstYAMLVersionLine extracts the value of the first top-level `version:` line. RE-EXPORT shim: the body was RELOCATED to spec/spec (yaml_version_line.go, #55 coneG import-purity — charly core's refs.go inlines spec.FirstYAMLVersionLine, dropping its sdk/kit import). This var keeps the existing kit.FirstYAMLVersionLine plugin call sites (candy/plugin-migrate/engine.go) unchanged; new charly-core consumers reference spec.* directly. Pure string parsing (strings.SplitSeq + CutPrefix + TrimSpace), no yaml.v3.
var FormatHTTPHeaders = http.FormatHTTPHeaders
FormatHTTPHeaders renders an http.Header into a "Key: value\n" blob. Re-exported from http.FormatHTTPHeaders (the body lives there).
var FormatStepResultsJSON = report.FormatStepResultsJSON
FormatStepResultsJSON emits a structured JSON document. Re-exported from report.FormatStepResultsJSON.
var FormatStepResultsJUnit = report.FormatStepResultsJUnit
FormatStepResultsJUnit emits JUnit XML for CI dashboards. Re-exported from report.FormatStepResultsJUnit.
var FormatStepResultsTAP = report.FormatStepResultsTAP
FormatStepResultsTAP emits TAP v13. Re-exported from report.FormatStepResultsTAP.
var FormatStepResultsText = report.FormatStepResultsText
FormatStepResultsText emits a human-readable per-step report to w. Re-exported from report.FormatStepResultsText.
var HTTPClientFor = http.HTTPClientFor
HTTPClientFor builds a per-request *http.Client honoring the HTTPRequest policy, derived from the engine's base client. Re-exported from http.HTTPClientFor (the body lives there).
var InputStr = spec.InputStr
InputStr reads a string field from the step's desugared plugin input map — homed in the spec contract module (spec.InputStr, op_input.go, #55 CHECK-ENGINE cone) so charly core reads a step's per-verb input while importing only spec; re-exported here so the kit.InputStr / kit.Pos* call sites compile unchanged.
var InspectContainer = defaultInspectContainer
InspectContainer is swappable for tests. Real calls shell out to `<engine> inspect <name>` (which returns a one-element JSON array).
var InspectImageLabels = container.InspectImageLabels
InspectImageLabels reads a local image's OCI labels via engine inspect. RELOCATED to spec/container (coneA); re-exported here so every existing kit.InspectImageLabels call site is untouched.
var InspectLabels = container.InspectLabels
InspectLabels reads OCI labels from a local image via engine inspect. Package-level var for testability — re-exported from spec/container (the canonical home). Override container.InspectLabels to stub in tests.
var InstallDirAtomic = lock.InstallDirAtomic
InstallDirAtomic atomically installs the freshly-populated tmp directory as final.
var InvalidateImageCache = container.InvalidateImageCache
InvalidateImageCache clears the persistent image-list cache. Called by the build and deploy commands (charly box build / deploy add / update) — every operation that creates or pulls an image — so the next status run re-fetches the fresh image list instead of serving a stale cache.
var IsHostNetworked = container.IsHostNetworked
container_probe.go — the pure container-runtime host probes (K4: relocated from the deleted charly/container.go and charly/shell.go — genuinely pure `<engine>` shell-outs with no project-loader dependency). Consumed directly by candy/plugin-deploy-pod/plugin-pod/plugin-adb and by charly core's remaining caller (commands.go, the check harness), which import kit directly (K3 ZERO-ALIASES — no alias file); android_deploy_cmd.go and volume_cp_tags_cmd.go, former core callers, are both since deleted.
IsHostNetworked RELOCATED to the spec fabric slice github.com/opencharly/spec/container (#55 CHECK-ENGINE cone Option A — a podman-inspect probe, the slice's charter), re-exported below so kit.IsHostNetworked call sites are untouched.
var IsValidCheckLevel = spec.IsValidCheckLevel
IsValidCheckLevel reports whether level is one of the four canonical rungs.
var ListLocalImages = container.ListLocalImages
ListLocalImages returns all images in the engine's local storage.
var LocalImageExists = container.LocalImageExists
LocalImageExists checks whether an image reference exists in the given engine's local store. Package-level var for testability (same pattern as DetectGPU in gpu.go). RELOCATED to the spec/container fabric slice (#55 coneB build-render cone, Class A — co-located with the ResolveLocalImageRef family that reads it); re-exported here so every existing direct kit.LocalImageExists call site (candy/plugin-build, candy/plugin-box, candy/plugin-deploy-pod, candy/plugin-kube, charly core's host_build_pod_config_seams + ensure_image) is unchanged. Override container.LocalImageExists (the var container.ResolveLocalImageRef reads) to stub the resolution path in tests; this kit re-export var is a value-copy that no longer affects the relocated body.
var LooksLikeFullRef = container.LooksLikeFullRef
LooksLikeFullRef returns true if the image ref contains a registry segment (a "/" before any ":") — e.g. "ghcr.io/org/name:tag" — so it can be pulled without charly.yml resolution.
var MappingRoot = spec.MappingRoot
MappingRoot unwraps a YAML document node to its top-level mapping node (or nil). Relocated to sdk/spec (FLOOR-SLIM axis-A mechanical batch, zero logic change); aliased here so every existing kit.MappingRoot call site (charly core's former mappingRoot alias + the out-of-module candy/plugin-migrate engine) keeps compiling unchanged (R3).
var ParseCalVer = calver.ParseCalVer
var ParseLocalImagesJSON = container.ParseLocalImagesJSON
ParseLocalImagesJSON parses `{podman,docker} images --format json` output into ONE LocalImageInfo per distinct image ID.
var ParsePublishedPort = container.ParsePublishedPort
ParsePublishedPort RELOCATED to the spec fabric slice github.com/opencharly/spec/container (#55 CHECK-ENGINE cone Option A — a pure `podman port` output parser, the slice's charter), re-exported here so kit.ParsePublishedPort call sites are untouched.
var Plural = report.Plural
Plural returns "" for n==1 and "s" otherwise — the trivial English pluralization used by the result reporters and the eventually-retry summaries. Re-exported from report.Plural.
var RepoLayoutDirs = []string{"candy", "box"}
RepoLayoutDirs is the repo layout subdirectory vocabulary — the candy/ + box/ dirs that hold authorable entities in every OpenCharly repo (superproject and box submodules). The ONE shared sdk constant (F4.4 parser consolidation): candywalk's root walk and the migrators' candidate-file scan both read it, replacing the byte-identical hand literals.
var ReportStepResults = report.ReportStepResults
ReportStepResults writes results in the requested format. Re-exported from report.ReportStepResults.
var ReportStepResultsCount = report.ReportStepResultsCount
ReportStepResultsCount renders results per format via ReportStepResults and returns how many results ended in a FAIL verdict. Re-exported from report.ReportStepResultsCount.
var ResolveBuiltImageRef = container.ResolveBuiltImageRef
ResolveBuiltImageRef resolves like ResolveLocalImageRef and REFUSES when the elected image is not the newest local build of that short name. The resolver for every verb that pronounces a VERDICT on a built artifact (`charly check box`, `charly box feature run`, `charly box labels`): a green verdict against a stale artifact is indistinguishable from a real one, so the ambiguity is an error rather than a silent choice.
var ResolveCheckLevel = spec.ResolveCheckLevel
ResolveCheckLevel normalizes an authored check_level to a canonical rung, applying the default for the empty value.
var ResolveLocalImage = container.ResolveLocalImage
ResolveLocalImage is ResolveLocalImageRef's full-answer form (elected ref + newest build ref).
var ResolveLocalImageRef = container.ResolveLocalImageRef
ResolveLocalImageRef resolves a user-supplied image reference against the engine's local storage — never reads charly.yml. The LENIENT form: it elects a ref and says nothing about what it passed over.
var ResolveNewestLocalCalVer = container.ResolveNewestLocalCalVer
ResolveNewestLocalCalVer is the canonical "find the newest local image for this short name" helper.
var ResolvePackageName = checkstep.ResolvePackageName
ResolvePackageName picks the correct package name for the running image's distro. Re-exported from checkstep.ResolvePackageName (the body lives there); the single cross-distro name resolver shared by the `package` candy's check + act + step materializer (R3).
var ResolveShellImageRef = container.ResolveShellImageRef
ResolveShellImageRef builds the full image reference from registry, name, and tag.
var RuntimeOnlyVarPrefixes = []string{
"HOST_PORT",
"VOLUME_PATH",
"VOLUME_CONTAINER_PATH",
"CONTAINER_IP",
"CONTAINER_NAME",
"INSTANCE",
"ENV_",
"STEP_ID",
"VM_HOSTDEV_COUNT",
"DEPLOY_NAME",
"HOST",
}
RuntimeOnlyVarPrefixes lists variable name prefixes that are only resolvable against a running container. scope:"build" checks must not reference these.
var ScalarNode = spec.ScalarNode
ScalarNode builds a string scalar YAML node. Relocated to sdk/spec (FLOOR-SLIM axis-A mechanical batch, zero logic change) so charly core can call it without importing kit; aliased here so every existing kit.ScalarNode call site (candy/plugin-migrate + others) keeps compiling unchanged.
var SudoLocalImageExists = defaultSudoLocalImageExists
SudoLocalImageExists checks whether an image reference exists in the rootful (sudo podman) local store. Mirrors LocalImageExists but always queries the root user's storage namespace, regardless of the caller's BuildEngine. The rootless and rootful podman storage roots are isolated, so an image built by the user's `podman build` is invisible to `sudo podman` until transferred.
Package-level var for testability (same pattern as LocalImageExists).
var TestVarRefPattern = regexp.MustCompile(`\$\{([A-Z_][A-Z0-9_]*)(?::([^}]+))?\}`)
TestVarRefPattern matches a ${NAME} or ${NAME:arg} reference (uppercase-underscore names).
var TransferImage = container.TransferImage
TransferImage pipes an image from one engine to another via save | load. RELOCATED to the spec/container fabric slice (#55 coneC — charly/ off sdk/kit, co-located with the EngineBinary + LocalImageExists family this transfer path complements); re-exported here so every existing direct kit.TransferImage call site (candy/plugin-build, candy/plugin-box, candy/plugin-deploy-pod, …) is unchanged. A package-level var (not a func) so tests can override it the same way as LocalImageExists.
var TrimPreview = spec.TrimPreview
TrimPreview truncates s to a 200-char preview — homed in the fabric slice github.com/opencharly/spec/spec (the same fabric-primitive class as ShellQuote), re-exported here so kit.TrimPreview callers compile unchanged (R3, single source).
var UnixToTCPBridge = checkhost.UnixToTCPBridge
vnc_bridge.go — UnixToTCPBridge RELOCATED to the spec fabric slice github.com/opencharly/spec/checkhost (#55 CHECK-ENGINE cone Option A — pure host-side networking, a check host-vantage primitive). kit re-exports so every existing kit.UnixToTCPBridge call site (charly's ssh.go / the VM-VNC endpoint resolution) is untouched.
var VmSshAlias = spec.VmSshAlias
VmSshAlias returns the canonical alias for a VM deployment name ("charly-" namespaced). The pure naming leaf now lives in package spec (a peer of VmDomainIdentity — the always-floor- legal wire/vocabulary home, #55 K4); kit re-exports it so the host-coupled ssh-config-fragment writers here (renderStanza/VmSshStanza/SshFragmentPath, which STAY in kit — they write ~/.config/charly/ssh_config) reference `kit.VmSshAlias` unchanged.
var WrapContainerCommand = spec.WrapContainerCommand
WrapContainerCommand guards an in-container command-check script against stdin-consuming subcommands. RELOCATED to the spec contract module (spec.WrapContainerCommand, wrap_container.go, #55 CHECK-ENGINE cone Option A — a pure stdlib string guard charly core's check-op dispatch reaches importing zero kit); re-exported here so every existing kit.WrapContainerCommand call site (charly core + the candies + sdk) is untouched. New consumers should call spec.WrapContainerCommand directly.
Functions ¶
func AddBox ¶ added in v0.2026193.1241
AddBox writes a new box to its discovered per-box file box/<name>/charly.yml as a node-form IMAGE — `<name>: {candy: {base: …}}`. The base argument is the value of the image's `base:` field (an external URL or the name of another box). If layers is non-nil it populates the image's `candy:` composition list. Errors if box/<name>/charly.yml exists.
func AddCandyDeployment ¶ added in v0.2026190.848
func AddCandyDeployment(paths *LedgerPaths, candyName, deployID string, update func(*CandyRecord)) error
AddCandyDeployment adds deployID to candy.DeployedBy and writes the record. Used at install time.
A candy record is SHARED by every deploy that uses it (refcounted by DeployedBy), so its reverse_ops must be the UNION of the ops each deploy contributed — a replacement would lose an earlier deploy's teardown and leak its resource. The callback's `rec.ReverseOps = …` is therefore treated as DECLARING THIS deploy's ops and merged (content-dedup) over the ops already recorded, rather than replacing them; see MergeReverseOps and charly#687.
func AddCandyDeploymentVia ¶ added in v0.2026190.848
func AddCandyDeploymentVia(exec spec.DeployExecutor, paths *LedgerPaths, candyName, deployID string, update func(*CandyRecord)) error
AddCandyDeploymentVia is the executor-routed variant of AddCandyDeployment. When exec is nil or a local executor, it falls back to operator-side file I/O (today's behaviour). When exec is a non-local DeployExecutor (SSHExecutor / NestedExecutor), the ledger I/O goes through exec.GetFile + exec.RunUser so the ledger lands on the substrate's filesystem under the substrate's ~/.config/charly/charly.yml — matching the install's actual venue (arch-vm.arch-host writes in the arch VM guest; sway-pod with nested pods writes in the parent pod; etc.).
func AnnotateNeverHangKill ¶ added in v0.2026229.1907
AnnotateNeverHangKill names the per-attempt never-hang bound in a step's failure message. The exec layer reports only "process terminated by signal (signal: killed)", which describes the mechanism of death and not its cause — so a step killed by the bound reads as a crash in whatever the step was running, and the reader goes looking for a bug in their own command. The bound is known at the moment the deadline fires; not saying so is what makes it a diagnostic dead end.
A legitimately slow step raises the ceiling with `timeout:`, which ProbeNeverHang honours over the floor — the mechanism's own parameter, not a workaround.
func AnnotateNeverHangKillWithEvidence ¶ added in v0.2026282.1057
func AnnotateNeverHangKillWithEvidence(msg string, ev KillEvidence) string
AnnotateNeverHangKillWithEvidence appends the bound-and-remedy line the never-hang kill always carries, and — when a local observation exists — one more line naming the absent signal: the process was still alive and silent, or it was already gone. It is the ONE implementation; AnnotateNeverHangKill is its unobserved case.
func AppendUnique ¶ added in v0.2026198.345
AppendUnique appends items to dst, skipping any already present in dst.
func ApplyPortOverrides ¶ added in v0.2026190.848
ApplyPortOverrides modifies port mappings based on --port flags. Each override is "newHost:containerPort". It replaces the host port for the matching container port in the ports list. Preserves protocol suffixes like /udp.
func AtomicWriteFile ¶ added in v0.2026192.1709
AtomicWriteFile writes data to path atomically: a temp file in the SAME dir (same filesystem, so rename is atomic) is written, chmod'd, then renamed over path. A concurrent reader sees either the old complete file or the new complete file, never a partial write; concurrent writers of identical content converge (last rename wins, bytes identical). Relocated from charly core (P8) so the build render engine (sdk/deploykit) and charly's staging primitives share it.
func BareVolumeName ¶ added in v0.2026197.1320
BareVolumeName strips the "charly-<box>[-<instance>]-" prefix from a resolved volume name.
P12a: relocated from sdk/deploykit/quadlet.go (a pure string helper with no deploykit-specific coupling) so this file's mergeRuntimeVars can call it without a kit→deploykit import (deploykit already imports kit — the reverse direction would cycle). deploykit's own caller now calls kit.BareVolumeName.
func BuildActivityDir ¶ added in v0.2026205.1618
BuildActivityDir is the user-scope directory of live build-activity locks — one flocked nonce file per in-flight `charly box build` engine run.
func BuildArchExports ¶
func BuildArchExports() string
BuildArchExports emits the BUILD_ARCH=$(uname -m) + ARCH=<buildkit-triplet> shell preamble so a cmd:/download: body can template ${ARCH}/${BUILD_ARCH} at deploy-time the same way the container build gets them from BuildKit's TARGETARCH.
func BuildCommandLine ¶ added in v0.2026269.700
BuildCommandLine composes the line typed for a command: the command (prefixed with sudo when requested), a terminating `; echo <marker>`, so the shell echoes marker only after the command has finished. The prefix is appended with `;` so it runs regardless of the command's own exit status.
It is PURE, so the exact line the engine types is unit-locked without a device.
func BuilderCollectContext ¶
func BuilderCollectContext(word string, in spec.BuilderCollectInput) map[string]any
BuilderCollectContext returns the builder-specific stage-context keys for `word` given the host-supplied candy descriptor. An unknown word returns nil (a custom candy builder with no plugin keeps base-only context — the host never invokes a plugin for it).
func BuilderResolve ¶
func BuilderResolve(word string, in spec.BuilderResolveInput) (spec.BuilderResolveReply, error)
BuilderResolve renders `word`'s build-time multi-stage from the host-supplied context, returning the pieces the host splices into the Containerfile: Stage (pre-main-FROM), CopyArtifacts + CopyBinary (post-main-FROM), or InlineFragment (in-candy, inline builders). An unknown word is a LOUD error (never a silent empty stage). This is the ONE render both the box-build plugin OpResolve and the in-proc pod-overlay build-emit call (R3).
func BuilderReverse ¶
func BuilderReverse(word string, in spec.BuilderReverseInput) []spec.ReverseOp
BuilderReverse returns the teardown ops for `word` given its resolved stage context (the BuilderCollectContext output the host stored on the BuilderStep). An unknown word, or a context missing the keys a builder needs, returns nil (no teardown — the same best-effort the in-proc builders had).
func CargoLdConfPath ¶ added in v0.2026240.2049
CargoLdConfPath returns the ld.so.conf.d drop-in that puts CargoLibDir on the loader path. Without it a per-candy directory would be invisible to the dynamic loader, which is the price of making the install identifiable — so the drop-in is emitted with it, never separately.
func CargoLibDir ¶ added in v0.2026240.2049
CargoLibDir returns the directory a cargo LIBRARY crate's artifacts install into for a given candy. Per-candy rather than a flat /usr/local/lib so the install is identifiable and therefore reversible: BuilderReverse can remove exactly this directory, where a flat install would leave charly unable to tell its own .so files from anyone else's.
func CloseHostCleanups ¶ added in v0.2026197.1537
func CloseHostCleanups(cleanups []func())
CloseHostCleanups tears down any ssh -L forwards opened while resolving ${HOST:<member>} address variables. Safe to call on a nil/empty slice.
func CloseTerminal ¶ added in v0.2026269.700
func CloseTerminal(ctx context.Context, tr ConsoleTransport) (string, error)
CloseTerminal exits an open terminal. The generic `close-terminal` (R3).
func CollectAnyStrings ¶ added in v0.2026191.2033
CollectAnyStrings returns every string within a plugin_input value (scalar string / nested map / list), depth-first. The READ-ONLY analogue of ExpandAnyVars: it lets the ${HOST:…} cross-member scan (collectHostRefs) reach a plugin verb's authored fields, which live in the opaque PluginInput map rather than StringFields.
func CollectHostRefs ¶ added in v0.2026197.1537
CollectHostRefs returns the distinct ${HOST:<member>} variable keys referenced across every string field of every check (keys in the "NAME:arg" form used by ExpandTestVars).
func ConsolePreview ¶ added in v0.2026266.2315
ConsolePreview clips s to a single line of at most n characters, for an error message. It collapses ALL whitespace runs (newlines included) to single spaces and appends an ellipsis when it truncates. It is the ONE such clip in the SDK — artifact.go's error paths call it too, so OCR text is rendered the same way wherever it is quoted back.
func ContainerPortsFromMappings ¶ added in v0.2026190.848
ContainerPortsFromMappings extracts the container-side port number from each mapping. "auto" sentinels are skipped (they have no container port to extract — they ARE the request to allocate one). Unparseable entries are silently dropped (the loud-skip warning lives in CheckPortAvailability).
func DecodeInput ¶
DecodeInput decodes an Op's plugin_input (map[string]any) into a candy's CUE-generated typed params struct via a JSON round-trip. A nil/empty input leaves out at its zero value; the host has already validated the input against the served schema.
func DeleteCandyRecord ¶ added in v0.2026190.848
func DeleteCandyRecord(paths *LedgerPaths, layer string) error
DeleteCandyRecord removes ledger.candies[layer].
func DeleteDeployRecord ¶ added in v0.2026190.848
func DeleteDeployRecord(paths *LedgerPaths, id string) error
DeleteDeployRecord removes ledger.deploys[id]; silently ignores not-found (teardown is idempotent).
func DirectDeployMarkerDir ¶ added in v0.2026198.345
DirectDeployMarkerDir returns ~/.config/charly/direct/, the registry directory for direct-mode deploys (the equivalent of ~/.config/containers/systemd/ for quadlet deploys).
func DirectDeployMarkerPath ¶ added in v0.2026198.345
DirectDeployMarkerPath returns the marker JSON path for a deploy.
func DiscoverRemoteCandy ¶ added in v0.2026192.1026
DiscoverRemoteCandy returns the list of candy names in a remote repo directory
func EffectiveStepID ¶ added in v0.2026191.2205
EffectiveStepID returns the step's author id when set, else a derived id.
func EffectiveTags ¶ added in v0.2026191.1413
EffectiveTags normalizes and de-dups a step's tags, preserving first-seen order. (Per-step tags only — there is no group-level tag inheritance.)
func EnableUnit ¶ added in v0.2026276.152
EnableUnit runs `systemctl [--user] enable --now <unit>` on the venue. Exported for the workflow/lowering path, which enables a generated TIMER unit beside the engine's own deploy steps — the deployment walk and the workflow lowering must drive systemd through ONE call site (R3).
func EnsureSshConfigInclude ¶ added in v0.2026186.739
EnsureSshConfigInclude inserts the managed `Include ~/.config/charly/ssh_config` directive at the TOP of the user's ~/.ssh/config (creating it if needed) — the Include MUST be outside any Host block (ssh_config(5) lexical scoping), so it is PREPENDED. Idempotent.
func EnvPairsToMap ¶ added in v0.2026190.848
EnvPairsToMap converts KEY=VALUE pairs (the CLI -e / label wire form) into the map form the deploy schema stores since the env-shape unification.
func EnvdFilePath ¶
EnvdFilePath returns the env file path for a given candy under a home.
func ExpandAnyVars ¶ added in v0.2026191.2033
ExpandAnyVars expands ${VAR} references in every string within a plugin_input value (scalar string / nested map / list), mutating maps and slices in place, and returns the (possibly rewritten) value plus the unresolved var names. Non-string scalars pass through untouched.
func ExpandOpVars ¶ added in v0.2026191.2033
ExpandOpVars rewrites every ${...} reference on an Op in place using the supplied environment map. Returns the combined (sorted) list of unresolved refs encountered across all string fields.
func ExpandTestVars ¶ added in v0.2026191.2033
ExpandTestVars substitutes ${NAME} and ${NAME:arg} references using the supplied environment map.
Keys in env for plain refs use just the name: env["HOME"] = "/home/user". Keys for parameterized refs combine name and argument with a colon: env["HOST_PORT:6379"] = "16379", env["VOLUME_PATH:workspace"] = "/var/lib/…".
Returns the substituted string and a list of unresolved refs (in encounter order, deduplicated). The caller decides whether unresolved refs are an error (build-time validation) or a skip reason (runtime).
func FillReverseUninstallCmds ¶ added in v0.2026190.848
func FillReverseUninstallCmds(ops []ReverseOp, renderUninstall func(format string, packages []string) string)
FillReverseUninstallCmds renders the host-venue uninstall command for every ReverseOpPackageRemove op in the slice from the format's uninstall_template (the embedded build vocabulary, charly/charly.yml), in place. Called at install/record time by the local deploy target and the external vm deploy (R3 — one shared filler) when the DistroConfig is in hand, so the persisted ledger op carries the exact removal command the teardown will run. Ops whose format declares no uninstall_template, or whose format isn't in the config, are left with an empty UninstallCmd (teardown then errors loudly rather than silently running a wrong command). The renderUninstall seam maps (format, packages) → the format's uninstall command, or "" when the format has no uninstall template. It keeps this function free of the buildkit DistroConfig/RenderTemplate dependency (which would cycle kit→buildkit→kit once reverse_ops lives in kit) — the caller (candy/plugin-fleet/deploy_target.go, S3b — was charly core's deploy_target_external.go before the deploy-dispatch cluster moved) closes over DistroCfg + RenderTemplate.
func FilterHostVars ¶ added in v0.2026191.2205
FilterHostVars returns the ${HOST:…} cross-member references among the unresolved keys. An unresolved ${HOST:…} means the member is unreachable — a real failure, never a SKIP (a skip on an unreachable dependency is a fake pass). Other unresolved vars (a deploy-only var under build scope, an unmounted volume) stay a legitimate skip — this function does not decide that; ClassifyUnresolved does.
func FindMappingValue ¶
FindMappingValue returns the value node for key in a YAML mapping node, or nil. (Like MapValue, but requires the key node to be a scalar — the form the migration transforms + the core loader's legacy-shape detection both use.)
func FindPortOwner ¶ added in v0.2026190.848
FindPortOwner checks running containers to identify what is using a port.
func FirstUnmetDepStep ¶ added in v0.2026201.1934
FirstUnmetDepStep returns the first dep id in s.DependsOn whose verdict is anything other than "pass" (or that is unknown / not yet run). Returns "" if every dep passed (or the step has no deps).
func FormatPortConflicts ¶ added in v0.2026190.848
func FormatPortConflicts(conflicts []PortConflict, image string) string
FormatPortConflicts produces a user-friendly error message with remediation suggestions.
func HammingDistance ¶ added in v0.2026269.700
func HammingDistance(a, b ScreenSignature) int
HammingDistance returns the number of differing bits between two signatures (0 = identical fingerprint, 64 = opposite).
func HumanBytes ¶ added in v0.2026202.1944
HumanBytes renders a byte count as a compact human-readable string.
func IsAutoPort ¶ added in v0.2026190.848
IsAutoPort reports whether a port-list entry is the literal "auto" sentinel. Authors write `port: [auto]` (or `port: [auto, "8443:443"]` to mix auto-allocation with explicit pins) in charly.yml.
func IsDirectDeploy ¶ added in v0.2026198.345
IsDirectDeploy reports whether the named deploy was created in direct mode (i.e. has a marker file). Used by lifecycle commands.
func IsGitSubmoduleDir ¶
IsGitSubmoduleDir reports whether p (≠ root) contains a .git entry (a nested submodule/repo boundary).
func IsNotFound ¶ added in v0.2026277.352
IsNotFound reports whether err means "the path does not exist". It is the ONE classifier for a missing file read back over the DeployExecutor reverse channel, shared by every GetFile caller that must tolerate absence: the env.d managed-block read above, the substrate deploy ledger (install_ledger.go, where a fresh guest legitimately has no charly.yml yet), and deploykit's `optional:` artifact retrieval. It recognizes a local not-found sentinel (`errors.Is(err, fs.ErrNotExist)`, so a wrapped one counts too) as well as the text a remote read produces — `ssh cat` reports "No such file or directory", `ls` reports "cannot access", and a tool that names the path without the errno wording reports a bare "not found".
Anything else is NOT tolerated: a permission denial, a broken channel, or a syntax error in the substrate's charly.yml stays a loud failure, because treating it as "absent" would let the caller silently overwrite a file it could not read.
func IsRuntimeOnlyVar ¶ added in v0.2026191.2033
IsRuntimeOnlyVar reports whether the given variable key (as returned by TestVarRefs) refers to a runtime-only value. The check matches on name prefix because parameterized vars share a common prefix with their arg.
func KeywordOf ¶ added in v0.2026191.2205
func KeywordOf(s *spec.Step) spec.StepKeyword
KeywordOf returns the populated step keyword, or "" when none is set.
func LUKSUnlock ¶ added in v0.2026269.700
func LUKSUnlock(ctx context.Context, tr ConsoleTransport, passphrase string, success, failure []string, timeoutSec int, artifact string) (string, error)
LUKSUnlock enters a disk-encryption passphrase at the initramfs prompt and waits for a success anchor; a failure anchor FAILS fast. It is the generic `luks-unlock` (R3).
func LedgerTxLockPath ¶ added in v0.2026250.154
func LedgerTxLockPath(paths *LedgerPaths) string
LedgerTxLockPath returns the LEDGER TRANSACTION lock path for one LedgerPaths: the config path + ".ledger.lock". This is NOT paths.LockFile, and the separation is load-bearing (the deploy-del self-deadlock, RCA 2026-09-07): paths.LockFile guards the per-host charly.yml read-modify-write — the SAME brief exclusion every writer of that FILE shares (writeLedger here, deploykit.MutateDeployConfig/SaveDeployConfig, spec/refs GitClient.save's cache section). The ledger TRANSACTION lock is a different logical resource: the deploy-del/add transaction bracket (resolve → members-down → node-del-dispatch) holds it for the WHOLE operation — minutes, network fetches included. Collapsing both onto charly.yml.lock made every in-process nested config RMW under a transaction hold contend with the holder's own fd (flock is per-open-file-description; two acquires of one path in ONE process conflict): the del's resolve-phase GitClient.save and teardown-phase MutateDeployConfig each stalled the full lockTimeout against the del's own transaction hold, silently dropping their writes — the cache never persisted, so the next run re-stalled. Deterministic, 7/7-reproducible deploy-del hang.
The dedicated file restores the genesis semantics (the pre-sdk ledger lock was a dedicated ~/.config/opencharly/installed/.lock — NEVER the config lock): the transaction lock orders deploy flows against EACH OTHER; brief config-file writers stay ordered by charly.yml.lock and legitimately interleave inside a transaction (each RMW re-reads the current file under the config lock and preserves the other sections).
func ListCandyNames ¶ added in v0.2026241.1032
func ListCandyNames(paths *LedgerPaths) []string
ListCandyNames returns every candy name in the `ledger:` section, sorted. The candy-side counterpart of ListDeployIDs; see that doc for why it exists.
func ListCandyNamesStrict ¶ added in v0.2026241.1051
func ListCandyNamesStrict(paths *LedgerPaths) ([]string, error)
ListCandyNamesStrict is ListCandyNames with the same malformed-ledger contract as ListDeployIDsStrict.
func ListDeployIDs ¶ added in v0.2026241.1032
func ListDeployIDs(paths *LedgerPaths) []string
ListDeployIDs returns every deploy id in the `ledger:` section, sorted.
This is the enumeration half of the ledger API. Before the relocation, a consumer enumerated by listing *.json stems under LedgerPaths.Deploys; that directory no longer exists, so without this an out-of-tree consumer cannot discover what is deployed at all — it can only ReadDeployRecord an id it already knows. Absent/corrupt file yields an empty slice, matching readLedger's best-effort contract (and the old empty-directory case).
func ListDeployIDsStrict ¶ added in v0.2026241.1051
func ListDeployIDsStrict(paths *LedgerPaths) ([]string, error)
ListDeployIDsStrict is ListDeployIDs but reports a malformed ledger instead of reading it as an empty one. Prefer it wherever a user-facing command would otherwise print "nothing deployed" for a file it simply could not parse.
func ListVmSshAliases ¶ added in v0.2026186.739
ListVmSshAliases returns the alias names in the managed fragment, sorted.
func ManagedBlockBody ¶
ManagedBlockBody returns the shell-specific loop that sources the env.d directory under a home. POSIX-sh for bash/zsh, fish syntax for fish.
func ManagedBody ¶ added in v0.2026186.739
ManagedBody returns just the contents between the begin/end fence markers (the global, untagged managed block) in text. Returns "" when the markers are absent.
func MappingChild ¶ added in v0.2026186.1019
MappingChild looks up a key in a mapping node. Returns the value node or nil if missing. yaml mapping nodes store [key, value, key, value, …].
func MarkersForTag ¶
MarkersForTag returns the begin/end fence pair for a marker tag. Empty tag → the global-block fence; non-empty → a per-candy fence so multiple candies coexist.
func MergeAnswers ¶ added in v0.2026266.2315
func MergeAnswers(envVars, secrets, authored map[string]string, envName, secretName func(string) string) map[string]string
MergeAnswers resolves the three answer sources into one map. Precedence (lowest first): env < secret < authored. `envName` reads an ENVIRONMENT VARIABLE name; `secretName` reads a credential-store key. An unresolved env var or secret is left OUT (so a missing var fails visibly as an unsubstituted {{placeholder}} rather than silently empty). PURE over its inputs — the caller owns the readers.
func MergeReverseOps ¶ added in v0.2026269.1752
MergeReverseOps returns existing plus every op in incoming not already present. Dedup is by CONTENT (reflect.DeepEqual: ReverseOp carries an Extra map, so `==` cannot compare it). A shared candy record's reverse_ops are the UNION of every deploy's ops, because teardown replays the whole list only when the refcount empties — so an overwrite silently drops an earlier deploy's teardown.
charly#687: two `deploy:kindcluster` deploys (a root + its member) each record `kind delete cluster --name <that deploy's cluster>` against the SHARED `plugin-kube` provider candy. The second write overwrote the first, so teardown deleted only the member's cluster and left the root's running. Merging keeps both, and dedup makes a re-run (same deploy, same op) idempotent.
func MigrateCandidateYAMLFiles ¶
MigrateCandidateYAMLFiles is the ONE candidate-file scanner the multi-document doc-migration steps share AND the core loader's legacy-vocab rejection scan uses: every `.yml`/`.yaml` under each of treeSubdirs (walked recursively, skipping nested git submodules + any `testdata` dir) plus the root-level YAML siblings in dir. Sorted, deduplicated.
func NodeShapedValue ¶
NodeShapedValue reports whether a mapping node carries a reserved kind word as a key (i.e. it is a name-first node-form value).
func NormalizeTag ¶ added in v0.2026191.1413
NormalizeTag strips a single leading '@' so `@smoke` and `smoke` are identical — authors commonly write `@smoke` from Gherkin habit, but the sigil is optional in the YAML surface.
func OCRBytes ¶ added in v0.2026266.2315
OCRBytes runs tesseract over a PNG held in memory and returns its text, with the console upscale applied (ConsoleOCRScale). It is the ONE OCR implementation in the SDK — the console transports AND the artifact validator (RunArtifactValidators' artifact_contains_text, via OCRBytesScaled) all call it, so there is exactly one tesseract invocation to keep correct (R3). The bytes are written to a temp file because tesseract reads a path.
FAILING TO RUN IS NOT FAILING TO MATCH: a missing engine, or missing language data (tesseract writes the complaint to stderr and can still exit 0 with EMPTY stdout), returns an error that NAMES the cause — never an empty string a caller would read as "the text is absent".
func OCRBytesScaled ¶ added in v0.2026266.2315
OCRBytesScaled is OCRBytes with an explicit nearest-neighbour upscale factor applied first (1 = none). The artifact validator upscales a screen-resolution capture (see sdk's ocrUpscale); a framebuffer console reads at 1.
func OpUnifyCandidateFiles ¶
OpUnifyCandidateFiles is the candidate-file set the op/plan-unify migrators AND the core loader's legacy-test-vocab rejection scan walk (candy/ + box/ trees + root siblings).
func OpenTerminal ¶ added in v0.2026269.700
func OpenTerminal(ctx context.Context, tr ConsoleTransport, o TerminalOpen) (string, error)
OpenTerminal opens a terminal on the transport and waits for a shell prompt. It is the generic `open-terminal`: the transport sends the combo, the shared engine waits for a prompt anchor. One implementation, either transport (R3).
func ParseContainerPort ¶ added in v0.2026190.848
ParseContainerPort extracts the container port from a mapping. Accepts every form ParsePortMapping does, including the IP:H:C bind-address form.
func ParseHostPort ¶ added in v0.2026190.848
ParseHostPort extracts the host port from a mapping. Accepts every form ParsePortMapping does, including the IP:H:C bind-address form.
func ParseTaskMode ¶
ParseTaskMode parses a candy task mode string ("0644","0o755") into a uint32 file mode, falling back to def when empty/unparseable.
func PopulateSystemInfo ¶ added in v0.2026241.1140
func PopulateSystemInfo() error
PopulateSystemInfo detects the host identity and writes it into the `system:` section of the per-host charly.yml, preserving every other key (deploy:, provides:, cache:, ledger:). It is the "refresh the local system snapshot" operation — called by `charly status` (and available to any command that needs the host identity persisted).
func PosArtifact ¶
func PosCommandFields ¶
PosCommandFields splits the input `command` into argv slots, prefixed with `--` so kong does not treat embedded -flags as its own (libvirt:guest/exec). For shell metachars use `command: "sh -c '<full>'"`.
func PosKeyNameSplit ¶
PosKeyNameSplit splits the input `key` on whitespace (libvirt send-key: "ctrl alt F2" → 3 slots).
func PosLibvirtQmp ¶
PosLibvirtQmp emits a QMP method name + optional JSON args (input text = method, input = JSON).
func ReadLedger ¶ added in v0.2026241.1311
func ReadLedger(paths *LedgerPaths) (map[string]DeployRecord, map[string]CandyRecord, error)
ReadLedger returns the FULL ledger maps (deploys + candies) in ONE read of the per-host charly.yml. The status collector uses this to avoid re-reading the config once per record (measured: 186 reads of a 310KB config per status run). STRICT: a malformed ledger is an error (never reported as an empty one).
func ReloadDaemon ¶ added in v0.2026276.152
ReloadDaemon runs `systemctl [--user] daemon-reload` so a freshly-written unit/drop-in is picked up before enable. Exported alongside EnableUnit (R3): one daemon-reload call site.
func RemoveEnvdFile ¶ added in v0.2026206.837
RemoveEnvdFile deletes an env.d entry. Silently succeeds when absent.
func RemoveImagesByReference ¶ added in v0.2026186.831
func RemoveImagesByReference(engineBin, reference string)
RemoveImagesByReference best-effort removes every local image whose repository BASENAME exactly equals `reference` (e.g. "<deploy>-overlay") via `<engineBin> images … | rmi`. Silent on error (image cleanup is best-effort). engineBin is the resolved engine binary (the host resolves "podman"/"docker"/"auto" and passes the concrete binary — kit does no detection).
The `--filter reference=<reference>` glob is NOT trusted alone: podman lists EVERY repo:tag of any matched image ID, so a base image or a cross-deploy image that shares content (same image ID as the overlay) leaks into the output. rmi'ing those blindly would destroy the base + unrelated deploys' images. So the emitted repo is re-checked in Go and only the EXACT `<reference>` repo is removed.
func RemoveManagedBlockAt ¶ added in v0.2026190.848
RemoveManagedBlockAt strips the managed block (tagged with marker) from the file at path, in place. A file left empty is removed; a missing file is a no-op. The file-level counterpart to StripManagedBlock (the pure string op).
func RemoveSshConfigInclude ¶ added in v0.2026186.739
RemoveSshConfigInclude removes the managed Include line from ~/.ssh/config. Idempotent.
func RemoveVmSshStanza ¶ added in v0.2026186.739
RemoveVmSshStanza drops the named alias and returns the remaining count (0 → the caller also removes the Include). Idempotent.
func RenderDownloadScript ¶
RenderDownloadScript emits a shell snippet that fetches op.Download to a temp file, optionally extracts it into op.To, then cleans up — honoring the same flags the container build path respects (extract format, strip_components, include, mode, env). candyVars are exported alongside op.Env so a vars: key referenced in the URL resolves at deploy time.
func RenderEnvdBody ¶
RenderEnvdBody produces the deterministic, shell-agnostic POSIX-sh fragment for a candy's env vars + PATH additions. Sorted keys guarantee stable output.
func RenderFlowEvidence ¶ added in v0.2026269.700
func RenderFlowEvidence(res ConsoleFlowResult) string
RenderFlowEvidence renders a flow run's per-node evidence, including the OCR-read output of any command action, so "read the results via OCR" is visible in the verdict. Shared so both transports render it identically (R3).
func RenderManagedBlockStrip ¶ added in v0.2026190.848
RenderManagedBlockStrip is the remote analogue of RemoveManagedBlockAt: a POSIX-sh snippet that drops the marker's begin/end fence pair (and its body) from the file IN PLACE on the venue. The fences come from MarkersForTag so they match exactly what the forward walk wrote, and awk index() matches them LITERALLY (no regex). The final `cat > "$f"` rewrites in place to preserve the rc file's perms/owner.
func RenderOpCommand ¶
RenderOpCommand turns an op into a shell command suitable for sudo/user execution. It handles every plugin-renderable verb EXCEPT copy (staged via the executor's PutFile) and the act-`plugin:` verb (whose ProvisionActor shell needs the in-proc registry — package main / RunHostStep render those). Returns (cmd, handled): handled=false means the op is a copy or an act-`plugin:` verb the caller must route elsewhere; handled=true with an empty cmd never occurs (every handled verb yields a body).
func ReplaceOrAppendManagedBlock ¶
ReplaceOrAppendManagedBlock replaces the begin/end fence pair's body (tagged with marker, empty for the global block) in existing, appending a fresh block at EOF when absent.
func ReplaceOrPrependManagedBlock ¶ added in v0.2026186.739
ReplaceOrPrependManagedBlock replaces the marker-tagged managed block in place, or PREPENDS it (with a blank-line separator before the rest of the file) when absent. Used for the ssh-config Include line, which MUST be at the TOP of ~/.ssh/config (outside any Host block) — an appended Include would be gated on the last preceding Host stanza's match (ssh_config(5) lexical scoping).
func ResolveDeployPorts ¶ added in v0.2026190.848
func ResolveDeployPorts(containerPorts []int, pins, prior []string, occupied map[int]bool) ([]string, error)
ResolveDeployPorts maps each image-declared container port to a host:container publish mapping — the AUTO-PORT-MAPPING default. For every container port:
- an explicit deploy pin (host:container, matched by container port) wins;
- else a still-valid prior allocation (from a previous `charly config` — keeps a deploy's host ports STABLE across `charly update`) is reused;
- else a fresh free 127.0.0.1 host port is allocated.
`occupied` seeds host ports already taken by SIBLING deployments so concurrent beds never collide; every chosen host port is recorded back into it. Pins for container ports the image does not expose are honored too (an operator publishing an extra port). A stray `auto` token in `pins` is ignored (treated as "no pin" → allocate), so a not-yet-migrated `port: [auto]` still works. Returned mappings carry no bind address; localizePort prepends BindAddress (127.0.0.1 by default) at quadlet/run time so every published port is loopback.
func ResolveEntrypointFromMeta ¶ added in v0.2026198.345
func ResolveEntrypointFromMeta(meta *spec.BoxMetadata) []string
ResolveEntrypointFromMeta determines the entrypoint from image metadata (runtime mode). The build-resolved init contract is baked into the ai.opencharly.init_def label (meta.InitDef), so EVERY init system declared in the embedded `init:` vocabulary reaches runtime — including openrc and any custom one — with no table to register in.
func ResolveInitDefFromMeta ¶ added in v0.2026198.345
func ResolveInitDefFromMeta(meta *spec.BoxMetadata) (*spec.ResolvedInit, error)
ResolveInitDefFromMeta returns the init contract for management-command rendering, read from the ai.opencharly.init_def label. An image without that label errors: it predates the label and must be rebuilt.
func ResolveNetwork ¶ added in v0.2026198.345
ResolveNetwork returns the network to use for a container. If configured is non-empty (explicit override like "host"), it is returned as-is. Otherwise, the shared "charly" network is ensured and returned.
func ResolveVmSshPort ¶ added in v0.2026201.1934
ResolveVmSshPort resolves the guest SSH host port from the resolved spec:
- ssh.port_auto: true → reuse persistedPort when the caller already resolved one (idempotent across rebuilds), else allocate a free host port.
- ssh.port: N → that fixed port.
- neither → 2222.
The persisted-state READ is the caller's concern (it differs by placement: charly core reads its project config directly; an out-of-process plugin reads over a host seam) — this is the PURE resolution/allocation decision only.
func RunAgentOnce ¶ added in v0.2026197.1320
func RunAgentOnce(ctx context.Context, ai *spec.AgentExecSpec, prompt string, timeout time.Duration) (string, string, error)
RunAgentOnce launches the configured AI CLI exactly once with the given prompt and returns its stdout/stderr. It is the bounded, single-shot sibling of the harness loop's iteration launcher (candy/plugin-check/harness_loop.go) and of LocalCaptureVersion (candy/plugin-check/agent.go) — same host-exec shape, no iteration directories, no plateau state. ${PROMPT} in the AI's command argv (and a PromptVia: file temp file) is substituted with the prompt text.
func RunBootOrder ¶ added in v0.2026269.700
RunBootOrder sets the UEFI boot order over the terminal. The generic `boot-order` (R3). Reading (list) needs no privilege; writing (next/set) does.
func RunCommands ¶ added in v0.2026269.700
func RunCommands(ctx context.Context, tr ConsoleTransport, cmds []ConsoleCommand, sudoPassword string, closeTerminal bool, promptAnchors []string) (string, error)
RunCommands runs ordered commands in an open terminal, reading each result by OCR. It is the generic `run-command`; sudoPassword is entered at a sudo prompt. closeTerminal sends `exit` afterwards. promptAnchors, when set, make every command verify a shell prompt first (the fast-fail guard against typing into a pager/menu/login screen). One implementation, either transport (R3).
func RunReverseOps ¶ added in v0.2026190.848
func RunReverseOps(ops []ReverseOp, exec ReverseExecutor)
RunReverseOps executes ops in REVERSE order (last-installed, first- removed). Idempotent where possible: a missing file is treated as "already removed" rather than an error.
func SameStringSlice ¶ added in v0.2026190.848
SameStringSlice reports whether two string slices are element-wise equal (order-sensitive) — used to skip a redundant resolved-port re-save.
func SanitizeDeployName ¶ added in v0.2026197.1320
func SaveYAMLNodeFile ¶ added in v0.2026193.1241
SaveYAMLNodeFile marshals a node tree back to an arbitrary file path, preserving comments + key order (the yaml.v3 Node round-trip). Shared by the scaffold/authoring engine (kit.AddBox) and charly core's box add-candy/rm-candy verbs — ONE marshal-to-file home (R3).
func ScaffoldCandy ¶ added in v0.2026193.1241
ScaffoldCandy creates a new candy directory at dir/<DefaultCandyDir>/<name> with a placeholder manifest in the compact name-first node form. ADE mandates a description + at least one deterministic check: step, so the scaffold ships a minimal passing pair the author replaces. Errors if the candy already exists. The caller prints the created path.
func ScaffoldProject ¶ added in v0.2026193.1241
ScaffoldProject creates an empty charly project at dir. Idempotency: errors out if dir already contains an charly.yml so we never silently clobber an existing project. The dir itself may exist.
func ScreenMatches ¶ added in v0.2026269.700
func ScreenMatches(current, reference ScreenSignature, maxDistance int) bool
ScreenMatches reports whether the current frame's signature is within maxDistance of the reference (1..64). A maxDistance <= 0 (the Go zero value of an omitted optional field) uses ScreenDefaultMaxDistance — the documented tolerance of a clock tick, a cursor blink, or minor rendering noise. A caller wanting an (almost) exact match authors maxDistance 1; 0 is not meaningful because an omitted field and a literal 0 are indistinguishable in the decoded struct.
GEOMETRY GUARD: when both signatures carry dimensions and they differ by more than a factor of 2, the frames are almost certainly different screens (a resolution change / a different display) — reported as no-match regardless of the hash, rather than a coincidental near-hash.
func ScreenPreview ¶ added in v0.2026269.700
func ScreenPreview(s ScreenSignature) string
ScreenPreview renders a signature for an evidence line.
func SetByDotPath ¶ added in v0.2026186.1019
SetByDotPath edits the file at path, navigating into the YAML structure via dotpath (dot-separated keys) and replacing the leaf value with valueYAML (parsed as YAML so callers can pass scalars, lists, or maps). Comments and key order are preserved.
func SetMappingKey ¶ added in v0.2026241.1032
SetMappingKey sets (or replaces) a top-level key in a YAML mapping node. The ONE shared helper for the section-preserving per-host charly.yml writers (deploykit.SaveDeployConfig, the GitClient cache, the ledger I/O) — R3.
func ShDoubleQuote ¶
ShDoubleQuote wraps a string in double quotes for a shell context where variable expansion MUST still happen (e.g. download URLs that template ${BUILD_ARCH}). Escapes the metachars that break out of a double-quoted string, but deliberately does NOT escape `$` so authored ${FOO} / $FOO still expand.
func ShDoubleQuotePath ¶
ShDoubleQuotePath escapes a PATH-list value for use INSIDE double quotes, leaving `$` unescaped so `$PATH` expands at sourcing time.
func ShQuoteArg ¶
ShQuoteArg single-quotes an argument for POSIX shell embedding.
func ShQuoteEnv ¶
ShQuoteEnv single-quotes a value for POSIX sh (env.d export values). Inside single quotes nothing needs escaping except the single quote itself.
func ShellInitFilePath ¶
ShellInitFilePath returns the init file the managed block lands in for each shell under a home.
func SidecarConfigDir ¶ added in v0.2026198.358
SidecarConfigDir returns the per-user directory where sidecar companion config files live (e.g. charly-foo-tailscale-serve.json), used by the `charly config remove` sidecar-config sweep.
func SortStrings ¶
func SortStrings(s []string)
SortStrings sorts s in place (ascending). A small insertion-free bubble sort, kept identical to the original package-main helper.
func SplitHostKey ¶ added in v0.2026197.1537
SplitHostKey splits a "HOST:web" / "HOST:web:8080" key into the variable name and the remaining argument(s) (everything after the FIRST colon).
func SshConfigPath ¶ added in v0.2026186.739
SshConfigPath returns ~/.ssh/config for the user's home dir.
func SshFragmentPath ¶ added in v0.2026186.739
SshFragmentPath returns ~/.config/charly/ssh_config for the user's home dir.
func StepDoMode ¶ added in v0.2026191.2205
StepDoMode maps the step keyword to the act/assert/instruct dispatch enum.
func StepID ¶ added in v0.2026191.2205
StepID returns the stable identifier used for plan-overlay merge lookups, depends_on references, and ${STEP_ID} substitution — a deterministic id derived from origin + position.
func StripManagedBlock ¶
StripManagedBlock removes the begin/end fence pair (tagged with marker) and its body.
func SubstituteConsoleAnswers ¶ added in v0.2026266.2315
SubstituteConsoleAnswers replaces `{{name}}` placeholders in s with answers[name], single-pass and literal. An unknown placeholder is left verbatim so a mis-authored recipe is visible in the failing step rather than silently typing an empty string.
func TaskShellPreamble ¶
TaskShellPreamble returns the BUILD_ARCH/ARCH exports plus any candy vars + op env (sorted for deterministic output) so cmd: bodies can reference ${ARCH} / ${MY_CANDY_VAR} at deploy-time the same way they do at build-time.
func TestVarRefs ¶ added in v0.2026191.2033
TestVarRefs returns the set of ${NAME[:arg]} references in s, as their fully-qualified keys (matching the env-map format used by ExpandTestVars). Used by the validator to catch typos at config time.
func TransferToRootful ¶ added in v0.2026190.848
TransferToRootful pipes an image from rootless podman storage into rootful (sudo podman) storage via `podman save | sudo podman load`. Idempotent — returns nil immediately when the image already exists in rootful storage.
Used by RunPrivileged when engine.rootful=sudo because rootless and rootful podman maintain separate container-storage trees (~/.local/share/containers vs /var/lib/containers). Without this transfer, sudo podman run against a locally-built image falls back to a registry pull (which 403s for build-only images that were never pushed).
Surfaced 2026-05 by the cachyos / cachyos-pacstrap-builder pair — the first time the bootstrap-builder framework was exercised end-to-end on a host with rootless build + sudo run.
func UpscalePNG ¶ added in v0.2026266.2315
UpscalePNG returns the PNG enlarged by an integer nearest-neighbour factor (scale <= 1 returns the bytes unchanged). Nearest-neighbour keeps glyph edges hard, which is what tesseract thresholds against; a smoothing filter blurs thin UI type. Exposed because the ENLARGEMENT ITSELF is a behavior worth pinning — tesseract read ZERO words from a real 1280x800 desktop capture at 1x, 2x and 3x and read it once enlarged, so a test asserts the output geometry.
func ValidatePlanSteps ¶ added in v0.2026197.1320
planvalidate.go — ValidatePlanSteps, the SHARED static plan-block validator (P12a: relocated from charly/plan_validate.go). It lives here — not candy/plugin-check — because the externalized validators `charly box validate` (candy/plugin-box) and the check/feature surfaces call it directly, so it must be reachable without importing a plugin candy. One copy, R3.
- description non-empty
- every step has exactly one keyword (StepKind())
- run/check steps carry exactly one Op verb; agent-* steps carry none
Returns a list of human-readable error strings (empty if OK).
func ValidateTagExpr ¶ added in v0.2026201.1934
ValidateTagExpr syntax-checks an optional --tag expression (rejecting a malformed one) without keeping the parsed *TagExpr — moved from charly/check_feature_run.go (CHECK-wave), a pure wrapper with zero core-state coupling. It does NOT apply the parsed expression as a step filter: kit.RunPlan (the walk both hostFeatureBox, still core, and candy/plugin-check's pluginCheckRunFeatureLive drive) takes no tag-filter parameter and walks every step unconditionally — a confirmed, RCA'd, non-blocking gap (per-tag filtering was never wired past this parse), routed to the next check-correctness thematic batch.
func WalkPlans ¶
func WalkPlans(ctx context.Context, exec DeployExecutor, plans []spec.InstallPlanView, opts WalkOpts) ([]spec.ReverseOp, error)
WalkPlans executes every plan's steps on the venue and returns the combined teardown ops (plugin-renderable kinds echo the host-computed view.ReverseOps; host-engine kinds return theirs from RunHostStep). The caller folds them into its DeployReply.
func WrapUnlessExists ¶ added in v0.2026269.1353
WrapUnlessExists and WrapUnlessExistsBlock wrap cmd in the `unless_exists` capability GATE, or return cmd unchanged when the guard is empty. They share the gate's SEMANTICS and differ only in how the guarded list is terminated, because their call sites sit in genuinely different lexical contexts:
- WrapUnlessExists `else { cmd; }; fi` — one line. EmitDownload's payload is a single-quoted argument on ONE Containerfile RUN line, where a literal newline would end the instruction, so `;` is the only terminator available.
- WrapUnlessExistsBlock `else {\ncmd\n}; fi` — a payload that is a heredoc body or a multi-line script, already multi-line by construction, where a newline costs nothing.
The gate is evaluated where the step runs: on a distro that packages the tool, `distro:` package sections compile into the plan before the `plan:` steps, so the guarded path already exists by the time the step runs. The guard is shell-quoted in BOTH positions so a path containing a double quote or `$(…)` cannot corrupt the test or the message.
verb names the step kind in the skip message ("download", "run"), because a log that prints "skipping: X already present" for three different reasons is worse than one that says which step declined to run.
func WrapUnlessExistsBlock ¶ added in v0.2026269.1353
WrapUnlessExistsBlock is the newline-terminated form, for a payload that is already multi-line.
func WriteCandyRecord ¶ added in v0.2026190.848
func WriteCandyRecord(paths *LedgerPaths, rec *CandyRecord) error
WriteCandyRecord serializes rec into the `ledger:` section under ledger.candies[rec.Candy].
func WriteDeployRecord ¶ added in v0.2026190.848
func WriteDeployRecord(paths *LedgerPaths, rec *DeployRecord) error
WriteDeployRecord serializes rec into the `ledger:` section under ledger.deploys[rec.DeployID].
func WriteDeployRecordVia ¶ added in v0.2026190.848
func WriteDeployRecordVia(exec spec.DeployExecutor, paths *LedgerPaths, rec *DeployRecord) error
WriteDeployRecordVia is the executor-routed variant of WriteDeployRecord. Same semantics as AddCandyDeploymentVia but for deploy records.
func WriteVmSshStanza ¶ added in v0.2026186.739
func WriteVmSshStanza(home string, s VmSshStanza) error
WriteVmSshStanza adds (or replaces) a Host stanza in the managed fragment. Idempotent.
Types ¶
type AgentForwardMounts ¶ added in v0.2026198.345
type AgentForwardMounts struct {
Volumes []string // host:container[:options] — only for container CREATION
Env []string // KEY=VALUE — for both creation and exec
}
AgentForwardMounts holds the resolved bind mounts and env vars needed to forward SSH and GPG agent sockets from the host into a container.
func ResolveAgentForwarding ¶ added in v0.2026198.345
func ResolveAgentForwarding(rt *ResolvedRuntime, deploy *spec.DeployNode, containerHome string) AgentForwardMounts
ResolveAgentForwarding detects available agent sockets on the host and returns the bind mounts and environment variables needed to forward them into a container. deploy may be nil (no per-image overrides). containerHome is the home directory inside the container (e.g., "/root" or "/home/user") — determines where GPG expects its agent socket.
Graceful degradation: logs warnings to stderr for missing sockets but never returns errors — missing agents are silently skipped.
type AgentGrader ¶ added in v0.2026197.1320
type AgentGrader struct {
Agent *spec.AgentExecSpec // the resolved kind:agent exec spec (how to launch the CLI)
Target string // the deployment name the agent probes (e.g. "check-pod")
Instance string // optional deploy instance
Timeout string // optional Go-duration override (from --timeout)
}
AgentGrader is the production StepGrader: it drives the configured `kind: agent` CLI against a live deployment.
func (*AgentGrader) Grade ¶ added in v0.2026197.1320
func (g *AgentGrader) Grade(ctx context.Context, req GraderRequest) CheckResult
Grade builds the grader prompt, runs the AI once, and parses its verdict.
type BootOrder ¶ added in v0.2026269.700
type BootOrder struct {
// Action is list | next | set.
Action string
// Entry is the entry number for next.
Entry string
// Sequence is the comma-separated order for set.
Sequence string
// Binary overrides the boot-manager command (default "efibootmgr").
Binary string
// SudoPassword is used for the NVRAM-writing actions (next/set).
SudoPassword string
}
BootOrder describes a generic `boot-order` action — set the UEFI boot order from INSIDE the running system via the OS-side EFI boot manager.
type BuilderRunOpts ¶ added in v0.2026190.848
type BuilderRunOpts = spec.BuilderRunOpts
type CalVer ¶
type CalVer = calver.ParsedCalVer
calver.go — re-export of the parsed CalVer type + comparator, RELOCATED to spec/calver (#55 value extraction). The parsed type is a pure value/transform over a CalVer string, so it homes in spec; it is named calver.ParsedCalVer there (spec already binds CalVer=string, a CUE wire scalar). kit re-exports it as `type CalVer = calver.ParsedCalVer` + var forwarders so existing kit.CalVer / kit.ParseCalVer call sites are unchanged.
The former LatestSchemaVersion / SchemaFloor forwarders are GONE (the schema-versioning removal cutover): there is no schema HEAD/floor. CalVer remains a REAL identity — the binary's stamped build version and git release/candy tags — never an authored-file schema stamp.
type CandyRecord ¶ added in v0.2026190.848
type CandyRecord = spec.CandyRecord
SPIKE (value-type relocation, #55 cluster 4): DeployRecord/CandyRecord/ StepRecord relocated to spec (spec/spec/ledger_records.go) — every field already resolved to a spec.* type and none carried methods, so they moved verbatim. Zero-churn aliases.
func ReadCandyRecord ¶ added in v0.2026190.848
func ReadCandyRecord(paths *LedgerPaths, layer string) (*CandyRecord, error)
ReadCandyRecord loads ledger.candies[layer]; returns nil, nil if absent.
func RemoveCandyDeployment ¶ added in v0.2026190.848
func RemoveCandyDeployment(paths *LedgerPaths, candyName, deployID string) (*CandyRecord, bool, error)
RemoveCandyDeployment decrements a candy's deployed_by set. Returns (recordAfter, shouldFullyRemove, error). When shouldFullyRemove is true, the caller should perform the actual file/package/service teardown and then delete the candy ledger entry.
type CharlyInstallStrategy ¶ added in v0.2026186.739
type CharlyInstallStrategy = exec.CharlyInstallStrategy
type CheckContext ¶
type CheckContext = spec.CheckContext
CheckContext is the live check-engine surface a host-coupled verb's RunVerb consumes — homed in the spec contract module (spec.CheckContext, checkcontext.go) so charly core's reverse-channel dispatch references it while importing only spec; charly's *Runner implements it, and this alias keeps candy RunVerb signatures compiling unchanged.
type CheckEndpoint ¶ added in v0.2026209.2002
type CheckEndpoint = checkhost.CheckEndpoint
check_endpoint.go — EndpointForVenue + CheckEndpoint RELOCATED to the spec fabric slice github.com/opencharly/spec/checkhost (#55 CHECK-ENGINE cone Option A — the check-verb host-vantage resolution family: net/ssh host primitives belong in a spec fabric slice, so charly core's check dispatch reaches them importing zero kit). The kind-blind resolver + its containerPublishedAddr / sshForwardEndpoint bodies live there; kit re-exports the exported surface so every existing kit.EndpointForVenue / kit.CheckEndpoint call site (the candies + sdk) is untouched. New consumers reference spec/checkhost directly.
type CheckResult ¶ added in v0.2026191.1732
type CheckResult struct {
spec.CheckResult
// DeadlineExceeded marks a result whose probe was killed by hitting its OWN
// per-attempt deadline (probeNeverHang), NOT an external infra interruption. The
// group-kill in runCaptureCmd surfaces the deadline SIGKILL as a signal-kill, so
// without this flag the killed-probe retry (probeWasKilled) would futilely re-run a
// probe that will only re-hang and re-hit the same deadline. An authoritative
// "too slow" failure — never retried. NEVER crosses the wire (see above).
DeadlineExceeded bool `json:"-"`
}
CheckResult is the engine's record of running a single check: the verb's verdict (Status/Message/CapturedValue — the same three fields a verb returns as a Result) plus the engine bookkeeping a Result does not carry (which Op ran, its Verb, and the timing / retry accounting). The dispatch boundary builds a CheckResult from a verb's Result by stamping Op/Verb/Elapsed.
Attempts and TotalElapsed are populated only when the check had an `eventually:` modifier (retry loop): Attempts=1 + TotalElapsed==Elapsed for a check that ran exactly once. Reporters surface these when Attempts>1 so slow startup paths are visible ("PASS in 5 attempts over 12.3s").
FLOOR-SLIM Unit 4 — the wire-envelope split: every field above is now spec.CheckResult (CUE-sourced, sdk/schema/checkresult.cue), EMBEDDED here. The ONE exception is DeadlineExceeded (below) — the spike-proven (P12) exception the wire mandate's own documented exception path authorizes: `json:"-"` (keep-in-Go, drop-from-wire) has no gengotypes construct. charly core's registry-coupled floor files (provider.go, provider_verb.go, verb_builtins.go, unified_targets.go, provider_checkenv.go) reference spec.CheckResult DIRECTLY (they never touch DeadlineExceeded) — zero new sdk/kit import. Field-promotion means every existing `.Status`/`.Op`/`.Verb`/`.Message`/`.Elapsed`/ `.Attempts`/`.TotalElapsed`/`.CapturedValue` selector expression compiles UNCHANGED; only a composite LITERAL naming one of those fields must nest it under the embedded field name (`CheckResult{CheckResult: spec.CheckResult{Status: ...}, ...}`) — Go does not promote embedded-struct field names into a literal key position.
The wire keys are deliberately snake_case now (op/verb/status/message/elapsed/…), a documented breaking change to `--format json`/TAP output — see sdk/schema/checkresult.cue and CHANGELOG for the old→new key mapping.
func RunOne ¶ added in v0.2026191.2205
func RunOne(ctx context.Context, pc PlanContext, c *spec.Op) CheckResult
RunOne handles all the per-check housekeeping (verb resolution, skip handling, variable expansion, venue swap, do-mode routing) and dispatches to a verb handler through the VerbResolver seam. The `eventually:` retry wraps the verb dispatch when requested.
func RunWithEventually ¶ added in v0.2026191.1837
func RunWithEventually(ctx context.Context, check *spec.Op, handler func() CheckResult) CheckResult
RunWithEventually wraps a per-check verb handler in a retry loop when the check declares `eventually: <duration>`. The handler is called with no arguments — it closes over the check, runner, and context.
Semantics:
- eventually: outer retry cap (parsed as time.Duration). Defaults the returned CheckResult to Attempts=1 when unset (handler runs exactly once, unchanged).
- retry_interval: sleep between retries. Defaults to 1s. Must be ≤ eventually or the loop would sleep past the deadline on the first miss.
- PASS semantics: the FIRST attempt that returns StatusPass wins; its stdout/captures/message are what propagate.
- FAIL semantics: the LAST attempt before deadline is returned, ensuring authors see the most recent failure detail rather than a stale first-attempt error.
- SKIP semantics: treated the same as FAIL for retry purposes — skips aren't actionable to retry against.
Variable expansion: the handler re-runs from the same expanded check each attempt. The caller must expand variables BEFORE calling RunWithEventually — re-expansion per attempt would re-evaluate ${CAPTURED:name} mid-run, which is unwanted (captures record on PASS only, and pre-pass attempts wouldn't see their own future capture).
Context: RunWithEventually honours ctx.Deadline / ctx.Done — a canceled context short-circuits the loop with the last attempt's result.
type CheckRunReply ¶ added in v0.2026194.1605
type CheckRunReply = spec.CheckRunReply
CheckRunReply is the host-resolved result of a check-run. Aliased to spec.CheckRunReply (the body lives there).
type CheckVarResolver ¶ added in v0.2026197.1320
type CheckVarResolver struct {
// Env is the final flat map: plain refs use the name as key, parameterized
// refs use "name:arg" as key (e.g., "HOST_PORT:6379"). Matches the format
// expected by ExpandTestVars.
Env map[string]string
// HasRuntime is true when the resolver was populated from a running
// container. When false, runtime-only vars return unresolved (skip path).
HasRuntime bool
}
CheckVarResolver holds the materials for variable expansion under `charly check live` (running container present) and `charly check box` (build-time, no container). Builders for each scope are ResolveCheckVarsRuntime and ResolveCheckVarsBuild.
func NewRuntimeCheckVarResolver ¶ added in v0.2026206.837
func NewRuntimeCheckVarResolver(env map[string]string) *CheckVarResolver
NewRuntimeCheckVarResolver constructs a runtime check-var resolver (HasRuntime true) from an env map, stamping CHARLY_BIN via StampCharlyBin.
func ResolveCheckVarsBuild ¶ added in v0.2026197.1320
func ResolveCheckVarsBuild(meta *spec.BoxMetadata) *CheckVarResolver
ResolveCheckVarsBuild builds a variable map for build-time tests (no running container). Only BoxMetadata-derived vars are populated.
func ResolveCheckVarsRuntime ¶ added in v0.2026197.1320
func ResolveCheckVarsRuntime(meta *spec.BoxMetadata, deploy *vmshared.DeployNode, engine, deployName, containerName, instance string) (*CheckVarResolver, error)
ResolveCheckVarsRuntime builds a variable map for `charly check live` against a running container. It combines image metadata (build-time knowledge), deploy overlay (per-host knowledge), and podman inspect (effective runtime state). Any of the inputs may be nil.
On inspect failure the function still returns a resolver with the build-time portion populated; HasRuntime is false and runtime-only vars will be unresolved downstream.
func StampCharlyBin ¶ added in v0.2026206.837
func StampCharlyBin(res *CheckVarResolver) *CheckVarResolver
StampCharlyBin records the active charly executable path into a runtime check-var resolver's Env as CHARLY_BIN, so host-side plan re-entry (a step referencing ${CHARLY_BIN}) drives the active binary instead of a stale PATH selection. CHARLY_BIN is deliberately never synthesized from PATH: an unavailable executable leaves the variable unresolved instead of silently selecting an unrelated installed charly. nil-safe; idempotent.
type CheckVerbProvider ¶
type CheckVerbProvider = spec.CheckVerbProvider
CheckVerbProvider is the typed in-process contract a host-coupled check-verb candy implements — homed in the spec contract module (spec.CheckVerbProvider, checkcontext.go) so charly core's registry references it while importing only spec; aliased here so every candy implementing it (RunVerb signature) compiles unchanged.
type ConsoleCommand ¶ added in v0.2026269.700
type ConsoleCommand struct {
// Command is the shell command line to type and submit.
Command string
// Sudo runs the command through sudo (prefixed with `sudo `), entering
// SudoPassword at the prompt when the target asks for it.
Sudo bool
// Expect is an optional substring that MUST appear in the OCR-read result;
// when set and absent the command FAILS naming what was read. It is the
// assertion half of "read the results via OCR".
Expect string
// TimeoutSec bounds the wait for the completion marker (default 120).
TimeoutSec int
// Artifact, when set, is a host path the completion frame is written to.
Artifact string
// Description is an optional evidence label.
Description string
}
ConsoleCommand is ONE command to run in a terminal session.
type ConsoleCommandResult ¶ added in v0.2026269.700
type ConsoleCommandResult struct {
// Command is the line that was run (marker stripped).
Command string
// Output is the OCR text read from the screen when the marker appeared.
Output string
// Sudo records whether the command ran through sudo.
Sudo bool
}
ConsoleCommandResult is the OCR-read outcome of one command.
type ConsoleFlow ¶ added in v0.2026269.700
type ConsoleFlow struct {
// Start is the entry node ID.
Start string
// Nodes is the node set, keyed by ID.
Nodes map[string]ConsoleFlowNode
// Transport is the per-transport capture/input primitive set.
Transport ConsoleTransport
// SudoPassword is entered at a sudo prompt for a Command action.
SudoPassword string
// OCR defaults to OCRBytes when nil.
OCR func(png []byte) (string, error)
// PollInterval is the continuous-capture cadence (default
// ConsoleSessionDefaultPollInterval) — a condition poll, not a sleep.
PollInterval time.Duration
// MaxSteps is the hard bound on node executions for the WHOLE flow (default
// ConsoleFlowDefaultMaxSteps). Exceeding it FAILS, so a cycle that never
// reaches a terminal node cannot spin forever (R4 — no unbounded loops).
MaxSteps int
// MaxLoops is the per-node revisit bound (default ConsoleFlowDefaultMaxLoops).
MaxLoops int
// ResumeFromScreen, when true, makes Run AUTO-DETECT the node whose wait
// matches the CURRENT screen and start there, instead of at Start — so a flow
// re-run after a stall/restart recovers to the right step rather than
// replaying from the beginning. A node with a reference-screenshot wait is
// detectable even when its screen OCRs badly.
ResumeFromScreen bool
// ResumeOrder, when set, disambiguates a screen that matches SEVERAL nodes:
// the matching node that appears LAST in this list wins (so an authored list
// from earliest to latest step resumes at the most-advanced match). Without
// it, an ambiguous match FAILS naming the candidates.
ResumeOrder []string
// PromptAnchors, when set, are passed to the internal session so a node's
// `command` action first verifies a shell prompt before typing (the fast-fail
// guard against typing into a pager/menu/login screen).
PromptAnchors []string
// Deadline, when non-zero, is a WALL-CLOCK budget for the whole flow. It is
// checked between nodes (and bounds each node's wait to the remaining time),
// so a flow that would exceed the host's per-step never-hang kill instead
// returns its collected evidence CLEANLY, naming where it stopped — rather
// than being SIGKILLed mid-node with no result (RCA: a long login+install
// flow was killed at the 2m bound with only "context deadline exceeded").
Deadline time.Time
// Logger, when set, receives one line per node (evidence).
Logger func(format string, args ...any)
// contains filtered or unexported fields
}
ConsoleFlow drives a state machine over a ConsoleTransport.
func (*ConsoleFlow) DetectStart ¶ added in v0.2026269.700
DetectStart identifies which node's wait matches the CURRENT screen, so a flow can resume at the right step. It captures ONCE, then tests every node's wait outcomes (reference-screenshot first, then OCR substring). It returns the node ID. When several nodes match:
- if ResumeOrder is set, the matching node appearing LAST in it wins (the authored earliest→latest order, so the most-advanced match resumes);
- otherwise the match is AMBIGUOUS and it returns an error naming the candidates — never a silent arbitrary choice.
It returns ("", reason, nil) when NO node matches, with a reason for the caller.
func (*ConsoleFlow) Run ¶ added in v0.2026269.700
func (f *ConsoleFlow) Run(ctx context.Context) (ConsoleFlowResult, error)
Run executes the flow from Start, returning per-node evidence. It FAILS on: an undefined node (should be caught by Validate), a wait timeout (naming the node, its outcomes, and what OCR read), a failure outcome with no recovery transition, exceeding MaxSteps, or exceeding a node's MaxLoops.
With ResumeFromScreen set, the entry node is AUTO-DETECTED from the current screen (see DetectStart), so a re-run recovers to the right step.
func (*ConsoleFlow) Validate ¶ added in v0.2026269.700
func (f *ConsoleFlow) Validate() error
Validate checks the flow's shape WITHOUT a transport: the start node exists, every transition and Next names a real node, and bounds are positive. It is PURE, so a malformed flow fails before any device session.
type ConsoleFlowAction ¶ added in v0.2026269.700
type ConsoleFlowAction struct {
// Key / Combo / Type are the raw inputs a node can send.
Key string
Combo string
Text string
// Command runs a shell command in an OPEN terminal, reading its output by
// OCR (the marker-completed path from ConsoleSession). Sudo runs it through
// sudo with the flow's SudoPassword.
Command string
Sudo bool
// Expect, for Command, requires the substring in the command's output.
Expect string
// CloseTerminal sends `exit` (a convenience for the final node).
CloseTerminal bool
}
ConsoleFlowAction is what a node sends once its wait matched (or immediately, if it has no wait). Exactly one of the fields is used.
type ConsoleFlowNode ¶ added in v0.2026269.700
type ConsoleFlowNode struct {
// ID is the node's identifier (its map key; carried for evidence).
ID string
// Description is an optional evidence label.
Description string
// Wait lists the outcomes to OCR-poll for. Empty means "act immediately".
Wait []ConsoleFlowOutcome
// Action is sent after a wait matched (or immediately when Wait is empty).
Action ConsoleFlowAction
// Transitions maps an outcome Name to the next node ID. A matched outcome
// with no entry falls through to Next.
Transitions map[string]string
// Next is the default target for an unmatched outcome ("" = end the flow).
Next string
// Artifact, when set, saves the frame captured at this node's decision.
Artifact string
// TimeoutSec bounds this node's OCR poll (default ConsoleDefaultTimeoutSec).
TimeoutSec int
}
ConsoleFlowNode is ONE state of the flow.
type ConsoleFlowOutcome ¶ added in v0.2026269.700
type ConsoleFlowOutcome struct {
// Name is the outcome's identifier, keyed in a node's Transitions.
Name string
// Match is the case-insensitive OCR substring that identifies this outcome
// (empty when the outcome is a screen-reference match).
Match string
// Reference is a host path to a PREVIOUSLY-CAPTURED screenshot of this
// screen. When set, the outcome matches when the CURRENT frame's perceptual
// hash is within MaxDistance of that reference — no OCR needed.
Reference string
// MaxDistance is the Hamming threshold for a Reference match (default
// ScreenDefaultMaxDistance; only meaningful with Reference).
MaxDistance int
// Failure marks an outcome that is a FAILURE unless a transition routes it
// explicitly. It lets a flow fail fast on a wrong passphrase / an error
// screen while still allowing a deliberate recovery branch.
Failure bool
}
ConsoleFlowOutcome is ONE named condition a node waits for. The engine OCR-polls until any outcome matches. An outcome matches EITHER by an OCR substring (Match) OR by a reference SCREENSHOT (Reference) — so a screen that OCRs badly (a firmware menu, a graphical lock) is still recognisable.
type ConsoleFlowResult ¶ added in v0.2026269.700
type ConsoleFlowResult struct {
Steps []ConsoleStepResult
Final string
LogText string
}
ConsoleFlowResult is the full evidence of a flow run.
func RunConsoleFlow ¶ added in v0.2026269.700
func RunConsoleFlow(ctx context.Context, tr ConsoleTransport, spec ConsoleFlowSpec) (ConsoleFlowResult, error)
RunConsoleFlow drives a bounded console flow on the transport. The generic `flow` (R3). It returns the flow result on success, or the partial result plus the error. One implementation, both transports.
type ConsoleFlowSpec ¶ added in v0.2026269.700
type ConsoleFlowSpec struct {
Start string
Nodes map[string]ConsoleFlowNode
SudoPassword string
MaxSteps int
MaxLoops int
// ResumeFromScreen + ResumeOrder: auto-detect the entry node from the current
// screen (see ConsoleFlow.ResumeFromScreen / DetectStart).
ResumeFromScreen bool
ResumeOrder []string
// PromptAnchors guards a node's `command` action against typing into a
// non-shell screen (a pager/menu/login).
PromptAnchors []string
// Deadline bounds the whole flow's wall clock so it returns clean evidence
// before the host's per-step never-hang kill.
Deadline time.Time
}
ConsoleFlowSpec is the transport-neutral input to RunConsoleFlow — the fields both plugins decode their CUE params into.
type ConsoleSession ¶ added in v0.2026269.700
type ConsoleSession struct {
Transport ConsoleTransport
// OCR defaults to OCRBytes when nil, so every transport reads the screen the
// same way as the artifact validator.
OCR func(png []byte) (string, error)
// SudoPassword is entered at a sudo password prompt (`[sudo] password for …`).
SudoPassword string
// PromptAnchors, when set, makes every command FIRST verify a shell prompt is
// on screen (case-insensitive substring match) before typing. It is the
// fast-fail guard against typing into the WRONG screen — a pager (`omarchy`
// help), a menu, a login prompt — where the command and its marker are
// swallowed and the wait then burns the full timeout. Without it a command is
// typed blindly (the previous behavior). Default nil = no preflight.
PromptAnchors []string
// PromptTimeoutSec bounds the preflight prompt wait (default 30).
PromptTimeoutSec int
// PollInterval is how often the engine re-captures while waiting (default
// ConsoleSessionDefaultPollInterval). A real condition poll, not a sleep.
PollInterval time.Duration
// Logger, when set, receives one line per command (evidence).
Logger func(format string, args ...any)
// contains filtered or unexported fields
}
ConsoleSession runs commands on an open terminal over a ConsoleTransport.
func (*ConsoleSession) EnterPassphrase ¶ added in v0.2026269.700
func (s *ConsoleSession) EnterPassphrase(ctx context.Context, passphrase string, successAnchors, failureAnchors []string, timeoutSec int, artifact string) (string, bool, error)
EnterPassphrase types a passphrase and submits it with Return, then waits for a SUCCESS anchor, failing FAST on a FAILURE anchor (a wrong-passphrase message) or on timeout. It is the LUKS/initramfs primitive: no shell exists there to echo a marker, so completion is a screen condition the caller names.
ok=true means a success anchor appeared; a failure anchor returns an error naming it (never a silent success — a wrong passphrase is a real failure, not an "outcome"). The OCR text read at the decision is returned either way.
func (*ConsoleSession) NextMarker ¶ added in v0.2026269.700
func (s *ConsoleSession) NextMarker() string
NextMarker returns the next completion marker for this session. It carries a FRESH per-command nonce (a 12-digit token from a time-seeded LCG, DIGIT-ONLY because tesseract misreads similar letters) so neither a marker from a previous RUN nor an EARLIER COMMAND's marker (still on screen) can satisfy this command's wait — the stale-echo RCAs. The counter is carried for evidence.
func (*ConsoleSession) RunCommand ¶ added in v0.2026269.700
func (s *ConsoleSession) RunCommand(ctx context.Context, c ConsoleCommand) (ConsoleCommandResult, error)
RunCommand types one command, submits it, waits for its completion marker (entering the sudo password if the target prompts), and returns the OCR-read screen text. It is the ONE place a command is driven, so a session of N commands is N calls to it — never a second drive loop (R3).
func (*ConsoleSession) RunCommands ¶ added in v0.2026269.700
func (s *ConsoleSession) RunCommands(ctx context.Context, cmds []ConsoleCommand) ([]ConsoleCommandResult, error)
RunCommands runs each command in order, returning all results. It stops at the first failure and returns the results collected so far alongside the error.
func (*ConsoleSession) WaitForAny ¶ added in v0.2026269.700
func (s *ConsoleSession) WaitForAny(ctx context.Context, wants []string, timeoutSec int, artifact string) (string, bool, error)
WaitForAny OCR-polls until ANY of the wanted substrings appears, returning the full OCR text read. It is the readiness primitive for opening a terminal (the shell is ready when its prompt appears) and for passphrase flows where the shell is not reachable to echo a marker.
type ConsoleStep ¶ added in v0.2026266.2315
type ConsoleStep struct {
WaitFor string
Action string // key | type | key-combo ("" = pure wait)
Key string
Combo string
Text string
TimeoutSec int
Optional bool
Artifact string
Description string
}
ConsoleStep is ONE step of a console-wizard recipe: OCR-wait for its WaitFor anchor to appear on screen, then perform ONE input action. WaitFor MUST be a screen-UNIQUE string — a string present on every screen (an OS logo, a window title) passes vacuously and desynchronises the whole drive.
func SelectRecipe ¶ added in v0.2026266.2315
func SelectRecipe(recipes map[string][]ConsoleStep, steps []ConsoleStep, name string) ([]ConsoleStep, error)
SelectRecipe returns the named recipe from a set of named recipes, with the bare `steps` list serving as the single default recipe. PURE over plain Go data: the caller decodes its OWN CUE-sourced recipe and passes the result here, so this engine holds no wire type. An unknown name (when recipes are declared) is a clear error, never a silent empty drive.
type ConsoleStepPlan ¶ added in v0.2026266.2315
type ConsoleStepPlan struct {
WaitFor string
Action string
Key string
Combo string
Text string
TimeoutSec int
Optional bool
Artifact string
Description string
}
ConsoleStepPlan is one recipe step after answer substitution — the pure, testable unit of the engine.
func BuildConsolePlan ¶ added in v0.2026266.2315
func BuildConsolePlan(steps []ConsoleStep, answers map[string]string) ([]ConsoleStepPlan, error)
BuildConsolePlan validates an authored recipe and applies answer substitution. It is PURE over (steps, answers): no transport, no clock — so a recipe's shape is unit-locked without a device and a malformed recipe fails before any session.
type ConsoleStepResult ¶ added in v0.2026269.700
type ConsoleStepResult struct {
Node string
Outcome string
// Text is the OCR text read at the node's decision.
Text string
// CommandOutput is the OCR-read output of a `command` action (empty for a
// raw-input node), so "read the results via OCR" is visible in the evidence.
CommandOutput string
}
ConsoleStepResult is the outcome of one visited node.
type ConsoleTransport ¶ added in v0.2026266.2315
type ConsoleTransport interface {
// Capture returns the CURRENT screen as PNG bytes.
Capture(ctx context.Context) ([]byte, error)
// PressKey presses and releases one named key (Return, Escape, F5, ...).
PressKey(ctx context.Context, name string) error
// PressCombo presses a modifier chord (ctrl+c, ctrl+alt+Delete, ...).
PressCombo(ctx context.Context, combo string) error
// Type types a string.
Type(ctx context.Context, text string) error
}
ConsoleTransport is the per-transport primitive set the engine drives: capture the current screen as PNG, and send keyboard input. Each plugin implements it over its own wire (JetKVM HID, SPICE keyboard).
type ConsoleWizard ¶ added in v0.2026266.2315
type ConsoleWizard struct {
Steps []ConsoleStep
Answers map[string]string
Transport ConsoleTransport
OCR func(png []byte) (string, error)
PollInterval time.Duration
// Logger, when set, receives a line per screen seen / input sent (evidence).
Logger func(format string, args ...any)
}
ConsoleWizard drives a recipe over a transport. OCR defaults to OCRBytes when nil, so both transports read the screen the same way as the artifact validator.
func (*ConsoleWizard) Run ¶ added in v0.2026266.2315
func (w *ConsoleWizard) Run(ctx context.Context) (string, error)
Run drives the recipe on the transport, OCR-gating each screen. It returns a per-step evidence log on success; on a wait timeout it FAILS naming the step, the anchor and what OCR actually read (never a silent pass). An `Optional` step whose anchor times out is SKIPPED instead (its action not sent).
type ContainerInspection ¶ added in v0.2026197.1320
type ContainerInspection struct {
Name string `json:"Name"`
Config InspectConfig `json:"Config"`
HostConfig InspectHostConfig `json:"HostConfig"`
NetworkSettings InspectNetwork `json:"NetworkSettings"`
Mounts []InspectMount `json:"Mounts"`
}
ContainerInspection is the subset of `podman inspect` JSON that the test runner needs to resolve runtime ${…} variables. Field names mirror the podman/docker inspect schema — we read the JSON the engine produces, we do not construct it.
func (*ContainerInspection) IsHostNetworked ¶ added in v0.2026197.1320
func (c *ContainerInspection) IsHostNetworked() bool
IsHostNetworked returns true when the container uses --network=host, in which case every container port is trivially the same host port.
type DefaultDownloader ¶ added in v0.2026192.1026
type DefaultDownloader struct{}
DefaultDownloader is the built-in git fetch backend — it delegates to DownloadRepo (git clone into the cache). The host uses it until a refs plugin registers a different RefsDownloader. Stays in kit (real git-clone I/O, not a pure seam contract).
type DeployExecutor ¶
type DeployExecutor interface {
// Venue returns the host executor's stable venue identifier.
Venue(ctx context.Context) (string, error)
// RunSystem runs a root (sudo) script on the venue; optsJSON is a marshalled EmitOpts (nil ok).
RunSystem(ctx context.Context, script string, optsJSON []byte) error
// RunUser runs an unprivileged script on the venue.
RunUser(ctx context.Context, script string, optsJSON []byte) error
// PutFile places content at a path on the venue (ownerRoot → root:root). Binary-safe.
PutFile(ctx context.Context, remotePath string, content []byte, mode uint32, ownerRoot bool) error
// GetFile reads a venue file back to the host (asRoot reads via sudo).
GetFile(ctx context.Context, path string, asRoot bool) ([]byte, error)
// RunCapture runs a command on the venue, returning stdout/stderr/exit separately.
RunCapture(ctx context.Context, script string) (stdout, stderr string, exit int, err error)
// RunHostStep drives a HOST-ENGINE step on the host engine + applies onto the venue,
// returning the step's recorded reverse ops.
RunHostStep(ctx context.Context, step spec.InstallStepView, optsJSON []byte) ([]spec.ReverseOp, error)
}
DeployExecutor is the reverse-channel surface WalkPlans drives. charly's plugin SDK *Executor satisfies it structurally (identical method set), so a plugin passes its sdk.Executor straight through — kit need not import the SDK (no cycle).
type DeployRecord ¶ added in v0.2026190.848
type DeployRecord = spec.DeployRecord
SPIKE (value-type relocation, #55 cluster 4): DeployRecord/CandyRecord/ StepRecord relocated to spec (spec/spec/ledger_records.go) — every field already resolved to a spec.* type and none carried methods, so they moved verbatim. Zero-churn aliases.
func ReadDeployRecord ¶ added in v0.2026190.848
func ReadDeployRecord(paths *LedgerPaths, id string) (*DeployRecord, error)
ReadDeployRecord loads ledger.deploys[id]; returns nil, nil if absent.
type EngineConfig ¶ added in v0.2026190.848
type EngineConfig = hostenv.EngineConfig
runtime_config.go — re-export of the user-level runtime configuration subsystem, RELOCATED to spec/hostenv/runtime_config.go (#55 host-env fabric extraction). Resolving engine / run-mode / storage paths from env > config-file > defaults is a HOST-ENVIRONMENT primitive, homed in spec/hostenv. kit re-exports the types + funcs so the ~23 kit.ResolveRuntime / kit.RuntimeConfig / kit.ResolvedRuntime / … call sites (charly core + plugins) are untouched.
NOTE: the two test-injection SEAM vars — RuntimeConfigPath and SystemdUserRuntimeDir — are DELIBERATELY NOT re-exported. A live var that callers REASSIGN cannot be `var X = hostenv.X` aliased (that copies the value, so a reassignment through kit would never reach hostenv's own reader). Every reader/writer references hostenv.RuntimeConfigPath / hostenv.SystemdUserRuntimeDir directly (charly host_build_hostprobe.go, plugin-settings, and the test-injection sites).
type EnvConfig ¶ added in v0.2026190.848
EnvConfig — resolved candy env (KEY=value vars + PATH-append entries). CUE-SOURCED in spec now (sdk/schema/candymodel.cue, the S-CM enabler) so #CandyModel can compose it; this ALIASES onto spec (SDD). The helper functions below operate on it unchanged.
func ExpandEnvConfig ¶ added in v0.2026190.848
ExpandEnvConfig expands all ~ and $HOME references in an EnvConfig
func MergeEnvConfigs ¶ added in v0.2026190.848
MergeEnvConfigs merges multiple env configs, later configs override earlier
type Executor ¶
type Executor = spec.CheckExecutor
Executor is the subset of charly's DeployExecutor a check verb needs (spec.CheckExecutor, checkcontext.go): run one command/script on the venue and capture stdout/stderr/exit separately. charly's DeployExecutor satisfies it structurally, so *Runner.Exec is passed straight through. Aliased here so candy call sites compile unchanged.
type FetchedImage ¶ added in v0.2026190.848
FetchedImage is the result of FetchQcow2: the absolute path to the cached file plus the resolved sha256 (useful for logging / audit).
func FetchArtifact ¶ added in v0.2026242.1032
func FetchArtifact(src VmSource, ext string) (FetchedImage, error)
FetchArtifact is FetchQcow2 generalised over the cached file's EXTENSION, and nothing else. Every behaviour below — the content-addressed cache keyed on sha256(url), the cross-process flock, the sidecar-sum auto-resolve, the resumable .part download, the stale-partial single refetch, the atomic promote — is identical for a qcow2 cloud image and for an installer ISO, because none of it ever looks inside the file.
The extension is not cosmetic: the cache is shared, and a bare hash with no suffix would let a qcow2 and an ISO fetched from two URLs that happened to collide in the operator's mind land on indistinguishable paths in a directory a human reads during an incident. It also lets `file`/`qemu-img` on a cache entry mean something.
This exists because `source.kind: iso` needs exactly this fetcher for the installer image. Copying it would be the second copy of a resumable, lock-protected, checksum-verifying downloader (R3).
func FetchQcow2 ¶ added in v0.2026190.848
func FetchQcow2(src VmSource) (FetchedImage, error)
FetchQcow2 downloads (or reuses a cached copy of) a qcow2 URL, verifying the sha256 checksum. Resumable: partial downloads with a matching Content-Length are continued via Range: bytes=.
If the checksum value is empty, the fetcher attempts to auto-resolve a sidecar file at <url>.SHA256 / .sha256 / .sha256sum (Arch convention is .SHA256). The first one that returns HTTP 200 wins.
type GraderRequest ¶ added in v0.2026191.2205
type GraderRequest struct {
Description string
Keyword string
Text string
// ReadOnly is true for agent-check: (assessment only), false for agent-run: (may mutate).
ReadOnly bool
}
GraderRequest is the agent grader's input for one agent-run:/agent-check: step.
type GraphicsEndpoint ¶ added in v0.2026187.2153
type GraphicsEndpoint = spec.CheckGraphicsEndpoint
GraphicsEndpoint is the resolved, dialable VM graphics endpoint a vnc/spice verb gets from CheckContext.ResolveGraphicsEndpoint — homed in the spec contract module (spec.CheckGraphicsEndpoint, checkcontext.go), aliased here for unchanged candy call sites.
type HTTPRequest ¶
type HTTPRequest = spec.CheckHTTPRequest
HTTPRequest is the host-vantage HTTP request a check verb hands cc.HTTPDo — homed in the spec contract module (spec.CheckHTTPRequest, checkcontext.go), aliased here unchanged.
type HTTPResponse ¶
type HTTPResponse = spec.CheckHTTPResponse
HTTPResponse is the result of cc.HTTPDo — homed in the spec contract module (spec.CheckHTTPResponse, checkcontext.go), aliased here unchanged.
type InspectConfig ¶ added in v0.2026197.1320
InspectConfig carries the fields inside the "Config" object that we need: the hostname (container's internal name) and the effective env.
type InspectHostConfig ¶ added in v0.2026197.1320
type InspectHostConfig struct {
NetworkMode string `json:"NetworkMode"`
}
InspectHostConfig carries the fields inside the "HostConfig" object that we need — currently just NetworkMode so host-networked containers can be detected (their NetworkSettings.Ports is empty, but container ports are bound 1:1 to host ports).
type InspectMount ¶ added in v0.2026197.1320
type InspectMount struct {
Type string `json:"Type"`
Name string `json:"Name,omitempty"`
Source string `json:"Source"`
Destination string `json:"Destination"`
}
InspectMount describes a single mount attached to the container. For named volumes Name is set and Source is the volume's _data path; for bind mounts Name is empty and Source is the host directory.
type InspectNetwork ¶ added in v0.2026197.1320
type InspectNetwork struct {
IPAddress string `json:"IPAddress"`
Networks map[string]InspectNetworkBind `json:"Networks"`
// Ports keys are like "6379/tcp"; values are nil when unexposed or
// a slice of bindings when published.
Ports map[string][]InspectPortBind `json:"Ports"`
}
InspectNetwork carries IP address and port-binding data. Both top-level IPAddress and per-network IPAddress are captured — podman rootless with the default network uses the per-network form; docker bridge uses the top-level form.
type InspectNetworkBind ¶ added in v0.2026197.1320
type InspectNetworkBind struct {
IPAddress string `json:"IPAddress"`
}
InspectNetworkBind is the per-network record under NetworkSettings.Networks.
type InspectPortBind ¶ added in v0.2026197.1320
InspectPortBind is the host-side record of a port publication.
type KillEvidence ¶ added in v0.2026282.1057
type KillEvidence struct {
// Bound is the per-attempt never-hang ceiling that fired.
Bound time.Duration
// Observed reports whether a local progress observation was available at kill time.
Observed bool
// Pid is the local process that was running the probe (0 when unknown).
Pid int
// Alive reports whether that process was still running when the bound fired.
Alive bool
// SilentFor is how long the probe had produced no progress when the bound fired.
SilentFor time.Duration
}
never_hang_evidence.go — the per-attempt never-hang kill must name WHAT WAS ABSENT, not only which bound fired.
The bound alone answers "how long did it run"; it does not answer "was the probe making progress, or was it wedged?" — and those two have different owners: a wedged probe is a defect in the probe, a slow-but-progressing probe needs an authored `timeout:`. Where a LOCAL pid is known, the process itself is the witness: it is either still alive (so the kill cut short a probe that was still running and had produced no output since the observation started) or already gone (so the bound was not what ended it). Saying which is the difference between a diagnosable kill and a dead end.
Remote/venue probes have no local pid to read, so they report Observed=false and keep exactly the message they had before — the qualifier the design draws is "where a local pid exists", not "everywhere".
func ObserveLocalKill ¶ added in v0.2026282.1057
ObserveLocalKill builds the evidence for a local pid: whether it is still alive and how long it has been silent. `alive` and `now` are injected so a caller (and a test) can read liveness and time deterministically — the seam that lets the never-hang path be proven without waiting for a real bound to elapse.
type LabelDescriptionSet ¶ added in v0.2026191.2205
type LabelDescriptionSet = spec.LabelDescriptionSet
func MergeDeployDescriptions ¶ added in v0.2026197.1537
func MergeDeployDescriptions(baked *LabelDescriptionSet, localPlan []spec.Step, originName string) *LabelDescriptionSet
MergeDeployDescriptions overlays a deployment node's local `plan:` steps onto a label-baked LabelDescriptionSet's Deploy section. A baked deploy step with the same step id is replaced by the local one; otherwise the local step is appended. This is the per-host override surface for acceptance steps (charly.yml deploy entries). If localPlan is empty, returns baked unchanged.
type LabeledDescription ¶ added in v0.2026191.2205
type LabeledDescription = spec.LabeledDescription
LabeledDescription + LabelDescriptionSet are CUE-sourced in spec (boxmetadata.cue, P2B, #60) and ALIASED here — spec.BoxMetadata.Description contains a *LabelDescriptionSet and spec sits below kit, so containment forces them down to spec (like VolumeMount → spec). Consumers keep using kit.LabelDescriptionSet / kit.LabeledDescription unchanged; the IsEmpty method lives in spec/labelset_methods.go beside the type.
type LedgerLock ¶ added in v0.2026190.848
type LedgerLock struct {
// contains filtered or unexported fields
}
LedgerLock is an acquired advisory lock on the ledger. Call Release() when done. Panic-safe via defer.
func AcquireLedgerLock ¶ added in v0.2026190.848
func AcquireLedgerLock(paths *LedgerPaths) (*LedgerLock, error)
AcquireLedgerLock takes a blocking exclusive flock on the ledger TRANSACTION lock file (LedgerTxLockPath — NOT the config RMW lock, see its doc comment) via the shared AcquireFileLock primitive (filelock.go). Blocks until the lock is available.
func (*LedgerLock) Release ¶ added in v0.2026190.848
func (l *LedgerLock) Release() error
Release releases the flock and closes the file.
type LedgerPaths ¶ added in v0.2026190.848
type LedgerPaths struct {
ConfigFile string // the per-host charly.yml path
LockFile string // the advisory lock path
}
LedgerPaths describes where the ledger lives. The ledger is the `ledger:` section of the per-host charly.yml. Extracted so tests can redirect to a temp file.
The legacy per-deploy JSON-file layout (~/.config/opencharly/installed/) is DELETED by this cutover. The consumers (plugin-fleet, plugin-substrate) migrate to ConfigFile in the same wave (their PRs land with the new sdk pin); a stale consumer fails to COMPILE against this shape — a loud failure, never a silent wrong answer.
func DefaultLedgerPaths ¶ added in v0.2026190.848
func DefaultLedgerPaths() (*LedgerPaths, error)
DefaultLedgerPaths returns the canonical paths anchored at the per-host charly.yml (~/.config/charly/charly.yml, honoring the CHARLY_DEPLOY_CONFIG override).
func (*LedgerPaths) Ensure ¶ added in v0.2026190.848
func (p *LedgerPaths) Ensure() error
Ensure creates the config directory if missing.
type LocalImageInfo ¶ added in v0.2026197.1320
type LocalImageInfo = container.LocalImageInfo
LocalImageInfo describes an image present in the engine's local storage.
type LocalImageResolution ¶ added in v0.2026227.1713
type LocalImageResolution = container.LocalImageResolution
LocalImageResolution is the full-answer form of a local-image resolve: the elected ref plus the newest local BUILD of the same short name.
type MemberRun ¶ added in v0.2026250.928
type MemberRun struct {
// Origin is the member's origin key ("deploy:<name>" / "vm:<name>"/…),
// used for deterministic result ordering (venue-keyed).
Origin string
// Set is the member's collected plan (include-expanded, overlay-merged).
Set *LabelDescriptionSet
// Runner is the member's OWN independent PlanContext. Never nil for a
// member with steps; the walk calls Scenario/SetScenario on it (one
// scenario per member for the whole walk).
Runner PlanContext
}
MemberRun is ONE member's contribution to a bed walk: its already-collected plan set plus an INDEPENDENT Runner (PlanContext) for that member. A4 — the walk NEVER shares one Runner across members; every concurrently-executing step of a different member runs on that member's own Runner.
type MethodSpec ¶
type MethodSpec struct {
// Path is the `charly check <verb> <method...>` subcommand path.
Path []string
// Required names the plugin-input fields that must be set for this method.
Required []string
// PosArgs builds the positional args inserted after the image name, before -i.
PosArgs func(c *spec.Op) []string
// Artifact marks a state-dependent capture method (screenshot) whose produced
// file is validated.
Artifact bool
// SkipBox = true means the verb targets a cluster/other non-image target, so the
// usual image/deploy-name positional is NOT inserted.
SkipBox bool
}
MethodSpec is one method's nested-CLI dispatch spec: the `charly check <verb> <method...>` subcommand path, the required #Op modifiers, the positional-arg builder, and the artifact / skip-box flags. A plugin's method allowlist is a map[string]MethodSpec; fields are exported so a candy module can author it.
type NestedExecutor ¶ added in v0.2026190.848
type NestedExecutor = exec.NestedExecutor
type NestedJump ¶ added in v0.2026190.848
type NestedJump = exec.NestedJump
type ParsedPortMapping ¶ added in v0.2026190.848
type ParsedPortMapping = spec.ParsedPortMapping
The pure podman port-mapping PARSE/FORMAT value-vocabulary — the ParsedPortMapping value type + ParsePortMapping / FormatPortMapping / StripPortSuffix — now lives in spec (#55 value-type consolidation; stdlib-only, no mechanism dependency, in-process only, so it is a plain spec Go value, not a wire type). These forwarders keep kit's own host-coupled port helpers (ParseHostPort / CheckPortAvailability / ApplyPortOverrides / AllocateAutoPorts / …) + the deploy candies compiling against kit.* unchanged.
func AllocateAutoPorts ¶ added in v0.2026190.848
func AllocateAutoPorts(containerPorts []int, occupied map[int]bool) ([]ParsedPortMapping, error)
AllocateAutoPorts probes free TCP host ports — one per container port, in declaration order. The `occupied` set names host ports already in use by other deployments (so two `port: [auto]` deploys on the same host don't collide). Returned mappings have BindAddr="" (default host bind) and Protocol="tcp". Each successful allocation is recorded back into `occupied` so subsequent calls in the same DeployConfig pass see the reservation.
Free-port discovery uses the same net.Listen("tcp","127.0.0.1:0") + immediate-close pattern already used by ssh_tunnel.go:78 and vnc_helpers.go's unixToTcpBridge — the OS picks an ephemeral port, we close, and the caller binds in the (small) window before the OS reassigns.
type ParsedRef ¶ added in v0.2026198.345
remote_ref.go — re-export of the remote-ref parsing helpers, RELOCATED to spec (#55 value extraction). The ref-parsing VOCAB (ParsedRef/IsRemoteImageRef/ParseRemoteRef/SplitRepoAndSubPath) already lived in spec/spec/ref_parse.go; kit's former self-contained copy was a duplicate (R3), now collapsed. StripURLScheme/ResolveBoxName rejoined it in spec/spec/box_name.go. kit re-exports them here so every existing kit.ParseRemoteRef / kit.ResolveBoxName / … call site (plugins + sdk) is untouched. New consumers should reference spec.* directly.
type PlanContext ¶ added in v0.2026191.2205
type PlanContext interface {
// Distros is the image's distro tag list, for the exclude_distros: skip.
Distros() []string
// Mode selects RunModeLive vs RunModeBox routing.
Mode() RunMode
// VerifyOnly restricts a plan walk to idempotent verify steps (check:/agent-check:),
// skipping mutating steps (run:/agent-run:) — the check live / check box mode.
VerifyOnly() bool
// SkipDeterministicRun skips deterministic run: install-timeline steps while still
// running check:/agent-check: and the agent-graded agent-run: — the feature-run mode.
SkipDeterministicRun() bool
// ContextSkipReason returns a non-empty skip message when the op's effective execution
// context is not active in the current mode (box→build, live→runtime); "" means the op
// runs. Wraps the core VerbCatalog grammar so ExecContext never crosses this seam.
ContextSkipReason(op *spec.Op) string
// EffectiveDo resolves the op's do-mode (the keyword-stamped intentDo, else the verb's
// VerbCatalog default, else DoAssert). Wraps the core grammar.
EffectiveDo(op *spec.Op) spec.DoMode
// EffectiveEnv builds the variable-expansion env for the current step (the resolver base
// overlaid with cross-deployment ${HOST:…} addresses + the scenario captures).
EffectiveEnv() map[string]string
// ClassifyUnresolved reports whether `name` could be supplied to op in some OTHER mode or
// scope (UnresolvedConditional), or could never resolve for a step of this kind
// (UnresolvedUnknown). Only the host knows its own variable vocabulary, so only the host can
// answer this; the walk uses the answer to tell a legitimate skip from a dead assertion
// (opencharly/charly#865).
ClassifyUnresolved(op *spec.Op, name string) UnresolvedClass
// ProbeNeverHang is the per-probe-attempt never-hang ceiling for op.
ProbeNeverHang(op *spec.Op) time.Duration
// SwapVenue retargets the host executor/resolver to op's per-step venue for the duration
// of one dispatch, returning a restore func (nil when no swap) and a non-empty failReason
// when the venue could not be resolved (the op is reported FAIL). The core impl mutates
// the *Runner it wraps, so EffectiveEnv + the verb dispatch see the swapped venue.
SwapVenue(op *spec.Op) (restore func(), failReason string)
// Scenario is the per-run capture/var context; SetScenario installs a fresh one for a
// RunPlan walk (restored by the caller).
Scenario() *ScenarioContext
SetScenario(sc *ScenarioContext)
// Verbs is the verb-dispatch seam; Grader is the agent-step grader (nil when unbound).
Verbs() VerbResolver
Grader() StepGrader
}
PlanContext is the host-driver surface the plan walk consumes. The core *Runner implements it; a plugin running a plan in-proc supplies its own impl. Every method is kind-blind — no concrete kind, no provider word crosses this interface (spec.ExecContext is a plain vocabulary type; the grammar that consults it stays core behind ContextSkipReason / EffectiveDo).
type PlanGrammar ¶ added in v0.2026194.1605
type PlanGrammar interface {
// EffectiveDo resolves op's do-mode (the keyword-stamped intentDo wins, else the verb's
// VerbCatalog default, else DoAssert).
EffectiveDo(op *spec.Op) spec.DoMode
// InContext reports whether op is legal in the run's active context: runtime=true → the
// live (runtime) context, runtime=false → the box (build) context.
InContext(op *spec.Op, runtime bool) bool
// ContextsLabel is op's effective-contexts list pre-formatted for the context-skip message.
ContextsLabel(op *spec.Op) string
}
PlanGrammar is the do-mode + execution-context grammar seam. charly core's VerbCatalog impl stays core (ExecContext lives in deploykit, which imports kit, so the concrete context enum never crosses this seam: the context predicate is a bool and the skip-message contexts a pre-formatted string).
type PollCond ¶ added in v0.2026186.739
type PollCond = poll.PollCondition
type PortConflict ¶ added in v0.2026190.848
type PortConflict struct {
HostPort int
ContPort int
Owner string // container name, or "unknown"
OwnerType string // "charly-container", "container", "host-process"
}
PortConflict describes a host port that is already in use.
func CheckPortAvailability ¶ added in v0.2026190.848
func CheckPortAvailability(ports []string, bindAddr string, engine string) []PortConflict
CheckPortAvailability tests whether each host port can be bound. Returns a list of conflicts for ports that are already in use. Detects /udp suffix and uses UDP bind check accordingly.
type ProvisionActor ¶
type ProvisionActor = checkstep.ProvisionActor
ProvisionActor is the OPTIONAL second role of a host-coupled verb candy: the do:act renderer for a state-provision verb. Aliased to checkstep.ProvisionActor.
type RefsDownloader ¶ added in v0.2026192.1026
type RefsDownloader = spec.RefsDownloader
refs_downloader.go — the swappable remote-repo FETCH BACKEND seam (P7). The interface itself relocated to sdk/spec (FLOOR-SLIM axis-A mechanical batch, alongside DocParser/ProjectWalker/ CandyScanner) so charly core's plugin_inproc.go can type-assert against it without importing kit; aliased here so every existing kit.RefsDownloader reference (candy/plugin-refs, charly/refs_threaded.go) keeps compiling unchanged. Only the DOWNLOAD is pluggable — the backend that turns a (repoPath, version) into a populated local cache tree. The fetch ORCHESTRATION (local-override resolution, cache-hit short-circuit, and the post-fetch schema auto-migration) used to be a P7-era "the host keeps it" boundary; K1 unit 4 relocated it to sdk/loaderkit.EnsureRepoDownloaded (reached through the ProjectLoader seam), since the v2 end-state ("core does not parse config, resolve, build, deploy, or check") supersedes that earlier boundary the same way K1 unit 1 already superseded materialize.go's own former "stays core, clause M" self-classification. The host still supplies the registry-touching legs (the resolved RefsDownloader, the migrate-command dispatch) as spec.RefsCollectSeams callbacks.
type ResolvedRuntime ¶ added in v0.2026190.848
type ResolvedRuntime = hostenv.ResolvedRuntime
runtime_config.go — re-export of the user-level runtime configuration subsystem, RELOCATED to spec/hostenv/runtime_config.go (#55 host-env fabric extraction). Resolving engine / run-mode / storage paths from env > config-file > defaults is a HOST-ENVIRONMENT primitive, homed in spec/hostenv. kit re-exports the types + funcs so the ~23 kit.ResolveRuntime / kit.RuntimeConfig / kit.ResolvedRuntime / … call sites (charly core + plugins) are untouched.
NOTE: the two test-injection SEAM vars — RuntimeConfigPath and SystemdUserRuntimeDir — are DELIBERATELY NOT re-exported. A live var that callers REASSIGN cannot be `var X = hostenv.X` aliased (that copies the value, so a reassignment through kit would never reach hostenv's own reader). Every reader/writer references hostenv.RuntimeConfigPath / hostenv.SystemdUserRuntimeDir directly (charly host_build_hostprobe.go, plugin-settings, and the test-injection sites).
type Result ¶
type Result = spec.CheckVerbResult
Result is a host-coupled verb's verdict — homed in the spec contract module (spec.CheckVerbResult, checkcontext.go), aliased here so the Pass/Fail/Skip constructors and every candy call site compile unchanged. charly converts it to its internal CheckResult (stamping the Op/Verb/timing) at the dispatch boundary.
type ReverseExecutor ¶ added in v0.2026190.848
type ReverseExecutor interface {
ReverseDryRun() bool
ReverseKeepRepoChanges() bool
ReverseKeepServices() bool
ReverseRunner() ReverseRunner
}
ReverseExecutor is the interface ReverseOp handlers expect. Allows us to pass either DeployDelCmd (for real teardown) or a test mock.
ReverseRunner returns the shell-runner used to execute reversal commands. When non-nil, handlers dispatch through it (so VM teardown runs commands over SSH instead of locally); when nil, handlers fall back to local `exec.Command` — the long-standing host-teardown path.
type ReverseOpKind ¶ added in v0.2026190.848
type ReverseOpKind = spec.ReverseOpKind
type ReverseRunner ¶ added in v0.2026190.848
type ReverseRunner interface {
// RunSystem runs a bash script as root (wraps with sudo on host
// runners; uses `ssh sudo bash -s` on VM runners).
RunSystem(script string) error
// RunUser runs a bash script as the deploy user (no sudo).
RunUser(script string) error
}
ReverseRunner executes reversal shell scripts at the requested privilege level. Implemented by both the local-exec host runner and the SSH-based VM runner (SSHReverseRunner, below).
type RunMode ¶
type RunMode = spec.CheckRunMode
RunMode mirrors charly's RunMode: the mode a check runs under. The type (+ its consts + String()) is homed in the spec contract module (spec.CheckRunMode, checkcontext.go) with the rest of the check-verb contract cluster, so charly core references the contract while importing only spec; aliased here (with the const re-exports) so candy call sites compile UNCHANGED.
type Runner ¶ added in v0.2026194.1605
type Runner struct {
// contains filtered or unexported fields
}
Runner wires the execution context for one pass of checks. Constructor-shaped: build it with NewRunner and reach its state through the methods below.
func NewRunner ¶ added in v0.2026194.1605
func NewRunner(cfg RunnerConfig) *Runner
NewRunner constructs a Runner from cfg, applying defaults for a zero HTTPClient (10s), DialTimeout (3s), and ProbeTimeout (the fallback ceiling; the host normally supplies its readiness-derived value).
func (*Runner) Box ¶ added in v0.2026194.1605
Box / Instance are the deployment's image + instance names (empty under ModeBox).
func (*Runner) CandyScanErr ¶ added in v0.2026194.1605
func (*Runner) ClassifyUnresolved ¶ added in v0.2026282.1947
func (r *Runner) ClassifyUnresolved(op *spec.Op, name string) UnresolvedClass
ClassifyUnresolved implements PlanContext. See SetUnresolvedClassifier for why the answer comes from the host and what the unset default means.
func (*Runner) ContextSkipReason ¶ added in v0.2026194.1605
ContextSkipReason returns a non-empty skip message when op's effective execution context is not active in the run's mode (box→build, live→runtime); "" means the op runs. The mode-composition and the message formatting are kit-side; only the VerbCatalog context predicate crosses the grammar seam (a nil grammar — a bare-Op test — never skips on context).
func (*Runner) DialTimeout ¶ added in v0.2026194.1605
DialTimeout is the per-dial ceiling for host-side TCP reachability probes. HTTPClient is the engine's base client (the host HTTPDo leg derives per-request clients from it). HasRuntime reports whether the resolved env carries running-container state (false → runtime-only vars resolve to a skip). CandyDirs / CandyScanErr anchor a relative committed-APK path.
func (*Runner) Distros ¶ added in v0.2026194.1605
Distros is the image's distro tag list, for the exclude_distros: skip.
func (*Runner) EffectiveDo ¶ added in v0.2026194.1605
EffectiveDo resolves op's do-mode via the injected grammar (DoAssert when no grammar is wired).
func (*Runner) EffectiveEnv ¶ added in v0.2026194.1605
EffectiveEnv builds the variable-expansion env for the current step: the resolver base overlaid with cross-deployment ${HOST:…} addresses (per-run, target-independent) then the scenario captures (which win on a key collision). Copy-on-overlay keeps the base map clean across runs.
func (*Runner) Exec ¶ added in v0.2026194.1605
Exec is the venue executor for the current (possibly venue-swapped) target.
func (*Runner) Grader ¶ added in v0.2026194.1605
func (r *Runner) Grader() StepGrader
func (*Runner) HTTPClient ¶ added in v0.2026194.1605
func (*Runner) HasRuntime ¶ added in v0.2026194.1605
func (*Runner) MCPProvide ¶ added in v0.2026250.731
func (r *Runner) MCPProvide() []spec.CandyMCPProvide
func (*Runner) ProbeNeverHang ¶ added in v0.2026194.1605
ProbeNeverHang is the per-probe-attempt never-hang ceiling for op. It is NOT the probe's semantic timeout (the http client, dial timeout, a verb's own timeout:, and the eventually: retry all operate INSIDE it) — it is the kill-switch for a probe that wedges in its data phase. A longer author-declared timeout: is honored over the floor so a slow probe is never cut short.
func (*Runner) Run ¶ added in v0.2026194.1605
Run executes the supplied checks sequentially and returns per-check results. It does not short-circuit on failure — the report shows every check's outcome. The per-check walk lives in RunOne; Runner is its driver (it implements PlanContext).
func (*Runner) Scenario ¶ added in v0.2026194.1605
func (r *Runner) Scenario() *ScenarioContext
Scenario is the per-run capture/var context; SetScenario installs one for a RunPlan walk.
func (*Runner) SetScenario ¶ added in v0.2026194.1605
func (r *Runner) SetScenario(sc *ScenarioContext)
func (*Runner) SetUnresolvedClassifier ¶ added in v0.2026282.1947
func (r *Runner) SetUnresolvedClassifier(f func(op *spec.Op, name string) UnresolvedClass)
SetUnresolvedClassifier installs the host's classification of an unresolved variable name. The host is the only party that knows its own variable vocabulary — which names a deploy scope, a mounted volume or the runner itself can supply in SOME mode — so the SDK asks rather than guesses. Without one, every unresolved name is UnresolvedConditional, which is exactly the behaviour that existed before opencharly/charly#865: a host that has not opted in keeps its verdicts, so adopting the classifier is a deliberate cutover rather than a silent change.
func (*Runner) SkipDeterministicRun ¶ added in v0.2026194.1605
SkipDeterministicRun skips deterministic run: install-timeline steps (feature-run mode).
func (*Runner) SwapVenue ¶ added in v0.2026194.1605
SwapVenue retargets the executor + env + image to op's per-step venue for the duration of one dispatch, returning a restore func (nil when no swap) and a non-empty failReason when the venue cannot be resolved. It mutates the Runner in place so EffectiveEnv + the verb dispatch (which read exec/env/box) see the swapped venue — the same self-swap guard the classical inline path used (venue set, differs from the active target, and a TargetResolver is wired).
func (*Runner) Verbs ¶ added in v0.2026194.1605
func (r *Runner) Verbs() VerbResolver
Verbs is the verb-dispatch seam; Grader is the agent-step grader (nil when unbound).
func (*Runner) VerifyOnly ¶ added in v0.2026194.1605
VerifyOnly restricts the walk to idempotent verify steps (check:/agent-check:).
func (*Runner) VmName ¶ added in v0.2026194.1605
VmName is the caller-set VM domain-target (the resolved per-deploy domain identity; empty for non-VM deployments); VmTargetName falls back to Box, the name the host vm/spice legs hand the plugin as the libvirt-domain target.
func (*Runner) VmTargetName ¶ added in v0.2026194.1605
type RunnerConfig ¶ added in v0.2026194.1605
type RunnerConfig struct {
Exec Executor
Mode RunMode
// Env is the resolved variable map (the host CheckVarResolver.Env); HasRuntime mirrors
// CheckVarResolver.HasRuntime (false → runtime-only vars resolve to an unresolved skip).
Env map[string]string
HasRuntime bool
Distros []string
Box string
Instance string
// VmName is the VM domain-target name the host vm/spice/libvirt verb legs address for a VM
// deployment: the caller sets it to the already-resolved per-deploy domain identity
// (charly-<VmName> is the live libvirt domain). Empty for non-VM deployments, where
// VmTargetName falls back to Box.
VmName string
// MCPProvide carries the deployment's mcp_provide declarations (VM/host venues have no
// podman-inspectable OCI label; the check env threads them for the out-of-process mcp:
// check verb). Empty for container venues, where the label resolution path applies.
MCPProvide []spec.CandyMCPProvide
HostVars map[string]string
// CandyDirs maps candy name → resolved source dir (relative committed-APK anchoring);
// CandyScanErr is its build error (only an apk-anchoring check consults it). Host-read.
CandyDirs map[string]string
CandyScanErr error
VerifyOnly bool
SkipDeterministicRun bool
Scenario *ScenarioContext
Grader StepGrader
// Injected host seams (all required for a live run; a bare-Op test may leave Grammar/
// TargetResolver nil — SwapVenue/ContextSkipReason then no-op, matching the classical path).
Verbs VerbResolver
Grammar PlanGrammar
TargetResolver VenueResolver
// Optional overrides — zero values take the NewRunner defaults.
DialTimeout time.Duration
ProbeTimeout time.Duration
HTTPClient *http.Client
}
RunnerConfig carries every field a Runner is built with. The host fills it (folding the former post-construction field-pokes + attachCheckRunnerContext); zero DialTimeout/ProbeTimeout/ HTTPClient fall back to sensible defaults in NewRunner.
type RuntimeConfig ¶ added in v0.2026190.848
type RuntimeConfig = hostenv.RuntimeConfig
runtime_config.go — re-export of the user-level runtime configuration subsystem, RELOCATED to spec/hostenv/runtime_config.go (#55 host-env fabric extraction). Resolving engine / run-mode / storage paths from env > config-file > defaults is a HOST-ENVIRONMENT primitive, homed in spec/hostenv. kit re-exports the types + funcs so the ~23 kit.ResolveRuntime / kit.RuntimeConfig / kit.ResolvedRuntime / … call sites (charly core + plugins) are untouched.
NOTE: the two test-injection SEAM vars — RuntimeConfigPath and SystemdUserRuntimeDir — are DELIBERATELY NOT re-exported. A live var that callers REASSIGN cannot be `var X = hostenv.X` aliased (that copies the value, so a reassignment through kit would never reach hostenv's own reader). Every reader/writer references hostenv.RuntimeConfigPath / hostenv.SystemdUserRuntimeDir directly (charly host_build_hostprobe.go, plugin-settings, and the test-injection sites).
type RuntimeVmConfig ¶ added in v0.2026190.848
type RuntimeVmConfig = hostenv.RuntimeVmConfig
runtime_config.go — re-export of the user-level runtime configuration subsystem, RELOCATED to spec/hostenv/runtime_config.go (#55 host-env fabric extraction). Resolving engine / run-mode / storage paths from env > config-file > defaults is a HOST-ENVIRONMENT primitive, homed in spec/hostenv. kit re-exports the types + funcs so the ~23 kit.ResolveRuntime / kit.RuntimeConfig / kit.ResolvedRuntime / … call sites (charly core + plugins) are untouched.
NOTE: the two test-injection SEAM vars — RuntimeConfigPath and SystemdUserRuntimeDir — are DELIBERATELY NOT re-exported. A live var that callers REASSIGN cannot be `var X = hostenv.X` aliased (that copies the value, so a reassignment through kit would never reach hostenv's own reader). Every reader/writer references hostenv.RuntimeConfigPath / hostenv.SystemdUserRuntimeDir directly (charly host_build_hostprobe.go, plugin-settings, and the test-injection sites).
type SSHExecutor ¶ added in v0.2026190.848
type SSHExecutor = exec.SSHExecutor
type SSHReverseRunner ¶ added in v0.2026201.1934
type SSHReverseRunner struct {
Exec *SSHExecutor
}
SSHReverseRunner adapts an *SSHExecutor to ReverseRunner (P13-KERNEL), so a teardown replays recorded ReverseOps over SSH — inside a VM guest, or on a `local: {host: user@machine}` remote — instead of on the operator host.
func (*SSHReverseRunner) RunSystem ¶ added in v0.2026201.1934
func (r *SSHReverseRunner) RunSystem(script string) error
func (*SSHReverseRunner) RunUser ¶ added in v0.2026201.1934
func (r *SSHReverseRunner) RunUser(script string) error
type ScenarioContext ¶ added in v0.2026191.1837
type ScenarioContext struct {
// CurrentStepID is rewritten for each step as the plan run executes, so ${STEP_ID}
// references resolve to the currently-running step's identifier. Reporters surface this
// on failures.
CurrentStepID string
// Backgrounds tracks PIDs of host-side processes spawned by `command:` verbs with
// `background: true`. Reaped at plan teardown via SIGTERM (best-effort; non-fatal on
// failure).
Backgrounds []int
// Results accumulates CheckResults from steps that have completed, indexed by step ID.
// Used by the `summarize:` verb to walk prior steps' Elapsed durations and compute
// distribution metrics.
Results map[string]CheckResult
// contains filtered or unexported fields
}
ScenarioContext carries per-plan-run mutable state across the execution of that run's steps — principally the capture store populated by checks with `capture: <name>`. Instantiated fresh per plan run (and per count expansion) so cross-run state never leaks.
The struct also threads the current step identifier through variable expansion (${STEP_ID}) so artifact paths and narrative text can embed stable references without the runner having to know about them.
A ScenarioContext is OWNED by one plan run's execution pass. When that pass completes, the context is discarded; the next run gets a fresh one. `capture:` values never survive the run that produced them.
func NewScenarioContext ¶ added in v0.2026191.1837
func NewScenarioContext() *ScenarioContext
NewScenarioContext returns an empty plan-run context.
func (*ScenarioContext) AddBackground ¶ added in v0.2026191.1837
func (s *ScenarioContext) AddBackground(pid int)
AddBackground records a PID for later teardown reaping. Thread-safe.
func (*ScenarioContext) ApplyToEnv ¶ added in v0.2026191.1837
func (s *ScenarioContext) ApplyToEnv(env map[string]string)
ApplyToEnv merges plan-run-scope variables into an env map for variable expansion. Called by the runner immediately before `Check.ExpandVars(env)` so the existing `${NAME[:arg]}` grammar picks up captures and the step id without knowing about the ScenarioContext type.
Keys populated:
- STEP_ID → ctx.CurrentStepID
ApplyToEnv overlays — it never overwrites existing keys so a host-level `${STEP_ID}` override (if ever introduced for testing) continues to win. The runner builds env by copying its resolver's base env first and then calling ApplyToEnv on the copy.
func (*ScenarioContext) SnapshotBackgrounds ¶ added in v0.2026191.1837
func (s *ScenarioContext) SnapshotBackgrounds() []int
SnapshotBackgrounds returns a copy of the current backgrounds slice. Used by the teardown reaper.
type ScreenSignature ¶ added in v0.2026269.700
type ScreenSignature struct {
// Hash is the 64-bit dHash (row-major adjacent-pixel comparisons).
Hash uint64
// Width / Height are the source frame dimensions, carried for evidence and
// for a sanity check (a wildly different geometry is reported).
Width, Height int
}
ScreenSignature is a perceptual fingerprint of one frame: a 64-bit difference hash plus the source geometry. Two frames of the SAME screen have a small Hamming distance; different screens have a large one.
func LoadScreenSignature ¶ added in v0.2026269.700
func LoadScreenSignature(path string) (ScreenSignature, error)
LoadScreenSignature reads a reference PNG/JPEG from the host path and hashes it. The reference is a "previously made screenshot" captured on the same machine.
func ScreenHash ¶ added in v0.2026269.700
func ScreenHash(frame []byte) (ScreenSignature, error)
ScreenHash computes a frame's perceptual signature. It decodes the PNG/JPEG, reduces it to a 9x8 grayscale grid (nearest-neighbour, so glyph/thin-line edges stay hard), and sets one bit per horizontal neighbour comparison (left<right). PURE and deterministic over the input bytes.
type ShellExecutor ¶ added in v0.2026190.848
type ShellExecutor = exec.ShellExecutor
type ShellKind ¶
type ShellKind string
ShellKind classifies the venue's login shell.
func DetectShellFromPath ¶
DetectShellFromPath maps a $SHELL path (or shell base name) to a ShellKind. Unknown / empty shells default to bash — the POSIX-safest choice.
type Status ¶
Status is a check verdict. It is the ONE pass/fail/skip enum for the check engine and every plugin candy — charly's CheckStatus is a type alias of it. FLOOR-SLIM Unit 4: Status itself (+ the iota consts + the String() method) moved to spec.Status (sdk/spec/status_result.go) as part of the CheckResult wire-envelope split — gengotypes has no construct for an iota enum + Stringer, so CUE owns the wire VALUE SET (a plain int) and Go owns the formatting behavior there. Kept as a type ALIAS here (not a repointed reference) so kit.Result + every out-of-process plugin candy's kit.Pass/Fail/Skip/StatusPass call sites compile UNCHANGED — this is a public SDK surface with ~15 external consumers, out of scope for an internal core-floor refactor.
type StepGrader ¶ added in v0.2026191.2205
type StepGrader interface {
Grade(ctx context.Context, req GraderRequest) CheckResult
}
StepGrader judges an agent step (agent-run:/agent-check:). The host impl spawns the configured kind:agent CLI to probe the live target and return a pass/fail verdict; nil when no grader is bound (agent steps then advisory-skip, or fail under strict).
type StepPass ¶ added in v0.2026194.1605
StepPass is the verbatim stdout/stderr/exit-code of a host-delegated guest sub-invocation. Aliased to spec.StepPass (the body lives there).
type StepProvider ¶
type StepProvider = checkstep.StepProvider
StepProvider is the OPTIONAL third role of a host-coupled verb candy: a verb whose build/deploy ACT lowers into a TYPED install-plan step (the candy owns both the kind mapping and the materialization). Aliased to checkstep.StepProvider.
type StepRecord ¶ added in v0.2026190.848
type StepRecord = spec.StepRecord
SPIKE (value-type relocation, #55 cluster 4): DeployRecord/CandyRecord/ StepRecord relocated to spec (spec/spec/ledger_records.go) — every field already resolved to a spec.* type and none carried methods, so they moved verbatim. Zero-churn aliases.
type StepResult ¶ added in v0.2026191.1732
type StepResult = spec.StepResult
StepResult is one plan step's outcome — the step's identity (keyword/text/origin/id) plus the CheckResult of running it. The result reporters consume a []StepResult. RELOCATED to the spec contract module (spec.StepResult, CUE-sourced in spec/schema/checkresult.cue, #55 CHECK-ENGINE cone Option A) so charly core's check-run seam + deploy-verify path reference it importing only spec; aliased here (kit.StepResult = spec.StepResult) so every candy call site compiles UNCHANGED. The wire shape is byte-identical: kit.CheckResult embeds spec.CheckResult + the engine-internal DeadlineExceeded (json:"-"), so on the wire only spec.CheckResult fields ever crossed — spec.StepResult.Result is spec.CheckResult directly, the SAME wire bytes. Construction sites that wrap a kit.CheckResult extract the embedded spec.CheckResult (.CheckResult).
func RunPlan ¶ added in v0.2026191.2205
func RunPlan(ctx context.Context, pc PlanContext, set *LabelDescriptionSet, strict bool) []StepResult
RunPlan executes the flat plan in a LabelDescriptionSet (already collected + include-expanded + overlay-merged) against the plan context, returning per-step results.
The context's mode selects which steps execute: VerifyOnly (check live / box) runs check:/agent-check: only; provision-and-verify (default) runs every step in order. include: steps never reach here (expanded at collect time); a residual one is a no-op skip. Agent steps route to the grader; run/check stamp the keyword-derived do-mode and dispatch through RunOne.
Stage-aware (Cutover C task 5): when any step of the plan carries a `stage:` modifier, RunPlan groups steps by stage and executes the stage groups in first-seen order (a single-member bed delegates to the same engine the multi-member walk uses — one canonical walk, R3). Without stages: today's sequential in-authored-order walk.
func RunPlanStaged ¶ added in v0.2026250.928
func RunPlanStaged(ctx context.Context, members []MemberRun, parallel bool, strict bool) []StepResult
RunPlanStaged executes a bed's member plans with stage grouping + member concurrency per the model above. members are in authored order; strict selects the agent-grader no-grader disposition (see RunPlan).
type TagExpr ¶ added in v0.2026191.1413
type TagExpr struct {
// contains filtered or unexported fields
}
TagExpr is an opaque compiled tag expression. Nil means "match everything" (no filter), so callers can write `if expr.Match(tags)` without a nil check.
func CombineTagFilters ¶ added in v0.2026191.1413
CombineTagFilters composes an include-filter and an exclude-filter into one effective expression. Either side may be nil:
- include nil, exclude nil → always matches
- include X, exclude nil → matches when X is true
- include nil, exclude Y → matches when Y is false
- include X, exclude Y → matches when X is true AND Y is false
func ParseTagExpr ¶ added in v0.2026191.1413
ParseTagExpr compiles a tag expression. Empty / whitespace input produces a nil TagExpr that matches everything. A syntax error is returned rather than silently matching or silently failing.
type TerminalOpen ¶ added in v0.2026269.700
type TerminalOpen struct {
// Combo is the hotkey that opens a terminal ("super+Return") or a VT switch
// ("ctrl+alt+F3").
Combo string
// PromptAnchors are the substrings that mean a shell prompt is ready.
PromptAnchors []string
// TimeoutSec bounds the wait for the prompt.
TimeoutSec int
// Artifact, when set, saves the frame captured at the decision.
Artifact string
}
TerminalOpen describes an `open-terminal` action.
type UnresolvedClass ¶ added in v0.2026282.1947
type UnresolvedClass int
UnresolvedClass says WHY a plan-step variable could not be resolved. The walk must not treat every unresolved name alike: one class is an honest skip, the other is an authoring error that would otherwise be handed to the operator as a PASS (opencharly/charly#865).
const ( // UnresolvedConditional — the host CAN supply this name in some OTHER mode or scope: a // deploy-scoped var under build scope, a var an unmounted volume would provide. The input // genuinely does not apply to THIS run, so a skip is the honest verdict. UnresolvedConditional UnresolvedClass = iota // UnresolvedUnknown — no mode or scope of this runner can supply the name to a step of this // kind. On an ASSERT-ONLY step that is an authoring error: a check's env is the runner's // auto-exports BY CONSTRUCTION, so the name can never resolve in ANY run — the assertion is // dead, and skipping it reads exactly like passing it. UnresolvedUnknown )
type VenueResolver ¶ added in v0.2026194.1605
type VenueResolver func(venue string) (exec Executor, env map[string]string, hasRuntime bool, err error)
VenueResolver retargets a per-step venue (the `on:` modifier / venue swap) to a host executor, its resolved variable env, and whether that env carries runtime state. venue→executor is the host check_venue atom and the env is host var resolution — both stay core; Runner drives the swap through this seam. An unknown venue returns a non-nil err.
type VerbResolver ¶ added in v0.2026191.2205
type VerbResolver interface {
// RunVerb resolves op's verb word and runs it, returning (result, true). (_, false)
// means no such verb is registered — the walk reports the op as an unknown-verb skip.
RunVerb(ctx context.Context, op *spec.Op) (spec.CheckResult, bool)
// RunProvisionAct runs a do:act state-provision verb's act (create/configure) and
// returns (result, true). (_, false) means the verb has no act path — the walk falls
// through to the assert dispatch (the handler IS the act for action verbs).
RunProvisionAct(ctx context.Context, op *spec.Op, verb string) (spec.CheckResult, bool)
}
VerbResolver is the verb-dispatch seam — the ONE thing the walk needs from the core provider registry. The core impl resolves the op's verb word and runs it (in-proc CheckVerbProvider fast path or out-of-process Invoke envelope), threading the live host CheckContext it owns; the walk never sees a provider type or the registry. VerbResolver's methods return spec.CheckResult (not the richer kit.CheckResult) — FLOOR-SLIM Unit 4: the host-side implementer (charly's hostVerbResolver) dispatches through the core-only provider registry down to package-main's own CheckVerbProvider family, which never sets DeadlineExceeded (an engine-internal retry signal kit's OWN dispatch loop, below, stamps AFTER the verb call returns) — so the interface boundary needs only the wire-portable base.
type VmSshStanza ¶ added in v0.2026186.739
type VmSshStanza struct {
Alias string // ssh-config Host alias (e.g. "charly-arch-vm"); unique within the fragment
Hostname string // IP/DNS ssh connects to ("127.0.0.1" for user-mode networking)
Port int // host-side port forwarded to the guest's :22
User string // guest account ssh logs in as
IdentityFile string // absolute private-key path
KnownHostsFile string // absolute per-VM known_hosts path
}
VmSshStanza captures the fields to render one ssh-config Host stanza for a VM.
type WalkOpts ¶
type WalkOpts struct {
// Shell overrides the detected venue login shell for the managed-block finalizer.
Shell ShellKind
// Home overrides the detected venue home. When empty WalkPlans probes `$HOME`.
Home string
}
WalkOpts tunes the walk. All fields optional — WalkPlans probes the venue for the shell + home it needs (the env.d managed-block finalizer) when they are not supplied.
Source Files
¶
- agent_forward.go
- apk_path.go
- append_unique.go
- atomic_write.go
- box_metadata.go
- build_activity.go
- builder.go
- builder_resolve.go
- calver.go
- calver_compare.go
- check_endpoint.go
- check_step_descriptors.go
- checklevel.go
- checkresult.go
- checkrun_seam.go
- checkvars.go
- checkvars_charlybin.go
- checkvars_expand.go
- console.go
- console_actions.go
- console_flow.go
- console_session.go
- container_image.go
- container_name.go
- container_probe.go
- deploy_name.go
- deploy_types.go
- deployconfig.go
- descent.go
- description_merge.go
- direct_deploy.go
- engine.go
- entrypoint.go
- env.go
- envfile_aliases.go
- eventually.go
- exec_aliases.go
- filelock.go
- grader.go
- hostrefs.go
- http_do.go
- http_fetch.go
- images.go
- install_dir.go
- install_ledger.go
- kit.go
- loader_classify.go
- loader_directives.go
- loader_discover.go
- local_image.go
- methodspec.go
- migrate_helpers.go
- migrate_support.go
- network.go
- never_hang_evidence.go
- planrun.go
- planrun_staged.go
- planspec.go
- planvalidate.go
- ports.go
- profile.go
- quadlet_paths.go
- refs_downloader.go
- refs_git.go
- remote_ref.go
- render.go
- report.go
- reverse_ops.go
- runner.go
- runtime_config.go
- scaffold.go
- scenario.go
- screen.go
- sidecar_naming.go
- sshconfig.go
- step_deps.go
- step_keyword.go
- system_info.go
- tagexpr.go
- transfer.go
- unless_exists.go
- vm_domain_lock.go
- vm_ssh_port.go
- vnc_bridge.go
- walk.go
- yaml.go