Build the telemetry recording foundation - #286
gmemuriuki wants to merge 30 commits into
Conversation
Co-authored-by: Codex <codex@openai.com>
Make room for new telemetry pieces without changing behavior.
Use UUIDs so malformed identifiers are rejected when data is read.
Validate stored dates and versions and keep timestamps to whole seconds.
Add shared row metadata and reject schema drift in version 1.
Classify recognized but invalid rows separately from malformed input.
Give each scoped telemetry identifier a fixed prefix and canonical 128-bit hexadecimal representation. Parse the same representation strictly and use it for JSON serialization. Keep identifier domains separate at the type level, and check the published examples so code and the telemetry contract cannot drift.
Separate identifier windows from domain-scoped dimensions so callers cannot exchange them or mix identifiers from different domains. Length-prefix each input field and pin the HMAC domain constants in the recording contract. This keeps component boundaries unambiguous and makes accidental identifier rotation visible in tests.
Create each 256-bit identity key from the operating system random source and return failures to the caller. Keep generation independently testable so the complete buffer and error path are covered without relying on probabilistic assertions.
Keep identity material in strict, versioned TOML before adding file persistence. Share lowercase hexadecimal encoding with scoped identifiers so keys and identifiers follow the same rules. Reject unknown fields, future versions, malformed keys, and noncanonical anchor dates. Pin storage-limit JSON field order in its contract test.
Generate fresh state from one UTC day while leaving the return-cohort anchor absent until a session is observed. Use a deterministic constructor to pin the exact initial TOML in tests. Keep identity resets monotonic with the latest-opened-day high-water mark and document that rule consistently across the RFD.
Represent cohort days as a bounded D0-D30 value and advance the private return-cohort anchor as sessions are observed. Persist state before recording D0 so partial failures keep identifiers stable and undercount returns.
Roll identifier windows over on the first observation at day 30 or later, while keeping the identity key stable. Select identifier and return-cohort anchors before mutating private state, so storage can persist one coherent session transition.
Rotate the identity key, advance the window anchor, and clear the return cohort as one state replacement. Generate the new key before mutation so failures leave the previous state intact. Document reset's clock-clamping rules and future state obligations.
Make room for focused state submodules while preserving the existing implementation unchanged. The telemetry parent continues to load state through the same private module boundary.
Keep the serialized private-state model in the module root and move identifier reset, window, and cohort transitions into lifecycle.rs. Leave each responsibility's tests beside its implementation and record the boundary in the module structure guide.
Prepare the schema for event-family modules without changing its behavior. Adjust the contract fixture path for the file's new directory depth.
Use closed enums for hook agents, platforms, and session starts. Pin serialized names to the version-one contract and reject unknown values.
Define the agent, platform, and start values recorded for a session. Read session-start rows through the versioned classifier and test them against the JSONL contract. Document that platform values describe the binary's compilation target rather than its physical host.
Keep the seven-agent configuration list separate from the smaller hook agent list. Convert every project agent explicitly so future agent support requires a deliberate telemetry update. Pin each version-one serialized name, including the opencode spelling.
Add the version-one row for one entry in the daily agent configuration snapshot. Keep fixed fields inside the constructor and test every value without wiring storage or production recording yet.
Recognize version-one agent configuration rows through the shared envelope classifier. Keep future versions separate from invalid rows and pin serialization to the JSONL contract example.
Link hook agents to the broader supported-agent vocabulary so rows that refer to the same agent cannot drift apart. Group per-agent configuration values at construction sites, making the configured flag explicit and preparing for the daily batch builder.
Add the fixed triggers, outcomes, and unnamed-package reasons used by resolution summaries. Keep reason counters private, increment them through checked operations, and align dropped resolution batches with storage-limit reporting.
Build resolution summary rows from their reason counters so the stored unnamed-package total cannot drift from its breakdown. Apply the same validation when reading JSON, and reject overflow or missing fields before invalid data reaches analysis.
Teach the shared JSONL reader to recognize version one resolution summaries and serialize them through TelemetryRow. Keep future versions distinct from invalid supported rows, including summaries with unknown fields or inconsistent package counts.
Add the closed version one package ecosystem and extension match values before introducing the package resolution row. Pin their JSON names and reject unknown values so later schema changes remain explicit.
9bca222 to
7b84afb
Compare
A session start's day is derived from its completion timestamp. Reject stored rows where those values disagree instead of admitting inconsistent data to typed readers. Keep file membership checks with the archive reader, which has the daily file context needed for that separate invariant.
|
This looks pretty nice, I've made my agents play around with this solution & the #287 one. The identity API here gets reworked in #287, so thing like
|
What does this PR do?
This builds the foundation for the accepted telemetry RFD (#273).
It adds strict, versioned schemas for the first telemetry rows, typed classification of stored lines, scoped HMAC identifiers, and private in-memory identity state. Cohort, window-rollover, and reset transitions are defined without adding persistence or production event emission.
It also defines the initial package-resolution vocabulary and clarifies that a future uploader will read validated records from closed days.
Verification
Disclosure questions
AI disclosure.
Questions for reviewers.
Does this provide the right boundary for the storage work that follows?