v3: Add ledger, drift detection, canary checks, per-agent privacy, writer registry
This commit is contained in:
@@ -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
|
||||
- `CONFIG_PATH`: ~/.hermes/config.yaml
|
||||
- `LEDGER_PATH`: ~/.hermes/memories/MEMORY_AUDIT_LEDGER.md
|
||||
Reference in New Issue
Block a user