Skip to content

Quiet-by-default logging with --json for agents#18

Merged
KayleeWilliams merged 4 commits into
mainfrom
KayleeWilliams/less-noisy-logs
May 10, 2026
Merged

Quiet-by-default logging with --json for agents#18
KayleeWilliams merged 4 commits into
mainfrom
KayleeWilliams/less-noisy-logs

Conversation

@KayleeWilliams
Copy link
Copy Markdown
Collaborator

Summary

  • Rewrites src/internal/logger.ts as a dual-form {human, json} API. Default human mode is terse and prefix-free on stderr; LEADTYPE_LOG_FORMAT=json (or --json on CLI commands) emits one structured event per line for agents and CI; LEADTYPE_VERBOSE=1 / --verbose firehoses per-file events.
  • Collapses per-file convert chatter into one batch summary with timing; migrates stray process.stderr.write callers (search/node.ts, remark/plugins/include.remark.ts, cli.ts) to the new logger; moves success summaries from stdout to stderr so pipelines stay clean.
  • Silences rollup build output and bun run preambles so bun dev from the example app emits ~4 lines instead of the prior 30+.

What it looks like

Default (interactive terminal):

$ bun run docs:generate
Converted 15 docs in 128 ms
Generated /…/AGENTS.md and /…/docs/*.md

--json (agents, CI):

$ leadtype generate --src … --out … --json
# stdout (out.md): the GenerateResult JSON payload
# stderr (one event per line):
{"ts":"…","level":"info","event":"convert.batch","files":15,"ok":15,"failed":0,"ms":125}
{"ts":"…","level":"info","event":"generate.done","outDir":"…","mode":"site"}

--verbose / LEADTYPE_VERBOSE=1: per-file events with timing.

Test plan

  • bun --cwd packages/leadtype run test — 98/98 pass
  • bun --cwd packages/leadtype run lint — clean (ultracite)
  • bun --cwd packages/leadtype run check-types — clean (tsgo)
  • bun --cwd packages/leadtype run build smoke — 2 lines on stderr, stdout empty
  • LEADTYPE_LOG_FORMAT=json smoke — every stderr line parses as JSON with an event key
  • LEADTYPE_VERBOSE=1 smoke — per-file events appear
  • cd apps/example && bun dev build phase — ~4 lines instead of ~30

🤖 Generated with Claude Code

Rewrites the internal logger as a dual-form {human, json} API so each
call site spells out both shapes explicitly. Default human mode is
terse and prefix-free on stderr; LEADTYPE_LOG_FORMAT=json (or --json
on CLI commands) emits one structured event per line for agents and
CI; LEADTYPE_VERBOSE=1 / --verbose firehoses per-file events.

- Collapse per-file convert chatter into one batch summary with timing
- Migrate stray process.stderr.write callers in search/node.ts and
  remark/plugins/include.remark.ts to the new logger
- Move success summaries from stdout to stderr so pipelines stay clean
- Couple --json to log format in generate and lint CLIs; add --verbose
- Silence rollup build output and bun run preambles so the example
  app's bun dev flow is ~4 lines instead of the prior 30+
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 10, 2026

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added -v/--verbose to generate and lint commands and selectable JSON logging for machine-readable output.
  • Improvements

    • Unified structured logging across tooling for clearer progress, completion, warnings, and errors.
    • Build/dev and doc/conversion steps run more quietly by default (silent flags applied).
  • Tests

    • Updated test assertions to reflect logging moved between IO streams.

Walkthrough

Replaces a string-based log helper with a structured, configurable logger (human/json formats, verbosity, and stream targets) and updates CLI, generate/lint commands, MDX conversion, remark include plugin, search/vercel modules, scripts, package-scripts (silenced), and tests to emit structured log events.

Changes

Logging Infrastructure and CLI Integration

Layer / File(s) Summary
Logger API
packages/leadtype/src/internal/logger.ts
Replaces log helper with structured logger, adds LogCall type, setLogFormat(), setVerbose(), setLogStreams(), JSON sanitization, and emit logic.
CLI Entry Point
packages/leadtype/src/cli.ts
Initializes logger streams via setLogStreams(io); fatal errors now use logger.error() with structured payloads.
Generate Command
packages/leadtype/src/cli/generate.ts
Adds --verbose/-v to GenerateArgs; configures JSON/human format and verbosity; replaces manual JSON/error writes with logger.info()/logger.error() events.
Lint Command
packages/leadtype/src/lint/cli.ts
Adds --verbose/-v to CliArgs; configures logger format and verbosity before lint execution.
MDX Conversion
packages/leadtype/src/convert/convert.ts
Uses logger for all messages, adds per-file timing, emits convert.file and convert.fail structured events, and emits batch convert.batch summary.
Generation & Plugins
packages/leadtype/scripts/generate-docs.ts, packages/leadtype/src/remark/plugins/include.remark.ts, packages/leadtype/src/search/node.ts, packages/leadtype/src/search/vercel.ts
Switch from direct stdout/stderr writes to logger events (errors/warnings/info); adds formatBytes() helper and structured event names.
Build Scripts & Silencing
apps/example/package.json, packages/leadtype/package.json
Add --silent to pipeline:build, rollup, and docs:generate commands to suppress intermediate output.
Example Script Cleanup
apps/example/scripts/mdx-convert.ts
Removes manual process.stdout.write() logs around convertAllMdx(); rely on structured logging.
Test Update
packages/leadtype/src/cli.test.ts
Asserts the “Generated docs pipeline output” message appears on stderr and that stdout is empty as appropriate.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CLI
  participant Module
  participant logger
  participant stderr
  User->>CLI: run leadtype generate -v
  CLI->>Module: invoke generate
  Module->>logger: logger.info / logger.error
  logger->>stderr: emit human or JSON
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • inthhq/docs#12: Modifies logging/console behavior and logger implementation across repo scripts and tooling.
  • inthhq/leadtype#19: Modifies the same apps/example/package.json dev/build pipeline commands.
  • inthhq/leadtype#14: Related updates to package scripts and build tooling (tsup → rollup, etc.).

Poem

🐰 I scrubbed the stdout, made logs precise,
JSON and human, both look nice.
Silent builds hum, events politely say,
Verbose if you ask — progress leads the way.
🥕📡

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Quiet-by-default logging with --json for agents' directly and clearly summarizes the main change: a logging refactor that defaults to quiet/terse output and adds JSON mode for agents/CI.
Description check ✅ Passed The description is well-detailed and directly related to the changeset, explaining the dual-form logging API, JSON/verbose modes, stderr migration, and output reduction in the example app.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bdd8cb1c71

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/leadtype/src/cli/generate.ts Outdated
Comment on lines +361 to +365
if (args.format === "json") {
setLogFormat("json");
}
if (args.verbose) {
setVerbose(true);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reset logger state for each CLI invocation

Because setLogFormat("json") and setVerbose(true) mutate module-global logger state and are only called when the flag is present, an in-process caller that reuses the exported runCli after a generate --format json or --verbose run will keep emitting JSON/debug logs on later default invocations. This affects test harnesses or agent integrations that call the CLI API multiple times in one process; set the logger format and verbosity from the parsed args on every invocation or scope the settings to the command run.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/leadtype/src/cli.test.ts`:
- Around line 114-116: The test currently asserts exit code, stderr and that a
file exists but doesn't lock down stdout; update the test in cli.test.ts to also
assert that capture.stdout is empty for the text-mode path by adding an
assertion using the existing capture object (e.g.,
expect(capture.stdout).toBe("") or equivalent) so stdout remains clean and no
human logs leak into pipeline output.

In `@packages/leadtype/src/cli/generate.ts`:
- Around line 361-366: The current code only calls setLogFormat and setVerbose
when flags are present causing runtime state to leak between invocations; make
logger configuration deterministic by always calling setLogFormat and setVerbose
based on args: call setLogFormat(args.format === "json" ? "json" : "default"/*or
explicit non-json value your logger expects*/) and call
setVerbose(Boolean(args.verbose)) so every command invocation resets logging
state regardless of whether flags were provided; update the logic around
args.format and args.verbose in generate.ts to use these unconditional calls
(referencing args.format, args.verbose, setLogFormat, setVerbose).

