total-divination

/home/avalon/.hermes/skills/astrology/total-divination/SKILL.md · raw

Total Divination

When to use

Use when the user asks for a composite / full divination reading — anything like: - "give me a total divination" - "full reading" - "do the works" - "I Ching + tarot + transits" - "everything you've got"

This is an orchestrator that runs three oracles and synthesizes them into one coherent reading, not three readings glued together.

Parameters

Component skills

This orchestrator invokes the three component skills as-is — it does not re-implement their logic. Load and follow each:

  1. skill_view(name='iching-api-reading') — six-cast hexagram reading via iching-study app at :4017.
  2. skill_view(name='tarot-single-card') — single cryptographic card draw from alexTarot deck JSON.
  3. skill_view(name='astral-transit-snapshot') — exact-now transit→natal aspects + fast-mover layer.

Each component skill keeps its own RNG/API discipline, time anchoring, and pitfall rules. The composite does not override them.

Composite image (parallel)

A composite divination image is built in parallel with the text synthesis. As soon as the three calculations (six casts resolved, card drawn, transits ranked) are done, fire-and-forget a background process that renders the PNG while you write the reading. The user receives both: the image as a MEDIA: attachment, the text as the message body.

Renderer: scripts/compose-divination.py (in this skill's directory). Reads a JSON input file, writes a PNG. Render time ~0.2s on a small composite, fully programmatic (Pillow + the astro-font TTF), no image generator. Alex's strong preference: build divination/astro composites programmatically — never with an image generator. Do not propose AI-generated drafts for this composite; if visual direction is unclear, iterate on the Pillow script.

Glyph key for transit rows: see references/astro-glyph-key.md.

Design rules locked in (do not regress these): - Background #f7f3ec parchment, ink #1a1a1a, highlight #E85D2C (changing-line bars only). - Hexagram bars stacked bottom-up (lines[0] = line 1 = bottom). Solid for yang (7/9), broken with center gap for yin (6/8). Changing lines (totals 6 or 9) drawn in highlight; relating hexagram in default ink only — its changes are already shown on the primary. - Arrow between primary and relating, large (~100pt), only rendered when changing lines exist. - Hexagram label format: #NN · English · Chinese (e.g. #21 · Shih Ho · 噬嗑) — serif ~30pt, CJK ~34pt, English name kept short (no slash-suffixed alternative names). - Transit rows: strict 4-column grid (A: transit planet+sign, B: aspect, C: natal planet+sign, D: annotation). Symbol block A+B+C is centered on the canvas; annotation D floats to the right of C and does NOT participate in centering. This is what makes the composition beautiful — Alex's explicit call. - Planet glyphs full size; sign glyphs ~75% of planet size and drawn in muted gray (140,130,120) so signs sit politely without competing. Aspect glyph at planet size. - Mars glyph (J) is rendered ~83% of normal planet size — the astro font's Mars sits oversized in its viewbox and dominates other planets otherwise. There's a mars_font constant and a planet_font(ch) selector that switches per-glyph. If new planet glyphs ever show similar viewbox quirks, extend that selector pattern — don't try to rescale everything globally. - Glyphs drawn via draw_baseline() helper so per-glyph bbox bottoms align to a shared baseline (the astro font has inconsistent vertical metrics). - Annotation column D: orb + applying/separating + · in ~Nh or · Nd ago time-to-exact, in muted gray sans ~13pt. The orchestrator computes eta_str from orb / daily_speed × 24h; the script just renders it.

Iteration history note: Each visual refinement Alex requested (bigger labels → bigger arrow → column-justified grid → centered symbol block → smaller gray signs → Mars special-case) compounded — never revert a prior fix when applying a new one. Read the current state of compose-divination.py before patching.

Execution pattern (inside the orchestrator's execute_code block):

import json, subprocess, tempfile, os, pathlib

# After the three oracle calculations have resolved:
composite_input = {
  "tarot": {"image_path": "/home/avalon/apps/alexTarot/public/cards/" + card["img"],
            "name": card["name"], "reversed": bool(rev)},
  "iching": {
    "primary":   {"number": prim["number"], "displayName": prim["displayName"],
                  "chineseName": prim["chineseName"], "character": prim["character"]},
    "relating":  ({"number": rel["number"], "displayName": rel["displayName"],
                   "chineseName": rel["chineseName"], "character": rel["character"]}
                  if reading["changingLineNumbers"] else None),
    "lines":     [{"total": L["total"], "changing": L["changing"]} for L in reading["lines"]],
    "changingLineNumbers": reading["changingLineNumbers"],
  },
  "transits": [
    {"transit_planet": h["tb"], "transit_sign": <sign of transit>, "aspect": h["a"],
     "natal_planet":   h["nb"], "natal_sign":   <sign of natal>,
     "orb_str": f"{int(h['orb'])}°{int(round((h['orb']-int(h['orb']))*60)):02d}'",
     "tag": h["tag"]}
    for h in top_aspects[:5]
  ],
}

# Write input + spawn renderer in background — do not wait
tmp_in  = tempfile.NamedTemporaryFile('w', suffix='.json', delete=False)
json.dump(composite_input, tmp_in); tmp_in.close()
out_png = f"/tmp/divination-composite-{os.getpid()}.png"
script  = "/home/avalon/.hermes/skills/astrology/total-divination/scripts/compose-divination.py"
proc = subprocess.Popen(["python3", script, "--input", tmp_in.name, "--output", out_png])
# ... continue with text synthesis ...
# At the end, wait briefly for the renderer (it's ~0.2s):
proc.wait(timeout=5)
assert os.path.exists(out_png) and os.path.getsize(out_png) > 50_000
print("COMPOSITE:", out_png)

The composite path is included in the final reply as MEDIA:<out_png>placed at the very top of the message (replacing the bare tarot card image — the composite already contains the card).

Skip rules: - If the renderer fails for any reason, the reading still ships — just fall back to the bare tarot MEDIA: line. Never block the text on the image. - If include excludes any oracle, omit its zone from the composite (script handles missing iching or transits gracefully — pass empty/null).

Required workflow

1. Time + subject + context

2. Run all three oracles in parallel where possible

Inside one execute_code block, do: - POST /api/divination/throw-line six times (with 1–3s gaps) + POST /api/divination/reading → I Ching result. - secrets.choice on the alexTarot deck JSON + reversal roll → tarot result. - GET /api/transits/current + load/compute natal chart + local aspect computation → transit result.

The randomized I Ching gaps are still required (ritual gap, not a perf concern). Tarot and transits don't need gaps. Print all three structured results, then compose the reply.

3. Compose — the synthesis is the point

The reply is one composite reading, not three sections stapled together. Each oracle gets a compact "card" of its derivation, but the headline is a synthesis paragraph that triangulates all three — looking for resonance, tension, or commentary between them.

Examples of resonance to listen for: - I Ching's primary hexagram theme echoed in the tarot card's archetype. - Transit's headline aspect matching the moving-line inflection ("change pressure" in both). - Tarot reversal mirroring a separating/applying transit's direction. - All three pointing at the same life-area when a context was supplied.

Examples of tension worth surfacing: - I Ching says "stay low" while tarot pulls a fiery upright card → the synthesis names the tension instead of forcing a single message. - Transits show release/separating while I Ching shows building moving lines → time-layering: outer field releasing, inner field still gathering.

Never invent resonance that isn't there. If the three feel unrelated, say so — and lean on whichever oracle had the strongest signal (tightest transit orb / clearest moving lines / unambiguous tarot draw).

Reply formatting

Strict order, mobile-readable:

  1. Composite image at the very top. MEDIA:<composite_png_path> — absolute first line of the reply, nothing before it. The composite already contains the tarot card, both hexagrams (with changing lines highlighted + arrow to relating), and the transit glyph rows. If the composite renderer failed, fall back to MEDIA:/home/avalon/apps/alexTarot/public/cards/<img> (bare tarot card) — never ship without an image.

  2. Header line (italic). Subject · local time (UTC) · context if supplied.

    Alex · 2026-05-23 08:24 PDT (15:24 UTC) · context: "about launching this week"

  3. 🎴 Tarot · 🪙 I Ching · 🔭 Transit — one-line slate. A single compact slate line naming what was drawn, before any interpretation:

    🎴 The Tower (reversed) · 🪙 ䷽ 62 Hsiao Kuo → ䷞ 31 Hsien · 🔭 headline: Uranus □ natal Moon (0°13′, applying)

  4. ✨ The Synthesis (the headline section). 4–8 sentences. This is the reading. Triangulate the three oracles into one coherent present-moment picture. If context was supplied, anchor the synthesis there. End with a bold one-to-three-sentence one-breath summary.

  5. Component cards (below the synthesis — derivation). Three compact sub-sections, each shorter than its standalone version because the synthesis already carried the meaning:

🪙 I Ching — show the cast stack (line 6 top, line 1 bottom), the hexagram header glyph + number + name (English / Chinese / pinyin) + relating hexagram if changing lines exist, then a 2–4 sentence interpretation. Moving-line text(s) quoted for changing lines.

🎴 Tarot — bold card name header (with "— Reversed" if applicable), arcana · suit · number line, 2–3 sentence reading. Tie back to the context if any.

🔭 Transit — top 3 exact-now aspects as bullets (transit-first format with orb in degrees/minutes and applying/separating tag if confident), a 1–2 line fast-layer note (Moon/Mercury/Venus/Sun/Mars highlights + any 48h ingress), and a 2–3 sentence interpretation focused on the tightest aspect.

  1. 🌬️ One breath (final). Single bold sentence distilling the composite. May repeat or refine the synthesis closer.

Pitfalls

Verification