InstructionsLoaded hook — direct rule-load observability
Feature B (FUTURE-001) of the path-scoped-rules-pat001 line. A fail-open InstructionsLoaded telemetry hook records each time a .claude/rules/*.md rule file is loaded into the agent’s editing context, and a /cwtf section presents those rule-load events beside audit-trail hook-edit entries so a human can see whether a rule (e.g. hooks-pretooluse.md) was in context around a hook edit — and classify a clause-5 violation themselves.
This upgrades the PAT-001 measurement signal from the indirect git-archaeology proxy (accepted 2026-04-14) to direct runtime observation. It does not re-open that accepted gate.
What it does
hooks/instructions-loaded.sh(registered on theInstructionsLoadedevent, matcher*) appends one JSON line per.claude/rules/*.mdload to.correctless/meta/instructions-loaded.jsonl(gitignored runtime telemetry). It is fail-open: missingjq/lib.sh/canonicalize_path, malformed or empty stdin, or an unwritable meta dir all →exit 0with no log. Exit codes are ignored by the harness for this event, so any non-zero exit would be dead behavior.hooks/audit-trail.shgained an additivesession_idfield (from the harness stdin field — the same source the new hook reads) so the two logs can be shown side-by-side for the same session. This is a display-alignment aid, not a machine-join key./cwtf→ “Rule-Load Observability” reads both logs and presents raw evidence — rule-loads with timestamps +trigger_file_path, alongside hook-edits grouped per edit-session — with plain-language framing, a liveness/denominator line, and no automated MG-001/MG-002 verdict (the human classifies).
Why no automated classifier
An earlier draft built a correlator that joined the two logs on session_id + whole-second timestamp ordering + path match to auto-label each hook edit MG-001 vs MG-002. Multi-agent review found ~8 CRITICAL/HIGH failure modes concentrated in that one fragile cross-file join, every one biasing the verdict optimistic (the “flying blind” / silent-telemetry class). Because this is an advisory, forward-looking signal on an already-accepted gate, the join’s risk did not justify its value. The feature was scoped down to raw observability the human interprets (PRH-005) — matching /cwtf’s “context, not judgment” ethos.
Firing model (verified)
Confirmed empirically against the live harness (Claude Code 2.1.185, 2026-07-01): opening a .claude/rules/-scoped file mid-session emits a fresh, per-open path_glob_match event the first time that rule enters context (a rule already resident at session start does not re-fire). This per-open model is what makes per-edit observation meaningful. See ENV-012 and the verification report for the attestation.
Data flow
flowchart LR
A["Agent opens a<br/>.claude/rules/*.md<br/>-scoped file"] -->|InstructionsLoaded event| B["instructions-loaded.sh<br/>(fail-open)"]
B -->|canonicalize + prefix-check<br/>rule-file scope only| C["jq -n --arg<br/>one JSON line"]
C -->|O(1) append| D[".correctless/meta/<br/>instructions-loaded.jsonl<br/>(gitignored)"]
E["Agent edits a<br/>hooks/ file"] -->|PostToolUse| F["audit-trail.sh<br/>(+ session_id)"]
F --> G[".correctless/artifacts/<br/>audit-trail-{slug}.jsonl"]
D --> H["/cwtf Rule-Load<br/>Observability"]
G --> H
H -->|raw evidence + liveness line<br/>NO verdict| I["Human classifies<br/>MG-001 vs MG-002"]
Configuration & limitations
- Requires Claude Code ≥ 2.1.69 for the
InstructionsLoadedevent (ENV-012). On older harnesses the hook never fires, the log stays empty, and the/cwtfsection is dormant (a non-alarming advisory) — graceful degradation. - Activation on upgrade: the hook is installed by
/csetupbut only registered insettings.jsonon the nextregister_hooks()run — re-run/csetupafter upgrading, or the log stays dormant. - Unbounded local growth: the log is O(1)-append, gitignored, and local. There is currently no
/cprunereaper for it (accepted; see ABS-046). - Forgeable: the log is agent-writable and deliberately not SFG-protected (per-session telemetry, not a security asset). Because there is no automated verdict, a forged line only misleads a human reading raw evidence with the liveness counts in view — an accepted residual for an advisory signal.
References
- Spec:
.correctless/specs/instructionsloaded-hook.md(INV-001..016, PRH-001..005) - Architecture: ABS-004 (amended), ABS-046, TB-010, ENV-012, ENV-005
- Verification / attestation:
.correctless/verification/instructionsloaded-hook-verification.md