Commit Graph
2230 Commits
Author SHA1 Message Date
Claude 9779e195a4 Merge branch 'codex/chart-pending-1103' into codex/loading-1103
# Conflicts:
#	CHANGELOG.md
#	docs/BUG_HISTORY.md
#	docs/research/pre_work_error_ledger.md
2026-11-03 17:20:09 +08:00
ClaudeandClaude Opus 5.5 17825b9212 feat(settings): settings modal and avatar menu redesign (approved prototype)
Settings modal:
- 72px header with the one title 「设置」 and a transparent 44px close;
  184px nav + 1fr, 24px gap, no divider; current pane in the pale accent.
- Sections 32px apart with one hairline, 16px/600 body-face headings.
- 账户头像: 64px avatar beside 换一个形象; eight swatches in one row, each a
  44px target with a 40px ring previewing this avatar in that palette.
- 账户信息: two 52px rows, 96px labels, no 名称同步 caption.
- 外观主题: one 420px segmented track (theme-preference-segment); the
  ayanamsa options get their original theme-preference-option look back
  (the previous commit had restyled that shared class).
- 注销账号: one 44px row with a borderless danger-text 「注销…」.
- Phone: full screen, 56px header, 3-segment label-only nav, 16px inset,
  4x2 swatches; no inner scroll at 390x844.

Avatar menu: 264 wide; the identity row opens 个人资料; balance on
账户与点数; no chevrons; 外观 as three icon radio segments named by
aria-label; 退出登录 not red; 44px legal links.

DESIGN.md, CHANGELOG and contract tests updated (原值/新值/原因).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-03 17:13:57 +08:00
Claude 69c47c9602 Merge remote-tracking branch 'origin/staging' into codex/loading-1103
# Conflicts:
#	docs/BUG_HISTORY.md
#	frontend/src/components/rectification-page/rectification-entry-page.tsx
2026-11-03 17:07:52 +08:00
ClaudeandClaude Opus 5.5 40b44f1462 fix(loading): steady sidebar, no spinner on 生时校正, picker not gated on its flag read (BUG-1526..1529)
Staging loading report, 2026-11-03.

- Sidebar (BUG-1526): 生时校正 / 婚恋合盘 rows follow the product registry
  default until the account has been read; only an account that says off
  hides them, so rows are no longer inserted mid-list. The shell commits the
  account as soon as it is read (loadSessionList onAccount), ahead of the
  people list and the sessions. 「最近」 reserves an empty fixed-height block
  while the sessions are read instead of a line of copy (no skeleton).
- /api/account GET: avatar columns ride on the first profile select; profile,
  membership, admin check and both product flags run in one Promise.all.
- loadRuntimeFeatureFlags caches per key, joins in-flight keys and batches
  same-tick single-key calls into one query (parallel calls no longer evict
  each other).
- GET /api/sessions (BUG-1527): page and pinned queries run in parallel. The
  messages <> '[]' filter was measured on a local PG16 with synthetic data
  (EXPLAIN ANALYZE: ~0.7 ms -> ~0.1 ms warm, ~2-3 ms -> ~0.2 ms cold buffers
  per query); not worth a production schema change, so no migration.
- /rectification (BUG-1528): gated only on the account (plus the people list
  for someone else); the intro, person line and a fixed-height status card
  slot paint at once and only the card fills when the summary lands. The
  first summary read joins Home's in-flight read or the HTML early read
  (/rectification added to BOOT_READ_PAGES); Home's warm-snapshot summary
  seeds the card and is revalidated. shell-motion NAV gains /rectification.
- /synastry (BUG-1529): open/closed comes from the shell account
  (registry default until known); people and balance come from the shell; the
  price and the history are read at mount without the setTimeout tick and
  fill in on arrival; 开始合盘 stays disabled until the price is known.
  /api/product-access runs its flags, catalog and prices in parallel.

Tests: new loading-shell-20261103 and loading-routes-20261103; every changed
assertion (six files) carries 原值/新值/原因 comments. BUG_HISTORY, CHANGELOG, DESIGN.md
and the pre-work ledger updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-03 17:06:23 +08:00
ClaudeandClaude Opus 5.5 c165669e00 docs(bugs): record fix version for BUG-1516
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate (push) Canceled after 21m58s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-03 16:37:58 +08:00
ClaudeandClaude Opus 5.5 8c4290f2b0 fix(rectification): offer 新建一次 over an unfinished case; stop showing a slow read as "not started" (BUG-1516)
- /rectification: an unfinished case shows 继续上次 and 新建一次; 新建一次
  closes the old case (abandoned_by_user) before opening a fresh one.
