chore(release): bump version to 2.1.6 (build 131)

Version: CURRENT_PROJECT_VERSION 130 -> 131 (project.yml, AGENTS.md, READMEs,
docs/llms.txt).

fix(flow): host-app identification now compiles in every build configuration
(Debug, TestFlight, Release). The arbiter probe and HostAppIdentity were
DEBUG-only, so TestFlight/App Store builds never knew the host bundle id and
could not auto-return after a startflow handoff. Debug-only logging and the
Home test card are unchanged.

Also includes the pending work in the tree:
- Home: single account/setup card surface (HomeAccountSurfacePolicy/Views)
- Wide screens: voice key row and centred mic placement, iPhone Duo layout
- Keyboard: clipboard skill ranking and AI skill layout updates
- Debug: account session handoff to the Simulator (+ import script)
- Docs: portfolio assets, privacy policy URL, site/README refresh
This commit is contained in:
Rocky
2026-10-29 11:54:13 +08:00
parent 055a40976f
commit 4dce67df84
65 changed files with 3682 additions and 787 deletions
@@ -133,6 +133,60 @@ final class ClipboardSkillSemanticRankerTests: XCTestCase {
XCTAssertLessThan(try XCTUnwrap(translateIndex), try XCTUnwrap(speakAsMeIndex))
}
/// Device-language text + a configured target → "Translate to <target>",
/// and never the foreign-text actions (system translate / polish).
func testSystemLanguageTextOffersTranslateToTarget() {
let recommendations = ClipboardSkillSemanticRanker.recommended(
skills: Self.catalogWithoutOptInSkills,
sourceText: "明天下午三点开会,别迟到。",
analysis: analysis(language: "zh"),
uiLanguage: .chinese,
limit: 5,
preferredLanguages: ["zh-Hans-CN"],
translationTargetLocaleId: "en"
).map(\.id)
XCTAssertTrue(recommendations.contains(AIClipboardSkillCatalog.translateToTargetID))
XCTAssertFalse(recommendations.contains(AIClipboardSkillCatalog.translateID))
XCTAssertFalse(recommendations.contains(AIClipboardSkillCatalog.polishOriginalID))
}
func testTranslateToTargetIsHiddenWhenTranslationIsOffOrTargetMatchesText() {
for target in [TranslationLanguageCatalog.offLocaleId, "zh-Hans"] {
let recommendations = ClipboardSkillSemanticRanker.recommended(
skills: Self.catalogWithoutOptInSkills,
sourceText: "明天下午三点开会,别迟到。",
analysis: analysis(language: "zh"),
uiLanguage: .chinese,
limit: 5,
preferredLanguages: ["zh-Hans-CN"],
translationTargetLocaleId: target
).map(\.id)
XCTAssertFalse(
recommendations.contains(AIClipboardSkillCatalog.translateToTargetID),
"target \(target)"
)
}
}
/// Foreign text: system translate + polish, never translate-to-target.
func testForeignTextOffersPolishButNotTranslateToTarget() {
let recommendations = ClipboardSkillSemanticRanker.recommended(
skills: Self.catalogWithoutOptInSkills,
sourceText: "I has a meeting tomorrow, please dont be late.",
analysis: analysis(language: "en"),
uiLanguage: .chinese,
limit: 5,
preferredLanguages: ["zh-Hans-CN"],
translationTargetLocaleId: "ja"
).map(\.id)
XCTAssertTrue(recommendations.contains(AIClipboardSkillCatalog.translateID))
XCTAssertTrue(recommendations.contains(AIClipboardSkillCatalog.polishOriginalID))
XCTAssertFalse(recommendations.contains(AIClipboardSkillCatalog.translateToTargetID))
}
func testTranslationIsNotRecommendedForSystemLanguage() {
let recommendations = ClipboardSkillSemanticRanker.recommended(
skills: Self.catalogWithoutOptInSkills,
@@ -161,6 +215,7 @@ final class ClipboardSkillSemanticRankerTests: XCTestCase {
recommendations,
[
AIClipboardSkillCatalog.translateID,
AIClipboardSkillCatalog.polishOriginalID,
AIClipboardSkillCatalog.replyID
]
)
@@ -523,7 +578,8 @@ final class ClipboardSkillSemanticRankerTests: XCTestCase {
recommendations.map(\.id),
[
AIClipboardSkillCatalog.translateID,
AIClipboardSkillCatalog.replyID
AIClipboardSkillCatalog.replyID,
AIClipboardSkillCatalog.polishOriginalID
]
)
}