In `@packages/leadtype/src/convert/convert.ts`:
- Around line 465-470: The current failure log misleadingly hints that
LEADTYPE_VERBOSE=1 will print a stack even though this code path never emits
error.stack; update logger.error in convert.ts so that if reason is an Error you
include reason.stack (e.g. add stack to human.message or human.hint and to
json.fields) and otherwise change the hint text to not promise a stack (e.g.
"run with LEADTYPE_VERBOSE=1 for more verbose logs"); specifically modify the
logger.error call that references mdxFilePath and reason to conditionally
include reason.stack when available and adjust the hint accordingly.

In `@packages/leadtype/src/internal/logger.ts`:
- Around line 33-40: The JSON log output currently spreads call.json.fields
after reserved keys (ts, level, event) so those reserved keys can be overwritten
or removed; change the serialization in logger.ts so that when building the
object for JSON output you first merge sanitized fields and then set reserved
keys (or filter call.json.fields to remove keys "ts", "level", and "event" and
drop undefined values) before stringifying; locate the block that writes
`${JSON.stringify({ ts: ..., level, event: call.json.event, ...call.json.fields
})}` and update it to exclude/ignore any fields named "ts", "level", or "event"
(and skip undefined values) so reserved schema keys cannot be overwritten.

In `@packages/leadtype/src/lint/cli.ts`:
- Around line 137-142: The CLI currently only toggles json/verbose when flags
are present, so previous runs can leak logging state; in the lint CLI entry
(packages/leadtype/src/lint/cli.ts) explicitly reset logger state at the start
of each run by calling setLogFormat("text" or the default format) and
setVerbose(false) before applying the args checks, then apply the existing if
(args.format === "json") setLogFormat("json") and if (args.verbose)
setVerbose(true); this ensures setLogFormat and setVerbose are always
deterministically initialized per invocation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9ecf1040-f74b-4db8-aa50-d262965e8756

