Commit Graph
1688 Commits
Author SHA1 Message Date
ClaudeandClaude Opus 5.5 97afd1716a feat: chart choice replaces event-scored rectification page
Event scoring was measured at chance level on the 77 Rodden-AA holdout
cases (BUG-1091). The new flow finds the dividing line nearest the reported
time, describes how the flipped divisional charts read on either side, asks
up to five self-assessment questions, and saves the user's own choice
(provenance user_choice) with the domains to read in both versions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXozbkyFNqbu8pVEtZ7W
2026-11-06 02:06:17 +08:00
Claude 945e86911a Merge remote-tracking branch 'origin/staging' into codex/consult-dasha-horizon-20261105
Independent Staging Quality Gate / validate-python (push) Successful in 6m24s
Independent Staging Quality Gate / validate-frontend (push) Successful in 6m28s
Independent Staging Quality Gate / publish (push) Successful in 2m37s
2026-11-06 01:12:14 +08:00
ClaudeandClaude Opus 5.5 f926bb6d60 test(chat): record the shell registration in an effect, not by reassigning an outer variable during render (BUG-1642)
Independent Staging Quality Gate / validate-python (push) Successful in 6m31s
Independent Staging Quality Gate / validate-frontend (push) Successful in 6m41s
Independent Staging Quality Gate / publish (push) Successful in 2m54s
The React Compiler lint rule failed the staging frontend job on 6bbf638d.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-06 01:00:14 +08:00
ClaudeandClaude Opus 5.5 c0860e9638 fix(chat): queued question and 开新对话 survive leaving Home (BUG-1642 follow-up 2)
- The question queued during a reply lives in the session store, keyed by
  chat and by the reply it waits for. A mounted Home sends it to that chat
  once the reply completes, or puts it back in that chat's composer; nothing
  is sent from another page with a stale Home closure.
- The full-chat notice's 开新对话 records a carry-over in the store and
  returns to Home if needed; the mounted Home opens the new chat with the
  question, linked to the full chat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-06 00:33:55 +08:00
Claude 84960c6c52 Merge remote-tracking branch 'origin/staging' into codex/consult-dasha-horizon-20261105
# Conflicts:
#	docs/BUG_HISTORY.md
2026-11-06 00:29:29 +08:00
Claude 8c08ed7447 Merge remote-tracking branch 'origin/staging' into codex/chat-background-run-notice-20261106
Independent Staging Quality Gate / validate-python (push) Failing after 6m53s
Independent Staging Quality Gate / validate-frontend (push) Failing after 7m6s
Independent Staging Quality Gate / publish (push) Skipped
2026-11-06 00:15:45 +08:00
ClaudeandClaude Opus 5.5 e478280596 fix(chat): a run's error and handed-back question reach the Home the user is on (BUG-1642 follow-up)
- requestError and replyOutcome move from Home state into the session store;
  a Home remount keeps them, a new session-list provider drops them.
- A stop or an uncommitted reservation hands its question back through the
  store (composerRestore); use-composer-restore puts it into that chat's
  composer whenever the chat is open, on the Home mounted now or later.
- While a stop is still being confirmed the question stays with the stopped
  chat, so switching rows no longer loses it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-06 00:15:17 +08:00
ClaudeandClaude Opus 5.5 3d7efeafc1 fix(reports): typed lane claim is its own function, so the original claim is never overloaded
Independent Staging Quality Gate / validate-python (push) Successful in 6m38s
Independent Staging Quality Gate / validate-frontend (push) Successful in 6m44s
Independent Staging Quality Gate / publish (push) Successful in 3m7s
The staging DB gate replays 20260814040000 on top of the new migration;
with claim_personal_report_job overloaded by a defaulted fourth argument,
a three-argument call became ambiguous. The lane now calls
claim_personal_report_job_for_types and the original stays untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXozbkyFNqbu8pVEtZ7W
2026-11-06 00:09:51 +08:00
Claude a190d0660b Merge remote-tracking branch 'origin/staging' into codex/chat-background-run-20261105
# Conflicts:
#	docs/BUG_HISTORY.md
2026-11-06 00:01:29 +08:00
ClaudeandClaude Opus 5.5 a01289515d fix(chat): other chats open while a reply generates; coming back attaches to the live reply (BUG-1642)
- Sidebar rows always open; a reply in flight locks only their menu and drag.
  新建对话 is no longer locked by generation.
