layout

package
v0.169.0 Latest Latest
Warning

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

Go to latest
Published: Sep 25, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Overview

Package layout audits and safely cleans local clone placement under a projects root. Canonical clones live at {root}/{host}/{owner}/{repository}, where {host} is the literal forge hostname. The legacy {owner}/{repository} placement this fleet still uses is read in place and reported as a finding, never silently accepted as a forge.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CleanFailed

func CleanFailed(report CleanReport) bool

CleanFailed reports whether clean had errors or leftover skips that need attention when apply was requested. Dry-run never fails solely for planned removals.

func Failed

func Failed(report Report) bool

Failed reports whether an audit found layout problems.

func MigrateFailed added in v0.142.0

func MigrateFailed(report MigrateReport) bool

MigrateFailed reports whether a migrate run left any clone refused or failed, which is the condition the command exits with the findings code for.

func OriginAddress added in v0.138.0

func OriginAddress(ctx context.Context, path string) (repopath.Address, error)

OriginAddress returns the canonical clone address the origin remote of the repository at path identifies: the literal forge hostname plus owner/repository. The host is empty for a local-only remote, which names no forge and therefore no first path level.

func OriginSlug

func OriginSlug(ctx context.Context, path string) (string, error)

OriginSlug returns owner/repository from path's origin remote.

Types

type CleanAction

type CleanAction struct {
	Path       string `json:"path" yaml:"path"`
	OriginSlug string `json:"origin_slug,omitempty" yaml:"origin_slug,omitempty"`
	Status     string `json:"status" yaml:"status"` // removed, planned, skipped, error
	Reason     string `json:"reason" yaml:"reason"`
}

CleanAction is one planned or applied cleanup.

type CleanOptions

type CleanOptions struct {
	Apply                 bool
	AllowMissingCanonical bool
}

CleanOptions controls safe removal of top-level clones.

type CleanReport

type CleanReport struct {
	SchemaVersion int           `json:"schema_version" yaml:"schema_version"`
	ProjectsRoot  string        `json:"projects_root" yaml:"projects_root"`
	DryRun        bool          `json:"dry_run" yaml:"dry_run"`
	Actions       []CleanAction `json:"actions" yaml:"actions"`
}

CleanReport summarizes a clean run.

func Clean

func Clean(ctx context.Context, projectsRoot string, options CleanOptions) (CleanReport, error)

Clean removes safe top-level clones. Without Apply it only plans.

func (CleanReport) Markdown

func (report CleanReport) Markdown() string

Markdown renders a clean plan/result.

type Finding

type Finding struct {
	Path         string `json:"path" yaml:"path"`
	Kind         Kind   `json:"kind" yaml:"kind"`
	PathSlug     string `json:"path_slug,omitempty" yaml:"path_slug,omitempty"`
	OriginSlug   string `json:"origin_slug,omitempty" yaml:"origin_slug,omitempty"`
	ExpectedPath string `json:"expected_path,omitempty" yaml:"expected_path,omitempty"`
	// RemoteURL is the remote URL the clone's canonical path corresponds to. A
	// clone that already sits at <root>/{host}/{owner}/{repository} inverts to
	// it by pure path arithmetic — no configuration and no repository remote
	// is read — and a legacy two-level clone reports the host its origin
	// already names, which is the host level it must move under.
	RemoteURL       string `json:"remote_url,omitempty" yaml:"remote_url,omitempty"`
	CanonicalExists bool   `json:"canonical_exists,omitempty" yaml:"canonical_exists,omitempty"`
	Reason          string `json:"reason" yaml:"reason"`
}

Finding is one inspected checkout relative to the projects root.

type Kind

type Kind string

Kind classifies one layout finding.

const (
	KindOK         Kind = "ok"
	KindTopLevel   Kind = "top_level"
	KindMisowned   Kind = "misowned"
	KindNoOrigin   Kind = "no_origin"
	KindUnreadable Kind = "unreadable"
	// KindBadHost reports a first-level entry under the projects root that is
	// not a literal forge hostname while carrying canonical clones of hosted
	// repositories. The legacy {owner}/{repository} placement is read in
	// place — no fleet is ever forced to move to be audited — but it is never
	// presented as if its owner level were a forge.
	KindBadHost Kind = "bad_host"
)