📥 Commits

Reviewing files that changed from the base of the PR and between f64df00 and bdd8cb1.

📒 Files selected for processing (13)
  • apps/example/package.json
  • apps/example/scripts/mdx-convert.ts
  • packages/leadtype/package.json
  • packages/leadtype/scripts/generate-docs.ts
  • packages/leadtype/src/cli.test.ts
  • packages/leadtype/src/cli.ts
  • packages/leadtype/src/cli/generate.ts
  • packages/leadtype/src/convert/convert.ts
  • packages/leadtype/src/internal/logger.ts
  • packages/leadtype/src/lint/cli.ts
  • packages/leadtype/src/remark/plugins/include.remark.ts
  • packages/leadtype/src/search/node.ts
  • packages/leadtype/src/search/vercel.ts
💤 Files with no reviewable changes (1)
  • apps/example/scripts/mdx-convert.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Prefer unknown over any when the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions

Files:

  • packages/leadtype/src/search/vercel.ts
  • packages/leadtype/scripts/generate-docs.ts
  • packages/leadtype/src/lint/cli.ts
  • packages/leadtype/src/cli.ts
  • packages/leadtype/src/remark/plugins/include.remark.ts
  • packages/leadtype/src/internal/logger.ts
  • packages/leadtype/src/search/node.ts
  • packages/leadtype/src/cli/generate.ts
  • packages/leadtype/src/convert/convert.ts
  • packages/leadtype/src/cli.test.ts
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,jsx,tsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Prefer for...of loops over .forEach() and indexed for loops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Use const by default, let only when reassignment is needed, never var
Always await promises in async functions - don't forget to use the return value
Use async/await syntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Remove console.log, debugger, and alert statements from production code
Throw Error objects with descriptive messages, not strings or other values
Use try-catch blocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Don't use eval() or assign directly to document.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use descriptive names for functions, variables, and types for meaningful naming
Add comments for complex logic, but prefer self-documenting code

