Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 90 additions & 82 deletions docs/execplans/3-12-1-define-design-tokens.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This ExecPlan (execution plan) is a living document. The sections
`Decision Log`, and `Outcomes & Retrospective` must be kept up to date as work
proceeds.

Status: DRAFT
Status: COMPLETE

## Purpose / big picture

Expand Down Expand Up @@ -129,13 +129,19 @@ Observable success means:
resolved tokens. Added `resolve_from_theme()` and
`resolve_from_theme_with()` functions to `output_prefs` module that
delegate to theme system. Updated `main.rs` to resolve `OutputMode` and
pass it to theme resolution. Theme infrastructure is complete and
functional. Full reporter integration (using spacing tokens in status.rs
and status_timing.rs) deferred to follow-up work.
- [ ] Stage D: Add behavioural coverage for theme selection and consistency.
Deferred pending full reporter integration.
- [ ] Stage E: Update documentation, mark the roadmap item done, and run the
full quality gates.
pass it to theme resolution. Completed reporter integration by routing
semantic prefixes through resolved theme symbols and replacing hard-coded
task/timing indentation with spacing token accessors in `status.rs` and
`status_timing.rs`.
- [x] (2026-03-21 00:00Z) Stage D: Add behavioural coverage for theme
selection and consistency. Activated the dormant `tests/cli_tests/`
harness, added theme parsing and merge-precedence tests, and added BDD
scenarios covering explicit ASCII and Unicode themes plus invalid
`--theme` input.
- [x] (2026-03-21 00:00Z) Stage E: Update documentation, mark the roadmap item
done, and run the full quality gates. Updated the user guide and design
record, corrected the execplan command-list Markdown structure, and
completed the roadmap entry after the full gates passed.

## Surprises & discoveries

Expand All @@ -146,26 +152,24 @@ Observable success means:
use OrthoConfig immediately, but the plan must avoid baking reporter code
directly into the current `Cli` type.

- Observation: there is no current theme abstraction; `OutputPrefs` only tracks
whether emoji are allowed, while `TASK_INDENT` and several prefixes are still
hard-coded in the reporters. Evidence: `src/output_prefs.rs`,
`src/status.rs`, `src/status_timing.rs`, and `src/main.rs`. Impact: 3.12.1
must create the abstraction before 3.12.2 can snapshot it.
- Observation: theme-token rollout was simplest when `OutputPrefs` became the
compatibility wrapper around the resolved theme rather than introducing a new
reporter-facing type. Evidence: `src/output_prefs.rs`, `src/status.rs`, and
`src/status_timing.rs`. Impact: existing reporter constructors and most call
sites stayed stable while tokens became authoritative for prefixes and
spacing.

- Observation: strict clippy/lint behaviour has already required `build.rs`
anchors for shared CLI helpers. Evidence: `build.rs` contains `const _`
symbol anchors for `cli::diag_json_hint_from_args`,
`cli_l10n::parse_bool_hint`, and related helpers. Impact: new theme parsing
helpers must follow the same pattern.

- (2026-03-17) Observation: Implementing full reporter token integration
(replacing TASK_INDENT literals with spacing tokens in status.rs,
status_timing.rs) requires touching multiple reporter files and extensive
testing. Evidence: Current implementation successfully adds CLI theme
preference, theme resolution pipeline, and OutputPrefs façade, but full
reporter refactoring needs dedicated focus. Impact: Stages C and D are
partially complete with infrastructure in place. Follow-up work needed to
complete reporter integration and add comprehensive BDD coverage.
- Observation: the repository already contained a dormant `tests/cli_tests/`
module tree that was not an active Cargo integration target. Evidence:
`tests/cli_tests/mod.rs` existed without a matching `tests/cli_tests.rs`
harness. Impact: the roadmap item needed a small harness file plus stale-test
fixes before the new theme merge tests could participate in `cargo test`.

## Decision log

Expand All @@ -187,9 +191,15 @@ Observable success means:
language. Preset token sets are enough to unblock 3.12.2 snapshots and 3.12.3
terminal validation. Date/Author: 2026-03-13 / Codex.

