Skip to content

fix(cli): add sudo hint to debug dmesg-restricted message - #4384

Merged
cv merged 5 commits into
mainfrom
fix/4366-dmesg-restricted-sudo-hint
May 29, 2026
Merged

fix(cli): add sudo hint to debug dmesg-restricted message#4384
cv merged 5 commits into
mainfrom
fix/4366-dmesg-restricted-sudo-hint

Conversation

@jason-ma-nv

@jason-ma-nv jason-ma-nv commented May 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

nemoclaw debug running as a non-root user with kernel.dmesg_restrict=1 already explains in the Kernel Messages section that dmesg is restricted, but it does not tell the user how to include kernel logs. Add a "Re-run with sudo nemoclaw debug" hint to the skipped message so users and triagers see a concrete next step, matching the spec in the issue's Suggested Fix. The optional TTY-aware sudo -n dmesg fallback in the same Suggested Fix is intentionally out of scope for this minimum-viable change.

Related Issue

Fixes #4366.

Changes

  • src/lib/diagnostics/debug.ts: extend dmesgRestrictedMessage to append a second line — Re-run with `sudo nemoclaw debug` to include kernel logs in this report. — to the parenthetical block, and export the function so the wording can be unit-tested.
  • src/lib/diagnostics/debug.test.ts: two new #4366 tests asserting the message still explains why kernel messages were skipped and that it contains the sudo re-run hint.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Verification

  • npx prek run --all-files passes
  • npm test passes
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Jason Ma jama@nvidia.com

Summary by CodeRabbit

  • New Features

    • Improved message when kernel log collection is skipped: explains the restriction, warns privileged diagnostics may include sensitive data, and shows a suggested elevated re-run command that preserves your original --quick/--output flags (with safe quoting).
  • Tests

    • Added tests verifying the restricted-access diagnostic message and the correctness of the suggested re-run command.

Review Change Stack

