filetrack

package
v0.9.21 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Overview

Package filetrack records file changes made by agent tools so sessions can expose a cumulative diff (baseline = file state at first touch in a session). Bulky before/after contents live in a dedicated SQLite database as content-addressed compressed blobs, keeping the main sessions DB slim.

Index

Constants

View Source
const (
	ObservationUnclaimed        = "unclaimed_transition"
	ObservationMaterialized     = "materialized_output"
	ObservationUnconfirmedClaim = "unconfirmed_claim"
	ObservationClaimMismatch    = "claim_mismatch"
	ObservationClaimConflict    = "claim_conflict"
	ObservationIncomplete       = "observation_incomplete"
)
View Source
const (
	DefaultMaxFileBytes    = config.DefaultFileTrackingMaxFileBytes    // per-file content cap
	DefaultMaxSessionBytes = config.DefaultFileTrackingMaxSessionBytes // retained-content budget per session
	DefaultMaxTotalBytes   = config.DefaultFileTrackingMaxTotalBytes   // whole-database size cap (across sessions)
)

Default caps, overridable via config.

View Source
const (
	KindCreate = "create"
	KindModify = "modify"
	KindDelete = "delete"
)

Change kinds.

View Source
const (
	ProvenanceDirect            = "direct"
	ProvenanceDeclaredTransform = "declared_transform"
	ProvenanceDeclaredGenerate  = "declared_generate"
	ProvenanceLegacyUnverified  = "legacy_unverified"

	ClaimTransform   = "transform"
	ClaimGenerate    = "generate"
	ClaimMaterialize = "materialize"

	CoverageComplete    = "complete"
	CoverageTruncated   = "truncated"
	CoverageUnavailable = "unavailable"

	BaselineNormal           = "normal"
	BaselinePreexistingDirty = "preexisting_dirty"
	BaselineUnknown          = "unknown"

	ContentRetained           = "retained"
	ContentRetainedImage      = "retained_image"
	ContentBinaryUnrenderable = "binary_unrenderable"
	ContentOversized          = "oversized"
	ContentSessionBudget      = "session_budget"
	ContentStoreBudget        = "store_budget"
	ContentBeforeUnknown      = "before_unknown"
	ContentAfterUnknown       = "after_unknown"
	ContentBothUnknown        = "both_unknown"
)

Closed attribution and evidence values persisted by the tracker.

Variables

View Source
var ErrInvalidDiffSide = errors.New("invalid file diff side")

ErrInvalidDiffSide means the requested side does not exist for the resolved change kind, such as the baseline side of a newly created file.

Functions

func CountAddsDels

func CountAddsDels(oldContent, newContent []byte) (adds, dels int)

CountAddsDels counts added and removed lines between two contents. Empty/nil sides are treated as a missing file (pure create/delete).

func IsRenderableText added in v0.9.11

func IsRenderableText(data []byte) bool

IsRenderableText reports whether data is valid UTF-8 text and not a browser-renderable image or other binary content.

func LineCount added in v0.0.407

func LineCount(content []byte) int

LineCount reports the number of displayable lines in retained file content.

Types

type Change

type Change struct {
	Seq              int64
	EventSeq         int64
	RunID            string
	Path             string
	Kind             string
	ToolName         string
	ToolCallID       string
	BeforeHash       string // empty when absent/unknown/not retained
	AfterHash        string
	BeforeSize       int64
	AfterSize        int64
	Adds             int
	Dels             int
	Truncated        bool
	IsBinary         bool
	Provenance       string
	Provenances      []string
	ClaimKind        string
	ClaimPattern     string
	ClaimLiteral     bool
	ClaimCoverage    string
	BaselineState    string
	ContentStatus    string
	ContentAvailable bool
}

Change is one recorded change row.

type ChangeRecord

type ChangeRecord struct {
	SessionID  string
	RunID      string
	ToolName   string
	ToolCallID string
	Path       string // absolute path

	// Provenance is mandatory for new callers of RecordAttributedChange.
	Provenance    string
	ClaimKind     string
	ClaimPattern  string
	ClaimLiteral  bool
	ClaimCoverage string
	BaselineState string

	Before []byte // content before the change (ignored when BeforeMissing/BeforeUnknown)
	After  []byte // content after the change (ignored when AfterMissing/AfterUnknown)

	BeforeMissing bool // file did not exist before the change
	AfterMissing  bool // file does not exist after the change (deletion)
	BeforeUnknown bool // file existed before but its content was not captured
	AfterUnknown  bool // file exists after but its content was not captured (e.g. oversized)

	// Size hints for unknown-content sides (from stat); ignored when the
	// corresponding content is provided.
	BeforeSizeHint int64
	AfterSizeHint  int64
}

