Commit Graph
74 Commits
Author SHA1 Message Date
jesse-ux e760b1d610 fix(consult): 窗口溢出重试保留预跑证据包,回填修复版本 SHA
Independent Staging Quality Gate / validate (push) Successful in 10m28s
Independent Staging Quality Gate / publish (push) Successful in 10m58s
2026-09-18 18:47:01 +08:00
jesse-ux 53d78137ff fix(consult): 申报时段计算改为服务端预跑并走同请求缓存(BUG-957)
窗口计算挂在 agent context 缓存上,模型开口前预跑并注入 packet;工具再调用命中同请求缓存,成功次数仍为 1。
2026-09-18 18:45:19 +08:00
jesse-ux e32ce6247e fix(consult): BUG-945~949 领域截断、思考分片、Pass 4 按模式分流
schema 上限与执行上限解耦;校正思考改分片门;日期观察不删字,保证句与无分钟个人盘退回重写。
2026-09-18 13:17:35 +08:00
jesse-ux 94c1e81fa9 feat(consult): 进度、思考、正文三通道在生成时分开(BUG-942/943/944) 2026-09-18 12:16:20 +08:00
Jesse_ChenandClaude Fable 5.1 84b293fb47 feat(consult): 对话口气改成反差与扮演象的形状
Independent Staging Quality Gate / validate (push) Failing after 7m5s
Independent Staging Quality Gate / publish (push) Skipped
产品判定现有人设(懂行、可靠、说人话的占星师朋友)出来的是顾问报告。
人设改成把人当一个人认真对待、行动力很强、嘴有点毒但靠谱的同事:直接、
有立场、带一点锋利,毒只对处境不对人且每句锋利都要有盘上的证据。

开场从「一句结论 + 2–3 条短要点 + 一句下一步」换成固定形状,三种模式共用:
反差(表面 A 底下 B,命名成一个格局)→ 谁在推、谁在修(大运主星在推,
行运只负责把结果修得体面)→ 别去应 X 的象,去扮演 Y 的象 → 最多三条短行动
(破折号短句,各 ≤ 20 字)。仍无标题、总长 ≤ 400 字。术语当场用引号里的
白话套住。申报时段与无出生分钟两条降级路线形状照给,只把「谁在推谁在修」
换成窗口内稳定层或公开日历,不编月份。

新增希望纪律:盘上有转机且 answer_policy 允许精确应期时说到月份;没有就说
这段时间是拿来干什么的、可以扮演哪个象。禁「一切都会好 / 相信自己 / 加油 /
你值得更好的 / 宇宙自有安排」。