When `kernel.dmesg_restrict=1` and the user runs `nemoclaw debug` as
non-root, the Kernel Messages section explained why the section was
skipped but did not tell the user how to include kernel logs anyway.
Extend `dmesgRestrictedMessage` to append a "Re-run with `sudo
nemoclaw debug`" hint so users and triagers see a concrete next step,
matching the spec in the bug's Suggested Fix.

The TTY-aware `sudo -n dmesg` fallback from the same Suggested Fix is
intentionally out of scope for this minimum-viable change.

Export `dmesgRestrictedMessage` so the wording can be pinned by a
unit test.

Fixes #4366.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Jason Ma <jama@nvidia.com>
@jason-ma-nv jason-ma-nv self-assigned this May 28, 2026
@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Exports a dmesg re-run hint helper and adds buildDmesgRerunCommand; threads DebugOptions through kernel message collection so the hint preserves --quick/--output. Tests verify message text and shell-safe quoting/escaping of the re-run command.

Changes

dmesg re-run hint + option threading

Layer / File(s) Summary
buildDmesgRerunCommand and exported dmesgRestrictedMessage
src/lib/diagnostics/debug.ts, src/lib/diagnostics/debug.test.ts
Adds buildDmesgRerunCommand(opts) to construct a sudo nemoclaw debug re-run command that preserves --quick and safely single-quotes/escapes --output. Exports dmesgRestrictedMessage(reason, opts) which returns a multi-line guidance string embedding that command. Tests assert message content and quoting/escaping.
Thread DebugOptions through kernel collection
src/lib/diagnostics/debug.ts
collectKernelMessages now accepts opts: DebugOptions; non-macOS path calls collectDmesg(collectDir, opts); runDebug forwards opts to enable option-aware restricted/denied hints.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • NVIDIA/NemoClaw#3854: Both PRs modify src/lib/diagnostics/debug.ts to change nemoclaw debug’s handling of restricted dmesg output—fix(cli): explain restricted dmesg in debug output #3854 adds detection via isDmesgPermissionDeniedOutput/collectDmesg, while the main PR adds exported helpers (dmesgRestrictedMessage, buildDmesgRerunCommand) and threads options into the same restricted-kernel-messages path.
  • NVIDIA/NemoClaw#3890: Main PR expands the restricted-dmesg feature by adding the user-facing dmesgRestrictedMessage/buildDmesgRerunCommand (and threading debug options) for the same restriction scenario that PR #3890 began by exporting isDmesgRestrictedForCurrentUser to detect kernel.dmesg_restrict-based failures.

Suggested labels

v0.0.51

Suggested reviewers

  • jyaunches
  • ericksoa

Poem

🐰 I hopped through logs both terse and grand,
Wove a sudo hint with a careful hand.
Quote the path, escape a single-quote too,
Now rerun advice is clear and true.
Tests nod, the rabbit gives a grateful chew.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adding a sudo hint to the dmesg-restricted message shown by the debug command.
Linked Issues check ✅ Passed The PR implements the core objective from #4366: appending a sudo re-run hint to the dmesg-restricted message, preserving user options like --quick and --output in the suggested command.
Out of Scope Changes check ✅ Passed All changes are scoped to the objectives: exporting dmesgRestrictedMessage and buildDmesgRerunCommand, threading DebugOptions through the collection path, and adding comprehensive tests verifying the new functionality.

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

✨ 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/4366-dmesg-restricted-sudo-hint

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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

@github-actions

github-actions Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: diagnostics-e2e
Optional E2E: None

Dispatch hint: diagnostics-e2e

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • diagnostics-e2e (medium): Direct coverage for nemoclaw debug --quick, nemoclaw debug --output, diagnostics tarball creation, and credential sanitization. The PR changes the diagnostics collector’s dmesg-restricted path and option-aware debug rerun hints, so this should run before merge.

Optional E2E

  • None.

New E2E recommendations

  • diagnostics-debug-cli (medium): Existing diagnostics E2E exercises debug quick/output and tarball sanitization, but does not appear to assert the restricted-dmesg user message or preservation of --quick and --output in the sudo rerun hint. Add an E2E assertion that simulates dmesg permission denial/restriction and verifies the emitted hint and sensitive-data warning.
    • Suggested test: Extend test/e2e/test-diagnostics.sh with a restricted-dmesg case for nemoclaw debug --quick --output <path> asserting the generated dmesg.txt/message contains sudo nemoclaw debug --quick --output '<path>' and the sensitive-data warning.

Dispatch hint

  • Workflow: nightly-e2e.yaml
  • jobs input: diagnostics-e2e

@github-actions

github-actions Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

E2E Scenario Advisor Recommendation

Required scenario E2E: None
Optional scenario E2E: None

Workflow run

Full scenario advisor summary

E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required scenario E2E

  • None. Changes are limited to diagnostics/debug implementation and its unit test outside test/e2e-scenario/ and the scenario workflows. The scenario catalog/suites do not exercise the debug command, so no scenario E2E job is recommended.

Optional scenario E2E

  • None.

Relevant changed files

  • None.

@github-actions

github-actions Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor

Findings: 1 needs attention, 3 worth checking, 0 nice ideas
Since last review: 1 prior item resolved, 1 still applies, 2 new items found

Review findings

🛠️ Needs attention

  • Offset the debug collector hotspot growth (src/lib/diagnostics/debug.ts:164): This PR adds more logic to an already-large diagnostics module. The deterministic monolith check reports src/lib/diagnostics/debug.ts growing from 606 to 630 lines (+24), crossing the configured hotspot threshold for current monolith growth.
    • Recommendation: Extract the new dmesg rerun-command/message helpers, or offset the growth by moving existing dmesg/debug-message code into a focused diagnostics helper module before merge.
    • Evidence: Monolith delta: src/lib/diagnostics/debug.ts baseLines=606, headLines=630, delta=24, severity=blocker. The new code starts around buildDmesgRerunCommand() and dmesgRestrictedMessage().

🔎 Worth checking

  • Source-of-truth review needed: Restricted dmesg recovery message: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: collectDmesg() detects isDmesgRestrictedForCurrentUser() or isDmesgPermissionDeniedOutput(raw), then emits dmesgRestrictedMessage(..., opts). buildDmesgRerunCommand() preserves quick/output but not sandboxName.
  • Preserve the full debug target context in the privileged rerun hint (src/lib/diagnostics/debug.ts:164): The new sudo hint preserves --quick and --output, but DebugOptions also carries sandboxName and the generated command omits --sandbox. A user who ran a scoped command such as nemoclaw debug --quick --sandbox alpha may be told to run sudo nemoclaw debug --quick, which can target root's default/autodetected sandbox instead of the original target. Because the hint recommends privileged diagnostics that may gather broader host, OpenShell, sandbox, Docker, process, and kernel information, losing target context can misdirect or broaden data collection. The output path is shell single-quoted and single quotes are escaped, but pathological display characters such as newlines/control characters are still rendered into copy/paste shell guidance.
    • Recommendation: Include --sandbox with safe display quoting when opts.sandboxName is set, or explicitly document why it is intentionally omitted. Consider normalizing or rejecting control characters in values rendered into the copy/paste command. Add tests for --sandbox preservation and unusual output display values.
    • Evidence: DebugOptions declares sandboxName, quick, and output, but buildDmesgRerunCommand() only appends --quick and --output. runDebug() resolves sandboxName separately for collection, while collectKernelMessages(collectDir, opts) receives the original opts.
  • Add runtime-path coverage for the restricted dmesg hint (src/lib/diagnostics/debug.test.ts:153): The new helper tests cover the message and command builder well, including --quick, --output, combined flags, single-quote escaping, and the sensitive-data warning. However, the regression from [All Platforms][CLI&UX] nemoclaw debug: dmesg-restricted kernel section still not labeled as clearly as spec (no sudo hint) #4366 is a runtime collector path: debug --quick on a dmesg-restricted host. The current tests do not prove runDebug({ quick: true }) reaches collectKernelMessages() and emits the option-aware restricted message, nor do they cover the remaining source-of-truth lifecycle details for when this recovery guidance can be removed or replaced.
    • Recommendation: Add or identify a targeted runtime/integration-style test that stubs the dmesg restriction path and asserts the collected/printed Kernel Messages section includes sudo nemoclaw debug --quick, plus any preserved target context such as --sandbox. Document the removal/replacement condition, for example if an interactive privileged dmesg path is later implemented.
    • Evidence: Tests call dmesgRestrictedMessage() and buildDmesgRerunCommand() directly. The production path is runDebug() -> collectKernelMessages(collectDir, opts) -> collectDmesg(collectDir, opts) -> dmesgRestrictedMessage(..., opts). Deterministic test-depth context recommends runtime validation for src/lib/diagnostics/debug.ts.

🌱 Nice ideas

  • None.
Since last review details

Current findings:

  • Source-of-truth review needed: Restricted dmesg recovery message: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: collectDmesg() detects isDmesgRestrictedForCurrentUser() or isDmesgPermissionDeniedOutput(raw), then emits dmesgRestrictedMessage(..., opts). buildDmesgRerunCommand() preserves quick/output but not sandboxName.
  • Offset the debug collector hotspot growth (src/lib/diagnostics/debug.ts:164): This PR adds more logic to an already-large diagnostics module. The deterministic monolith check reports src/lib/diagnostics/debug.ts growing from 606 to 630 lines (+24), crossing the configured hotspot threshold for current monolith growth.
    • Recommendation: Extract the new dmesg rerun-command/message helpers, or offset the growth by moving existing dmesg/debug-message code into a focused diagnostics helper module before merge.
    • Evidence: Monolith delta: src/lib/diagnostics/debug.ts baseLines=606, headLines=630, delta=24, severity=blocker. The new code starts around buildDmesgRerunCommand() and dmesgRestrictedMessage().
  • Preserve the full debug target context in the privileged rerun hint (src/lib/diagnostics/debug.ts:164): The new sudo hint preserves --quick and --output, but DebugOptions also carries sandboxName and the generated command omits --sandbox. A user who ran a scoped command such as nemoclaw debug --quick --sandbox alpha may be told to run sudo nemoclaw debug --quick, which can target root's default/autodetected sandbox instead of the original target. Because the hint recommends privileged diagnostics that may gather broader host, OpenShell, sandbox, Docker, process, and kernel information, losing target context can misdirect or broaden data collection. The output path is shell single-quoted and single quotes are escaped, but pathological display characters such as newlines/control characters are still rendered into copy/paste shell guidance.
    • Recommendation: Include --sandbox with safe display quoting when opts.sandboxName is set, or explicitly document why it is intentionally omitted. Consider normalizing or rejecting control characters in values rendered into the copy/paste command. Add tests for --sandbox preservation and unusual output display values.
    • Evidence: DebugOptions declares sandboxName, quick, and output, but buildDmesgRerunCommand() only appends --quick and --output. runDebug() resolves sandboxName separately for collection, while collectKernelMessages(collectDir, opts) receives the original opts.
  • Add runtime-path coverage for the restricted dmesg hint (src/lib/diagnostics/debug.test.ts:153): The new helper tests cover the message and command builder well, including --quick, --output, combined flags, single-quote escaping, and the sensitive-data warning. However, the regression from [All Platforms][CLI&UX] nemoclaw debug: dmesg-restricted kernel section still not labeled as clearly as spec (no sudo hint) #4366 is a runtime collector path: debug --quick on a dmesg-restricted host. The current tests do not prove runDebug({ quick: true }) reaches collectKernelMessages() and emits the option-aware restricted message, nor do they cover the remaining source-of-truth lifecycle details for when this recovery guidance can be removed or replaced.
    • Recommendation: Add or identify a targeted runtime/integration-style test that stubs the dmesg restriction path and asserts the collected/printed Kernel Messages section includes sudo nemoclaw debug --quick, plus any preserved target context such as --sandbox. Document the removal/replacement condition, for example if an interactive privileged dmesg path is later implemented.
    • Evidence: Tests call dmesgRestrictedMessage() and buildDmesgRerunCommand() directly. The production path is runDebug() -> collectKernelMessages(collectDir, opts) -> collectDmesg(collectDir, opts) -> dmesgRestrictedMessage(..., opts). Deterministic test-depth context recommends runtime validation for src/lib/diagnostics/debug.ts.

Workflow run details

This is an automated advisory review. A human maintainer must make the final merge decision.

@cv cv added v0.0.55 and removed v0.0.54 labels May 28, 2026
@cjagwani cjagwani self-assigned this May 28, 2026
@wscurran

Copy link
Copy Markdown
Contributor

@jyaunches jyaunches added the R3 label May 29, 2026
Address PR review advisor feedback: the previous hint hardcoded
`sudo nemoclaw debug` regardless of the user's invocation, which would
nudge a user who ran `debug --quick` into the broader privileged
collector.

- Make `dmesgRestrictedMessage` accept `DebugOptions` and build the
  rerun command via new `buildDmesgRerunCommand` helper that preserves
  `--quick` and `--output` (with shell-safe single-quoting).
- Plumb `opts` through `collectKernelMessages` -> `collectDmesg`.
- Add a sensitive-data caution to the recovery message so users review
  privileged diagnostics before sharing.
- Add option-aware regression tests covering the rerun-command builder
  and message wording.

Refs: #4366
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
@jyaunches jyaunches added v0.0.56 and removed v0.0.55 labels May 29, 2026

@coderabbitai coderabbitai 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.

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 `@src/lib/diagnostics/debug.ts`:
- Around line 157-173: The dmesg rerun hint omits sandbox scoping: update
buildDmesgRerunCommand to append "--sandbox" followed by the sandbox name when
opts.sandboxName is set (use the same single-quote escaping logic as for
opts.output — replace any "'" with "'\\''" and wrap the escaped value in single
quotes), so the generated command preserves sandbox scope; also add/extend unit
tests for buildDmesgRerunCommand to verify a sandboxName results in a "--sandbox
'<name>'" token and that embedded single quotes are correctly escaped.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 686a5741-6dc0-4748-9aff-d00a52eb0703

📥 Commits

Reviewing files that changed from the base of the PR and between ad97b46 and b56f12a.

📒 Files selected for processing (2)
  • src/lib/diagnostics/debug.test.ts
  • src/lib/diagnostics/debug.ts

Comment on lines +157 to +173
/**
* Build the option-aware re-run command for the dmesg-restricted hint.
*
* Preserves the user's original invocation flags (`--quick`, `--output`) so the
* hint nudges them back into the same scoped diagnostic instead of a broader
* privileged collector. See issue #4366.
*/
export function buildDmesgRerunCommand(opts: DebugOptions = {}): string {
const parts = ["sudo", "nemoclaw", "debug"];
if (opts.quick) parts.push("--quick");
if (opts.output) {
// Single-quote the path and escape embedded single quotes for shell safety.
const escaped = opts.output.replace(/'/g, "'\\''");
parts.push("--output", `'${escaped}'`);
}
return parts.join(" ");
}

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if sandbox name affects diagnostic collection behavior

# Find where sandboxName is used in debug collection
rg -n -C3 'sandboxName' src/lib/diagnostics/debug.ts

# Check if there are sandbox-specific collection steps
ast-grep --pattern 'function collect$_($$$, sandboxName, $$$) { $$$ }'

Repository: NVIDIA/NemoClaw

Length of output: 3397


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find where buildDmesgRerunCommand is used (rerun hint path)
rg -n "buildDmesgRerunCommand" -S src/lib/diagnostics/debug.ts src/lib/diagnostics

# 2) Inspect dmesgRestrictedMessage and surrounding logic to see what opts are passed
rg -n "dmesgRestrictedMessage|collectDmesg|debug.*rerun|rerun" -S src/lib/diagnostics/debug.ts

# 3) Check how detectSandboxName determines a default (and whether it depends on registry/home)
rg -n "function detectSandboxName|detectSandboxName\\(" -S src/lib/diagnostics/debug.ts src/lib

# 4) If registry is involved, check where it’s stored/scoped
rg -n "REGISTRY_FILE|sandboxes\\.json|sandbox.*registry|nemoclaw.*sandboxes" -S src/lib

Repository: NVIDIA/NemoClaw

Length of output: 9589


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show relevant code blocks in debug.ts
sed -n '140,260p' src/lib/diagnostics/debug.ts
echo "----"
sed -n '200,280p' src/lib/diagnostics/debug.ts
echo "----"
sed -n '220,260p' src/lib/diagnostics/debug.ts
echo "----"
sed -n '560,640p' src/lib/diagnostics/debug.ts
echo "----"

# Show relevant tests for buildDmesgRerunCommand
sed -n '160,250p' src/lib/diagnostics/debug.test.ts
echo "----"
rg -n "4366|dmesg-rerun|buildDmesgRerunCommand" -S src/lib/diagnostics/debug.test.ts

Repository: NVIDIA/NemoClaw

Length of output: 13189


Preserve --sandbox in the dmesg-restricted rerun hint

buildDmesgRerunCommand() only carries --quick and --output and ignores opts.sandboxName, so dmesgRestrictedMessage() generates a re-run command without --sandbox. Since runDebug() uses opts.sandboxName to scope sandbox-specific collection (e.g., OpenShell fetches/logs use sandboxName), re-running via the hint under sudo can target a different sandbox because auto-detection reads the HOME-scoped registry and otherwise falls back to the first entry from openshell sandbox list.

Add --sandbox '<name>' to the hint when opts.sandboxName is set (using the same single-quote escaping as --output) and extend the existing buildDmesgRerunCommand unit tests.

🤖 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 `@src/lib/diagnostics/debug.ts` around lines 157 - 173, The dmesg rerun hint
omits sandbox scoping: update buildDmesgRerunCommand to append "--sandbox"
followed by the sandbox name when opts.sandboxName is set (use the same
single-quote escaping logic as for opts.output — replace any "'" with "'\\''"
and wrap the escaped value in single quotes), so the generated command preserves
sandbox scope; also add/extend unit tests for buildDmesgRerunCommand to verify a
sandboxName results in a "--sandbox '<name>'" token and that embedded single
quotes are correctly escaped.

@cv
cv merged commit eae6f8a into main May 29, 2026
30 checks passed
@cv
cv deleted the fix/4366-dmesg-restricted-sudo-hint branch May 29, 2026 21:46
@wscurran wscurran added area: cli Command line interface, flags, terminal UX, or output bug-fix PR fixes a bug or regression and removed NemoClaw CLI labels Jun 3, 2026
@wscurran wscurran added the NV QA Bugs found by the NVIDIA QA Team label Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: cli Command line interface, flags, terminal UX, or output bug-fix PR fixes a bug or regression NV QA Bugs found by the NVIDIA QA Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[All Platforms][CLI&UX] nemoclaw debug: dmesg-restricted kernel section still not labeled as clearly as spec (no sudo hint)

5 participants