Skip to content

fix(cli): wheels test --verbose renders the per-spec tree via the runtime verboseEnabled signal#3168

Merged
bpamiri merged 2 commits into
developfrom
peter/issue-3113-test-verbose
Jun 12, 2026
Merged

fix(cli): wheels test --verbose renders the per-spec tree via the runtime verboseEnabled signal#3168
bpamiri merged 2 commits into
developfrom
peter/issue-3113-test-verbose

Conversation

@bpamiri

@bpamiri bpamiri commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Fixes #3113 (the --verbose half; the --ci half shipped in #3132).

Root cause — where the data dropped

The suite-endpoint JSON and the CLI renderer were both fine. The drop is in flag delivery, in two places:

  1. LuCLI launcher (upstream): the picocli root defines -v/--verbose as GLOBAL options and consumes them wherever they appear — wheels test --verbose forwards only test to the module (the shortcut notice proves it: equivalent to 'lucli modules run wheels test', no --verbose). Worse, the shortcut re-dispatch (spec.commandLine().execute("modules","run",...)) re-parses from scratch and resets LuCLI.verbose to false, so the module received init(verboseEnabled = false) no matter what the user typed. Verified live with a probe: verboseEnabled=false despite the verbose notice printing.
  2. Module side (this repo): even when the runtime delivers verboseEnabled = true, test() only read the parsed --verbose token (opts.verbose) — which can never arrive on a normal install — and ignored variables.verboseEnabled entirely.

displayTestResults()'s verbose tree and the live JSON's bundleStats both work — confirmed by rendering live results: lucli modules run wheels test --core --filter=di --verbose (the one path where the token survives) printed the full per-spec tree even before this fix.

Fix

  • This PR (module half): test() resolves verbosity via new $resolveTestVerbosity(opts.verbose) — parsed token OR the runtime verboseEnabled signal LuCLI passes through init(). Public $-prefixed for spec reachability; auto-hidden from MCP by the mcpHiddenTools() structural sweep.
  • LuCLI half (upstream): re-assert the consumed global flags on the re-dispatched command line. Branch pushed to bpamiri/LuCLI:peter/3113-preserve-global-flags-module-shortcut (commit 491f2e6); the upstream PR to cybersonic/LuCLI needs to be opened manually (sandbox classifier blocks cross-repo PR creation) — staged body at /tmp/wf3113-lucli-pr-body.md.

Live end-to-end proof (docker lucee7 on :63313 serving this worktree, patched LuCLI jar run exactly as the wheels binary)

