TermAl

Feature Reference: File Change Awareness

Status

Implemented for active local workspace/session roots, source tabs, diff preview tabs, file-tree refresh, git status refresh, stale-save protection, and agent-turn changed-file summaries.

Problem

Git diff and file editing both work, but the user does not get immediate visibility when an agent modifies files on disk. If a file is open in the TermAl editor, the visible buffer can become stale without any obvious signal.

The risk is worse when the user is also editing the same file:

TermAl needs a file-change awareness layer between the agent, disk, editor, and git state.

Related: Editor Buffer Persistence describes how an in-flight editor buffer (scroll, cursor, undo history) survives reloads and tab switches. Code Navigation MCP consumes the same file-change invalidation signal for source indexes. When a persisted buffer is rehydrated, the rebase / conflict semantics described in this document are what decide how that buffer meets the current on-disk version.

Goals

Non-goals for v1

Core idea

Introduce a file-change awareness pipeline:

filesystem watcher / git status
  -> backend coalesced change events
  -> SSE file-change notifications
  -> editor buffer freshness checks
  -> user-visible badges, banners, and diff entry points

The guiding rule is:

Never auto-overwrite a dirty user buffer.

Auto-reload is only safe when the open editor tab has no unsaved local edits.

Current implementation status

Implemented in the current tree:

Next-session handoff

Start by validating the implemented watcher path end to end before adding more UI surface area.

Run these checks first:

Manual test matrix:

Important implementation constraints for future changes:

User experience

Agent changes a file that is not open

Agent changes a clean open file

Agent changes a dirty open file

User saves a stale buffer

User edits survive an external reload

The ideal dirty-buffer flow is:

base version user opened
  -> user edits in TermAl
  -> user buffer

base version user opened
  -> agent edits on disk
  -> new disk version

diff(base, user buffer)
  -> apply onto new disk version
  -> rebased user buffer

If this applies cleanly, the user sees the agent’s disk changes and keeps their own unsaved edits. The editor stays dirty because the rebased buffer still has local changes relative to the new disk version.

Backend plan

File watching

Backend watcher for active workspace roots:

SSE event data for the workspaceFilesChanged event:

{
  "revision": 42,
  "changes": [
    {
      "path": "C:\\github\\Personal\\TermAl\\src\\runtime.rs",
      "kind": "modified",
      "mtimeMs": 1775860000000,
      "sizeBytes": 123456
    }
  ]
}

The event intentionally does not include content hashes for every changed file. The frontend treats watcher events as hints and fetches full file metadata only for open source tabs that match a changed path.

Save preconditions

Extend file write endpoints to accept a base content identity:

{
  "content": "...",
  "baseHash": "sha256:...",
  "overwrite": false
}

Rules:

Response shape for conflict:

{
  "error": "file changed on disk",
  "kind": "file-conflict",
  "path": "src/runtime.rs",
  "currentHash": "sha256:...",
  "baseHash": "sha256:..."
}

Agent turn changed-file summary

At agent turn start:

At agent turn completion:

Initial implementation can use git diff --name-status for git worktrees and fallback to watcher-collected changes for non-git roots.

Frontend plan

Editor buffer metadata

Every open file tab should track:

type FileBufferState = {
  path: string;
  loadedContent: string | null;
  loadedContentHash: string | null;
  loadedMtimeMs: number | null;
  currentBufferHash: string;
  dirty: boolean;
  staleOnDisk: boolean;
  conflict: boolean;
};

When a workspaceFilesChanged event arrives:

Rebase and merge options

There are several implementation choices for preserving user edits after an external reload.

Option 1: Safety-only conflict banner

Behavior:

Pros:

Cons:

Option 2: Text patch reapply

Behavior:

Pros:

Cons:

Option 3: Line-based three-way merge

Behavior:

Pros:

Cons:

Option 4: Monaco merge editor

Behavior:

Pros:

Cons:

Option 5: Backend merge helper

Behavior:

Pros:

Cons:

Start with Option 2: Text patch reapply, backed by the safety behavior from Option 1.

The first implementation should:

This gives the “awesome” behavior for the common case without blocking the first version on a full merge editor. After that works, upgrade the merge engine toward Option 3 and add Monaco merge UI from Option 4 for conflicts.

Badges and banners

Add visible state in the file explorer and editor tabs:

Conflict banner actions:

Agent changed-files card

After an agent turn, add a compact session card:

Agent changed files
M src/runtime.rs
M ui/src/App.tsx
A docs/features/file-change-awareness.md

Each row should support:

This makes agent edits visible without requiring the user to run git diff.

MVP

Implemented safety path:

Later enhancements

Open questions