Files:

  • packages/leadtype/src/search/vercel.ts
  • packages/leadtype/scripts/generate-docs.ts
  • packages/leadtype/src/lint/cli.ts
  • packages/leadtype/src/cli.ts
  • packages/leadtype/src/remark/plugins/include.remark.ts
  • packages/leadtype/src/internal/logger.ts
  • packages/leadtype/src/search/node.ts
  • packages/leadtype/src/cli/generate.ts
  • packages/leadtype/src/convert/convert.ts
  • packages/leadtype/src/cli.test.ts
**/*.{test,spec}.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{test,spec}.{js,ts,jsx,tsx}: Write assertions inside it() or test() blocks
Avoid done callbacks in async tests - use async/await instead
Don't use .only or .skip in committed code
Keep test suites reasonably flat - avoid excessive describe nesting

Files:

  • packages/leadtype/src/cli.test.ts
🔍 Remote MCP Context7

Tool Library Documentation Retrieved

Bun --silent Flag

The PR's use of bun run --silent in package.json scripts aligns with Bun's documented behavior. The --silent flag suppresses the command execution preamble, preventing Bun from printing "Running '...'..." messages to the console. This can be set via CLI flags (bun run --silent pipeline:convert) or in bunfig.toml configuration. This is the standard approach for reducing noise in build pipelines and development workflows.

Rollup --silent Flag

Similarly, the PR's addition of --silent to Rollup invocations is a documented CLI option that suppresses warnings printed to the console. Importantly, Rollup's --silent flag does not suppress errors (which must be handled via the logLevel option); it only suppresses warning-level logs. Any onLog or onwarn handlers defined in the config or plugins are still executed even with --silent enabled. This is relevant for the PR since it's combining Rollup's --silent with a structured logging migration—the logging handlers will still fire.

Remark Plugin Architecture

The PR modifies packages/leadtype/src/remark/plugins/include.remark.ts to emit structured logger calls instead of direct process.stderr.write statements. This aligns with Remark's plugin pattern: plugins receive the markdown AST (mdast) and return a transform function that visits and modifies nodes. The standard approach uses unist-util-visit to traverse the tree. The PR's migration to structured logging within the plugin is compatible with this architecture—plugins can emit events/logs without breaking the tree transformation flow.

PR-Specific Insights

  1. Output Silencing Strategy: The PR uses both tool-level flags (bun run --silent, rollup --silent) and application-level structured logging to achieve quiet-by-default behavior. This is a sound dual-layer approach.

  2. Stderr as Default Output Stream: Moving success summaries from stdout to stderr (e.g., in convert.ts, cli.ts, generate.ts) is appropriate for keeping generated artifacts on stdout clean for pipeline consumption while relegating logging and diagnostics to stderr.

  3. Structured Logging Compatibility: The new logger API with setLogFormat("json") and setVerbose(true) is compatible with how the underlying libraries (Rollup, Bun, Remark) handle their own logging—they all support structured event emission or suppression independently.

🔇 Additional comments (7)
apps/example/package.json (1)

7-8: LGTM! Clean reduction of pipeline noise.

The addition of --silent to the bun run pipeline:convert steps in both dev and build scripts appropriately suppresses Bun's command execution preamble while preserving error output. This aligns with the PR's goal of reducing the example app's output from ~30+ lines to ~4 lines and keeps the approach consistent across both development and production build flows.

packages/leadtype/src/search/vercel.ts (1)

110-117: Structured provider-error logging looks solid.

Nice migration to logger.error with a stable event name and explicit reason field.

packages/leadtype/src/search/node.ts (1)

173-181: Large-index warning refactor is clean.

The new human+JSON warning payload is clear and keeps diagnostics machine-friendly.

Also applies to: 183-221

packages/leadtype/src/remark/plugins/include.remark.ts (1)

368-378: Good move to structured include warnings.

These warnings now flow through the shared logger with useful event metadata.

Also applies to: 438-446

packages/leadtype/src/cli.ts (1)

40-40: CLI entrypoint logging integration looks good.

setLogStreams(io) plus structured cli.fatal emission is a solid migration.

Also applies to: 77-80

packages/leadtype/scripts/generate-docs.ts (1)

38-44: Structured logger migration here looks solid.

Both error and success paths now emit consistent { human, json } events with useful fields, which matches the stderr-first/pipeline-safe logging direction.

Also applies to: 60-68

packages/leadtype/package.json (1)

72-72: Build-script quieting is aligned with the PR goal.

Using --silent in both commands keeps build output focused while preserving the existing build flow.

Comment thread packages/leadtype/src/cli.test.ts
Comment thread packages/leadtype/src/cli/generate.ts Outdated
Comment thread packages/leadtype/src/convert/convert.ts Outdated
Comment thread packages/leadtype/src/internal/logger.ts
Comment thread packages/leadtype/src/lint/cli.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/leadtype/src/cli/generate.ts`:
- Around line 361-363: After calling setLogFormat(...) and setVerbose(...) bind
the logger output to the command-local io.stderr so logs go to the provided io
rather than global process.stderr; update the logging configuration (e.g., add a
call like setLogStreams/ioStreamSetter or equivalent) immediately after
setVerbose using the local io.stderr reference so subsequent logger calls (those
around the setLogFormat/setVerbose block and later lines 370/459/469) write to
io.stderr.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3bebba33-39a0-4d90-911c-2661a52bf805

📥 Commits

Reviewing files that changed from the base of the PR and between bdd8cb1 and 9668b6c.

📒 Files selected for processing (5)
  • packages/leadtype/src/cli.test.ts
  • packages/leadtype/src/cli/generate.ts
  • packages/leadtype/src/convert/convert.ts
  • packages/leadtype/src/internal/logger.ts
  • packages/leadtype/src/lint/cli.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Prefer unknown over any when the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions

Files:

  • packages/leadtype/src/cli.test.ts
  • packages/leadtype/src/lint/cli.ts
  • packages/leadtype/src/internal/logger.ts
  • packages/leadtype/src/convert/convert.ts
  • packages/leadtype/src/cli/generate.ts
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,jsx,tsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Prefer for...of loops over .forEach() and indexed for loops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Use const by default, let only when reassignment is needed, never var
Always await promises in async functions - don't forget to use the return value
Use async/await syntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Remove console.log, debugger, and alert statements from production code
Throw Error objects with descriptive messages, not strings or other values
Use try-catch blocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Don't use eval() or assign directly to document.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use descriptive names for functions, variables, and types for meaningful naming
Add comments for complex logic, but prefer self-documenting code

Files:

  • packages/leadtype/src/cli.test.ts
  • packages/leadtype/src/lint/cli.ts
  • packages/leadtype/src/internal/logger.ts
  • packages/leadtype/src/convert/convert.ts
  • packages/leadtype/src/cli/generate.ts
**/*.{test,spec}.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{test,spec}.{js,ts,jsx,tsx}: Write assertions inside it() or test() blocks
Avoid done callbacks in async tests - use async/await instead
Don't use .only or .skip in committed code
Keep test suites reasonably flat - avoid excessive describe nesting

