Skip to content

Implement accessibility preferences via OutputPrefs (emoji/no-emoji)#267

Merged
leynos merged 8 commits intomainfrom
respect-accessibility-preferences-ubavwa
Feb 17, 2026
Merged

Implement accessibility preferences via OutputPrefs (emoji/no-emoji)#267
leynos merged 8 commits intomainfrom
respect-accessibility-preferences-ubavwa

Conversation

@leynos
Copy link
Owner

@leynos leynos commented Feb 12, 2026

Summary

  • Introduces accessibility preferences for output formatting: emoji suppression and consistent semantic prefixes across modes.
  • Adds a centralized OutputPrefs resolution mechanism to determine whether emoji glyphs are allowed and to render localized semantic prefixes accordingly.
  • Integrates Preferences into CLI, status reporting, and main error handling.
  • Adds tests, BDD scenarios, and documentation to cover preference resolution, rendering, and edge cases.

Changes

Core functionality

  • New module: src/output_prefs.rs
    • OutputPrefs struct with emoji flag and helpers to render prefixes (error, warning, success).
    • resolve and resolve_with functions to determine emoji usage from explicit config, NO_COLOR, and NETSUKE_NO_EMOJI environment variables.
    • Prefix rendering uses Fluent localization with an emoji variant when allowed.
  • Status and reporting integration
    • src/runner/mod.rs: create prefs and pass to AccessibleReporter.
    • src/status.rs: AccessibleReporter now holds OutputPrefs and uses it to render completion prefixes (e.g.,
      “✖ Error: …” vs “Error: …”).
    • src/main.rs: on error, prefixes are applied to stderr alongside diagnostic output.

CLI and localization

  • CLI enhancements
    • src/cli/mod.rs: added no_emoji: Option to Cli and documented its behavior.
    • Updated cli_overrides_from_matches to consider no_emoji.
  • Localization updates
    • src/localization/keys.rs: added CLI_FLAG_NO_EMOJI_HELP and semantic prefix keys.
    • locales/en-US/messages.ftl and locales/es-ES/messages.ftl: added semantic prefix messages and help text for no-emoji flag.
    • src/cli_l10n.rs: map new no_emoji help key.

Documentation

  • ExecPlan for accessibility preferences
    • docs/execplans/3-8-2-respect-accessibility-preferences.md: new exec plan outlining constraints, risks, progress, and outcomes.
  • Roadmap status
    • docs/roadmap.md: 3.8.2 entry updated to mark as complete.
  • User guide updates
    • docs/users-guide.md: section added detailing emoji suppression rules and semantic prefixes.

Tests

  • Unit tests
    • New tests in src/output_prefs.rs validating resolve_with behavior and prefix rendering under emoji/no-emoji configurations.
  • BDD tests
    • New feature: tests/features/accessibility_preferences.feature and steps in tests/bdd/steps/accessibility_preferences.rs.
    • Updated fixtures to carry OutputPrefs state and rendered prefixes for assertions.
  • Test coverage
    • 18 unit tests for OutputPrefs resolution and prefix rendering.
    • 10 BDD scenarios covering emoji suppression, explicit no-emoji, NO_COLOR, and CLI parsing for --no-emoji.

Files touched

  • Added: src/output_prefs.rs
  • Added: tests/features/accessibility_preferences.feature
  • Added: tests/bdd/steps/accessibility_preferences.rs
  • Added/updated: src/main.rs, src/runner/mod.rs, src/status.rs, src/cli/mod.rs, src/cli_l10n.rs
  • Updated: src/lib.rs, src/localization/keys.rs
  • Updated: locales/en-US/messages.ftl, locales/es-ES/messages.ftl
  • Updated: docs/execplans/3-8-2-respect-accessibility-preferences.md (new)
  • Updated: docs/roadmap.md
  • Updated: docs/users-guide.md

How to test

  • Build and run
    • NETSUKE_NO_EMOJI=1 cargo run -- build (verify no emoji and semantic prefixes are present/printed)
    • NO_COLOR=1 cargo run -- build (verify no emoji and ASCII prefixes)
    • cargo run -- build with --no-emoji true/false to override auto-detection
  • Run unit tests and lint
    • make check-fmt && make lint && make test
  • Execute the new BDD scenarios under tests/features/accessibility_preferences.feature

Migration and compatibility

  • Public API signatures remain backward compatible; new CLI flag and internal module are opt-in.
  • Default behavior preserves emoji unless auto-detected as disallowed or explicitly disabled.
  • Fluent keys for semantic prefixes are used to render localized text with/without emoji as appropriate.

