Menu

#447 feat(cli): add --quiet to doberman demo (#441)

closed
nobody
None
2026-08-27
2026-08-21
Anonymous
No

Originally created by: blackcoderx

Slice

  • Repo: doberman-core
  • Feature / Slice: [#441]doberman demo --quiet

What this PR does

Adds a --quiet / -q flag to doberman demo, mirroring scan --quiet. When
set, it suppresses the opening banner, the per-scenario narration line, and the
closing "Run doberman dash" hint — keeping only the summary (silent on a full
match, loud with details on a mismatch) and the exit code. This lets demo run
as a CI smoke test ("is the engine alive") without polluting build logs.
Display-only: the scenarios and the engine decision path are untouched.

Tests added (run in CI)

  • tests/unit/test_cli_demo_quiet.pydemo --fast --quiet produces far
    fewer stdout lines than demo --fast (banner/narration/hint gone), exit
    codes match between quiet and loud runs, and the quiet run still reports the
    summary line.

Public-release safety (doberman-core only)

  • [x] Contains nothing from the "not allowed" list: no enterprise/hosted code, no proprietary detection, no customer data, no secrets, no commercial-license code
  • [x] Core still builds/tests/runs with NO enterprise package installed

Security checklist

  • [x] Fails closed on error / uncertainty
  • [x] No secret, full file, or unredacted prompt logged or committed
  • [x] Any guardrail/learning change is raise-only (no silent loosening)
  • [x] Every BLOCK/AUTH carries reason codes + a human explanation
  • [x] doberman-core does not import doberman_enterprise

Edge cases covered / Deviations from plan / Risks introduced

  • Covered: quiet mode still surfaces the mismatch summary (loud, with per-scenario detail) if a scenario disagrees with its expected verdict — only the narration is suppressed, not failure visibility.
  • No deviations from the issue's proposed approach.
  • No risks: purely a CLI display change, no engine/rule/decision-path changes.

Written with Claude Code assistance.

Closes [#441]

Related

Tickets: #441
Tickets: #452
Tickets: #458
Tickets: #460
Tickets: #483

Discussion

  • Anonymous

    Anonymous - 2026-08-21

    Originally posted by: blackcoderx

    @fu351 — flagging this for you.

    CI: 5/6 checks are green (secret-scan, package-smoke-test, test (ubuntu-latest, 3.12), test (ubuntu-latest, 3.13), test (windows-latest, 3.12)). Only test (ubuntu-latest, 3.11) fails, and it's unrelated to this PR's diff.

    Root cause: test collection dies with the same error in ~230 unrelated modules:

    TypeError: type 'DictReader' is not subscriptable
    

    traced through doberman/subjective/baseline.pyriverriver/stream/iter_csv.py:21:

    class DictReader(csv.DictReader["FeatureName"]):
    

    csv.DictReader isn't subscriptable at runtime on Python 3.11 — only on newer Python, which is exactly why 3.12/3.13/Windows-3.12 all passed and only the 3.11 leg died.

    It's a fresh regression, not a pre-existing bug in this repo's code: the failing job's pip resolve pulled river==0.26.0 (pyproject.toml has an unpinned floor, river>=0.21). The previously-resolved river==0.25.0 has the unsubscripted form (class DictReader(csv.DictReader):, no ["FeatureName"]), so 0.26.0 is the version that introduced the runtime subscript. main's last CI run this morning was green only because its pip cache still held the older wheel — the next cache miss on main will hit this too, independent of any change here.

    Confirmed this reproduces against a clean main checkout as well, before any of this PR's changes existed, so it's not something introduced by this slice. Leaving the call on whether/how to pin river to you rather than bundling an unrelated dependency fix into this PR.

     
  • Anonymous

    Anonymous - 2026-08-24

    Originally posted by: fu351

    Thanks @blackcoderx, and thank you for the river diagnosis, tracing it to the 0.25→0.26 DictReader subscript and reproducing against a clean main saved me the whole investigation. The pin is merged as [#452]. Two small things on the PR itself: the one behavior this flag exists for, a mismatch still failing loudly with a nonzero exit under --quiet, has no direct test, and test_demo.py already has the mismatch-forcing pattern, so one test combining the two closes that. And docs/CLI.md's flag table borrows scan's no-output wording, but demo --quiet keeps the summary line, your CHANGELOG entry says it right and the table doesn't. Don't worry about the merge conflict the pin created, that one's mine, I'll land the branch from here once the test is in.

     

    Related

    Tickets: #452

  • Anonymous

    Anonymous - 2026-08-24

    Originally posted by: blackcoderx

    @fu351 Both addressed, pushed as cbf31be:

    • Added test_mismatch_still_reported_loudly_under_quiet to test_cli_demo_quiet.py, combining test_demo.py's mismatch-forcing pattern with --quiet — asserts nonzero exit, MISMATCH, and the actual/expected detail still print under --quiet.
    • Fixed docs/CLI.md's flag table: it no longer claims demo --quiet is fully silent like scan --quiet — now says it keeps the banner/narration/hint suppressed but the summary line/table still prints, matching what the CHANGELOG entry already said.

    Left the CHANGELOG.md conflict from [#452] alone as you asked — branch is otherwise a straight fast-forward push, no rebase.

     

    Related

    Tickets: #452

  • Anonymous

    Anonymous - 2026-08-27

    Ticket changed by: fu351

    • status: open --> closed
     
  • Anonymous

    Anonymous - 2026-08-27

    Ticket changed by: fu351

    • status: closed --> open
     
  • Anonymous

    Anonymous - 2026-08-27

    Ticket changed by: fu351

    • status: open --> closed
     
  • Anonymous

    Anonymous - 2026-08-27

    Originally posted by: fu351

    Merged, thanks @blackcoderx! test_mismatch_still_reported_loudly_under_quiet is the test this flag needed, I moved the summary print under the quiet guard locally and it went red straight away. I landed it through a landing branch in our repo rather than pushing to your fork: docs/CLI.md had been restructured on main since you branched, so I put --quiet into the new demo row and the flags sentence, and I tightened the --help string, which was copied from scan and said it silences everything. Nothing else touched. If you want the next parity cell, [#407] (level-4) proves approvals stay single-use and action-bound on OpenClaw, one step up from the three you've already landed.

     

    Related

    Tickets: #407


Log in to post a comment.