Choice legends and spoken collect prompts were hidden after BUG-461, and occupation still blocked canAdopt once dated coverage was done. Restore visible stems and stop polling extra collects when adopt is allowed.
Co-authored-by: Cursor <cursoragent@cursor.com>
eslint-plugin-react-hooks now analyzes the smaller Home, so render-time ref writes and sync effect setState were failing the staging gate.
Co-authored-by: Cursor <cursoragent@cursor.com>
Keep async job and chart-cache files across API recreates, freeze jyotish_api_server.py growth, and fail fast with 429 when rectification or high-rigor compute is saturated.
Co-authored-by: Cursor <cursoragent@cursor.com>
Close the home-page split by moving account/onboarding and rectification glue out of page.tsx without relocating React state, keeping the route static and hook order intact.
Co-authored-by: Cursor <cursoragent@cursor.com>
Reviewed: tsc + consult 295 + rectification 747 + python suites green;
guard functions and window/general instructions verified unchanged.
Conflict: BUG entry renumbered 467→468 (467 taken by report-extraction).
Review fix: test_consultation_birth_accuracy.py added to CORE_PYTEST_TARGETS
(pytest-style file outside the rectification glob would never hit the auto gate).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
PROGRESS carries the engine contract snapshot (including the fields the
task brief assumed exist but the consultation API does not return), the
claim card before/after text, the per-section prompt growth table, the
knowledge pack inventory, and the actual quality-gate output.
BLOCKED records four things: no model credentials and no PostgreSQL here,
so the live writer comparison could not be produced; the per-section
prompt p50 landing at 2.83x raw (2.28x cost-weighted), which is over the
brief's 2x line and needs a decision rather than an evidence cut; and the
fact that /api/consultation_workflow serves the reduced prompt pack, so
the server narrative seeds the brief pointed at do not exist yet.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016P5RoqzmUQEbeC2qjAkeGr
The report writer had no interpretation methodology at all: a local agent
calling the jyotish skill can read the reference library, the report model
could read nothing. It could only restate the bundle.
- frontend/src/lib/report-interpretation-packs/ holds one general pack and
one pack per report theme, distilled from the in-repo reference guides.
They constrain wording and reasoning discipline (term modernisation,
how to talk about relative strength and SAV scores, the reasoning errors
to avoid, the banned phrasings) and never assert a chart fact.
- The general pack rides INSIDE the cached system message so the cached
prefix stays byte-identical across sections; the chapter pack follows it
and summary calls get the general pack only.
- Skill jyotish-personal-report goes to 1.1.0 (1.0.0 deprecated): the
contract now names interpretiveFacts and themeNarrativeSeeds as a
bounded fact layer and states that the knowledge pack is not a fact
source and cannot raise certainty.
- Telemetry records interpretiveFactCount and knowledgePackCharacters as
numbers only; the counter never throws so telemetry cannot break a run.
Tests lock every theme resolving a pack, the 3,000 character budget, a
forbidden-substring scan (paths, module names, vendor names, artefact
names), the byte-stable cache prefix, and that no evidence id or date
appears in the static content.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016P5RoqzmUQEbeC2qjAkeGr
The consultation workflow already returns a functional benefic/malefic
table, a shadbala ranking, SAV scores, the current maha/antardasha,
detected yogas and guided-topic copy. The report extraction layer threw
all of it away, so claim cards could only say "the server closed the
minimum evidence group" and the writer had no conclusions to work from.
- ReportEvidenceBundleV2 gains interpretiveFacts (yogas, functionalRoles,
shadbalaRanking, savScores/savTotal, currentDasha, convergenceDomains)
and themeNarrativeSeeds. Both are required, allow empty, keep .strict(),
are covered by the canonical sort + bundleHash, and fail closed on
dangling refs, duplicate ranks/houses/themes and out-of-bound text.
- Extraction is allowlist-style: closed enums for yoga category and
functional role, safeCelestialName for planets, sign->whole-sign-house
projection for SAV, and a forbidden-token scrub that drops any seed line
naming an external provider or internal route.
- Claim card conclusions and supportingFacts are now deterministic
astrological statements built from those facts; risks become
counterFacts. assertionLevel derivation is unchanged, and a theme with
no seed keeps the old receipt wording with consensus capped down.
- filterReportEvidenceBundleForSection trims seeds and SAV houses to the
chapter's theme while letting the chart-wide interpretive receipts ride
along, so every section can cite them.
Contract snapshot taken from a real local /api/consultation_workflow call
with fictional smoke birth data; the new fixture test locks the shapes
that call actually returns, including the fields that are absent.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016P5RoqzmUQEbeC2qjAkeGr
Keep archive as a PATCH of archived_at rather than DELETE, pass entry_mode through onboarding, and let popstate to the default chat reuse selectSession. Then move send/stop/recovery and session management out of page.tsx so the home surface stays within the batch-two line budget.
Co-authored-by: Cursor <cursoragent@cursor.com>
Natal answers were opening on parameter tables, and rectification turns were one-sentence legal copy. Centralize user-facing strings, keep representative-minute and question-slot red lines, and stop duplicating the opening collect prompt as a second assistant message.
Co-authored-by: Cursor <cursoragent@cursor.com>
Hospital records and adopted rectification times were still fed to the model as not_auto_rectified because the chart request omitted declared_accuracy/time_source and mastra hardcoded the boundary. Map profile truth into the engine request, keep rectified for accepted/confirmed active times only, and leave window/general guards unchanged.
Co-authored-by: Cursor <cursoragent@cursor.com>
page.tsx still owns the chat main chain, but the first product surfaces now
live in their own modules so later splits can land without editing the 4k-line
Home. Source-lock tests follow the moved tokens; the orphan user-data contract
is aligned and added to the quick gate.
Co-authored-by: Cursor <cursoragent@cursor.com>
Local fallbacks were creating fake saves and resurrecting deleted rows.
Pin and archive now live on chat_sessions so they follow the account.
Co-authored-by: Cursor <cursoragent@cursor.com>
Refresh, back, and login return were dropping the open conversation because selection lived only in React state.
Co-authored-by: Cursor <cursoragent@cursor.com>
List GET no longer ships transcripts; consult appends questions after reserve and ignores client history so dual-tab last-write-wins cannot erase messages.
Co-authored-by: Cursor <cursoragent@cursor.com>
subprocess.run does not shell-expand tests/test_rectification_*.py, so a
string pin could stay green while the suite never ran. Expand glob targets
to real files and fail closed on zero matches.
Co-authored-by: Cursor <cursoragent@cursor.com>
Window_scan assertions now match the public from_sign/to_sign contract, the
staging quick gate runs the rectification Python suite, and compare-candidates
rescores when stored policy lags the live engine identity.
Co-authored-by: Cursor <cursoragent@cursor.com>
Day-level events now score Vimshottari/Narayana transition closeness so
nearby candidate minutes can diverge, with gated quality probes and
answer-prior ranking so high-base-rate existence questions stay out.
Co-authored-by: Cursor <cursoragent@cursor.com>
deliveryCapability no longer ties adoption to minute separation or holdout;
those stay on the exact-minute confirmation gate so users can save a range.
Co-authored-by: Cursor <cursoragent@cursor.com>
Spoken collect no longer renders a second visual prompt; choice legends stay screen-reader only and live cards share the assistant inset. Exhaustion collect avoids colliding with the opening question id, and a successful billed turn no longer surfaces run_failed after the exit gate.
Co-authored-by: Cursor <cursoragent@cursor.com>
The previous pass closed the "adoptable on one event" hole but left no
forward path: case 645ba774 ends with can_adopt false and
current_question null, so the user is stuck with neither a result nor a
next question. Two causes: answer_choice never reaches
ensureNonTerminalTurnExit or persistNextInterviewIfIdle, all of whose
call sites sit in the message/opening branches; and once every probe is
answered or dropped, decideRectification returns offer_provisional_range
before the holdout branch, ignoring unused oos_blind prompts and the
nakshatra boundary question.
Same defect class as BUG-456, which was fixed by patching one branch
rather than gating every exit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVapmh2oGNyr6ECHKjPJY8
The registry packagePath points at versions/<version>/, but the root
SKILL.md copy makes it easy to hash the package root instead. Hashing
the root pulls the entire versions/ subtree into the digest and still
returns a value, so the mistake surfaces only as a failing gate later.
Records BUG-459 and corrects the task brief's D-2 table, which listed
the root SKILL.md as the hash target.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVapmh2oGNyr6ECHKjPJY8
The engine receipt says acceptance_allowed/selection_allowed false with
reasons insufficient_events and insufficient_domain_diversity, yet the
top-level projection flips both to true and renders adoptable candidates
after a single piece of evidence. Records the four structural causes:
dual decision authority where overlayPublicDecision lets TS override the
engine, insufficient-evidence sharing an exit with exhausted, capability
flags hardcoded across eleven branches, and several fail-open paths
including holdout "unavailable" granting adoption.
Also folds in the skill bump (D-2) after verifying that existing cases
bind their own skill_version and deprecated packages still resolve, so
no case migration is required.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVapmh2oGNyr6ECHKjPJY8
Traces the staging run_failed on the first user message to a missing
feature_pricing row: the opening turn is free and skips reserve(), so
the first `message` action is the first request to hit
resolve_feature_pricing, which raises feature_pricing_missing and maps
to the generic run_failed fallback. Also records the independent
opening-turn defect that leaves current_question null.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVapmh2oGNyr6ECHKjPJY8
Verified both round-1 briefs against the code rather than the progress
notes. Billing 0/1/2/3/6 and rectification 0/1/2/3/6 are in and clean, and
neither the confirmation gate nor the sealed holdout was loosened.
Two gaps remain. Prompt caching only emits its marker for Anthropic, so on
a DeepSeek-class provider it buys observability and no cost reduction, and
the membership fair-use numbers are untouched — correctly so, since no
real unit cost has been measured yet. The round-2 brief gates those on a
staging measurement pass and pulls the per-answer narrowing table forward,
since it is the deliverable and depends on nothing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu