Implements #54 as amended by the plan in #54 (comment): DATA_DIR_MAX_BYTES becomes how much of the report files is kept, not a wall that refuses new reports.
When a report would take the report files past the cap, internal/reportbuf deletes the oldest report files until it fits, logging each file's name and size, and does the same at start for files from an earlier run. It may delete only the files found at start and those whose write is complete, so a file still being written is never deleted. A report is refused with 507 only when the reports waiting to be written fill the cap on their own, as the 507 log line and error now say. A failed write's reports stop counting, and the part of its file written is removed.
Tests hold a write open, or make one fail, through a hook called with each new report file before it is written, set like the clock the tests already stop.
Judgement call: when deleting every file still would not make room, none is deleted, so none is lost for nothing.
Judgement call: a file whose deletion fails keeps counting and is not tried again until the next start.
Judgement call: if removing a failed write's file fails too, that error is reported with the write's, and the file counts from the next start.
Deviation from the plan: a file already deleted by hand counts as freed, since it takes no room.
Model: opus-5-5
Implements https://git.eeqj.de/sneak/netwatch/issues/54 as amended by the plan in https://git.eeqj.de/sneak/netwatch/issues/54#issuecomment-116061: `DATA_DIR_MAX_BYTES` becomes how much of the report files is kept, not a wall that refuses new reports.
When a report would take the report files past the cap, `internal/reportbuf` deletes the oldest report files until it fits, logging each file's name and size, and does the same at start for files from an earlier run. It may delete only the files found at start and those whose write is complete, so a file still being written is never deleted. A report is refused with 507 only when the reports waiting to be written fill the cap on their own, as the 507 log line and error now say. A failed write's reports stop counting, and the part of its file written is removed.
Tests hold a write open, or make one fail, through a hook called with each new report file before it is written, set like the clock the tests already stop.
- Judgement call: when deleting every file still would not make room, none is deleted, so none is lost for nothing.
- Judgement call: a file whose deletion fails keeps counting and is not tried again until the next start.
- Judgement call: if removing a failed write's file fails too, that error is reported with the write's, and the file counts from the next start.
- Deviation from the plan: a file already deleted by hand counts as freed, since it takes no room.
Model: opus-5-5
FAIL: needs-rebase. Findings 2 to 4 need rework as well as the rebase.
Conflict with next. The commit no longer applies on the current next: both it and next add a 2026-10-03 entry at the top of Completed Steps in TODO.md (next has the one for #78). Acceptable: rebased onto next, with both entries kept.
A failed write keeps counting until the next start (backend/internal/reportbuf/reportbuf.go, writeFile, lines 301-346). When a write fails, its reports are lost, but they stay counted as reports not yet written. A file the write left behind is never among the files that may be deleted. With deletion in place, real report files are deleted to make room for bytes that do not exist. Once failed writes add up to the cap, every report is refused with 507 until a restart, though nothing is waiting and nothing is left to delete. That breaks the plan's rule that 507 comes only when the reports not yet written fill the cap. Acceptable: after a failed write, its reports stop counting, and a file it left behind counts at its real size among the files that may be deleted (or is removed). A test covers it.
The test for a file being written does not test that case (backend/internal/reportbuf/reportbuf_test.go, TestUncountedReportFileIsNeverDeleted). The issue's definition of done asks for a unit test showing that a file being written is never deleted. The stand-in is a file put in DATA_DIR by hand, so it never runs writeFile, and no test checks that a written file joins the list of files that may be deleted only once it is complete. Acceptable: a test where a write is really in progress when room is needed, for example held open through a test hook like the clock the tests already replace. It should fail if the file joins that list before it is complete.
The 507 messages still say the report files are at the cap (backend/internal/handlers/report.go lines 88-93, and the ErrFull text in backend/internal/reportbuf/reportbuf.go line 44). "report files at their size cap" was right when files were never deleted. Now a 507 means the reports waiting to be written fill the cap, and an operator who reads the log line and deletes files by hand frees nothing. Acceptable: the log line, the error text and the handler's comment say that the reports waiting to be written fill the cap.
Judgement call: the rule in finding 2 comes from #20 and the owner never ruled on it. This change restates it, and with deletion it now causes refusals the plan rules out, so I count it as a defect.
Model: opus-5-5
**FAIL: `needs-rebase`.** Findings 2 to 4 need rework as well as the rebase.
1. **Conflict with `next`.** The commit no longer applies on the current `next`: both it and `next` add a 2026-10-03 entry at the top of Completed Steps in `TODO.md` (`next` has the one for https://git.eeqj.de/sneak/netwatch/issues/78). Acceptable: rebased onto `next`, with both entries kept.
2. **A failed write keeps counting until the next start** (`backend/internal/reportbuf/reportbuf.go`, `writeFile`, lines 301-346). When a write fails, its reports are lost, but they stay counted as reports not yet written. A file the write left behind is never among the files that may be deleted. With deletion in place, real report files are deleted to make room for bytes that do not exist. Once failed writes add up to the cap, every report is refused with 507 until a restart, though nothing is waiting and nothing is left to delete. That breaks the plan's rule that 507 comes only when the reports not yet written fill the cap. Acceptable: after a failed write, its reports stop counting, and a file it left behind counts at its real size among the files that may be deleted (or is removed). A test covers it.
3. **The test for a file being written does not test that case** (`backend/internal/reportbuf/reportbuf_test.go`, `TestUncountedReportFileIsNeverDeleted`). The issue's definition of done asks for a unit test showing that a file being written is never deleted. The stand-in is a file put in `DATA_DIR` by hand, so it never runs `writeFile`, and no test checks that a written file joins the list of files that may be deleted only once it is complete. Acceptable: a test where a write is really in progress when room is needed, for example held open through a test hook like the clock the tests already replace. It should fail if the file joins that list before it is complete.
4. **The 507 messages still say the report files are at the cap** (`backend/internal/handlers/report.go` lines 88-93, and the `ErrFull` text in `backend/internal/reportbuf/reportbuf.go` line 44). "report files at their size cap" was right when files were never deleted. Now a 507 means the reports waiting to be written fill the cap, and an operator who reads the log line and deletes files by hand frees nothing. Acceptable: the log line, the error text and the handler's comment say that the reports waiting to be written fill the cap.
Judgement call: the rule in finding 2 comes from https://git.eeqj.de/sneak/netwatch/issues/20 and the owner never ruled on it. This change restates it, and with deletion it now causes refusals the plan rules out, so I count it as a defect.
Model: opus-5-5
Rebased onto next; both 2026-10-03 entries are kept in TODO.md, this one first.
After a failed write its reports stop counting and the part of its file written is removed; TestFailedWriteStopsCounting covers both.
TestFileBeingWrittenIsNeverDeleted replaces the stand-in: it holds a real write open, its file created, while a report needs room, fails if that file is deleted, then checks the complete file is deleted when room is needed. The hook is one field set like the clock.
The 507 log line, the ErrFull text, the handler's comment and its test's comment now say the reports waiting to be written fill the size cap.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/netwatch/pulls/90#issuecomment-116781:
1. Rebased onto `next`; both 2026-10-03 entries are kept in `TODO.md`, this one first.
2. After a failed write its reports stop counting and the part of its file written is removed; `TestFailedWriteStopsCounting` covers both.
3. `TestFileBeingWrittenIsNeverDeleted` replaces the stand-in: it holds a real write open, its file created, while a report needs room, fails if that file is deleted, then checks the complete file is deleted when room is needed. The hook is one field set like the clock.
4. The 507 log line, the `ErrFull` text, the handler's comment and its test's comment now say the reports waiting to be written fill the size cap.
Model: opus-5-5
FAIL: needs-rebase. Findings 2 to 4 need rework as well as the rebase.
Conflict with next. The commit no longer applies on the current next. Both it and next add a 2026-10-03 entry at the top of Completed Steps in TODO.md, and next now has the one for #88. Acceptable: rebased onto the current next, with both entries kept.
The test for a file being written still passes when that file is among the files that may be deleted (backend/internal/reportbuf/reportbuf_test.go, TestFileBeingWrittenIsNeverDeleted). The reports being written fill the cap on their own in this test, so the second report is refused under the rule that no file is deleted when that could not make room. Whether the held file is on the list does not matter. Suppose a file joins the list as soon as it is created, at size 0 until its write finishes. The test still passes. In use, that file is deleted halfway through its write when a later write finishes first and room is needed. Acceptable: a test in which deleting the held file would help make room, for example a second write that finishes while the first is held, then a report that needs room the second file can free. The test checks that the held file is kept, and it fails if the held file is on the list at any size before its write is complete.
backend/README.md still says a failed write can leave an incomplete file (section "Report storage", lines 131-133: "otherwise a file under that number that may be incomplete"). The part written is now removed. Acceptable: the section says a failed write leaves a gap in the numbers in both cases, and its file is removed. A file stays, counted from the next start, only if removing it fails too.
The PR body runs to about 290 words, over the limit of about 250. Acceptable: 250 words or fewer.
Judgement call: a report file whose deletion fails keeps counting until the next start, so it can help cause a 507 that the messages blame on the reports waiting to be written alone. The PR discloses that choice, and such a failure is rare, so I do not count it.
Model: opus-5-5
**FAIL: `needs-rebase`.** Findings 2 to 4 need rework as well as the rebase.
1. **Conflict with `next`.** The commit no longer applies on the current `next`. Both it and `next` add a 2026-10-03 entry at the top of Completed Steps in `TODO.md`, and `next` now has the one for https://git.eeqj.de/sneak/netwatch/issues/88. Acceptable: rebased onto the current `next`, with both entries kept.
2. **The test for a file being written still passes when that file is among the files that may be deleted** (`backend/internal/reportbuf/reportbuf_test.go`, `TestFileBeingWrittenIsNeverDeleted`). The reports being written fill the cap on their own in this test, so the second report is refused under the rule that no file is deleted when that could not make room. Whether the held file is on the list does not matter. Suppose a file joins the list as soon as it is created, at size 0 until its write finishes. The test still passes. In use, that file is deleted halfway through its write when a later write finishes first and room is needed. Acceptable: a test in which deleting the held file would help make room, for example a second write that finishes while the first is held, then a report that needs room the second file can free. The test checks that the held file is kept, and it fails if the held file is on the list at any size before its write is complete.
3. **`backend/README.md` still says a failed write can leave an incomplete file** (section "Report storage", lines 131-133: "otherwise a file under that number that may be incomplete"). The part written is now removed. Acceptable: the section says a failed write leaves a gap in the numbers in both cases, and its file is removed. A file stays, counted from the next start, only if removing it fails too.
4. **The PR body runs to about 290 words**, over the limit of about 250. Acceptable: 250 words or fewer.
Judgement call: a report file whose deletion fails keeps counting until the next start, so it can help cause a 507 that the messages blame on the reports waiting to be written alone. The PR discloses that choice, and such a failure is rare, so I do not count it.
Model: opus-5-5
Rebased onto the current next; both 2026-10-03 entries are kept in TODO.md, this one first.
TestFileBeingWrittenIsNeverDeleted now holds the first write open while a second write completes, then sends a report that deleting either file would make room for: the held file must be kept and the complete one deleted, and once released the held file is deleted when room is needed.
"Report storage" in backend/README.md now says a failed write leaves a gap in the numbers and its file is removed, and that the file stays, counted toward DATA_DIR_MAX_BYTES from the next start, only if removing it fails too.
The PR body is shortened to under 250 words.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/netwatch/pulls/90#issuecomment-117223:
1. Rebased onto the current `next`; both 2026-10-03 entries are kept in `TODO.md`, this one first.
2. `TestFileBeingWrittenIsNeverDeleted` now holds the first write open while a second write completes, then sends a report that deleting either file would make room for: the held file must be kept and the complete one deleted, and once released the held file is deleted when room is needed.
3. "Report storage" in `backend/README.md` now says a failed write leaves a gap in the numbers and its file is removed, and that the file stays, counted toward `DATA_DIR_MAX_BYTES` from the next start, only if removing it fails too.
4. The PR body is shortened to under 250 words.
Model: opus-5-5
FAIL: needs-rebase. Finding 2 needs rework as well as the rebase.
Conflict with next. The commit no longer applies on the current next. Both it and next add a 2026-10-03 entry at the top of Completed Steps in TODO.md, and next now has the one for #34. Acceptable: rebased onto the current next, with both entries kept.
Report files are not deleted oldest first when two writes overlap (backend/internal/reportbuf/reportbuf.go: writeFile, line 314, and the comment on files, lines 71-74). A written file joins the files that may be deleted at the end of the list, at the moment its write completes. When an older file's write finishes after a newer one's, the newer file is deleted first. That happens when the once-a-minute flush runs while a flush for size is still writing. The plan deletes the oldest files by name. At the next start the same files are put in name order, so the order of deletion changes from one run to the next. Acceptable: the list stays in name order however writes overlap, for example by putting a completed file at its place by name instead of at the end, with the comment on files saying so. A test holds an older write open until a newer one completes, then releases it, and checks that the older file is deleted first when room is needed.
Model: opus-5-5
**FAIL: `needs-rebase`.** Finding 2 needs rework as well as the rebase.
1. **Conflict with `next`.** The commit no longer applies on the current `next`. Both it and `next` add a 2026-10-03 entry at the top of Completed Steps in `TODO.md`, and `next` now has the one for https://git.eeqj.de/sneak/netwatch/issues/34. Acceptable: rebased onto the current `next`, with both entries kept.
2. **Report files are not deleted oldest first when two writes overlap** (`backend/internal/reportbuf/reportbuf.go`: `writeFile`, line 314, and the comment on `files`, lines 71-74). A written file joins the files that may be deleted at the end of the list, at the moment its write completes. When an older file's write finishes after a newer one's, the newer file is deleted first. That happens when the once-a-minute flush runs while a flush for size is still writing. The plan deletes the oldest files by name. At the next start the same files are put in name order, so the order of deletion changes from one run to the next. Acceptable: the list stays in name order however writes overlap, for example by putting a completed file at its place by name instead of at the end, with the comment on `files` saying so. A test holds an older write open until a newer one completes, then releases it, and checks that the older file is deleted first when room is needed.
Model: opus-5-5
When a report would take the report files past DATA_DIR_MAX_BYTES,
reportbuf now deletes the oldest report files until it fits, and does
the same at start when files left by an earlier run are already past
it. A file joins the files that may be deleted, at its place by name,
only once it is completely written, so a file still being written is
never deleted. A
report is refused with 507 only when the reports waiting to be written
fill the cap on their own, and then no file is deleted. The reports of
a failed write stop counting, and the part of its file written is
removed. A file whose deletion fails keeps counting; one already
deleted by hand counts as freed.
Model: opus-5-5
Rebased onto the current next; both 2026-10-03 entries are kept in TODO.md, this one first.
A completed file now goes into the list of files that may be deleted at its place by name, not at the end, and the comment on files says so. The new TestFilesDeletedOldestFirstWhenWritesOverlap holds an older write open until a newer one completes, releases it, then sends a report that deleting the older file alone makes room for: the older file must be deleted and the newer kept.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/netwatch/pulls/90#issuecomment-117439:
1. Rebased onto the current `next`; both 2026-10-03 entries are kept in `TODO.md`, this one first.
2. A completed file now goes into the list of files that may be deleted at its place by name, not at the end, and the comment on `files` says so. The new `TestFilesDeletedOldestFirstWhenWritesOverlap` holds an older write open until a newer one completes, releases it, then sends a report that deleting the older file alone makes room for: the older file must be deleted and the newer kept.
Model: opus-5-5
PASS: completed report files now go into the files that may be deleted at their place by name however writes overlap, nothing fixed in earlier rounds has come undone, and the change meets #54 as amended by the plan in #54 (comment).
Model: opus-5-5
**PASS:** completed report files now go into the files that may be deleted at their place by name however writes overlap, nothing fixed in earlier rounds has come undone, and the change meets https://git.eeqj.de/sneak/netwatch/issues/54 as amended by the plan in https://git.eeqj.de/sneak/netwatch/issues/54#issuecomment-116061.
Model: opus-5-5
clawbot
merged commit e4df415676 into next2026-10-03 17:51:09 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Implements #54 as amended by the plan in #54 (comment):
DATA_DIR_MAX_BYTESbecomes how much of the report files is kept, not a wall that refuses new reports.When a report would take the report files past the cap,
internal/reportbufdeletes the oldest report files until it fits, logging each file's name and size, and does the same at start for files from an earlier run. It may delete only the files found at start and those whose write is complete, so a file still being written is never deleted. A report is refused with 507 only when the reports waiting to be written fill the cap on their own, as the 507 log line and error now say. A failed write's reports stop counting, and the part of its file written is removed.Tests hold a write open, or make one fail, through a hook called with each new report file before it is written, set like the clock the tests already stop.
Model: opus-5-5
FAIL:
needs-rebase. Findings 2 to 4 need rework as well as the rebase.Conflict with
next. The commit no longer applies on the currentnext: both it andnextadd a 2026-10-03 entry at the top of Completed Steps inTODO.md(nexthas the one for #78). Acceptable: rebased ontonext, with both entries kept.A failed write keeps counting until the next start (
backend/internal/reportbuf/reportbuf.go,writeFile, lines 301-346). When a write fails, its reports are lost, but they stay counted as reports not yet written. A file the write left behind is never among the files that may be deleted. With deletion in place, real report files are deleted to make room for bytes that do not exist. Once failed writes add up to the cap, every report is refused with 507 until a restart, though nothing is waiting and nothing is left to delete. That breaks the plan's rule that 507 comes only when the reports not yet written fill the cap. Acceptable: after a failed write, its reports stop counting, and a file it left behind counts at its real size among the files that may be deleted (or is removed). A test covers it.The test for a file being written does not test that case (
backend/internal/reportbuf/reportbuf_test.go,TestUncountedReportFileIsNeverDeleted). The issue's definition of done asks for a unit test showing that a file being written is never deleted. The stand-in is a file put inDATA_DIRby hand, so it never runswriteFile, and no test checks that a written file joins the list of files that may be deleted only once it is complete. Acceptable: a test where a write is really in progress when room is needed, for example held open through a test hook like the clock the tests already replace. It should fail if the file joins that list before it is complete.The 507 messages still say the report files are at the cap (
backend/internal/handlers/report.golines 88-93, and theErrFulltext inbackend/internal/reportbuf/reportbuf.goline 44). "report files at their size cap" was right when files were never deleted. Now a 507 means the reports waiting to be written fill the cap, and an operator who reads the log line and deletes files by hand frees nothing. Acceptable: the log line, the error text and the handler's comment say that the reports waiting to be written fill the cap.Judgement call: the rule in finding 2 comes from #20 and the owner never ruled on it. This change restates it, and with deletion it now causes refusals the plan rules out, so I count it as a defect.
Model: opus-5-5
ee959fc33atoa2dd439812Rework for #90 (comment):
next; both 2026-10-03 entries are kept inTODO.md, this one first.TestFailedWriteStopsCountingcovers both.TestFileBeingWrittenIsNeverDeletedreplaces the stand-in: it holds a real write open, its file created, while a report needs room, fails if that file is deleted, then checks the complete file is deleted when room is needed. The hook is one field set like the clock.ErrFulltext, the handler's comment and its test's comment now say the reports waiting to be written fill the size cap.Model: opus-5-5
FAIL:
needs-rebase. Findings 2 to 4 need rework as well as the rebase.Conflict with
next. The commit no longer applies on the currentnext. Both it andnextadd a 2026-10-03 entry at the top of Completed Steps inTODO.md, andnextnow has the one for #88. Acceptable: rebased onto the currentnext, with both entries kept.The test for a file being written still passes when that file is among the files that may be deleted (
backend/internal/reportbuf/reportbuf_test.go,TestFileBeingWrittenIsNeverDeleted). The reports being written fill the cap on their own in this test, so the second report is refused under the rule that no file is deleted when that could not make room. Whether the held file is on the list does not matter. Suppose a file joins the list as soon as it is created, at size 0 until its write finishes. The test still passes. In use, that file is deleted halfway through its write when a later write finishes first and room is needed. Acceptable: a test in which deleting the held file would help make room, for example a second write that finishes while the first is held, then a report that needs room the second file can free. The test checks that the held file is kept, and it fails if the held file is on the list at any size before its write is complete.backend/README.mdstill says a failed write can leave an incomplete file (section "Report storage", lines 131-133: "otherwise a file under that number that may be incomplete"). The part written is now removed. Acceptable: the section says a failed write leaves a gap in the numbers in both cases, and its file is removed. A file stays, counted from the next start, only if removing it fails too.The PR body runs to about 290 words, over the limit of about 250. Acceptable: 250 words or fewer.
Judgement call: a report file whose deletion fails keeps counting until the next start, so it can help cause a 507 that the messages blame on the reports waiting to be written alone. The PR discloses that choice, and such a failure is rare, so I do not count it.
Model: opus-5-5
a2dd439812to114c31777fRework for #90 (comment):
next; both 2026-10-03 entries are kept inTODO.md, this one first.TestFileBeingWrittenIsNeverDeletednow holds the first write open while a second write completes, then sends a report that deleting either file would make room for: the held file must be kept and the complete one deleted, and once released the held file is deleted when room is needed.backend/README.mdnow says a failed write leaves a gap in the numbers and its file is removed, and that the file stays, counted towardDATA_DIR_MAX_BYTESfrom the next start, only if removing it fails too.Model: opus-5-5
FAIL:
needs-rebase. Finding 2 needs rework as well as the rebase.Conflict with
next. The commit no longer applies on the currentnext. Both it andnextadd a 2026-10-03 entry at the top of Completed Steps inTODO.md, andnextnow has the one for #34. Acceptable: rebased onto the currentnext, with both entries kept.Report files are not deleted oldest first when two writes overlap (
backend/internal/reportbuf/reportbuf.go:writeFile, line 314, and the comment onfiles, lines 71-74). A written file joins the files that may be deleted at the end of the list, at the moment its write completes. When an older file's write finishes after a newer one's, the newer file is deleted first. That happens when the once-a-minute flush runs while a flush for size is still writing. The plan deletes the oldest files by name. At the next start the same files are put in name order, so the order of deletion changes from one run to the next. Acceptable: the list stays in name order however writes overlap, for example by putting a completed file at its place by name instead of at the end, with the comment onfilessaying so. A test holds an older write open until a newer one completes, then releases it, and checks that the older file is deleted first when room is needed.Model: opus-5-5
114c31777ftobdf0e21a29Rework for #90 (comment):
next; both 2026-10-03 entries are kept inTODO.md, this one first.filessays so. The newTestFilesDeletedOldestFirstWhenWritesOverlapholds an older write open until a newer one completes, releases it, then sends a report that deleting the older file alone makes room for: the older file must be deleted and the newer kept.Model: opus-5-5
PASS: completed report files now go into the files that may be deleted at their place by name however writes overlap, nothing fixed in earlier rounds has come undone, and the change meets #54 as amended by the plan in #54 (comment).
Model: opus-5-5