Commit Graph
992 Commits
Author SHA1 Message Date
Claude f91608244a merge: upstream sync 10 into the data audit branch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y

# Conflicts:
#	docs/BUG_HISTORY.md
2026-11-04 12:41:54 +08:00
ClaudeandClaude Opus 5.5 1c69c1b7e2 fix(chart): chart-page Shadbala takes the precise path readings use (BUG-1548)
The chart API called calc_shadbala without a context and so used the
simplified fallback, and it rewrote `degree` as the in-sign degree, which the
precise Dig bala reads as a longitude. Readings and reports took the precise
path, so the same chart showed different strengths and a different strongest
planet (Jobs: Moon 10.61 vs 6.61 Rupa). The endpoint now builds the same
context as cmd_shadbala and passes absolute longitudes; a test locks the two
equal per planet. Also records the astrologer's ruling on waning-Moon Paksha.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-04 12:33:23 +08:00
ClaudeandClaude Opus 5.5 7dcf8112ad fix(saham): natal Vivaha Saham uses the shared day/night rule (BUG-1547, upstream 26d5a52d)
The natal marriage point was hard-coded to Venus - Saturn + Asc with no
zodiacal-order exception, while the annual Tajika point already followed
references/saham_rules.json (PVR Table 74: night reverses the operands, plus
the +30 exception). The same night-born person had two marriage points; 6 of
the 9 public charts move. The full reading, the vivah-saham command and the
consult card now share tajika._formula_saham_trace, with day/night from the
card's own day_night evidence. 0 deg Aries is no longer "missing".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-04 12:23:21 +08:00
ClaudeandClaude Opus 5.5 9cd1e35f94 fix(shadbala): fold the Sun-Moon elongation before Paksha bala (BUG-1546)
abs(Sun - Moon) / 3 was never folded to 0-180 degrees, so on charts whose
raw difference passes 180 benefics got more than 60, malefics went negative
and the doubled Moon passed 120 (Monroe's Moon -45.76; 5 of 19 benchmark
charts). PyJHora has the same line, which is why the comparison agreed.

Same audit, no code change: the +/-60 Kala gap is PyJHora's hora formula;
PyJHora is the outlier on Mars/Jupiter/Venus Chesta; Sun/Moon Chesta is a
school difference. Shadbala totals stay off the card until those settle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-04 12:14:20 +08:00
ClaudeandClaude Opus 5.5 71510682dc fix(narayana): run the second cycle instead of replaying the first (BUG-1545)
The legacy current-period lookup took the age modulo the first-cycle total,
so anyone older than their first cycle (61-96 years on the nine public
charts) got a first-cycle period: an 80-year-old was placed in 2-12. The
second cycle runs the same signs for 12 minus their first-cycle years; the
lookup now places the age on both cycles and subdivides with the second
cycle's years. The rectification cache only covers the first cycle and falls
back to the live lookup past it, so first-cycle scoring is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-04 12:05:22 +08:00
ClaudeandClaude Opus 5.5 9d69cd5625 fix(kp): feed sub-lord analysis unrounded cusps, degrees and time (BUG-1543, upstream 26d5a52d)
cmd_kp handed calc_kp_analysis the cusps from calculate_bhava_boundaries
(rounded to 4 decimals), degree_in_sign (4 decimals) and the chart's
display julian_day (6 decimals). KP star, sub and sub-sub boundaries are
cut on raw longitude, so a body or cusp sitting on a boundary could land
one cell off. The fix recomputes the JD from the civil instant with the
compute_chart_data formula, uses calculate_cusps directly, and uses
degree_raw % 30.

Only the KP part of 26d5a52d is ported. Its Vivaha Saham day/night change
and Yoga status pass-through are left for a separate decision. Test ported
from upstream tests/test_kp_unrounded_inputs.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-04 12:01:47 +08:00
ClaudeandClaude Opus 5.5 8137c692b1 fix(full-reading): one observation date for Narayana, nakshatra and annual age (BUG-1542, upstream 933f254e)
today_str and transit_reference_date already followed transit_date, then
today, then now. Narayana's current period read only args.today, and the
nakshatra-dasha age and the annual fallback age used datetime.now(). A
dated report therefore mixed two dates. The annual fallback age also used
days // 365, which moves to the next year of age early.

