Skip to content

Commit de2ae26

Browse files
committed
docs: add output handling guide for contributors
- Create comprehensive output-handling.md guide - Document ProgressReporter as primary abstraction for controllers - Explain UserOutput for simple, non-step messages - Explain sink-based architecture and dual-channel strategy - Provide examples for ProgressReporter and direct UserOutput usage - Add testing guidance with captured buffers - Update docs/README.md to include new guide in key sections - Update AGENTS.md with new essential rule #8 (marked CRITICAL) - Update docs/contributing/README.md quick reference table This ensures contributors use the correct abstraction level: - ProgressReporter for multi-step controller operations - UserOutput directly for simple messages All output remains testable and theme-aware.
1 parent 18126be commit de2ae26

File tree

4 files changed

+498
-9
lines changed

4 files changed

+498
-9
lines changed

AGENTS.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,24 +98,26 @@ These principles should guide all development decisions, code reviews, and featu
9898

9999
7. **When handling errors in code**: Read [`docs/contributing/error-handling.md`](docs/contributing/error-handling.md) for error handling principles. Prefer explicit enum errors over anyhow for better pattern matching and user experience. Make errors clear, include sufficient context for traceability, and ensure they are actionable with specific fix instructions.
100100

101-
8. **Understanding expected errors**: Read [`docs/contributing/known-issues.md`](docs/contributing/known-issues.md) for known issues and expected behaviors. Some errors that appear red in E2E test output (like SSH host key warnings) are normal and expected - not actual failures.
101+
8. **When producing any output to users** (CRITICAL for architecture): Read [`docs/contributing/output-handling.md`](docs/contributing/output-handling.md) for output handling conventions. **NEVER use `println!`, `eprintln!`, `print!`, `eprint!`, or direct access to `std::io::stdout()`/`std::io::stderr()`**. Always use `UserOutput` methods through the execution context. This ensures testability, consistent formatting, proper channel routing (stdout vs stderr), verbosity control, and theme support. Example: `ctx.user_output().lock().borrow_mut().progress("Processing...")` instead of `println!("Processing...")`.
102102

103-
9. **Before making engineering decisions**: Document significant architectural or design decisions as Architectural Decision Records (ADRs) in `docs/decisions/`. Read [`docs/decisions/README.md`](docs/decisions/README.md) for the ADR template and guidelines. This ensures decisions are properly documented with context, rationale, and consequences for future reference.
103+
9. **Understanding expected errors**: Read [`docs/contributing/known-issues.md`](docs/contributing/known-issues.md) for known issues and expected behaviors. Some errors that appear red in E2E test output (like SSH host key warnings) are normal and expected - not actual failures.
104104

105-
10. **When organizing code within modules**: Follow the module organization conventions in [`docs/contributing/module-organization.md`](docs/contributing/module-organization.md). Use top-down organization with public items first, high-level abstractions before low-level details, and important responsibilities before secondary concerns like error types.
105+
10. **Before making engineering decisions**: Document significant architectural or design decisions as Architectural Decision Records (ADRs) in `docs/decisions/`. Read [`docs/decisions/README.md`](docs/decisions/README.md) for the ADR template and guidelines. This ensures decisions are properly documented with context, rationale, and consequences for future reference.
106106

107-
11. **When writing Rust imports** (CRITICAL for code style): Follow the import conventions in [`docs/contributing/module-organization.md`](docs/contributing/module-organization.md). Two essential rules:
107+
11. **When organizing code within modules**: Follow the module organization conventions in [`docs/contributing/module-organization.md`](docs/contributing/module-organization.md). Use top-down organization with public items first, high-level abstractions before low-level details, and important responsibilities before secondary concerns like error types.
108+
109+
12. **When writing Rust imports** (CRITICAL for code style): Follow the import conventions in [`docs/contributing/module-organization.md`](docs/contributing/module-organization.md). Two essential rules:
108110

109111
- **Imports Always First**: Keep all imports at the top of the file, organized in groups (std → external crates → internal crate).
110112
- **Prefer Imports Over Full Paths**: Always import types and use short names (e.g., `Arc<UserOutput>`) rather than fully-qualified paths. Never use long paths like `std::sync::Arc<crate::presentation::views::UserOutput>` in regular code - only use full paths when disambiguating naming conflicts.
111113