- Case GET: engine identity read runs alongside the database reads, which
  now run in parallel; /v5/versions waits 2 s and falls back to the last
  trusted pair.
- Surface: an unread Case is "loading" (正在读取校正记录…), not 「这段校正
  还没有开始」; the hydration-incomplete toast is gone; the question poll
  no longer aborts its own in-flight read.
- Remove the 看盘面 board from the rectification surface; the shared chart
  panel stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-03 16:37:47 +08:00
ClaudeandClaude Opus 5.5 514eeca08e fix(chart, settings): pending chart layers keep the finished board's box; settings modal and avatar menu bugs
Chart (BUG-1520, BUG-1524):
- Split the whole-page skeleton into per-card pieces (chart-card-skeletons.tsx)
  shared by the page wait and each card waiting on its own layer.
- A board waiting on its chart-type layer draws an empty board in the
  finished .chart-board-plot box, in the current North/South style, with the
  caption row kept; a failed layer shows its note and 重试 in the same box.
- The inspector with no model fills its fixed card with the ascendant head
  and skeleton rows.
- useChartBoard exposes a natal model; tags and 命盘速览 always read it,
  宫位主题 waits as a skeleton card instead of an empty div.
- overflow-x: clip on the chat natal panel and the phone sheet body.
- The /chart onboarding hint describes the South drawing when it is chosen.

Settings and menu (BUG-1521, BUG-1522, BUG-1523, BUG-1525):
- Avatar palette swatches stretch and fill their cell.
- Theme options mark the current one via data-active / aria-selected with the
  pale accent; gap between options, labels on one line.
- Avatar menu positioner z-index 60, above the phone drawer.
- Account deletion confirmation is its own fixed-width dialog on a neutral
  surface with list bullets; no inner scroll.
- Avatar palettes: 桂影 -> 青瓷 (index 7), 莲火 base no longer brown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-03 16:30:46 +08:00
ClaudeandClaude Opus 5.5 ae1e9ada42 docs(bugs): record fix versions for BUG-1513, BUG-1514 and BUG-1515
Independent Staging Quality Gate / validate (push) Successful in 20m34s
Independent Staging Quality Gate / publish (push) Successful in 4m4s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-03 10:48:42 +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
jesse-uxandGrok (agent loop) 5213a861d4 docs(tasks): record the #144 database verification run (agent loop, issue #144)
Independent Staging Quality Gate / validate (push) Successful in 19m5s
Independent Staging Quality Gate / publish (push) Successful in 3m45s
Verify-only run on the intake branch: tsc 0 errors, lint 0 errors, the ten
changed frontend test files 105/105, and test:db 98 tests with 82 passing.
All 13 known Windows failures still fail; three tests in
database-segment-saved-native.test.ts fail only because the Windows Python
alias returns 9009, and they pass 3/3 when PYTHON points at the repo venv.

No source, test or migration changes. Flagged for a decision instead of
fixing, per the brief.

