From 9ac383e812f0a5b247cb4c36c2c2781c8881a535 Mon Sep 17 00:00:00 2001 From: Jerome Date: Mon, 29 Jun 2026 00:42:54 +0000 Subject: [PATCH] v3: Add ledger, drift detection, canary checks, per-agent privacy, writer registry --- memory-audit-maintenance.prose.md | 111 +++++++++++++++++++++++++++--- 1 file changed, 102 insertions(+), 9 deletions(-) diff --git a/memory-audit-maintenance.prose.md b/memory-audit-maintenance.prose.md index 703f529..21d90e8 100644 --- a/memory-audit-maintenance.prose.md +++ b/memory-audit-maintenance.prose.md @@ -6,7 +6,7 @@ id: 067NC4KG01RG50R40M30E20918 ### Goal -Autonomously audit and reorganize an agent's native memory (MEMORY.md, USER.md, SOUL.md), categorize entries, redistribute them to correct locations, verify live configurations, and free character budget all without user intervention unless a truly unresolvable ambiguity exists. +Autonomously audit and reorganize an agent's native memory (MEMORY.md, USER.md, SOUL.md), categorize entries, redistribute them to correct locations, verify live configurations, and free character budget all without user intervention unless a truly unresolvable ambiguity exists. Every agent runs this contract for **its own** memory files only no cross-agent access, no shared state. ### Requires @@ -14,7 +14,7 @@ Autonomously audit and reorganize an agent's native memory (MEMORY.md, USER.md, ### Maintains -Memory health state current utilization, last audit timestamp, and any unresolved ambiguities. Postcondition: no entry is duplicated, no session note or stale snapshot survives, and no config is unverified. +Memory health state current utilization, last audit timestamp, drift alerts, and any unresolved ambiguities. Postcondition: no entry is duplicated, no session note or stale snapshot survives, no config is unverified, and the audit ledger is up-to-date. #### utilization Current character utilization of MEMORY.md and USER.md. Material: the percentages. @@ -25,6 +25,12 @@ Timestamp of the most recent successful audit. Material: the timestamp. #### unresolved Any entries that could not be autonomously categorized. Material: the entry text and the reason for ambiguity. +#### drift_alerts +Active alerts from drift detection (e.g., deletions accelerating, unverified configs growing). Material: the alert list. + +#### ledger +Persistent audit trail stored at `~/.hermes/memories/MEMORY_AUDIT_LEDGER.md`. Material: append-only, never modified or deleted. + ### Continuity - self-driven: re-audit every 14 days (2 weeks) @@ -41,11 +47,12 @@ Any entries that could not be autonomously categorized. Material: the entry text ### Strategies -- **Autonomous first:** Never ask the user about entries that clearly belong in a deletion or move category. Only escalate on true ambiguity (e.g., an entry could be either a Preference or a Technical Config, and the choice affects which file it goes in). +- **Autonomous first:** Never ask the user about entries that clearly belong in a deletion or move category. Only escalate on true ambiguity. - **Incremental over nuclear:** Always use patch-level edits (find-and-replace) rather than wholesale file rewrites. If the patch tool fails, fall back to rewrite only as a last resort. - **Verify before trusting:** Every technical config in MEMORY.md must be verified against the live system. If a service is unreachable, mark it as `UNVERIFIED` rather than deleting it. - **Stale state has a shelf life:** Any entry marked as "Temporary State" (e.g., "verbal offer", "deal pending", "negotiation phase") is deleted if older than 14 days. - **Work around tool failures:** If the `memory` tool fails after 2 retries, add a summary marker and report the stale state in the unresolved list. +- **Privacy isolation:** Each agent only reads and writes its own memory files. No cross-agent memory access, no shared ledger, no shared state. The contract is the standard; each agent runs it independently. ### Invariants @@ -53,14 +60,43 @@ Any entries that could not be autonomously categorized. Material: the entry text - No duplicate entries survive across MEMORY.md and USER.md - No session note or temporary state survives past 14 days - No config is trusted without verification (or marked UNVERIFIED) +- The audit ledger is append-only never modified or deleted +- The canary entry survives every audit unmodified ### Execution ```prose # ============================================================ -# PHASE 1: Pre-flight +# PHASE 0: Canaries & Privacy # ============================================================ +# Check canaries if either is missing or modified, raise CRITICAL alert +memory_canary = read_file_line("~/.hermes/memories/MEMORY.md", containing="CANARY: Do not modify this line") +user_canary = read_file_line("~/.hermes/memories/USER.md", containing="CANARY: Do not modify this line") + +if memory_canary is null or user_canary is null: + return { + status: "CRITICAL", + alert: "CANARY BREACH memory integrity compromised", + details: { + memory_canary_intact: memory_canary is not null, + user_canary_intact: user_canary is not null + } + } + +# This agent only touches its own files no cross-agent access +# Confirm we are operating on this agent's own memory directory +if not directory_exists("~/.hermes/memories"): + return {status: "ERROR", reason: "Memory directory not found for this agent"} + +# ============================================================ +# PHASE 1: Pre-flight & Ledger +# ============================================================ + +# Read the audit ledger for drift detection +ledger = read_file("~/.hermes/memories/MEMORY_AUDIT_LEDGER.md") +last_audit_entry = parse_last_entry(ledger) + # Verify the memory tool works try: memory_status = call check_memory_tool @@ -76,9 +112,36 @@ memory_util = len(memory_content) / max_memory_chars * 100 user_util = len(user_content) / max_user_chars * 100 # Check if audit is needed -if last_audit > 14 days and memory_util < 75 and user_util < 75: +if last_audit_entry.timestamp > 14 days and memory_util < 75 and user_util < 75: return {status: "SKIP", reason: "No audit needed"} +# ============================================================ +# PHASE 1b: Drift Detection (Compare to Last Audit) +# ============================================================ + +drift_alerts = [] + +if last_audit_entry exists: + # Deletions accelerating? (50% increase from last audit) + if last_audit_entry.deletions > 0: + deletion_increase = (memory_util - last_audit_entry.memory_util_after) / last_audit_entry.deletions * 100 + if deletion_increase > 50: + drift_alerts.append("ALERT: Memory bloat accelerating deletions increasing by " + deletion_increase + "% vs last audit") + + # Unverified configs growing? + if last_audit_entry.unverified > 0: + unverified_increase = count_entries(memory_content, "[UNVERIFIED]") - last_audit_entry.unverified + if unverified_increase > 2: + drift_alerts.append("ALERT: Unverified configs growing " + unverified_increase + " new unverified entries since last audit") + + # Audit missed? (No audit for >21 days) + if last_audit_entry.timestamp > 21 days: + drift_alerts.append("ALERT: Audit gap no audit completed in 21+ days") + + # Utilization not improving? (After audit, still >70%) + if last_audit_entry.memory_util_after > 70: + drift_alerts.append("ALERT: Previous audit failed to reduce MEMORY.md below 70% capacity issue") + # ============================================================ # PHASE 2: Categorize every entry # ============================================================ @@ -140,7 +203,7 @@ for item in categorized: # ============================================================ if dry_run: - return {status: "DRY_RUN", actions: actions, summary: generate_summary(actions)} + return {status: "DRY_RUN", actions: actions, drift_alerts: drift_alerts, summary: generate_summary(actions)} # Apply deletions for action in actions: @@ -180,12 +243,39 @@ new_user_content = read_file("~/.hermes/memories/USER.md") new_memory_util = len(new_memory_content) / max_memory_chars * 100 new_user_util = len(new_user_content) / max_user_chars * 100 +# Verify canaries survived the audit +post_canary_check = read_file_line("~/.hermes/memories/MEMORY.md", containing="CANARY: Do not modify this line") +if post_canary_check is null: + drift_alerts.append("CRITICAL: Canary destroyed during audit memory integrity compromised") + # Add summary markers to in-memory stores memory action=add target=memory content="MEMORY.md rewritten. Utilization: " + new_memory_util + "%." memory action=add target=user content="USER.md rewritten. Utilization: " + new_user_util + "%." # ============================================================ -# PHASE 7: Report +# PHASE 7: Append to Ledger +# ============================================================ + +ledger_entry = """ +## """ + now() + """ +- memory_util_before: """ + memory_util + """% +- memory_util_after: """ + new_memory_util + """% +- user_util_before: """ + user_util + """% +- user_util_after: """ + new_user_util + """% +- deletions: """ + count(actions, "DELETE") + """ +- moves: """ + count(actions, "MOVE") + """ +- corrections: """ + count(actions, "CORRECT") + """ +- unverified: """ + count(actions, "MARK_UNVERIFIED") + """ +- unresolved: """ + len(unresolved_entries) + """ +- drift_alerts: """ + len(drift_alerts) + """ +- canary_intact: """ + (post_canary_check is not null) + """ +- status: COMPLETE +""" + +append_file path="~/.hermes/memories/MEMORY_AUDIT_LEDGER.md" content=ledger_entry + +# ============================================================ +# PHASE 8: Report # ============================================================ return { @@ -198,14 +288,16 @@ return { corrections: count(actions, "CORRECT"), unverified: count(actions, "MARK_UNVERIFIED"), unresolved: unresolved_entries, + drift_alerts: drift_alerts, last_audit: now(), + ledger_updated: true, summary: generate_summary(actions) } ``` ### Shape -- `self`: categorize, verify configs, apply incremental patches, generate reports +- `self`: categorize, verify configs, apply incremental patches, generate reports, drift detection, ledger management, canary checks - `delegates`: - `categorize_entry`: determine the category of a memory entry - `check_memory_tool`: verify the memory tool is functional @@ -227,4 +319,5 @@ return { - `MEMORY_PATH`: ~/.hermes/memories/MEMORY.md - `USER_PATH`: ~/.hermes/memories/USER.md -- `CONFIG_PATH`: ~/.hermes/config.yaml \ No newline at end of file +- `CONFIG_PATH`: ~/.hermes/config.yaml +- `LEDGER_PATH`: ~/.hermes/memories/MEMORY_AUDIT_LEDGER.md \ No newline at end of file