test(ai): expand AI flow and clipboard semantic coverage

- Cover reply-variant decision paths, scene-detector abstention, and
  the merged reply center stance catalog.
- Lock in clipboard semantic analyzer thresholds, complaint-only
  suppression, and existing-skill routing.
- Add durable session, refresh, and managed-gateway reliability tests
  for the Apple account path.
- Verify personal-style prompt derivation, low-confidence ASR
  tendencies, and Polish style learning against real corpus evidence.
- Exercise the assistant keyboard and Polish styles UI flows in
  end-to-end UI tests.
This commit is contained in:
Rocky
2026-08-29 11:51:25 +08:00
parent 3c10d73d7f
commit b275b6b0d9
15 changed files with 1348 additions and 125 deletions
@@ -241,6 +241,37 @@ final class ClipboardReplyFeedbackStoreTests: XCTestCase {
XCTAssertNil(example.playfulCandidate)
}
func testSceneDecisionTeachesStyleOnlyAfterUserFinalEdit() throws {
let candidate = ClipboardReplyCandidateSnapshot(
kind: .invitationDecline,
text: "谢谢邀请,不过这次先不去了。",
emotion: "grateful"
)
let recordID = try XCTUnwrap(
store.begin(
sourceText: "周六一起吃饭吗?",
candidates: [candidate],
styleID: "user.personal"
)
)
store.recordSelection(
recordID: recordID,
candidateID: candidate.id,
answerID: candidate.id
)
XCTAssertTrue(store.learningExamples().isEmpty)
store.recordFinalEdit(
answerID: candidate.id,
text: "这周六不行,下次约~",
revision: 1
)
let example = try XCTUnwrap(store.learningExamples().first)
XCTAssertEqual(example.selection, .contextual)
XCTAssertEqual(example.finalEdit, "这周六不行,下次约~")
}
private func makeCandidates(
suffix: String = ""
) -> [ClipboardReplyCandidateSnapshot] {