Decompose Step 6 snapshot: 140 task specs + contract docs

Closes out greenfield Step 6 (Decompose) for all 14 components
(C1-C13 + cross-cutting helpers/replay). Covers tasks AZ-266..AZ-446
plus the _dependencies_table.md and component contract documents.

State file updated to greenfield Step 7 (Implement), not_started.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-11 00:39:48 +03:00
parent 8171fcb29e
commit 880eabcb3f
172 changed files with 22897 additions and 35 deletions
@@ -0,0 +1,84 @@
# Contract: log_record_schema
**Component**: shared_logging (cross-cutting concern owned by E-CC-LOG / AZ-245)
**Producer task**: AZ-266 — `_docs/02_tasks/todo/AZ-266_log_module.md`
**Consumer tasks**: every component task that emits logs (C1C13 components, plus C12 operator tooling)
**Version**: 1.0.0
**Status**: draft
**Last Updated**: 2026-05-10
## Purpose
Frozen, machine-parseable JSON envelope for every log record emitted by any onboard component. Stable field set + ordering is a hard requirement for FDR analysis tooling (`kind="log"` records are post-flight queryable) and for the contract test that verifies field-name + ordering invariants.
## Shape
### One JSON object per log line, UTF-8, no trailing comma, newline-terminated
```python
# Conceptual dataclass — actual implementation may emit via orjson / python-json-logger
@frozen
class LogRecord:
ts: str # ISO 8601 UTC, microsecond precision, e.g. "2026-05-10T03:14:15.123456Z"
level: str # one of {"DEBUG", "INFO", "WARN", "ERROR"} — matches Python stdlib levelname (no "WARNING")
component: str # component slug from module-layout.md, e.g. "c2_vpr", "c5_state", "shared.logging"
frame_id: int | None # monotonic per-flight frame counter; None for non-frame-correlated records (startup, shutdown, periodic)
kind: str # categorical tag, e.g. "vio.tick", "vpr.query", "fdr.write", "log.diag"
msg: str # human-readable short message, no PII, no stack traces (those go in `exc`)
kv: dict[str, Any] # arbitrary structured key-value payload, JSON-safe scalars + nested dict/list only
exc: str | None # optional formatted exception traceback for ERROR/WARN; None otherwise
```
| Field | Type | Required | Description | Constraints |
|-------|------|----------|-------------|-------------|
| `ts` | string (ISO 8601 UTC, µs) | yes | Emit timestamp | RFC 3339 with `Z` suffix |
| `level` | string | yes | Log level | strictly one of `DEBUG`, `INFO`, `WARN`, `ERROR` |
| `component` | string | yes | Origin component slug | snake_case, must match a module-layout entry or `shared.<name>` |
| `frame_id` | integer or null | no | Per-flight monotonic frame index | non-negative when present |
| `kind` | string | yes | Record category tag | dotted snake_case, max 64 chars |
| `msg` | string | yes | Human message | no embedded newlines (use `kv` for multi-line context) |
| `kv` | object | yes (may be `{}`) | Structured key-value payload | JSON-safe scalars + nested objects/arrays |
| `exc` | string or null | no | Exception traceback for ERROR/WARN | absent or `null` for INFO/DEBUG |
### Field ordering (REQUIRED — verified by contract test)
`ts, level, component, frame_id, kind, msg, kv, exc` — formatter MUST emit keys in this order. Re-ordering breaks downstream column-aligned parsers used by FDR tooling.
## Invariants
- Every record is a single JSON object on a single line (newline-terminated, no embedded newlines in any field value).
- `level` value uses `WARN` not `WARNING` (intentional, simpler grep target).
- `frame_id` is omitted (`null`) — never invented — when the emitter has no current frame context.
- `kv` values must be JSON-serialisable without custom encoders; binary payloads are base64-encoded strings within `kv`.
- `exc` is present only for `level in {WARN, ERROR}` records that originated from an exception; otherwise it is `null` or absent.
- The schema is strictly additive — no field is ever removed or renamed without a major version bump and a matching FDR record-schema migration in E-CC-FDR-CLIENT.
## Non-Goals
- This contract does not define WHAT to log (per-component § 9 sections own that).
- This contract does not define log routing (stdout vs journald vs FDR — see handler topology in E-CC-LOG epic).
- This contract does not define structured event types — `kind` is a free-form tag, not a closed enum.
## Versioning Rules
- **Breaking changes** (field renamed/removed, type changed, ordering changed, level enum reduced) require a new major version + a deprecation pass through every consumer.
- **Non-breaking additions** (new optional field appended at the end of the order, new `kind` tag, new `level` value) require a minor version bump.
- The contract test (`tests/contract/log_schema.py`) MUST be updated alongside any version bump.
## Test Cases
| Case | Input | Expected | Notes |
|------|-------|----------|-------|
| valid-info-no-frame | `level=INFO, component="c2_vpr", kind="vpr.warmup", msg="loaded model", kv={"model": "salad"}` | accepted; `frame_id=null`, `exc=null`; field order matches spec | Startup-time INFO record |
| valid-warn-with-frame | `level=WARN, component="c5_state", frame_id=4321, kind="state.cov_spike", msg="covariance jumped 5x", kv={"jump_factor": 5.2}` | accepted; key order locked; FDR bridge MUST forward this record | Cross-cuts AC: WARN flows into FDR |
| valid-error-with-exc | `level=ERROR, component="c11_tilemanager", kind="tile.upload_fail", msg="HTTP 503", kv={"tile": "z18/x12345/y67890"}, exc="Traceback (most recent call last):..."` | accepted; `exc` present and non-null; FDR bridge MUST forward | Cross-cuts AC: ERROR + exc captured |
| invalid-bad-level | `level="WARNING"` | rejected with `LogSchemaError` (or formatter logs at ERROR and drops record) | Contract test enforces `WARN` not `WARNING` |
| invalid-multiline-msg | `msg="line1\nline2"` | rejected OR newline replaced with `\\n` literal — formatter must guarantee single-line output | One JSON object per line invariant |
| invalid-non-serialisable-kv | `kv={"obj": <numpy.ndarray>}` | rejected with `LogSchemaError` (caller must convert to list before passing) | JSON-safe-only invariant |
| ordering-stable | any valid record | emitted JSON keys appear in `ts, level, component, frame_id, kind, msg, kv, exc` order regardless of construction order | Contract test parses raw bytes and asserts key order |
## Change Log
| Version | Date | Change | Author |
|---------|------|--------|--------|
| 1.0.0 | 2026-05-10 | Initial contract derived from E-CC-LOG epic (AZ-245) | autodev decompose Step 2 |