type MigrateClone added in v0.142.0

type MigrateClone struct {
	Repository  string            `json:"repository"`
	Source      string            `json:"source"`
	Destination string            `json:"destination"`
	Worktrees   []MigrateWorktree `json:"worktrees,omitempty"`
	// Status is one of: planned, done, already_done, needs_repair, repaired,
	// skipped, failed, reversed. needs_repair is a dry-run-only finding: a
	// clone already at its host-level path whose worktree registration was
	// left stranded by an earlier or partial move; like planned, it is not a
	// failure — it names what `--apply` will fix.
	Status string `json:"status"`
	Reason string `json:"reason,omitempty"`
	// Relocations lists this clone's managed task checkouts whose placement
	// differs from the store-mode placement, and what became of each: moved
	// via the existing `wb worktree relocate` implementation, left in place
	// with a finding, or reported unmanaged.
	Relocations []MigrateRelocation `json:"relocations,omitempty"`
	// Head is the clone's own HEAD at plan time, carried through to the
	// undo manifest. It is not part of the report's public JSON shape.
	Head string `json:"-"`
	// IncludedTasks names every task whose live-claim refusal was lifted by
	// --include-task/--include-active-tasks for this clone, carried through
	// to the undo manifest so --undo can honour exactly those inclusions
	// without --include-task/--include-active-tasks being passed again (they
	// are refused with --undo; see UndoIncludeFlagsError). Not part of the
	// report's public JSON shape.
	IncludedTasks []string `json:"-"`
}

MigrateClone is one legacy or host-level clone's migration plan or outcome.

type MigrateKeptOwner added in v0.142.0

type MigrateKeptOwner struct {
	Path   string `json:"path"`
	Reason string `json:"reason"`
}

MigrateKeptOwner is one legacy owner directory a migration did not remove, with the reason it was kept.

type MigrateOptions added in v0.142.0

type MigrateOptions struct {
	// Repositories restricts migration to these owner/repository slugs. Empty
	// means every legacy clone under the root.
	Repositories []string
	// Apply moves clones; without it the command only plans.
	Apply bool
	// ClonesOnly skips relocating managed task checkouts: clones move and
	// their linked worktrees repoint, exactly as before this option existed.
	ClonesOnly bool
	// UndoID reverses a previously completed manifest instead of migrating.
	UndoID string
	// IncludeTasks names tasks whose live Work Log claim must not refuse
	// their clone's move. A name matching no live claim in any resolved
	// home is a usage error before anything moves.
	IncludeTasks []string
	// IncludeActiveTasks lifts the live-claim refusal for every task, not
	// only the ones IncludeTasks names.
	IncludeActiveTasks bool
	Now                func() time.Time
}

MigrateOptions configures wb layout migrate.

type MigrateRelocation added in v0.144.1

type MigrateRelocation struct {
	Task        string `json:"task,omitempty"`
	Source      string `json:"source"`
	Destination string `json:"destination,omitempty"`
	// Status is one of: planned, done, skipped, failed, unmanaged,
	// moved-with-clone. unmanaged names a linked worktree with no WB task
	// identity: Git repointed it along with the clone, but it is never
	// relocated. moved-with-clone names an active task's checkout whose
	// live-claim refusal was lifted by --include-task/--include-active-tasks:
	// it moved and repointed with its clone (a relocation intent/receipt was
	// recorded for it) but, like any active task, is not relocated to the
	// store -- a successful outcome, not a finding.
	Status string `json:"status"`
	Reason string `json:"reason,omitempty"`
}

MigrateRelocation is one managed task checkout's relocation plan or outcome, considered after its clone reached its host-level placement.

type MigrateReport added in v0.142.0

