--- name: astral-transit-calendar description: Use when Alex asks Hermes to retrieve current/global transits, compare transits to Alex's natal chart, generate transit calendars, or sync astrology transit events to Apple/Google Calendar. version: 1.0.0 author: Hermes Agent + Alex license: MIT metadata: hermes: tags: [astrology, transits, calendar, ics, apple-calendar, google-calendar, transit-list-demo] related_skills: [astral-chart-api, astrology-location-time-utc, astrology-lens-rulership-chains, astrology-reading-compose, astral-tenant-kb] --- # Astral Transit Calendar ## Overview This skill is the local Hermes workflow for turning Alex's `transit-list-demo` code into reusable transit context and calendar feeds. It supports two complementary use cases: 1. **Global transits** — exact planetary aspects/ingresses in the sky, independent of a natal chart. 2. **Alex transits** — exact transiting aspects to Alex's natal planetary positions. The canonical local store is: ```text ~/.hermes/astral-transits/ ├── astral-transits.js # generator script ├── profiles/alex.json # Alex profile/natal UTC metadata ├── events/*.json # structured events for Hermes context/RAG ├── calendars/*.ics # Apple/Google import/subscription files └── reports/*.md # mobile-readable summaries ``` ## When to Use Use this skill when Alex asks for: - current transits / “what are the transits now?” - global transits for a date range - transits to Alex's chart - rest-of-year or monthly transit calendars - an `.ics` feed for Apple Calendar or Google Calendar - a structured transit dataset Hermes can reference later Do **not** invent transit times. Use `transit-list-demo` via the generator or API. ## Source Service / Code Local code: ```text /home/avalon/apps/transit-list-demo ``` Public API: ```text https://transit-list-demo.apps.poofc.com ``` Useful existing API endpoints: ```text GET /api/health GET /api/transits/current GET /api/time/resolve?date=YYYY-MM-DD&time=HH:mm[:ss]&location=LOCATION GET /api/chart?date=YYYY-MM-DD&time=HH:mm[:ss]&location=LOCATION GET /api/chart?utc=day/month/year/hour/minute/second&coordinates=LAT%20LON ``` Important implementation finding: `server.js` currently exposes current/chart endpoints, but not a dedicated HTTP scan endpoint for date-range transit calendars. Date-range scanning exists in the CLI / `Program.scan(start, stop, natal)` path. Use the local generator for calendars until a `/api/transits/scan` endpoint is added. ## Alex Profile Confirmed Alex profile file: ```text ~/.hermes/astral-transits/profiles/alex.json ``` Confirmed birth data: ```text Date: 1985-09-26 Local time: 07:14:00 Location: London, UK Timezone: Europe/London UTC: 1985-09-26T06:14:00.000Z transit-list-demo natalUtc: 26/9/1985/6/14/0 Coordinates: 51.5072178, -0.1275862 ``` Source: Alex confirmed this in Telegram on 2026-05-13. UTC was resolved through `transit-list-demo` `/api/time/resolve`. ## Generator Commands Generate global + Alex transit datasets and `.ics` feeds for the rest of 2026: ```bash ~/.hermes/astral-transits/astral-transits.js --kind both --start 2026-05-13 --end 2027-01-01 ``` Generate a full calendar year: ```bash ~/.hermes/astral-transits/astral-transits.js --kind both --year 2026 ``` Generate global-only: ```bash ~/.hermes/astral-transits/astral-transits.js --kind global --start 2026-06-01 --end 2026-07-01 ``` Generate Alex-only: ```bash ~/.hermes/astral-transits/astral-transits.js --kind alex --start 2026-06-01 --end 2026-07-01 ``` Include Moon if Alex explicitly wants a high-volume calendar or a high-frequency timing dataset for strategy research/trading experiments: ```bash ~/.hermes/astral-transits/astral-transits.js --kind both --year 2026 --include-moon ``` For crypto/market-timing research, the Moon should usually be treated as an execution-timing layer rather than a background calendar layer: use Moon ingresses, degree pulses, applying/separating aspects, and translations as frequent testable triggers, with Sun/Mercury/Venus as setup windows and Mars/Saturn/Jupiter as regime filters. Default planet set excludes Moon for normal calendar signal/noise and excludes South Node because it is always opposite True North Node and creates duplicate node-opposition spam: ```text Sun, Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, True North Node ``` ## Output Files The generator writes: ```text ~/.hermes/astral-transits/events/global-START_to_END.json ~/.hermes/astral-transits/events/alex-START_to_END.json ~/.hermes/astral-transits/events/combined-START_to_END.json ~/.hermes/astral-transits/events/current-transits.json ~/.hermes/astral-transits/calendars/global-START_to_END.ics ~/.hermes/astral-transits/calendars/alex-START_to_END.ics ~/.hermes/astral-transits/reports/report-START_to_END.md ``` JSON is the canonical Hermes context store. ICS is a calendar interchange/export artifact. ## Event Schema Each JSON event has this shape: ```json { "id": "global-20260602T224842Z-Sun-Sextile-Saturn", "kind": "global", "profileId": null, "title": "Sun Sextile Saturn", "summary": "Global transit: Sun Sextile Saturn", "startUtc": "2026-06-02T22:48:42.000Z", "endUtc": "2026-06-02T22:48:42.000Z", "allDay": false, "eventType": "aspect", "aspect": "Sextile", "orb": "exact", "planet1": "Sun", "planet2": "Saturn", "position1": { "degree": 12, "minute": 24, "second": 25, "sign": "Gemini", "longitude": 72.407 }, "position2": { "degree": 12, "minute": 24, "second": 25, "sign": "Aries", "longitude": 12.407 }, "source": "transit-list-demo", "raw": { } } ``` Ingress events use: ```json { "eventType": "ingress", "planet1": "Mercury", "planet2": "Cancer", "title": "Mercury enters Cancer" } ``` ## Calendar Sync Pattern Apple Calendar / Google Calendar can import `.ics` files directly. For ongoing sync, expose `~/.hermes/astral-transits/calendars/` via a stable HTTPS path, then subscribe to those URLs from calendar clients. Recommended future hosting path if needed: ```text https://astral-transits.apps.poofc.com/calendars/global-current.ics https://astral-transits.apps.poofc.com/calendars/alex-current.ics ``` For now, deliver or copy the `.ics` files manually from: ```text ~/.hermes/astral-transits/calendars/ ``` ## Tenant KB persistence (Phase 4) After every generator run, mirror the outputs into `astral-tenant-kb` so reading skills can pick them up by slug + range. ```bash KB=~/.hermes/skills/astrology/astral-tenant-kb/scripts/kb.py RANGE=2026-05-13_to_2027-01-01 # global window python3 $KB save_global_transits $RANGE --json ~/.hermes/astral-transits/events/global-${RANGE}.json # per-person window python3 $KB save_transit_profile alex $RANGE --json ~/.hermes/astral-transits/events/alex-${RANGE}.json python3 $KB save_transit_calendar alex $RANGE --ics ~/.hermes/astral-transits/calendars/alex-${RANGE}.ics ``` Hard rules: - Only mirror after the existing transit-first label normalization passes verification (see "Reading Transits into a Hermes Reply" step 4–6). - `range_id` format: `YYYY-MM-DD_to_YYYY-MM-DD` — used as the filename suffix. - The original `~/.hermes/astral-transits/` tree remains the working set; the KB mirror is the per-person canonical store that reading skills consult. ## Reading Transits into a Hermes Reply For a concise mobile response: If Alex asks for transits as part of another person's reading package, interpret **current transits to that subject's natal chart**, not Alex's transits. Use the subject's saved natal chart JSON when available, fetch current transits with `curl -sS https://transit-list-demo.apps.poofc.com/api/transits/current`, then compute major aspects from transiting planets to natal planets/angles with sensible orbs (rough defaults: Moon 1.5°, Mercury/Venus/Mars/Nodes 2°, Sun 2.5°, Jupiter/Saturn 3°, Uranus/Neptune/Pluto 2.5°). Lead with exact/high-impact overlays and synthesize them back into the natal + HD themes. 1. Read the relevant report first: ```text ~/.hermes/astral-transits/reports/report-START_to_END.md ``` 2. If a specific date is requested, filter the JSON events by `startUtc` date. 3. Separate `kind=global` from `kind=alex`. 4. For `kind=alex` aspect events, the generator must normalize labels and fields to **transiting body → natal body**. The raw upstream `transit-list-demo` scan may emit natal body first because it searches `p1 = natal longitude`, `p2 = transiting planet`; keep that raw object only under `raw` for audit, never as the user-facing title/summary/ICS label. 5. Verify Alex aspect events expose `body1Role: "transit"`, `body2Role: "natal"`, `transitPlanet`, and `natalPlanet` before interpreting or importing into downstream knowledge bases. Do not rely on a visually corrected title alone; validate the role fields (`planet1 === transitPlanet`, `planet2 === natalPlanet`) so stale natal-first copies fail fast. 6. If a KB/prototype import is involved, regenerate from the canonical `~/.hermes/astral-transits/events/*.json` after normalization and then search both the source store and KB for stale labels such as `Saturn Opposition Mercury`. 7. Mention UTC unless converting for Alex's local Pacific time. 7. Interpret using Alex's astrology style if interpretation is requested; otherwise report exact event facts. ## Downstream: transit-derived UX captions Astral Hermes loading states (provisioning spinner, chat stalls, etc.) use a filler-caption layer fed by the daily transit pipeline. The pipeline emits a small `captions` array alongside the JSON events, and the web app serves it from `/api/daily-captions`. See `chat-interface-development` SKILL.md → "Filler caption layer" for the consuming UI shape. **Caption generation rules** (Alex called the first-pass invented filler "dumb and cheesy" — these are hard rules): - **Source from real ephemeris data, not invented flavor.** Each caption must be derivable from current transit JSON: Moon degree+sign, planetary day, planetary hour, decan/face ruler (Coppock 36 Faces is Alex's default unless he says otherwise), traditional rulerships, applying aspects within orb, ingresses today. - **Write in Alex's traditional astrology register.** Decans, faces, bounds, domiciles, day/hour rulers, applying/separating aspects. NOT "asking Mercury for safe passage", "checking the decans for a good omen", "aligning fixed stars over your container" — those are made-up flavor text and read as fake. - **Factual phrasing, no verbs of supplication.** "Moon 4° Virgo — Mercury's domicile, Sun-faced decan." ✓ — "Mercury blessing your tenant…" ✗. - **Two layers**: global captions (from `events/current-transits.json` / `events/global-*.json`) for use before a tenant exists, and per-tenant captions (transits to that person's natal chart, from `transits/profiles/-.json`) for use inside a tenant. **Pipeline shape**: 1. VPS cron (hourly, for Moon-degree + planetary-hour drift) → writes `/data/hermes/astral-daily/global-.json` with `{ generatedAt, transits: {...}, captions: [...] }`. 2. Astral Hermes web serves `GET /api/daily-captions` → global captions. 3. Per-tenant cron at provisioning time (daily) → writes `/transits/daily/.json` with natal-overlay captions. 4. Astral Hermes web serves `GET /api/daily-captions?tenant=` → tenant-specific if available, else falls back to global. **Caption template examples** (templatically derived from JSON, not hand-written one-shots): - `"Moon ${deg}° ${sign} — ${signRuler}'s domicile, ${decanRuler}-faced decan."` - `"Day of ${dayRuler}. Moon waxing through ${moonSign}."` - `"${planet} ${deg}° ${sign} — ${face}, ${faceRuler}'s decan."` (per visible inner planet) - `"${transit_planet} applying ${aspect} natal ${natal_planet} (${orb}° orb)."` (tenant-only) - `"${count} planets in ${modality} signs."` (when ≥3 share a modality) Generator script lives at `astral-hermes-platform/scripts/daily-transits.mjs` (planned). It should accept `--natal --coordinates ` to emit per-tenant overlays; without those args, it emits global-only. ## Verification Checklist - [ ] `node --check ~/.hermes/astral-transits/astral-transits.js` passes. - [ ] Generator exits with `{ "ok": true }`. - [ ] JSON event counts are nonzero for normal multi-month ranges. - [ ] `.ics` files contain `BEGIN:VCALENDAR` and `VEVENT` entries. - [ ] Alex personal aspect summaries are transiting-first (e.g. `Mercury Opposition Saturn`), and stale natal-first summaries (e.g. `Saturn Opposition Mercury`) are absent from generated JSON/ICS/Markdown copies. - [ ] Alex profile is not treated as confirmed birth data until Alex confirms location/time. ## References - `references/alex-2026-transit-ordering-kb-import.md` — session-specific root cause, verification, and downstream KB import guard for natal-first raw scan output. ## Common Pitfalls 1. **Using `/api/transits/current` for a date range.** That endpoint only gives current positions. Use the local generator/CLI scan. 2. **Forgetting UTC day-first format.** Transit-list-demo dates are `day/month/year/hour/minute/second` in UTC. 3. **Including Moon or South Node by default.** Moon creates a noisy high-volume calendar. South Node is always opposite True North Node and can produce duplicate node-opposition spam. Only include them when Alex explicitly wants that layer and understands the volume. 4. **Using stale Alex birth data.** Alex's confirmed chart is 1985-09-26 07:14 London, UK → `26/9/1985/6/14/0` UTC date string. Do not use recovered/demo SVG values or any unconfirmed Alex birth data. 5. **Calendar subscription vs import.** A file import is one-time. True sync requires serving the `.ics` at a stable URL and subscribing to it.