Documentation
¶
Overview ¶
Package fs provides filesystem helpers for the agent-memory project:
- Atomic writes (atomic.go): write a file such that readers always see either the pre-write or post-write contents, never a partial state.
- Path validation (paths.go): refuse paths that escape the .agent-memory/ root or target server-managed derived files.
See docs/patterns/atomic-writes.md and docs/patterns/path-validation.md.
Example (WriteAtomic) ¶
Example_writeAtomic shows the canonical use of WriteAtomic.
dir, _ := os.MkdirTemp("", "example-")
defer os.RemoveAll(dir)
path := filepath.Join(dir, "hello.txt")
if err := WriteAtomic(path, []byte("hello, world\n"), 0644); err != nil {
fmt.Println("error:", err)
return
}
got, _ := os.ReadFile(path)
fmt.Print(string(got))
Output: hello, world
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsDerivedPath ¶
IsDerivedPath reports whether rel refers to a server-managed derived file that agents must never write through ValidateMemoryPath.
rel is expected to use forward slashes (the canonical form used in the design doc and manifest examples). Callers that have OS-separator paths should pass them through filepath.ToSlash first.
The list:
- meta/index.sqlite and its WAL/SHM companions (the FTS5 shadow index).
- meta/lock (the advisory-lock file).
Files that are server-interpreted but stored as canonical Markdown or YAML (manifest.yaml, schema.yaml, index.md) are NOT derived in this sense — agents reach them through the normal staged/applied write machinery.
func PathExists ¶
PathExists is a small convenience used by callers and tests.
func ValidateMemoryPath ¶
ValidateMemoryPath validates a relative path intended to reference content inside the .agent-memory/ directory of a repository.
- root must be the absolute path to .agent-memory/.
- rel is a path relative to root. It may use either forward slashes or the OS path separator; the result uses the OS separator.
On success, returns the cleaned absolute path inside root.
Rejects:
- non-absolute root (programmer error).
- absolute rel paths.
- rel paths containing ".." segments (including those that Clean resolves to leaving rel above root).
- rel paths that target server-managed derived files (see IsDerivedPath).
Symlink resolution is intentionally not performed here; callers that dereference symlinks should re-validate the resolved path before any filesystem access.
func WriteAtomic ¶
WriteAtomic writes data to path atomically using the canonical write-temp-then-rename pattern:
- Create a temp file in the same directory as path (cross-device renames are not atomic on POSIX).
- Write all of data, then fsync the temp file.
- Rename the temp file to path. Both NTFS and POSIX guarantee rename is atomic when source and destination are on the same filesystem.
- On POSIX, fsync the parent directory so the rename survives power loss. Windows skips this step (NTFS handles rename durability internally and directory handles do not support Sync there).
Readers of path always see either the previous contents or the new contents, never a partial write. If any step fails, the temp file is removed and the original target (if any) is left untouched.
Constraints:
- path must be absolute.
- The parent directory must exist.
- perm is applied to both the temp file (briefly) and the final file.
Types ¶
This section is empty.