Documentation
¶
Overview ¶
Package pkg provides package management actions for the operation graph.
Index ¶
- Constants
- type MutationKind
- type Observation
- type Provider
- func (p *Provider) CompensateInstall(activation *op.ActivationRecord, stack *op.RecoveryStack) error
- func (p *Provider) CompensatePackageMutation(activationRecord *op.ActivationRecord, receipt *Receipt) error
- func (p *Provider) CompensateRemove(activation *op.ActivationRecord, stack *op.RecoveryStack) error
- func (p *Provider) CompensateUpgrade(activation *op.ActivationRecord, stack *op.RecoveryStack) error
- func (p *Provider) Install(activationRecord *op.ActivationRecord, packages []*Resource, ...) (result []*Resource, stack *op.RecoveryStack, err error)
- func (p *Provider) Installed(name *Resource) (bool, error)
- func (p *Provider) NotInstalled(name *Resource) (bool, error)
- func (p *Provider) Observe(resource *Resource) (*Observation, error)
- func (p *Provider) Remove(activationRecord *op.ActivationRecord, packages []*Resource, ...) (result []*Resource, stack *op.RecoveryStack, err error)
- func (p *Provider) Update() error
- func (p *Provider) Upgrade(activationRecord *op.ActivationRecord, packages []*Resource, ...) (result []*Resource, stack *op.RecoveryStack, err error)
- func (p *Provider) VersionGTE(name *Resource, version string) (bool, error)
- type Receipt
- type Resource
- func (r *Resource) Addressing() op.AddressingMode
- func (*Resource) CanConvertFrom(source reflect.Type) bool
- func (*Resource) ConvertFrom(value any) (any, error)
- func (r *Resource) Digest() (op.Digest, error)
- func (r *Resource) Equal(other any) bool
- func (r *Resource) Etag() (string, error)
- func (r *Resource) String() string
- func (r *Resource) UnmarshalJSON(data []byte) error
- func (r *Resource) UnmarshalText(text []byte) error
- func (r *Resource) UnmarshalYAML(unmarshal func(any) error) error
Constants ¶
const ( Install op.ActionName = "pkg.install" Installed op.ActionName = "pkg.installed" NotInstalled op.ActionName = "pkg.not_installed" Observe op.ActionName = "pkg.observe" Remove op.ActionName = "pkg.remove" Update op.ActionName = "pkg.update" Upgrade op.ActionName = "pkg.upgrade" VersionGTE op.ActionName = "pkg.version_gte" )
Action-name constants for the pkg provider's plan-mode actions.
Each constant is the short dotted action label its method dispatches under. Pass these to plan.Plan, op.ReceiverRegistry().BuildAction, RuntimeEnvironment.ActionByName, or WithActionNamed in place of a string literal so a typo is a compile error and rename / find-references work through the constant.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type MutationKind ¶
type MutationKind string
MutationKind identifies the package mutation a Receipt records, so Provider.CompensatePackageMutation can invert it: remove a newly-installed package, restore a pre-existing one's prior version, reinstall a removed package, or best-effort restore an upgraded package's prior version.
const ( // MutationInstall records an install; its undo removes a newly-installed package, or restores a pre-existing one's // prior version when the install drifted it. MutationInstall MutationKind = "install" // MutationRemove records a removal; its undo reinstalls a package that was present before. MutationRemove MutationKind = "remove" // MutationUpgrade records an upgrade; its undo best-effort restores the package's prior version. MutationUpgrade MutationKind = "upgrade" )
type Observation ¶
type Observation struct {
op.ObservationBase
// Version is the version string the platform's package manager reports for the package at
// observation time. Empty when `Exists` is false.
Version string
}
Observation captures the runtime-observed state of a *Resource (a host package) at the moment it was observed.
Distinct from Resource, which carries identity (the purl URI, `Name`, `Type`). An observation is a point-in-time metadata snapshot record — not a Resource, never cataloged — whose identity comes from the resource it references (op.ObservationBase.OfResource, by pointer value). It embeds op.ObservationBase (the back-link + op.ObservationBase.Exists) and adds the package-specific measurement field: `Version`.
func NewObservation ¶
func NewObservation(ofResource *Resource, exists bool, version string) *Observation
NewObservation constructs a *Observation anchored to the resource it observes.
Parameters:
- `ofResource`: the *Resource this observation is of. Must be non-nil (asserted by op.NewObservationBase).
- `exists`: true when the package was installed at observation time.
- `version`: the installed version reported by the package manager.
Returns:
- `*Observation`: the constructed observation.
func (*Observation) String ¶
func (o *Observation) String() string
String returns a debug-oriented single-line representation of the observation.
Returns:
- `string`: `pkg.Observation{of=<OfResource.URI()>, exists=<bool>, version=<string>}`.
type Provider ¶
type Provider struct {
op.ProviderBase
}
Provider is a thin veneer over the platform's Composite package-manager router.
It carries no convergence policy of its own: each verb projects its *Resource slice into a platform.PURL slice, calls the router once, and adapts the router's per-package platform.Receipt slice into the provider's *Receipt compensation state. All convergence and verification live in the platform's leaf drivers.
+devlore:access=planned
func NewProvider ¶
func NewProvider(runtimeEnvironment *op.RuntimeEnvironment) *Provider
NewProvider constructs a package-management Provider bound to the given runtime environment.
Parameters:
- `runtimeEnvironment`: the runtime environment that supplies the platform abstraction and status sink.
Returns:
- `*Provider`: the initialized provider.
func (*Provider) CompensateInstall ¶
func (p *Provider) CompensateInstall(activation *op.ActivationRecord, stack *op.RecoveryStack) error
CompensateInstall reverses an install by unwinding its recovery stack.
Each entry is a self-describing *Receipt naming Provider.CompensatePackageMutation, so unwinding removes each newly-installed package and restores any pre-existing one whose version the install drifted.
Parameters:
- `activation`: the per-dispatch record; supplies the *op.RuntimeEnvironment passed to op.RecoveryStack.Unwind.
- `stack`: the recovery stack Provider.Install returned as its compensator; a nil stack returns nil.
Returns:
- `error`: the joined errors from the per-package compensations, or nil when all succeed.
func (*Provider) CompensatePackageMutation ¶
func (p *Provider) CompensatePackageMutation(activationRecord *op.ActivationRecord, receipt *Receipt) error
CompensatePackageMutation inverts one package mutation, dispatching on the receipt's MutationKind: remove a newly-installed package or restore a pre-existing one's drifted version (install), reinstall a removed package (remove), or best-effort restore an upgraded package's prior version (upgrade). It is the single undo named by every package receipt; the verb companions (Provider.CompensateInstall / Provider.CompensateRemove / Provider.CompensateUpgrade) just unwind the stack of these.
Parameters:
- `activationRecord`: the dispatch activation (the required floor for compensating actions — step 27).
- `receipt`: the package *Receipt to invert; a nil receipt or nil resource is a no-op.
Returns:
- `error`: a missing platform, an unknown kind, or any removal / reinstall failure.
func (*Provider) CompensateRemove ¶
func (p *Provider) CompensateRemove(activation *op.ActivationRecord, stack *op.RecoveryStack) error
CompensateRemove reverses a removal by unwinding its recovery stack — each entry reinstalls a package that was present before.
Parameters:
- `activation`: the per-dispatch record; supplies the *op.RuntimeEnvironment passed to op.RecoveryStack.Unwind.
- `stack`: the recovery stack Provider.Remove returned as its compensator; a nil stack returns nil.
Returns:
- `error`: the joined errors from the per-package compensations, or nil when all succeed.
func (*Provider) CompensateUpgrade ¶
func (p *Provider) CompensateUpgrade(activation *op.ActivationRecord, stack *op.RecoveryStack) error
CompensateUpgrade reverses an upgrade by unwinding its recovery stack — each entry best-effort restores its package's prior version.
Parameters:
- `activation`: the per-dispatch record; supplies the *op.RuntimeEnvironment passed to op.RecoveryStack.Unwind.
- `stack`: the recovery stack Provider.Upgrade returned as its compensator; a nil stack returns nil.
Returns:
- `error`: the joined errors from the per-package compensations, or nil when all succeed.
func (*Provider) Install ¶
func (p *Provider) Install( activationRecord *op.ActivationRecord, packages []*Resource, kwargs map[string]any, ) (result []*Resource, stack *op.RecoveryStack, err error)
Install installs each package via the platform's Composite router.
Parameters:
- `activationRecord`: the dispatch activation (the required floor for compensable actions — step 27).
- `packages`: package resources to install, each carrying its requested version.
- `kwargs`: opaque native-installer flags passed through to the routed leaf (e.g. `cask`).
Returns:
- `result`: the input packages, each with Type set to the purl type of the leaf that handled it.
- `stack`: a op.RecoveryStack carrying one self-describing *Receipt per package, in input order, so a failed run unwinds it in reverse — each receipt routes to Provider.CompensatePackageMutation.
- `error`: non-nil if no packages were specified, no platform is available, or any package failed to install.
func (*Provider) Installed ¶
Installed reports whether the named package is installed, querying the router by purl.
Parameters:
- `name`: the package resource to check.
Returns:
- `bool`: true when the package is installed.
- `error`: non-nil when no platform is available.
func (*Provider) NotInstalled ¶
NotInstalled reports whether the named package is not installed, querying the router by purl.
Parameters:
- `name`: the package resource to check.
Returns:
- `bool`: true when the package is not installed.
- `error`: non-nil when no platform is available.
func (*Provider) Observe ¶
func (p *Provider) Observe(resource *Resource) (*Observation, error)
Observe captures the runtime-observed state of `resource` as an *Observation.
Asks the platform's Composite router for the installed version of the package identified by `resource`. When a platform exists and the router reports a non-empty version, the Observation carries `Exists=true` and the version string; otherwise it carries `Exists=false`.
Parameters:
- `resource`: the *Resource whose installed state to observe.
Returns:
- `*Observation`: the constructed observation; never nil.
- `error`: always nil — a missing platform or an uninstalled package is a valid observation, not a failure; the error return keeps the announced fallible-action shape.
func (*Provider) Remove ¶
func (p *Provider) Remove( activationRecord *op.ActivationRecord, packages []*Resource, kwargs map[string]any, ) (result []*Resource, stack *op.RecoveryStack, err error)
Remove removes each package via the platform's Composite router.
Parameters:
- `activationRecord`: the dispatch activation (the required floor for compensable actions — step 27).
- `packages`: package resources to remove.
- `kwargs`: opaque native-installer flags passed through to the routed leaf.
Returns:
- `result`: the input packages, each with Type set to the purl type of the leaf that handled it.
- `stack`: a op.RecoveryStack carrying one self-describing *Receipt per package, in input order.
- `error`: non-nil if no packages were specified, no platform is available, or any package failed to remove.
func (*Provider) Update ¶
Update forces an immediate index refresh on every leaf via the platform's Composite router.
Returns:
- `error`: aggregated per-leaf refresh failures, or non-nil when no platform is available.
func (*Provider) Upgrade ¶
func (p *Provider) Upgrade( activationRecord *op.ActivationRecord, packages []*Resource, kwargs map[string]any, ) (result []*Resource, stack *op.RecoveryStack, err error)
Upgrade upgrades each package to the latest available version via the platform's Composite router.
Parameters:
- `activationRecord`: the dispatch activation (the required floor for compensable actions — step 27).
- `packages`: package resources to upgrade.
- `kwargs`: opaque native-installer flags passed through to the routed leaf.
Returns:
- `result`: the input packages, each with Type set to the purl type of the leaf that handled it.
- `stack`: a op.RecoveryStack carrying one self-describing *Receipt per package, in input order.
- `error`: non-nil if no packages were specified, no platform is available, or any package failed to upgrade.
func (*Provider) VersionGTE ¶
VersionGTE reports whether the installed version of `name` is greater than or equal to `version`.
Parameters:
- `name`: the package resource to check.
- `version`: the minimum version string to compare against.
Returns:
- `bool`: true when the installed version is non-empty and >= `version`.
- `error`: non-nil when no platform is available.
type Receipt ¶
type Receipt struct {
op.ReceiptBase
// Manager is the purl type of the leaf that handled the package.
Manager string
// InstalledBefore records whether the package was present before the action.
InstalledBefore bool
// PreviousVersion is the version observed before the action.
PreviousVersion string
// contains filtered or unexported fields
}
Receipt holds the per-package compensation state Provider.CompensatePackageMutation needs to undo one package mutation.
The embedded op.ReceiptBase carries the affected Resource and the opaque op.ReceiptBase.TransactionID minted at op.ReceiptBase.Commit. One Receipt records one package: `kind` is the mutation it undoes, `Manager` is the purl type of the leaf that handled it, `InstalledBefore` records whether the package was present before the action (so unwind does not remove a package the user already had), and `PreviousVersion` is the version observed before the action (so an upgrade or a drifted install can be best-effort restored). A multi-package verb pushes one Receipt per package onto a op.RecoveryStack.
func NewReceipt ¶
func NewReceipt(resource *Resource, kind MutationKind, manager string, installedBefore bool, previousVersion string) *Receipt
NewReceipt builds a per-package *Receipt that declares its undo at construction.
The receipt names [compensatePackageMutationAction] as its compensating action (so Provider.CompensatePackageMutation inverts it regardless of which verb or dispatcher created it) and records the mutation kind and the package fields. The transactionID is minted later at op.ReceiptBase.Commit.
Parameters:
- `resource`: the package *Resource the mutation affected.
- `kind`: the MutationKind the receipt records.
- `manager`: the purl type of the leaf that handled the package.
- `installedBefore`: whether the package was present before the action.
- `previousVersion`: the version observed before the action.
Returns:
- `*Receipt`: the constructed receipt, born naming its compensator.
func (*Receipt) Kind ¶
func (r *Receipt) Kind() MutationKind
Kind returns the MutationKind this receipt records, or "" when unset.
Returns:
- `MutationKind`: the recorded mutation kind.
func (*Receipt) MarshalJSON ¶
MarshalJSON encodes the receipt's compensation state as JSON.
Delegates to Receipt.MarshalYAML for the serialized-shape value, then runs json.Marshal over it.
Returns:
- `[]byte`: JSON-encoded object carrying the receipt's resource URI and package fields.
- `error`: any error from Receipt.MarshalYAML or json.Marshal.
func (*Receipt) MarshalYAML ¶
MarshalYAML returns the receipt's compensation state as an anonymous struct value the encoder serializes.
This is the `receipt` sub-field the recovery stack embeds: the resource URI, transaction id, mutation kind, and the package fields. The base execution state (`action`/`compensating_action`/`result`/`status`) rides the stack-owned envelope, so it is not repeated here; resume reconstructs the receipt in Receipt.RestoreEncoded.
Returns:
- `any`: the populated anonymous struct for the encoder to walk.
- `error`: nil under normal conditions.
func (*Receipt) RestoreEncoded ¶
func (r *Receipt) RestoreEncoded( runtimeEnvironment *op.RuntimeEnvironment, base op.ReceiptData, fields map[string]any, ) error
RestoreEncoded reconstructs the receipt from its codec-decoded envelope.
It is the op.Receipt.RestoreEncoded override for package receipts. The recovery stack already decoded the envelope, so this consumes decoded values, never bytes: `base` carries the execution state and `fields` the receipt sub-field. It rehydrates the resource from its URI via DiscoverResource, seeds the base via op.NewReceiptBase + op.ReceiptBase.Restore, and restores the kind and package fields.
Parameters:
- `runtimeEnvironment`: the resume environment; its catalog must hold (or be able to construct) the resource.
- `base`: the codec-decoded base execution state.
- `fields`: the receipt sub-field, decoded to a format-neutral map.
Returns:
- `error`: a missing catalog or a DiscoverResource failure (an external-system interaction). The envelope itself arrives post-op.LoadTrace — checksum-verified — so document-derived failures panic (docs/architecture/5-graph-trace-integrity.md).
type Resource ¶
type Resource struct {
op.ResourceBase
Name string // package name ("jq", "curl", "VisualStudioCode")
Type string // purl type / manager ("brew", "deb", "port", "winget")
Version string // requested version (purl @version); empty means latest
}
Resource identifies a host package by its package-URL (purl) coordinates.
`Name` and `Type` together form the versionless purl encoded in the op.ResourceBase URI; "git" and "git@2.39.0" intern to the same catalog entry. `Version` is the requested version (the purl `@version`; empty means latest) — mutable state on the Resource, not part of its identity. Runtime-observed state (the installed version reported by the platform's package manager) lives on a separate *Observation minted by Provider.Observe.
func DiscoverResource ¶
func DiscoverResource(runtimeEnvironment *op.RuntimeEnvironment, value any) (*Resource, error)
DiscoverResource registers a pkg.Resource via op.ResourceCatalog.Discover without claiming production.
Used by the framework's resource registry adapter for slot coercion (when starlark supplies a string package name and the slot expects a *pkg.Resource), and by callers holding a reference handle without claiming production (receipt rehydration is the canonical example).
Discover does not stamp a producer, so unlike NewResource it takes only `runtimeEnvironment` — no unit reference is needed.
Nil-Catalog tolerance: returns the unlinked candidate when no catalog is present.
Parameters:
- `runtimeEnvironment`: the session runtime environment.
- `value`: a string package name with an optional manager prefix.
Returns:
- `*Resource`: the canonical catalog entry (or the unlinked candidate when no catalog is present).
- `error`: if `value` is not a string or the manager prefix is unknown.
func NewResource ¶
func NewResource(runtimeEnvironment *op.RuntimeEnvironment, producerID string, value any) (*Resource, error)
NewResource constructs a pkg.Resource and claims production via op.ResourceCatalog.GetOrCreate.
Use NewResource from a producer dispatch context — typically a provider method that has received an op.ActivationRecord from the framework. The returned Resource is the canonical catalog entry, stamped with `producerID = activationRecord.CallerID.ID()` (or empty when `Unit` is nil for non-graph dispatch). Use DiscoverResource instead when the caller is not claiming production (rehydration, reference handles, the framework's slot-coercion adapter).
Today no pkg provider method actually claims production — Install / Remove / Upgrade all take an existing `[]*Resource` and return the same pointers with their `Type` field updated to reflect which platform manager handled them. URIs (purls) are unchanged. NewResource exists for symmetry with the m.4 two-constructor pattern and as a stable surface for any future pkg producer that creates a new purl.
The value is a string package name with an optional manager prefix and optional version (e.g., "jq", "brew:jq", "port:wget", "git@2.39.0"). When no prefix is present, the platform's default purl type is used; the prefix otherwise resolves through platform.Platform.ResolvePurlType. The `@version` tail becomes the Resource's requested version and is excluded from the versionless catalog URI.
Nil-Catalog tolerance: returns the unlinked candidate when no catalog is present.
Parameters:
- `runtimeEnvironment`: the session runtime environment (must have `Platform` set).
- `producerID`: the producing caller's id (`activationRecord.CallerID`), or "" for caller-less dispatch. for non-graph dispatch.
- `value`: a string package name with an optional manager prefix.
Returns:
- `*Resource`: the canonical catalog entry (or the unlinked candidate when no catalog is present).
- `error`: if `value` is not a string or the manager prefix is unknown.
func (*Resource) Addressing ¶
func (r *Resource) Addressing() op.AddressingMode
Addressing reports that pkg.Resource is location-keyed: identity is the package URI (the purl).
The installed state (version, presence) under that purl is mutable, and the catalog uses op.AddressingLocation semantics — content drift triggers shadow chains, not new URIs.
Returns:
- `op.AddressingMode`: always op.AddressingLocation.
func (*Resource) CanConvertFrom ¶
CanConvertFrom reports whether `source` can be projected into a *Resource via Resource.ConvertFrom.
Opts the pkg Resource into the framework's op.TargetConverter contract — accepted source shape is `string` (interpreted as a package identifier, either a bare name like "jq" or a purl-prefixed form like "brew:jq"). The framework consults this probe both at plan-time via [op.typesAreInterconvertible] (the bubble-up parameter-consistency check) and at dispatch-time via op.Convert step 7 (env-less fallback). The canonical dispatch-time path remains the registered constructor at op.Convert step 6, which receives the full op.RuntimeEnvironment and parses any manager prefix via [buildCandidate].
Cheap-probe contract: this method is called against a nil-or-zero `*Resource` receiver by [op.typesAreInterconvertible] during plan-time bubble-up checks. MUST NOT dereference receiver fields.
Parameters:
- `source`: the candidate source type to test.
Returns:
- `bool`: true when `source` is `string`.
func (*Resource) ConvertFrom ¶
ConvertFrom projects `value` into an env-less unlinked *Resource.
Used by op.Convert step 7 when the env-aware registered constructor (step 6) is unavailable — env-less library callers, tests, or op.RuntimeEnvironment.Registry-missing contexts. The returned Resource carries only the Name set from `value`; the manager prefix is NOT parsed here, and the canonical URI on the embedded op.ResourceBase is not populated. Provider methods consuming the projected Resource are responsible for re-canonicalization via their own NewResource/DiscoverResource path when full identity is required.
Parameters:
- `value`: the source value; must be `string`.
Returns:
- `any`: the constructed unlinked *Resource.
- `error`: non-nil when `value` is not a `string`.
func (*Resource) Digest ¶
Digest returns the honest content hash: sha256 of (installed version + "\n" + canonical purl URI).
The canonical purl encodes the package identity (type + name); the installed version encodes the mutable state. Hashing the pair gives a stable, content-addressable token that changes when either the identity (which would normally mean a different URI / different Resource) or the installed state changes.
Uninstalled packages produce a deterministic digest of (empty version + URI), distinct from any installed digest for the same package, and distinct across different packages (since URIs differ).
Always fresh — re-queries the version at call time via Resource.Etag. Errors when Etag would error.
Returns:
- `op.Digest`: sha256 algorithm with 32 raw bytes.
- `error`: any error from Resource.Etag (no Platform, no manager for Type).
func (*Resource) Equal ¶
Equal reports whether r and other identify the same pkg resource.
Strict equality: other must be a *pkg.Resource (not merely an op.Resource with the same URI). Once the type check passes, URI comparison is delegated to op.ResourceBase.Equal. A cross-type URI collision is treated as a caller-side construction error, not a case Equal needs to disambiguate.
Parameters:
- `other`: the value to compare against; may be any, including nil or a non-Resource.
Returns:
- `bool`: true if `other` is a *pkg.Resource with the same URI as r.
func (*Resource) Etag ¶
Etag returns the currently-installed version of the package as a cheap change-detection token.
Empty string when the package is not installed (a valid state, distinguishable from errors by the nil error return). The catalog uses Etag as the cheap signal; mismatch triggers a full Resource.Digest comparison.
Always fresh — queries the platform's Composite package-manager router at call time. Does not consult Resource.Version, which is the requested version rather than installed state. The router routes by purl type; an unknown type reports "" (absent), not an error. Errors only when the runtime environment has no Platform.
Returns:
- `string`: the installed version string, or "" when uninstalled.
- `error`: when Platform is missing.
func (*Resource) String ¶
String returns a compact JSON representation of the resource.
Returns:
- `string`: the compact JSON encoding of r.
func (*Resource) UnmarshalJSON ¶
UnmarshalJSON populates the receiver from its JSON document (a bare purl string).
The caller pre-seeds the receiver's embedded op.ResourceBase with a valid op.RuntimeEnvironment before invoking this method; the runtime environment provides the platform needed to parse the purl. Rehydration flows through DiscoverResource (non-production claim).
Parameters:
- `data`: JSON-encoded purl string.
Returns:
- `error`: non-nil if the RuntimeEnvironment is missing, the JSON does not decode as a string, or resource construction fails.
func (*Resource) UnmarshalText ¶
UnmarshalText populates the receiver from raw UTF-8 bytes containing the purl string.
Parameters:
- `text`: UTF-8 bytes containing the purl.
Returns:
- `error`: missing RuntimeEnvironment on receiver, or rehydration failure.
func (*Resource) UnmarshalYAML ¶
UnmarshalYAML populates the receiver from its YAML document (a bare purl scalar).
Parameters:
- `unmarshal`: yaml decode hook supplied by the YAML library; called with a *string target.
Returns:
- `error`: missing RuntimeEnvironment on receiver, decode failure, or rehydration failure.