Compare commits

Author SHA1 Message Date
jjbrunton f7c686d5cf docs(release): verify iOS extension versions 2026-08-30 10:39:33 +01:00
jjbrunton 314664ecd6 chore(ios): record v1.0.6 build 45
chore(ios): record v1.0.6 build 45
2026-08-30 10:37:43 +01:00
jjbrunton 11f89b1345 chore(ios): record v1.0.6 build 45 2026-08-30 10:33:16 +01:00
jjbrunton 2481956c11 chore(agents): prohibit em dashes 2026-08-30 10:17:37 +01:00
jjbrunton 8804e121b6 chore(release): promote iOS compliance fix
chore(release): promote iOS compliance fix
2026-08-30 10:15:27 +01:00
jjbrunton 7b3de48dbd Merge pull request #11 from jjbrunton/task/ios-export-compliance
chore(ios): declare exempt encryption
2026-08-30 10:07:24 +01:00
jjbrunton 5ebf57bdbf Merge branch 'staging' into task/ios-export-compliance 2026-08-30 10:07:10 +01:00
jjbrunton 089e629021 docs(agents): delegate substantive repository tasks 2026-08-30 10:06:37 +01:00
jjbrunton 58b70710db chore(ios): declare exempt encryption 2026-08-30 09:58:26 +01:00
jjbrunton d645d83c47 chore(ios): record v1.0.6 build 44 2026-08-30 01:29:55 +01:00
jjbrunton 179f912170 chore(android): record v1.0.6 build 48 2026-08-30 01:05:13 +01:00
jjbrunton a604f82110 chore(release): prepare v1.0.6 2026-08-30 00:46:46 +01:00
jjbrunton ae8e72ddb5 Merge pull request #10 from jjbrunton/staging
chore(release): complete mobile release configuration
2026-08-30 00:41:09 +01:00
jjbrunton fd38b303f0 Merge pull request #9 from jjbrunton/staging
fix(api): keep auth sync timestamps monotonic
2026-08-29 23:57:39 +01:00
jjbrunton 387b242aea Merge pull request #8 from jjbrunton/staging
chore(release): promote staging for v1.0.6
2026-08-29 23:34:30 +01:00
12 changed files with 101 additions and 26 deletions

No files matched your search