ChangeRecord describes one before→after attributed file transition to record.

type CumulativeChange

type CumulativeChange struct {
	Path             string   `json:"path"`
	Kind             string   `json:"kind"`
	Adds             int      `json:"adds"`
	Dels             int      `json:"dels"`
	Truncated        bool     `json:"truncated"`
	Seq              int64    `json:"seq"`                    // latest change sequence for this path in the session
	SnapshotSeq      int64    `json:"snapshot_seq,omitempty"` // compatibility identity for a multi-run window
	Provenance       string   `json:"provenance,omitempty"`
	Provenances      []string `json:"provenances,omitempty"`
	BaselineState    string   `json:"baseline_state,omitempty"`
	ContentStatus    string   `json:"content_status,omitempty"`
	ContentAvailable bool     `json:"content_available"`
	ClaimCoverage    string   `json:"claim_coverage,omitempty"`
}

CumulativeChange summarizes a file's net attributed change relative to the selected baseline.

type DiffLine

type DiffLine struct {
	T string `json:"t"` // "ctx" | "add" | "del"
	S string `json:"s"` // line text without the diff prefix
}

DiffLine is one row of a structured diff hunk.

type FileDiffContent

type FileDiffContent struct {
	Path             string
	Kind             string
	Before           []byte
	After            []byte
	Truncated        bool
	IsImage          bool
	ContentStatus    string
	ContentAvailable bool
	Provenance       string
	BaselineState    string
	ClaimCoverage    string
}

FileDiffContent holds the baseline and current contents for one file.

type FileDiffSide added in v0.0.333

type FileDiffSide struct {
	Path      string
	Kind      string
	Side      string
	Data      []byte
	MediaType string
}

FileDiffSide contains one retained side of a browser-renderable image diff.

type FileDiffTextSide added in v0.9.11

type FileDiffTextSide struct {
	Path string
	Kind string
	Side string
	Data []byte
}

FileDiffTextSide contains one retained textual side of a file diff.

type FilesystemObservation added in v0.9.0

type FilesystemObservation struct {
	ID               int64          `json:"id"`
	SessionID        string         `json:"-"`
	RunID            string         `json:"-"`
	EventSeq         int64          `json:"event_seq"`
	ToolName         string         `json:"-"`
	ToolCallID       string         `json:"-"`
	Classification   string         `json:"classification"`
	Root             string         `json:"root,omitempty"`
	CreatedCount     int            `json:"created_count"`
	ModifiedCount    int            `json:"modified_count"`
	DeletedCount     int            `json:"deleted_count"`
	SampledPaths     []string       `json:"sampled_paths,omitempty"`
	SamplesTruncated bool           `json:"samples_truncated,omitempty"`
	CoverageStatus   string         `json:"coverage_status"`
	Details          map[string]any `json:"details,omitempty"`
}

type Hunk

type Hunk struct {
	OldStart int        `json:"old_start"`
	NewStart int        `json:"new_start"`
	Lines    []DiffLine `json:"lines"`
}

Hunk is one contiguous block of a structured diff.

func BuildHunks

func BuildHunks(path string, oldContent, newContent []byte) []Hunk

BuildHunks computes a structured diff between two file contents. Returns nil when the contents are identical.

func BuildHunksWithContext added in v0.0.407

func BuildHunksWithContext(path string, oldContent, newContent []byte, contextLines int) []Hunk

BuildHunksWithContext computes a structured diff with at least contextLines unchanged lines around each change. The underlying diff library emits three lines of context; larger requests extend and merge those hunks using the original retained contents.

type Options

type Options struct {
	MaxFileBytes               int   // 0 = DefaultMaxFileBytes
	MaxSessionBytes            int   // 0 = DefaultMaxSessionBytes
	MaxTotalBytes              int64 // 0 = DefaultMaxTotalBytes; whole-database size cap enforced live and by GC
	MaxObservationRows         int   // 0 = 10,000; independent sidecar row cap
	MaxObservationSessionRows  int   // 0 = 1,000; independent per-session sidecar row cap
	MaxObservationBytes        int64 // 0 = 16 MiB metadata cap
	MaxObservationSessionBytes int64 // 0 = 2 MiB per-session metadata cap
	MaxObservationAgeDays      int   // 0 = 30
}