- The in-flight run's refs live in lib/consultation-run-refs.ts instead of
  Home's useRefs; a Home remount keeps the store's run fields while a run is
  live, so the Home that mounts on return attaches to the same stream instead
  of starting a second recovery that the first closure then cleared.
- Completion drops the tab's pending-consultation record for that request.
- One reply at a time is unchanged (client send guard and queue).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 23:59:31 +08:00
ClaudeandClaude Opus 5.5 e2c61f1a9a fix(consult): carry the next dasha periods on the card for long-range questions (BUG-1643)
A ten-year career question got a timing section that stopped at the running
Vimshottari mahadasha and the running Narayana sign, so the answer padded the
decade with "no period available" sentences and could not compare the systems.

- API: dasha_sub_periods.next_mahadasha (next MD cut by the same
  dasha_analyzer.build_antardasha); frozen engine files untouched.
- Card: every card carries the next MD and next Narayana sign; a question
  that looks N years ahead also gets timing.horizon, the next MD's
  antardashas, later MDs inside the horizon and two to four Narayana signs
  with years, all copied from the engine.
- Goldens: only the new engine field grafted in (rest byte-identical).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 23:59:05 +08:00
ClaudeandClaude Opus 5.5 efceab8a2a feat(reports): report queue lanes — two at once with a short-report lane, waiting screens show the expected wait
Independent Staging Quality Gate / validate-frontend (push) Failing after 4m38s
Independent Staging Quality Gate / validate-python (push) Successful in 6m35s
Independent Staging Quality Gate / publish (push) Skipped
Every report type already queued in personal_report_jobs, one at a time per
server. The worker now runs PERSONAL_REPORT_WORKER_CONCURRENCY lanes (default
2); the second takes only annual and synastry reports so they never wait
behind long personal reports. claim_personal_report_job gains an optional
report-type filter; personal_report_queue_view (owner-only, security definer)
gives the wait, shown as a single line on the annual, personal and synastry
waiting screens. Also keeps the privacy whitelist line numbers in
personal-report-api.test.ts unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXozbkyFNqbu8pVEtZ7W
2026-11-05 23:41:31 +08:00
ClaudeandClaude Opus 5.5 6c11dfd335 fix(reports): paid reports have no daily or hourly cap; a failed run is never counted (BUG-1641)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXozbkyFNqbu8pVEtZ7W
2026-11-05 23:29:17 +08:00
Claude cf08be14c0 Merge remote-tracking branch 'origin/staging' into codex/consult-career-field-20261105
# Conflicts:
#	docs/BUG_HISTORY.md
2026-11-05 22:43:59 +08:00
ClaudeandClaude Opus 5.5 1968218331 docs(annual): VOICE line follows the plain voice (BUG-1640)
Independent Staging Quality Gate / validate-python (push) Successful in 6m35s
Independent Staging Quality Gate / validate-frontend (push) Successful in 6m35s
Independent Staging Quality Gate / publish (push) Successful in 3m4s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXozbkyFNqbu8pVEtZ7W
2026-11-05 22:32:57 +08:00
ClaudeandClaude Opus 5.5 8face773e3 fix(annual): plain voice round 3 — short spoken house names, overview in three paragraphs, no repeats, concrete advice (BUG-1640)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXozbkyFNqbu8pVEtZ7W
2026-11-05 22:24:00 +08:00
ClaudeandClaude Opus 5.5 01eeb45b68 fix(annual): plain voice after a live DeepSeek run — planet placements stated, look-back only for past phases, why lines are sky events (BUG-1640)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXozbkyFNqbu8pVEtZ7W
2026-11-05 22:17:39 +08:00
ClaudeandClaude Opus 5.5 ca35ef2061 feat(annual): plain voice — life-first copy from a plain-language layer, one paragraph per area, months allowed (BUG-1640)
The writer now reads houses as parts of life, turning points as plain sky
sentences and months instead of dates; a one-page guide with passages from
the approved sample replaces the ban list, and each section sees what the
earlier ones said. Areas are one paragraph plus a 记住 line; window cards
show topic and action with a folded plain 为什么.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXozbkyFNqbu8pVEtZ7W
2026-11-05 22:12:50 +08:00
ClaudeandClaude Opus 5.5 2d65773c06 fix(annual): no 顺/紧 verdicts, wording slips no longer stop a report, a waiting card shows the step (BUG-1640)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXozbkyFNqbu8pVEtZ7W
2026-11-05 22:07:01 +08:00
ClaudeandClaude Opus 5.5 28ab75edc3 fix(consult): the obvious/possible sorting rule is not explained to the user (BUG-1633 round 2)
Round 1 blind eval: answers narrated the sorting rule back
(「这两处一致,所以这一层可以算明显」) and sentences reading out counts went
28 -> 59 / 36. The clause now says a point goes under obvious only when
another placement backs it, and the sorting is not explained to the user.
VISIBLE VOICE stays at 2,182 characters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 21:10:01 +08:00
ClaudeandClaude Opus 5.5 5255f1662e fix(consult): named techniques are written as the user named them; the user's framing wins; affliction counts stay unspoken (BUG-1633)
A staging career answer to a question naming D1 houses, D10, A10 and AmK
wrote every item as 「代表事业的那颗星」, half-excluded a field despite
「不凭星盘排除某个职业」, put over-certain points under 明显倾向 and read out
「两处受冲」. VISIBLE VOICE now says: items the user named are written as
named, with chart, sign, house and planet, a few plain words on meaning,
once each; the user's own framing wins (no sentence ruling a kind of work
or setting in or out when asked not to exclude; obvious only with two or
more agreeing placements). 受冲 joins the term-table words that are not
named, and the judgment table's count is not reported to the user. Voice
2,182 -> 2,174 (the pressure clause defers to the card lines; two copyable
comfort quotes and an optional numbering note go).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 21:10:01 +08:00
ClaudeandClaude Opus 5.5 b14e65f413 fix(consult): career boundary line says the house life-area gloss is not work content and planet nature is not working style (BUG-1632)
The remaining 27 / 72 severe career answers turned the 10th lord's or
AmK's house into work content through the house life-area gloss (6th ->
handling problems, 8th -> taking on hard cases, 2nd -> talking and money)
and planet nature into working style (Mercury -> speaking and writing, D10
Saturn -> rules and process). The card's career `boundary` line now names
AmK and says the life-area gloss is not work content and planet nature is
not working style; the "how far" clause goes (the field-ask rule already
answers it with strength, resistance and timing). Line 135 -> 142.

