feat(consult): answer the sentence asked — no motive guessing, follow-up turns answer directly, first turn says each thing once (BUG-1070~1073)
- Voice: contrast limited to chart structures; drop 「这句我按『……』理解了」; forbid motive/need sentences; yes/no answered first (BUG-1070) - Follow-up turn (session already holds an answer): ≤200-char direct answer, no skeleton; decided from stored history, no intent regex; tool still runs each turn (BUG-1071) - Thinking bar first section 「先回答你问的这件事」 (BUG-1072) - First turn: opener without actions, body headings 盘里支持 / 时间怎么看 / 这周可以做的一件事 only, actions once, ≤900 chars (BUG-1073, D8) - Checklist is a list to check, not paragraphs to write (T3) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0199rbQDTsUbCVw84wc8BTFe
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
2ce3c2165c
commit
9a42333a55
@@ -44,8 +44,9 @@ import { consultationPublicActivityEvent, streamAgentResponse } from "@/lib/stre
|
||||
import type { AgentExecutionReceipt, WorkflowReceipt } from "@/lib/consultation-agent-events";
|
||||
import {
|
||||
consultationContinueMessages,
|
||||
dailyAnswerShapeInstruction,
|
||||
natalAnswerShapeInstruction,
|
||||
followUpAnswerShapeInstruction,
|
||||
hasPriorAssistantAnswer,
|
||||
natalUserTurnShape,
|
||||
natalConsultationThinkingPlan,
|
||||
type PublicThinkingSection,
|
||||
} from "@/lib/consultation-thinking-plan";
|
||||
@@ -991,9 +992,11 @@ export async function POST(request: Request) {
|
||||
: "如需新的个人星盘结论,必须调用服务器绑定的排盘工具。";
|
||||
// The loop's own step after the calculation writes the answer (BUG-1053),
|
||||
// so the answer shape the removed compose prompt used to carry is here.
|
||||
const natalInstruction = consultEntrypoint === "daily_starlanguage"
|
||||
? `${natalToolInstruction}${dailyAnswerShapeInstruction()}`
|
||||
: `${natalToolInstruction}${natalAnswerShapeInstruction()}`;
|
||||
// A session that already holds an answer gets the follow-up shape
|
||||
// (BUG-1071): a direct answer, no skeleton. That is read from the stored
|
||||
// history, never from the wording of the question.
|
||||
const followUpTurn = hasPriorAssistantAnswer(history);
|
||||
const natalInstruction = `${natalToolInstruction}${natalUserTurnShape({ entrypoint: consultEntrypoint, history })}`;
|
||||
const adoptedRangeNote = consultationMode === "verified_chart"
|
||||
&& prepared.serverChart?.truth.birthTimeStatus === "accepted"
|
||||
&& prepared.serverChart.toolInput.candidate_range
|
||||
@@ -1311,6 +1314,7 @@ export async function POST(request: Request) {
|
||||
if (!prepared.serverChart) throw new Error("server_chart_truth_missing");
|
||||
state.thinkingPlan = natalConsultationThinkingPlan({
|
||||
domains: [consultationTheme],
|
||||
followUp: followUpTurn,
|
||||
});
|
||||
const agentContext = createConsultationAgentContext({
|
||||
userId,
|
||||
@@ -1320,6 +1324,7 @@ export async function POST(request: Request) {
|
||||
plan: prepared.preReserveResult,
|
||||
theme: consultationTheme,
|
||||
entrypoint: consultEntrypoint,
|
||||
followUpTurn,
|
||||
serverChart: prepared.serverChart,
|
||||
abortSignal: agentAbortSignal,
|
||||
state,
|
||||
@@ -1511,6 +1516,11 @@ export async function POST(request: Request) {
|
||||
{ birthTimeSource: prepared.serverChart.truth.birthTimeSource },
|
||||
);
|
||||
const workflowReceipt = consultationWorkflowReceipt(workflowContext);
|
||||
// The grounded fallback writes from the injected workflow; same first-turn
|
||||
// / follow-up split as the agentic path (BUG-1071), one statement of it.
|
||||
const legacyNatalInstruction = hasPriorAssistantAnswer(history)
|
||||
? followUpAnswerShapeInstruction()
|
||||
: "先用不超过 400 字口语直接回答下面的问题,不要加标题;形状为:先给反差(表面 A,底下 B,都是盘上的结构,命名成一个格局)、再说清谁在推谁在修、然后「别去应 X 的象,去扮演 Y 的象」;开场不写行动。然后按三个二级标题写:## 盘里支持这个判断的地方(原始结构、六步宫位、Yoga 表作为依据,只写开场没说过的,表格与正文二选一)、## 时间怎么看、## 这周可以做的一件事(最多三条行动,只在这里出现一次)。全文不超过 900 字。骨架不可省略;不写「先回答你的问题」这个标题,文末技法审计表由产品界面折叠展示,不写进正文。星盘事实只使用系统里已经注入的计算结果,不要复述内部字段、JSON 或再跑一遍咨询流程。";
|
||||
|
||||
const cacheBoundary = cachedSystemMessage("【上下文缓存边界】后续内容为本轮请求输入。", selectedModel.model);
|
||||
const legacyHistory = history.map((message) => message.role === "user"
|
||||
@@ -1527,7 +1537,7 @@ export async function POST(request: Request) {
|
||||
content: consultationUserTurnContent({
|
||||
currentTime: currentTimeContext(requestTime),
|
||||
name,
|
||||
instruction: "先用不超过 400 字口语直接回答下面的问题,不要加标题;形状为:先给反差(表面 A,底下 B,命名成一个格局)、再说清谁在推谁在修、然后「别去应 X 的象,去扮演 Y 的象」、收尾最多三条短行动(破折号短句,每条不超过 20 字);然后再按 skill Level 2 骨架写:原始结构、六步宫位、Yoga 表、时机、综合、文末技法审计表,最后才是现代生活。骨架不可省略。星盘事实只使用系统里已经注入的计算结果,不要复述内部字段、JSON 或再跑一遍咨询流程。",
|
||||
instruction: legacyNatalInstruction,
|
||||
summaryText: historyWindow.summaryText,
|
||||
droppedCount: historyWindow.droppedCount,
|
||||
question: resolvedQuestion.modelQuestion,
|
||||
@@ -1552,7 +1562,7 @@ export async function POST(request: Request) {
|
||||
content: consultationUserTurnContent({
|
||||
currentTime: currentTimeContext(requestTime),
|
||||
name,
|
||||
instruction: "先用不超过 400 字口语直接回答下面的问题,不要加标题;形状为:先给反差(表面 A,底下 B,命名成一个格局)、再说清谁在推谁在修、然后「别去应 X 的象,去扮演 Y 的象」、收尾最多三条短行动(破折号短句,每条不超过 20 字);然后再按 skill Level 2 骨架写:原始结构、六步宫位、Yoga 表、时机、综合、文末技法审计表,最后才是现代生活。骨架不可省略。星盘事实只使用系统里已经注入的计算结果,不要复述内部字段、JSON 或再跑一遍咨询流程。",
|
||||
instruction: legacyNatalInstruction,
|
||||
summaryText: historyWindow.summaryText,
|
||||
droppedCount: historyWindow.droppedCount,
|
||||
question: resolvedQuestion.modelQuestion,
|
||||
|
||||
Reference in New Issue
Block a user