Private
Public Access
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).
|
- **Functions/Methods:** `[C: Caller1, Caller2]` (Primary callers).
|
||||||
- **State Variables:** `[M: File:Line, Method]` (Mutation points) and `[U: File]` (Major use paths).
|
- **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
|
## 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/).
|
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