Help us shape the future of Go! Take the 2026 Go Developer Survey

state

package
v0.11.0 Latest Latest
Warning

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

Go to latest
Published: Jul 28, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package state persists agentsync's own bookkeeping under ~/.agentsync/.state/: the last-applied hashes and marketplace/plugin pinning in targets.json, and the per-machine run record in last-run.json (see lastrun.go).

Index

Constants

View Source
const LastRunFile = "last-run.json"

LastRunFile is the basename of the per-machine run record inside .state/.

View Source
const SchemaVersion = 1

Variables

View Source
var ErrCorruptLastRun = errors.New("corrupt last-run record")

ErrCorruptLastRun reports a run record that exists but cannot be parsed.

It is distinguished from an I/O error on purpose. A record is a UX marker with no authority: an unparseable one carries no information, so the honest reading is "this machine has shown nothing", NOT "say nothing forever". Treating a parse failure like an I/O failure meant a single truncated file — the classic crash-mid-write artifact, or an empty file after a full disk — suppressed the notice permanently, silently contradicting the documented contract that a corrupt record only means the notice shows again later.

LoadLastRun therefore returns a USABLE zero record alongside this error, so a caller that wants the forgiving behavior can take it and overwrite the file, while one that wants to bail can still check the error.

Functions

func Save

func Save(path string, t *Targets) error

Save serializes t to path atomically (iox.AtomicWrite).

func SaveLastRun added in v0.11.0

func SaveLastRun(path string, l *LastRun) error

SaveLastRun writes the run record atomically. Callers MUST treat a failure as non-fatal — a read-only home or a full disk must not fail the user's command over a UX marker.

Types

type FileEntry

type FileEntry struct {
	SHA256    string    `json:"sha256"`
	Mode      uint32    `json:"mode"`
	AppliedAt time.Time `json:"applied_at"`
	SourceID  string    `json:"source_id"` // canonical file that produced this dest
}

FileEntry tracks one fully-managed destination file. Key format: "<agent>:<scope>:<project>:<dest_path>"

type KeyEntry

type KeyEntry struct {
	SHA256    string    `json:"sha256"`
	AppliedAt time.Time `json:"applied_at"`
	SourceID  string    `json:"source_id"`
}

KeyEntry tracks one managed JSON-pointer-addressable key inside a shared destination file. Key format: "<agent>:<scope>:<project>:<file>:<json_pointer>"

type LastRun added in v0.11.0

type LastRun struct {
	// Version is the agentsync version that last ran on this machine. Empty on
	// a record written by a build with no version stamped.
	Version string `json:"version"`
	// NoticesSeen holds the ids of the upgrade notices already shown, so a
	// version jump that skips releases still shows each notice exactly once and
	// a re-install never re-shows one.
	NoticesSeen []string `json:"notices_seen,omitempty"`
}

LastRun records what the last agentsync invocation on this machine was, so a release can tell a user once — and only once — what changed under them.

It is deliberately a SEPARATE file from targets.json rather than a field on Targets, for three reasons:

  • targets.json is drift state guarded by SchemaVersion; a UX marker has no business gating on (or bumping) that version.
  • targets.json is written only by the MUTATING commands. A read-only `status` must be able to record that it showed the notice, or the notice repeats forever for a user whose daily loop never applies.
  • a corrupt or unwritable run record must never be able to take the drift state down with it. Callers treat every error here as "skip the notice".

It lives under .state/, which `init` gitignores, so a committed dotfiles repo never carries one machine's run record to another.

func LoadLastRun added in v0.11.0

func LoadLastRun(path string) (*LastRun, error)

LoadLastRun reads the run record at path.

It always returns a non-nil record, so callers never nil-check before calling Seen/MarkSeen. A MISSING file yields the zero record with a nil error — absence is not an error condition, and "has this machine seen notice X?" is correctly "no" for a machine with no record at all. (Distinguishing a fresh install from an upgrade is NOT this function's job: that is the existence of the agentsync home, checked by the caller.)

A record that exists but does not parse yields the zero record wrapped with ErrCorruptLastRun. Any other failure (a real I/O error — .state is a regular file, permissions, a bad mount) returns the zero record and that error; callers skip the notice rather than fail the command.

func (*LastRun) MarkSeen added in v0.11.0

func (l *LastRun) MarkSeen(id string)

MarkSeen adds id to the seen set (idempotent, kept sorted for a stable file).

func (*LastRun) Seen added in v0.11.0

func (l *LastRun) Seen(id string) bool

Seen reports whether the notice id has already been shown on this machine.

type Marketplace

type Marketplace struct {
	URL       string    `json:"url"`
	Ref       string    `json:"ref"`
	HeadSHA   string    `json:"head_sha"`
	FetchedAt time.Time `json:"fetched_at"`
}

type PluginEntry

type PluginEntry struct {
	Version     string `json:"version"`
	ManifestSHA string `json:"manifest_sha"`
	Enabled     bool   `json:"enabled"`
}

type Targets

type Targets struct {
	SchemaVersion int                    `json:"schema_version"`
	Files         map[string]FileEntry   `json:"files,omitempty"`
	Keys          map[string]KeyEntry    `json:"keys,omitempty"`
	Marketplaces  map[string]Marketplace `json:"marketplaces,omitempty"`
	Plugins       map[string]PluginEntry `json:"plugins,omitempty"`
}

Targets is the root state document.

func Load

func Load(path string) (*Targets, error)

Load reads targets.json from path. If the file is missing, returns a fresh state at the current SchemaVersion.

func New

func New() *Targets

New returns a fresh empty Targets at SchemaVersion.

Jump to

Keyboard shortcuts

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