- Decision: render semantic prefixes from theme symbols plus localized text
labels instead of keeping symbol selection inside Fluent select expressions.
Rationale: the roadmap item requires design tokens to become the single
source of truth for glyph choice, while translation should still own the text
labels (`Error:`, `Advertencia:`, and so on). Date/Author: 2026-03-21 / Codex.

## Outcomes & retrospective

Status: Partially complete (2026-03-17)
Status: Complete (2026-03-21)

Implementation achieved:

Expand All @@ -198,24 +208,22 @@ Implementation achieved:
resolution pipeline
- CLI integration: `--theme` flag with OrthoConfig merging, localized
validation, and precedence handling
- OutputPrefs compatibility façade delegates to theme system
- 12 passing unit tests for theme resolution precedence
- OutputPrefs compatibility façade now carries resolved theme tokens and
renders semantic prefixes from token glyphs plus localized labels
- Reporter integration: `src/status.rs` and `src/status_timing.rs` now use
theme-backed spacing accessors instead of hard-coded indentation literals
- Active unit/integration coverage for theme parsing, precedence, and rendered
output, including a reactivated `tests/cli_tests.rs` harness
- BDD coverage for explicit ASCII and Unicode theme rendering, verbose ASCII
timing output, and invalid `--theme` validation
- Backward compatibility preserved: existing `no_emoji` preference continues to
work

Remaining work (deferred to follow-up):

- Reporter integration: Update `src/status.rs` and `src/status_timing.rs` to
use spacing tokens instead of hard-coded `TASK_INDENT` literals
- BDD coverage: Add `rstest-bdd` scenarios for end-to-end theme selection and
ASCII/Unicode consistency
- Documentation: Update `docs/users-guide.md` with theme selection guidance
- Mark roadmap 3.12.1 done after completion

The implementation successfully adds the user-visible theme selection story
through OrthoConfig and centralizes token definitions. The infrastructure is
complete and functional. Full reporter integration requires focused work on
status rendering modules and comprehensive BDD test coverage.
The implementation now satisfies the roadmap item end to end: theme selection
flows through OrthoConfig, semantic prefixes and spacing come from one resolved
token set, ASCII and Unicode output stay structurally aligned, and the docs and
tests reflect the resulting behaviour. Roadmap item 3.12.1 is complete and its
full quality gates have passed.

## Context and orientation

Expand All @@ -226,13 +234,13 @@ The current CLI output flow is spread across several modules:
- `src/cli_l10n.rs` maps clap arguments and subcommands to Fluent help keys.
- `src/output_mode.rs` resolves whether output is `Accessible` or `Standard`
from `accessible`, `NO_COLOR`, and `TERM`.
- `src/output_prefs.rs` resolves whether emoji are allowed from `no_emoji`,
`NO_COLOR`, and `NETSUKE_NO_EMOJI`, then renders semantic prefixes such as
`Error:`, `Info:`, `Success:`, and `Timing:`.
- `src/output_prefs.rs` resolves the theme-backed output preferences and now
exposes semantic prefixes plus spacing accessors through a compatibility
façade.
- `src/status.rs` renders pipeline stages, task progress, and completion
messages. It still embeds spacing decisions locally via `TASK_INDENT`.
- `src/status_timing.rs` renders verbose timing summaries and currently applies
its own prefix and indentation rules.
messages using `OutputPrefs` for semantic prefixes and task indentation.
- `src/status_timing.rs` renders verbose timing summaries using the same
`OutputPrefs` façade for timing prefixes and indentation.
- `src/main.rs` renders top-level errors using `OutputPrefs`.
- `src/runner/mod.rs` resolves `OutputMode` and `OutputPrefs`, then constructs
the reporter stack.
Expand Down Expand Up @@ -474,57 +482,57 @@ cd /home/user/project

1. Establish the current baseline and locate the relevant code.

```sh
rg -n "theme|OutputPrefs|no_emoji|accessible|progress" src tests docs
```
```sh
rg -n "theme|OutputPrefs|no_emoji|accessible|progress" src tests docs
```

1. Implement the theme module and CLI/config wiring.
2. Implement the theme module and CLI/config wiring.

