From efda737f93e81b9971bbac11dfc306fbfc12df33 Mon Sep 17 00:00:00 2001 From: "C.D.Lee" <265386841+opencdlee-dotcom@users.noreply.github.com> Date: Wed, 23 Sep 2026 15:07:43 -0700 Subject: [PATCH 1/3] One edit to a shared payload was seven HIGH incidents, and the rung that explained it was lost to every git timeout Precision plan step S7 (Phase 3): the operator's own LaunchAgents. Gap 1: one payload edit, seven cases. #383 and #392-#397 were one edit to ~/Ai/Universe/tools/aikit/schedule/run.py (4a1646366adf -> 25ee9a4593c2), one incident per com.aikit.* plist that runs it. check_persistence now collects a change confined to a payload's bytes (same program, argv, env and payload path; never an attack-defined job) and emits ONE finding per (payload, new sha): case persistence:payload-update:, the referring labels in the detail and their plist paths in referrer_paths. Same shape as the OS-program case. _accept_into_baseline promotes every job a verdicted payload case names, so one benign-positive ends the re-assertion for all of them. Store migration persistence_payload_case_20260923 folds open per-plist incidents whose newest evidence is payload-only into that case (evidence matched, created_at < now, adjudicated rows untouched). Gap 2: why custody read null. The rung did reach the payload. _custody(run.py, sha) answered local-commit (MEDIUM) on 193 of the 217 scans that recorded the change. The 24 scans that recorded custody null and HIGH were the scans where git did not answer: 11-190 s per plist there, against 0-1 s when it answered (probe timeouts are 10-15 s). Seven plists asked git about the same file seven times a scan. Each non-answer flipped the case back to HIGH and wrote a new event. The payload is now graded once per scan, by _custody_payload. It asks the same intent-then-git questions. When git gives no answer at all, it asks whether the bytes were already explained: by the custody ledger (a rung this payload earned on an earlier scan, now remembered) or by an intent receipt for the same sha at another path. Either one carries as copy-of-graded, the weakest rung. On the recorded corpus that takes run.py from 24 HIGH scans to 1 (the first sighting, before any answer existed). #319 (~/.local/bin/improver bytes -> a588f96d11b4) was never asked. An extension-less payload fails _intent_worthy, and its receipt binds the source path the agent wrote (.../VSCode Projects/improver/improver.py), not the installed copy. _custody_payload drops that hook-mode prefilter, and _intent_receipt finds the receipt by sha. Result: copy-of-graded, MEDIUM. Also touched in the same branch: the per-job payload custody lookup now honours attack_defined, as its comment already promised. Before this, a DYLD-injected job whose payload was committed recorded custody=self-committed on an attack-defined finding. The severity was untouched, but the chain and routing tiers read that field. Gap 3: producer fields. On current code the NEW finding already resolves a producer class through its subject. The seven cited incidents lack one only in their pre-2026-08-29 evidence, which predates subjects and the runner subcommand fix (script_target None) and cannot be recovered. The NEW finding now also carries program_sha and target_sha flat, and target_sha on the subject, so recorded evidence names both halves of what the job executes. Also touched: tests/conftest.py. The new ledger writer turned an existing test leak into a write. FamiliesAreTheAdjudicationSurface re-diffs the REAL LaunchAgents through _accept_into_baseline, and during this branch's suite run it appended a local-commit row for run.py to the operator's ~/.aegis/custody.jsonl. That row has been removed by hand. The suite now refuses and reports any _custody_remember aimed at the real ledger, the same way it handles the notary anchor. The guard also stops a pre-existing leak: TestWritEnforcementIsActuallyWired reached the real ledger 45 times through _grade_binary. Tests: tests/test_persistence_payload_case.py (28). Co-Authored-By: Claude Opus 5.5 (1M context) --- aegis.py | 280 ++++++++++++- tests/conftest.py | 30 ++ tests/test_persistence_payload_case.py | 550 +++++++++++++++++++++++++ 3 files changed, 843 insertions(+), 17 deletions(-) create mode 100644 tests/test_persistence_payload_case.py diff --git a/aegis.py b/aegis.py index 4a2d512..fed9061 100755 --- a/aegis.py +++ b/aegis.py @@ -6489,6 +6489,64 @@ def _retire_unjoinable_chain_incidents(db, now): return retired +# FROZEN recognizer for the 2026-09-23 payload-case migration: the first +# detail line check_persistence wrote for a change confined to a payload's +# bytes, `