All three now take the same observation date. The fallback age counts
calendar birthdays. Tests are ported from upstream
test_full_reading_observation_date.py and test_tajika_report_age.py and
adapted to cmd_full_reading. Same-day web consultations are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-04 12:00:44 +08:00
ClaudeandClaude Opus 5.5 4b6aa08726 fix(varga): count D12 linkage houses from the D12 ascendant (BUG-1541, upstream cf6c316d)
The full reading's inter-chart linkage appended D12 with a hard-coded None
ascendant, so every D12 row had house None even though d12_asc_idx was
already computed a few lines above. An unknown sign name also fell back to
Aries. Port upstream cf6c316d and f60568a0: pass d12_asc_idx through, and
raise on an unknown sign or a non 0-11 ascendant index. The full reading
records the error and the consult native layer marks it blocked.

Test ported from upstream tests/test_inter_chart_d12_house.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-04 11:59:33 +08:00
ClaudeandClaude Opus 5.5 74169e1bfc fix(benchmark): pass the ayanamsa to both engines and refuse a mismatched baseline
The local baseline still claimed "lahiri_assumed_by_skill" after the engine
default moved to Raman, so the PyJHora comparison reported 59% instead of
~95% (every longitude 1.446 deg off). The baseline now passes --ayanamsa and
--node-mode to the engine and records what the engine reports; the compare
takes --ayanamsa and stops when the baseline was built differently. The nine
public Rodden AA backtest figures join the fixed samples.

Raman run (19 samples): ascendant, planets, nakshatras, D2/D4/D9/D10 and
Ashtakavarga all 100%; Shadbala and three old-chart dashas differ (separate).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-04 11:55:22 +08:00
ClaudeandClaude Opus 5.5 3bae79fbca docs(upstream): mirror upstream SKILL.md at main 5fb8379c (sync 10)
Run scripts/import_yinduzhanxing.py --apply from a clean clone of upstream
main 5fb8379c, the upstream HEAD on 2026-11-04. Only the root SKILL.md
moves into references/upstream/yinduzhanxing; the six semantic-merge paths
stay review_required and untouched. The new mirror drops the private
"yn-1993" sample wording the b9a0ef8f mirror still carried.

source-manifest.json and import-plan.json now pin 5fb8379c. The b9a0ef8f
import record stays as history and its test now checks only the record.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-04 11:51:04 +08:00
ClaudeandClaude Opus 5.5 a14040c0d7 ci: balance the two validate jobs by moving the CLI smoke tests
Independent Staging Quality Gate / validate-python (push) Successful in 6m41s
Independent Staging Quality Gate / validate-frontend (push) Successful in 6m44s
Independent Staging Quality Gate / publish (push) Successful in 2m37s
After the fixture change validate-frontend finished ~3 min before
validate-python (307 s vs 491 s in run 6487). tests/test_cli_smoke.py
(~110 s) now runs in validate-frontend after the frontend suite, with the
same PYTHONPATH/PYTHON the gate sets. run_quality_gate.py gains
--exclude-pytest-target, which refuses anything not in the selected
targets; a test checks every exclusion is run by the other job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-03 18:19:06 +08:00
ClaudeandClaude Opus 5.5 884a17997c ci: run the fragment audit once per quality gate
Independent Staging Quality Gate / validate-frontend (push) Successful in 5m7s
Independent Staging Quality Gate / validate-python (push) Successful in 8m11s
Independent Staging Quality Gate / publish (push) Successful in 2m31s
The gate ran scripts/audit_fragments.py --strict (~52 s on xiaoxin) and then
pytest ran the same audit() again in tests/test_api_server_security.py
(test_fragment_audit_blocks_registry_surface_drift asserts valid and more).
The separate step is gone; tests/test_quality_gate_fragment_audit_once.py,
now in the core targets, keeps the pytest copy and its target listing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-03 18:05:32 +08:00
ClaudeandClaude Opus 5.5 a84ebff6e4 ci: run the Python and frontend gates in parallel and keep install caches on the runner
Independent Staging Quality Gate / validate-python (push) Successful in 17m4s
Independent Staging Quality Gate / validate-frontend (push) Successful in 23m50s
Independent Staging Quality Gate / publish (push) Successful in 5m38s
- Split `validate` into `validate-python` and `validate-frontend`; publish
  needs both. Runner capacity is >= 2 (publish and migrate already overlap).
- deploy/ci-python-venv.sh: venv kept under /root/.cache keyed by Python
  version, ISO week, pins and requirements; persistent pip cache. A fresh
  venv per run spent ~3 min re-downloading the same wheels.
- npm ci gets a persistent download cache and --prefer-offline (every one
  of 1,010 packages was a cache miss).