Files:

  • packages/leadtype/src/cli.test.ts
🔍 Remote MCP Context7

Summary of relevant facts for reviewing this PR

  • Bun: bun run --silent (or bun --silent run / run.silent = true in bunfig.toml) suppresses Bun’s “Running '…'…” preamble and prevents printing the command itself; it does not affect the command’s own stdout/stderr output. This aligns with the PR’s use of bun run --silent to reduce Bun preamble noise.

  • Rollup: rollup --silent prevents printing warnings to the console but does not suppress errors. Plugins or config-level onLog/onwarn handlers are still invoked when --silent is used; to fully suppress handler activity you must also change logLevel (e.g., --logLevel silent) or adjust onLog/onwarn. Thus adding --silent reduces Rollup warning chatter but will not hide errors or prevent plugin onLog hooks from running.

Tools/sources used

  • Context7 — Context7_resolve-library-id (resolved Bun and Rollup library IDs)
  • Context7 — Context7_query-docs (queried Bun and Rollup docs for --silent behavior)
🔇 Additional comments (4)
packages/leadtype/src/internal/logger.ts (1)

37-63: Reserved-field sanitization in JSON mode looks solid.

Line 43 correctly drops undefined and reserved keys before emission, so schema keys remain stable in Line 57-62.

packages/leadtype/src/lint/cli.ts (1)

