fix: avoid duplicate rectification errors

This commit is contained in:
Jesse_Chen
2026-07-19 20:24:44 +08:00
parent aeef08f79e
commit 82d48c0777
4 changed files with 10 additions and 11 deletions
@@ -69,6 +69,8 @@ export function BirthTimeRectification(props: BirthTimeRectificationProps) {
const heading = dynamicHeading(action);
const error = props.controller.error || props.externalError;
const showsProgress = action.kind !== "ask_dynamic_choice" && action.kind !== "clarify_unmatched_answer";
const childOwnsError = action.kind === "ask_dynamic_choice"
|| action.kind === "clarify_unmatched_answer";
const showsCandidate = action.kind === "present_low_result"
|| action.kind === "present_medium_result"
|| action.kind === "request_candidate_confirmation"
@@ -122,7 +124,7 @@ export function BirthTimeRectification(props: BirthTimeRectificationProps) {
journey={props.journey}
/>
) : null}
{error && !showsCandidate ? <p className="form-error" role="alert">{error}</p> : null}
{error && !showsCandidate && !childOwnsError ? <p className="form-error" role="alert">{error}</p> : null}
</section>
);
}
@@ -141,15 +141,6 @@ export function guidedBirthTimePreview(mode: string): JourneyClientResponse {
progress: { ...response().progress, phase: "adaptive", baselineDomainCount: 3, confirmedEvidenceCount: 3, adaptiveRound: 1 },
});
}
if (mode === "birth-time-rectification-low") {
return response({
snapshot: { ...response().snapshot, state: "candidate", input: "candidate_actions", confidence: "low", assistantIntent: "explain_event_evidence_insufficient" },
candidateResult: { ...candidate, confidence: "low", canApply: false },
turnVersion: 6,
nextAction: { kind: "present_low_result", resultId },
progress: { ...response().progress, phase: "result", baselineDomainCount: 3, confirmedEvidenceCount: 4, adaptiveRound: 3 },
});
}
const candidateSnapshot = {
...response().snapshot,
state: "candidate",
@@ -34,6 +34,7 @@ test("draft revision publishes its new version before confirmation can fail", as
});
test("low without a result and saved medium both return to declared-time editing safely", () => {
const dynamicLow = dynamicBirthTimePreview("low");
const low = guidedBirthTimePreview("birth-time-rectification-low");
const nullResultLow = parseJourneyResponse({
...low,
@@ -42,6 +43,7 @@ test("low without a result and saved medium both return to declared-time editing
});
const saved = guidedBirthTimePreview("birth-time-rectification-saved");
assert.equal(dynamicLow.candidateResult, null);
assert.deepEqual(guidedTerminalPath(nullResultLow), {
kind: "edit_birth_time_details",
preservesCase: true,
@@ -121,6 +123,7 @@ test("ready completion is explicit and terminal low has no finish mutation", ()
test("terminal candidate owns one explicit next step and its completion error", () => {
const candidateResultSource = readFileSync(new URL("../src/components/birth-time-candidate-result.tsx", import.meta.url), "utf8");
const choiceQuestionSource = readFileSync(new URL("../src/components/birth-time-choice-question.tsx", import.meta.url), "utf8");
const rectificationSource = readFileSync(new URL("../src/components/birth-time-rectification.tsx", import.meta.url), "utf8");
const legacyRectificationSource = readFileSync(new URL("../src/components/birth-time-legacy-rectification.tsx", import.meta.url), "utf8");
const globalCssSource = readFileSync(new URL("../src/app/globals.css", import.meta.url), "utf8");
@@ -130,7 +133,9 @@ test("terminal candidate owns one explicit next step and its completion error",
assert.match(candidateResultSource, /正在采用 \$\{path\.time\}…/);
assert.match(candidateResultSource, /birth-time-next-step/);
assert.match(rectificationSource, /error=\{error\}/);
assert.match(rectificationSource, /error && !showsCandidate/);
assert.match(rectificationSource, /const childOwnsError = action\.kind === "ask_dynamic_choice"\s*\|\| action\.kind === "clarify_unmatched_answer"/);
assert.match(rectificationSource, /error && !showsCandidate && !childOwnsError/);
assert.equal(choiceQuestionSource.match(/role="alert"/g)?.length, 1);
assert.match(legacyRectificationSource, /error=\{error\}/);
assert.match(legacyRectificationSource, /error && !showsCandidate/);
assert.match(globalCssSource, /\.birth-time-next-step/);
@@ -33,6 +33,7 @@ test("low-confidence preview mirrors the persisted dynamic terminal state", () =
assert.equal(low.snapshot.state, "rectifying");
assert.equal(low.nextAction.kind, "present_low_result");
assert.ok(low.candidateResult);
assert.equal(low.candidateResult.winningSegment?.representativeTime, "05:21");
assert.equal(low.nextAction.resultId, low.candidateResult.resultId);
assert.deepEqual(guidedTerminalPath(low), {
kind: "complete_with_candidate",