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
- 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
- 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
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
- 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
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
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
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
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
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
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
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
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
- 年运: 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
- 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
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
- 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
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
- 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
- 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
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