Options configures a Store.

type OutputClaimDiagnostic added in v0.9.0

type OutputClaimDiagnostic struct {
	NormalizedPattern string `json:"normalized_pattern"`
	ClaimKind         string `json:"claim_kind"`
	Reason            string `json:"reason"`
	CoverageStatus    string `json:"coverage_status"`
	MatchingPathCount int    `json:"matching_path_count"`
	Message           string `json:"message,omitempty"`
}

type Recorder

type Recorder struct {
	// contains filtered or unexported fields
}

Recorder adapts a Store to the tools-facing FileChangeRecorder interface. Recording is best-effort: failures are reported once on stderr and never surface to the calling tool — tracking must not break editing.

func NewRecorder

func NewRecorder(store *Store) *Recorder

NewRecorder wraps a store in a Recorder.

func (*Recorder) HasAttributedPath added in v0.9.0

func (r *Recorder) HasAttributedPath(ctx context.Context, sessionID, path string) bool

func (*Recorder) MaxFileBytes

func (r *Recorder) MaxFileBytes() int

MaxFileBytes returns the per-file content cap.

func (*Recorder) RecordAttributedChange added in v0.9.0

func (r *Recorder) RecordAttributedChange(ctx context.Context, rec ChangeRecord) (*llm.FileChange, error)

RecordAttributedChange persists one explicitly classified attributed transition.

func (*Recorder) RecordChange

func (r *Recorder) RecordChange(ctx context.Context, rec ChangeRecord) *llm.FileChange

RecordChange is the compatibility adapter for older direct integrations.

func (*Recorder) RecordFileTrackingRunComplete added in v0.9.0

func (r *Recorder) RecordFileTrackingRunComplete(ctx context.Context, sessionID, runID string) error

func (*Recorder) RecordFileTrackingRunStart added in v0.9.0

func (r *Recorder) RecordFileTrackingRunStart(ctx context.Context, sessionID, runID string) error

func (*Recorder) RecordFilesystemObservation added in v0.9.0

func (r *Recorder) RecordFilesystemObservation(ctx context.Context, obs FilesystemObservation) (*llm.FilesystemObservationSummary, error)

RecordFilesystemObservation persists metadata in the independent sidecar.

func (*Recorder) RecordRunComplete added in v0.9.0

func (r *Recorder) RecordRunComplete(ctx context.Context, run RunRecord) error

func (*Recorder) RecordRunStart added in v0.9.0

func (r *Recorder) RecordRunStart(ctx context.Context, run RunRecord) error

func (*Recorder) SessionPaths

func (r *Recorder) SessionPaths(ctx context.Context, sessionID string) []string

SessionPaths returns paths already recorded for the session (best-effort).

type RunRecord added in v0.9.0

type RunRecord struct {
	SessionID   string
	RunID       string
	StartedAt   time.Time
	CompletedAt time.Time
}

type SnapshotToken added in v0.9.0

type SnapshotToken struct {
	AttributedEventSeq  int64 `json:"a"`
	ObservationEventSeq int64 `json:"o"`
	RunGeneration       int64 `json:"r"`
}

func DecodeSnapshotToken added in v0.9.0

func DecodeSnapshotToken(value string) (SnapshotToken, error)

func (SnapshotToken) Encode added in v0.9.0

func (t SnapshotToken) Encode() string

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store persists file-change history in a dedicated SQLite database.

func Open

func Open(path string, opts Options) (*Store, error)

Open opens (creating if necessary) the file-change history database at path.

func (*Store) Close

func (s *Store) Close() error

Close closes both attributed and observation databases.

func (*Store) CurrentSnapshotToken added in v0.9.0

func (s *Store) CurrentSnapshotToken(ctx context.Context, sessionID string) string

func (*Store) GC

func (s *Store) GC(ctx context.Context, sessionsDBPath string, maxAgeDays int) error

GC removes change rows for sessions that no longer exist in the sessions DB (and rows older than maxAgeDays when > 0), then sweeps unreferenced blobs.

func (*Store) GetFileDiffContent

func (s *Store) GetFileDiffContent(ctx context.Context, sessionID, path string) (*FileDiffContent, error)

