= infra-tools-filesystem == purpose Provides three filesystem tool implementations for the Correx tool system: `FileReadTool` (read file content with optional line range), `FileWriteTool` (write or delete files with artifact capture via CAS), and `FileEditTool` (append, replace, or patch file content). All tools enforce path allowlisting and validate parameters before execution. == responsibilities * Read file contents with optional 1-indexed line range slicing * Write content to files, optionally capturing artifacts to the CAS store * Delete files on disk * Edit files via three modes: append (add to end), replace (exact-target string replacement), patch (apply unified diff via external `patch` command) * Validate paths against configured allowlists * Report affected paths for sandbox backup/diff tracking == non-responsibilities * Do not implement sandboxed execution — that belongs to `infra:tools` (`SandboxedToolExecutor`) * Do not define tool contracts — that belongs to `core:tools` * Do not manage file permissions beyond optional POSIX mode setting * Do not perform approval gating == key types === FileReadTool * **kind**: class * **purpose**: Reads a file from disk within allowed paths, with optional start/end line range. Tier T1. * **fields**: `allowedPaths` (set of permitted root directories) === FileWriteTool * **kind**: class * **purpose**: Writes content to a file or deletes a file, validates path against allowlist, optionally captures a `FileWrittenArtifact` to the CAS store. Tier T2. * **fields**: `allowedPaths`, `artifactStore`, `materializingWriter`, `sandboxRoot`, `workingDir` === FileEditTool * **kind**: class * **purpose**: Edits a file via three operations: `append`, `replace` (exact single-occurrence string replacement), or `patch` (applies unified diff via external `patch` binary). Tier T3. * **fields**: `allowedPaths`, `workingDir` == event flow *Inbound:* `ToolRequest` with parameters (`path`, `content`, `operation`, etc.) *Outbound:* None directly. Event emission is handled by the wrapping `SandboxedToolExecutor`. The tools return `ToolResult.Success` or `ToolResult.Failure` synchronously. == integration points * `core:tools.contract` — `Tool`, `ToolExecutor`, `ToolResult`, `FileAffectingTool`, `ToolCapability`, `ValidationResult` * `core:approvals` — `Tier` * `core:artifactstore` — `ArtifactStore` * `core:artifacts` — `MaterializingArtifactWriter`, `MaterializationResult`, `FileWrittenArtifact`, `FileWrittenPayload` * `infra:artifacts-cas` — used by `FileWriteTool` for CAS artifact storage (via writer interface) == invariants * All tools validate path against allowed paths — if `allowedPaths` is empty, validation fails ("No paths are allowed") * `FileWriteTool` prevents directory traversal via path normalization * `FileEditTool.replace()` requires exactly one occurrence of the target string — zero or multiple occurrences produce a failure * `FileEditTool.patch()` requires the external `patch` utility to be available * All tools run on `Dispatchers.IO` for blocking filesystem operations == PlantUML diagram [plantuml, infra-tools-filesystem, "png"] ---- include::../../diagrams/infra-tools-filesystem.puml[] ---- == known issues * `FileEditTool.patch()` shells out to the `patch` binary — not available on all platforms; no error if `patch` is missing beyond a failed `ProcessBuilder` * `FileWriteTool.storeArtifact()` silently logs on materialization failure rather than failing the tool call * `FileEditTool.replace()` reads the entire file into memory — unsuitable for very large files * `FileWriteTool` and `FileEditTool` have duplicated path resolution logic == open questions * Should `FileEditTool` support a pure-Kotlin patching implementation to remove `patch` dependency? * Should line-range edits (insert before/after line N) be added?