零业务逻辑改动,Skill 版本不变。tsc 0 错、lint 0 error(118 warning 不变)、
npm test 3468→3471 条且 36 条失败与基线 ff0427cf 逐条相同、/ 仍 Static、
首屏 gzip 两侧字节相同。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
2026-09-17 16:18:07 +00:00
jesse-ux 6d81062be9 fix(web): 校正会话上不再出现可用的普通输入框
Independent Staging Quality Gate / validate (push) Canceled after 5m37s
Independent Staging Quality Gate / publish (push) Canceled after 0s
send() 对校正会话不发 /api/consult,草稿保留并打开校正面。
普通输入框只有禁用态。咨询接口把类型不对改成 409 session_not_consultation。
删除和回退不再直接切到校正会话。
2026-09-17 20:06:25 +08:00
jesse-ux dc2f2a16bb fix(consult): 每一轮回答前都必须调用排盘工具
Independent Staging Quality Gate / validate (push) Successful in 9m22s
Independent Staging Quality Gate / publish (push) Successful in 13m39s
2026-09-17 14:21:33 +08:00
jesse-ux 149e1ec4c3 fix(consult): drop traces, budget checkpoints, silent summary inherit
Independent Staging Quality Gate / validate (push) Canceled after 3m8s
Independent Staging Quality Gate / publish (push) Canceled after 0s
BUG-729: dropped history rounds leave an omission marker in the model-visible summary slot.
BUG-730: checkpoint threshold is 0.4 of historyBudgetChars (128k still 16,000).
BUG-731: session_full new chat copies owned context_summary on the server; clients send only continued_from_session_id.
2026-09-16 07:38:36 +08:00
jesse-ux 8144fca27d fix(chat): fold natal reports and drop homepage topic cards
Independent Staging Quality Gate / validate (push) Failing after 9m47s
Independent Staging Quality Gate / publish (push) Skipped
Homepage no longer waits on /api/onboarding for six starter questions.
Natal answers show the spoken layer first; the Level 2 skeleton sits in a
collapsed 完整分析 block. Wide tables scroll sideways on a phone. Form
inputs are 16px so iOS does not zoom on focus.
2026-09-15 12:27:16 +08:00
Jesse_ChenandCursor c53decdb85 fix(consult): complete natal chart tool on homepage topic cards (BUG-630)
Thinking models were spending the first natal step on skill_read or a Level 2 draft, so home chips such as 家庭 never satisfied the calculation contract.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 22:46:46 +08:00
Jesse_ChenandCursor 17b36f3a9f fix(consult): pin daily entrypoint domains and sentence-filter thinking (BUG-612/613)
Independent Staging Quality Gate / validate (push) Successful in 10m6s
Independent Staging Quality Gate / publish (push) Successful in 2m4s
Homepage「深入看今日」was rewritten to natal 综合, then each compose slice burned its only step on a tool call, so the answer stayed empty. Pin the route theme, write the three daily sections with tools disabled, and filter thinking by sentence so English word-salad cannot leak.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 17:38:08 +08:00
Jesse_ChenandCursor 814c924e4a fix(rectification): exhaustion exit, explain layer, range reading, unknown-time scan (BUG-565–568)
Independent Staging Quality Gate / validate (push) Successful in 9m20s
Independent Staging Quality Gate / publish (push) Successful in 6m51s
Keep askable cards after exhaustion, explain each probe, read the adopted credible range in reports and chat, and compare declared periods before the minute grid when the clock is unknown.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-07 09:10:37 +08:00
Jesse_ChenandCursor 0102a973a3 fix(web): persist generated session titles against the post-RPC title (BUG-557)
The first-round title guard compared the pre-RPC snapshot, so append_consultation_question had already rewritten the title and the model name never landed.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-06 19:22:43 +08:00
Jesse_ChenandCursor bf8ad0d1ff fix(web): keep consultation conclusions across turns and surface cache hits (BUG-555, BUG-556)
Session history was silently clipped to the first 4000 characters of the last 12 messages, so follow-ups could not see timing or audit tables. Keep an append-only tail plus a checkpoint summary, retry overflow in the same request, and expose cache hit rate in admin usage.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-06 15:16:18 +08:00
Jesse_ChenandCursor a1956deb63 fix(web): summarize session titles, sort by activity, and paginate history (BUG-553)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-06 14:34:30 +08:00
Jesse_ChenandCursor 5483649bc1 fix(api): stop labeling database blips as unconfigured (BUG-542)
Deploy-window connection errors were translated into "服务尚未配置".
Only real configuration errors keep that copy; other 503s use service_unavailable.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-06 12:37:21 +08:00
Jesse_ChenandCursor b6a70aa7df fix(ayanamsa): pin Lahiri on reference sets and add a user setting
Product default stays Raman. Public-case revalidation and fixture dashas now pass --ayanamsa lahiri; profiles store the four selectable values.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-03 16:33:46 +08:00
Jesse_ChenandClaude Fable 5 80e7736163 Merge PR #48: humane agent voice with boundary semantics intact
Independent Staging Quality Gate / validate (push) Failing after 11m3s
Independent Staging Quality Gate / publish (push) Has been skipped
Reviewed: tsc + rectification/voice 757 + consult 289 green; E-1 predicate
verified structural (no body-text matching); boundary phrases preserved in
delivery turns. Conflict: BUG entry renumbered 467→469.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
2026-09-01 20:49:06 +00:00
Jesse_ChenandCursor ed9497e76a fix(voice): speak first, then keep Level 2 skeleton and boundary semantics
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>
2026-09-02 02:27:50 +08:00
Jesse_ChenandCursor 56daf6be49 fix(consult): pass birth-time accuracy instead of treating every chart as unrectified
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>
2026-09-02 01:21:40 +08:00
Jesse_ChenandCursor b6989c3eea fix(chat): make the server the only writer of session messages
Independent Staging Quality Gate / validate (push) Has been cancelled
Independent Staging Quality Gate / publish (push) Has been cancelled
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>
2026-09-01 19:51:19 +08:00
Jesse_Chen 47b4b06bfb fix(rectification): surface pricing failures and persist opening question
Independent Staging Quality Gate / validate (push) Successful in 12m42s
Independent Staging Quality Gate / publish (push) Successful in 22m34s
2026-08-31 15:16:23 +08:00
Jesse_Chen 3a762e1fca feat(billing): record prompt cache usage 2026-08-31 09:59:53 +08:00
Jesse_Chen 6e13949d3b feat(billing): resolve chat and rectification pricing by feature 2026-08-31 04:29:45 +08:00
Jesse_ChenandCursor 31b54aa71d fix(frontend): say the database is missing, not Supabase
Independent Staging Quality Gate / validate (push) Successful in 9m34s
Independent Staging Quality Gate / publish (push) Successful in 7m21s
Self-hosted PostgreSQL is the runtime. A missing APP_DATABASE_URL
must not tell users the retired hosted service is unconfigured.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 09:44:53 +08:00
Jesse_ChenandCursor 04463e9af3 feat(web): show consult runs as a Lucide timeline with sliced compose
Keep provider thinking on a separate channel so process talk is not billed as the spoken reply (BUG-359).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-23 14:38:50 +08:00
Jesse_ChenandCursor 0ca7da997f fix(web): stop consultation thinking from pinching the answer
Disable provider thinking so Flash CoT cannot fill max_tokens, raise the
spoken budget to 16384, emit a server-owned step tree, and continue once
when the body ends on length.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-22 21:19:00 +08:00
Jesse_ChenandCursor 8ed6118b9a fix(web): persist uncertain birth time as a start/end clock window
Users pick a clock range instead of a coarse period plus notes, so
rectification and window consult scan that range instead of a leftover afternoon bucket.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-22 20:48:01 +08:00
Jesse_ChenandCursor 59559d4b24 fix(web): persist thinking, title sessions distinctly, and send follow-ups from the answer
Thinking disappeared on failure and never reached session storage. Keep the
sanitized chain on disk and on errors, and regroup the sidebar around reports,
charts, favorites, and dated history titles.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-22 09:10:47 +08:00
Jesse_ChenandCursor 9958e00abc fix(web): keep unrectified birth data usable without inventing a minute
Rectification stays optional. Reported minutes can consult and generate reports; date-plus-period uses a declared window instead of a midpoint or 00:00. Updates BUG-341.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-21 15:29:58 +08:00
Jesse_ChenandCursor 8010245981 feat(product): present consult and rectification in local skill form
Independent Staging Quality Gate / validate (push) Failing after 6m42s
Independent Staging Quality Gate / publish (push) Has been skipped
Default ayanamsa to Raman with true_pushya support, attach governed Raman packets, restore Path C questionnaires and eight-method verification copy, and keep unique-minute confirmation blocked.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-20 21:42:47 +08:00
Jesse_ChenandCursor 7d667fecbf fix(consult): treat pinched answers as failed and restore reply actions
Incomplete Flash generations were billed as completed consultations. Fail
those runs, keep the partial text, and reuse the rectification like/copy/rerun
bar on ordinary chat replies.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 19:40:50 +08:00
Jesse_ChenandCursor e635c40224 fix(consult): fold the technique audit out of the spoken answer
Independent Staging Quality Gate / validate (push) Has been cancelled
Independent Staging Quality Gate / publish (push) Has been cancelled
Keep comparative tables in chat, but hide the long audit behind a collapsed control so the reply stays readable.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 15:29:04 +08:00
Jesse_ChenandCursor 2bf7472645 fix(consult): run the local skill's full technique spectrum on the web path
Independent Staging Quality Gate / validate (push) Successful in 10m59s
Independent Staging Quality Gate / publish (push) Successful in 9m7s
Web answers were thinner than a local Agent calling yinduzhanxing-skill:
theme-subset vargas, no visible audit table, and a prompt that dropped the
invocation contract. Bind the commercial method, compute D1–D60 plus Western
layers, and deliver the same Full-Spectrum checklist.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 23:30:36 +08:00
Jesse_ChenandCursor d04fc30b63 feat(consult): bind the skill method into the prompt instead of re-activating it every turn
Independent Staging Quality Gate / validate (push) Successful in 10m34s
Independent Staging Quality Gate / publish (push) Successful in 11m10s
Activating the skill answered with the entrypoint plus a flat listing of every
file in the package, and nothing carried over between requests: the agent is
rebuilt per request, no thread memory is configured, and the replayed history is
plain question/answer text. So the model re-activated on every turn and paid for
that listing every time, twice more whenever a retry opened a fresh model loop.

