Implements the 4-phase documentation reorganization master plan. - Consolidation: Merged brief/, handoff/, planning/, and decisions/ into briefs/, handoffs/, plans/, and adr/ respectively (101 ADRs relocated) - Root Cleanup: Relocated HANDOFF-gpt55-*.md and key top-level docs (runtime_contracts.md, etc.) to canonical folders. Added superseded alerts. - Indices & Navigation: Created docs/README.md navigation document, docs/sessions/README.md index, docs/adr/README.md index - Note: Also includes prior commit adding ADR-0200+ corpus hygiene governance (ADR-0225, dependency map, backfilled cross-references)
97 lines
3.8 KiB
Markdown
97 lines
3.8 KiB
Markdown
# ADR-0158 — reboot_event audit trail entry (W-024 / L10b.3)
|
|
|
|
Status: accepted
|
|
Date: 2026-05-26
|
|
|
|
## Context
|
|
|
|
L10 scope §Sub-question 3 asked:
|
|
|
|
> **What does reboot record?** A `reboot_event` analog of `TurnEvent`,
|
|
> written to the audit trail, that lets future audit reconstruct the fact
|
|
> that this engine instance lost and regained its lifetime here.
|
|
|
|
ADR-0156 §"Out of scope" deferred this to L10b.3 / W-024. After W-022
|
|
(atomic writes) and W-023 (revision-mismatch warning), the checkpoint path
|
|
is now correct and observable. The missing piece is the audit record itself:
|
|
without it, the telemetry JSONL cannot distinguish a fresh start from a
|
|
reboot recovery, making the engine's lifetime history uninterpretable.
|
|
|
|
## Decision
|
|
|
|
### Serializer (`chat/telemetry.py`)
|
|
|
|
Add `serialize_reboot_event(...)` and `format_reboot_event_jsonl(...)`,
|
|
following the same pattern as `serialize_correction_event` / ADR-0059:
|
|
|
|
```jsonc
|
|
{
|
|
"type": "reboot", // discriminator
|
|
"restored_turn_count": 5, // manifest["turn_count"]
|
|
"stored_revision": "abc123", // manifest["written_at_revision"]
|
|
"current_revision": "def456", // _git_revision() at load time
|
|
"revision_matched": false, // true iff both known and equal
|
|
"recognizers_count": 2, // DerivedRecognizers restored
|
|
"candidates_count": 1, // DiscoveryCandidates restored
|
|
"timestamp": "..." // optional, caller-provided
|
|
}
|
|
```
|
|
|
|
`revision_matched` is `False` when either side is `"unknown"` or `""` —
|
|
the same guard as W-023's warning suppression, keeping the two features
|
|
consistent.
|
|
|
|
### Runtime wiring (`chat/runtime.py`)
|
|
|
|
The telemetry sink is `None` at `__init__` time — attached later via
|
|
`attach_telemetry_sink()`. Two-step buffered emission:
|
|
|
|
1. **`_load_engine_state()`** — builds and stores the JSONL string in
|
|
`self._pending_reboot_payload: str | None`. The string is the fully
|
|
serialized line; no further computation required at flush time.
|
|
|
|
2. **`attach_telemetry_sink(sink)`** — if `_pending_reboot_payload` is
|
|
set and `sink` is not None, emits the line and clears the field.
|
|
Subsequent calls to `attach_telemetry_sink` (e.g. replacing the sink)
|
|
do NOT re-emit; the payload is consumed exactly once.
|
|
|
|
This placement guarantees the reboot event appears **before any turn
|
|
events** in the audit stream for the session, matching the semantic intent
|
|
of "lifetime boundary record".
|
|
|
|
### Trust boundary
|
|
|
|
Metadata only — no surface text, no tokens, no versor coordinates.
|
|
`_git_revision()` returns a short SHA derived from the local git repo;
|
|
already used for the manifest and W-023 warning.
|
|
|
|
## Invariants pinned by tests
|
|
|
|
`tests/test_adr_0158_reboot_event.py` (11 tests):
|
|
|
|
**Serializer:**
|
|
- Structure, fields, and `revision_matched` logic (match / mismatch / unknown)
|
|
- Optional `timestamp` field
|
|
- Byte-identical output for identical inputs (determinism)
|
|
|
|
**Runtime integration:**
|
|
- Reboot event emitted to sink on `attach_telemetry_sink` after checkpoint load
|
|
- Emitted exactly once — second `attach_telemetry_sink` call does not re-emit
|
|
- No event when no checkpoint directory exists (fresh start)
|
|
- No event when `no_load_state=True`
|
|
- `revision_matched: true` when revisions agree
|
|
- Reboot event precedes synthetic turn events in the stream
|
|
|
|
## L10b closure
|
|
|
|
With W-024, the L10b sequence is complete:
|
|
|
|
| Chunk | Work item | ADR | What it does |
|
|
|---|---|---|---|
|
|
| L10b.1 | W-022 | ADR-0156 | Atomic checkpoint writes (write-temp + fsync + rename) |
|
|
| L10b.2 | W-023 | ADR-0157 | Revision-mismatch `RuntimeWarning` on load |
|
|
| L10b.3 | W-024 | ADR-0158 | `reboot_event` audit trail entry |
|
|
|
|
The checkpoint path now satisfies all three of ADR-0146's runtime-model
|
|
commitments: **atomic**, **observable** (warning on staleness), and
|
|
**auditable** (reboot recorded in the telemetry stream).
|