- publish builds and pushes the API and web images concurrently; the web
  Dockerfile mounts BuildKit caches for npm and .next/cache.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-03 16:59:57 +08:00
ClaudeandClaude Opus 5.5 a861d26977 feat(chart): per-item birth-window stability, verify-first prompt, explicit calc settings (issue #165)
Part 2 of #144.
- The varga-segments scan gains opt-in stability_items: lagna degree, Sripati
  cusp signs, Moon sign / nakshatra / pada / house per minute, plus a
  historical-timezone check. The precheck requests D1/D9/D10 with it.
- Chart page shows nine computed items (一致 / 有变化) only for a range the
  user gave, the verbatim comparison sentence, a verify-first block for the
  conditions stored data can show, and the verbatim Dasha boundary sentence.
- Precheck sends the chart's ayanamsa and node mode and drops replies with
  other settings; the endpoint honours node_mode. candidate_time_sensitivity_scan
  and flexible_birth_time_profile take no defaults (BUG-1515).
- 只记得时辰 third question, stored in birth_time_clue; no migration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-03 10:39:18 +08:00
ClaudeandClaude Opus 5.5 6e89ac175e fix(report): name the five-level sample 大运 / 小运 / 细运 / 微运 / 息运
Independent Staging Quality Gate / validate (push) Successful in 15m8s
Independent Staging Quality Gate / publish (push) Successful in 4m33s
Sookshma (subtle) becomes 微运 and Prana (breath) 息运, after their Sanskrit
sense, replacing the temporary Latin "Sookshma" header. Product, 2026-11-02.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 21:40:50 +08:00
ClaudeandClaude Opus 5.5 7d1057ccc5 feat(report): Vimshottari levels 大运 / 小运 / 细运 across the report pipeline
Independent Staging Quality Gate / validate (push) Successful in 21m50s
Independent Staging Quality Gate / publish (push) Successful in 4m21s
The personal report now uses the astrologer-approved names, matching the
chart page and the consult prompts since 7a56840f (issue #163 Q5): MD 大运,
AD 小运, PD 细运. Old names replaced in code-rendered text only: 主运 / 主大运
-> 大运, 子运 / 分运 / 副运 (AD) -> 小运, 次子运 / 次小运 / 再小运 and the
fact table's PD 小运 -> 细运. PD strings were converted before AD, and AD
before MD.

Covered: the focus card and its export text, the raw fact tables, theme
claim cards, the timing interpretation pack, the PL9 full-data export
(tables, dasha prose templates, AD/PD density anchors), rashi / Narayana
second level, KP monthly focus, orchestrator texts and technique-audit
rows. English translation keys follow the new Chinese labels
(大运 = Mahadasha, 小运 = Antardasha, 细运 = Pratyantardasha), and a new test
pins that no English mapping reads 小运 as the third level.

The five-level monthly sample table used 细运 for Sookshma; it now shows
Sookshma until the astrologer names the fourth level.

Saved reports are not migrated. Focus fences render from md/ad/pd codes,
and stored fact tables validate by structure, so old and new labels both
open. Goldens were updated in place and two hash pins re-pinned; reverting
only the term swap reproduces the old hashes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 21:32:51 +08:00
Claude 7a56840fab Merge branch 'codex/163-engine-columns' into codex/integrate-163
Independent Staging Quality Gate / validate (push) Successful in 18m55s
Independent Staging Quality Gate / publish (push) Successful in 4m39s
# Conflicts:
#	CHANGELOG.md
#	frontend/src/components/chart-board/chart-data-card.tsx
2026-11-02 20:38:18 +08:00
ClaudeandClaude Opus 5.5 ca8d63b5b6 feat: chart terms and board overlays per the astrologer's #163 answers 4-8
Shadbala (Q4): one rule everywhere, total / the body's own BPHS minimum.
100 % or more is 达标 (light green), below is 未达标 (light warm tint), a
body the engine left out is grey 未计算, never 0. The 120 % / 90 % strong /
medium / weak tiers are gone from the inspector, 命盘速览, 能量图谱, the board
星力 tags and the data card.

Dasha (Q5): MD 大运, AD 小运, PD 细运 across the chart page, 深读, inspector,
命盘速览, the data card, board chips and the consult / report-reading model
prompts. The board keeps the wash on the houses the period lord rules, adds
an outline on the house it sits in, drops the lines between period lords,
and gets a 「从运主起算」 toggle that renumbers the houses from the lord with
a 「宫位从某星起算」 chip. Chara marks the lord the engine used (co-lords as
returned) and outlines its house from the engine's lord_in_sign.

敌友 (Q6): the centre defaults to the lagna lord (the Moon with a chip when
the lagna may change), remembered per browser; the seven grahas only;
natural, temporary and compound side by side plus the reverse direction;
the board says which relationship it shows.

瑜伽 (Q7): highlight only, no array-order lines (the yoga rows carry no
relation data).

Names (Q8): 八分法 (title 八分法(Ashtakavarga)), BAV / SAV labels,
Arudha 映射.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 20:36:18 +08:00
ClaudeandClaude Opus 5.5 578a361460 feat(chart): functional roles, 7/8 Chara Karaka and three new 特殊点 groups (#163 1-3)
/api/chart_points:
- karaka_scheme 7 (default) / 8 / both; shared ranking in
  chart_view_points/karaka_rank.py (unrounded in-sign degree, Rahu reversed
  in the 8 scheme, Ketu out). Bodies equal at full precision mark only the
  roles they span as tied; Goel uses the same ranking (BUG-1512).
- functional_roles: v2 BPHS ch.34 profile laid out per body, nodes pending,
  Yogakaraka / Badhaka / Kendradhipati (conditions not evaluated) as
  separate labels.
- sensitive_points (Bhrigu Bindu per chart node_mode, 64th Navamsa, 22nd
  Drekkana sign-only), sahams (PVR Table 74, nine first, all kept),
  goel_points (printed-text policy, worked example beside it).

盘面数据: 行星 gets Chara Karaka (AK · 自我, 七星/八星 switch), 自然属性,
管辖宫位, 功能角色, 补充身份; 特殊点 splits into 特殊上升 / 敏感点 / Saham /
Goel 特殊点 and the board's 特殊点 layer follows the open group.

jaimini.py, functional_benefics.py and varga.py are untouched (rectification
frozen identity).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 20:35:31 +08:00
ClaudeandClaude Opus 5.5 7c5ac4dca4 feat(home): top-bar chip, one person switcher, drop 今日星语 and the model picker
Product-approved home UI cleanup (2026-11-02):

- Blank home has no 「新对话」 title; conversations keep theirs. The chat
  header person control is a two-line chip (initial, full name + relation
  tag, then date time · city only). Points pill reads 「N 点」 with a coin in
  the action colour, 36px like its neighbours, label 「剩余 N 点,点开充值」.
- The chart panel's person switcher (issue #150) is removed; the header
  chip is the only entry. Panel title stays.
- 今日星语 leaves the UI: greeting sub-line, entry pill and its captions,
  binder, warm snapshot / prefetch / localStorage cache, checklist item and
  its signal. Loading copy no longer mentions it. The API route and the
  consultation's daily answers are untouched; starter-question signs come
  from the computed chart.
- No model picker: chat and rectification composers lose it, client-side
  per-session model persistence is gone, ordinary turns ask for the admin
  default, and the consult route moves an older session onto the default
  (persisted, so billing reads the answering model). Synastry turns keep
  their session model.
- Composer: one strong hairline + soft shadow, focus only recolours the
  border (input-group ring cancelled); AI notice centred under it.

Tests that pinned removed UI are replaced with ones asserting the new
behaviour (原值/新值/原因 comments). DESIGN.md, VOICE.md, CHANGELOG updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 11:50:42 +08:00
ClaudeandClaude Opus 5.5 bc4a6c2b49 fix(report): bound VedAstro wait in report generation (BUG-1508, BUG-1504)
Reports send vedastro_evidence_budget=report. The API defers like consult
(no sync main-entry overview, cache-only gate, gateway in the foreground
pool) with a 25 s deadline from session start (cap 45 s). On overrun the
report continues with VedAstro official_blocked /
report_vedastro_deadline_exceeded and the failure is stored in the day's
negative snapshot cache. The main-entry overview attach now fails soft.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 07:50:03 +08:00
ClaudeandClaude Opus 5.5 eb5e9adcf9 fix(shadbala): move /api/shadbala into shadbala_service; birth data no longer 500 (BUG-1463)
_compute_shadbala called swe.julday with no swe in scope, so any request with
year/month/day/lat/lon raised NameError. The endpoint now lives in
scripts/shadbala_service/api.py, which imports Swiss Ephemeris itself; the
handler only forwards. _shadbala_rule_variants and
_compute_shadbala_advanced_layer moved with it (handler methods 217 -> 215,
baseline lowered). New real-HTTP regression test with ruff F821 on the server,
added to the quick gate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 23:29:30 +08:00
ClaudeandClaude Opus 5.5 1a7aba0280 Merge annual_service refactor (growth budget fix for the staging gate)
Independent Staging Quality Gate / validate (push) Failing after 14m52s
Independent Staging Quality Gate / publish (push) Skipped
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 21:09:55 +08:00
ClaudeandClaude Opus 5.5 32fa756bd4 refactor(annual): move the annual package and report facts into annual_service
Staging's backend gate (run 6338) failed three budgets: handler method
count 218 > 217, JyotishAPIHandler.__new__ sites 6 > 5, and the scripts/
root .py count. The package and facts code now live in
scripts/annual_service/ (package.py, report_facts.py, api.py with
compute_annual_package / compute_annual_report_facts and
AnnualServiceInputError). jyotish_api_server.py registers /api/annual
mode=package, /api/annual/package and /api/annual/report_facts thinly
through a module-level _annual_service helper, like /api/chart_points,
with no handler methods: back to 217. Tests call the module functions
and keep a thin-registration test; no cap or baseline changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 20:33:17 +08:00
Claude 5b566af981 Merge annual report generation and entry overlay (#153, #154)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y

# Conflicts:
#	CHANGELOG.md
2026-11-01 20:20:47 +08:00
ClaudeandClaude Opus 5.5 4972fa40a6 feat(annual): annual report generation and annual.full billing (#153)
New report type annual_full on the personal report queue, like
synastry_full. POST /api/reports {reportType: annual_full} reserves
annual.full (20 credits by default, admin-editable), stores the range
and the optional situation, and queues the job; a year already written
for the same subject opens directly without a second charge. The worker
asks /api/annual/report_facts for the server cards, writes the sections
one at a time (person, overview, domains, windows, remaining, close)
with a program gate and one rewrite, saves the snapshot after every
section, then settles; a failure releases the reservation.
GET /api/annual/overview serves the overlay from the slim package.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 20:15:45 +08:00
ClaudeandClaude Opus 5.5 7512d3d654 test(audit): the capability audit scans the /learn routes (issue #157)
The app route list is asserted exactly; /learn and /learn/[column]/[slug]
are new public routes from the knowledge base framework.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 17:31:25 +08:00
ClaudeandClaude Opus 5.5 1643bad25b feat(annual): report facts and claim cards; slim package (#153)
/api/annual/report_facts returns the annual report's only allowed facts:
natal base (functional roles, house lords, yogas as structure, domain
vargas and A10/A7/UL/DK), the year's phases with a lean from the natal
skeleton lords' functional roles, turning points, 4-6 candidate windows
from computed boundaries and exact contacts (independent systems only),
per-domain signals, conflicts and the technique audit with MEVG and Real
Case Calibration blocked. Open defaults sit in CONFIG / HOUSE_DOMAINS.
The package gains detail=slim for the entry overlay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 17:24:39 +08:00
ClaudeandClaude Opus 5.5 340f0f2b85 feat(annual): annual data package v1 (#152 ruling, phase 1 of #153)
POST /api/annual with mode=package (or /api/annual/package) returns one
versioned package built from the existing producers: year charts with
ascendant/lord, Muntha, Panchadhikari year lord, annual strength, Sahams,
Tajika yogas, Tripataki, Mudda, native Patyayini, Tajika monthly charts;
natal Vimshottari MD/AD/PD and Narayana (legacy + Rath); slow-planet
ingresses, stations, retrograde loops and natal-point crossings; Tithi
Pravesha as an independent view. Report range, year-chart validity and each
period system's own year are separate, every boundary is an exact instant
with timezone, and every block carries computed/blocked/not_applicable with
a reason. The default /api/annual response is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 17:07:54 +08:00
ClaudeandClaude Opus 5.5 5157f96df3 feat(chart): 盘面数据 card beside the board, linked both ways
Independent Staging Quality Gate / validate (push) Successful in 29m39s
Independent Staging Quality Gate / publish (push) Successful in 4m3s
The chart page's tables move into one fixed-height card beside the board
with nine tabs: 行星, 虚星, 特殊点, 映射, 八分点, 星力, 大运, 敌友, 瑜伽.
The point tabs and 八分点 are the board's layers, switched together from
either side. 星力, 大运, 敌友 and 瑜伽 mark, tint, link and fade bodies on
the natal board (lib/chart-board-focus.ts).

The planet table gains the ascendant row, nakshatra lord, pada and the
seven Chara karakas, now produced by /api/chart_points from
jaimini.calc_chara_karaka_7 (blocked on a tie). Every card keeps a fixed
height and scrolls inside; tables never wrap and can be dragged sideways.
Hint captions are gone, 八宫点 reads 八分点, and the deep reading keeps
time, energy and birth data only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-10-30 16:27:04 +08:00
jesse-uxandGrok (agent loop) 3bc82acba6 research(d60): ship the G2/G5 script and report per-switch flips (issue #149)
The G2 precheck and the G5 noise floor had only a results file; the script
that produces them is now in scripts/research/d60_two_way_g2_g5.py, with
a test that reproduces the committed JSON byte for byte.

G5 is now reported per switch, with the ayanamsa offset in arcminutes.
Against the Raman baseline all three alternatives flip 77/77. Between the
alternatives themselves the number follows the offset: Lahiri to KP 21/77
(27.3%, 5.81'), KP to True Chitra 19/77 (24.7%, 5.02'), Lahiri to True
Chitra 2/77 (2.6%, 0.83'). The report says so and no longer claims that
any frame change flips every chart; the registered gate is baseline
relative and still triggers.

The report also states that G2's "not evaluable" comes from the registered
same-day answer policy, not from a measurement that D60 does not help.

Co-Authored-By: Grok (agent loop)
2026-10-29 16:32:54 +08:00
jesse-uxandGrok (agent loop) 129313e175 fix(varga): count D60 from the sign itself for every sign (BUG-1500, issue #149)
Independent Staging Quality Gate / validate (push) Successful in 20m59s
Independent Staging Quality Gate / publish (push) Successful in 4m25s
The production D60 branch added one sign to 1-based even signs, with no
source, while the repository's own guide and the vedastro mapping count
from the sign itself. PyJHora agrees with the latter: 33/77 recorded times
before, 77/77 after.

- scripts/varga.py: D60 is (si+pi)%12 for odd and even signs; other
  mappings and the vedastro mode are untouched.
- tests/test_d60_varga_mapping.py: 12 signs x 60 parts against
  PyJHora, plus the even-sign first part.
- scripts/research/d60_two_way_run.py: the G1 reconciliation that found
  this, now in the repository with a test; G1 passes 77/77.
- scripts/varga.py is part of the extended frozen identity, so the sealed
  holdout and the reported-offset sweep were re-frozen per ERR-110. All
  20 and 900 trials match the upstream_sync9b records on every field and
  the metrics and summary are unchanged.

Co-Authored-By: Grok (agent loop)
2026-10-29 14:30:57 +08:00
jesseandClaude Opus 5.5 537beb2934 test: each test gets its own foreground VedAstro pool, drained at teardown (BUG-1498)
Independent Staging Quality Gate / validate (push) Successful in 16m7s
Independent Staging Quality Gate / publish (push) Successful in 4m22s
A task left running wrote its outcome into the next test's cache directory,
so the next test saw a remembered failure and never called the gateway.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 19:39:28 +08:00
Jesse_ChenandClaude f80f3b75f8 Merge origin/staging into upstream sync 9 batch B (issue #159)
Independent Staging Quality Gate / validate (push) Successful in 18m34s
Independent Staging Quality Gate / publish (push) Successful in 5m14s
Co-Authored-By: Claude (agent loop) <noreply@anthropic.com>
2026-10-28 17:23:59 +08:00
jesseandClaude Opus 5.5 cbfb37f7c8 test: list /rectification in the capability audit app routes (issue #145)
Independent Staging Quality Gate / validate (push) Successful in 20m54s
Independent Staging Quality Gate / publish (push) Successful in 5m43s
Staging gate run 2009 failed on test_capability_audit_scans_registry_and_local_sources:
the new app route app/(app)/rectification was not in the expected list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:23:17 +08:00
jesse-uxandGrok (agent loop) cbe665107f test(freeze-guard): keep the sync8 freeze paths in the forbidden list (issue #159)
The sync9b edit replaced the two sync8 entries in
IDENTITY_FORBIDDEN_PREFIXES instead of appending after them, so the guard
covered two records instead of four while still passing. Restore the
sync8 pair under its own comment and keep the sync9b pair after it.

The freshness test passes again (9) and the frontend confirmation-gate
test for the moved sealed report passes (8).

Co-Authored-By: Grok (agent loop)
2026-10-28 17:01:31 +08:00
jesse-uxandGrok (agent loop) 5c5f333d4d fix(varga): port the five sarpa ranges and the 22nd drekkana house (BUG-1494, BUG-1495, issue #159)
Upstream 50847e57, ported semantically:

- Sarpa Drekkana now accepts the five classical ranges (Cancer 2/3,
  Scorpio 1/2, Pisces 3) and partitions on the raw longitude instead of
  the rounded display degrees.
- The 22nd Drekkana is the eighth house of D3 (+7), not +21 zodiacal
  ten-degree divisions.

scripts/varga.py is part of the extended frozen identity, so the sealed
holdout and the reported-offset sweep were re-frozen under ERR-110:
20/20 sealed trials and 900/900 sweep trials match the sync8 records on
every compared field, and the metrics, summary and widening geometry are
unchanged.

Tests: the upstream varga/ sarpa files are added under
tests/test_upstream_sync9b_*.py; the stale +21 assertion and the sarpa
definition string are updated with the original/new/reason columns in
PROGRESS.

Co-Authored-By: Grok (agent loop)
2026-10-28 16:25:45 +08:00
Jesse_ChenandClaude Opus 5.5 8d1cb4a53b Heavy routes run in worker processes, one per heavy slot (issue #133, BUG-1493)
The single ThreadingHTTPServer ran pure-Python v5 score / block_scan / report
reference under one GIL, so the gate's two slots shared a core. start_server
now starts a spawn pool (workers = heavy concurrency, PYTHONHASHSEED=0, engine
pre-imported); those three routes call the same compute method in a worker.
Over HTTP: score alone 4.74 s, two at once 5.01 / 4.58 s (1.06x; in-process
1.56x). Results equal except per-process fingerprints; report markdown equal.
~165 MB extra. A crashed pool answers inline and restarts; off with
JYOTISH_HEAVY_COMPUTE_PROCESSES=0; tests calling compute methods unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 14:28:05 +08:00
Jesse_ChenandClaude Opus 5.5 5fd79a5649 Chart surfaces start Vimshottari from the birth moment, as reports do (issue #137, BUG-1492)
/api/chart, /api/dasha and the analysis layer, daily guidance and the KP
monthly packet used compute_vimshottari_timeline, which hands
build_dasha_timeline only the birth date, so periods started at midnight;
cmd_dasha (reports) starts from the birth clock and lays antardashas from the
full parent with float days. scripts/chart_dasha/birth_moment.py reproduces
cmd_dasha; 60 standard charts: MD and AD 60/60 equal (old chart path 9/60),
51 charts move by at most one day. Frozen scoring files are untouched, so
rectification probes keep the day start (left for a product decision).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 14:27:35 +08:00
Jesse_ChenandClaude Opus 5.5 a614895a2b Loader waits for a module another thread is still importing (issue #132, BUG-1482 reopened)
Independent Staging Quality Gate / validate (push) Successful in 16m40s
Independent Staging Quality Gate / publish (push) Successful in 4m32s
Gate run 5888 failed: the synastry full dossier computes two full readings
on a thread pool, and the second thread got jyotish_engine from sys.modules
while the first was still executing it (no cmd_full_reading yet). Reuse now
goes through importlib.import_module, which waits on the module lock.

Four threads loading one module in a fresh interpreter: before
[False, True, True, True], after all True three times. Dossier scenario
before 4/4 AttributeError, after 6/6 ok; synastry-full-report.test.ts 17/17.
Ledger ERR-117: local npm baseline hid it (system python3 lacks swisseph).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 13:47:30 +08:00
Jesse_ChenandClaude cd6ad9d27a Merge origin/staging into upstream sync 9 (issue #141)
Independent Staging Quality Gate / validate (push) Failing after 14m40s
Independent Staging Quality Gate / publish (push) Skipped
Staging took BUG-1472..1482 while this branch was in review, so the
branch's eight entries move to BUG-1483..1490. Docs and one test
comment only; the branch's commit messages keep the old numbers.

Co-Authored-By: Claude (agent loop) <noreply@anthropic.com>
2026-10-28 12:45:29 +08:00
Jesse_ChenandClaude Opus 5.5 8a72aa5b44 API loader shares one module object per file (issue #132, BUG-1482)
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate (push) Canceled after 8m49s
_load_local_module always re-executed the file as _jyotish_local_<name>, so
engine, dasha, varga and others ran as extra copies with their own caches.
It now reuses scripts.<name> / <name> when that file is already imported,
else imports it under its plain name so later imports share it; the private
copy remains only as a fallback. Call sites unchanged. Probe after one
consultation and one chart: loader-made copies 19 -> 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:43:59 +08:00
Jesse_ChenandClaude Opus 5.5 0594afcd5c Remove 11 closure ledger scripts only their own tests used (issue #138, BUG-1481)
Batch 1 of the scripts/ root cleanup: the closure scripts no runtime entry,
other script, workflow, deploy file, ops doc or quality gate reaches, with
their 11 test files (30 cases). Their references/ outputs stay. Scripts still
imported elsewhere, named by the gate, or listed in archived reference indexes
are kept. Root budget 452 -> 441.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:43:08 +08:00
jesse-uxandGrok (agent loop) 60116f2813 test(cli): lock Darakaraka to the canonical karaka table (BUG-1478, issue #141)
The D9 smoke case expected Sun, which is what the old reader produced when
it took the 7th highest degree in the 8-karaka variant. The canonical table
and the fixed reader both give Moon for this chart (Moon 3.09 degrees).

Expect Moon and the D9 fields that follow it, and assert the reader agrees
with chara_karaka_8.karaka_table_8.Darakaraka.planet so the test locks
reader/main-table identity instead of one planet name.

Co-Authored-By: Grok (agent loop)
2026-10-28 12:39:55 +08:00
Jesse_ChenandClaude Opus 5.5 b9a5415e71 VedAstro failures are remembered for the day; the rectification check fits the frontend's wait (issue #130, BUG-1479)
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate (push) Canceled after 2m17s
- Foreground gateway: a run that ended without official data is written to
  the existing same-day negative snapshot store; later turns that day answer
  from it without starting the gateway (second call <= 0.15 s, same fields).
  Success still goes to the positive cache first; a consult-gate deferral and
  a join timeout are not failures.
- /v5/vedastro-validate: a result blocked by VedAstro itself is kept in memory
  for a day per (evidence fingerprint, candidate pair); evidence-decided
  results are not. The whole check has 11 s (frontend waits 12 s); calls with
  time to spare keep the adapter timeout, so normal output is unchanged.
- conftest also isolates the negative store and clears the check memory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:38:17 +08:00
Jesse_ChenandClaude Opus 5.5 18c6e13028 Consult card keeps parsed packets in memory, prewarms each turn, writes 0600 (issue #129, BUG-1476)
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate (push) Canceled after 11s
- consult_packet_view keeps the last 3 parsed packets with their shared domain
  base (~30 MB each). A hit reads no file and copies nothing: attach for one
  domain 0.106 s -> 0.002 s. Memory holds the file's JSON round trip, i.e.
  exactly what a hit returned before; consult_card_facts sha256 equal old/new.
- Cache files are created 0600, same bytes as before.
- The consult route fires a warm for the turn's chart before reserving credit,
  so the day's first question does not build the packet on the answer path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 11:57:53 +08:00
jesse-uxandGrok (agent loop) 8aed605a43 fix(aspects): pass planet speed into the three production callers (BUG-1479, upstream e628118d)
aspects.py itself is in d226b0e53 because it was already staged. Ketu and applying/separating behavior are covered by the geometry test. Callers pass numeric speeds, or None when speed is absent. calc_house_aspects does not take speed.

Co-Authored-By: Grok (agent loop)
2026-10-28 09:45:39 +08:00
jesse-uxandGrok (agent loop) bd09485243 fix(arudha): sign-only coordinates, no invented degree (BUG-1477, upstream 8b55630a)
Arudha, A10, and Upapada report the sign and house only. Rectification still reads Bhava, Hora, and Ghati degrees plus frozen jaimini padas. Sealed 20-case replay and 900 reported-offset windows match the sync8 metrics line for line. Frozen-file hash matched.

Co-Authored-By: Grok (agent loop)
2026-10-28 09:45:39 +08:00
jesse-uxandGrok (agent loop) c1bd59e97a test(dasha): keep the upstream boundary contract (upstream 07fc5be3)
A8 is tests only. dasha_analyzer.py is frozen and was not edited. Both contract tests passed.

Co-Authored-By: Grok (agent loop)
2026-10-28 09:45:09 +08:00
jesse-uxandGrok (agent loop) 7bede9c99a fix(darakaraka): sort with the existing Jaimini tables (BUG-1478, upstream 45b3b66b)
Calls calc_chara_karaka_7 and calc_chara_karaka_8. jaimini.py is not edited.

Co-Authored-By: Grok (agent loop)
2026-10-28 09:45:08 +08:00