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