Skip to content

feat: Rule subtype for permanent preferences (no decay/prune)#37

Merged
stevepridemore merged 1 commit into
mainfrom
feat/rule-subtype
May 17, 2026
Merged

feat: Rule subtype for permanent preferences (no decay/prune)#37
stevepridemore merged 1 commit into
mainfrom
feat/rule-subtype

Conversation

@stevepridemore
Copy link
Copy Markdown
Owner

Summary

  • Adds subtype: 'rule' semantic on Preference (or any) nodes for permanent constraints — "never X" / "always Y" with no expected sunset
  • Rule-subtype nodes and their anchor edges are exempt from decay and pruning
  • Schema docs (project) + extractor prompts updated so future captures recognize hard rules

Why

Some user preferences are genuinely permanent constraints, not soft preferences that should fade with time. Letting decay erode them is wrong — never-edit-domino-odp-files has been silently approaching the prune threshold for weeks. A first-class "Rule" semantic keeps these pinned without requiring custom handling everywhere.

What changed

src/shared/neo4j-client.ts — Five Cypher filters added:

  • applyDecay node loop: skip subtype = 'rule' nodes per type
  • applyDecay edge loop: skip edges where either endpoint is a rule (so PREFERS anchor doesn't decay)
  • applyDecay flagged-for-pruning count: skip rules
  • prune low-confidence node query: skip rules (defense-in-depth)
  • prune orphan query: skip rules (stranded rule → reconnect, not delete)
  • prune edge query: skip edges with rule endpoints

GRAPH_SCHEMA.md — Preference row updated to document the rule subtype semantics.

prompts/dream-nightly.md + prompts/graph-capture.md — Extractor guidance: hard "never/always" statements → Preference with subtype: 'rule', confidence: 1.0, PREFERS weight 1.0.

Backward compatibility

All existing nodes have subtype = null. The new filters are no-ops for them. No data migration required at deploy time. Other tenants (Jodi) unaffected.

Already deployed + validated

Built, deployed via docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --force-recreate graph-memory-mcp, healthcheck green. Three Preferences promoted to Rule subtype on the steve tenant for validation:

  • never-edit-domino-odp-files (also merged never-edit-odp-directly into it)
  • no-em-dashes (also merged preference-no-em-dashes-in-any-strings into it)
  • no-python

All three now sit at confidence: 1.0, subtype: 'rule', PREFERS weight 1.0. Pre-migration backup at backup-2026-05-17T18-35-41-pre-rule-subtype-migration.jsonl.

Test plan

  • npm run build succeeds (TypeScript check)
  • After merge + deploy, graph_stats returns healthy (no errors)
  • Next nightly dream pass should NOT decay confidence on the 3 rule nodes — verify via graph_cypher MATCH (n:Preference {subtype:'rule'}) RETURN n.id, n.confidence
  • graph_prune --dry-run should NOT list any rule nodes even after weeks of inactivity

🤖 Generated with Claude Code

Adds a `subtype: 'rule'` semantic on Preference (and any) nodes for
permanent constraints — "never X" / "always Y" with no expected sunset.

Rule-subtype nodes are exempt from:
- Time-based decay (both node confidence and edges touching them)
- Low-confidence pruning (defense-in-depth; rules sit at 1.0 anyway)
- Orphan pruning (a stranded rule should be reconnected, not deleted)
- Edge-weight pruning when either endpoint is a rule

The rule's anchor edge (typically Person -[PREFERS]-> Rule) is held at
weight 1.0 and exempt from edge decay so the rule never drifts loose.

Schema docs (project + universal) updated to describe the subtype.
Extractor prompts (dream + graph-capture) updated to recognize hard
"never/always" statements and emit them as Rules rather than Preferences.

Backward-compatible: all existing nodes have subtype=null and are
unaffected by the new filters.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@stevepridemore stevepridemore merged commit fabdea0 into main May 17, 2026
2 checks passed
@stevepridemore stevepridemore deleted the feat/rule-subtype branch May 17, 2026 19:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant