From 01352ab3dab5164f177938d1923b132a541cbaec Mon Sep 17 00:00:00 2001 From: Adrian Bonpin Date: Wed, 7 Oct 2026 17:03:29 +0800 Subject: [PATCH] docs: the alert shows size and age, not the old line count The code never reads a file it is about to replace just to count its lines: stat gives the size and the age, and the new content's line count is known without reading anything. The spec overpromised the old count. --- .../superpowers/plans/2026-10-07-file-system-access.md | 2 +- .../specs/2026-10-07-file-system-access-design.md | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/superpowers/plans/2026-10-07-file-system-access.md b/docs/superpowers/plans/2026-10-07-file-system-access.md index 59275e9..70b98ab 100644 --- a/docs/superpowers/plans/2026-10-07-file-system-access.md +++ b/docs/superpowers/plans/2026-10-07-file-system-access.md @@ -1134,7 +1134,7 @@ describe("the mutating operations", () => { allow, ); expect(asked[0].operation).toBe("overwrite"); - expect(asked[0].details.join(" ")).toContain("Replaces 14 bytes, 4 lines"); + expect(asked[0].details.join(" ")).toContain("Replaces 14 bytes"); }); it("creates missing folders, and says so before it does", async () => { diff --git a/docs/superpowers/specs/2026-10-07-file-system-access-design.md b/docs/superpowers/specs/2026-10-07-file-system-access-design.md index cb376df..ce57537 100644 --- a/docs/superpowers/specs/2026-10-07-file-system-access-design.md +++ b/docs/superpowers/specs/2026-10-07-file-system-access-design.md @@ -115,8 +115,10 @@ ones that follow from them are recorded here. a move that silently destroys the file it lands on. The model can delete the destination first, which asks again under A2. - **A6. `write_file` overwrites without a separate flag, and discloses which it is.** - The approval alert says whether the file exists, how big it is, and how many lines - it has, so an overwrite is never a surprise. A `mustNotExist` flag would add a + The approval alert says whether the file exists, how big it is and when it last + changed, so an overwrite is never a surprise. The old line count is deliberately not + among them: counting it would mean reading a file Lam is about to replace, and stat + gives the size and the age for free. A `mustNotExist` flag would add a round trip and a second approval to the common case to guard against something the alert already shows. - **A7. Relative paths resolve against `$HOME`, not the working directory.** A launcher @@ -221,7 +223,7 @@ ask rather than retry in the second. | `list_directory` | `path`, `hidden?` | Directories first, then files, each sorted. Capped at `MAX_LIST_ENTRIES` (200), with a count of what was left out. | | `search_files` | `path`, `pattern`, `contains?` | `pattern` is a glob (`*`, `?`, `**`) matched against the basename; `contains` is a case-insensitive substring test on the file's first `MAX_SEARCH_BYTES` (64 KB). Capped at `MAX_SEARCH_RESULTS` (50) and `MAX_SEARCH_DEPTH` (8). A path that fails the read check is skipped, contents and all, so the denylist holds for search results as well as for direct reads. | | `read_file` | `path`, `offset?`, `limit?` | Numbered lines, stopping at whichever comes first of the default 200 lines and `MAX_READ_CHARS` (8000) characters, with the notice naming that cap so it is clear which one stopped it. Binary content (a NUL byte in the first 8 KB) is refused with its size and detected type rather than returned as mojibake. | -| `write_file` | `path`, `content` | Creates the parent directory chain when it is missing, disclosed in the alert, since `~/Downloads/reports/may.md` is a normal thing to ask for and there is no separate mkdir tool. Reports `Created` or `Overwrote (was 1,240 bytes, 40 lines)`. | +| `write_file` | `path`, `content` | Creates the parent directory chain when it is missing, disclosed in the alert, since `~/Downloads/reports/may.md` is a normal thing to ask for and there is no separate mkdir tool. Reports `Created` or `Overwrote (...)` with the size and line count of what it wrote. | | `edit_file` | `path`, `old_string`, `new_string`, `all?` | Exact substitution. Refuses when `old_string` occurs zero times or more than once without `all`, naming the count so the model can add context instead of guessing. | | `delete_path` | `path` | One file, or an empty directory. A non-empty directory is refused with its entry count (A4). | | `move_path` | `from`, `to` | Both the source and the destination are policy checked and both are approved. Refuses an existing destination (A5). | @@ -256,7 +258,7 @@ left to the implementation: ``` Title: Overwrite report.md? Body: /Users/me/Downloads/report.md - Replaces 1,240 bytes, 40 lines, last changed 3 days ago. + Replaces 1,240 bytes, last changed 3 days ago. New content is 2,180 bytes, 61 lines. [Allow] [Decline] ```