Documentation
¶
Overview ¶
directives.go — the loaderkit-local WALK-only directives: MaxIncludeDepth, namespaceAliasRe, and validateNamespaceAlias. The kind-blind document directives (ImportList/ImportEntry, DiscoverConfig/ScanSpec, anchorScanSpecs, docShape/classifyDoc) relocated to sdk/kit (loader_directives.go + loader_classify.go) so charly core AND sdk/loaderkit share ONE copy (R3) — see kit.ImportList / kit.DiscoverConfig / kit.AnchorScanSpecs / kit.ClassifyDoc.
discover.go — the K1 port of charly/unified.go's discover walk (ApplyDiscover / applyDiscoveredManifest): scans each `discover:` spec for directories carrying its manifest (via the shared kit.FindEntityDirs primitive) and PARSES every document each discovered manifest contains into a spec.DiscoveredManifest. Faithful port, MINUS the host-only candy-image lazy-ref registration + the per-node materialize FOLD (candy/plugin-loader's own Materializer seam, K1 unit 1 — the not-found policy lives there too now; only the ACTUAL registry resolve + provider dispatch stays host-side, boundary law clause M) — this file only WALKS + PARSES, exactly like the rest of loaderkit.
load_unified.go — the K1 keystone (task #24 unit 2) port of charly's TOP-LEVEL LoadUnified ORCHESTRATION out of charly core. This is the entry point every command (build/deploy/check/validate) calls to load a project's charly.yml — the sequence of steps (bootstrap phase, early + post-merge schema gate, kind-blind walk, registry materialize, venue flatten, member fold, descent stamp, the validation chain) now lives here, kind-blind, exactly as charly/unified.go's former inline body did. Every step that touches the provider registry, the build-vocabulary plugins, or a standing K5-final-decision core file (bundle_members.go's foldMembers/validateMembers) is a SEAM CALLBACK the host supplies via LoadSeams — the same injected-seam pattern spec.WalkSeams/ spec.MaterializeSeams already established (#46); LoadUnified itself never touches the registry. charly-core's own LoadUnified(dir) becomes a thin wrapper that builds a LoadSeams from its existing host-coupled functions and delegates here.
materialize.go — the K1 unit-1 port of charly's per-node kind-decode DISPATCH POLICY (charly/node_normalize.go's former normalizeNodeInto) out of charly core. Materialize decides what to do with ONE parsed entity node: if the provider registry resolves its discriminator, the host-supplied DecodeEntity seam callback has already folded it (clause M stays host-side, unchanged — provider_registry.go / provider_kind_invoke.go are the TRUE mechanism, this package never touches the registry); otherwise Materialize applies the NOT-FOUND policy purely from the host-threaded spec.Threaded snapshot (clause D) plus two small state-check callbacks — a recognized-but-unconnected external deploy substrate routes to the bundle builder, a declared- but-unconnected kind is deferred (mid re-entrant connect pass) or warned-and-skipped, and a truly unrecognized discriminator is a hard load error. This is the exact fallback branch normalizeNodeInto's "not found" arm ran, faithfully ported (the former in-proc KindProvider fast path is NOT ported — it was dead code: spec.KindWords is permanently empty, so no real provider has ever satisfied ClassKind + KindProvider; the DecodeEntity seam callback always dispatches via the JSON-envelope path now, exactly as it already did in production).
Package loaderkit is the importable form of charly's unified-config PARSE — the parse half of LoadUnified relocated out of charly core (P6). It decomposes one node-form YAML document into the generic, sdk-expressible spec.ParsedProject the host MATERIALIZES into the typed *UnifiedFile. Shared by the loader plugin candy (candy/plugin-loader, its OpLoad) and, during the transition, by charly core — the SAME parse, one copy (R3), the way sdk/kit is the one copy of the check walk.
The parse consults ONLY spec vocabulary (CUE-sourced) + yaml + host-threaded kind-recognition DATA (Threaded) — never the provider registry directly. The registry is core fabric; the host snapshots which words it recognizes (kinds / deploy substrates / structural / scalar-sugar primaries) into Threaded before the parse, and the re-entrant connect-then-reload re-parses with an updated snapshot. That keeps the parse a kind-blind mechanism (boundary law clause D).
walk.go — the K1 port of charly's unified-config loader ORCHESTRATION: the kind-blind WALK+PARSE half of LoadUnified (charly/unified.go) relocated out of charly core. Walk drives the import queue + discover + namespaced-import mounts and PARSES every document (via the existing loaderkit.ParseDoc, P6) into a generic spec.LoadedProject envelope — it does NO materialize (registry kind-decode) and NO merge (root-wins field folding) into a typed *UnifiedFile; the host replays materialize+merge over the returned spec.LoadedProject to reconstruct that, exactly as it did inline before.
Everything registry-coupled or host-coupled (the parse pre-scan + connect-declared-kind-plugins side effects, the #NodeDoc CUE validate-before-execute gate, remote-ref resolution + the project-repo cache, and the repo-identity cycle-break) is a SEAM CALLBACK the host supplies via spec.WalkSeams (#46 — the seam contract lives in sdk/spec, not here, so charly core references it without importing this package) — Walk itself calls the seam and never does the coupled work directly (boundary law clause D: Walk consults host-threaded DATA, never the provider registry).
Faithful-port mapping (see charly/unified.go + charly/ns_identity.go):
LoadUnified (the walk portion only) → Walk loadUnifiedInto → (*walker).walkFile mergeUnifiedDocs (the parse portion) → (*walker).parseDocs (materialize/mergeUnified excluded) loadNamespaceCached → (*walker).walkNamespace the per-project "load + discover" body → (*walker).walkProject ApplyDiscover/… → discover.go
The kind-blind document DIRECTIVES (kit.ImportList/kit.DiscoverConfig/kit.ClassifyDoc/ kit.FindEntityDirs/…) live in sdk/kit (loader_directives.go/loader_classify.go/ loader_discover.go), shared with charly core (R3) — this package keeps only its own walk-scoped namespace-alias validation (directives.go).
Index ¶
- Constants
- func DecodePluginKindMap[T any](uf *UnifiedFile, kind string) map[string]*T
- func EncodeInlineCandy(il *InlineCandy) json.RawMessage
- func GateSchemaVersion(root, version string) error
- func GitRemoteIdentity(dir string) string
- func Materialize(pn spec.ParsedNode, t spec.Threaded, seams spec.MaterializeSeams, ...) error
- func NormalizeGitRemoteURL(raw string) string
- func NormalizeRepoIdentity(s string) string
- func NormalizeRepoSpec(spc string) (repoPath, version string)
- func NormalizeV4Aliases(u *UnifiedFile)
- func ParseDoc(doc *yaml.Node, t spec.Threaded) (directives map[string]*yaml.Node, pp spec.ParsedProject, err error)
- func QualifyRemoteSiblingDeps(repoPath, subPathPrefix string, refs *spec.CandyRefs)
- func RepoIdentity(ref, baseDir string) string
- func ResolvePluginKindViaPlugin[T any](uf *UnifiedFile, kind string, resolve func(json.RawMessage) (*T, error)) map[string]*T
- func RootRepoIdentity(dir string) string
- func RunDiscover(rootDir string, specs []kit.ScanSpec, seams spec.WalkSeams) ([]spec.DiscoveredManifest, error)
- func ScanCandyManifest(path, name, manifestName string, ...) (spec.CandyModel, spec.CandyView, spec.CandyRefs, error)
- func ScanInlineCandy(name, sourceDir string, ly *spec.CandyYAML) (spec.CandyModel, spec.CandyView, spec.CandyRefs)
- func ScanRemoteCandy(repoDir, repoPath string, wantRefs map[string]bool, ...) (map[string]spec.ScannedCandy, error)
- func Walk(rootDir string, rootData []byte, rootIdentity string, seams spec.WalkSeams) (spec.LoadedProject, error)
- type InlineCandy
- type LoadSeams
- type UnifiedFile
- func (uf *UnifiedFile) Android() map[string]json.RawMessage
- func (uf *UnifiedFile) BoxConfig(name string) (spec.BoxConfig, bool)
- func (uf *UnifiedFile) BoxNames() []string
- func (uf *UnifiedFile) CheckBeds() map[string]spec.BundleNode
- func (uf *UnifiedFile) HasBox(name string) bool
- func (uf *UnifiedFile) K8s() map[string]json.RawMessage
- func (uf *UnifiedFile) Local() map[string]json.RawMessage
- func (uf *UnifiedFile) Pod() map[string]json.RawMessage
- func (uf *UnifiedFile) ProjectBundleConfig() *deploykit.BundleConfig
- func (uf *UnifiedFile) ProjectConfig() *spec.Config
- func (uf *UnifiedFile) SetBox(name string, b spec.BoxConfig)
- func (uf *UnifiedFile) SetCandy(name string, il *InlineCandy)
- func (uf *UnifiedFile) VM() map[string]json.RawMessage
Constants ¶
const MaxIncludeDepth = 8
MaxIncludeDepth caps recursive include resolution. A cycle or excessive depth raises a clear error with the offending file path.
Variables ¶
This section is empty.
Functions ¶
func DecodePluginKindMap ¶ added in v0.2026206.1046
func DecodePluginKindMap[T any](uf *UnifiedFile, kind string) map[string]*T
DecodePluginKindMap reconstructs the typed name-keyed map[string]*T for a plugin kind from uf.PluginKinds[kind] (each body the canonical spec.T JSON the kind plugin's Invoke produced) via a PLAIN json.Unmarshal — no plugin OpResolve round-trip, for a kind whose body is already self-contained (Builder). Compare ResolvePluginKindViaPlugin above, its sibling for kinds that DO need a plugin-side resolve leg. A bad entry is skipped rather than poisoning the whole vocabulary. Returns nil when the kind has no entities.
func EncodeInlineCandy ¶ added in v0.2026206.1046
func EncodeInlineCandy(il *InlineCandy) json.RawMessage
EncodeInlineCandy marshals a loader InlineCandy into its opaque body.
func GateSchemaVersion ¶ added in v0.2026206.1046
GateSchemaVersion enforces the load-time schema-version contract: a config NEWER than this binary supports → "update charly"; an OLDER/absent/non-CalVer version → the `charly migrate` hint. Shared by the early pre-parse gate (root's raw version) and the post-merge gate (merged version) so both speak identically. Pure — kit.ParseCalVer/kit.LatestSchemaVersion carry no registry coupling.
func GitRemoteIdentity ¶ added in v0.2026198.2057
GitRemoteIdentity returns the normalized `host/owner/repo` identity of dir's git `origin` remote, or "" when dir is not a git repo / has no origin / git is unavailable.
func Materialize ¶ added in v0.2026206.837
func Materialize(pn spec.ParsedNode, t spec.Threaded, seams spec.MaterializeSeams, acc *spec.MaterializedProject) error
Materialize folds ONE parsed entity node into acc via the registered Materializer plugin's not-found policy, calling back into the host-supplied seams for everything registry-coupled.
func NormalizeGitRemoteURL ¶ added in v0.2026198.2057
NormalizeGitRemoteURL strips the scheme / `git@` / `.git` decorations from a git remote URL, leaving `host/owner/repo`. scp-style (`git@host:owner/repo`) and scheme URLs (`https://`, `ssh://`, `git://`, with optional `user@`) are both handled. A value already in `host/owner/repo` (or bare `owner/repo`) form passes through unchanged.
func NormalizeRepoIdentity ¶ added in v0.2026198.2057
NormalizeRepoIdentity normalizes an explicit `repo:` value (which may be a full git URL, an scp-style ref, or a bare `owner/repo`) to the `host/owner/repo` form ParseRemoteRef produces — so an explicit declaration and a remote `@`-ref compare equal. Reuses NormalizeRepoSpec's bare-`owner/repo` → github.com rule.
func NormalizeRepoSpec ¶ added in v0.2026198.2057
NormalizeRepoSpec turns a user-supplied --repo spec into a (repoPath, version) pair suitable for a repo-cache download. Spec formats:
"default" → (spec.DefaultProjectRepo, "")
"owner/repo" → ("github.com/owner/repo", "")
"owner/repo@ref" → ("github.com/owner/repo", "ref")
"host/owner/repo[@ref]" → used literally
An empty version means "resolve to default branch at lookup time".
func NormalizeV4Aliases ¶ added in v0.2026206.1046
func NormalizeV4Aliases(u *UnifiedFile)
NormalizeV4Aliases — RETIRED by the field-singular cutover (2026-05). Dual Images/ImageSingular and Deploys/DeploySingular fields collapsed into single canonical singular fields with matching yaml tags. Function kept as a no-op so external callers don't break; remove on next refactor pass.
func ParseDoc ¶
func ParseDoc(doc *yaml.Node, t spec.Threaded) (directives map[string]*yaml.Node, pp spec.ParsedProject, err error)
ParseDoc decomposes a node-form document mapping into its reserved directives + the generic spec.ParsedProject (its top-level entity nodes, each with the opaque JSON body the host materializes). Faithful port of core's parseNodeTree + genericNodeToParsed.
func QualifyRemoteSiblingDeps ¶ added in v0.2026198.2057
QualifyRemoteSiblingDeps records, for a freshly-scanned remote candy, the fully-qualified "<repo>/<subpathprefix><dep>" map key of each plain-name require:/candy:/bake_plugin: dep — the same form the fetched-sibling scan keys under. It sets each ref's resolved key (CandyRefEntry.Resolved) and leaves CandyRefEntry.Raw intact, so the graph resolves on .Bare() (qualified) while the transitive fetch loop still keys on the original .Raw plain name. @-ref deps are left untouched — their bare path already resolves directly. Ported verbatim from the pre-move charly/layers.go qualifyRemoteSiblingDeps, retargeted at the CandyRefs carrier (the live *Candy's Require/IncludedCandy/BakePlugin fields this mutated in place pre-move).
func RepoIdentity ¶ added in v0.2026198.2057
RepoIdentity returns the canonical repo identity of an import ref, or "" when it can't be determined (in which case the loader degrades to version-keyed behavior). A remote `@host/org/repo[/sub]:ver` ref yields `host/org/repo` directly (no fetch, no git); a local path yields the git `origin` identity of the target directory.
func ResolvePluginKindViaPlugin ¶ added in v0.2026206.1046
func ResolvePluginKindViaPlugin[T any](uf *UnifiedFile, kind string, resolve func(json.RawMessage) (*T, error)) map[string]*T
ResolvePluginKindViaPlugin projects uf.PluginKinds[kind] (opaque bodies) into *T value envelopes via resolve, a per-body plugin OpResolve leg — the ONE shared loop every "resolve a plugin-kind catalog through its OpResolve leg" accessor uses (charly-core's Distros/Builders/ resolveResources/resolveAndroids/resolveInits each supply their own registry-coupled resolve callback; this loop itself touches no registry). A bad entry is skipped rather than poisoning the whole vocabulary.
func RootRepoIdentity ¶ added in v0.2026198.2057
RootRepoIdentity determines the local root project's own repo identity for cycle-break registration. An explicit `repo:` field in charly.yml is authoritative; otherwise it falls back to the `git remote origin` identity of the working tree. Returns "" when neither is available (the loader then behaves exactly as before — version-keyed, no self-identity short-circuit).
func RunDiscover ¶ added in v0.2026206.1046
func RunDiscover(rootDir string, specs []kit.ScanSpec, seams spec.WalkSeams) ([]spec.DiscoveredManifest, error)
RunDiscover is the STANDALONE discover-only entry point (K1 keystone, task #24 unit 3): charly's ApplyDiscover (unified.go) calls this directly — reusing the SAME runDiscover/ parseDiscoveredManifest walker mechanism the whole-project Walk drives internally for its own depth-0 discover pass — rather than duplicating the walk+parse logic. Bypasses the spec.ProjectWalker plugin-swap indirection deliberately: ApplyDiscover has never gone through the whole-project walker (it talks to the parser/threaded seam primitives directly, mirroring Walk's OWN internal discover call), so a custom loader plugin overriding Walk's discover behavior was never honored by ApplyDiscover before this move either — this preserves that pre-existing scope exactly.
func ScanCandyManifest ¶ added in v0.2026198.2057
func ScanCandyManifest(path, name, manifestName string, parseDoc func(path string) (*spec.CandyYAML, error)) (spec.CandyModel, spec.CandyView, spec.CandyRefs, error)
ScanCandyManifest scans a single candy DIRECTORY (the `from:`-directory / legacy-discovered-candy path) and returns its two resolved envelope views. Named distinctly from the ESTABLISHED exported charly.ScanCandy(dir) (the whole-project scan-all-candies entry point) to avoid confusion between the two similarly-shaped-but-different scans while both exist side by side during the cutover. parseDoc is the injected per-document parse seam (charly's parseCandyYAML — registry-coupled, so it stays host-side; see the CandyScanner interface doc in sdk/spec/loader_seam.go).
func ScanInlineCandy ¶ added in v0.2026198.2057
func ScanInlineCandy(name, sourceDir string, ly *spec.CandyYAML) (spec.CandyModel, spec.CandyView, spec.CandyRefs)
ScanInlineCandy builds the two resolved envelope views + the rich pre-qualification refs for a candy declared INLINE in a unified charly.yml (no separate manifest file — ly is already the parsed body). sourceDir is the charly.yml's own directory (an inline candy's SourceDir always equals its declaring file's dir). Mirrors the pre-move charly/unified.go synthesizeInlineCandy, which called the SAME populateCandyFromYAML + fs-probe pair scanCandy did — the two paths can never drift because they share this one function.
func ScanRemoteCandy ¶ added in v0.2026198.2057
func ScanRemoteCandy(repoDir, repoPath string, wantRefs map[string]bool, parseDoc func(path string) (*spec.CandyYAML, error)) (map[string]spec.ScannedCandy, error)
ScanRemoteCandy scans specific candies out of a downloaded remote repository directory — only the bare refs in wantRefs (each "github.com/org/repo/candy/name" form, keyed by that same bare ref in the returned map). Ported verbatim from the pre-move charly/layers.go ScanRemoteCandy: for each wanted ref, ScanCandyManifest the candy dir, then set the resulting CandyView's Remote/RepoPath/SubPathPrefix (the post-scan "construct-then-mutate" step scan-time cannot do itself — a candy doesn't know it's REMOTE until the fetch layer resolves it there) and qualify its plain-name sibling deps (QualifyRemoteSiblingDeps) so the dependency graph + validator can resolve a remote candy's transitive deps against siblings pulled from the same repo, without per-call-site repo-path plumbing.
func Walk ¶ added in v0.2026194.1400
func Walk(rootDir string, rootData []byte, rootIdentity string, seams spec.WalkSeams) (spec.LoadedProject, error)
Walk walks a project rooted at rootDir and returns its kind-blind parse envelope. rootData is the (possibly bootstrap-transformed) bytes of the root charly.yml — used for the root file instead of re-reading; pass nil for a namespace child (read from disk). rootIdentity is the root project's own repo identity (the host's rootRepoIdentity), seeded into the cycle-break so a transitive self-import resolves to the in-progress root — mirrors LoadUnified seeding loadingRepos[rootRepoIdentity(dir)] = merged BEFORE the walk starts.
Types ¶
type InlineCandy ¶ added in v0.2026206.1046
type InlineCandy struct {
From string `yaml:"from,omitempty" json:"from,omitempty"`
spec.CandyYAML `yaml:",inline"`
// Manifest carries the discovery manifest filename for a `From:` directory so the candy
// scan reads the right file. Not YAML-authored; carried through the opaque candy-map fold
// via JSON, hence exported + json-tagged.
Manifest string `yaml:"-" json:"__manifest,omitempty"`
}
InlineCandy is a candy declared inline in the unified file's `candy:` map. Mutually exclusive options: `from:` points at a directory to scan (the loader's CandyScanner seam), OR the inline body defines the candy (same fields as the candy manifest, flattened via yaml:",inline").
func DecodeInlineCandy ¶ added in v0.2026206.1046
func DecodeInlineCandy(raw json.RawMessage) (*InlineCandy, bool)
DecodeInlineCandy decodes one opaque layer body into the InlineCandy loader shape.
type LoadSeams ¶ added in v0.2026206.1046
type LoadSeams struct {
// RunBootstrapPhase invokes every registered bootstrap-phase plugin
// (sdk.PhaseBootstrap) on the raw root config bytes, returning the
// (possibly transformed) bytes. A no-op seam returns data unchanged.
RunBootstrapPhase func(data []byte) []byte
// WalkProject runs the kind-blind import/discover/namespace walk (the
// registered spec.ProjectWalker, reached via the host's spec.WalkSeams) and
// returns the generic spec.LoadedProject envelope — no materialize, no merge.
WalkProject func(dir string, rootData []byte) (spec.LoadedProject, error)
// MaterializeLoadedProject replays the host's per-document/per-namespace
// MATERIALIZE + root-wins MERGE over the walk envelope, reconstructing merged
// (registry kind-decode via the registered spec.Materializer).
MaterializeLoadedProject func(lp *spec.LoadedProject, merged *UnifiedFile, byID map[int64]*UnifiedFile) error
// FlattenBundleVenues stamps every plan step's execution venue from its
// bundle-tree position and hoists member/child steps into the root Plan.
FlattenBundleVenues func(uf *UnifiedFile) error
// FoldMembers copies every deploy node's `peer:` entries into the Bundle map
// as top-level addressable entries. Its relocation (if any) is a FINAL/K5
// decision (bundle_members.go) — it stays host-resident, reached only via
// this seam.
FoldMembers func(uf *UnifiedFile) error
// StampBundleDescents stamps every deploy node's venue-hop descent
// descriptor (P9 DeployTraits, resolved from the provider registry).
StampBundleDescents func(uf *UnifiedFile)
// ValidateEphemeral auto-promotes disposable:true on ephemeral entries and
// validates the ephemeral / vm-naming invariants.
ValidateEphemeral func(uf *UnifiedFile) error
// ValidateCheckBeds enforces the kind:check bed invariants (disposable,
// cross-ref, external-substrate recognition via the provider registry).
ValidateCheckBeds func(uf *UnifiedFile) error
// ValidateAndroidDevices enforces the kind:android box⊻adb XOR (resolves
// android templates via the plugin-substrate provider).
ValidateAndroidDevices func(uf *UnifiedFile) error
// ValidateMembers enforces the member-specific invariants beyond the generic
// deploy validation. Paired with FoldMembers under the same FINAL/K5 ruling.
ValidateMembers func(uf *UnifiedFile) error
// ValidatePreemptible validates preemptible/requires_exclusive/requires_shared
// across the deploy map, including the resource-vocabulary cross-check
// (resolves the `resource:` plugin kind via the provider registry).
ValidatePreemptible func(uf *UnifiedFile) error
}
LoadSeams bundles every registry-coupled or standing-core-resident step LoadUnified's orchestration calls out to. A nil field panics on use — the host wrapper (charly/unified.go) is the SOLE constructor and always populates every field before calling LoadUnified.
type UnifiedFile ¶ added in v0.2026206.1046
type UnifiedFile struct {
Version string `yaml:"version,omitempty" json:"version,omitempty"`
// Repo is this project's canonical repo identity (e.g. "github.com/opencharly/charly").
// Optional; only meaningful on the ROOT file. See repo_identity.go.
Repo string `yaml:"repo,omitempty" json:"repo,omitempty"`
// Import is the SINGLE composition statement. A list whose items are either a bare string
// (flat import into THIS root namespace) or a single-key map `alias: ref` (a namespaced
// child import). See ImportList (directives.go).
Import kit.ImportList `yaml:"import,omitempty" json:"import,omitempty"`
Discover kit.DiscoverConfig `yaml:"discover,omitempty" json:"discover,omitempty"`
// Defaults carries the `defaults:` block (BoxConfig-shaped inheritance defaults).
Defaults spec.BoxConfig `yaml:"defaults,omitempty" json:"defaults,omitempty"`
// Box is the generic kind-keyed IMAGE map (P6): name → opaque marshaled spec.BoxConfig.
Box spec.BoxMap `yaml:"box,omitempty" json:"box,omitempty"`
// Candy is the generic kind-keyed LAYER map: name → opaque marshaled InlineCandy.
Candy map[string]json.RawMessage `yaml:"candy,omitempty" json:"candy,omitempty"`
// Bundle is the flat name-keyed deploy map (the canonical `deploy:` surface).
Bundle map[string]spec.BundleNode `yaml:"deploy,omitempty" json:"deploy,omitempty"`
Provides *deploykit.ProvidesConfig `yaml:"provides,omitempty" json:"provides,omitempty"`
// PluginKinds holds entities of KINDS contributed by plugins (a kind the core has no typed
// map for). NAME-KEYED: kind word → entity NAME → canonical body (opaque JSON). Built-in
// kinds decode into their typed maps above. Host-internal — never serialized.
PluginKinds map[string]map[string]json.RawMessage `yaml:"-" json:"-"`
// Namespaces holds child namespaces mounted by namespaced `import:` entries (alias →
// fully-resolved isolated UnifiedFile). NOT authored directly — populated by the
// materialize pass. Entries are referenced qualified, e.g. `base: cachyos.cachyos`.
Namespaces map[string]*UnifiedFile `yaml:"-"`
// RootDir is this UnifiedFile's OWN base directory — the dir its root document's SrcDir
// names. Set once per materialize, for both the top-level project and each mounted
// namespace. Empty for a project-less / synthetic UnifiedFile.
RootDir string `yaml:"-"`
}
UnifiedFile is the full schema of a single unified-format YAML document. Every field is optional — a file with only `distro:` is valid (typical for the embedded build vocabulary); a file with only `deploy:` is valid; etc.
func LoadUnified ¶ added in v0.2026206.1046
func LoadUnified(dir string, seams LoadSeams) (*UnifiedFile, bool, error)
LoadUnified reads <dir>/charly.yml and returns the fully loaded, validated *UnifiedFile — the kind-blind orchestration ported verbatim from charly's former inline LoadUnified body. Every registry-coupled or standing-core- resident step is reached through seams; LoadUnified itself never imports or touches the provider registry.
func (*UnifiedFile) Android ¶ added in v0.2026206.1046
func (uf *UnifiedFile) Android() map[string]json.RawMessage
func (*UnifiedFile) BoxConfig ¶ added in v0.2026206.1046
func (uf *UnifiedFile) BoxConfig(name string) (spec.BoxConfig, bool)
BoxConfig decodes the authored image config for name; ok=false when absent.
func (*UnifiedFile) BoxNames ¶ added in v0.2026206.1046
func (uf *UnifiedFile) BoxNames() []string
BoxNames returns the image names, sorted.
func (*UnifiedFile) CheckBeds ¶ added in v0.2026206.1046
func (uf *UnifiedFile) CheckBeds() map[string]spec.BundleNode
CheckBeds returns the disposable R10 beds keyed by name. In the unified node-form model a bed IS a `disposable: true` bundle, so the bed set is derived directly from the disposable bundles in the Bundle map. Members are instruments (brought up alongside a driver), never standalone beds. Single enumeration source for `charly check run <bed>` (and the /verify-beds fan-out).
func (*UnifiedFile) HasBox ¶ added in v0.2026206.1046
func (uf *UnifiedFile) HasBox(name string) bool
HasBox reports whether an image named name is present.
func (*UnifiedFile) K8s ¶ added in v0.2026206.1046
func (uf *UnifiedFile) K8s() map[string]json.RawMessage
func (*UnifiedFile) Local ¶ added in v0.2026206.1046
func (uf *UnifiedFile) Local() map[string]json.RawMessage
func (*UnifiedFile) Pod ¶ added in v0.2026206.1046
func (uf *UnifiedFile) Pod() map[string]json.RawMessage
func (*UnifiedFile) ProjectBundleConfig ¶ added in v0.2026206.1046
func (uf *UnifiedFile) ProjectBundleConfig() *deploykit.BundleConfig
ProjectBundleConfig returns the *deploykit.BundleConfig equivalent (deployments: section of the authored file, independent of any per-machine ~/.config/charly/charly.yml, which remains loaded separately by deploykit.LoadBundleConfig).
func (*UnifiedFile) ProjectConfig ¶ added in v0.2026206.1046
func (uf *UnifiedFile) ProjectConfig() *spec.Config
ProjectConfig returns the *spec.Config equivalent of uf (the box config view).
func (*UnifiedFile) SetBox ¶ added in v0.2026206.1046
func (uf *UnifiedFile) SetBox(name string, b spec.BoxConfig)
SetBox stores an authored image config under name (marshaling it opaque).
func (*UnifiedFile) SetCandy ¶ added in v0.2026206.1046
func (uf *UnifiedFile) SetCandy(name string, il *InlineCandy)
SetCandy stores a layer under name (marshaling it opaque).
func (*UnifiedFile) VM ¶ added in v0.2026206.1046
func (uf *UnifiedFile) VM() map[string]json.RawMessage
VM/Pod/K8s/Local/Android are DERIVED accessors over uf.PluginKinds[disc] — the 5 standalone-substrate-TEMPLATE kinds fold into PluginKinds generically (no per-kind-word switch). Each returns the opaque name→body map for its kind (nil when none configured); the kernel never decodes the bodies itself — consuming PLUGINS decode a body into the concrete kind they need.