The method is now read from the hash-verified package and bound into the
instructions, and the activation tools are withdrawn while skill_read stays. The
agents also stopped loading from the working-tree view, whose reference listing
no hash covered - only SKILL.md was compared - so what the model sees is finally
what the registry pinned.

Withdrawing an activation the model could forget also removes the failure it
mostly produced: the contract no longer waits on a model action for method, and
the no-birth-time path has no contract left to repair.

Measured against this package: activation 118,352 bytes, bound method 47,289.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 21:47:15 +08:00
Jesse_ChenandCursor ff70ba87b0 feat(consult): deliver the route's strict method with the evidence instead of listing 1592 filenames
Activating the skill returned 129,651 bytes, of which 99KB was a flat list of
1,592 undifferentiated file paths against 30KB of actual method. The one line
telling the model to open the strict-workflow router sat inside that method,
so no reference was ever opened and every answer was composed from the model's
own background knowledge over server evidence.

The route is already decided server-side and the skill already states which
checklist each route requires, so the selection needs no model turn: read the
mandated sections from the hash-pinned package and hand them to the model with
the evidence they apply to. A route the router declares no checklist for is
reported as such rather than filled in with another route's.

The receipt now reports delivered sections separately from model-initiated
reads, because only one of those is under the model's control.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 20:53:07 +08:00
Jesse_ChenandCursor 927bdd7a21 fix(consult): compute the antardasha boundaries answers need, and stop billing an apology for an unwritten answer
Independent Staging Quality Gate / validate (push) Failing after 8m32s
Independent Staging Quality Gate / publish (push) Has been skipped
The model packet read chart.modules.dasha_boundaries, a key the engine never
wrote, so no answer ever had sub-period boundaries while the receipt still
reported precise timing as allowed. The server now cuts the running mahadasha
into antardashas out of the periods the packet already shows, exposes them as
their own evidence section, and precise timing requires that section.

