Rewrite memory-fixer to v3 semantics: when Kwame replies to an escalation, execute the action fully - set state (archived/active), clear or rename the [REVIEW:] tag, and bump updated_at so the node exits the stale window and is not re-flagged on the next run. Bump version 1.1.0 -> 2.0.0.
8.3 KiB
kind, name, description, version
| kind | name | description | version |
|---|---|---|---|
| pattern | memory-fixer | Auto-fix low-hanging fruit in the RA-H OS knowledge graph. No judgment calls — only deterministic Level 1 operations. Escalate anything that needs Kwame's input. Executes confirmed Kwame decisions to completion (state + updated_at). | 2.0.0 |
Memory Fixer
Canonical copy:
/root/.hermes/contracts/memory-fixer-v3.md(used by thememory-fixer-dailycron job). This file is the institutional record of the same contract. When the two diverge, treat the v3 source in/root/.hermes/contracts/as executable truth.
Purpose
Auto-fix low-hanging fruit in the graph. No judgment calls — only deterministic Level 1 operations. Escalate anything that needs Kwame's input. When Kwame replies to an escalation, execute the decision to completion (update state and timestamps), never leaving a node in review-pending forever.
Type: Write-only (Level 1 fixes only) Scope: RA-H OS knowledge graph (192.168.68.65) Schedule: Daily at 8 AM ET Escalation: Level 2+ to Kwame as task items
Key Design Decision
The updateNode tool's metadata field performs a restricted merge — the state key only accepts 'processed' or 'not_processed'. Additionally, new metadata keys cannot be added via the merge.
Solution: Use the description field to tag stale nodes with review actions, since description is a simple string overwritable via updateNode.
Tag Format: [REVIEW: action] original description text...
Where action is one of:
archive— node is stale and should be archivedrefresh— node is stale and should be refreshed (infrastructure)keep— node has been confirmed as currentmerge— node is a duplicate candidate
Query for finding review-tagged nodes:
SELECT id, title, description
FROM nodes
WHERE description LIKE '[REVIEW:%';
Level 1 Auto-Fixes (No Kwame Decision Needed)
1. Missing type Auto-Classification
SELECT id, title,
CASE
WHEN title LIKE '%infrastructure%' OR title LIKE '%proxmox%' OR title LIKE '%setup%' THEN 'infrastructure'
WHEN title LIKE '%skill%' OR title LIKE '%how to%' OR title LIKE '%guide%' THEN 'skill'
WHEN title LIKE '%doc%' OR title LIKE '%template%' OR title LIKE '%brand%' THEN 'documentation'
WHEN title LIKE 'WAL:%' OR title LIKE 'TASK:%' THEN 'note'
WHEN title LIKE '%[LEARN]%' THEN 'documentation'
ELSE 'note'
END as auto_type
FROM nodes
WHERE json_extract(metadata, '$.type') IS NULL;
2. Missing namespace Auto-Population
SELECT id, title, json_extract(metadata, '$.tenant') as tenant
FROM nodes
WHERE json_extract(metadata, '$.namespace') IS NULL;
3. Staleness Review Tagging
Using the type-based windows from the memory-monitor contract, tag nodes stale beyond their window. Only process a maximum of 10 nodes per run to avoid overwhelming Kwame. Prioritize infrastructure first, then dynamic, then ephemeral.
Exclusion Rules:
- Nodes with
state=review_pending,deprecated,archived, ornot_processedare NOT processed - Nodes whose
descriptionalready starts with[REVIEW:are NOT re-processed
SELECT id, title, json_extract(metadata, '$.type') as node_type,
CAST(julianday('now') - julianday(updated_at) AS INTEGER) as days_stale,
CASE
WHEN json_extract(metadata, '$.type') IN ('infrastructure', 'deployment', 'system', 'system-health') THEN 'refresh'
WHEN json_extract(metadata, '$.type') IN ('business', 'philosophy', 'research', 'learning', 'learn', 'investigation', 'analysis', 'project') THEN 'refresh'
ELSE 'archive'
END as suggested_action
FROM nodes
WHERE updated_at < datetime('now',
CASE
WHEN json_extract(metadata, '$.type') IN ('infrastructure', 'deployment', 'system', 'system-health') THEN '-14 days'
WHEN json_extract(metadata, '$.type') IN ('skill', 'documentation', 'template', 'protocol-enforcement', 'prd', 'architecture') THEN '-90 days'
WHEN json_extract(metadata, '$.type') IN ('note', 'wal', 'WAL', 'task', 'TASK', 'event') THEN '-30 days'
WHEN json_extract(metadata, '$.type') IN ('business', 'philosophy', 'research', 'learning', 'learn', 'investigation', 'analysis', 'project') THEN '-120 days'
WHEN json_extract(metadata, '$.type') IN ('deprecated-relay', 'audit', 'audit-report', 'incident', 'incident-report') THEN '-3650 days'
ELSE '-45 days'
END
)
AND json_extract(metadata, '$.state') NOT IN ('review_pending', 'deprecated', 'archived', 'not_processed')
AND (description IS NULL OR description NOT LIKE '[REVIEW:%')
ORDER BY days_stale ASC
LIMIT 10;
For each identified node, call updateNode(id, { description: "[REVIEW: action] " + originalDescription }).
Level 2 Escalations (Kwame Decision Required)
- Stale nodes flagged with
[REVIEW: …]— Archive, refresh, or keep? - Duplicate Nodes (same title or >70% title overlap) — Merge or keep?
- Orphan Nodes >90 days old — Archive or connect?
Reporting Format
The fixer reports to Kwame via this Zulip DM:
🦅 Memory Fixer — [HH:MM UTC]
Level 1 fixes applied:
- Missing type: X nodes classified
- Missing namespace: Y nodes populated
Stale nodes needing review (max 10):
1. [Node #XXX] Title — X days stale, SUGGEST: refresh
2. [Node #YYY] Title — Y days stale, SUGGEST: archive
...
Duplicates needing decision:
1. [Node #AAA] vs [Node #BBB] — Same title
Orphans >90 days:
1. [Node #EEE] Title — X days stale, orphaned
Reply with:
- "archive #XXX, #YYY" to mark for archive
- "archive all" to archive all stale nodes listed
- "keep #XXX" to confirm a node is current
- "merge #AAA into #BBB" to merge duplicates
- "refresh #XXX" to mark as current
Execution on Next Run
The fixer reads Kwame's previous response and executes the decision to completion — it must not leave a node in review-pending forever. Tagging alone is NOT enough; each confirmed decision must also update state and updated_at so the node drops out of the stale window on the next run.
⚠️
updateNodecannot setstateto non-standard values (restricted toprocessed/not_processed) and cannot add metadata keys. For state transitions andupdated_atbumps, use direct SSH + SQLite on the bridge host:ssh root@192.168.68.65 "sqlite3 /root/.local/share/RA-H/db/rah.sqlite \"UPDATE nodes SET metadata = json_set(metadata, '$.state', '<state>'), updated_at = datetime('now') WHERE id = <id>;\""Use
updateNodeonly for description/source/title/link edits.
Decision → completed action mapping:
| Kwame reply | Description change | State | updated_at |
|---|---|---|---|
archive #XXX |
replace [REVIEW: archive] → [ARCHIVED] prefix |
archived |
bumped to now |
keep #XXX / refresh #XXX |
clear the [REVIEW: …] tag entirely |
active |
bumped to now |
merge #AAA into #BBB |
set [REVIEW: merge_into #BBB] on #AAA, then follow manual merge workflow |
handled manually | bumped to now |
archive all |
apply the archive row to every node listed in the prior report | archived |
bumped to now |
Why updated_at must be bumped (critical): the Level-1 staleness query keys off updated_at < now - window. If the fixer clears the tag but leaves a stale updated_at, the node is immediately re-flagged on the very next run and the cycle repeats forever. Bumping updated_at to now pushes the node back to the front of the window.
Exclusion after action: once an action is applied, the node's description no longer starts with [REVIEW: (archive → [ARCHIVED], refresh/keep → original text), so it is not re-processed.
After all actions are applied, verify with:
SELECT id, json_extract(metadata, '$.state') FROM nodes WHERE description LIKE '[REVIEW:%';
The result must be 0 rows when all decisions are executed. Report what was done.
Checks
- State integrity: archived nodes have
state: archived+[ARCHIVED]prefix; kept nodes arestate: activewithout a[REVIEW:]tag. - No review-pending forever: after executing Kwame's decisions,
[REVIEW:%node count must be 0. - Timestamps: every executed decision bumps
updated_at, so the node exits the stale window on the next run.
Logging
Every Level 1 fix logged to ~/.hermes/logs/memory-fixer/YYYY-MM-DD.md
Every Level 2 escalation logged and delivered to Kwame.