Skip to content

host: Clear truncates the error log's leaf but leaves the rotated diagnostics.jsonl.1 on disk #2345

Closed

Description

@HugoXK

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.

Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: 4251909595cd4627953f9f22aa2fb041
Branch: dev/4-p517-diag-clear-rotated
Base: 7226d74
At: 2026-11-04T03:25:37Z

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.

Written-by: FlyBot Lead

What happens today

The Feedback page's Clear removes what the app shows but not what it has written to disk. core/src/host/diagnostics.js keeps one rotated generation:

  • the append path renames the leaf aside past 1 MiB — if (size > LOG_MAX_BYTES) await rename(logPath, \${logPath}.1`) (:159, LOG_MAX_BYTES = 1 << 20at:17`);
  • clear() (:284-295) writes an empty leaf — await writeFile(logPath, '', 'utf8') (:292) — and never touches diagnostics.jsonl.1;
  • the endpoint (core/src/host/channel.js:663-665) only calls clear(), and no code anywhere reads or removes the rotated file;
  • the client still reports success: core/src/client/feedback.js:87 says Cleared the error log.

So a host whose log has rotated once keeps up to 1 MiB of older errors on disk after the user asked for them to be cleared, while the UI says they are gone. core/README.md:189 documents the file as It moves to diagnostics.jsonl.1 past 1 MB. Safe to delete. — the app itself never deletes it.

Reproduction (live 7226d745, the module's own install() against a temp home): write ~700 entries of ~2 KB so the log crosses 1 MiB and rotates, then call rt.diagnostics.clear() — the same call the Clear button makes:

before: leaf 396,480 B   .1 1,048,910 B   entries 200   report.total 200
after:  leaf       0 B   .1 1,048,910 B   entries   0   report.total   0

A real host shows the same shape: <home>/logs/diagnostics.jsonl.1 1,048,774 B / 2,065 entries covering 2026-10-31T16:38:05Z → 2026-11-02T19:07:36Z, beside a 142,162 B leaf; Clear removes the leaf's rows and leaves those 2,065 behind.

Expected

For the same <home>, after Clear neither logs/diagnostics.jsonl nor logs/diagnostics.jsonl.1 holds error text.

  • clear() removes \${logPath}.1` (rm(..., { force: true })) **inside the same writing` chain and after the same guard** as the leaf truncation, so it cannot race an append or a rotation.
  • The rotated path gets the same leaf question as the leaf: fileKind(...) === 'other' (a symbolic link, a hard link, a directory, or a check that could not run) is not ours to delete — leave it and keep the existing one-line stderr refusal, exactly as #2089/#2159 settled for writes.
  • config.diagnosticsFile === false still means no file at all.
  • A host that has never rotated behaves exactly as today (no .1, nothing extra to delete).

Scope

Five files, +71/−7, measured on a bench branch cut from 7226d745:

  • core/src/host/diagnostics.js +5/−1 — clear() removes \${logPath}.1`withrm(..., { force: true }), inside the same writingchain and after the samefileKind(...) === 'other'guard as the leaf truncation;toFile === false` still returns before any file work.
  • core/test/diagnostics.test.js +26/−1 — clear removes the rotated log, not only the leaf: writes past LOG_MAX_BYTES, asserts the rotation happened, clears, then asserts neither file holds text. The existing clear cases stay green (:101 basic, :123-149 link, :545-570 hard link).
  • docs/subsystems/core-host.md +1/−1 — one line naming the rotated generation in the Clear behaviour (arch-docs requires a note for the owned path).
  • patches/ds-bot/0001-core-fixes.patch +12/−2 and patches/ds-bot/0007-version-and-tooling.patch +27/−2 — the generator's output for the two files above; this PR runs generate and includes them.

core/README.md:189 ("Safe to delete") stays as it is: after this change the sentence is still true, and the app now acts on it. Tier T2 by the live risk-rules.json at 7226d745 (core/src/host/diagnostics.js is T2, the other three paths T1). Bundle lane: it rewrites 0001 and 0007.

Red first (clean 7226d745, tests only): the file runs 28 tests → 27 success + 0 cancelled + 1 failure, the one failure being clear removes the rotated log, not only the leaf. After the fix: 28 of 28, and the full core suite 2,756 / 0 failures.

XS. Not in scope: reading the rotated generation (Download / Report on GitHub still only see the leaf) — that is P-518, a separate enhancement.

Duplicate check (live 7226d745)

  • #2302 / PR #2333 ("a read-only window's Feedback Clear truncates the shared diagnostics log") is about who may truncate, not about the rotated generation: it moved diagnostics-clear out of READS and left clear()'s file set unchanged.
  • #2089 / #2094 / #2159 / #2162 are about writing through a link; they settled the leaf guard this issue reuses for the rotated path.
  • #2339 / PR #2341 (landed 2026-11-04T03:11:42Z as 7226d745) changed the same file's neighbours for text bounds, not this file.
  • GitHub search diagnostics clear, diagnostics.jsonl, in:title clear returns no issue or PR about the rotated file surviving Clear; code search for diagnostics.jsonl.1 on live main hits only core/README.md:189 and its ds-bot/ mirror.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions