Packages2 MIN READ109 / 116

Internal module guide. This module is now part of @astrology/western; use the public package README for application setup.

synastry module

Implements synastry, the comparison of two people’s charts. Compares two already-admitted Composer snapshots using an injected GeometryPort. The ordered source/target pair determines contact identities and placement of source points in target houses. Reverse the pair for the other direction.

const rules = validateSynastryRules({
  aspectPolicy: {
    id: 'relationship-orbs', version: '1', motion: 'unknown',
    rules: [{ id: 'square', angle: 90, orb: 3 }],
  },
  overlays: { enabled: true, ruleId: 'target-cusp-intervals@1' },
});
const result = evaluateSynastry({
  source, target, completeness: 'allow-partial',
}, geometry, rules);

Contacts (aspects) use the selected orb policy and the full cross product of supplied bodies and available Ascendant/Midheaven points, through the existing Western snapshot adapter. Construction-time Binder aspects and source house assignments do not decide the comparison. Coordinates and zodiac/ayanamsa must be compatible; different birth instants and local house observers are allowed. Topocentric position observers (positions measured from a place on Earth’s surface) must still match the shared geometry admission contract.

Timeless rules require motion: 'unknown': birth-time speeds cannot determine applying/separating phase. Shared geometry still labels geometrically exact contacts exact. Neither input snapshot is changed.

With requested overlays and missing target cusps, require-complete throws FACTOR_UNAVAILABLE before evaluation. allow-partial retains contacts, returns empty overlays, and reports missing-target-houses with complete: false. Disabling overlays explicitly removes that requirement. Malformed supplied cusps and incompatible coordinates fail rather than becoming availability gaps.

createSynastryFeature(admittedRules) binds the bundle hash and declares the existing cross-chart-geometry gate. Use the coordinator’s operation({ profile, technique: 'synastry', request: pair }); engine.compose can acquire both inputs first. Direct feature evaluation also accepts a bound geometry port. The operation retains both chart identities and propagates overlay gaps to envelope completeness. No astronomy reads within the comparison, composite construction or relationship scoring occur here.

Results include directed contacts, overlays, deciding RuleMatch evidence and explicit gaps. Contact rule IDs identify policy/version/aspect; overlay evidence uses the elected overlay rule ID and records source/target identities and house.

Related code: admission, evaluation, feature binding, rule contracts, reviewed fixtures.

Verification: pnpm --filter @astrology/western... -r build, then pnpm --filter @astrology/western check and pnpm --filter @astrology/western test.