500 lines
24 KiB
Markdown
500 lines
24 KiB
Markdown
# Input & output formats
|
|
|
|
See [`architecture.md`](architecture.md) for how these fit together.
|
|
There are two ways to provide input (direct CLI flags, or `run-engine.sh`
|
|
+ `user.properties`) and three output formats (`text`, `html`, `json`); the
|
|
`DailyReading` struct is the programmatic form all three are rendered
|
|
from, and the one watch UI code consumes directly. `json` is also
|
|
`interpreter-cli`'s input format — see "The interpreter" at the bottom
|
|
of this file, which supports the same three output formats (and the
|
|
same `--lang`) for its own report, independently of `deck-engine`.
|
|
|
|
## Input
|
|
|
|
### Direct CLI flags (`dist/deck-engine`)
|
|
|
|
```
|
|
deck-engine --seed <string> --birth-date YYYY-MM-DD --birth-time HH:MM
|
|
--birth-utc-offset <hours> --birth-lat <deg> --birth-lon <deg>
|
|
[--date YYYY-MM-DDTHH:MM] [--format text|html|json]
|
|
[--gender male|female|unspecified]
|
|
```
|
|
|
|
| Flag | Required | Format | Meaning |
|
|
|---|---|---|---|
|
|
| `--seed` | yes | any string | Tarot seed. The same seed always produces the same 10-card spread, positions, and orientations (see `rng.c`/`tarot.c`). |
|
|
| `--birth-date` | yes | `YYYY-MM-DD` | Birth date, local calendar. |
|
|
| `--birth-time` | yes | `HH:MM` (24h) | Birth time, local clock. |
|
|
| `--birth-utc-offset` | yes | decimal hours, e.g. `2` or `-5.5` | Hours to **subtract** from local birth time to get UTC (e.g. `2` for CEST). |
|
|
| `--birth-lat` | yes | decimal degrees | Birth latitude, north positive. |
|
|
| `--birth-lon` | yes | decimal degrees | Birth longitude, east positive. |
|
|
| `--date` | no | `YYYY-MM-DDTHH:MM[:SS]` | UTC moment used for today's transits and as the moment the tarot seed is drawn against. Defaults to the current system time. |
|
|
| `--format` | no | `text` \| `html` \| `json` | Output format, defaults to `text`. `json` always uses language-independent identifiers, ignoring `--lang`. |
|
|
| `--gender` | no | `male` \| `female` \| `unspecified` | Who the reading is for. Only affects the Celtic Cross position text's pronouns (e.g. "His House" vs. "Her House" vs. "Their House") - never the chart/draw itself. Defaults to `unspecified` (pronoun-neutral phrasing). |
|
|
| `--lang` | no | language code, e.g. `en`, `de` | Reading language, defaults to `en`. Matches a file named `<code>.lang` in `--i18n-dir` (see "Translations" below). Unknown codes or missing files fall back to English with a warning on stderr. |
|
|
| `--i18n-dir` | no | path | Directory to look for `<lang>.lang` in. Defaults to an `i18n/` directory next to the binary itself (resolved from `argv[0]`, so `dist/deck-engine` finds `dist/i18n/` regardless of the caller's working directory). |
|
|
|
|
Birth latitude/longitude only affect the Ascendant/houses — planet signs
|
|
are geocentric and location-independent.
|
|
|
|
### `run-engine.sh` + `user.properties`
|
|
|
|
`dist/run-engine.sh [text|html|json] [lang]` wraps the binary for daily
|
|
use:
|
|
|
|
- **Seed and `--date`** come from the OS clock: `date +%Y-%m-%d` (stable
|
|
all day) and `date -u +%Y-%m-%dT%H:%M`.
|
|
- **Birth data and language** are read from `dist/user.properties`, a
|
|
`key=value` properties file next to the script (`#`-prefixed lines and
|
|
blank lines are comments; whitespace around `=` is trimmed):
|
|
|
|
```properties
|
|
birth_date=1990-05-14
|
|
birth_time=14:32
|
|
birth_utc_offset=2
|
|
birth_lat=52.5200
|
|
birth_lon=13.4050
|
|
gender=unspecified
|
|
lang=en
|
|
```
|
|
|
|
The file is seeded once from `engine/scripts/user.properties.template`
|
|
with placeholder values (`YOUR_BIRTH_DATE_HERE`, etc.). `run-engine.sh`
|
|
checks every birth field for an empty value or a leftover `YOUR_`
|
|
placeholder and refuses to run with a clear error until the file is
|
|
filled in; `gender` and `lang` have no such check since they always
|
|
have a usable default (`unspecified`/`en`). Since `dist/` itself can be wiped (`make clean`, or
|
|
deleting the directory), the build also keeps a durable backup at
|
|
`engine/scripts/user.properties.local` (gitignored) once the file
|
|
looks filled in, and restores from it if `dist/user.properties` is
|
|
ever missing — see `CLAUDE.md`'s "Build & run".
|
|
- The optional second argument overrides `lang=` for a single run without
|
|
editing the file, e.g. `dist/run-engine.sh html de`.
|
|
- `dist/run-interpreter.sh` (no arguments) is the equivalent wrapper for
|
|
the interpreter: same OS clock + `user.properties` inputs, but calls
|
|
`deck-engine --format json` and pipes it straight into
|
|
`dist/interpreter-cli` — see "The interpreter" below.
|
|
|
|
### Translations (`--lang`, `dist/i18n/`)
|
|
|
|
Every piece of display text — planet/sign/moon-phase/aspect names, tarot
|
|
card names and meanings, Celtic Cross position names, and the section
|
|
headers in the `text`/`html` output — is looked up in a translation
|
|
catalog with the built-in English text as the fallback for any key the
|
|
catalog doesn't have. See `CLAUDE.md`'s "Translations" section for the
|
|
key-naming convention and how to add a new language.
|
|
|
|
Celtic Cross position text additionally varies with `--gender`: the
|
|
plain key (e.g. `position.present.desc`) is the pronoun-neutral wording
|
|
used for `unspecified`, and `.male`/`.female`-suffixed keys (e.g.
|
|
`position.present.desc.male`) hold the gendered wording where it
|
|
differs. A position whose wording doesn't vary by gender (e.g. "The
|
|
Outcome") simply has no `.male`/`.female` keys - the neutral key's
|
|
translation is used for every `--gender` value in that case.
|
|
|
|
`engine/i18n/en.lang` and `de.lang` are the shipped translation files;
|
|
`make` copies `engine/i18n/*.lang` to `dist/i18n/` (refreshed on every
|
|
build, like `dist/img/`). Adding a language is just dropping another
|
|
`<code>.lang` file into `engine/i18n/` — no code changes needed.
|
|
|
|
## Output
|
|
|
|
### `DailyReading` (the real output — `reading.h`)
|
|
|
|
`reading_generate()` is the actual API; `text`/`html` below are just two
|
|
ways of rendering the struct it fills in. This is what watch UI code
|
|
reads directly.
|
|
|
|
```c
|
|
typedef struct {
|
|
NatalChart natal;
|
|
DailyTransits transits;
|
|
CelticCrossSpread spread;
|
|
} DailyReading;
|
|
```
|
|
|
|
- **`NatalChart`** (`astro.h`): `bodies[10]` (Sun..Pluto, each a sign +
|
|
degree-in-sign + raw ecliptic longitude + whole-sign `house` 1-12),
|
|
`ascendant_longitude`, `houses[12]` (whole-sign: `houses[0]` is the
|
|
Ascendant's sign).
|
|
- **`DailyTransits`** (`astro.h`): `bodies[10]` (today's positions, same
|
|
shape as above — `house` here is the natal chart's house the
|
|
transiting planet currently occupies, not a fresh "houses for right
|
|
now" chart), `moon_phase` (one of 8 named phases), `aspects[]` +
|
|
`aspect_count` (each aspect names a transiting planet, a natal planet,
|
|
an `AspectType` — conjunction/sextile/square/trine/opposition — and
|
|
the orb in degrees).
|
|
- **`CelticCrossSpread`** (`tarot.h`): `positions[10]`, indexed by
|
|
`CelticCrossPosition` (Present, Challenge, Crown, Foundation, Recent
|
|
Past, Near Future, Attitude, Environment, Hopes and Fears, Outcome —
|
|
Waite's own drawing order), each holding a `TarotCard` and a `reversed`
|
|
bool.
|
|
|
|
### `--format text`
|
|
|
|
Four `=====`-delimited sections, in order: natal chart (each body's sign
|
|
+ degree + house, then the Ascendant), today's sky (Moon phase, then each
|
|
body's transiting position + the natal house it currently occupies),
|
|
today's aspects to the natal chart (one line per aspect, with orb), and
|
|
the Celtic Cross (one block per position: name, card, `(Reversed)` if
|
|
applicable, the position's meaning, then the card's meaning).
|
|
|
|
```
|
|
===== Natal Chart =====
|
|
Sun 23.5° Taurus (House 3)
|
|
Moon 15.2° Capricorn (House 11)
|
|
...
|
|
Ascendant 18.4° Pisces
|
|
|
|
===== Today's Sky =====
|
|
Moon phase: Waning Gibbous
|
|
Sun 11.5° Cancer (House 5)
|
|
...
|
|
|
|
===== Today's Aspects to Natal Chart =====
|
|
Transiting Sun Opposition natal Moon (orb 3.7°)
|
|
...
|
|
|
|
===== Celtic Cross =====
|
|
The Present The High Priestess (Reversed)
|
|
This covers them: the general influence affecting the matter.
|
|
Passion, moral or physical ardour, conceit, surface knowledge.
|
|
...
|
|
```
|
|
|
|
### `--format html`
|
|
|
|
A single self-contained HTML page (inline `<style>`, no JS, no external
|
|
requests) with the same four sections, plus each of the 10 Celtic Cross
|
|
cards rendered as an image:
|
|
|
|
```html
|
|
<img class="reversed" src="img/RWS_Tarot_02_High_Priestess.jpeg" alt="The High Priestess">
|
|
```
|
|
|
|
- `src="img/<file>"` is relative to the **HTML file's own location** —
|
|
it expects to sit next to an `img/` directory, exactly like
|
|
`dist/reading.html` next to `dist/img/` (which `make images` populates
|
|
from `res/img/`). Saving the HTML output anywhere else breaks the
|
|
image links.
|
|
- Reversed cards get `class="reversed"`, styled with `transform:
|
|
rotate(180deg)` in the page's inline CSS.
|
|
|
|
### `--format json`
|
|
|
|
A single JSON object mirroring `DailyReading` exactly — `date`, `gender`,
|
|
`natal`, `transits`, `spread` — using the **slug** accessors
|
|
(`astro_body_slug()`, `astro_sign_slug()`, `astro_moon_phase_slug()`,
|
|
`astro_aspect_slug()`, `tarot_card_slug()`, `tarot_position_slug()`)
|
|
rather than the display-name ones, so the output is identical regardless
|
|
of `--lang` — this is the one format meant for another program to parse
|
|
(`dist/interpreter-cli`, see "The interpreter" below), not for a human to
|
|
read.
|
|
|
|
```json
|
|
{
|
|
"date": "2026-07-16",
|
|
"gender": "unspecified",
|
|
"natal": {
|
|
"bodies": [
|
|
{"body": "sun", "sign": "taurus", "degree_in_sign": 23.4926, "ecliptic_longitude": 53.4926, "house": 3},
|
|
...
|
|
],
|
|
"ascendant_longitude": 348.4123,
|
|
"houses": ["pisces", "aries", ...]
|
|
},
|
|
"transits": {
|
|
"bodies": [
|
|
{"body": "sun", "sign": "cancer", "degree_in_sign": 11.5012, "ecliptic_longitude": 101.5012, "house": 5},
|
|
...
|
|
],
|
|
"moon_phase": "waning_gibbous",
|
|
"aspects": [
|
|
{"transiting_planet": "sun", "natal_planet": "moon", "type": "opposition", "orb": 3.7021},
|
|
...
|
|
]
|
|
},
|
|
"spread": {
|
|
"positions": [
|
|
{"position": "present", "card": "high_priestess", "reversed": true},
|
|
...
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
- `date` is the UTC calendar date of `--date` (or the current system time
|
|
if `--date` was omitted) — the day this reading is *for*, not
|
|
necessarily the day it was generated on. `reading_generate()` stores
|
|
the full moment in `DailyReading.utc_moment`; only the date part is
|
|
serialized here since that's the only thing the rest of this format
|
|
(and the interpreter's own reports, which read this field back — see
|
|
"The interpreter" below) ever display.
|
|
- `gender` is `--gender`'s value (`male`/`female`/`unspecified`,
|
|
`tarot_gender_slug()`) — who the reading is for. Only affects the
|
|
Celtic Cross position text's pronouns, nothing else in this document.
|
|
The interpreter reads this field back the same way it reads `date`.
|
|
- `bodies` is always `NUM_BODIES` (10) entries, Sun..Pluto in `Body` enum
|
|
order; `spread.positions` is always `TAROT_SPREAD_SIZE` (10) entries in
|
|
`CelticCrossPosition` enum order (Present, Challenge, Crown,
|
|
Foundation, Recent Past, Near Future, Attitude, Environment, Hopes and
|
|
Fears, Outcome — see `CLAUDE.md`'s "Tarot" section for why that's not
|
|
the order most tutorials use).
|
|
- `natal.houses[i]` is the sign occupying whole-sign house `i + 1`;
|
|
`houses[0]` is the Ascendant's own sign. `transits.bodies[*].house` is
|
|
a house number (1-12) into the **natal** chart, not a fresh "houses for
|
|
right now" chart — same rule as the `text`/`html` output.
|
|
- All angles are decimal degrees, `%.4f`. `aspects` may be an empty array
|
|
(a valid "no aspects today"), but the key itself is always present.
|
|
|
|
## The interpreter (`interpreter/`, `dist/interpreter-cli`)
|
|
|
|
`dist/interpreter-cli` is a separate binary — see `CLAUDE.md`'s
|
|
"Interpretation" section for the full architecture — that reads a
|
|
`--format json` document and scores how significant today's transits
|
|
are. It never links `astro.c`/`tarot.c`/`reading.c` (or the vendored
|
|
Astronomy Engine) — only `engine/src/tarot_data.c`/`i18n.c` are linked
|
|
in, for real card/position names and Waite meaning text (see
|
|
`CLAUDE.md`'s `INTERP_TAROT_TEXT_OBJS` note). Otherwise it depends only
|
|
on the JSON shape above.
|
|
|
|
Like `deck-engine`, its own output supports `--format text|html|json`
|
|
and `--lang <code>`/`--i18n-dir <path>`:
|
|
|
|
| Flag | Required | Format | Meaning |
|
|
|---|---|---|---|
|
|
| `[reading.json]` | no | file path or `-` | Input file; stdin (or `-`) if omitted. |
|
|
| `--format` | no | `text` \| `html` \| `json` | This binary's **own output** format, defaults to `text`. Entirely independent of the `--format json` that produced its *input* - see below. |
|
|
| `--lang` | no | language code, e.g. `en`, `de` | This binary's **own output** language, defaults to `en`. Same `<code>.lang`/`--i18n-dir` convention as `deck-engine` (see "Translations" above) - `main.c` calls `i18n_load()` itself, so `narrative.c`'s/`guidance.c`'s own text (in `engine/i18n/*.lang` under `narrative.*`/`guidance.*` keys) is translated too, not just the card/position/body/sign/aspect vocabulary it shares with `deck-engine`. |
|
|
| `--i18n-dir` | no | path | Same convention as `deck-engine`'s: defaults to an `i18n/` directory next to this binary. |
|
|
|
|
**This `--lang` is unrelated to whatever `--lang` `deck-engine` was run
|
|
with to produce the `--format json` input** - that JSON is always
|
|
language-independent (slugs only, see above), so it doesn't matter what
|
|
language `deck-engine` printed anything in, or whether it was even asked
|
|
to print anything at all (`--format json` never touches `--lang`
|
|
either). The two `--lang` flags, on the two sides of the pipe, are
|
|
independent settings.
|
|
|
|
```bash
|
|
dist/deck-engine ... --format json | dist/interpreter-cli --format html --lang de
|
|
# or:
|
|
dist/deck-engine ... --format json > reading.json
|
|
dist/interpreter-cli --format json reading.json
|
|
# or, for daily use (OS clock + user.properties, same inputs as run-engine.sh,
|
|
# including user.properties' lang=):
|
|
dist/run-interpreter.sh # text output, language from user.properties
|
|
dist/run-interpreter.sh html de # override format/language for this run
|
|
```
|
|
|
|
- **Input**: a file path argument, or stdin if no argument (or `-`) is
|
|
given. `"transits"."aspects"` is required (an empty array is valid and
|
|
means "no notable transits today"; a missing key is treated as invalid
|
|
input) and drives scoring. `"natal"."bodies"`/`"transits"."bodies"` are
|
|
read too, for the sign/house context printed alongside each event below
|
|
(not for scoring), and `"spread"."positions"` is read for the full
|
|
Celtic Cross readout and the guidance paragraph below — an entry naming
|
|
an unrecognized body/card/position, a missing `house`, or a missing
|
|
`"spread"` key entirely is silently skipped/zeroed rather than failing
|
|
the load (see `parse_bodies()`/`parse_spread()` in `reading_io.c`).
|
|
- **Input**: same for all three output formats above - only how the
|
|
parsed data gets rendered differs.
|
|
|
|
### `--format text`
|
|
|
|
A plain-text report, printed in a fixed order —
|
|
1. the day this reading is for (`Reading for: 2026-07-16`), from the
|
|
input JSON's top-level `date` field (see `--format json` above) —
|
|
not necessarily the day the report is actually being read on, if
|
|
`reading.json` was generated earlier and piped into
|
|
`interpreter-cli` later;
|
|
2. the day's overall significance level (`Quiet`/`Notable`/
|
|
`Significant`/`Major`, plus its rank out of the 4 defined levels,
|
|
e.g. `Notable (2/4)`), with a "worth a deeper Celtic Cross look"
|
|
line on `Major` days only;
|
|
3. up to 5 of today's aspects ranked by score, each naming the sign
|
|
and natal house the transiting planet currently occupies and the
|
|
sign and house of the natal planet it's aspecting, followed by a
|
|
short narrative sentence about what that transiting planet
|
|
classically signifies *and which area of life its current house
|
|
governs* (see `CLAUDE.md`'s `narrative.c` bullet) — omitted only if
|
|
the source material has nothing to say for that planet/aspect
|
|
combination;
|
|
4. the full 10-position Celtic Cross spread, in Waite's own drawing
|
|
order, each with its card (and orientation), the position's own
|
|
description, and that card's actual meaning;
|
|
5. finally, a guidance paragraph tying the day's top transit to the
|
|
spread's Attitude/Outcome cards, with its opening sentence tailored
|
|
to `day_level` (stronger wording on `Major`, softer on
|
|
`Quiet`/`Notable`, falling back to a transit-free reading of the
|
|
Attitude card alone on a day with no aspects at all) and, for the
|
|
Attitude/Outcome cards it names, their actual Waite meaning for the
|
|
orientation they landed in — see `CLAUDE.md`'s `guidance.c` bullet.
|
|
This is printed last, as the closing takeaway after the reader has
|
|
seen the full spread it references.
|
|
|
|
```
|
|
Reading for: 2026-07-16
|
|
|
|
Day significance: Major (4/4)
|
|
(a major transit today - worth a deeper Celtic Cross look)
|
|
|
|
Top 5 significant transits:
|
|
1. Transiting Pluto in Aquarius (house 3) Conjunction natal Moon in Aquarius (house 3) (orb 2.9°, score 9.60)
|
|
In matters of communication, siblings, and everyday learning (house 3). Brings deep, often hidden transformation - the surfacing or dismantling of something that has outgrown its old form.
|
|
2. Transiting Neptune in Aries (house 5) Sextile natal Moon in Aquarius (house 3) (orb 2.5°, score 9.25)
|
|
In matters of romance, creativity, and children (house 5). Brings a state of chaos and confusion - an involved, uncertain condition of affairs, with plots, subtlety, or unseen influences at work.
|
|
3. Transiting Uranus in Gemini (house 7) Trine natal Moon in Aquarius (house 3) (orb 2.0°, score 8.96)
|
|
In matters of partnerships and close relationships (house 7). Brings separations, estrangements, sudden dislocations and violent upsets. Success through official or civic channels, and beneficial changes or appointments, are possible.
|
|
|
|
Celtic Cross:
|
|
1. The Present: The Emperor (Reversed)
|
|
This covers them: the general influence affecting the matter.
|
|
Benevolence, compassion, credit; also confusion to enemies, obstruction, immaturity.
|
|
2. The Challenge: The Devil
|
|
This crosses them: the nature of the obstacle in the matter.
|
|
Ravage, violence, vehemence, extraordinary efforts, force, fatality.
|
|
...
|
|
7. Themself: The Magician
|
|
Their position or attitude in the circumstances.
|
|
Skill, diplomacy, address, subtlety; self-confidence, will.
|
|
...
|
|
10. The Outcome: Strength
|
|
What will come: the final result of the matter.
|
|
Power, energy, action, courage, magnanimity; complete success and honours.
|
|
|
|
With Pluto as today's dominant influence: Today concentrates whatever you already
|
|
bring to it - your current approach will be amplified, so make sure it's the one
|
|
you want.
|
|
Your Attitude card is The Magician: Skill, diplomacy, address, subtlety; self-confidence, will.
|
|
The spread's likely Outcome is Strength: Power, energy, action, courage, magnanimity; complete success and honours.
|
|
```
|
|
|
|
On a quieter day, only the opening of the guidance paragraph changes:
|
|
|
|
```
|
|
Day significance: Notable (2/4)
|
|
...
|
|
With a mild touch from Jupiter today: Your instincts are sound, but the day is
|
|
testing them - hold your position without forcing the issue.
|
|
Your Attitude card is The Sun: Material happiness, fortunate marriage, contentment.
|
|
The spread's likely Outcome is Justice: Equity, rightness, probity, executive; triumph of the deserving side in law.
|
|
```
|
|
|
|
The same report with `--lang de` (same input as the Major example
|
|
above):
|
|
|
|
```
|
|
Lesung für: 2026-07-16
|
|
|
|
Bedeutung des Tages: Einschneidend (4/4)
|
|
(ein einschneidender Transit heute - ein genauerer Blick auf das Keltische Kreuz lohnt sich)
|
|
|
|
Top 5 wichtige Transits:
|
|
1. Transit Pluto in Wassermann (Haus 3) Konjunktion natal Mond in Wassermann (Haus 3) (Orbis 2.9°, Punktzahl 9.60)
|
|
In Fragen von Kommunikation, Geschwistern und alltäglichem Lernen (Haus 3). Bringt tiefgreifenden, oft verborgenen Wandel - das Auftauchen oder die Auflösung von etwas, das seine alte Form überwachsen hat.
|
|
...
|
|
|
|
Keltisches Kreuz:
|
|
1. Die Gegenwart: Der Herrscher (Umgekehrt)
|
|
Dies bedeckt die fragende Person: der allgemeine Einfluss, der die Angelegenheit betrifft.
|
|
Wohlwollen, Mitgefühl, Ansehen; auch Verwirrung der Feinde, Behinderung, Unreife.
|
|
...
|
|
|
|
Pluto ist heute der bestimmende Einfluss: Der heutige Tag verstärkt, was du bereits
|
|
mitbringst - deine derzeitige Herangehensweise wird verstärkt, also stelle sicher,
|
|
dass es die richtige ist.
|
|
Deine Haltungskarte ist Der Magier: Geschick, Diplomatie, Gewandtheit, Feinsinn; Selbstvertrauen, Wille.
|
|
Das wahrscheinliche Ergebnis des Blatts ist Kraft: Macht, Energie, Tatkraft, Mut, Großmut; voller Erfolg und Ehren.
|
|
```
|
|
|
|
### `--format html`
|
|
|
|
A single self-contained HTML page, same inline-CSS/no-JS approach as
|
|
`deck-engine`'s own `--format html`, and the same three sections as text
|
|
(significant transits as a table, the full Celtic Cross as an image
|
|
grid, guidance as a closing callout) - reusing the exact same
|
|
`img/<file>` card-art convention (`tarot_card_image_file()`), so it
|
|
expects to sit next to an `img/` directory just like `deck-engine`'s
|
|
HTML output:
|
|
|
|
```html
|
|
<div class="card">
|
|
<div class="position">The Present</div>
|
|
<img class="reversed" src="img/RWS_Tarot_04_Emperor.jpeg" alt="The Emperor">
|
|
<div class="name">The Emperor (Reversed)</div>
|
|
<div class="desc">This covers them: the general influence affecting the matter.</div>
|
|
<div class="meaning">Benevolence, compassion, credit; also confusion to enemies, obstruction, immaturity.</div>
|
|
</div>
|
|
```
|
|
|
|
The guidance section renders as one `<p>` per line of the same text
|
|
`--format text` prints last (intro sentence, Attitude line, Outcome
|
|
line), inside a `<div class="guidance">`.
|
|
|
|
### `--format json`
|
|
|
|
Unlike `deck-engine`'s own `--format json` - which is deliberately
|
|
**language-independent** (slugs only, no `--lang`-dependent prose, since
|
|
it's a machine interchange format between the two binaries) -
|
|
`interpreter-cli`'s `--format json` embeds the *same localized
|
|
narrative/guidance prose* `--format text` prints, in whatever `--lang`
|
|
was loaded, **alongside** stable, language-independent slug fields. This
|
|
is a deliberate difference: rendering that prose is this module's whole
|
|
job, so a JSON consumer that wants it doesn't have to reimplement
|
|
`narrative.c`/`guidance.c`'s logic itself - but a consumer that only
|
|
wants structured data (e.g. watch UI code with its own rendering) still
|
|
has the slugs to work with directly.
|
|
|
|
```json
|
|
{
|
|
"date": "2026-07-16",
|
|
"day_significance": {
|
|
"level": "major",
|
|
"rank": 4,
|
|
"count": 4,
|
|
"deserves_framing": true
|
|
},
|
|
"significant_transits": [
|
|
{
|
|
"transiting_planet": "pluto",
|
|
"transiting_sign": "aquarius",
|
|
"transiting_house": 3,
|
|
"natal_planet": "moon",
|
|
"natal_sign": "aquarius",
|
|
"natal_house": 3,
|
|
"aspect": "conjunction",
|
|
"orb": 2.8821,
|
|
"score": 9.5961,
|
|
"narrative": "In matters of communication, siblings, and everyday learning (house 3). Brings deep, often hidden transformation - the surfacing or dismantling of something that has outgrown its old form."
|
|
}
|
|
],
|
|
"celtic_cross": [
|
|
{
|
|
"position": "present",
|
|
"card": "emperor",
|
|
"reversed": true,
|
|
"card_name": "The Emperor",
|
|
"meaning": "Benevolence, compassion, credit; also confusion to enemies, obstruction, immaturity."
|
|
}
|
|
],
|
|
"guidance": "With Pluto as today's dominant influence: Today concentrates whatever you already bring to it - your current approach will be amplified, so make sure it's the one you want.\nYour Attitude card is The Magician: Skill, diplomacy, address, subtlety; self-confidence, will.\nThe spread's likely Outcome is Strength: Power, energy, action, courage, magnanimity; complete success and honours."
|
|
}
|
|
```
|
|
|
|
- `date` is copied straight through from the input JSON's own top-level
|
|
`date` field (see `--format json` above) - always language-independent
|
|
regardless of `--lang`, same as every other slug in this document.
|
|
- `significant_transits` has `interp.top_item_count` entries (0-5, same
|
|
ranking as `--format text`); `celtic_cross` always has exactly 10, in
|
|
`CelticCrossPosition` enum order (same order as `deck-engine`'s own
|
|
`spread.positions`).
|
|
- `orb`/`score` are `%.4f`, matching `deck-engine`'s own JSON precision
|
|
for angles.
|
|
- `guidance` is always present and non-empty (unlike
|
|
`significant_transits`, which can be `[]` on a genuinely quiet day) -
|
|
see `guidance.c`'s no-aspects-at-all fallback in `CLAUDE.md`.
|
|
- With `--lang de`, every string value above except the slugs
|
|
(`"level"`, `"transiting_planet"`, `"aspect"`, `"card"`, `"position"`,
|
|
etc.) changes language; the slugs never do.
|