Documentation
¶
Overview ¶
Auto-skip learning for ChangeTracker shell-mutation tracking.
After the first walk of a fat directory (one whose file count exceeds autoSkipFileCountThreshold or autoSkipCumulativeThreshold), the dir is added to autoSkipDirs so subsequent walks skip it entirely. Learned sets persist across agent sessions via change_tracking_shell_persist.go.
Mutation recording and bulk rollup for ChangeTracker shell-mutation tracking.
Takes the diff from before/after snapshots and records TrackedFileChange entries, collapsing high-churn directories into bulk rollups when appropriate.
Shell-mutation tracking: captures before/after snapshots around shell_command invocations to detect file changes the structured tools miss (sed, mv, rm, etc.). Supporting code: change_tracking_snapshot.go, change_tracking_mutations.go, change_tracking_autoskip.go, change_tracking_shell_persist.go.
Persistence for the ChangeTracker's adaptive auto-skip set.
The walker learns "fat directories" on first visit (those with more immediate child files than autoSkipFileCountThreshold) and skips them on subsequent walks within the same session. Without persistence, every new agent session re-learns from scratch — paying the first-walk cost over and over for the same dirs.
This file persists the learned set to `~/.config/sprout/shell_skip_dirs.json`, keyed by absolute workspace root, so subsequent sessions in the same workspace inherit the learning. The file is best-effort: read failures fall back to an empty set (re-learn), write failures log a warning.
To prevent unbounded growth across many workspaces, the file caps at maxPersistedWorkspaces entries — least-recently-used workspaces are evicted first when the cap is exceeded.
Snapshot walking and file I/O for ChangeTracker shell-mutation tracking.
Walks the workspace tree before and after shell commands, capturing file bytes inside size/binary limits, then diffing the two snapshots.
SP-141 phase 2: the pure transcript-manifest half of the old pkg/agent/transcript_snapshot.go. The snapshot/diff structs stay in pkg/agent (their State field is *agent.ConversationState, a core type that moves last); everything here is agent-free logic: file-change manifest extraction, compacted-segment block round-tripping, message-source annotation, snapshot directory layout + working-dir path normalization, retention pruning, and label sanitizing.
Index ¶
- Constants
- func BackupFileWithExt(src, ext string) error
- func FormatFileChangesForSummary(changes []TranscriptFileChange) string
- func ListTranscriptSnapshots(sessionID, workingDir string) ([]string, error)
- func NormalizeWorkingDirectory(workingDir string) (string, error)
- func PruneTranscriptDir(dir string)
- func SanitizeSnapshotLabel(label string) string
- func SetTrackedChangeCaps(maxChanges int, maxBytes int64)
- func TranscriptSessionDir(sessionID, workingDir string) (string, error)
- func WorkingDirectoryScopeHash(workingDir string) string
- func WriteFileAtomic(path string, data []byte, perm os.FileMode) error
- type AgentView
- type ChangeTracker
- func (ct *ChangeTracker) ApplyShellWalkConfig(cfg ShellWalkConfig)
- func (ct *ChangeTracker) Clear()
- func (ct *ChangeTracker) CollectFileChangesForCheckpoint() ([]CheckpointFileChange, string)
- func (ct *ChangeTracker) Commit(llmResponse string, conversation []api.Message) error
- func (ct *ChangeTracker) Disable()
- func (ct *ChangeTracker) Enable()
- func (ct *ChangeTracker) GenerateAISummary() (string, error)
- func (ct *ChangeTracker) GetChangeCount() int
- func (ct *ChangeTracker) GetChanges() []TrackedFileChange
- func (ct *ChangeTracker) GetRevisionID() string
- func (ct *ChangeTracker) GetSummary() string
- func (ct *ChangeTracker) GetTrackedFiles() []string
- func (ct *ChangeTracker) IsEnabled() bool
- func (ct *ChangeTracker) IsOutsideWorkspace(filePath string) bool
- func (ct *ChangeTracker) MarkTurnStart()
- func (ct *ChangeTracker) MergeChild(changes []TrackedFileChange, source string)
- func (ct *ChangeTracker) PrimeShellTracking(workDir string)
- func (ct *ChangeTracker) RebaseShellTracking(workDir string)
- func (ct *ChangeTracker) RecordRevert(filePath, before, after string, existsAfter bool, toolCall string)
- func (ct *ChangeTracker) RecordShellMutations(before, after map[string]*shellSnapshotEntry, toolCall string)
- func (ct *ChangeTracker) Reset(instructions string)
- func (ct *ChangeTracker) SetRevisionIDForTest(id string)
- func (ct *ChangeTracker) SetSessionID(sessionID string)
- func (ct *ChangeTracker) SetTrackedChangesForTesting(changes []TrackedFileChange)
- func (ct *ChangeTracker) SetView(view AgentView)
- func (ct *ChangeTracker) ShellCachePrimed() bool
- func (ct *ChangeTracker) SyncShellCacheForPath(path string)
- func (ct *ChangeTracker) TrackFileEdit(filePath string, originalContent string, newContent string) error
- func (ct *ChangeTracker) TrackFileWrite(filePath string, originalContent string, newContent string) error
- func (ct *ChangeTracker) TrackFileWriteState(filePath string, originalContent string, newContent string, existed bool) error
- func (ct *ChangeTracker) TrackShellCommandTurn(workDir, command string, destructive bool)
- func (ct *ChangeTracker) TrackShellTurn(workDir, toolCall string, destructive bool)
- func (ct *ChangeTracker) TrackerSessionID() string
- func (ct *ChangeTracker) TurnChangedPaths() []string
- type CheckpointFileChange
- type DebugLogger
- type MessageAnnotation
- type MessageSource
- type ShellWalkConfig
- type TrackedBulkItem
- type TrackedFileChange
- type TranscriptFileChange
- func ExtractFileChangesFromMessages(messages []api.Message) []TranscriptFileChange
- func FileChangesAdded(older, newer []TranscriptFileChange) []TranscriptFileChange
- func MergeFileChanges(primary, secondary []TranscriptFileChange) []TranscriptFileChange
- func TrackedChangesAsTranscript(changes []TrackedFileChange) []TranscriptFileChange
Constants ¶
const CompactedFilesHeader = "Files modified during compacted segment:"
CompactedFilesHeader marks the file-change manifest block that `/compact` appends to its LLM-generated summary. Future compactions re-parse this block to keep the running file-change history visible across the summary boundary — without this, every `/compact` would lose the manifest of files touched in the summarized turns. pkg/agent aliases this constant next to its snapshot methods.
const RedactedContentMarker = history.RedactedContentMarker
RedactedContentMarker aliases history.RedactedContentMarker so existing call sites within this package keep working.
Variables ¶
This section is empty.
Functions ¶
func BackupFileWithExt ¶
backupFileWithExt copies the current contents of src to src+ext, overwriting any previous backup. Best-effort: errors are returned to the caller, who treats them as non-fatal. Exported for pkg/agent's session-persistence forwarder (SP-141 phase 2).
func FormatFileChangesForSummary ¶
func FormatFileChangesForSummary(changes []TranscriptFileChange) string
FormatFileChangesForSummary renders a manifest into the canonical text block appended to a /compact summary. The format is chosen so parseCompactedFilesBlock can round-trip it back to TranscriptFileChange entries, preserving source / tool attribution across compaction boundaries. Returns the empty string when the manifest is empty so callers can skip appending altogether.
func ListTranscriptSnapshots ¶
ListTranscriptSnapshots returns snapshot file paths for the given session within the current workspace scope, sorted oldest-first.
func NormalizeWorkingDirectory ¶
NormalizeWorkingDirectory normalizes a working directory to a cleaned, symlink-resolved absolute path (empty resolves to the process CWD). Moved from pkg/agent/persistence_message.go in SP-141 phase 2; shared by transcript session-dir resolution and session persistence.
func PruneTranscriptDir ¶
func PruneTranscriptDir(dir string)
PruneTranscriptDir enforces the default per-bucket retention caps on a session's transcript directory. Exported for pkg/agent's CaptureTranscriptSnapshot (SP-141 phase 2).
func SanitizeSnapshotLabel ¶
SanitizeSnapshotLabel reduces a snapshot label to the canonical filename-safe form. Exported for pkg/agent's CaptureTranscriptSnapshot (SP-141 phase 2).
func SetTrackedChangeCaps ¶ added in v0.22.6
SetTrackedChangeCaps overrides the buffer caps (tests / tuning).
func TranscriptSessionDir ¶
TranscriptSessionDir returns the per-session transcript directory for the given session within the current workspace scope: <state>/transcripts/<scope-hash>/<session-id>. Exported for pkg/agent's CaptureTranscriptSnapshot (SP-141 phase 2).
func WorkingDirectoryScopeHash ¶
WorkingDirectoryScopeHash returns the short hash that scopes per-working-directory state directories (transcripts, scoped sessions). Moved from pkg/agent/persistence_message.go in SP-141 phase 2.
func WriteFileAtomic ¶
WriteFileAtomic durably replaces path's contents: write to a temp file in the same directory, fsync, then rename over the destination. A crash at any point leaves either the old or the new file — never a torn write. Exported because pkg/agent's session persistence shares it (SP-141 phase 2); the package-local writeFileAtomic name continues below.
Types ¶
type AgentView ¶
type AgentView interface {
// GetSessionID returns the session identifier ("" when unset).
GetSessionID() string
// GetModel returns the model identifier ("unknown" fallback is the
// tracker's, not the agent's).
GetModel() string
// GetWorkspaceRoot returns the logical workspace root ("" when unset).
GetWorkspaceRoot() string
// GenerateResponse runs an LLM completion (AI summary path).
GenerateResponse(messages []api.Message) (string, error)
// DebugLogger returns the agent logger or nil; the tracker logs
// debug-level shell-snapshot messages through it when non-nil.
DebugLogger() DebugLogger
// PublishFileChange emits a file_changed event for tracker-detected
// mutations. Implementations drop the event when no bus is wired.
PublishFileChange(filePath, action, content string)
// PublishRawFileChanged publishes a file_changed event WITHOUT the
// agent's event-metadata decoration (bulk rollups and destructive
// rollups publish command labels / directory paths, not real files,
// and historically bypassed decorateEventPayload via a raw
// eventBus.Publish). Implementations must preserve that behavior.
PublishRawFileChanged(eventType string, payload interface{})
}
AgentView is the seam between the change tracker and its host agent (SP-141 phase 2). The tracker lives in pkg/agent/changes; the agent lives in pkg/agent, and the import arrow is one-way (pkg/agent → changes), so the tracker sees only this narrow interface. pkg/agent adapts *Agent to it via the unexported changesAgentView adapter — the same shape phase 1 used for workflow.LoopAgent. Every method is nil-tolerant on the implementation side where the old direct-field access was nil-checked.
type ChangeTracker ¶
type ChangeTracker struct {
// contains filtered or unexported fields
}
ChangeTracker manages change tracking for the agent workflow
func NewChangeTracker ¶
func NewChangeTracker(view AgentView, instructions string) *ChangeTracker
NewChangeTracker creates a new change tracker for an agent session. view may be nil (bare trackers in tests); every view access is nil-guarded exactly where the old ct.agent accesses were.
func NewTrackerForTesting ¶
func NewTrackerForTesting(revisionID string) *ChangeTracker
NewTrackerForTesting returns a minimal enabled tracker for tests that exercise tracker methods directly: no agent view, no history-path initialization. revisionID may be empty.
func (*ChangeTracker) ApplyShellWalkConfig ¶
func (ct *ChangeTracker) ApplyShellWalkConfig(cfg ShellWalkConfig)
ApplyShellWalkConfig stamps resolved ChangeTrackingConfig values onto the tracker. Exported for pkg/agent's applyChangeTrackingConfig facade (SP-141 phase 2); zero-value MaxFiles/MaxTotalBytes/ MaxDuration/AutoSkipFileCountThreshold mean "no override — use the package default", exactly as before.
func (*ChangeTracker) Clear ¶
func (ct *ChangeTracker) Clear()
Clear clears all tracked changes (but keeps the tracker enabled). Also resets the shell-snapshot cache.
func (*ChangeTracker) CollectFileChangesForCheckpoint ¶
func (ct *ChangeTracker) CollectFileChangesForCheckpoint() ([]CheckpointFileChange, string)
CollectFileChangesForCheckpoint returns the (path, op) manifest of changes appended since the most recent checkpoint capture.
func (*ChangeTracker) Commit ¶
func (ct *ChangeTracker) Commit(llmResponse string, conversation []api.Message) error
Commit commits all tracked changes to the change tracker
func (*ChangeTracker) Disable ¶
func (ct *ChangeTracker) Disable()
Disable disables change tracking.
func (*ChangeTracker) GenerateAISummary ¶
func (ct *ChangeTracker) GenerateAISummary() (string, error)
GenerateAISummary creates an AI-generated summary of the changes.
func (*ChangeTracker) GetChangeCount ¶
func (ct *ChangeTracker) GetChangeCount() int
GetChangeCount returns the number of tracked changes
func (*ChangeTracker) GetChanges ¶
func (ct *ChangeTracker) GetChanges() []TrackedFileChange
GetChanges returns a copy of the tracked changes
func (*ChangeTracker) GetRevisionID ¶
func (ct *ChangeTracker) GetRevisionID() string
GetRevisionID returns the current revision ID
func (*ChangeTracker) GetSummary ¶
func (ct *ChangeTracker) GetSummary() string
GetSummary returns a deterministic summary of tracked changes (no LLM call).
func (*ChangeTracker) GetTrackedFiles ¶
func (ct *ChangeTracker) GetTrackedFiles() []string
GetTrackedFiles returns a list of files that have been modified
func (*ChangeTracker) IsEnabled ¶
func (ct *ChangeTracker) IsEnabled() bool
IsEnabled returns whether change tracking is enabled. Production code must call this instead of reading ct.enabled directly.
func (*ChangeTracker) IsOutsideWorkspace ¶
func (ct *ChangeTracker) IsOutsideWorkspace(filePath string) bool
IsOutsideWorkspace returns true if filePath is outside the agent's workspace root. Exported for pkg/agent's IsPathOutsideWorkspace facade (SP-141 phase 2).
func (*ChangeTracker) MarkTurnStart ¶ added in v0.23.0
func (ct *ChangeTracker) MarkTurnStart()
MarkTurnStart records the change count at the moment the current turn window opens. The agent calls it from EnableChangeTracking, which runs once per turn, so the window spans exactly that turn's own changes.
func (*ChangeTracker) MergeChild ¶
func (ct *ChangeTracker) MergeChild(changes []TrackedFileChange, source string)
MergeChild appends a subagent's tracked changes into this (parent) tracker so list_changes / recover_file / revert_my_changes see subagent edits too. Each merged entry is tagged with Source.
func (*ChangeTracker) PrimeShellTracking ¶
func (ct *ChangeTracker) PrimeShellTracking(workDir string)
PrimeShellTracking captures the workspace's current state as the baseline against which future shell_command invocations are diffed. Idempotent: a second call against the already-primed tracker is a no-op. Safe to call multiple times — only the first does work.
Lazy callers can skip this and rely on TrackShellTurn to auto-prime on first invocation; in that mode the first shell_command's own pre-state is captured but no changes are recorded for it (the initial walk IS the baseline). When the first shell command's mutations need to be tracked, PrimeShellTracking should be called from EnableChangeTracking so the baseline pre-exists.
func (*ChangeTracker) RebaseShellTracking ¶ added in v0.21.5
func (ct *ChangeTracker) RebaseShellTracking(workDir string)
RebaseShellTracking re-captures the workspace as the shell-diff baseline (priming it if needed). Called at the start of each primary-agent turn so the user's own edits between turns — files they create, change, or delete in their editor — become part of the baseline instead of being reported as the agent's mutations at its next shell command (where revert would then undo or delete the user's work).
func (*ChangeTracker) RecordRevert ¶ added in v0.21.5
func (ct *ChangeTracker) RecordRevert(filePath, before, after string, existsAfter bool, toolCall string)
RecordRevert records that a revert or recovery restored filePath, so the change history reflects it: list_changes nets the file out (it is back to its original state) instead of still listing the reverted change, and a later revert sees the restored content as current. existsAfter=false records the removal of a file the session created.
func (*ChangeTracker) RecordShellMutations ¶
func (ct *ChangeTracker) RecordShellMutations(before, after map[string]*shellSnapshotEntry, toolCall string)
RecordShellMutations diffs a pair of snapshots (before/after a shell_command invocation) and appends TrackedFileChange entries for every file that materially changed. Deduplicates against direct-tool hooks. Above shellBulkThreshold, collapses into bulk rollup.
Production diffing now happens inside TrackShellTurn (walkWorkspace computes pending changes against the live cache), so this exists for callers that hold explicit before/after snapshot pairs — the tests, and any future caller that captures snapshots out-of-band.
func (*ChangeTracker) Reset ¶
func (ct *ChangeTracker) Reset(instructions string)
Reset resets the change tracker with a new revision ID and instructions
func (*ChangeTracker) SetRevisionIDForTest ¶
func (ct *ChangeTracker) SetRevisionIDForTest(id string)
SetRevisionIDForTest stamps a fixed revision ID (tests need deterministic revision ids that the generated one can't provide).
func (*ChangeTracker) SetSessionID ¶
func (ct *ChangeTracker) SetSessionID(sessionID string)
func (*ChangeTracker) SetTrackedChangesForTesting ¶
func (ct *ChangeTracker) SetTrackedChangesForTesting(changes []TrackedFileChange)
SetTrackedChangesForTesting replaces the tracker's change buffer. Test seam: production code appends through the Track* methods.
func (*ChangeTracker) SetView ¶
func (ct *ChangeTracker) SetView(view AgentView)
SetView (re)binds the tracker's host view. Construction wires the view; tests that build a bare tracker (nil view) then attach an Agent rebind here, mirroring the old `tracker.agent = a` in-package assignment.
func (*ChangeTracker) ShellCachePrimed ¶
func (ct *ChangeTracker) ShellCachePrimed() bool
ShellCachePrimed reports whether the shell-snapshot baseline cache has been primed. Exported as part of the phase-2 seam: pkg/agent's TestAgent_EnableChangeTracking_SubagentSkipsShellPrime reads the old unexported shellCache field to distinguish eager (primary) from lazy (subagent) priming.
func (*ChangeTracker) SyncShellCacheForPath ¶
func (ct *ChangeTracker) SyncShellCacheForPath(path string)
SyncShellCacheForPath refreshes the shell cache entry for one path against its current on-disk state. Called by direct file-write hooks so the cache reflects writes the agent just performed.
func (*ChangeTracker) TrackFileEdit ¶
func (ct *ChangeTracker) TrackFileEdit(filePath string, originalContent string, newContent string) error
TrackFileEdit tracks an edit operation (EditFile tool)
func (*ChangeTracker) TrackFileWrite ¶
func (ct *ChangeTracker) TrackFileWrite(filePath string, originalContent string, newContent string) error
TrackFileWrite tracks a write operation (WriteFile tool). originalContent is the file's pre-write state, captured by the handler before the write. Empty means the file did not exist (a create). Never re-read filePath here: the write has already happened, so a re-read returns new content and recovery becomes a no-op.
func (*ChangeTracker) TrackFileWriteState ¶ added in v0.21.5
func (ct *ChangeTracker) TrackFileWriteState(filePath string, originalContent string, newContent string, existed bool) error
TrackFileWriteState is TrackFileWrite for callers that know whether the file existed before the write. An empty original alone can't distinguish a new file from an existing empty one (.gitkeep, __init__.py); recording the latter as a create made revert delete it.
func (*ChangeTracker) TrackShellCommandTurn ¶ added in v0.21.5
func (ct *ChangeTracker) TrackShellCommandTurn(workDir, command string, destructive bool)
TrackShellCommandTurn is TrackShellTurn for a shell_command run: entries keep the stable "shell_command" tool label, while the command text drives git-stash detection and names destructive rollup rows (so each rollup is distinguishable and individually recoverable).
func (*ChangeTracker) TrackShellTurn ¶
func (ct *ChangeTracker) TrackShellTurn(workDir, toolCall string, destructive bool)
TrackShellTurn diffs the workspace against the primed baseline, records mutations, and rebases the baseline to the new state. Auto-primes if the cache hasn't been primed yet (no changes recorded first time). `destructive` enables the safer mode that bypasses autoSkipDirs.
func (*ChangeTracker) TrackerSessionID ¶
func (ct *ChangeTracker) TrackerSessionID() string
TrackerSessionID exposes the tracker's current session identifier (the rotation contract: pkg/agent re-points it on session rotate and its test reads it back; SP-141 phase 2).
func (*ChangeTracker) TurnChangedPaths ¶ added in v0.23.0
func (ct *ChangeTracker) TurnChangedPaths() []string
TurnChangedPaths returns the distinct workspace paths of the changes recorded since the current turn window opened (MarkTurnStart), in first-seen order. It is non-destructive: the window is not consumed, so repeated calls and the separate checkpoint capture (CollectFileChangesForCheckpoint) are unaffected. Nil when the tracker is nil or disabled, or when the turn recorded no changes.
type CheckpointFileChange ¶
CheckpointFileChange is a single file-change entry in a turn checkpoint's manifest. Op is one of "A" (added), "M" (modified), "D" (deleted), "R" (renamed) to mirror git's status codes; anything else is "?" (other). pkg/agent aliases this type so the TurnCheckpoint JSON shape is unchanged (SP-141 phase 2).
type DebugLogger ¶
type DebugLogger interface {
Debug(format string, args ...interface{})
}
DebugLogger is the logger facet the tracker needs from the agent logger (mirrors *agent.AgentLogger.Debug).
type MessageAnnotation ¶
type MessageAnnotation struct {
Index int `json:"index"`
Role string `json:"role"`
Source MessageSource `json:"source"`
ContentChars int `json:"content_chars"`
ToolCallCount int `json:"tool_call_count,omitempty"`
FirstLine string `json:"first_line,omitempty"`
}
MessageAnnotation is the per-message diagnostic view. Index aligns 1:1 with TranscriptSnapshot.State.Messages.
func AnnotateMessages ¶
func AnnotateMessages(messages []api.Message) []MessageAnnotation
AnnotateMessages builds the per-message diagnostic annotations (exported for pkg/agent's BuildTranscriptSnapshot).
type MessageSource ¶
type MessageSource string
MessageSource tags how a message arrived in the live conversation. It is the single most useful diagnostic field in a snapshot: it tells a reader whether what the model sees at index i is the user's original turn, a turn collapsed to a rule-based heuristic bullet list, or a structural summary produced by seed's LLM summarizer.
const ( MessageSourceOriginal MessageSource = "original" MessageSourceLLMCheckpoint MessageSource = "llm_checkpoint" )
type ShellWalkConfig ¶
type ShellWalkConfig struct {
ShellWalkEnabled bool
MaxFiles int
MaxTotalBytes int64
MaxDuration time.Duration
AutoSkipFileCountThreshold int
}
ShellWalkConfig carries the per-tracker shell-walk budgets and thresholds stamped from the change_tracking config section. ApplyShellWalkConfig is the single write path (formerly pkg/agent's applyChangeTrackingConfig reaching directly into unexported fields).
type TrackedBulkItem ¶
type TrackedBulkItem struct {
FilePath string `json:"file_path"`
OriginalCode string `json:"original_code"`
NewCode string `json:"new_code"`
Operation string `json:"operation"` // "create" | "edit" | "delete"
}
TrackedBulkItem is the per-file payload packed inside a bulk TrackedFileChange.
type TrackedFileChange ¶
type TrackedFileChange struct {
FilePath string `json:"file_path"`
OriginalCode string `json:"original_code"`
NewCode string `json:"new_code"`
Operation string `json:"operation"` // "write", "edit", "create", "delete", "bulk"
Timestamp time.Time `json:"timestamp"`
ToolCall string `json:"tool_call"`
// Source attributes a change to its origin. Empty for direct
// primary-agent edits; "subagent:<persona>" for subagent changes.
Source string `json:"source,omitempty"`
// BulkCount is set on a rollup entry when a single shell command
// churns more than the bulk threshold. FilePath names the directory
// or command label and Operation is "bulk".
BulkCount int `json:"bulk_count,omitempty"`
// BulkItems carries the per-file recovery payload for bulk entries.
BulkItems []TrackedBulkItem `json:"bulk_items,omitempty"`
}
TrackedFileChange represents a file change made during agent execution
type TranscriptFileChange ¶
type TranscriptFileChange struct {
Path string `json:"path"`
Operation string `json:"operation"`
Source string `json:"source"`
ToolCall string `json:"tool_call,omitempty"`
Timestamp time.Time `json:"timestamp,omitempty"`
BulkCount int `json:"bulk_count,omitempty"`
}
TranscriptFileChange is the slim per-file projection embedded in a snapshot's top-level FileChanges field. It deliberately omits the full original/new file bodies that the ChangeTracker keeps for recovery — those can be multi-megabyte per file and would blow up snapshot size. The path, operation, and tool-call identifier give a reader enough to answer "what files were touched between snapshot A and snapshot B" without loading the bytes themselves.
Source distinguishes changes the primary agent made directly ("primary") from rollups parsed out of subagent tool results ("subagent"). The subagent's [subagent files modified] block is the authoritative per-call manifest, so the parser is a deterministic text scan rather than heuristic prose extraction.
func ExtractFileChangesFromMessages ¶
func ExtractFileChangesFromMessages(messages []api.Message) []TranscriptFileChange
ExtractFileChangesFromMessages walks the supplied message slice and returns a deduped manifest of files touched, drawn from three authoritative sources: (1) tool_calls on assistant messages whose function name is a known file-write tool, (2) `[subagent files modified]` blocks embedded by tool_handlers_subagent in subagent tool results, and (3) `Files modified during compacted segment:` blocks that this package writes when /compact substitutes a summary for prior turns. The third source is what carries the manifest forward across successive compactions.
func FileChangesAdded ¶
func FileChangesAdded(older, newer []TranscriptFileChange) []TranscriptFileChange
fileChangesAdded returns the entries present in newer but not in older, keyed by source+op+path. Used by /transcript diff to highlight what touched the filesystem between two snapshots. FileChangesAdded returns manifest entries present in newer but not older (exported for pkg/agent's DiffTranscriptSnapshots).
func MergeFileChanges ¶
func MergeFileChanges(primary, secondary []TranscriptFileChange) []TranscriptFileChange
MergeFileChanges dedupes and concatenates primary+secondary manifest entries (exported for pkg/agent's BuildTranscriptSnapshot).
func TrackedChangesAsTranscript ¶
func TrackedChangesAsTranscript(changes []TrackedFileChange) []TranscriptFileChange
trackedChangesAsTranscript projects the ChangeTracker's full TrackedFileChange records to the slim TranscriptFileChange shape and tags them as primary-source. The original/new bodies are intentionally dropped — they belong to the recovery flow, not to the diagnostic snapshot. TrackedChangesAsTranscript projects tracker changes to the slim manifest shape (exported for pkg/agent's BuildTranscriptSnapshot).
Source Files
¶
- atomic_write.go
- change_tracking.go
- change_tracking_autoskip.go
- change_tracking_checkpoint.go
- change_tracking_helpers.go
- change_tracking_history_adapter.go
- change_tracking_mutations.go
- change_tracking_paths.go
- change_tracking_shell.go
- change_tracking_shell_persist.go
- change_tracking_snapshot.go
- change_tracking_summary.go
- change_tracking_testing.go
- transcript_manifest.go