GetFileDiffContent returns the baseline and current contents for one path in a session, or nil when the path has no net change recorded.

func (*Store) GetFileDiffSide added in v0.0.333

func (s *Store) GetFileDiffSide(ctx context.Context, sessionID, path, side string) (*FileDiffSide, error)

GetFileDiffSide returns one retained side of an image diff without loading the other side. It returns nil for unknown paths, truncated content, and non-image diffs.

func (*Store) GetFileDiffTextSide added in v0.9.11

func (s *Store) GetFileDiffTextSide(ctx context.Context, sessionID, path, side string) (*FileDiffTextSide, error)

GetFileDiffTextSide returns one retained UTF-8 text side without loading the other side. It returns nil for unknown, truncated, binary, and image content.

func (*Store) GetRecentRunFileDiffContent added in v0.0.404

func (s *Store) GetRecentRunFileDiffContent(ctx context.Context, sessionID, path string, runs int, snapshotSeq int64) (*FileDiffContent, error)

GetRecentRunFileDiffContent returns one file diff across the latest runs that recorded file changes. A positive snapshotSeq pins the rolling window.

func (*Store) GetRecentRunFileDiffSide added in v0.0.404

func (s *Store) GetRecentRunFileDiffSide(ctx context.Context, sessionID, path, side string, runs int, snapshotSeq int64) (*FileDiffSide, error)

GetRecentRunFileDiffSide returns one retained image side across the latest runs that recorded file changes. A positive snapshotSeq pins the window.

func (*Store) GetRecentRunFileDiffTextSide added in v0.9.11

func (s *Store) GetRecentRunFileDiffTextSide(ctx context.Context, sessionID, path, side string, runs int, snapshotSeq int64) (*FileDiffTextSide, error)

GetRecentRunFileDiffTextSide returns one retained UTF-8 text side across the latest runs that recorded file changes. A positive snapshotSeq pins the window.

func (*Store) HasAttributedPath added in v0.9.0

func (s *Store) HasAttributedPath(ctx context.Context, sessionID, path string) (bool, error)

func (*Store) ListRecentRunChanges added in v0.0.404

func (s *Store) ListRecentRunChanges(ctx context.Context, sessionID string, runs int) ([]CumulativeChange, error)

ListRecentRunChanges returns the cumulative changes across the latest file tracking runs, including an in-progress run. Rows without run identities are excluded.

func (*Store) ListRunObservations added in v0.9.0

func (s *Store) ListRunObservations(ctx context.Context, sessionID string, runIDs []string) ([]FilesystemObservation, error)

func (*Store) ListSessionChanges

func (s *Store) ListSessionChanges(ctx context.Context, sessionID string) ([]CumulativeChange, error)

ListSessionChanges returns the cumulative per-file changes for a session, sorted by path. Net no-ops are omitted.

func (*Store) MaxFileBytes

func (s *Store) MaxFileBytes() int

MaxFileBytes returns the per-file content cap.

func (*Store) RecentRunIDs added in v0.9.0

func (s *Store) RecentRunIDs(ctx context.Context, sessionID string, limit int) ([]string, error)

func (*Store) RecordAttributedChange added in v0.9.0

func (s *Store) RecordAttributedChange(ctx context.Context, rec ChangeRecord) (*Change, error)

RecordAttributedChange records a classified, witnessed/claim-verified file transition. Missing or incompatible attribution metadata is rejected.

func (*Store) RecordChange

func (s *Store) RecordChange(ctx context.Context, rec ChangeRecord) (*Change, error)

RecordChange is retained for source compatibility with older direct callers. New code must use RecordAttributedChange and provide explicit provenance. The compatibility path never upgrades shell detections: shell rows remain legacy unverified and are excluded from attributed views.

func (*Store) RecordFilesystemObservation added in v0.9.0

func (s *Store) RecordFilesystemObservation(ctx context.Context, obs FilesystemObservation) (*FilesystemObservation, error)

func (*Store) RecordRunComplete added in v0.9.0

func (s *Store) RecordRunComplete(ctx context.Context, run RunRecord) error

func (*Store) RecordRunStart added in v0.9.0

func (s *Store) RecordRunStart(ctx context.Context, run RunRecord) error

func (*Store) SessionPaths

func (s *Store) SessionPaths(ctx context.Context, sessionID string) ([]string, error)

SessionPaths returns the distinct absolute paths already recorded for a session.

Jump to

Keyboard shortcuts

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