Private
Public Access
feat(directives): scavenge sweep 4/5 (tracks + commands + styleguides + todos): 18 batch-4 directives + concurrent worker batches
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
# per_aggregate_dataclass_promotion
|
||||
|
||||
## v1
|
||||
|
||||
**Why this iteration:** Lifted from `conductor/code_styleguides/type_aliases.md` §2.5 — the per-aggregate promotion rule codifies that any sub-aggregate with stable distinct fields must be its OWN `@dataclass(frozen=True, slots=True)`, not a shared mega-dataclass.
|
||||
**Source:** `conductor/code_styleguides/type_aliases.md` §2.5 ("When the role has stable distinct fields, promote it to its OWN dataclass")
|
||||
|
||||
---
|
||||
|
||||
**Lifted:** 2026-07-03 scavenge sweep batch 4/5: tracks + commands + styleguides + todos
|
||||
@@ -0,0 +1,40 @@
|
||||
# Promote a sub-aggregate with stable distinct fields to its OWN @dataclass(frozen=True, slots=True) — do not share one mega-dataclass across multiple concepts
|
||||
|
||||
## What it says
|
||||
|
||||
When a sub-aggregate has a known set of stable, distinct fields (e.g., `CommsLogEntry` has `ts, role, kind, direction, model, source_tier, content, error`; `FileItem` has `path, view_mode, custom_slices`; `RAGChunk` has `id, document, path, score, metadata`), promote it to its OWN `@dataclass(frozen=True, slots=True)` with its OWN fields. Do NOT share one mega-dataclass across multiple concepts.
|
||||
|
||||
## Why
|
||||
|
||||
The per-aggregate dataclass is the "names for shapes" pattern extended to the structural level. Each concept gets its own type, its own fields, its own `to_dict()` / `from_dict()` round-trip. Consumers use direct field access (`entry.ts`, `t.depends_on`, `chunk.document`) which compiles to a single C-level field read with 0 branches.
|
||||
|
||||
## When NOT to promote
|
||||
|
||||
When the shape is genuinely unknown at type level and the fields are heterogeneous (e.g., log entries from 5 different vendors with mutually-exclusive keys). Use `Metadata: Metadata` (the dataclass) as the catch-all — its 36 explicit fields cover the common wire schema, and its dict-compat methods allow ad-hoc keys for vendor-specific extensions. Do NOT use `dict[str, Any]` directly anywhere; `Metadata` is the typed replacement.
|
||||
|
||||
## Canonical pattern (from src/openai_schemas.py and src/type_aliases.py)
|
||||
|
||||
```python
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class CommsLogEntry:
|
||||
ts: str = ""
|
||||
role: str = ""
|
||||
kind: str = ""
|
||||
direction: str = ""
|
||||
model: str = "unknown"
|
||||
source_tier: str = "main"
|
||||
content: Any = None
|
||||
error: str = ""
|
||||
|
||||
def to_dict(self) -> Metadata:
|
||||
return asdict(self)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, raw: Metadata) -> "CommsLogEntry":
|
||||
valid = {f.name for f in fields(cls)}
|
||||
return cls(**{k: v for k, v in raw.items() if k in valid})
|
||||
```
|
||||
|
||||
## The rule (Tier 1 audit 2026-06-25)
|
||||
|
||||
If the original `data_structure_strengthening_20260606` design intent was per-concept promotion (it was — see `spec.md §3.3`: *"Phase 2 can convert `Metadata` to a `TypedDict` (or split into per-concept `TypedDict`s)..."*), then `metadata_promotion_20260624` must continue in that direction: per-aggregate dataclasses, not a shared mega-dataclass.
|
||||
Reference in New Issue
Block a user