112-
12. **When writing Markdown documentation**: Be aware of GitHub Flavored Markdown's automatic linking behavior. Read [`docs/contributing/github-markdown-pitfalls.md`](docs/contributing/github-markdown-pitfalls.md) for critical patterns to avoid. **NEVER use hash-number patterns for enumeration or step numbering** - this creates unintended links to GitHub issues/PRs. Use ordered lists or alternative formats instead.
114+
13. **When writing Markdown documentation**: Be aware of GitHub Flavored Markdown's automatic linking behavior. Read [`docs/contributing/github-markdown-pitfalls.md`](docs/contributing/github-markdown-pitfalls.md) for critical patterns to avoid. **NEVER use hash-number patterns for enumeration or step numbering** - this creates unintended links to GitHub issues/PRs. Use ordered lists or alternative formats instead.
113115

114-
13. **When creating new environment variables**: Read [`docs/contributing/environment-variables-naming.md`](docs/contributing/environment-variables-naming.md) for comprehensive guidance on naming conventions (condition-based vs action-based), decision frameworks, and best practices. Also review [`docs/decisions/environment-variable-prefix.md`](docs/decisions/environment-variable-prefix.md) to ensure all project environment variables use the `TORRUST_TD_` prefix for proper namespacing and avoiding conflicts with system or user variables.
116+
14. **When creating new environment variables**: Read [`docs/contributing/environment-variables-naming.md`](docs/contributing/environment-variables-naming.md) for comprehensive guidance on naming conventions (condition-based vs action-based), decision frameworks, and best practices. Also review [`docs/decisions/environment-variable-prefix.md`](docs/decisions/environment-variable-prefix.md) to ensure all project environment variables use the `TORRUST_TD_` prefix for proper namespacing and avoiding conflicts with system or user variables.
115117

116-
14. **When adding new templates**: Read [`docs/technical/template-system-architecture.md`](docs/technical/template-system-architecture.md) to understand the Project Generator pattern. The `templates/` directory contains source templates. Dynamic templates (`.tera`) are automatically processed, but static files must be explicitly registered in their respective `ProjectGenerator` to be copied to the build directory.
118+
15. **When adding new templates**: Read [`docs/technical/template-system-architecture.md`](docs/technical/template-system-architecture.md) to understand the Project Generator pattern. The `templates/` directory contains source templates. Dynamic templates (`.tera`) are automatically processed, but static files must be explicitly registered in their respective `ProjectGenerator` to be copied to the build directory.
117119

118-
15. **When writing unit tests** (CRITICAL for test quality): Read [`docs/contributing/testing/unit-testing.md`](docs/contributing/testing/unit-testing.md) and follow the behavior-driven naming convention. **NEVER use the `test_` prefix** for test function names. Always use the `it_should_{expected_behavior}_when_{condition}` or `it_should_{expected_behavior}_given_{state}` pattern. This ensures tests clearly document the behavior being validated and the conditions under which it occurs. Example: `it_should_return_error_when_username_is_invalid()` instead of `test_invalid_username()`. Test names should follow the three-part structure (What-When-Then) and be descriptive enough that the test's purpose is clear without reading the code.
120+
16. **When writing unit tests** (CRITICAL for test quality): Read [`docs/contributing/testing/unit-testing.md`](docs/contributing/testing/unit-testing.md) and follow the behavior-driven naming convention. **NEVER use the `test_` prefix** for test function names. Always use the `it_should_{expected_behavior}_when_{condition}` or `it_should_{expected_behavior}_given_{state}` pattern. This ensures tests clearly document the behavior being validated and the conditions under which it occurs. Example: `it_should_return_error_when_username_is_invalid()` instead of `test_invalid_username()`. Test names should follow the three-part structure (What-When-Then) and be descriptive enough that the test's purpose is clear without reading the code.
119121

120122
## 🧪 Build & Test
121123

