From 2b62dbec3f306328098c41d3fdde9894acc98e0f Mon Sep 17 00:00:00 2001 From: idevlab Date: Fri, 16 Oct 2026 13:35:29 +0800 Subject: [PATCH 1/3] fix: sign Developer ID release disk images --- .github/workflows/release-artifact.yml | 3 + .../evidence/configuration-state.json | 16 + .../evidence/deployment-rules-after.json | 17 + .../evidence/environment-secrets-after.json | 30 + .../evidence/full-test-evidence.json | 13 + .../evidence/identity-check.json | 8 + .../independent-config-source-review.json | 8 + .../independent-final-approvals-readback.json | 39 + .../independent-final-jobs-readback.json | 253 ++++++ .../independent-final-run-readback.json | 230 ++++++ .../independent-final-verification.json | 63 ++ .../evidence/independent-local-readiness.json | 14 + .../evidence/main-branch-after.json | 104 +++ .../evidence/main-effective-rules.json | 50 ++ ...n-protection-independent-verification.json | 66 ++ .../evidence/main-ruleset-after.json | 67 ++ .../evidence/main-ruleset-before.json | 35 + .../evidence/main-ruleset-request.json | 44 + .../evidence/notarization-authentication.json | 6 + .../evidence/production-after.json | 53 ++ .../evidence/production-before.json | 12 + .../evidence/release-basic-checks.log | 252 ++++++ ...release-before-production-independent.json | 140 ++++ ...elease-final-independent-verification.json | 93 +++ .../release-first-failure-summary.json | 17 + ...elease-human-production-authorization.json | 11 + .../evidence/release-jobs-attempt-1.json | 1 + .../release-jobs-before-approval.json | 1 + .../evidence/release-pending-deployment.json | 1 + .../release-production-approval-readback.json | 39 + .../release-production-approval-response.json | 131 +++ .../evidence/release-readiness.json | 116 +++ .../evidence/release-run-started.json | 1 + .../evidence/release-tag.json | 12 + .../evidence/release-test-summary.json | 13 + .../evidence/repository-secrets-after.json | 15 + .../evidence/repository-secrets-before.json | 15 + .../evidence/source-sha256-before.json | 6 + .../2026-10-15-developer-id-ci/intent.md | 101 +++ .../2026-10-15-developer-id-ci/plan.md | 94 +++ .../2026-10-15-developer-id-ci/release.md | 131 +++ .../2026-10-15-developer-id-ci/spec.md | 123 +++ .../verification.md | 126 +++ .../basic-checks-python39-attempt-1.log | 107 +++ .../evidence/basic-checks.log | 115 +++ .../evidence/design-approval-snapshot.json | 12 + .../evidence/design-independent-review.json | 121 +++ .../evidence/evidence-retention.json | 29 + .../evidence/full-test-evidence.json | 14 + .../evidence/implementation-baseline.json | 776 ++++++++++++++++++ .../evidence/implementation-code-review.json | 68 ++ .../implementation-final-verification.json | 99 +++ ...uild-attempt-1-environment-correction.json | 7 + .../evidence/local-build-process.json | 1 + .../evidence/local-checks-summary.json | 52 ++ .../local-release-build-attempt-1.json | 15 + .../local-release-build-attempt-1.log | 127 +++ .../evidence/local-release-build.json | 16 + .../evidence/local-release-build.log | 195 +++++ .../evidence/merge-prerequisites.json | 27 + .../evidence/native-dmg-progress.json | 117 +++ .../evidence/native-dmg-verification.json | 132 +++ .../evidence/native-independent-rerun.json | 141 ++++ .../native-suite-independent-review.json | 110 +++ .../evidence/native-suite-preflight.json | 17 + .../evidence/native-tests-run.log | 43 + .../evidence/protected-swift-test.json | 16 + .../evidence/protected-swift-test.log | 5 + .../evidence/regression-verifier-after.log | 5 + .../evidence/regression-verifier-before.log | 74 ++ .../evidence/regression-workflow-after.log | 7 + .../evidence/regression-workflow-before.log | 12 + .../evidence/sdlc-checks.log | 34 + .../evidence/verification-handoff.json | 19 + .../verification-human-acceptance.json | 10 + .../intent.md | 79 ++ .../plan.md | 142 ++++ .../spec.md | 133 +++ .../verification.md | 110 +++ scripts/tests/test_release_artifact.py | 144 ++++ .../tests/test_release_workflow_contract.sh | 61 ++ scripts/verify-release-artifact.sh | 23 +- 82 files changed, 5783 insertions(+), 2 deletions(-) create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/configuration-state.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/deployment-rules-after.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/environment-secrets-after.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/full-test-evidence.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/identity-check.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-config-source-review.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-approvals-readback.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-jobs-readback.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-run-readback.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-verification.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-local-readiness.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-branch-after.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-effective-rules.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-protection-independent-verification.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-ruleset-after.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-ruleset-before.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-ruleset-request.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/notarization-authentication.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/production-after.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/production-before.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-basic-checks.log create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-before-production-independent.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-final-independent-verification.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-first-failure-summary.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-human-production-authorization.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-jobs-attempt-1.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-jobs-before-approval.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-pending-deployment.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-production-approval-readback.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-production-approval-response.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-readiness.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-run-started.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-tag.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-test-summary.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/repository-secrets-after.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/repository-secrets-before.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/source-sha256-before.json create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/intent.md create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/plan.md create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/release.md create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/spec.md create mode 100644 docs/sdlc/changes/2026-10-15-developer-id-ci/verification.md create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1.log create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks.log create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/design-approval-snapshot.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/design-independent-review.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/evidence-retention.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/full-test-evidence.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-baseline.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-code-review.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-final-verification.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-build-attempt-1-environment-correction.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-build-process.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-checks-summary.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.log create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/merge-prerequisites.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-progress.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-verification.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-independent-rerun.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-independent-review.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-preflight.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-tests-run.log create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.log create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-after.log create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before.log create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-after.log create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-before.log create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/sdlc-checks.log create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/verification-handoff.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/verification-human-acceptance.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/intent.md create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/plan.md create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/spec.md create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/verification.md create mode 100644 scripts/tests/test_release_artifact.py diff --git a/.github/workflows/release-artifact.yml b/.github/workflows/release-artifact.yml index e7fbb6d7..e89bfe58 100644 --- a/.github/workflows/release-artifact.yml +++ b/.github/workflows/release-artifact.yml @@ -176,6 +176,9 @@ jobs: ) if grep -q '^Authority=Developer ID Application:' <<<"$SIGNATURE"; then SIGNING_MODE=developer-id + codesign --force --sign "$SIGN_IDENTITY" --timestamp \ + --identifier com.opentype.voiceinput.dmg \ + "dist/Utter-$RELEASE_VERSION.dmg" VERIFY_ARGS+=(--require-developer-id) elif grep -q '^TeamIdentifier=not set$' <<<"$SIGNATURE"; then SIGNING_MODE=self-signed diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/configuration-state.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/configuration-state.json new file mode 100644 index 00000000..25fc5f06 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/configuration-state.json @@ -0,0 +1,16 @@ +{ + "phase": "configured", + "attempted_secret_names": [ + "APPLE_ID", + "APPLE_TEAM_ID", + "APPLE_APP_PASSWORD", + "APPLE_CERTIFICATE_PASSWORD", + "APPLE_CERTIFICATE_P12" + ], + "cleanup_errors": [], + "temporary_keychain_deleted": true, + "keychain_search_list_restored": true, + "temporary_private_directory_removed": true, + "configuration_success": true, + "success": true +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/deployment-rules-after.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/deployment-rules-after.json new file mode 100644 index 00000000..7743af91 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/deployment-rules-after.json @@ -0,0 +1,17 @@ +{ + "total_count": 2, + "branch_policies": [ + { + "id": 63176355, + "node_id": "MDE2OkdhdGVCcmFuY2hQb2xpY3k2MzE3NjM1NQ==", + "name": "main", + "type": "branch" + }, + { + "id": 63176361, + "node_id": "MDE2OkdhdGVCcmFuY2hQb2xpY3k2MzE3NjM2MQ==", + "name": "v*", + "type": "tag" + } + ] +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/environment-secrets-after.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/environment-secrets-after.json new file mode 100644 index 00000000..e58bdb4a --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/environment-secrets-after.json @@ -0,0 +1,30 @@ +{ + "total_count": 5, + "secrets": [ + { + "name": "APPLE_APP_PASSWORD", + "created_at": "2026-10-15T16:16:45Z", + "updated_at": "2026-10-15T16:16:45Z" + }, + { + "name": "APPLE_CERTIFICATE_P12", + "created_at": "2026-10-15T16:16:49Z", + "updated_at": "2026-10-15T16:16:49Z" + }, + { + "name": "APPLE_CERTIFICATE_PASSWORD", + "created_at": "2026-10-15T16:16:46Z", + "updated_at": "2026-10-15T16:16:46Z" + }, + { + "name": "APPLE_ID", + "created_at": "2026-10-15T16:16:41Z", + "updated_at": "2026-10-15T16:16:41Z" + }, + { + "name": "APPLE_TEAM_ID", + "created_at": "2026-10-15T16:16:43Z", + "updated_at": "2026-10-15T16:16:43Z" + } + ] +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/full-test-evidence.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/full-test-evidence.json new file mode 100644 index 00000000..96336488 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/full-test-evidence.json @@ -0,0 +1,13 @@ +{ + "xctest_bundles": 14, + "xctest_executed": 1143, + "xctest_skipped": 17, + "xctest_failures": 0, + "unique_swift_testing_cases": 1, + "swift_testing_failures": 0, + "empty_swift_testing_bundles": 13, + "complete": true, + "test_bundle_hashes_unchanged": true, + "native_evidence": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/native-run-9d5cbdd1", + "swiftpm_wrapper": "blocked before test execution by nested sandbox_apply; preserved in swift-test.log" +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/identity-check.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/identity-check.json new file mode 100644 index 00000000..03c9e2ab --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/identity-check.json @@ -0,0 +1,8 @@ +{ + "isolated_import_and_sign" : "passed", + "keychain_search_list_restored" : true, + "sha1" : "0A1A804E9C5D7BE644E4A6B884487BB5191F691D", + "sha256" : "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", + "team" : "G9L7H3T3D5", + "temporary_keychain_deleted" : true +} \ No newline at end of file diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-config-source-review.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-config-source-review.json new file mode 100644 index 00000000..db75605e --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-config-source-review.json @@ -0,0 +1,8 @@ +{ + "verifier": "/root/signing_verifier", + "result": "no remaining blocker", + "helper_sha256": "b7fe86e2080cd7b6a007cb05a2eff6035fd4a15fb8c432f01e963b0c42749512", + "human_approval": false, + "scope": "technical readiness under approved plan; does not approve production", + "compatibility_correction": "System LibreSSL used for Apple PKCS12; independently reviewed" +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-approvals-readback.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-approvals-readback.json new file mode 100644 index 00000000..25014275 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-approvals-readback.json @@ -0,0 +1,39 @@ +[ + { + "user": { + "login": "IchenDEV", + "id": 34794972, + "node_id": "MDQ6VXNlcjM0Nzk0OTcy", + "avatar_url": "https://avatars.githubusercontent.com/u/34794972?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IchenDEV", + "html_url": "https://github.com/IchenDEV", + "followers_url": "https://api.github.com/users/IchenDEV/followers", + "following_url": "https://api.github.com/users/IchenDEV/following{/other_user}", + "gists_url": "https://api.github.com/users/IchenDEV/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IchenDEV/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IchenDEV/subscriptions", + "organizations_url": "https://api.github.com/users/IchenDEV/orgs", + "repos_url": "https://api.github.com/users/IchenDEV/repos", + "events_url": "https://api.github.com/users/IchenDEV/events{/privacy}", + "received_events_url": "https://api.github.com/users/IchenDEV/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "state": "approved", + "comment": "Human user explicitly approved production for run 38770474797 and v0.0.53 after reviewing passing CI and independent verification. Direct chat decision on 2026-10-16: approve this production release.", + "environments": [ + { + "id": 20910208532, + "node_id": "EN_kwDORZD8nM8AAAAE3lh2FA", + "name": "production", + "url": "https://api.github.com/repos/IchenDEV/utter/environments/production", + "html_url": "https://github.com/IchenDEV/utter/deployments/activity_log?environments_filter=production", + "created_at": "2026-08-31T07:05:58Z", + "updated_at": "2026-10-15T16:16:22Z", + "can_admins_bypass": false + } + ] + } +] diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-jobs-readback.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-jobs-readback.json new file mode 100644 index 00000000..7bf7184e --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-jobs-readback.json @@ -0,0 +1,253 @@ +{ + "total_count": 2, + "jobs": [ + { + "id": 116544650129, + "run_id": 38770474797, + "workflow_name": "Release", + "head_branch": "v0.0.53", + "run_url": "https://api.github.com/repos/IchenDEV/utter/actions/runs/38770474797", + "run_attempt": 1, + "node_id": "CR_kwDORZD8nM8AAAAbIpo7kQ", + "head_sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "url": "https://api.github.com/repos/IchenDEV/utter/actions/jobs/116544650129", + "html_url": "https://github.com/IchenDEV/utter/actions/runs/38770474797/job/116544650129", + "status": "completed", + "conclusion": "success", + "created_at": "2026-10-15T16:36:53Z", + "started_at": "2026-10-15T16:37:02Z", + "completed_at": "2026-10-15T16:46:46Z", + "name": "Release Candidate Tests", + "steps": [ + { + "name": "Set up job", + "status": "completed", + "conclusion": "success", + "number": 1, + "started_at": "2026-10-15T16:37:02Z", + "completed_at": "2026-10-15T16:37:03Z" + }, + { + "name": "Run actions/checkout@v4", + "status": "completed", + "conclusion": "success", + "number": 2, + "started_at": "2026-10-15T16:37:03Z", + "completed_at": "2026-10-15T16:37:09Z" + }, + { + "name": "Require a SemVer tag on main", + "status": "completed", + "conclusion": "success", + "number": 3, + "started_at": "2026-10-15T16:37:09Z", + "completed_at": "2026-10-15T16:37:10Z" + }, + { + "name": "Run repository checks", + "status": "completed", + "conclusion": "success", + "number": 4, + "started_at": "2026-10-15T16:37:10Z", + "completed_at": "2026-10-15T16:39:11Z" + }, + { + "name": "Ensure Metal toolchain", + "status": "completed", + "conclusion": "success", + "number": 5, + "started_at": "2026-10-15T16:39:11Z", + "completed_at": "2026-10-15T16:39:17Z" + }, + { + "name": "Resolve version from tag", + "status": "completed", + "conclusion": "success", + "number": 6, + "started_at": "2026-10-15T16:39:17Z", + "completed_at": "2026-10-15T16:39:17Z" + }, + { + "name": "Run unit tests", + "status": "completed", + "conclusion": "success", + "number": 7, + "started_at": "2026-10-15T16:39:17Z", + "completed_at": "2026-10-15T16:46:40Z" + }, + { + "name": "Post Run actions/checkout@v4", + "status": "completed", + "conclusion": "success", + "number": 14, + "started_at": "2026-10-15T16:46:40Z", + "completed_at": "2026-10-15T16:46:42Z" + }, + { + "name": "Complete job", + "status": "completed", + "conclusion": "success", + "number": 15, + "started_at": "2026-10-15T16:46:42Z", + "completed_at": "2026-10-15T16:46:44Z" + } + ], + "check_run_url": "https://api.github.com/repos/IchenDEV/utter/check-runs/116544650129", + "labels": [ + "macos-26" + ], + "runner_id": 1000020757, + "runner_name": "GitHub Actions 1000020757", + "runner_group_id": 0, + "runner_group_name": "GitHub Actions" + }, + { + "id": 116549335673, + "run_id": 38770474797, + "workflow_name": "Release", + "head_branch": "v0.0.53", + "run_url": "https://api.github.com/repos/IchenDEV/utter/actions/runs/38770474797", + "run_attempt": 1, + "node_id": "CR_kwDORZD8nM8AAAAbIuG6eQ", + "head_sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "url": "https://api.github.com/repos/IchenDEV/utter/actions/jobs/116549335673", + "html_url": "https://github.com/IchenDEV/utter/actions/runs/38770474797/job/116549335673", + "status": "completed", + "conclusion": "failure", + "created_at": "2026-10-15T16:46:46Z", + "started_at": "2026-10-15T16:51:57Z", + "completed_at": "2026-10-15T17:06:54Z", + "name": "Sign, Verify & Publish / Sign, Verify & Publish", + "steps": [ + { + "name": "Set up job", + "status": "completed", + "conclusion": "success", + "number": 1, + "started_at": "2026-10-15T16:51:57Z", + "completed_at": "2026-10-15T16:51:58Z" + }, + { + "name": "Run actions/checkout@v4", + "status": "completed", + "conclusion": "success", + "number": 2, + "started_at": "2026-10-15T16:51:58Z", + "completed_at": "2026-10-15T16:52:02Z" + }, + { + "name": "Validate version and tag", + "status": "completed", + "conclusion": "success", + "number": 3, + "started_at": "2026-10-15T16:52:02Z", + "completed_at": "2026-10-15T16:52:02Z" + }, + { + "name": "Require a SemVer tag on main", + "status": "completed", + "conclusion": "success", + "number": 4, + "started_at": "2026-10-15T16:52:02Z", + "completed_at": "2026-10-15T16:52:02Z" + }, + { + "name": "Create and push release tag", + "status": "completed", + "conclusion": "skipped", + "number": 5, + "started_at": "2026-10-15T16:52:02Z", + "completed_at": "2026-10-15T16:52:02Z" + }, + { + "name": "Require release credentials", + "status": "completed", + "conclusion": "success", + "number": 6, + "started_at": "2026-10-15T16:52:02Z", + "completed_at": "2026-10-15T16:52:03Z" + }, + { + "name": "Import signing certificate", + "status": "completed", + "conclusion": "success", + "number": 7, + "started_at": "2026-10-15T16:52:03Z", + "completed_at": "2026-10-15T16:52:03Z" + }, + { + "name": "Ensure Metal toolchain", + "status": "completed", + "conclusion": "success", + "number": 8, + "started_at": "2026-10-15T16:52:03Z", + "completed_at": "2026-10-15T16:52:08Z" + }, + { + "name": "Build signed app and DMG", + "status": "completed", + "conclusion": "success", + "number": 9, + "started_at": "2026-10-15T16:52:08Z", + "completed_at": "2026-10-15T17:05:53Z" + }, + { + "name": "Classify and verify signed artifact", + "status": "completed", + "conclusion": "success", + "number": 10, + "started_at": "2026-10-15T17:05:53Z", + "completed_at": "2026-10-15T17:05:57Z" + }, + { + "name": "Notarize and staple DMG", + "status": "completed", + "conclusion": "success", + "number": 11, + "started_at": "2026-10-15T17:05:57Z", + "completed_at": "2026-10-15T17:06:41Z" + }, + { + "name": "Verify distribution and checksum", + "status": "completed", + "conclusion": "failure", + "number": 12, + "started_at": "2026-10-15T17:06:41Z", + "completed_at": "2026-10-15T17:06:47Z" + }, + { + "name": "Publish GitHub Release", + "status": "completed", + "conclusion": "skipped", + "number": 13, + "started_at": "2026-10-15T17:06:47Z", + "completed_at": "2026-10-15T17:06:47Z" + }, + { + "name": "Post Run actions/checkout@v4", + "status": "completed", + "conclusion": "success", + "number": 26, + "started_at": "2026-10-15T17:06:47Z", + "completed_at": "2026-10-15T17:06:48Z" + }, + { + "name": "Complete job", + "status": "completed", + "conclusion": "success", + "number": 27, + "started_at": "2026-10-15T17:06:48Z", + "completed_at": "2026-10-15T17:06:52Z" + } + ], + "check_run_url": "https://api.github.com/repos/IchenDEV/utter/check-runs/116549335673", + "labels": [ + "macos-26" + ], + "runner_id": 1000020758, + "runner_name": "GitHub Actions 1000020758", + "runner_group_id": 0, + "runner_group_name": "GitHub Actions" + } + ] +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-run-readback.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-run-readback.json new file mode 100644 index 00000000..ae10db9a --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-run-readback.json @@ -0,0 +1,230 @@ +{ + "id": 38770474797, + "name": "Release", + "node_id": "WFR_kwLORZD8nM8AAAAJBuZ_LQ", + "head_branch": "v0.0.53", + "head_sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "path": ".github/workflows/release.yml", + "display_title": "Merge pull request #122 from IchenDEV/t3/xiaomi-remote-mic", + "run_number": 48, + "event": "push", + "status": "completed", + "conclusion": "failure", + "workflow_id": 238787847, + "check_suite_id": 105067868459, + "check_suite_node_id": "CS_kwDORZD8nM8AAAAYdohxKw", + "url": "https://api.github.com/repos/IchenDEV/utter/actions/runs/38770474797", + "html_url": "https://github.com/IchenDEV/utter/actions/runs/38770474797", + "pull_requests": [], + "created_at": "2026-10-15T16:36:52Z", + "updated_at": "2026-10-15T17:06:55Z", + "actor": { + "login": "IchenDEV", + "id": 34794972, + "node_id": "MDQ6VXNlcjM0Nzk0OTcy", + "avatar_url": "https://avatars.githubusercontent.com/u/34794972?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IchenDEV", + "html_url": "https://github.com/IchenDEV", + "followers_url": "https://api.github.com/users/IchenDEV/followers", + "following_url": "https://api.github.com/users/IchenDEV/following{/other_user}", + "gists_url": "https://api.github.com/users/IchenDEV/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IchenDEV/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IchenDEV/subscriptions", + "organizations_url": "https://api.github.com/users/IchenDEV/orgs", + "repos_url": "https://api.github.com/users/IchenDEV/repos", + "events_url": "https://api.github.com/users/IchenDEV/events{/privacy}", + "received_events_url": "https://api.github.com/users/IchenDEV/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "run_attempt": 1, + "referenced_workflows": [ + { + "path": "IchenDEV/utter/.github/workflows/release-artifact.yml@f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "ref": "refs/tags/v0.0.53" + } + ], + "run_started_at": "2026-10-15T16:36:52Z", + "triggering_actor": { + "login": "IchenDEV", + "id": 34794972, + "node_id": "MDQ6VXNlcjM0Nzk0OTcy", + "avatar_url": "https://avatars.githubusercontent.com/u/34794972?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IchenDEV", + "html_url": "https://github.com/IchenDEV", + "followers_url": "https://api.github.com/users/IchenDEV/followers", + "following_url": "https://api.github.com/users/IchenDEV/following{/other_user}", + "gists_url": "https://api.github.com/users/IchenDEV/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IchenDEV/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IchenDEV/subscriptions", + "organizations_url": "https://api.github.com/users/IchenDEV/orgs", + "repos_url": "https://api.github.com/users/IchenDEV/repos", + "events_url": "https://api.github.com/users/IchenDEV/events{/privacy}", + "received_events_url": "https://api.github.com/users/IchenDEV/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "jobs_url": "https://api.github.com/repos/IchenDEV/utter/actions/runs/38770474797/jobs", + "logs_url": "https://api.github.com/repos/IchenDEV/utter/actions/runs/38770474797/logs", + "check_suite_url": "https://api.github.com/repos/IchenDEV/utter/check-suites/105067868459", + "artifacts_url": "https://api.github.com/repos/IchenDEV/utter/actions/runs/38770474797/artifacts", + "cancel_url": "https://api.github.com/repos/IchenDEV/utter/actions/runs/38770474797/cancel", + "rerun_url": "https://api.github.com/repos/IchenDEV/utter/actions/runs/38770474797/rerun", + "previous_attempt_url": null, + "workflow_url": "https://api.github.com/repos/IchenDEV/utter/actions/workflows/238787847", + "head_commit": { + "id": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "tree_id": "12783f01e00ad57369e15dad78868dbeee761479", + "message": "Merge pull request #122 from IchenDEV/t3/xiaomi-remote-mic", + "timestamp": "2026-10-10T21:48:02Z", + "author": { + "name": "idevlab", + "email": "idevlab@outlook.com" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com" + } + }, + "repository": { + "id": 1167129756, + "node_id": "R_kgDORZD8nA", + "name": "utter", + "full_name": "IchenDEV/utter", + "private": false, + "owner": { + "login": "IchenDEV", + "id": 34794972, + "node_id": "MDQ6VXNlcjM0Nzk0OTcy", + "avatar_url": "https://avatars.githubusercontent.com/u/34794972?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IchenDEV", + "html_url": "https://github.com/IchenDEV", + "followers_url": "https://api.github.com/users/IchenDEV/followers", + "following_url": "https://api.github.com/users/IchenDEV/following{/other_user}", + "gists_url": "https://api.github.com/users/IchenDEV/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IchenDEV/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IchenDEV/subscriptions", + "organizations_url": "https://api.github.com/users/IchenDEV/orgs", + "repos_url": "https://api.github.com/users/IchenDEV/repos", + "events_url": "https://api.github.com/users/IchenDEV/events{/privacy}", + "received_events_url": "https://api.github.com/users/IchenDEV/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/IchenDEV/utter", + "description": "Local AI-powered voice input for macOS menu bar", + "fork": false, + "url": "https://api.github.com/repos/IchenDEV/utter", + "forks_url": "https://api.github.com/repos/IchenDEV/utter/forks", + "keys_url": "https://api.github.com/repos/IchenDEV/utter/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/IchenDEV/utter/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/IchenDEV/utter/teams", + "hooks_url": "https://api.github.com/repos/IchenDEV/utter/hooks", + "issue_events_url": "https://api.github.com/repos/IchenDEV/utter/issues/events{/number}", + "events_url": "https://api.github.com/repos/IchenDEV/utter/events", + "assignees_url": "https://api.github.com/repos/IchenDEV/utter/assignees{/user}", + "branches_url": "https://api.github.com/repos/IchenDEV/utter/branches{/branch}", + "tags_url": "https://api.github.com/repos/IchenDEV/utter/tags", + "blobs_url": "https://api.github.com/repos/IchenDEV/utter/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/IchenDEV/utter/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/IchenDEV/utter/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/IchenDEV/utter/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/IchenDEV/utter/statuses/{sha}", + "languages_url": "https://api.github.com/repos/IchenDEV/utter/languages", + "stargazers_url": "https://api.github.com/repos/IchenDEV/utter/stargazers", + "contributors_url": "https://api.github.com/repos/IchenDEV/utter/contributors", + "subscribers_url": "https://api.github.com/repos/IchenDEV/utter/subscribers", + "subscription_url": "https://api.github.com/repos/IchenDEV/utter/subscription", + "commits_url": "https://api.github.com/repos/IchenDEV/utter/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/IchenDEV/utter/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/IchenDEV/utter/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/IchenDEV/utter/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/IchenDEV/utter/contents/{+path}", + "compare_url": "https://api.github.com/repos/IchenDEV/utter/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/IchenDEV/utter/merges", + "archive_url": "https://api.github.com/repos/IchenDEV/utter/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/IchenDEV/utter/downloads", + "issues_url": "https://api.github.com/repos/IchenDEV/utter/issues{/number}", + "pulls_url": "https://api.github.com/repos/IchenDEV/utter/pulls{/number}", + "milestones_url": "https://api.github.com/repos/IchenDEV/utter/milestones{/number}", + "notifications_url": "https://api.github.com/repos/IchenDEV/utter/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/IchenDEV/utter/labels{/name}", + "releases_url": "https://api.github.com/repos/IchenDEV/utter/releases{/id}", + "deployments_url": "https://api.github.com/repos/IchenDEV/utter/deployments" + }, + "head_repository": { + "id": 1167129756, + "node_id": "R_kgDORZD8nA", + "name": "utter", + "full_name": "IchenDEV/utter", + "private": false, + "owner": { + "login": "IchenDEV", + "id": 34794972, + "node_id": "MDQ6VXNlcjM0Nzk0OTcy", + "avatar_url": "https://avatars.githubusercontent.com/u/34794972?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IchenDEV", + "html_url": "https://github.com/IchenDEV", + "followers_url": "https://api.github.com/users/IchenDEV/followers", + "following_url": "https://api.github.com/users/IchenDEV/following{/other_user}", + "gists_url": "https://api.github.com/users/IchenDEV/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IchenDEV/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IchenDEV/subscriptions", + "organizations_url": "https://api.github.com/users/IchenDEV/orgs", + "repos_url": "https://api.github.com/users/IchenDEV/repos", + "events_url": "https://api.github.com/users/IchenDEV/events{/privacy}", + "received_events_url": "https://api.github.com/users/IchenDEV/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/IchenDEV/utter", + "description": "Local AI-powered voice input for macOS menu bar", + "fork": false, + "url": "https://api.github.com/repos/IchenDEV/utter", + "forks_url": "https://api.github.com/repos/IchenDEV/utter/forks", + "keys_url": "https://api.github.com/repos/IchenDEV/utter/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/IchenDEV/utter/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/IchenDEV/utter/teams", + "hooks_url": "https://api.github.com/repos/IchenDEV/utter/hooks", + "issue_events_url": "https://api.github.com/repos/IchenDEV/utter/issues/events{/number}", + "events_url": "https://api.github.com/repos/IchenDEV/utter/events", + "assignees_url": "https://api.github.com/repos/IchenDEV/utter/assignees{/user}", + "branches_url": "https://api.github.com/repos/IchenDEV/utter/branches{/branch}", + "tags_url": "https://api.github.com/repos/IchenDEV/utter/tags", + "blobs_url": "https://api.github.com/repos/IchenDEV/utter/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/IchenDEV/utter/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/IchenDEV/utter/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/IchenDEV/utter/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/IchenDEV/utter/statuses/{sha}", + "languages_url": "https://api.github.com/repos/IchenDEV/utter/languages", + "stargazers_url": "https://api.github.com/repos/IchenDEV/utter/stargazers", + "contributors_url": "https://api.github.com/repos/IchenDEV/utter/contributors", + "subscribers_url": "https://api.github.com/repos/IchenDEV/utter/subscribers", + "subscription_url": "https://api.github.com/repos/IchenDEV/utter/subscription", + "commits_url": "https://api.github.com/repos/IchenDEV/utter/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/IchenDEV/utter/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/IchenDEV/utter/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/IchenDEV/utter/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/IchenDEV/utter/contents/{+path}", + "compare_url": "https://api.github.com/repos/IchenDEV/utter/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/IchenDEV/utter/merges", + "archive_url": "https://api.github.com/repos/IchenDEV/utter/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/IchenDEV/utter/downloads", + "issues_url": "https://api.github.com/repos/IchenDEV/utter/issues{/number}", + "pulls_url": "https://api.github.com/repos/IchenDEV/utter/pulls{/number}", + "milestones_url": "https://api.github.com/repos/IchenDEV/utter/milestones{/number}", + "notifications_url": "https://api.github.com/repos/IchenDEV/utter/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/IchenDEV/utter/labels{/name}", + "releases_url": "https://api.github.com/repos/IchenDEV/utter/releases{/id}", + "deployments_url": "https://api.github.com/repos/IchenDEV/utter/deployments" + } +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-verification.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-verification.json new file mode 100644 index 00000000..e048d3b9 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-verification.json @@ -0,0 +1,63 @@ +{ + "verifier": "/root/signing_verifier", + "verified_at_utc": "2026-10-15T16:21:04.173122+00:00", + "result": "passed", + "human_approval": false, + "remote_readback": { + "reviewer": "IchenDEV", + "prevent_self_review": false, + "can_admins_bypass": false, + "custom_deployment_restrictions_active": true, + "rules": [ + { + "name": "main", + "type": "branch" + }, + { + "name": "v*", + "type": "tag" + } + ], + "environment_secret_names": [ + "APPLE_APP_PASSWORD", + "APPLE_CERTIFICATE_P12", + "APPLE_CERTIFICATE_PASSWORD", + "APPLE_ID", + "APPLE_TEAM_ID" + ], + "repository_secrets_count": 2, + "repository_secret_metadata_unchanged": true, + "saved_remote_readbacks_match_live": true, + "workflow_hashes_match_validated_baseline": true + }, + "cleanup": { + "configuration_state_success": true, + "keychain_search_list_before_after_equal": true, + "private_directory_exists": false, + "private_material_inspected": false + }, + "helper_sha256": "b7fe86e2080cd7b6a007cb05a2eff6035fd4a15fb8c432f01e963b0c42749512", + "native_tests": { + "xctest": 1143, + "xctest_skipped": 17, + "xctest_non_skipped_passed": 1126, + "failures": 0, + "unique_swift_testing_passed": 1, + "expected_empty_swift_testing_invocations": 13, + "all_discovered_identity_sets_complete": true, + "frozen_bundle_files_unchanged": 300 + }, + "notarization_authentication": { + "read_only_store_and_history_exit_zero": true, + "team": "G9L7H3T3D5", + "independent_credential_reauthentication_performed": false + }, + "helper_operation_scope": "Reviewed source and configuration journal contain environment/secret mutations only, no workflow dispatch, tag creation, release publishing, or production approval. This does not establish absence of unrelated actors activity.", + "evidence_gaps": [ + "GitHub secret values cannot be read back; metadata confirms names and timestamps only.", + "Read-only Apple authentication is recorded by helper, not an independently repeated authentication.", + "Protected SwiftPM wrapper failed before test execution; complete native engines passed.", + "No authorized release run has yet proven CI signing, notarization submission, stapling, Gatekeeper, mounted-DMG, or checksum distribution results." + ], + "actionable_findings": [] +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-local-readiness.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-local-readiness.json new file mode 100644 index 00000000..a2801b55 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-local-readiness.json @@ -0,0 +1,14 @@ +{ + "verifier": "/root/signing_verifier", + "result": "passed", + "human_approval": false, + "scope": "local certificate export/import/signing, workflow wiring, full native behavioral tests", + "xctest_executed": 1143, + "xctest_passed": 1126, + "xctest_skipped": 17, + "swift_testing_unique_passed": 1, + "discovery_identity_sets_match": true, + "all_tests_complete": true, + "all_bundle_files_unchanged": true, + "swiftpm_wrapper": "setup failure preserved separately; not marked passed" +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-branch-after.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-branch-after.json new file mode 100644 index 00000000..cae038e5 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-branch-after.json @@ -0,0 +1,104 @@ +{ + "name": "main", + "commit": { + "sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "node_id": "C_kwDORZD8nNoAKGYwZWYyYWE4ODI5NmRhMDE3ZTI5Y2VkMmI3YmM5MjcxYWY5NmU0ZmI", + "commit": { + "author": { + "name": "idevlab", + "email": "idevlab@outlook.com", + "date": "2026-10-10T21:48:02Z" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com", + "date": "2026-10-10T21:48:02Z" + }, + "message": "Merge pull request #122 from IchenDEV/t3/xiaomi-remote-mic", + "tree": { + "sha": "12783f01e00ad57369e15dad78868dbeee761479", + "url": "https://api.github.com/repos/IchenDEV/utter/git/trees/12783f01e00ad57369e15dad78868dbeee761479" + }, + "url": "https://api.github.com/repos/IchenDEV/utter/git/commits/f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "comment_count": 0, + "verification": { + "verified": true, + "reason": "valid", + "signature": "-----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJqyrKSCRC1aQ7uu5UhlAAAWa0QADaPWzjZ+YIRpSdBmaCHTpD1\nzciZRQRFfYUxZdVialOt4ioYTsItCA/jp604fleQLxQ280jyCpfE37uCd0TRYJB7\nryAVh9gh2271Luy35Che25AgB4e/5CQGBYlJ1Ec5v950uTl/kAcFv7DhU019xbBz\niDnD+mrRp32NXcSLesdxlMuVMHg3HXE0lagSQzJR9N0EV6e9cei3BSNGdvMDzRZg\nQQeXdzWCT1veuliv7fnRFzTcZj19WI+TyoX/7ncfTfQ7ZuXzHPmhw/l8w3VVSCkN\n5f7Gyqf+JVNJHlQph0Aqy2meTavvcRs8jbfV1nbphdAZNwtT3aajUJTzjaenvb9n\nWPNYB5cEsmtjs1yeGMS9v9NeerDndahGCLMciYAvN+TAzVjixxeYoQTGAs4QjbCm\nUWqerS2nWVphw+1xOP70S+hsDBZmCfPrmLbXBwITaGi3twmrazIeJu0KIoTrpkWm\n89lkKHl7oHwVnnngKF13iWP4fE6LeXtkCa7BVrd40nDV9o9tGNKQOo0B+WzyPqdJ\n7WtXYbghtg5+mj7eSfIaQOTnW+AKyqWA9/gRFIRnRUupYxM5a/CpI0APg2xK3T2r\nHshdFHa8ItL/QFtzdUKG1rQMsN1tMtVJUPJl6EL0JTTqaLJI55YBzzhsnV3J0PB3\nDCkICq62tK+fBCmJpC3f\n=nBOV\n-----END PGP SIGNATURE-----\n", + "payload": "tree 12783f01e00ad57369e15dad78868dbeee761479\nparent 64817558dc1e50911a198e0025bee6d6cafdea6d\nparent 51f7f10ae24d9001911840c826a57211ff41a2dd\nauthor idevlab 1791668882 +0800\ncommitter GitHub 1791668882 +0800\n\nMerge pull request #122 from IchenDEV/t3/xiaomi-remote-mic", + "verified_at": "2026-10-10T21:48:02Z" + } + }, + "url": "https://api.github.com/repos/IchenDEV/utter/commits/f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "html_url": "https://github.com/IchenDEV/utter/commit/f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "comments_url": "https://api.github.com/repos/IchenDEV/utter/commits/f0ef2aa88296da017e29ced2b7bc9271af96e4fb/comments", + "author": { + "login": "IchenDEV", + "id": 34794972, + "node_id": "MDQ6VXNlcjM0Nzk0OTcy", + "avatar_url": "https://avatars.githubusercontent.com/u/34794972?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IchenDEV", + "html_url": "https://github.com/IchenDEV", + "followers_url": "https://api.github.com/users/IchenDEV/followers", + "following_url": "https://api.github.com/users/IchenDEV/following{/other_user}", + "gists_url": "https://api.github.com/users/IchenDEV/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IchenDEV/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IchenDEV/subscriptions", + "organizations_url": "https://api.github.com/users/IchenDEV/orgs", + "repos_url": "https://api.github.com/users/IchenDEV/repos", + "events_url": "https://api.github.com/users/IchenDEV/events{/privacy}", + "received_events_url": "https://api.github.com/users/IchenDEV/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "committer": { + "login": "web-flow", + "id": 19864447, + "node_id": "MDQ6VXNlcjE5ODY0NDQ3", + "avatar_url": "https://avatars.githubusercontent.com/u/19864447?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/web-flow", + "html_url": "https://github.com/web-flow", + "followers_url": "https://api.github.com/users/web-flow/followers", + "following_url": "https://api.github.com/users/web-flow/following{/other_user}", + "gists_url": "https://api.github.com/users/web-flow/gists{/gist_id}", + "starred_url": "https://api.github.com/users/web-flow/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/web-flow/subscriptions", + "organizations_url": "https://api.github.com/users/web-flow/orgs", + "repos_url": "https://api.github.com/users/web-flow/repos", + "events_url": "https://api.github.com/users/web-flow/events{/privacy}", + "received_events_url": "https://api.github.com/users/web-flow/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "parents": [ + { + "sha": "64817558dc1e50911a198e0025bee6d6cafdea6d", + "url": "https://api.github.com/repos/IchenDEV/utter/commits/64817558dc1e50911a198e0025bee6d6cafdea6d", + "html_url": "https://github.com/IchenDEV/utter/commit/64817558dc1e50911a198e0025bee6d6cafdea6d" + }, + { + "sha": "51f7f10ae24d9001911840c826a57211ff41a2dd", + "url": "https://api.github.com/repos/IchenDEV/utter/commits/51f7f10ae24d9001911840c826a57211ff41a2dd", + "html_url": "https://github.com/IchenDEV/utter/commit/51f7f10ae24d9001911840c826a57211ff41a2dd" + } + ] + }, + "_links": { + "self": "https://api.github.com/repos/IchenDEV/utter/branches/main", + "html": "https://github.com/IchenDEV/utter/tree/main" + }, + "protected": true, + "protection": { + "enabled": false, + "required_status_checks": { + "enforcement_level": "off", + "contexts": [], + "checks": [] + } + }, + "protection_url": "https://api.github.com/repos/IchenDEV/utter/branches/main/protection" +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-effective-rules.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-effective-rules.json new file mode 100644 index 00000000..76e3e940 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-effective-rules.json @@ -0,0 +1,50 @@ +[ + { + "type": "deletion", + "ruleset_source_type": "Repository", + "ruleset_source": "IchenDEV/utter", + "ruleset_id": 14695153 + }, + { + "type": "non_fast_forward", + "ruleset_source_type": "Repository", + "ruleset_source": "IchenDEV/utter", + "ruleset_id": 14695153 + }, + { + "type": "pull_request", + "parameters": { + "required_approving_review_count": 1, + "dismiss_stale_reviews_on_push": true, + "required_reviewers": [], + "require_code_owner_review": true, + "require_last_push_approval": true, + "required_review_thread_resolution": true, + "require_extra_approval_for_unattributed_changes": true, + "allowed_merge_methods": [ + "merge", + "squash", + "rebase" + ] + }, + "ruleset_source_type": "Repository", + "ruleset_source": "IchenDEV/utter", + "ruleset_id": 14695153 + }, + { + "type": "required_status_checks", + "parameters": { + "strict_required_status_checks_policy": true, + "do_not_enforce_on_create": false, + "required_status_checks": [ + { + "context": "SDLC Gate", + "integration_id": 15368 + } + ] + }, + "ruleset_source_type": "Repository", + "ruleset_source": "IchenDEV/utter", + "ruleset_id": 14695153 + } +] diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-protection-independent-verification.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-protection-independent-verification.json new file mode 100644 index 00000000..7e95d5bd --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-protection-independent-verification.json @@ -0,0 +1,66 @@ +{ + "verified_at_utc": "2026-10-15T16:36:21.782792+00:00", + "verifier": "/root/signing_verifier", + "result": "passed", + "human_authorization": "Parent relayed direct user request: \u5148\u542f\u7528 main \u5206\u652f\u4fdd\u62a4", + "main_protected": true, + "main_sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "ruleset_id": 14695153, + "enforcement": "active", + "target": "branch", + "ref_condition": { + "exclude": [], + "include": [ + "refs/heads/main" + ] + }, + "bypass_actors": [], + "rules": [ + { + "type": "deletion" + }, + { + "type": "non_fast_forward" + }, + { + "type": "pull_request", + "parameters": { + "required_approving_review_count": 1, + "dismiss_stale_reviews_on_push": true, + "required_reviewers": [], + "require_code_owner_review": true, + "require_last_push_approval": true, + "required_review_thread_resolution": true, + "require_extra_approval_for_unattributed_changes": true, + "allowed_merge_methods": [ + "merge", + "squash", + "rebase" + ] + } + }, + { + "type": "required_status_checks", + "parameters": { + "strict_required_status_checks_policy": true, + "do_not_enforce_on_create": false, + "required_status_checks": [ + { + "context": "SDLC Gate", + "integration_id": 15368 + } + ] + } + } + ], + "effective_rule_types": [ + "deletion", + "non_fast_forward", + "pull_request", + "required_status_checks" + ], + "requirements_source": "docs/sdlc/github-controls.md", + "codeowners_present": true, + "remote_mutations_performed_by_verifier": false, + "findings": [] +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-ruleset-after.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-ruleset-after.json new file mode 100644 index 00000000..5647fd17 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-ruleset-after.json @@ -0,0 +1,67 @@ +{ + "id": 14695153, + "name": "main", + "target": "branch", + "source_type": "Repository", + "source": "IchenDEV/utter", + "enforcement": "active", + "conditions": { + "ref_name": { + "exclude": [], + "include": [ + "refs/heads/main" + ] + } + }, + "rules": [ + { + "type": "deletion" + }, + { + "type": "non_fast_forward" + }, + { + "type": "pull_request", + "parameters": { + "required_approving_review_count": 1, + "dismiss_stale_reviews_on_push": true, + "required_reviewers": [], + "require_code_owner_review": true, + "require_last_push_approval": true, + "required_review_thread_resolution": true, + "require_extra_approval_for_unattributed_changes": true, + "allowed_merge_methods": [ + "merge", + "squash", + "rebase" + ] + } + }, + { + "type": "required_status_checks", + "parameters": { + "strict_required_status_checks_policy": true, + "do_not_enforce_on_create": false, + "required_status_checks": [ + { + "context": "SDLC Gate", + "integration_id": 15368 + } + ] + } + } + ], + "node_id": "RRS_lACqUmVwb3NpdG9yec5FkPyczgDgOvE", + "created_at": "2026-04-04T23:20:35.411+08:00", + "updated_at": "2026-10-16T00:35:47.448+08:00", + "bypass_actors": [], + "current_user_can_bypass": "never", + "_links": { + "self": { + "href": "https://api.github.com/repos/IchenDEV/utter/rulesets/14695153" + }, + "html": { + "href": "https://github.com/IchenDEV/utter/rules/14695153" + } + } +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-ruleset-before.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-ruleset-before.json new file mode 100644 index 00000000..c5010d2d --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-ruleset-before.json @@ -0,0 +1,35 @@ +{ + "id": 14695153, + "name": "main", + "target": "branch", + "source_type": "Repository", + "source": "IchenDEV/utter", + "enforcement": "disabled", + "conditions": { + "ref_name": { + "exclude": [], + "include": [] + } + }, + "rules": [ + { + "type": "deletion" + }, + { + "type": "non_fast_forward" + } + ], + "node_id": "RRS_lACqUmVwb3NpdG9yec5FkPyczgDgOvE", + "created_at": "2026-04-04T23:20:35.411+08:00", + "updated_at": "2026-04-04T23:20:35.424+08:00", + "bypass_actors": [], + "current_user_can_bypass": "never", + "_links": { + "self": { + "href": "https://api.github.com/repos/IchenDEV/utter/rulesets/14695153" + }, + "html": { + "href": "https://github.com/IchenDEV/utter/rules/14695153" + } + } +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-ruleset-request.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-ruleset-request.json new file mode 100644 index 00000000..76b18bb7 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-ruleset-request.json @@ -0,0 +1,44 @@ +{ + "name": "main", + "target": "branch", + "enforcement": "active", + "bypass_actors": [], + "conditions": { + "ref_name": { + "include": [ + "refs/heads/main" + ], + "exclude": [] + } + }, + "rules": [ + { + "type": "deletion" + }, + { + "type": "non_fast_forward" + }, + { + "type": "pull_request", + "parameters": { + "dismiss_stale_reviews_on_push": true, + "require_code_owner_review": true, + "require_last_push_approval": true, + "required_approving_review_count": 1, + "required_review_thread_resolution": true + } + }, + { + "type": "required_status_checks", + "parameters": { + "required_status_checks": [ + { + "context": "SDLC Gate", + "integration_id": 15368 + } + ], + "strict_required_status_checks_policy": true + } + } + ] +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/notarization-authentication.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/notarization-authentication.json new file mode 100644 index 00000000..c9a850c3 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/notarization-authentication.json @@ -0,0 +1,6 @@ +{ + "store_credentials_exit": 0, + "history_exit": 0, + "team": "G9L7H3T3D5", + "read_only": true +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/production-after.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/production-after.json new file mode 100644 index 00000000..5be63a3c --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/production-after.json @@ -0,0 +1,53 @@ +{ + "id": 20910208532, + "node_id": "EN_kwDORZD8nM8AAAAE3lh2FA", + "name": "production", + "url": "https://api.github.com/repos/IchenDEV/utter/environments/production", + "html_url": "https://github.com/IchenDEV/utter/deployments/activity_log?environments_filter=production", + "created_at": "2026-08-31T07:05:58Z", + "updated_at": "2026-10-15T16:16:22Z", + "can_admins_bypass": false, + "protection_rules": [ + { + "id": 68930215, + "node_id": "GA_kwDORZD8nM4EG8qn", + "type": "required_reviewers", + "prevent_self_review": false, + "reviewers": [ + { + "type": "User", + "reviewer": { + "login": "IchenDEV", + "id": 34794972, + "node_id": "MDQ6VXNlcjM0Nzk0OTcy", + "avatar_url": "https://avatars.githubusercontent.com/u/34794972?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IchenDEV", + "html_url": "https://github.com/IchenDEV", + "followers_url": "https://api.github.com/users/IchenDEV/followers", + "following_url": "https://api.github.com/users/IchenDEV/following{/other_user}", + "gists_url": "https://api.github.com/users/IchenDEV/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IchenDEV/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IchenDEV/subscriptions", + "organizations_url": "https://api.github.com/users/IchenDEV/orgs", + "repos_url": "https://api.github.com/users/IchenDEV/repos", + "events_url": "https://api.github.com/users/IchenDEV/events{/privacy}", + "received_events_url": "https://api.github.com/users/IchenDEV/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + } + } + ] + }, + { + "id": 68930216, + "node_id": "GA_kwDORZD8nM4EG8qo", + "type": "branch_policy" + } + ], + "deployment_branch_policy": { + "protected_branches": false, + "custom_branch_policies": true + } +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/production-before.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/production-before.json new file mode 100644 index 00000000..8f05f8fa --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/production-before.json @@ -0,0 +1,12 @@ +{ + "id": 20910208532, + "node_id": "EN_kwDORZD8nM8AAAAE3lh2FA", + "name": "production", + "url": "https://api.github.com/repos/IchenDEV/utter/environments/production", + "html_url": "https://github.com/IchenDEV/utter/deployments/activity_log?environments_filter=production", + "created_at": "2026-08-31T07:05:58Z", + "updated_at": "2026-08-31T07:05:58Z", + "can_admins_bypass": true, + "protection_rules": [], + "deployment_branch_policy": null +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-basic-checks.log b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-basic-checks.log new file mode 100644 index 00000000..dc8c3074 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-basic-checks.log @@ -0,0 +1,252 @@ + +==> Checking Package.swift +Swift module boundaries passed. +...... +---------------------------------------------------------------------- +Ran 6 tests in 0.003s + +OK +Owned resources passed. +..... +---------------------------------------------------------------------- +Ran 5 tests in 0.023s + +OK +........................... +---------------------------------------------------------------------- +Ran 27 tests in 0.256s + +OK + +==> Checking SDLC artifacts and harness regression tests +==> Checking docs/sdlc/changes/2026-08-25-ai-native-sdlc/ +==> Checking docs/sdlc/changes/2026-08-26-dmg-installer-polish/ +==> Checking docs/sdlc/changes/2026-08-29-espresso-ane/ +==> Checking docs/sdlc/changes/2026-08-30-dev-app-icon-packaging/ +==> Checking docs/sdlc/changes/2026-08-30-history-mode-switch/ +==> Checking docs/sdlc/changes/2026-08-30-model-type-selection/ +==> Checking docs/sdlc/changes/2026-08-30-settings-window-layout/ +==> Checking docs/sdlc/changes/2026-08-30-system-settings-groups/ +==> Checking docs/sdlc/changes/2026-08-31-ane-lm-runtime/ +==> Checking docs/sdlc/changes/2026-08-31-settings-semantic-background/ +==> Checking docs/sdlc/changes/2026-08-31-shell-sdlc-gate/ +==> Checking docs/sdlc/changes/2026-08-31-website-native-redesign/ +==> Checking docs/sdlc/changes/2026-09-03-release-p12-openssl3/ +==> Checking docs/sdlc/changes/2026-09-18-nightly-release-pipeline/ +==> Checking docs/sdlc/changes/2026-09-21-model-download-retry-recovery/ +==> Checking docs/sdlc/changes/2026-09-21-remote-mic-integration/ +==> Checking docs/sdlc/changes/2026-09-21-settings-surface-parity/ +==> Checking docs/sdlc/changes/2026-09-23-confucius4-r2t2-mlx/ +==> Checking docs/sdlc/changes/2026-09-23-input-session-ownership/ +==> Checking docs/sdlc/changes/2026-09-23-silent-input-insertion/ +==> Checking docs/sdlc/changes/2026-09-24-industry-lexicon-expansion/ +==> Checking docs/sdlc/changes/2026-09-24-release-workflow-permissions/ +==> Checking docs/sdlc/changes/2026-09-28-release-input-contract/ +==> Checking docs/sdlc/changes/2026-09-30-firered-asr-download-completeness/ +==> Checking docs/sdlc/changes/2026-10-01-clamshell-mic-failover/ +==> Checking docs/sdlc/changes/2026-10-01-stable-prompt-prefix-cache/ +==> Checking docs/sdlc/changes/2026-10-03-builtin-plugin-composition/ +==> Checking docs/sdlc/changes/2026-10-03-promo-videos/ +==> Checking docs/sdlc/changes/2026-10-04-voice-input-reliability/ +==> Checking docs/sdlc/changes/2026-10-07-desktop-numeral-list-fidelity/ +==> Checking docs/sdlc/changes/2026-10-07-xiaomi-remote-connection/ +==> Checking docs/sdlc/changes/2026-10-15-developer-id-ci/ +SDLC checks passed. +Build version tests passed. +Release version tests passed. +Nightly release plan tests passed. +From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.o4WLIZxDtn/origin + * branch main -> FETCH_HEAD +From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.o4WLIZxDtn/origin + * branch main -> FETCH_HEAD +Release workflow contract tests passed. + +==> Linting property lists and localized strings +Resources/Info.plist: OK +Resources/OpenType.entitlements: OK +Sources/UtterContracts/Resources/en.lproj/Localizable.strings: OK +Sources/UtterContracts/Resources/zh-Hans.lproj/Localizable.strings: OK + +==> Checking brand and compatibility identifiers + +==> Checking localization key parity + +==> Checking industry vocabulary +Building for debugging... +[0/15] Write sources +[4/15] Copying Info.plist +[4/15] Copying Localizable.strings +[6/15] Copying Info.plist +[7/15] Copying Localizable.strings +[7/15] Copying THUOCL-LICENSE.txt +[8/15] Copying IndustryLexicons.json +[10/15] Write UtterLexiconCheck-entitlement.plist +[11/15] Write swift-version--1AB21518FC5DEDBE.txt +[13/25] Compiling UtterRuntime PluginScope.swift +[14/26] Compiling UtterRuntime PluginRuntimeError.swift +[15/26] Compiling UtterRuntime ContributionRegistry.swift +[16/26] Compiling UtterRuntime PluginContext.swift +[17/26] Compiling UtterRuntime ConfigurationValue.swift +[18/26] Emitting module UtterRuntime +[19/26] Compiling UtterRuntime PluginDescriptor.swift +[20/26] Compiling UtterRuntime CallbackTasks.swift +[21/26] Compiling UtterRuntime PluginGraph.swift +[22/26] Compiling UtterRuntime PluginRuntime.swift +[23/26] Compiling UtterRuntime ServiceKey.swift +[24/127] Compiling UtterContracts DeferredReplacementPolicy.swift +[25/127] Compiling UtterContracts DeliveryServices.swift +[26/127] Compiling UtterContracts DictionaryEntry.swift +[27/127] Compiling UtterContracts DictionaryService.swift +[28/127] Compiling UtterContracts DownloadProgressInfo.swift +[29/127] Compiling UtterContracts EspressoGenerationOutcome.swift +[30/127] Compiling UtterContracts EspressoLLMError.swift +[31/127] Compiling UtterContracts EspressoMLXFallbackError.swift +[32/127] Compiling UtterContracts FrozenModelFiles.swift +[33/127] Compiling UtterContracts GenerationServices.swift +[34/127] Compiling UtterContracts GenerationTimingObservation.swift +[35/138] Compiling UtterContracts ModelStorageService.swift +[36/138] Compiling UtterContracts NoSpaceScript.swift +[37/138] Compiling UtterContracts OperationDeadline.swift +[38/138] Compiling UtterContracts PermissionRequest.swift +[39/138] Compiling UtterContracts PersonalDictionarySnapshot.swift +[40/138] Compiling UtterContracts PlatformServices.swift +[41/138] Compiling UtterContracts ProcessingDecision.swift +[42/138] Compiling UtterContracts ProductBrand.swift +[43/138] Compiling UtterContracts ProviderCapabilities.swift +[44/138] Compiling UtterContracts ProviderCatalog.swift +[45/138] Compiling UtterContracts ProviderRegistry.swift +[46/138] Emitting module UtterContracts +[47/138] Compiling UtterContracts AppSettingTypes.swift +[48/138] Compiling UtterContracts AudioActivityThresholds.swift +[49/138] Compiling UtterContracts AudioCaptureActivity.swift +[50/138] Compiling UtterContracts AudioInputDevice.swift +[51/138] Compiling UtterContracts Character+ASCIIWord.swift +[52/138] Compiling UtterContracts CompositionDocument.swift +[53/138] Compiling UtterContracts CompositionLayer.swift +[54/138] Compiling UtterContracts CorrectionCaptureSeed.swift +[55/138] Compiling UtterContracts CorrectionClassificationService.swift +[56/138] Compiling UtterContracts CredentialsService.swift +[57/138] Compiling UtterContracts DataServices.swift +[58/138] Compiling UtterContracts DeferredReplacement.swift +[59/138] Compiling UtterContracts QwenASRModel.swift +[60/138] Compiling UtterContracts QwenAudioPreprocessorError.swift +[61/138] Compiling UtterContracts QwenNativeASRError.swift +[62/138] Compiling UtterContracts RemoteConnectionService.swift +[63/138] Compiling UtterContracts RemoteLLMError.swift +[64/138] Compiling UtterContracts RemoteMicBridgeState.swift +[65/138] Compiling UtterContracts RemoteMicDiagnostics.swift +[66/138] Compiling UtterContracts RemoteModelConfig.swift +[67/138] Compiling UtterContracts ResourceBundle.swift +[68/138] Compiling UtterContracts ScreenContextMode.swift +[69/138] Compiling UtterContracts SessionExecutionService.swift +[70/138] Compiling UtterContracts SpokenEditCommandLLMResolver+ActionTarget.swift +[71/138] Compiling UtterContracts SpokenEditCommandLLMResolver.swift +[72/138] Compiling UtterContracts SpokenEditEvidence.swift +[73/138] Compiling UtterContracts StateNotifications.swift +[74/138] Compiling UtterContracts StreamingPreviewAccumulator.swift +[75/138] Compiling UtterContracts StreamingSpeechSupport.swift +[76/138] Compiling UtterContracts TextFormatKind.swift +[77/138] Compiling UtterContracts TextPreparationService.swift +[78/138] Compiling UtterContracts TextProcessingMode.swift +[79/138] Compiling UtterContracts TextProcessingOptions.swift +[80/138] Compiling UtterContracts TranscriptSegmentJoiner.swift +[81/138] Compiling UtterContracts MLXSTTError.swift +[82/138] Compiling UtterContracts ModelArtifact.swift +[83/138] Compiling UtterContracts ModelArtifactService.swift +[84/138] Compiling UtterContracts ModelBenchmarkResult.swift +[85/138] Compiling UtterContracts ModelBenchmarkSuite.swift +[86/138] Compiling UtterContracts ModelCatalogService.swift +[87/138] Compiling UtterContracts ModelCatalogValues.swift +[88/138] Compiling UtterContracts ModelCompatibility.swift +[89/138] Compiling UtterContracts ModelDownloadKey.swift +[90/138] Compiling UtterContracts ModelLocationLease.swift +[91/138] Compiling UtterContracts ModelServices.swift +[92/138] Compiling UtterContracts SessionFailurePresentation.swift +[93/138] Compiling UtterContracts SessionOutputStateService.swift +[94/138] Compiling UtterContracts SessionPerformance.swift +[95/138] Compiling UtterContracts SessionPresentation.swift +[96/138] Compiling UtterContracts SettingsService.swift +[97/138] Compiling UtterContracts SettingsValues.swift +[98/138] Compiling UtterContracts SpeechArtifactPolicy.swift +[99/138] Compiling UtterContracts SpeechModelProgress.swift +[100/138] Compiling UtterContracts SpeechRecognitionContext.swift +[101/138] Compiling UtterContracts SpeechSelection.swift +[102/138] Compiling UtterContracts SpokenEditCommand.swift +[103/138] Compiling UtterContracts LLMActionValue.swift +[104/138] Compiling UtterContracts LLMDecodedValue.swift +[105/138] Compiling UtterContracts LLMError.swift +[106/138] Compiling UtterContracts LLMFinalTextOutput.swift +[107/138] Compiling UtterContracts LLMScaffoldedOutput.swift +[108/138] Compiling UtterContracts LLMStructuredOutput+DecodedStrings.swift +[109/138] Compiling UtterContracts LLMStructuredOutput.swift +[110/138] Compiling UtterContracts LearnedCorrectionPolicy.swift +[111/138] Compiling UtterContracts Loc.swift +[112/138] Compiling UtterContracts LocalGenerationBudget.swift +[113/138] Compiling UtterContracts Log.swift +[114/138] Compiling UtterContracts HistoryService.swift +[115/138] Compiling UtterContracts HotkeyAction.swift +[116/138] Compiling UtterContracts IndustryLexiconSnapshot.swift +[117/138] Compiling UtterContracts InputContext.swift +[118/138] Compiling UtterContracts InputRecord.swift +[119/138] Compiling UtterContracts InputSessionModels.swift +[120/138] Compiling UtterContracts InputSessionService.swift +[121/138] Compiling UtterContracts InsertResult.swift +[122/138] Compiling UtterContracts IntegrationClient.swift +[123/138] Compiling UtterContracts IntegrationError.swift +[124/138] Compiling UtterContracts IntegrationServices.swift +[125/138] Compiling UtterContracts TranslationAssessment.swift +[126/138] Compiling UtterContracts TranslationLanguage.swift +[127/138] Compiling UtterContracts VocabularyReplacementEngine.swift +[128/138] Compiling UtterContracts VoiceInputSettings.swift +[129/138] Compiling UtterContracts VolcASRError.swift +[130/138] Compiling UtterContracts VolcASRModel.swift +[131/138] Compiling UtterContracts WhisperError.swift +[132/138] Compiling UtterContracts WhisperModelDimensions.swift +[133/138] Compiling UtterContracts WhisperModelSelection.swift +[134/138] Compiling UtterContracts WhisperTokenizerAssets.swift +[135/138] Compiling UtterContracts resource_bundle_accessor.swift +[136/158] Compiling UtterData SettingsStore+Load.swift +[137/158] Compiling UtterData SettingsStore+Persistence.swift +[138/158] Compiling UtterData HistoryMemoryService.swift +[139/158] Compiling UtterData HistoryStore.swift +[140/158] Compiling UtterData DictionaryStore+Transfer.swift +[141/158] Compiling UtterData DictionaryStore.swift +[142/158] Compiling UtterData DataResources.swift +[143/158] Compiling UtterData DictionaryStore+Learning.swift +[144/158] Compiling UtterData BuiltinCorrectionClassification.swift +[145/158] Compiling UtterData CompositionResolver.swift +[146/158] Compiling UtterData CompositionStore.swift +[147/158] Compiling UtterData SettingsStore+Token.swift +[148/158] Compiling UtterData SettingsStore.swift +[149/158] Compiling UtterData MemoryStore.swift +[150/158] Compiling UtterData SettingsCredentialsService.swift +[151/158] Compiling UtterData IndustryLexicon.swift +[152/158] Compiling UtterData IntegrationClientRegistry.swift +[153/160] Emitting module UtterData +[154/160] Compiling UtterData CorrectionCandidateClassifier.swift +[155/160] Compiling UtterData DataPlugins.swift +[156/160] Compiling UtterData SystemDiagnostics.swift +[157/160] Compiling UtterData resource_bundle_accessor.swift +[158/162] Compiling UtterLexiconCheck IndustryLexiconCheck.swift +[159/162] Emitting module UtterLexiconCheck +[159/162] Write Objects.LinkFileList +[160/162] Linking UtterLexiconCheck +[161/162] Applying UtterLexiconCheck +Build of product 'UtterLexiconCheck' complete! (24.38s) +Industry lexicon deterministic evaluation passed + baseline term recall: 20.59% + treatment term recall: 100.00% + absolute improvement: 79.41 points + non-target preservation: 100.00% + +==> Checking required app resources + +==> Checking bundled helper names + +==> Checking for conflict markers + +==> Checking tracked secret-bearing file types + +==> Checking for broken symlinks + +Basic CI checks passed. diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-before-production-independent.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-before-production-independent.json new file mode 100644 index 00000000..2875959c --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-before-production-independent.json @@ -0,0 +1,140 @@ +{ + "verifier": "/root/signing_verifier", + "verified_at_utc": "2026-10-15T16:48:27.316814+00:00", + "result": "passed_before_production", + "human_production_approval": false, + "remote_mutations_performed": false, + "tag": { + "name": "v0.0.53", + "annotated_tag_object": "b8e869cddca904cd525ece4fcb36d55fd4a14a33", + "peeled_commit": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb" + }, + "workflow_run": { + "id": 38770474797, + "url": "https://github.com/IchenDEV/utter/actions/runs/38770474797", + "head_sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "head_branch": "v0.0.53", + "event": "push", + "path": ".github/workflows/release.yml", + "status": "waiting", + "conclusion": null + }, + "candidate_test_job": { + "id": 116544650129, + "url": "https://github.com/IchenDEV/utter/actions/runs/38770474797/job/116544650129", + "status": "completed", + "conclusion": "success", + "steps": [ + { + "name": "Set up job", + "status": "completed", + "conclusion": "success", + "started_at": "2026-10-15T16:37:02Z", + "completed_at": "2026-10-15T16:37:03Z" + }, + { + "name": "Run actions/checkout@v4", + "status": "completed", + "conclusion": "success", + "started_at": "2026-10-15T16:37:03Z", + "completed_at": "2026-10-15T16:37:09Z" + }, + { + "name": "Require a SemVer tag on main", + "status": "completed", + "conclusion": "success", + "started_at": "2026-10-15T16:37:09Z", + "completed_at": "2026-10-15T16:37:10Z" + }, + { + "name": "Run repository checks", + "status": "completed", + "conclusion": "success", + "started_at": "2026-10-15T16:37:10Z", + "completed_at": "2026-10-15T16:39:11Z" + }, + { + "name": "Ensure Metal toolchain", + "status": "completed", + "conclusion": "success", + "started_at": "2026-10-15T16:39:11Z", + "completed_at": "2026-10-15T16:39:17Z" + }, + { + "name": "Resolve version from tag", + "status": "completed", + "conclusion": "success", + "started_at": "2026-10-15T16:39:17Z", + "completed_at": "2026-10-15T16:39:17Z" + }, + { + "name": "Run unit tests", + "status": "completed", + "conclusion": "success", + "started_at": "2026-10-15T16:39:17Z", + "completed_at": "2026-10-15T16:46:40Z" + }, + { + "name": "Post Run actions/checkout@v4", + "status": "completed", + "conclusion": "success", + "started_at": "2026-10-15T16:46:40Z", + "completed_at": "2026-10-15T16:46:42Z" + }, + { + "name": "Complete job", + "status": "completed", + "conclusion": "success", + "started_at": "2026-10-15T16:46:42Z", + "completed_at": "2026-10-15T16:46:44Z" + } + ], + "log_file": "release-candidate-tests-independent.log", + "log_sha256": "f46e1adc5ae48fe311d2c069d6dec5f2c63fad5e485b6341b95db41e8edde1bc", + "xctest": { + "executed": 1143, + "skipped": 18, + "failures": 0, + "started": 1143, + "finished": 1143, + "all_tests_completed": true + }, + "swift_testing": { + "executed": 1, + "result": "passed" + }, + "additional_ci_skip_vs_local": { + "test": "OpenTypeTests.DeferredReplacementPolicyTests.testDecisionRequiresSameFrontmostApp", + "reason": "Current test process has no bundle identifier", + "local_case_passed": true + } + }, + "pending_production": { + "environment_id": 20910208532, + "environment_name": "production", + "reviewer": "IchenDEV", + "pending": true, + "prevent_self_review": false, + "can_admins_bypass": false, + "custom_branch_policy_active": true + }, + "main_protection": { + "protected": true, + "sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "effective_rule_types": [ + "deletion", + "non_fast_forward", + "pull_request", + "required_status_checks" + ], + "ruleset_id": 14695153 + }, + "findings": [], + "next_gate": "The authorized human must decide whether to approve production for this exact run. Independent verification does not provide that approval.", + "remaining_evidence": [ + "Developer ID certificate identity/team/runtime on built release", + "Accepted software notarization and stapled ticket", + "Gatekeeper and mounted-DMG verification", + "Published checksum and download equality" + ] +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-final-independent-verification.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-final-independent-verification.json new file mode 100644 index 00000000..b02c7bd6 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-final-independent-verification.json @@ -0,0 +1,93 @@ +{ + "verifier": "/root/signing_verifier", + "verified_at_utc": "2026-10-15T17:09:20.540756+00:00", + "result": "blocked_release_failed", + "run_id": 38770474797, + "run_url": "https://github.com/IchenDEV/utter/actions/runs/38770474797", + "candidate_sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "tag": "v0.0.53", + "run_conclusion": "failure", + "human_production_authorization": { + "direct_user_record": true, + "github_approval_state": "approved", + "github_reviewer": "IchenDEV", + "environment_id": 20910208532, + "environment_admin_bypass": false + }, + "candidate_tests": { + "result": "success", + "xctest": 1143, + "skipped": 18, + "failures": 0, + "swift_testing_passed": 1 + }, + "ci_signed_app_evidence": { + "identity": "Developer ID Application: Chen Li", + "certificate_sha256": "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", + "team": "G9L7H3T3D5", + "team_evidence": "Previously inspected selected certificate. CI masks team in identity output; fingerprint matches the approved certificate.", + "hardened_runtime": "Checked by successful require-developer-id verification. Raw flags were not printed.", + "signature_and_mounted_copy_checks": "Passed before and after stapling, including built/mounted app equality, according to executed verifier source and subsequent log progress.", + "independent_local_binary_inspection": false + }, + "apple_notarization": { + "submission_id": "29a24fa6-d6b6-4053-9213-a9989e6e705a", + "status": "Accepted", + "accepted_log_time_utc": "2026-10-15T17:06:38.9288310Z", + "stapling": "success", + "stapled_ticket_validation": "success" + }, + "distribution_failure": { + "step": "Verify distribution and checksum", + "command": "spctl --assess --type open --context context:primary-signature --verbose=2 dist/Utter-0.0.53.dmg", + "command_source": "scripts/verify-release-artifact.sh:183", + "output": [ + "dist/Utter-0.0.53.dmg: rejected", + "source=no usable signature" + ], + "exit_code": 3, + "time_utc": "2026-10-15T17:06:47.9765820Z", + "app_execute_assessment": "Not reached after DMG rejection.", + "published_sha256_generation": "Not reached after verifier failure." + }, + "actionable_findings": [ + { + "priority": 1, + "title": "Outer DMG is never Developer ID signed before the required primary-signature assessment", + "location": "scripts/build-app.sh:239", + "evidence": "build-app.sh signs APP_BUNDLE at lines179-180, creates DMG at231-237, then verifies it at241-244. There is no codesign operation on DMG_PATH and dmg-settings.py provides no signing identity. The required DMG assessment fails with no usable signature after Apple Accepted and stapler validate success.", + "root_cause_confidence": "High from source plus exact failure signature. Failed CI artifact is unavailable for independent byte inspection.", + "smallest_remedy": "On the Developer ID path, sign the newly created outer DMG with the selected Developer ID Application identity and secure timestamp before notarization submission. Verify that outer signature and expected certificate before upload. Keep the existing Gatekeeper assessment.", + "external_propagation_assessment": "Current evidence indicates a deterministic missing container signature, not an Apple propagation delay. No blind retry is justified.", + "apple_reference": "https://developer.apple.com/documentation/xcode/packaging-mac-software-for-distribution" + } + ], + "publication": { + "publish_step": "skipped", + "v0_0_53_release_api": "404 Not Found from independent read-only check", + "latest_release": "v0.0.52", + "latest_release_url": "https://github.com/IchenDEV/utter/releases/tag/v0.0.52", + "latest_unchanged": true, + "run_artifacts_count": 0, + "downloaded_release_files": [], + "independent_download_directory": null, + "independent_mounts_created": 0, + "independent_mounts_remaining": 0 + }, + "evidence": { + "signing_job_log": "release-signing-independent-attempt-1.log", + "signing_job_log_sha256": "99ed5253bec64abdf7ca64dc54a3a950acac5365bde6b61aac1c901ccfe0f020", + "run_readback": "independent-final-run-readback.json", + "job_readback": "independent-final-jobs-readback.json", + "approval_readback": "independent-final-approvals-readback.json" + }, + "remaining_gaps": [ + "No published v0.0.53 asset or retained workflow artifact exists for independent local DMG/app inspection.", + "App execute Gatekeeper assessment was not reached.", + "Published DMG checksum/digest and download equality were not produced." + ], + "remote_mutations_performed_by_verifier": false, + "code_changes_performed_by_verifier": false, + "release_retry_performed_by_verifier": false, + "retry_boundary": "Preserve existing failed v0.0.53 tag and first-failure evidence. A source correction requires its normal reviewed change/PR and a new release commit/version; do not move this tag or replace same-version published assets." +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-first-failure-summary.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-first-failure-summary.json new file mode 100644 index 00000000..3babaeea --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-first-failure-summary.json @@ -0,0 +1,17 @@ +{ + "recorded_at_utc": "2026-10-15T17:10:34.100521+00:00", + "run_id": 38770474797, + "conclusion": "failure_before_publication", + "app_signing_classification": "developer-id", + "apple_submission_id": "29a24fa6-d6b6-4053-9213-a9989e6e705a", + "apple_status": "Accepted", + "dmg_staple_and_ticket_validation": "passed", + "dmg_gatekeeper": "rejected: no usable signature", + "app_execute_gatekeeper": "not reached", + "sha256_generation": "not reached", + "publish": "skipped", + "retained_workflow_artifacts": 0, + "failed_tag_unchanged": true, + "corrective_intent": "../2026-10-16-dmg-developer-id-signing/intent.md", + "implementation_started": false +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-human-production-authorization.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-human-production-authorization.json new file mode 100644 index 00000000..a46f6ca1 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-human-production-authorization.json @@ -0,0 +1,11 @@ +{ + "source": "Direct user answer to run-specific approval question", + "decision": "批准本次 production 发版", + "client_date": "2026-10-16", + "recorded_at_utc": "2026-10-15T16:51:40.414959+00:00", + "run_id": 38770474797, + "tag": "v0.0.53", + "candidate_sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "environment_id": 20910208532, + "environment": "production" +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-jobs-attempt-1.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-jobs-attempt-1.json new file mode 100644 index 00000000..0bce6118 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-jobs-attempt-1.json @@ -0,0 +1 @@ +{"total_count":2,"jobs":[{"id":116544650129,"run_id":38770474797,"workflow_name":"Release","head_branch":"v0.0.53","run_url":"https://api.github.com/repos/IchenDEV/utter/actions/runs/38770474797","run_attempt":1,"node_id":"CR_kwDORZD8nM8AAAAbIpo7kQ","head_sha":"f0ef2aa88296da017e29ced2b7bc9271af96e4fb","url":"https://api.github.com/repos/IchenDEV/utter/actions/jobs/116544650129","html_url":"https://github.com/IchenDEV/utter/actions/runs/38770474797/job/116544650129","status":"completed","conclusion":"success","created_at":"2026-10-15T16:36:53Z","started_at":"2026-10-15T16:37:02Z","completed_at":"2026-10-15T16:46:46Z","name":"Release Candidate Tests","steps":[{"name":"Set up job","status":"completed","conclusion":"success","number":1,"started_at":"2026-10-15T16:37:02Z","completed_at":"2026-10-15T16:37:03Z"},{"name":"Run actions/checkout@v4","status":"completed","conclusion":"success","number":2,"started_at":"2026-10-15T16:37:03Z","completed_at":"2026-10-15T16:37:09Z"},{"name":"Require a SemVer tag on main","status":"completed","conclusion":"success","number":3,"started_at":"2026-10-15T16:37:09Z","completed_at":"2026-10-15T16:37:10Z"},{"name":"Run repository checks","status":"completed","conclusion":"success","number":4,"started_at":"2026-10-15T16:37:10Z","completed_at":"2026-10-15T16:39:11Z"},{"name":"Ensure Metal toolchain","status":"completed","conclusion":"success","number":5,"started_at":"2026-10-15T16:39:11Z","completed_at":"2026-10-15T16:39:17Z"},{"name":"Resolve version from tag","status":"completed","conclusion":"success","number":6,"started_at":"2026-10-15T16:39:17Z","completed_at":"2026-10-15T16:39:17Z"},{"name":"Run unit tests","status":"completed","conclusion":"success","number":7,"started_at":"2026-10-15T16:39:17Z","completed_at":"2026-10-15T16:46:40Z"},{"name":"Post Run actions/checkout@v4","status":"completed","conclusion":"success","number":14,"started_at":"2026-10-15T16:46:40Z","completed_at":"2026-10-15T16:46:42Z"},{"name":"Complete job","status":"completed","conclusion":"success","number":15,"started_at":"2026-10-15T16:46:42Z","completed_at":"2026-10-15T16:46:44Z"}],"check_run_url":"https://api.github.com/repos/IchenDEV/utter/check-runs/116544650129","labels":["macos-26"],"runner_id":1000020757,"runner_name":"GitHub Actions 1000020757","runner_group_id":0,"runner_group_name":"GitHub Actions"},{"id":116549335673,"run_id":38770474797,"workflow_name":"Release","head_branch":"v0.0.53","run_url":"https://api.github.com/repos/IchenDEV/utter/actions/runs/38770474797","run_attempt":1,"node_id":"CR_kwDORZD8nM8AAAAbIuG6eQ","head_sha":"f0ef2aa88296da017e29ced2b7bc9271af96e4fb","url":"https://api.github.com/repos/IchenDEV/utter/actions/jobs/116549335673","html_url":"https://github.com/IchenDEV/utter/actions/runs/38770474797/job/116549335673","status":"completed","conclusion":"failure","created_at":"2026-10-15T16:46:46Z","started_at":"2026-10-15T16:51:57Z","completed_at":"2026-10-15T17:06:54Z","name":"Sign, Verify & Publish / Sign, Verify & Publish","steps":[{"name":"Set up job","status":"completed","conclusion":"success","number":1,"started_at":"2026-10-15T16:51:57Z","completed_at":"2026-10-15T16:51:58Z"},{"name":"Run actions/checkout@v4","status":"completed","conclusion":"success","number":2,"started_at":"2026-10-15T16:51:58Z","completed_at":"2026-10-15T16:52:02Z"},{"name":"Validate version and tag","status":"completed","conclusion":"success","number":3,"started_at":"2026-10-15T16:52:02Z","completed_at":"2026-10-15T16:52:02Z"},{"name":"Require a SemVer tag on main","status":"completed","conclusion":"success","number":4,"started_at":"2026-10-15T16:52:02Z","completed_at":"2026-10-15T16:52:02Z"},{"name":"Create and push release tag","status":"completed","conclusion":"skipped","number":5,"started_at":"2026-10-15T16:52:02Z","completed_at":"2026-10-15T16:52:02Z"},{"name":"Require release credentials","status":"completed","conclusion":"success","number":6,"started_at":"2026-10-15T16:52:02Z","completed_at":"2026-10-15T16:52:03Z"},{"name":"Import signing certificate","status":"completed","conclusion":"success","number":7,"started_at":"2026-10-15T16:52:03Z","completed_at":"2026-10-15T16:52:03Z"},{"name":"Ensure Metal toolchain","status":"completed","conclusion":"success","number":8,"started_at":"2026-10-15T16:52:03Z","completed_at":"2026-10-15T16:52:08Z"},{"name":"Build signed app and DMG","status":"completed","conclusion":"success","number":9,"started_at":"2026-10-15T16:52:08Z","completed_at":"2026-10-15T17:05:53Z"},{"name":"Classify and verify signed artifact","status":"completed","conclusion":"success","number":10,"started_at":"2026-10-15T17:05:53Z","completed_at":"2026-10-15T17:05:57Z"},{"name":"Notarize and staple DMG","status":"completed","conclusion":"success","number":11,"started_at":"2026-10-15T17:05:57Z","completed_at":"2026-10-15T17:06:41Z"},{"name":"Verify distribution and checksum","status":"completed","conclusion":"failure","number":12,"started_at":"2026-10-15T17:06:41Z","completed_at":"2026-10-15T17:06:47Z"},{"name":"Publish GitHub Release","status":"completed","conclusion":"skipped","number":13,"started_at":"2026-10-15T17:06:47Z","completed_at":"2026-10-15T17:06:47Z"},{"name":"Post Run actions/checkout@v4","status":"completed","conclusion":"success","number":26,"started_at":"2026-10-15T17:06:47Z","completed_at":"2026-10-15T17:06:48Z"},{"name":"Complete job","status":"completed","conclusion":"success","number":27,"started_at":"2026-10-15T17:06:48Z","completed_at":"2026-10-15T17:06:52Z"}],"check_run_url":"https://api.github.com/repos/IchenDEV/utter/check-runs/116549335673","labels":["macos-26"],"runner_id":1000020758,"runner_name":"GitHub Actions 1000020758","runner_group_id":0,"runner_group_name":"GitHub Actions"}]} \ No newline at end of file diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-jobs-before-approval.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-jobs-before-approval.json new file mode 100644 index 00000000..29e29f24 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-jobs-before-approval.json @@ -0,0 +1 @@ +{"total_count":2,"jobs":[{"id":116544650129,"run_id":38770474797,"workflow_name":"Release","head_branch":"v0.0.53","run_url":"https://api.github.com/repos/IchenDEV/utter/actions/runs/38770474797","run_attempt":1,"node_id":"CR_kwDORZD8nM8AAAAbIpo7kQ","head_sha":"f0ef2aa88296da017e29ced2b7bc9271af96e4fb","url":"https://api.github.com/repos/IchenDEV/utter/actions/jobs/116544650129","html_url":"https://github.com/IchenDEV/utter/actions/runs/38770474797/job/116544650129","status":"completed","conclusion":"success","created_at":"2026-10-15T16:36:53Z","started_at":"2026-10-15T16:37:02Z","completed_at":"2026-10-15T16:46:46Z","name":"Release Candidate Tests","steps":[{"name":"Set up job","status":"completed","conclusion":"success","number":1,"started_at":"2026-10-15T16:37:02Z","completed_at":"2026-10-15T16:37:03Z"},{"name":"Run actions/checkout@v4","status":"completed","conclusion":"success","number":2,"started_at":"2026-10-15T16:37:03Z","completed_at":"2026-10-15T16:37:09Z"},{"name":"Require a SemVer tag on main","status":"completed","conclusion":"success","number":3,"started_at":"2026-10-15T16:37:09Z","completed_at":"2026-10-15T16:37:10Z"},{"name":"Run repository checks","status":"completed","conclusion":"success","number":4,"started_at":"2026-10-15T16:37:10Z","completed_at":"2026-10-15T16:39:11Z"},{"name":"Ensure Metal toolchain","status":"completed","conclusion":"success","number":5,"started_at":"2026-10-15T16:39:11Z","completed_at":"2026-10-15T16:39:17Z"},{"name":"Resolve version from tag","status":"completed","conclusion":"success","number":6,"started_at":"2026-10-15T16:39:17Z","completed_at":"2026-10-15T16:39:17Z"},{"name":"Run unit tests","status":"completed","conclusion":"success","number":7,"started_at":"2026-10-15T16:39:17Z","completed_at":"2026-10-15T16:46:40Z"},{"name":"Post Run actions/checkout@v4","status":"completed","conclusion":"success","number":14,"started_at":"2026-10-15T16:46:40Z","completed_at":"2026-10-15T16:46:42Z"},{"name":"Complete job","status":"completed","conclusion":"success","number":15,"started_at":"2026-10-15T16:46:42Z","completed_at":"2026-10-15T16:46:44Z"}],"check_run_url":"https://api.github.com/repos/IchenDEV/utter/check-runs/116544650129","labels":["macos-26"],"runner_id":1000020757,"runner_name":"GitHub Actions 1000020757","runner_group_id":0,"runner_group_name":"GitHub Actions"},{"id":116549335673,"run_id":38770474797,"workflow_name":"Release","head_branch":"v0.0.53","run_url":"https://api.github.com/repos/IchenDEV/utter/actions/runs/38770474797","run_attempt":1,"node_id":"CR_kwDORZD8nM8AAAAbIuG6eQ","head_sha":"f0ef2aa88296da017e29ced2b7bc9271af96e4fb","url":"https://api.github.com/repos/IchenDEV/utter/actions/jobs/116549335673","html_url":"https://github.com/IchenDEV/utter/actions/runs/38770474797/job/116549335673","status":"waiting","conclusion":null,"created_at":"2026-10-15T16:46:46Z","started_at":"2026-10-15T16:46:46Z","completed_at":null,"name":"Sign, Verify & Publish / Sign, Verify & Publish","steps":[],"check_run_url":"https://api.github.com/repos/IchenDEV/utter/check-runs/116549335673","labels":["macos-26"],"runner_id":null,"runner_name":null,"runner_group_id":null,"runner_group_name":null}]} \ No newline at end of file diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-pending-deployment.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-pending-deployment.json new file mode 100644 index 00000000..54a06dcb --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-pending-deployment.json @@ -0,0 +1 @@ +[{"environment":{"id":20910208532,"node_id":"EN_kwDORZD8nM8AAAAE3lh2FA","name":"production","url":"https://api.github.com/repos/IchenDEV/utter/environments/production","html_url":"https://github.com/IchenDEV/utter/deployments/activity_log?environments_filter=production"},"wait_timer":0,"wait_timer_started_at":null,"current_user_can_approve":true,"reviewers":[{"type":"User","reviewer":{"login":"IchenDEV","id":34794972,"node_id":"MDQ6VXNlcjM0Nzk0OTcy","avatar_url":"https://avatars.githubusercontent.com/u/34794972?u=d38f5bc38663aa6425ebb139cad99b2facf5ff21&v=4","gravatar_id":"","url":"https://api.github.com/users/IchenDEV","html_url":"https://github.com/IchenDEV","followers_url":"https://api.github.com/users/IchenDEV/followers","following_url":"https://api.github.com/users/IchenDEV/following{/other_user}","gists_url":"https://api.github.com/users/IchenDEV/gists{/gist_id}","starred_url":"https://api.github.com/users/IchenDEV/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IchenDEV/subscriptions","organizations_url":"https://api.github.com/users/IchenDEV/orgs","repos_url":"https://api.github.com/users/IchenDEV/repos","events_url":"https://api.github.com/users/IchenDEV/events{/privacy}","received_events_url":"https://api.github.com/users/IchenDEV/received_events","type":"User","user_view_type":"public","site_admin":false}}]}] \ No newline at end of file diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-production-approval-readback.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-production-approval-readback.json new file mode 100644 index 00000000..25014275 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-production-approval-readback.json @@ -0,0 +1,39 @@ +[ + { + "user": { + "login": "IchenDEV", + "id": 34794972, + "node_id": "MDQ6VXNlcjM0Nzk0OTcy", + "avatar_url": "https://avatars.githubusercontent.com/u/34794972?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IchenDEV", + "html_url": "https://github.com/IchenDEV", + "followers_url": "https://api.github.com/users/IchenDEV/followers", + "following_url": "https://api.github.com/users/IchenDEV/following{/other_user}", + "gists_url": "https://api.github.com/users/IchenDEV/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IchenDEV/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IchenDEV/subscriptions", + "organizations_url": "https://api.github.com/users/IchenDEV/orgs", + "repos_url": "https://api.github.com/users/IchenDEV/repos", + "events_url": "https://api.github.com/users/IchenDEV/events{/privacy}", + "received_events_url": "https://api.github.com/users/IchenDEV/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "state": "approved", + "comment": "Human user explicitly approved production for run 38770474797 and v0.0.53 after reviewing passing CI and independent verification. Direct chat decision on 2026-10-16: approve this production release.", + "environments": [ + { + "id": 20910208532, + "node_id": "EN_kwDORZD8nM8AAAAE3lh2FA", + "name": "production", + "url": "https://api.github.com/repos/IchenDEV/utter/environments/production", + "html_url": "https://github.com/IchenDEV/utter/deployments/activity_log?environments_filter=production", + "created_at": "2026-08-31T07:05:58Z", + "updated_at": "2026-10-15T16:16:22Z", + "can_admins_bypass": false + } + ] + } +] diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-production-approval-response.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-production-approval-response.json new file mode 100644 index 00000000..126fb614 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-production-approval-response.json @@ -0,0 +1,131 @@ +[ + { + "url": "https://api.github.com/repos/IchenDEV/utter/deployments/7098728919", + "id": 7098728919, + "node_id": "DE_kwDORZD8nM8AAAABpx4B1w", + "task": "deploy", + "original_environment": "production", + "environment": "production", + "description": null, + "created_at": "2026-10-15T16:46:46Z", + "updated_at": "2026-10-15T16:46:48Z", + "statuses_url": "https://api.github.com/repos/IchenDEV/utter/deployments/7098728919/statuses", + "repository_url": "https://api.github.com/repos/IchenDEV/utter", + "creator": { + "login": "IchenDEV", + "id": 34794972, + "node_id": "MDQ6VXNlcjM0Nzk0OTcy", + "avatar_url": "https://avatars.githubusercontent.com/u/34794972?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IchenDEV", + "html_url": "https://github.com/IchenDEV", + "followers_url": "https://api.github.com/users/IchenDEV/followers", + "following_url": "https://api.github.com/users/IchenDEV/following{/other_user}", + "gists_url": "https://api.github.com/users/IchenDEV/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IchenDEV/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IchenDEV/subscriptions", + "organizations_url": "https://api.github.com/users/IchenDEV/orgs", + "repos_url": "https://api.github.com/users/IchenDEV/repos", + "events_url": "https://api.github.com/users/IchenDEV/events{/privacy}", + "received_events_url": "https://api.github.com/users/IchenDEV/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "ref": "v0.0.53", + "payload": {}, + "transient_environment": false, + "production_environment": false, + "performed_via_github_app": { + "id": 15368, + "client_id": "Iv1.05c79e9ad1f6bdfa", + "slug": "github-actions", + "node_id": "MDM6QXBwMTUzNjg=", + "owner": { + "login": "github", + "id": 9919, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjk5MTk=", + "avatar_url": "https://avatars.githubusercontent.com/u/9919?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/github", + "html_url": "https://github.com/github", + "followers_url": "https://api.github.com/users/github/followers", + "following_url": "https://api.github.com/users/github/following{/other_user}", + "gists_url": "https://api.github.com/users/github/gists{/gist_id}", + "starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/github/subscriptions", + "organizations_url": "https://api.github.com/users/github/orgs", + "repos_url": "https://api.github.com/users/github/repos", + "events_url": "https://api.github.com/users/github/events{/privacy}", + "received_events_url": "https://api.github.com/users/github/received_events", + "type": "Organization", + "user_view_type": "public", + "site_admin": false + }, + "name": "GitHub Actions", + "description": "Automate your workflow from idea to production", + "external_url": "https://help.github.com/en/actions", + "html_url": "https://github.com/apps/github-actions", + "created_at": "2018-07-30T09:30:17Z", + "updated_at": "2026-06-18T16:17:48Z", + "permissions": { + "actions": "write", + "administration": "read", + "artifact_metadata": "write", + "attestations": "write", + "checks": "write", + "code_quality": "write", + "contents": "write", + "copilot_requests": "write", + "deployments": "write", + "discussions": "write", + "drives": "write", + "issues": "write", + "merge_queues": "write", + "metadata": "read", + "models": "read", + "packages": "write", + "pages": "write", + "pull_requests": "write", + "repository_hooks": "write", + "repository_projects": "write", + "security_events": "write", + "statuses": "write", + "vulnerability_alerts": "read" + }, + "events": [ + "branch_protection_rule", + "check_run", + "check_suite", + "create", + "delete", + "deployment", + "deployment_status", + "discussion", + "discussion_comment", + "fork", + "gollum", + "issues", + "issue_comment", + "label", + "merge_group", + "milestone", + "page_build", + "public", + "pull_request", + "pull_request_review", + "pull_request_review_comment", + "push", + "registry_package", + "release", + "repository", + "repository_dispatch", + "status", + "watch", + "workflow_dispatch", + "workflow_run" + ] + } + } +] diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-readiness.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-readiness.json new file mode 100644 index 00000000..b3f23015 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-readiness.json @@ -0,0 +1,116 @@ +{ + "verifier": "/root/signing_verifier", + "verified_at_utc": "2026-10-15T16:35:49.199196+00:00", + "scope": "Independent read-only v0.0.53 preflight", + "candidate_sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "candidate_on_current_main": true, + "main_protected": true, + "local_head_matches": true, + "tag": "v0.0.53", + "parsed_version": "0.0.53", + "local_tag_absent": true, + "remote_tag_absent": true, + "same_version_release_absent": true, + "latest_release": { + "tag": "v0.0.52", + "url": "https://github.com/IchenDEV/utter/releases/tag/v0.0.52", + "signing": "self-signed; not Apple-notarized according to published notes" + }, + "exact_sha_sdlc_gate": [ + { + "name": "SDLC Gate", + "head_sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "status": "completed", + "conclusion": "success", + "html_url": "https://github.com/IchenDEV/utter/actions/runs/38089004676/job/114323708817", + "completed_at": "2026-10-10T22:00:49Z" + } + ], + "other_exact_sha_ci": [ + { + "name": "Release-style App Build", + "head_sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "status": "completed", + "conclusion": "success", + "html_url": "https://github.com/IchenDEV/utter/actions/runs/38089004676/job/114321389503", + "completed_at": "2026-10-10T22:00:44Z" + }, + { + "name": "Contract & Tests", + "head_sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "status": "completed", + "conclusion": "success", + "html_url": "https://github.com/IchenDEV/utter/actions/runs/38089004676/job/114321389329", + "completed_at": "2026-10-10T21:57:28Z" + } + ], + "production": { + "reviewer": "IchenDEV", + "prevent_self_review": false, + "can_admins_bypass": false, + "custom_deployment_restrictions_active": true, + "rules": [ + { + "name": "main", + "type": "branch" + }, + { + "name": "v*", + "type": "tag" + } + ], + "environment_secret_names": [ + "APPLE_APP_PASSWORD", + "APPLE_CERTIFICATE_P12", + "APPLE_CERTIFICATE_PASSWORD", + "APPLE_ID", + "APPLE_TEAM_ID" + ], + "original_repository_secret_metadata_unchanged": true + }, + "release_workflows_match_validated_baseline": true, + "local_full_test_evidence": { + "source_sha": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "xctest": 1143, + "passed": 1126, + "skipped": 17, + "failures": 0, + "unique_swift_testing_passed": 1, + "protected_swiftpm_wrapper": "Failed during setup; native engines completed all discovered cases." + }, + "verification_status": "approved", + "release_artifact_status": "pending approval", + "active_release_runs": [], + "candidate_ci_and_credentials_ready": true, + "ready_to_create_tag_or_trigger_tests_under_runbook": true, + "blockers": [], + "rollback": { + "configuration": "Remove only the five task-created production secrets; keep unchanged repository credentials and production protections.", + "release": "Retain v0.0.52 assets. If v0.0.53 is defective, remove its latest recommendation and recommend v0.0.52 with its self-signed trust warning. Preserve evidence; never move the tag or replace published same-version assets." + }, + "post_trigger_requirements": [ + "Exact tag and candidate SHA must be verified after push.", + "Release workflow must rerun repository checks and Swift tests.", + "Human production environment approval remains required; independent review does not provide it.", + "Independently verify Developer ID certificate fingerprint/team/runtime, accepted software notarization, stapling, Gatekeeper, mounted DMG and published checksum." + ], + "limitations": [ + "Secret metadata cannot prove unreadable secret values.", + "Read-only Apple authentication has passed, but no v0.0.53 signed/notarized software artifact exists yet." + ], + "remote_mutations_performed": false, + "production_approval_performed": false, + "resolved_blockers": [ + { + "finding": { + "code": "MAIN_NOT_PROTECTED", + "source": "docs/sdlc/release-runbook.md:11", + "observed": "GitHub branches/main reports protected=false.", + "remedy": "Obtain explicit user acceptance of releasing this tested fixed SHA as a documented exception, or activate the approved main protection before tag creation. Do not change protection without user authorization." + }, + "resolution": "User authorized main protection. Live branches/main protected=true and active effective rules independently verified.", + "evidence": "main-protection-independent-verification.json" + } + ], + "main_protection_independently_verified_at_utc": "2026-10-15T16:36:21.782792+00:00" +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-run-started.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-run-started.json new file mode 100644 index 00000000..50f63c9d --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-run-started.json @@ -0,0 +1 @@ +{"conclusion":null,"created_at":"2026-10-15T16:36:52Z","head_branch":"v0.0.53","head_sha":"f0ef2aa88296da017e29ced2b7bc9271af96e4fb","html_url":"https://github.com/IchenDEV/utter/actions/runs/38770474797","id":38770474797,"run_started_at":"2026-10-15T16:36:52Z","status":"in_progress","updated_at":"2026-10-15T16:37:03Z"} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-tag.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-tag.json new file mode 100644 index 00000000..ca05cdf0 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-tag.json @@ -0,0 +1,12 @@ +{ + "repository": "IchenDEV/utter", + "tag": "v0.0.53", + "annotated_tag_object": "b8e869cddca904cd525ece4fcb36d55fd4a14a33", + "candidate_commit": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "remote_refs": { + "refs/tags/v0.0.53": "b8e869cddca904cd525ece4fcb36d55fd4a14a33", + "refs/tags/v0.0.53^{}": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb" + }, + "push_verified": true, + "production_approved_by_agent": false +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-test-summary.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-test-summary.json new file mode 100644 index 00000000..538097a7 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-test-summary.json @@ -0,0 +1,13 @@ +{ + "run_id": 38770474797, + "job_id": 116544650129, + "candidate_commit": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "command": "swift test", + "conclusion": "success", + "xctest_cases": 1143, + "xctest_conditional_skips": 18, + "xctest_failures": 0, + "swift_testing_cases_passed": 1, + "all_job_steps_success": true, + "production_approval": "pending_human_decision" +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/repository-secrets-after.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/repository-secrets-after.json new file mode 100644 index 00000000..5d5477ce --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/repository-secrets-after.json @@ -0,0 +1,15 @@ +{ + "total_count": 2, + "secrets": [ + { + "name": "APPLE_CERTIFICATE_P12", + "created_at": "2026-02-27T16:14:36Z", + "updated_at": "2026-02-27T16:14:36Z" + }, + { + "name": "APPLE_CERTIFICATE_PASSWORD", + "created_at": "2026-02-27T16:14:54Z", + "updated_at": "2026-02-27T16:14:54Z" + } + ] +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/repository-secrets-before.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/repository-secrets-before.json new file mode 100644 index 00000000..5d5477ce --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/repository-secrets-before.json @@ -0,0 +1,15 @@ +{ + "total_count": 2, + "secrets": [ + { + "name": "APPLE_CERTIFICATE_P12", + "created_at": "2026-02-27T16:14:36Z", + "updated_at": "2026-02-27T16:14:36Z" + }, + { + "name": "APPLE_CERTIFICATE_PASSWORD", + "created_at": "2026-02-27T16:14:54Z", + "updated_at": "2026-02-27T16:14:54Z" + } + ] +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/source-sha256-before.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/source-sha256-before.json new file mode 100644 index 00000000..e45555a4 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/source-sha256-before.json @@ -0,0 +1,6 @@ +{ + ".github/workflows/release.yml": "5f836d4fe1942cd4e978280cbac674673fbec8d7e7e0bef6b4565b6aa8c74932", + ".github/workflows/nightly-release.yml": "da4d1d3a9bfa3a0be2e6cd7d6285f9cd740e33ff3e442caef1ef0a0dfc1b20a9", + ".github/workflows/release-artifact.yml": "89251dd81b042c06cbf1c417444216c58caf92e39798cb2fc795e6acbcb17836", + "Package.resolved": "3a007c520b8b69aa9a675a42675662d7d272e4808dd3e71e4f12e074150219ad" +} diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/intent.md b/docs/sdlc/changes/2026-10-15-developer-id-ci/intent.md new file mode 100644 index 00000000..b2e6c6c3 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/intent.md @@ -0,0 +1,101 @@ +# Intent: Configure Developer ID signing for CI + +**Status:** approved +**Approved-by:** User, explicit chat reply: 批准 +**Approved-date:** 2026-10-15 +**Upstream:** User request on 2026-10-15: 帮我配置CI,支持公签 +**Risk:** High, signing credentials and release configuration + +## Problem + +The release workflow already supports Developer ID signing and Apple +notarization, but its GitHub configuration lacks notarization credentials. +The supplied `Apple Developer.p12` contains an Apple Development certificate, +which cannot satisfy the workflow's Developer ID distribution requirement. + +## Outcome + +Tag releases and nightly releases use a Developer ID Application identity, +receive Apple notarization, staple the DMG, and pass the existing distribution +checks before publication. + +## Scope + +- Reuse `.github/workflows/release-artifact.yml` for both release entry points. +- Configure the five existing `APPLE_*` secrets in the `production` environment. +- Obtain a PKCS#12 export of the intended Developer ID Application identity. + The local keychain contains `Developer ID Application: Chen Li (G9L7H3T3D5)`. + Confirm this identity with the user before exporting its private key. +- Validate the certificate, matching private key, Apple team, and notarization + credentials before activating the configuration. +- Record local checks and GitHub results separately. A production release + requires its own authorization. + +## Constraints + +- Collect passwords through local hidden input. Keep passwords, private keys, + PKCS#12 contents, and notarization credentials out of chat, logs, and Git. +- Preserve existing repository secrets. Environment secrets can override them + without destroying the current configuration. +- Do not change workflow code unless credential configuration proves + insufficient. Any required code change returns to reviewed design and plan. +- Never fall back to ad-hoc signing after a signing or notarization failure. +- Do not create tags, publish releases, or dispatch a publishing workflow as a + credential test without explicit production authorization. +- The `production` environment currently has no required reviewers or tag + restrictions. Secret configuration alone does not establish those controls. +- Follow the repository's per-stage human approval contract. + +## Acceptance criteria + +- The selected PKCS#12 contains a valid Developer ID Application certificate + and its matching private key. Record only public identity metadata. +- The certificate's team matches `APPLE_TEAM_ID`, and Apple accepts the + notarization credentials through a read-only `notarytool` request. +- `production` contains `APPLE_CERTIFICATE_P12`, + `APPLE_CERTIFICATE_PASSWORD`, `APPLE_ID`, `APPLE_TEAM_ID`, and + `APPLE_APP_PASSWORD`. Preserve existing repository secrets. +- Both release entry points continue to inherit secrets and use the existing + `production` job. The release workflow contract test passes. +- Before implementation handoff, record `sdlc-checks.sh`, + `ci-basic-checks.sh`, and `swift test` results, plus risk-specific validation. + Mark unavailable checks explicitly. +- Claim successful public distribution only after an authorized GitHub run + proves signing, notarization, stapling, Gatekeeper assessment, mounted-DMG + verification, and checksum verification. + +## Initial evidence + +- Checkout: `main` at `f0ef2aa88296da017e29ced2b7bc9271af96e4fb`. +- The local reusable workflow matches GitHub's current file byte for byte. +- `bash scripts/tests/test_release_workflow_contract.sh` passed. +- The supplied PKCS#12 was opened with a local hidden password prompt. + Its certificate is Apple Development and expires on 2027-10-05. + No password was retained and no private key was exported. +- The local Developer ID Application certificate expires on 2027-11-14. + Its ability to export the private key remains unverified. +- GitHub repository secrets contain the two certificate secret names. + Their values cannot be read through GitHub and were not inspected. +- No `production` environment secrets are currently configured. +- GitHub reports no `production` protection rules and allows admin bypass. +- No workflow code, GitHub secrets, or release settings have been changed. + +## Rollback requirement + +Keep existing repository secrets intact. If environment secrets are added, +record exactly which names were created so they can be removed to restore the +previous secret selection. Stop publishing while credentials are incomplete. + +## Resolved questions + +- The user approved this intent and use of the named local Developer ID + Application identity on 2026-10-15. +- The user supplied Apple notarization credentials through local input on + 2026-10-16. Apple accepted the read-only authentication request. +- Production protection follows the separately approved design. Configuration + is complete; production release authorization remains separate. + +## References + +- [Apple Developer ID distribution](https://developer.apple.com/developer-id/) +- [GitHub reusable workflow environment secrets](https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows#using-inputs-and-secrets-in-a-reusable-workflow) diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/plan.md b/docs/sdlc/changes/2026-10-15-developer-id-ci/plan.md new file mode 100644 index 00000000..230343e6 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/plan.md @@ -0,0 +1,94 @@ +# Plan: Configure Developer ID signing for CI + +**Status:** approved +**Approved-by:** User, explicit chat reply: 批准 +**Approved-date:** 2026-10-15 +**Upstream:** [Spec](spec.md) + +## Work items + +- [x] Recheck the checkout, approved certificate fingerprint, GitHub admin + access, and both release entry points. Save production settings, deployment + rules, workflow states, and repository secret metadata as public evidence. +- [x] Confirm that the five target environment secrets are absent. Stop if + another actor has created any of them. Never overwrite an unknown value. +- [x] Export only the approved Developer ID identity through macOS Security + APIs, with a generated password and private temporary storage. Stop on export + denial without changing key permissions or using a different identity. +- [x] Import the export into a temporary keychain. Sign a disposable executable + and verify its signature, certificate fingerprint, team, and hardened runtime. + Retain the signed executable as public verification evidence. +- [x] Collect the Apple ID and app-specific password through local input. + Authenticate a read-only `notarytool history` request for `G9L7H3T3D5`. + Suppress credentials and submission history in all recorded output. +- [x] Run the local checks below. Stop before remote mutation if a required + check fails or a prerequisite is unavailable. +- [x] Configure production review by `IchenDEV`, allow owner approval of their + own runs, disable administrator bypass, and restrict deployment to branch + `main` and tags `v*`. Read back the settings before proceeding. +- [x] Recheck all incomplete release runs, including queued and waiting runs. + Stop before secret writes if a signing or publishing job is already running. + Leave waiting deployments unapproved throughout configuration. +- [x] Recheck secret absence, then write the five secrets from the approved + spec through `gh secret set` standard input. Record successful names only. + Preserve repository secrets and workflow source. +- [x] Read back environment protections, deployment rules, and all five secret + names. Compare repository secret metadata and workflow source with the saved + baseline. Report remote API results separately from local test results. +- [x] Delete temporary private material and the temporary keychain. Restore + the keychain search list if changed. Keep only public verification artifacts. +- [x] Obtain a fresh-context, read-only independent verification of the + configuration and evidence. Resolve findings within the approved scope. +- [x] Record results and remaining release evidence gaps in `verification.md`. + Set its status to `pending approval` for the human verification decision. + +## Verification plan + +- [x] `bash scripts/sdlc-checks.sh` +- [x] `bash scripts/ci-basic-checks.sh` +- [x] `swift test` attempted. Its protected wrapper failed before tests; + the complete native test suites passed as recorded below. +- [x] `bash scripts/tests/test_release_workflow_contract.sh` +- [x] Check the exported PKCS#12 certificate against the approved fingerprint + and validity dates. Prove its private key works by signing the disposable + executable with the isolated imported identity. +- [x] Run `codesign --verify --strict` and inspect the signed executable's + certificate, team, and hardened runtime flags. The independent verifier + repeats these checks on the retained public executable. +- [x] Confirm notarization authentication succeeds without uploading software. +- [x] Query GitHub to prove reviewer, bypass, deployment rules, and secret-name + configuration. Confirm the repository credential metadata is unchanged. +- [x] Independently verify both callers still inherit secrets and their shared + signing job still targets `production`. + +## Failure and rollback + +Local validation failure or user cancellation leaves GitHub unchanged. A +remote failure stops subsequent writes. Remove only the environment secrets +created by this attempt, and verify their removal. Keep the new production +approval gate and report any cleanup failure. Repository secrets remain the +fallback after environment secrets are removed. Restoring weaker production +protection requires separate human authorization. + +## Human gates + +Intent and design are approved by the user's separate chat replies on +2026-10-15. The user also approved this plan on 2026-10-15. Execute the listed +configuration and validation work without further per-operation confirmation. +The user supplied credentials locally. The approved configuration is complete. +Human verification acceptance remains pending. + +Human verification approval, any required PR approval, and production approval +remain separate. Do not create a release tag, dispatch a publishing workflow, +approve a waiting production deployment, or publish a release under this plan. +Actual CI signing, Apple notarization, stapling, Gatekeeper assessment, and +mounted-DMG results require a separately authorized release run. + +## Execution evidence + +Completed on 2026-10-16. See [verification](verification.md). The protected +SwiftPM test wrapper failed before tests, so all 14 complete bundles ran through +the native XCTest and Swift Testing engines under the corrected runtime policy. +An independent verifier matched all discovered test identities and final suite +completion. The complete suite has zero behavioral failures. The wrapper setup +failure remains recorded separately. No product or workflow source was changed. diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/release.md b/docs/sdlc/changes/2026-10-15-developer-id-ci/release.md new file mode 100644 index 00000000..44b5107c --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/release.md @@ -0,0 +1,131 @@ +# Release: Utter v0.0.53 with Developer ID + +**Status:** approved +**Approved-by:** User, explicit decision for run 38770474797: 批准本次 production 发版 +**Approved-date:** 2026-10-16 +**Upstream:** [Verification](verification.md) +**Risk:** High, public software distribution + +## Authorization and candidate + +The user requested "帮我发版" on 2026-10-16 after receiving the configuration +verification. Use the existing tag release workflow and retain GitHub's human +`production` approval. The user explicitly approved production for run +`38770474797` on 2026-10-16. The agent submits that human decision to GitHub; +the independent verifier does not supply the approval. + +- Candidate: `f0ef2aa88296da017e29ced2b7bc9271af96e4fb`, current `origin/main`. +- Next version: `v0.0.53`. Latest published release is `v0.0.52`. +- Product and workflow source are unchanged. This release changes distribution + signing to the configured Developer ID identity and Apple notarization. +- Existing local SDLC evidence remains untracked and outside the release tag. + +## Preconditions + +- The candidate's `SDLC Gate`, `Contract & Tests`, and `Release-style App Build` + checks passed in PR workflow run `38089004676`. +- Complete local native suites passed on this exact source as recorded in + verification. The protected `swift test` wrapper limitation remains disclosed. +- Version syntax is valid. No remote `v0.0.53` tag or release exists. +- Production requires human reviewer `IchenDEV`, disallows administrator + bypass, and restricts deployments to `main` and `v*`. +- All five approved signing and notarization secret names exist in production. +- Initial preflight found `main` unprotected with its ruleset disabled. The + user explicitly chose "先启用 main 分支保护" on 2026-10-16. Activation + completed; a fresh GitHub read reports `protected: true` and all required + effective rules. The candidate SHA is unchanged. + +## Approved branch-protection prerequisite + +Reuse ruleset `14695153` with `enforcement: active`, target exactly +`refs/heads/main`, and no bypass actors. Retain deletion and force-push +prohibitions. Add the existing repository contract's PR requirements: one +approval, code-owner review, dismissal of stale approvals, approval of the +latest push, and resolved review threads. Require current `SDLC Gate` from +GitHub Actions integration `15368` with strict up-to-date checks. + +Save the original ruleset and the live result. Read both the effective rules +and `branches/main.protected` before tag creation. This operation changes +repository protection settings only. The user's explicit prerequisite request +authorizes this addition to the release preparation. + +The mutation and readback passed. Public before/request/after records and +effective rules are saved as `evidence/main-*.json`. Refreshed local SDLC and +basic CI checks passed. No bypass role was added. + +## Execution and acceptance + +Create an annotated tag on the exact candidate and push only that tag. The +workflow reruns repository checks and `swift test` before waiting for production +approval. Signing, notarization, stapling, Gatekeeper, mounted-DMG, checksum, and +download equality checks must succeed before publication. + +Retain the workflow URL, tag object and commit, Apple notarization result, +certificate and team, published asset checksum, and independent final review. +No tag, asset, credential, or protection is replaced on failure. Diagnose any +failure before proceeding. + +## Rollback + +Keep `v0.0.52` and its assets intact. If the new release is defective, remove it +from the latest recommendation and restore `v0.0.52` as latest with clear +notice that the prior version is not Apple-notarized. Preserve failure evidence +and open a corrective change. Never move the tag or replace same-version assets. + +## Current state + +Independent readiness review and refreshed local repository checks passed. +Main protection activation passed independent remote confirmation. + +Annotated tag `v0.0.53` was pushed and read back successfully. Its tag object is +`b8e869cddca904cd525ece4fcb36d55fd4a14a33`; its peeled commit is exactly the +candidate SHA. Public evidence is `evidence/release-tag.json`. + +[Release run 38770474797](https://github.com/IchenDEV/utter/actions/runs/38770474797) +started on that candidate. Release Candidate Tests passed. The actual CI log +records 1,143 XCTest cases, 18 conditional skips, zero failures, and one Swift +Testing case passed. Repository checks, version/main validation, and Metal +toolchain setup also passed. This CI `swift test` result is separate from the +earlier local wrapper limitation. + +The protected `production` deployment waited for required reviewer +`IchenDEV`. Its environment ID is `20910208532`; bypass is disabled. The log and pre-approval API +responses are retained in `evidence/release-candidate-tests.log`, +`evidence/release-jobs-before-approval.json`, and +`evidence/release-pending-deployment.json`. + +Independent pre-production verification passed and is recorded in +`evidence/release-before-production-independent.json`. The verifier matched +all 1,143 XCTest starts and completions. The one extra skip compared with the +local run is `DeferredReplacementPolicyTests.testDecisionRequiresSameFrontmostApp`: +the CI test process has no bundle identifier. That case passed locally. + +The user answered "批准本次 production 发版" to the question naming this exact +run, candidate test results, version, and production deployment. The agent +submitted that decision to GitHub, which records approval by `IchenDEV` for the +production environment. Deployment ID is `7098728919`. Public request-source, +response, and readback records are `evidence/release-human-production-authorization.json`, +`evidence/release-production-approval-response.json`, and +`evidence/release-production-approval-readback.json`. + +## First execution result + +The run completed with failure before publication. Candidate tests, Developer +ID app signing, certificate fingerprint checks, and mounted-DMG app equality +passed. Apple accepted submission `29a24fa6-d6b6-4053-9213-a9989e6e705a`. +Stapling and subsequent ticket validation passed. + +The DMG Gatekeeper assessment then returned `rejected`, +`source=no usable signature`, exit 3. Packaging signs the App but not the outer +DMG. `Publish GitHub Release` was skipped. GitHub reports no v0.0.53 release and +no retained workflow artifacts; latest remains v0.0.52. The failed tag remains +unchanged. Do not blindly rerun or weaken distribution verification. + +The signing log is `evidence/release-signing-attempt-1.log`; complete job states +are `evidence/release-jobs-attempt-1.json`. Independent diagnosis agrees that the +outer DMG needs Developer ID signing before notarization. The failed artifact +is unavailable for direct byte-level reinspection. + +[Corrective intent](../2026-10-16-dmg-developer-id-signing/intent.md) records the +minimal follow-up scope. It awaits human intent approval before design and +implementation under the repository's strict stage contract. diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/spec.md b/docs/sdlc/changes/2026-10-15-developer-id-ci/spec.md new file mode 100644 index 00000000..d9b59c18 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/spec.md @@ -0,0 +1,123 @@ +# Spec: Configure Developer ID signing for CI + +**Status:** approved +**Approved-by:** User, explicit chat reply: 批准 +**Approved-date:** 2026-10-15 +**Upstream:** [Intent](intent.md) + +## Context + +Both release entry points call `release-artifact.yml` with `secrets: inherit`. +Its signing job uses the `production` environment and already verifies +Developer ID signatures, notarization, stapling, and distribution artifacts. +Credential configuration is sufficient unless validation identifies a defect. + +The public repository currently has no production reviewers or deployment +restrictions. Both release entry points are active. No incomplete workflow +runs were visible during the initial inspection. Recheck before mutation. + +## Certificate and credentials + +Use only the approved local identity: + +- Name: `Developer ID Application: Chen Li (G9L7H3T3D5)`. +- Team: `G9L7H3T3D5`. +- Certificate SHA-256: + `1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112`. + +Select that identity by its certificate fingerprint through macOS Security +APIs. Export that identity as password-protected PKCS#12 with a generated +password. Do not export every identity or change login-keychain trust or +private-key access permissions. If macOS denies export, stop and request a +PKCS#12 export of this Developer ID identity. + +Collect the Apple ID and its app-specific password through local input. Check +the credentials with a read-only `notarytool history` request for the selected +team. Do not upload an app or expose submission history in the evidence. +Keep credentials out of command arguments and captured terminal output. + +Any temporary PKCS#12 file has mode `0600` inside a private temporary directory. +Use an isolated temporary keychain for import and signing checks. Restore the +original keychain search list if a check changes it. Delete temporary secrets +and the temporary keychain on completion or failure. + +## Production approval + +Before configuring secrets, set the `production` environment to require the +repository owner `IchenDEV` as reviewer, and disable administrator bypass. +Allow the owner to approve their own triggered run so the single-owner +repository can release. The independent verification requirement remains. + +Allow only branch `main` and tags `v*`. Nightly runs enter the environment with +`refs/heads/main` and create a tag inside the protected job. A tags-only +environment would block nightly before that step. Existing SemVer and +main-ancestry checks continue to constrain release artifacts. + +Recheck active release runs after setting the approval gate. Stop before +changing secrets if a signing or publishing job is already running. Do not +approve a waiting production job during configuration. No publishing workflow +is dispatched by this change. + +## Secret configuration + +Write these names only in `production`, using `gh secret set` through standard +input. Preserve the existing repository-level secrets. + +| Secret | Value source | +|---|---| +| `APPLE_CERTIFICATE_P12` | Base64 of the approved identity's PKCS#12 export | +| `APPLE_CERTIFICATE_PASSWORD` | Generated export password | +| `APPLE_ID` | User's Apple ID entered locally | +| `APPLE_TEAM_ID` | Verified certificate team `G9L7H3T3D5` | +| `APPLE_APP_PASSWORD` | User's app-specific password entered locally | + +Finish all local validation before writing secrets. Recheck that no same-name +environment secrets appeared since inspection. If any appeared, stop rather +than overwrite values that GitHub cannot return for rollback. + +Record each successful write by secret name only. Read back environment +metadata and secret names after configuration. GitHub cannot return secret +values, so their presence alone does not prove a successful signed CI build. + +## Failure containment and rollback + +Wrong identity, missing private key, failed import, failed signature check, +team mismatch, or rejected notarization credentials stop before secret writes. +Cancellation has the same effect. Do not use the supplied Apple Development +PKCS#12 as a substitute. + +If a secret write fails, remove only the environment secrets created by this +attempt. Preserve the production approval gate and report cleanup failures. +The previous repository secrets then supply the original credential values. +Save the previous environment settings as public metadata. Restoring weaker +production protection requires a separate explicit human decision. + +Workflow source remains unchanged. Any defect that requires a code change +returns to design review before implementation. + +## Verification + +- Check the exported certificate fingerprint, validity, team, and matching + private key. Import into the temporary keychain and sign a disposable local + executable. Verify its signature, certificate fingerprint, and team. +- Verify Apple accepts the notarization credentials through the read-only + request. Report authentication success without history contents. +- Run the required SDLC checks, basic repository checks, Swift tests, and the + release workflow contract test. Record failures or unmet prerequisites. +- Read back production reviewers, bypass policy, branch and tag rules, and all + five secret names. Check that repository secret metadata is unchanged. +- Obtain independent verification of the risk-critical evidence before + implementation handoff. A verifier does not approve production. +- A real GitHub signing, notarization, and Gatekeeper result remains unverified + until a separately authorized release run completes. + +## Approval boundary + +This design does not begin implementation. After human design approval, +prepare the implementation plan and obtain its required approval before +exporting keys, collecting notarization credentials, or changing GitHub. + +## References + +- [GitHub environment protection and deployment ref rules](https://docs.github.com/en/actions/reference/workflows-and-actions/deployments-and-environments) +- [Apple keychain import and export APIs](https://developer.apple.com/documentation/security/keychain-items) diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/verification.md b/docs/sdlc/changes/2026-10-15-developer-id-ci/verification.md new file mode 100644 index 00000000..81f685b1 --- /dev/null +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/verification.md @@ -0,0 +1,126 @@ +# Verification: Configure Developer ID signing for CI + +**Status:** approved +**Approved-by:** User, explicit chat request after verification handoff: 帮我发版 +**Approved-date:** 2026-10-16 +**Upstream:** [Plan](plan.md) + +## Current state + +Configuration completed on 2026-10-16. Intent, design, and plan have separate +human approvals. Apple credential validation and GitHub configuration passed. +After receiving this verification and its disclosed limitations, the user +requested a release on 2026-10-16. That request accepts this configuration +verification and authorizes preparation of the separate production release. +The original configuration operation did not dispatch a release. + +## Remote result + +- `notarytool store-credentials` validated the supplied credentials, and the + read-only `notarytool history` request succeeded for team `G9L7H3T3D5`. +- The `production` environment contains all five approved `APPLE_*` secret + names. Values were sent through standard input and cannot be read back. +- Production requires reviewer `IchenDEV`. The owner can review their own + triggered runs. Administrator bypass is disabled. +- Custom deployment restrictions are active and contain exactly branch `main` + and tags `v*`. Both release entry points retain their shared workflow. +- Both original repository secret metadata records are unchanged. Workflow + source and `Package.resolved` remain unchanged. +- The temporary credential keychain and private directory were removed. The + original user keychain search list matches byte for byte. +- The helper exited 0 with `configuration_success` and `success` true and no + cleanup errors. No tag, publishing dispatch, or production approval was sent. +- Independent post-configuration verification passed. Fresh GitHub API reads + match the approved settings and saved evidence. The verifier reconfirmed + workflow hashes, test identity coverage, bundle hashes, and cleanup records. + +Public readbacks and summaries are saved in [evidence](evidence/). They contain +secret names and public metadata, never secret values. + +## Local evidence + +| Check | Result | +|---|---| +| `bash scripts/sdlc-checks.sh` | Pass | +| `bash scripts/ci-basic-checks.sh` | Pass | +| `bash scripts/tests/test_release_workflow_contract.sh` | Pass | +| Native SwiftPM test build, four jobs | Pass, native SwiftPM sandbox retained | +| Protected `swift test --skip-build` | Setup failure before tests: nested `sandbox_apply` denied | +| All 14 native XCTest bundles | 1,143 cases complete, 1,126 passed, 17 conditional skips, zero failures | +| Swift Testing | One unique case passed | +| Test bundle integrity | All 300 recorded files unchanged after execution | +| Workflow and `Package.resolved` hashes | Unchanged | +| Developer ID export, isolated import, signing | Pass | +| Disposable executable signature, team, certificate, hardened runtime | Pass | +| Independent local verification | Pass, discovery identities match all completed cases | +| Configuration helper failure-path checks | Pass, rollback preserves unrelated secrets and cancellation ends its child | + +The full native test run uses Xcode's `xctest` and `swiftpm-testing-helper` +against every complete bundle built from this checkout. The latter runs the +sole Swift Testing case again as a cross-check. Count that case once. +Thirteen bundles declare no Swift Testing cases; their helper invocations +report empty suites and exit 69. These are not extra passed test cases. + +The original protected `swift test` command did not pass. Its wrapper failed +before test execution. The complete native run establishes the actual test +results without placing the build process inside the runtime policy. + +The runtime policy blocks production preference, keychain, Contacts, and app +storage paths and the corresponding sensitive Mach services. It permits the +AppKit and UUID-named pasteboard services required by the tests. A fresh-domain +canary cannot persist real user preferences. Opening the real keychain file +returns `EPERM`. A separate nonexistent-keychain-item query returned item not +found and does not prove broker denial. Test processes receive a minimal +environment with no inherited API credentials. + +The selected Developer ID certificate SHA-256 is +`1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112`, +with team `G9L7H3T3D5`. The signed executable's embedded certificate matches. +Its verification enables hardened runtime; it is a local signing check, not a +release artifact or notarization result. + +## Corrected setup failures + +- Blanket denial of Mach services prevented named pasteboard tests and + interrupted the recovery-composition test. The corrected policy preserves + sensitive-service denial while allowing those required native services. +- Loader variables assigned before `sandbox-exec` were stripped. Assigning + framework and library paths inside the guard loads the native test engines. +- The first configuration preflight used Homebrew OpenSSL 4, which rejects + Apple's RC2-40-CBC PKCS#12 encoding. It attempted no secret writes and fully + cleaned up. System LibreSSL decodes the export and verifies its fingerprint. + The configuration helper now explicitly uses `/usr/bin/openssl`. + +## Remaining verification + +- The separately authorized release run for real CI signing, accepted + notarization of software, stapling, Gatekeeper, mounted-DMG verification, and + published-checksum evidence. Successful authentication alone proves none of + those release results. + +The user requested that run on 2026-10-16. Its state and evidence are tracked +in [release](release.md). GitHub's human production approval remains required. + +## Rollback + +Remove only the five `production` environment secrets listed in +`evidence/configuration-state.json`. This restores selection of the unchanged +repository-level certificate credentials. Preserve the production reviewer and +deployment restrictions. Restoring weaker protection requires separate human +authorization. No release artifact needs rollback because none was published. + +## Security note + +An unsuccessful XCTest help invocation unexpectedly printed its inherited +environment, including an existing API token, in tool output. The token was +not copied into repository files or evidence. The user was notified and +advised to rotate it. Subsequent test and credential operations use minimal +environments. Token rotation has not been performed by this task. + +## Evidence location + +Public task evidence is at +`/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/`. +The complete passing run is `native-run-9d5cbdd1/`, with per-bundle discovery, +commands, completion records, and logs. No credential values belong in this +verification document. diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1.log new file mode 100644 index 00000000..27e58064 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1.log @@ -0,0 +1,107 @@ + +==> Checking Package.swift +Swift module boundaries passed. +...... +---------------------------------------------------------------------- +Ran 6 tests in 0.002s + +OK +Owned resources passed. +..... +---------------------------------------------------------------------- +Ran 5 tests in 0.031s + +OK +FFFFFF...................E +====================================================================== +ERROR: test_voice_quality_acceptance (unittest.loader._FailedTest) +---------------------------------------------------------------------- +ImportError: Failed to import test module: test_voice_quality_acceptance +Traceback (most recent call last): + File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/unittest/loader.py", line 436, in _find_test_path + module = self._get_module_from_name(name) + File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/unittest/loader.py", line 377, in _get_module_from_name + __import__(name) + File "/Users/chenli/projects/utter/scripts/tests/test_voice_quality_acceptance.py", line 6, in + from voice_quality_acceptance import REQUIRED_DEMOS, acceptance_report + File "/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py", line 8, in + def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]: +TypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType' + + +====================================================================== +FAIL: test_fidelity_preserves_sentence_email_opaque_paths_and_quotes (test_evaluate_voice_quality.VoiceQualityEvaluatorTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py", line 145, in test_fidelity_preserves_sentence_email_opaque_paths_and_quotes + self.assertEqual(result.returncode, 0, result.stderr) +AssertionError: 1 != 0 : Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py", line 14, in + from voice_quality_acceptance import acceptance_report + File "/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py", line 8, in + def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]: +TypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType' + + +====================================================================== +FAIL: test_fidelity_rejects_added_numbers_and_changed_unicode_space_path (test_evaluate_voice_quality.VoiceQualityEvaluatorTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py", line 103, in test_fidelity_rejects_added_numbers_and_changed_unicode_space_path + self.assertEqual(result.returncode, 0, result.stderr) +AssertionError: 1 != 0 : Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py", line 14, in + from voice_quality_acceptance import acceptance_report + File "/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py", line 8, in + def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]: +TypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType' + + +====================================================================== +FAIL: test_fidelity_rejects_reordered_number_ownership (test_evaluate_voice_quality.VoiceQualityEvaluatorTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py", line 169, in test_fidelity_rejects_reordered_number_ownership + self.assertEqual(result.returncode, 0, result.stderr) +AssertionError: 1 != 0 : Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py", line 14, in + from voice_quality_acceptance import acceptance_report + File "/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py", line 8, in + def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]: +TypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType' + + +====================================================================== +FAIL: test_help_documents_schema (test_evaluate_voice_quality.VoiceQualityEvaluatorTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py", line 189, in test_help_documents_schema + self.assertEqual(result.returncode, 0) +AssertionError: 1 != 0 + +====================================================================== +FAIL: test_rejects_missing_required_field_with_line_number (test_evaluate_voice_quality.VoiceQualityEvaluatorTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py", line 178, in test_rejects_missing_required_field_with_line_number + self.assertEqual(result.returncode, 2) +AssertionError: 1 != 2 + +====================================================================== +FAIL: test_reports_asr_processed_fidelity_hallucination_and_latency (test_evaluate_voice_quality.VoiceQualityEvaluatorTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py", line 61, in test_reports_asr_processed_fidelity_hallucination_and_latency + self.assertEqual(result.returncode, 0, result.stderr) +AssertionError: 1 != 0 : Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py", line 14, in + from voice_quality_acceptance import acceptance_report + File "/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py", line 8, in + def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]: +TypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType' + + +---------------------------------------------------------------------- +Ran 26 tests in 17.409s + +FAILED (failures=6, errors=1) diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks.log new file mode 100644 index 00000000..b3ef88df --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks.log @@ -0,0 +1,115 @@ + +==> Checking Package.swift +Swift module boundaries passed. +...... +---------------------------------------------------------------------- +Ran 6 tests in 0.002s + +OK +Owned resources passed. +..... +---------------------------------------------------------------------- +Ran 5 tests in 0.022s + +OK +............................... +---------------------------------------------------------------------- +Ran 31 tests in 14.442s + +OK + +==> Checking SDLC artifacts and harness regression tests +==> Checking docs/sdlc/changes/2026-08-25-ai-native-sdlc/ +==> Checking docs/sdlc/changes/2026-08-26-dmg-installer-polish/ +==> Checking docs/sdlc/changes/2026-08-29-espresso-ane/ +==> Checking docs/sdlc/changes/2026-08-30-dev-app-icon-packaging/ +==> Checking docs/sdlc/changes/2026-08-30-history-mode-switch/ +==> Checking docs/sdlc/changes/2026-08-30-model-type-selection/ +==> Checking docs/sdlc/changes/2026-08-30-settings-window-layout/ +==> Checking docs/sdlc/changes/2026-08-30-system-settings-groups/ +==> Checking docs/sdlc/changes/2026-08-31-ane-lm-runtime/ +==> Checking docs/sdlc/changes/2026-08-31-settings-semantic-background/ +==> Checking docs/sdlc/changes/2026-08-31-shell-sdlc-gate/ +==> Checking docs/sdlc/changes/2026-08-31-website-native-redesign/ +==> Checking docs/sdlc/changes/2026-09-03-release-p12-openssl3/ +==> Checking docs/sdlc/changes/2026-09-18-nightly-release-pipeline/ +==> Checking docs/sdlc/changes/2026-09-21-model-download-retry-recovery/ +==> Checking docs/sdlc/changes/2026-09-21-remote-mic-integration/ +==> Checking docs/sdlc/changes/2026-09-21-settings-surface-parity/ +==> Checking docs/sdlc/changes/2026-09-23-confucius4-r2t2-mlx/ +==> Checking docs/sdlc/changes/2026-09-23-input-session-ownership/ +==> Checking docs/sdlc/changes/2026-09-23-silent-input-insertion/ +==> Checking docs/sdlc/changes/2026-09-24-industry-lexicon-expansion/ +==> Checking docs/sdlc/changes/2026-09-24-release-workflow-permissions/ +==> Checking docs/sdlc/changes/2026-09-28-release-input-contract/ +==> Checking docs/sdlc/changes/2026-09-30-firered-asr-download-completeness/ +==> Checking docs/sdlc/changes/2026-10-01-clamshell-mic-failover/ +==> Checking docs/sdlc/changes/2026-10-01-stable-prompt-prefix-cache/ +==> Checking docs/sdlc/changes/2026-10-03-builtin-plugin-composition/ +==> Checking docs/sdlc/changes/2026-10-03-promo-videos/ +==> Checking docs/sdlc/changes/2026-10-04-voice-input-reliability/ +==> Checking docs/sdlc/changes/2026-10-07-desktop-numeral-list-fidelity/ +==> Checking docs/sdlc/changes/2026-10-07-xiaomi-remote-connection/ +==> Checking docs/sdlc/changes/2026-10-15-developer-id-ci/ +==> Checking docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/ +SDLC checks passed. +Build version tests passed. +Release version tests passed. +Nightly release plan tests passed. +From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.alrzU6hYot/origin + * branch main -> FETCH_HEAD +From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.alrzU6hYot/origin + * branch main -> FETCH_HEAD +Signing mode: developer-id +Signing mode: self-signed +Release workflow contract tests passed. + +==> Linting property lists and localized strings +Resources/Info.plist: OK +Resources/OpenType.entitlements: OK +Sources/UtterContracts/Resources/en.lproj/Localizable.strings: OK +Sources/UtterContracts/Resources/zh-Hans.lproj/Localizable.strings: OK + +==> Checking brand and compatibility identifiers + +==> Checking localization key parity + +==> Checking industry vocabulary +Building for debugging... +[Pre-planning 1 / 181] +[Planning deferred tasks] +[1 / 11] +[2 / 12] UtterRuntime +[13 / 47] +[20 / 47] +[22 / 47] +[26 / 47] +[29 / 47] +[34 / 47] +[35 / 47] +[36 / 47] +[37 / 47] +[43 / 51] UtterRuntime +[44 / 52] UtterContracts +[48 / 54] UtterData +[52 / 57] UtterData +[57 / 61] UtterLexiconCheck-product +[60 / 61] UtterLexiconCheck-product +Build complete! (4.94秒) +Industry lexicon deterministic evaluation passed + baseline term recall: 20.59% + treatment term recall: 100.00% + absolute improvement: 79.41 points + non-target preservation: 100.00% + +==> Checking required app resources + +==> Checking bundled helper names + +==> Checking for conflict markers + +==> Checking tracked secret-bearing file types + +==> Checking for broken symlinks + +Basic CI checks passed. diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/design-approval-snapshot.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/design-approval-snapshot.json new file mode 100644 index 00000000..9f6de29f --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/design-approval-snapshot.json @@ -0,0 +1,12 @@ +{ + "recorded_at_utc": "2026-10-15T17:40:04.012020+00:00", + "stage": "design", + "status": "pending human approval", + "spec_path": "spec.md", + "spec_sha256": "f44f318e69ccae7fb844369441ed6d2a8d60e2ea123f5cdd5a72a71e870f23f3", + "independent_review_result": "no_design_blocker", + "independent_review_spec_sha256": "1295ed50787bbf334ac566298486f231537d4e4a5d20d8f00e2eb2abf44a6d59", + "post_review_changes": "Incorporated actual-verifier positive/negative test clarification and recorded completed review. No design policy change.", + "implementation_started": false, + "next_stage": "Plan only after explicit human design approval" +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/design-independent-review.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/design-independent-review.json new file mode 100644 index 00000000..07511918 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/design-independent-review.json @@ -0,0 +1,121 @@ +{ + "verifier": "/root/signing_verifier", + "reviewed_at_utc": "2026-10-15T17:38:48.371981+00:00", + "result": "no_design_blocker", + "human_design_approval": false, + "spec_sha256": "1295ed50787bbf334ac566298486f231537d4e4a5d20d8f00e2eb2abf44a6d59", + "scope": "Read-only independent review of proposed shared CI DMG signing and verifier boundary; implementation has not been reviewed because it does not exist.", + "reviewed_files": [ + "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/intent.md", + "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/spec.md", + ".github/workflows/release.yml", + ".github/workflows/nightly-release.yml", + ".github/workflows/release-artifact.yml", + ".github/workflows/manual-app-artifact.yml", + "scripts/build-app.sh", + "scripts/build-and-run.sh", + "scripts/verify-release-artifact.sh", + "scripts/tests/test_release_workflow_contract.sh", + "scripts/tests/test_release_version.sh", + "scripts/tests/test_nightly_release_plan.sh", + ".github/CODEOWNERS" + ], + "call_path_review": [ + { + "caller": "release.yml and nightly-release.yml", + "route": "Both invoke release-artifact.yml with inherited secrets.", + "effect": "Single Developer ID signing correction before first strict verification covers both public release entry points." + }, + { + "caller": "release-artifact.yml classification block", + "route": "App must match imported SIGN_IDENTITY before Developer ID branch; expected certificate SHA-256 is already passed to verifier.", + "effect": "Signing DMG with exact identity then checking its certificate against app/imported fingerprint fails closed before notarization." + }, + { + "caller": "release-artifact.yml final distribution block", + "route": "require-developer-id plus require-notarization", + "effect": "Reuses strengthened container check after staple, with existing ticket, Gatekeeper and checksum gates retained." + }, + { + "caller": "build-app.sh generic and app-only paths", + "route": "No require-developer-id option currently passed to generic packaging verification.", + "effect": "They keep current packaging scope. Shared CI step owns distribution container signing." + }, + { + "caller": "manual-app-artifact.yml", + "route": "Fixed historical checkout, app-only acceptance verification without DMG or Developer ID requirement.", + "effect": "Does not enter the new container guard." + }, + { + "caller": "self-signed release classification", + "route": "require-self-signed branch", + "effect": "Does not receive a Developer ID-only DMG signature requirement." + } + ], + "security_review": { + "exact_imported_identity_reused": true, + "fingerprint_equality_required_even_without_expected_flag": true, + "secure_timestamp_required": true, + "container_identifier_distinct_from_app": true, + "app_entitlements_runtime_deep_not_applied_to_dmg": true, + "signing_failure_stops_before_notarization": true, + "gatekeeper_gate_retained": true, + "new_credentials_permissions_dependencies_required": false, + "failed_v0053_tag_and_old_assets_preserved": true + }, + "blockers": [], + "implementation_test_clarifications": [ + { + "priority": 2, + "location": "spec.md Test strategy", + "requirement": "Native smoke must execute the actual verify-release-artifact.sh boundary for positive and unsigned/mismatched/no-secure-timestamp negative images. Merely running native codesign/extraction commands does not prove the new verifier guard.", + "resolution": "Make this explicit in the implementation plan; reuse the existing real release-style app fixture and/or a credential-free tool boundary fixture rather than adding a framework or needing another real signing credential." + }, + { + "priority": 2, + "location": "Workflow literal-block regression", + "requirement": "Run the actual extracted run block with external bash -e semantics and an observable signing-before-verification order. Signing failure must prevent verifier invocation; the old block must fail the new check.", + "resolution": "Extend the existing contract harness as proposed. A source grep alone is insufficient." + } + ], + "rollout_evidence_gap": { + "observed_collaborators": [ + { + "login": "IchenDEV", + "role_name": "admin", + "admin": true + } + ], + "sensitive_path_codeowner": "IchenDEV", + "ruleset_active": true, + "bypass_actors": [], + "required_approving_review_count": 1, + "require_code_owner_review": true, + "require_last_push_approval": true, + "gap": "No distinct eligible code-owner reviewer is currently identified if the eventual PR author is IchenDEV. Resolve the concrete PR approval route by explicit human decision before merge.", + "not_authorized_by_this_review": [ + "Adding collaborators", + "Changing CODEOWNERS", + "Weakening or bypassing main rules", + "Approving production" + ] + }, + "rollout_remaining_gates": [ + "Human design approval", + "Implementation plan approval", + "Actual diff plus regression old/fail/pass evidence and native boundary smoke", + "Required repository/full native tests and release-style packaging", + "Independent implementation verification and human verification acceptance", + "Concrete PR approval and protected main merge", + "Exact merged SHA CI gate, new unused version, run-specific human production approval", + "Independent final signed/notarized artifact and checksum download review" + ], + "apple_reference": "https://developer.apple.com/documentation/xcode/packaging-mac-software-for-distribution", + "verifier_mutations": { + "source_edits": false, + "remote_writes": false, + "credential_access": false, + "human_approval_recorded": false, + "report_only": true + } +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/evidence-retention.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/evidence-retention.json new file mode 100644 index 00000000..8cb5c6c0 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/evidence-retention.json @@ -0,0 +1,29 @@ +{ + "included": "Public JSON summaries, SDLC artifacts and focused local logs; original hosted logs remain byte-for-byte local and available by run/job, without binaries or credentials", + "local_only_raw_logs": [ + { + "path": "docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-candidate-tests-independent.log", + "size": 1178762, + "sha256": "f46e1adc5ae48fe311d2c069d6dec5f2c63fad5e485b6341b95db41e8edde1bc", + "retention": "Preserved locally; complete hosted CI test log remains available in run 38770474797, job 116544650129" + }, + { + "path": "docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-candidate-tests.log", + "size": 1178762, + "sha256": "f46e1adc5ae48fe311d2c069d6dec5f2c63fad5e485b6341b95db41e8edde1bc", + "retention": "Preserved locally; complete hosted CI test log remains available in run 38770474797, job 116544650129" + }, + { + "path": "docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-signing-attempt-1.log", + "size": 64187, + "sha256": "99ed5253bec64abdf7ca64dc54a3a950acac5365bde6b61aac1c901ccfe0f020", + "retention": "Preserved byte-for-byte locally, including original trailing whitespace; exact hosted signing log is run 38770474797, job 116549335673. Failure summary and independent verification are committed." + }, + { + "path": "docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-signing-independent-attempt-1.log", + "size": 64187, + "sha256": "99ed5253bec64abdf7ca64dc54a3a950acac5365bde6b61aac1c901ccfe0f020", + "retention": "Preserved byte-for-byte locally, including original trailing whitespace; exact hosted signing log is run 38770474797, job 116549335673. Failure summary and independent verification are committed." + } + ] +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/full-test-evidence.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/full-test-evidence.json new file mode 100644 index 00000000..137626df --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/full-test-evidence.json @@ -0,0 +1,14 @@ +{ + "native_evidence": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/native-run-f8535155", + "xctest_bundles": 14, + "xctest_executed": 1143, + "xctest_skipped": 17, + "xctest_failures": 0, + "unique_swift_testing_cases": 1, + "swift_testing_failures": 0, + "expected_empty_swift_testing_bundles": 13, + "complete": true, + "frozen_bundle_files_unchanged": 300, + "runtime_preflight": "native-suite-preflight.json", + "standard_swift_test": "Separate protected-wrapper result; not inferred from native engines." +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-baseline.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-baseline.json new file mode 100644 index 00000000..74fc66c9 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-baseline.json @@ -0,0 +1,776 @@ +{ + "recorded_at_utc": "2026-10-16T02:51:05.829002+00:00", + "head": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "branch_before": "main", + "status_before": "?? docs/sdlc/changes/2026-10-15-developer-id-ci/\n?? docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/\n", + "disk_free_bytes": 23619723264, + "build_inputs_sha256": { + "Package.resolved": "3a007c520b8b69aa9a675a42675662d7d272e4808dd3e71e4f12e074150219ad", + "Package.swift": "ded5ad0b89a458016a01547dce0045c9034d3947ee556fb7d185ecbcd2271d24", + "Resources/Info.plist": "7c9a6e49d9f5c74cff2ef390ed89f90cf599887e0474b11b61c1c85200393797", + "Resources/OpenType.entitlements": "7abff119408b92f34f7b5b7399f5281ff270c74e2b6a2719dc87a6ef744f36b8", + "Sources/App/OpenTypeApp.swift": "6eab726c65ddb63c1a257f5c0700e5729224209a942b93329f7bf87ad3f8ce31", + "Sources/UtterANE/ANEGenerationService.swift": "a943b8535a01151e792cc62aebd6fd5bcc3aa7a5dc17409d74656665578144bc", + "Sources/UtterANE/ANELMTokenizerValidation.swift": "004a407bb0cb7377eb3cdf5c43bbe79a5816614a3fb2680900a3387f9629aaa1", + "Sources/UtterANE/ANEPlugins.swift": "fce2b1c33b72d6e8d1ecc3b3628f0a82b05bb81e6af70ee8fb9ed9acacf35e68", + "Sources/UtterANE/EspressoLLMEngine.swift": "63e13661ad3d753f1e8c798a82cb953c2a32bc40b1fc966ac418a51ae2974453", + "Sources/UtterAppleSpeech/AppleSpeechAnalyzer.swift": "52871c84af4b39e4667635e41cb49898c83c10d0ee028d886be3b4ace67e2829", + "Sources/UtterAppleSpeech/AppleSpeechEngine.swift": "9da2d9d94d5c9a7c9a3b29a840b2471660c9f012e7d0e6d55dacec4be116402b", + "Sources/UtterAppleSpeech/AppleSpeechEngineAdapter.swift": "ce40d5c88b92d8fbdfee2666e4773506b9ee8255911ee2b9db0388b162483485", + "Sources/UtterAppleSpeech/AppleSpeechPlugins.swift": "3de4b8706c6309052097e21f9798a820a97c660e24f5825d06abb0bdca289dbd", + "Sources/UtterAppleSpeech/AppleSpeechTranscriptionFallback.swift": "806d7c18e78fb9ac490e2726bcf2e9879da91b37094854bd52057ef24b03da61", + "Sources/UtterAudio/AudioCaptureDiagnostics.swift": "038108af891b7b8ed3df36d620cfdacea15095e02baedb9eb5caaca130557448", + "Sources/UtterAudio/AudioInputResolver.swift": "340817d645900ee41bdcfe0d47cf5f76a5da256ec5ec6a052043c8ffaf50722c", + "Sources/UtterAudio/AudioTailDrain.swift": "ba2251dc010898ced4d93c7b7c0877ef86de505cab82586388694d4acc565fcf", + "Sources/UtterAudio/ClamshellValue.swift": "8dbb684f6a526f6b0991ab2c3c56915fa0a9ca15472f36be220479329bee3443", + "Sources/UtterAudio/Native/AudioCaptureManager+Devices.swift": "8c53a31d93ab1e9f4abb8f400eff5a43cd02b02018d75b74e6e2563c44f73885", + "Sources/UtterAudio/Native/AudioCaptureManager+Remote.swift": "ef6b0273a498cc9db2819265d2d9ddd3abfb7d63b75bd3b802daa6896c1e77cc", + "Sources/UtterAudio/Native/AudioCaptureManager+Tap.swift": "5183579dd24c3a32c13d5772bbe477e166ce9dcef5e0e16f9e64cbaf405a8cf1", + "Sources/UtterAudio/Native/AudioCaptureManager.swift": "5eb24fc5d746392d363d619133936f329c662108ff532493c08bc8173fca9083", + "Sources/UtterAudio/Native/AudioFileService.swift": "11d64d275c77c52fb9327a5cc6eadbc4041bfaa7571f10253f6c86ddcaffa4f1", + "Sources/UtterAudio/Native/AudioInputDevices.swift": "c80245d0bb925ee1d667bb591ab1e11c8ec92afb3110ce108875fb19be326638", + "Sources/UtterAudio/Native/AudioPlugins+Devices.swift": "64f20f1516b805d952c072750512719eb97f7992ccec61d03d2f1f6035543fb0", + "Sources/UtterAudio/Native/AudioPlugins+Evidence.swift": "ee85d3e740a261f83eaa6e3687ab206be8c57f6f421486bb350b43bfd7b466bc", + "Sources/UtterAudio/Native/AudioPlugins.swift": "2c707cab349dc3aa950a9ba63ceb958250fc4c831102fac82f5eba9d8be859a9", + "Sources/UtterAudio/Native/CaptureCallbackGate.swift": "069505111e1ee161845df7ef8f397f161667038ec4d340939c1a0927716b7e97", + "Sources/UtterAudio/Native/CaptureDrivers.swift": "1a2238c839c91e29d391c8e315d7ed99e7fa58451001595981578047b84af5d6", + "Sources/UtterAudio/Native/ClamshellState.swift": "1ccdb3729fc5301f815baf9cb9423d8971eab8c5146980a5b50232aec7575d1a", + "Sources/UtterAudio/Native/ScopedCaptureService.swift": "d365d27dee488a0d0c876c6440e6bd9249203c4919feb243f1ff9d47a0e606b6", + "Sources/UtterAudio/Native/ScopedSpeechEvidenceService.swift": "3ac7eaed9e312537e16002e4dd7e4d1c774493a38aa8bd8b954364efb540b92a", + "Sources/UtterAudio/Native/SpeechActivityClassifier.swift": "b7e5250967f94522d0050cef96c9c8834d751ff572f41b743ce79ea3f798c709", + "Sources/UtterBuiltins/BuiltinRegistrationPolicy.swift": "1407e97cc96766237e8b413189f0c499d92c8a301acbf8bbf5a525944ad9238d", + "Sources/UtterBuiltins/Native/BuiltinApplication.swift": "7f09503db7154e7f010a80ea22513d48de93bcab60bf27016d077d583826eb2c", + "Sources/UtterBuiltins/Native/BuiltinCompositions.swift": "71181a2c89f098e46ec70db04addf7245a2b9000c89133a390f9a1d27de9e182", + "Sources/UtterBuiltins/Native/BuiltinPlugins.swift": "e74b67657f4f05591dde17be70d7ae79f25c3545ab212267d88e0e108b52d8c1", + "Sources/UtterContracts/AppSettingTypes.swift": "a9a42573644dd3fe12440d49cd2f62667ff73c2038885d31f0629d77653293cf", + "Sources/UtterContracts/AudioActivityThresholds.swift": "8bda48cc4782159cc011eab897278b200baa7eaff4f2ab13dc12c73138a8061b", + "Sources/UtterContracts/AudioCaptureActivity.swift": "c4f09bd439965d3864767cb895cc33e1479e8ff14eb7194159e4192bc122f724", + "Sources/UtterContracts/AudioInputDevice.swift": "5dd4d866a9140085120f0693fae0872f0ce641f27e6dbaebf0867d94121a6344", + "Sources/UtterContracts/Character+ASCIIWord.swift": "8972e835784b616a11251fbfe01e34403421ff6d166c7cf4a44db8dd80f43bc1", + "Sources/UtterContracts/CompositionDocument.swift": "19380a7e2af47134dd8498fd9f5089a9c218c8b570baa6b3f58a2364070969b7", + "Sources/UtterContracts/CompositionLayer.swift": "57e180ea7e3b087bcc16809486a20ebea3827ac9daa462b9f733c45aa5b07dc1", + "Sources/UtterContracts/CorrectionCaptureSeed.swift": "287553bbf9465e193df0f81f048034976c194a5d21e9eb6033ce45bd7f4c274d", + "Sources/UtterContracts/CorrectionClassificationService.swift": "672bfbc2001e0b7862027265696f1d2d02879e95b69a7049e45280d07987d1c3", + "Sources/UtterContracts/CredentialsService.swift": "e455bc75f3276106f1cdb86fefee3b30f3eef24acac53e0099477a49900588bf", + "Sources/UtterContracts/DataServices.swift": "c2a8421783fbb500eb92320d8d5b9b18212b6c4533f12c5ec5f13f5645882d99", + "Sources/UtterContracts/DeferredReplacement.swift": "e5b5bb247c681be999b31a9c2f5e008d709dc43e20737097a4f765811bd385f7", + "Sources/UtterContracts/DeferredReplacementPolicy.swift": "ddf8fa44bf237f2ced23aab8f2dadf7a8197b4dea20362735c48bf622be48665", + "Sources/UtterContracts/DeliveryServices.swift": "735ab7f6e8ca7bede44fabe778d08273a644a510d020f957d4f8bc18dbfa15ae", + "Sources/UtterContracts/DictionaryEntry.swift": "383c3cd5365b70048f02edc6cbe4a601923695feb42cc759aacf365b378bd15c", + "Sources/UtterContracts/DictionaryService.swift": "70973fb1e15fcf5452a180066e08ed65e8674e350ca69f19b4e499a7adbae33d", + "Sources/UtterContracts/DownloadProgressInfo.swift": "d69e4f3e1999d9eaecc38919abc0b841a7cae464d60469cebde7ce0ab5f2f8e2", + "Sources/UtterContracts/EspressoGenerationOutcome.swift": "69e4f870e9f0a9f373a2943d5992a4121a1727de4a52554b5df426a449229f00", + "Sources/UtterContracts/EspressoLLMError.swift": "c7326920219e673846186d5092d5ead772748a09b3746e3bc7aa6163ebe3ef20", + "Sources/UtterContracts/EspressoMLXFallbackError.swift": "dcc8fa7ff26df31ccb9276c92e8e5e8a92bcf3867e9adaea3c9c1c1f2f188182", + "Sources/UtterContracts/FrozenModelFiles.swift": "e767edb73dfab26f5afaa6934906d49903ce52f735010edea07333e013bdec2f", + "Sources/UtterContracts/GenerationServices.swift": "e9c4dcd9320f354413b1e5ee85ab90d35cd19bda032952c09ac56adb12e4edf5", + "Sources/UtterContracts/GenerationTimingObservation.swift": "3ffb5236b56e8dce81b66a0462141328d88d5389153462291aeadd99468ea0e3", + "Sources/UtterContracts/HistoryService.swift": "e56cf76534d267e90e7330e9cd22db3d47d9551d59407f36b4cff5981f441cda", + "Sources/UtterContracts/HotkeyAction.swift": "f469067853f1685948e4da615d7599c9f13bcbba4eb8f68e6c29e0a51967dc31", + "Sources/UtterContracts/IndustryLexiconSnapshot.swift": "0c0e32d3247ed42a2a76926cf4a056b8cc3e5a4605cb60cbfb41c5a0388a9ac6", + "Sources/UtterContracts/InputContext.swift": "babcb2ad1727fad56da7648d97e9bc1e2a6349cad98efe713cf66a86a10ec29e", + "Sources/UtterContracts/InputRecord.swift": "775c1581023de42b264915ea2712a8c8e2d6e423a43511cb056d929573a70206", + "Sources/UtterContracts/InputSessionModels.swift": "02ed200adf10091098699964ece8dabd8f5862e01dccdf2bcc7ea5788a12fd9c", + "Sources/UtterContracts/InputSessionService.swift": "d75bc28ca7ed7edbf2f7563f4c82e23a08893a705b0332af78df89b0383b2b1b", + "Sources/UtterContracts/InsertResult.swift": "524b9a5306dbf25f5831ddf973df285435cee2048a0dcab978617fa6b65cc61a", + "Sources/UtterContracts/IntegrationClient.swift": "721ee0f98b41bf654bbb0747b67c33cce4886e9309fb4ab3206d25603fe463fe", + "Sources/UtterContracts/IntegrationError.swift": "40436a88e956704f8853b4a530624307ef9af877e271e2855d18d4bee0e00ce5", + "Sources/UtterContracts/IntegrationServices.swift": "65ec02cae3e36ef55da985c791e9bd38e7ccc3fdb155fa0c93bb3006b150603e", + "Sources/UtterContracts/LLMActionValue.swift": "54e38ff467cd62e5b04f50beabad0977ed455b038447491f27b76bb7d7ee5d47", + "Sources/UtterContracts/LLMDecodedValue.swift": "c1b86efff1530954a8a4661e772bd9c9ebfdbc61d0ce8ac7d31fd753b1aac7fe", + "Sources/UtterContracts/LLMError.swift": "3d60f4618f8d09a8f61373ae609ff62bdbbfad4e4ba746d42254783e260ec5cf", + "Sources/UtterContracts/LLMFinalTextOutput.swift": "a2827331f41f3f432c21dae3cd17e30dd9baebe7b9e4e656f807aaf25ed2cdcf", + "Sources/UtterContracts/LLMScaffoldedOutput.swift": "51b96d2348e37917f5f929e5817c43731873da6fb4ee847649f0cef1f96b9fc5", + "Sources/UtterContracts/LLMStructuredOutput+DecodedStrings.swift": "4104c494d8fcbe7e508162de650a6004cdf6ada57016947df5af83ae2308e535", + "Sources/UtterContracts/LLMStructuredOutput.swift": "274645a3bb8c9e2f5da035faca0a9d44c63779c30de7bebbc678cce154c09757", + "Sources/UtterContracts/LearnedCorrectionPolicy.swift": "9a35f9d13f83dd9d82b4eaaf0108f4849ece6c3a56f557c5d5dd8b55d36225d8", + "Sources/UtterContracts/Loc.swift": "ffbb5c7a8c1ddf7a3845b6ecceceb5d01cd50141cc473184bfa2861e1162ba18", + "Sources/UtterContracts/LocalGenerationBudget.swift": "a8fa76f11df4b749b39d18302291ba5cdb4d49055141d0bce042cdcdbe1c2f7e", + "Sources/UtterContracts/Log.swift": "cc85aaeeac89358e7038ab41975e57053b282dc7bf361823f20651ae250b6741", + "Sources/UtterContracts/MLXSTTError.swift": "04d2c2dfa5de265c30abb9e988b6173a9e8c6af317b091cf5cf72c27e28a1eac", + "Sources/UtterContracts/ModelArtifact.swift": "9732b188cbcea6ea4018989fe44afbde41253b8e2b134df612c72ade4b7b376b", + "Sources/UtterContracts/ModelArtifactService.swift": "3e250b4868aafd3e6d63d782c862bf67b0f1e54cfba42cb761db52aaf571dcdc", + "Sources/UtterContracts/ModelBenchmarkResult.swift": "b5f59ff919aa78d89daba48226cb0faaf3e2841b312e04b411e66581edc005c7", + "Sources/UtterContracts/ModelBenchmarkSuite.swift": "689dbf13af5a8815fe22cc814ba1d477c1a1ab4d4a7e9a44e3d381fd3ee2c2f5", + "Sources/UtterContracts/ModelCatalogService.swift": "0d9e591e0e374bf53152f9695a567a69062ef9d63daacc8943899e27fcd45f3e", + "Sources/UtterContracts/ModelCatalogValues.swift": "4e8b7376111f2ae49fa85c44f6b5838965a21546f6aa4d236d03acb702603aa0", + "Sources/UtterContracts/ModelCompatibility.swift": "f66e412cec333834d2857dd495342e3de30e30115cb58e11a3ac37975fef8497", + "Sources/UtterContracts/ModelDownloadKey.swift": "500965b7669db10ef1096c10bc5fdc44eb8bca6ff4f75ad74d2be6a67efd9a45", + "Sources/UtterContracts/ModelLocationLease.swift": "afe26c59f14b9507d99fbeb0b77923417bcd994487a3c2ed61cba09989816ee2", + "Sources/UtterContracts/ModelServices.swift": "4b9be876142271b2fb64a85b083f6677ada36f0d22d13fe7bc8b55f4dce8d7e1", + "Sources/UtterContracts/ModelStorageService.swift": "2e68e349e966e5037c82030881309c1605c4f495a495d3085fad0eb1f4950bc8", + "Sources/UtterContracts/NoSpaceScript.swift": "cb52e31b245497c926a08c46716866ca5e450f6873b3ae7881fdaacec225771f", + "Sources/UtterContracts/OperationDeadline.swift": "77aee07b6b4a4af84f88baf3dc051031966d3b9898aa8466e8b0fb1d0bb3c40f", + "Sources/UtterContracts/PermissionRequest.swift": "38a0dd995a2be00270005743a9b0d4678d23aea902f58ddba64b54b66b1ee105", + "Sources/UtterContracts/PersonalDictionarySnapshot.swift": "71a3d6faf08480ff0b9b5148eae2992a92dab4c7eb618e7ce43440b2e7abbe08", + "Sources/UtterContracts/PlatformServices.swift": "595965e3263643053c990fc2157bb3f11ea0fee91d1b3f56151b61dd188f9dfa", + "Sources/UtterContracts/ProcessingDecision.swift": "1e2bfb5300407f9da42806eb770513bffe81ff5d5e9b48b1eb493ba6fa1309b9", + "Sources/UtterContracts/ProductBrand.swift": "c1d3ddd35dde4f46eceb89c6864ad399561214d82b820640a5df02cdf645596a", + "Sources/UtterContracts/ProviderCapabilities.swift": "928cf9a896b91cfba96d34708675579b3cba350c99bf3e0692c70c074e2b9c08", + "Sources/UtterContracts/ProviderCatalog.swift": "4c5f0c57050cea8585a2c28cd4c5b58dce4b625bc464b049a4b508db610ac22b", + "Sources/UtterContracts/ProviderRegistry.swift": "bfdaa9743a38d25d88c47c40f0f47f2b8592dce3a9eba8123f66e0de3840ae2f", + "Sources/UtterContracts/QwenASRModel.swift": "b4a4567a50e705b792c1421d35d25877d5a559074640bf84af1c0470f68db1ca", + "Sources/UtterContracts/QwenAudioPreprocessorError.swift": "761a7b247d6194299ffee1f41b7c29e45b738e9cd1bbd7c8e66ecc140cb37c0b", + "Sources/UtterContracts/QwenNativeASRError.swift": "0fa19ffc773d5738a7fb5cd30383f8a1567d6ae62a71a13a0b3982b9203a3600", + "Sources/UtterContracts/RemoteConnectionService.swift": "38c7bcc999465468aa7e56be859cdd03f8682bb8bf9c71f3d4cc0c2f7cc36141", + "Sources/UtterContracts/RemoteLLMError.swift": "9a01f5ba7ce4df6d936c09f0fded0a12fb5ee8f2b3451e41a236e0fb3c06b0c3", + "Sources/UtterContracts/RemoteMicBridgeState.swift": "f97baca2699778b63b6d18cf1861b9e2b5d00b22e64968d6c1320bb0016f1f43", + "Sources/UtterContracts/RemoteMicDiagnostics.swift": "e93aaea2bd9d53a866acdc19533a374949e335db69578fc6211bfb4e079b1818", + "Sources/UtterContracts/RemoteModelConfig.swift": "82a7032fd93bc1ed40a8b0329cf69a502daa7cf4266a34eda392283ededdb558", + "Sources/UtterContracts/ResourceBundle.swift": "8086fdcd86bcfb4479e313a4b33a8aed0b67aa182a5e8da2da8f3cd0bdc1cda2", + "Sources/UtterContracts/Resources/en.lproj/Localizable.strings": "8faba55eb6df33cd1e6b4f163bbf2c3f1108d290d7810a53c18af2ce2ff76963", + "Sources/UtterContracts/Resources/zh-Hans.lproj/Localizable.strings": "0774d72c352f4b5ba27da9432939f303e2e45627543a8c491413e8f3ca830944", + "Sources/UtterContracts/ScreenContextMode.swift": "4db650508d76ee3b519e0a68d9894ce93eb98567735c794b70b365e076c132c9", + "Sources/UtterContracts/SessionExecutionService.swift": "f4dfe4a4f993a6884b0be62b9da38c77378ec51c486803992a0dfc99a8f533d3", + "Sources/UtterContracts/SessionFailurePresentation.swift": "33093995c87d4f02f1d2fa8d233db32f201dadece922164a6fb50787a9af27e0", + "Sources/UtterContracts/SessionOutputStateService.swift": "053bd3105cd5f42f073950bc2cd907dfe7de175194fa5245cf0f182936fead4c", + "Sources/UtterContracts/SessionPerformance.swift": "75083fc5ace2ce03cfc49c5af4881cb87d1f73d8ba582fab95275078bc8146de", + "Sources/UtterContracts/SessionPresentation.swift": "210dcd028672ce0a8bc0350aa43ef1e29588ed9adc71d327ef70cd316b690eb9", + "Sources/UtterContracts/SettingsService.swift": "c587d2e5061f6d097f21c4de7e4821460f019950ec04967ee331fb3651dd32a9", + "Sources/UtterContracts/SettingsValues.swift": "1ef52c3e7bfb1217667d9b24c3c6ba0899c41482263f38917e2ef278726517e2", + "Sources/UtterContracts/SpeechArtifactPolicy.swift": "246b45c0f558d05c9596773223a0d47d6441e35016fadeeed8aaed13503cca92", + "Sources/UtterContracts/SpeechModelProgress.swift": "b2f0ba8118fe96534c4e3f24d2c44293b9ee02c8fd43037a8e43387f22ada467", + "Sources/UtterContracts/SpeechRecognitionContext.swift": "33ea8acb9b26f21cb570baa9dd6700f2ee05080eb3bc353370b68144ce5e229f", + "Sources/UtterContracts/SpeechSelection.swift": "5f1ebf93e8cb15e3f010f1e8ac44d3f03d7ba2a55d8c47915305a1c4c6b2c243", + "Sources/UtterContracts/SpokenEditCommand.swift": "ced59b1749354b8af870442349ab824390047d214849cf5254d0f5fdc432cd9c", + "Sources/UtterContracts/SpokenEditCommandLLMResolver+ActionTarget.swift": "1c318a455f0b301034a6a9621cda2d079b78b87afcbed6b476c3247fb7e94539", + "Sources/UtterContracts/SpokenEditCommandLLMResolver.swift": "208537e0904ce4d01c09c5d4241aff9d38109bd33587b7d2087f1f7d2a2be344", + "Sources/UtterContracts/SpokenEditEvidence.swift": "711d39d308514c7821dccd1c7d834e2e24150dfa10a4fe9694b330e4117a1c58", + "Sources/UtterContracts/StateNotifications.swift": "03bd2c2917c222cc6d8e8d9694e27241a08a2c7bd1673596cf9c2e90b49e65f3", + "Sources/UtterContracts/StreamingPreviewAccumulator.swift": "6177c5fc31e3fb1f82f15b16897d3bba302d355755e4348c8123d5893a24f835", + "Sources/UtterContracts/StreamingSpeechSupport.swift": "46c8cb5dc8c239fed06b1101f7deefc27d8d6d5587eff9b1d323d3373f4060d7", + "Sources/UtterContracts/TextFormatKind.swift": "1df431369c76917e83d01edb53367fe8f70a2add3d22ecebb7de91f78b7bc335", + "Sources/UtterContracts/TextPreparationService.swift": "5e3699ea0e02e93e6f6d45d7e462aa49759e5b94376a3a950004b0c94eef5bd1", + "Sources/UtterContracts/TextProcessingMode.swift": "fb3a06580063244c7e6b54bf3b5ec4f486942d8b1103ab0b5520969a2977611c", + "Sources/UtterContracts/TextProcessingOptions.swift": "3952788e6bf59b2f2fcedad205fa7a16dccf205599599475be958424689772b6", + "Sources/UtterContracts/TranscriptSegmentJoiner.swift": "058edb95f0309df4a7645d0a0f1df0ed2b3be0d8e27bcefae3de00bdee78b1b6", + "Sources/UtterContracts/TranslationAssessment.swift": "c6aa7114cac74262fcf77ca20817450c360dff184b1b21e97715f24e9033e25e", + "Sources/UtterContracts/TranslationLanguage.swift": "3d09159a3ef6713e52757bb362e21c9bf7ba88462f9258462c39d12b18e857f8", + "Sources/UtterContracts/VocabularyReplacementEngine.swift": "80da12a564e670196d8931cbfce341070b3d975aad2874e39600fc40ac4f24e2", + "Sources/UtterContracts/VoiceInputSettings.swift": "e9940ee174aa6084254aa0cd95d408618e83b5f8b25a2b7162eed2c6b3fc8934", + "Sources/UtterContracts/VolcASRError.swift": "9cffa04b53338c36755cb7ad472df5e13712180cd161ed3bbfb52e469dc078b0", + "Sources/UtterContracts/VolcASRModel.swift": "4a6a316c35d49a8fec4e133fc8ce25220f449836ec652e63360b1bc2d5cba9bb", + "Sources/UtterContracts/WhisperError.swift": "c97030ade71e56796f00c0c77a8993ce7e90f520cba11d5c9fc670cced20345f", + "Sources/UtterContracts/WhisperModelDimensions.swift": "d2c8a6fd3c54cad4bec18fcaa13ccd4314cde8c893d00301f4045b9740f1d3fc", + "Sources/UtterContracts/WhisperModelSelection.swift": "6125cb1ec1120893ca91c75d748e157ed6bbb6954208c12d3a9db048ba2534d5", + "Sources/UtterContracts/WhisperTokenizerAssets.swift": "072ee2b171152cd633c90de80e395fd54b1b6604f28156ec3d40b9107e78d2c7", + "Sources/UtterData/BuiltinCorrectionClassification.swift": "9de7c83b9c99a4697b6c4304e73e466d6279a051aefef9bda3f3dc365427ba5c", + "Sources/UtterData/CompositionResolver.swift": "16ffb2745f17ac0bdb3bd1894a704ccb26a70eb748a3a89b1d4a189f0385f507", + "Sources/UtterData/CompositionStore.swift": "e793a7520b4947c5e89f77915283d6da60da0951491e31adbb49276b22c62b56", + "Sources/UtterData/CorrectionCandidateClassifier.swift": "11ab6489f1bbc6def66f576ce4a20062e1387d00206c23a763eb12551ae95adc", + "Sources/UtterData/DataPlugins.swift": "fbcf9736989be03a16cfbf490d6c4db285ea6fdfb505660eb532b560b3edf834", + "Sources/UtterData/DataResources.swift": "2b50ee533ea3fb3789ff8ed12349fa008fecc527c4f5945b55a417d7b0e00664", + "Sources/UtterData/DictionaryStore+Learning.swift": "22421b85b8c5fe58425f7369b5e5b3680222ff0d65a779dde94d5678fd3213f1", + "Sources/UtterData/DictionaryStore+Transfer.swift": "e0c8c01d0022a8f12c50f3bd19d2e1ebfebde049d2a08a763a6add679ab50817", + "Sources/UtterData/DictionaryStore.swift": "6ee84cb6c735d71d4fb8666ada2b28caa9b4c2cb1a56ddac9d22699be8833b54", + "Sources/UtterData/HistoryMemoryService.swift": "3578be643734e0ca6a58aa7fb52bba02085fa0a237d4b2eb3135e680a607b0fa", + "Sources/UtterData/HistoryStore.swift": "371a0e388002f90949ad37a0654e9b86c43ff81b134848312c7aed50682c74b7", + "Sources/UtterData/IndustryLexicon.swift": "ec90f94073144049ba88029940248963de1dbfee96ffda062dc234a97d83be57", + "Sources/UtterData/IntegrationClientRegistry.swift": "33a5353a8a7b56ad632d5d6203d1ef44792af4800dcecae883436de929286823", + "Sources/UtterData/MemoryStore.swift": "ca9d744c42cfbf663e16834e931865f1f7f768108e9669365851dee2da14b15e", + "Sources/UtterData/Resources/IndustryLexicons.json": "842c687b28889d037c5edd532f22732c4861ddb32ce394f4bf4f320bcd2a3106", + "Sources/UtterData/Resources/THUOCL-LICENSE.txt": "db4b8cca414db4cf487b933d07a0514f77caf44f9f3d392f2bc9d7ba0d511c58", + "Sources/UtterData/SettingsCredentialsService.swift": "81f399ababcacabb6a89f6d666e9dd601e560f78d57305bb168e6297d51a129d", + "Sources/UtterData/SettingsStore+Load.swift": "2cfa46d234b9b4ff89d26b6a0c9ac0b60bb588870b71b2f50fe3c31455c7edf5", + "Sources/UtterData/SettingsStore+Persistence.swift": "0a90cb4cc35279ec0472a6bae8bf1f3817da506a24f2f781959c2bc9587b605a", + "Sources/UtterData/SettingsStore+Token.swift": "48ebd07c7021f2b12157f2ddbb6bcfd5db0f6f4347c8bdb2c555cc4f8705593a", + "Sources/UtterData/SettingsStore.swift": "54692f233ef1671fced327afdbf72cfb51a6a6471442e389849de5a0209146b6", + "Sources/UtterData/SystemDiagnostics.swift": "6fd0cd58565e702d7307c4fdc07c788d8795e4dc4ccaf5730fc1d7eb3e6f9af5", + "Sources/UtterEvaluation/EvaluationTokenBudget.swift": "71cefd3f93ae4445d26b4e93bf2ab9f55846b900ce0b29fb93e877f89ac24036", + "Sources/UtterEvaluation/SpeechEvaluationSelection.swift": "bfc6001d88bffe9c7be4611fb53cb8b4d1d1efab50fb86486778a45995dc34f0", + "Sources/UtterEvaluation/VoiceEvaluationArguments.swift": "429cd89d88407dc4cd30f4f1fbfc39ecac4b5b91002a308efe18b43693e43120", + "Sources/UtterEvaluation/VoiceEvaluationCase.swift": "3dab6e868d934114cf0688f4db815c69cd43a907130c2295f97f414b3f201214", + "Sources/UtterIngress/HotkeySessionBinding.swift": "9d1f98038723b72102f42e79fa4a7b9bb790c48464de866d9230f0d63f156e25", + "Sources/UtterIngress/IngressPlugins.swift": "ff751d94566c6bdc20deb603d00e37996edd87e33f88eb302063a532e58089ae", + "Sources/UtterIngress/IngressTasks.swift": "66a36343a455dcfd78b7b60d6a57c82bb841b796c4fbafca2a527bec85a274eb", + "Sources/UtterIngress/IntegrationHTTPDispatcher.swift": "19d4e8b1f1ccca2f592e3c3b1e41344d36ff29433ce13dafff511b9d2ac5fa7c", + "Sources/UtterIngress/IntegrationHTTPTypes.swift": "b7d254be079cbeddb42e90c3dc8fe9b2891d9076c3f03f3e186612277bd19e17", + "Sources/UtterIngress/Native/IngressPlugins+Native.swift": "2292f48412db9ac518883a595f7551ce6a9adbd4b8f0bdd8e417353a4041b54f", + "Sources/UtterIngress/Native/IntegrationHTTPServer.swift": "37dc0b7658a28a7f91670e55e1a513d670de9982d744c530724f2e324658cb56", + "Sources/UtterIngress/Native/IntegrationXPCConnectionHandler.swift": "fa7de80bfee35b1c0662aa8aa48900932ddab6dcf8c13b880e9764e81fa62142", + "Sources/UtterIngress/Native/IntegrationXPCProtocol.swift": "cca44c4c6e1ff6f60e6a0853d012c29fc62303d5fdef3ae495fba54a47b717bd", + "Sources/UtterIngress/Native/IntegrationXPCServer.swift": "2ef0445f3328561fbb7b5257e4e0f8909355122b603eb68a56f785ef53a51471", + "Sources/UtterIngress/Native/RemoteSessionBinding.swift": "9cafac065749562c4f6f441a120f67d5f3e52d2403521c69a682dfef0c900cdd", + "Sources/UtterIngress/Native/TransportController.swift": "a284da0d4ee7bd0396dce556e16dbbe338ece13597189d3ac1aad84c4d77233d", + "Sources/UtterMLX/LLMEngine.swift": "9243764e8c3e6127bcba561cb2fb7842b4955a1975aeaaaf8870d803a4b9d204", + "Sources/UtterMLX/MLXGenerationService.swift": "71ab8fddc10d9520b2ecb09283dad774dbc2201accb61026a7b0864555f6dfac", + "Sources/UtterMLX/MLXImageGenerationService.swift": "1e47cd9e84780ee253b6cd109ec78e1232121167754b14222445f15a15342e0e", + "Sources/UtterMLX/MLXModelArtifacts.swift": "c7e7f08712a267314241ddd479bbd5a43223c342131a3d3026ceab6644b04c36", + "Sources/UtterMLX/MLXModelDownloadPlugin.swift": "89becc5333f6db3a4c2de6fdd1fa4056b747044afa4ed9146a43ef5bbed4395b", + "Sources/UtterMLX/MLXModelDownloads.swift": "fc594d1d8e226009c372193c5f8c7615099222c708cc0805b22c67f3640d3f4d", + "Sources/UtterMLX/MLXModelLoading.swift": "a4747b5feb9094ef680f1f1039ca5868057338c8336de2fe2add57b5ddfbf3dc", + "Sources/UtterMLX/MLXModelMemoryRequirements.swift": "47cd2918743098a93eb739e35b56664ef614bc0c65844ca5f3179d4a3656924d", + "Sources/UtterMLX/MLXPlugins.swift": "cbc9208fc9e16535beffd9e0fc269e07f9faadd99c1b750b924fc198bb14a7e3", + "Sources/UtterMLX/MLXSTTEngine.swift": "ec0de58608b3f6f4acf43b7c116b5dcba166d46f5eecf09ac7c945ba264f1b85", + "Sources/UtterMLX/MLXSpeechPlugins.swift": "4e9cdf769f584ed1ee526edf245f92c0b2ff6b711cfea63fe0ce9d255b5d0b3b", + "Sources/UtterMLX/QwenAudioPreprocessor.swift": "d6890feee5b9fc5826c366f5753735fcd73a8cbf6e28ee69234016c9a2754de6", + "Sources/UtterMLX/QwenNativeASREngine.swift": "4abc4b28f828facb1b3cb49383704b1328bc2257edd1bdb9d6d7a91a3cb264dc", + "Sources/UtterMLX/QwenRecognitionPrompt.swift": "0d8a985ca1e34cc3bf44707bea7c8c6f1eefd7f58fdb96501f10ba7fdd348df0", + "Sources/UtterMLX/VLMEngine.swift": "1a7ba1e94329a3092747410b82c817bd52e2dca6efd0809ba80c07d7a9e96116", + "Sources/UtterMacServices/ClipboardPasteTransaction.swift": "ef96a00d8e413def8e50adc1b746462cde62478cbe5dafdfe1d2d132a6aa8b6f", + "Sources/UtterMacServices/CorrectionCapturePrivacyPolicy.swift": "e86d567c3497c3b39ab35d15095689ec179eda94e8ccba66a1d76e7736f65eb0", + "Sources/UtterMacServices/CorrectionCaptureRegion.swift": "784f18aa83918c958319cd2ac3faed352a925dc1bf9c3bca7f37fafd09b74112", + "Sources/UtterMacServices/CorrectionCaptureService.swift": "7ecfa4fc5e934af21573fde558d73bbf45d740cfb1f5d64b41658c1680c19efc", + "Sources/UtterMacServices/DeliveryTextChange.swift": "fc78032b000aab042bc65ca25f6363ebee4195dc4474aabe1823e01c93176080", + "Sources/UtterMacServices/DeliveryTextObservation.swift": "17137339ed7bd92663dd4b2af76a4777e5371f0b1c15e97996ae28dab9ccbbb0", + "Sources/UtterMacServices/HotkeyActivationController.swift": "625a23d7faf140bd1dd21d4209b5b85fc216d2046a54bf5647aec7c11f886861", + "Sources/UtterMacServices/HotkeyGestureController.swift": "df30d79835b9aaf027c63e000e52ba068f32ce04a217cb44e750218d71aa3cd6", + "Sources/UtterMacServices/MacPlugins.swift": "fe50439214875de1af6850cfc68dc0d35aedf340214b07d04f19988b3d09c965", + "Sources/UtterMacServices/MacServiceResources.swift": "45bb57aeb3c96f6e7c319b1f38230683d9819cc8fbe4b84969d15c092a4566a9", + "Sources/UtterMacServices/Native/AXCorrectionObservation.swift": "7aeadccf4166c54fbc5946d0fdc460dabc24edb51bfc4d05240875733b03eccb", + "Sources/UtterMacServices/Native/AXTargetState.swift": "34ef0db6c36c14cc0ee1d5089ca52bdfe9445d3640f9d1dd957c7ee975c396f6", + "Sources/UtterMacServices/Native/HotkeyEventTime.swift": "81328ac4d64e8f6c70853f1dbce9e4ee3c0b27f5eaaa4cdd10314cab46a232cf", + "Sources/UtterMacServices/Native/HotkeyIngress.swift": "820ee4655b6ca4c5522d85f5850d6a96bd8178935fb02b941425590ba83410c4", + "Sources/UtterMacServices/Native/HotkeyManager+Gestures.swift": "a18c6a4a46139b147237d327ab6d916f84a2aa24ce9fe312bc8955140b7da899", + "Sources/UtterMacServices/Native/HotkeyManager+Lifetime.swift": "57c15c851ac3e532638faf5da03ed9a68e702ae3e9ed056cc890014e25611a76", + "Sources/UtterMacServices/Native/HotkeyManager.swift": "0a1b36fb51f654942abf23279b3d61838e53423cdc560805e081c94ecc5d5e46", + "Sources/UtterMacServices/Native/InputContext+Capture.swift": "847fb5901e3d8096519785d0877782bf9b51adb32e3295888263b4f358f4febf", + "Sources/UtterMacServices/Native/LaunchAtLoginService.swift": "f16ffd84c9cd351a39133d67fdcac342bf8efefb1c81e5b025c3c58ba1f5188b", + "Sources/UtterMacServices/Native/MacPlugins+Inputs.swift": "0768ad382c67bdaf69fa209425bc6fec0eabc04bbb371fad76de97eac160ba94", + "Sources/UtterMacServices/Native/NativeDeliveryKeys.swift": "4130b197dbc358379afdb2143555d05955a49c82a3c68ccbc521a0d4eca0118b", + "Sources/UtterMacServices/Native/NativeDeliveryPasteboard.swift": "1f58782d2e0c7529eb42aa64f2efd61ec8c94db4b47d862f4f04780ba9448a39", + "Sources/UtterMacServices/Native/NativeDeliveryTarget.swift": "651f9d0400865b9c2c4af424981229dd26bcc50e7b0a9239cc586a060c614723", + "Sources/UtterMacServices/Native/NativeOutputAnchor.swift": "5166107869a282ebcdc490daa5332c908cf6ca001872fef2846eff91119c9e1e", + "Sources/UtterMacServices/Native/NativeOutputBackend.swift": "6b42c05a9f0ccfa9c8e63eadb044bde64bfbc1047061635bbae73be651a819ac", + "Sources/UtterMacServices/Native/NativeTargetLease.swift": "0c700eb1811eac635e14d827233ad4d615dc14effdc391f0f8fd6b483cb6c851", + "Sources/UtterMacServices/Native/RecentInsertionAnchor.swift": "0c34c1751ce5e1662be6dddc2d9751b02c2848c937b81ab77889294930309f0a", + "Sources/UtterMacServices/Native/ScopedScreenCapture.swift": "33854677e1c50ac67d947459feeedcef3e69ecec4f3ac2130a51d80ba146385a", + "Sources/UtterMacServices/Native/ScreenOCR+Recognition.swift": "147db93fb6d6c12e17d675eb16969d26ba15bee66d37848a733e54ba251b9f16", + "Sources/UtterMacServices/Native/ScreenOCR.swift": "ee5f23049aa87cb0bc371fe5a51d4f554af3fb4822fb67884f735c81298b7a83", + "Sources/UtterMacServices/Native/SoundPlayer.swift": "b8b318555e94169851b4fa705b10b0a84fc49f891b073cbd7a99e7fc98376b05", + "Sources/UtterMacServices/RecentInsertionGuard.swift": "72061f1e22b995a1e32a98295eb599189658a6cf792fe2510b53188f1b445ba9", + "Sources/UtterMacServices/Resources/Sounds/start.caf": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "Sources/UtterMacServices/Resources/Sounds/stop.caf": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "Sources/UtterMacServices/ScopedOutputService.swift": "6ca339f51cfd0d4721e5ca4198ce7bd3e007fdb8f6b741e9cefebef9f6a789ea", + "Sources/UtterMacServices/TextDeliveryTransaction.swift": "5e955f1f8284688b3a56e62b558b2b56d9249bdfe370e001ce5f0650f5532197", + "Sources/UtterMediaContracts/AudioDeviceService.swift": "43d46b481c6676d0c4fc8473351d8f221f4c1d25333666b5627c8f2d5cdf8f0c", + "Sources/UtterMediaContracts/AudioFileService.swift": "988773629b57a08f1d8c96463a9d45b13a8493e7b8be2b5ca8231d2c00d56946", + "Sources/UtterMediaContracts/CaptureService.swift": "787ff86c9c71dcb4765de382f136888fa74afa383d00e2b365e26e4b7e13968e", + "Sources/UtterMediaContracts/ImageGenerationService.swift": "b68e694b3e12b108e0b6840a9010e69ae1f3a65fcb101b2d991ce2efd70813ca", + "Sources/UtterMediaContracts/ModeRecipeService.swift": "8168b245a3d0d8188a5f73843fbced16f958c8006f2d87badc8698fae2564209", + "Sources/UtterMediaContracts/ModelLifecycleService.swift": "f25152b0cbc66f5be1104816794229a850a2cbea4ae6e77d8097c53e95bd341f", + "Sources/UtterMediaContracts/ProcessingModelService.swift": "725f2dfec0ac60571776f32c4e078150eefc464a7d3b128198ba8d33a25ae31a", + "Sources/UtterMediaContracts/ProcessingService.swift": "a2c7dacf0a3b1f329808a4c671c4a962702a58705681c857b4cd77e6b84d8e1a", + "Sources/UtterMediaContracts/RealtimeAudioConversion.swift": "5e2dcd8cdb81511bba307e4fad4aff56561628a72b3d977a2d9c4c8c4e6da20c", + "Sources/UtterMediaContracts/RemoteCaptureSource.swift": "7cf21b0e1e6d7b7ab019cce9f5b0fc33132eb63717fc58345a4f6338587f1aff", + "Sources/UtterMediaContracts/RemoteMicControlService.swift": "1f03b79ace92f9bb795614b8b5549753183c33eacfca50a76ef918a829f13a71", + "Sources/UtterMediaContracts/ScreenCaptureService.swift": "8fde713f756931ef0d9ac4963bf4b8b42c474bb691b9a52eafcf6c5be85ca1bb", + "Sources/UtterMediaContracts/ScreenContextFailure.swift": "8ba5cbe785f6064f6f71a13c107b8c0066baa8d481e9c085f224a8cb82e770b1", + "Sources/UtterMediaContracts/ScreenContextSnapshot.swift": "915aaf0f77279af6c519f7fb8eb9abd053908b81b79fd7aeaaa22c5e6abf4fe5", + "Sources/UtterMediaContracts/SpeechEngine.swift": "c07d85ff153d501f92bc362a312119ef2e94e3a105e0f7a889b2e0e1254ceeb2", + "Sources/UtterMediaContracts/SpeechProviders.swift": "c10b8f669a64b224d3844b0c1e7cd9d35205162368daab3d905dbcfb1d1d2674", + "Sources/UtterModels/ConfiguredModelFiles.swift": "9b72c5ed34cb50763ffc0aa5d0ca6f305955f623fc623ba6b164d7e88597345c", + "Sources/UtterModels/ImageRegistry.swift": "1774928bfd96b795078fabb872a380dfa7c6eb2dabbf452fe6e7cb512b120fca", + "Sources/UtterModels/LocalModelAccessGate.swift": "38c74ff1c33c3870171f7cc15f29411ee7eb9fcbe491aef6772f11126ad5f79c", + "Sources/UtterModels/ModelArtifactRegistry.swift": "84b683121c060e1d85637f18df64758cd2f3ea08c4c3fcfd6754d6baac83eaea", + "Sources/UtterModels/ModelAssets.swift": "df46aa2f5ec4c70c93d049f26c0f32fff7c932b6ff16ef69b05e24181515b3af", + "Sources/UtterModels/ModelDownloadTasks.swift": "19b5b9e121049d27a5991a71d8c2312a5e30a434953ccf76fc2cd1b86a82d8c8", + "Sources/UtterModels/ModelFilesPlugin.swift": "f4c10d63d5f4f098c3fdcedee8dcb68bc6c8388eb06ba682e3a23d72422992a7", + "Sources/UtterModels/ModelGenerationValues.swift": "7c2dfb2f0a87d5a331d65704fbb2c0a7440bcb167de302d49cfa5ffd3e0686c8", + "Sources/UtterModels/ModelGenerations+Cleanup.swift": "d126a309901395142b0d574ae59cb0c22e220f62d5393f0ab2e087673eefb051", + "Sources/UtterModels/ModelGenerations+Materialization.swift": "a71f485003d4a99153cdb9926196751dd5d6c2b9770ca48dfe03add85c86a91f", + "Sources/UtterModels/ModelGenerations.swift": "7a97ca2f05e61f3052d7e497e797a73f88163cbd81d7b23a66f1cda1249a7002", + "Sources/UtterModels/ModelPlugins.swift": "97fbb3d40d9eb38e02c48ff3cd895482540c13594b0ae6e11e559ac2b629eb68", + "Sources/UtterModels/ModelPreloadPolicy.swift": "4aaa81aa777a9a3bec18b22e0c8aaa48860100ea07d9251673f618b428a43e47", + "Sources/UtterModels/Native/ConfiguredModelStorage.swift": "aa12c35822dfdd556b9e8ae87394c524e54db98876ac140d82992a399c8a3308", + "Sources/UtterModels/Native/ConfuciusModelDownloader.swift": "4e16675b18e9942acbbd943c24eaee14849e24866b1e3dadedb5fb6359ae2ddf", + "Sources/UtterModels/Native/DeviceCapability.swift": "d677917ce5691603b5f1ec4bbb8bf2cd0e06716dc8a22c4915cdf2f7fad208c8", + "Sources/UtterModels/Native/DownloadProgressTracker.swift": "2c0d033ce9fec13ac4a106918b8bf4d68144956d7a96fe9c5722145db47218c6", + "Sources/UtterModels/Native/DownloadStallWatchdog.swift": "59b96f1f625a6b08975d480599b5643a57110d2cfacf945acd1b0154dc01aa6c", + "Sources/UtterModels/Native/ModelCatalog.swift": "26a0683ce3bff0b3deabf724fa4bc2de5382717dc061f252fa14d672822c333a", + "Sources/UtterModels/Native/ModelCatalogASR.swift": "4d180aa224947e5e5fab9b5c48f10089f24694e1f3c8b0ff07f0c8f516152deb", + "Sources/UtterModels/Native/ModelCatalogASRFiles.swift": "2ecfc0da1180316c0f557f3c1d611e3e41737c238c5ec526b25b6d7e212d8db5", + "Sources/UtterModels/Native/ModelCatalogASRStorage.swift": "40162a3ff4de3fefe5c01e01b04717831889ad82b66c46f796e5bb87cb56923f", + "Sources/UtterModels/Native/ModelCatalogDownloadCancellation.swift": "0fa72bfdd555de1680dc61dab49b9c3128db3a9c626649af19033602095059f2", + "Sources/UtterModels/Native/ModelCatalogDownloadEstimates.swift": "c6321a992e73950399a51e4cd3ad64a4ca8e8bc0fa898e494be5e64a1b5f3ed7", + "Sources/UtterModels/Native/ModelCatalogDownloadStatus.swift": "9bc7b1099428f45a6cfd08ce0179248cab3396d73bc623bea42667870d5d6ff1", + "Sources/UtterModels/Native/ModelCatalogDownloads.swift": "3ddb45589c055ac24b56e465b24e60af66eca2e3a3793972f15585273e9a90c9", + "Sources/UtterModels/Native/ModelCatalogInventory.swift": "49cda533ec6c94589b4f7afe8a21fa7bba39ad15081624855c7936c6902f9d4c", + "Sources/UtterModels/Native/ModelCatalogMaintenance.swift": "082f9eb7ff977a3d5e7c402efb0f5eaf8a44cf0ef1fe87822f5094bc77e51805", + "Sources/UtterModels/Native/ModelCatalogObservation.swift": "aad969828fbd866b7fcf457f8b84f9ca6bcbf03914290f6dcae6df6c5e727960", + "Sources/UtterModels/Native/ModelCatalogPlugin.swift": "9d7202f8108babe6b8d3284cc96c9aad5ba88698caf6c427a4bb3253e5e764cc", + "Sources/UtterModels/Native/ModelCatalogSelection.swift": "873b21a4bd45746a14969c9da044b7473ac52c078866335a737f8daf4690bf32", + "Sources/UtterModels/Native/ModelCatalogTextDownloads.swift": "32cb3ac927c0ba51942f3042b3fea1cff141a72d7225ecd2961ff533bec40607", + "Sources/UtterModels/Native/ModelCatalogWhisperTokenizer.swift": "3f3e516716586f9c2fbe2710e67924aab334864dd91915bf9e1fe3bfa41fe6f4", + "Sources/UtterModels/Native/ModelDownloadFailureMessage.swift": "4ba3257f24f48033e7dc3c48544bcd48a4e0149ee1a460216d9b939efcec70c6", + "Sources/UtterModels/Native/ModelDownloadRecovery.swift": "43741f27e9752efe3c3f4fba5f1e9543457cebe96ee206432f7a306c4135aef1", + "Sources/UtterModels/Native/ModelDownloadRecoveryFiles.swift": "33f905c9046e821ae334bb0276f81f5ec2e833c160a4ffc3780f0648b7823467", + "Sources/UtterModels/Native/ModelLifecycle.swift": "980b4d8902a3283cb3166492fa69f0e23b84b30f968852493dc2ff4c81afa1ed", + "Sources/UtterModels/Native/ModelLifecyclePlugin.swift": "eb124c94eecc2d762f548402e8e4c1088be27f187e2c846df4d25483a41ca52d", + "Sources/UtterModels/Native/ModelStorage.swift": "4abcb722abd9582a88a80f0df55c8af11e153df46a3ba75f78233a3a4126cc1f", + "Sources/UtterModels/Native/ModelStoragePlugin.swift": "d550891c150ff7be5f150c6bc4adf070b9728272c168f73f47abedb059b63f04", + "Sources/UtterModels/Native/TextModelDownloadOperations.swift": "503f4113c0bd6e2f8d6b726584d84b8d3a45f0390b6b1d3ad8a979d4a93a1dd8", + "Sources/UtterModels/SpeechRegistry.swift": "98d089d5a8e7ce7a982a0befa4efc2b8ac6974a09af33139a80e0f24fbc2522f", + "Sources/UtterModels/TextRegistry.swift": "d362b333723e3429eed9bbc420e6a9e090ad5093868f739577d5f8b307a7eec7", + "Sources/UtterPresentation/App/AppIcon.swift": "b82c40f76dce3f652b3a7ae381d371cbcb94fc1fbebac3826c4faabc5899a878", + "Sources/UtterPresentation/App/PopoverOutsideClickMonitor.swift": "d62f639ef29b92bbe3711edeea0dfc37915d305e28f9c9c438ead81d0d86b0ba", + "Sources/UtterPresentation/AppResources.swift": "de3a51f43a0f7df90cb3235527b1200e45615c96a3d4f4aad5d84fd88683f32c", + "Sources/UtterPresentation/InputHistoryAnalytics.swift": "472001584fcd526b17d269ee906832a325adf7b836361b50d7548ce696a44f8b", + "Sources/UtterPresentation/NativeDesktopHost+Actions.swift": "ed35412f0ed2511316e0f4b2f3145b83b81627383b0ddaa89ff323317f041dfa", + "Sources/UtterPresentation/NativeDesktopHost+Windows.swift": "d418a1661d7e5a802b0ce4262e9c779994e284c48c29dbf7392c9521045829d6", + "Sources/UtterPresentation/NativeDesktopHost.swift": "8952e865d1b28042532ccd0b1875f8d32e5b55d34a046280d06ad23c01051fdb", + "Sources/UtterPresentation/PresentationPlugins+Configuration.swift": "1f74dc17be3c98157f233654b3494ba1db01dc38a9a56311e2f2f74df73e6ff7", + "Sources/UtterPresentation/PresentationPlugins+Settings.swift": "b550a1f6015c53c3ed8d781818fb3f0aa99cdf4962419b20e745c73a1afe1c91", + "Sources/UtterPresentation/PresentationPlugins.swift": "6875f671548856ccc3d6cb535b13202c9dba326e66d6947a316452e18fdba6a3", + "Sources/UtterPresentation/PresentationRegistry.swift": "40ea653ac4be299aa3f225a50275d28dacacdbbbf1c6678ad95f11a17e8ada71", + "Sources/UtterPresentation/Resources/AppIcon.icns": "ecb90dc46a59f11944074e8b6bd22dd52a261bf8f0264e4c6bd00876b6b6a70f", + "Sources/UtterPresentation/Resources/AppIcon.icon/Assets/AppIconDarkForeground.png": "6db03e42e2f4c735138d938bca5fded73688953fe642e134ec188d24e7b2c1fd", + "Sources/UtterPresentation/Resources/AppIcon.icon/Assets/AppIconLightForeground.png": "1d70bd7c135d0ba2a679b82a40fc3c293ded9bdf6c057f5d7e10a479d68ffd7b", + "Sources/UtterPresentation/Resources/AppIcon.icon/icon.json": "bc70ac59d63cfd768c524dc5cc7b42b381d572cc44632f03e1ac2fa5578c3bf2", + "Sources/UtterPresentation/Resources/AppIcon.png": "0df06c83a96064cea37e8776bf12229fd0a7c4c13e2b9800078ea29767b89b49", + "Sources/UtterPresentation/Resources/AppIconDark.icns": "5a8f442e6b0f1dc224dd36991a42898d2977e16a5fdd884dd7bbf5eb6791a20a", + "Sources/UtterPresentation/Resources/AppIconDark.png": "448f8fe0fd8477f38253d14b2ce79525f73f49abe2935157391829a5d3074208", + "Sources/UtterPresentation/Resources/AppIconLight.icns": "ecb90dc46a59f11944074e8b6bd22dd52a261bf8f0264e4c6bd00876b6b6a70f", + "Sources/UtterPresentation/Resources/AppIconLight.png": "0df06c83a96064cea37e8776bf12229fd0a7c4c13e2b9800078ea29767b89b49", + "Sources/UtterPresentation/Resources/SettingsAboutIllustration.png": "91dd6f03d7720e8b75dde6cf2df9c56fb9e7281bab4422334f50b758d0169f82", + "Sources/UtterPresentation/Resources/SettingsActivityIllustration.png": "565061299ccb53f73bb2a1bd1c33ea391babb0a2f89e8695658586dd290a8818", + "Sources/UtterPresentation/Resources/SettingsIntegrationsIllustration.png": "1daa0fa1590c8a4358d8e2c49856eea85ecb13889f00170361faf13b44432c38", + "Sources/UtterPresentation/Resources/SettingsModelsIllustration.png": "0666cd4cadf72e9b8afe2507f0b965a392231295ea26be567f14646fd7383329", + "Sources/UtterPresentation/Resources/SettingsStyleIllustration.png": "d1a2deaf6a4efccdabf4dc64a1d4033b2f36f1fb829cbbf3a118c488f247baa5", + "Sources/UtterPresentation/Resources/SettingsVoiceIllustration.png": "5440069ed132314e3f809bcb76f2fec078ba5db9c2eb1c189e695d4f9e199f23", + "Sources/UtterPresentation/UI/AboutView.swift": "9c6b3fd51287a05126ca597bfe0dbcb0340ee700920cf6cd1988fbe7ab10cc09", + "Sources/UtterPresentation/UI/AppIconView.swift": "6df0afde3de78c8020adae31f6dbc27821cb117b4db15acfc6796ec47e663585", + "Sources/UtterPresentation/UI/BenchmarkDetailsView.swift": "109ca48877922ce750d31866cceaccd44ca1e9e11455e6d19d61d69fe0d16797", + "Sources/UtterPresentation/UI/DictionaryFilePanel.swift": "bd755262e469f23542de535183ef5378d504d561297f3e86419218b18e377666", + "Sources/UtterPresentation/UI/DictionaryManagementView.swift": "abbc15657be9506ebf208fbb30f75fb3a5064fa4cecc246f4446e5c9cb06af15", + "Sources/UtterPresentation/UI/DictionaryStyleView.swift": "8061c20415ba2906089082b5f7acbbf05706def2e33c3cd5ac25f8e2566f0eea", + "Sources/UtterPresentation/UI/GeneralSettingsOutputSection.swift": "00b459116120ed11171b84f6bf1f68d6f9e0681dbb61cb0abaab23a6808a2b78", + "Sources/UtterPresentation/UI/GeneralSettingsView.swift": "918eb45b3ecc845ae0f755c2acca1ff4367135de9928b2d252b12a469340a7b2", + "Sources/UtterPresentation/UI/HistoryInsightCards.swift": "4abe009b86690993977040d32764c1529c92ab864a516ac5a57aa35c8ba63afb", + "Sources/UtterPresentation/UI/HistoryInsightsOverview.swift": "68eed026e912150f80842206c01e170e02330577725779dfeee3d2939072084a", + "Sources/UtterPresentation/UI/HistoryRecordsView.swift": "c3dff31045e1f361c0b9f185aa53eb4330dd0770f52c5c0bddad1e417bca339c", + "Sources/UtterPresentation/UI/HistoryStatsView.swift": "e19bbf7172e49f09fa2f00e4fce736f3bd9df602387d3576355e808c471735c1", + "Sources/UtterPresentation/UI/IndustryLexiconView.swift": "84e3435b40e9229516a999fbcf081575eeb7eba0d635e09225e522a88df895b4", + "Sources/UtterPresentation/UI/IntegrationsSettingsView.swift": "9b26511148806a85f5767abeb5dc374e99f725e44b1fa20027a96a57a31ac6b1", + "Sources/UtterPresentation/UI/MenuBarView.swift": "eafff6ea76db9a7bbb1a5b5c3cc5a8456bc30a06ff427e39d03a3601b1a5cd33", + "Sources/UtterPresentation/UI/ModelManagementASRSection.swift": "2851aad7d6d7d0cbfca086d02f753c1080f7a7eab7f19f60195a66c521624163", + "Sources/UtterPresentation/UI/ModelManagementActions.swift": "92d93dffc68c8fb5f2f3223c1d984a13e1d8976b755824b56d45beb7a9f536dd", + "Sources/UtterPresentation/UI/ModelManagementEnginePicker.swift": "09546149910082b5d69e7129fd5395df59c5240cfc04d25aae4e1569956e8f19", + "Sources/UtterPresentation/UI/ModelManagementFamilies.swift": "635a1fde75b33b7e4412b0d6381bca044a49c805c276dbc8225abc39cdeee12c", + "Sources/UtterPresentation/UI/ModelManagementRows.swift": "0297a52e7cfd7141e7a6f493a15c130e53abbcb803f313af7131a667f2da8a56", + "Sources/UtterPresentation/UI/ModelManagementSections.swift": "04655695bd46b8941bed52f6c5c80a42c13970080479e1d375ef2c227c4c48e1", + "Sources/UtterPresentation/UI/ModelManagementStatus.swift": "3fb99f3d5a338454df5194921e77d48c8a33f110295261aca43bc40d100e1157", + "Sources/UtterPresentation/UI/ModelManagementView.swift": "dd1580ba51b7f852541f5a53b038c25c2aee5007b30c790a6b3ef6dbbb8e9e78", + "Sources/UtterPresentation/UI/OnboardingModels.swift": "9d698c198112c33a1976abf217da954da438cc6b16c74c0a17719347105e3555", + "Sources/UtterPresentation/UI/OnboardingPermissions.swift": "0f5c6121f84ef36db5782130e45e710bc58a3285b321bff8b60c1afed454e3e3", + "Sources/UtterPresentation/UI/OnboardingView.swift": "f8257cbfd749421ed00ad9094354706dad8b3e9bdc13d87a957c0677c8137b16", + "Sources/UtterPresentation/UI/OverlayActionButton.swift": "d6013fbbe85ca9802ef5035f3110fb59340093f7e86f7ad2982096048b8b15ac", + "Sources/UtterPresentation/UI/OverlayPanel.swift": "d5eecd0097e0d5876b23b686f693525e01383f795a13594bba822b2200f590de", + "Sources/UtterPresentation/UI/OverlayPanelContent.swift": "4044a4cea0b69365e0823d245519d6429f11003588f931ad8a47cdc1e0e23bac", + "Sources/UtterPresentation/UI/PermissionsView.swift": "5ab9dc91a3a72995983b7572f2a3b5a2b3aaaec7c1e41f2f16f0312da09ff1b2", + "Sources/UtterPresentation/UI/RemoteLLMConfigView.swift": "bc4f27221d08a2f222565fb50ca8beae2e4e8cb049b6346ddfab655fe15fa3ab", + "Sources/UtterPresentation/UI/RemoteMicSettingsView.swift": "4637685f62e2d79f9eb245c242aeb13ee1e1245cec0f8611b00b9af6c41c8016", + "Sources/UtterPresentation/UI/SettingsSectionHeader.swift": "8c4e53af7dc415802d83850a56f89462d3765b285550c78f8d2271427542e41d", + "Sources/UtterPresentation/UI/SettingsSurface.swift": "c493b51492e7fb588eed02cff3f0ff41cb5fd5218d16b7d7cc045226a888e3cc", + "Sources/UtterPresentation/UI/SettingsView.swift": "535c63377ac766e44e21663f5b8a698f2175d6e4b1d0e01e17ec3895022810a3", + "Sources/UtterPresentation/UI/SettingsVoiceIllustration.swift": "373776f5248638dbfd746486ab99e6cc16ec607b2a4889070fef5c38ed6f877c", + "Sources/UtterPresentation/UI/WaveformView.swift": "6773e7c9e3c60b1b852b04bb414754bb0bd506961896931c808ce51d65e21744", + "Sources/UtterPresentationContracts/AppSettings.swift": "dd61716748c1f15e86807d45b340efdafa6dc7fed3e5d6391e15a6ce412eef99", + "Sources/UtterPresentationContracts/AppState.swift": "0073d1e2fe4f6e8e975aa7e967acdaf14cd8ee7361e94800af8ce36298bf466b", + "Sources/UtterPresentationContracts/InputHistory.swift": "a34946353f6ef3a18339fce9c2c32dc73007fa9c3b99021390e3dc052018cc38", + "Sources/UtterPresentationContracts/IntegrationClientAppIdentity.swift": "a3eb10d3662d74812ab8bb1625645b68e53c5145447547f1626fd34f381f26bb", + "Sources/UtterPresentationContracts/ModelCatalogProjection.swift": "bf5a61e9501ae08411b851b7b093b4fed5b5ca03bdf00bdc111c60fbcd2a68be", + "Sources/UtterPresentationContracts/ModelLifecycleProjection.swift": "59bf7cedd57ac74c789ed2bbb8543f1944144d482c6c2a22fec8161dba60d4e3", + "Sources/UtterPresentationContracts/PersonalDictionary.swift": "ecb26897fd7024863742b990e7abf05352493b8147e91e3c997fe1608008a385", + "Sources/UtterPresentationContracts/PlatformProjection.swift": "918e191188994a221deae16631ecfc5e16044e469ef51efe39908c3b0af19ba9", + "Sources/UtterPresentationContracts/PresentationServices.swift": "10db18005eb48d73a675e09dad6433fd5cb5526a3f343bb3b80fca7fc388c874", + "Sources/UtterProcessing/CommandOutputCleaner.swift": "e95c98871fdeb502ab071f80e8ac14822a361f71f992866e49b0d331663fff1c", + "Sources/UtterProcessing/EspressoGenerationTracker.swift": "3925bef307e2ba9ae896dff0fef32c2b5f3dd5ea0936ce433099bd9bc0cd587b", + "Sources/UtterProcessing/FactSupportVerdict.swift": "5110024886c24422b662648c3bf24e8b0dd66be3bace49e683feb53ad42cd3b8", + "Sources/UtterProcessing/FormattedOutputCleaner+Sections.swift": "5a5e786909e6a6f6c62d5b7495ce6a3153a3033e2259447c053d7cf8be9efcb3", + "Sources/UtterProcessing/FormattedOutputCleaner.swift": "8084ba80fee6158c0a24a5b965641526742852d5aed00f3affb0ec2fcd9268ed", + "Sources/UtterProcessing/GenerationFallback.swift": "96453dc6e9cd9c050ec44e02c69a6a55e8417c1263b2ad6688c05aaac1dd85bc", + "Sources/UtterProcessing/Native/ModePlugins.swift": "e5dfaf55c464f54eb5dad2ba9a761fc427799056bba7d7f6f7dc71c42fddc8e7", + "Sources/UtterProcessing/Native/ProcessingPlugins+Text.swift": "95668821c12b03928bdb0b8ccdd7c576c668265dc3fe75984f633ded9532009f", + "Sources/UtterProcessing/Native/ScopedProcessingModels.swift": "f045cb22ce2e408e85f25a3ff80b991399942fae17f9f6538d2834b7f66edc77", + "Sources/UtterProcessing/Native/ScopedProcessingService.swift": "55f4998a182fbee7f4b39ab2f5cb4ae4b34d43c2d6d159158ac473be70eaeb02", + "Sources/UtterProcessing/Native/TextProcessor+Benchmark.swift": "6356179db045ed5ce985a674ba901126747ab6e262059ba900deff815f2d1c00", + "Sources/UtterProcessing/Native/TextProcessor+Command.swift": "ff8d64fb3ff65f7d27d693e36605611af02ad38e506af68a987eba1ecb21a6f5", + "Sources/UtterProcessing/Native/TextProcessor+EditCommandResolution.swift": "48cd915ef1bb991a6e75f3bccaa76e077aef2e5011312ea10648479c4e981b30", + "Sources/UtterProcessing/Native/TextProcessor+FactSupport.swift": "19cfd00ac93a609ef17357afabcb2bdc1af3befe4ccb4da6cc068b97e57d20aa", + "Sources/UtterProcessing/Native/TextProcessor+Generation.swift": "af81dc5ec5075d7aa76cfb4758e5a851f17a6376e31eb0e56a68ac126a84ea3f", + "Sources/UtterProcessing/Native/TextProcessor+ModelPreparation.swift": "1f89dd1b0ffee3a6b3ab712add5bf34e62b3a57b77a54fb5ebc7f6abcbcc703d", + "Sources/UtterProcessing/Native/TextProcessor+Models.swift": "8b76437cd2bad08001828ea30d0a3f18613b80b603b57fc52740ec1e8db44d11", + "Sources/UtterProcessing/Native/TextProcessor+Observation.swift": "3fe4ec5662062ea5a660172891f675e9a1852bcacc1e33aab28ab1317707c211", + "Sources/UtterProcessing/Native/TextProcessor+Output.swift": "941c877c9e23e66c583241b962e73e6360dbcafeccf6674e6233f31e858bfcea", + "Sources/UtterProcessing/Native/TextProcessor+PromptConstruction.swift": "ecb30304fff404e55a417ad522c145a95f180e0d9cbea9477a02921632f9573a", + "Sources/UtterProcessing/Native/TextProcessor+SelectionEdit.swift": "c8de079fd3d782282084595f1871c77c1dd991374899a48427107ab3946e1cd8", + "Sources/UtterProcessing/Native/TextProcessor+SelectionEditInstructions+Asian.swift": "8f9687ada292c61dcb3360365b98b5be5f37fb9c85e6d321656685096de867fb", + "Sources/UtterProcessing/Native/TextProcessor+SelectionEditInstructions.swift": "9574f5e74b6d2ca78847ed800329f252f3b4b9a1a6bb32535297495706448f49", + "Sources/UtterProcessing/Native/TextProcessor+SelectionEditPrompting.swift": "8d4d852dd172afc9469f38a54bddbd7ed73e79ea0ddc720e2c93fd0a9683246a", + "Sources/UtterProcessing/Native/TextProcessor+Translation.swift": "5f48b5017a3b6a48cc346735595d8c182717ce98c16a28b585293d897a55a177", + "Sources/UtterProcessing/Native/TextProcessor.swift": "de598b8c8455a630ad07743c947993bad47c2acc1eba09e28b28d465c8b6b620", + "Sources/UtterProcessing/Native/TranslationLanguageRecognition.swift": "44028cfb0a5421c78bfbe9c9075610e26a281ff388fe4c029be1443b16218329", + "Sources/UtterProcessing/ProcessingObservation.swift": "2ba29e1a33ea381e7b74b105554f540f9d80c644251b5a088b33e837aaeb7748", + "Sources/UtterProcessing/ProcessingPlugins.swift": "e2a63f78480b8c9fd4d32f60afe7d210567aa54c394a8d5b32bf087adf46c679", + "Sources/UtterProcessing/PromptAssembly.swift": "02c50a550bdde01cdc6cacdc80ab775a1d1a7269d0407b4d746bd3632ffa72a0", + "Sources/UtterProcessing/PromptBuilder.swift": "d310123940d5fbf85d7de92a2d084ee7e9d9880e7db3d0989a5547eaac74f1c2", + "Sources/UtterProcessing/PromptCatalog+ASRQuality.swift": "0668235cf69f582a17a9ce1915afceaaa4c85dbb2c7042708feaa4ce07bebc72", + "Sources/UtterProcessing/PromptCatalog+AsianSystem.swift": "838d0c56c50d92bdaed6ba751aa5e6f586b898de337fb107e91a5850ee3ec4b0", + "Sources/UtterProcessing/PromptCatalog+AutoCantonese.swift": "98cd0e64382cc03d15214793cec62e89a77f2e1a3225ac01708419cb5f8e3ca9", + "Sources/UtterProcessing/PromptCatalog+Command.swift": "dfeb25adc328045a3e6e6ffbe96d9c9683c1ad3f29733bf9876e46bacd3c8a5c", + "Sources/UtterProcessing/PromptCatalog+EditCommandContextPreview.swift": "1b20ead97a054b50ee9e49d10a9866206d21e96d5a95b21e98850a644bc91a23", + "Sources/UtterProcessing/PromptCatalog+EditCommandResolution.swift": "b87db585ac25aff8eb5186bce74bd14239d2904a1af5d399bbeed44ca632b86b", + "Sources/UtterProcessing/PromptCatalog+EditRules.swift": "74a03d3a1e46bfc894c4670672b42a548fbeccc3a78ee4bda4b81786bb3d33d6", + "Sources/UtterProcessing/PromptCatalog+FactSupport.swift": "e16186662abf39962cdd963e5b850827178af8fd5ecf4806cb35f163ec82b9c1", + "Sources/UtterProcessing/PromptCatalog+FormatKind.swift": "708820a8498d432b57e5d95b0ecef0e7c26d9fc813e10edd62069163a0033abd", + "Sources/UtterProcessing/PromptCatalog+IndustryLexicon.swift": "9270981725da53a70a690c766312e5a880e2074e6ac0b11c0910a5cb37369a80", + "Sources/UtterProcessing/PromptCatalog+InputContext.swift": "b389174ffbd0d349313ca9e3f74e549a37c5bf886f62e3cc2007cc728d320cb2", + "Sources/UtterProcessing/PromptCatalog+ProcessingContext.swift": "7b8de43f7a9d339027a71112a56301f8ab53e67d1b35ea7e33e036461500ab45", + "Sources/UtterProcessing/PromptCatalog+RuntimeContext.swift": "91bee3858541cfe36fcd01c45603b483d5b688c05db62c15e5e74fcf855ec4fc", + "Sources/UtterProcessing/PromptCatalog+Translation.swift": "95437542056c49f724c124ee667fa5e14139f3be4ff1a069ab320ed872af3310", + "Sources/UtterProcessing/PromptCatalog.swift": "4305cfa41e3d4318b97a242c54a17322ca68a28208a227fce23cdc74c5a1512a", + "Sources/UtterProcessing/PromptStylePrompts.swift": "adb44fbb3ecb9b060fc5cfe1e28564f1eba2b85fcb59ec9ca6b12f9e4931053b", + "Sources/UtterProcessing/PromptTextBlock.swift": "5ac34425d956f3139b3cf46efe968b6860161284e493c0e51b82feaf59b4407a", + "Sources/UtterProcessing/TextFormatClassifier.swift": "cbef702a0da51d2daad22c84be157ebf56e57ef19c87de9fb69cae21f32022dd", + "Sources/UtterProcessing/TranscriptClockEvidence.swift": "196a93509e944953fe7244111f5e8d1d098825c7c332a48fd7f71a66a9001534", + "Sources/UtterProcessing/TranscriptContentFidelity.swift": "a9a9b485dbdf836b4bc61eff0bc946c770eb1f199f1b88c24dbb2ea4f655286e", + "Sources/UtterProcessing/TranscriptFactEvidence.swift": "15872d2b5e719e175dd905f291284d699089ad9c39cdfb1f1acfa85ecc114c98", + "Sources/UtterProcessing/TranscriptFidelityGuard.swift": "1acd12b8edccad6af13ef1046b697b4f2f3030b9a3d02f6d456816a49550c9f5", + "Sources/UtterProcessing/TranscriptListMarkers.swift": "b6b5d1d8646624259046d016532ff6c4747d386db659e1e038e7a2d934ca58b0", + "Sources/UtterProcessing/TranscriptMeasurementEvidence.swift": "5de99dc3f960902139537f27e2dbee4f765bef1a5fb5211d06679e1a9a84c600", + "Sources/UtterProcessing/TranscriptNumberBindings.swift": "09fe6333262ff6fefa589718d6ccab5ddab64dcbcd84cbbc6fa6f41150f6f737", + "Sources/UtterProcessing/TranscriptNumberEvidence.swift": "ed0f7e693dec5b75a5a071ebfc7fd926622b07bd0082afe9a25da4a3ee7d2eca", + "Sources/UtterProcessing/TranscriptProtectedTokens.swift": "9bdcc1689d03de4f121102e640eadd4f97c3945a3d6f449656a8fa824be4be91", + "Sources/UtterProcessing/TranscriptSpokenNumberParsing.swift": "9939a269640f655236e5125b5925bc897625c7391c263518d369833e98668c2e", + "Sources/UtterProcessing/TranscriptionSanitizer.swift": "f82f774d9953e5225ca67bea93103e3312e6366ba3e6da3d01ac17ae9eee3062", + "Sources/UtterProcessing/TranslationLanguageSample.swift": "3e17cc512439aac1a2da819ccde9e3da61a0202ec1c19d2c4a03b1d0e1307a7c", + "Sources/UtterRemoteInference/GzipCompression.swift": "00c653aaf7fbd6393ab772ae134ed0a588a0da58b10b03a93edae6fc80dcecfa", + "Sources/UtterRemoteInference/RemoteConnectionPlugin.swift": "cb0663b1a70825dabc7e2e7c6b631425f9cbe10aeed680ff56439abb8efd5cfa", + "Sources/UtterRemoteInference/RemoteInferencePlugins.swift": "f5e36b82b715d8480d4c2f220f176f8986997fdf3ca05c93cc152c197476496b", + "Sources/UtterRemoteInference/RemoteLLMClient+HTTP.swift": "a61c619e521ff13c7a4fbe9969bc791bbc706f50cb67b2a1f69f14d2a751cf75", + "Sources/UtterRemoteInference/RemoteLLMClient.swift": "7732bcd7671171aea13a6f62725cc4625402bf9a091d7ee52e6cd03361e37149", + "Sources/UtterRemoteInference/RemoteLLMEventPayloads.swift": "b92e1e34588675598348e4a87d1cbf4cdb127791d0dfffeb3a1bca5d05aa4af7", + "Sources/UtterRemoteInference/RemoteLLMEventStreamText.swift": "7f9e3d245bee43de6898ce5ead82bb6dcce3b08c44c6d6e718cebb3e83f41d14", + "Sources/UtterRemoteInference/RemoteLLMResponseText.swift": "a941e28c60fa4a54aa772ba3fffb9d9ffe9f09ec79da12dae3052ea7a7eb0b5d", + "Sources/UtterRemoteInference/RemoteLLMResponseTruncation.swift": "d356c7be3514b9e27416b8c9955b14bb5c065268a9fe6537800c20136ebf2137", + "Sources/UtterRemoteInference/RemoteLLMResponsesEventStreamText.swift": "a2a6ac4cdabf2c804611c2bed734971a64cf41fe50d94cfc0f15ab87b83b2e9a", + "Sources/UtterRemoteInference/RemoteLLMStreamContentDeltaText.swift": "cb15a188122eb83a9a79d1c7ccefaebdd2bab93637f22d52886205b066db50e5", + "Sources/UtterRemoteInference/RemoteTransport.swift": "4b1d02114c0e7c0587748683c57abe3e38fd63a2f79460469d1ced7b94e93369", + "Sources/UtterRemoteInference/VolcSpeechEngine+Audio.swift": "42efe6f74a35cd5ba2ba4dc949a4cb5121d369953f61ccb8293d41e2590f010d", + "Sources/UtterRemoteInference/VolcSpeechEngine+Codec.swift": "73ce5fcc1f4d0b6dbb2d1025b382d22167a60ab77eeed090f28812af3cedc672", + "Sources/UtterRemoteInference/VolcSpeechEngine+Requests.swift": "607fd3aa0d2ddedcdf7c4fad3d11eaf300da59fa39de36430230ea53d351ae4d", + "Sources/UtterRemoteInference/VolcSpeechEngine+Transport.swift": "053d1564a4c37f1a23b09b17f2cfd0faaf29fe13ccca673de01896b485444b9f", + "Sources/UtterRemoteInference/VolcSpeechEngine.swift": "46af394e76d2c7d7b75c7361adff7d6d0b0b3db815a6f0c01948ec44296e5dae", + "Sources/UtterRemoteInference/VolcSpeechPlugins.swift": "eb54a5f11f3da2916a8728f0bfe7a065b1b698141144731a896c0884a8cf03ce", + "Sources/UtterRemoteInference/VolcStreamingSession.swift": "06d2d3d81d6ee7cf4195d5c5f9795e8aadc78568773a638882e39d45124f029b", + "Sources/UtterRemoteMic/Native/RemoteMicBridge+Capture.swift": "09abf4a67a5a26a832f83bd80d1e78420a5aa77f4808b7b510297a219290cf82", + "Sources/UtterRemoteMic/Native/RemoteMicBridge+CentralDelegate.swift": "bf0949db8dcd17cb38727160ce01f981e648e590f1a90defc9b8e465f90d1809", + "Sources/UtterRemoteMic/Native/RemoteMicBridge+CentralTerminal.swift": "1d6e1d0d00a7d6a12d06b45007c9063f075fa5f965f7ce5da273c2d1df0a282a", + "Sources/UtterRemoteMic/Native/RemoteMicBridge+Commands.swift": "47be4553afd2d69ae56773695dcc7e4a69f4e74f475604c0e841a377ca69dde5", + "Sources/UtterRemoteMic/Native/RemoteMicBridge+Connection.swift": "d9f496f079f256bf800d4d810b5d5071c9f04dc34acb719b68de6f1bfa633ec6", + "Sources/UtterRemoteMic/Native/RemoteMicBridge+Discovery.swift": "0cba3d2a05e26438d7f100c61097a2a9293adc512f1b711afa48a22af7c80033", + "Sources/UtterRemoteMic/Native/RemoteMicBridge+KnownDevices.swift": "acc7c91a722dd60ebefcbe6b872d3d34e52083c4ea2f9321ce483ca7f1bc4349", + "Sources/UtterRemoteMic/Native/RemoteMicBridge+Lifetime.swift": "a7ba9ae67206a9238433854701ac86a310ddb9c19aba2da878ac8a7e82078b89", + "Sources/UtterRemoteMic/Native/RemoteMicBridge+Model.swift": "95225697018b13157a4c2a40bb31084664674eade1d5874c4c3cf100e9e88990", + "Sources/UtterRemoteMic/Native/RemoteMicBridge+Peripheral.swift": "51969d801c393847ec11f3349d594a873aaebd379efbf90b2722713511d4881f", + "Sources/UtterRemoteMic/Native/RemoteMicBridge+Protocol.swift": "af49bbbbba68d4ff0db9e2d42f83874a5b3491b033a448a039ba15192bf78620", + "Sources/UtterRemoteMic/Native/RemoteMicBridge+Recovery.swift": "ba7cee9c237cb44b00c3423feb802363f54cb88e8e41a149f09b209735e5e594", + "Sources/UtterRemoteMic/Native/RemoteMicBridge+Testing.swift": "3edd9b741249bdb9cff2c8ef743eaf247a81dd65d0758d2c0d6ce7d88fad7e9d", + "Sources/UtterRemoteMic/Native/RemoteMicCaptureManager.swift": "057c1c79804f84defd4aed85e294a5003e37e7546005aadc4f34705f2898f0b3", + "Sources/UtterRemoteMic/Native/RemoteMicController.swift": "b50cedacbe0de0adfbe5dfc915dfdd6efcc169d644dec4704139f46fb8ba1c9c", + "Sources/UtterRemoteMic/Native/RemoteMicDelegateProxies.swift": "039e1a61c1674c465b01a94a49865c5deeb1e625e8faeb98e5254eb26fc90187", + "Sources/UtterRemoteMic/Native/RemoteMicDeviceMatcher.swift": "3cbd5df2d51cfd8f8284cdc113664f42ccf82b655b0e48685af2bf7c78406996", + "Sources/UtterRemoteMic/Native/RemoteMicPlugins.swift": "736b3ba6bbea320fa2a2bde72e67d2671e9a727f2d32dbe1efb2643057830952", + "Sources/UtterRemoteMic/Native/RemoteMicTransport.swift": "f1b7260121e906ee28076acf44b030daf1c984bfe21a00f9ad417f49affdc6a1", + "Sources/UtterRemoteMic/Native/XiaomiRemoteMicBridge.swift": "4840f33032d276aa1b01446e44aff242c213761366df402988e71cffbac246e3", + "Sources/UtterRemoteMic/RemoteMicHandshake.swift": "322b71c6ff1dd00764ac322a50bc93f31e66045051a21976179325ffaba62543", + "Sources/UtterRemoteMic/RemoteMicPreRoll.swift": "155ffc17bca27f299a642d18dda65192bfc354843690c8288d29a4c21e0e845d", + "Sources/UtterRemoteMic/RemoteMicProtocol.swift": "551368eca56a8f8ed6e0f5f2527795d165078357555ab25e8bbcd56a5a5a1122", + "Sources/UtterRemoteMic/RemoteMicReleaseDecision.swift": "4362b99453c95192985156865be6513e2c283afa624549f1c182dce75dbc5daa", + "Sources/UtterRemoteMic/RemoteMicSession.swift": "1f499f32ac1e5cfd1e8ab024cb32e99f726a4049dd682488963943f000ec8617", + "Sources/UtterRemoteMic/RemoteMicStartGuard.swift": "bdbcec1bdeb52a85a9db5e915513753684e760e1b5cae0d8d094e1c2ea14f033", + "Sources/UtterRemoteMic/RemoteMicSubscription.swift": "a047dcf2da26d48717a46c2d66e64f6dd63f367a40b9a7615bc09791f91290cf", + "Sources/UtterRuntime/CallbackTasks.swift": "c05a1cece27c0b10ca1858a38e0f3c8f87114f11d387adada580add881f20d3d", + "Sources/UtterRuntime/ConfigurationValue.swift": "e5432fb539c76909a7116e01eb529330d5d0591f474a7263f6d07a1e07c44f89", + "Sources/UtterRuntime/ContributionRegistry.swift": "313bc43aee700096fcd270a255766c5add22f420e93a7fe5aebd03ca345b7cef", + "Sources/UtterRuntime/PluginContext.swift": "da16bc4d4eea724b7cfea5ae473288254931b189897d7acb90122aa13467f8d4", + "Sources/UtterRuntime/PluginDescriptor.swift": "86915cd22ca0e42d06b2674bb127a7d5b085f4b13e50d7f540079ac1f77c6f86", + "Sources/UtterRuntime/PluginGraph.swift": "850913002aa66a99936b3c0bcbddb092345410f875b9cddcaea347e5f7889ea8", + "Sources/UtterRuntime/PluginRuntime.swift": "45459262d9f43ddd6366b0c60817f3092d25f6c6a1a5fb02fd34d446f010f541", + "Sources/UtterRuntime/PluginRuntimeError.swift": "1d3cbff8499adbc160eb90a9308c11a5105de03fab6c9c19a26a914eb87474ef", + "Sources/UtterRuntime/PluginScope.swift": "d1ec53d9b88e58157b574c2004889fe91c16ebd2301c70007fcbc3b052ce7831", + "Sources/UtterRuntime/ServiceKey.swift": "66cc0973d83d83159561216df4fa7fdd6f2b6cfb7367984c5a5106c7d28fdf80", + "Sources/UtterSession/CopySessionJob.swift": "2b0146723790915468b3394c0edc1e0e3dc6e7cf0a3e972041fa04d1d496ac13", + "Sources/UtterSession/DeferredReplacementJob.swift": "ec99e0789bbe82aab3cc082046e015ff16b5c41d17230e4da53828fcd78b20af", + "Sources/UtterSession/InputSessionOwnership.swift": "8355ac35ca6adc30b64688a3db8d57d6fb0d07f645aae55506827219fd8a685b", + "Sources/UtterSession/Native/DeferredFormatWork.swift": "f656f9697a95341253f4e76b8408d31fee8c70088414bf9d0133468960897eb5", + "Sources/UtterSession/Native/SessionPlugins+Voice.swift": "66e587dd20385fde4b77a7d78500f1f91c905e5978f1f818de20894f9fbd5301", + "Sources/UtterSession/Native/VoiceSessionJob+Authorization.swift": "aa700d6183ef99ec81e2b0e4f65f4bd35212a54aa960acd6b76f4271a2579950", + "Sources/UtterSession/Native/VoiceSessionJob+Capture.swift": "c945fa5053c4481732c619f28ff500d95d910d861e7b9401b9742e8d40970684", + "Sources/UtterSession/Native/VoiceSessionJob+Delivery.swift": "855bdac10cf1d7ea9b0d1678dc6367f05f0282c92c2974ce9264101979a5bd0a", + "Sources/UtterSession/Native/VoiceSessionJob+Editing.swift": "e7e3490fc8c81e3d8fc43234522c7e7a753b27722408426df071ea7e68341138", + "Sources/UtterSession/Native/VoiceSessionJob+InstantInsert.swift": "1bc3e19af9e18d35a9092c4b2a14e130f246c4d19eefd0d903b2b03297e60a57", + "Sources/UtterSession/Native/VoiceSessionJob+Transcription.swift": "b60e3467fb57eefd23381cf306d00375593c9065ef8cac7ab791afb2f8968376", + "Sources/UtterSession/Native/VoiceSessionJob.swift": "7524e8632a53c9fc37d69cfc37aa2e6b4882ffcd339574a4c60fdb9937d21693", + "Sources/UtterSession/Native/VoiceWorkflowDependencies.swift": "abb15a982f304c8540e157a1b815651e8b5a4a066f7a90836e4e4815ba7f7fff", + "Sources/UtterSession/Native/VoiceWorkflowFactory.swift": "be5d80ff6791e9bf641140533ba701953cd8a4395b2dc15009c8eabf76b2a909", + "Sources/UtterSession/OpenTypeService+AudioFile.swift": "00cdd8ccc902a5fcc749fa03ebb5894d2dc42d56de7379861f79ed6a85468cee", + "Sources/UtterSession/OpenTypeService+Creation.swift": "df416b78cbd7503527cfe6b0fadab1bfbc2f446ed26bdedf8a737cc62d68f790", + "Sources/UtterSession/OpenTypeService+Execution.swift": "be8e06dd4c682038504315473bd29aa4b9058c62a3df983d5bfea5b67cb3f6db", + "Sources/UtterSession/OpenTypeService+Stop.swift": "99c74e26398cdb41a324a6aa5ca70efa62516c77fd4942af96f0259a9de2e802", + "Sources/UtterSession/OpenTypeService.swift": "4fe330018ad0e2432bc5e9e19dad6a2c87bc8078d354ad8149b320bd6765152c", + "Sources/UtterSession/SessionControl.swift": "76529378204b858378deefc764efa18871f35e0042c1a99ca9beb8e17a0e4ad2", + "Sources/UtterSession/SessionDriver.swift": "9f932052b9ae0447f67d9c47188f9cbbb07b2b998958e61fa34f88a8c876897b", + "Sources/UtterSession/SessionMetrics.swift": "2cbe6ea648b4a971b67685f7f5f8cc00939992421edfb49817b10e08bb13e215", + "Sources/UtterSession/SessionOutputState.swift": "bcc65edadf025905ab6b12bb35e3195d9a2da625eb021c99551aa491919fc72a", + "Sources/UtterSession/SessionPlugins.swift": "60e9ea9d6034c9f78da891588100f21992d7a13c1f446a1cd20318bdc14b0ad2", + "Sources/UtterSession/SessionTiming.swift": "0733ce26da7d1348fb4b80e8165c6e6aee7a52ec01bb095a1729d88de00f8de3", + "Sources/UtterSession/StreamingCapturePlan.swift": "4cc70fc09c0c21ad2aeafccb412f0e7ac50b447ff85f76e7e457f7387bb2f42a", + "Sources/UtterWhisper/LocalWhisperTokenizer.swift": "14cfabd45db2a69509f33e2c60a5c20491457eca62f692dad5a708360b04675e", + "Sources/UtterWhisper/WhisperEngine+Loading.swift": "5361c241b4860e0b54a74f905ae14a4eb123977967d2b904172dc5a23405f268", + "Sources/UtterWhisper/WhisperEngine.swift": "dd7bcf4eaeccbdc47682dfb5fde7ded774fa4d780bf506470eee387960254c93", + "Sources/UtterWhisper/WhisperPlugins.swift": "52dfe722e16bb0cfe8434b0f26895d5e00a752b4d9b2a335d19f65a239bada32", + "Sources/UtterWhisper/WhisperStreamingSession.swift": "529c14f1c70b582db2b90796abe17c707cf33416b1ce3ab72f0bf2f066f84c95", + "Tests/OpenTypeTests/ANELMRuntimeTestFixtures.swift": "50cd8f38d9795230761677c9062db6d76243f8a5a759de8d5589f7693cf51eef", + "Tests/OpenTypeTests/ANELMRuntimeTests.swift": "8ddd8c3399c2652fef47aaacbf6f4730f57da1fdf2aac81fdb7f0a410b351341", + "Tests/OpenTypeTests/ASRQualityPromptTests.swift": "2d3a9837a8c851f233431e9db03b78c7f239b78a3eb1cb54a70a7e27c299e13e", + "Tests/OpenTypeTests/AppleSpeechAnalyzerIntegrationTests.swift": "cb6b0f9f93554ee8598411299fa2ad573d90efe1f523785177c75aff47e374e1", + "Tests/OpenTypeTests/AppleSpeechFallbackTests.swift": "acbf564470773c88c3661a34de87dc48c81cc27cdb2534babd2858e1d12b07a7", + "Tests/OpenTypeTests/AppleSpeechPluginTests.swift": "63f28a8e3d38c4d6b9a71a8743cda17634ac3dd65d5052664959d61d67ecfa58", + "Tests/OpenTypeTests/AudioFilePluginTests.swift": "d0a1512284637386ecffbe7fd26b3d160471729545d194b990b6c6951684081b", + "Tests/OpenTypeTests/AudioSensitivityThresholdTests.swift": "5e24106c5b6838e90ec5db91a985da59bf4f296dfb467cdbedafbadf52363ef9", + "Tests/OpenTypeTests/AudioTransportTests.swift": "be7f779a9aa1fbeff44f2ed317f6488b7049854a7f7f6a65768605b883cedecc", + "Tests/OpenTypeTests/AutoCantonesePromptTests.swift": "27f94e7dd884050909918a9cce351dcf4bbb4f31507dca572e1fac03de203919", + "Tests/OpenTypeTests/BuiltinCatalogTests.swift": "216fcbb40a3092809108617cee182cb319da7a14a386716bb9d4a23d1832379d", + "Tests/OpenTypeTests/CapturePluginTests.swift": "b9c424bfe133d8143967759d712c8da089b16011a6f98add4f62cdb8fe335de5", + "Tests/OpenTypeTests/ChatTemplateProbe.swift": "8ba57243b117604a4d0ae42855940029e2e689d93f0ef46cdfea775d2f2bc762", + "Tests/OpenTypeTests/ConfigurationTests.swift": "cae6c11646073dbf4f8a3b5e279e57798d5f1056f88922a0a55ab6369e9c155d", + "Tests/OpenTypeTests/ConfuciusASRTests.swift": "4452a4ef1b3d8457ae9b6efd41582b1d3c7f8ca86e92bc539cabf999cca8998c", + "Tests/OpenTypeTests/ConfuciusModelDownloaderTests.swift": "5560f4b70e3d259c5d6a28fe0490a94c050edaa483afbbe7db0786cddcd2ba02", + "Tests/OpenTypeTests/CredentialsProjectionTests.swift": "c1e683f9d225042acfbf63ba3e09607c64dbfb9cb1059269c3af45cfc58b971e", + "Tests/OpenTypeTests/DeferredReplacementPolicyTests.swift": "3440d786caaf8fd0aedb84cdc80644215702459bdf98a3c85f54e0a2aafc51ac", + "Tests/OpenTypeTests/EspressoFallbackTests.swift": "e26ca7476b1510e33b7bbb2293c83211f2bd7817206644816858a62c27ef4f6a", + "Tests/OpenTypeTests/EspressoOutcomeTests.swift": "78f51a6435a50f200338cef64ba70d34980263d6f9cf951e01c347e45bf84498", + "Tests/OpenTypeTests/HotkeyManagerChordTests.swift": "c99b0f2e4c9dd4afecce5544f3eb946e556a1048457d168bd1a8f62d813a438b", + "Tests/OpenTypeTests/IndustryLexiconTests.swift": "538e384ac9d49c6e0546f00dbdca5e8f9a76ba84c7eed06039b5748f3e03970f", + "Tests/OpenTypeTests/InputHistoryTests.swift": "d1e7f17cdd4a37b995e39091d72d28976f0a2e55b6a1eb5aec2c4fcb1868950a", + "Tests/OpenTypeTests/IntegrationXPCProtocolTests.swift": "7487a00798bf6ff5dd5b1efc69d6d18d901fa7891ddc614e572187d35d04df11", + "Tests/OpenTypeTests/LLMOutputContractTests.swift": "45f801e03f5bf50d612765d0aa72d800a27ed68056669c0f527badc7ca716f85", + "Tests/OpenTypeTests/LaunchAtLoginServiceTests.swift": "888f62e319722fe57f6e8aadaf9afc59ee4594ad4ca157dde48dc32cf52cbacf", + "Tests/OpenTypeTests/LiveDownloadVerificationTests.swift": "f45f05682ca2fe5353cfeb0af4c6ec0bd6d26ca41aeccbea117b01d8a853adf1", + "Tests/OpenTypeTests/LocalGenerationLoadingTests.swift": "4e1072a10cb920c4e5635c4a691b6511f6568d21ba1751ba6cf528fdcdcdd30b", + "Tests/OpenTypeTests/LocalModelAccessTests.swift": "26e63def26b6fbd5f285f11c7d88b03e43ad5092d542722f4467708075c1d111", + "Tests/OpenTypeTests/MacServiceLifetimeTests.swift": "66755332d61e599dd18d67288afbc0eb5459a79c822104810b3c8a445c5eb9c7", + "Tests/OpenTypeTests/ModeRecipePluginTests.swift": "506143148c25cdc63a369d62f9389f05a8ac711b14d7c77666bb1e9f1aecc398", + "Tests/OpenTypeTests/ModelCatalogArtifactTests.swift": "66a1dcd9e68673a45efc21909004e0a7f4d42cdebdd1d8cd623fa66b672070fa", + "Tests/OpenTypeTests/ModelCatalogLifetimeTests.swift": "b6e016c458ed2a8c07326b497182577d48b4b10e5e45a604175171436c8d308a", + "Tests/OpenTypeTests/ModelDownloadFailureMessageTests.swift": "36ace66b5fc54f63af108ab7a42506e91bed9ad6237542e206190b6b6ab2e541", + "Tests/OpenTypeTests/ModelDownloadRecoveryTests.swift": "09d153349f395bcb4bf06919a504954738c1664951cf2399dc84a50bb5282aaf", + "Tests/OpenTypeTests/ModelDownloadTasksTests.swift": "47f68c4d6175e991785d6e99a55783831457948cdcea74650a15253d627e6232", + "Tests/OpenTypeTests/ModelUpgradeTests.swift": "f18561a8b4542823c0357df5114314c944d3f1491e80efcf3d2b00600e125ea2", + "Tests/OpenTypeTests/MultilingualPromptTests.swift": "a283292569e9205e39aec9a305c46db136865168b0092030e0d9198ba6645f77", + "Tests/OpenTypeTests/NativeBackendPluginTests.swift": "1b81a7c9afa312f87422475e294b0fde4cd4f737f1e27a99b8eebc05d7361fab", + "Tests/OpenTypeTests/OverlayLayoutTests.swift": "ff3971350f9b652095313c92c5daa00047cca782fe7747e9a05259d1d3eb4f0d", + "Tests/OpenTypeTests/PresentationProjectionTests.swift": "f85c2abfa5b39281920b739fc4836b0dfe1b844eca026e366e77ecdefcdbaa43", + "Tests/OpenTypeTests/PresentationRenderingTests.swift": "1925d51cd1e065d2a229f9d22380f91e1fa09e6846bee989c82324b8182b8dd8", + "Tests/OpenTypeTests/ProcessingPluginTests.swift": "55a45029af75c6388fc426f897f46dc8076f9b87fd0d1694d9bfbd09ac46467a", + "Tests/OpenTypeTests/PromptAndProcessingTests.swift": "b57dd9c08034b8541dcadf1550750b835e738dc65ba177acc24e7608aa9ba4a7", + "Tests/OpenTypeTests/PromptBuilderTests.swift": "f45762bdf5f50ae1addb5756407834d570f9c2ed240c4cba2ee6854dba8b05f9", + "Tests/OpenTypeTests/PromptDelimiterSafetyTests.swift": "0765b48d40ce42b5823d0cb0713305be6071aad097d35da8a3b03ed028d56fd6", + "Tests/OpenTypeTests/PromptDumpProbe.swift": "2257abd137c3e3af2c54410c0ef19811d72f6fc2fe5b9baa74f147060e492964", + "Tests/OpenTypeTests/QualityProbeTests.swift": "19311aa14ad9bef4f0257549cca1a094e9850066371093c02afd8a0d283f0cdb", + "Tests/OpenTypeTests/QwenAudioPreprocessorTests.swift": "7a7159d8aaed453240a9b9703ed7a0fec96320708a949a1e193458f3a4aca041", + "Tests/OpenTypeTests/QwenNativeASREngineTests.swift": "7d3f4c843434a22d44bb3e9d152ca82c3fb7b1557c717d8e53b7a2ab5f5c67a6", + "Tests/OpenTypeTests/QwenRecognitionContextTests.swift": "c063ab9116a20e7e1ac20ab17a64a75cb1df8906426a3f69776a565c37c580a8", + "Tests/OpenTypeTests/RealtimeAudioConversionTests.swift": "29a718e9800befa05013e836df7f84498722322e0fa5b009d9c82baab804a718", + "Tests/OpenTypeTests/RemoteMicBridgeLatchTests.swift": "2a4c3b0de0e0a764dc7e1a0ca28d84b3c0a6eb23a4b1455b0ab2395eb1034103", + "Tests/OpenTypeTests/RemoteMicCallbackRoutingTests.swift": "bdffd1e182b41600bff2abcb4a2b3403f7e5de94c52a503a051bad024cb43f05", + "Tests/OpenTypeTests/RemoteMicDiscoveryTests.swift": "a96bb7978c2bb6e53d52f2ef57569b0d2fc1b83766d16deb02d96d6f4d855269", + "Tests/OpenTypeTests/RemoteMicGainSettingsTests.swift": "faba275b5aafb7e7d53c008cf276951e1fc999a76c896d76b65769c6dd1eda45", + "Tests/OpenTypeTests/RemoteMicHostCapturePluginTests.swift": "03eb66a87fec1c79a8e7ee9e7b4352d7a68ecb8e42e904ace8f8cd0444cf0357", + "Tests/OpenTypeTests/RemoteMicHostSessionTests.swift": "3cf4419ef8f86b1fe5c846ac061529f5feb9b638de45b0f4b665afb4b076d07e", + "Tests/OpenTypeTests/RemoteMicPluginFixtures.swift": "919cf72ddc9c9100d4c8687f64f2c2b1dd359581b0af69bb703d216a729f661a", + "Tests/OpenTypeTests/RemoteMicPluginTests.swift": "d362d32c4db6fe1c73d47248f17c9beeb3de1394f61c06039374b4256e1f243c", + "Tests/OpenTypeTests/RemoteSessionIngressTests.swift": "e6e3ff5ff1ab576047a8af09dcb45ff7ede376e0627476a1b1d6d497f0dadb1a", + "Tests/OpenTypeTests/RuntimeContextPromptTests.swift": "757f0a998e73beb3eb1c9bb1cd34ffb2a0ccbd42181a95ceb980808935a86c87", + "Tests/OpenTypeTests/ScreenContextModeTests.swift": "3d48f027d74e30bcedbc6fc0fd67741c58bf29266499d9375eb9bb5dfbcb058e", + "Tests/OpenTypeTests/ScreenReliabilityTests.swift": "a4552c2508b36fe852c79598782ee1ae6d19e3b366aa13d1108ece66f5b496bd", + "Tests/OpenTypeTests/SelectionEditCustomIntentTests.swift": "584a8970301efd1fb6ebe1d41858f8fd816eb2a686d6308be8a67b74204f4180", + "Tests/OpenTypeTests/SelectionEditPromptTests.swift": "38279fe4bcb96c885471975ed9906e1f3c5c8477df85cf5ff6e92cea33354a10", + "Tests/OpenTypeTests/SettingsProjectionTests.swift": "ea3d48f3baf5a370bb84ee613d7b53b34f10bab38ce10707f627a39a6e6ab87d", + "Tests/OpenTypeTests/SettingsSurfaceTests.swift": "71652a83fd27b54aa0898980f0181f827b15b33895db2cd3919601132115e1dc", + "Tests/OpenTypeTests/SpeechActivityClassifierTests.swift": "347d0b40cd4042555a057bcf3a255eb5bd349ca3f0b5feb69f6ff5f28005eb68", + "Tests/OpenTypeTests/SpeechEvidencePluginTests.swift": "5f3277c64398674fd2b5200bf11fc5e38ad5d653ae895a5bbdaf32b7fa0f9995", + "Tests/OpenTypeTests/SpeechRecognitionQualityTests.swift": "2f47e9b455d70d4c5d1337b8451a044fe1ef27e4da59922bc66c15e880925f0d", + "Tests/OpenTypeTests/SpokenEditCommandAdditionIntentTests.swift": "b9f607671c3e1bfe3054623e5239754850ce438a1d20282e1d726e4b514b69ef", + "Tests/OpenTypeTests/SpokenEditCommandContextTests.swift": "1569d9bcf69480acfea7f4d80473c6dd4aba01fdd69495b9af963b3f29b85103", + "Tests/OpenTypeTests/SpokenEditCommandLLMResolverTests.swift": "7abb8de6ef28e9582ae163b423e8fd063c9ed1fed655d8fce8d9daf2d1e3830b", + "Tests/OpenTypeTests/StablePromptPrefixTests.swift": "9588fe5fae3a32140d369530cd8b369b6047f09ca958d423799633d90f11e137", + "Tests/OpenTypeTests/StreamingASRIntegrationTests.swift": "459935717f5b5810d626706f8dacedebb48fb0345df248d35c22b9679ddbbd3b", + "Tests/OpenTypeTests/StructuredFinalTextDecodingTests.swift": "8249fca55e5d7aa40022d5f29d918e8cd511c96acd99952d102b26b7a8ac04fc", + "Tests/OpenTypeTests/Support/AppSettings.swift": "0e1ee4f0043b8d891f6d32aaa254ddbf72874212b363758e2bcdb342d99f96d6", + "Tests/OpenTypeTests/Support/AppleSpeechFixtures.swift": "5367998f73e232bf1a5042736ab995b75b1b192cb18bc6b1ae6e983aa7cdb4b1", + "Tests/OpenTypeTests/Support/AudioFixtures.swift": "efb64e42c9645363a0e1ed952fe0118eba6c11c66f832253927bbe521af28df3", + "Tests/OpenTypeTests/Support/DeferredReplacementFixtures.swift": "1ea189bd0b973a1fb4ac8d12d2c773f3dd95bc3e1e68a0e82ff0f98553704421", + "Tests/OpenTypeTests/Support/EspressoGenerationOutcome.swift": "d42cb497761cc0fa8dd8494b683bf60d2de2f578876916cc6a0b9f99915454e0", + "Tests/OpenTypeTests/Support/InputHistory.swift": "77bdad2f331312d33628172204c1b3398b811208adecb13a6e8b944da9d6bc45", + "Tests/OpenTypeTests/Support/IntegrationFixtures.swift": "e039d378a5f0021ac55e7c7c0c11e554c87f0d7520c21bafcc5f2408c66f1cc1", + "Tests/OpenTypeTests/Support/LegacyGenerationCatalog.swift": "8c75bdff3b1546141a6ae42d08421e2727fceb3a91cb154997de8bcfdf137cac", + "Tests/OpenTypeTests/Support/LocalLLMFixtures.swift": "0bff061674a9aaf11f3064f2f2321e20e8378e343a4542f19b6aebed8089213d", + "Tests/OpenTypeTests/Support/Log.swift": "10e480e63a456a7022368aada39db325abfbc4f440e953de1a356f6e1ec28fe1", + "Tests/OpenTypeTests/Support/MLXSpeechFixtures.swift": "193d1ea9ec3246a61c71b1607f79f269205b39b6b3a6c5a6cb5acfb604df330c", + "Tests/OpenTypeTests/Support/MacServicesFixtures.swift": "ba435753418b6cf623d56c7142aa7e22477efec49df266b80c648a6c2b358dd4", + "Tests/OpenTypeTests/Support/MemoryStore.swift": "36b2ae7e2367321ca0465d5c8318b91cb6402c1cb40e32a6e232bc18704be973", + "Tests/OpenTypeTests/Support/ModelCatalogFixtures.swift": "054b7cbf49b1e6ee7ec3e47af8ea65b55f462125b27bc198a8d9ba5e15de5226", + "Tests/OpenTypeTests/Support/ModelFilesFixtures.swift": "a4983664c339e3f2332741e71134ea39839ed7fc3beeeddd8dde086d1fafbc11", + "Tests/OpenTypeTests/Support/ModelRecoveryFixtures.swift": "e55d8529d4fb11f37e44da0eb49466e25be5301b56810f45b04a7c1071962f79", + "Tests/OpenTypeTests/Support/ModelStorageFixtures.swift": "9158d6d4932cde4ab4ca10db0436d91be7d1035758c963b5bc5924c553e1c70a", + "Tests/OpenTypeTests/Support/PersonalDictionary.swift": "7a1d13636ef98abc1884cab9b307406a6a81efc0cc57ec9a6797845557452de8", + "Tests/OpenTypeTests/Support/RemoteLLMFixtures.swift": "9f7a6209b8788438dc4c4a1d490b567c489778aa9db10e473510579e36ad33ae", + "Tests/OpenTypeTests/Support/RemoteMicCaptureSpy.swift": "7c4c787fa0482a374e1d6c57a04d5660205ba52afbd01fd05b6ed61892b0b80e", + "Tests/OpenTypeTests/Support/RemoteMicFixtures.swift": "2ba630bd598b4e53cf0f8a8025b181f69eae9a2825174635f911990b95eae554", + "Tests/OpenTypeTests/Support/SpeechSelection+Settings.swift": "bb0cbc665f2064fe0c0d91ad39c89432c7e087d875493c8ab84cb07735f5a274", + "Tests/OpenTypeTests/Support/TextProcessingOptions.swift": "380672adea1cbaacb4f9cb6a06c52fb216c955431db4409277d340ed5b13a0e4", + "Tests/OpenTypeTests/Support/TextProcessorFixtures.swift": "458dc2f41f826068a272e0b64ca8a1d93f81f911975a067d4cec7a9daacadadf", + "Tests/OpenTypeTests/Support/VoiceInputSettings.swift": "4216c07ba5e5edbb7297a142cddfa54b5a4d76db4153c88db19dd858e3bebe32", + "Tests/OpenTypeTests/Support/VolcSpeechFixtures.swift": "530f301dfdf98c83148a9afe5b5aa8b186054fac74a21f7d847fb01680900e92", + "Tests/OpenTypeTests/Support/WhisperFixtures.swift": "06aef26f9c841b2e4466ffad9f9592e3e3072dc96b6651734203949297d8a9d3", + "Tests/OpenTypeTests/TextFormatKindTests.swift": "bde7f6589b6ba3a0226547800ae1fb7c0f9cd69063ab5bacb2bad0c39f0f2d82", + "Tests/OpenTypeTests/TextProcessingProviderTests.swift": "56ce975a3792043c3f4f1e0378cfd07bc082839a5fc7ce39b75018d103d5d859", + "Tests/OpenTypeTests/TextProcessingSnapshotTests.swift": "9f0b6ea110966cfe84defdcb60a0f58288a5ec9493fc293301a3ffdeba07399e", + "Tests/OpenTypeTests/TextProcessorFallbackTests.swift": "b1599b9064e4ec8cfec2bf20a37af4358a3f1436707c3431bc1e33bec0415b2b", + "Tests/OpenTypeTests/TranscriptSegmentJoinerTests.swift": "27eed3e2182175b5989fc792179d894deb4de84dda8cbacc6f124d2c8e641e8b", + "Tests/OpenTypeTests/TranslationLanguageRecognitionTests.swift": "7b54ebf7d740a1c8d40b3f759187b725fdcb3c93f4a7c0e2246853f5b3b8ca0f", + "Tests/OpenTypeTests/UtilityTests.swift": "9c538103ebc3eadb25d2ec4641427400dbd63dadc20f02c489266f78c8329863", + "Tests/OpenTypeTests/VocabularyReplacementEngineTests.swift": "daf47a6748ce82f4c664d692a1299f92704b4dd30e9266003b9f1f8a75db7e0d", + "Tests/OpenTypeTests/VoiceAuthorizationTests.swift": "d591392d75e05558c4dff4e0fdc694dac153badc5b7690b07ebe2508dfa3af32", + "Tests/OpenTypeTests/VoiceEditingTests.swift": "4dc6ed89020864d7d972969d1b59701d7184a7068071dc5a45f5f5f4268ecf61", + "Tests/OpenTypeTests/VoiceFileBindingTests.swift": "69c825c9976705b5898a3d4c7abf51b6c8fd236586840ab295d434a7218e1b4c", + "Tests/OpenTypeTests/VoiceInstantInsertTests.swift": "5dafde7309620d5daa34765addae468ae5412e2c8fcde79224ec6e387fa9c0ac", + "Tests/OpenTypeTests/VoiceModelQueueCaptureTests.swift": "c803a91aa4929da536d6ae9e2a9da0bcae7bbb84a0d1e993a3baded9f9b43e11", + "Tests/OpenTypeTests/VoiceNoSpeechTests.swift": "806481f721b8044d14fe84a940922f236d0aa8a2512a5bd532f95c3e3e3dd12b", + "Tests/OpenTypeTests/VoiceRecognitionDrainTests.swift": "af1e181371c40372a4ffe50bef1df1cac79359a4591929f14d30f6dae5ce9420", + "Tests/OpenTypeTests/VoiceReplacementTests.swift": "8af06c694cd76c43249c55b94726d889a4d1b1db394fd43b16e39395cc4b22ad", + "Tests/OpenTypeTests/VoiceScreenFailureTests.swift": "93c50050ac8af85bfa44ba61c1f8d5f2a51a1d44b7ac0110f3832c000e1e0ec3", + "Tests/OpenTypeTests/VoiceTextInputTests.swift": "733cb8d0097b40d40fe8696c0a91e00a86bed6ec3a4e275878867b02d8b72ecc", + "Tests/OpenTypeTests/VoiceTranslationDeliveryTests.swift": "0e095c9200601eac7837a6499051e0867229dbce4ff1b451282f7e1fe344bd99", + "Tests/OpenTypeTests/VoiceWorkflowFixture.swift": "c30a774b72792a3ba82fbb2e21e8a02f4567bd1e27992beb88edfcf466fd43d4", + "Tests/OpenTypeTests/VoiceWorkflowTests.swift": "59402d3e520fdd089d7d945901bf64373569e36b9264557a1d341abd3489acfc", + "Tests/OpenTypeTests/VolcSpeechEnginePayloadTests.swift": "df3053f646d1ba9f357d58c3f0619cca05b8adb36b25ab634eaf9bc637f345b8", + "Tests/OpenTypeTests/WhisperOfflineLoadingTests.swift": "aa92fd82ee166f693101fa26496f7e966c2977d49c5a9ced27977fd0e09a2b3b", + "Tests/UtterAudioTests/AudioCaptureActivityTests.swift": "c2442883b42670ea87117da39d26bd4be9994e349985a68beb48add6eb2f20db", + "Tests/UtterAudioTests/AudioInputResolverTests.swift": "51bd906b90e13093551fe85d4685ef9a73d967e3eaee76e0b7d7804a54250b1e", + "Tests/UtterAudioTests/AudioTailDrainTests.swift": "cb391d39d67bfe24fd58fca795ca20c5f9e5d1b6411fb69029d2b6cec67b8d81", + "Tests/UtterBuiltinsTests/BuiltinRegistrationPolicyTests.swift": "f3bf389a12efb375a9ffa8f87acca673041cd08210e21f7afaef3af546268b88", + "Tests/UtterContractsTests/FrozenModelFilesTests.swift": "ea5f06786174d77244e382c11236b0f39f601e19ed4dcfedc21e892a554ae329", + "Tests/UtterContractsTests/HUDRecoveryLocalizationTests.swift": "de97dd8db4146a21a1ae1f684546fedf2d9a08c314e98d1e7a9450bb8ee18b0e", + "Tests/UtterContractsTests/IntegrationModelTests.swift": "2b1f58706cb5ff90a9fb5f6bcf517e48c189c68fed0f3a3874b441dc90b63a43", + "Tests/UtterContractsTests/LLMResolutionFieldAliasTests.swift": "e4fce85c7051654daadbd2f5e88e286ce688bb22570914842ff63d1e8fab3b82", + "Tests/UtterContractsTests/LLMStructuredOutputTests.swift": "eb91e3fca372cccf37e953ad493c6dd347db61559d7f263800bc5e9355d78e86", + "Tests/UtterContractsTests/LocalModelReliabilityTests.swift": "827be1f7c9d28ce90fa74f618ad49d27888c78e7a0301d0f3a48268c39b02a07", + "Tests/UtterContractsTests/ModelBenchmarkSuiteTests.swift": "f541db8e303f3a86b4c8344f3d2fbf0e8cfb2f97fd4ed86366e4911a4af64275", + "Tests/UtterContractsTests/ModelLocationLeaseTests.swift": "5f8a34405ee32647992b702dc708c88131c96ac5a200d7861895e54cc0c32fbf", + "Tests/UtterContractsTests/OperationDeadlineTests.swift": "703b7f8c1c459eacff366d3a5cd2655508e4fd48ecf367f9b155b34369b80e57", + "Tests/UtterContractsTests/PermissionRequestTests.swift": "a3b35a30b6e1829742ed6252f2c063cc9cbf46f1a584c883019252606d9b8a3c", + "Tests/UtterContractsTests/ProviderCapabilitiesTests.swift": "554cdb12bf99629bee86483189f6fe36b2032e30466d10067084fd24fd810e15", + "Tests/UtterContractsTests/ProviderFactoryLifetimeTests.swift": "e0db1431cf48599e83f0f822c5a82cf24193ad01ae6aeaa8aa06efff26177717", + "Tests/UtterContractsTests/ProviderRegistryTests.swift": "ac4abce2a8188ac279763eb7d3dac369cea3be46f66d6995d010e2eb0571d35b", + "Tests/UtterContractsTests/SessionPresentationTests.swift": "97d9b04ede64809417c35464a10ad3877e1b56974ff2a144fbd27ad4de380fb6", + "Tests/UtterContractsTests/SpeechSelectionTests.swift": "cb612c2f3a9f8931a1997b4872f39cc292885c5877bcecc57d5626c58354f37b", + "Tests/UtterContractsTests/SpokenEditCommandActionValueTests.swift": "b68eeab9e9f117b49632897492ef3a6aed1e45016cffa1e9082f84c751edfbbb", + "Tests/UtterContractsTests/SpokenEditCommandConfidenceValueTests.swift": "24ef899e9ab1d1279fac2691ee5192f31ba6c4701e2112367c82fc4c51939284", + "Tests/UtterContractsTests/SpokenEditCommandIntentValueTests.swift": "20c5e02860b4987d870996b90558a92bb8f612f825b6dac91ce947f5c7a033e3", + "Tests/UtterContractsTests/SpokenEditCommandLLMOrderingTests.swift": "13d1079ad7e05bd3597611cddf05f3a9fe92d811cdd9887f52b171cbc12804e3", + "Tests/UtterContractsTests/SpokenEditCommandLLMRobustnessTests.swift": "2771a3a97970ef5ef45847571798ea81d481789b625d9d0c338c04aed19e738d", + "Tests/UtterContractsTests/SpokenEditCommandMetadataValueTests.swift": "52b5c164f00ae36c49c6a619cd83bf5d1fc285e1e934f46a63c285a45af4e1a9", + "Tests/UtterContractsTests/SpokenEditCommandQuotedJSONTests.swift": "025fbab6369362aa1adcde43a00e4f56936c1f8ff46f03ff5566eb22b9afa495", + "Tests/UtterContractsTests/SpokenEditCommandReplacementValueTests.swift": "eff5a00d5d95960220355d0cecd3bc769c1b8090c58229136d1fa774f6f588d3", + "Tests/UtterContractsTests/SpokenEditEvidenceTests.swift": "0d57dd80101cd485cf1257e9543fb2b280684f6839e1b8c063af9c311dafa3ff", + "Tests/UtterContractsTests/StreamingSpeechSupportTests.swift": "88d67960822495fe48eadc589a19b38fbf1494eb4df4fb405015e0bd8246d1c3", + "Tests/UtterContractsTests/TextProcessingSnapshotTests.swift": "bdbca563f87845fb59465d8cc023e69db83f039598cadf236e92dfcf5f2bdde9", + "Tests/UtterContractsTests/TranslationAssessmentTests.swift": "f12b5e28f9d6f0953e9f5c02ae9a0d39d314b68a7d6c8617c682f496aa13f81f", + "Tests/UtterContractsTests/VoiceInputSettingsTests.swift": "5cacfe0bd9fc757a3ff0a2438cfec3a1e882d60da650110be2d3ae7cfd86201f", + "Tests/UtterContractsTests/WhisperTokenizerAssetsTests.swift": "adccfdab4949d15a9366f69ab4997720e0c519bd0f302aaaff5a96be9ac5a454", + "Tests/UtterDataTests/CompositionTests.swift": "79b224d6aae041116d74d83d6baafab12b4e2e71d670f2ee8b7bf4d485960a86", + "Tests/UtterDataTests/CorrectionCandidateClassifierTests.swift": "d9bf9f0747368b9892c2a0529926e14f88c607758a2be45d1496ff1e85df0b0d", + "Tests/UtterDataTests/CredentialsServiceTests.swift": "790169bbaff842efe99080751558deac92b88e71dd4aa64874251496e18299b2", + "Tests/UtterDataTests/DataPluginTests.swift": "801263ff88b0226b66b1b5a4bd4762e6a4f0624305c028a87d220b9cda698fd9", + "Tests/UtterDataTests/DictionaryStorageRecoveryTests.swift": "30dedc7e84a857a48b2d48add85365c62fa2f95de9d438cc027f766f547de113", + "Tests/UtterDataTests/HistoryStoreTests.swift": "b7bdaf16cddba3a20bdbc2e1cd91b76cb094560b710c1f84823b44f0ed8f82c6", + "Tests/UtterDataTests/IntegrationAuthTests.swift": "b55acc83fced3adb1c8b0a2c976e4cfb9271597b917ae6fc61724204be4a10cb", + "Tests/UtterDataTests/IntegrationAuthorizationObservationTests.swift": "25a7b3ab1918e5fb83315d0a8cae491702c402d820d9e1403099302e9103f232", + "Tests/UtterDataTests/PersonalDictionaryLearningTests.swift": "b8dfc02befea1a4fd791226f55d8a5e4b9008f3431fb853b5d4a01e7ea040549", + "Tests/UtterDataTests/SettingsStoreTests.swift": "511dacaf182f88abb9073c480f70f0c9471f03ffb5cca1141a964b4f7da7ccc4", + "Tests/UtterDataTests/TechnologyLexiconRegressionTests.swift": "d295a55e29f93fa709c4d7896d15330eaad7f88edc92f256bd2df1b39486275c", + "Tests/UtterEvaluationTests/VoiceEvaluationTests.swift": "00c153be383f5c54ab0568f9e4ee85c69268ee6cdb6e5bb50de89974ddc8c538", + "Tests/UtterIngressTests/HotkeySessionBindingTests.swift": "1416176433e2abfa325d2b8d13e402c394e4bc82b1f630d368743dee7a105d4e", + "Tests/UtterIngressTests/IntegrationHTTPTests.swift": "26a82e64db0497bdfd0d90e1ef1209d29947efc9fa6c383d3047dc60443987df", + "Tests/UtterMacServicesTests/ClipboardPasteTransactionTests.swift": "63d058b894e284c8a0fb5c59c986f3518326d406d3640a3adb6fdc1350d65a66", + "Tests/UtterMacServicesTests/CorrectionCaptureLifetimeTests.swift": "c53c850796a68a3a84c8e212686660f84bfbc249acda6ed899d76cb82643fceb", + "Tests/UtterMacServicesTests/CorrectionCapturePrivacyPolicyTests.swift": "dd45332f4fe541b22ed3c2209960caa891414afe9d488b98c3f0eb30323928d6", + "Tests/UtterMacServicesTests/CorrectionCaptureRegionTests.swift": "00c05b00bcf3cb0cbf8ff0cd3c0da5f167531d5a39767753a02b34ec515e9c12", + "Tests/UtterMacServicesTests/DeliveryEffectSetTests.swift": "4f95dc555edc21f196d7cdccbd1dfafed3ee3890ec29cb2a0676173cc67e26f4", + "Tests/UtterMacServicesTests/DeliveryReceiptTests.swift": "2c5ef4e79fffd40b96731e5077b03091f1a72a1e14c698ae9aff87f82993af87", + "Tests/UtterMacServicesTests/DeliveryTextChangeTests.swift": "7fbf43f7817a9e8b6d52fc01c23f7aea8706ababf3f46854749fac4e57612ffa", + "Tests/UtterMacServicesTests/DeliveryTextObservationTests.swift": "136a609a992a7ab0a173704abae6e8e4d99b995631fc84d1a4eb732868e70296", + "Tests/UtterMacServicesTests/HotkeyActivationControllerTests.swift": "375743e251f2a19840727658b8abf5cf14b7d97e5e2951b97deb9834b28c2f85", + "Tests/UtterMacServicesTests/HotkeyGestureControllerTests.swift": "fbe3ce65a7690982718ea5ce4bef5ebba90def95f4e387431f45d5aebc6fdaac", + "Tests/UtterMacServicesTests/HotkeyGestureLifetimeTests.swift": "8ef12a1c0138ff8fc824a5c65301834ae9e2a13b017f36ba2a7c75a7f4b5d243", + "Tests/UtterMacServicesTests/NativeOutputBackendClipboardTests.swift": "b75d1abd5a7d1ca3eff98e00aa8a46723120daef06be6fb159547006a0441642", + "Tests/UtterMacServicesTests/RecentInsertionGuardTests.swift": "6c65065cc76ba09a3b6784d3c1fbd9d552acd05e053961393bf91ca304a12c75", + "Tests/UtterMacServicesTests/TextDeliveryTransactionTests.swift": "c34be47e46463e38b58ac75918f38e74a6765ee7102ea6da73aa60a56afe52dc", + "Tests/UtterModelsTests/BorrowedModelAccessTests.swift": "cd38f0ab06f3cacedc2884226f10988faf93cfaefccf91d00e2594f285320cf9", + "Tests/UtterModelsTests/ModelArtifactRegistryTests.swift": "bd34879e9980a8d71cb7c1b06ed2f92bb6f71f1a16063c56aaf13497707f7ade", + "Tests/UtterModelsTests/ModelAssetsTests.swift": "3cdfd0acb31e8060b7fe1af57bd78320fa6f076fb62c3591e6f5cdd7dc8a1098", + "Tests/UtterModelsTests/ModelDownloadDrainTests.swift": "201331407d25903d47aaca15b3da169f0fd69b48883cf3c8093e5f9cee6236ae", + "Tests/UtterModelsTests/ModelFilesPluginTests.swift": "2c9fd70613cbd9310f166af3f1e62abf652f38bd31558941756bd92b830ec35a", + "Tests/UtterModelsTests/ModelFilesTests.swift": "84cda5ef982c6175addf636c7d74e0acfc25b3f3606f5b7ffc757f895d26524d", + "Tests/UtterModelsTests/ModelGenerationTests.swift": "1bae344477c08aa076faca449d8aa98f553d73ffbc1dd9122cd25ad1bfb794dd", + "Tests/UtterModelsTests/ModelPreloadPolicyTests.swift": "87bdb60994372153f6fdbd52986ed69001b678d2100e0d7a5bac17fee1859b5e", + "Tests/UtterModelsTests/ModelResourceAccessTests.swift": "f87829eb1f4d110fd0fa8233957c2b0330271c752ec4e12ff534e7ab6f31f8e1", + "Tests/UtterProcessingTests/CommandOutputCleanerTests.swift": "1ea7a879bacfdc59e2d0b56b7982d11b02a53856826f6fb7122c715b61511753", + "Tests/UtterProcessingTests/CustomFactSupportTests.swift": "220f81d0b2e768c581d313243fcc5282e2e9620bdc264c7e970d3fcceee4a22a", + "Tests/UtterProcessingTests/FormattedOutputCleanerMetadataTests.swift": "43a317828e776442dd325dfaf0c6053d199e5fc59635bb3fd1facc4cdbc12c4a", + "Tests/UtterProcessingTests/FormattedOutputCleanerTests.swift": "a4be4e43dc4fdcc6a59d7decb174f794a70e879d284369b315a90009f167056f", + "Tests/UtterProcessingTests/GenerationCancellationTests.swift": "df2cd2800756a0e46bc257ea85e83a092a80b04d0912a039882d7b4c6f34e36f", + "Tests/UtterProcessingTests/GenerationFallbackTests.swift": "c33da8708915711ca882a8be449b47432fe16863050abf06cd269bcf59b5025b", + "Tests/UtterProcessingTests/LLMFinalTextOutputTests.swift": "40fd6e21782203fe65feba84540423aff8b89df84234ab2a015b42d56ff8cfda", + "Tests/UtterProcessingTests/ListMarkerFidelityTests.swift": "5008d39f26695f0a1cd66737d2ec8d0afc15ab0ab787c08c6f50d022b02d4728", + "Tests/UtterProcessingTests/MemoryContextFactBoundaryTests.swift": "6984748b6c95d0ab0f98230e0228da31200b6706e2ec5022114bab91e3ef7b5c", + "Tests/UtterProcessingTests/ProcessingObservationTests.swift": "11db403920db6ffb442911eeab0a5b2fa516c1bc1e8d1a54812fc952bc09d7e3", + "Tests/UtterProcessingTests/SpokenQuantityFidelityTests.swift": "1aaf8d50c6bfb08399bc09301c3b66a66b2822b2b0ab3a4ceb676fa98eb4a4c2", + "Tests/UtterProcessingTests/TranscriptFidelityEdgeCaseTests.swift": "111f54016119d3e82ea969abc71cd01a9bf71139e5339862ce4c3de0a96a3b08", + "Tests/UtterProcessingTests/TranscriptFidelityGuardTests.swift": "14c2bf52293e845e540e253c1728ced82bc20a3ffbdaf52f4ce509e42e02ad58", + "Tests/UtterProcessingTests/TranscriptionSanitizerTests.swift": "726c44af817a0412b6ff336dff745ffe7f9994067930ca970217d91fcac331c4", + "Tests/UtterProcessingTests/TranslationLanguageSampleTests.swift": "3870440ff41dc15406b17a51f5a723f3de176cfe6ab2a9420a54e07c0477d7f4", + "Tests/UtterProcessingTests/TranslationPromptTests.swift": "caa488ca0efc971d801b392df498633fbdf536e4836ec0d02fd3c2ca54c43c72", + "Tests/UtterRemoteInferenceTests/RemoteConnectionPluginTests.swift": "8b69c7acff4067918050fe25521347b3bad6eca626e901f67cde49db2acd5477", + "Tests/UtterRemoteInferenceTests/RemoteLLMAnthropicEventStreamAliasTests.swift": "991c6619b58ed64609eb3dcd3a75afc515a81c688d2488128290fbae5aa9ab3e", + "Tests/UtterRemoteInferenceTests/RemoteLLMAnthropicPayloadTests.swift": "2cfdc196d0462c8420320d91562d821f4fd0b39ace08b324ec173a3070dc799f", + "Tests/UtterRemoteInferenceTests/RemoteLLMEventStreamTextTests.swift": "20a4bd113a196e6a7f990f47bb3e18bc544917267248a489ca7b54e5e161ee1f", + "Tests/UtterRemoteInferenceTests/RemoteLLMIrrelevantToolPayloadTests.swift": "dbcdbba703b19de5a3a7d77076279f513b04a9cffb4554dc7cb8609976de988f", + "Tests/UtterRemoteInferenceTests/RemoteLLMJSONBlockTests.swift": "18100d6a1b4efd99f5a6db43fae4ccde7db382ae9889cfb95b799510df2afdb4", + "Tests/UtterRemoteInferenceTests/RemoteLLMOpenAIEventStreamAliasTests.swift": "1af7bc6b9e981c21d660143c979cde9f19330a63c5681e289d79c3e6a4cbca9e", + "Tests/UtterRemoteInferenceTests/RemoteLLMParsedPayloadTests.swift": "5f48b34dc42898adc85b4d1a8842384e4e30f4f6270092c0bb9afd073ba2078b", + "Tests/UtterRemoteInferenceTests/RemoteLLMResponseTextTests.swift": "8c3e4b42460236ed0092e4837621f0546878939ffd138dc8146f2575bd2fc90f", + "Tests/UtterRemoteInferenceTests/RemoteLLMTokenBudgetTests.swift": "278419bd27d3a92c0175edd0e3d09d426aaba28bb5926c76e925ac837115c344", + "Tests/UtterRemoteInferenceTests/RemoteRetryCancellationTests.swift": "058d1715b27133e2e729cd83a05eb312f08383a3f953ba616ba4392c6bcbd4a6", + "Tests/UtterRemoteInferenceTests/RemoteTransportFixture.swift": "48df3346c3ee1996944761f76baabaf882e5eba30ba0e1904643a93bc49214a0", + "Tests/UtterRemoteInferenceTests/RemoteTransportTests.swift": "727d6324f846dd629c879d3d500e34dbb05c18a244ab73568fffe83dfe113400", + "Tests/UtterRemoteMicTests/RemoteMicHandshakeTests.swift": "ec424439703c5568be3941cba9698a9a3bfd9168af2ad3fbe100637cef5e606c", + "Tests/UtterRemoteMicTests/RemoteMicProtocolTests.swift": "807892515c1b1c4760357f5c399994241b3440e9f1500a0eb68c9b14bd20a60e", + "Tests/UtterRemoteMicTests/RemoteMicReleasePathTests.swift": "5bc1b70010d8584cb8489a8a7e91c222ff059d412d5f27cc574a36d7d06ccf20", + "Tests/UtterRemoteMicTests/RemoteMicSessionTests.swift": "726d250a1ab422d40db5df44bc3641acc0fd01d89f2299d1f6277237daf5096b", + "Tests/UtterRemoteMicTests/RemoteMicStartGuardTests.swift": "b4bfa8f3fea56c5cba2ac2fcd7428bf0ccb34b5e42db9a6c9c5770302454d7ba", + "Tests/UtterRuntimeTests/CallbackTasksTests.swift": "d6f7235fc0a843f6418e6dd051a7a083a01999a147cca24b7660fd6dfb5254ed", + "Tests/UtterRuntimeTests/PluginGraphTests.swift": "1db13c413b5826286e97039af5b57e2396fb96afb40b099456273faa540f8c49", + "Tests/UtterRuntimeTests/PluginLifecycleTests.swift": "a1df6ead273fde30736cf3cdb5cf936a500d3b41046f3ac8743bcc23c9c2b7de", + "Tests/UtterRuntimeTests/PluginReadinessTests.swift": "2b8b64a269472170db4ccceb6b5bb3cabae814da9db66ed01bec76a90a32dbe3", + "Tests/UtterRuntimeTests/PluginRevocationTests.swift": "1dceda019da9f79f7b3b5e0aa92e201b60bdc369b5eb5988d29afdfb881c8dc6", + "Tests/UtterRuntimeTests/PluginRuntimeTests.swift": "148049a801c12c135901d05d7e02a1e036966db7a20c18a3cbea8b0a25d93c0f", + "Tests/UtterSessionTests/CopySessionJobTests.swift": "8b2e7680362a94f34dc26aa63854216492fd4121c3acc526b76a341345e72d4f", + "Tests/UtterSessionTests/DeferredReplacementExecutionTests.swift": "8f5898e5b4c32ac5e6940b6127ecbd4ac4b9990ce7f27be243cf48ce6234076e", + "Tests/UtterSessionTests/OpenTypeServiceTests.swift": "c80df878a4a39802a1bdcb4272af25b97a0cccc4146c3af15d5bb4bc6faab1ef", + "Tests/UtterSessionTests/SessionAPIExecutionTests.swift": "93e839b833b695ecaad986a32c6169b4dbd3eeb68c3b62730e2f3fee125da95b", + "Tests/UtterSessionTests/SessionCommitTests.swift": "09b3f4f3afde34f98b503b5c3248dbbd94e190f16be1724800282034f836e16d", + "Tests/UtterSessionTests/SessionControlTests.swift": "fa61c962f4fbb323ca0d2f8b3afc601e07a99b08cfb762cd748d0840d562e032", + "Tests/UtterSessionTests/SessionDriverTests.swift": "93ffa921d959bb0ffd3ff9dfab77a4012cf46a8ad17fb0fdef4b053790d1858a", + "Tests/UtterSessionTests/SessionMetricsTests.swift": "08ac1734571933374691959509d700832893257006e40408ca30a3935dbd7da6", + "Tests/UtterSessionTests/SessionOutputStateTests.swift": "3687c68151a63c4da6b0c8a0edac1ddc14affcb6c5e49e69feedeaaa61e49593", + "Tests/UtterSessionTests/SessionPluginTests.swift": "b9b24e8e69f999f1ac19ce3ff851d5ddb60959002ec25f88f3977c5ea73d7529", + "Tests/UtterSessionTests/SessionTestFixture.swift": "1b7f7f719d1663cbc6948d5dcd7a866607b95455169ff89ab3aee3ab02fb61e4", + "Tests/UtterSessionTests/SessionTimingTests.swift": "b5a3afe046a262dbf56e925164b84c6ee2af7992dc2a8fab56ab8f73424a23ff", + "Tests/UtterSessionTests/StreamingCapturePlanTests.swift": "bf6b9bf17c712a2871ac5cd956bd19ab15740c951303ca2832bb493201b4bba1" + } +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-code-review.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-code-review.json new file mode 100644 index 00000000..6e474153 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-code-review.json @@ -0,0 +1,68 @@ +{ + "verifier": "/root/signing_verifier", + "reviewed_at_utc": "2026-10-16T02:58:40.586603+00:00", + "result": "no_code_findings_pending_native_and_full_suite_verification", + "human_verification_approval": false, + "base_head": "f0ef2aa88296da017e29ced2b7bc9271af96e4fb", + "reviewed_file_sha256": { + ".github/workflows/release-artifact.yml": "f9845ad9d4b7d35367d5cffa722b208f998f90a400ce3dffc44173d4449af73b", + "scripts/verify-release-artifact.sh": "e2ee26c5fc9c5b2cb122731a7d801f8ef91176733256f92cbd76cf1c3a1b735b", + "scripts/tests/test_release_workflow_contract.sh": "7ba76b3f1edd5ec01601f62b3a98c7571e5e244cd9ef730f55c0ae1dffe05c37", + "scripts/tests/test_release_artifact.py": "23004ea623723d5649fc211ca2efdd775d6b57930622afa65462ae3d69e9f995" + }, + "findings": [], + "boundary_assessment": { + "shared_entry_points": "Tag and nightly callers both reach the amended shared classification block.", + "developer_id_order": "Existing app/imported-identity equality precedes DMG sign; exact imported identity, timestamp, distinct identifier are used before first verification and Apple submission.", + "signing_failure": "Actual extracted block runs under an external bash -e process. A codesign failure stops before verifier invocation or later notarization steps.", + "dmg_verifier": "The actual script rejects invalid primary signatures, non-Developer-ID authorities, missing Timestamp, failed/empty fingerprint extraction and certificate mismatch before any hdiutil mount.", + "expected_fingerprint": "App matches optional imported fingerprint first. DMG must match app, so both are tied to expected fingerprint when supplied. DMG/app equality remains required without the option.", + "certificate_helper": "Explicit if-failure handling under global pipefail plus exact 64-hex output validation prevents conditional-context errexit suppression from returning empty success.", + "unaffected_paths": "Generic packaging, app-only acceptance and self-signed branch retain their prior contracts.", + "post_staple_controls": "Same strict DMG guard runs again; stapler validation, both Gatekeeper assessments, mounted-app equality and publication checksum gates remain in place.", + "secrets_permissions_dependencies": "No new credential export, remote permission, API secret, dependency or app behavior introduced." + }, + "independently_executed_checks": [ + { + "command": "bash -n scripts/verify-release-artifact.sh scripts/tests/test_release_workflow_contract.sh", + "exit": 0 + }, + { + "command": "bash scripts/tests/test_release_workflow_contract.sh", + "exit": 0, + "covered": "Literal YAML block sign-before-verify, exact arguments, abort on signing failure, self-signed branch." + }, + { + "command": "python3 scripts/tests/test_release_artifact.py", + "exit": 0, + "test_methods": 4, + "covered": "Actual verifier with controlled external tool boundary: success, unsigned, ad-hoc, no timestamp, mismatch with/without expected fingerprint, extraction failure, nonzero/empty OpenSSL output, generic unsigned packaging." + } + ], + "regression_evidence_review": { + "workflow_before": "regression-workflow-before.log", + "workflow_before_observed": "Old literal block reached verifier without a signed-DMG marker and failed order/fail-closed assertions.", + "verifier_before": "regression-verifier-before.log", + "verifier_before_observed": "Old actual verifier accepted unsigned/ad-hoc/untimestamped/mismatched images and failed the new negative assertions.", + "after_logs": [ + "regression-workflow-after.log", + "regression-verifier-after.log" + ], + "baseline_limit": "Before-verifier log contains three test methods; the final four-method suite additionally covers generic behavior and newer parser negatives. Core original regression failures are directly evidenced." + }, + "ci_integration": "scripts/ci-basic-checks.sh already executes python3 -m unittest discover -s scripts/tests and the shell contract test. The new test is included without adding another runner.", + "remaining_evidence_gates": [ + "Real versioned release-style app/DMG build and actual native verifier positive/unsigned/no-secure-timestamp cases.", + "Independent inspection of native certificate/timestamp metadata and task-owned mount cleanup.", + "Complete Swift/native test identity coverage with build inputs and frozen bundle integrity verified.", + "Required SDLC/basic checks, human verification acceptance and concrete PR review route.", + "Protected merge, fresh exact-SHA CI and new run-specific production approval.", + "Real software notarization/Gatekeeper/published checksum and independent download evidence." + ], + "reviewer_mutations": { + "source_edits": false, + "remote_writes": false, + "credential_access": false, + "report_only": true + } +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-final-verification.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-final-verification.json new file mode 100644 index 00000000..9fa82483 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-final-verification.json @@ -0,0 +1,99 @@ +{ + "verifier": "/root/signing_verifier", + "verified_at_utc": "2026-10-16T03:35:06.638022+00:00", + "result": "passed_local_implementation_verification", + "human_verification_acceptance": false, + "branch": "codex/fix-developer-id-dmg-signing", + "reviewed_source_sha256": { + ".github/workflows/release-artifact.yml": "f9845ad9d4b7d35367d5cffa722b208f998f90a400ce3dffc44173d4449af73b", + "scripts/verify-release-artifact.sh": "e2ee26c5fc9c5b2cb122731a7d801f8ef91176733256f92cbd76cf1c3a1b735b", + "scripts/tests/test_release_workflow_contract.sh": "7ba76b3f1edd5ec01601f62b3a98c7571e5e244cd9ef730f55c0ae1dffe05c37", + "scripts/tests/test_release_artifact.py": "23004ea623723d5649fc211ca2efdd775d6b57930622afa65462ae3d69e9f995" + }, + "findings": [], + "completed_verification": { + "code_and_controlled_tool_regressions": "Prior independent focused checks passed; reviewed production/test file hashes remain unchanged. Old-code regression logs show the original missing-signature behavior failed the new controls.", + "native_actual_verifier": { + "independently_rerun": true, + "signed_with_expected": "passed", + "signed_without_expected": "passed", + "unsigned": "rejected at DMG signature is invalid", + "no_secure_timestamp": "rejected at DMG signature has no secure timestamp", + "app_and_dmg_certificate_sha256": "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", + "team": "G9L7H3T3D5", + "dmg_identifier": "com.opentype.voiceinput.dmg", + "secure_timestamp_present": true, + "app_hardened_runtime_present": true, + "fixture_hashes_unchanged": true, + "fixture_files_hashed": 44, + "dmg_sha256": "24765f7ce54b07cb7b1c9427d8e67cdbcf9df270e8011bb8d82e7e2049a89101", + "own_mounts_remaining": [], + "probe_directory": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx", + "report": "native-independent-rerun.json" + }, + "native_mismatch_boundary": "Actual verifier controlled-tool fixtures cover mismatch including no expected-fingerprint option. No second real Developer ID identity is claimed.", + "shared_yaml_native_signing": "Recorded signing fixture block is byte-for-byte identical to current actual YAML literal block. Verifier did not re-sign or access private keys.", + "release_style_build": { + "exit": 0, + "python": "Python 3.14.6", + "lockfile_unchanged": true, + "artifact_verification_log_present": true + }, + "full_suite": { + "build_inputs_unchanged": 767, + "bundles": 14, + "xctest_executed": 1143, + "xctest_non_skipped_passed": 1126, + "xctest_skipped": 17, + "failures": 0, + "unique_swift_testing_passed": 1, + "empty_swift_testing_exit69": 13, + "all_discovered_identity_sets_completed": true, + "frozen_files_hashes_unchanged": 300, + "runtime_preflight_canary_records_pass": true, + "runtime_policy_hash_matches": true, + "report": "native-suite-independent-review.json" + }, + "required_local_checks": { + "fresh_sdlc_checks_exit": 0, + "fresh_git_diff_check_exit": 0, + "basic_check_success_log_verified": true, + "protected_swift_test_wrapper": "Setup failure before tests is preserved; this command is not marked passed." + }, + "first_validation_failures_preserved": [ + "Python3.9 basic-check failure, corrected to installed Python3.14 without production source changes.", + "First local build stopped for same Python PATH correction; prior log and result preserved.", + "Runtime-canary witness parser corrected before full suite; sensitive runtime policy unchanged." + ] + }, + "integrity": { + "package_resolved_sha256": "3a007c520b8b69aa9a675a42675662d7d272e4808dd3e71e4f12e074150219ad", + "failed_v0053_tag_object_unchanged": "b8e869cddca904cd525ece4fcb36d55fd4a14a33", + "source_and_fixture_files_modified_by_verifier": false, + "private_key_access_by_verifier": false, + "signing_by_verifier": false, + "app_launch_by_verifier": false, + "remote_operations_by_verifier": false + }, + "rollback_review": "Scoped correction can be reverted through a reviewed PR. Preserve credentials, protections, failed tags, first-failure evidence and prior public assets. No new published artifact exists in this local correction stage.", + "remaining_gates": [ + "Update verification.md from its in-progress draft to the completed evidence and pending human acceptance before handoff.", + "Human verification acceptance before remote PR stage.", + "Concrete PR plus eligible independent/code-owner approving route under protected main; no approval bypass or collaborator change is authorized by this review.", + "Fresh CI swift test and SDLC Gate on exact PR/merged candidate.", + "New unused stable version without moving failed v0.0.53.", + "Run-specific human production decision.", + "Real Apple software notarization acceptance, staple, both Gatekeeper assessments, mounted app equality, published checksum and independent asset download verification." + ], + "release_claim_limit": "Local signed DMG and actual verifier smoke are proven. No new Apple submission, public release or Gatekeeper notarization acceptance is claimed by this review.", + "evidence_files": [ + "implementation-code-review.json", + "native-independent-rerun.json", + "native-suite-independent-review.json", + "native-dmg-verification.json", + "local-release-build.json", + "protected-swift-test.json", + "full-test-evidence.json" + ], + "git_status_snapshot": " M .github/workflows/release-artifact.yml\n M scripts/tests/test_release_workflow_contract.sh\n M scripts/verify-release-artifact.sh\n?? docs/sdlc/changes/2026-10-15-developer-id-ci/\n?? docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/\n?? scripts/tests/test_release_artifact.py\n" +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-build-attempt-1-environment-correction.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-build-attempt-1-environment-correction.json new file mode 100644 index 00000000..aa9ab6b4 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-build-attempt-1-environment-correction.json @@ -0,0 +1,7 @@ +{ + "build_processes_stopped": [ + 1935 + ], + "reason": "Validation launcher PATH chose system Python 3.9.6; build requires Python 3.10+. Restart with installed Homebrew Python 3.14.6 first in minimal PATH.", + "production_source_changed": false +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-build-process.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-build-process.json new file mode 100644 index 00000000..d1af02c0 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-build-process.json @@ -0,0 +1 @@ +{"pid": 12422, "python": "Python 3.14.6", "start": "2026-10-16T03:02:25.343116+00:00"} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-checks-summary.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-checks-summary.json new file mode 100644 index 00000000..d4d6abfb --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-checks-summary.json @@ -0,0 +1,52 @@ +{ + "recorded_at_utc": "2026-10-16T03:34:39.955281+00:00", + "source_sha256": { + ".github/workflows/release-artifact.yml": "f9845ad9d4b7d35367d5cffa722b208f998f90a400ce3dffc44173d4449af73b", + "scripts/verify-release-artifact.sh": "e2ee26c5fc9c5b2cb122731a7d801f8ef91176733256f92cbd76cf1c3a1b735b", + "scripts/tests/test_release_workflow_contract.sh": "7ba76b3f1edd5ec01601f62b3a98c7571e5e244cd9ef730f55c0ae1dffe05c37", + "scripts/tests/test_release_artifact.py": "23004ea623723d5649fc211ca2efdd775d6b57930622afa65462ae3d69e9f995" + }, + "syntax": { + "workflow_yaml": "Ruby YAML.parse_file passed", + "shell": "bash -n passed for verifier, contract harness, and extracted shared workflow block" + }, + "basic_checks": { + "result": "pass", + "python": "3.14.6", + "log_sha256": "9abda60c70729ffcc3d95107783ba5b23ca5f3e695a260697c0c3a82e20923e8" + }, + "swift": { + "native_evidence": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/native-run-f8535155", + "xctest_bundles": 14, + "xctest_executed": 1143, + "xctest_skipped": 17, + "xctest_failures": 0, + "unique_swift_testing_cases": 1, + "swift_testing_failures": 0, + "expected_empty_swift_testing_bundles": 13, + "complete": true, + "frozen_bundle_files_unchanged": 300, + "runtime_preflight": "native-suite-preflight.json", + "standard_swift_test": "Separate protected-wrapper result; not inferred from native engines." + }, + "protected_wrapper": { + "command": [ + "/usr/bin/sandbox-exec", + "-f", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/test-runtime-narrow.sb", + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift", + "test", + "--skip-build", + "--skip-update", + "--disable-automatic-resolution" + ], + "exit": 1, + "nested_sandbox_setup_failure": true, + "lockfile_unchanged": true, + "native_full_suite_evidence": "full-test-evidence.json" + }, + "native_dmg_result": true, + "package_resolved_sha256": "3a007c520b8b69aa9a675a42675662d7d272e4808dd3e71e4f12e074150219ad", + "remote_source_writes_performed": false, + "new_release_created": false +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.json new file mode 100644 index 00000000..061bdbbe --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.json @@ -0,0 +1,15 @@ +{ + "command": [ + "bash", + "scripts/build-app.sh", + "--version=0.0.54", + "--sign=0A1A804E9C5D7BE644E4A6B884487BB5191F691D" + ], + "started_at_utc": "2026-10-16T02:56:05.744193+00:00", + "finished_at_utc": "2026-10-16T03:01:57.210079+00:00", + "exit": -15, + "guard_failure": null, + "lockfile_unchanged": true, + "log": "/Users/chenli/projects/utter/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log", + "disk_free_bytes": 21671313408 +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.log new file mode 100644 index 00000000..38b21859 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.log @@ -0,0 +1,127 @@ + +▶ Building Utter (Release, arm64)… +2026-10-16 10:59:54.747 xcodebuild[1954:7813064] [MT] IDERunDestination: Supported platforms for the buildables in the current scheme is empty. +--- xcodebuild: WARNING: Using the first of multiple matching destinations: +{ platform:macOS, arch:arm64, id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:x86_64, id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:arm64, variant:Mac Catalyst, id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:x86_64, variant:Mac Catalyst, id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:arm64, variant:DriverKit, id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:arm64, variant:Designed for [iPad,iPhone], id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:arm64e.x1, variant:Designed for [iPad,iPhone], id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:arm64_32, variant:Designed for [iPad,iPhone], id:00008132-001828593639001C, name:My Mac } +In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/steel_attention.metal:6: +In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:3: +In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/attn.h:6: +In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/../../steel/attn/mma.h:11: +/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/../../steel/utils/integral_constant.h:108:6: warning: constexpr if is a C++17 extension [-Wc++17-extensions] + if constexpr (start < stop) { + ^ +In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/steel_attention.metal:6: +/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:356:16: warning: constexpr if is a C++17 extension [-Wc++17-extensions] + if constexpr (is_bool) { + ^ +/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:426:14: warning: constexpr if is a C++17 extension [-Wc++17-extensions] + if constexpr (BD == 128) { + ^ +/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:436:14: warning: constexpr if is a C++17 extension [-Wc++17-extensions] + if constexpr (BD == 128) { + ^ +4 warnings generated. +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Benchmark.swift:29:53: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +27 | } +28 | return try await withLocalModelAccess { +29 | let provider = try await self.providers.create(id: "generation.mlx", request: .benchmark) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +30 | return try await ModelBenchmarkSuite.run(workloads: workloads, provider: provider) +31 | } + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+FactSupport.swift:29:34: warning: reference to captured var 'checkOptions' in concurrently-executing code; this is an error in the Swift 6 language mode [#SendableClosureCaptures] +27 | try await withOperationDeadline(for: ProcessingDeadlines.factSupport) { +28 | try await self.generateText(prompt: prompt, systemPrompt: PromptCatalog.factSupportSystemPrompt, +29 | options: checkOptions, maxTokens: 768, temperature: 0) + | `- warning: reference to captured var 'checkOptions' in concurrently-executing code; this is an error in the Swift 6 language mode [#SendableClosureCaptures] +30 | } +31 | } + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:60:43: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] + 58 | maxTokens: maxTokens, temperature: temperature + 59 | ) + 60 | let primary = try await providers.create(id: providerID, request: .inference) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] + 61 | try Task.checkCancellation() + 62 | guard usesANE else { + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:81:65: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] + 79 | prepareForMLXFallback: { await primary.unload() }, + 80 | mlx: { + 81 | let fallback = try await self.providers.create(id: options.fallbackProviderID, request: .inference) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] + 82 | try Task.checkCancellation() + 83 | return try await ProcessingObservations.$generationStage.withValue(.fallback) { + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:128:49: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +126 | ) +127 | guard let imageProviders else { throw GenerationServiceError.unsupportedOperation } +128 | let provider = try await imageProviders.create(id: providerID, request: .inference) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +129 | try Task.checkCancellation() +130 | let result = try await ProcessingObservations.$generationStage.withValue(.image) { + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+ModelPreparation.swift:11:52: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] + 9 | maxTokens: 1, temperature: 0, usesANE: usesANE) +10 | return try await withLocalModelAccess { +11 | let primary = try await self.providers.create(id: id, request: .inference) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +12 | guard usesANE else { try await primary.prepare(request); return nil } +13 | let result = try await GenerationFallback.run(fallbackEnabled: options.fallbackToMLXOnEspressoFailure, + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+ModelPreparation.swift:16:61: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +14 | espresso: { try await primary.prepare(request) }, prepareForMLXFallback: { await primary.unload() }, +15 | mlx: { +16 | let fallback = try await self.providers.create(id: options.fallbackProviderID, request: .inference) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +17 | let request = self.generationRequest(prompt: "", systemPrompt: nil, options: options, maxTokens: 1, temperature: 0) +18 | try await fallback.prepare(request) + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Models.swift:37:42: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +35 | try await withLocalModelAccess { +36 | for descriptor in await self.providers.descriptors { +37 | try await self.providers.reset(id: descriptor.id) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +38 | } +39 | if let images = self.imageProviders { + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Models.swift:40:79: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +38 | } +39 | if let images = self.imageProviders { +40 | for descriptor in await images.descriptors { try await images.reset(id: descriptor.id) } + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +41 | } +42 | } + +[#IsolatedConformances]: +[#SendableClosureCaptures]: +/Users/chenli/projects/utter/Sources/UtterMacServices/CorrectionCaptureRegion.swift:75:5: warning: 'package' modifier conflicts with extension's default access of 'private' +73 | } +74 | private extension CorrectionCaptureRegionLocator { +75 | package func nearbyRange( + | `- warning: 'package' modifier conflicts with extension's default access of 'private' +76 | of needle: String, +77 | in text: NSString, +/Users/chenli/projects/utter/Sources/UtterIngress/Native/IntegrationXPCServer.swift:97:61: warning: variable 'handler' was written to, but never read + 95 | connection.exportedInterface = NSXPCInterface(with: OpenTypeXPCProtocol.self) + 96 | connection.exportedObject = handler + 97 | connection.invalidationHandler = { [weak self, weak handler] in + | `- warning: variable 'handler' was written to, but never read + 98 | Task { @MainActor in + 99 | self?.retire(id) + +/Users/chenli/projects/utter/Sources/UtterIngress/Native/IntegrationXPCServer.swift:102:61: warning: variable 'handler' was written to, but never read +100 | } +101 | } +102 | connection.interruptionHandler = { [weak self, weak handler] in + | `- warning: variable 'handler' was written to, but never read +103 | Task { @MainActor in +104 | self?.retire(id) +** BUILD INTERRUPTED ** diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.json new file mode 100644 index 00000000..df9423c6 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.json @@ -0,0 +1,16 @@ +{ + "command": [ + "bash", + "scripts/build-app.sh", + "--version=0.0.54", + "--sign=0A1A804E9C5D7BE644E4A6B884487BB5191F691D" + ], + "python": "Python 3.14.6", + "started_at_utc": "2026-10-16T03:02:25.343116+00:00", + "finished_at_utc": "2026-10-16T03:07:25.910963+00:00", + "exit": 0, + "guard_failure": null, + "lockfile_unchanged": true, + "log": "/Users/chenli/projects/utter/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log", + "disk_free_bytes": 19542142976 +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log new file mode 100644 index 00000000..6647c89d --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log @@ -0,0 +1,195 @@ + +▶ Building Utter (Release, arm64)… +2026-10-16 11:02:33.762 xcodebuild[12441:7852556] [MT] IDERunDestination: Supported platforms for the buildables in the current scheme is empty. +--- xcodebuild: WARNING: Using the first of multiple matching destinations: +{ platform:macOS, arch:arm64, id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:x86_64, id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:arm64, variant:Mac Catalyst, id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:x86_64, variant:Mac Catalyst, id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:arm64, variant:DriverKit, id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:arm64, variant:Designed for [iPad,iPhone], id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:arm64e.x1, variant:Designed for [iPad,iPhone], id:00008132-001828593639001C, name:My Mac } +{ platform:macOS, arch:arm64_32, variant:Designed for [iPad,iPhone], id:00008132-001828593639001C, name:My Mac } +In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/steel_attention.metal:6: +In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:3: +In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/attn.h:6: +In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/../../steel/attn/mma.h:11: +/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/../../steel/utils/integral_constant.h:108:6: warning: constexpr if is a C++17 extension [-Wc++17-extensions] + if constexpr (start < stop) { + ^ +In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/steel_attention.metal:6: +/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:356:16: warning: constexpr if is a C++17 extension [-Wc++17-extensions] + if constexpr (is_bool) { + ^ +/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:426:14: warning: constexpr if is a C++17 extension [-Wc++17-extensions] + if constexpr (BD == 128) { + ^ +/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:436:14: warning: constexpr if is a C++17 extension [-Wc++17-extensions] + if constexpr (BD == 128) { + ^ +4 warnings generated. +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Benchmark.swift:29:53: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +27 | } +28 | return try await withLocalModelAccess { +29 | let provider = try await self.providers.create(id: "generation.mlx", request: .benchmark) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +30 | return try await ModelBenchmarkSuite.run(workloads: workloads, provider: provider) +31 | } + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+FactSupport.swift:29:34: warning: reference to captured var 'checkOptions' in concurrently-executing code; this is an error in the Swift 6 language mode [#SendableClosureCaptures] +27 | try await withOperationDeadline(for: ProcessingDeadlines.factSupport) { +28 | try await self.generateText(prompt: prompt, systemPrompt: PromptCatalog.factSupportSystemPrompt, +29 | options: checkOptions, maxTokens: 768, temperature: 0) + | `- warning: reference to captured var 'checkOptions' in concurrently-executing code; this is an error in the Swift 6 language mode [#SendableClosureCaptures] +30 | } +31 | } + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:60:43: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] + 58 | maxTokens: maxTokens, temperature: temperature + 59 | ) + 60 | let primary = try await providers.create(id: providerID, request: .inference) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] + 61 | try Task.checkCancellation() + 62 | guard usesANE else { + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:81:65: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] + 79 | prepareForMLXFallback: { await primary.unload() }, + 80 | mlx: { + 81 | let fallback = try await self.providers.create(id: options.fallbackProviderID, request: .inference) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] + 82 | try Task.checkCancellation() + 83 | return try await ProcessingObservations.$generationStage.withValue(.fallback) { + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:128:49: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +126 | ) +127 | guard let imageProviders else { throw GenerationServiceError.unsupportedOperation } +128 | let provider = try await imageProviders.create(id: providerID, request: .inference) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +129 | try Task.checkCancellation() +130 | let result = try await ProcessingObservations.$generationStage.withValue(.image) { + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+ModelPreparation.swift:11:52: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] + 9 | maxTokens: 1, temperature: 0, usesANE: usesANE) +10 | return try await withLocalModelAccess { +11 | let primary = try await self.providers.create(id: id, request: .inference) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +12 | guard usesANE else { try await primary.prepare(request); return nil } +13 | let result = try await GenerationFallback.run(fallbackEnabled: options.fallbackToMLXOnEspressoFailure, + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+ModelPreparation.swift:16:61: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +14 | espresso: { try await primary.prepare(request) }, prepareForMLXFallback: { await primary.unload() }, +15 | mlx: { +16 | let fallback = try await self.providers.create(id: options.fallbackProviderID, request: .inference) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +17 | let request = self.generationRequest(prompt: "", systemPrompt: nil, options: options, maxTokens: 1, temperature: 0) +18 | try await fallback.prepare(request) + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Models.swift:37:42: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +35 | try await withLocalModelAccess { +36 | for descriptor in await self.providers.descriptors { +37 | try await self.providers.reset(id: descriptor.id) + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +38 | } +39 | if let images = self.imageProviders { + +/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Models.swift:40:79: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +38 | } +39 | if let images = self.imageProviders { +40 | for descriptor in await images.descriptors { try await images.reset(id: descriptor.id) } + | `- warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +41 | } +42 | } + +[#IsolatedConformances]: +[#SendableClosureCaptures]: +/Users/chenli/projects/utter/Sources/UtterMacServices/CorrectionCaptureRegion.swift:75:5: warning: 'package' modifier conflicts with extension's default access of 'private' +73 | } +74 | private extension CorrectionCaptureRegionLocator { +75 | package func nearbyRange( + | `- warning: 'package' modifier conflicts with extension's default access of 'private' +76 | of needle: String, +77 | in text: NSString, +/Users/chenli/projects/utter/Sources/UtterIngress/Native/IntegrationXPCServer.swift:97:61: warning: variable 'handler' was written to, but never read + 95 | connection.exportedInterface = NSXPCInterface(with: OpenTypeXPCProtocol.self) + 96 | connection.exportedObject = handler + 97 | connection.invalidationHandler = { [weak self, weak handler] in + | `- warning: variable 'handler' was written to, but never read + 98 | Task { @MainActor in + 99 | self?.retire(id) + +/Users/chenli/projects/utter/Sources/UtterIngress/Native/IntegrationXPCServer.swift:102:61: warning: variable 'handler' was written to, but never read +100 | } +101 | } +102 | connection.interruptionHandler = { [weak self, weak handler] in + | `- warning: variable 'handler' was written to, but never read +103 | Task { @MainActor in +104 | self?.retire(id) +error: the following command failed with exit code 0 but produced no further output +SwiftCompile normal arm64 (in target 'UtterModels' from project 'OpenType') +/Users/chenli/projects/utter/Sources/UtterModels/Native/DownloadStallWatchdog.swift:24:59: warning: reference to property 'pollInterval' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode +22 | pollTask = Task { @MainActor [weak self] in +23 | while !Task.isCancelled { +24 | try? await Task.sleep(nanoseconds: UInt64(pollInterval * 1_000_000_000)) + | `- warning: reference to property 'pollInterval' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode +25 | guard let self, !Task.isCancelled else { return } +26 | guard Date().timeIntervalSince(self.lastActivity) >= self.timeout else { continue } + ✓ Build succeeded + +▶ Building Utter CLI helper (Release, arm64)… +Building for production... +[Planning deferred tasks] +[8 / 13] +[9 / 14] OpenTypeCLI-product +[21 / 77] +[31 / 77] +[34 / 77] +[40 / 77] +[43 / 77] +[50 / 77] +[52 / 77] +[55 / 77] +[56 / 77] +[67 / 77] +[68 / 77] +[72 / 77] +[73 / 77] OpenTypeCLI-product +[75 / 77] OpenTypeCLI-product +Build complete! (6.45秒) + ✓ CLI helper built + +▶ Assembling Utter.app… + ✓ App bundle assembled + +▶ Building AppIcon asset catalog (system appearances)… + ✓ AppIcon compiled to Assets.car (system appearances) + +▶ Code signing (hardened runtime + entitlements)… +/Users/chenli/projects/utter/dist/Utter.app: replacing existing signature + ✓ Signed with: 0A1A804E9C5D7BE644E4A6B884487BB5191F691D (hardened runtime) + +▶ Creating DMG… +DMG background -> /Users/chenli/projects/utter/.build/xcode/dmg-background/installer-background.png +DMG background -> /Users/chenli/projects/utter/.build/xcode/dmg-background/installer-background@2x.png +hdiutil: WARNING: 'hdiutil create -volname -size ...' is deprecated. Please use 'diskutil image create from/blank --volumeName -size ...' instead. +hdiutil: WARNING: 'hdiutil attach -nobrowse -owners ...' is deprecated. Please use 'diskutil image attach --mountOptions nobrowse --mountOptions owners ...' instead. +hdiutil: WARNING: 'hdiutil convert -format ...' is deprecated. Please use 'diskutil image create from --format ...' instead. + ✓ DMG created +Owned resources passed. +--prepared:/Users/chenli/projects/utter/dist/Utter.app/Contents/MacOS/opentype-cli +--validated:/Users/chenli/projects/utter/dist/Utter.app/Contents/MacOS/opentype-cli +/Users/chenli/projects/utter/dist/Utter.app: valid on disk +/Users/chenli/projects/utter/dist/Utter.app: satisfies its Designated Requirement +hdiutil: verify: checksum of "/Users/chenli/projects/utter/dist/Utter-0.0.54.dmg" is VALID +Owned resources passed. +--prepared:/private/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.XqYxwSowRo/Utter.app/Contents/MacOS/opentype-cli +--validated:/private/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.XqYxwSowRo/Utter.app/Contents/MacOS/opentype-cli +/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.XqYxwSowRo/Utter.app: valid on disk +/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.XqYxwSowRo/Utter.app: satisfies its Designated Requirement +Release artifact verification passed. + +═══════════════════════════════════════════════════ + App: /Users/chenli/projects/utter/dist/Utter.app + DMG: /Users/chenli/projects/utter/dist/Utter-0.0.54.dmg + + To install: open /Users/chenli/projects/utter/dist/Utter-0.0.54.dmg +═══════════════════════════════════════════════════ diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/merge-prerequisites.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/merge-prerequisites.json new file mode 100644 index 00000000..6f486ec1 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/merge-prerequisites.json @@ -0,0 +1,27 @@ +{ + "read_at_utc": "2026-10-15T17:38:08.510898+00:00", + "collaborators": [ + { + "login": "IchenDEV", + "role_name": "admin" + } + ], + "sensitive_path_codeowners": "IchenDEV", + "ruleset_enforcement": "active", + "bypass_actors": [], + "pull_request_rule": { + "required_approving_review_count": 1, + "dismiss_stale_reviews_on_push": true, + "required_reviewers": [], + "require_code_owner_review": true, + "require_last_push_approval": true, + "required_review_thread_resolution": true, + "require_extra_approval_for_unattributed_changes": true, + "allowed_merge_methods": [ + "merge", + "squash", + "rebase" + ] + }, + "required_future_gate": "Before merge, the concrete PR needs an eligible human approval path. This design does not modify governance." +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-progress.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-progress.json new file mode 100644 index 00000000..dfea2588 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-progress.json @@ -0,0 +1,117 @@ +{ + "native_directory": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b", + "results": [ + { + "name": "unsigned-rejected", + "command": [ + "bash", + "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "--app", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "--version", + "0.0.54", + "--require-developer-id", + "--expected-cert-sha256", + "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", + "--dmg", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/unsigned.dmg" + ], + "exit": 1, + "expected_exit": 1, + "diagnostic": "DMG signature is invalid", + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/unsigned-rejected.log" + }, + { + "name": "sign-without-timestamp", + "command": [ + "/usr/bin/codesign", + "--force", + "--sign", + "Developer ID Application: Chen Li (G9L7H3T3D5)", + "--timestamp=none", + "--identifier", + "com.opentype.voiceinput.dmg", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" + ], + "exit": 0, + "expected_exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/sign-without-timestamp.log" + }, + { + "name": "untimestamped-rejected", + "command": [ + "bash", + "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "--app", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "--version", + "0.0.54", + "--require-developer-id", + "--expected-cert-sha256", + "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", + "--dmg", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" + ], + "exit": 1, + "expected_exit": 1, + "diagnostic": "DMG signature has no secure timestamp", + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/untimestamped-rejected.log" + }, + { + "name": "actual-shared-signing-block", + "command": [ + "bash", + "-e", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/shared-signing-block.sh" + ], + "exit": 0, + "expected_exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/actual-shared-signing-block.log" + }, + { + "name": "matching-without-expected", + "command": [ + "bash", + "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "--app", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "--dmg", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg", + "--version", + "0.0.54", + "--require-developer-id" + ], + "exit": 0, + "expected_exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/matching-without-expected.log" + }, + { + "name": "dmg-signature-metadata", + "command": [ + "/usr/bin/codesign", + "-dvvv", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + ], + "exit": 0, + "expected_exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dmg-signature-metadata.log" + }, + { + "name": "extract-native-dmg-certificate", + "command": [ + "/usr/bin/codesign", + "-d", + "--extract-certificates=/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dmg-cert-", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + ], + "exit": 0, + "expected_exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/extract-native-dmg-certificate.log" + } + ] +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-verification.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-verification.json new file mode 100644 index 00000000..4246062a --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-verification.json @@ -0,0 +1,132 @@ +{ + "verified_at_utc": "2026-10-16T03:30:17.184449+00:00", + "native_directory": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b", + "app": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "signed_dmg": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg", + "unsigned_dmg": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/unsigned.dmg", + "untimestamped_dmg": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg", + "certificate_sha256": "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", + "identity": "Developer ID Application: Chen Li (G9L7H3T3D5)", + "team": "G9L7H3T3D5", + "dmg_sha256": "24765f7ce54b07cb7b1c9427d8e67cdbcf9df270e8011bb8d82e7e2049a89101", + "actual_shared_workflow_block_sha256": "c1ca7730b16cd04fcd44379832f4bb5d1bd66a2d71b258c5d90e9de68455df79", + "results": [ + { + "name": "unsigned-rejected", + "command": [ + "bash", + "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "--app", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "--version", + "0.0.54", + "--require-developer-id", + "--expected-cert-sha256", + "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", + "--dmg", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/unsigned.dmg" + ], + "exit": 1, + "expected_exit": 1, + "diagnostic": "DMG signature is invalid", + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/unsigned-rejected.log" + }, + { + "name": "sign-without-timestamp", + "command": [ + "/usr/bin/codesign", + "--force", + "--sign", + "Developer ID Application: Chen Li (G9L7H3T3D5)", + "--timestamp=none", + "--identifier", + "com.opentype.voiceinput.dmg", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" + ], + "exit": 0, + "expected_exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/sign-without-timestamp.log" + }, + { + "name": "untimestamped-rejected", + "command": [ + "bash", + "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "--app", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "--version", + "0.0.54", + "--require-developer-id", + "--expected-cert-sha256", + "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", + "--dmg", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" + ], + "exit": 1, + "expected_exit": 1, + "diagnostic": "DMG signature has no secure timestamp", + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/untimestamped-rejected.log" + }, + { + "name": "actual-shared-signing-block", + "command": [ + "bash", + "-e", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/shared-signing-block.sh" + ], + "exit": 0, + "expected_exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/actual-shared-signing-block.log" + }, + { + "name": "matching-without-expected", + "command": [ + "bash", + "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "--app", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "--dmg", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg", + "--version", + "0.0.54", + "--require-developer-id" + ], + "exit": 0, + "expected_exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/matching-without-expected.log" + }, + { + "name": "dmg-signature-metadata", + "command": [ + "/usr/bin/codesign", + "-dvvv", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + ], + "exit": 0, + "expected_exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dmg-signature-metadata.log" + }, + { + "name": "extract-native-dmg-certificate", + "command": [ + "/usr/bin/codesign", + "-d", + "--extract-certificates=/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dmg-cert-", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + ], + "exit": 0, + "expected_exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/extract-native-dmg-certificate.log" + } + ], + "task_mounts_remaining": [], + "certificate_mismatch_coverage": "Controlled-tool actual verifier fixture; no second native Developer ID identity claimed.", + "notarization_performed": false, + "published": false, + "success": true +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-independent-rerun.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-independent-rerun.json new file mode 100644 index 00000000..d3742944 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-independent-rerun.json @@ -0,0 +1,141 @@ +{ + "verifier": "/root/signing_verifier", + "verified_at_utc": "2026-10-16T03:32:07.445817+00:00", + "success": true, + "directory": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx", + "results": [ + { + "name": "signed-with-expected", + "command": [ + "bash", + "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "--app", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "--version", + "0.0.54", + "--require-developer-id", + "--expected-cert-sha256", + "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", + "--dmg", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + ], + "exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/signed-with-expected.log" + }, + { + "name": "signed-without-expected", + "command": [ + "bash", + "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "--app", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "--version", + "0.0.54", + "--require-developer-id", + "--dmg", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + ], + "exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/signed-without-expected.log" + }, + { + "name": "unsigned-rejected", + "command": [ + "bash", + "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "--app", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "--version", + "0.0.54", + "--require-developer-id", + "--expected-cert-sha256", + "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", + "--dmg", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/unsigned.dmg" + ], + "exit": 1, + "diagnostic": "DMG signature is invalid", + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/unsigned-rejected.log" + }, + { + "name": "untimestamped-rejected", + "command": [ + "bash", + "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "--app", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "--version", + "0.0.54", + "--require-developer-id", + "--expected-cert-sha256", + "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", + "--dmg", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" + ], + "exit": 1, + "diagnostic": "DMG signature has no secure timestamp", + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/untimestamped-rejected.log" + }, + { + "name": "dmg-display", + "command": [ + "/usr/bin/codesign", + "-dvvv", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + ], + "exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/dmg-display.log" + }, + { + "name": "app-display", + "command": [ + "/usr/bin/codesign", + "-dvvv", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app" + ], + "exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/app-display.log" + }, + { + "name": "dmg-extract-certificate", + "command": [ + "/usr/bin/codesign", + "-d", + "--extract-certificates=/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/dmg-cert-", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + ], + "exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/dmg-extract-certificate.log" + }, + { + "name": "app-extract-certificate", + "command": [ + "/usr/bin/codesign", + "-d", + "--extract-certificates=/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/app-cert-", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app" + ], + "exit": 0, + "diagnostic": null, + "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/app-extract-certificate.log" + } + ], + "fixture_file_hashes_unchanged": true, + "fixture_files_hashed": 44, + "fixture_dmg_sha256": "24765f7ce54b07cb7b1c9427d8e67cdbcf9df270e8011bb8d82e7e2049a89101", + "fingerprints": { + "dmg": "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", + "app": "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112" + }, + "own_mounts_remaining": [], + "failures": [], + "private_key_access": false, + "signing_performed": false, + "app_launched": false, + "notarization_submitted": false +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-independent-review.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-independent-review.json new file mode 100644 index 00000000..c0dc05ff --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-independent-review.json @@ -0,0 +1,110 @@ +{ + "verifier": "/root/signing_verifier", + "verified_at_utc": "2026-10-16T03:34:01.553051+00:00", + "result": "passed", + "build_inputs_checked": 767, + "build_inputs_unchanged": true, + "reviewed_source_hashes_unchanged": true, + "package_resolved_sha256": "3a007c520b8b69aa9a675a42675662d7d272e4808dd3e71e4f12e074150219ad", + "test_bundle_files_unchanged": 300, + "bundle_coverage": [ + { + "bundle": "OpenTypeTests.xctest", + "completed_discovered_unique_cases": 499, + "skipped": 17, + "failures": 0 + }, + { + "bundle": "UtterAudioTests.xctest", + "completed_discovered_unique_cases": 20, + "skipped": 0, + "failures": 0 + }, + { + "bundle": "UtterBuiltinsTests.xctest", + "completed_discovered_unique_cases": 2, + "skipped": 0, + "failures": 0 + }, + { + "bundle": "UtterContractsTests.xctest", + "completed_discovered_unique_cases": 123, + "skipped": 0, + "failures": 0 + }, + { + "bundle": "UtterDataTests.xctest", + "completed_discovered_unique_cases": 58, + "skipped": 0, + "failures": 0 + }, + { + "bundle": "UtterEvaluationTests.xctest", + "completed_discovered_unique_cases": 7, + "skipped": 0, + "failures": 0 + }, + { + "bundle": "UtterIngressTests.xctest", + "completed_discovered_unique_cases": 12, + "skipped": 0, + "failures": 0 + }, + { + "bundle": "UtterMacServicesTests.xctest", + "completed_discovered_unique_cases": 54, + "skipped": 0, + "failures": 0 + }, + { + "bundle": "UtterModelsTests.xctest", + "completed_discovered_unique_cases": 34, + "skipped": 0, + "failures": 0 + }, + { + "bundle": "UtterProcessingTests.xctest", + "completed_discovered_unique_cases": 107, + "skipped": 0, + "failures": 0 + }, + { + "bundle": "UtterRemoteInferenceTests.xctest", + "completed_discovered_unique_cases": 89, + "skipped": 0, + "failures": 0 + }, + { + "bundle": "UtterRemoteMicTests.xctest", + "completed_discovered_unique_cases": 54, + "skipped": 0, + "failures": 0 + }, + { + "bundle": "UtterRuntimeTests.xctest", + "completed_discovered_unique_cases": 26, + "skipped": 0, + "failures": 0 + }, + { + "bundle": "UtterSessionTests.xctest", + "completed_discovered_unique_cases": 58, + "skipped": 0, + "failures": 0 + } + ], + "xctest": 1143, + "skipped": 17, + "non_skipped_passed": 1126, + "failures": 0, + "unique_swift_testing_passed": 1, + "expected_empty_swift_testing_invocations": 13, + "native_run": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/native-run-f8535155", + "runtime_preflight_canaries_verified_from_record": true, + "runtime_policy_hash_verified": true, + "protected_swift_test": "Setup failure retained, not passed.", + "native_signing_block_matches_current_literal_yaml": true, + "native_signing_block_sha256": "c1ca7730b16cd04fcd44379832f4bb5d1bd66a2d71b258c5d90e9de68455df79", + "private_credentials_accessed": false, + "test_binaries_rerun_by_verifier": false +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-preflight.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-preflight.json new file mode 100644 index 00000000..98400e00 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-preflight.json @@ -0,0 +1,17 @@ +{ + "swift_resource_package_inputs_match_f0ef2aa": true, + "frozen_bundle_files_match": 300, + "runtime_policy_sha256": "1c3ccabadb90565b1ddf23d4de039713845ba7d0f32970fa043456b8acdbcf67", + "canaries": { + "preferences-canary": { + "exit": 0, + "stdout": "false\n/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/test-home" + }, + "private-path-canary": { + "exit": 0, + "stdout": "errno=1" + } + }, + "production_probe_file_absent_before_after": true, + "preflight_parser_correction": "Initial witness parser expected JSON; canaries emit plain text. Corrected parser before running tests." +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-tests-run.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-tests-run.log new file mode 100644 index 00000000..fab8b15d --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-tests-run.log @@ -0,0 +1,43 @@ +NATIVE_EVIDENCE_DIR=/private/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/native-run-f8535155 +OpenTypeTests xctest: exit=0, executed=499, failures=0, complete=True +OpenTypeTests swift-testing: exit=0, executed=1, failures=0, complete=True +UtterAudioTests xctest: exit=0, executed=20, failures=0, complete=True +UtterAudioTests swift-testing: exit=69, executed=0, failures=0, complete=True + +UtterBuiltinsTests xctest: exit=0, executed=2, failures=0, complete=True +UtterBuiltinsTests swift-testing: exit=69, executed=0, failures=0, complete=True + +UtterContractsTests xctest: exit=0, executed=123, failures=0, complete=True +UtterContractsTests swift-testing: exit=69, executed=0, failures=0, complete=True + +UtterDataTests xctest: exit=0, executed=58, failures=0, complete=True +UtterDataTests swift-testing: exit=69, executed=0, failures=0, complete=True + +UtterEvaluationTests xctest: exit=0, executed=7, failures=0, complete=True +UtterEvaluationTests swift-testing: exit=69, executed=0, failures=0, complete=True + +UtterIngressTests xctest: exit=0, executed=12, failures=0, complete=True +UtterIngressTests swift-testing: exit=69, executed=0, failures=0, complete=True + +UtterMacServicesTests xctest: exit=0, executed=54, failures=0, complete=True +UtterMacServicesTests swift-testing: exit=69, executed=0, failures=0, complete=True + +UtterModelsTests xctest: exit=0, executed=34, failures=0, complete=True +UtterModelsTests swift-testing: exit=69, executed=0, failures=0, complete=True + +UtterProcessingTests xctest: exit=0, executed=107, failures=0, complete=True +UtterProcessingTests swift-testing: exit=69, executed=0, failures=0, complete=True + +UtterRemoteInferenceTests xctest: exit=0, executed=89, failures=0, complete=True +UtterRemoteInferenceTests swift-testing: exit=69, executed=0, failures=0, complete=True + +UtterRemoteMicTests xctest: exit=0, executed=54, failures=0, complete=True +UtterRemoteMicTests swift-testing: exit=69, executed=0, failures=0, complete=True + +UtterRuntimeTests xctest: exit=0, executed=26, failures=0, complete=True +UtterRuntimeTests swift-testing: exit=69, executed=0, failures=0, complete=True + +UtterSessionTests xctest: exit=0, executed=58, failures=0, complete=True +UtterSessionTests swift-testing: exit=69, executed=0, failures=0, complete=True + +{"bundle_count": 14, "invocations": 28, "nonzero_exits": 13, "incomplete_invocations": 0, "total_xctest": 1143, "total_swift_testing": 1, "bundle_hashes_unchanged": true} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.json new file mode 100644 index 00000000..93839c11 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.json @@ -0,0 +1,16 @@ +{ + "command": [ + "/usr/bin/sandbox-exec", + "-f", + "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/test-runtime-narrow.sb", + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift", + "test", + "--skip-build", + "--skip-update", + "--disable-automatic-resolution" + ], + "exit": 1, + "nested_sandbox_setup_failure": true, + "lockfile_unchanged": true, + "native_full_suite_evidence": "full-test-evidence.json" +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.log new file mode 100644 index 00000000..0b15647d --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.log @@ -0,0 +1,5 @@ +warning: '--skip-update' option is deprecated and will be removed in a future release +error: 'utter': Invalid manifest (compiled with: ["/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", "-vfsoverlay", "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/test-home/tmp/TemporaryDirectory.03znRQ/vfs.yaml", "-L", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/ManifestAPI", "-lPackageDescription", "-Xlinker", "-rpath", "-Xlinker", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/ManifestAPI", "-target", "arm64-apple-macosx14.0", "-plugin-path", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/plugins/testing", "-sdk", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX27.0.sdk", "-F", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks", "-I", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib", "-L", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib", "-swift-version", "6", "-I", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/ManifestAPI", "-sdk", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX27.0.sdk", "-package-description-version", "6.2.0", "/Users/chenli/projects/utter/Package.swift", "-o", "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/test-home/tmp/TemporaryDirectory.31BUpi/utter-manifest"]) +sandbox-exec: sandbox_apply: Operation not permitted +error: ExitCode(rawValue: 1) +error: no tests found; create a target in the 'Tests' directory diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-after.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-after.log new file mode 100644 index 00000000..70808122 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-after.log @@ -0,0 +1,5 @@ +.... +---------------------------------------------------------------------- +Ran 4 tests in 10.774s + +OK diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before.log new file mode 100644 index 00000000..efa6e81f --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before.log @@ -0,0 +1,74 @@ +FFFFFF. +====================================================================== +FAIL: test_certificate_match_is_required_without_expected_fingerprint (test_release_artifact.ReleaseArtifactTests.test_certificate_match_is_required_without_expected_fingerprint) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py", line 125, in test_certificate_match_is_required_without_expected_fingerprint + self.assertNotEqual(result.returncode, 0) + ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^ +AssertionError: 0 == 0 + +====================================================================== +FAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='unsigned') +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py", line 118, in test_invalid_container_stops_before_mounting + self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) + ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +AssertionError: 0 == 0 : Owned resources passed. +Owned resources passed. +Release artifact verification passed. + + +====================================================================== +FAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='adhoc') +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py", line 118, in test_invalid_container_stops_before_mounting + self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) + ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +AssertionError: 0 == 0 : Owned resources passed. +Owned resources passed. +Release artifact verification passed. + + +====================================================================== +FAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='untimestamped') +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py", line 118, in test_invalid_container_stops_before_mounting + self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) + ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +AssertionError: 0 == 0 : Owned resources passed. +Owned resources passed. +Release artifact verification passed. + + +====================================================================== +FAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='mismatch') +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py", line 118, in test_invalid_container_stops_before_mounting + self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) + ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +AssertionError: 0 == 0 : Owned resources passed. +Owned resources passed. +Release artifact verification passed. + + +====================================================================== +FAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='extract-failure') +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py", line 118, in test_invalid_container_stops_before_mounting + self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) + ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +AssertionError: 0 == 0 : Owned resources passed. +Owned resources passed. +Release artifact verification passed. + + +---------------------------------------------------------------------- +Ran 3 tests in 11.983s + +FAILED (failures=6) diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-after.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-after.log new file mode 100644 index 00000000..affdc421 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-after.log @@ -0,0 +1,7 @@ +From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.bLx8i1YQgO/origin + * branch main -> FETCH_HEAD +From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.bLx8i1YQgO/origin + * branch main -> FETCH_HEAD +Signing mode: developer-id +Signing mode: self-signed +Release workflow contract tests passed. diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-before.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-before.log new file mode 100644 index 00000000..c3488b60 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-before.log @@ -0,0 +1,12 @@ +From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.5RrqhVRHzc/origin + * branch main -> FETCH_HEAD +From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.5RrqhVRHzc/origin + * branch main -> FETCH_HEAD +Signing mode: developer-id +unsigned Developer ID DMG reached verification +FAIL: bash -e /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.5RrqhVRHzc/classify.sh +FAIL: test verify = sign +verify +FAIL: test verify = sign +Signing mode: self-signed +3 release contract checks failed. diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/sdlc-checks.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/sdlc-checks.log new file mode 100644 index 00000000..e48e7a61 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/sdlc-checks.log @@ -0,0 +1,34 @@ +==> Checking docs/sdlc/changes/2026-08-25-ai-native-sdlc/ +==> Checking docs/sdlc/changes/2026-08-26-dmg-installer-polish/ +==> Checking docs/sdlc/changes/2026-08-29-espresso-ane/ +==> Checking docs/sdlc/changes/2026-08-30-dev-app-icon-packaging/ +==> Checking docs/sdlc/changes/2026-08-30-history-mode-switch/ +==> Checking docs/sdlc/changes/2026-08-30-model-type-selection/ +==> Checking docs/sdlc/changes/2026-08-30-settings-window-layout/ +==> Checking docs/sdlc/changes/2026-08-30-system-settings-groups/ +==> Checking docs/sdlc/changes/2026-08-31-ane-lm-runtime/ +==> Checking docs/sdlc/changes/2026-08-31-settings-semantic-background/ +==> Checking docs/sdlc/changes/2026-08-31-shell-sdlc-gate/ +==> Checking docs/sdlc/changes/2026-08-31-website-native-redesign/ +==> Checking docs/sdlc/changes/2026-09-03-release-p12-openssl3/ +==> Checking docs/sdlc/changes/2026-09-18-nightly-release-pipeline/ +==> Checking docs/sdlc/changes/2026-09-21-model-download-retry-recovery/ +==> Checking docs/sdlc/changes/2026-09-21-remote-mic-integration/ +==> Checking docs/sdlc/changes/2026-09-21-settings-surface-parity/ +==> Checking docs/sdlc/changes/2026-09-23-confucius4-r2t2-mlx/ +==> Checking docs/sdlc/changes/2026-09-23-input-session-ownership/ +==> Checking docs/sdlc/changes/2026-09-23-silent-input-insertion/ +==> Checking docs/sdlc/changes/2026-09-24-industry-lexicon-expansion/ +==> Checking docs/sdlc/changes/2026-09-24-release-workflow-permissions/ +==> Checking docs/sdlc/changes/2026-09-28-release-input-contract/ +==> Checking docs/sdlc/changes/2026-09-30-firered-asr-download-completeness/ +==> Checking docs/sdlc/changes/2026-10-01-clamshell-mic-failover/ +==> Checking docs/sdlc/changes/2026-10-01-stable-prompt-prefix-cache/ +==> Checking docs/sdlc/changes/2026-10-03-builtin-plugin-composition/ +==> Checking docs/sdlc/changes/2026-10-03-promo-videos/ +==> Checking docs/sdlc/changes/2026-10-04-voice-input-reliability/ +==> Checking docs/sdlc/changes/2026-10-07-desktop-numeral-list-fidelity/ +==> Checking docs/sdlc/changes/2026-10-07-xiaomi-remote-connection/ +==> Checking docs/sdlc/changes/2026-10-15-developer-id-ci/ +==> Checking docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/ +SDLC checks passed. diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/verification-handoff.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/verification-handoff.json new file mode 100644 index 00000000..fddbee6a --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/verification-handoff.json @@ -0,0 +1,19 @@ +{ + "recorded_at_utc": "2026-10-16T03:37:34.515850+00:00", + "status": "pending_human_verification_acceptance", + "independent_result": "passed_local_implementation_verification", + "findings": [], + "final_checks": { + "sdlc": { + "exit_code": 0 + }, + "diff": { + "exit_code": 0 + } + }, + "reviewed_source_hashes_match": true, + "package_resolved_sha256": "3a007c520b8b69aa9a675a42675662d7d272e4808dd3e71e4f12e074150219ad", + "verification_artifact_sha256": "6c32d41f720b28dff23ab63955361de7b5ab4da876165aec085f5ff0eee88b52", + "remote_pr_stage_started": false, + "new_release_published": false +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/verification-human-acceptance.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/verification-human-acceptance.json new file mode 100644 index 00000000..affd0e5a --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/verification-human-acceptance.json @@ -0,0 +1,10 @@ +{ + "recorded_at_utc": "2026-10-16T05:34:37.461067+00:00", + "decision": "approved", + "approved_by": "User", + "approved_date": "2026-10-16", + "explicit_chat_reply": "批准", + "scope": "Accept completed local implementation verification and authorize scoped commit, push and PR creation under the approved plan", + "pr_approval_granted": false, + "new_run_production_approval_granted": false +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/intent.md b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/intent.md new file mode 100644 index 00000000..e1cfd0e5 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/intent.md @@ -0,0 +1,79 @@ +# Intent: Sign the Developer ID distribution DMG + +**Status:** approved +**Approved-by:** User, explicit chat decision: 批准修复意图 +**Approved-date:** 2026-10-16 +**Upstream:** [Failed v0.0.53 release](../2026-10-15-developer-id-ci/release.md) +**Risk:** High, release signing and distribution + +## Problem + +The authorized v0.0.53 release run `38770474797` passed complete candidate +tests, Developer ID app signing, Apple notarization, and ticket stapling. It +stopped at the DMG Gatekeeper check with `source=no usable signature`, exit 3. +Nothing was published; the latest public release remains v0.0.52. + +The packaging script signs Utter.app but creates the outer DMG without signing +it. The release verifier assesses the DMG's primary signature after checking +its notarization ticket. Independent review confirmed that missing container +signature explains this failure. No evidence points to notarization latency. + +## Outcome + +The existing CI pipeline publishes a Developer ID-signed and Apple-notarized +DMG whose own signature, embedded app, ticket, Gatekeeper assessments, and +published checksum all pass. The self-signed release path remains explicit. + +## Scope + +- Sign the Developer ID distribution DMG before its notarization submission. +- Verify the DMG uses the intended Developer ID certificate and timestamp. +- Add a focused regression control for the missing DMG-signing step and its + failure path; keep the real Gatekeeper gate. +- Deliver the fix through a reviewed PR and protected main, then use a new + release version for a separately identified production run. + +## Constraints + +- Keep failed tag `v0.0.53` at tag object + `b8e869cddca904cd525ece4fcb36d55fd4a14a33`, peeled commit + `f0ef2aa88296da017e29ced2b7bc9271af96e4fb`. Do not move or delete it. +- Preserve v0.0.52, existing assets, configured credentials, main protection, + and human production approval. Never replace same-version published assets. +- Stop when configured signing fails. No ad-hoc fallback, Gatekeeper bypass, + or delay-only workaround. +- Do not change app behavior, permissions, bundle identifiers, or dependencies. +- Follow intent, design, plan, verification, PR, and production human gates. + +## Acceptance criteria + +- A regression check fails against the current missing-signature behavior and + passes with the fix. Signing failure stops before notarization/publication. +- The generated Developer ID DMG's certificate matches the approved app + certificate SHA-256 + `1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112`. +- Appropriate local repository checks, complete tests, and release-style + packaging pass, with unavailable checks disclosed separately. +- Independent verification confirms the change, rollback, and actual results. +- A new approved CI run receives Apple acceptance, staples the ticket, passes + both DMG and app Gatekeeper checks, and publishes a checksum-verified download. + +## Evidence and rollback + +The original signing log, job status, and independent failure analysis are in +`../2026-10-15-developer-id-ci/evidence/`. Apple accepted submission +`29a24fa6-d6b6-4053-9213-a9989e6e705a`; that is notarization evidence only. +The failed run exposes no retained downloadable artifact. No release or assets +exist for v0.0.53, so no public artifact needs rollback. Revert the scoped fix +through a PR if necessary, preserving the failed tag and release evidence. + +## Open questions + +The user approved intent, [design](spec.md), [plan](plan.md), and +[local verification](verification.md) on 2026-10-16. PR approval and the new +run-specific production decision remain required. + +## References + +- [Failed release run](https://github.com/IchenDEV/utter/actions/runs/38770474797) +- [Apple packaging requirements](https://developer.apple.com/documentation/xcode/packaging-mac-software-for-distribution) diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/plan.md b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/plan.md new file mode 100644 index 00000000..ebf04d26 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/plan.md @@ -0,0 +1,142 @@ +# Plan: Sign the Developer ID distribution DMG + +**Status:** approved +**Approved-by:** User, explicit chat reply to implementation plan: 批准 +**Approved-date:** 2026-10-16 +**Upstream:** [Spec](spec.md) + +## Baseline and scope + +Intent, design, and this plan have explicit human approvals. The user approved +this plan on 2026-10-16. Keep the failed v0.0.53 tag and its first-run +evidence intact. Current public latest remains v0.0.52. + +The production change is limited to the shared release workflow and existing +artifact verifier. Extend the existing workflow contract test; add a focused +script under `scripts/tests/` only if needed to keep files below 300 lines. +Do not change app source, dependencies, credentials, code owners, or protections. + +## Work items + +- [x] Record current HEAD, branch, tracked/index/untracked changes, source and + `Package.resolved` hashes, and available disk. Preserve existing SDLC bundles. + Use a `codex/` fix branch in this checkout when safe so existing build caches + can be reused. Stop on unexpected owner changes; do not reset or overwrite. +- [x] Extend the existing contract harness to run the actual extracted + classification/signing block in an external `bash -e` process. Its fixture + models signing state and records command order without credentials or remote + writes. Prove the new regression fails against the old unsigned-DMG block in + a disposable baseline copy before changing production code. +- [x] In `.github/workflows/release-artifact.yml`, add native DMG signing in the + existing Developer ID branch before its first verifier call. Use exact + `SIGN_IDENTITY`, `--timestamp`, and identifier `com.opentype.voiceinput.dmg`. + Keep the existing self-signed branch and all publication gates. +- [x] In `scripts/verify-release-artifact.sh`, when a DMG and + `--require-developer-id` are supplied, verify the DMG's own strict signature, + Developer ID authority, secure timestamp, and certificate equality with the + app and optional expected fingerprint. Reuse certificate extraction. Reject + before mounting or notarization; retain existing post-staple checks. +- [x] Complete contract cases for successful sign-before-verify order, signing + failure before any verifier/submission progression, and the self-signed + branch. Invoke the extracted block as a separate `bash -e` command so shell + conditional contexts cannot suppress the production error behavior. +- [x] Build a release-style local app and DMG using the existing build script + and approved available Developer ID identity. Use task-owned output copies + for native verification; keep private key material in the existing keychain. + No new identity export or notarization credential is needed for these checks. +- [x] Run the actual verifier on the real app plus disposable DMG variants: + signed/timestamped success, unsigned rejection, and missing-timestamp + rejection. Record the exact diagnostic so a prior unrelated failure cannot + masquerade as reaching the new container guard. +- [x] Verify the fingerprint-mismatch branch, including invocation without + `--expected-cert-sha256`. Use a controlled external-tool fixture if a second + real Developer ID identity is unavailable. Run the actual verifier, and label + this as fixture coverage rather than a second native signing identity. +- [x] Run required local repository/full-suite checks and release packaging + checks as detailed below. Preserve first failures and resolve findings within + the approved scope. Keep `Package.resolved` unchanged. +- [x] Obtain independent read-only verification of the actual diff, regression + old-fail/new-pass evidence, native verifier results, and cleanup. Address its + actionable findings before presenting implementation verification. +- [x] Record commands, outcomes, skips, evidence paths, rollback, and remaining + release gates in `verification.md`. Set it to `pending approval` and stop for + the human verification decision before starting the remote PR stage. + +## Verification plan + +- [x] `bash -n` for changed shell scripts and extracted workflow shell blocks. +- [x] `bash scripts/tests/test_release_workflow_contract.sh`, including the + observed regression and fail-closed cases. The baseline run must fail for the + missing DMG signing operation, rather than fixture setup. +- [x] Any focused verifier fixture test added under `scripts/tests/`, including + missing signature, certificate mismatch, and missing secure timestamp. +- [x] `bash scripts/sdlc-checks.sh`. +- [x] `bash scripts/ci-basic-checks.sh`. +- [x] Complete local Swift test suites with all discovered test identities and + final completion accounted for. Preserve the distinction between a command + wrapper failure and actual test results. +- [x] Release-style packaging through `bash scripts/build-app.sh`, followed by + the approved shared signing block and real verifier on task-owned copies. +- [x] Native signature/certificate/timestamp inspection plus verifier positive + and negative cases. Retain public metadata and logs, never private keys or + credentials. Detach only task-owned mounts and confirm cleanup. +- [x] Independent implementation verification and fresh SDLC/diff checks. + +### Complete local test execution + +The previous protected `swift test` wrapper failed before execution because of +nested `sandbox_apply`. Complete native XCTest and Swift Testing runs passed. +Use the already validated runtime approach; do not weaken the runtime policy +or disable SwiftPM's native sandbox as a workaround. + +Before reusing the complete frozen bundles, verify that current Swift sources, +package configuration, resources, and bundle hashes still match their build +inputs. If they differ, build the tests outside the private runtime policy +with native SwiftPM sandboxing, then freeze the complete bundles and hashes. +Run only test processes under the validated policy with a minimal environment. +Recheck its preference/keychain canaries and complete identity coverage. + +Keep the original wrapper setup failure visible. If recording a fresh standard +wrapper attempt, stop after the same setup failure and use the complete native +engines; do not start another sandbox-workaround search. A fresh CI `swift test` +must pass on the exact PR/merged candidate before production. + +Check disk before each heavy build and retain at least 10 GiB free. Verify the +lockfile hash after Swift/Xcode commands. Stop on unplanned dependency changes +or insufficient disk; preserve source and evidence rather than broad cleanup. + +## Human gates and release sequence + +The user's separate decisions approved intent and design on 2026-10-16. +Approval of this plan authorizes the listed local implementation, signing +fixtures, required tests, and independent review. It does not supply later +verification acceptance, PR approval, or a new production decision. + +After human verification acceptance, push the scoped fix branch and open a +reviewable PR. Attach that PR to this task and verify its remote SHA and CI. +Main currently has one collaborator/code owner and requires an independent +approving review. Resolve an eligible human approval route for that concrete +PR before merge. Do not add collaborators, alter code owners, or bypass rules +under this plan. + +After the protected merge, verify the exact merged SHA's `SDLC Gate`, recheck +tags/releases and main, and select the next unused stable version, expected +v0.0.54. Never move v0.0.53. Trigger its normal release tests and request a +separate human production decision for that specific run. + +The authorized production run must show accepted Apple notarization, stapling, +DMG and app Gatekeeper acceptance, mounted-app equality, and published checksum +and download equality. Independently download and verify the published asset +before claiming the release complete. + +## Stop conditions and rollback + +Signing, timestamp, fingerprint, verifier, test, or packaging failure stops +progression to the remote PR/release stage until corrected or explicitly +reviewed. Preserve exact missing prerequisites and failure evidence. No ad-hoc +fallback, gate removal, or blind release retry is allowed. + +Revert a defective scoped fix through a PR. Preserve protections, credentials, +failed tags, and older assets. If a published release needs withdrawal, restore +the previous latest recommendation without replacing assets, and disclose the +older release's signing status. No public artifact requires rollback now. diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/spec.md b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/spec.md new file mode 100644 index 00000000..35796d53 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/spec.md @@ -0,0 +1,133 @@ +# Spec: Sign the Developer ID distribution DMG + +**Status:** approved +**Approved-by:** User, explicit chat decision: 批准修复设计 +**Approved-date:** 2026-10-16 +**Upstream:** [Intent](intent.md) + +## Context + +Both tag and nightly releases use `.github/workflows/release-artifact.yml`. +It imports one selected identity, records its SHA-256 fingerprint, builds the +App and DMG, classifies the app signature, and verifies the artifacts before +notarization. The v0.0.53 run proved that app signing and Apple credentials +work, but its outer DMG had no signature. Gatekeeper rejected that container +after Apple accepted the submission and the ticket was stapled. + +The shared workflow already owns distribution signing policy and has the +exact identity and fingerprint. Put the correction there, alongside its +Developer ID classification. This is smaller than adding identity discovery +to the generic packaging script or maintaining two release entry-point fixes. + +## Sign before the first Developer ID verification + +In the shared `Classify and verify signed artifact` run block, once the app is +classified as Developer ID, sign `dist/Utter-$RELEASE_VERSION.dmg` with: + +- The existing exact `SIGN_IDENTITY` selected from the imported CI identity. +- A secure timestamp, requested explicitly with `--timestamp`. +- A stable container identifier, `com.opentype.voiceinput.dmg`, distinct from + the app's unchanged bundle identifier. + +Use native `codesign` directly in the existing run block. A disk image does +not receive the app's entitlements, runtime options, or recursive signing. +Let a nonzero signing command stop that step under the workflow's existing +`bash -e` behavior. Verify the signed image before uploading it to Apple. + +The resulting order is build -> classify app -> sign Developer ID DMG -> +verify app and DMG -> notarize DMG -> staple -> verify distribution -> checksum +and download verification -> publish. The existing public release gates remain +in that order. The self-signed branch does not enter the Developer ID DMG step. + +## Verify the container at the existing boundary + +Extend `scripts/verify-release-artifact.sh` only when a DMG is supplied with +`--require-developer-id`. Before mounting the image or submitting it for +notarization, require: + +1. `codesign --verify --strict` succeeds for the DMG itself. +2. Its primary authority is Developer ID Application and it has a secure + timestamp. +3. The DMG certificate fingerprint matches the app certificate. When + `--expected-cert-sha256` is supplied, both must also match that imported + certificate fingerprint. + +Reuse the existing `certificate_sha256` extraction helper for both signed +paths. Keep signature parsing and validation in the verifier rather than +duplicating them in workflow YAML. The CLI arguments stay unchanged. + +The first shared workflow verification catches a missing, ad-hoc, mismatched, +or untimestamped DMG signature before Apple submission. The same verification +also runs after stapling. The existing ticket validation, DMG open assessment, +app execute assessment, mounted-app equality, and checksum gates still apply. + +## Safety and failure modes + +| Failure | Required result | +|---|---| +| App authority differs from imported identity | Existing classification stops | +| DMG signing or timestamp service fails | Stop before notarization | +| DMG has no usable signature | Reject before notarization | +| DMG uses another certificate or lacks secure timestamp | Reject before notarization | +| Image or app changes after signing | Signature or mounted equality check rejects | +| Apple rejects submission, staple fails, or Gatekeeper rejects | Existing workflow stops before publication | + +No new credentials, dependencies, signing exports, or GitHub permissions are +needed. Diagnostic output contains public signing metadata, never private +keys or passwords. Preserve the current configured-identity failure behavior. + +## Test strategy + +- Extend `scripts/tests/test_release_workflow_contract.sh` to execute the + shared workflow's actual classification/signing shell block in its existing + disposable, credential-free fixture. Assert signing occurs with the chosen + identity, explicit timestamp, and container identifier before verification. +- Prove the regression check fails against the old unsigned-DMG run block. + Exercise signing failure and the self-signed branch; signing failure must + prevent progression, and self-signed behavior must stay explicit. +- Invoke the actual `verify-release-artifact.sh` with a real packaged app and + task-owned Developer ID DMG fixtures. Prove a valid image passes and the + unsigned, mismatched, and missing-secure-timestamp cases reach and fail the + intended container guard. Native signing/extraction alone is insufficient. + Identify fixture-based certificate cases separately from native results. +- Run required SDLC/basic checks, complete Swift tests, and release-style + packaging. Separate native runtime evidence from any wrapper setup failure. +- Obtain independent verification of the diff and results. The approved new + production run must still prove Apple acceptance, stapling, both Gatekeeper + checks, mounted equality, and the published asset checksum/download equality. + +Fixtures do not claim Apple acceptance or public release success. Only the +actual authorized production run can provide that evidence. + +## Rollout and rollback + +Implementation begins only after design and plan approval. Deliver the scoped +fix through a PR and protected main. Verify `SDLC Gate` on the exact merged +candidate. Recheck remote tags and use the next unused stable version, expected +to be v0.0.54. Retain the failed v0.0.53 tag and its first-failure evidence. + +Current GitHub readback lists only `IchenDEV` as a collaborator and sensitive +path code owner. Main requires a separate approving review, code-owner review, +and last-push approval, with no bypass actors. Before merge, the concrete PR +must have an eligible human approval path. This is a rollout prerequisite; +changing collaborators, code owners, or protection rules is outside this fix. +Do not represent an agent review as satisfying that human gate. + +The new run requires its own human production decision. Preserve v0.0.52 and +its assets until the new release is verified. Revert the scoped fix through a +PR if it regresses packaging; keep protections and failure evidence. If a +published release is defective, restore the previous latest recommendation +without replacing same-version assets, and state its older signing status. + +## Review state + +The user approved intent, design, [implementation plan](plan.md), and +[local verification](verification.md) on 2026-10-16. Independent design and +implementation reviews found no blocker. Their reports record technical +verification; human approvals are recorded in the artifact headers. The PR +approval and new run-specific production decision remain separate gates. + +## References + +- [First-run independent diagnosis](../2026-10-15-developer-id-ci/evidence/release-final-independent-verification.json) +- [Apple packaging and container signing](https://developer.apple.com/documentation/xcode/packaging-mac-software-for-distribution) diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/verification.md b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/verification.md new file mode 100644 index 00000000..7f364912 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/verification.md @@ -0,0 +1,110 @@ +# Verification: Sign the Developer ID distribution DMG + +**Status:** approved +**Approved-by:** User, explicit chat reply to verification acceptance: 批准 +**Approved-date:** 2026-10-16 +**Upstream:** [Plan](plan.md) + +## Current state + +Local implementation and validation completed on `codex/fix-developer-id-dmg-signing`. +Intent, design, and execution plan have separate human approvals. No remote +source, tag, release, collaborator, or protection changes have been made during +this correction. Final independent verification passed with no findings. +The user accepted this verification on 2026-10-16 and authorized the PR stage. + +## Implemented behavior + +The shared workflow signs the Developer ID DMG with its exact imported identity, +secure timestamp, and dedicated container identifier before its first artifact +verification. The verifier rejects invalid container signatures, non-Developer +ID authorities, absent timestamps, and app/DMG certificate mismatches before +mounting. It also rejects failed or malformed certificate fingerprint decoding. +Self-signed and generic packaging paths retain their existing requirements. + +## Local evidence + +| Check | Result | +|---|---| +| Old workflow with new regression | Failed: unsigned DMG reached verification | +| Old verifier with new regression | Failed: invalid container cases were accepted | +| Fixed literal workflow contract | Pass, including signing failure stopping before verification | +| Actual verifier with controlled tool fixtures | Four tests pass, including invalid signatures, mismatch, missing timestamp, and generic packaging | +| `bash -n` | Pass for changed shell scripts; extracted workflow block executes under `bash -e` | +| `bash scripts/ci-basic-checks.sh` | Pass with installed Python 3.14.6 | +| Protected `swift test --skip-build` | Setup failure before tests: nested `sandbox_apply` denied | +| Complete native XCTest suites | 1,143 cases, 17 skipped, zero failures | +| Swift Testing | One unique case passed | +| Test input and bundle integrity | Swift/resources/package inputs match baseline; all 300 frozen files unchanged | +| Runtime canaries | Preference synchronization denied; real keychain file open denied with EPERM | +| Independent final verification | Pass, no findings; actual native verifier, complete test identities, hashes, and cleanup independently checked | +| Release-style local build | Pass, Developer ID app and complete DMG packaging | +| Actual shared workflow block on native App/DMG | Pass, signing then full artifact verification | +| Native unsigned DMG | Rejected at the new signature guard | +| Native signed DMG without secure timestamp | Rejected at the new timestamp guard | +| Native matching certificate without expected flag | Pass, app and DMG certificates still compared | +| Native DMG identity/fingerprint/timestamp | Pass, selected Developer ID and dedicated identifier | +| Temporary mounts | None remain | + +The complete suites use all 14 frozen XCTest bundles. Thirteen Swift Testing +invocations contain no cases and return the expected exit 69; count only the +one unique passing Swift Testing case. The native results do not turn the +protected `swift test` wrapper failure into a command pass. + +Public summaries and focused logs are in [evidence](evidence/). The full native +run is recorded in `evidence/full-test-evidence.json`. The +[final independent report](evidence/implementation-final-verification.json) +includes the code review, native verifier reruns, full-suite identity and hash +checks, and remaining human gates. The independent native commands are in +[native-independent-rerun.json](evidence/native-independent-rerun.json). + +## Native artifact scope + +`evidence/native-dmg-verification.json` records the exact commands and fixture +directory. The real local build uses Xcode 27.0, the existing Developer ID +identity, and version 0.0.54. Its app is copied into a task-owned fixture with +the unsigned DMG produced by the generic packager. The actual shared workflow +block signs that DMG and invokes the actual repository verifier successfully. +The verifier checks real signatures, owned resources, architectures, versions, +mounted app equality, and the matching certificate. + +The selected certificate SHA-256 is +`1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112`, +team `G9L7H3T3D5`. Native DMG metadata shows a secure timestamp and identifier +`com.opentype.voiceinput.dmg`. The local signed DMG SHA-256 is +`24765f7ce54b07cb7b1c9427d8e67cdbcf9df270e8011bb8d82e7e2049a89101`. +This checksum identifies a local verification fixture, not a published asset. + +Unsigned and deliberately untimestamped copies fail at their intended guards. +Certificate mismatch uses controlled external-tool fixtures against the actual +verifier, both with and without the expected fingerprint argument. A second +native Developer ID identity was not used or claimed. + +These new local fixtures have not been notarized, assessed by Gatekeeper as +notarized software, uploaded, or published. Apple acceptance from the earlier +failed v0.0.53 run does not establish those outcomes for this correction. + +## Corrected validation setup + +The first minimal PATH selected system Python 3.9.6, below the repository's +Python 3.10+ requirement. Basic checks failed in existing evaluator tests. +The launcher now selects installed Homebrew Python 3.14.6 and the complete +basic check passes. The first build was stopped before packaging to correct +the same PATH, then restarted using its cache. Initial logs are preserved. + +The runtime-canary witness parser initially expected JSON, while the existing +canary binaries emit plain text. The parser was corrected before running the +full suite. Both canaries passed; no private runtime policy was weakened. + +## Remaining gates + +Human verification acceptance is complete. The remote PR stage is authorized. +An eligible human PR approval route and a new run-specific production approval +remain required. +The failed v0.0.53 tag and latest public v0.0.52 are preserved. + +## Rollback + +Revert the scoped source correction through a reviewed PR if needed. Preserve +existing credentials, protections, failed tags, and prior assets. No new public +release has been published by this correction. diff --git a/scripts/tests/test_release_artifact.py b/scripts/tests/test_release_artifact.py new file mode 100644 index 00000000..9c3eb490 --- /dev/null +++ b/scripts/tests/test_release_artifact.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +"""Exercise the actual release verifier with controlled native-tool boundaries.""" +from pathlib import Path +import plistlib +import subprocess +import tempfile +import unittest + +import test_resource_bundles as resource_fixtures + +ROOT = Path(__file__).resolve().parents[2] +CERT = "A" * 64 +TOOLS = r'''#!/usr/bin/env python3 +import os +from pathlib import Path +import shutil +import sys + +name = Path(sys.argv[0]).name +args = sys.argv[1:] +case = os.environ['SIGNATURE_CASE'] +with open(os.environ['TOOL_TRACE'], 'a') as trace: + trace.write(name + ' ' + ' '.join(args) + '\n') +if name == 'lipo': + print('arm64') +elif name == 'codesign': + dmg = args[-1].endswith('.dmg') + if '--verify' in args: + sys.exit(1 if dmg and case == 'unsigned' else 0) + extract = next((a for a in args if a.startswith('--extract-certificates=')), None) + if extract: + if dmg and case == 'extract-failure': + sys.exit(1) + marker = 'B' if dmg and case == 'mismatch' else 'A' + if dmg and case in ('fingerprint-failure', 'empty-fingerprint'): + marker = case + Path(extract.split('=', 1)[1] + '0').write_text(marker) + elif dmg and case == 'adhoc': + print('Signature=adhoc\nTeamIdentifier=not set') + else: + print('CodeDirectory flags=0x10000(runtime)') + print('Authority=Developer ID Application: Fixture (ABC1234567)') + print('TeamIdentifier=ABC1234567') + if not (dmg and case == 'untimestamped'): + print('Timestamp=Oct 16, 2026 at 12:00:00 AM') +elif name == 'openssl': + marker = Path(args[args.index('-in') + 1]).read_text() + if marker == 'fingerprint-failure': + sys.exit(1) + if marker == 'empty-fingerprint': + sys.exit(0) + print('sha256 Fingerprint=' + marker * 64) +elif name == 'hdiutil': + if args[0] == 'attach': + mount = Path(args[args.index('-mountpoint') + 1]) + shutil.copytree(os.environ['FIXTURE_APP'], mount / 'Utter.app') + elif args[0] == 'detach': + shutil.rmtree(Path(args[1]) / 'Utter.app') +''' + + +class ReleaseArtifactTests(unittest.TestCase): + def setUp(self): + self.temporary = tempfile.TemporaryDirectory() + self.addCleanup(self.temporary.cleanup) + self.root = Path(self.temporary.name) + self.app = self.root / "Utter.app" + resource_fixtures.ResourceBundleTests().populate(self.app) + plist = { + "CFBundleIdentifier": "com.opentype.voiceinput", + "CFBundleShortVersionString": "0.0.54", + "CFBundleVersion": "0.0.54", + } + (self.app / "Contents/Info.plist").write_bytes(plistlib.dumps(plist)) + self.dmg = self.root / "Utter.dmg" + self.dmg.write_bytes(b"controlled disk image fixture") + self.trace = self.root / "tools.log" + tools = self.root / "bin" + tools.mkdir() + stub = tools / "native-tool" + stub.write_text(TOOLS) + stub.chmod(0o755) + for name in ("codesign", "openssl", "lipo", "hdiutil", "xcrun", "spctl"): + (tools / name).symlink_to(stub) + self.env = { + "PATH": str(tools) + ":/usr/bin:/bin:/usr/sbin:/sbin", + "FIXTURE_APP": str(self.app), "TOOL_TRACE": str(self.trace), + "TMPDIR": str(self.root), "LANG": "C.UTF-8", + } + + def verify(self, case, expected=True, notarization=False, developer_id=True): + command = ["bash", str(ROOT / "scripts/verify-release-artifact.sh"), + "--app", str(self.app), "--dmg", str(self.dmg), + "--version", "0.0.54"] + if developer_id: + command += ["--require-developer-id"] + if expected: + command += ["--expected-cert-sha256", CERT] + if notarization: + command += ["--require-notarization"] + self.trace.write_text("") + return subprocess.run(command, env={**self.env, "SIGNATURE_CASE": case}, + capture_output=True, text=True, timeout=30) + + def test_signed_matching_timestamped_image_reaches_distribution_checks(self): + result = self.verify("valid", notarization=True) + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + trace = self.trace.read_text() + self.assertIn("hdiutil attach", trace) + self.assertIn("xcrun stapler validate", trace) + self.assertIn("spctl --assess --type open", trace) + self.assertIn("spctl --assess --type execute", trace) + + def test_invalid_container_stops_before_mounting(self): + for case, message in ( + ("unsigned", "DMG signature is invalid"), + ("adhoc", "DMG is not signed with a Developer ID Application identity"), + ("untimestamped", "DMG signature has no secure timestamp"), + ("mismatch", "DMG signing certificate does not match the app certificate"), + ("extract-failure", "could not extract the DMG signing certificate"), + ("fingerprint-failure", "could not extract the DMG signing certificate"), + ("empty-fingerprint", "could not extract the DMG signing certificate"), + ): + with self.subTest(case=case): + result = self.verify(case) + self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertIn(message, result.stderr) + self.assertNotIn("hdiutil attach", self.trace.read_text()) + self.assertNotIn("xcrun", self.trace.read_text()) + + def test_certificate_match_is_required_without_expected_fingerprint(self): + result = self.verify("mismatch", expected=False) + self.assertNotEqual(result.returncode, 0) + self.assertIn("DMG signing certificate does not match the app certificate", result.stderr) + self.assertNotIn("hdiutil attach", self.trace.read_text()) + + def test_generic_packaging_keeps_its_unsigned_container_contract(self): + result = self.verify("unsigned", expected=False, developer_id=False) + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertIn("hdiutil attach", self.trace.read_text()) + + +if __name__ == "__main__": + unittest.main() diff --git a/scripts/tests/test_release_workflow_contract.sh b/scripts/tests/test_release_workflow_contract.sh index a789d521..1ec9c86a 100644 --- a/scripts/tests/test_release_workflow_contract.sh +++ b/scripts/tests/test_release_workflow_contract.sh @@ -49,6 +49,7 @@ step_script "$MANUAL" 'Resolve version from tag' > "$FIXTURE/manual.sh" step_script "$ARTIFACT" 'Validate version and tag' > "$FIXTURE/validate.sh" step_script "$ARTIFACT" 'Require a SemVer tag on main' > "$FIXTURE/ancestor.sh" step_script "$ARTIFACT" 'Create and push release tag' > "$FIXTURE/create.sh" +step_script "$ARTIFACT" 'Classify and verify signed artifact' > "$FIXTURE/classify.sh" # Verify the values emitted by shell steps actually reach the reusable caller. job_text "$NIGHTLY" plan > "$FIXTURE/plan-job" @@ -175,5 +176,65 @@ check reject_step create v0.0.50 check test -z "$(git tag -l v0.0.50)" check test ! -e "$PUSH_LOG" +# Run the literal distribution block with observable external signing state. +export SIGN_IDENTITY='Developer ID Application: Fixture (ABC1234567)' +export SIGN_CERT_SHA256="$(printf '%064d' 0)" +export RELEASE_VERSION=0.0.54 TEAM_IDENTIFIER=ABC1234567 FAIL_SIGN=0 +export SIGNING_TRACE="$FIXTURE/signing-trace" SIGNED_DMG="$FIXTURE/signed-dmg" +export GITHUB_ENV="$FIXTURE/github-env" GITHUB_STEP_SUMMARY="$FIXTURE/summary" +cat > "$FIXTURE/bin/codesign" <<'STUB' +#!/usr/bin/env bash +set -euo pipefail +if [ "$1" = -dvvv ]; then + printf 'Authority=%s\nTeamIdentifier=%s\n' "$SIGN_IDENTITY" "$TEAM_IDENTIFIER" + exit 0 +fi +echo sign >> "$SIGNING_TRACE" +[ "$FAIL_SIGN" = 0 ] || exit 42 +timestamp=false identifier=false identity=false +while [ "$#" -gt 0 ]; do + case "$1" in + --timestamp) timestamp=true ;; + --identifier|-i) [ "$2" = com.opentype.voiceinput.dmg ]; identifier=true; shift ;; + --sign|-s) [ "$2" = "$SIGN_IDENTITY" ]; identity=true; shift ;; + --deep|--entitlements|--options) exit 43 ;; + esac + last="$1" + shift +done +$timestamp && $identifier && $identity +[ "$last" = dist/Utter-0.0.54.dmg ] +touch "$SIGNED_DMG" +STUB +cat > scripts/verify-release-artifact.sh <<'STUB' +#!/usr/bin/env bash +echo verify >> "$SIGNING_TRACE" +for arg in "$@"; do + if [ "$arg" = --require-developer-id ] && [ ! -f "$SIGNED_DMG" ]; then + echo 'unsigned Developer ID DMG reached verification' >&2 + exit 1 + fi +done +STUB +chmod +x "$FIXTURE/bin/codesign" scripts/verify-release-artifact.sh +: > "$SIGNING_TRACE" +check bash -e "$FIXTURE/classify.sh" +check test "$(cat "$SIGNING_TRACE")" = $'sign\nverify' +check grep -Fxq SIGNING_MODE=developer-id "$GITHUB_ENV" + +rm -f "$SIGNED_DMG" +: > "$SIGNING_TRACE" +export FAIL_SIGN=1 +check reject_step classify unused +check test "$(cat "$SIGNING_TRACE")" = sign +check test ! -e "$SIGNED_DMG" + +export FAIL_SIGN=0 SIGN_IDENTITY='Utter Signing' TEAM_IDENTIFIER='not set' +: > "$SIGNING_TRACE" +check bash -e "$FIXTURE/classify.sh" +check test "$(cat "$SIGNING_TRACE")" = verify +check grep -Fxq SIGNING_MODE=self-signed "$GITHUB_ENV" +check test ! -e "$SIGNED_DMG" + [ "$failures" -eq 0 ] || { echo "$failures release contract checks failed." >&2; exit 1; } echo "Release workflow contract tests passed." diff --git a/scripts/verify-release-artifact.sh b/scripts/verify-release-artifact.sh index a99e079d..43698733 100755 --- a/scripts/verify-release-artifact.sh +++ b/scripts/verify-release-artifact.sh @@ -68,9 +68,13 @@ certificate_sha256() { rm -r "$cert_dir" return 1 fi - fingerprint="$(openssl x509 -inform DER -in "${cert_prefix}0" -noout \ - -fingerprint -sha256 | cut -d= -f2 | tr -d ':' | tr '[:lower:]' '[:upper:]')" + if ! fingerprint="$(openssl x509 -inform DER -in "${cert_prefix}0" -noout \ + -fingerprint -sha256 | cut -d= -f2 | tr -d ':' | tr '[:lower:]' '[:upper:]')"; then + rm -r "$cert_dir" + return 1 + fi rm -r "$cert_dir" + [[ "$fingerprint" =~ ^[A-F0-9]{64}$ ]] || return 1 printf '%s\n' "$fingerprint" } @@ -158,6 +162,21 @@ verify_app "$APP_PATH" if [ -n "$DMG_PATH" ]; then [ -f "$DMG_PATH" ] || fail "DMG not found: $DMG_PATH" + if [ "$REQUIRE_DEVELOPER_ID" = true ]; then + codesign --verify --strict --verbose=2 "$DMG_PATH" \ + || fail "DMG signature is invalid" + dmg_signature="$(codesign -dvvv "$DMG_PATH" 2>&1)" + grep -q '^Authority=Developer ID Application:' <<<"$dmg_signature" \ + || fail "DMG is not signed with a Developer ID Application identity" + grep -Eq '^Timestamp=.+$' <<<"$dmg_signature" \ + || fail "DMG signature has no secure timestamp" + app_cert_sha256="$(certificate_sha256 "$APP_PATH")" \ + || fail "could not extract the app signing certificate" + dmg_cert_sha256="$(certificate_sha256 "$DMG_PATH")" \ + || fail "could not extract the DMG signing certificate" + [ "$dmg_cert_sha256" = "$app_cert_sha256" ] \ + || fail "DMG signing certificate does not match the app certificate" + fi hdiutil verify "$DMG_PATH" >/dev/null mount_point="$(mktemp -d)" From b405f46634df66e678b94b15e94b37cb4dc64d8d Mon Sep 17 00:00:00 2001 From: idevlab Date: Fri, 16 Oct 2026 13:42:09 +0800 Subject: [PATCH 2/3] docs: preserve failure logs as lossless JSON evidence --- .../basic-checks-python39-attempt-1-log.json | 7 ++ .../basic-checks-python39-attempt-1.log | 107 ------------------ .../evidence-packaging-independent.json | 53 +++++++++ .../evidence/evidence-retention.json | 12 ++ .../evidence/pr-ci-first-failure.json | 12 ++ .../regression-verifier-before-log.json | 7 ++ .../evidence/regression-verifier-before.log | 74 ------------ .../verification.md | 6 + 8 files changed, 97 insertions(+), 181 deletions(-) create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1-log.json delete mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1.log create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/evidence-packaging-independent.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/pr-ci-first-failure.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before-log.json delete mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before.log diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1-log.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1-log.json new file mode 100644 index 00000000..36d9bca1 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1-log.json @@ -0,0 +1,7 @@ +{ + "original_local_path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1.log", + "sha256": "1c8e7f3d8a72365cd32beadd052b33c381355f03c4499312fdcdd0670821b901", + "encoding": "UTF-8", + "reason_for_json": "Preserve unittest separator lines without presenting them as repository conflict markers", + "content": "\n==> Checking Package.swift\nSwift module boundaries passed.\n......\n----------------------------------------------------------------------\nRan 6 tests in 0.002s\n\nOK\nOwned resources passed.\n.....\n----------------------------------------------------------------------\nRan 5 tests in 0.031s\n\nOK\nFFFFFF...................E\n======================================================================\nERROR: test_voice_quality_acceptance (unittest.loader._FailedTest)\n----------------------------------------------------------------------\nImportError: Failed to import test module: test_voice_quality_acceptance\nTraceback (most recent call last):\n File \"/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/unittest/loader.py\", line 436, in _find_test_path\n module = self._get_module_from_name(name)\n File \"/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/unittest/loader.py\", line 377, in _get_module_from_name\n __import__(name)\n File \"/Users/chenli/projects/utter/scripts/tests/test_voice_quality_acceptance.py\", line 6, in \n from voice_quality_acceptance import REQUIRED_DEMOS, acceptance_report\n File \"/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n======================================================================\nFAIL: test_fidelity_preserves_sentence_email_opaque_paths_and_quotes (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py\", line 145, in test_fidelity_preserves_sentence_email_opaque_paths_and_quotes\n self.assertEqual(result.returncode, 0, result.stderr)\nAssertionError: 1 != 0 : Traceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py\", line 14, in \n from voice_quality_acceptance import acceptance_report\n File \"/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n======================================================================\nFAIL: test_fidelity_rejects_added_numbers_and_changed_unicode_space_path (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py\", line 103, in test_fidelity_rejects_added_numbers_and_changed_unicode_space_path\n self.assertEqual(result.returncode, 0, result.stderr)\nAssertionError: 1 != 0 : Traceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py\", line 14, in \n from voice_quality_acceptance import acceptance_report\n File \"/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n======================================================================\nFAIL: test_fidelity_rejects_reordered_number_ownership (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py\", line 169, in test_fidelity_rejects_reordered_number_ownership\n self.assertEqual(result.returncode, 0, result.stderr)\nAssertionError: 1 != 0 : Traceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py\", line 14, in \n from voice_quality_acceptance import acceptance_report\n File \"/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n======================================================================\nFAIL: test_help_documents_schema (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py\", line 189, in test_help_documents_schema\n self.assertEqual(result.returncode, 0)\nAssertionError: 1 != 0\n\n======================================================================\nFAIL: test_rejects_missing_required_field_with_line_number (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py\", line 178, in test_rejects_missing_required_field_with_line_number\n self.assertEqual(result.returncode, 2)\nAssertionError: 1 != 2\n\n======================================================================\nFAIL: test_reports_asr_processed_fidelity_hallucination_and_latency (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py\", line 61, in test_reports_asr_processed_fidelity_hallucination_and_latency\n self.assertEqual(result.returncode, 0, result.stderr)\nAssertionError: 1 != 0 : Traceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py\", line 14, in \n from voice_quality_acceptance import acceptance_report\n File \"/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n----------------------------------------------------------------------\nRan 26 tests in 17.409s\n\nFAILED (failures=6, errors=1)\n" +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1.log deleted file mode 100644 index 27e58064..00000000 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1.log +++ /dev/null @@ -1,107 +0,0 @@ - -==> Checking Package.swift -Swift module boundaries passed. -...... ----------------------------------------------------------------------- -Ran 6 tests in 0.002s - -OK -Owned resources passed. -..... ----------------------------------------------------------------------- -Ran 5 tests in 0.031s - -OK -FFFFFF...................E -====================================================================== -ERROR: test_voice_quality_acceptance (unittest.loader._FailedTest) ----------------------------------------------------------------------- -ImportError: Failed to import test module: test_voice_quality_acceptance -Traceback (most recent call last): - File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/unittest/loader.py", line 436, in _find_test_path - module = self._get_module_from_name(name) - File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/unittest/loader.py", line 377, in _get_module_from_name - __import__(name) - File "/Users/chenli/projects/utter/scripts/tests/test_voice_quality_acceptance.py", line 6, in - from voice_quality_acceptance import REQUIRED_DEMOS, acceptance_report - File "/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py", line 8, in - def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]: -TypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType' - - -====================================================================== -FAIL: test_fidelity_preserves_sentence_email_opaque_paths_and_quotes (test_evaluate_voice_quality.VoiceQualityEvaluatorTests) ----------------------------------------------------------------------- -Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py", line 145, in test_fidelity_preserves_sentence_email_opaque_paths_and_quotes - self.assertEqual(result.returncode, 0, result.stderr) -AssertionError: 1 != 0 : Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py", line 14, in - from voice_quality_acceptance import acceptance_report - File "/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py", line 8, in - def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]: -TypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType' - - -====================================================================== -FAIL: test_fidelity_rejects_added_numbers_and_changed_unicode_space_path (test_evaluate_voice_quality.VoiceQualityEvaluatorTests) ----------------------------------------------------------------------- -Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py", line 103, in test_fidelity_rejects_added_numbers_and_changed_unicode_space_path - self.assertEqual(result.returncode, 0, result.stderr) -AssertionError: 1 != 0 : Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py", line 14, in - from voice_quality_acceptance import acceptance_report - File "/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py", line 8, in - def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]: -TypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType' - - -====================================================================== -FAIL: test_fidelity_rejects_reordered_number_ownership (test_evaluate_voice_quality.VoiceQualityEvaluatorTests) ----------------------------------------------------------------------- -Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py", line 169, in test_fidelity_rejects_reordered_number_ownership - self.assertEqual(result.returncode, 0, result.stderr) -AssertionError: 1 != 0 : Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py", line 14, in - from voice_quality_acceptance import acceptance_report - File "/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py", line 8, in - def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]: -TypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType' - - -====================================================================== -FAIL: test_help_documents_schema (test_evaluate_voice_quality.VoiceQualityEvaluatorTests) ----------------------------------------------------------------------- -Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py", line 189, in test_help_documents_schema - self.assertEqual(result.returncode, 0) -AssertionError: 1 != 0 - -====================================================================== -FAIL: test_rejects_missing_required_field_with_line_number (test_evaluate_voice_quality.VoiceQualityEvaluatorTests) ----------------------------------------------------------------------- -Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py", line 178, in test_rejects_missing_required_field_with_line_number - self.assertEqual(result.returncode, 2) -AssertionError: 1 != 2 - -====================================================================== -FAIL: test_reports_asr_processed_fidelity_hallucination_and_latency (test_evaluate_voice_quality.VoiceQualityEvaluatorTests) ----------------------------------------------------------------------- -Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py", line 61, in test_reports_asr_processed_fidelity_hallucination_and_latency - self.assertEqual(result.returncode, 0, result.stderr) -AssertionError: 1 != 0 : Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py", line 14, in - from voice_quality_acceptance import acceptance_report - File "/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py", line 8, in - def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]: -TypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType' - - ----------------------------------------------------------------------- -Ran 26 tests in 17.409s - -FAILED (failures=6, errors=1) diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/evidence-packaging-independent.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/evidence-packaging-independent.json new file mode 100644 index 00000000..132e4a69 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/evidence-packaging-independent.json @@ -0,0 +1,53 @@ +{ + "verifier": "/root/signing_verifier", + "verified_at_utc": "2026-10-16T05:41:45.011437+00:00", + "result": "passed", + "scope": "Read-only review of proposed staged evidence packaging correction after first PR CI failure.", + "wrappers": [ + { + "original_local_log": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1.log", + "staged_json": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1-log.json", + "sha256": "1c8e7f3d8a72365cd32beadd052b33c381355f03c4499312fdcdd0670821b901", + "size_bytes": 6666, + "decoded_bytes_equal_original": true, + "original_equals_pre_correction_commit": true, + "raw_log_removed_from_index": true, + "staged_json_matches_worktree": true + }, + { + "original_local_log": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before.log", + "staged_json": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before-log.json", + "sha256": "9172cdd7e88908a0dc53752ed33dfdd720201789a9e9b395cbc35e9e38f79efa", + "size_bytes": 4454, + "decoded_bytes_equal_original": true, + "original_equals_pre_correction_commit": true, + "raw_log_removed_from_index": true, + "staged_json_matches_worktree": true + } + ], + "production_and_regression_source_sha256_unchanged": { + ".github/workflows/release-artifact.yml": "f9845ad9d4b7d35367d5cffa722b208f998f90a400ce3dffc44173d4449af73b", + "scripts/verify-release-artifact.sh": "e2ee26c5fc9c5b2cb122731a7d801f8ef91176733256f92cbd76cf1c3a1b735b", + "scripts/tests/test_release_workflow_contract.sh": "7ba76b3f1edd5ec01601f62b3a98c7571e5e244cd9ef730f55c0ae1dffe05c37", + "scripts/tests/test_release_artifact.py": "23004ea623723d5649fc211ca2efdd775d6b57930622afa65462ae3d69e9f995" + }, + "compared_code_snapshots": [ + "working tree", + "index", + "current HEAD", + "implementation-final-verification.json" + ], + "staged_tracked_conflict_marker_scan": { + "command": "git grep --cached -n -E ^(<<<<<<<|=======|>>>>>>>) -- .", + "exit": 1, + "matches": 0 + }, + "ci_first_failure_log_hash_matches_record": true, + "conflict_guard_source_modified": false, + "findings": [], + "remaining_boundary": "This validates the proposed index. Fresh remote exact-head CI must pass after the correction is committed and pushed.", + "repository_edits_by_verifier": false, + "remote_writes_by_verifier": false, + "private_key_access": false, + "heavy_checks_rerun": false +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/evidence-retention.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/evidence-retention.json index 8cb5c6c0..63be0f00 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/evidence-retention.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/evidence-retention.json @@ -25,5 +25,17 @@ "sha256": "99ed5253bec64abdf7ca64dc54a3a950acac5365bde6b61aac1c901ccfe0f020", "retention": "Preserved byte-for-byte locally, including original trailing whitespace; exact hosted signing log is run 38770474797, job 116549335673. Failure summary and independent verification are committed." } + ], + "json_wrapped_raw_logs": [ + { + "original": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before.log", + "committed": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before-log.json", + "sha256": "9172cdd7e88908a0dc53752ed33dfdd720201789a9e9b395cbc35e9e38f79efa" + }, + { + "original": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1.log", + "committed": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1-log.json", + "sha256": "1c8e7f3d8a72365cd32beadd052b33c381355f03c4499312fdcdd0670821b901" + } ] } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/pr-ci-first-failure.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/pr-ci-first-failure.json new file mode 100644 index 00000000..edf4d2ef --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/pr-ci-first-failure.json @@ -0,0 +1,12 @@ +{ + "recorded_at_utc": "2026-10-16T05:40:11.703734+00:00", + "run_id": 38856649852, + "job_id": 116829504780, + "head_sha": "2b62dbec3f306328098c41d3fdde9894acc98e0f", + "url": "https://github.com/IchenDEV/utter/actions/runs/38856649852/job/116829504780", + "first_failure": "Repository conflict-marker scan matched unittest separators in two newly tracked raw evidence logs", + "unit_test_step": "Skipped after basic-check failure", + "raw_log_local_path": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-pr-bot_2ek2/ci-quality-attempt-1.log", + "raw_log_sha256": "9df5b899c3aab581380d8533afd2c7b8573e59d8e120447283474713cebb7533", + "remedy": "Keep original raw logs locally and commit lossless JSON representations; retain unchanged conflict-marker guard and production/test code" +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before-log.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before-log.json new file mode 100644 index 00000000..44aeb469 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before-log.json @@ -0,0 +1,7 @@ +{ + "original_local_path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before.log", + "sha256": "9172cdd7e88908a0dc53752ed33dfdd720201789a9e9b395cbc35e9e38f79efa", + "encoding": "UTF-8", + "reason_for_json": "Preserve unittest separator lines without presenting them as repository conflict markers", + "content": "FFFFFF.\n======================================================================\nFAIL: test_certificate_match_is_required_without_expected_fingerprint (test_release_artifact.ReleaseArtifactTests.test_certificate_match_is_required_without_expected_fingerprint)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py\", line 125, in test_certificate_match_is_required_without_expected_fingerprint\n self.assertNotEqual(result.returncode, 0)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='unsigned')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='adhoc')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='untimestamped')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='mismatch')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='extract-failure')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n----------------------------------------------------------------------\nRan 3 tests in 11.983s\n\nFAILED (failures=6)\n" +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before.log deleted file mode 100644 index efa6e81f..00000000 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before.log +++ /dev/null @@ -1,74 +0,0 @@ -FFFFFF. -====================================================================== -FAIL: test_certificate_match_is_required_without_expected_fingerprint (test_release_artifact.ReleaseArtifactTests.test_certificate_match_is_required_without_expected_fingerprint) ----------------------------------------------------------------------- -Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py", line 125, in test_certificate_match_is_required_without_expected_fingerprint - self.assertNotEqual(result.returncode, 0) - ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^ -AssertionError: 0 == 0 - -====================================================================== -FAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='unsigned') ----------------------------------------------------------------------- -Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py", line 118, in test_invalid_container_stops_before_mounting - self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) - ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -AssertionError: 0 == 0 : Owned resources passed. -Owned resources passed. -Release artifact verification passed. - - -====================================================================== -FAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='adhoc') ----------------------------------------------------------------------- -Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py", line 118, in test_invalid_container_stops_before_mounting - self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) - ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -AssertionError: 0 == 0 : Owned resources passed. -Owned resources passed. -Release artifact verification passed. - - -====================================================================== -FAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='untimestamped') ----------------------------------------------------------------------- -Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py", line 118, in test_invalid_container_stops_before_mounting - self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) - ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -AssertionError: 0 == 0 : Owned resources passed. -Owned resources passed. -Release artifact verification passed. - - -====================================================================== -FAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='mismatch') ----------------------------------------------------------------------- -Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py", line 118, in test_invalid_container_stops_before_mounting - self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) - ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -AssertionError: 0 == 0 : Owned resources passed. -Owned resources passed. -Release artifact verification passed. - - -====================================================================== -FAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='extract-failure') ----------------------------------------------------------------------- -Traceback (most recent call last): - File "/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py", line 118, in test_invalid_container_stops_before_mounting - self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) - ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -AssertionError: 0 == 0 : Owned resources passed. -Owned resources passed. -Release artifact verification passed. - - ----------------------------------------------------------------------- -Ran 3 tests in 11.983s - -FAILED (failures=6) diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/verification.md b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/verification.md index 7f364912..da9799cd 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/verification.md +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/verification.md @@ -96,6 +96,12 @@ The runtime-canary witness parser initially expected JSON, while the existing canary binaries emit plain text. The parser was corrected before running the full suite. Both canaries passed; no private runtime policy was weakened. +The first PR CI attempt rejected unittest separator lines in two newly tracked +raw evidence logs as conflict markers. The original logs remain unchanged +locally; lossless JSON copies preserve their contents and SHA-256 in the PR. +The conflict-marker guard and reviewed production/test code are unchanged. +`evidence/pr-ci-first-failure.json` preserves the exact run, job, and cause. + ## Remaining gates Human verification acceptance is complete. The remote PR stage is authorized. From 95f63b2b967b6ce30107ab52d5287463b27f2425 Mon Sep 17 00:00:00 2001 From: idevlab Date: Fri, 16 Oct 2026 13:58:28 +0800 Subject: [PATCH 3/3] docs: sanitize public evidence and adopt single-maintainer gates --- AGENTS.md | 2 +- .../evidence/full-test-evidence.json | 8 +- .../independent-final-run-readback.json | 8 +- .../evidence/main-branch-after.json | 12 +- .../evidence/release-basic-checks.log | 4 +- .../verification.md | 2 +- .../basic-checks-python39-attempt-1-log.json | 9 +- .../evidence/basic-checks.log | 4 +- .../evidence/full-test-evidence.json | 8 +- .../implementation-final-verification.json | 8 +- .../evidence/local-checks-summary.json | 10 +- .../local-release-build-attempt-1.json | 8 +- .../local-release-build-attempt-1.log | 42 +++--- .../evidence/local-release-build.json | 8 +- .../evidence/local-release-build.log | 74 ++++----- .../evidence/native-dmg-progress.json | 50 +++--- .../evidence/native-dmg-verification.json | 58 +++---- .../evidence/native-independent-rerun.json | 60 ++++---- .../native-suite-independent-review.json | 8 +- .../evidence/native-suite-preflight.json | 8 +- .../evidence/native-tests-run.log | 2 +- ...e-and-single-maintainer-authorization.json | 18 +++ .../evidence/pr-ci-code-verification.json | 22 +++ .../evidence/pr-ci-first-failure.json | 8 +- .../evidence/protected-swift-test.json | 8 +- .../evidence/protected-swift-test.log | 2 +- .../evidence/public-audit-independent.json | 67 +++++++++ .../evidence/public-disclosure-audit.json | 20 +++ .../evidence/public-redaction-manifest.json | 142 ++++++++++++++++++ .../regression-verifier-before-log.json | 9 +- .../evidence/regression-workflow-after.log | 4 +- .../evidence/regression-workflow-before.log | 6 +- .../evidence/single-maintainer-controls.json | 56 +++++++ .../plan.md | 17 ++- .../spec.md | 18 ++- .../verification.md | 33 +++- docs/sdlc/github-controls.md | 15 +- docs/sdlc/review-policy.md | 5 +- 38 files changed, 644 insertions(+), 199 deletions(-) create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/owner-merge-and-single-maintainer-authorization.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/pr-ci-code-verification.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/public-audit-independent.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/public-disclosure-audit.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/public-redaction-manifest.json create mode 100644 docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/single-maintainer-controls.json diff --git a/AGENTS.md b/AGENTS.md index ee06ba3f..de74a6b8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -58,7 +58,7 @@ Tests use owner modules directly. Construction fixtures under `Tests/OpenTypeTes - **Every stage requires explicit human approval before the next one starts.** Set the artifact's `Status: pending approval` and stop for the user's decision; never mark a stage `approved` on the user's behalf. `approved` requires `Approved-by` and `Approved-date`. Artifacts without a Status header are legacy merged bundles. - Begin implementation only after intent has observable acceptance criteria and medium/high-risk design choices have been reviewed. - Always run `bash scripts/sdlc-checks.sh`, `bash scripts/ci-basic-checks.sh`, and `swift test`. Add release-style build, real-window visual QA, permission/privacy paths, or clean-machine checks in proportion to risk. -- High-risk changes require an independent verifier, explicit rollback, PR approval, and protected production approval. +- High-risk changes require an independent verifier, explicit rollback, the owner's explicit merge authorization, and protected production approval. This single-maintainer repository requires PRs and passing CI, but not a separate GitHub approving reviewer; see `docs/sdlc/github-controls.md`. - A production incident must link a corrective intent and add a regression test, deterministic guardrail, eval case, or explicit reason automation is impossible. - Never fall back to ad-hoc signing when configured signing fails. A self-signed release must use the configured identity, pass the same artifact/checksum checks, and be labeled as not Apple-notarized. diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/full-test-evidence.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/full-test-evidence.json index 96336488..58358866 100644 --- a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/full-test-evidence.json +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/full-test-evidence.json @@ -8,6 +8,10 @@ "empty_swift_testing_bundles": 13, "complete": true, "test_bundle_hashes_unchanged": true, - "native_evidence": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/native-run-9d5cbdd1", - "swiftpm_wrapper": "blocked before test execution by nested sandbox_apply; preserved in swift-test.log" + "native_evidence": "TASK_TMP/utter-developer-id-ci-evidence-8lm_1sy5/native-run-9d5cbdd1", + "swiftpm_wrapper": "blocked before test execution by nested sandbox_apply; preserved in swift-test.log", + "_public_redaction": { + "original_sha256": "4837b5e5549a9387fb11c26b7c00fc52d776f24a8da111d73888743675e293e0", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-run-readback.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-run-readback.json index ae10db9a..85512e66 100644 --- a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-run-readback.json +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-run-readback.json @@ -84,11 +84,11 @@ "timestamp": "2026-10-10T21:48:02Z", "author": { "name": "idevlab", - "email": "idevlab@outlook.com" + "email": "REDACTED_COMMIT_EMAIL" }, "committer": { "name": "GitHub", - "email": "noreply@github.com" + "email": "REDACTED_COMMIT_EMAIL" } }, "repository": { @@ -226,5 +226,9 @@ "labels_url": "https://api.github.com/repos/IchenDEV/utter/labels{/name}", "releases_url": "https://api.github.com/repos/IchenDEV/utter/releases{/id}", "deployments_url": "https://api.github.com/repos/IchenDEV/utter/deployments" + }, + "_public_redaction": { + "original_sha256": "ee6f284818a79af6946d76ac4a056f4451fc3944f2205ba0a87c9aa476c6fb89", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" } } diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-branch-after.json b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-branch-after.json index cae038e5..4f6047ae 100644 --- a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-branch-after.json +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-branch-after.json @@ -6,12 +6,12 @@ "commit": { "author": { "name": "idevlab", - "email": "idevlab@outlook.com", + "email": "REDACTED_COMMIT_EMAIL", "date": "2026-10-10T21:48:02Z" }, "committer": { "name": "GitHub", - "email": "noreply@github.com", + "email": "REDACTED_COMMIT_EMAIL", "date": "2026-10-10T21:48:02Z" }, "message": "Merge pull request #122 from IchenDEV/t3/xiaomi-remote-mic", @@ -25,7 +25,7 @@ "verified": true, "reason": "valid", "signature": "-----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJqyrKSCRC1aQ7uu5UhlAAAWa0QADaPWzjZ+YIRpSdBmaCHTpD1\nzciZRQRFfYUxZdVialOt4ioYTsItCA/jp604fleQLxQ280jyCpfE37uCd0TRYJB7\nryAVh9gh2271Luy35Che25AgB4e/5CQGBYlJ1Ec5v950uTl/kAcFv7DhU019xbBz\niDnD+mrRp32NXcSLesdxlMuVMHg3HXE0lagSQzJR9N0EV6e9cei3BSNGdvMDzRZg\nQQeXdzWCT1veuliv7fnRFzTcZj19WI+TyoX/7ncfTfQ7ZuXzHPmhw/l8w3VVSCkN\n5f7Gyqf+JVNJHlQph0Aqy2meTavvcRs8jbfV1nbphdAZNwtT3aajUJTzjaenvb9n\nWPNYB5cEsmtjs1yeGMS9v9NeerDndahGCLMciYAvN+TAzVjixxeYoQTGAs4QjbCm\nUWqerS2nWVphw+1xOP70S+hsDBZmCfPrmLbXBwITaGi3twmrazIeJu0KIoTrpkWm\n89lkKHl7oHwVnnngKF13iWP4fE6LeXtkCa7BVrd40nDV9o9tGNKQOo0B+WzyPqdJ\n7WtXYbghtg5+mj7eSfIaQOTnW+AKyqWA9/gRFIRnRUupYxM5a/CpI0APg2xK3T2r\nHshdFHa8ItL/QFtzdUKG1rQMsN1tMtVJUPJl6EL0JTTqaLJI55YBzzhsnV3J0PB3\nDCkICq62tK+fBCmJpC3f\n=nBOV\n-----END PGP SIGNATURE-----\n", - "payload": "tree 12783f01e00ad57369e15dad78868dbeee761479\nparent 64817558dc1e50911a198e0025bee6d6cafdea6d\nparent 51f7f10ae24d9001911840c826a57211ff41a2dd\nauthor idevlab 1791668882 +0800\ncommitter GitHub 1791668882 +0800\n\nMerge pull request #122 from IchenDEV/t3/xiaomi-remote-mic", + "payload": "tree 12783f01e00ad57369e15dad78868dbeee761479\nparent 64817558dc1e50911a198e0025bee6d6cafdea6d\nparent 51f7f10ae24d9001911840c826a57211ff41a2dd\nauthor idevlab 1791668882 +0800\ncommitter GitHub 1791668882 +0800\n\nMerge pull request #122 from IchenDEV/t3/xiaomi-remote-mic", "verified_at": "2026-10-10T21:48:02Z" } }, @@ -100,5 +100,9 @@ "checks": [] } }, - "protection_url": "https://api.github.com/repos/IchenDEV/utter/branches/main/protection" + "protection_url": "https://api.github.com/repos/IchenDEV/utter/branches/main/protection", + "_public_redaction": { + "original_sha256": "aa5341ddad3af0bc62da6bc4701441786bf3bd91f56d63c9a4ec7ca2d91487f4", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-basic-checks.log b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-basic-checks.log index dc8c3074..75d4875d 100644 --- a/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-basic-checks.log +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-basic-checks.log @@ -55,9 +55,9 @@ SDLC checks passed. Build version tests passed. Release version tests passed. Nightly release plan tests passed. -From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.o4WLIZxDtn/origin +From TASK_TMP/tmp.o4WLIZxDtn/origin * branch main -> FETCH_HEAD -From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.o4WLIZxDtn/origin +From TASK_TMP/tmp.o4WLIZxDtn/origin * branch main -> FETCH_HEAD Release workflow contract tests passed. diff --git a/docs/sdlc/changes/2026-10-15-developer-id-ci/verification.md b/docs/sdlc/changes/2026-10-15-developer-id-ci/verification.md index 81f685b1..8a3e5dfa 100644 --- a/docs/sdlc/changes/2026-10-15-developer-id-ci/verification.md +++ b/docs/sdlc/changes/2026-10-15-developer-id-ci/verification.md @@ -120,7 +120,7 @@ environments. Token rotation has not been performed by this task. ## Evidence location Public task evidence is at -`/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/`. +`TASK_TMP/utter-developer-id-ci-evidence-8lm_1sy5/`. The complete passing run is `native-run-9d5cbdd1/`, with per-bundle discovery, commands, completion records, and logs. No credential values belong in this verification document. diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1-log.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1-log.json index 36d9bca1..4007dfa0 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1-log.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1-log.json @@ -3,5 +3,12 @@ "sha256": "1c8e7f3d8a72365cd32beadd052b33c381355f03c4499312fdcdd0670821b901", "encoding": "UTF-8", "reason_for_json": "Preserve unittest separator lines without presenting them as repository conflict markers", - "content": "\n==> Checking Package.swift\nSwift module boundaries passed.\n......\n----------------------------------------------------------------------\nRan 6 tests in 0.002s\n\nOK\nOwned resources passed.\n.....\n----------------------------------------------------------------------\nRan 5 tests in 0.031s\n\nOK\nFFFFFF...................E\n======================================================================\nERROR: test_voice_quality_acceptance (unittest.loader._FailedTest)\n----------------------------------------------------------------------\nImportError: Failed to import test module: test_voice_quality_acceptance\nTraceback (most recent call last):\n File \"/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/unittest/loader.py\", line 436, in _find_test_path\n module = self._get_module_from_name(name)\n File \"/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/unittest/loader.py\", line 377, in _get_module_from_name\n __import__(name)\n File \"/Users/chenli/projects/utter/scripts/tests/test_voice_quality_acceptance.py\", line 6, in \n from voice_quality_acceptance import REQUIRED_DEMOS, acceptance_report\n File \"/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n======================================================================\nFAIL: test_fidelity_preserves_sentence_email_opaque_paths_and_quotes (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py\", line 145, in test_fidelity_preserves_sentence_email_opaque_paths_and_quotes\n self.assertEqual(result.returncode, 0, result.stderr)\nAssertionError: 1 != 0 : Traceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py\", line 14, in \n from voice_quality_acceptance import acceptance_report\n File \"/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n======================================================================\nFAIL: test_fidelity_rejects_added_numbers_and_changed_unicode_space_path (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py\", line 103, in test_fidelity_rejects_added_numbers_and_changed_unicode_space_path\n self.assertEqual(result.returncode, 0, result.stderr)\nAssertionError: 1 != 0 : Traceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py\", line 14, in \n from voice_quality_acceptance import acceptance_report\n File \"/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n======================================================================\nFAIL: test_fidelity_rejects_reordered_number_ownership (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py\", line 169, in test_fidelity_rejects_reordered_number_ownership\n self.assertEqual(result.returncode, 0, result.stderr)\nAssertionError: 1 != 0 : Traceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py\", line 14, in \n from voice_quality_acceptance import acceptance_report\n File \"/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n======================================================================\nFAIL: test_help_documents_schema (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py\", line 189, in test_help_documents_schema\n self.assertEqual(result.returncode, 0)\nAssertionError: 1 != 0\n\n======================================================================\nFAIL: test_rejects_missing_required_field_with_line_number (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py\", line 178, in test_rejects_missing_required_field_with_line_number\n self.assertEqual(result.returncode, 2)\nAssertionError: 1 != 2\n\n======================================================================\nFAIL: test_reports_asr_processed_fidelity_hallucination_and_latency (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_evaluate_voice_quality.py\", line 61, in test_reports_asr_processed_fidelity_hallucination_and_latency\n self.assertEqual(result.returncode, 0, result.stderr)\nAssertionError: 1 != 0 : Traceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/evaluate-voice-quality.py\", line 14, in \n from voice_quality_acceptance import acceptance_report\n File \"/Users/chenli/projects/utter/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n----------------------------------------------------------------------\nRan 26 tests in 17.409s\n\nFAILED (failures=6, errors=1)\n" + "content": "\n==> Checking Package.swift\nSwift module boundaries passed.\n......\n----------------------------------------------------------------------\nRan 6 tests in 0.002s\n\nOK\nOwned resources passed.\n.....\n----------------------------------------------------------------------\nRan 5 tests in 0.031s\n\nOK\nFFFFFF...................E\n======================================================================\nERROR: test_voice_quality_acceptance (unittest.loader._FailedTest)\n----------------------------------------------------------------------\nImportError: Failed to import test module: test_voice_quality_acceptance\nTraceback (most recent call last):\n File \"/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/unittest/loader.py\", line 436, in _find_test_path\n module = self._get_module_from_name(name)\n File \"/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/unittest/loader.py\", line 377, in _get_module_from_name\n __import__(name)\n File \"WORKSPACE/scripts/tests/test_voice_quality_acceptance.py\", line 6, in \n from voice_quality_acceptance import REQUIRED_DEMOS, acceptance_report\n File \"WORKSPACE/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n======================================================================\nFAIL: test_fidelity_preserves_sentence_email_opaque_paths_and_quotes (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"WORKSPACE/scripts/tests/test_evaluate_voice_quality.py\", line 145, in test_fidelity_preserves_sentence_email_opaque_paths_and_quotes\n self.assertEqual(result.returncode, 0, result.stderr)\nAssertionError: 1 != 0 : Traceback (most recent call last):\n File \"WORKSPACE/scripts/evaluate-voice-quality.py\", line 14, in \n from voice_quality_acceptance import acceptance_report\n File \"WORKSPACE/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n======================================================================\nFAIL: test_fidelity_rejects_added_numbers_and_changed_unicode_space_path (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"WORKSPACE/scripts/tests/test_evaluate_voice_quality.py\", line 103, in test_fidelity_rejects_added_numbers_and_changed_unicode_space_path\n self.assertEqual(result.returncode, 0, result.stderr)\nAssertionError: 1 != 0 : Traceback (most recent call last):\n File \"WORKSPACE/scripts/evaluate-voice-quality.py\", line 14, in \n from voice_quality_acceptance import acceptance_report\n File \"WORKSPACE/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n======================================================================\nFAIL: test_fidelity_rejects_reordered_number_ownership (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"WORKSPACE/scripts/tests/test_evaluate_voice_quality.py\", line 169, in test_fidelity_rejects_reordered_number_ownership\n self.assertEqual(result.returncode, 0, result.stderr)\nAssertionError: 1 != 0 : Traceback (most recent call last):\n File \"WORKSPACE/scripts/evaluate-voice-quality.py\", line 14, in \n from voice_quality_acceptance import acceptance_report\n File \"WORKSPACE/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n======================================================================\nFAIL: test_help_documents_schema (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"WORKSPACE/scripts/tests/test_evaluate_voice_quality.py\", line 189, in test_help_documents_schema\n self.assertEqual(result.returncode, 0)\nAssertionError: 1 != 0\n\n======================================================================\nFAIL: test_rejects_missing_required_field_with_line_number (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"WORKSPACE/scripts/tests/test_evaluate_voice_quality.py\", line 178, in test_rejects_missing_required_field_with_line_number\n self.assertEqual(result.returncode, 2)\nAssertionError: 1 != 2\n\n======================================================================\nFAIL: test_reports_asr_processed_fidelity_hallucination_and_latency (test_evaluate_voice_quality.VoiceQualityEvaluatorTests)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"WORKSPACE/scripts/tests/test_evaluate_voice_quality.py\", line 61, in test_reports_asr_processed_fidelity_hallucination_and_latency\n self.assertEqual(result.returncode, 0, result.stderr)\nAssertionError: 1 != 0 : Traceback (most recent call last):\n File \"WORKSPACE/scripts/evaluate-voice-quality.py\", line 14, in \n from voice_quality_acceptance import acceptance_report\n File \"WORKSPACE/scripts/voice_quality_acceptance.py\", line 8, in \n def acceptance_report(records: list[dict[str, Any]], manifest: dict[str, Any] | None) -> dict[str, Any]:\nTypeError: unsupported operand type(s) for |: 'types.GenericAlias' and 'NoneType'\n\n\n----------------------------------------------------------------------\nRan 26 tests in 17.409s\n\nFAILED (failures=6, errors=1)\n", + "_public_redaction": { + "original_sha256": "4304c14bc9bb34eab55c259775fb9e017ed16f0fdfec09a49dd53432dba93845", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + }, + "content_is_sanitized": true, + "sha256_scope": "original private raw log", + "published_content_sha256": "d6e0175685d20ed1e5ff5a29db15cf392a1a6ab0a8853f11a4746f239f141759" } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks.log index b3ef88df..9bd79d06 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks.log +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks.log @@ -56,9 +56,9 @@ SDLC checks passed. Build version tests passed. Release version tests passed. Nightly release plan tests passed. -From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.alrzU6hYot/origin +From TASK_TMP/tmp.alrzU6hYot/origin * branch main -> FETCH_HEAD -From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.alrzU6hYot/origin +From TASK_TMP/tmp.alrzU6hYot/origin * branch main -> FETCH_HEAD Signing mode: developer-id Signing mode: self-signed diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/full-test-evidence.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/full-test-evidence.json index 137626df..6995149a 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/full-test-evidence.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/full-test-evidence.json @@ -1,5 +1,5 @@ { - "native_evidence": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/native-run-f8535155", + "native_evidence": "TASK_TMP/utter-developer-id-ci-evidence-8lm_1sy5/native-run-f8535155", "xctest_bundles": 14, "xctest_executed": 1143, "xctest_skipped": 17, @@ -10,5 +10,9 @@ "complete": true, "frozen_bundle_files_unchanged": 300, "runtime_preflight": "native-suite-preflight.json", - "standard_swift_test": "Separate protected-wrapper result; not inferred from native engines." + "standard_swift_test": "Separate protected-wrapper result; not inferred from native engines.", + "_public_redaction": { + "original_sha256": "edf8da0d2dd5be877621e475a48ba26425ad3b48a0f7803d4ae3bbccbf7e9edb", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-final-verification.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-final-verification.json index 9fa82483..cd716601 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-final-verification.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-final-verification.json @@ -28,7 +28,7 @@ "fixture_files_hashed": 44, "dmg_sha256": "24765f7ce54b07cb7b1c9427d8e67cdbcf9df270e8011bb8d82e7e2049a89101", "own_mounts_remaining": [], - "probe_directory": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx", + "probe_directory": "TASK_TMP/utter-dmg-independent-verifier-6rohbzkx", "report": "native-independent-rerun.json" }, "native_mismatch_boundary": "Actual verifier controlled-tool fixtures cover mismatch including no expected-fingerprint option. No second real Developer ID identity is claimed.", @@ -95,5 +95,9 @@ "protected-swift-test.json", "full-test-evidence.json" ], - "git_status_snapshot": " M .github/workflows/release-artifact.yml\n M scripts/tests/test_release_workflow_contract.sh\n M scripts/verify-release-artifact.sh\n?? docs/sdlc/changes/2026-10-15-developer-id-ci/\n?? docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/\n?? scripts/tests/test_release_artifact.py\n" + "git_status_snapshot": " M .github/workflows/release-artifact.yml\n M scripts/tests/test_release_workflow_contract.sh\n M scripts/verify-release-artifact.sh\n?? docs/sdlc/changes/2026-10-15-developer-id-ci/\n?? docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/\n?? scripts/tests/test_release_artifact.py\n", + "_public_redaction": { + "original_sha256": "0c9ebf7aa8c3098a414cb367d9a6399cc32ffa7d92c6ccc6342f55908bf0c25f", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-checks-summary.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-checks-summary.json index d4d6abfb..085c8d94 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-checks-summary.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-checks-summary.json @@ -16,7 +16,7 @@ "log_sha256": "9abda60c70729ffcc3d95107783ba5b23ca5f3e695a260697c0c3a82e20923e8" }, "swift": { - "native_evidence": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/native-run-f8535155", + "native_evidence": "TASK_TMP/utter-developer-id-ci-evidence-8lm_1sy5/native-run-f8535155", "xctest_bundles": 14, "xctest_executed": 1143, "xctest_skipped": 17, @@ -33,7 +33,7 @@ "command": [ "/usr/bin/sandbox-exec", "-f", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/test-runtime-narrow.sb", + "TASK_TMP/utter-developer-id-ci-evidence-8lm_1sy5/test-runtime-narrow.sb", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift", "test", "--skip-build", @@ -48,5 +48,9 @@ "native_dmg_result": true, "package_resolved_sha256": "3a007c520b8b69aa9a675a42675662d7d272e4808dd3e71e4f12e074150219ad", "remote_source_writes_performed": false, - "new_release_created": false + "new_release_created": false, + "_public_redaction": { + "original_sha256": "8b85b3c1c2e1202f88cdad68e17740d8b09df91e16cdfc091b67fc195c596c76", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.json index 061bdbbe..eed38656 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.json @@ -10,6 +10,10 @@ "exit": -15, "guard_failure": null, "lockfile_unchanged": true, - "log": "/Users/chenli/projects/utter/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log", - "disk_free_bytes": 21671313408 + "log": "WORKSPACE/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log", + "disk_free_bytes": 21671313408, + "_public_redaction": { + "original_sha256": "c1cba81b6c8aef2d7dd9a595feb00e10be7ecf03cecb7e028a68051b92dd72a2", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.log index 38b21859..fae5372a 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.log +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.log @@ -10,25 +10,25 @@ { platform:macOS, arch:arm64, variant:Designed for [iPad,iPhone], id:00008132-001828593639001C, name:My Mac } { platform:macOS, arch:arm64e.x1, variant:Designed for [iPad,iPhone], id:00008132-001828593639001C, name:My Mac } { platform:macOS, arch:arm64_32, variant:Designed for [iPad,iPhone], id:00008132-001828593639001C, name:My Mac } -In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/steel_attention.metal:6: -In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:3: -In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/attn.h:6: -In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/../../steel/attn/mma.h:11: -/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/../../steel/utils/integral_constant.h:108:6: warning: constexpr if is a C++17 extension [-Wc++17-extensions] +In file included from WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/steel_attention.metal:6: +In file included from WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:3: +In file included from WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/attn.h:6: +In file included from WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/../../steel/attn/mma.h:11: +WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/../../steel/utils/integral_constant.h:108:6: warning: constexpr if is a C++17 extension [-Wc++17-extensions] if constexpr (start < stop) { ^ -In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/steel_attention.metal:6: -/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:356:16: warning: constexpr if is a C++17 extension [-Wc++17-extensions] +In file included from WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/steel_attention.metal:6: +WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:356:16: warning: constexpr if is a C++17 extension [-Wc++17-extensions] if constexpr (is_bool) { ^ -/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:426:14: warning: constexpr if is a C++17 extension [-Wc++17-extensions] +WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:426:14: warning: constexpr if is a C++17 extension [-Wc++17-extensions] if constexpr (BD == 128) { ^ -/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:436:14: warning: constexpr if is a C++17 extension [-Wc++17-extensions] +WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:436:14: warning: constexpr if is a C++17 extension [-Wc++17-extensions] if constexpr (BD == 128) { ^ 4 warnings generated. -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Benchmark.swift:29:53: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+Benchmark.swift:29:53: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 27 | } 28 | return try await withLocalModelAccess { 29 | let provider = try await self.providers.create(id: "generation.mlx", request: .benchmark) @@ -36,7 +36,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 30 | return try await ModelBenchmarkSuite.run(workloads: workloads, provider: provider) 31 | } -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+FactSupport.swift:29:34: warning: reference to captured var 'checkOptions' in concurrently-executing code; this is an error in the Swift 6 language mode [#SendableClosureCaptures] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+FactSupport.swift:29:34: warning: reference to captured var 'checkOptions' in concurrently-executing code; this is an error in the Swift 6 language mode [#SendableClosureCaptures] 27 | try await withOperationDeadline(for: ProcessingDeadlines.factSupport) { 28 | try await self.generateText(prompt: prompt, systemPrompt: PromptCatalog.factSupportSystemPrompt, 29 | options: checkOptions, maxTokens: 768, temperature: 0) @@ -44,7 +44,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 30 | } 31 | } -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:60:43: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:60:43: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 58 | maxTokens: maxTokens, temperature: temperature 59 | ) 60 | let primary = try await providers.create(id: providerID, request: .inference) @@ -52,7 +52,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 61 | try Task.checkCancellation() 62 | guard usesANE else { -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:81:65: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:81:65: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 79 | prepareForMLXFallback: { await primary.unload() }, 80 | mlx: { 81 | let fallback = try await self.providers.create(id: options.fallbackProviderID, request: .inference) @@ -60,7 +60,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 82 | try Task.checkCancellation() 83 | return try await ProcessingObservations.$generationStage.withValue(.fallback) { -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:128:49: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:128:49: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 126 | ) 127 | guard let imageProviders else { throw GenerationServiceError.unsupportedOperation } 128 | let provider = try await imageProviders.create(id: providerID, request: .inference) @@ -68,7 +68,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 129 | try Task.checkCancellation() 130 | let result = try await ProcessingObservations.$generationStage.withValue(.image) { -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+ModelPreparation.swift:11:52: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+ModelPreparation.swift:11:52: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 9 | maxTokens: 1, temperature: 0, usesANE: usesANE) 10 | return try await withLocalModelAccess { 11 | let primary = try await self.providers.create(id: id, request: .inference) @@ -76,7 +76,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 12 | guard usesANE else { try await primary.prepare(request); return nil } 13 | let result = try await GenerationFallback.run(fallbackEnabled: options.fallbackToMLXOnEspressoFailure, -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+ModelPreparation.swift:16:61: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+ModelPreparation.swift:16:61: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 14 | espresso: { try await primary.prepare(request) }, prepareForMLXFallback: { await primary.unload() }, 15 | mlx: { 16 | let fallback = try await self.providers.create(id: options.fallbackProviderID, request: .inference) @@ -84,7 +84,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 17 | let request = self.generationRequest(prompt: "", systemPrompt: nil, options: options, maxTokens: 1, temperature: 0) 18 | try await fallback.prepare(request) -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Models.swift:37:42: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+Models.swift:37:42: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 35 | try await withLocalModelAccess { 36 | for descriptor in await self.providers.descriptors { 37 | try await self.providers.reset(id: descriptor.id) @@ -92,7 +92,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 38 | } 39 | if let images = self.imageProviders { -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Models.swift:40:79: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+Models.swift:40:79: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 38 | } 39 | if let images = self.imageProviders { 40 | for descriptor in await images.descriptors { try await images.reset(id: descriptor.id) } @@ -102,14 +102,14 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c [#IsolatedConformances]: [#SendableClosureCaptures]: -/Users/chenli/projects/utter/Sources/UtterMacServices/CorrectionCaptureRegion.swift:75:5: warning: 'package' modifier conflicts with extension's default access of 'private' +WORKSPACE/Sources/UtterMacServices/CorrectionCaptureRegion.swift:75:5: warning: 'package' modifier conflicts with extension's default access of 'private' 73 | } 74 | private extension CorrectionCaptureRegionLocator { 75 | package func nearbyRange( | `- warning: 'package' modifier conflicts with extension's default access of 'private' 76 | of needle: String, 77 | in text: NSString, -/Users/chenli/projects/utter/Sources/UtterIngress/Native/IntegrationXPCServer.swift:97:61: warning: variable 'handler' was written to, but never read +WORKSPACE/Sources/UtterIngress/Native/IntegrationXPCServer.swift:97:61: warning: variable 'handler' was written to, but never read 95 | connection.exportedInterface = NSXPCInterface(with: OpenTypeXPCProtocol.self) 96 | connection.exportedObject = handler 97 | connection.invalidationHandler = { [weak self, weak handler] in @@ -117,7 +117,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 98 | Task { @MainActor in 99 | self?.retire(id) -/Users/chenli/projects/utter/Sources/UtterIngress/Native/IntegrationXPCServer.swift:102:61: warning: variable 'handler' was written to, but never read +WORKSPACE/Sources/UtterIngress/Native/IntegrationXPCServer.swift:102:61: warning: variable 'handler' was written to, but never read 100 | } 101 | } 102 | connection.interruptionHandler = { [weak self, weak handler] in diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.json index df9423c6..8a9c2b71 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.json @@ -11,6 +11,10 @@ "exit": 0, "guard_failure": null, "lockfile_unchanged": true, - "log": "/Users/chenli/projects/utter/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log", - "disk_free_bytes": 19542142976 + "log": "WORKSPACE/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log", + "disk_free_bytes": 19542142976, + "_public_redaction": { + "original_sha256": "4edb304564c3f2c96090e56f2da427bf029473c7aa3b4aa376972bd931927250", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log index 6647c89d..11ae5469 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log @@ -10,25 +10,25 @@ { platform:macOS, arch:arm64, variant:Designed for [iPad,iPhone], id:00008132-001828593639001C, name:My Mac } { platform:macOS, arch:arm64e.x1, variant:Designed for [iPad,iPhone], id:00008132-001828593639001C, name:My Mac } { platform:macOS, arch:arm64_32, variant:Designed for [iPad,iPhone], id:00008132-001828593639001C, name:My Mac } -In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/steel_attention.metal:6: -In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:3: -In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/attn.h:6: -In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/../../steel/attn/mma.h:11: -/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/../../steel/utils/integral_constant.h:108:6: warning: constexpr if is a C++17 extension [-Wc++17-extensions] +In file included from WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/steel_attention.metal:6: +In file included from WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:3: +In file included from WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/attn.h:6: +In file included from WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/../../steel/attn/mma.h:11: +WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/../../steel/utils/integral_constant.h:108:6: warning: constexpr if is a C++17 extension [-Wc++17-extensions] if constexpr (start < stop) { ^ -In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/steel_attention.metal:6: -/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:356:16: warning: constexpr if is a C++17 extension [-Wc++17-extensions] +In file included from WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/steel_attention.metal:6: +WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:356:16: warning: constexpr if is a C++17 extension [-Wc++17-extensions] if constexpr (is_bool) { ^ -/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:426:14: warning: constexpr if is a C++17 extension [-Wc++17-extensions] +WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:426:14: warning: constexpr if is a C++17 extension [-Wc++17-extensions] if constexpr (BD == 128) { ^ -/Users/chenli/projects/utter/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:436:14: warning: constexpr if is a C++17 extension [-Wc++17-extensions] +WORKSPACE/.build/xcode/SourcePackages/checkouts/mlx-swift/Source/Cmlx/mlx-generated/metal/steel/attn/kernels/../../../steel/attn/kernels/steel_attention.h:436:14: warning: constexpr if is a C++17 extension [-Wc++17-extensions] if constexpr (BD == 128) { ^ 4 warnings generated. -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Benchmark.swift:29:53: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+Benchmark.swift:29:53: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 27 | } 28 | return try await withLocalModelAccess { 29 | let provider = try await self.providers.create(id: "generation.mlx", request: .benchmark) @@ -36,7 +36,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 30 | return try await ModelBenchmarkSuite.run(workloads: workloads, provider: provider) 31 | } -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+FactSupport.swift:29:34: warning: reference to captured var 'checkOptions' in concurrently-executing code; this is an error in the Swift 6 language mode [#SendableClosureCaptures] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+FactSupport.swift:29:34: warning: reference to captured var 'checkOptions' in concurrently-executing code; this is an error in the Swift 6 language mode [#SendableClosureCaptures] 27 | try await withOperationDeadline(for: ProcessingDeadlines.factSupport) { 28 | try await self.generateText(prompt: prompt, systemPrompt: PromptCatalog.factSupportSystemPrompt, 29 | options: checkOptions, maxTokens: 768, temperature: 0) @@ -44,7 +44,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 30 | } 31 | } -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:60:43: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:60:43: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 58 | maxTokens: maxTokens, temperature: temperature 59 | ) 60 | let primary = try await providers.create(id: providerID, request: .inference) @@ -52,7 +52,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 61 | try Task.checkCancellation() 62 | guard usesANE else { -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:81:65: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:81:65: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 79 | prepareForMLXFallback: { await primary.unload() }, 80 | mlx: { 81 | let fallback = try await self.providers.create(id: options.fallbackProviderID, request: .inference) @@ -60,7 +60,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 82 | try Task.checkCancellation() 83 | return try await ProcessingObservations.$generationStage.withValue(.fallback) { -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:128:49: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+Generation.swift:128:49: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 126 | ) 127 | guard let imageProviders else { throw GenerationServiceError.unsupportedOperation } 128 | let provider = try await imageProviders.create(id: providerID, request: .inference) @@ -68,7 +68,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 129 | try Task.checkCancellation() 130 | let result = try await ProcessingObservations.$generationStage.withValue(.image) { -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+ModelPreparation.swift:11:52: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+ModelPreparation.swift:11:52: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 9 | maxTokens: 1, temperature: 0, usesANE: usesANE) 10 | return try await withLocalModelAccess { 11 | let primary = try await self.providers.create(id: id, request: .inference) @@ -76,7 +76,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 12 | guard usesANE else { try await primary.prepare(request); return nil } 13 | let result = try await GenerationFallback.run(fallbackEnabled: options.fallbackToMLXOnEspressoFailure, -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+ModelPreparation.swift:16:61: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+ModelPreparation.swift:16:61: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 14 | espresso: { try await primary.prepare(request) }, prepareForMLXFallback: { await primary.unload() }, 15 | mlx: { 16 | let fallback = try await self.providers.create(id: options.fallbackProviderID, request: .inference) @@ -84,7 +84,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 17 | let request = self.generationRequest(prompt: "", systemPrompt: nil, options: options, maxTokens: 1, temperature: 0) 18 | try await fallback.prepare(request) -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Models.swift:37:42: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+Models.swift:37:42: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 35 | try await withLocalModelAccess { 36 | for descriptor in await self.providers.descriptors { 37 | try await self.providers.reset(id: descriptor.id) @@ -92,7 +92,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 38 | } 39 | if let images = self.imageProviders { -/Users/chenli/projects/utter/Sources/UtterProcessing/Native/TextProcessor+Models.swift:40:79: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] +WORKSPACE/Sources/UtterProcessing/Native/TextProcessor+Models.swift:40:79: warning: conformance of 'τ_1_0' to protocol 'ProviderCatalog' may be isolated and cannot be passed to main actor-isolated context [#IsolatedConformances] 38 | } 39 | if let images = self.imageProviders { 40 | for descriptor in await images.descriptors { try await images.reset(id: descriptor.id) } @@ -102,14 +102,14 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c [#IsolatedConformances]: [#SendableClosureCaptures]: -/Users/chenli/projects/utter/Sources/UtterMacServices/CorrectionCaptureRegion.swift:75:5: warning: 'package' modifier conflicts with extension's default access of 'private' +WORKSPACE/Sources/UtterMacServices/CorrectionCaptureRegion.swift:75:5: warning: 'package' modifier conflicts with extension's default access of 'private' 73 | } 74 | private extension CorrectionCaptureRegionLocator { 75 | package func nearbyRange( | `- warning: 'package' modifier conflicts with extension's default access of 'private' 76 | of needle: String, 77 | in text: NSString, -/Users/chenli/projects/utter/Sources/UtterIngress/Native/IntegrationXPCServer.swift:97:61: warning: variable 'handler' was written to, but never read +WORKSPACE/Sources/UtterIngress/Native/IntegrationXPCServer.swift:97:61: warning: variable 'handler' was written to, but never read 95 | connection.exportedInterface = NSXPCInterface(with: OpenTypeXPCProtocol.self) 96 | connection.exportedObject = handler 97 | connection.invalidationHandler = { [weak self, weak handler] in @@ -117,7 +117,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 98 | Task { @MainActor in 99 | self?.retire(id) -/Users/chenli/projects/utter/Sources/UtterIngress/Native/IntegrationXPCServer.swift:102:61: warning: variable 'handler' was written to, but never read +WORKSPACE/Sources/UtterIngress/Native/IntegrationXPCServer.swift:102:61: warning: variable 'handler' was written to, but never read 100 | } 101 | } 102 | connection.interruptionHandler = { [weak self, weak handler] in @@ -126,7 +126,7 @@ In file included from /Users/chenli/projects/utter/.build/xcode/SourcePackages/c 104 | self?.retire(id) error: the following command failed with exit code 0 but produced no further output SwiftCompile normal arm64 (in target 'UtterModels' from project 'OpenType') -/Users/chenli/projects/utter/Sources/UtterModels/Native/DownloadStallWatchdog.swift:24:59: warning: reference to property 'pollInterval' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode +WORKSPACE/Sources/UtterModels/Native/DownloadStallWatchdog.swift:24:59: warning: reference to property 'pollInterval' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in the Swift 6 language mode 22 | pollTask = Task { @MainActor [weak self] in 23 | while !Task.isCancelled { 24 | try? await Task.sleep(nanoseconds: UInt64(pollInterval * 1_000_000_000)) @@ -164,32 +164,32 @@ Build complete! (6.45秒) ✓ AppIcon compiled to Assets.car (system appearances) ▶ Code signing (hardened runtime + entitlements)… -/Users/chenli/projects/utter/dist/Utter.app: replacing existing signature +WORKSPACE/dist/Utter.app: replacing existing signature ✓ Signed with: 0A1A804E9C5D7BE644E4A6B884487BB5191F691D (hardened runtime) ▶ Creating DMG… -DMG background -> /Users/chenli/projects/utter/.build/xcode/dmg-background/installer-background.png -DMG background -> /Users/chenli/projects/utter/.build/xcode/dmg-background/installer-background@2x.png +DMG background -> WORKSPACE/.build/xcode/dmg-background/installer-background.png +DMG background -> WORKSPACE/.build/xcode/dmg-background/installer-background@2x.png hdiutil: WARNING: 'hdiutil create -volname -size ...' is deprecated. Please use 'diskutil image create from/blank --volumeName -size ...' instead. hdiutil: WARNING: 'hdiutil attach -nobrowse -owners ...' is deprecated. Please use 'diskutil image attach --mountOptions nobrowse --mountOptions owners ...' instead. hdiutil: WARNING: 'hdiutil convert -format ...' is deprecated. Please use 'diskutil image create from --format ...' instead. ✓ DMG created Owned resources passed. ---prepared:/Users/chenli/projects/utter/dist/Utter.app/Contents/MacOS/opentype-cli ---validated:/Users/chenli/projects/utter/dist/Utter.app/Contents/MacOS/opentype-cli -/Users/chenli/projects/utter/dist/Utter.app: valid on disk -/Users/chenli/projects/utter/dist/Utter.app: satisfies its Designated Requirement -hdiutil: verify: checksum of "/Users/chenli/projects/utter/dist/Utter-0.0.54.dmg" is VALID +--prepared:WORKSPACE/dist/Utter.app/Contents/MacOS/opentype-cli +--validated:WORKSPACE/dist/Utter.app/Contents/MacOS/opentype-cli +WORKSPACE/dist/Utter.app: valid on disk +WORKSPACE/dist/Utter.app: satisfies its Designated Requirement +hdiutil: verify: checksum of "WORKSPACE/dist/Utter-0.0.54.dmg" is VALID Owned resources passed. ---prepared:/private/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.XqYxwSowRo/Utter.app/Contents/MacOS/opentype-cli ---validated:/private/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.XqYxwSowRo/Utter.app/Contents/MacOS/opentype-cli -/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.XqYxwSowRo/Utter.app: valid on disk -/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.XqYxwSowRo/Utter.app: satisfies its Designated Requirement +--prepared:TASK_TMP/tmp.XqYxwSowRo/Utter.app/Contents/MacOS/opentype-cli +--validated:TASK_TMP/tmp.XqYxwSowRo/Utter.app/Contents/MacOS/opentype-cli +TASK_TMP/tmp.XqYxwSowRo/Utter.app: valid on disk +TASK_TMP/tmp.XqYxwSowRo/Utter.app: satisfies its Designated Requirement Release artifact verification passed. ═══════════════════════════════════════════════════ - App: /Users/chenli/projects/utter/dist/Utter.app - DMG: /Users/chenli/projects/utter/dist/Utter-0.0.54.dmg + App: WORKSPACE/dist/Utter.app + DMG: WORKSPACE/dist/Utter-0.0.54.dmg - To install: open /Users/chenli/projects/utter/dist/Utter-0.0.54.dmg + To install: open WORKSPACE/dist/Utter-0.0.54.dmg ═══════════════════════════════════════════════════ diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-progress.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-progress.json index dfea2588..c5e66569 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-progress.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-progress.json @@ -1,25 +1,25 @@ { - "native_directory": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b", + "native_directory": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b", "results": [ { "name": "unsigned-rejected", "command": [ "bash", - "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "WORKSPACE/scripts/verify-release-artifact.sh", "--app", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", "--version", "0.0.54", "--require-developer-id", "--expected-cert-sha256", "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", "--dmg", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/unsigned.dmg" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/unsigned.dmg" ], "exit": 1, "expected_exit": 1, "diagnostic": "DMG signature is invalid", - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/unsigned-rejected.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/unsigned-rejected.log" }, { "name": "sign-without-timestamp", @@ -31,54 +31,54 @@ "--timestamp=none", "--identifier", "com.opentype.voiceinput.dmg", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" ], "exit": 0, "expected_exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/sign-without-timestamp.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/sign-without-timestamp.log" }, { "name": "untimestamped-rejected", "command": [ "bash", - "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "WORKSPACE/scripts/verify-release-artifact.sh", "--app", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", "--version", "0.0.54", "--require-developer-id", "--expected-cert-sha256", "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", "--dmg", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" ], "exit": 1, "expected_exit": 1, "diagnostic": "DMG signature has no secure timestamp", - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/untimestamped-rejected.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/untimestamped-rejected.log" }, { "name": "actual-shared-signing-block", "command": [ "bash", "-e", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/shared-signing-block.sh" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/shared-signing-block.sh" ], "exit": 0, "expected_exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/actual-shared-signing-block.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/actual-shared-signing-block.log" }, { "name": "matching-without-expected", "command": [ "bash", - "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "WORKSPACE/scripts/verify-release-artifact.sh", "--app", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", "--dmg", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg", "--version", "0.0.54", "--require-developer-id" @@ -86,32 +86,36 @@ "exit": 0, "expected_exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/matching-without-expected.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/matching-without-expected.log" }, { "name": "dmg-signature-metadata", "command": [ "/usr/bin/codesign", "-dvvv", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" ], "exit": 0, "expected_exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dmg-signature-metadata.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dmg-signature-metadata.log" }, { "name": "extract-native-dmg-certificate", "command": [ "/usr/bin/codesign", "-d", - "--extract-certificates=/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dmg-cert-", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + "--extract-certificates=TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dmg-cert-", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" ], "exit": 0, "expected_exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/extract-native-dmg-certificate.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/extract-native-dmg-certificate.log" } - ] + ], + "_public_redaction": { + "original_sha256": "584f2e8e4b746de595277aedd68dfb1e6e46b32dcf817cd383af7a79765f2bbd", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-verification.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-verification.json index 4246062a..7188e22a 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-verification.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-verification.json @@ -1,10 +1,10 @@ { "verified_at_utc": "2026-10-16T03:30:17.184449+00:00", - "native_directory": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b", - "app": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", - "signed_dmg": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg", - "unsigned_dmg": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/unsigned.dmg", - "untimestamped_dmg": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg", + "native_directory": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b", + "app": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "signed_dmg": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg", + "unsigned_dmg": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/unsigned.dmg", + "untimestamped_dmg": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg", "certificate_sha256": "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", "identity": "Developer ID Application: Chen Li (G9L7H3T3D5)", "team": "G9L7H3T3D5", @@ -15,21 +15,21 @@ "name": "unsigned-rejected", "command": [ "bash", - "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "WORKSPACE/scripts/verify-release-artifact.sh", "--app", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", "--version", "0.0.54", "--require-developer-id", "--expected-cert-sha256", "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", "--dmg", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/unsigned.dmg" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/unsigned.dmg" ], "exit": 1, "expected_exit": 1, "diagnostic": "DMG signature is invalid", - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/unsigned-rejected.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/unsigned-rejected.log" }, { "name": "sign-without-timestamp", @@ -41,54 +41,54 @@ "--timestamp=none", "--identifier", "com.opentype.voiceinput.dmg", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" ], "exit": 0, "expected_exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/sign-without-timestamp.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/sign-without-timestamp.log" }, { "name": "untimestamped-rejected", "command": [ "bash", - "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "WORKSPACE/scripts/verify-release-artifact.sh", "--app", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", "--version", "0.0.54", "--require-developer-id", "--expected-cert-sha256", "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", "--dmg", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" ], "exit": 1, "expected_exit": 1, "diagnostic": "DMG signature has no secure timestamp", - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/untimestamped-rejected.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/untimestamped-rejected.log" }, { "name": "actual-shared-signing-block", "command": [ "bash", "-e", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/shared-signing-block.sh" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/shared-signing-block.sh" ], "exit": 0, "expected_exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/actual-shared-signing-block.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/actual-shared-signing-block.log" }, { "name": "matching-without-expected", "command": [ "bash", - "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "WORKSPACE/scripts/verify-release-artifact.sh", "--app", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", "--dmg", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg", "--version", "0.0.54", "--require-developer-id" @@ -96,37 +96,41 @@ "exit": 0, "expected_exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/matching-without-expected.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/matching-without-expected.log" }, { "name": "dmg-signature-metadata", "command": [ "/usr/bin/codesign", "-dvvv", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" ], "exit": 0, "expected_exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dmg-signature-metadata.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dmg-signature-metadata.log" }, { "name": "extract-native-dmg-certificate", "command": [ "/usr/bin/codesign", "-d", - "--extract-certificates=/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dmg-cert-", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + "--extract-certificates=TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dmg-cert-", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" ], "exit": 0, "expected_exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/extract-native-dmg-certificate.log" + "log": "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/extract-native-dmg-certificate.log" } ], "task_mounts_remaining": [], "certificate_mismatch_coverage": "Controlled-tool actual verifier fixture; no second native Developer ID identity claimed.", "notarization_performed": false, "published": false, - "success": true + "success": true, + "_public_redaction": { + "original_sha256": "e14fcb008de3c5300205fca1a920e8f55b67d6f8623cdbe3d72a4692da2ac7da", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-independent-rerun.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-independent-rerun.json index d3742944..8de4b485 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-independent-rerun.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-independent-rerun.json @@ -2,127 +2,127 @@ "verifier": "/root/signing_verifier", "verified_at_utc": "2026-10-16T03:32:07.445817+00:00", "success": true, - "directory": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx", + "directory": "TASK_TMP/utter-dmg-independent-verifier-6rohbzkx", "results": [ { "name": "signed-with-expected", "command": [ "bash", - "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "WORKSPACE/scripts/verify-release-artifact.sh", "--app", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", "--version", "0.0.54", "--require-developer-id", "--expected-cert-sha256", "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", "--dmg", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" ], "exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/signed-with-expected.log" + "log": "TASK_TMP/utter-dmg-independent-verifier-6rohbzkx/signed-with-expected.log" }, { "name": "signed-without-expected", "command": [ "bash", - "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "WORKSPACE/scripts/verify-release-artifact.sh", "--app", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", "--version", "0.0.54", "--require-developer-id", "--dmg", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" ], "exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/signed-without-expected.log" + "log": "TASK_TMP/utter-dmg-independent-verifier-6rohbzkx/signed-without-expected.log" }, { "name": "unsigned-rejected", "command": [ "bash", - "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "WORKSPACE/scripts/verify-release-artifact.sh", "--app", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", "--version", "0.0.54", "--require-developer-id", "--expected-cert-sha256", "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", "--dmg", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/unsigned.dmg" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/unsigned.dmg" ], "exit": 1, "diagnostic": "DMG signature is invalid", - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/unsigned-rejected.log" + "log": "TASK_TMP/utter-dmg-independent-verifier-6rohbzkx/unsigned-rejected.log" }, { "name": "untimestamped-rejected", "command": [ "bash", - "/Users/chenli/projects/utter/scripts/verify-release-artifact.sh", + "WORKSPACE/scripts/verify-release-artifact.sh", "--app", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app", "--version", "0.0.54", "--require-developer-id", "--expected-cert-sha256", "1B499618154DEB0204896CDB199AA65D25EDA2188FEDBB0E29A73063728E4112", "--dmg", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/no-timestamp.dmg" ], "exit": 1, "diagnostic": "DMG signature has no secure timestamp", - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/untimestamped-rejected.log" + "log": "TASK_TMP/utter-dmg-independent-verifier-6rohbzkx/untimestamped-rejected.log" }, { "name": "dmg-display", "command": [ "/usr/bin/codesign", "-dvvv", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" ], "exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/dmg-display.log" + "log": "TASK_TMP/utter-dmg-independent-verifier-6rohbzkx/dmg-display.log" }, { "name": "app-display", "command": [ "/usr/bin/codesign", "-dvvv", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app" + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app" ], "exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/app-display.log" + "log": "TASK_TMP/utter-dmg-independent-verifier-6rohbzkx/app-display.log" }, { "name": "dmg-extract-certificate", "command": [ "/usr/bin/codesign", "-d", - "--extract-certificates=/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/dmg-cert-", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" + "--extract-certificates=TASK_TMP/utter-dmg-independent-verifier-6rohbzkx/dmg-cert-", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter-0.0.54.dmg" ], "exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/dmg-extract-certificate.log" + "log": "TASK_TMP/utter-dmg-independent-verifier-6rohbzkx/dmg-extract-certificate.log" }, { "name": "app-extract-certificate", "command": [ "/usr/bin/codesign", "-d", - "--extract-certificates=/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/app-cert-", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app" + "--extract-certificates=TASK_TMP/utter-dmg-independent-verifier-6rohbzkx/app-cert-", + "TASK_TMP/utter-dmg-signing-native-pp1zkm9b/dist/Utter.app" ], "exit": 0, "diagnostic": null, - "log": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-independent-verifier-6rohbzkx/app-extract-certificate.log" + "log": "TASK_TMP/utter-dmg-independent-verifier-6rohbzkx/app-extract-certificate.log" } ], "fixture_file_hashes_unchanged": true, @@ -137,5 +137,9 @@ "private_key_access": false, "signing_performed": false, "app_launched": false, - "notarization_submitted": false + "notarization_submitted": false, + "_public_redaction": { + "original_sha256": "fca7c9841ef15f6938cfcb08b5dc1ff186dd3763c768f7d4740d43d4585a466b", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-independent-review.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-independent-review.json index c0dc05ff..6dbb2245 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-independent-review.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-independent-review.json @@ -99,12 +99,16 @@ "failures": 0, "unique_swift_testing_passed": 1, "expected_empty_swift_testing_invocations": 13, - "native_run": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/native-run-f8535155", + "native_run": "TASK_TMP/utter-developer-id-ci-evidence-8lm_1sy5/native-run-f8535155", "runtime_preflight_canaries_verified_from_record": true, "runtime_policy_hash_verified": true, "protected_swift_test": "Setup failure retained, not passed.", "native_signing_block_matches_current_literal_yaml": true, "native_signing_block_sha256": "c1ca7730b16cd04fcd44379832f4bb5d1bd66a2d71b258c5d90e9de68455df79", "private_credentials_accessed": false, - "test_binaries_rerun_by_verifier": false + "test_binaries_rerun_by_verifier": false, + "_public_redaction": { + "original_sha256": "2631c84bff644e543eadc6d57dfa7e3312823d1125fe070a79c30ead1b41feb8", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-preflight.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-preflight.json index 98400e00..713a9bf6 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-preflight.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-preflight.json @@ -5,7 +5,7 @@ "canaries": { "preferences-canary": { "exit": 0, - "stdout": "false\n/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/test-home" + "stdout": "false\nTASK_TMP/utter-developer-id-ci-evidence-8lm_1sy5/test-home" }, "private-path-canary": { "exit": 0, @@ -13,5 +13,9 @@ } }, "production_probe_file_absent_before_after": true, - "preflight_parser_correction": "Initial witness parser expected JSON; canaries emit plain text. Corrected parser before running tests." + "preflight_parser_correction": "Initial witness parser expected JSON; canaries emit plain text. Corrected parser before running tests.", + "_public_redaction": { + "original_sha256": "4d28f8574a6f2492b3b7f0ce831f55c348071117c64057dcc4d6422562a9bc40", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-tests-run.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-tests-run.log index fab8b15d..4f2305e7 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-tests-run.log +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-tests-run.log @@ -1,4 +1,4 @@ -NATIVE_EVIDENCE_DIR=/private/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/native-run-f8535155 +NATIVE_EVIDENCE_DIR=TASK_TMP/utter-developer-id-ci-evidence-8lm_1sy5/native-run-f8535155 OpenTypeTests xctest: exit=0, executed=499, failures=0, complete=True OpenTypeTests swift-testing: exit=0, executed=1, failures=0, complete=True UtterAudioTests xctest: exit=0, executed=20, failures=0, complete=True diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/owner-merge-and-single-maintainer-authorization.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/owner-merge-and-single-maintainer-authorization.json new file mode 100644 index 00000000..fe19e773 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/owner-merge-and-single-maintainer-authorization.json @@ -0,0 +1,18 @@ +{ + "recorded_at_utc": "2026-10-16T05:51:52.377140+00:00", + "approved_by": "User", + "approved_date": "2026-10-16", + "direct_instructions": [ + "检查公开不要有 泄漏", + "merged就行,", + "这个只有我开发,移除不合理卡点" + ], + "authorized_actions": [ + "Audit and sanitize public evidence", + "Merge PR 125 after required checks", + "Remove impossible separate-reviewer gates for the single developer while retaining PR, strict CI, conversation resolution, blocked force pushes/deletions and no bypass actors" + ], + "production_environment_change_authorized": false, + "new_production_run_approved": false, + "collaborator_or_codeowners_change_required": false +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/pr-ci-code-verification.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/pr-ci-code-verification.json new file mode 100644 index 00000000..98b54416 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/pr-ci-code-verification.json @@ -0,0 +1,22 @@ +{ + "head_sha": "b405f46634df66e678b94b15e94b37cb4dc64d8d", + "run_id": 38857155983, + "url": "https://github.com/IchenDEV/utter/actions/runs/38857155983", + "conclusion": "success", + "jobs": [ + "Contract & Tests", + "Release-style App Build", + "SDLC Gate" + ], + "standard_ci_swift_test_passed": true, + "summary_lines": [ + "2026-10-16T05:43:56.8645830Z Ran 31 tests in 17.205s", + "2026-10-16T05:45:04.0646050Z Basic CI checks passed.", + "2026-10-16T05:50:09.2879810Z \t Executed 1143 tests, with 18 tests skipped and 0 failures (0 unexpected) in 34.508 (34.666) seconds", + "2026-10-16T05:50:09.2880280Z Test Suite 'All tests' passed at 2026-10-16 05:50:08.924.", + "2026-10-16T05:50:09.2880760Z \t Executed 1143 tests, with 18 tests skipped and 0 failures (0 unexpected) in 34.508 (34.667) seconds", + "2026-10-16T05:50:09.2890180Z \u2714 Test run with 1 test in 1 suite passed after 0.001 seconds." + ], + "raw_log_sha256": "caa1264cf2158df0c806e824141cb894baaa0c1c672a6c2f2547421e468f530e", + "scope": "Before public metadata redaction and single-maintainer documentation changes; four production/test code hashes unchanged. Final exact-head CI remains required." +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/pr-ci-first-failure.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/pr-ci-first-failure.json index edf4d2ef..5ba89748 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/pr-ci-first-failure.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/pr-ci-first-failure.json @@ -6,7 +6,11 @@ "url": "https://github.com/IchenDEV/utter/actions/runs/38856649852/job/116829504780", "first_failure": "Repository conflict-marker scan matched unittest separators in two newly tracked raw evidence logs", "unit_test_step": "Skipped after basic-check failure", - "raw_log_local_path": "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-dmg-pr-bot_2ek2/ci-quality-attempt-1.log", + "raw_log_local_path": "TASK_TMP/utter-dmg-pr-bot_2ek2/ci-quality-attempt-1.log", "raw_log_sha256": "9df5b899c3aab581380d8533afd2c7b8573e59d8e120447283474713cebb7533", - "remedy": "Keep original raw logs locally and commit lossless JSON representations; retain unchanged conflict-marker guard and production/test code" + "remedy": "Keep original raw logs locally and commit lossless JSON representations; retain unchanged conflict-marker guard and production/test code", + "_public_redaction": { + "original_sha256": "4214c950528baee592668e1a6e8d6f5906fd0e670323fa3bb126c229939e37ea", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.json index 93839c11..c324282b 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.json @@ -2,7 +2,7 @@ "command": [ "/usr/bin/sandbox-exec", "-f", - "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/test-runtime-narrow.sb", + "TASK_TMP/utter-developer-id-ci-evidence-8lm_1sy5/test-runtime-narrow.sb", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift", "test", "--skip-build", @@ -12,5 +12,9 @@ "exit": 1, "nested_sandbox_setup_failure": true, "lockfile_unchanged": true, - "native_full_suite_evidence": "full-test-evidence.json" + "native_full_suite_evidence": "full-test-evidence.json", + "_public_redaction": { + "original_sha256": "169c0910c74f25eebef1c3b5fdd997dd6a53bd4b290dbe15142bfcce3cbe99a7", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + } } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.log index 0b15647d..2b996653 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.log +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.log @@ -1,5 +1,5 @@ warning: '--skip-update' option is deprecated and will be removed in a future release -error: 'utter': Invalid manifest (compiled with: ["/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", "-vfsoverlay", "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/test-home/tmp/TemporaryDirectory.03znRQ/vfs.yaml", "-L", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/ManifestAPI", "-lPackageDescription", "-Xlinker", "-rpath", "-Xlinker", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/ManifestAPI", "-target", "arm64-apple-macosx14.0", "-plugin-path", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/plugins/testing", "-sdk", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX27.0.sdk", "-F", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks", "-I", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib", "-L", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib", "-swift-version", "6", "-I", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/ManifestAPI", "-sdk", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX27.0.sdk", "-package-description-version", "6.2.0", "/Users/chenli/projects/utter/Package.swift", "-o", "/var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/utter-developer-id-ci-evidence-8lm_1sy5/test-home/tmp/TemporaryDirectory.31BUpi/utter-manifest"]) +error: 'utter': Invalid manifest (compiled with: ["/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", "-vfsoverlay", "TASK_TMP/utter-developer-id-ci-evidence-8lm_1sy5/test-home/tmp/TemporaryDirectory.03znRQ/vfs.yaml", "-L", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/ManifestAPI", "-lPackageDescription", "-Xlinker", "-rpath", "-Xlinker", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/ManifestAPI", "-target", "arm64-apple-macosx14.0", "-plugin-path", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/plugins/testing", "-sdk", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX27.0.sdk", "-F", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks", "-I", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib", "-L", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib", "-swift-version", "6", "-I", "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/ManifestAPI", "-sdk", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX27.0.sdk", "-package-description-version", "6.2.0", "WORKSPACE/Package.swift", "-o", "TASK_TMP/utter-developer-id-ci-evidence-8lm_1sy5/test-home/tmp/TemporaryDirectory.31BUpi/utter-manifest"]) sandbox-exec: sandbox_apply: Operation not permitted error: ExitCode(rawValue: 1) error: no tests found; create a target in the 'Tests' directory diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/public-audit-independent.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/public-audit-independent.json new file mode 100644 index 00000000..9fdd1a06 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/public-audit-independent.json @@ -0,0 +1,67 @@ +{ + "verifier": "/root/signing_verifier", + "audited_at_utc": "2026-10-16T05:57:52.671303+00:00", + "result": "passed_current_publication_snapshot", + "pr": 125, + "existing_head": "b405f46634df66e678b94b15e94b37cb4dc64d8d", + "scope": "Existing PR added content plus current uncommitted sanitization and single-maintainer governance changes.", + "initial_pr_files": 84, + "initial_added_lines": 5699, + "current_files_scanned": 92, + "current_json_files_parsed": 66, + "findings": [], + "confirmed_credentials_detected": false, + "machine_path_or_true_email_residuals": 0, + "false_positives": [ + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log", + "line": 172, + "type": "retina_resource_filename_not_email", + "severity": "informational" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/public-disclosure-audit.json", + "line": 16, + "type": "retina_resource_filename_not_email", + "severity": "informational" + } + ], + "sanitization": { + "redacted_files": 26, + "original_and_public_hashes_verified": true, + "sanitized_wrapped_log_content_hashes_verified": true, + "original_private_backups_inspected": false, + "history_limit": "Current copies are sanitized; earlier public branch snapshots are not claimed purged. Prior-head inspection found low-risk path/email metadata, without detected credentials." + }, + "metadata_classification": [ + "Certificate identity, Apple team and certificate fingerprints are public signing metadata.", + "Secret names/timestamps do not reveal secret values.", + "The retained retina resource filename is not an email address." + ], + "governance": { + "fresh_remote_gets_independently_verified": true, + "mandatory_pr": true, + "required_approvals": 0, + "mandatory_codeowner_review": false, + "last_push_approval": false, + "extra_unattributed_change_approval": false, + "conversation_resolution": true, + "strict_sdlc_gate": true, + "gate_integration_id": 15368, + "force_push_and_deletion_blocked": true, + "main_protected": true, + "bypass_actors": [], + "production_full_snapshot_unchanged": true, + "human_production_approval_preserved": true, + "codeowners_unchanged": true, + "AGENTS_and_control_review_documents_consistent": true, + "per_stage_human_decisions_preserved": true, + "assessment": "No security blocker within the direct single-owner authorization." + }, + "four_production_and_regression_files_unchanged": true, + "merge_condition": "Commit the reviewed publication/governance snapshot and require fresh exact-head CI success before the owner-authorized merge. No new production release is authorized by this review.", + "proposed_snapshot_digest": "823b1401735d686491affa991e1b1eb28203a1fa3ccbd7eafc66b0985357ef49", + "verifier_remote_writes": false, + "verifier_repo_edits": false, + "credential_store_access": false +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/public-disclosure-audit.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/public-disclosure-audit.json new file mode 100644 index 00000000..653a17d0 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/public-disclosure-audit.json @@ -0,0 +1,20 @@ +{ + "audited_at_utc": "2026-10-16T05:55:10.398114+00:00", + "scope": [ + "Current tracked repository files", + "Changes introduced by PR 125", + "GitHub open secret-scanning alerts", + "Public evidence local-path/email copies" + ], + "tracked_files_scanned": 1252, + "credential_pattern_findings": [], + "github_open_secret_scanning_alerts": [], + "actual_password_token_private_key_or_p12_found": false, + "public_evidence_machine_paths_redacted": true, + "redundant_commit_emails_redacted": true, + "public_signing_metadata_retained": "Developer ID subject, team and certificate fingerprints are public verification metadata, not credentials", + "image_name_false_positive": "background@2x.png is an image filename, not an email address", + "historical_snapshot_limit": "Current-tip cleanup does not claim removal of old GitHub snapshots. Prior published snapshots contained machine path metadata and repeated public commit emails; no credential material was detected.", + "production_and_test_code_hashes_unchanged": true, + "user_merge_and_governance_directive": "owner-merge-and-single-maintainer-authorization.json" +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/public-redaction-manifest.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/public-redaction-manifest.json new file mode 100644 index 00000000..3a060bba --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/public-redaction-manifest.json @@ -0,0 +1,142 @@ +{ + "scope": "Added SDLC evidence in PR 125", + "credentials_found": false, + "redaction_rules": [ + "Replace local home/workspace and task temporary paths with stable placeholders", + "Remove redundant human commit email copies from API snapshots" + ], + "originals_retained_privately": true, + "historical_public_branch_snapshots": "Earlier commits contained local path metadata and redundant emails, without detected credential material. Current-tip redaction does not claim that GitHub has purged earlier snapshots.", + "files": [ + { + "path": "docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/full-test-evidence.json", + "original_sha256": "4837b5e5549a9387fb11c26b7c00fc52d776f24a8da111d73888743675e293e0", + "public_sha256": "3da35abcb6c1797d534a57e8fc7599c3e316170902cdffd8586b2d51b800ad9f" + }, + { + "path": "docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/independent-final-run-readback.json", + "original_sha256": "ee6f284818a79af6946d76ac4a056f4451fc3944f2205ba0a87c9aa476c6fb89", + "public_sha256": "08a80b2c256f6cc377cbb566d5d9b7ab2c733d5cb8cb89a0dce8424e22fdc64a" + }, + { + "path": "docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/main-branch-after.json", + "original_sha256": "aa5341ddad3af0bc62da6bc4701441786bf3bd91f56d63c9a4ec7ca2d91487f4", + "public_sha256": "9fd6559066806a7e214cdb4e1f6eef0f08841bcf8df983de7ec9e2f6c21a7db0" + }, + { + "path": "docs/sdlc/changes/2026-10-15-developer-id-ci/evidence/release-basic-checks.log", + "original_sha256": "6ef8ccc4e8b288f7148ce6e666571f2542bd4fc0b182df1f0eec8071ac591f22", + "public_sha256": "b84a092a300ca852e37c32ac204b9983c361aca3a127831a1d41327b2d508bd5" + }, + { + "path": "docs/sdlc/changes/2026-10-15-developer-id-ci/verification.md", + "original_sha256": "6539d2c3295251121c248967ec9556459e4820e80eecac84d2145aa173ca7beb", + "public_sha256": "b0ee5b946a72b43446e84483fc7916549f4c3cfabb0d76b99fae14c4d6448b0f" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks-python39-attempt-1-log.json", + "original_sha256": "4304c14bc9bb34eab55c259775fb9e017ed16f0fdfec09a49dd53432dba93845", + "public_sha256": "c967080f24e1f3334613017acf5ba71093cf33c7ab7dc8d8d22b4126df29c424" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/basic-checks.log", + "original_sha256": "9abda60c70729ffcc3d95107783ba5b23ca5f3e695a260697c0c3a82e20923e8", + "public_sha256": "23b1705320e321d280704736749c82a5cae468f5626727aa2906cb927523e18c" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/full-test-evidence.json", + "original_sha256": "edf8da0d2dd5be877621e475a48ba26425ad3b48a0f7803d4ae3bbccbf7e9edb", + "public_sha256": "afa6c677860ad10c3e05ad562588c44e1ed64b357ccc73113c864cc9533eb14c" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/implementation-final-verification.json", + "original_sha256": "0c9ebf7aa8c3098a414cb367d9a6399cc32ffa7d92c6ccc6342f55908bf0c25f", + "public_sha256": "63f31ea23d18672db8637fadfd130904f23d6764185516856ff2c84f494c3c4f" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-checks-summary.json", + "original_sha256": "8b85b3c1c2e1202f88cdad68e17740d8b09df91e16cdfc091b67fc195c596c76", + "public_sha256": "55e41b8205aacdb7a047227c6279d7b6f72b74cca0b4ebc3b585d0bf74a53eb3" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.json", + "original_sha256": "c1cba81b6c8aef2d7dd9a595feb00e10be7ecf03cecb7e028a68051b92dd72a2", + "public_sha256": "ff18a57d4a9a4cfb5ca7ceb2ad2c19ac18c1f20b4302cf81a66faf36958e3e4a" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build-attempt-1.log", + "original_sha256": "043b74230b2b04d0c2a5bd6cd8bf65ba200b16512194ccafcc8eb333d3af004c", + "public_sha256": "ff1a236658c294f5e6f51bb2ea0f61f8e35a87b58e82a37781104e48587947e8" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.json", + "original_sha256": "4edb304564c3f2c96090e56f2da427bf029473c7aa3b4aa376972bd931927250", + "public_sha256": "713f29ba6b3dade7d9728d239ba7a4f749e085284258c6ca321a0a06252cb798" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/local-release-build.log", + "original_sha256": "6372562a9c5827a85dbf3c87fd9d2fd82ffa5933d70f1f47b6aab7213efa7ffb", + "public_sha256": "cbc65ffe3f97887af62e5b9bd53d2270a540e1279803f1dcdaf572f8579f6d15" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-progress.json", + "original_sha256": "584f2e8e4b746de595277aedd68dfb1e6e46b32dcf817cd383af7a79765f2bbd", + "public_sha256": "96946c188a4e92693491b27a37825973c329d22699e6fb43757b1da32a9c4b87" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-dmg-verification.json", + "original_sha256": "e14fcb008de3c5300205fca1a920e8f55b67d6f8623cdbe3d72a4692da2ac7da", + "public_sha256": "0828f39d32ff1ebd1b6f2da0e8b01fe8cf26fb97d2709bcb01522c0e26db7c01" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-independent-rerun.json", + "original_sha256": "fca7c9841ef15f6938cfcb08b5dc1ff186dd3763c768f7d4740d43d4585a466b", + "public_sha256": "e634a7afb39e21bcb133bbf9223bf67293084cc4f3fe079e5021bacbbbf1121b" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-independent-review.json", + "original_sha256": "2631c84bff644e543eadc6d57dfa7e3312823d1125fe070a79c30ead1b41feb8", + "public_sha256": "d075d931dc8aaff580b05a8988c0344f075fca8490ed37eec85df8763b59a91e" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-suite-preflight.json", + "original_sha256": "4d28f8574a6f2492b3b7f0ce831f55c348071117c64057dcc4d6422562a9bc40", + "public_sha256": "9cf71bd6260991e067f6226d6cabf9865d4840514d3d47b2897e49de57480db4" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/native-tests-run.log", + "original_sha256": "f6d6bd680a39d61a4a40262947528f16bdcdc17c28178af42a72f9775f2d0c65", + "public_sha256": "160ca1d1b1ab1f1b8324142934119917cfb3bd9ddf9530bf60820a11db267394" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/pr-ci-first-failure.json", + "original_sha256": "4214c950528baee592668e1a6e8d6f5906fd0e670323fa3bb126c229939e37ea", + "public_sha256": "123ca763854d266ae5964e2ffe53d2fb62b80fa6acdd6ca9831e41dfef15affe" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.json", + "original_sha256": "169c0910c74f25eebef1c3b5fdd997dd6a53bd4b290dbe15142bfcce3cbe99a7", + "public_sha256": "d7fcd15598ccc7ad0be49303995b417e1af791564c03f0dcc8a0c5075f6f505a" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/protected-swift-test.log", + "original_sha256": "1238844883c9a8fe21cd191b2c15d1b57b4029974273dc2a7ac3b07d395d37d6", + "public_sha256": "859fcb01eb27f4a0082bdfbe7f80f7ebfaec234ff5678c03492280a880509260" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before-log.json", + "original_sha256": "d51e1478ee710d7a7e404b86a575056ece095d43336ad15fddb109917671f90a", + "public_sha256": "eafb1951d43278c0048af898de96f746ccf0eacddb641d2c75d63102a737c80f" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-after.log", + "original_sha256": "1f51eddc10881c9baca8a7168ab949ad64192ee9eefd94d62004b9fb1ded2229", + "public_sha256": "6b05929495e4479d049fef3cf4dabf35e5356688ef5cdb713f87ca8cfeff06c7" + }, + { + "path": "docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-before.log", + "original_sha256": "57f8a928583ff0bb5d7b05cd21c8558822be8342edc1d0a4266979113571d06f", + "public_sha256": "69f8fbe392248aa0353b85bcf5889101da6bf77828a75e3984fe84a1cfdce224" + } + ] +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before-log.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before-log.json index 44aeb469..fbe6981f 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before-log.json +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-verifier-before-log.json @@ -3,5 +3,12 @@ "sha256": "9172cdd7e88908a0dc53752ed33dfdd720201789a9e9b395cbc35e9e38f79efa", "encoding": "UTF-8", "reason_for_json": "Preserve unittest separator lines without presenting them as repository conflict markers", - "content": "FFFFFF.\n======================================================================\nFAIL: test_certificate_match_is_required_without_expected_fingerprint (test_release_artifact.ReleaseArtifactTests.test_certificate_match_is_required_without_expected_fingerprint)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py\", line 125, in test_certificate_match_is_required_without_expected_fingerprint\n self.assertNotEqual(result.returncode, 0)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='unsigned')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='adhoc')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='untimestamped')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='mismatch')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='extract-failure')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"/Users/chenli/projects/utter/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n----------------------------------------------------------------------\nRan 3 tests in 11.983s\n\nFAILED (failures=6)\n" + "content": "FFFFFF.\n======================================================================\nFAIL: test_certificate_match_is_required_without_expected_fingerprint (test_release_artifact.ReleaseArtifactTests.test_certificate_match_is_required_without_expected_fingerprint)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"WORKSPACE/scripts/tests/test_release_artifact.py\", line 125, in test_certificate_match_is_required_without_expected_fingerprint\n self.assertNotEqual(result.returncode, 0)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='unsigned')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"WORKSPACE/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='adhoc')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"WORKSPACE/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='untimestamped')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"WORKSPACE/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='mismatch')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"WORKSPACE/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n======================================================================\nFAIL: test_invalid_container_stops_before_mounting (test_release_artifact.ReleaseArtifactTests.test_invalid_container_stops_before_mounting) (case='extract-failure')\n----------------------------------------------------------------------\nTraceback (most recent call last):\n File \"WORKSPACE/scripts/tests/test_release_artifact.py\", line 118, in test_invalid_container_stops_before_mounting\n self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)\n ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: 0 == 0 : Owned resources passed.\nOwned resources passed.\nRelease artifact verification passed.\n\n\n----------------------------------------------------------------------\nRan 3 tests in 11.983s\n\nFAILED (failures=6)\n", + "_public_redaction": { + "original_sha256": "d51e1478ee710d7a7e404b86a575056ece095d43336ad15fddb109917671f90a", + "scope": "Local machine paths and redundant commit emails; original evidence retained privately" + }, + "content_is_sanitized": true, + "sha256_scope": "original private raw log", + "published_content_sha256": "b67fab6047ca5655e98935cad18325142cf7007567d6669c2b27d77aff891044" } diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-after.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-after.log index affdc421..005aa362 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-after.log +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-after.log @@ -1,6 +1,6 @@ -From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.bLx8i1YQgO/origin +From TASK_TMP/tmp.bLx8i1YQgO/origin * branch main -> FETCH_HEAD -From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.bLx8i1YQgO/origin +From TASK_TMP/tmp.bLx8i1YQgO/origin * branch main -> FETCH_HEAD Signing mode: developer-id Signing mode: self-signed diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-before.log b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-before.log index c3488b60..c60e0751 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-before.log +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/regression-workflow-before.log @@ -1,10 +1,10 @@ -From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.5RrqhVRHzc/origin +From TASK_TMP/tmp.5RrqhVRHzc/origin * branch main -> FETCH_HEAD -From /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.5RrqhVRHzc/origin +From TASK_TMP/tmp.5RrqhVRHzc/origin * branch main -> FETCH_HEAD Signing mode: developer-id unsigned Developer ID DMG reached verification -FAIL: bash -e /var/folders/8w/4lcbknl57rj88rn6_lqdk50r0000gn/T/tmp.5RrqhVRHzc/classify.sh +FAIL: bash -e TASK_TMP/tmp.5RrqhVRHzc/classify.sh FAIL: test verify = sign verify FAIL: test verify = sign diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/single-maintainer-controls.json b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/single-maintainer-controls.json new file mode 100644 index 00000000..3ea2a028 --- /dev/null +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/evidence/single-maintainer-controls.json @@ -0,0 +1,56 @@ +{ + "ruleset_id": 14695153, + "enforcement": "active", + "bypass_actors": [], + "conditions": { + "ref_name": { + "exclude": [], + "include": [ + "refs/heads/main" + ] + } + }, + "rules": [ + { + "type": "deletion" + }, + { + "type": "non_fast_forward" + }, + { + "type": "pull_request", + "parameters": { + "required_approving_review_count": 0, + "dismiss_stale_reviews_on_push": true, + "required_reviewers": [], + "require_code_owner_review": false, + "require_last_push_approval": false, + "required_review_thread_resolution": true, + "require_extra_approval_for_unattributed_changes": false, + "allowed_merge_methods": [ + "merge", + "squash", + "rebase" + ] + } + }, + { + "type": "required_status_checks", + "parameters": { + "strict_required_status_checks_policy": true, + "do_not_enforce_on_create": false, + "required_status_checks": [ + { + "context": "SDLC Gate", + "integration_id": 15368 + } + ] + } + } + ], + "production_environment_unchanged": true, + "production_required_reviewers_preserved": true, + "production_admin_bypass": false, + "user_authorization": "owner-merge-and-single-maintainer-authorization.json", + "rollback": "Restore the prior required approving review count and review flags if another maintainer joins; preserve CI and production protection" +} diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/plan.md b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/plan.md index ebf04d26..24d886f2 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/plan.md +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/plan.md @@ -16,6 +16,13 @@ artifact verifier. Extend the existing workflow contract test; add a focused script under `scripts/tests/` only if needed to keep files below 300 lines. Do not change app source, dependencies, credentials, code owners, or protections. +The owner's subsequent direct instructions on 2026-10-16 authorize merge, +public-evidence redaction, and removal of impossible second-person approval +requirements for this single-developer repository. That explicit instruction +supersedes this plan's earlier restriction on protection changes only for the +review settings described below. Keep all CI, signing, production, no-bypass, +force-push, and deletion controls. + ## Work items - [x] Record current HEAD, branch, tracked/index/untracked changes, source and @@ -114,10 +121,12 @@ verification acceptance, PR approval, or a new production decision. After human verification acceptance, push the scoped fix branch and open a reviewable PR. Attach that PR to this task and verify its remote SHA and CI. -Main currently has one collaborator/code owner and requires an independent -approving review. Resolve an eligible human approval route for that concrete -PR before merge. Do not add collaborators, alter code owners, or bypass rules -under this plan. +The owner subsequently authorized merging PR #125 and a single-maintainer +ruleset. Keep mandatory PRs, strict `SDLC Gate`, resolved conversations, +blocked deletion/force pushes, and no bypass actors. Set required review count +to zero and disable mandatory code-owner, last-push, and extra unattributed- +change approvals. Do not add collaborators or change CODEOWNERS. Verify these +exact settings and the unchanged production human gate before merging. After the protected merge, verify the exact merged SHA's `SDLC Gate`, recheck tags/releases and main, and select the next unused stable version, expected diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/spec.md b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/spec.md index 35796d53..c82b0018 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/spec.md +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/spec.md @@ -106,12 +106,15 @@ fix through a PR and protected main. Verify `SDLC Gate` on the exact merged candidate. Recheck remote tags and use the next unused stable version, expected to be v0.0.54. Retain the failed v0.0.53 tag and its first-failure evidence. -Current GitHub readback lists only `IchenDEV` as a collaborator and sensitive -path code owner. Main requires a separate approving review, code-owner review, -and last-push approval, with no bypass actors. Before merge, the concrete PR -must have an eligible human approval path. This is a rollout prerequisite; -changing collaborators, code owners, or protection rules is outside this fix. -Do not represent an agent review as satisfying that human gate. +Initial GitHub readback listed only `IchenDEV` as collaborator, sensitive-path +owner, PR author, and pusher. The owner later explicitly requested merge and +removal of impossible second-person gates for this single-developer repository. +The authorized adjustment sets required reviews to zero and disables mandatory +code-owner, last-push, and extra unattributed-change reviews. Mandatory PRs, +strict `SDLC Gate`, resolved conversations, blocked deletion/force pushes, +production human approval, and no bypass actors remain. No collaborator or +CODEOWNERS change is authorized. Independent technical verification is evidence; +the owner's separate explicit merge instruction supplies the human PR decision. The new run requires its own human production decision. Preserve v0.0.52 and its assets until the new release is verified. Revert the scoped fix through a @@ -125,7 +128,8 @@ The user approved intent, design, [implementation plan](plan.md), and [local verification](verification.md) on 2026-10-16. Independent design and implementation reviews found no blocker. Their reports record technical verification; human approvals are recorded in the artifact headers. The PR -approval and new run-specific production decision remain separate gates. +authorization was subsequently supplied by the owner. A new run-specific +production decision remains a separate gate. ## References diff --git a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/verification.md b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/verification.md index da9799cd..4edb8b43 100644 --- a/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/verification.md +++ b/docs/sdlc/changes/2026-10-16-dmg-developer-id-signing/verification.md @@ -98,17 +98,42 @@ full suite. Both canaries passed; no private runtime policy was weakened. The first PR CI attempt rejected unittest separator lines in two newly tracked raw evidence logs as conflict markers. The original logs remain unchanged -locally; lossless JSON copies preserve their contents and SHA-256 in the PR. +privately. Public JSON copies preserve the failure diagnostics and original +hashes, with local paths and redundant commit emails redacted. The conflict-marker guard and reviewed production/test code are unchanged. `evidence/pr-ci-first-failure.json` preserves the exact run, job, and cause. ## Remaining gates -Human verification acceptance is complete. The remote PR stage is authorized. -An eligible human PR approval route and a new run-specific production approval -remain required. +Human verification acceptance is complete. The owner subsequently requested +merge, a public disclosure audit, and removal of impossible second-person gates +for this single-developer repository. The authorized main rules retain PRs, +strict `SDLC Gate`, blocked force pushes/deletions, and no bypass actors; required +review count becomes zero, with mandatory code-owner, last-push, and extra +unattributed-change reviews disabled. Independent technical review and a new +run-specific production approval remain required. The failed v0.0.53 tag and latest public v0.0.52 are preserved. +## Public disclosure and single-maintainer follow-up + +The owner explicitly authorized public disclosure checks, merge, and removal +of impossible second-person gates. No credential, token, private key, PKCS12, +or notarization credential was found in the audited tracked tree and PR files; +GitHub reported no open secret-scanning alerts. Twenty-six evidence files now +use public path/email redactions while original records remain private. +Earlier GitHub snapshots are not claimed to have been purged. + +The independent [public audit](evidence/public-audit-independent.json) found +no remaining disclosure or governance blocker in the final publication files. +It independently read the actual ruleset and confirmed that PRs, strict CI, +resolved conversations, blocked force pushes/deletions, and no bypass actors +remain. The production environment is byte-for-byte unchanged in the readbacks. + +Standard CI on the unchanged production/test code passed in run `38857155983`, +with 1,143 XCTest cases, 18 conditional skips, zero failures, and one Swift +Testing case. The final exact-head CI after these evidence/documentation changes +must pass before the already-authorized squash merge. + ## Rollback Revert the scoped source correction through a reviewed PR if needed. Preserve diff --git a/docs/sdlc/github-controls.md b/docs/sdlc/github-controls.md index 3686a175..22365cbf 100644 --- a/docs/sdlc/github-controls.md +++ b/docs/sdlc/github-controls.md @@ -5,16 +5,21 @@ gap even when repository CI is green. ## `main` ruleset -Enable an active ruleset targeting `main` with: +This repository currently has one developer. Keep an active ruleset targeting +`main` with: - pull requests required; -- at least one approval; -- code-owner review for the sensitive paths in `.github/CODEOWNERS`; -- approval of the most recent reviewable push; +- zero required approving reviews, without mandatory code-owner or last-push + approval; the sole developer cannot provide a separate reviewer identity; - all review conversations resolved; - required status check `SDLC Gate`; - force pushes and deletions blocked; -- bypass limited to an explicit emergency role, with an audit reason. +- no bypass actors. + +The owner explicitly authorizes merge after reviewing the change and its +evidence. High-risk changes still require independent technical verification. +`CODEOWNERS` continues to document ownership. If another maintainer joins, +review whether separate approving reviews should become mandatory. The stable gate name lets internal CI jobs change without repeatedly editing the ruleset. diff --git a/docs/sdlc/review-policy.md b/docs/sdlc/review-policy.md index b52162be..b12153b3 100644 --- a/docs/sdlc/review-policy.md +++ b/docs/sdlc/review-policy.md @@ -34,4 +34,7 @@ requires one. The verifier reads the accepted artifacts, inspects the actual diff and results, and reruns risk-critical checks. The verifier reports findings and evidence gaps; it does not repair the change or approve production. -The author or implementation agent cannot satisfy the human approval gate. +For this single-maintainer repository, the owner's explicit merge authorization +is the human PR decision. GitHub does not require a separate approving reviewer. +An implementation agent cannot supply that human decision or production +approval. Independent technical verification remains required for high-risk work.