A run whose calculation succeeded and whose model then wrote nothing was
answered with a fixed apology and billed as completed. It now asks once more
against the cached calculation, and fails with empty_answer—no charge—if that
attempt is silent too.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 18:32:49 +08:00
Jesse_ChenandCursor 46f38422f6 fix(consult): speak like a person instead of a calculation report
Independent Staging Quality Gate / validate (push) Failing after 7m21s
Independent Staging Quality Gate / publish (push) Has been skipped
Keep skill truth boundaries, but stop asking the model to announce skipped domains or parrot tool JSON.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 17:54:42 +08:00
Jesse_ChenandCursor 52f3c04b3b refactor(chat): remove the post-answer suggestion chips and the table that fed them
Measured use of the three chips above the composer was negligible. They
were also not what they appeared to be: the server looked up a fixed
triplet by session theme and passed it as metadata that overrode
anything the model produced, so the same ten hardcoded sets served every
user regardless of question or chart. That is a plausible reason nobody
pressed them.

Both copies of the per-theme table are gone, reply metadata narrows to
the session title, and the two parse entry points collapse into one now
that they return the same shape. The write schema still tolerates a
suggestions field so a client on the previous bundle does not lose its
message mid-deploy, and stored answers containing the legacy hidden
block are still stripped rather than shown raw.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 15:44:19 +08:00
Jesse_ChenandCursor 10ae149c58 fix(consult): check the evidence gate against the route the answer is on
Independent Staging Quality Gate / validate (push) Successful in 7m41s
Independent Staging Quality Gate / publish (push) Successful in 9m39s
七条路由的证据门都不是自己的:route_requirements 的键写成 relationship/finance,而
路由名是 marriage/wealth,另有 5 条路由压根没有条目,全部静默落到 general 的门。
missingLayers: [] 因此不表示证据齐备,只表示没检查过——婚姻的 UL 与财富的 D2 从未
进入检查。