137-144: Deterministic logger initialization is correctly implemented.

Line 137-144 now resets and reapplies log mode/verbosity per run, which avoids cross-invocation leakage.

packages/leadtype/src/convert/convert.ts (1)

464-477: Failure logging is materially improved.

Line 464-477 now preserves both message and stack (when available), improving debuggability in both human and JSON modes.

packages/leadtype/src/cli.test.ts (1)

114-117: Good test hardening for stream separation.

Line 115-116 correctly locks in clean stdout and verifies the human completion log on stderr.

Comment thread packages/leadtype/src/cli/generate.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/leadtype/src/cli/generate.ts (1)

374-389: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Route text-mode failures through logger.error too.

The non-JSON branches still write manual prefixed stderr strings, which bypasses the centralized human logger path and creates inconsistent output behavior.

Proposed minimal diff
   if (!existsSync(docsDir)) {
-    if (args.format === "json") {
-      logger.error({
-        human: { message: `docs directory not found at ${docsDir}` },
-        json: {
-          event: "generate.docs_not_found",
-          fields: { error: "docs directory not found", path: docsDir },
-        },
-      });
-    } else {
-      io.stderr.write(
-        `leadtype generate: docs directory not found at ${docsDir}\n`
-      );
-    }
+    logger.error({
+      human: { message: `docs directory not found at ${docsDir}` },
+      json: {
+        event: "generate.docs_not_found",
+        fields: { error: "docs directory not found", path: docsDir },
+      },
+    });
     return 1;
   }