A first version (a35f1847) also folded the rule's quoted 「不在台前」 list
and CAREER_SIGNIFICATOR_STRENGTH_RULE into the line; the blind eval had
severe 34 -> 52 / 72 with front-stage denials back, so the rule and
checklist stay as on staging.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 21:10:01 +08:00
ClaudeandClaude Opus 5.5 a09fcaf188 revert(consult): BUG-1632 first version (folded the 「不在台前」 list into the card line; severe 34 -> 52 / 72)
This reverts commit a35f1847b14fc53c797447b23d4d1ab82baf6a4a.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 21:10:01 +08:00
ClaudeandClaude Opus 5.5 75a5fe24fb fix(consult): career boundary line also covers work content, working style and size; placements give support, effort and timing only (BUG-1632)
The remaining 27 / 72 severe career answers turned the 10th lord's house
into work content through the house life-area gloss (6th -> handling
problems, 8th -> taking on hard cases, 2nd -> talking and money), planet
nature into working style (Mercury -> speaking and writing, D10 Saturn ->
rules and process) and strength or SAV into scale. The card's career
`boundary` line now says what kind of work, how it is done and how big it
is are not on the chart, that the 10th / 10th lord / AmK / A10 / AL
placements only give where the career gets support, where it costs effort
and when it moves, and that the life-area gloss is not work content and
planet nature is not working style; what the user said stands.
CAREER_SIGNIFICATOR_STRENGTH_RULE folds into it and the field-ask rule's
A10 / AL clause points at it. Instruction size: rule 293 -> 196, career
checklist 870 -> 705, card line 135 -> 210 (net -165).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 21:10:01 +08:00
ClaudeandClaude Opus 5.5 1ef62f30ec feat(chart): 盘面数据 fills its card — 八分法 spans the width, every yoga shows with what it needs (BUG-1639)
Independent Staging Quality Gate / validate-python (push) Successful in 6m30s
Independent Staging Quality Gate / validate-frontend (push) Successful in 6m24s
Independent Staging Quality Gate / publish (push) Successful in 2m57s
The 八分法 table is width 100% with fixed columns and full-width 32px cells (a
640px minimum keeps the drag on phones). The 瑜伽 tab lists all eight classical
yogas as a two-column grid: formed ones first and still a pick on the board,
the rest muted with their classical condition, in place of one sentence and a
collapsed 「未满足 N 条」.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-05 18:31:44 +08:00
ClaudeandClaude Opus 5.5 1698837486 fix(annual,chart): 年运 starts a new run instead of reopening the last; chart type picker centred on desktop (BUG-1637, BUG-1638)
Independent Staging Quality Gate / validate-frontend (push) Failing after 2m10s
Independent Staging Quality Gate / validate-python (push) Successful in 6m28s
Independent Staging Quality Gate / publish (push) Skipped
- 年运: the page no longer opens the finished report of the same range; only a
  run still being written opens by itself. The server reuses only that in-flight
  run; a finished year no longer blocks a new one, which is charged once like
  any report. The start card says 「这一年已经写过一份,再写一份会另扣 N 点」
  with a link to the last one; history still opens from 过往的报告.