同一函数另有两处判据也没接到权威来源。7 块正则用问题文本重猜领域,而领域早已由模型
声明并写进 route_packet,一句写作「情感」而非表里「感情」的提问在 marriage 路由上完全
拿不到性别解读边界。timing_layers_ready 读的是 missing_route_layers,该列表只装本路由
要求的层,于是对任何不要求 narayana_dasha 的路由恒为真,精确应期在该层根本没算出来时
也照样放行。三处的失败方向都是静默放宽,因此没有任何人报错。

三处都接回权威来源:10 条路由逐条显式列出必需层(层名限定为证据包真实构建的 section,
所以 wealth 不要求引擎不产出的 D11)、领域边界按 route 查表、出生时间边界从矫正闸门的
effective_accuracy 与 Lagna 敏感度派生、就绪判断直接读 section 状态。唯一保留文本探测
的是「用户有没有要一个具体日期」——服务端对此没有权威来源,改为 timing/annual 路由结构
性携带、文本仅作叠加,一次措辞漏判不再能把信号清零。

另外把 skillReferenceReadCount 暴露为回执的 skill.referenceReads(必填)与可观测日志的
skillReferenceReads。它此前数完即丢,而 skill_read 按设计不记成 runtime step,因此「模型
有没有真的翻开方法文档」在运行结束后无处可查。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 11:50:28 +08:00
Jesse_ChenandCursor 1955ba8cef fix(consult): give a multi-domain plan a top-level answer contract it can obey
A staging consultation submitted a three-domain plan, calculated all three
successfully in 62.9s, and returned nothing but the ensureFinalResponseText
fallback. The step budget was barely touched, so this is not the exhaustion
c8d9ec64 fixed. toModelDomainPlanContext returns two different shapes: a single
domain flattens the evidence packet to the top level, several domains return only
success, domains and consultations. Every hard output rule in jyotishInstructions
is written against those top-level paths — evidence_contract.answer_policy,
hard_blockers, rectification.boundary, status. None of them resolve in the
multi-domain shape, and under a policy that forbids stating anything the server
evidence does not support, silence is what the instructions ask for.

Merge the packets into one top-level contract shaped exactly like the single
domain one. Merging may only restrict: status takes the worst of ready >
degraded > blocked, hard_blockers and missing_route_layers take the union,
permission booleans need every domain to agree while limitation booleans need
only one, and a field the domains genuinely disagree on is reported as
unresolved rather than decided. available_layers is the one permission-shaped
union, because a layer really was computed for some domain and denying it would
deny real evidence. The natal projection is the same chart for every domain, so
it is hoisted to one copy when the domains agree and left per-domain when they
do not.

The domain cap was six, advertised as six, and could never be paid for. Domains
run sequentially at ~21s each against a cumulative 110s abort signal, so six is
~126s and four leaves nothing to write the answer with. Concurrency is not
available: the Python API is a single GIL-bound ThreadingHTTPServer whose async
work already sits behind a two-worker bounded queue that answers 503 when full.
Derive the cap from the clock instead of choosing it — 110s minus a 45s answer
reserve, divided by 21s, is three — and let the model-facing schema carry that
bound so an unpayable plan is unrepresentable. A caller that builds a plan
without that schema is truncated rather than refused, the loop stops early when
the measured pace says the next domain will not fit, and either way the dropped
domains are disclosed through omitted_domains and the receipt while status
degrades, so a partial answer cannot be presented as complete.

run.failed carried a code and nothing else, so the step durations, step budget
and workflow route recorded by c8d9ec64 were unavailable exactly when a run
needed explaining. Send the same allowlisted receipt run.completed sends,
built through publicConsultationRuntimeSteps so the internal failure code and
model loop diagnostics stay server-side, and never let building it replace the
failure event with a silent close. An agentic run that fails before
streamAgentResponse exists never reached the settle-and-log path either, so the
request-level catch now goes through the same entry point.

