Skip to content

host: a Clear with no log on disk prints "not truncated: ENOENT" while the window says Cleared - #2380

Merged
Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/1-clear-enoent-quiet
Nov 4, 2026
Merged

Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/1-clear-enoent-quiet

Conversation

@HugoXK

@HugoXK HugoXK commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #2379

Branch: dev/1-clear-enoent-quiet
Owner: Dev-1
Claim-Id: a575b70efc6a44c6bd2eba764db93030
Reviewer: Birfy
Tip: f70a950
Tree: 095d1c2b5497546a68b5446cb2f846f5175c5859
Base: 205bd44
Diff: 5 files, +115/−12
Tier: T3
why: core/test/diagnostics.test.js: /\.(only|skip)\(/ (the t.skip('root truncates a leaf without its write bit') line); core/src/host/diagnostics.js is T2 by path, the rest T1

What changed

Settings → Feedback's Clear on a home whose logs/ folder does not exist used to print [ds-bot] diagnostics log not truncated: ENOENT on the host's stderr while the window said Cleared the error log. — one click, two opposite reports, and the line went into support bundles where it could not be told apart from a leaf that really refused the truncate. The repository's own "no log folder" case (core/test/diagnostics.test.js) asserted {leaf:'absent',rotated:'none'} and passed while printing that line.

absent vs kept, in one line: ENOENT means there was nothing on disk to empty, so clear() answers {leaf:'absent',rotated:'none'} and prints nothing (the window's Cleared the error log. is what happened); any other code means the answer wanted to clear and could not, so it answers {leaf:'kept',…}, prints exactly one [ds-bot] diagnostics log not truncated: line carrying that code (EACCES for 0444), and leaves the bytes alone.

The 0444 leaf is unchanged: exactly one [ds-bot] diagnostics log not truncated: EACCES line, {leaf:'kept',rotated:'none'}, bytes kept — #2364's guarantee is not weakened. core/src/client/feedback.js is untouched, and so is core/client.js / patches/ds-bot/0008-client-bundle.patch.

The two tests now pin both halves: the no-log Clear asserts {leaf:'absent',rotated:'none'} with zero captured console.error lines and no logs/ folder created, and the 0444 Clear keeps its one-line EACCES assertion. console.error is captured in the test itself; no production code was changed to make it testable.

Verification at the tip

Verified tree: 095d1c2b5497546a68b5446cb2f846f5175c5859 — the push path rebuilt the head f70a950 from this same tree, and only that tree is what was checked here.
Ran:

  • red first, on a clean 205bd44f checkout with only the new tests: core/test/diagnostics.test.js → 41 tests / 40 pass / 1 fail; not ok 40 - a clear with no log on disk stays quiet / a Clear with nothing to empty does not claim it could not truncate / + '[ds-bot] diagnostics log not truncated: ENOENT' vs - []
  • after the fix: 41 / 41 pass / 0 fail
  • TZ=UTC ARCH_DOCS_BASE=205bd44f npm run verify → exit 0, 4786 tests / 4786 pass / 0 fail / 0 cancelled, arch-docs: OK (5 changed file(s))
  • node scripts/ds-bot-patches.mjs check → exit 0, 10 patches apply cleanly in order, core/ equals ds-bot/ + patches/ds-bot/
  • node scripts/ds-bot-patches.mjs canonical → exit 0, generate is a no-op
  • node scripts/ds-bot-patches.mjs generate twice → exit 0, patch sha256 identical both runs, working tree clean
  • node core/scripts/build-client.mjs --check → exit 0
  • node .github/scripts/changelog.mjs check → exit 0, 18 fragment(s) well formed
  • node .github/scripts/check-empty-catch.mjs → exit 0; node .github/scripts/check-mojibake.mjs --check → exit 0, 0 occurrences of U+FFFD
  • npm --prefix core run lint → exit 0 (part of verify)

Not run: the live endpoint (GET /api/diagnostics + Clear) against a running instance — no instance was started for this slice; the host function and the window's note are covered by the two unit tests above. No merge queue run was attempted.

Scope: core/src/host/diagnostics.js, core/test/diagnostics.test.js, changelog.d/2379-clear-enoent-quiet.fixed.md, plus the two regenerated patches patches/ds-bot/0001-core-fixes.patch and patches/ds-bot/0007-version-and-tooling.patch. Nothing else.

Docs-not-needed: docs/core-host.md already says absent means there was nothing on disk to clear (not a refusal) and names the one line a refused leaf prints (EACCES); it never described an ENOENT line, so no documentation sentence changes with this fix.

Checkpoint

{
  "pr": 2380,
  "claim": "Dev-1",
  "issue": 2379,
  "summary": "Clear on a home with no log file no longer prints `[ds-bot] diagnostics log not truncated: ENOENT`: the truncate's ENOENT means there was nothing on disk to empty, so the host stays silent and the window's `Cleared the error log.` is what happened. A leaf that is there and refuses the truncate (`0444` → `EACCES`) still prints exactly one line and still answers `leaf: 'kept'`, so #2364's guarantee holds. Both halves are pinned by tests that capture `console.error` themselves, and the two affected patches are the output of `generate`.",
  "files": ["core/src/host/diagnostics.js", "core/test/diagnostics.test.js", "changelog.d/2379-clear-enoent-quiet.fixed.md", "patches/ds-bot/0001-core-fixes.patch", "patches/ds-bot/0007-version-and-tooling.patch"],
  "checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=205bd44f npm run verify; ds-bot-patches check/canonical; generate x2; build-client --check; changelog check; check-empty-catch; check-mojibake", "result": "green", "at": "f70a9506621275b24483992f3dba8b34c402e5da" },
  "next": "none — ready for review at the pushed tip"
}

ENOENT from the truncate means the folder is not there, so there was nothing on disk to empty: the answer is already `absent` and the window reads "Cleared the error log.". Printing "not truncated" for it was a false alarm that reached support bundles and could not be told apart from a leaf that really refused the truncate. Only a non-ENOENT code prints the line now, on exactly one line, and ThinkFlowLab#2364's guarantee is unchanged.

Docs-not-needed: the core-host page already says `absent` means nothing was on disk to clear and names the one line for a refused leaf (`EACCES`); it never described an ENOENT line, so the sentence it writes is unchanged.
@HugoXK

HugoXK commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

@Birfy — review request for the queue (one comment, this tip only).

  • PR host: a Clear with no log on disk prints "not truncated: ENOENT" while the window says Cleared #2380 — host: a Clear with no log on disk prints "not truncated: ENOENT" while the window says Cleared, base 205bd44fa57cf1c1e4d520e04018b9c12774ad0b
  • Tip f70a9506621275b24483992f3dba8b34c402e5da, tree 095d1c2b5497546a68b5446cb2f846f5175c5859, single parent
  • 5 files +115/−12: core/src/host/diagnostics.js +11/−5, core/test/diagnostics.test.js +45/−0, changelog.d/2379-clear-enoent-quiet.fixed.md +1/−0, patches/ds-bot/0001-core-fixes.patch +12/−6, patches/ds-bot/0007-version-and-tooling.patch +46/−1
  • Tier T3 (core/test/diagnostics.test.js hits the live diffPatterns /\.(only|skip)\(/ through t.skip(…) on the root-only case; by path it is T2 core/src/host/**). checkpointReasons() on this exact body + this exact diff against the live .github/scripts/enqueue-rules.mjs → [] (pr: 2380, claim: "Dev-1", summary 538, checks.at = this tip)
  • Checks at this tip: 16 success + 0 cancelled + 1 failure — the failure is enqueue-guard: do not enqueue #2380: no Verifier report names the tip f70a95066212, which is what this comment is for
  • Non-draft, maintainer_can_modify: true, body opens with Fixes #2379

Request: a formal Verdict: PASS naming f70a9506621275b24483992f3dba8b34c402e5da. T3 needs the PASS on the current tip; a PASS on any other tip does not carry.

The contract this changes, in one line: ENOENT means there was nothing on disk to empty, so it stays leaf: 'absent' and prints nothing — the window's "Cleared the error log." is correct there; every other code stays leaf: 'kept' and prints exactly one [ds-bot] diagnostics log not truncated: <CODE> (no path), which is #2364's promise, and the throw is unchanged.

Evidence to re-run if you want it: on clean base 205bd44f with only the new test file, core/test/diagnostics.test.js is 41 = 40 pass + 1 fail, and the failing case prints the false alarm itself:

not ok 40 - a clear with no log on disk stays quiet
  a Clear with nothing to empty does not claim it could not truncate
  +   '[ds-bot] diagnostics log not truncated: ENOENT'
  -   []

After the fix the same file is 41/41 and the two #2364 regression cases stay green (a 0444 leaf still prints exactly one EACCES line). TZ=UTC ARCH_DOCS_BASE=205bd44f npm run verify → 4786 pass / 0 fail / 0 cancelled; generate is a no-op on a second run; build-client --check, ds-bot-patches check, canonical, changelog check, check-empty-catch, check-mojibake and lint all exit 0.

Documentation: unchanged on purpose and stated in the body — docs/subsystems/core-host.md already says absent means there was nothing on disk to clear (not a refusal) and describes the one line a refused leaf prints; it never described an ENOENT line.

@Birfy

Birfy commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at f70a950
Written-by: Reviewer
Attestation: f70a950 role=Reviewer

Ran at this tip:

$ TZ=UTC node --import ./test/harness-resolve.mjs --test test/diagnostics.test.js
# tests 41  # pass 41  # fail 0

Red first (base 205bd44f blob of core/src/host/diagnostics.js swapped in, same command, source restored after):

$ cp 2380base/core/src/host/diagnostics.js core/src/host/diagnostics.js && TZ=UTC node --import ./test/harness-resolve.mjs --test test/diagnostics.test.js
# tests 41  # pass 40  # fail 1

The single failure is not ok 40 - a clear with no log on disk stays quiet with + '[ds-bot] diagnostics log not truncated: ENOENT' against the expected empty stderr — exactly the defect #2379 names.

Review at the tip:

  • core/src/host/diagnostics.js: the catch now splits by code — ENOENT answers {leaf:'absent'} and prints nothing (there was no leaf to empty, matching the !toFile host above), every other code answers {leaf:'kept'} and prints the one line with the code, never the folder. The throw stays, so the chain still ends where it did.
  • core/test/diagnostics.test.js: both halves pinned. The no-log Clear asserts {leaf:'absent',rotated:'none'}, zero captured console.error args, and that no logs/ folder was created; the 0444 Clear keeps its one-line EACCES assertion, {leaf:'kept',rotated:'none'} and untouched bytes, so host: a Clear that cannot truncate the leaf says nothing and still reads as cleared #2364 is not weakened. console.error is captured in the tests themselves; no production hook.
  • changelog.d/2379-clear-enoent-quiet.fixed.md is the required user-visible fragment; core/src/client/feedback.js, core/client.js and patches/ds-bot/0008-client-bundle.patch are untouched, and the two changed patches are what generate produces.
  • Check-runs at the tip: tests-ok, package, plugins (tree|social|timeline|workflow), merge-gate, Node 24 · DSH 0.2.0-rc.2 all success. enqueue-guard is red only because no PASS named this tip yet; this conclusion is that PASS.

Not run: npm run verify in full and the live GET /api/diagnostics + Clear endpoint; the changed file's own suite is the one command above, and the fork's CI carried the rest.

Reviewer: Reviewer

Checkpoint

{
  "pr": 2380,
  "claim": "Dev-1",
  "issue": 2379,
  "summary": "Review of the Clear-on-a-home-with-no-log fix. The host function now answers 'absent' and stays silent for ENOENT, and only a leaf that exists and refuses the truncate answers 'kept' with one EACCES line; #2364's guarantee is unchanged. Both halves are pinned by tests that capture console.error themselves. At f70a9506 the changed test file is 41/41 green, and swapping the base host file back turns it into 40/1 with the ENOENT failure. Tip checks are green; a PASS stands at this sha.",
  "files": ["core/src/host/diagnostics.js", "core/test/diagnostics.test.js", "changelog.d/2379-clear-enoent-quiet.fixed.md"],
  "checks": { "ran": "TZ=UTC node --import ./test/harness-resolve.mjs --test test/diagnostics.test.js (green 41/41; red-first 40/1)", "result": "green", "at": "f70a9506621275b24483992f3dba8b34c402e5da" },
  "next": "PASS posted at this tip; Reviewer enqueues through the merge queue."
}

@Birfy Birfy added the agent-pr Pull request opened by an agent label Nov 4, 2026
@Birfy
Birfy added this pull request to the merge queue Nov 4, 2026
@github-actions github-actions Bot added the pass label Nov 4, 2026
Merged via the queue into ThinkFlowLab:main with commit 9a0a106 Nov 4, 2026
18 checks passed
@Birfy
Birfy deleted the dev/1-clear-enoent-quiet branch November 4, 2026 10:22
@github-actions github-actions Bot removed the agent-pr Pull request opened by an agent label Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

host: a Clear with no log on disk prints "not truncated: ENOENT" while the window says Cleared

2 participants