type MigrateReport struct {
	SchemaVersion         int            `json:"schema_version"`
	ProjectsRoot          string         `json:"projects_root"`
	ObservedAt            time.Time      `json:"observed_at"`
	DryRun                bool           `json:"dry_run"`
	Undo                  bool           `json:"undo,omitempty"`
	ManifestID            string         `json:"manifest_id,omitempty"`
	ManifestPath          string         `json:"manifest_path,omitempty"`
	DaemonRestartRequired bool           `json:"daemon_restart_required,omitempty"`
	Clones                []MigrateClone `json:"clones"`
	// KeptOwners lists every legacy owner directory a migration left in
	// place because it still holds something, with why.
	KeptOwners []MigrateKeptOwner `json:"kept_owners,omitempty"`
	// Notes carries run-level observations that are not per-clone, such as
	// the busy-process check being unsupported on this OS.
	Notes []string `json:"notes,omitempty"`
}

MigrateReport is the result of one wb layout migrate run.

func Migrate added in v0.142.0

func Migrate(ctx context.Context, projectsRoot string, options MigrateOptions) (MigrateReport, error)

Migrate plans, and with Apply performs, moving every legacy <root>/<org>/<repo> canonical clone under root to its host-level <root>/<host>/<org>/<repo> placement, repointing every worktree Git has registered against it. See the "Clone migration" section of the projects-root-layout Feature for the full contract.

func (MigrateReport) Markdown added in v0.142.0

func (report MigrateReport) Markdown() string

Markdown renders a migration plan or result.

type MigrateWorktree added in v0.142.0

type MigrateWorktree struct {
	Source      string `json:"source"`
	Destination string `json:"destination"`
}

MigrateWorktree is one linked worktree a clone move repoints.

type Report

type Report struct {
	SchemaVersion int       `json:"schema_version" yaml:"schema_version"`
	ProjectsRoot  string    `json:"projects_root" yaml:"projects_root"`
	ObservedAt    time.Time `json:"observed_at" yaml:"observed_at"`
	Summary       Summary   `json:"summary" yaml:"summary"`
	Findings      []Finding `json:"findings" yaml:"findings"`
}

Report is the deterministic layout audit index.

func Audit

func Audit(ctx context.Context, projectsRoot string) (Report, error)

Audit walks projectsRoot for canonical, top-level, and misowned clones.

The first level under the root is the literal forge hostname: canonical clones live at {root}/{host}/{owner}/{repository}. A first-level entry that is not a valid hostname is reported as a layout finding. Its clones are still inspected at the legacy {owner}/{repository} placement, so a fleet that has not moved yet stays fully auditable in place.

func (Report) Markdown

func (report Report) Markdown() string

Markdown renders a human/agent layout audit index.

type Summary

type Summary struct {
	Inspected  int `json:"inspected" yaml:"inspected"`
	OK         int `json:"ok" yaml:"ok"`
	TopLevel   int `json:"top_level" yaml:"top_level"`
	Misowned   int `json:"misowned" yaml:"misowned"`
	NoOrigin   int `json:"no_origin" yaml:"no_origin"`
	Unreadable int `json:"unreadable" yaml:"unreadable"`
	BadHost    int `json:"bad_host" yaml:"bad_host"`
}

Summary counts findings by kind.

func Counts

func Counts(ctx context.Context, projectsRoot string) (Summary, error)

Counts returns summary fields useful for fleet rollups without retaining findings.

type UndoIncludeFlagsError added in v0.144.6

type UndoIncludeFlagsError struct{}

UndoIncludeFlagsError reports that --include-task or --include-active-tasks was passed together with --undo. Undo reverses exactly the inclusions its manifest recorded when the clones were moved; those flags have no meaning for it and are refused rather than silently ignored.

func (*UndoIncludeFlagsError) Error added in v0.144.6

func (*UndoIncludeFlagsError) Error() string

type UnknownIncludeTaskError added in v0.144.6

type UnknownIncludeTaskError struct {
	Task string
}

UnknownIncludeTaskError reports that an --include-task name matches no live Work Log claim in any home Migrate resolves for the root. Migrate returns it before anything moves, so a typo cannot silently include nothing.

func (*UnknownIncludeTaskError) Error added in v0.144.6

func (err *UnknownIncludeTaskError) Error() string

Jump to

Keyboard shortcuts

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