Solar-Arc Directions solar-arc-naibod@1 — Specification (W-05)
Status: Implemented v1 convention · Task: W-05 · Updated: 2026-10-25 · Implementation: W-09 package.
Solar-arc directions move every point of a reference chart by one shared arc and compare the moved points with the original chart. The technique is a static transformation plus a contact evaluation: no astronomy is requested at the target date, and the reference chart never changes. Primary directions are a different coordinate problem and stay out of scope.
1. Admitted variant
| Field | Value |
|---|---|
| Technique | directions |
| Version | 1 |
| Variant | solar-arc-naibod |
| Rulebook entry | { "technique": "directions", "version": "1", "variant": "solar-arc-naibod", "hash": "<payload hash>" } |
Rule payload (validated by validateDirectionRules):
{
"arc": "naibod",
"yearLength": "tropical-2000",
"angles": "advanced",
"contacts": "directed-to-natal",
"houses": "none",
"excludeSelfPairs": true
}
arc: "true" (the progressed-Sun arc) is not admitted by this variant
(§11); it would make directions depend on the progression mapping and
must be specified with it.
2. Inputs
| Input | Source | Meaning |
|---|---|---|
| Reference snapshot | Engine | Bodies and, optionally, angles |
targetInstant |
Request | Date to direct to |
| Profile | Engine | Body set, aspect/orb policy |
Injected GeometryPort |
WesternFeatureContext.upstream.geometry |
Contact evaluation |
No ComposerPort and no ProbePort: this variant reads nothing at the target date.
3. Arc
Constants are identical to the progression specification §3.1 and are repeated here because this package does not import that one:
| Name | Value |
|---|---|
YEAR_DAYS |
365.242190 |
YEAR_MS |
31 556 925 216 |
NAIBOD |
0.9856473590852142 |
t0 = reference snapshot instant (epoch ms)
tt = targetInstant (epoch ms)
require tt > t0
elapsedYears = (tt - t0) / YEAR_MS
arc = NAIBOD × elapsedYears // degrees, no rounding before use
arc is the mean solar motion for one day of the day-for-a-year mapping, applied once per year of
life. Directions do not perform a progression: no chart is composed at t0 + elapsedYears days,
and the arc does not depend on the Sun’s actual position at any instant. NAIBOD × elapsedYears is
therefore one arithmetic step, not a hidden call into progressions.
arc is retained unrounded. Rounding for display is a consumer concern; rounding before contact
evaluation would change orbs near a boundary.
4. Directed points
For every body in the profile body order, and for the ascendant and midheaven when present:
λ_directed = wrap360(λ_reference + arc)
| Point | Rule |
|---|---|
| Bodies | Every body present in the reference snapshot |
| Ascendant | wrap360(asc + arc) when the reference has angles |
| Midheaven | wrap360(mc + arc) when the reference has angles |
Other angles (vertex, armc, co-ascendants) |
Not directed |
| Cusps | Not directed; the directed chart carries no cusps |
armc is equatorial right ascension and is excluded for the same reason as in the composite
method: adding an ecliptic arc to it produces neither quantity.
Every directed point is:
{ "kind": "derived", "method": "directions.solar-arc-naibod", "version": "1",
"sources": ["<reference snapshot hash>"] }
The reference snapshot itself is returned unchanged and is never mutated.
5. Speeds and phase
All directed points have speedLongitude: null. A direction is not a motion; this method defines no
derivative, so contacts are evaluated with motion: "unknown" and phase is never reported as
applying or separating. A directed point’s speed is never borrowed from the natal body it came from.
6. Contact policy
Contacts are directed → natal, never directed → directed and never natal → natal:
policy = { ...profile.aspectPolicy, motion: 'unknown' }
raw = geometry.evaluateCrossChartAspects(directedGeometry, natalGeometry, policy)
contacts = raw.filter(contact => contact.sourceBody !== contact.targetBody)
| Rule | Detail |
|---|---|
| Source | Directed chart (derived points) |
| Target | Reference chart (observed points) |
| Orb set | The profile’s aspectPolicy.rules; no separate angle orb |
| Motion | unknown; the evaluated policy is recorded verbatim |
| Self-pairs | Excluded by id after evaluation; no separation is recomputed |
| Angles | Included when the reference has them (ascendant, midheaven are geometry points) |
| Directed-to-directed | Not evaluated in v1 |
Self-pair exclusion matters: at a small arc every directed body is within a conjunction orb of its own natal position. That is an artifact of the transformation, not an event. Filtering by id keeps the shared geometry as the only aspect implementation.
excludeSelfPairs: false is a different variant; it changes every result and must be fixtured
separately.
7. Result
| Field | Meaning |
|---|---|
method |
{ id: 'solar-arc-naibod', version: '1', arc: 'naibod', yearLength: 'tropical-2000' } |
reference |
{ instant: t0, snapshot: <hash> } |
target |
{ instant: tt } |
arc |
{ degrees, elapsedYears, convention: 'naibod' } |
points[] |
{ id, longitude, origin: DerivedPointOrigin } for bodies and angles |
contacts[] |
Directed-to-natal contacts, phase: 'unknown' |
missing |
missing-angles, missing-aspects |
The result retains the reference chart, the arc value, the convention identity and each derived origin, so the same target date reproduces the same chart without re-reading astronomy.
8. Composer facts and ports
| Need | Provided by | Absent behaviour |
|---|---|---|
| Reference bodies | Reference snapshot | INSUFFICIENT_INPUT |
| Reference angles | Reference snapshot (house read) | missing-angles; body contacts still evaluate |
| Cross-chart geometry | GeometryPort |
missing-aspects only |
ComposerPort, ProbePort |
Not used | — |
Declared requirements: snapshot: 'houses', upstream: ['positions', 'houses'],
optionalUpstream: ['cross-chart-geometry'], dependencies: [].
The admitted variant needs the reference angles, so the snapshot requirement is houses. A host
that cannot supply a house observer fails context assembly explicitly rather than silently producing
a positions-only direction chart. A positions-only variant is a different version; the
missing-angles row in §9 applies to snapshots supplied directly to the pure functions.
9. Failures
| Case | Behaviour |
|---|---|
targetInstant absent, unparsable or <= t0 |
INVALID_REQUEST |
Unknown arc, yearLength, angles, contacts or houses value |
INVALID_RULES |
solar-arc-true requested |
LAYER_UNSUPPORTED; never approximated by Naibod |
primary requested |
LAYER_UNSUPPORTED (separate scope) |
| Reference has no angles | missing-angles; body points and body contacts still returned |
| Geometry absent | contacts omitted, missing-aspects |
| Directed houses requested | LAYER_UNSUPPORTED |
10. Worked examples
t0 = 2000-01-01T00:00:00.000Z. tt is expressed as a multiple of YEAR_MS unless stated.
D1 — 30 years.
elapsedYears = 30
arc = 0.9856473590852142 × 30 = 29.5694207726°
Sun 100° -> 129.5694207726°
D2 — contact. Natal Venus at 130°; directed Sun at 129.5694207726°.
separation = 0.4305792274° -> conjunction (orb 8), phase 'unknown'
D3 — wrap. Natal Moon 350° → wrap360(379.5694207726) = 19.5694207726°.
D4 — angles. Natal ascendant 15° → 44.5694207726°; midheaven 105° →
134.5694207726°. Both are directed by the same arc; the angles do not advance at a different rate.
D5 — self-pair. At tt = t0 + 2 × YEAR_MS, arc = 1.9712947182°. Directed Sun is 1.97° from
natal Sun, inside the conjunction orb; the pair is excluded by id and the contact list is empty.
D6 — no angles. Reference composed position-only → body points and body contacts evaluate;
ascendant/midheaven are absent with missing-angles; no angle contact is fabricated.
D7 — identity date. tt = t0 is rejected rather than returning the natal chart as a direction.
D8 — variant rejection. A profile electing directions@1/solar-arc-true fails
LAYER_UNSUPPORTED at capability time, before any request.
11. Unsupported variants
| Variant | Why unsupported |
|---|---|
solar-arc-true (progressed-Sun arc) |
Arc depends on the secondary-progression mapping; must be specified and fixtured with W-07 |
primary |
Needs right ascension, declination, geographic latitude and a named key; a separate coordinate and input scope |
converse directions |
Negative arc; a distinct convention |
excludeSelfPairs: false |
Different contact set at small arcs |
| Directed-to-directed contacts | Different evaluation graph |
| Directed house placement | No reviewed construction; natal cusps are not inherited |
| Solar-arc-to-angle-only, midpoint directions | Different point sets |
The engine never substitutes Naibod for a requested true arc, and never aliases primary directions to solar arc.
12. Prerequisites before W-09
The implementation and coordinator integration now satisfy these runtime seams; convention sources remain the responsibility of each supplied production rulebook. See the package tests.
| Id | Prerequisite | Owner |
|---|---|---|
| P1 | A reviewed source for the Naibod rate, the tropical year length and the self-pair exclusion | Direction reviewer |
| P2 | directions.solar-arc-naibod@1 payload schema and validator registered |
W-09 |
| P3 | Reference snapshots with angles for the angle-contact fixtures (C-02/C-07) | Compose owner |
| P4 | Cross-chart geometry with motion: 'unknown' verified on derived points (C-03) |
Compose owner |