harn-stdlib 0.10.129

Embedded Harn standard library source catalog
Documentation
// std/agent/pattern_knowledge_matching.harn
//
// Ranking boundary for cross-session pattern learning. This module owns the
// vocabulary a task and a learned skill are reduced to, and the score that
// decides whether a learned skill is served for a task. `pattern_knowledge`
// retains the lifecycle around it: capture, curation, review, and the public
// entry points that call in here.
const STOP_WORDS = [
  "about",
  "after",
  "again",
  "all",
  "and",
  "any",
  "are",
  "can",
  "could",
  "for",
  "from",
  "has",
  "have",
  "how",
  "into",
  "just",
  "make",
  "more",
  "not",
  "now",
  "off",
  "the",
  "this",
  "that",
  "then",
  "there",
  "these",
  "those",
  "through",
  "use",
  "using",
  "was",
  "what",
  "when",
  "where",
  "with",
  "would",
  "you",
  "your",
]

pub fn pl_normalize_words(text: string) -> list {
  const cleaned = regex_replace(r"[^a-z0-9]+", " ", (text ?? "").lower()) ?? ""
  return cleaned.split(" ").filter({ word -> word != "" }).to_list()
}

pub fn pl_significant_words(text: string) -> list {
  let seen = []
  let out = []
  for word in pl_normalize_words(text) {
    if len(word) < 3 || STOP_WORDS.contains(word) || seen.contains(word) {
      continue
    }
    seen = seen + [word]
    out = out + [word]
  }
  return out
}

pub fn pl_normalized_domain_words(value: any) -> list {
  let seen = []
  let out = []
  if type_of(value) != "list" {
    return out
  }
  for entry in value {
    const word = to_string(entry ?? "").trim().lower()
    if word && !seen.contains(word) {
      seen = seen + [word]
      out = out + [word]
    }
  }
  return out
}

/**
 * Score one learned skill against a query's significant words.
 *
 * `task_domain_words` is the host's own task-signal, not a second opinion
 * computed here: the host's own task-intent or language matcher already
 * decided what this task is genuinely about, and passes those terms
 * through unchanged. When it is non-empty, a lexical hit only counts if the
 * matched word is also one the host flagged as a real domain term, not an
 * incidental overlap on a word this module's own stopword list happens not
 * to cover (a repository-meta learned skill sharing generic words like
 * "file" or "new" with an unrelated task, for one measured example). When
 * it is empty -- the host found no task domain to name -- scoring is
 * unchanged from before this field existed: any nonzero lexical overlap
 * counts. This narrows only on positive host signal; it never turns a match
 * back on that today's overlap check would have rejected.
 *
 * @effects: []
 * @errors: []
 * @api_stability: internal
 */
pub fn pl_score_skill(skill_entry: dict, query_words: list, task_domain_words: list = []) -> dict {
  if len(query_words) == 0 {
    return {learned_skill: skill_entry, score: 0.0, reason: "project learned skill"}
  }
  const haystack = join(
    [skill_entry.name, skill_entry.description, skill_entry.when_to_use, skill_entry.body],
    " ",
  )
  const skill_words = pl_significant_words(haystack)
  let overlap = []
  for word in query_words {
    if skill_words.contains(word) && !overlap.contains(word) {
      overlap = overlap + [word]
    }
  }
  if len(overlap) == 0 {
    return {}
  }
  if len(task_domain_words) > 0 {
    let domain_overlap = []
    for word in overlap {
      if task_domain_words.contains(word) {
        domain_overlap = domain_overlap + [word]
      }
    }
    if len(domain_overlap) == 0 {
      return {}
    }
  }
  return {
    learned_skill: skill_entry,
    score: (len(overlap) + 0.0) / (max(1, len(query_words)) + 0.0),
    reason: "matched " + join(overlap.sorted()[0:min(4, len(overlap))], ", "),
  }
}

pub fn pl_insert_match(matches: list, item: dict) -> list {
  if item?.learned_skill == nil {
    return matches
  }
  let out = []
  let inserted = false
  for existing in matches {
    const before = item.score > existing.score
      || (item.score == existing.score
        && item.learned_skill.name
          < existing.learned_skill.name)
    if before && !inserted {
      out = out + [item]
      inserted = true
    }
    out = out + [existing]
  }
  if !inserted {
    out = out + [item]
  }
  return out
}