astral-tenant-kb

/home/avalon/.hermes/skills/astrology/astral-tenant-kb/SKILL.md · raw

Astral Tenant KB

Per-user astrology memory store. Separate from source wikis (astro-sources-wiki, wiki-human-design) which are interpretive content shared across users.

Root

Default: ~/.hermes/astral-kb-prototype/knowledge/ Override via env: ASTRAL_KB_ROOT (used when running inside an Astral Hermes tenant).

Layout

knowledge/
├── entities/
│   ├── people/<slug>.md          ← person profile w/ birth frontmatter
│   ├── places/  trips/  events/
├── charts/<slug>-<hash>.json     ← computed chart cache (hashed by birth data)
├── readings/<yyyy-mm-dd>-<slug>-<combo>.md
├── transits/
│   ├── global/<range>.json
│   ├── profiles/<slug>-<range>.json
│   └── calendars/<slug>-<range>.ics
├── raw/                          ← long-form reports, source PDFs (S3-mirrored)
├── _meta/manifest.json
├── index.md  log.md  SCHEMA.md

Person profile frontmatter

---
slug: alex-mataha                    # canonical slug — globally unique within this KB
aliases: [alex, MaTaHa]              # ambiguous nicknames the user might say
name: Alex MaTaHa
relationship: self                   # self | client | family | friend | partner | public-figure
disambiguation: |
  Free-text note distinguishing this person from others with similar names.
birth:
  date: 1985-09-26
  time: 07:14
  location: London, UK
  utc: 1985-09-26T06:14:00Z
  coordinates: "51.5072178 -0.1275862"
  tz: Europe/London
notes: professional astrologer; prefers traditional rulerships
---

Disambiguation policy (CRITICAL — prevents identity collisions)

The compose layer must use this resolution order when a user mentions a person:

  1. Exact slug match: slug: <input> — unambiguous, use directly.
  2. Exact name match: case-insensitive name == input — single hit → use; multiple hits → DISAMBIGUATE.
  3. Alias match: <input> appears in any person's aliases: list — single hit → use; multiple hits → DISAMBIGUATE.
  4. Fuzzy match (first-name only or partial): collect all matches → if more than one, DISAMBIGUATE.
  5. No match: confirm with the user this is a new person, propose a slug (e.g. alex-mataha, alex-durran), then save_person.

DISAMBIGUATE means: - Show the user all candidates with birth-data summary (date + city) — one line each. - Ask "which one?" with the option "none of these — this is a new person." - Never silently pick the most-recent or alphabetical-first match.

Never reuse a slug that already exists for a different person. If the user says "do a chart for Alex" and the KB has both alex-mataha and alex-durran, the assistant must ask which Alex before computing.

Reading frontmatter (required for A/B testing)

---
person: alex
date: 2026-05-22T19:45-07:00
chart_hash: <sha1-of-birth-data>
lenses: [rulership-chains, decans-36-faces]
sources_cited:
  - astro-sources-wiki:concepts/libra-i
  - astro-sources-wiki:concepts/decans
prompt: "what does my Saturn return look like"
---

Helpers (call via terminal/python)

Conceptually:

Implementation: plain Python with pathlib + pyyaml frontmatter. No daemon, no DB.

Required workflow when used by a reading skill

Self vs other comes first. The compose layer must decide whether the reading is for the user (self) or someone else BEFORE calling this skill. See astrology-reading-compose "Self vs other" section.

For self: 1. Read identity + birth data from Hermes built-in memory (USER.md) — it's already in context. 2. Look up the KB profile whose frontmatter has relationship: self. If found, use it. If not, bootstrap one from memory's identity via save_person(..., relationship='self'). 3. Cross-check: if Hermes memory's birth data differs from the self profile's birth data, surface the discrepancy. Never silently pick.

For other: 1. Apply the disambiguation policy (slug → exact name → alias → fuzzy → no match) — see "Disambiguation policy" above. 2. After resolving identity, recall the profile via recall_person(slug).

Then (both paths): 3. Compute or load: chart_hash; if load_chart returns null, compute via astral-chart-api then save_chart. 4. Read sources: query astro-sources-wiki (or HD wiki) via llm-wiki for the relevant pages. 5. Save reading: after the response is written, call save_reading with lens combo + citations. 6. Append to log.md with one-line summary.

What goes in Hermes memory vs. this KB

Hermes built-in memory (USER.md, MEMORY.md): - User's identity (name, aliases, timezone, contact) - User's birth data summary (the canonical source — it's always in context) - Stable preferences (astrology style, lens defaults, "no folk language", etc.) - ONE pointer to the KB self-profile path and the disambiguation contract reference - NEVER: chart JSON, reading prose, other people's profiles, transit windows

This tenant KB: - The self profile (relationship: self) — sourced FROM Hermes memory, kept in sync - All other people's profiles - All chart JSON - All saved readings (with lens-combo frontmatter) - All transit windows - Raw source uploads

Hard rules

Verification

After any save: - entities/people/<slug>.md exists - charts/<slug>-<hash>.json exists - latest readings/*.md has correct lenses: list + ≥1 citation when sources were used

References