@@ -0,0 +1,39 @@
---
id: 2026-08-30-ios-extension-version-verification
date: 2026-08-30
status: promoted
scope: iOS release artifact verification
evidence: build 45 Xcode archive warning plus direct PlistBuddy inspection of the exported IPA
destination: .codex/skills/release-mobile/SKILL.md
review_after: 2027-02-28
---
## Symptom
The signed iOS build logged that the widget extension build number 44 did not
match the containing app build number 45, even though export completed.
## Reproduction
Build iOS version 1.0.6 with EAS auto-increment from build 44 to 45 and retain the
archive log. Extract the resulting IPA with `ditto`, then read the containing app
and every packaged extension `Info.plist` with `PlistBuddy`.
## Cause
The archive warning described an intermediate state and was not authoritative
for the exported package. Direct IPA inspection showed both the app and
`LiveDrawWidget.appex` at version 1.0.6 build 45.
## Remediation
For every iOS release, inspect version and build values in the exported app and
all packaged extensions. Reject or rebuild only when the final IPA values differ;
do not accept or reject a release from archive warnings alone.
## Evidence
`PlistBuddy` read `CFBundleShortVersionString` 1.0.6 and `CFBundleVersion` 45 from
both packaged plists. `codesign --verify --deep --strict` passed for the app, and
the verified IPA SHA-256 was
`9d4779bddac4647911a3a38e4ee37cf794c2b8691e0746a041b629c62b308e7f`.
+6 -2
View File
@@ -54,5 +54,9 @@ additional TestFlight distribution requires another fresh authorization.
Preserve platform signing and local EAS versioning. After a build, verify that
tracked changes are limited to the expected version metadata, then independently
read the artifact version and signature. Report the artifact, version/build
number, upload result when authorized, and store read-back state.
read the artifact version and signature. For an iOS IPA, inspect every packaged
app extension as well as the containing app and require matching
`CFBundleShortVersionString` and `CFBundleVersion` values. Treat Xcode archive
warnings as diagnostic evidence, not the final artifact state: decide whether to
reject or rebuild only after reading the exported IPA itself. Report the artifact,
version/build number, upload result when authorized, and store read-back state.
+10 -3
View File
@@ -25,11 +25,18 @@ MCP service in one npm/Turborepo workspace.
and prove the relevant compatibility contracts still hold. Preserve deployed
interfaces and supported client behavior; repository checks alone do not
prove a live change is safe.
10. Scope work to the task. Route bounded implementation through the project
`implementation` agent when delegation is useful; the primary agent retains
acceptance, review, and final verification. Do not delegate trivial edits.
10. Delegate every substantive repository task to at least one project agent so
detailed exploration or execution stays out of the primary context.
"Substantive" includes repository exploration, multi-file reasoning,
implementation, test execution, or contract/risk analysis. Use `repo_scout`
for read-only investigation and `implementation` for bounded changes; use
the additional roles according to `docs/agents/routing.md`. The primary
agent retains scope, acceptance, review, and the final answer. Skip
delegation only for trivial conversation, a single obvious lookup, or a
mechanical one-line edit whose coordination cost exceeds the work.
11. Use high-effort reviewers only for the risk triggers in
`docs/agents/routing.md`.
12. Agents must not use em dash characters in text they add to this repository.
## Repository map
+2 -2
View File
@@ -92,8 +92,8 @@ android {
applicationId 'com.sauci.app'
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 47
versionName "1.0.5"
versionCode 48
versionName "1.0.6"
buildConfigField "String", "REACT_NATIVE_RELEASE_LEVEL", "\"${findProperty('reactNativeReleaseLevel') ?: 'stable'}\""
}
signingConfigs {
+6 -3
View File
@@ -2,7 +2,7 @@
"expo": {
"name": "Sauci",
"slug": "sauci",
"version": "1.0.5",
"version": "1.0.6",
"orientation": "portrait",
"icon": "./assets/icon.png",
"scheme": "app.sauci",
@@ -16,12 +16,15 @@
"ios": {
"supportsTablet": false,
"bundleIdentifier": "com.sauci.app",
"config": {
"usesNonExemptEncryption": false
},
"entitlements": {
"com.apple.security.application-groups": [
"group.com.sauci.app"
]
},
"buildNumber": "43",
"buildNumber": "45",
"usesAppleSignIn": true,
"googleServicesFile": "./GoogleService-Info.plist",
"infoPlist": {
@@ -183,7 +186,7 @@
"backgroundColor": "#1a1a2e"
},
"package": "com.sauci.app",
"versionCode": 47,
"versionCode": 48,
"googleServicesFile": "./google-services.json",
"permissions": [
"RECEIVE_BOOT_COMPLETED",
@@ -570,7 +570,7 @@
INFOPLIST_FILE = Sauci/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -599,7 +599,7 @@
INFOPLIST_FILE = Sauci/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -772,7 +772,7 @@
CODE_SIGN_ENTITLEMENTS = ../targets/widget/generated.entitlements;
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 43;
CURRENT_PROJECT_VERSION = 44;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = BXVPBATDZY;
GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -782,7 +782,7 @@
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.sauci.app.LiveDrawWidget;
@@ -808,7 +808,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = ../targets/widget/generated.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 43;
CURRENT_PROJECT_VERSION = 44;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = BXVPBATDZY;
GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -818,7 +818,7 @@
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
+4 -2
View File
@@ -21,7 +21,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0.5</string>
<string>1.0.6</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
@@ -47,9 +47,11 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>43</string>
<string>45</string>
<key>GOOGLE_ANALYTICS_INAPURCHASE_COLLECTION_ENABLED</key>
<false/>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSMinimumSystemVersion</key>
<string>12.0</string>
<key>LSRequiresIPhoneOS</key>
+3 -3
View File
@@ -8,8 +8,8 @@
<string>com.apple.widgetkit-extension</string>
</dict>
<key>CFBundleVersion</key>
<string>43</string>
<string>45</string>
<key>CFBundleShortVersionString</key>
<string>1.0.5</string>
<string>1.0.6</string>
</dict>
</plist>
</plist>
+7 -4
View File
@@ -1,9 +1,12 @@
# Agent routing and effort
The primary agent owns scope, acceptance criteria, task decomposition, and the
final answer. Use one implementation agent when a bounded handoff will keep noisy
execution out of the primary context. Do not pay the coordination cost for a
trivial one-file edit. Add other agents only for separable work or a risk trigger.
The primary agent owns scope, acceptance criteria, task decomposition, review,
and the final answer. Every substantive repository task must delegate at least
one bounded unit to the best-fit project agent. Use `repo_scout` for read-only
discovery or analysis and `implementation` for product or harness changes. Add
other agents only for separable work or the risk triggers below. Skip delegation
only for trivial conversation, a single obvious lookup, or a mechanical one-line
edit whose coordination cost exceeds the work.
## Implementation and integration
+10
View File
@@ -1,5 +1,15 @@
# Sauci Mobile Release Notes
## v1.0.6 — 30 August 2026
_iOS build 44 · Android build 48_
A little more clarity, momentum, and playfulness for your shared check-ins.
- **Your turn at a glance** — A private Home prompt now shows when questions from your partner are waiting, without revealing their answers.
- **New ways to play** — Browse, send, and respond to Dares together from a dedicated shared space.
- **Streaks that fit your day** — Shared streaks now follow your local day, with clearer progress and reminder controls.
- **Smoother shared moments** — Leaner syncing keeps questions, matches, chat, and Live Draw feeling current with less unnecessary refreshing.
## v1.0.1 (Build 30) - January 2025
### New Features
+1 -1
View File
@@ -258,7 +258,7 @@ To verify you're using the correct keystore:
keytool -list -v -keystore android/sauci-release.keystore -storepass <password>
```
Expected SHA1: `C3:70:C5:8C:85:E5:B5:92:97:82:A9:B0:47:98:40:99:AC:C8:47:43`
Expected EAS production upload-key SHA1: `F0:60:26:C7:54:B0:46:F2:80:FE:AC:43:8A:69:10:BD:9A:62:B4:59`
---
+7
View File
@@ -40,6 +40,13 @@ for (const file of allFiles) {
}
if (!scoped) {
const agentsFile = path.join(root, 'AGENTS.md');
const agents = await readFile(agentsFile, 'utf8');
const noEmDashRule = 'Agents must not use em dash characters in text they add to this repository.';
if (!agents.includes(noEmDashRule)) {
fail(agentsFile, 'agent writing rule against em dash characters is missing', `restore: ${noEmDashRule}`);
}
const packageJson = JSON.parse(await readFile(path.join(root, 'package.json'), 'utf8'));
const codexConfigFile = path.join(root, '.codex', 'config.toml');
const codexConfig = await readFile(codexConfigFile, 'utf8');