workspace

package
v0.4.2 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2026 License: GPL-3.0 Imports: 28 Imported by: 0

Documentation

Overview

Package workspace holds the shared building blocks for opening a workspace: the WorkspaceRegistry and the project, spell, and target option constructors that a magusfile's register(...) calls produce, plus the Load accumulator for Open/Inspect.

It is a separate package for two reasons:

  • Import cycle: package magus imports internal/interp to evaluate magusfiles, and internal/interp's Buzz bindings build project options when Buzz code calls magus.project(...). Those option types cannot live in package magus, and not in project either (the watch-ignore constructors need internal/file/watch, which already imports project).
  • Surface: Load and WithLimiter carry internal types (*config.Config, *cache.Limiter). Keeping them here lets the daemon inject a shared limiter without those internals leaking onto the public magus API.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddProvidedProjects added in v0.4.0

func AddProvidedProjects(ctx context.Context, ws *types.Workspace, spellNames []string, cache ProviderCache) error

AddProvidedProjects runs each wired provider in order and adds the projects it reports to ws. It is a no-op when no provider was wired, which is every workspace that does not have one - so the cost of the mechanism to everyone else is one nil check per open.

cache says where a provider's answer is remembered between commands; a zero value re-runs every provider. See provider_cache.go for what invalidates an entry.

Precedence, in the order the rules apply:

  • A path that already carries a magusfile is left alone (MGS1019). The magusfile is the workspace's own definition, the same rule that makes a magusfile target shadow a same-named spell op.
  • The FIRST provider to report a path owns it. Two providers claiming one directory is a real configuration (an nx repo with a cargo workspace inside it), and wiring order is the only deterministic tiebreak.
  • magus\project("libs/foo", {...}) still layers on top of everything here, because WorkspaceRegistry.Apply runs after this.

A rejected path FAILS the whole load rather than being skipped: a silently dropped project is a target that no longer exists with nothing on screen to say so. ws is mutated in place, so a caller continuing past an error holds a partially folded workspace; every caller today discards it.

func ContextWithRegistry

func ContextWithRegistry(ctx context.Context, reg *WorkspaceRegistry) context.Context

ContextWithRegistry installs reg in ctx so that interpreters can retrieve it via WorkspaceRegistryFromContext.

func IgnoreGlob

func IgnoreGlob(pattern string) types.IgnorePattern

IgnoreGlob constructs a doublestar-glob ignore pattern.

func IgnoreLiteral

func IgnoreLiteral(pattern string) types.IgnorePattern

IgnoreLiteral constructs a literal ignore pattern.

func IgnoreRegex

func IgnoreRegex(pattern string) types.IgnorePattern

IgnoreRegex constructs a Go-regexp ignore pattern.

func RegisterProviderRunner added in v0.4.0

func RegisterProviderRunner(fn ProviderRunner)

RegisterProviderRunner installs the runner AddProvidedProjects delegates to. Meant to be called once, from the bindings package's init; a second call panics rather than silently shadowing the first.

Types

type BindingOption

type BindingOption func(b *types.Binding) error

BindingOption mutates a spell Binding at registration time.

type Load

type Load struct {
	ConfigPath string
	Preloaded  *config.Config
	Limiter    *cache.Limiter
	Registry   *WorkspaceRegistry
	// MachineAdmitter injects the machine budget directly, for the ONE process that
	// holds it. Every other process finds the daemon over its socket; the daemon
	// cannot, because dialing its own socket from inside a request it is serving would
	// wait on itself.
	MachineAdmitter cache.MachineAdmitter
	MetricsCollect  bool // build an always-on local metrics collector (daemon dashboard feed)
	// Provider injects an already-constructed observability provider so several Magus
	// instances share one set of OTel instruments and one metrics collector. When set it
	// takes precedence over MetricsCollect (Open skips otlp.New and adopts it).
	Provider observability.Provider
	// Version is the running build's version, used only to check the workspace's
	// required_version floor. Empty disables the check, which is the same escape
	// hatch the daemon adoption gate uses (see internal/proc/identity.go): a bare
	// library caller that never set a version has no version to be too old.
	Version string
	// SkipWorkspaceProviders opens the workspace without running its wired workspace
	// providers, so it holds only the magusfile-declared projects.
	SkipWorkspaceProviders bool
}