Refs BUG-256, BUG-257, BUG-258.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 17:05:56 +08:00
Jesse_ChenandCursor c8d9ec64c3 fix(consult): stop the model spending its step budget on invalid tool params
Independent Staging Quality Gate / validate (push) Successful in 13m24s
Independent Staging Quality Gate / publish (push) Successful in 10m13s
A staging consultation calculated the chart and then returned nothing but the
ensureFinalResponseText fallback. The model had made four calls to
run-jyotish-consultation, and two of them never reached a calculation: they set
both domains and theme, which canonicalDomainPlan rejects at execution. The
schema declared those two fields as independent optionals, the description never
mentioned the constraint, and the instructions actively told the model to use
theme for a single-domain retry. Each attempt therefore bought a rule the
contract never stated, and because the throw happens before the step-recording
try/catch, it left no trace in the receipt either.

Make the constraint unrepresentable instead of enforced. The model-facing schema
keeps only question and domains, so Mastra refuses the pair before the tool body
runs; the description states the single-array contract, and the instruction that
advertised theme is gone. canonicalDomainPlan still resolves the single-value
form for callers that build a plan without that schema, and is now exported so
that path has its own tests.

maxSteps and the abort timeout bound the same run but were hard-coded apart. One
calculation takes about 20s against a 110s budget, so time is the binding
constraint and three failed calculations exhaust it whatever the step count. The
budget only has to cover the longest useful shape, so it moves to 8 beside the
timeout with that reasoning recorded, and the recorded step list is sized to
match so an exhausted run cannot truncate its own evidence.

Step exhaustion was only ever inferable by counting events, since finishReason
was recorded nowhere and progressive-disclosure reads never reach the public
stream. Capture it as a closed enum plus a step count, normalizing anything
unrecognized, and log both as controlled fields. Neither may enter the client
receipt, whose step schema is strict and would fail a successful run.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 15:21:11 +08:00
Jesse_ChenandCursor 8169bd85f7 feat(consult): classify consultation workflow failures for diagnosis
Independent Staging Quality Gate / validate (push) Failing after 13m12s
Independent Staging Quality Gate / publish (push) Has been skipped
Every workflow fault except abort and timeout collapsed into the single
calculation_failed code, and the upstream message was discarded, so a failing
run left no evidence of whether the API rejected the call or returned a payload
that missed the response contract.

Classify failures into a closed vocabulary carried on ConsultationWorkflowError
and record it as the failureCode of the runtime step. The observability tool
call schema gains one controlled optional field; upstream error text stays out
of logs, as that contract requires. Forward request_id to the API so a run can
be aligned with its access log.

Build public receipts from an explicit allowlist. The internal failure code
must not reach the client contract, whose step schema is strict and would
otherwise reject a successful run.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 12:44:19 +08:00
Jesse_Chen f12a43ad1d fix(consult): allow reported-time precision and persist receipts
Independent Staging Quality Gate / validate (push) Successful in 12m1s
Independent Staging Quality Gate / publish (push) Successful in 9m50s
2026-08-16 16:59:16 +08:00
Jesse_Chen 0d59d51814 fix: allow public daily guidance without birth minute
Independent Staging Quality Gate / validate (push) Successful in 14m4s
Independent Staging Quality Gate / publish (push) Successful in 9m22s
2026-08-15 23:55:57 +08:00
Jesse_Chen 24fc83d972 Merge codex/pr2-final-response into staging integration 2026-08-15 12:27:00 +08:00
Jesse_Chen e58bc36909 test: add agent evals and safe observability 2026-08-15 07:06:19 +08:00
Jesse_Chen 6d192ad175 feat: add consultation and product domain registries 2026-08-15 06:04:23 +08:00
Jesse_Chen 65a75ab29f feat(consultation): enforce server plan boundaries 2026-08-14 20:22:52 +08:00
Jesse_Chen 09f811a79e fix(consultation): decouple reply metadata from prompt 2026-08-14 18:01:30 +08:00