Risks and notes

  • The AccessibleReporter now depends on OutputPrefs; ensure all call sites construct reporters with proper prefs (handled in runner).
  • Roadmap entry 3.8.2 is completed by this change; ensure docs reflect the updated capabilities.

If you want, I can adjust the PR description to emphasize particular user-facing benefits or tailor the test matrix for CI.

◳ Generated by DevBoxer

📎 Task: https://www.devboxer.com/task/79254424-c0da-4f85-8b04-4116d4aa87d1

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Feb 12, 2026

Reviewer's Guide

Adds a centralized OutputPrefs abstraction for emoji suppression and semantic prefixes, wires it through CLI parsing, status reporting, and main error handling, and updates localization, docs, and tests to cover accessibility preference behavior.

Sequence diagram for status reporting with OutputPrefs

sequenceDiagram
    actor User
    participant Cli
    participant Main as MainModule
    participant Runner as RunnerModule
    participant OutputPrefsMod as OutputPrefsModule
    participant Reporter as AccessibleReporter
    participant Stderr as StderrStream

    User->>Cli: Invoke netsuke --accessible true --no-emoji true build
    Cli-->>Main: Parsed Cli{accessible: Some(true), no_emoji: Some(true)}

    Main->>OutputPrefsMod: resolve(merged_cli.no_emoji)
    OutputPrefsMod-->>Main: OutputPrefs{emoji: false}

    Main->>Runner: run(&merged_cli)
    Runner->>OutputPrefsMod: resolve(cli.no_emoji)
    OutputPrefsMod-->>Runner: OutputPrefs{emoji: false}
    Runner->>Runner: mode = OutputMode::resolve(cli.accessible)
    Runner->>Reporter: new(prefs)
    Runner-->>Main: Ok(()) after build

    loop build stages
        Runner->>Reporter: report_stage(current, total, description)
        Reporter->>Stderr: write Stage line
    end

    Runner->>Reporter: report_complete(tool_key)
    Reporter->>OutputPrefsMod: success_prefix() on prefs
    OutputPrefsMod-->>Reporter: LocalizedMessage "Success:" (no emoji)
    Reporter->>Stderr: write "Success: {localized status complete message}"
Loading

Sequence diagram for error handling with semantic prefixes

sequenceDiagram
    participant Main as MainModule
    participant OutputPrefsMod as OutputPrefsModule
    participant Runner as RunnerModule
    participant Stderr as StderrStream

    Main->>OutputPrefsMod: resolve(merged_cli.no_emoji)
    OutputPrefsMod-->>Main: OutputPrefs prefs

    Main->>Runner: run(&merged_cli)
    Runner-->>Main: Err(err)

    Main->>OutputPrefsMod: prefs.error_prefix()
    OutputPrefsMod-->>Main: LocalizedMessage prefix

    alt err is RunnerError
        Main->>Main: report = Report::new(runner_err)
        Main->>Stderr: write "{prefix} {report:?}"
    else other error type
        Main->>Stderr: write "{prefix} {other_err}"
    end
Loading

Class diagram for OutputPrefs and related CLI/status structures