@@
   } catch (error) {
     const message = error instanceof Error ? error.message : String(error);
-    if (args.format === "json") {
-      logger.error({
-        human: { message },
-        json: {
-          event: "generate.fail",
-          fields: {
-            error: message,
-            filters: {
-              exclude: args.exclude,
-              include: args.include,
-            },
-          },
-        },
-      });
-    } else {
-      io.stderr.write(`leadtype generate: ${message}\n`);
-    }
+    logger.error({
+      human: { message },
+      json: {
+        event: "generate.fail",
+        fields: {
+          error: message,
+          filters: {
+            exclude: args.exclude,
+            include: args.include,
+          },
+        },
+      },
+    });
     return 1;
   } finally {

Also applies to: 472-490

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/leadtype/src/cli/generate.ts` around lines 374 - 389, The code
currently writes human-readable error strings directly to stderr (using
io.stderr.write) when args.format !== "json" (e.g., the existsSync(docsDir)
check), bypassing the centralized logger; replace those io.stderr.write calls
with logger.error(...) calls that use the human field (e.g., logger.error({
human: { message: `leadtype generate: docs directory not found at ${docsDir}` },
json: { event: "generate.docs_not_found", fields: { error: "docs directory not
found", path: docsDir } } })) so both JSON and text modes go through the same
logging path; apply the same change to the other occurrence referenced around
the check at the later block (the code around lines handling the same error at
472-490) and keep the existing json payload intact for args.format === "json".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/leadtype/src/cli/generate.ts`:
- Around line 374-389: The code currently writes human-readable error strings
directly to stderr (using io.stderr.write) when args.format !== "json" (e.g.,
the existsSync(docsDir) check), bypassing the centralized logger; replace those
io.stderr.write calls with logger.error(...) calls that use the human field
(e.g., logger.error({ human: { message: `leadtype generate: docs directory not
found at ${docsDir}` }, json: { event: "generate.docs_not_found", fields: {
error: "docs directory not found", path: docsDir } } })) so both JSON and text
modes go through the same logging path; apply the same change to the other
occurrence referenced around the check at the later block (the code around lines
handling the same error at 472-490) and keep the existing json payload intact
for args.format === "json".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: dd140429-60c8-4f86-bf1a-f12fafd15a73

📥 Commits

Reviewing files that changed from the base of the PR and between 9668b6c and 6b6001c.

📒 Files selected for processing (1)
  • packages/leadtype/src/cli/generate.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Prefer unknown over any when the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions

Files:

  • packages/leadtype/src/cli/generate.ts
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,jsx,tsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Prefer for...of loops over .forEach() and indexed for loops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Use const by default, let only when reassignment is needed, never var
Always await promises in async functions - don't forget to use the return value
Use async/await syntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Remove console.log, debugger, and alert statements from production code
Throw Error objects with descriptive messages, not strings or other values
Use try-catch blocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Don't use eval() or assign directly to document.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use descriptive names for functions, variables, and types for meaningful naming
Add comments for complex logic, but prefer self-documenting code

Files:

  • packages/leadtype/src/cli/generate.ts
🔍 Remote MCP Context7

Summary of additional facts relevant to this PR review

  • bun run --silent suppresses the “Running ''...” preamble (equivalent CLI forms: bun --silent run, bun --silent , bun run --silent). It prevents bun from printing the command being run but does not affect the command’s own stdout/stderr.

  • rollup --silent prevents printing warnings to the console but does not stop onLog/onwarn handlers or plugin onLog hooks from being invoked. To more fully suppress logging from Rollup (including handlers), use the logLevel option or pass --logLevel silent. Errors are still printed by the CLI.

Tools/sources used

  • Context7: resolve-library-id + query-docs for Bun and Rollup documentation (see citations above).
🔇 Additional comments (1)
packages/leadtype/src/cli/generate.ts (1)

366-369: Good logger bootstrap for this command.

This is now deterministic per invocation and correctly binds logs to io.stderr.

…oisy-logs

# Conflicts:
#	apps/example/package.json
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/leadtype/src/search/node.ts`:
- Around line 177-185: The function formatBytes uses raw numeric literals (1024
and 1024 * 1024); extract these into named constants (e.g., BYTES_PER_KB = 1024
and BYTES_PER_MB = BYTES_PER_KB * 1024) near the top of the module and replace
the literals inside formatBytes with those constants so the comparisons and
divisions use BYTES_PER_MB and BYTES_PER_KB; update the string formatting logic
to use the constants for readability and consistency.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2f03b75e-57b8-4a47-a11f-d7d11557e578

📥 Commits

Reviewing files that changed from the base of the PR and between 6b6001c and 7023f66.

📒 Files selected for processing (5)
  • apps/example/package.json
  • packages/leadtype/package.json
  • packages/leadtype/src/cli.test.ts
  • packages/leadtype/src/cli/generate.ts
  • packages/leadtype/src/search/node.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Prefer unknown over any when the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions

Files:

  • packages/leadtype/src/search/node.ts
  • packages/leadtype/src/cli.test.ts
  • packages/leadtype/src/cli/generate.ts
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,jsx,tsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Prefer for...of loops over .forEach() and indexed for loops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Use const by default, let only when reassignment is needed, never var
Always await promises in async functions - don't forget to use the return value
Use async/await syntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Remove console.log, debugger, and alert statements from production code
Throw Error objects with descriptive messages, not strings or other values
Use try-catch blocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Don't use eval() or assign directly to document.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use descriptive names for functions, variables, and types for meaningful naming
Add comments for complex logic, but prefer self-documenting code

Files:

  • packages/leadtype/src/search/node.ts
  • packages/leadtype/src/cli.test.ts
  • packages/leadtype/src/cli/generate.ts
**/*.{test,spec}.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{test,spec}.{js,ts,jsx,tsx}: Write assertions inside it() or test() blocks
Avoid done callbacks in async tests - use async/await instead
Don't use .only or .skip in committed code
Keep test suites reasonably flat - avoid excessive describe nesting

Files:

  • packages/leadtype/src/cli.test.ts
🔍 Remote MCP Context7

Summary of additional facts relevant to reviewing this PR

  • Bun: "bun run --silent" / "bun --silent run" suppresses Bun's "Running ''..." preamble (the command-printing line) but does not alter or suppress the invoked command's own stdout/stderr. It is equivalent to setting run.silent = true in bunfig.toml.

  • Rollup: the CLI flag --silent prevents Rollup from printing warnings to the console but does not stop onLog/onwarn handlers or plugin onLog hooks from being invoked. To more fully silence Rollup (including handlers), use the logLevel option or pass --logLevel silent; errors are still printed.

Tooling lookups performed

  • Resolved Context7 library IDs for Bun and Rollup before querying docs.,
🔇 Additional comments (8)
packages/leadtype/package.json (1)

76-76: Build script change is aligned with quiet-by-default goals.

Using --silent here reduces wrapper/tool noise while keeping the build pipeline intact (rollup then docs generation). This is consistent with the PR’s logging objective.

apps/example/package.json (1)

7-8: Dev/build script updates look good.

Switching pipeline:build to bun run --silent is a clean noise reduction change and keeps the existing workflow unchanged.

packages/leadtype/src/search/node.ts (2)

5-5: Logger import change is aligned with the new logging architecture.

Using the shared logger here keeps stderr handling centralized and consistent.


188-224: Breach aggregation and structured warning payload look solid.

The early return plus single logger.warn emission keeps logs concise while preserving machine-readable threshold data.

packages/leadtype/src/cli/generate.ts (3)

47-47: Verbose flag wiring is clean and consistent.

GenerateArgs, defaults, parser handling, and help text all align for -v/--verbose.

Also applies to: 116-117, 143-144, 178-180


372-375: Deterministic per-invocation logger setup looks correct.

Configuring format, verbosity, and command-local stderr up front is the right shape for command-scoped logging.


382-388: Structured event logging paths are well implemented.

The generate.docs_not_found, generate.done, and generate.fail events are explicit and keep machine payload output separated from operational logs.

Also applies to: 481-487, 491-503

packages/leadtype/src/cli.test.ts (1)

115-116: Great test hardening for stdout/stderr routing.

This correctly locks in the “quiet stdout” contract while still validating user-facing completion feedback on stderr.

Comment on lines +177 to +185
function formatBytes(bytes: number): string {
if (bytes >= 1024 * 1024) {
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}
if (bytes >= 1024) {
return `${(bytes / 1024).toFixed(1)} KB`;
}
return `${bytes} B`;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Extract byte unit magic numbers into named constants.

Line 178 and Line 181 use raw unit values (1024, 1024 * 1024). Pull them into named constants for readability and consistency.

♻️ Proposed refactor
 const WARN_INDEX_BYTES = 5 * 1024 * 1024;
 const WARN_TOTAL_BYTES = 10 * 1024 * 1024;
 const WARN_CHUNK_COUNT = 10_000;
+const BYTES_PER_KB = 1024;
+const BYTES_PER_MB = BYTES_PER_KB * 1024;
 const WINDOWS_PATH_PATTERN = /\\/g;
@@
 function formatBytes(bytes: number): string {
-  if (bytes >= 1024 * 1024) {
-    return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
+  if (bytes >= BYTES_PER_MB) {
+    return `${(bytes / BYTES_PER_MB).toFixed(1)} MB`;
   }
-  if (bytes >= 1024) {
-    return `${(bytes / 1024).toFixed(1)} KB`;
+  if (bytes >= BYTES_PER_KB) {
+    return `${(bytes / BYTES_PER_KB).toFixed(1)} KB`;
   }
   return `${bytes} B`;
 }

As per coding guidelines, Use meaningful variable names instead of magic numbers - extract constants with descriptive names.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/leadtype/src/search/node.ts` around lines 177 - 185, The function
formatBytes uses raw numeric literals (1024 and 1024 * 1024); extract these into
named constants (e.g., BYTES_PER_KB = 1024 and BYTES_PER_MB = BYTES_PER_KB *
1024) near the top of the module and replace the literals inside formatBytes
with those constants so the comparisons and divisions use BYTES_PER_MB and
BYTES_PER_KB; update the string formatting logic to use the constants for
readability and consistency.

@KayleeWilliams KayleeWilliams merged commit dc5ac66 into main May 10, 2026
3 checks passed
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.

1 participant