fix: close sentinel audit integrity gaps 1–5 (v3.5.1)#331
Merged
Conversation
Gap 4: Replace hardcoded MAX_RECORDS=200 with a constructor parameter (max_records) wired to CONF_AUDIT_HOT_MAX_RECORDS / RECOMMENDED_AUDIT_HOT_MAX_RECORDS, following the DiscoveryStore pattern. Gap 5: action_policy_path was written by async_append_finding but absent from _V2_FIELD_DEFAULTS, so the v1→v2 migration silently omitted it from records loaded from storage. Added to the defaults dict. Tests: test_audit_store_respects_config_max_records, test_audit_store_default_max_records, test_migrate_record_backfills_action_policy_path, test_migrate_record_preserves_action_policy_path_if_set.
…cations, propagate trigger_source
Gap 1: Suppressed findings (cooldown or policy gate) now produce an audit
record via _append_finding_audit before returning, so every evaluated
finding has an audit trail regardless of outcome. Applied to both simple
(_dispatch_item) and compound (_dispatch_compound) paths.
Gap 2: Findings where ACTION_POLICY_BLOCKED is returned by evaluate_canary
now skip notification (register_finding for cooldown only; no
register_prompt; no async_notify). The BLOCKED state is audited with
action_policy_path='blocked'. The register_finding / register_prompt split
also required reordering the compound dispatch path so exec_result is
computed before the cooldown/prompt loops.
Gap 3: _run_once now accepts a trigger_source parameter ('poll', 'event',
'on_demand'). All three scheduler call sites pass the correct value via
lambda. The value is threaded through _dispatch_item and _dispatch_compound
to _append_finding_audit and written to every audit record.
Tests: test_suppressed_finding_creates_audit_record,
test_suppression_gate_fires_before_triage, test_blocked_finding_no_notification,
test_blocked_finding_creates_audit_record, test_blocked_finding_registers_cooldown_not_prompt,
test_trigger_source_{poll,event,on_demand}_in_audit (10 new tests).
Version bump: 3.5.0 → 3.5.1 (closes audit integrity gaps 1–5). CLAUDE.md: project-level guidance for Claude Code. TODOS.md: captures deferred work — shim removal (P3/S), entity-ID fix for people_home (P2/M), and Operational Health Entity (P1/XL, now unblocked by this PR). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
mwmdeadpool
pushed a commit
to mwmdeadpool/home-generative-agent
that referenced
this pull request
Mar 16, 2026
PR goruck#331: Sentinel audit integrity gaps - audit suppressed findings, skip BLOCKED notifications, propagate trigger_source, config-driven max_records, v1→v2 migration fix for action_policy_path PR goruck#332: Remove _supports_suppression_reason_code() introspection shim - dead code cleanup, direct async_append_finding calls PR goruck#333: Use entity IDs for people_home/people_away in snapshot derived context; v2→v3 suppression state migration to drop stale friendly-name grace keys Custom files preserved: Mem0 client, intent resolver, lambda registry, MCP tools, config_flow custom toggles.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
_append_finding_auditbefore returning on suppression.ACTION_POLICY_BLOCKEDfindings skip notification entirely.register_finding(cooldown) is called;register_prompt(pending user action) is not. The BLOCKED outcome is audited withaction_policy_path='blocked'. Compound dispatch was reordered to computeexec_resultbefore the cooldown/prompt loops.trigger_source('poll','event','on_demand') is now threaded from the scheduler call sites through_run_once→_dispatch_item/_dispatch_compound→_append_finding_audit→ every audit record.AuditStoremax-records cap is config-driven viaCONF_AUDIT_HOT_MAX_RECORDS/RECOMMENDED_AUDIT_HOT_MAX_RECORDS(default 200), following theDiscoveryStorepattern. HardcodedMAX_RECORDSconstant removed.action_policy_pathwas written byasync_append_findingbut missing from_V2_FIELD_DEFAULTS, so the v1→v2 migration silently omitted it for records loaded from storage. Added to the migration defaults.test_audit_schema.pyandtest_sentinel_end_to_end.py.Pre-Landing Review
Pre-Landing Review: 2 issues (0 critical, 2 informational)
audit/store.py:71— Constructor defaultmax_records: int = 200is a bare literal separate fromRECOMMENDED_AUDIT_HOT_MAX_RECORDS. A test covers drift; risk is low.sentinel/engine.py:770— All-suppressed compound path uses hardcodedsuppression_reason_code="suppressed"rather than per-constituent codes. Minor; audit consumers see an opaque value.Eval Results
No prompt-related files changed — evals skipped.
TODOS
No TODO items completed in this PR (gaps 1–5 close the dependency for "Remove shim" P3/S and "Operational Health Entity" P1/XL — those items are now unblocked but not done).
Test plan
make lint: All checks passedmake typecheck: 0 errors, 0 warnings🤖 Generated with Claude Code