WIP Phase 4 ingestion: platform guides, exclusion gate, gitea/vault/graph harvest, payload provenance
This commit is contained in:
94
corpus/areas.py
Normal file
94
corpus/areas.py
Normal file
@@ -0,0 +1,94 @@
|
||||
"""Which resume area a harvested document feeds.
|
||||
|
||||
The payload `area` is what lets the query path filter *before* it searches, so a
|
||||
harvested file has to be classified once, deterministically, and never promoted
|
||||
to make a page read better.
|
||||
|
||||
The classification is keyword evidence, in this order: the path, the repository
|
||||
name, the description and topics, then the languages. The result is constrained
|
||||
to the platform guide's `fits` list: a platform cannot feed an area it does not
|
||||
declare. When nothing matches, the first `fits` entry wins, which is why every
|
||||
guide lists its strongest area first.
|
||||
|
||||
This is a heuristic and it is labelled as one. It is not a claim about Sam's
|
||||
career; the curated `content/` tree carries the claims.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
from .payloads import AREAS
|
||||
|
||||
# Order matters: the first area with a hit wins, so the more specific evidence
|
||||
# (an ESP32 repository is edge, not platform) is checked before the general.
|
||||
_RULES = (
|
||||
("edge", (
|
||||
"esp32", "esp8266", "arduino", "lora", "lorawan", "mqtt", "sensor",
|
||||
"zigbee", "z-wave", "relay", "gpio", "pir", "modbus", "iot",
|
||||
"firmware", "breadboard", "raspberry pi", "rpi", "camera", "cam",
|
||||
"temperature", "watering", "fish feeder", "driveway", "light",
|
||||
"snapcast", "mopidy", "audio", "voice bridge",
|
||||
)),
|
||||
("ai", (
|
||||
"ai", "llm", "agent", "agentic", "rag", "embedding", "vector",
|
||||
"model", "ml", "prompt", "graphify", "omniroute", "paperclip",
|
||||
"langgraph", "prefect", "whisper", "piper", "chat", "memory",
|
||||
"knowledge graph", "vision", "triage",
|
||||
)),
|
||||
("platform", (
|
||||
"nixos", "nix", "docker", "compose", "kubernetes", "k8s", "deploy",
|
||||
"deployment", "backup", "borg", "kopia", "restic", "network", "dns",
|
||||
"email", "caddy", "proxmox", "postgres", "terraform", "ansible",
|
||||
"linux", "systemd", "homelab", "server", "infrastructure", "git",
|
||||
"gitea", "monitor", "logging", "security", "firewall", "vpn",
|
||||
"tailscale", "storage", "garage", "s3",
|
||||
)),
|
||||
("products", (
|
||||
"product", "app", "web", "dashboard", "react", "laravel", "flutter",
|
||||
"kotlin", "calendar", "photo", "kontra", "store", "resume", "site",
|
||||
"gps", "tracker", "api", "frontend", "ui", "ux",
|
||||
)),
|
||||
("history", (
|
||||
"history", "agency", "client", "archive", "old", "legacy", "2019",
|
||||
"2018", "2020", "2021", "career", "resume copy",
|
||||
)),
|
||||
("about", ("about", "profile", "bio", "personal", "cv")),
|
||||
)
|
||||
|
||||
_WORD_SPLIT = re.compile(r"[^0-9a-z]+")
|
||||
|
||||
|
||||
def area_for(evidence: str, fits, fallback: str = None) -> str:
|
||||
"""Classify one document from its path, name, description and topics."""
|
||||
haystack = " " + _WORD_SPLIT.sub(" ", (evidence or "").lower()) + " "
|
||||
allowed = [area for area in (fits or AREAS) if area in AREAS]
|
||||
if not allowed:
|
||||
allowed = list(AREAS)
|
||||
for area, needles in _RULES:
|
||||
if area not in allowed:
|
||||
continue
|
||||
for needle in needles:
|
||||
if f" {needle} " in haystack or f" {needle}s " in haystack:
|
||||
return area
|
||||
if fallback in allowed:
|
||||
return fallback
|
||||
return allowed[0]
|
||||
|
||||
|
||||
def area_for_repo(repo: dict, fits) -> str:
|
||||
topics = " ".join(repo.get("topics") or [])
|
||||
evidence = " ".join(
|
||||
str(part)
|
||||
for part in (
|
||||
repo.get("full_name", ""),
|
||||
repo.get("name", ""),
|
||||
repo.get("description", ""),
|
||||
topics,
|
||||
)
|
||||
)
|
||||
return area_for(evidence, fits, fallback=(fits or [None])[0])
|
||||
|
||||
|
||||
def area_for_note(path: str, fits) -> str:
|
||||
return area_for(path, fits, fallback=(fits or [None])[0])
|
||||
Reference in New Issue
Block a user