Skip to content

fix(logging): stop the no-config window dropping every log line - #2467

Merged
kriszyp merged 1 commit into
mainfrom
fix/format-check-query-array-scoping
Sep 3, 2026
Merged

fix(logging): stop the no-config window dropping every log line#2467
kriszyp merged 1 commit into
mainfrom
fix/format-check-query-array-scoping

Conversation

@kriszyp

@kriszyp kriszyp commented Sep 2, 2026

Copy link
Copy Markdown
Member

Summary

This PR has been repurposed. It was opened to unbreak main's Format Check by reformatting unitTests/resources/query-array-scoping.test.js, and to fix the red Windows unit gate. #2468 landed both while this was in flight — the reformat is upstream, and main's Format Check and Windows gate are green. Rebased onto main, all of that is gone and what remains is the one thing #2468 left in place: the product bug underneath the Windows failure.

initLogSettings() falls back to a no-config branch on any host without a harperdb-config.yaml — the install window, and a fresh CI runner. It sets log_to_file = false; logToStdstreams = true, which reads as "the streams are the sink now", and then called createLogger() without passing stdStreams. createLogger destructures that option into a local of the same name, which shadows the module-level flag inside logStdOut/logStdErr — so the branch wrote nowhere at all. Before a config exists, every log line Harper produced was silently dropped, install diagnostics included.

That branch also returns before the stdioLogging() call at the end of initLogSettings(), so the streams it now writes to would have had no EPIPE/EIO listener: harper install | head -1 closes the reader and the async error lands on a stream with none, taking the install down. The guards are installed on that branch too; their write override is inert there, because log_to_file is false.

This is what the Windows gate was actually reporting when watcherFallback.test.js's warn-cadence case counted 0 of 2 warnings (#2364): the Ubuntu unit job runs harper install first and the Windows job does not, so only Windows had no config to read. #2468 gave that harness a config of its own — the right fix for the test — which leaves the product behaviour unchanged.

A child-process case pins both halves. It spawns with ROOTPATH at a directory holding no config, which reaches the fallback on an installed machine and a bare one alike (with boot properties present the config read throws ENOENT; without them initLogSettings() only swallows that failure when ROOTPATH does hold a config), and asserts the warning on stderr plus the guard listener on each stream.

For the human reviewer

  • Close this instead if you would rather the logging fix land on its own branch — the CI goal it was opened for is already met by Stop the lost-watch harness aborting the Windows unit job on an 8.3 short temp path #2468, so nothing is lost by dropping it. The commit is self-contained.
  • This changes product behaviour in the pre-config window, which is the part to weigh. Previously-silent logs now reach stdout/stderr, which is what the two lines above the call always intended. Two consequences you may want the other way, both one-liners I did not decide: notify/info route to stdout, so a CLI emitting machine-readable stdout before a config exists would interleave log lines with it (none does at those levels today); and the branch hard-sets logToStdstreams = true while its cmd/env loop honours only LOGGING_LEVEL/LOGGING_CONSOLE, so an operator's explicit LOGGING_STDSTREAMS=false is overridden in that window, where it was previously inert by accident.
  • The alternative fix I did not take: rename the destructured local in createLogger so the module-level logToStdstreams stays visible and no caller can silently drop it. The shadow is the actual trap and it will re-fire on the next new caller — but the rename changes logStdOut's fallback semantics for every logger, which is a call for a human rather than a side effect of a CI fix.
  • Coverage boundary: the new case asserts the guard listener is installed, not that a broken pipe is survived end to end. Closing the child's stdout reader and asserting survival would also exercise disableStdio(), which replaces the process-global nativeStdWrite and therefore mutes stderr along with stdout — worth its own change, not this one.
  • Adjacent, pre-existing, filed rather than fixed here: logStdOut/logStdErr read the per-instance logger.logToStdstreams in the file branch but the closure capture in the no-file branch, while updateLogger writes only the property — so with logging.file: false, flipping stdStreams through the config watcher has no effect. Same option-plumbing trap, one level up. Also if (process.env.DEV_MODE) logToStdstreams = true runs after createLogger() in both branches, so it has been dead for the same shadowing reason.

Verification

  • npm run test:unit:windows (the Windows gate's own group runner, on Linux) — all 9 groups pass, 3637 tests.
  • The new case verified against both regressions it covers: reverting the createLogger() option fails it on the missing warning; removing the stdioLogging() call fails it on stdout-guard=true stderr-guard=true.
  • Test style follows AGENTS.mdnode:assert against a real child process, no sinon/rewire; the fallback branch is reachable by spawning with a config-less ROOTPATH, so there was nothing to stub.
  • npx prettier --check . passes repo-wide; npx oxlint clean on the changed files.

Refs #2364, #2468


🤖 Generated with Claude Code

https://claude.ai/code/session_017gPFHKnh2qasUuy53fdzbe

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

Review-Coverage: authored=claude; ran=codex; adjudicated=domain; blocked=gemini(auth); declined=cursor-grok,cursor-composer; rounds=8 @ 521369e

Human-Review-Need: 3 (decisions: epipe-survive-vs-crash, stdstreams-fix-at-callsite-vs-shadowing, child-process-fixture-vs-rewire) @ 521369e

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request simplifies the formatting of two test assertions in unitTests/resources/query-array-scoping.test.js by condensing multi-line assert.deepStrictEqual calls into single lines. There are no review comments, and I have no feedback to provide.

@kriszyp
kriszyp marked this pull request as ready for review September 2, 2026 12:07
@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Reviewed; no blockers found.

initLogSettings() falls back to a no-config branch on any host without a
harperdb-config.yaml — the install window, and a fresh CI runner. It sets
`log_to_file = false; logToStdstreams = true`, which reads as "the streams are the sink
now", and then called createLogger() without passing stdStreams. createLogger
destructures that option into a local of the same name, which shadows the module-level
flag inside logStdOut/logStdErr, so the branch wrote nowhere at all: before a config
exists, every log line Harper produced was silently dropped, install errors included.

That branch also returns before the stdioLogging() call at the end of initLogSettings(),
so the streams it now writes to would have had no EPIPE/EIO listener — `harper install |
head -1` closes the reader, and the async error would land on a stream with none and take
the install down. Install the guards there too; their write override is inert on this
branch, because log_to_file is false.

Found from the Windows unit gate, where the guard's warn-cadence case counted 0 of 2
warnings (harper#2364). #2468 has since made that harness bring its own config, which is
the right fix for the test; this is the product bug underneath it, which that leaves in
place.

A child-process case pins both halves: it spawns with ROOTPATH at a directory holding no
config, which reaches the fallback on an installed machine and a bare one alike, and
asserts the warning on stderr and the guard listener on each stream. It fails on the old
createLogger() call, and again without the stdioLogging() call.

Verified: `npm run test:unit:windows` (the Windows gate's own groups, on Linux).

Refs #2364

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017gPFHKnh2qasUuy53fdzbe
@kriszyp
kriszyp force-pushed the fix/format-check-query-array-scoping branch from 97396cc to 521369e Compare September 2, 2026 15:05
@kriszyp kriszyp changed the title fix(test): reformat query-array-scoping.test.js to fix red Format Check fix(logging): stop the no-config window dropping every log line Sep 2, 2026
@kriszyp
kriszyp merged commit 1d61262 into main Sep 3, 2026
45 of 46 checks passed
@kriszyp
kriszyp deleted the fix/format-check-query-array-scoping branch September 3, 2026 23:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants