Expand description
PostToolUse observation classifier.
Third supply line for candidate rules. When the Claude Code
PostToolUse hook fires for an Edit / MultiEdit / Write tool, the
CLI calls classify to turn the raw event into a structured
Observation and enqueues it via OutboxQueue with
kind="observation". The cloud consumer clusters those rows by
content_hash and feeds the rule-promoter alongside remember_rule
captures and GitHub-App PR-merge signatures.
Classification is deterministic and keyword-driven — no LLM call, sub-millisecond target. The heuristics are intentionally simple:
Writeof a brand-new file ⇒feature- Edit that strips a visible
FIXME/BUG/TODO⇒bugfix - Edit where the diff is whitespace-only (no semantic deltas) ⇒
refactor - Anything else ⇒
change
discovery and decision are declared as valid obs_type values
for forward-compat but are never emitted from the local classifier
(they need LLM or conversation context).
Privacy guard: edits touching secret-bearing paths (.env*,
*.secrets*, *.key, *.pem, id_rsa*, credentials*) are
dropped before classification. The user cannot opt in — these
files must never leave the local machine via the observation
channel.
Re-exports§
pub use crate::cloud::api_types::Observation;pub use crate::cloud::api_types::ObservationScope;
Structs§
- Classify
Input - Input payload for
classify. Borrowed so the caller doesn’t have to clone every string coming out of the hook event; the classifier only needs read access.
Constants§
- DIFF_
EXCERPT_ MAX_ BYTES - Maximum size of the diff excerpt captured in the observation payload. The cloud side does its own heavier clustering; we ship just enough context for a human reviewer to recognise the edit.
- NARRATIVE_
MAX_ CHARS - Hard narrative length cap.
- TITLE_
MAX_ CHARS - Hard title length cap. Matches the
titledoc comment onObservation.
Functions§
- classify
- Classify a
PostToolUseevent. ReturnsNonewhen the event should not produce an observation (non-edit tool, no file path, missing diff signal, or a privacy-denied path). - is_
privacy_ denied truewhen the path matches one of the hardcoded secret patterns. Substring match (not full-glob) — good enough to coversrc/config/.env.localandinfra/prod.credentials.json.