#!/usr/bin/env python3 """Apply the reviewed deployment thresholds and pinned model selections.""" from __future__ import annotations import argparse import json import shutil from pathlib import Path DEFAULT_RESOURCE_DIRECTORY = Path( "OSGKeyboardShared/Resources/ClipboardSemantics" ) DEFAULT_BASELINE_DIRECTORY = Path( "ModelTraining/ClipboardSemantics/baselines/2026-08-26-nine-model-v1" ) # Core thresholds were selected on the 680-record development holdout and # checked against the golden gate. Task and complaint were later tightened on # focused development gates; the 20260830 release profile is acceptance-only. THRESHOLD_POLICY = { "task": { "global": 0.88, "byLanguage": {"en": 0.88, "zh-Hans": 0.73}, }, "complaint": { "global": 0.82, "byLanguage": {"en": 0.84, "zh-Hans": 0.82}, }, "scheduleNegotiation": { "global": 0.68, "byLanguage": {"en": 0.68, "zh-Hans": 0.53}, }, "confirmationDecision": { "global": 0.72, "byLanguage": {"en": 0.72, "zh-Hans": 0.72}, }, "followUpReminder": { "global": 0.73, "byLanguage": {"en": 0.73, "zh-Hans": 0.73}, }, "blessing": { "global": 0.69, "byLanguage": {"en": 0.69, "zh-Hans": 0.77}, }, } PINNED_MODELS = { "scheduleNegotiation": "ScheduleNegotiationIntentClassifier.mlmodel", } def parse_arguments() -> argparse.Namespace: parser = argparse.ArgumentParser() parser.add_argument( "--resource-directory", type=Path, default=DEFAULT_RESOURCE_DIRECTORY, ) parser.add_argument( "--baseline-directory", type=Path, default=DEFAULT_BASELINE_DIRECTORY, ) parser.add_argument( "--candidate-resource-directory", type=Path, default=None, ) parser.add_argument( "--promote-classifier", action="append", default=[], ) return parser.parse_args() def main() -> None: arguments = parse_arguments() resource_directory: Path = arguments.resource_directory baseline_directory: Path = arguments.baseline_directory manifest_path = resource_directory / "clipboard-semantic-models.json" manifest = json.loads(manifest_path.read_text(encoding="utf-8")) classifiers = { classifier["id"]: classifier for classifier in manifest["classifiers"] } promoted_classifiers = arguments.promote_classifier if promoted_classifiers: candidate_directory: Path | None = arguments.candidate_resource_directory if candidate_directory is None: raise RuntimeError( "--candidate-resource-directory is required when promoting classifiers" ) candidate_manifest_path = ( candidate_directory / "clipboard-semantic-models.json" ) candidate_manifest = json.loads( candidate_manifest_path.read_text(encoding="utf-8") ) candidates = { classifier["id"]: classifier for classifier in candidate_manifest["classifiers"] } for classifier_id in promoted_classifiers: if classifier_id not in candidates: raise RuntimeError( f"Cannot promote missing classifier: {classifier_id}" ) candidate = dict(candidates[classifier_id]) candidate["trainedAt"] = candidate_manifest["generatedAt"] candidate["trainingCorpusRecordCount"] = candidate_manifest[ "corpusRecordCount" ] model_file = candidate["modelFile"] shutil.copy2( candidate_directory / model_file, resource_directory / model_file, ) if classifier_id in classifiers: classifiers[classifier_id].clear() classifiers[classifier_id].update(candidate) else: manifest["classifiers"].append(candidate) classifiers[classifier_id] = candidate missing = sorted(set(THRESHOLD_POLICY) - set(classifiers)) if missing: raise RuntimeError(f"Manifest is missing classifiers: {missing}") for classifier_id, policy in THRESHOLD_POLICY.items(): classifier = classifiers[classifier_id] classifier["acceptedForAutomaticRouting"] = True classifier["confidenceThreshold"] = policy["global"] classifier["confidenceThresholdsByLanguage"] = policy["byLanguage"] for classifier_id, model_file in PINNED_MODELS.items(): source = baseline_directory / model_file destination = resource_directory / classifiers[classifier_id]["modelFile"] if not source.is_file(): raise RuntimeError(f"Pinned model is missing: {source}") shutil.copy2(source, destination) manifest_path.write_text( json.dumps(manifest, ensure_ascii=False, indent=2, sort_keys=True) + "\n", encoding="utf-8", ) print( "DEPLOYMENT_POLICY_DONE " f"thresholds={len(THRESHOLD_POLICY)} pinnedModels={len(PINNED_MODELS)} " f"promotedModels={len(promoted_classifiers)}" ) if __name__ == "__main__": main()