Load is the accumulated state of an Open or Inspect call.

type Option

type Option func(*Load)

Option configures Open or Inspect.

func WithLimiter

func WithLimiter(lim *cache.Limiter) Option

WithLimiter injects a pre-built concurrency limiter (e.g. shared across daemon workspaces).

func WithLoadedConfig

func WithLoadedConfig(cfg config.Config) Option

WithLoadedConfig injects an already-parsed config instead of reading magus.yaml.

func WithMachineAdmitter added in v0.4.0

func WithMachineAdmitter(a cache.MachineAdmitter) Option

WithMachineAdmitter injects the machine-wide admission budget the daemon holds, so the workspaces it serves arbitrate against the same one every other magus on the host reaches over the socket.

func WithMetricsCollection added in v0.2.0

func WithMetricsCollection() Option

WithMetricsCollection builds an always-on in-process metrics collector for this workspace so its OTel instruments record even when telemetry export is off, and the daemon can serve OTLP snapshots to the /dashboard. The CLI leaves it unset to keep one-shot runs a true no-op.

func WithTelemetryProvider added in v0.4.0

func WithTelemetryProvider(p observability.Provider) Option

WithTelemetryProvider injects an already-constructed observability provider so several Magus instances (a daemon's bridge plus each of its per-workspace registry Magus) share ONE set of OTel instruments and one metrics collector. The provider is owned by the caller (the daemon process), not by any single workspace, so workspace eviction never discards accumulated metrics. It supersedes WithMetricsCollection: Open adopts the injected provider instead of constructing its own.

Named Telemetry, not just WithProvider, because "provider" is already taken twice over in this package: ProviderRunner/ProviderCache/RegisterProviderRunner/ WithoutWorkspaceProviders all mean a WORKSPACE provider (magus\workspace.provider), and observability.WithProvider (a different package, same short name) stores a Provider on a context rather than an Option. This is the one that meant something else entirely.

func WithVersion added in v0.4.0

func WithVersion(v string) Option

WithVersion supplies the running build's version so Open and Inspect can check it against the workspace's required_version floor. cmd/magus passes its linker-stamped version; a caller that omits it gets no floor check.

func WithoutWorkspaceProviders added in v0.4.0

func WithoutWorkspaceProviders() Option

WithoutWorkspaceProviders opens the workspace without running its wired workspace providers (magus\workspace.provider), leaving only the magusfile-declared projects.

It exists for a caller inspecting a tree that is not a working checkout - `magus graph diff --rev` exports a bare revision to a temp dir, with no node_modules, no installed toolchain and no VCS metadata. A provider shells out to a foreign tool that needs all three, so running it there fails the open and takes the whole command with it. The base side of a diff is deliberately narrower rather than broken; a project that only a provider knows about shows up as added.

Unrelated to WithTelemetryProvider above, which injects an observability provider.

type ProjectOption

type ProjectOption func(p *types.Project) error

ProjectOption mutates a Project at registration time; a non-nil error aborts Open.

func WithDependsOn

func WithDependsOn(paths ...string) ProjectOption

WithDependsOn adds upstream project paths as dependencies. Paths may be repo-relative or dot-relative to the project.

This is the one caller that wants ResolveDependsOn.s two-mode reading, because a human hand-writes these entries and both spellings are a deliberate affordance. Paths that come from an `import "project/<path>"` are always dot-relative and use file.ResolveImport instead; do not collapse the two.

func WithExclusive

func WithExclusive() ProjectOption

WithExclusive marks a project as must-not-run-alongside-peers in a RunAll batch.

func WithName added in v0.4.0

func WithName(name string) ProjectOption

WithName sets the project's declared display name, overriding the path-derived default. See types.Project.Name for why the root needs it.

func WithNoLanguage added in v0.4.0

func WithNoLanguage(reason string) ProjectOption

WithNoLanguage records why a project binds no toolchain spell deliberately.

func WithOutputs

func WithOutputs(paths ...string) ProjectOption

WithOutputs declares the file globs this project produces (project-relative).

func WithRegisteredSpell

func WithRegisteredSpell(name string, opts ...BindingOption) ProjectOption

WithRegisteredSpell registers a built-in spell by name (wire-layer equivalent of magus.WithSpell).

func WithReviewRequired added in v0.4.0

func WithReviewRequired(globs ...string) ProjectOption

WithReviewRequired declares the globs where an unread change is worth reporting.

A glob escaping the workspace root is REFUSED, the same way WithSources refuses one, and for a sharper reason: a source glob that escapes merely fails to key a cache entry, while this one silently matches nothing and the project goes on believing it has marked its riskiest paths. A feature whose whole job is to say "read this one" must not fail quiet.

func WithSources added in v0.2.0

func WithSources(paths ...string) ProjectOption

WithSources declares additional file globs (project-relative) that feed this project's cache key and affected-set membership, alongside whatever its resolved spells already contribute via their own Sources(). Use this when a project's real inputs reach beyond what its spells claim - e.g. non-code assets, sibling proto schemas, or docs a generator target reads.

A glob may REACH OUT of the project ("../proto/**" from docs/); that is what makes this the option for a sibling schema. types.RootGlob resolves the reach when the glob is rooted at the workspace, so the cache key and affected attribution both see "proto/**".

Storing the path.Clean'd spelling is what keeps one glob one string. Every check downstream compares declarations by string equality - Project.DeclaredGlobs dedups that way, MGS1005 asks whether a per-target glob is already project-wide the same way - and "./docs/**" and "docs/**" are one declaration, not two.

A glob reaching PAST the workspace root is rejected here, where it is written, rather than stored and ignored. The source walk starts at the workspace root and yields workspace-relative paths, so a glob outside it can never match a file, never move a cache key, and never mark this project affected - accepting one would record a declaration magus has no way to honor.

func WithTarget

func WithTarget(name string, opts ...TargetOption) ProjectOption

WithTarget attaches a behavioral policy to the named target. name is normalized (see types.DefaultTargetNameNormalizer) so a policy declared under any spelling matches the target under any other.

func WithToolBounds added in v0.4.0

func WithToolBounds(bounds map[string]spells.VersionBounds) ProjectOption

WithToolBounds sets the project's per-binary version windows, rejecting a bound that is not a version.

Rejecting at load is what keeps VersionBounds.Check's unknown verdict a backstop rather than the normal path: a typo here would otherwise widen the window to everything and report nothing, which is the opposite of what declaring one is for.

func WithWatchIgnore

func WithWatchIgnore(patterns ...types.IgnorePattern) ProjectOption

WithWatchIgnore appends patterns to the project's watch ignore list.

type ProviderCache added in v0.4.0

type ProviderCache struct {
	Dir string
	// Immutable mirrors cache.immutable: the workspace may be read but never
	// written, so a miss re-runs the provider without storing the result.
	Immutable bool
}

ProviderCache says where a provider's answer is remembered between commands. A zero value (empty Dir) disables the cache and re-runs every provider.

type ProviderRunner added in v0.4.0

type ProviderRunner func(ctx context.Context, spellName, root string) ([]spells.ProvidedProject, error)

ProviderRunner invokes spellName's list_projects contract against the workspace at root and returns the records it reported, undecoded. It returns the wire record (spells.ProvidedProject) rather than options so the result stays serializable - which is what lets AddProvidedProjects cache it instead of shelling out to the foreign tool on every magus command.

type TargetOption

type TargetOption func(t *types.Target)

TargetOption sets a per-target execution-policy field on a types.Target at registration time.

func Drift added in v0.4.0

func Drift(policy types.DriftPolicy, reason string) TargetOption

Drift sets what happens when this target's declared outputs move under a read-only run. The zero policy already gates a target that declares outputs, so this is for stating that out loud, downgrading to a warning, or switching it off with a reason.

func Exclusive

func Exclusive() TargetOption

Exclusive returns a TargetOption that runs the target alone — no other target runs concurrently while it does.

func IncludeArch added in v0.4.0

func IncludeArch(v bool) TargetOption

IncludeArch overrides whether the host architecture keys this target's entry.

func IncludeOS added in v0.4.0

func IncludeOS(v bool) TargetOption

IncludeOS overrides whether the host OS keys this target's cache entry.

func MemoryMB added in v0.4.0

func MemoryMB(n int) TargetOption

MemoryMB returns a TargetOption setting the target's memory budget in megabytes. See types.Target.MemoryMB.

func RetryOnVolatile added in v0.2.0

func RetryOnVolatile() TargetOption

RetryOnVolatile returns a TargetOption that enables volatility detection and auto-retry.

func SkipCache

func SkipCache(reason string) TargetOption

SkipCache returns a TargetOption that opts the target out of the cache, so magus always runs it and never replays or snapshots it. reason states why REPLAYING the target would be wrong (a fresh signature, a screen capture, a go.mod mutation); it is recorded rather than merely documented so a reader can tell a real opt-out from a workaround, and so `--no-cache`, which only distrusts the cache for one run, is not reached for by mistake.

func Slots

func Slots(n int) TargetOption

Slots returns a TargetOption that makes the target hold n concurrency slots while it runs, throttling parallel work around a resource-heavy step. n is clamped to the run's total slot budget at schedule time; n >= the budget makes the target hold every slot, so no peer runs concurrently with it.

type WorkspaceRegistry

type WorkspaceRegistry struct {
	// contains filtered or unexported fields
}

WorkspaceRegistry holds the per-Open project-option overrides for a single workspace open. Create one with NewWorkspaceRegistry, populate it via RegisterProject, then pass it to Inspect or Open via WithWorkspaceRegistry. A fresh WorkspaceRegistry per Open call means there is no shared mutable state between concurrent opens.

func NewWorkspaceRegistry

func NewWorkspaceRegistry() *WorkspaceRegistry

NewWorkspaceRegistry returns an empty WorkspaceRegistry.

func WorkspaceRegistryFromContext

func WorkspaceRegistryFromContext(ctx context.Context) *WorkspaceRegistry

WorkspaceRegistryFromContext returns the per-Open WorkspaceRegistry from ctx, or nil. Used by the Teal magus.project and magus.target bindings.

func (*WorkspaceRegistry) AddProvider added in v0.4.0

func (r *WorkspaceRegistry) AddProvider(spellName string)

AddProvider records a spell name a magusfile wired as a workspace provider, ignoring a repeat of one already wired so a magusfile that wires the same spell twice does not run it twice. Safe to call concurrently.

func (*WorkspaceRegistry) Apply

Apply applies the registered project options to every project in w. Paths that do not match any discovered project are errors. Option errors are collected and joined. Spell names are resolved to *spells.Spell values and their declared deps are unioned into each project's DependsOn.

func (*WorkspaceRegistry) ProjectPaths

func (r *WorkspaceRegistry) ProjectPaths() []string

ProjectPaths returns the registered project paths in sorted order.

func (*WorkspaceRegistry) Providers added in v0.4.0

func (r *WorkspaceRegistry) Providers() []string

Providers returns the workspace-provider spell names in wiring order, or nil when none were wired.

func (*WorkspaceRegistry) RegisterProject

func (r *WorkspaceRegistry) RegisterProject(path string, opts ...ProjectOption)

RegisterProject appends opts for the repo-relative project path. Safe to call concurrently.

func (*WorkspaceRegistry) RemoteBackend

func (r *WorkspaceRegistry) RemoteBackend() string

RemoteBackend returns the remote-cache-backend spell name a magusfile wired, or "" when none was.

func (*WorkspaceRegistry) SetRemoteBackend

func (r *WorkspaceRegistry) SetRemoteBackend(spellName string)

SetRemoteBackend records the spell name a magusfile chose as the remote cache backend. Last writer wins; safe to call concurrently.

Jump to

Keyboard shortcuts

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