Documentation
¶
Index ¶
- Constants
- Variables
- func CanonicalBucketPath(bucket CanonicalBucket, parts ...string) string
- func CanonicalBucketRoot(agentsHome string, bucket CanonicalBucket) string
- func CanonicalBucketScopePath(bucket CanonicalBucket, scope string, parts ...string) string
- func CanonicalBucketScopeRoot(agentsHome string, bucket CanonicalBucket, scope string) string
- func CollectAndExecuteSharedTargetPlan(project, repoPath string, platforms []Platform) error
- func CollectManagedOutputs(platforms []Platform) []string
- func DryRunSharedTargetPlanLines(project, repoPath string, platforms []Platform) ([]string, error)
- func EnsureUnderMCPScopeTree(agentsHome, scope, target string) error
- func EnsureUnderRulesScopeTree(agentsHome, scope, target string) error
- func EnsureUnderSettingsScopeTree(agentsHome, scope, target string) error
- func ExecuteSharedSkillMirrorPlan(project, repoPath string, targetRoots ...string) error
- func HasMultipleHardLinks(path string) bool
- func IsManagedCodexAgentTomlFile(path string) (bool, error)
- func ListScopedResourceDirsForBucket(agentsHome string, bucket CanonicalBucket, scope, marker string) ([]resourceDir, error)
- func MaterializeArtifact(agentsHome, family, sourceID, name string, bundle config.Bundle, ...) (casPath, digest string, err error)
- func ProjectResolvedUnits(project, repoPath string, units []ResolvedUnit, platforms []Platform, ...) ([]string, error)
- func RemoveSharedTargetPlan(project, repoPath string, platforms []Platform) error
- func ResolveHookCommand(spec HookSpec) string
- func RunSharedTargetProjection(project, repoPath string, platforms []Platform, dryRun bool) ([]string, error)
- func RunSharedTargetProjectionExact(project, repoPath string, platforms []Platform, dryRun, exact bool) ([]string, error)
- func SortedUniqueStrings(values []string) []string
- func SupportedPipelinePlatforms() []string
- func ValidateResolvedUnit(agentsHome string, u ResolvedUnit, localScopes ...string) error
- func ValidateResolvedUnitIdentity(family, sourceID, name string, localScopes ...string) error
- type AuditPrinter
- type BranchSessionFinder
- type BranchSessionInfo
- type BrokenLink
- type BrokenLinkReporter
- type CanonicalBucket
- type CanonicalBucketSpec
- type CommitAttribution
- type DailyUsage
- type DirMirrorRootsProvider
- type HookEmissionMode
- type HookPlatformOverride
- type HookShape
- type HookSourceKind
- type HookSpec
- type HookTransport
- type LinkCounter
- type MCPFileSpec
- type ManagedOutputReporter
- type ManagedRenderProjector
- type ModelTokenUsage
- type OrphanCanonical
- type OrphanCanonicalReporter
- type PipelineArtifact
- type PipelineProjector
- type PipelineSpec
- type Platform
- func All() []Platform
- func ByID(id string) Platform
- func Filter(all []Platform, agentFilter string) []Platform
- func InstalledEnabledPlatforms(cfg *config.Config) []Platform
- func NewAntigravity() Platform
- func NewClaude() Platform
- func NewCodex() Platform
- func NewCopilot() Platform
- func NewCursor() Platform
- func NewOpenCode() Platform
- type PlatformBadge
- type PlatformUsageStats
- type PluginKind
- type PluginMarketplace
- type PluginResources
- type PluginSpec
- type ResolvedUnit
- type ResourceIntent
- func BuildSharedAgentFileSymlinkIntents(project, targetRoot, destFileSuffix string) ([]ResourceIntent, error)
- func BuildSharedAgentMirrorIntents(project string, targetRoots ...string) ([]ResourceIntent, error)
- func BuildSharedCodexAgentTomlIntents(project string) ([]ResourceIntent, error)
- func BuildSharedPluginBundleIntents(project string, targetRoots ...string) ([]ResourceIntent, error)
- func BuildSharedSkillMirrorIntents(project string, targetRoots ...string) ([]ResourceIntent, error)
- type ResourceOwnership
- type ResourcePlan
- type ResourceProvenance
- type ResourcePrunePolicy
- type ResourceReplacePolicy
- type ResourceShape
- type ResourceSourceKind
- type ResourceSourceRef
- type ResourceTransport
- type RuleFileSpec
- type SessionReader
- type SessionSummary
- type SessionTokenMetrics
- type SessionTokenScanner
- type SettingsFileSpec
- type SingleFileLinkSpec
- type SourcedAgentFileProjector
- type SourcedAgentFilePruneRootProvider
- type StageRoute
- type StatsReader
- type StatusBadger
- type UserConfigReporter
Constants ¶
const ( // CCPipelineArtifactName is the emitted per-task inner-pipeline workflow. CCPipelineArtifactName = "profile-pipeline.mjs" // CCReconcileArtifactName is the emitted reconcile-pass workflow. CCReconcileArtifactName = "profile-reconcile.mjs" )
const ( // OMPInnerArtifactName is the emitted inner per-task pipeline filename. OMPInnerArtifactName = "profile-driven.swarm.yaml" // OMPReconcileArtifactName is the emitted reconcile-pass filename. OMPReconcileArtifactName = "reconcile.swarm.yaml" )
const PluginManifestName = "PLUGIN.yaml"
Variables ¶
var BackupBeforeOverwrite = func(dst string) error { return sidecarBackup(stdPlatformIO{}, dst) }
BackupBeforeOverwrite preserves an existing managed-file destination before writeManagedFile replaces it with freshly rendered content. The default writes a sibling <dst>.dot-agents-backup (the existing repo backup convention, headless-safe, no layering inversion). The future config-distribution / lock-file model can wire a richer mirror-backup adapter through this seam without touching internal/platform.
This is a deliberate forward-compat extension point (NOT a test seam) — see the docstring above. Tests swap it via the legacy func-var pattern because that pattern matches its intended runtime-swap contract; the seam-interface-di-migration plan does not target this var.
var ErrReservedSourceID = errors.New("platform: source id collides with a reserved local scope")
ErrReservedSourceID reports a packages ref whose source id collides with a local scope segment (package-artifact-install spec §3A H3): the universal "global" scope or a caller-supplied local project scope name. errors.Is lets a caller distinguish this from any other materialize failure.
var PluginManifestSchema = schemas.Plugin
PluginManifestSchema is the embedded compiled schema for PLUGIN.yaml.
Functions ¶
func CanonicalBucketPath ¶
func CanonicalBucketPath(bucket CanonicalBucket, parts ...string) string
CanonicalBucketPath returns a slash-normalized canonical registry key (not a filesystem path). Keys are stored and compared in POSIX form on every OS, so the join is forced to forward slashes.
func CanonicalBucketRoot ¶
func CanonicalBucketRoot(agentsHome string, bucket CanonicalBucket) string
func CanonicalBucketScopePath ¶
func CanonicalBucketScopePath(bucket CanonicalBucket, scope string, parts ...string) string
CanonicalBucketScopePath returns a slash-normalized canonical registry key (not a filesystem path). See CanonicalBucketPath.
func CanonicalBucketScopeRoot ¶
func CanonicalBucketScopeRoot(agentsHome string, bucket CanonicalBucket, scope string) string
func CollectAndExecuteSharedTargetPlan ¶
CollectAndExecuteSharedTargetPlan runs BuildSharedTargetPlan then executes it against the repo and agents home. This is the command-layer entry point for centralized shared-target writes.
func CollectManagedOutputs ¶ added in v0.5.0
CollectManagedOutputs aggregates the repo-relative managed-output .gitignore patterns for the given platforms (typically the enabled set). A platform that implements ManagedOutputReporter supplies its own patterns; otherwise the static staticManagedOutputs table is consulted. The raw union is returned unsorted and possibly duplicated — links.EnsureManagedGitignore normalizes, de-duplicates, sorts, and filters the never-ignored contract files, so this collector never has to.
func DryRunSharedTargetPlanLines ¶
DryRunSharedTargetPlanLines describes what CollectAndExecuteSharedTargetPlan would write (merged shared-target rows, duplicate-intent counts) without touching the filesystem.
func EnsureUnderMCPScopeTree ¶
EnsureUnderMCPScopeTree checks that target is under agentsHome/mcp/scope.
func EnsureUnderRulesScopeTree ¶
EnsureUnderRulesScopeTree checks that target is under agentsHome/rules/scope (after clean).
func EnsureUnderSettingsScopeTree ¶
EnsureUnderSettingsScopeTree checks that target is under agentsHome/settings/scope.
func HasMultipleHardLinks ¶
HasMultipleHardLinks is the exported entry point that the commands/internal/lifecycle HasMultipleHardLinks func-var seam now delegates to. Exported (not package-private) because lifecycle's backup.go and status.go need to read it across the package boundary, and because backup_test.go overrides the lifecycle-side seam directly — both callers are within the dot-agents binary so the surface stays internal.
func IsManagedCodexAgentTomlFile ¶ added in v0.5.0
IsManagedCodexAgentTomlFile reports whether path is a dot-agents managed rendered codex agent `.toml` (carries codexManagedTomlMarker as its first line). Exported for commands/import.go (t2c): the project-scope import scan already walks `.codex/agents` (projectImportWalkDirs) and needs to skip re-importing dot-agents' OWN renders as if they were foreign user content — commands already imports internal/platform, so this is the one cycle-free direction for import.go to consult codex's provenance check.
func ListScopedResourceDirsForBucket ¶
func ListScopedResourceDirsForBucket(agentsHome string, bucket CanonicalBucket, scope, marker string) ([]resourceDir, error)
func MaterializeArtifact ¶ added in v0.5.0
func MaterializeArtifact(agentsHome, family, sourceID, name string, bundle config.Bundle, localScopes ...string) (casPath, digest string, err error)
MaterializeArtifact installs an H1-normalized bundle into the H2 content- addressed store and returns the immutable CAS path plus the resolved digest. Under the corrected per-project model (H13) it does NOT project: there is no shared mutable alias, and the projection target is a per-PROJECT decision driven by that project's resolved lock (ProjectResolvedUnits), not a global side effect of materialize. Identity components are validated (H15) and the source id is checked against reserved local scopes (H3) before any store write; H14 (CAS gitignored before first byte) and H16 (verify-on-hit) are enforced inside config.MaterializeToStore.
localScopes are the local scope names the source id must not collide with (H3) — typically the consuming project's own scope name; "global" is always rejected.
func ProjectResolvedUnits ¶ added in v0.5.0
func ProjectResolvedUnits(project, repoPath string, units []ResolvedUnit, platforms []Platform, dryRun, exact bool, localScopes ...string) ([]string, error)
ProjectResolvedUnits projects a caller-supplied set of resolved packages units into project's repo, each linking DIRECTLY to its immutable CAS digest path (H13 per-project CAS-direct). The units are pure INVOCATION- LOCAL data — a function parameter threaded straight into the CAS-intent builder and never stored in any package-level variable — so two concurrent projections with different resolved-unit sets cannot cross-contaminate (the previous package-global projection context, which a concurrent plain RunSharedTargetProjectionExact could read, is gone).
It reuses the exact/prune projection machinery (D4: same BuildResourcePlan / Execute / PruneStaleSharedTargets, not a parallel linker): local-authored intents (from the platforms) and the caller's CAS-direct intents are merged into ONE plan, executed, and pruned together. The per-platform dir-mirror roots are resolved deterministically (sharedDirMirrorRoots) so a bucket projects — and, critically, is PRUNE-SCANNED — even when the caller's set for it is empty (H17/one-to-zero: dropping a bucket to zero units still removes its stale link) and even when the project has no local-authored sibling.
Every unit is validated (H15 identity + H13/H16 CAS-path binding) before projection; a single invalid unit fails the whole call closed. localScopes are the reserved local scope names each unit's source id must not equal (H3). CAS projection covers BOTH shapes: the DIR-MIRROR buckets (skills + agents-dir + plugins, via buildCASIntents) AND the FILE-shaped agents surfaces (Codex .toml render, OpenCode/Copilot agent-file symlink, via collectSourcedAgentFileIntents) — t2b closed the gap where a sourced agent reached only the dir-mirror platforms.
func RemoveSharedTargetPlan ¶
RemoveSharedTargetPlan removes repo-local shared targets implied by the merged plan for the given platforms (same aggregation as CollectAndExecuteSharedTargetPlan). Symlinks are removed only when they point into agentsHome; rendered files are removed for known materializers (e.g. codex-agent-toml).
func ResolveHookCommand ¶
ResolveHookCommand returns the hook command with relative paths resolved against the HOOK.yaml location.
func RunSharedTargetProjection ¶
func RunSharedTargetProjection(project, repoPath string, platforms []Platform, dryRun bool) ([]string, error)
RunSharedTargetProjection is the command-layer entry point for shared-target projection: it builds the merged ResourcePlan (BuildSharedTargetPlan) and either returns dry-run preview lines or executes writes. This keeps refresh/install/add on one code path for "build intents → plan → dry-run or apply".
Callers must set config.SetWindowsMirrorContext(repoPath) before calling when the repo needs Windows-specific path behavior for intent resolution.
func RunSharedTargetProjectionExact ¶ added in v0.4.0
func RunSharedTargetProjectionExact(project, repoPath string, platforms []Platform, dryRun, exact bool) ([]string, error)
RunSharedTargetProjectionExact is the EXACT/PRUNE command-layer entry point (config-v2-coherence §7A.5 / D10 "outputs half"): it projects the resolved asset-store union AND prunes managed outputs that are no longer in the resolved set, so the repo tree converges to exactly what the plan declares. It is the projection refresh/install drive by default; pass exact=false (`--inexact`) to keep the additive RunSharedTargetProjection behavior (write the wanted set, leave stale managed outputs in place).
Dry-run returns the same preview lines as RunSharedTargetProjection plus a "prune" line for every managed output the apply path would delete, so the preview is a faithful diff of the exact projection. Apply executes the plan then prunes; prune is best-effort relative to the write — a prune failure is returned so the caller can withhold a clean-success stamp.
Callers must set config.SetWindowsMirrorContext(repoPath) before calling when the repo needs Windows-specific path behavior for intent resolution.
func SortedUniqueStrings ¶
SortedUniqueStrings trims whitespace, drops empties + duplicates, and returns values sorted. Exported so commands/import_plugins.go can share the implementation instead of duplicating it.
func SupportedPipelinePlatforms ¶ added in v0.5.0
func SupportedPipelinePlatforms() []string
SupportedPipelinePlatforms is the sorted list of platform ids with a PipelineProjector implementation.
func ValidateResolvedUnit ¶ added in v0.5.0
func ValidateResolvedUnit(agentsHome string, u ResolvedUnit, localScopes ...string) error
ValidateResolvedUnit checks a caller-supplied resolved unit before it is trusted as a projection input: identity-component containment (H15), a well-formed digest, and — critically — that CASPath is EXACTLY the store path the unit's (family, digest) names under agentsHome (never trusted as passed, H13/H16). A unit whose CASPath does not equal config.ArtifactStorePath(agentsHome, family, digest) is rejected, so a caller cannot smuggle a link target outside the immutable store.
func ValidateResolvedUnitIdentity ¶ added in v0.5.0
ValidateResolvedUnitIdentity enforces the H15 identity-component containment contract for a resolved packages unit's on-disk identity: family, source-id, and name must EACH be a single canonical path segment (config.ValidateStoreSegment — rejects "."/".."/separators/absolute/ volume/NUL), and the source id must not collide with a reserved local scope (H3 — "global" or any caller-supplied local scope, typically the consuming project's own scope name). It is the single gate every materialize/projection entry point calls BEFORE deriving any filesystem path from caller-influenced identity, so a hostile ".." source id can never widen a CAS or projection path.
Types ¶
type AuditPrinter ¶
AuditPrinter is implemented by platforms that render the per-platform audit block shown by `da status --audit`. Resolved in Phase 5 (Q2): the printer takes an io.Writer rather than a *ui.Sink — the platform layer only needs the ANSI colour constants from internal/ui (plain strings), so io.Writer keeps the dependency surface minimal while the lifecycle layer supplies os.Stdout at the call site.
type BranchSessionFinder ¶
type BranchSessionFinder interface {
FindSessionsOnBranch(home, projectPath, branch string, maxResults int) []BranchSessionInfo
}
BranchSessionFinder is implemented by platforms that embed git branch metadata in their session files, allowing orient to surface recent sessions on the current branch.
type BranchSessionInfo ¶
BranchSessionInfo holds brief info about a session that was active on a specific git branch. Used by BranchSessionFinder.
type BrokenLink ¶
type BrokenLink struct {
// PlatformID identifies which platform owns this link (e.g. "cursor").
PlatformID string
// LinkPath is the display-friendly path to the broken link — typically
// repo-relative for project links or home-relative for user-config links.
LinkPath string
// Dest is the raw target string returned by the OS (os.Readlink output
// for symlinks/junctions; empty for hard links whose canonical source
// could not be matched).
Dest string
// DisplayDest is Dest after path resolution and ~/-prefix formatting,
// suitable for direct rendering by doctor/status.
DisplayDest string
}
BrokenLink describes a single managed link that exists but does not resolve to the expected canonical source. PlatformID is intentionally carried on the value so JSON reports can self-describe per-entry (Q1 in the proposal — kept).
func ScanSingleFileLinks ¶
func ScanSingleFileLinks(specs []SingleFileLinkSpec) []BrokenLink
ScanSingleFileLinks evaluates each spec and returns a BrokenLink for every entry that exists at LinkPath but does not satisfy any CanonicalPaths match. The rules mirror what cursor + the single-file managed paths in doctor.go already encode:
- If LinkPath does not exist on disk, nothing is reported — an absent link is "not present" rather than "broken".
- If LinkPath is hard-linked to ANY of CanonicalPaths, it is healthy and nothing is reported.
- If LinkPath is a resolvable managed link (POSIX symlink / Windows junction) and its target is missing, it is reported broken with the raw target in Dest.
- If LinkPath is a resolvable managed link and its target exists but does not match any canonical (mis-pointed), it is also reported broken — the canonical contract is "link matches a known source", not "link resolves to anything".
Note that platforms supply the PlatformID at the call site by post- processing the returned slice (this keeps the helper platform-agnostic and avoids threading platform identity through every spec).
func ScanSymlinkDir ¶
func ScanSymlinkDir(dir string) (ok, broken int, brokenLinks []BrokenLink)
ScanSymlinkDir reads dir and classifies each entry as healthy or broken via the managed-link semantics used by status/doctor today. Returns the healthy count, the broken count, and the broken entries with raw + display target populated. Hidden files and subdirectories are skipped (the existing per-platform dirs are flat — rules/, agents/, skills/, agent/).
dir may not exist; in that case (0, 0, nil) is returned without error — "absent dir" is "not present" rather than "broken", matching the existing doctor/status behavior. Symlinks to directories (which on Windows show up as junctions and on POSIX as plain symlinks) are classified using managedLinkBroken so their broken state is reported even though they are not files.
type BrokenLinkReporter ¶
type BrokenLinkReporter interface {
BrokenLinks(project, repoPath, agentsHome string) []BrokenLink
}
BrokenLinkReporter is implemented by platforms that can enumerate their own broken project-scope links. Consumer: doctor.collectBrokenLinks.
type CanonicalBucket ¶
type CanonicalBucket string
const ( CanonicalBucketRules CanonicalBucket = "rules" CanonicalBucketSettings CanonicalBucket = "settings" CanonicalBucketMCP CanonicalBucket = "mcp" CanonicalBucketSkills CanonicalBucket = "skills" CanonicalBucketAgents CanonicalBucket = "agents" CanonicalBucketHooks CanonicalBucket = "hooks" CanonicalBucketCommands CanonicalBucket = "commands" CanonicalBucketOutputStyles CanonicalBucket = "output-styles" CanonicalBucketIgnore CanonicalBucket = "ignore" CanonicalBucketModes CanonicalBucket = "modes" CanonicalBucketPlugins CanonicalBucket = "plugins" CanonicalBucketThemes CanonicalBucket = "themes" CanonicalBucketPrompts CanonicalBucket = "prompts" )
type CanonicalBucketSpec ¶
type CanonicalBucketSpec struct {
Name CanonicalBucket
Stage int
CountDirs bool
MarkerFile string
Description string
}
func CanonicalStoreBucketSpecs ¶
func CanonicalStoreBucketSpecs() []CanonicalBucketSpec
func CanonicalStoreStage1BucketSpecs ¶
func CanonicalStoreStage1BucketSpecs() []CanonicalBucketSpec
func CanonicalStoreStage2BucketSpecs ¶
func CanonicalStoreStage2BucketSpecs() []CanonicalBucketSpec
type CommitAttribution ¶
type CommitAttribution struct {
CommitHash string
BranchName string
ScoredAt string
LinesAdded int
LinesDeleted int
ComposerLinesAdded int
ComposerLinesDeleted int
HumanLinesAdded int
V2AIPercentage float64
}
CommitAttribution holds AI vs human code attribution for a single commit. Sourced from Cursor's scored_commits table.
type DailyUsage ¶
DailyUsage holds activity counts for a single day.
type DirMirrorRootsProvider ¶ added in v0.5.0
DirMirrorRootsProvider is implemented by platforms with DIR-MIRROR shaped shared-target buckets (skills/agents/plugins dirs symlinked wholesale, rather than rendered or symlinked per entry). DirMirrorRoots returns a platform's bucket roots (bucket -> repo-relative target roots) INDEPENDENT of any local content, so CAS projection (buildCASIntents) and one-to-zero pruning work even when a project has no local-authored sibling and even when the caller's unit set for the bucket is empty. It mirrors exactly the roots each platform passes to BuildSharedSkillMirrorIntents / BuildSharedAgentMirrorIntents / BuildSharedPluginBundleIntents inside its SharedTargetIntents. Platforms whose agents bucket is FILE-shaped instead (Codex .toml render, OpenCode/Copilot agent-file symlink) omit "agents" here and implement SourcedAgentFileProjector instead (t2b).
codex/opencode/copilot implement this in their own files; claude/cursor/ antigravity implement it below — t2b's write scope does not include claude.go/cursor.go/antigravity.go, and Go permits a method on a same-package type to live in a different file, so this is the narrowest way to consolidate the former type-switch into first-class methods without touching files outside this task's scope.
type HookEmissionMode ¶
type HookEmissionMode struct {
Shape HookShape
Transport HookTransport
}
type HookPlatformOverride ¶
type HookSourceKind ¶
type HookSourceKind string
const ( HookSourceLegacyFile HookSourceKind = "legacy_file" HookSourceCanonicalBundle HookSourceKind = "canonical_bundle" )
type HookSpec ¶
type HookSpec struct {
Name string
Scope string
SourcePath string
SourceBucket string
SourceKind HookSourceKind
Description string
When string
// WhenEvents, when non-empty, declares a multi-event hook. The
// loader rejects manifests that set both `when` and `when_events`
// (mutual exclusion) and manifests with duplicate or unknown
// canonical events (P1c contract `when_events` rules). At render
// time the spec is expanded into one rendered action per canonical
// event the target platform documents.
WhenEvents []string
MatchTools []string
MatchExpression string
Command string
TimeoutMS int
EnabledOn []string
RequiredOn []string
PlatformOverrides map[string]HookPlatformOverride
}
func ListHookSpecs ¶
ListHookSpecs returns hook entries under ~/.agents/hooks/<scope>/: canonical bundles (…/<name>/HOOK.yaml) and legacy single-file JSON hooks. The hooks directory must exist; if it is missing, ReadDir fails with an error satisfying os.IsNotExist.
type HookTransport ¶
type HookTransport string
const ( HookTransportSymlink HookTransport = "symlink" HookTransportHardlink HookTransport = "hardlink" HookTransportWrite HookTransport = "write" )
type LinkCounter ¶
LinkCounter is implemented by platforms that can count their healthy and broken managed links for a project. Consumer: doctor.countProjectLinks and the badge-math feeding status.
type MCPFileSpec ¶
MCPFileSpec describes one canonical MCP config file under ~/.agents/mcp/<scope>/.
func ListCanonicalMCPFiles ¶
func ListCanonicalMCPFiles(agentsHome, scope string) ([]MCPFileSpec, error)
ListCanonicalMCPFiles returns non-directory MCP config files under ~/.agents/mcp/<scope>/, sorted by basename. If the scope directory is missing, the error satisfies os.IsNotExist.
func ResolveCanonicalMCPFile ¶
func ResolveCanonicalMCPFile(agentsHome, scope, name string) (*MCPFileSpec, error)
ResolveCanonicalMCPFile finds an MCP file by scope and name (basename or stem).
type ManagedOutputReporter ¶ added in v0.5.0
type ManagedOutputReporter interface {
ManagedOutputs() []string
}
ManagedOutputReporter is implemented by platforms whose generated repo-local outputs are dynamic enough (or divergent enough from the static table) to warrant per-platform enumeration — e.g. Copilot's rendered .github/hooks/*.json fanout, which is not a single owned directory like the other platforms' surfaces. A platform that does not implement it falls back to the staticManagedOutputs table in CollectManagedOutputs. The returned entries are repo-relative .gitignore patterns (forward-slash, trailing slash for directories) for the managed-.gitignore block (config-distribution-model §15 / D14 / R8).
type ManagedRenderProjector ¶ added in v0.5.0
type ManagedRenderProjector interface {
// ManagedRenderDir is the repo-relative directory the platform renders its
// managed files into (e.g. .codex/agents). Forced into the exact scan even
// on a one-to-zero pass, so a render dropped to zero is still pruned.
ManagedRenderDir() string
// IsManagedRender reports whether path is one of THIS platform's managed
// rendered files — identity-verified provenance, never a bare name/suffix
// match — so a user-authored file in the same directory is never pruned.
IsManagedRender(path string) (bool, error)
}
ManagedRenderProjector is implemented by a platform whose shared agents surface is a MANAGED RENDERED FILE (codex `.toml`) rather than a symlink. Such a file is a plain regular file — never a managed symlink — so the generic exact/prune scan (pruneManagedEntries, which only reaps symlinks via links.IsManagedLinkUnder) cannot see it. These methods let the exact projection reap a stale managed render uniformly with the symlink shapes (defect 3), driven by the SAME wanted-target set the plan already carries.
type ModelTokenUsage ¶
type ModelTokenUsage struct {
InputTokens int
OutputTokens int
CacheReadInputTokens int
CacheCreationInputTokens int
}
ModelTokenUsage holds cumulative token counts for a single model.
type OrphanCanonical ¶
type OrphanCanonical struct {
// Name is the entry basename as it appears under ~/.agents/<bucket>/.
Name string
// DisplayNote is either "" (plain orphan) or a pre-formatted suffix
// describing the mis-pointed target. Callers concatenate it directly
// when rendering.
DisplayNote string
}
OrphanCanonical describes a canonical entry under ~/.agents/ that has no corresponding managed link in the project (orphan from the project's perspective). DisplayNote is empty for plain orphans; a mis-pointed link surfaces as a non-empty note formatted as " (mis-pointed: <target>)".
type OrphanCanonicalReporter ¶
type OrphanCanonicalReporter interface {
OrphanCanonicals(project, projectPath, agentsHome, bucket string) []OrphanCanonical
}
OrphanCanonicalReporter is implemented by platforms that maintain a canonical store under ~/.agents/<bucket>/ that can be inspected for orphans (entries with no matching project link). Consumer: doctor.collectOrphanCanonicals.
type PipelineArtifact ¶ added in v0.5.0
type PipelineArtifact struct {
// Name is the artifact filename relative to the platform's runtime dir
// (e.g. "profile-driven.swarm.yaml").
Name string
// Content is the full file body, terminated by a single trailing newline.
Content string
}
PipelineArtifact is one emitted file: a repo-relative filename and its full content. A projector returns the complete set for one emission.
type PipelineProjector ¶ added in v0.5.0
type PipelineProjector interface {
// Platform is the projector's target platform id (e.g. "omp").
Platform() string
// RuntimeRelDir is the repo-relative directory the projector's artifacts are
// emitted into (each harness owns its own runtime location).
RuntimeRelDir() string
// Emit renders the pipeline artifacts from the spec, or an error when the
// spec is invalid for this platform.
Emit(spec PipelineSpec) ([]PipelineArtifact, error)
}
PipelineProjector renders a PipelineSpec into a target harness's materialized per-task pipeline. It is platform-agnostic: the OMP implementation emits swarm YAML and the Claude-Code implementation emits dynamic-workflow `.mjs`.
func PipelineProjectorFor ¶ added in v0.5.0
func PipelineProjectorFor(platform string) (PipelineProjector, error)
PipelineProjectorFor returns the projector for a target platform id. Both the OMP beachhead and the Claude-Code dynamic-workflow projector are implemented; any other id is unknown.
type PipelineSpec ¶ added in v0.5.0
type PipelineSpec struct {
// Workspace is the absolute repo root the emitted pipeline runs in.
Workspace string
// AppType is the app_type this pipeline was specialized for, or "" for the
// app_type-agnostic maximal skeleton (7 verify + 4 routine slots) that the
// runtime profile_resolve stage narrows per task.
AppType string
// TargetCount is the bounded fold-back re-entry ceiling (craft §3).
TargetCount int
// Executor is the executor/default route; it also drives the swarm default
// model and the gate/reconcile/profile_resolve routes.
Executor StageRoute
// Verifiers is the ordered verifier slot routes (1..7). For the skeleton every
// slot carries the executor route; a specialized projection binds each slot to
// its verifier_sequence slug's stage_profile.
Verifiers []StageRoute
// RoutineLenses is the ordered routine review lens routes (0..4), excluding the
// cross-family lens.
RoutineLenses []StageRoute
// CrossFamily is the blocking cross-family adversarial route, or nil when the
// app_type's lens_set does not include the cross-harness-adversarial slug.
CrossFamily *StageRoute
}
PipelineSpec is the resolved, platform-agnostic IR a PipelineProjector renders. It is the single input from which any harness projection is generated, so two harness projectors reading the same spec agree on models, cardinality, and topology by construction.
func BuildPipelineSpec ¶ added in v0.5.0
func BuildPipelineSpec(workspace, appType string, stageProfiles map[string]map[string]config.StageProfile, ep *config.ExecutionProfile) (PipelineSpec, error)
BuildPipelineSpec resolves stage_profiles + execution_profile topology into a PipelineSpec for the given app_type. An empty appType yields the maximal app_type-agnostic skeleton (7 verify + 4 routine slots + cross-family), which the runtime profile_resolve stage narrows per task; a named appType yields the specialized projection whose slot count equals that app_type's verifier_sequence / lens_set (still capped ≤7 / ≤4).
func (PipelineSpec) Digest ¶ added in v0.5.0
func (s PipelineSpec) Digest() string
Digest is the stable config digest stamped into the generated header comment. It is computed over the routing/topology inputs ONLY (never the workspace path or any wall-clock value), so re-emitting the same profile IR yields a byte-identical artifact (idempotence) while a stage_profiles/topology change registers as drift.
func (PipelineSpec) Validate ¶ added in v0.5.0
func (s PipelineSpec) Validate() error
Validate enforces the cardinality caps and the non-empty-route rule before any projector renders the spec (craft §2/§4).
type Platform ¶
type Platform interface {
// ID returns the platform identifier (e.g. "cursor", "claude").
ID() string
// DisplayName returns the human-readable name.
DisplayName() string
// IsInstalled checks if this platform is installed on the system.
IsInstalled() bool
// Version returns the detected version string, or empty string.
Version() string
// CreateLinks creates all managed links for a project in repoPath.
CreateLinks(project, repoPath string) error
// RemoveLinks removes all managed links for a project from repoPath.
RemoveLinks(project, repoPath string) error
// HasDeprecatedFormat checks if the project has deprecated config files.
HasDeprecatedFormat(repoPath string) bool
// DeprecatedDetails returns a description of the deprecated format.
DeprecatedDetails(repoPath string) string
// to shared (cross-platform) repo-local targets such as .agents/skills/*.
// These intents are aggregated by the command layer into a single
// ResourcePlan so compatible targets are deduped and conflicts are caught
// before any filesystem writes occur.
SharedTargetIntents(project string) ([]ResourceIntent, error)
}
Platform defines the interface all AI agent platforms must implement.
func Filter ¶ added in v0.4.1
Filter returns the subset of all whose ID() matches agentFilter, in the original order. An empty agentFilter selects every platform (the unfiltered `da status`/`da doctor --verbose` audit). This is the single platform-selection primitive the lifecycle audit loop dispatches over, replacing the per-platform `agentFilter == "" || agentFilter == "<id>"` chain that previously lived in status.go's printAudit.
func InstalledEnabledPlatforms ¶
InstalledEnabledPlatforms returns platforms that are enabled in cfg and detected as installed on this machine. Order matches All().
func NewAntigravity ¶ added in v0.5.0
func NewAntigravity() Platform
NewAntigravity constructs the Antigravity platform with the real filesystem IO.
func NewCopilot ¶
func NewCopilot() Platform
func NewOpenCode ¶
func NewOpenCode() Platform
type PlatformBadge ¶
type PlatformBadge struct {
// Name is the human-readable platform name shown in the badge row
// (e.g. "Cursor", "Claude Code").
Name string
// Present is true when this platform has any managed state for the
// inspected scope (project or user-home).
Present bool
// Broken is true when any of the platform's managed links are broken.
Broken bool
}
PlatformBadge is the per-platform summary consumed by both the text (badge row) and JSON (statusJSONPlatform) status output. Per D5 of the proposal, this is the single source of truth that replaces the parallel `*TextBadge` and `collectProjectPlatforms` paths.
type PlatformUsageStats ¶
type PlatformUsageStats struct {
PlatformID string
TotalSessions int
TotalMessages int
TokensByModel map[string]ModelTokenUsage
DailyActivity []DailyUsage
RecentSessions []SessionSummary
CommitAttribution []CommitAttribution
}
PlatformUsageStats holds pre-aggregated usage data from a platform's native store. Used by StatsReader.ReadUsageStats.
type PluginKind ¶
type PluginKind string
const ( PluginKindNative PluginKind = "native" PluginKindPackage PluginKind = "package" )
type PluginMarketplace ¶
type PluginResources ¶
type PluginSpec ¶
type PluginSpec struct {
SchemaVersion int `yaml:"schema_version"`
Kind PluginKind `yaml:"kind"`
Name string `yaml:"name"`
Version string `yaml:"version,omitempty"`
DisplayName string `yaml:"display_name,omitempty"`
Description string `yaml:"description,omitempty"`
Authors []string `yaml:"authors,omitempty"`
Homepage string `yaml:"homepage,omitempty"`
License string `yaml:"license,omitempty"`
Platforms []string `yaml:"platforms"`
Resources PluginResources `yaml:"resources,omitempty"`
Marketplace PluginMarketplace `yaml:"marketplace,omitempty"`
Dependencies map[string]any `yaml:"dependencies,omitempty"`
PlatformOverrides map[string]map[string]any `yaml:"platform_overrides,omitempty"`
Dir string `yaml:"-"`
ManifestPath string `yaml:"-"`
Scope string `yaml:"-"`
}
PluginSpec is the canonical dot-agents plugin bundle manifest. Schema contract: schemas/plugin.schema.json - keep this struct aligned with the manifest contract and validate raw YAML bytes via PluginManifestSchema before trusting the typed fields.
func ListPluginSpecs ¶
func ListPluginSpecs(agentsHome, scope string) ([]PluginSpec, error)
ListPluginSpecs returns canonical plugin specs for a scope. An empty scope scans all scopes under ~/.agents/plugins/.
func LoadPluginSpec ¶
func LoadPluginSpec(pluginDir string) (PluginSpec, error)
LoadPluginSpec parses and validates a canonical plugin manifest from pluginDir.
type ResolvedUnit ¶ added in v0.5.0
type ResolvedUnit struct {
// Family is the resource bucket ("skills" | "agents" | "plugins").
Family string
// Name is the resource directory name (one canonical segment).
Name string
// SourceID is the provenance source id (one canonical segment); used for a
// stable, source-namespaced intent id so two sources shipping a same-named
// resource never collide.
SourceID string
// Digest is the "sha256:<hex>" content digest THIS project resolved.
Digest string
// CASPath is the absolute immutable store path for Digest
// (config.ArtifactStorePath). Recomputed and asserted by
// ValidateResolvedUnit, never trusted as passed.
CASPath string
// ContentDigest is the OPTIONAL H16 content-integrity anchor
// (config.BundleContentDigest / the git-tracked "artifact-content" lock
// value) the caller resolved this unit against. When non-empty,
// ProjectResolvedUnits re-verifies it — via config.VerifyStoreContentDigest
// — immediately before the unit's CAS content is actually linked into the
// project (t3b, closing the verify→link TOCTOU: an earlier batch verify a
// driver ran before calling ProjectResolvedUnits does not, by itself, catch
// a store mutation that lands during this call). Left empty, a unit gets
// no invocation-time re-check — identical to pre-t3b behavior — so an
// older caller that has not yet threaded its lock's content digest through
// keeps working unchanged; the anchor is defense-in-depth on top of H13's
// existing identity/path binding, not a new hard requirement on every
// caller.
ContentDigest string
}
ResolvedUnit is one packages artifact a PROJECT resolved from its lock — the caller-supplied projection input (H13). It is the boundary between t2 (mechanism) and t3 (driver): t3 reads the project's lock, materializes each ref, and hands the resulting units to ProjectResolvedUnits. t2 NEVER discovers this set by scanning the global store; authority flows in, not out.
type ResourceIntent ¶
type ResourceIntent struct {
IntentID string `json:"intent_id"`
Project string `json:"project"`
Bucket string `json:"bucket"`
LogicalName string `json:"logical_name"`
TargetPath string `json:"target_path"`
Ownership ResourceOwnership `json:"ownership"`
SourceRef ResourceSourceRef `json:"source_ref"`
Shape ResourceShape `json:"shape"`
Transport ResourceTransport `json:"transport"`
Materializer string `json:"materializer"`
ReplacePolicy ResourceReplacePolicy `json:"replace_policy"`
PrunePolicy ResourcePrunePolicy `json:"prune_policy"`
Provenance ResourceProvenance `json:"provenance"`
Precedence int `json:"precedence,omitempty"`
ConflictKey string `json:"conflict_key,omitempty"`
MarkerFiles []string `json:"marker_files,omitempty"`
EnabledOn []string `json:"enabled_on,omitempty"`
ReviewHint string `json:"review_hint,omitempty"`
}
func BuildSharedAgentFileSymlinkIntents ¶
func BuildSharedAgentFileSymlinkIntents(project, targetRoot, destFileSuffix string) ([]ResourceIntent, error)
BuildSharedAgentFileSymlinkIntents builds symlink intents from each canonical AGENT.md file to a repo-local file path (OpenCode `.md`, Copilot `.agent.md`).
A missing canonical agents bucket (ENOENT) is treated as an empty resource set — projects without any agents yet are legitimate and should yield no intents, not a hard failure. Other errors (permission denied, IO) propagate so callers can surface them instead of silently producing an empty plan.
func BuildSharedAgentMirrorIntents ¶
func BuildSharedAgentMirrorIntents(project string, targetRoots ...string) ([]ResourceIntent, error)
BuildSharedAgentMirrorIntents builds symlink intents for canonical agents/ buckets (per-entry directories with AGENT.md) into the given repo-relative target roots.
func BuildSharedCodexAgentTomlIntents ¶
func BuildSharedCodexAgentTomlIntents(project string) ([]ResourceIntent, error)
BuildSharedCodexAgentTomlIntents builds render intents for `.codex/agents/*.toml` from canonical project agent directories.
A missing canonical agents bucket (ENOENT) is treated as an empty resource set — projects without any agents yet are legitimate and should yield no intents, not a hard failure. Other errors (permission denied, IO) propagate so callers can surface them instead of silently producing an empty plan.
func BuildSharedPluginBundleIntents ¶
func BuildSharedPluginBundleIntents(project string, targetRoots ...string) ([]ResourceIntent, error)
BuildSharedPluginBundleIntents returns ResourceIntents for each canonical plugin bundle under ~/.agents/plugins/{scope}/ pointing at the given target roots. Each platform's SharedTargetIntents calls this with its own native plugin target path (e.g. OpenCode uses .opencode/plugins/, Cursor uses .cursor-plugin/, Claude uses .claude-plugin/, etc.). Platforms that do not yet have an emitter for their native plugin format simply omit this call from their SharedTargetIntents implementation — add it there when the emitter lands.
func BuildSharedSkillMirrorIntents ¶
func BuildSharedSkillMirrorIntents(project string, targetRoots ...string) ([]ResourceIntent, error)
func (ResourceIntent) EffectiveConflictKey ¶
func (i ResourceIntent) EffectiveConflictKey() string
func (ResourceIntent) Validate ¶
func (i ResourceIntent) Validate() error
type ResourceOwnership ¶
type ResourceOwnership string
const ( ResourceOwnershipPlatformRepo ResourceOwnership = "platform_repo" ResourceOwnershipUserHome ResourceOwnership = "user_home" )
type ResourcePlan ¶
type ResourcePlan struct {
Resources []plannedResource
}
func BuildResourcePlan ¶
func BuildResourcePlan(intents []ResourceIntent) (ResourcePlan, error)
func BuildSharedTargetPlan ¶
func BuildSharedTargetPlan(project string, platforms []Platform) (ResourcePlan, error)
BuildSharedTargetPlan aggregates SharedTargetIntents from all provided platforms and builds a single merged ResourcePlan (dedupe, conflict detection). Dry-run and execute paths both use this so intent collection and planning happen once per operation.
func (ResourcePlan) Execute ¶
func (p ResourcePlan) Execute(repoPath, agentsHome string) error
func (ResourcePlan) PruneStaleSharedTargets ¶ added in v0.4.0
func (p ResourcePlan) PruneStaleSharedTargets(repoPath, agentsHome string) ([]string, error)
PruneStaleSharedTargets deletes managed outputs that are no longer in the resolved plan (the EXACT/PRUNE projection, config-v2-coherence §7A.5). It scans only the parent directories that own at least one ResourcePruneTarget intent — the directories da actively projects into — and removes any entry there that (a) is not a wanted plan target and (b) is a managed link under agentsHome. User-authored files and links pointing outside agentsHome are never touched, so the prune cannot delete content da does not own.
Returns the list of pruned absolute paths and an aggregated error: a single stuck removal is reported (errors.Join) rather than short-circuiting, so one failure cannot hide the prune status of the rest and the caller never reports a converged tree while a stale managed output is still live.
func (ResourcePlan) RemoveSharedTargets ¶
func (p ResourcePlan) RemoveSharedTargets(repoPath, agentsHome string) error
RemoveSharedTargets deletes managed outputs for each resource in the plan. Per-resource removal failures are aggregated (errors.Join) rather than short-circuiting so that one stuck target cannot hide the removal status of the rest, and so the caller (da remove) never reports a clean unlink while a managed output is still live on disk.
type ResourceProvenance ¶
type ResourcePrunePolicy ¶
type ResourcePrunePolicy string
const ( ResourcePruneNone ResourcePrunePolicy = "none" ResourcePruneTarget ResourcePrunePolicy = "target_only" ResourcePruneGeneratedChildren ResourcePrunePolicy = "generated_children" )
type ResourceReplacePolicy ¶
type ResourceReplacePolicy string
const ( ResourceReplaceNever ResourceReplacePolicy = "never" ResourceReplaceIfManaged ResourceReplacePolicy = "if_managed" ResourceReplaceAllowlistedImportedDirOnly ResourceReplacePolicy = "allowlisted_imported_dir_only" )
type ResourceShape ¶
type ResourceShape string
const ( ResourceShapeDirectDir ResourceShape = "direct_dir" ResourceShapeDirectFile ResourceShape = "direct_file" ResourceShapeRenderSingle ResourceShape = "render_single" ResourceShapeRenderFanout ResourceShape = "render_fanout" )
type ResourceSourceKind ¶
type ResourceSourceKind string
const ( ResourceSourceCanonicalFile ResourceSourceKind = "canonical_file" ResourceSourceCanonicalDir ResourceSourceKind = "canonical_dir" ResourceSourceCanonicalBundle ResourceSourceKind = "canonical_bundle" )
type ResourceSourceRef ¶
type ResourceSourceRef struct {
Scope string `json:"scope"`
Bucket string `json:"bucket"`
RelativePath string `json:"relative_path"`
Kind ResourceSourceKind `json:"kind"`
Origin string `json:"origin,omitempty"`
}
func (ResourceSourceRef) CanonicalPath ¶
func (r ResourceSourceRef) CanonicalPath(agentsHome string) string
func (ResourceSourceRef) Validate ¶
func (r ResourceSourceRef) Validate() error
type ResourceTransport ¶
type ResourceTransport string
const ( ResourceTransportSymlink ResourceTransport = "symlink" ResourceTransportHardlink ResourceTransport = "hardlink" ResourceTransportWrite ResourceTransport = "write" )
type RuleFileSpec ¶
type RuleFileSpec struct {
Scope string
BaseName string // full file name, e.g. rules.mdc
SourcePath string
}
RuleFileSpec describes one canonical rule file under ~/.agents/rules/<scope>/.
func ListCanonicalRuleFiles ¶
func ListCanonicalRuleFiles(agentsHome, scope string) ([]RuleFileSpec, error)
ListCanonicalRuleFiles returns non-directory rule files under ~/.agents/rules/<scope>/, sorted by basename. Subdirectories are ignored. If the scope directory is missing, the error satisfies os.IsNotExist.
func ResolveCanonicalRuleFile ¶
func ResolveCanonicalRuleFile(agentsHome, scope, name string) (*RuleFileSpec, error)
ResolveCanonicalRuleFile finds a rule file by scope and name. Name may be a full basename (e.g. rules.mdc) or a stem; stems try .mdc, .md, .txt in order.
type SessionReader ¶
type SessionReader interface {
// AIAgentPrefix returns the harness prefix used in the AI_AGENT env var
// convention (e.g. "claude-code" for AI_AGENT=claude-code_2-1-138_agent).
// Returns "" if this platform does not follow the AI_AGENT convention.
AIAgentPrefix() string
// SessionEnvs lists env var names (in preference order) that carry the
// active session ID. First non-empty value wins.
SessionEnvs() []string
// EntrypointEnvs lists env var names for the session launch entrypoint.
EntrypointEnvs() []string
// ResolveModel scans the platform's session store for the model active in
// the given session. Returns "" when unavailable or not yet implemented.
ResolveModel(home, projectPath, sessionID string) string
}
SessionReader is implemented by platforms that expose structured runtime session data. It is the read-side complement to the write-side Platform interface and is kept separate to avoid burdening platforms that do not yet have confirmed session env var contracts.
Implement on a platform struct to make it participate in agent identity detection at `da workflow checkpoint` time. Stubs that return "" / nil are valid until the env var contract for that platform is confirmed.
type SessionSummary ¶
SessionSummary holds a brief description of a session.
type SessionTokenMetrics ¶
type SessionTokenMetrics struct {
InputTokens int
OutputTokens int
CacheReadTokens int
CacheCreationTokens int
ReasoningTokens int // Codex o-series reasoning tokens; 0 for Claude Code
CacheHitRate float64 // CacheReadTokens/(CacheReadTokens+CacheCreationTokens); 0 = unavailable
MessageCount int
}
SessionTokenMetrics holds per-iteration token usage aggregated from a session's JSONL, time-windowed by checkpoint_at. Used by SessionTokenScanner.
type SessionTokenScanner ¶
type SessionTokenScanner interface {
ScanSessionTokens(home, projectPath, sessionID, afterTimestamp string) SessionTokenMetrics
}
SessionTokenScanner is implemented by platforms that support per-iteration token usage scanning from their session JSONL. Returns a zero SessionTokenMetrics when no matching entries exist or the session file is absent.
type SettingsFileSpec ¶
SettingsFileSpec describes one canonical settings file under ~/.agents/settings/<scope>/.
func ListCanonicalSettingsFiles ¶
func ListCanonicalSettingsFiles(agentsHome, scope string) ([]SettingsFileSpec, error)
ListCanonicalSettingsFiles returns non-directory settings files under ~/.agents/settings/<scope>/.
func ResolveCanonicalSettingsFile ¶
func ResolveCanonicalSettingsFile(agentsHome, scope, name string) (*SettingsFileSpec, error)
ResolveCanonicalSettingsFile finds a settings file by scope and name (basename or stem).
type SingleFileLinkSpec ¶
type SingleFileLinkSpec struct {
// LinkPath is the absolute path to the managed file link.
LinkPath string
// CanonicalPaths is the ordered list of acceptable sources. The first
// hard-linked match wins; if none match and the link exists, the link
// is reported as broken.
CanonicalPaths []string
}
SingleFileLinkSpec describes one managed file link a platform owns: a fixed link path and the ordered list of canonical source files any of which would satisfy the link (the ordered list supports the .mdc → .md fallback already used by cursor rules).
type SourcedAgentFileProjector ¶ added in v0.5.0
type SourcedAgentFileProjector interface {
// SourcedAgentFileIntents returns the CAS-direct ResourceIntents this
// platform's file-shaped agents surface needs for units — implementations
// filter to Family == "agents" themselves (units may carry other families).
SourcedAgentFileIntents(project string, units []ResolvedUnit) []ResourceIntent
}
SourcedAgentFileProjector is implemented by platforms whose agents bucket is FILE-shaped (a rendered or symlinked per-entry file, e.g. Codex's rendered `.toml`, OpenCode/Copilot's symlinked `.md`/`.agent.md`) rather than dir-mirror-shaped (buildCASIntents / casDirMirrorSpec). t2b closes the gap where a sourced agent unit reached only the dir-mirror platforms: ProjectResolvedUnits drives SourcedAgentFileIntents from the SAME caller-supplied resolved-unit set (H13) as every other CAS intent. A platform without a file-shaped agents bucket simply omits this method.
type SourcedAgentFilePruneRootProvider ¶ added in v0.5.0
type SourcedAgentFilePruneRootProvider interface {
SourcedAgentFilePruneRoot() string
}
SourcedAgentFilePruneRootProvider is implemented by platforms whose SourcedAgentFileIntents materializes a SYMLINK (OpenCode/Copilot) rather than a render (Codex): it names the repo-relative directory that must be forced into the exact/prune scan even when the current call's unit set is empty (H17 one-to-zero, extended from the dir-mirror buckets to t2b's file-shaped CAS intents) — otherwise a unit projected on a prior call and then fully removed leaves an orphaned managed symlink behind forever, since no intent this call touches that directory at all. Codex does NOT implement this: its rendered `.toml` is never a symlink, so forcing its directory into the generic symlink prune scan would not help — that shape's removal is the managed-RENDER prune (pruneManagedRenders via ManagedRenderProjector), which scans the codex render dir separately.
type StageRoute ¶ added in v0.5.0
StageRoute is one resolved stage's explicit model route (craft §2: every stage is a typed StageProfile with an explicit model AND model_family; a matched stage whose model or model_family is empty is refused, never emitted). Slug is empty for the app_type-agnostic skeleton slots (runtime profile_resolve fills the concrete route per task) and set for an app_type-specialized projection.
type StatsReader ¶
type StatsReader interface {
ReadUsageStats(home string) *PlatformUsageStats
}
StatsReader is implemented by platforms that expose pre-aggregated usage statistics. ReadUsageStats returns nil when the platform's stats file is absent or not yet implemented.
type StatusBadger ¶
type StatusBadger interface {
Badge(project, repoPath, agentsHome string) PlatformBadge
}
StatusBadger is implemented by platforms that can produce a one-line status badge for the project. Consumer: status.collectProjectTextBadges and status.collectProjectPlatforms (text + JSON share the same value per D5).
type UserConfigReporter ¶
type UserConfigReporter interface {
// UserBrokenLinks returns broken managed links under the user's home
// directory for this platform. Consumer: doctor.collectBrokenUserLinks.
UserBrokenLinks(home string) []BrokenLink
// UserBadge returns the user-config badge for the platform. Consumer:
// status.collectUserConfigPlatforms.
UserBadge(home string) PlatformBadge
}
UserConfigReporter is implemented by every platform that participates in the user-home diagnostics path. claude/codex/opencode/cursor report real managed user-home links; copilot implements it too but reports an empty/clean surface because its documented user-config layer is not yet wired by dot-agents (the user-scope wiring gap is tracked in PLATFORM_DIRS_DOCS). No platform lacks a user-config layer — the distinction is whether dot-agents wires it yet.
Source Files
¶
- antigravity.go
- buckets.go
- cc_pipeline.go
- claude.go
- claude_linkcount_unix.go
- cliprobe.go
- codex.go
- config_platform.go
- copilot.go
- cursor.go
- diagnostics.go
- diagnostics_helpers.go
- hooks.go
- io.go
- mcp_settings.go
- omp_pipeline.go
- opencode.go
- pipeline_projection.go
- platform.go
- plugins.go
- render_manifest.go
- resource_intent.go
- resource_plan.go
- resource_plan_swap_linux.go
- resources.go
- rules.go
- session.go
- stats.go