RED (released brew 4.0.3 binary + this worktree's module, pre-fix):

$ wheels test --core --db=sqlite --filter=di --verbose
Executing module shortcut: wheels (equivalent to 'lucli modules run wheels test --core --db=sqlite --filter=di')
Running core tests (sqlite)...
Scope: wheels.tests.specs.di
39 passed (0.06s)            # byte-identical to a plain run — exactly the issue report

GREEN (patched LuCLI jar + this PR's module fix):

$ java -Dlucli.binary.name=wheels -jar lucli.jar test --core --db=sqlite --filter=di --verbose
...
Bundle: wheels.tests.specs.di.InjectorLifecycleSpec
  Injector lifecycle — singleton survival
    [PASS] auth Authenticator + SessionStrategy survive ServiceProvider re-registration (H1 broad repro)
    ... (39 [PASS] lines total)
39 passed (0.03s)

All three flag positions verified live: wheels test --verbose → 39 per-spec lines, wheels test -v → 39, wheels -v test → 39; plain run → 0.

Tests (TDD red-first)

  • New $resolveTestVerbosity describe in TestCommandSpec.cfc — red first (Component [cli.lucli.Module] has no function with name [$resolveTestVerbosity], 3 errors), green after.
  • Full CLI suite in the docker container: 994 pass, 0 fail, 2 errors — both errors are the pre-existing deploy.lib.SshClientSpec/SshPoolSpec container artifacts (shell-out exit 127), identical on the red baseline run. (One ServerCommandsSpec flake appeared in a single run and passed on re-run.)

Docs

  • testing.mdx + ci-integration.mdx: replaced the "Accepted but currently inert" --verbose rows with the real behavior, including the note that binaries built on a pre-fix LuCLI runtime drop the signal.
  • Changelog fragment changelog.d/3113-cli-test-verbose-tree.fixed.md.

🤖 Generated with Claude Code

bpamiri and others added 2 commits June 12, 2026 13:14
…time verboseEnabled signal

Signed-off-by: Peter Amiri <peter@alurium.com>
… tree

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Peter Amiri <peter@alurium.com>
@bpamiri bpamiri enabled auto-merge (squash) June 12, 2026 20:17
@github-actions github-actions Bot added the docs label Jun 12, 2026

@wheels-bot wheels-bot 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.

Wheels Bot — Reviewer

TL;DR: This PR makes wheels test --verbose actually render the per-spec tree by resolving verbosity from the runtime verboseEnabled signal (init()variables.verboseEnabled) in addition to the parsed --verbose token, which the LuCLI picocli root consumes before the module ever sees it. The change is minimal, correct, TDD'd red-first, and the docs/changelog are accurate against the code. Verdict: comment — no blocking findings; one minor commit-trailer nit below.

What I verified against the head commit (5afcda82):

  • Correctness. $resolveTestVerbosity() (cli/lucli/Module.cfc:787-789) is parsedVerbose || (variables.verboseEnabled ?: false) — the parsed token still wins for direct invocations, and the ?: guard keeps it safe on a runtime/base that never sets verboseEnabled. The test-harness stub confirms the contract the fix relies on: cli/lucli/tests/_modules/BaseModule.cfc:14 stores variables.verboseEnabled = arguments.verboseEnabled, mirroring LuCLI's real BaseModule. Downstream, verboseOutput flows test()runTests()displayTestResults(result, verboseOutput, …) (Module.cfc:5648), where Module.cfc:5874 gates the bundleStats per-spec tree — so the one-line call-site change (Module.cfc:744) is exactly where the data was dropping.
  • Cross-engine. Not applicable in the usual matrix sense — the CLI runs only on the bundled Lucee (cli/CLAUDE.md § Cross-engine). No invariants tripped: no inline-closure constructor args, no reserved-scope parameter names (parsedVerbose is safe), no bracket-notation calls.
  • MCP surface. The new helper is public-$-prefixed per the cli/CLAUDE.md "public for specs" carve-out and is auto-hidden by the structural sweep in mcpHiddenTools() (Module.cfc:200-218), which exists precisely so new $-helpers need no denylist edit.

Tests

No findings — noting coverage for the record. The new $resolveTestVerbosity describe in TestCommandSpec.cfc:434-452 covers all three meaningful paths: plain run (false), runtime signal via a fresh new cli.lucli.Module(cwd=…, verboseEnabled=true) instance (the load-bearing path), and a parsed token that does reach the module's parser. BDD syntax on the CLI BaseSpec, red-first per the PR body (has no function with name [$resolveTestVerbosity]). The end-to-end test() path remains under the pre-existing xdescribe (TestCommandSpec.cfc:30, #2829 — needs a running server), which is a documented harness limitation, not a gap introduced here.

Docs

No findings — the rewritten --verbose rows are accurate against the code: the tree applies only to the default simple reporter (the reporter dispatch at Module.cfc:5639-5648 routes json/tap away from displayTestResults), and both pages honestly flag that binaries built on a pre-fix LuCLI runtime drop the signal. Changelog fragment changelog.d/3113-cli-test-verbose-tree.fixed.md uses the correct <slug>.fixed.md form with a complete bullet; no direct CHANGELOG.md edit.

Commits

  • Nit (non-blocking): 5afcda82 (docs(web/guides): …) carries a Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> trailer. cli/CLAUDE.md § "Things to remember" says not to add the Claude signature to commit messages, and the last 200 commits on develop contain zero such trailers — the fix commit 4f5c7c0d is correctly clean. Not a commitlint violation (commitlint.config.js has no trailer rules), so this only matters if the merge preserves individual commits; worth dropping on any rebase, otherwise fine.

Both commit headers pass commitlint: valid types (fix, docs), ≤ 100 chars, not ALL-CAPS, DCO sign-offs present and matching the author.

@bpamiri bpamiri merged commit 5d89911 into develop Jun 12, 2026
15 checks passed
@bpamiri bpamiri deleted the peter/issue-3113-test-verbose branch June 12, 2026 20:22
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.

cli: wheels test --verbose and --ci have no observable effect — docs promise per-spec output and CI tightening

1 participant