This was generated by AI during triage.
Parent
Refs #3347, finding F12.
What to build
Guard decisions are emitted only through a telemetry channel that is inert unless an environment variable points it somewhere. In the ordinary case, where no sink is configured, every guard decision is discarded as it is made. The component's own data root holds only run records, so nothing about what the guard allowed or denied survives the session.
The consequence is that the questions an operator actually asks afterwards are unanswerable. Why was this denied. Has it been denying this all along. Did the guard even run. The parent's sibling findings make this concrete: one is about a false denial that had to be reproduced by hand to be believed, and another is about the guard silently not running at all. Both would be trivially answerable from a decision record, and both currently require re-deriving the situation live.
Make guard decisions durable and inspectable by default.
Design points
- Default on, local, and bounded. The failure here is that observability is opt-in, so re-inventing it as opt-in solves nothing. The record should exist without configuration, live beside the component's existing run data, and be bounded so it cannot grow without limit. Bounding is what makes default-on defensible.
- Record the decision, not the payload. Enough to answer why an operation was allowed or denied, and to distinguish a guard that denied from a guard that never ran. Not the full inspected content. This matters for the same reason the sibling fail-open finding matters: the interesting states include the guard's own absence, and an absent guard writes nothing unless the record is designed to make absence visible.
- The telemetry channel stays. This is not a replacement. A configured sink should keep receiving what it receives now; the local record is the floor beneath it, for the ordinary case where no sink exists.
- Cost is a real constraint. This is a hook path with a latency budget, and the marketplace has a standing convention about always-on hook cost. Writing a decision record must be cheap enough not to breach it. Measure rather than assume, and state the measured cost in the PR.
- Readable without tooling. An operator diagnosing a denial should be able to read the record directly. A format needing a purpose-built reader reintroduces the opacity this fixes.
Acceptance criteria
Out of scope
- Changing any guard decision. This item observes; it does not adjudicate.
- Shipping a viewer or analysis tool.
- Cross-machine aggregation.
Blocked by
None. Can start immediately, and it would make the two sibling guard decisions easier to reason about with evidence rather than by reproduction.
This was generated by AI during triage.
Parent
Refs #3347, finding F12.
What to build
Guard decisions are emitted only through a telemetry channel that is inert unless an environment variable points it somewhere. In the ordinary case, where no sink is configured, every guard decision is discarded as it is made. The component's own data root holds only run records, so nothing about what the guard allowed or denied survives the session.
The consequence is that the questions an operator actually asks afterwards are unanswerable. Why was this denied. Has it been denying this all along. Did the guard even run. The parent's sibling findings make this concrete: one is about a false denial that had to be reproduced by hand to be believed, and another is about the guard silently not running at all. Both would be trivially answerable from a decision record, and both currently require re-deriving the situation live.
Make guard decisions durable and inspectable by default.
Design points
Acceptance criteria
scripts/affected-tests.sh --runselects and passes the suites mapped to the changed files.Out of scope
Blocked by
None. Can start immediately, and it would make the two sibling guard decisions easier to reason about with evidence rather than by reproduction.