- 星盘类型: from 768px the picker is a centred dialog (560px, full radius);
  phones keep the bottom sheet. The body and the select / close logic are shared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-05 18:04:05 +08:00
ClaudeandClaude Opus 5.5 6f24b41381 feat(annual): 这一年怎么走 timeline (option B); body copy drops dasha jargon and method talk (BUG-1636)
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate-python (push) Canceled after 2m51s
Independent Staging Quality Gate / validate-frontend (push) Canceled after 2m52s
The remaining phases and the windows render as one timeline: phases carry
the program's lean, each window is pinned to its phase, passed ones fold.
Window fields are capped so cards fit without an inner scroll; reports
written earlier keep the old layout. Writer rules and the gate keep dasha
and functional-role words, the counting method and the material itself
out of the body.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXozbkyFNqbu8pVEtZ7W
2026-11-05 17:53:59 +08:00
ClaudeandClaude Opus 5.5 f4f38f1a54 fix(annual): no more 有顺有紧; windows and 年尾 get the program's lean (BUG-1635)
Lean v2 is a weighted sum (AD 2, Narayana AD 2, PD 1; a tie follows the
Vimshottari AD) with only 偏顺 / 偏紧 / 平稳. Phases with both sides keep a
counterweight limit. Window, domain-window, year-end and remember evidence
carry the lean; the gate rejects mixed wording and a window lean that
contradicts the program.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXozbkyFNqbu8pVEtZ7W
2026-11-05 17:45:38 +08:00
ClaudeandClaude Opus 5.5 876018e127 fix(reports): export sheet redesign; an English export lists itself in English (BUG-1634)
Independent Staging Quality Gate / validate-python (push) Successful in 6m34s
Independent Staging Quality Gate / validate-frontend (push) Successful in 6m36s
Independent Staging Quality Gate / publish (push) Successful in 3m33s
The sheet is now a top-to-bottom column with the footer pinned: 导出报告 and
the file type, a full-width 中文 / English segment, two equal radio cards for
整篇 / 自选 (outline and dot only, per issue #90), and in 自选 a title filter
with 全选 / 清空 above a tighter list with sticky group heads. The group names
and the summary follow the chosen edition (Chapters / Charts / Tables, 「95
chapters · 21 charts · 8 tables」); the sheet's own controls stay in the app's
language. Rows in the scrolling body no longer shrink.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-05 17:32:37 +08:00
ClaudeandClaude Opus 5.5 2536603970 feat(chat): a finished answer no longer shows 已完成 N 步
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate-frontend (push) Canceled after 6m43s
Independent Staging Quality Gate / validate-python (push) Canceled after 6m52s
The product owner asked to drop the settled step entry under answers
(「没啥用」). The live 正在分析 timeline above an answer being written stays;
the footer toggle, its step panel and their styles are removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 17:24:12 +08:00
ClaudeandClaude Opus 5.5 c5331e5530 feat(reports): the full report leads 我的报告, 年运 ranges are radio cards, the reader has one bar (BUG-1631)
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate-frontend (push) Canceled after 48s
Independent Staging Quality Gate / validate-python (push) Canceled after 57s
Product picked A / B / A on the canvas.
- 我的报告 (A): the full natal report is the one large card with a solid
  生成报告; 年运 is a single row link under it. A report row's hover and focus
  band now spans the link and its ⋯ menu, so a row no longer looks split.
- 年运 start (B): 生日年度 / 公历年 / 未来十二个月 are three single-choice
  cards with a dot, a one-line hint, and the picked card's dates.
- Reader (A): SecondaryHeader gains `back` (‹ 我的报告 /) and the language
  switch and 导出 move into it (ReportActions placement="header"); the second
  bar is gone, the text is no longer in a card on screen (print unchanged),
  the reading column is 720px and the contents rail opens only the current
  chapter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-05 17:17:29 +08:00
ClaudeandClaude Opus 5.5 3fa0bc574b fix(reports): 生成报告 shows the curtain and opens the report; 年运 veil fills the page (BUG-1630)
Independent Staging Quality Gate / validate-frontend (push) Successful in 6m36s
Independent Staging Quality Gate / validate-python (push) Successful in 7m35s
Independent Staging Quality Gate / publish (push) Successful in 2m49s
The report center passed onCreated={() => void load()}, so a successful create
only re-read the list below: no move, no notice, a faint 「正在创建…」 at most.
The button now holds the page curtain while it submits and opens the created
report, whose page shows the writing progress; an error drops the curtain and
says why. The 年运 page took the content's height inside the start-aligned
page grid, so its veil stopped short of the window bottom; it now fills the cell.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-05 16:59:48 +08:00
ClaudeandClaude Opus 5.5 484b653ce3 feat(rectification): open the case from the click, the home only takes it (BUG-1629)
Independent Staging Quality Gate / validate-python (push) Successful in 7m21s
Independent Staging Quality Gate / validate-frontend (push) Successful in 7m29s
Independent Staging Quality Gate / publish (push) Successful in 3m24s
Direction B for 「为什么不能直接进入生时纠正对话」. The open request, the case
read, the source lookup and the surface chunk now start at the click that
leads to the rectification chat (the /rectification page's 开始 / 继续上次 /
新建一次 / 看结果, and a 生时校正 row in the sidebar off the home), while the
app navigates. The home's openRectificationCase takes that in-flight open
(same target, once, within 30 s) instead of asking again; errors are handled
exactly as before. The offer card inside a conversation still asks itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-05 16:38:08 +08:00
Claude af0c51b387 Merge remote-tracking branch 'origin/staging' into codex/consult-career-line-20261105
# Conflicts:
#	docs/BUG_HISTORY.md
2026-11-05 16:33:43 +08:00
Claude d20c802e74 Merge remote-tracking branch 'origin/staging' into codex/astrologer-166c-20261105
Independent Staging Quality Gate / validate-frontend (push) Canceled after 0s
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate-python (push) Canceled after 42s
2026-11-05 16:32:28 +08:00
ClaudeandClaude Opus 5.5 ba735aef0a fix(rectification): open a case behind the page curtain, never over the blank home (BUG-1628)
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate-python (push) Canceled after 6m32s
Independent Staging Quality Gate / validate-frontend (push) Canceled after 6m28s
The /rectification page's 开始 / 继续 go to `/?rectify=…`; the home painted its
blank starter (「正在打开生时校正…」 in the composer) until the case opened
over the network, and a `?c=` rectification session showed the home the same
way until its surface opened. The rectification hook now knows a queued open
from the first render until it settles, and while a case is opening the home
holds the page curtain at once (new `immediate` hold, no 140 ms show delay) and
renders nothing. A failed open drops the hold and shows its error as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-05 16:26:38 +08:00
Claude d9598e9319 Merge remote-tracking branch 'origin/staging' into codex/astrologer-166c-20261105
# Conflicts:
#	docs/BUG_HISTORY.md
2026-11-05 16:25:40 +08:00
ClaudeandClaude Opus 5.5 db0acb2a21 feat(chart): give the board the card's area — two control rows, drawing up to 720px (BUG-1627)
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate-frontend (push) Canceled after 5m57s
Independent Staging Quality Gate / validate-python (push) Canceled after 6m2s
Direction A from the layout canvas. The visible 北印度盘 title row goes (the
name stays for screen readers); row one keeps the chart type strip; row two
puts the caption (D1 · ascendant · degree) on the left and the 图层 menu plus
a compact 北 / 南 switch on the right. The caption loses its tinted 44px strip,
the degree never yields to the dasha chips (they shrink, then hide under
600px), and the drawing may grow to 720px. The skeleton follows the same two
rows; skeleton motion is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-05 16:17:11 +08:00
ClaudeandClaude Opus 5.5 e54fb6f35c test: repoint the composer handler slices after the home curtain hold (BUG-1613)
Independent Staging Quality Gate / validate-python (push) Successful in 6m41s
Independent Staging Quality Gate / validate-frontend (push) Successful in 6m49s
Independent Staging Quality Gate / publish (push) Successful in 2m56s
Three contracts cut page.tsx's Enter handler at "\n\n  if (!hydrated",
which became "const booting = …" when the home started holding the shell's
page curtain. Two failed in the staging gate (run #2196); the IME contract
passed only because indexOf returned -1 and sliced to the end of the file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-05 15:41:14 +08:00
ClaudeandClaude Opus 5.5 7827d9aff0 chore(rectification): re-freeze after the BUG-1622..1626 renumber (ERR-110)
The renumber (093da446) changed comments in shadbala.py and both replay
scripts, so the frozen identity moved. On top of staging 849343cd:
FREEZE / REPORT constants first, --freeze, then replay:
astrologer_166d_2026_11_05; contract rotated with previous =
astrologer_166c_2026_11_05 (kept byte-for-byte).

Versus astrologer_166c_2026_11_05 and astrologer_166b_2026_11_04: sealed 20
and reported offset 900 all identical, metrics and summary identical,
historical changed_trial_count 10 / 731. Still scoring-15; no tuning.
BUG-1622 records the second re-freeze.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 15:35:31 +08:00
ClaudeandClaude Opus 5.5 093da4468d docs: renumber this branch's records BUG-1613..1617 -> BUG-1622..1626
Another session shipped a different BUG-1613 (loading curtain) to staging.
Mapping in order: 1613->1622, 1614->1623, 1615->1624, 1616->1625,
1617->1626, in BUG_HISTORY headings and bodies, CHANGELOG, ledger, research
notes, code comments, rule text, test notes and the holdout contract text.
Text only. shadbala.py and the two replay scripts are in the frozen identity,
so an ERR-110 re-freeze follows in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 15:32:05 +08:00
ClaudeandClaude Opus 5.5 3c81ebf3cf chore(rectification): re-freeze sealed holdout and offset sweep for the #166 2026-11-05 labels (ERR-110, BUG-1613..1617)
shadbala.py (frozen identity) changed in 5ffef30a: labels, comments and the
shared mercury_malefic_companions() helper, no value change. Scoring identity
stays rectification-v5-matrix-scoring-15; no ALGORITHM_VERSION bump.

FREEZE / REPORT constants first, --freeze, then replay (after all code
commits of this branch, 09fd3a42): astrologer_166c_2026_11_05; contract
rotated with previous = astrologer_166b_2026_11_04 (kept byte-for-byte).

Versus astrologer_166b_2026_11_04, trial by trial:
- sealed 20: all identical; metrics identical (top-1 0.40, top-3 0.45, mean
  minute error 6.95); historical changed_trial_count still 10.
- reported offset 900: all identical; summary identical (top-1 hits at
  +-15/30/60 4/3/0, top-3 31/34/30, delivery coverage at +-15 219, mean top-1
  minute error 20.52); historical changed_trial_count still 731.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 15:31:43 +08:00
ClaudeandClaude Opus 5.5 28969a4b07 fix(consult): career boundary card line; health and career limits are analysis instructions, not narrated (BUG-1621)
Career sections carry one fixed analysis-only `boundary` line under the
label: public vs behind-the-scenes and the size of fame, standing or scale
are not on the chart; the answer neither asserts nor denies them and does
not tell the user about the limit; placements give effort or cost; "how
far" is answered with support, resistance and timing. The career rule drops
the copied gloss 「要经手、要绕路、来得晚」; the AL line points at the card.

The health pressure line now marks the range as a judgement placed inside
the parts to watch, and tells the model not to add a sentence about the
chart's limits or about what it will not write (BUG-1620 eval: such
sentences 16 -> 56). No-leak checks cover 盘分不出 / 往高往低 / 不替你.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 15:30:27 +08:00
ClaudeandClaude Opus 5.5 849343cd21 feat(ui): one loading curtain for every page entry, drawn as a North Indian chart (BUG-1613)
Independent Staging Quality Gate / validate-frontend (push) Failing after 4m52s
Independent Staging Quality Gate / validate-python (push) Successful in 6m55s
Independent Staging Quality Gate / publish (push) Skipped
- New ChartDrawLoader (direction B from the loader canvas): outer square,
  diagonals, inner diamond drawn in turn, the lagna house lights, repeat.
  Still under prefers-reduced-motion.
- PageCurtain moves into the app shell: in the server HTML, full window over
  sidebar and page, held by usePageCurtain. Cold load shows it from the first
  paint; in-app navigation shows it only after 140 ms (pages already in memory
  never flash it), keeps it at least 650 ms, fades in 360 ms; one hold lets go
  after 12 s. The main.app-loading DOM contract is kept for the first-paint
  fallback and stale-client recovery on every page.
- Held by: home (with the natal panel), chart (first entry only), people,
  reports list, opening a report, ephemeris, annual, rectification entry,
  synastry picker. Home's own curtain (boot-curtain.tsx) is removed.
- The in-page waits that remain (dasha layer, people dropdown, birth editor,
  birth-time assessment, report and synastry writing) use the same motion at
  small size. Skeletons keep their motion: switching person, system or layer
  on the chart still shows them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-05 15:29:37 +08:00
ClaudeandClaude Opus 5.5 5ec2ac8424 revert(consult): ship health only; career rule and checklist back to staging wording (BUG-1621)
The career rewording did not clear the blind-eval bar (severe 43 -> 36, CI
includes 0; claims moved to 「不在台面上」). CAREER_FIELD_ASK_RULE, the AL
checklist line and their test go back to 928aa5c6. BUG-1620 is marked for
staging, BUG-1621 stays investigating (next: a server card line).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 15:24:54 +08:00
ClaudeandClaude Opus 5.5 172a270b69 feat(home): one boot curtain over all three columns; natal panel ready at reveal (BUG-1613)
- The cold-boot loader now covers the whole window (sidebar, chat, natal
  panel) and fades off the finished page instead of cutting to it.
- The natal panel's code and chart load behind the curtain and count in the
  reveal gate (same 4 s prepare budget); the home HTML sends the chart read
  in its first round, and ChatChartFrame takes the preloaded module in its
  first render.
- Before the viewport is measured the shell frame is "pending" and sized by
  media query plus the remembered width (sync <head> script), not by its
  content, so the sidebar no longer starts ~184px wide and jumps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
2026-11-05 14:46:10 +08:00
ClaudeandClaude Opus 5.5 8252571572 fix(consult): server-counted health pressure line; career placements give effort and cost, never fame size (BUG-1620 / BUG-1621)
Health: the card's health section carries a `pressure` line under its label,
counted by the shared evidenceCardPressureSignals over the lagna, its lord,
Sun and Moon (a luminary in 6 / 8 / 12 counts) and D6 for signal 5. Two or
more: the line is under pressure, the range runs from wear to a problem that
needs a doctor, the answer does not call the constitution sound or recovery
strong, strength fields do not cancel it, and each part says when to get
checked. The checklist drops its sample range, the 「底子不差」 ban and
「力量只用来说恢复从哪里来」, and points at the card line.

Career: CAREER_FIELD_ASK_RULE no longer glosses weak A10 / AL / Sun / 10th
lord placements as 「要经手、要绕路、来得晚」 (echoed into answers as fame
arriving late or thin); placements give effort or cost only, and the size of
fame, visibility, standing or scale is not on the chart, up or down. The AL
checklist line no longer reads AL as the strength of fame. Rule 306 -> 306.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 14:16:14 +08:00
ClaudeandClaude Opus 5.5 531a047413 fix(consult): health leads say what to watch, rules say what to write instead of 「不替……断定」, pattern phrase is the user's own reaction (BUG-1603 round 2)
- Health checklist: no verdict on overall constitution; each part's bold lead
  says what to watch and when or under what conditions; strength only says
  where recovery comes from. The quotable 「身体这条线有压力的迹象」 is gone.
  (Round-1 blind eval: health severe 3 -> 7, 「身体底子中上 / 不虚」.)
- 「不替他 / 用户断定」 in the VISIBLE VOICE biography red line,
  AFFLICTION_RANGE_RULE and CAREER_FIELD_ASK_RULE, and 「不替对方做决定」 in
  the persona line, now say what to do (write only as far as the chart goes;
  the field is left to the closing ask). 「我不替你」 went 10 -> 15 in round 1.
  「不替」 joins the no-leak list.
- The pattern phrase names the user's own way of acting or reacting, not a
  situation (round 1 had 「两头都压着」).

VISIBLE VOICE 2,162 -> 2,182 characters (still below the 2,228 before BUG-1603).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 12:53:02 +08:00
ClaudeandClaude Opus 5.5 af6b4cb41e fix(consult): answers open on the user's life, one bold conclusion per part, no copied rule words; age line for marriage and career (BUG-1603, BUG-1604)
- VISIBLE VOICE: the shape statements are replaced in place (2,228 -> 2,162
  chars): the first paragraph says what this looks like in the user's life,
  no chart talk; one part of the question per paragraph, each opening with a
  bold plain conclusion; at most two placements per judgment with the
  mechanism; scenes on the user's own side only; two or three things to do at
  the end, by date segment for timing. One plain phrase for the user's own
  pattern is allowed (product 2026-11-05), never about another person.
  New red line: beyond the one range and one ask, the answer does not tell the
  user what it will not say or decide.
- PLAIN_TERMS: one term table shared by VISIBLE VOICE and PLAIN_SPEECH_RULE;
  no fixed glosses (functional roles are not named, acronyms not printed).
- The career ask loses its example sentence; the pressure line keeps its
  logic without 两头 / 留着 / 按…写 / 不替用户选; the dual-dasha rule says
  what to write instead of a quotable sentence.
- BUG-1604: marriage (>= 40) and career (>= 50) sections carry a server
  `life_stage` line computed like parents_life_stage; no birth data reaches
  the model.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 12:52:57 +08:00
ClaudeandClaude Opus 5.5 2057538c81 fix(skills): create the skill runtime alias root on first use and remove it at exit (BUG-1612)
Independent Staging Quality Gate / validate-python (push) Successful in 6m27s
Independent Staging Quality Gate / validate-frontend (push) Successful in 6m31s
Independent Staging Quality Gate / publish (push) Successful in 2m58s
Every node process that imported skill-package-registry left a
jyotisha-skill-runtime-* directory in the OS temp dir (9,933 on the shared
host, most of them empty), which helped exhaust inodes (ERR-117).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-05 12:04:26 +08:00