Class: ClaudeMemory::Resolve::PredicatePolicy

Inherits:
Object
  • Object
show all
Defined in:
lib/claude_memory/resolve/predicate_policy.rb

Constant Summary collapse

POLICIES =

Canonical predicate vocabulary. Curated after a multi-project survey of real memory databases under ~/src — predicates with zero facts across every database were pruned; predicates observed in the wild but missing from the policy (architecture, uses_language) were added.

  • convention / decision: workhorse multi-value predicates

  • uses_framework / uses_language: multi-value (projects use multiple)

  • uses_database / deployment_platform / auth_method: single-value, correctly 1:1 per project in observed data

  • architecture: multi-value structural knowledge (was implicit)

{
  "convention" => {cardinality: :multi, exclusive: false},
  "decision" => {cardinality: :multi, exclusive: false},
  "architecture" => {cardinality: :multi, exclusive: false},
  "reference" => {cardinality: :multi, exclusive: false},
  "uses_framework" => {cardinality: :multi, exclusive: false},
  "uses_language" => {cardinality: :multi, exclusive: false},
  "uses_database" => {cardinality: :single, exclusive: true},
  "deployment_platform" => {cardinality: :single, exclusive: true},
  "auth_method" => {cardinality: :single, exclusive: true}
}.freeze
DEFAULT_POLICY =
{cardinality: :multi, exclusive: false}.freeze
SYNONYMS =

Drift canonicalization. Maps predicate names the distiller has organically coined onto the canonical form in POLICIES. Consulted at insert time by the Resolver so synonym drift never fragments the knowledge graph.

Entries observed in real project DBs:

  • has_convention (chaos_to_the_rescue): prefix-drift of convention

  • primary_language (prior policy entry): supplanted by uses_language which the distiller emits naturally and has multi-value semantics

{
  "has_convention" => "convention",
  "primary_language" => "uses_language"
}.freeze
SECTION_MAP =

Section classification for the published snapshot. Keeps Publish from hard-coding predicate names; adding a new predicate to the policy and the section map in one place updates everything.

{
  "decision" => :decisions,
  "convention" => :conventions,
  "reference" => :references,
  "uses_database" => :constraints,
  "uses_framework" => :constraints,
  "uses_language" => :constraints,
  "deployment_platform" => :constraints,
  "auth_method" => :constraints
  # architecture intentionally falls through to :additional for now
}.freeze

Class Method Summary collapse

Class Method Details

.canonicalize(predicate) ⇒ Object

Return the canonical form of a predicate name, applying known synonym mappings. Leaves unmapped predicates unchanged.



65
66
67
68
# File 'lib/claude_memory/resolve/predicate_policy.rb', line 65

def self.canonicalize(predicate)
  return predicate if predicate.nil?
  SYNONYMS.fetch(predicate, predicate)
end

.exclusive?(predicate) ⇒ Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/claude_memory/resolve/predicate_policy.rb', line 87

def self.exclusive?(predicate)
  policy_for(predicate)[:exclusive]
end

.known_predicatesObject



59
60
61
# File 'lib/claude_memory/resolve/predicate_policy.rb', line 59

def self.known_predicates
  POLICIES.keys
end

.policy_for(predicate) ⇒ Object



79
80
81
# File 'lib/claude_memory/resolve/predicate_policy.rb', line 79

def self.policy_for(predicate)
  POLICIES.fetch(predicate, DEFAULT_POLICY)
end

.section_for(predicate) ⇒ Object

Return the snapshot section a predicate belongs to. Respects legacy prefix/suffix patterns (decided_*, *_convention) that pre-date the policy.



73
74
75
76
77
# File 'lib/claude_memory/resolve/predicate_policy.rb', line 73

def self.section_for(predicate)
  return :decisions if predicate&.start_with?("decided_")
  return :conventions if predicate&.include?("_convention")
  SECTION_MAP.fetch(predicate, :additional)
end

.single?(predicate) ⇒ Boolean

Returns:

  • (Boolean)


83
84
85
# File 'lib/claude_memory/resolve/predicate_policy.rb', line 83

def self.single?(predicate)
  policy_for(predicate)[:cardinality] == :single
end