Skip to content

test(cli): stop the skills CLI tests reading the module cache as CLI output - #3653

Merged
kwakayama merged 1 commit into
mainfrom
fix/skills-cli-stderr-module-cache
Aug 13, 2026
Merged

kwakayama merged 1 commit into
mainfrom
fix/skills-cli-stderr-module-cache

Conversation

@kojiwakayama

@kojiwakayama kojiwakayama commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

The flake

cli/commands/skills/handler.test.ts has been failing on coverage shard 7/8 for pull
requests that cannot reach the code it tests — #3648 (proxy WebSocket bridge identity) and
#3651 (a release PR touching three version files), both with the same two steps under
info JSON output, both 412 passed / 1 failed.

Root cause

The failing assertions are handler.test.ts:36 and handler.test.ts:52, both
assertEquals(result.stderr, "") against a child deno run -A cli/main.ts skills info --json. The diff in the CI log (run 31642742785, job coverage shard 7/8) says what
landed there:

    [Diff] Actual / Expected

-   Download https://registry.npmjs.org/yaml\n

That is the Deno runtime narrating its own work, not the CLI writing output. deno.json
sets nodeModulesDir to auto, so a child whose dependencies are not all present first
reconciles node_modules/ against cli/main.ts's graph, and it reports each fetch that
costs on stderr.

Nothing puts yaml where the child would find it. .github/actions/setup-deno warms the
Deno cache from src/index.ts, and npm:yaml@2.9.0 reaches the CLI only through
cli/main.ts — via @opentelemetry/configuration, bash-tool and just-bash — so it is
in neither the warmed blob nor the test process's own graph. actions/cache/restore falls
back through restore-keys, so which packages a shard actually has is decided by which
cache entry the runner happened to restore. That is the whole of the flakiness: the file
was asserting on the machine's module cache alongside the CLI's stderr.

This is a test defect, not a product one. The CLI writes nothing to stderr here; every
environment variable that any file in shard 7 mutates was probed against the command and
none of them change its stdout, stderr or exit code.

The fix

One line: --quiet on the child.

It suppresses the runtime's diagnostics and nothing else. What the CLI writes still
arrives — veryfront skills info with no name and no --json still reports
✗ Usage: veryfront skills info <name> on stderr underneath --quiet — so the assertions
still hold the command to a silent stderr. They just no longer hold the module cache to it
as well. No retry, no tolerance, no skip.

Verification

The failure reproduces deterministically by putting the machine in the state a partially
restored CI cache puts it in — evicting the yaml packument from DENO_DIR before each
run:

rm -rf "$DENO_DIR/npm/registry.npmjs.org/yaml"
deno test --preload=src/testing/preload.ts --no-check --parallel --allow-all \
  --v8-flags=--max-old-space-size=8192 --ignore=tests --ignore=src/workflow/__tests__ \
  --unstable-worker-options --unstable-net <the 232 shard-7 files>

It produces the CI diff byte for byte.

condition before after
this file alone, trigger armed each run 0 / 25 passed 25 / 25 passed
full shard-7 file set under --parallel, trigger armed each run 1 / 20 passed (19 skills failures) 55 / 55 passed (0 skills failures, 0 other failures)

Deno 2.7.7 throughout, matching CI.

Noticed while investigating, not fixed here

  • src/extensions/factory-loader.test.ts:201 reads const repositoryRoot = Deno.cwd()
    inside a test while cli/commands/schedule/handler.test.ts may hold the process
    directory through withCwd. It failed once in 25 baseline shard-7 runs with
    Module not found "file:///.../vf-schedule-local-timeout-.../src/platform/compat/path/index.ts"
    — a live flake of the class src/testing/cwd.ts exists to prevent, and one that file has
    not opted into. Deriving the root from import.meta.url fixes it.
  • With LOG_LEVEL=DEBUG in the environment, veryfront <cmd> --json writes ~35 lines of
    debug logs to stdout ahead of the JSON envelope, which breaks JSON.parse for any
    machine consumer. setJsonMode() (cli/shared/json-output.ts:20) lowers the level only
    after flag parsing, so module-load-time logs escape it. That one is a product bug and
    deserves its own issue.

Summary by CodeRabbit

  • Tests
    • Improved CLI test output by suppressing unrelated runtime dependency-resolution diagnostics.
    • Added documentation clarifying expected stderr behavior for CLI assertions.

…output

The two `info JSON output` tests run `cli/main.ts` as a child process and
require its stderr to be empty. They were also requiring something else: that
every npm dependency of the CLI already be present on the machine.

`deno.json` sets `nodeModulesDir` to `auto`, so before the child reaches the
command it reconciles `node_modules/` against `cli/main.ts`'s graph, and it
narrates that work on stderr -- `Download https://registry.npmjs.org/yaml`.
Nothing puts `yaml` there for us. CI warms its Deno cache from `src/index.ts`,
and `yaml` reaches the CLI only through `cli/main.ts`, via
`@opentelemetry/configuration` and `bash-tool`; it is in neither the warmed blob
nor the test process's own graph. Whether a shard paid for the fetch came down
to which cache entry `actions/cache` happened to restore, which is why coverage
shard 7 failed here on pull requests that cannot reach this code.

`--quiet` suppresses the runtime's diagnostics and nothing else. What the CLI
writes still arrives -- `veryfront skills info` with no name and no `--json`
still reports its usage error on stderr underneath it -- so the assertions still
hold the command to a silent stderr; they just no longer hold the module cache
to it as well.

Verified by evicting the `yaml` packument from `DENO_DIR` before each run, which
reproduces the CI diff exactly: 0/25 runs passed before, 25/25 after.
@coderabbitai

coderabbitai Bot commented Aug 12, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 88a067ea-1c3a-4361-a094-90864e54e140

📥 Commits

Reviewing files that changed from the base of the PR and between d5a0383 and 2059023.

📒 Files selected for processing (1)
  • cli/commands/skills/handler.test.ts

📝 Walkthrough

Walkthrough

The skills CLI test helper now passes --quiet to Deno. Documentation explains the stderr behavior and dependency-resolution diagnostics. Existing output and error handling remain unchanged.

Changes

Skills CLI test execution

Layer / File(s) Summary
Quiet Deno subprocess runner
cli/commands/skills/handler.test.ts
runSkillsInfo passes --quiet to Deno. A comment documents the stderr behavior and dependency-resolution issue. Output and error handling remain unchanged.

Estimated code review effort: 1 (Trivial) | ~2 minutes

Mergeability Score: ⚪ Minimal · up to 20590

This localized test-only change prevents runtime dependency-fetch diagnostics from being mistaken for CLI stderr output, without changing CLI behavior. No actionable merge-blocking risk remains beyond normal checks and review.

Suggested reviewers: kwakayama

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the test change that prevents module-cache diagnostics from being treated as CLI output.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/skills-cli-stderr-module-cache

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

kojiwakayama added a commit that referenced this pull request Aug 12, 2026
Address PR review feedback on #3652:

- Replace Number.parseInt with full-string digit check in parsePortEnv so
  PORT=3001abc is rejected rather than silently parsed as 3001
- Reject PORT values outside 1-65535 (zero, negative, overflow) with a
  logWarning that names the exact value and reason
- Update handleDevCommand warning block to reuse parsePortEnv("PORT")
  instead of a second inline parseInt path
- Add three tests: trailing garbage (3001abc), PORT=0, PORT=65536 — all
  must fall back to 3000 and emit a warning
- command-help.ts: drop the dangling comma, tell users to open the URL the
  CLI prints on port fallback
- quickstart.md: replace em dash with semicolon to fix lint:ci failure
- Revert skills/handler.test.ts and attachment-csrf.test.tsx to origin/main
  (changes belong to separate PRs #3653 and a future CSRF fix)
@kwakayama
kwakayama added this pull request to the merge queue Aug 13, 2026
Merged via the queue into main with commit 06d303a Aug 13, 2026
33 checks passed
@kwakayama
kwakayama deleted the fix/skills-cli-stderr-module-cache branch August 13, 2026 05:27
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