fix(polish): gate test-build style generation at 1,250 chars and cap export at 5,000

Remove the test-mode unlimited personal-style corpus bypass and replace it with a real 1,250-character minimum gate. Production stays at 2,500. Training-corpus export and the diagnostics view now use a 5,000-character upper bound so the user's full private history never leaves the device in a single export.

- Add PolishStyleLearningCorpusBuilder.testBuildEffectiveCharacterCount (1,250) and trainingExtractionMaximumCharacterCount (5,000); trainingWindow(from:maximumCharacterCount:) accepts a custom cap.
- PolishStylesView: drop bypassesStyleLearningCharacterGate in favor of styleLearningMinimumCharacterCount, unify the ready/remaining text, remove the obsolete polishStyles.learn.testBuildReady key.
- PolishStyleCorpusExportStore: pass the 5,000 cap to trainingWindow and expose trainingExtractionMaximumCharacterCount in the export schema.
- FlowDiagnosticsSettingsView: show the export-sized (5,000-cap) corpus so the diagnostics match what the export ZIP actually contains.
- Tests: rewrite the export cap test for 5,000, add below-cap coverage, add trainingWindow(maximumCharacterCount:) unit coverage, and convert the old UI test into a regression test for the 1,250 test-build minimum.
- L10n: drop the testBuildReady string in en + zh-Hans, update diagnostics.corpus.ready to mention 5,000.
- CHANGELOG: bilingual entry under [Unreleased].
This commit is contained in:
Rocky
2026-08-30 12:09:06 +08:00
parent eac44daaf4
commit 3033ca5b33
11 changed files with 175 additions and 35 deletions
@@ -1,21 +1,29 @@
import XCTest
final class PolishStylesGenerationUITests: XCTestCase {
func testTestBuildCanGenerateWithoutPersonalCorpus() {
func testTestBuildRequiresTwelveFiftyCharacterMinimum() {
// The old "unlimited" test-mode bypass has been removed. Test
// builds now enforce a 1,250-character minimum: an empty corpus
// must keep the generation button disabled, and the visible
// progress text should reflect the remaining distance to the
// active gate.
continueAfterFailure = false
let app = launchServiceHarness(
additionalArgument: "--polish-styles-service-ui-test-no-corpus"
)
XCTAssertTrue(
let generate = app.buttons["polishStyles.learn.generate"]
XCTAssertTrue(generate.waitForExistence(timeout: 5))
XCTAssertFalse(
generate.isEnabled,
"Empty corpus in a test build must not unlock generation; the 1,250-character minimum still applies."
)
XCTAssertFalse(
app.staticTexts[
"Test build: 2,500-character limit disabled"
]
.waitForExistence(timeout: 5)
].exists,
"The old unlimited-bypass label must no longer be shown."
)
let generate = app.buttons["polishStyles.learn.generate"]
XCTAssertTrue(generate.exists)
XCTAssertTrue(generate.isEnabled)
}
func testGeneratedStyleReviewAndSaveFlow() {