```sh
cargo test --workspace theme -- --nocapture
```
```sh
cargo test --workspace theme -- --nocapture
```

Expected shape after Stage B:
Expected shape after Stage B:

```plaintext
running N tests
test ...theme... ok
test ...cli... ok
```
```plaintext
running N tests
test ...theme... ok
test ...cli... ok
```

1. Refresh BDD-generated scenario code if feature text changes.
3. Refresh BDD-generated scenario code if feature text changes.

```sh
touch tests/bdd_tests.rs
```
```sh
touch tests/bdd_tests.rs
```

1. Run the full validation gates with logged output.
4. Run the full validation gates with logged output.

```sh
set -o pipefail && make check-fmt 2>&1 | tee /tmp/netsuke-3-12-1-check-fmt.log
set -o pipefail && make lint 2>&1 | tee /tmp/netsuke-3-12-1-lint.log
set -o pipefail && make test 2>&1 | tee /tmp/netsuke-3-12-1-test.log
set -o pipefail && make fmt 2>&1 | tee /tmp/netsuke-3-12-1-fmt.log
set -o pipefail && PATH="/root/.bun/bin:$PATH" make markdownlint 2>&1 | tee /tmp/netsuke-3-12-1-markdownlint.log
set -o pipefail && make nixie 2>&1 | tee /tmp/netsuke-3-12-1-nixie.log
```
```sh
set -o pipefail && make check-fmt 2>&1 | tee /tmp/netsuke-3-12-1-check-fmt.log
set -o pipefail && make lint 2>&1 | tee /tmp/netsuke-3-12-1-lint.log
set -o pipefail && make test 2>&1 | tee /tmp/netsuke-3-12-1-test.log
set -o pipefail && make fmt 2>&1 | tee /tmp/netsuke-3-12-1-fmt.log
set -o pipefail && PATH="/root/.bun/bin:$PATH" make markdownlint 2>&1 | tee /tmp/netsuke-3-12-1-markdownlint.log
set -o pipefail && make nixie 2>&1 | tee /tmp/netsuke-3-12-1-nixie.log
```

Expected final signal:
Expected final signal:

```plaintext
make check-fmt # exits 0
make lint # exits 0
make test # exits 0
make markdownlint # exits 0
make nixie # exits 0
```
```plaintext
make check-fmt # exits 0
make lint # exits 0
make test # exits 0
make markdownlint # exits 0
make nixie # exits 0
```

1. Inspect scope before finalizing.
5. Inspect scope before finalizing.

```sh
git status --short
git diff --stat
```
```sh
git status --short
git diff --stat
```

Only the intended source, test, and documentation files for 3.12.1 should
remain modified.
Expand Down
9 changes: 9 additions & 0 deletions docs/netsuke-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -2083,6 +2083,15 @@ Timing summaries are completion diagnostics. They are suppressed when verbose
mode is off and also suppressed on failed runs so failures do not imply a
successful pipeline completion.

Theme resolution for CLI output is centralized in `src/theme.rs`. Netsuke
resolves one theme through OrthoConfig layers (`--theme`, `NETSUKE_THEME`,
config file, then mode defaults) and hands the resulting symbol and spacing
tokens to reporters through the `OutputPrefs` compatibility façade. This keeps
reporter code focused on status semantics rather than glyph choice, preserves
`no_emoji` as a legacy ASCII-forcing alias when no explicit theme is supplied,
and gives later roadmap items a stable snapshot surface for validating ASCII
and Unicode renderings without duplicating formatting rules.

For screen readers: The following flowchart shows how the build script audits
localization keys against English and Spanish Fluent bundles.

Expand Down
7 changes: 4 additions & 3 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,10 @@ library, and CLI ergonomics.

### 3.12. Visual design validation