classDiagram
    class Cli {
        +bool fetch_default_deny
        +Option~bool~ accessible
        +Option~bool~ no_emoji
        +Option~Command~ command
    }

    class OutputPrefs {
        -bool emoji
        +bool emoji_allowed()
        +LocalizedMessage error_prefix()
        +LocalizedMessage warning_prefix()
        +LocalizedMessage success_prefix()
        +static OutputPrefs resolve(no_emoji: Option~bool~)
        +static OutputPrefs resolve_with(no_emoji: Option~bool~, read_env: Fn~&str -> Option~String~~)
    }

    class StatusReporter {
        <<trait>>
        +report_stage(current: u32, total: u32, description: &str)
        +report_pending(tool_key: &str)
        +report_complete(tool_key: &'static str)
    }

    class AccessibleReporter {
        -OutputPrefs prefs
        +new(prefs: OutputPrefs) AccessibleReporter
        +report_stage(current: u32, total: u32, description: &str)
        +report_pending(tool_key: &str)
        +report_complete(tool_key: &'static str)
    }

    class OutputMode {
        <<enum>>
        Accessible
        Standard
        +static resolve(accessible: Option~bool~) OutputMode
    }

    class RunnerModule {
        +run(cli: &Cli) Result~()~
    }

    class MainModule {
        +main() ExitCode
    }

    Cli --> OutputPrefs : no_emoji
    MainModule ..> OutputPrefs : resolve(no_emoji)
    RunnerModule ..> OutputMode : resolve(accessible)
    RunnerModule ..> OutputPrefs : resolve(no_emoji)
    RunnerModule ..> StatusReporter
    AccessibleReporter ..|> StatusReporter
    AccessibleReporter o--> OutputPrefs
Loading

File-Level Changes

Change Details Files
Introduce OutputPrefs module to resolve emoji usage and provide localized semantic prefixes.
  • Add OutputPrefs struct with emoji flag and helpers for error/warning/success prefixes using Fluent messages and an emoji select argument.
  • Implement resolve and resolve_with to derive emoji allowance from explicit no_emoji config plus NO_COLOR and NETSUKE_NO_EMOJI environment variables, with clear precedence rules.
  • Expose output_prefs as a public module in the crate root and add comprehensive unit tests for resolution logic and prefix rendering, ensuring ASCII-only behavior when emoji is disabled.
src/output_prefs.rs
src/lib.rs
Propagate OutputPrefs into runner status reporting and main error output.
  • Resolve OutputPrefs in runner::run based on cli.no_emoji and pass it into AccessibleReporter only in Accessible mode.
  • Refactor AccessibleReporter into a struct holding OutputPrefs and prepend success_prefix() to completion messages when reporting status.
  • Resolve OutputPrefs in main before running the runner and use error_prefix() to prefix all stderr error diagnostics, both for RunnerError reports and generic errors.
src/runner/mod.rs
src/status.rs
src/main.rs
Extend CLI and localization to support a --no-emoji flag and semantic prefix messages.
  • Add no_emoji: Option field to Cli, include it in Default, argument parsing, and cli_overrides_from_matches so explicit CLI values override config.
  • Add new localization keys for no-emoji flag help and semantic prefixes (error/warning/success), wire them into cli_l10n flag_help_key, and provide English and Spanish Fluent messages with emoji/no variants.
  • Ensure semantic prefixes are used consistently via Fluent localization so that text labels are present regardless of emoji availability.
src/cli/mod.rs
src/cli_l10n.rs
src/localization/keys.rs
locales/en-US/messages.ftl
locales/es-ES/messages.ftl
Document accessibility preferences and mark roadmap item 3.8.2 complete.
  • Add an ExecPlan document for respecting accessibility preferences, describing constraints, risks, decisions, and outcomes for OutputPrefs and emoji suppression behavior.
  • Update roadmap entry 3.8.2 to marked completed with sub-items for honoring NO_COLOR/NETSUKE_NO_EMOJI and maintaining semantic prefixes in all modes.
  • Extend the user guide with a section describing emoji suppression rules, precedence between CLI/env/config, and the guarantee of semantic prefixes with or without emoji.
docs/execplans/3-8-2-respect-accessibility-preferences.md
docs/roadmap.md
docs/users-guide.md
Add BDD coverage and fixtures for accessibility preference behavior and CLI parsing.
  • Introduce a new accessibility_preferences.feature capturing scenarios for env-based emoji suppression, explicit no_emoji settings, prefix rendering behavior, and CLI parsing for --no-emoji true/false.
  • Implement corresponding rstest-bdd step definitions that simulate NO_COLOR/NETSUKE_NO_EMOJI, resolve OutputPrefs with a fake environment, render prefixes, and assert CLI.no_emoji values.
  • Extend the BDD TestWorld fixtures to store simulated emoji-related env vars, resolved OutputPrefs, and rendered prefixes for assertions, and register the new step module in the BDD test harness.
tests/features/accessibility_preferences.feature
tests/bdd/steps/accessibility_preferences.rs
tests/bdd/fixtures/mod.rs
tests/bdd/steps/mod.rs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Introduce an output preference system resolving emoji rendering from CLI (--no-emoji), environment (NO_COLOR, NETSUKE_NO_EMOJI) and config; export OutputPrefs; add localisation keys and docs; wire prefs through main, runner and reporters; add unit and BDD tests and update test call sites.

Changes

Cohort / File(s) Summary
Core Output Preferences
src/output_prefs.rs, src/lib.rs
Add OutputPrefs type with resolve()/resolve_with() to determine emoji allowance and produce localized error_prefix()/warning_prefix()/success_prefix(); export module; include unit tests.
CLI surface
src/cli/mod.rs, src/cli_l10n.rs
Add no_emoji: Option<bool> to Cli, expose --no-emoji, include in CLI override extraction, and map flag to localisation help key.
Application wiring
src/main.rs, src/runner/mod.rs, src/status.rs
Resolve prefs in main and pass prefs into runner::run(cli, prefs); change run signature; make AccessibleReporter hold OutputPrefs (constructor new(prefs)) and use prefs to render prefixes.
Localisation files
locales/en-US/messages.ftl, locales/es-ES/messages.ftl, src/localization/keys.rs
Add cli.flag.no_emoji.help and semantic prefix keys (error/warning/success) and include them in ALL_KEYS; note duplicate key blocks present in locale files.
Documentation & Roadmap
docs/execplans/3-8-2-respect-accessibility-preferences.md, docs/roadmap.md, docs/users-guide.md
Add execplan document, mark roadmap item 3.8.2 complete, and document emoji/accessibility preference precedence, CLI flag, env vars and behaviour in the user guide.
BDD and feature tests
tests/features/accessibility_preferences.feature, tests/bdd/steps/accessibility_preferences.rs, tests/bdd/steps/mod.rs, tests/bdd/fixtures/mod.rs
Add Gherkin scenarios and Rust step implementations to simulate env/CLI combinations; extend TestWorld with output_prefs, simulated_no_emoji, rendered_prefix.
Test call-site updates
tests/runner_tests.rs, tests/runner_tool_subcommands_tests.rs, tests/bdd/steps/process.rs, tests/*
Update test call sites to pass output_prefs::resolve(None) to runner::run(); import netsuke::output_prefs; adjust error-to-string conversions to format!("{e}") or to_owned variants across many tests.
Minor refactors / formatting
src/ir/from_manifest.rs, src/manifest/diagnostics/yaml.rs, various tests
Replace some .to_string() usages with format!("{s}"), str::to_owned or format!("{e}") for Display-based conversions; no behavioural changes.
Docs execplans metadata
docs/execplans/3-7-3-translator-tooling-and-documentation.md, docs/execplans/3-8-1-add-accessible-output-mode.md
Minor reformatting and clarifications in execplan prose; no API changes.

Sequence Diagram

sequenceDiagram
    participant CLI as CLI Parser
    participant Main as main()
    participant OutputPrefs as output_prefs::resolve()
    participant Env as Environment
    participant Runner as runner::run()
    participant Reporter as AccessibleReporter
    participant Stderr as Stderr

    CLI->>Main: provide merged_cli (includes no_emoji)
    Main->>OutputPrefs: resolve(merged_cli.no_emoji)
    OutputPrefs->>OutputPrefs: evaluate explicit CLI/config
    alt explicit no_emoji = true
        OutputPrefs->>OutputPrefs: disable emoji
    else
        OutputPrefs->>Env: read NO_COLOR
        Env-->>OutputPrefs: value or none
        alt NO_COLOR set
            OutputPrefs->>OutputPrefs: disable emoji
        else
            OutputPrefs->>Env: read NETSUKE_NO_EMOJI
            Env-->>OutputPrefs: value or none
            alt NETSUKE_NO_EMOJI set
                OutputPrefs->>OutputPrefs: disable emoji
            else
                OutputPrefs->>OutputPrefs: enable emoji (default)
            end
        end
    end
    OutputPrefs-->>Main: return prefs
    Main->>Runner: run(cli, prefs)
    Runner->>Reporter: AccessibleReporter::new(prefs)
    Reporter->>Reporter: compute prefix via prefs.success_prefix()
    Reporter-->>Stderr: write prefixed message
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

✨ Glyphs choose silence or grin by demand,
Flags, env and config each take a hand,
Prefixes speak plain or dressed with a cheer,
OutputPrefs decides what the reader will hear,
Test the paths — accessibility well planned.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description comprehensively covers the changeset: accessibility preferences module, CLI integration, localization, documentation, and test coverage for emoji suppression and semantic prefixes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main
Title check ✅ Passed The title accurately and specifically summarises the main change: implementing accessibility preferences through an OutputPrefs module with emoji/no-emoji control.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch respect-accessibility-preferences-ubavwa

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

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Owner Author

leynos commented Feb 13, 2026

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix:

src/output_prefs.rs

Comment on lines +213 to +224

    fn error_prefix_contains_error_text_without_emoji() {
        let prefs = OutputPrefs { emoji: false };
        let rendered = prefs.error_prefix().to_string();
        assert!(
            rendered.contains("Error:"),
            "expected 'Error:' in '{rendered}'"
        );
        assert!(
            rendered.is_ascii(),
            "expected ASCII-only prefix, got '{rendered}'"
        );
    }

❌ New issue: Code Duplication
The module contains 3 functions with similar structure: tests.error_prefix_contains_error_text_without_emoji,tests.success_prefix_contains_success_text_without_emoji,tests.warning_prefix_contains_warning_text_without_emoji

@leynos
Copy link
Owner Author

leynos commented Feb 13, 2026

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix:

tests/bdd/steps/accessibility_preferences.rs

Comment on lines +101 to +108

fn render_error_prefix(world: &TestWorld) -> Result<()> {
    let prefs = world
        .output_prefs
        .get()
        .ok_or_else(|| anyhow::anyhow!("output prefs have not been resolved"))?;
    world.rendered_prefix.set(prefs.error_prefix().to_string());
    Ok(())
}

❌ New issue: Code Duplication
The module contains 2 functions with similar structure: render_error_prefix,render_success_prefix

@coderabbitai

This comment was marked as resolved.

@coderabbitai

This comment was marked as resolved.

@leynos leynos marked this pull request as ready for review February 14, 2026 14:22
sourcery-ai[bot]

This comment was marked as resolved.

Copy link

@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: 4dd8914b64

ℹ️ 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".

Copy link
Contributor

@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: 2

🤖 Fix all issues with AI agents
In `@docs/execplans/3-8-2-respect-accessibility-preferences.md`:
- Around line 99-101: Update the British-variant -ise spellings to -ize in the
document: change "localised Fluent messages" to "localized Fluent messages" and
any other occurrences of "-ise" (e.g., in the semantic-prefix description that
uses `$emoji` select and the surrounding lines referenced) to their "-ize"
forms; apply the same replacement to the other affected occurrences noted (lines
108-110 and 117-118) so all instances use the en-GB-oxendict "-ize" spelling
consistently.

In `@src/status.rs`:
- Around line 33-35: Update the doc comment that currently reads "localised
messages from the Fluent resource bundle" to use en-GB-oxendict -ize spelling by
replacing "localised" with "localized"; locate the doc comment containing
"localised messages from the Fluent resource bundle" in src/status.rs (the
module/section documenting completion messages) and change the word only so the
rest of the comment remains unchanged.

Copy link
Contributor

@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: 2

🤖 Fix all issues with AI agents
In `@docs/execplans/3-8-2-respect-accessibility-preferences.md`:
- Around line 13-18: Update the semantic prefix list in the docs entry titled
"3-8-2-respect-accessibility-preferences.md" by inserting the Oxford comma so
the phrase reads "Error, Warning, and Success" instead of "Error, Warning,
Success"; locate the sentence containing "semantic prefixes (Error, Warning,
Success)" and edit it to include the comma before "and" to comply with the style
guideline.

In `@docs/users-guide.md`:
- Around line 625-628: Reflow the paragraph that describes semantic text
prefixes so it is wrapped at 80 columns and insert the Oxford comma when listing
the three prefixes — render them as `Error:`, `Warning:`, and `Success:` — and
ensure the sentence about including a leading glyph when emoji are permitted is
kept intact and grammatically correct while fitting the 80-column wrap.

@leynos
Copy link
Owner Author

leynos commented Feb 14, 2026

@coderabbitai Have the following now been resolved?

Please address the comments from this code review:

## Overall Comments
- Consider avoiding duplicated preference resolution by passing a single `OutputPrefs` instance from `main` into `runner::run` (or returning it), so both status reporting and error handling share one resolved source rather than each calling `output_prefs::resolve` independently.
- In `main.rs` the non-`RunnerError` branch switches from `tracing::error!` to writing directly to stderr; if structured logging is still useful for diagnostics, consider keeping the `tracing::error!` call in addition to the prefixed stderr output.

## Individual Comments

### Comment 1
<location> `tests/bdd/steps/accessibility_preferences.rs:118-120` </location>
<code_context>
+    render_prefix_with(world, |prefs| prefs.error_prefix().to_string())
+}
+
+#[when("the success prefix is rendered")]
+fn render_success_prefix(world: &TestWorld) -> Result<()> {
+    render_prefix_with(world, |prefs| prefs.success_prefix().to_string())
+}
+
</code_context>

<issue_to_address>
**suggestion (testing):** Add BDD coverage for the warning prefix to mirror error/success prefix checks.

The BDD steps assert error and success prefixes but don’t exercise the warning prefix, even though `OutputPrefs` exposes `warning_prefix` and it’s user-visible. Please add a `#[when("the warning prefix is rendered")]` step mirroring the existing ones, plus `.feature` scenarios that check the localized "Warning:" text and emoji vs. no-emoji behavior so BDD coverage matches the unit tests and guards against regressions in warning output.

Suggested implementation:

```rust
#[when("the error prefix is rendered")]
fn render_error_prefix(world: &TestWorld) -> Result<()> {
    render_prefix_with(world, |prefs| prefs.error_prefix().to_string())
}

#[when("the warning prefix is rendered")]
fn render_warning_prefix(world: &TestWorld) -> Result<()> {
    render_prefix_with(world, |prefs| prefs.warning_prefix().to_string())
}

use crate::bdd::fixtures::TestWorld;

```

To fully implement the requested BDD coverage parity with error/success prefixes, you will also need to:

1. Update the relevant `.feature` file(s) under `tests/bdd/features/` (likely the one that currently covers accessibility/output preferences) to:
   - Add a scenario verifying the localized warning text (e.g. `Warning:`) is present when "the warning prefix is rendered".
   - Add a scenario verifying emoji vs. no-emoji behavior for the warning prefix, mirroring how error/success prefixes are tested (reusing the same Given steps that toggle emoji preferences / accessibility mode).
2. Wire the new step into those scenarios by using the new step phrase `When the warning prefix is rendered` so it binds to `render_warning_prefix`.
3. Ensure any existing step definitions or world state that compare the rendered prefix (e.g. `Then the rendered prefix is "⚠ Warning:"` / `Then the rendered prefix is "Warning:"`) are updated or extended to include the expected warning prefixes for both emoji-enabled and emoji-disabled configurations.
</issue_to_address>

### Comment 2
<location> `docs/users-guide.md:611` </location>
<code_context>
+Netsuke supports suppressing emoji glyphs in output for users who prefer
+ASCII-only output or use environments where emoji are not rendered correctly.
+
+Emoji is automatically suppressed when:
+
+- `NO_COLOR` is set (any value)
</code_context>

<issue_to_address>
**nitpick (typo):** Consider changing "Emoji is" to "Emoji are" for grammatical consistency with the rest of the docs.

The ExecPlan section already says “emoji are visual decoration,” so using “Emoji are automatically suppressed when:” here will keep the plural usage consistent.

```suggestion
Emoji are automatically suppressed when:
```
</issue_to_address>

### Comment 3
<location> `docs/execplans/3-8-2-respect-accessibility-preferences.md:70` </location>
<code_context>
+
+- Risk: `cli_overrides_from_matches` must be updated for `no_emoji`.
+  Severity: high. Likelihood: high.
+  Mitigation: add to `value_source` check array; covered by BDD scenario.
+
+## Progress
</code_context>

<issue_to_address>
**issue (review_instructions):** The acronym “BDD” is used here without being expanded on first use, which violates the acronym-definition requirement.

Please expand “BDD” the first time it appears, for example: “covered by a Behaviour-Driven Development (BDD) scenario.” Subsequent uses can then use just “BDD scenario.”

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.md`

**Instructions:**
Define uncommon acronyms on first use.

</details>
</issue_to_address>

### Comment 4
<location> `docs/execplans/3-8-2-respect-accessibility-preferences.md:99` </location>
<code_context>
+- `NO_COLOR` implies no-emoji (visual decoration suppressed with colour).
+- `no_emoji` is `Option<bool>` (tri-state: None/auto, Some(true)/off,
+  Some(false)/on).
+- Semantic prefixes use localised Fluent messages with `$emoji` select.
+- Emoji-allowed mode: `✖ Error:`, `⚠ Warning:`, `✔ Success:`.
+  No-emoji mode: `Error:`, `Warning:`, `Success:`.
</code_context>

<issue_to_address>
**issue (review_instructions):** “localised” uses -ise spelling where the guidelines require -ize forms for this project’s en-GB-oxendic style.

To match the specified en-GB-oxendic (-ize / -yse / -our) style, please change “localised” to “localized” here.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.md`

**Instructions:**
Use en-GB-oxendic (-ize / -yse / -our) spelling and grammar.

</details>
</issue_to_address>

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 14, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check main.rs for OutputPrefs passing and tracing::error! usage
echo "=== Checking main.rs ==="
cat src/main.rs

Length of output: 2557


🏁 Script executed:

#!/bin/bash
# Check tests/bdd/steps/accessibility_preferences.rs for warning prefix
echo "=== Checking accessibility_preferences.rs ==="
cat tests/bdd/steps/accessibility_preferences.rs | grep -A 5 "warning_prefix"

Length of output: 358


🏁 Script executed:

#!/bin/bash
# Check docs/users-guide.md for "Emoji is" vs "Emoji are"
echo "=== Checking users-guide.md ==="
rg -n "Emoji (is|are) automatically suppressed" docs/users-guide.md

Length of output: 76


🏁 Script executed:

#!/bin/bash
# Check docs/execplans for "BDD" acronym and "localised"
echo "=== Checking execplans document ==="
cat docs/execplans/3-8-2-respect-accessibility-preferences.md | grep -n -A 2 -B 2 "BDD\|localised\|localized"

Length of output: 1413


🏁 Script executed:

#!/bin/bash
# Check for warning prefix in feature files
echo "=== Checking for warning prefix scenarios ==="
rg -n "warning prefix" tests/features/

Length of output: 229


@leynos: Yes, all the review comments have been resolved! Here's the verification:

Overall Comments ✅

1. Single OutputPrefs instance passed to runner:

  • Resolved – Line 42 in src/main.rs shows let prefs = output_prefs::resolve(merged_cli.no_emoji); resolves preferences once, then line 43 passes it to runner::run(&merged_cli, prefs), and line 46 reuses the same prefs instance for error prefixing. No duplication exists.

2. Retain tracing::error! alongside stderr output:

  • Resolved – Lines 50-52 in src/main.rs show:
    Err(other_err) => {
        tracing::error!(error = %other_err, "runner failed");
        drop(writeln!(io::stderr(), "{prefix} {other_err}"));
    }
    The structured logging call is preserved in addition to the prefixed stderr output.

Individual Comments ✅

Comment 1 – BDD coverage for warning prefix:

  • Resolvedtests/bdd/steps/accessibility_preferences.rs includes the render_warning_prefix function, and tests/features/accessibility_preferences.feature contains scenarios at lines 45 and 51 that exercise "When the warning prefix is rendered".

Comment 2 – "Emoji are" (plural):

  • Resolved – Line 611 in docs/users-guide.md reads "Emoji are automatically suppressed when:" using the correct plural form.

Comment 3 – Expand "BDD" acronym:

  • Resolved – Lines 70-71 in docs/execplans/3-8-2-respect-accessibility-preferences.md read: "covered by Behaviour-Driven Development (BDD) scenario." The acronym is expanded on first use.

Comment 4 – "localized" (not "localised"):

  • Resolved – Line 100 in docs/execplans/3-8-2-respect-accessibility-preferences.md reads: "Semantic prefixes use localized Fluent messages" using the en-GB-oxendict -ize spelling.

All issues have been addressed! 🎉

@leynos leynos changed the title Implement accessibility preferences: emoji suppression and semantic prefixes Implement accessibility preferences: OutputPrefs and emoji prefixes Feb 16, 2026
Copy link
Contributor

@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

🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.


In `@tests/features/accessibility_preferences.feature`:
- Around line 52-56: Add a new scenario in accessibility_preferences.feature
mirroring the existing "Error prefix includes emoji glyph in standard mode" and
"Warning prefix includes emoji glyph in standard mode" scenarios: create
"Scenario: Success prefix includes emoji glyph in standard mode" that ensures
emoji is enabled (not suppressed), renders the success prefix, and asserts the
prefix contains the success emoji (e.g., the same glyph used for success in the
suite) and the text "Success:"; follow the same Given/When/Then step pattern
used by the other two scenarios so it fits the existing step definitions and
keeps test coverage symmetric.

Copy link
Contributor

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

Review comment resolved: all -ise spellings corrected to -ize.

Copy link
Contributor

@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: 2

🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.


In `@docs/execplans/3-7-3-translator-tooling-and-documentation.md`:
- Around line 94-98: Paragraph lines exceed the 80-column rule; reflow the
sentence describing the discovery so each line is wrapped at or under 80
characters while preserving meaning: mention LocalizedMessage::with_arg converts
args to strings via .to_string(), that Fluent CLDR plural categories (e.g.,
[one], [few]) require numeric FluentValue types and thus fall back to the
[other] variant, and note that this limitation is documented in the translator
guide. Ensure references to LocalizedMessage::with_arg, FluentValue, and the
plural categories remain unchanged.

In `@tests/features/accessibility_preferences.feature`:
- Around line 47-72: For the three emoji-enabled scenarios ("Error prefix
includes emoji glyph in standard mode", "Success prefix includes emoji glyph in
standard mode", "Warning prefix includes emoji glyph in standard mode") add an
explicit assertion that the rendered prefix contains non-ASCII (emoji)
characters; locate those scenarios by the step "Given emoji is allowed" and
append a step similar to "And the prefix contains non-ASCII characters" so the
tests validate presence of an emoji glyph in addition to the existing "Then the
prefix contains ..." checks.

Copy link
Contributor

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

✓ Resolved: The 'Success prefix includes emoji glyph in standard mode' scenario has been added at lines 58-61.

@leynos leynos changed the title Implement accessibility preferences: OutputPrefs and emoji prefixes Plan implementation respecting accessibility preferences Feb 16, 2026
leynos and others added 3 commits February 16, 2026 23:54
- Introduce OutputPrefs struct to encapsulate emoji allowance and semantic prefix formatting.
- Honor NO_COLOR and NETSUKE_NO_EMOJI environment variables and --no-emoji CLI flag.
- Update CLI to include no_emoji option; integrate output preferences into status reporting.
- Add localised semantic prefixes with and without emoji for Error, Warning, Success.
- Provide comprehensive unit and BDD tests covering preference resolution and output.
- Update documentation and roadmap to reflect new accessibility preference support.

This completes accessibility preference support for Netsuke output, ensuring emoji
can be suppressed and semantic prefixes remain consistent across modes.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
…stest

Replaced multiple similar unit tests for error, success, and warning prefixes with a single parameterized test using rstest. This reduces code duplication and improves test maintainability by covering both emoji and non-emoji cases in one test function.

Additionally, in accessibility preference BDD steps, introduced a helper function to abstract prefix rendering logic, simplifying step definitions for rendering error and success prefixes.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
…nt output

Refactor runner::run to accept output preferences, improving output handling consistency. Update main, tests, and relevant modules to pass resolved output preferences explicitly. Add BDD scenarios for warning prefix rendering in no-emoji mode. Adjust docs for wording fixes and terminology consistency.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
leynos and others added 5 commits February 16, 2026 23:54
The output preference resolution logic was updated so that an explicit
no_emoji value of Some(false) no longer forces emoji on unconditionally.
Instead, Some(false) defers to environment variables like NO_COLOR and
NETSUKE_NO_EMOJI, both of which use presence-based semantics to suppress
emoji output.

Only Some(true) forces emoji suppression unconditionally.

This change ensures that setting --no-emoji false does not override environment
variables that suppress emoji, addressing user expectations and aligning
cli behavior with documented semantics.

Updates include documentation, unit tests, BDD scenarios, and examples.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
This change updates the output preference resolution logic to treat
NETSUKE_NO_EMOJI environment variable values of "false" and "0" as
indications to disable emoji output, ensuring consistent and expected
behavior. Previously, these string values did not disable emoji as
intended. The commit also clarifies the override semantics in the
code comments and adds feature tests to verify this behavior.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
…d dumb terminals

- Implemented new accessible output mode replacing animated progress indicators with static, labelled status lines.
- Accessible mode auto-detects environment variables (NO_COLOR and TERM=dumb) and respects explicit configuration flags.
- Refactored output mode detection into an enum for extensibility.
- Added comprehensive unit and BDD tests covering detection logic and output formatting.
- Updated CLI parsing and config merging to support accessible mode.
- Documented accessible output usage in user guide and execution plans.
- Ensured compatibility with emoji and accessibility preferences, including semantic text prefixes.

This change enhances usability for users relying on screen readers or less capable terminals by providing clear, static progress feedback.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
… characters in prefix

Added a new step definition to verify the presence of non-ASCII (emoji) characters in error, success, and warning prefixes. Updated the accessibility preferences feature scenarios to include this verification step, ensuring prefixes correctly render emojis when allowed.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
The type is already imported; remove the redundant module path
qualifier introduced during rebase conflict resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@devboxerhub devboxerhub bot force-pushed the respect-accessibility-preferences-ubavwa branch from f655afd to c9497a8 Compare February 17, 2026 00:01
@leynos leynos changed the title Plan implementation respecting accessibility preferences Implement accessibility preferences via OutputPrefs (emoji/no-emoji) Feb 17, 2026
@leynos leynos merged commit 3b9bd39 into main Feb 17, 2026
16 checks passed
@leynos leynos deleted the respect-accessibility-preferences-ubavwa branch February 17, 2026 00:33
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

Comments