@@ -192,4 +194,5 @@ The project has comprehensive documentation organized in the [`docs/`](docs/) di
192194
| Fix a CI issue | [`docs/github-actions-issues/README.md`](docs/github-actions-issues/README.md) |
193195
| Work with templates | [`docs/contributing/templates.md`](docs/contributing/templates.md) |
194196
| Handle errors properly | [`docs/contributing/error-handling.md`](docs/contributing/error-handling.md) |
197+
| Handle output properly | [`docs/contributing/output-handling.md`](docs/contributing/output-handling.md) |
195198
| Organize Rust modules | [`docs/contributing/module-organization.md`](docs/contributing/module-organization.md) |

docs/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Welcome to the Torrust Tracker Deployer documentation! This index helps you quic
1313
| Follow development principles | [`development-principles.md`](development-principles.md) - Observability, Testability, User Friendliness, Actionability |
1414
| Commit code | [`contributing/commit-process.md`](contributing/commit-process.md) - Pre-commit checks, conventional commits |
1515
| Handle errors properly | [`contributing/error-handling.md`](contributing/error-handling.md) - Explicit enums, actionable messages |
16+
| Handle output properly | [`contributing/output-handling.md`](contributing/output-handling.md) - **CRITICAL** UserOutput, never `println!` |
1617
| Organize Rust code | [`contributing/module-organization.md`](contributing/module-organization.md) - **CRITICAL** import conventions |
1718
| Work with templates | [`contributing/templates.md`](contributing/templates.md) - **CRITICAL** Tera syntax, registration |
1819
| Write unit tests | [`contributing/testing/unit-testing.md`](contributing/testing/unit-testing.md) - Naming conventions (no `test_` prefix!) |
@@ -84,6 +85,7 @@ docs/
8485
| Fix a CI issue | [`github-actions-issues/README.md`](github-actions-issues/README.md) |
8586
| Work with templates | [`contributing/templates.md`](contributing/templates.md) |
8687
| Handle errors properly | [`contributing/error-handling.md`](contributing/error-handling.md) |
88+
| Handle output properly | [`contributing/output-handling.md`](contributing/output-handling.md) |
8789
| Organize Rust modules | [`contributing/module-organization.md`](contributing/module-organization.md) |
8890

8991
---
@@ -113,16 +115,17 @@ docs/
113115
<summary><strong>🤝 Contributing Guidelines (18 documents) (Click to Expand)</strong></summary>
114116

115117
Essential guides: DDD layer placement, module organization, error handling, templates, commit process, testing conventions
116-
117118
**Key Documents:**
118119

119120
- [`contributing/README.md`](contributing/README.md) - Quick reference guide to all contribution documentation
120121
- [`contributing/ddd-layer-placement.md`](contributing/ddd-layer-placement.md) - **CRITICAL**: Rules for placing code in correct DDD layers
121122
- [`contributing/module-organization.md`](contributing/module-organization.md) - **CRITICAL**: Module organization and Rust import patterns
122123
- [`contributing/templates.md`](contributing/templates.md) - **CRITICAL**: Tera template syntax and registration
124+
- [`contributing/output-handling.md`](contributing/output-handling.md) - **CRITICAL**: Output handling with UserOutput (never `println!`)
123125
- [`contributing/error-handling.md`](contributing/error-handling.md) - Error handling principles
124126
- [`contributing/commit-process.md`](contributing/commit-process.md) - Commit process and pre-commit checks
125127
- [`contributing/testing/unit-testing.md`](contributing/testing/unit-testing.md) - Unit testing conventions
128+
- [`contributing/testing/unit-testing.md`](contributing/testing/unit-testing.md) - Unit testing conventions
126129

127130
</details>
128131

docs/contributing/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This guide will help you understand our development practices and contribution w
1414
| Code quality and linting | [linting.md](./linting.md) |
1515
| Module organization and imports | [module-organization.md](./module-organization.md) |
1616
| Error handling principles | [error-handling.md](./error-handling.md) |
17+
| Output handling with UserOutput | [output-handling.md](./output-handling.md) |
1718
| Working with Tera templates | [templates.md](./templates.md) |
1819
| Environment variables naming | [environment-variables-naming.md](./environment-variables-naming.md) |
1920
| Debugging techniques | [debugging.md](./debugging.md) |

0 commit comments

Comments
 (0)