- [ ] 3.12.1. Define design tokens for colours, symbols, and spacing.
- [ ] Wire tokens through CLI theme system.
- [ ] Ensure ASCII and Unicode modes remain consistent.
- [x] 3.12.1. Define design tokens for colours, symbols, and spacing.
- [x] Route reporter prefixes and spacing through resolved theme tokens.
- [x] Add end-to-end theme coverage and documentation for ASCII/Unicode
consistency.
- [ ] 3.12.2. Snapshot progress and status output for themes.
- [ ] Cover unicode and ascii themes.
- [ ] Guard alignment and wrapping against regressions.
Expand Down
41 changes: 28 additions & 13 deletions docs/users-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -763,31 +763,46 @@ When progress is disabled, Netsuke suppresses stage and task progress output in
both standard and accessible modes. If verbose mode is enabled at the same
time, only the completion timing summary remains visible on successful runs.

### Emoji and accessibility preferences
### Theme and accessibility preferences

Netsuke supports suppressing emoji glyphs in output for users who prefer
ASCII-only output or use environments where emoji are not rendered correctly.
Netsuke resolves a CLI theme through the same layered configuration model as
its other user-facing preferences:

Emoji are automatically suppressed when:
- CLI flag: `--theme auto|unicode|ascii`
- Environment variable: `NETSUKE_THEME=auto|unicode|ascii`
- Configuration file: `theme = "auto" | "unicode" | "ascii"`

- `NO_COLOR` is set (any value)
- `NETSUKE_NO_EMOJI` is set (any value)
Theme precedence is:

1. Explicit `theme`
2. Legacy `no_emoji = true`
3. `NETSUKE_NO_EMOJI` present
4. `NO_COLOR` present
5. Output mode default (`unicode` for standard output, `ascii` for
accessible output)

Emoji suppression can be forced on explicitly:
`auto` keeps the mode-sensitive default. `unicode` forces Unicode symbols even
in accessible mode, while `ascii` forces ASCII-safe symbols everywhere.

Netsuke still supports the legacy no-emoji compatibility flag for users who
already rely on it:

- CLI flag: `--no-emoji true`
- Environment variable: `NETSUKE_NO_EMOJI` (any value, including empty)
- Configuration file: `no_emoji = true`

Only `--no-emoji true` acts as a hard override; `--no-emoji false` and omitting
the flag both defer to environment variable detection. `NETSUKE_NO_EMOJI` uses
presence-based semantics — setting it to any value (including `"false"` or
`"0"`) suppresses emoji.
presence-based semantics, so setting it to any value (including `"false"` or
`"0"`) still selects the ASCII theme unless an explicit `theme` overrides it.

In all output modes, Netsuke uses semantic text prefixes, so meaning is never
conveyed solely by colour. The active theme swaps only the glyph set:

In all output modes, Netsuke uses semantic text prefixes (`Error:`, `Warning:`,
and `Success:`) so that meaning is never conveyed solely by colour or symbol.
When emoji is permitted, these prefixes include a leading glyph for quick
visual scanning.
- Unicode theme: `✖ Error:`, `⚠ Warning:`, `✔ Success:`, `ℹ Info:`,
`⏱ Timing:`
- ASCII theme: `X Error:`, `! Warning:`, `+ Success:`, `i Info:`,
`T Timing:`

### Exit Codes

Expand Down
26 changes: 6 additions & 20 deletions locales/en-US/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -351,26 +351,12 @@ status.tool.manifest = Manifest
cli.flag.no_emoji.help = Suppress emoji glyphs in output.

# Semantic prefixes for accessible output.
semantic.prefix.error = { $emoji ->
[yes] ✖ Error:
*[no] Error:
}
semantic.prefix.warning = { $emoji ->
[yes] ⚠ Warning:
*[no] Warning:
}
semantic.prefix.success = { $emoji ->
[yes] ✔ Success:
*[no] Success:
}
semantic.prefix.info = { $emoji ->
[yes] ℹ Info:
*[no] Info:
}
semantic.prefix.timing = { $emoji ->
[yes] ⏱ Timing:
*[no] Timing:
}
semantic.prefix.error = Error:
semantic.prefix.warning = Warning:
semantic.prefix.success = Success:
semantic.prefix.info = Info:
semantic.prefix.timing = Timing:
semantic.prefix.rendered = {"{"}symbol{"}"} {"{"}label{"}"}

# Plural form examples for translators.
# These messages demonstrate Fluent's select expression syntax using CLDR
Expand Down
Loading
Loading