osint-investigation

Follow the money via public records and sanctions data.

  • osint
  • investigation
  • public-records
  • sec
  • sanctions
  • corporate-registry
  • property
  • courts
  • due-diligence
  • journalism

Declared platforms: linux · macos · windows

Install
npx skills add 'https://github.com/NousResearch/hermes-agent/tree/main/optional-skills/research/osint-investigation'
Download bundle ↓
main · 24fd22bScanned 2026-09-15

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗
View on GitHub
← Back to SKILL.md
"""Shared entity-name normalization helpers (stdlib-only). Used by entity_resolution.py and timing_analysis.py."""from __future__ import annotations import re # Legal suffixes / corporate boilerplate to strip during normalization._SUFFIX_TOKENS = {    "INC", "INCORPORATED", "LLC", "LLP", "LP", "LTD", "LIMITED",    "CORP", "CORPORATION", "CO", "COMPANY",    "GROUP", "GRP", "HOLDINGS", "HOLDING",    "PARTNERS", "ASSOCIATES",    "INTERNATIONAL", "INTL",    "ENTERPRISES", "ENTERPRISE",    "SERVICES", "SERVICE", "SVCS",    "SOLUTIONS", "MANAGEMENT", "MGMT", "CONSULTING",    "TECHNOLOGY", "TECHNOLOGIES", "TECH",    "INDUSTRIES", "INDUSTRY",    "AMERICA", "AMERICAN",    "USA", "US",    "PLLC", "PC",    "TRUST", "FOUNDATION",} _PUNCT_RE = re.compile(r"[^\w\s]")_WS_RE = re.compile(r"\s+")  def normalize_name(name: str | None) -> str:    """Standard normalization: uppercase, strip suffixes, drop punctuation."""    if not name:        return ""    s = _PUNCT_RE.sub(" ", name.upper())    s = _WS_RE.sub(" ", s).strip()    tokens = [t for t in s.split() if t and t not in _SUFFIX_TOKENS]    return " ".join(tokens)  def normalize_aggressive(name: str | None) -> str:    """Aggressive normalization: sorted unique tokens (word-bag)."""    base = normalize_name(name)    if not base:        return ""    return " ".join(sorted(set(base.split())))  def name_tokens(name: str | None, min_len: int = 4) -> set[str]:    """Token set used for overlap matching."""    base = normalize_name(name)    if not base:        return set()    return {t for t in base.split() if len(t) >= min_len}  def token_overlap_ratio(left: str | None, right: str | None) -> tuple[float, int]:    """Return (jaccard-like ratio, shared token count) over min-len tokens."""    a = name_tokens(left)    b = name_tokens(right)    if not a or not b:        return 0.0, 0    shared = a & b    if not shared:        return 0.0, 0    union = a | b    return len(shared) / len(union), len(shared)