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 ¶
const LastRunFile = "last-run.json"
LastRunFile is the basename of the per-machine run record inside .state/.
const SchemaVersion = 1
Variables ¶
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 SaveLastRun ¶ added in v0.11.0
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
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.
type Marketplace ¶
type PluginEntry ¶
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.