Co-Authored-By: Grok (agent loop)
2026-11-03 02:22:06 +08:00
Jesse_ChenandClaude Opus 5.5 d63757a736 docs(tasks): verify-only test:db brief for #144 part 1 (Grok)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 23:50:37 +08:00
ClaudeandClaude Opus 5.5 27af81de9b docs(tasks): birth-time source intake part 1 progress, changelog, device checklist
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 23:39:15 +08:00
ClaudeandClaude Opus 5.5 f00ddf2c4e feat(intake): six birth-time sources with a user-given range (issue #144 part 1)
- Intake: six verbatim options (出生证明 / 户口本 / 家人记得 / 只记得时辰 /
  只知道时段 / 完全不知道). Clock-time sources take an earliest / latest or
  「不清楚误差」; no source maps to a fixed error any more. Twelve 时辰
  picker (子时 23:00–00:59 from the filled date); the position answer is a
  clue and never narrows the window.
- Validation: drop the hospital 2/2 and family 15/30/60/120 rules; a time
  needs a containing range (minutes derived, may be uneven) or
  uncertainty_known=false. Older 2/2 and 15–120 profiles still resave as is.
- Lagna precheck: uses the given range; without one it scans only the
  stated minute and says the verbatim T4 line; ranges read as clocks.
- Migration 20261102020000 (additive): birth_time_source accepts
  id_document; profiles and chart_profiles gain birth_time_record_kind,
  birth_time_uncertainty_known, birth_time_shichen; chart_profiles gains
  birth_time_clue; sync trigger and backfill carry them.
- BUG-1513: readProfile now reads the camelCase library record of other
  people (source, stated time, window, status).
- BUG-1514: chart_profiles sync trigger is security definer, so a person
  without a clock time can be saved by the people route.
- id_document reaches the frozen engine contract as approximate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 23:39:15 +08:00
a2f80de505 docs(tasks): birth-time source intake brief, part 1 (agent loop, issue #144)
jesse chose A: keep asking for the source, stop mapping a source to a
fixed error, let the user give earliest/latest or "error unknown", and
add the columns needed (additive only). Part 2, per-item stability over
the range, is a separate queued issue.

Co-Authored-By: Claude (agent loop) <noreply@anthropic.com>
2026-11-02 22:36:31 +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
Jesse_ChenandClaude Opus 5.5 4dbaf51857 feat: preset-question menu beside the chat composer (#151)
Independent Staging Quality Gate / validate (push) Successful in 15m7s
Independent Staging Quality Gate / publish (push) Successful in 4m20s
Twelve domains x five astrologer-reviewed prompts fill the composer and
select the first blank. Phone bottom sheet, desktop popover; hidden for
synastry, rectification and incomplete profiles. No extra model call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 18:21:35 +08:00
Jesse_Chen 646dadc9a3 Merge remote-tracking branch 'origin/staging' into codex/consult-preset-prompts-20261102 2026-11-02 18:12:55 +08:00
ClaudeandClaude Opus 5.5 c8c08a49c6 fix: give the points pill a ringed planet, not the 星盘 orbit
Independent Staging Quality Gate / validate (push) Successful in 18m37s
Independent Staging Quality Gate / publish (push) Successful in 4m30s
Orbit already marks 星盘 in the sidebar and the chat chart toggle, so on
phones two identical orbits sat side by side in the top bar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 16:51:18 +08:00
ClaudeandClaude Opus 5.5 1cd73bc826 feat: 选择星盘 redesign, a full 盘面检视, and a chart page skeleton
Person picker (approved prototype):
- The chart page header uses the chat's two-line chip; the chip, the
  points pill, the chart toggle and 「那一刻的天空」 share
  `--chat-header-pill`, now 44px at every width.
- The popup is a 380px card: 「选择星盘」 with 「共 N 人」, rows of at
  least 60px (avatar, name + badge over the date line, the check on the
  selected row only, then ⋯), the selected row an accent wash with no
  box, a divider and 「+ 新增一个人」 in the accent. The list scrolls
  only on overflow. At ≤640px the same body opens as a bottom sheet
  (Drawer, grab handle, 64px rows, 44px ⋯). Choose, edit, delete
  confirm and every status are unchanged.

盘面检视:
- Nothing picked: six facts (宫主, 第 1 宫里的星, 看上升的星, 上升八分点,
  当前运期, 此刻月亮), a 九曜一览 3×3 grid whose cells pick a body, and
  「问 AI:我的上升」 / 「从太阳开始看」.
- A house: adds 宫主大运 and a 「和这一宫有关的星」 grid marking the
  occupants, the lord and the aspecting bodies; 「看宫主X」 picks the lord.
- The frame stays identical (the grid slot is empty for a planet or a
  point); measured in headless Chrome it fits every tier with no inner
  scroll. The chat panel shows compact cells.

Skeleton: while the view loads, the chart page renders the finished
page's own workspace, grid and cards at their fixed heights (titles as
text, soft pulsing blocks, still under reduced motion), with the board's
宫位依次点亮 drawing. Card boxes match the loaded page at 1280 and 390.
On a phone the chart page's top bar now keeps 52px once the page's own
birth line arrives.

BUG-1511: the person chip was hidden in phone headers by the static-note
rule's higher specificity; the override now outranks it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 16:47:54 +08:00
Claude 291bc53d7b Merge 深读 redesign + BUG-1510 宫位力量
# Conflicts:
#	docs/BUG_HISTORY.md
2026-11-02 12:47:34 +08:00
ClaudeandClaude Opus 5.5 8306959ec3 fix(home): 新建对话 no longer cold-starts Home off secondary pages (BUG-1509)
Recurrence of BUG-1040 / BUG-1104, reproduced in a production build:
- Warm decision now lasts until Home commits (releaseHomeWarmStart), not
  one microtask; the navigation note is peeked during render and taken
  after commit. React discarding and repeating Home's first render no
  longer flips it to the cold path.
- Secondary-page prefetch starts as soon as the list settles and on
  pointer intent; a 新建对话 click while it is in flight waits for it
  (at most 2 s, aria-busy) instead of cold-starting beside it.
- The session-list provider remembers its settled list on unmount, so
  returning from /learn starts warm; /learn header links use AppLink.
- Lifecycle tests repeat Home's first render inside a transition; 14
  new path tests (a)-(e), 12 fail on the old code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 12:36:08 +08:00
ClaudeandClaude Opus 5.5 e393f8bbf5 feat(chart): redesign 深读 as three stacked cards; fix blank 宫位力量 (BUG-1510)
深读 on the chart page drops its tabs, the 「深读」 header and the 640px
inner-scroll card. Three cards flow with the page: 时运流年 → 能量图谱 →
出生资料与口径. Graphics come first and the numbers sit behind 「看…」
controls (a link on desktop, a 44px button on a phone):

- 时运流年: 逐级放大 bars (大运 → 分运 → 子运, pale trapezoid
  connectors, today marker), a 星程 age ruler (title in one constant),
  and 九曜行运 as twelve house cells that select the house on the board,
  with the Sade Sati pill. Period tables, the second dasha (Chara now
  requested only when opened), the transit table and 叠到盘面 are
  behind expanders.
- 能量图谱: one bar per planet with a threshold tick and strong /
  medium / weak bands; twelve house bars with a dashed mean line.
  Shadbala parts, rupas and house values are behind an expander.
- 出生资料与口径: pills plus 「展开说明」 on desktop, a one-line summary row
  on a phone; the grid, boundary sentence and birth calendar unfold.

Colours come from theme tokens via color-mix: a pale accent wash marks
"current", planets are ink rather than rainbow colours, and dark mode
follows.

BUG-1510: when /api/bhava_bala failed alone, the ashtakavarga layer
arrived without houses, the section rendered an empty note, and the hook
cached the layer as loaded, so nothing could refetch it. The section now
shows a skeleton while waiting, and copy plus 重试 when the houses are
missing or the layer failed. An ashtakavarga layer without houses stays
re-requestable. The staging root cause is unconfirmed; a shared
per-IP API rate limit is suspected and tracked separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 12:16:52 +08:00
Jesse_ChenandClaude Opus 5.5 29cf4584f6 docs(research): consult preset prompts merged with the astrologer review (issue #151)
All 12 domains and 48 prompts kept; every review note applied, the two
"delete and replace" items use the reviewer's replacement text, and each
domain gains its reviewed candidate question (60 total). Menu text only;
backend execution rules from the review are tracked separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 11:18:10 +08:00
Claude 230a493fcd Merge BUG-1504/BUG-1508 VedAstro report deadline
Independent Staging Quality Gate / validate (push) Successful in 19m22s
Independent Staging Quality Gate / publish (push) Successful in 3m53s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y

# Conflicts:
#	CHANGELOG.md
#	docs/operations/outage-behaviour-2026-11-01.md
2026-11-02 07:50:47 +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
Claude c881dfb4ae Merge BUG-1506 birthplace fix
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y

# Conflicts:
#	CHANGELOG.md
2026-11-02 01:08:26 +08:00
ClaudeandClaude Opus 5.5 6721d320d8 fix(reports): release credits when lease recovery fails a report (BUG-1505)
recover_expired_personal_report_jobs now releases the reservation (by the
report's request_id, idempotent with the worker and the delete trigger)
before it fails a job; a release that raises or errors leaves that row
running for the next sweep and logs errorCode=report_refund_failed.
Migration 20261102010000_report_lease_expiry_release.sql replaces only the
function (invoker, empty search_path, service_role only).

The report worker no longer closes a failed job when its refund fails: it
logs report_refund_failed and leaves the lease to the recovery sweep.
Rectification retries a failed release once with the same case request id
and logs rectification_refund_failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 01:06:19 +08:00
ClaudeandClaude Opus 5.5 4ab81821cd fix(profile): keep the saved birth place when the timezone lookup fails (BUG-1506)
The birth place picker reported null on a failed timezone lookup and on a
half-chosen level; BirthLocationFields then cleared the place and the picker
reset its draft. Editing a saved person's date, time or place during a
timezone outage silently erased the birthplace with no error or retry.
The same path reset the picker when changing province/city/country on edit
and when opening an overseas person while the region list loaded.

- The picker only reports a freshly resolved place; failures and unfinished
  choices keep the previous value and report "pending" instead.
- BirthPlacePendingScope + BirthPlaceSubmitButton disable 保存 (edit dialogs)
  and 确定 (onboarding) while pending.
- Failure copy for a person with a place: 「时区这会儿没查到,原来的出生地还在,
  查到后才能保存。」 with 重试; new profiles keep the existing copy.
- Track the moment the stored offset was resolved for, so going back to the
  original date after a successful lookup re-resolves instead of saving a
  stale offset; ignore late results from aborted lookups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-02 00:58:09 +08:00
ClaudeandClaude Opus 5.5 ba1b4be71d Merge #119 items 42 and 46 (outage audit, BUG-1463 shadbala API)
Independent Staging Quality Gate / validate (push) Successful in 16m48s
Independent Staging Quality Gate / publish (push) Successful in 4m25s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 23:46:25 +08:00
ClaudeandClaude Opus 5.5 8f7814846b docs(ops): outage behaviour audit for VedAstro, location and model providers (#119 item 42)
Code-and-stub audit instead of a live drill (no staging SSH). Per-dependency
tables of what the user sees, charge/refund, logs/alerts and evidence, plus
gaps ranked by risk. Four clear bugs recorded as investigating: BUG-1504
(VedAstro truncated read -> 500), BUG-1505 (report lease expiry keeps
credits), BUG-1506 (profile edit wipes place on timezone failure),
BUG-1507 (legacy China profiles silently +8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 23:45:55 +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 7ff14329e9 docs(ops): notes for the 16 migrations added after 10-14 (#119 item 39)
Classifies the 16 production-pending migrations added since the 10-14 list
(A 1, B 3, C 7, D 5) with what production users see and what the rehearsal
should check. The one user-visible rewrite is the first-question-free
backfill: accounts that already completed a real question count as used,
confirmed by the product owner on 2026-11-01.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 23:25:48 +08:00
ClaudeandClaude Opus 5.5 0f1c179eb6 fix(deploy): web image installs packages from npmmirror like the gate (BUG-1503)
Independent Staging Quality Gate / validate (push) Successful in 16m19s
Independent Staging Quality Gate / publish (push) Successful in 6m6s
Publish job 11273 and its rerun 11284 timed out fetching from
registry.npmjs.org (zwitch, then zustand) while every validate check passed.
The gate's own install already uses registry.npmmirror.com; the image's npm ci
now does too. The lock file pins versions and integrity hashes, so the
installed packages are unchanged. Approved by the product owner 2026-11-01.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 22:39:53 +08:00
ClaudeandClaude Opus 5.5 9b1127c23c fix(rectification): v3 keeps no table access; a definer helper binds the case (BUG-1502)
Independent Staging Quality Gate / validate (push) Successful in 17m14s
Independent Staging Quality Gate / publish (push) Failing after 11m33s
Gate run 6343 refused the invoker v3 on agentic_rectification_cases: since
20260814010000 service_role has no direct rights on cases, every case write
goes through owner-held security-definer RPCs. v3 now only checks the person,
calls v2 and hands the case to agentic_rectification_bind_case_subject_v1,
a service_role-only security-definer function that locks the case, binds a new
case and its conversation to the person, and checks the person matches.
Migration parsed with pglast (58 statements, 17 PL/pgSQL bodies).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 21:56:59 +08:00
ClaudeandClaude Opus 5.5 ac83eb0df0 fix(rectification): v3 opens cases as the invoker so it can call v2 (BUG-1502)
Independent Staging Quality Gate / validate (push) Failing after 16m45s
Independent Staging Quality Gate / publish (push) Skipped
The staging gate's real-database tests refused open_agentic_rectification_case_v3:
it was security definer, and 20260814010000 revokes EXECUTE on the 11-argument
v2 even from its owner, leaving service_role alone. v3 is now security invoker,
like the 12-argument v2; reading the person and labelling the chat session move
into two service_role-only security-definer helpers, because service_role has
no rights on chart_profiles or chat_sessions. The migration has never run, so it
is corrected in place.

Also adds the annual.full price rows to the whole-table pricing assertion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 21:37:48 +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 ab0de9e842 feat(annual): annual report page with the start overlay (#154)
/reports/annual opens the annual report directly. A translucent overlay
shows the range, 「某人的这一年」, the three notes, the birth-time line
(self links to rectification), the short 现状 form, 「开始写年运」 and the
price line; then sections stream in as they are saved, and a year
already written opens without the overlay. 「我的报告」 gets the annual
card. Docs: design note with every default pending astrologer review,
DESIGN.md, VOICE.md, CHANGELOG.

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
Claude 80dc28a49a Merge #160 rectification for other people into staging integration
Independent Staging Quality Gate / validate (push) Failing after 13m11s
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

# Conflicts:
#	CHANGELOG.md
#	frontend/src/components/chart-page/chart-page-view.tsx
2026-11-01 17:32:14 +08:00
ClaudeandClaude Opus 5.5 46273a169e docs: rectification for other people (issue #160)
CHANGELOG, DESIGN, VOICE, onboarding red line 11 lifted, pre-work
ledger entry for this session's blocked checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-01 17:26:04 +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 52f85a793f fix(annual): pass node_mode to the solar-return charts (BUG-1501)
calc_solar_return_chart hard-coded the mean node for the birth and annual
charts, so node_mode=true never reached the annual Rahu/Ketu. The default
stays mean; cmd_solar_return and cmd_tajika now pass the request's mode.

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
Jesse_ChenandClaude 172178cdbd Merge origin/staging into D60 study (issue #149)
Independent Staging Quality Gate / validate (push) Successful in 20m20s
Independent Staging Quality Gate / publish (push) Successful in 4m21s
Co-Authored-By: Claude (agent loop) <noreply@anthropic.com>
2026-10-29 16:44:50 +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_ChenandClaude 09620c6e0a docs(tasks): D60 study second half, first rejection (agent loop, issue #149)
The G2-G5 results came without the script that produced them, so G5's
77/77 ayanamsa flip cannot be replayed. Commit the script, report G5 per
alternative ayanamsa, and say that G2's zero questions came from the
same-day scoring rule the planner chose.

Co-Authored-By: Claude (agent loop) <noreply@anthropic.com>
2026-10-29 16:14:25 +08:00
jesse-uxandGrok (agent loop) 028992257b research(d60): G2 not evaluable, G5 trips the noise floor (BUG-1497, issue #149)
The registered same-day answer policy needs an event dated on the birth day;
the v5 holdout has none in any of the 77 cases, so group B adds no question
and is identical to group A. G2 is therefore not evaluable by construction,
not a measured zero, and no placebo test has a lift to check.

G5 is measurable and decisive: switching the ayanamsa from Raman to Lahiri,
KP or True Chitra changes the ascendant D60 sign in 77 of 77 cases (100%,
threshold 20%). Under the registered stop rule any minute-level wording is
forbidden.

Recommendation: do not adopt. D60 stays reference-only and the external copy
does not claim seconds. BUG-1497 is closed_by_design; the mapping fix itself
is BUG-1500 and already merged.

Co-Authored-By: Grok (agent loop)
2026-10-29 15:48:08 +08:00
jesse-ux c163a74934 research(d60): preregister gates G2-G5 before scoring (issue #149)
Registered rules, thresholds, seeds and the same-day answer policy for the
D60 boundary probes. No scoring has run with this file in place.
2026-10-29 15:46:58 +08:00