docs(product-guidelines): add Data-Oriented Error Handling section
This commit is contained in:
@@ -47,6 +47,51 @@
|
||||
- **Functions/Methods:** `[C: Caller1, Caller2]` (Primary callers).
|
||||
- **State Variables:** `[M: File:Line, Method]` (Mutation points) and `[U: File]` (Major use paths).
|
||||
|
||||
## Data-Oriented Error Handling
|
||||
|
||||
The codebase follows the "errors are just cases" framework from Ryan Fleury's
|
||||
[The Easiest Way To Handle Errors](https://www.dgtlgrove.com/p/the-easiest-way-to-handle-errors).
|
||||
The canonical reference (with code examples) is in
|
||||
[`conductor/code_styleguides/error_handling.md`](code_styleguides/error_handling.md).
|
||||
Key principles:
|
||||
|
||||
- **Result dataclasses** instead of `Optional[T]` or exception-based control flow.
|
||||
- **Nil-sentinel dataclasses** instead of `None`.
|
||||
- **Zero-initialized fields** via `@dataclass` defaults.
|
||||
- **Fail early**: validation at the entry point, not deep in the call stack.
|
||||
- **AND over OR**: return a struct with data + side-channel errors, not a sum type.
|
||||
- **Exceptions reserved for the SDK boundary**: SDK errors are caught and converted
|
||||
to `ErrorInfo` dataclasses; the rest of the application works with data, not control flow.
|
||||
|
||||
This convention is established incrementally. The 2026-06-11
|
||||
`data_oriented_error_handling_20260606` track applies it to
|
||||
`src/mcp_client.py`, `src/ai_client.py`, and `src/rag_engine.py`. Future
|
||||
tracks will apply it to the remaining `src/` files
|
||||
(`src/app_controller.py`, `src/models.py`, `src/project_manager.py`, etc. —
|
||||
see `conductor/tracks/data_oriented_error_handling_20260606/spec.md` §12.2
|
||||
for the prioritized list).
|
||||
|
||||
### `Optional[T]` ban (return types only)
|
||||
|
||||
In the 3 refactored files (`src/mcp_client.py`, `src/ai_client.py`,
|
||||
`src/rag_engine.py`), `Optional[T]` return types are forbidden. Use
|
||||
`Result[T]` (with a `NIL_T` singleton if needed) instead. Argument types
|
||||
that may be `None` (e.g., `rag_engine: Optional[Any] = None`) remain
|
||||
allowed — they describe a caller choice, not a runtime failure of this
|
||||
function. The audit script `scripts/audit_optional_in_3_files.py` enforces
|
||||
this rule by failing CI on new `Optional[X]` return types in the 3
|
||||
refactored files.
|
||||
|
||||
### Public API deprecation: `ai_client.send()` → `ai_client.send_result()`
|
||||
|
||||
The public `ai_client.send()` is marked `@deprecated` (via
|
||||
`typing_extensions.deprecated`). It still works for backward compat but
|
||||
emits a `DeprecationWarning` at runtime. New code MUST use
|
||||
`ai_client.send_result()`, which returns `Result[str, ErrorInfo]` instead
|
||||
of `str`. Removal is planned in the follow-up
|
||||
`public_api_migration_20260606` track.
|
||||
|
||||
</new_content>
|
||||
## Testing Requirements
|
||||
|
||||
These are the process standards the project's test infrastructure enforces. For the full implementation contract (fixture names, anti-patterns, audit scripts), see [docs/guide_testing.md §Structural Testing Contract](../docs/guide_testing.md) and the per-styleguide audit scripts in [code_styleguides/](code_styleguides/).
|
||||
|
||||
Reference in New Issue
Block a user