Coming back to / from /people could show the previous rectification session
as a locked page: its title in the header, the composer stuck on
"正在打开生时校正…", and the new-chat greeting in the middle.
The state that survived between pages is the sessionStorage login-return
stash that secondary-page sidebar links write from the current ?c=:
- /people「和 TA 对话」used a second intent (?newChat=1) parsed by a
component mounted inside Home after bootstrap, so the bootstrap new-chat
branch never ran and the stash won.
- A stash id not in the current person's loaded list was looked up and
landed with urlAction "keep", which assumes ?c= is already in the address
bar. It was not, so the rectification auto-open never fired. The stash
also ignored which person was current.
- An in-page new chat left the stash in place.
Fix: delete NewChatDeepLink / ?newChat and route「和 TA 对话」through
newChatHref(); a looked-up stash writes ?c= back (replace-selected) and is
dropped when it belongs to another person; startNewChat and
openChatBoundToProfile clear the stash. ?c= deep links, BUG-989 and BUG-705
are unchanged.
Tests: new real-lifecycle suite mounting the real Home, sidebar and people
page (10 cases: four secondary pages + mobile drawer, 和 TA 对话 for self and
another person, out-of-scope stash, same-person stash beyond the first page,
in-page new chat), plus two contract/unit tests. Six fail on origin/staging,
all pass here. Full suite 3928 / 61 failing, failure names identical to the
0ab061b9 baseline (3916 / 61).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
- /people had zero CSS rules for its people-archive classes. Add the
approved layout: list -> detail below 1024px (data-view, ?person= history
entry so Back returns to the list), two columns at 1024px and above;
avatar rows with the current person highlighted, time cards with a
rectified state, readable ayanamsa name, three quick actions; delete moves
to the bottom of the edit view with unchanged confirm/count logic.
- Ephemeris: Chinese-first panchanga names from the brief's table only
(panchanga-names-zh.ts, three listed aliases, unknown names stay
Sanskrit), coloured 吉/中/凶 tags, N吉/M凶 counts and a fixed-rule day
summary (pure function, no model call); the header ask button becomes a
bottom hint card; transit rows show glyph, 「行星 在 星座」, house line and
degree; the Lahiri note names the subject's own ayanamsa.
- API, engine and database unchanged; /people and /ephemeris stay Static.
- DESIGN, VOICE, BUG_HISTORY, CHANGELOG, BLOCKED, PROGRESS and a manual
checklist updated. Two existing assertions changed, with 原值/新值/原因.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
Validate on Linux Node 22 and PostgreSQL 17: 3894 frontend tests and 64 database tests pass, with no removed test names or new failures. Preserve static Home, bounded gzip, assertion-change records and manual acceptance gaps.
Co-Authored-By: Claude Code <noreply@anthropic.com>
Chart, ephemeris, reports, daily language, consult, and synastry read birth data only through resolveSubjectBirth. The current person is a request parameter outside Home(). /people replaces the settings chart pane, and deleting someone removes that person's chats and reports.
The dasha tab leads with a now card and a duration bar, and keeps sub-periods inside the current details element. A zero-year Chara row stays grey, shows 0 年, and cannot expand. The tropical wheel uses a 520 view box, element bands, separated planet labels, and aspect lines that stay visible while a selected body is highlighted.
New reports request reader_main from upstream origin/main 23b9609e.
KP and transit no longer copy an empty vars() dict, solar returns keep
birth_asc_sign_idx, and ordinary projection deletes internal lines whole.
A zero-year Chara period is shown as 0 years instead of failing the whole chart. Switching ephemeris dates drops the previous day immediately and can be retried. Missing birth data links to chart settings.
Add bounded chart loading, per-layer retry states, and shared SVG skeletons. Add report block downloads with SVG, localized metadata, and inline deletion.
Record verification and retain CRLF export, full-build, and controlled-device acceptance blockers. User authorized staging delivery with these gaps documented.
Co-Authored-By: Claude Code <noreply@anthropic.com>
Create a fresh local consultation for explicit new-chat navigation and keep reserved recovery from taking over its landing. Add regression tests and record validation gaps for remote review.
Co-Authored-By: Claude Code <noreply@anthropic.com>
Gate run 2857 on 36a73761 ran 3,762 tests with one failure, the report
snapshot database test, so it is the last thing between staging and a deploy.
The brief told the executor to move the shared psql and psqlAs helpers to
stdin. That instruction is withdrawn. The two helpers serve 522 calls across
29 test files, and psql -c runs a multi-statement string as one implicit
transaction. selectAsAuthenticated relies on that: it sets the JWT subject
with set_config(..., true), which lasts only for the current transaction.
Statement-at-a-time execution would run every later RLS query with no user
set, so those tests would stop testing what they claim to test. Five other
files also write their own begin, commit or rollback.
The brief now asks for a separate single-transaction stdin helper with an
explicit maxBuffer, used only by the snapshot test, with a test proving a
transaction-local set_config stays visible. It also says that if the snapshot
test then fails a real assertion, that is a product defect to report, not an
assertion to relax.
Privacy scan on this tree before push: zero findings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
Preserve the parallel staging acceptance documentation while retaining the verified run 2857 failure evidence and deployment blocker.
Co-Authored-By: Claude Code <noreply@anthropic.com>