diff --git a/plugins/agent-portability-skills/.codex-plugin/plugin.json b/plugins/agent-portability-skills/.codex-plugin/plugin.json index 0ccf2894..9e024cd5 100644 --- a/plugins/agent-portability-skills/.codex-plugin/plugin.json +++ b/plugins/agent-portability-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agent-portability-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Maintainer skills for Socket-owned agent skill portability, Codex plugin surfaces, and host adapter guidance.", "author": { "name": "Gale", diff --git a/plugins/agent-portability-skills/pyproject.toml b/plugins/agent-portability-skills/pyproject.toml index 5442a7dc..1387cf9a 100644 --- a/plugins/agent-portability-skills/pyproject.toml +++ b/plugins/agent-portability-skills/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "agent-portability-skills-maintenance" -version = "8.5.2" +version = "8.5.3" description = "Maintainer-only Python tooling baseline for Agent Portability Skills." requires-python = ">=3.11" dependencies = [] diff --git a/plugins/agent-portability-skills/uv.lock b/plugins/agent-portability-skills/uv.lock index 9724db78..bee94a5c 100644 --- a/plugins/agent-portability-skills/uv.lock +++ b/plugins/agent-portability-skills/uv.lock @@ -8,7 +8,7 @@ resolution-markers = [ [[package]] name = "agent-portability-skills-maintenance" -version = "8.5.2" +version = "8.5.3" source = { virtual = "." } [package.dev-dependencies] diff --git a/plugins/agentdeck/.codex-plugin/plugin.json b/plugins/agentdeck/.codex-plugin/plugin.json index 168e1877..1ab58b8c 100644 --- a/plugins/agentdeck/.codex-plugin/plugin.json +++ b/plugins/agentdeck/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agentdeck", - "version": "8.5.2", + "version": "8.5.3", "description": "Local Codex runtime utilities for thread, hook, and app-server workflows.", "author": { "name": "Gale", diff --git a/plugins/android-dev-skills/.codex-plugin/plugin.json b/plugins/android-dev-skills/.codex-plugin/plugin.json index b38c0bd8..fd3b231a 100644 --- a/plugins/android-dev-skills/.codex-plugin/plugin.json +++ b/plugins/android-dev-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "android-dev-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Android, Kotlin, Java, Gradle, Android Gradle Plugin, testing, lint, UI implementation, and release-readiness workflow skills.", "author": { "name": "Gale", diff --git a/plugins/apple-dev-skills/.codex-plugin/plugin.json b/plugins/apple-dev-skills/.codex-plugin/plugin.json index 49d49912..9eb6cf8e 100644 --- a/plugins/apple-dev-skills/.codex-plugin/plugin.json +++ b/plugins/apple-dev-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "apple-dev-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Apple development workflows for Codex, including media and audio repair, XcodeGen migration, Xcode coding intelligence, SwiftUI animation and architecture, Core Animation, Apple typography, SF Symbols, AppKit architecture, Icon Composer app icons, Safari extensions, DeviceCheck/App Attest, Swift OpenAPI clients, and DocC authoring guidance.", "author": { "name": "Gale", diff --git a/plugins/apple-dev-skills/.github/scripts/validate_repo_docs.sh b/plugins/apple-dev-skills/.github/scripts/validate_repo_docs.sh index 501f19ce..c6d96522 100644 --- a/plugins/apple-dev-skills/.github/scripts/validate_repo_docs.sh +++ b/plugins/apple-dev-skills/.github/scripts/validate_repo_docs.sh @@ -298,9 +298,9 @@ xcode_agents_assets=( for agents_asset in "${xcode_agents_assets[@]}"; do require_contains "$agents_asset" 'Use `xcode-build-run-workflow`' require_contains "$agents_asset" 'Use `xcode-testing-workflow`' - require_contains "$agents_asset" 'scripts/repo-maintenance/config/profile.env' + require_contains "$agents_asset" 'Scripts/repo-maintenance/config/profile.env' require_contains "$agents_asset" '.swiftformat' - require_contains "$agents_asset" 'scripts/repo-maintenance/hooks/pre-commit.sample' + require_contains "$agents_asset" 'Scripts/repo-maintenance/hooks/pre-commit.sample' require_contains "$agents_asset" 'swiftformat --lint' require_contains "$agents_asset" '.xctestplan' require_contains "$agents_asset" 'project membership, target membership, build phases, and resource inclusion' diff --git a/plugins/apple-dev-skills/pyproject.toml b/plugins/apple-dev-skills/pyproject.toml index d769eaf0..9280066d 100644 --- a/plugins/apple-dev-skills/pyproject.toml +++ b/plugins/apple-dev-skills/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "apple-dev-skills-maintainer" -version = "8.5.2" +version = "8.5.3" description = "Maintainer tooling for the apple-dev-skills repository" requires-python = ">=3.10" dependencies = [] diff --git a/plugins/apple-dev-skills/shared/agents-snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/shared/agents-snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/shared/agents-snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/shared/agents-snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/appkit-app-architecture-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/appkit-app-architecture-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/appkit-app-architecture-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/appkit-app-architecture-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/apple-typography-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/apple-typography-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/apple-typography-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/apple-typography-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/apple-ui-accessibility-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/apple-ui-accessibility-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/apple-ui-accessibility-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/apple-ui-accessibility-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/avaudio-engine-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/avaudio-engine-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/avaudio-engine-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/avaudio-engine-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/avfaudio-session-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/avfaudio-session-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/avfaudio-session-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/avfaudio-session-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/avfoundation-media-pipeline-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/avfoundation-media-pipeline-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/avfoundation-media-pipeline-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/avfoundation-media-pipeline-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/SKILL.md b/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/SKILL.md index d7efe510..3d3d018c 100644 --- a/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/SKILL.md +++ b/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/SKILL.md @@ -67,24 +67,27 @@ This skill can be discovered from a standalone `apple-dev-skills` install, but i - treat `ask` as a legacy explicit-blocking value only when the user or customization state supplies it intentionally 7. Create the project: - for `xcodegen`, let `scripts/bootstrap_xcode_app_project.py` generate the repo scaffold from `templates/xcodegen/swiftui-app/`, including `project.yml`, checked-in `.xcconfig` files, source files, tests, and `AGENTS.md`, then run `xcodegen generate` + - create the standard top-level Xcode app layout: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/` + - keep app-owned implementation/resources/support under `Sources/`, tests under `Tests/`, reusable app/extension source under `Shared/`, extension target roots under `Extensions/`, `.xcconfig` layers under `Configurations/`, project-local automation under `Scripts/`, and justified local Swift package boundaries under `Packages/` - install `.codex/environments/xcode-project.toml` from `templates/codex-local-environments/xcode-project.toml` and replace the scheme placeholder with the generated app target name - keep the generated `project.yml` aligned with the current XcodeGen project spec concepts: project `options`, `configs`, `configFiles`, targets, sources, schemes, packages, project references, test-plan references, and `minimumXcodeGenVersion` - keep the generated `minimumXcodeGenVersion` on the recent validated baseline declared by the templates; when the baseline is raised, update the templates, docs, and tests together - - use exactly one top-level `Sources` entry for the app target and exactly one top-level `Tests` entry for the test target when the generated project format is Xcode 16 or newer; prefer `type: syncedFolder` on those broad roots, and use the same broad roots with explicit `includes` and `excludes` as the fallback when synchronized folders are not appropriate - - never split ordinary generated app project paths into separate XcodeGen source entries such as `Sources/App`, `Sources/Resources`, `Sources/Support`, feature subfolders, or `Tests/Tests`; use a separate top-level path only for a separate logical root such as repo-root `Resources` + - use exactly one top-level `Sources` entry for the app target, exactly one top-level `Shared` entry for shared app/extension source, and exactly one top-level `Tests` entry for the test target when the generated project format is Xcode 16 or newer; prefer `type: syncedFolder` on those broad roots, and use the same broad roots with explicit `includes` and `excludes` as the fallback when synchronized folders are not appropriate + - never split ordinary generated app project paths into separate XcodeGen source entries such as `Sources/App`, `Sources/Resources`, `Sources/Support`, feature subfolders, or `Tests/Tests`; extension targets may use one `Extensions/` entry per extension target - create exactly one app lifecycle entry point for the app target; do not create alternate `@main` app types, duplicate `main.swift` files, target-specific app entry files, or parallel app structs for variants; keep platform or configuration differences inside the single entry point with Swift conditional compilation or runtime conditionals - keep nontrivial build settings in external `.xcconfig` files by default, using shared, target-level, and per-configuration layers wired through the XcodeGen spec instead of duplicating settings inline - install a checked-in external app entitlement plist and wire it through `CODE_SIGN_ENTITLEMENTS` in the app `.xcconfig` so capability changes have a real tracked file owner instead of living only in generated project state - for `xcode`, use a guarded guidance path for now instead of pretending the repo supports full GUI automation already 8. Validate the scaffold: - verify the expected app files exist + - verify the standard top-level directories exist - verify `.swiftformat` exists - verify `AGENTS.md` exists when enabled - verify `.codex/environments/xcode-project.toml` exists and uses the generated app target name for Codex GUI actions - verify generated guidance says tracked `.pbxproj` changes must be reviewed, staged, and committed before push, merge, release, or cleanup - verify generated guidance says Xcode Build Settings UI edits may need to be moved from generated project overrides back into the owning `.xcconfig` - - verify `scripts/repo-maintenance/hooks/pre-commit.sample` exists - - verify `scripts/repo-maintenance/validate-all.sh` and `scripts/repo-maintenance/release.sh` exist + - verify `Scripts/repo-maintenance/hooks/pre-commit.sample` exists + - verify `Scripts/repo-maintenance/validate-all.sh` and `Scripts/repo-maintenance/release.sh` exist - verify branch protection, when enabled, requires the GitHub Actions check context `validate` rather than `Validate Repo Maintenance / validate` - when a GitHub remote is created or already exists, route repository settings audit or mutation through `productivity-skills:maintain-github-repository` @@ -117,7 +120,7 @@ This skill can be discovered from a standalone `apple-dev-skills` install, but i - `copy_agents_md` defaults to `true` - Codex GUI local environments are installed from `templates/codex-local-environments/xcode-project.toml` into `.codex/environments/xcode-project.toml` - validation runs unless `--skip-validation` is passed - - `maintain-project-repo` installs `scripts/repo-maintenance/` on successful mutating runs + - `maintain-project-repo` installs `Scripts/repo-maintenance/` on successful mutating runs ## Outputs @@ -156,7 +159,7 @@ This skill can be discovered from a standalone `apple-dev-skills` install, but i - After a successful XcodeGen bootstrap, treat `project.yml` as the editable source for generated project structure and regenerate with `xcodegen generate` after project-spec changes. - After a successful bootstrap, hand off to `sync-xcode-project-guidance` for repo-guidance alignment when needed, then to `xcode-build-run-workflow` for build, run, diagnostics, mutation, preview, and docs work. - After a successful bootstrap, hand off to `xcode-testing-workflow` for Swift Testing, XCTest, XCUITest, `.xctestplan`, and test diagnosis work. -- After a successful bootstrap, use `scripts/repo-maintenance/validate-all.sh` for local maintainer validation and `scripts/repo-maintenance/release.sh --mode standard --version vX.Y.Z` from a feature branch or worktree for protected-main releases. +- After a successful bootstrap, use `Scripts/repo-maintenance/validate-all.sh` for local maintainer validation and `Scripts/repo-maintenance/release.sh --mode standard --version vX.Y.Z` from a feature branch or worktree for protected-main releases. - After a successful bootstrap, configure protected branches to require `validate` for the managed repo-maintenance workflow; GitHub exposes that job check context directly rather than the workflow title plus job string. - When the app repository is published to GitHub, use `productivity-skills:maintain-github-repository` to audit repository features, diff --git a/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/assets/AGENTS.md b/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/assets/AGENTS.md index 77267ec9..cd1dc59c 100644 --- a/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/assets/AGENTS.md +++ b/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/assets/AGENTS.md @@ -5,10 +5,10 @@ - Use `apple-ui-accessibility-workflow` when the task is primarily about SwiftUI accessibility semantics, Apple UI accessibility review, accessibility tree shaping, or UIKit/AppKit accessibility bridge behavior. - Use `sync-xcode-project-guidance` when this repo's local workflow guidance drifts and should be refreshed or merged forward. - Re-run `sync-xcode-project-guidance` after substantial Xcode-workflow or plugin updates so local guidance stays aligned. -- Use `scripts/repo-maintenance/validate-all.sh` for local maintainer validation and `scripts/repo-maintenance/sync-shared.sh` for repo-local sync steps. -- Use `scripts/repo-maintenance/release.sh --mode standard --version vX.Y.Z` from a feature branch or worktree only when the task is actually a protected-main release, publish, merge, tag, or release-PR preparation. +- Use `Scripts/repo-maintenance/validate-all.sh` for local maintainer validation and `Scripts/repo-maintenance/sync-shared.sh` for repo-local sync steps. +- Use `Scripts/repo-maintenance/release.sh --mode standard --version vX.Y.Z` from a feature branch or worktree only when the task is actually a protected-main release, publish, merge, tag, or release-PR preparation. - Do not run the standard release workflow from `main`; when a protected-main release is explicitly requested, let it validate, bump versions, tag, push the branch and tag, open the release PR, watch CI, address valid PR comments or record out-of-scope concerns in `ROADMAP.md`, merge to protected `main`, fast-forward local `main`, and clean up stale branches. -- Treat `scripts/repo-maintenance/config/profile.env` as the installed `maintain-project-repo` profile marker, and keep it on the `xcode-app` profile for native Apple app repos. +- Treat `Scripts/repo-maintenance/config/profile.env` as the installed `maintain-project-repo` profile marker, and keep it on the `xcode-app` profile for native Apple app repos. - Read relevant Apple documentation before proposing or making Xcode, SwiftUI, lifecycle, or architecture changes. - Prefer Xcode MCP DocumentationSearch or local Apple docs first for Apple-owned SDK, framework, and lifecycle questions; use Dash MCP or Dash HTTP next when installed local package docs or multi-ecosystem docs are a better fit; then use official Apple docs when local docs are insufficient. - Prefer the simplest correct Swift that is easiest to read and reason about. @@ -19,12 +19,15 @@ - Keep data flow straight and dependency direction unidirectional. - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for app integration, schemes, and build settings. - Prefer Xcode-aware tooling or `xcodebuild` over ad hoc filesystem assumptions when project structure or target membership is involved. +- Use the standard top-level Xcode app repository layout: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable; do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos. - For new Xcode app, framework, and workspace repositories, prefer XcodeGen plus synced source folders, checked-in `.xcconfig` files, and checked-in entitlement files by default unless there is a concrete reason to avoid that generator dependency. - If this repo is XcodeGen-backed, treat `project.yml`, `project.yaml`, and any included XcodeGen specs as the source of truth for generated targets, schemes, build settings, build configurations, Swift packages, test-plan references, and file membership. - For XcodeGen-backed projects, edit the spec set and rerun `xcodegen generate` instead of hand-editing generated `.pbxproj` files. - Before running `xcodegen generate`, inspect the current git diff for generated `.xcodeproj` or `.pbxproj` changes. Treat existing project-file diffs as intentional user or Xcode GUI changes by default, promote intentional values into the owning tracked source files first, and only then regenerate. Use XcodeGen specs for structure, `.xcconfig` files for build settings, `.entitlements` files for entitlement keys, `Info.plist` for plist keys, scheme specs or `.xcscheme` files for scheme behavior, and `.xctestplan` files for test-plan content. - For Xcode 16 or newer project formats, prefer `syncedFolder` roots at the broad top-level directory boundary so Xcode and the filesystem stay aligned for file membership. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` does not fit a repo, use the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes` as the fallback; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Every native app target must have exactly one app lifecycle entry point: one `@main` app type, one `main.swift`, or the platform-equivalent single launch entry. Do not add alternate app entry points, second `@main` types, duplicate `main.swift` files, target-specific app entry files, or parallel app structs for variants. Keep platform, configuration, or feature-flag differences inside that single entry point with Swift conditional compilation or runtime conditionals. @@ -36,7 +39,7 @@ - Prefer Swift Testing for modern unit-style tests, keep XCTest where Apple tooling or dependencies still require it, and use XCUITest with explicit element wait APIs instead of fixed sleeps. - Keep `.xctestplan` files versioned when the project depends on repeatable test-plan configurations, and inspect or run them explicitly with `xcodebuild -showTestPlans` and `xcodebuild -testPlan ...`. - Prefer a checked-in repo-root `.swiftformat` file as the Swift formatting source of truth. -- Prefer a pre-commit hook such as `scripts/repo-maintenance/hooks/pre-commit.sample` that formats staged Swift sources and then verifies them with `swiftformat --lint` before commit. +- Prefer a pre-commit hook such as `Scripts/repo-maintenance/hooks/pre-commit.sample` that formats staged Swift sources and then verifies them with `swiftformat --lint` before commit. - Treat SwiftLint as an optional complementary signal layer for clarity, safety, and maintainability after SwiftFormat owns formatting shape. - Treat accessibility semantics and Apple UI accessibility review as a separate concern from UI automation; use `apple-ui-accessibility-workflow` for the semantic side and `xcode-testing-workflow` for runtime verification and XCUITest follow-through. - When scripts add files on disk, verify project membership, target membership, build phases, and resource inclusion afterward; files existing in the directory tree alone are not enough. diff --git a/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/references/project-generators.md b/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/references/project-generators.md index fab2064f..04091afb 100644 --- a/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/references/project-generators.md +++ b/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/references/project-generators.md @@ -14,7 +14,8 @@ Describe the supported generator choices for `bootstrap-xcode-app-project`. - The generated scaffold should require the recent validated XcodeGen baseline declared in the template. As of this guidance, that baseline is `minimumXcodeGenVersion: 2.45.4`. - Current project-spec concepts this skill should keep aligned include `options.minimumXcodeGenVersion`, `options.projectFormat`, `configs`, `configFiles`, targets, sources, schemes, Swift packages, project references, target templates, scheme templates, and test-plan references. - For Xcode 16 or newer project formats, prefer `syncedFolder` roots at the broad top-level directory boundary so Xcode and the filesystem stay aligned for file membership without hand-listing ordinary source files in YAML. -- Use exactly one top-level `Sources` entry for the app target and exactly one top-level `Tests` entry for the test target. If a repo has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root. +- Generate the standard top-level app repo layout: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- Use exactly one top-level `Sources` entry for the app target, exactly one top-level `Shared` entry for shared app/extension source, and exactly one top-level `Tests` entry for the test target. Extension targets use one `Extensions/` source entry per extension target. - Do not split ordinary folders such as `Sources/App`, `Sources/Resources`, `Sources/Support`, feature subfolders, or `Tests/Tests` into separate XcodeGen source entries. Use broad recursive source paths with explicit `includes` and `excludes` as the fallback when synchronized folders are not appropriate for a repo. Avoid per-file YAML source entries unless a file needs custom compiler flags, build-phase routing, or another exceptional setting. - Create exactly one app lifecycle entry point per app target. Use one `@main` app type, one `main.swift`, or the platform-equivalent single launch entry; put platform, configuration, or product-variant differences inside that single entry point with Swift conditional compilation or runtime conditionals. - Prefer checked-in external `.xcconfig` files for nontrivial build settings and wire them from the XcodeGen spec rather than duplicating settings inline. New app scaffolds should start with shared, target-level, and per-configuration `.xcconfig` layers. diff --git a/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/references/xcodegen-synced-folder-and-config-notes.md b/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/references/xcodegen-synced-folder-and-config-notes.md index d18236c4..fd7a126c 100644 --- a/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/references/xcodegen-synced-folder-and-config-notes.md +++ b/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/references/xcodegen-synced-folder-and-config-notes.md @@ -3,7 +3,8 @@ ## Decision - For new XcodeGen-backed app scaffolds that use `projectFormat: xcode16_0` or newer, prefer `syncedFolder` roots at the broad top-level directory boundary. -- Use exactly one top-level `Sources` source entry for the app target and exactly one top-level `Tests` source entry for the test target. If a repo has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root. +- Use the standard top-level Xcode app repository layout: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- Use exactly one top-level `Sources` source entry for the app target, exactly one top-level `Shared` source entry for shared app/extension source, and exactly one top-level `Tests` source entry for the test target. Extension targets use one `Extensions/` entry per extension target. - Use those same broad recursive paths with explicit `includes` and `excludes` as the fallback when synchronized folders do not fit a repo. - Avoid subdirectory fragmentation and one YAML entry per ordinary source file. Use narrower source entries only for exceptional compiler flags, build-phase routing, destination filters, target membership, or other file-specific behavior that cannot be represented from the broad root. @@ -11,6 +12,7 @@ - Keep app source, resources, support files, generated `Info.plist`, checked-in entitlements, feature folders, and nested implementation folders under `Sources/` when they belong to the app target. - Keep tests under `Tests/` when they belong to the test target. +- Keep shared app/extension source under `Shared/`, extension target roots under `Extensions/`, project-local automation under `Scripts/`, and justified local Swift packages under `Packages/`. - Keep resources under `Sources/Resources`, including a default `Assets.xcassets` with `AppIcon` and `AccentColor` placeholders, but do not add `Sources/Resources` as a separate XcodeGen source entry when `Sources` already owns the target root. - Set `options.defaultSourceDirectoryType: syncedFolder` and mark only the broad target roots with `type: syncedFolder` so the intended behavior is visible at the target boundary. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate ordinary XcodeGen source entries. diff --git a/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/scripts/bootstrap_xcode_app_project.py b/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/scripts/bootstrap_xcode_app_project.py index d4773292..1394ee30 100755 --- a/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/scripts/bootstrap_xcode_app_project.py +++ b/plugins/apple-dev-skills/skills/bootstrap-xcode-app-project/scripts/bootstrap_xcode_app_project.py @@ -29,6 +29,16 @@ "Configurations/Tests-Release.xcconfig.tmpl": "Configurations/Tests-Release.xcconfig", } +STANDARD_TOP_LEVEL_DIRECTORIES = ( + "Sources", + "Tests", + "Shared", + "Extensions", + "Configurations", + "Scripts", + "Packages", +) + def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description=__doc__) @@ -89,6 +99,21 @@ def install_xcodegen_templates(target_dir: Path, name: str, platform: str, bundl return installed_paths +def install_standard_directories(target_dir: Path) -> list[str]: + installed_paths: list[str] = [] + for relative_path in STANDARD_TOP_LEVEL_DIRECTORIES: + directory = target_dir / relative_path + directory.mkdir(parents=True, exist_ok=True) + installed_paths.append(str(directory)) + + for relative_path in ("Shared/.gitkeep", "Extensions/.gitkeep", "Scripts/.gitkeep", "Packages/.gitkeep"): + placeholder = target_dir / relative_path + write_text(placeholder, "") + installed_paths.append(str(placeholder)) + + return installed_paths + + def install_local_environment(target_dir: Path, scheme_name: str) -> str: template_path = ( Path(__file__).resolve().parents[3] @@ -214,6 +239,7 @@ def main() -> int: return 1 target_dir.mkdir(parents=True, exist_ok=True) + standard_directory_paths = install_standard_directories(target_dir) try: xcodegen_template_paths = install_xcodegen_templates( @@ -365,6 +391,7 @@ def main() -> int: "generator": "xcodegen", "project_file": str(target_dir / f"{args.name}.xcodeproj"), "xcodegen_template_paths": xcodegen_template_paths, + "standard_directory_paths": standard_directory_paths, "local_environment_path": local_environment_path, "agents_copied": agents_copied, "stdout": proc_install_toolkit.stdout + proc_generate.stdout + validation_stdout, diff --git a/plugins/apple-dev-skills/skills/core-animation-layer-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/core-animation-layer-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/core-animation-layer-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/core-animation-layer-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/coreaudio-modernization-repair-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/coreaudio-modernization-repair-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/coreaudio-modernization-repair-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/coreaudio-modernization-repair-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/coremedia-timing-samplebuffer-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/coremedia-timing-samplebuffer-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/coremedia-timing-samplebuffer-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/coremedia-timing-samplebuffer-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/devicecheck-app-attest-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/devicecheck-app-attest-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/devicecheck-app-attest-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/devicecheck-app-attest-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/explore-apple-swift-docs/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/explore-apple-swift-docs/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/explore-apple-swift-docs/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/explore-apple-swift-docs/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/format-swift-sources/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/format-swift-sources/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/format-swift-sources/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/format-swift-sources/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/SKILL.md b/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/SKILL.md index 2d55e25e..8c89cf35 100644 --- a/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/SKILL.md +++ b/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/SKILL.md @@ -50,10 +50,11 @@ Convert existing native Apple app projects to the current XcodeGen baseline with 6. Prepare the migration branch: - add or update `project.yml` - add or update `Configurations/*.xcconfig` + - add or preserve the standard top-level directories: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/` - add or update `Sources/Support/.entitlements` - add or update `Sources/Support/Info.plist` - add or update `Sources/Resources/Assets.xcassets` - - keep the app target's XcodeGen source declaration collapsed to one top-level `Sources` entry and the test target's declaration collapsed to one top-level `Tests` entry + - keep the app target's XcodeGen source declaration collapsed to one top-level `Sources` entry, shared app/extension code collapsed to one top-level `Shared` entry, and the test target's declaration collapsed to one top-level `Tests` entry - preserve exactly one app lifecycle entry point; do not create alternate `@main` app types, duplicate `main.swift` files, target-specific app entry files, or parallel app structs for variants - preserve existing package, framework, source, resource, script phase, scheme, and test-plan state 7. Generate into a temp or reviewed branch state: diff --git a/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/references/migration-audit-and-promotion.md b/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/references/migration-audit-and-promotion.md index 3a07c047..22207f4f 100644 --- a/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/references/migration-audit-and-promotion.md +++ b/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/references/migration-audit-and-promotion.md @@ -22,14 +22,15 @@ This is the `xcode-managed-to-xcodegen` path emitted by the audit script. - targets, product types, build configurations, schemes, packages, frameworks, source groups, resources, scripts, entitlements, Info.plist files, asset catalogs, and test plans 2. Create the external owner files: - shared, app, test, Debug, and Release `.xcconfig` layers + - standard top-level directories: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/` - app entitlement plist - support Info.plist if the project currently generates one internally - resource folder with `Assets.xcassets` when missing 3. Write `project.yml` from the inventory: - prefer `options.defaultSourceDirectoryType: syncedFolder` - prefer `type: syncedFolder` for broad top-level roots on Xcode 16 or newer - - use exactly one `Sources` entry for the app target and exactly one `Tests` entry for the test target - - use one separate top-level `Resources` entry only when the repo really has a separate repo-root resource tree + - use exactly one `Sources` entry for the app target, one `Shared` entry for shared app/extension source, and exactly one `Tests` entry for the test target + - use one `Extensions/` entry per extension target - never split ordinary paths such as `Sources/App`, `Sources/Resources`, `Sources/Support`, feature subfolders, or `Tests/Tests` into separate XcodeGen source entries - use the same broad recursive paths with explicit includes and excludes only when synced folders are not appropriate 4. Generate and compare: @@ -45,7 +46,7 @@ Use this `modernize-xcodegen` path to modernize XcodeGen projects that already h 2. Move inline or generated-only settings into `.xcconfig` files. 3. Add missing external entitlements, Info.plist, resource folders, and asset catalog defaults under the broad owning root. 4. Prefer synced folders for broad app, test, and top-level resource roots when the supported Xcode/XcodeGen versions allow it. -5. Collapse any ordinary source-root fragmentation back to one `Sources` entry, one `Tests` entry, and at most one entry for each genuinely separate top-level logical root. +5. Collapse any ordinary source-root fragmentation back to one `Sources` entry, one `Shared` entry, one `Tests` entry, and one `Extensions/` entry per extension target. 6. Regenerate and verify the generated `.pbxproj` diff is expected. ## Baseline Targets @@ -55,8 +56,10 @@ The current baseline should include: - XcodeGen `minimumXcodeGenVersion` on the current template baseline - `options.defaultSourceDirectoryType: syncedFolder` - app target source membership declared as one broad `Sources` entry marked with `type: syncedFolder` +- shared app/extension source membership declared as one broad `Shared` entry marked with `type: syncedFolder` - test target source membership declared as one broad `Tests` entry marked with `type: syncedFolder` - no ordinary fragmentation into `Sources/App`, `Sources/Resources`, `Sources/Support`, feature subfolders, or `Tests/Tests` source entries +- standard top-level directories present: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/` - exactly one app lifecycle entry point per app target - shared, app, test, Debug, and Release `.xcconfig` layers - `SWIFT_VERSION = 6.0` diff --git a/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/scripts/migrate_xcode_project_to_xcodegen.py b/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/scripts/migrate_xcode_project_to_xcodegen.py index 6dc094db..2905aa05 100755 --- a/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/scripts/migrate_xcode_project_to_xcodegen.py +++ b/plugins/apple-dev-skills/skills/migrate-xcode-project-to-xcodegen/scripts/migrate_xcode_project_to_xcodegen.py @@ -36,6 +36,16 @@ "version_build": "CFBundleVersion: $(CURRENT_PROJECT_VERSION)", } +STANDARD_TOP_LEVEL_DIRECTORIES = ( + "Sources", + "Tests", + "Shared", + "Extensions", + "Configurations", + "Scripts", + "Packages", +) + def read_text(path: Path) -> str: try: @@ -113,7 +123,7 @@ def extract_pbxproj_target_names(pbxproj_text: str) -> list[str]: def extract_fragmented_source_entries(project_yml_text: str) -> list[str]: fragments = set() - pattern = re.compile(r"^\s*-\s*(?:path:\s*)?(Sources|Tests|Resources)/([^\s#]+)", re.MULTILINE) + pattern = re.compile(r"^\s*-\s*(?:path:\s*)?(Sources|Tests|Shared|Resources)/([^\s#]+)", re.MULTILINE) for match in pattern.finditer(project_yml_text): fragments.add(f"{match.group(1)}/{match.group(2).rstrip(',')}") return sorted(fragments) @@ -163,6 +173,8 @@ def audit_project_yml(project_yml_path: Path | None) -> dict[str, Any]: gaps = [name for name, needle in BASELINE_PROJECT_YML_NEEDLES.items() if needle not in text] if not has_broad_source_entry(text, "Sources"): gaps.append("sources_root") + if not has_broad_source_entry(text, "Shared"): + gaps.append("shared_root") if not has_broad_source_entry(text, "Tests"): gaps.append("tests_root") fragmented_source_entries = extract_fragmented_source_entries(text) @@ -187,6 +199,9 @@ def audit_files(repo_root: Path, app_name: str | None) -> dict[str, Any]: expected_app_entitlements = ( f"Sources/Support/{app_name}.entitlements" if app_name else "Sources/Support/.entitlements" ) + missing_standard_directories = [ + relative_path for relative_path in STANDARD_TOP_LEVEL_DIRECTORIES if not (repo_root / relative_path).is_dir() + ] return { "xcconfigs": sorted_relative(xcconfigs, repo_root), "entitlements": sorted_relative(entitlements, repo_root), @@ -194,6 +209,7 @@ def audit_files(repo_root: Path, app_name: str | None) -> dict[str, Any]: "asset_catalogs": sorted_relative(asset_catalogs, repo_root), "schemes": sorted_relative(schemes, repo_root), "test_plans": sorted_relative(test_plans, repo_root), + "missing_standard_directories": missing_standard_directories, "app_entry_points": find_app_entry_points(repo_root), "expected_app_entitlements": expected_app_entitlements, "has_app_named_entitlements": (repo_root / expected_app_entitlements).exists() if app_name else False, @@ -241,7 +257,13 @@ def build_recommendations( recommendations.append( "Collapse fragmented XcodeGen source entries into broad top-level roots: " + ", ".join(project_yml_audit["fragmented_source_entries"]) - + ". Use one Sources entry for the app target, one Tests entry for the test target, and one entry per separate top-level logical root only." + + ". Use one Sources entry for the app target, one Shared entry for shared app/extension code, one Tests entry for the test target, and one Extensions/ entry per extension target only." + ) + if file_audit["missing_standard_directories"]: + recommendations.append( + "Add missing standard top-level Xcode app directories: " + + ", ".join(file_audit["missing_standard_directories"]) + + "." ) if len(file_audit["app_entry_points"]) > 1: recommendations.append( diff --git a/plugins/apple-dev-skills/skills/safari-extension-control-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/safari-extension-control-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/safari-extension-control-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/safari-extension-control-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/sf-symbols-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/sf-symbols-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/sf-symbols-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/sf-symbols-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/swiftui-animation-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/swiftui-animation-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/swiftui-animation-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/swiftui-animation-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/swiftui-app-architecture-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/swiftui-app-architecture-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/swiftui-app-architecture-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/swiftui-app-architecture-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/SKILL.md b/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/SKILL.md index 08de6168..d3d6bb92 100644 --- a/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/SKILL.md +++ b/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/SKILL.md @@ -69,15 +69,15 @@ This skill can be discovered from a standalone `apple-dev-skills` install, but i - verify the synced file preserves the no-direct-`.pbxproj` rule and the tracked `.pbxproj` stage-and-commit rule - verify the synced file preserves the XcodeGen source-of-truth rule for repos that use generated projects 8. Refresh `maintain-project-repo`: - - refresh `scripts/repo-maintenance/` + - refresh `Scripts/repo-maintenance/` - refresh `.github/workflows/validate-repo-maintenance.yml` - preserve repo-specific extra scripts that are not part of the managed file set 9. Verify the synced maintenance guidance still points at the expected maintainer files: - `.swiftformat` - - `scripts/repo-maintenance/hooks/pre-commit.sample` - - `scripts/repo-maintenance/validate-all.sh` - - `scripts/repo-maintenance/sync-shared.sh` - - `scripts/repo-maintenance/release.sh` + - `Scripts/repo-maintenance/hooks/pre-commit.sample` + - `Scripts/repo-maintenance/validate-all.sh` + - `Scripts/repo-maintenance/sync-shared.sh` + - `Scripts/repo-maintenance/release.sh` - protected branches, when configured, require the GitHub Actions check context `validate` rather than `Validate Repo Maintenance / validate` - when a GitHub remote exists, route repository settings audit or mutation through `productivity-skills:maintain-github-repository` @@ -132,7 +132,7 @@ This skill can be discovered from a standalone `apple-dev-skills` install, but i - The only current fallback is a non-mutating dry-run or guided result that explains what the sync would do. - After a successful sync, hand off ongoing build, run, diagnostics, preview, and mutation work to `xcode-build-run-workflow`. - After a successful sync, hand off ongoing test execution and test diagnosis work to `xcode-testing-workflow`. -- After a successful sync, use `scripts/repo-maintenance/validate-all.sh` for local maintainer validation and `scripts/repo-maintenance/release.sh --mode standard --version vX.Y.Z` from a feature branch or worktree for protected-main releases. +- After a successful sync, use `Scripts/repo-maintenance/validate-all.sh` for local maintainer validation and `Scripts/repo-maintenance/release.sh --mode standard --version vX.Y.Z` from a feature branch or worktree for protected-main releases. - After a successful sync, configure protected branches to require `validate` for the managed repo-maintenance workflow; GitHub exposes that job check context directly rather than the workflow title plus job string. - When a GitHub remote exists, use `productivity-skills:maintain-github-repository` to audit repository features, merge modes, security automation, sign-off @@ -147,7 +147,7 @@ When the user explicitly asks for subagents, `swift-steward`, review-packet plan Good `swift-steward` jobs for this skill: - classify the project shape and flag ambiguous SwiftPM/Xcode boundaries -- inspect `AGENTS.md`, README, CONTRIBUTING, ROADMAP, Xcode project/workspace markers, `.swiftformat`, `.swiftlint.yml`, and `scripts/repo-maintenance/` +- inspect `AGENTS.md`, README, CONTRIBUTING, ROADMAP, Xcode project/workspace markers, `.swiftformat`, `.swiftlint.yml`, and `Scripts/repo-maintenance/` - compare current repo guidance against this skill's current Xcode baseline - return a review packet with proposed patch set, validation handoff, affected files, and blockers diff --git a/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/assets/AGENTS.md b/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/assets/AGENTS.md index 6d3cd8bf..b454d18f 100644 --- a/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/assets/AGENTS.md +++ b/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/assets/AGENTS.md @@ -7,10 +7,10 @@ - Use `apple-ui-accessibility-workflow` when the task is primarily about SwiftUI accessibility semantics, Apple UI accessibility review, accessibility tree shaping, or UIKit/AppKit accessibility bridge behavior. - Use `sync-xcode-project-guidance` when the repo guidance for this project drifts and needs to be refreshed or merged forward. - Re-run `sync-xcode-project-guidance` after substantial Xcode-workflow or plugin updates so local guidance stays aligned. -- Use `scripts/repo-maintenance/validate-all.sh` for local maintainer validation and `scripts/repo-maintenance/sync-shared.sh` for repo-local sync steps. -- Use `scripts/repo-maintenance/release.sh --mode standard --version vX.Y.Z` from a feature branch or worktree only when the task is actually a protected-main release, publish, merge, tag, or release-PR preparation. +- Use `Scripts/repo-maintenance/validate-all.sh` for local maintainer validation and `Scripts/repo-maintenance/sync-shared.sh` for repo-local sync steps. +- Use `Scripts/repo-maintenance/release.sh --mode standard --version vX.Y.Z` from a feature branch or worktree only when the task is actually a protected-main release, publish, merge, tag, or release-PR preparation. - Do not run the standard release workflow from `main`; when a protected-main release is explicitly requested, let it validate, bump versions, tag, push the branch and tag, open the release PR, watch CI, address valid PR comments or record out-of-scope concerns in `ROADMAP.md`, merge to protected `main`, fast-forward local `main`, and clean up stale branches. -- Treat `scripts/repo-maintenance/config/profile.env` as the installed `maintain-project-repo` profile marker, and keep it on the `xcode-app` profile for native Apple app repos. +- Treat `Scripts/repo-maintenance/config/profile.env` as the installed `maintain-project-repo` profile marker, and keep it on the `xcode-app` profile for native Apple app repos. - Read relevant Apple documentation before proposing or making Xcode, SwiftUI, lifecycle, architecture, or build-configuration changes. - Prefer Xcode MCP DocumentationSearch or local Apple docs first for Apple-owned SDK, framework, and lifecycle questions; use Dash MCP or Dash HTTP next when installed local package docs or multi-ecosystem docs are a better fit; then use official Apple docs when local docs are insufficient. - Prefer the simplest correct Swift that is easiest to read and reason about. @@ -21,12 +21,15 @@ - Keep data flow straight and dependency direction unidirectional. - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for app integration, schemes, and build settings. - Prefer Xcode-aware tooling or `xcodebuild` over ad hoc filesystem assumptions when project structure or target membership is involved. +- Use the standard top-level Xcode app repository layout: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable; do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos. - For new Xcode app, framework, and workspace repositories, prefer XcodeGen plus synced source folders, checked-in `.xcconfig` files, and checked-in entitlement files by default unless there is a concrete reason to avoid that generator dependency. - If this repo is XcodeGen-backed, treat `project.yml`, `project.yaml`, and any included XcodeGen specs as the source of truth for generated targets, schemes, build settings, build configurations, Swift packages, test-plan references, and file membership. - For XcodeGen-backed projects, edit the spec set and rerun `xcodegen generate` instead of hand-editing generated `.pbxproj` files. - Before running `xcodegen generate`, inspect the current git diff for generated `.xcodeproj` or `.pbxproj` changes. Treat existing project-file diffs as intentional user or Xcode GUI changes by default, promote intentional values into the owning tracked source files first, and only then regenerate. Use XcodeGen specs for structure, `.xcconfig` files for build settings, `.entitlements` files for entitlement keys, `Info.plist` for plist keys, scheme specs or `.xcscheme` files for scheme behavior, and `.xctestplan` files for test-plan content. - For Xcode 16 or newer project formats, prefer `syncedFolder` roots at the broad top-level directory boundary so Xcode and the filesystem stay aligned for file membership. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` does not fit a repo, use the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes` as the fallback; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Every native app target must have exactly one app lifecycle entry point: one `@main` app type, one `main.swift`, or the platform-equivalent single launch entry. Do not add alternate app entry points, second `@main` types, duplicate `main.swift` files, target-specific app entry files, or parallel app structs for variants. Keep platform, configuration, or feature-flag differences inside that single entry point with Swift conditional compilation or runtime conditionals. @@ -41,7 +44,7 @@ - Prefer normal Xcode and XCTest parallel execution for ordinary Swift Testing, XCTest, and XCUITest runs when the project, scheme, destination, and test plan support it. Do not serialize regular tests just because they use Swift, XCTest, async tests, UI automation, or `.xctestplan` matrices. - Treat tests that load large local AI or ML models, especially models over 500 million parameters, as heavy system-resource tests. Run those tests sequentially, one at a time, and call `unload_models` on Gale's live TTS service before the heavy run and `reload_models` after it ends, even when the run fails or is interrupted. - Prefer a checked-in repo-root `.swiftformat` file as the Swift formatting source of truth. -- Prefer a pre-commit hook such as `scripts/repo-maintenance/hooks/pre-commit.sample` that formats staged Swift sources and then verifies them with `swiftformat --lint` before commit. +- Prefer a pre-commit hook such as `Scripts/repo-maintenance/hooks/pre-commit.sample` that formats staged Swift sources and then verifies them with `swiftformat --lint` before commit. - Treat SwiftLint as an optional complementary signal layer for clarity, safety, and maintainability after SwiftFormat owns formatting shape. - Treat accessibility semantics and Apple UI accessibility review as a separate concern from UI automation; use `apple-ui-accessibility-workflow` for the semantic side and `xcode-testing-workflow` for runtime verification and XCUITest follow-through. - When scripts add files on disk, verify project membership, target membership, build phases, and resource inclusion afterward; files existing in the directory tree alone are not enough. diff --git a/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/assets/append-section.md b/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/assets/append-section.md index 2d6514e2..4ffb6f17 100644 --- a/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/assets/append-section.md +++ b/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/assets/append-section.md @@ -5,10 +5,10 @@ - Use `apple-ui-accessibility-workflow` when the task is primarily about SwiftUI accessibility semantics, Apple UI accessibility review, accessibility tree shaping, or UIKit/AppKit accessibility bridge behavior. - Use `sync-xcode-project-guidance` when the repo guidance for this project drifts and needs to be refreshed or merged forward. - Re-run `sync-xcode-project-guidance` after substantial Xcode-workflow or plugin updates so local guidance stays aligned. -- Use `scripts/repo-maintenance/validate-all.sh` for local maintainer validation and `scripts/repo-maintenance/sync-shared.sh` for repo-local sync steps. -- Use `scripts/repo-maintenance/release.sh --mode standard --version vX.Y.Z` from a feature branch or worktree only when the task is actually a protected-main release, publish, merge, tag, or release-PR preparation. +- Use `Scripts/repo-maintenance/validate-all.sh` for local maintainer validation and `Scripts/repo-maintenance/sync-shared.sh` for repo-local sync steps. +- Use `Scripts/repo-maintenance/release.sh --mode standard --version vX.Y.Z` from a feature branch or worktree only when the task is actually a protected-main release, publish, merge, tag, or release-PR preparation. - Do not run the standard release workflow from `main`; when a protected-main release is explicitly requested, let it validate, bump versions, tag, push the branch and tag, open the release PR, watch CI, address valid PR comments or record out-of-scope concerns in `ROADMAP.md`, merge to protected `main`, fast-forward local `main`, and clean up stale branches. -- Treat `scripts/repo-maintenance/config/profile.env` as the installed `maintain-project-repo` profile marker, and keep it on the `xcode-app` profile for native Apple app repos. +- Treat `Scripts/repo-maintenance/config/profile.env` as the installed `maintain-project-repo` profile marker, and keep it on the `xcode-app` profile for native Apple app repos. - Read relevant Apple documentation before proposing or making Xcode, SwiftUI, lifecycle, architecture, or build-configuration changes. - Prefer Xcode MCP DocumentationSearch or local Apple docs first for Apple-owned SDK, framework, and lifecycle questions; use Dash MCP or Dash HTTP next when installed local package docs or multi-ecosystem docs are a better fit; then use official Apple docs when local docs are insufficient. - Prefer the simplest correct Swift that is easiest to read and reason about. @@ -19,12 +19,15 @@ - Keep data flow straight and dependency direction unidirectional. - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for app integration, schemes, and build settings. - Prefer Xcode-aware tooling or `xcodebuild` over ad hoc filesystem assumptions when project structure or target membership is involved. +- Use the standard top-level Xcode app repository layout: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable; do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos. - For new Xcode app, framework, and workspace repositories, prefer XcodeGen plus synced source folders, checked-in `.xcconfig` files, and checked-in entitlement files by default unless there is a concrete reason to avoid that generator dependency. - If this repo is XcodeGen-backed, treat `project.yml`, `project.yaml`, and any included XcodeGen specs as the source of truth for generated targets, schemes, build settings, build configurations, Swift packages, test-plan references, and file membership. - For XcodeGen-backed projects, edit the spec set and rerun `xcodegen generate` instead of hand-editing generated `.pbxproj` files. - Before running `xcodegen generate`, inspect the current git diff for generated `.xcodeproj` or `.pbxproj` changes. Treat existing project-file diffs as intentional user or Xcode GUI changes by default, promote intentional values into the owning tracked source files first, and only then regenerate. Use XcodeGen specs for structure, `.xcconfig` files for build settings, `.entitlements` files for entitlement keys, `Info.plist` for plist keys, scheme specs or `.xcscheme` files for scheme behavior, and `.xctestplan` files for test-plan content. - For Xcode 16 or newer project formats, prefer `syncedFolder` roots at the broad top-level directory boundary so Xcode and the filesystem stay aligned for file membership. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` does not fit a repo, use the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes` as the fallback; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Every native app target must have exactly one app lifecycle entry point: one `@main` app type, one `main.swift`, or the platform-equivalent single launch entry. Do not add alternate app entry points, second `@main` types, duplicate `main.swift` files, target-specific app entry files, or parallel app structs for variants. Keep platform, configuration, or feature-flag differences inside that single entry point with Swift conditional compilation or runtime conditionals. diff --git a/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/scripts/sync_xcode_project_guidance.py b/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/scripts/sync_xcode_project_guidance.py index 9c9a4aad..335c0f73 100755 --- a/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/scripts/sync_xcode_project_guidance.py +++ b/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/scripts/sync_xcode_project_guidance.py @@ -18,9 +18,9 @@ "sync-xcode-project-guidance", "Never edit `.pbxproj` files directly.", "treat that diff as critical project state", - "scripts/repo-maintenance/validate-all.sh", - "scripts/repo-maintenance/sync-shared.sh", - "scripts/repo-maintenance/release.sh", + "Scripts/repo-maintenance/validate-all.sh", + "Scripts/repo-maintenance/sync-shared.sh", + "Scripts/repo-maintenance/release.sh", ] diff --git a/plugins/apple-dev-skills/skills/xcode-app-project-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/xcode-app-project-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/xcode-app-project-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/xcode-app-project-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/xcode-app-project-workflow/references/xcodegen-project-maintenance.md b/plugins/apple-dev-skills/skills/xcode-app-project-workflow/references/xcodegen-project-maintenance.md index 5e7312cc..3df752b3 100644 --- a/plugins/apple-dev-skills/skills/xcode-app-project-workflow/references/xcodegen-project-maintenance.md +++ b/plugins/apple-dev-skills/skills/xcode-app-project-workflow/references/xcodegen-project-maintenance.md @@ -16,7 +16,8 @@ Authoritative XcodeGen references: - If the request asks for new-project defaults, template changes, minimum XcodeGen versions, or baseline `.xcconfig` layout, route to `bootstrap-xcode-app-project`. - Treat XcodeGen specs as the owner for targets, resources, schemes, packages, project references, test-plan references, configuration-file wiring, generation options, and generated file membership. - Before any regeneration, route existing generated `.xcodeproj` or `.pbxproj` diffs through the narrower build/run or testing workflow so user-made Xcode GUI changes can be promoted into the owning XcodeGen spec, `.xcconfig`, `.entitlements`, `Info.plist`, scheme, or test-plan file first. -- Treat Xcode 16 `syncedFolder` roots at the broad top-level directory boundary as the preferred file-membership model for new generated app and test targets. Use exactly one `Sources` entry for the app target and exactly one `Tests` entry for the test target; if a repo has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root. +- Preserve the standard top-level Xcode app layout when routing generated project changes: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- Treat Xcode 16 `syncedFolder` roots at the broad top-level directory boundary as the preferred file-membership model for new generated app and test targets. Use exactly one `Sources` entry for the app target, one `Shared` entry for shared app/extension source, and exactly one `Tests` entry for the test target. Extension targets use one `Extensions/` source entry per extension target. - Do not split ordinary folders such as `Sources/App`, `Sources/Resources`, `Sources/Support`, feature subfolders, or `Tests/Tests` into separate XcodeGen source entries. Use the same broad top-level recursive source paths plus explicit `includes` and `excludes` as the fallback when synchronized folders are not appropriate. - Preserve exactly one app lifecycle entry point per app target. Do not add alternate `@main` app types, duplicate `main.swift` files, target-specific app entry files, or parallel app structs for variants; put platform, configuration, or product-variant differences inside the single entry point with Swift conditional compilation or runtime conditionals. - Treat `.xcconfig` files as the owner for nontrivial build settings, with shared, target-level, and per-configuration layers when a repo uses that layout. diff --git a/plugins/apple-dev-skills/skills/xcode-build-run-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/xcode-build-run-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/xcode-build-run-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/xcode-build-run-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/xcode-build-run-workflow/references/xcodegen-project-maintenance.md b/plugins/apple-dev-skills/skills/xcode-build-run-workflow/references/xcodegen-project-maintenance.md index 8a5af8de..c8e3cf6e 100644 --- a/plugins/apple-dev-skills/skills/xcode-build-run-workflow/references/xcodegen-project-maintenance.md +++ b/plugins/apple-dev-skills/skills/xcode-build-run-workflow/references/xcodegen-project-maintenance.md @@ -25,8 +25,9 @@ Authoritative XcodeGen references: - Keep top-level `schemes` explicit when build, run, archive, profile, analyze, command-line arguments, environment variables, or test-plan behavior matters. Do not rely on generated scheme defaults after the repo has explicit scheme policy. - Declare Swift packages in the spec-level `packages` map and link them through target `dependencies`; do not add package references by hand in the generated project. - Use `projectReferences`, `targetTemplates`, and `schemeTemplates` when they remove real repetition across generated modules, not as ceremony for a tiny one-target project. +- Preserve the standard top-level Xcode app layout when adding or moving generated targets: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. - For Xcode 16 or newer project formats, prefer `syncedFolder` roots at the broad top-level directory boundary so Xcode and the filesystem stay aligned for file membership. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate ordinary XcodeGen source entries. If synchronized folders are not appropriate, use the same broad top-level recursive paths with explicit `includes` and `excludes` as the fallback instead of hand-listing every ordinary source file or fragmenting by child directory. - Prefer external `.xcconfig` files for nontrivial build settings and wire them from the XcodeGen spec instead of duplicating build settings inline. - Keep `.xcconfig` layering explicit, with a small shared base config, target-level configs for app/test/extension identity, and per-configuration configs that include the narrower target config and override only what changes. diff --git a/plugins/apple-dev-skills/skills/xcode-coding-intelligence-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/xcode-coding-intelligence-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/xcode-coding-intelligence-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/xcode-coding-intelligence-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/xcode-testing-workflow/references/snippets/apple-xcode-project-core.md b/plugins/apple-dev-skills/skills/xcode-testing-workflow/references/snippets/apple-xcode-project-core.md index 7449ff3f..1f2e66a2 100644 --- a/plugins/apple-dev-skills/skills/xcode-testing-workflow/references/snippets/apple-xcode-project-core.md +++ b/plugins/apple-dev-skills/skills/xcode-testing-workflow/references/snippets/apple-xcode-project-core.md @@ -78,6 +78,9 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - Treat the `.xcworkspace` or `.xcodeproj` as the source of truth for Apple platform app integration, schemes, build settings, destinations, and target membership. - Prefer edits through Xcode-aware project structure and keep project file changes intentional and reviewed closely. +- Use the standard top-level Xcode app repository layout when creating or normalizing native app repos: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. +- `Sources/` owns the main app target implementation and app-owned resources/support files. `Tests/` owns all test targets. `Shared/` owns reusable source intended to be compiled into the app and extension targets. `Extensions/` owns extension target roots, one folder per extension. `Configurations/` owns `.xcconfig` layers. `Scripts/` owns project-local automation and build helper scripts. `Packages/` owns local Swift packages only when a real package boundary is justified. +- Keep those top-level roots stable. Do not invent parallel names such as `AppSources`, `TestSources`, `Config`, `BuildScripts`, or `LocalPackages` for ordinary Xcode app repos unless the existing repo already has a deliberate, documented convention. - Use `xcodebuild` for Apple platform integration validation, including scheme, destination or SDK, and configuration-specific build or test runs. - Keep `xcodebuild` invocations reproducible in automation by passing explicit schemes, destinations or SDKs, and configurations when relevant. - For Codex GUI worktree-first Xcode repos, use a portable `.codex/environments/*.toml` local environment file when the repo wants shared app setup or action buttons. Start from `apple-dev-skills/templates/codex-local-environments/xcode-project.toml`, keep paths repo-relative, and prefer `-derivedDataPath ./DerivedData` or another ignored repo-local build directory instead of user-global DerivedData. @@ -99,7 +102,7 @@ Use this snippet in repository `AGENTS.md` files when you want baseline standard - For new XcodeGen-backed app scaffolds, start from the maintained `apple-dev-skills/templates/xcodegen/` templates when available instead of inventing a fresh project-spec shape from memory. - Keep `minimumXcodeGenVersion` on a recent validated release for new scaffolds. Prefer updating the template and validation together when the repo intentionally raises the baseline. - For Xcode 16 or newer project formats, prefer XcodeGen `syncedFolder` roots at the broad top-level directory boundary so file creation, deletion, and organization stay synchronized between Xcode and the filesystem without hand-listing every source file in YAML. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root, not one entry per child folder. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. If a project has another separate top-level logical root, use one top-level entry for that root, not one entry per child folder. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate XcodeGen source entries unless a specific non-ordinary file or folder truly needs custom compiler flags, build-phase routing, destination filters, or target membership that cannot be represented from the broad root. - If `syncedFolder` behaves poorly for a repo, fall back to the same broad top-level recursive paths such as `Sources`, `Tests`, or `Resources` with explicit `includes` and `excludes`; do not fall back to subdirectory-level fragmentation or one YAML entry per ordinary source file. - Keep XcodeGen specs readable as project structure, not as a dumping ground for every build setting. Use `configs`, `configFiles`, `targets`, `schemes`, `packages`, `projectReferences`, `targetTemplates`, and `schemeTemplates` deliberately so future edits have an obvious owner. diff --git a/plugins/apple-dev-skills/skills/xcode-testing-workflow/references/xcodegen-project-maintenance.md b/plugins/apple-dev-skills/skills/xcode-testing-workflow/references/xcodegen-project-maintenance.md index b1e46737..eab5ef62 100644 --- a/plugins/apple-dev-skills/skills/xcode-testing-workflow/references/xcodegen-project-maintenance.md +++ b/plugins/apple-dev-skills/skills/xcode-testing-workflow/references/xcodegen-project-maintenance.md @@ -24,8 +24,9 @@ Authoritative XcodeGen references: - Use top-level `schemes` for generated test behavior once the repo needs explicit test actions, coverage settings, command-line arguments, environment variables, test targets, or test-plan references. - Remember that XcodeGen references checked-in `.xctestplan` files by path; it does not create the test-plan file content for you. Create or update the `.xctestplan` through Xcode or a structured JSON-aware edit, then wire the path through the scheme spec. - Use target-level `configFiles` for test bundles when test-only build settings, bundle identifiers, compilation conditions, or host-app settings diverge from the app target. +- Preserve the standard top-level Xcode app layout when adding or moving generated targets: `Sources/`, `Tests/`, `Shared/`, `Extensions/`, `Configurations/`, `Scripts/`, and `Packages/`. - For Xcode 16 or newer project formats, prefer `syncedFolder` roots at the broad top-level directory boundary so Xcode and the filesystem stay aligned for file membership. -- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders. A standard test target gets one `Tests` source entry that includes all test subdirectories. If a project has a separate top-level logical root such as `Resources`, use one top-level `Resources` entry for that root. +- Do not fragment ordinary XcodeGen source roots by subdirectory. A standard app target gets one `Sources` source entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus one `Shared` source entry when shared app/extension code exists. A standard test target gets one `Tests` source entry that includes all test subdirectories. Extension targets use one `Extensions/` source entry per extension target. - Never split `Sources/App`, `Sources/Resources`, `Sources/Support`, feature folders, or `Tests/Tests` into separate ordinary XcodeGen source entries. If synchronized folders are not appropriate, use the same broad top-level recursive paths with explicit `includes` and `excludes` as the fallback instead of hand-listing every ordinary test file or fragmenting by child directory. - Prefer external `.xcconfig` files for nontrivial build settings and wire them from the XcodeGen spec instead of duplicating build settings inline. - Keep `.xcconfig` layering explicit, with a small shared base config, target-level configs for app/test/extension identity, and per-configuration configs that include the narrower target config and override only what changes. diff --git a/plugins/apple-dev-skills/templates/xcodegen/swiftui-app/project.yml.tmpl b/plugins/apple-dev-skills/templates/xcodegen/swiftui-app/project.yml.tmpl index 799e8449..e31a5219 100644 --- a/plugins/apple-dev-skills/templates/xcodegen/swiftui-app/project.yml.tmpl +++ b/plugins/apple-dev-skills/templates/xcodegen/swiftui-app/project.yml.tmpl @@ -9,6 +9,9 @@ configs: Release: release fileGroups: - Configurations + - Extensions + - Packages + - Scripts targets: __APP_NAME__: type: application @@ -16,6 +19,10 @@ targets: sources: - path: Sources type: syncedFolder + - path: Shared + type: syncedFolder + excludes: + - "**/.gitkeep" info: path: Sources/Support/Info.plist properties: diff --git a/plugins/apple-dev-skills/tests/test_xcode_app_bootstrap_workflow.py b/plugins/apple-dev-skills/tests/test_xcode_app_bootstrap_workflow.py index 48afa1ce..bceef612 100644 --- a/plugins/apple-dev-skills/tests/test_xcode_app_bootstrap_workflow.py +++ b/plugins/apple-dev-skills/tests/test_xcode_app_bootstrap_workflow.py @@ -198,6 +198,7 @@ def test_xcodegen_path_can_succeed_with_fake_tools(self) -> None: self.assertIn("configFiles:", project_yml) self.assertIn("type: syncedFolder", project_yml) self.assertIn("- path: Sources", project_yml) + self.assertIn("- path: Shared", project_yml) self.assertIn("- path: Tests", project_yml) self.assertNotIn("- path: Sources/App", project_yml) self.assertNotIn("- path: Sources/Resources", project_yml) @@ -208,6 +209,10 @@ def test_xcodegen_path_can_succeed_with_fake_tools(self) -> None: self.assertIn("Configurations/App-Debug.xcconfig", project_yml) self.assertIn("Configurations/Tests-Debug.xcconfig", project_yml) self.assertIn("parallelizable: true", project_yml) + for top_level_dir in ("Sources", "Tests", "Shared", "Extensions", "Configurations", "Scripts", "Packages"): + self.assertTrue((target / top_level_dir).is_dir(), top_level_dir) + for placeholder in ("Shared/.gitkeep", "Extensions/.gitkeep", "Scripts/.gitkeep", "Packages/.gitkeep"): + self.assertTrue((target / placeholder).exists(), placeholder) self.assertTrue((target / "Sources" / "Support" / "DemoApp.entitlements").exists()) self.assertTrue((target / "Sources" / "Resources" / "Assets.xcassets" / "Contents.json").exists()) self.assertTrue( @@ -284,6 +289,7 @@ def test_xcodegen_path_can_succeed_with_fake_tools(self) -> None: (target / "Configurations" / "Tests.xcconfig").read_text(encoding="utf-8"), ) self.assertIn("xcodegen_template_paths", payload) + self.assertIn("standard_directory_paths", payload) self.assertTrue((target / "AGENTS.md").exists()) local_environment_path = target / ".codex" / "environments" / "xcode-project.toml" self.assertTrue(local_environment_path.exists()) @@ -294,6 +300,8 @@ def test_xcodegen_path_can_succeed_with_fake_tools(self) -> None: self.assertIn("xcode-build-run-workflow", agents_text) self.assertIn("xcode-testing-workflow", agents_text) self.assertIn("XcodeGen plus synced source folders", agents_text) + self.assertIn("Use the standard top-level Xcode app repository layout", agents_text) + self.assertIn("`Shared/` owns reusable source intended to be compiled into the app and extension targets", agents_text) self.assertIn("A standard app target gets one `Sources` source entry", agents_text) self.assertIn("Every native app target must have exactly one app lifecycle entry point", agents_text) self.assertIn("Keep XcodeGen specs readable as project structure", agents_text) @@ -308,13 +316,13 @@ def test_xcodegen_path_can_succeed_with_fake_tools(self) -> None: self.assertIn("treat that diff as critical project state", agents_text) self.assertTrue((target / "DemoApp.xcodeproj").exists()) self.assertTrue((target / ".swiftformat").exists()) - self.assertTrue((target / "scripts" / "repo-maintenance" / "validate-all.sh").exists()) - self.assertTrue((target / "scripts" / "repo-maintenance" / "release.sh").exists()) - self.assertTrue((target / "scripts" / "repo-maintenance" / "hooks" / "pre-commit.sample").exists()) - self.assertTrue((target / "scripts" / "repo-maintenance" / "config" / "profile.env").exists()) + self.assertTrue((target / "Scripts" / "repo-maintenance" / "validate-all.sh").exists()) + self.assertTrue((target / "Scripts" / "repo-maintenance" / "release.sh").exists()) + self.assertTrue((target / "Scripts" / "repo-maintenance" / "hooks" / "pre-commit.sample").exists()) + self.assertTrue((target / "Scripts" / "repo-maintenance" / "config" / "profile.env").exists()) self.assertIn( 'REPO_MAINTENANCE_PROFILE="xcode-app"', - (target / "scripts" / "repo-maintenance" / "config" / "profile.env").read_text(encoding="utf-8"), + (target / "Scripts" / "repo-maintenance" / "config" / "profile.env").read_text(encoding="utf-8"), ) self.assertTrue((target / ".github" / "workflows" / "validate-repo-maintenance.yml").exists()) self.assertEqual(payload["validation_result"], "passed (xcodebuild -list)") @@ -343,6 +351,7 @@ def test_xcodegen_templates_are_checked_in_as_bootstrap_sources(self) -> None: self.assertIn("defaultSourceDirectoryType: syncedFolder", project_template) self.assertIn("type: syncedFolder", project_template) self.assertIn("- path: Sources", project_template) + self.assertIn("- path: Shared", project_template) self.assertIn("- path: Tests", project_template) self.assertNotIn("- path: Sources/App", project_template) self.assertNotIn("- path: Sources/Resources", project_template) diff --git a/plugins/apple-dev-skills/tests/test_xcode_guidance_sync_workflow.py b/plugins/apple-dev-skills/tests/test_xcode_guidance_sync_workflow.py index 9693e78e..f14ebc48 100644 --- a/plugins/apple-dev-skills/tests/test_xcode_guidance_sync_workflow.py +++ b/plugins/apple-dev-skills/tests/test_xcode_guidance_sync_workflow.py @@ -85,12 +85,12 @@ def test_sync_creates_agents_template(self) -> None: self.assertIn("four or more arguments or parameters", agents_text) self.assertIn("Prefer enums, enum cases with associated values", agents_text) self.assertTrue(Path(tmpdir, ".swiftformat").is_file()) - self.assertTrue(Path(tmpdir, "scripts/repo-maintenance/hooks/pre-commit.sample").is_file()) - self.assertTrue(Path(tmpdir, "scripts/repo-maintenance/validate-all.sh").is_file()) - self.assertTrue(Path(tmpdir, "scripts/repo-maintenance/config/profile.env").is_file()) + self.assertTrue(Path(tmpdir, "Scripts/repo-maintenance/hooks/pre-commit.sample").is_file()) + self.assertTrue(Path(tmpdir, "Scripts/repo-maintenance/validate-all.sh").is_file()) + self.assertTrue(Path(tmpdir, "Scripts/repo-maintenance/config/profile.env").is_file()) self.assertIn( 'REPO_MAINTENANCE_PROFILE="xcode-app"', - Path(tmpdir, "scripts/repo-maintenance/config/profile.env").read_text(encoding="utf-8"), + Path(tmpdir, "Scripts/repo-maintenance/config/profile.env").read_text(encoding="utf-8"), ) local_environment_path = Path(tmpdir, ".codex/environments/xcode-project.toml") self.assertTrue(local_environment_path.is_file()) @@ -129,11 +129,11 @@ def test_sync_appends_section_to_existing_agents(self) -> None: self.assertIn("four or more arguments or parameters", agents_text) self.assertIn("Prefer enums, enum cases with associated values", agents_text) self.assertTrue(Path(tmpdir, ".swiftformat").is_file()) - self.assertTrue(Path(tmpdir, "scripts/repo-maintenance/hooks/pre-commit.sample").is_file()) - self.assertTrue(Path(tmpdir, "scripts/repo-maintenance/release.sh").is_file()) + self.assertTrue(Path(tmpdir, "Scripts/repo-maintenance/hooks/pre-commit.sample").is_file()) + self.assertTrue(Path(tmpdir, "Scripts/repo-maintenance/release.sh").is_file()) self.assertIn( 'REPO_MAINTENANCE_PROFILE="xcode-app"', - Path(tmpdir, "scripts/repo-maintenance/config/profile.env").read_text(encoding="utf-8"), + Path(tmpdir, "Scripts/repo-maintenance/config/profile.env").read_text(encoding="utf-8"), ) def test_sync_preserves_existing_local_environment(self) -> None: @@ -217,7 +217,7 @@ def test_sync_discovers_socket_cache_sibling_productivity_runner(self) -> None: self.assertEqual(proc.returncode, 0, proc.stderr or proc.stdout) payload = json.loads(proc.stdout) self.assertEqual(payload["status"], "success") - self.assertTrue((repo_root / "scripts/repo-maintenance/validate-all.sh").is_file()) + self.assertTrue((repo_root / "Scripts/repo-maintenance/validate-all.sh").is_file()) if __name__ == "__main__": diff --git a/plugins/apple-dev-skills/tests/test_xcodegen_migration_workflow.py b/plugins/apple-dev-skills/tests/test_xcodegen_migration_workflow.py index cd915e1b..6f15c5f2 100644 --- a/plugins/apple-dev-skills/tests/test_xcodegen_migration_workflow.py +++ b/plugins/apple-dev-skills/tests/test_xcodegen_migration_workflow.py @@ -138,7 +138,12 @@ def test_audits_existing_xcodegen_project_for_current_baseline_gaps(self) -> Non self.assertIn("default_source_directory_type", output["project_yml_audit"]["baseline_gaps"]) self.assertIn("config_files", output["project_yml_audit"]["baseline_gaps"]) self.assertIn("sources_root", output["project_yml_audit"]["baseline_gaps"]) + self.assertIn("shared_root", output["project_yml_audit"]["baseline_gaps"]) self.assertIn("tests_root", output["project_yml_audit"]["baseline_gaps"]) + self.assertIn("Shared", output["file_audit"]["missing_standard_directories"]) + self.assertIn("Extensions", output["file_audit"]["missing_standard_directories"]) + self.assertIn("Scripts", output["file_audit"]["missing_standard_directories"]) + self.assertIn("Packages", output["file_audit"]["missing_standard_directories"]) self.assertIn("Sources/App", output["project_yml_audit"]["fragmented_source_entries"]) self.assertIn("Sources/Resources", output["project_yml_audit"]["fragmented_source_entries"]) self.assertIn("Tests/DemoAppTests", output["project_yml_audit"]["fragmented_source_entries"]) @@ -146,6 +151,7 @@ def test_audits_existing_xcodegen_project_for_current_baseline_gaps(self) -> Non self.assertIn("Sources/App/DemoAppBeta.swift", output["file_audit"]["app_entry_points"]) self.assertTrue(any("current baseline gaps" in phase for phase in output["recommended_phases"])) self.assertTrue(any("Collapse fragmented XcodeGen source entries" in phase for phase in output["recommended_phases"])) + self.assertTrue(any("Add missing standard top-level Xcode app directories" in phase for phase in output["recommended_phases"])) self.assertTrue(any("Collapse multiple app lifecycle entry points" in phase for phase in output["recommended_phases"])) def test_blocks_when_requested_modernization_has_no_project_yml(self) -> None: diff --git a/plugins/apple-dev-skills/uv.lock b/plugins/apple-dev-skills/uv.lock index 6d27efcd..093f6674 100644 --- a/plugins/apple-dev-skills/uv.lock +++ b/plugins/apple-dev-skills/uv.lock @@ -4,7 +4,7 @@ requires-python = ">=3.10" [[package]] name = "apple-dev-skills-maintainer" -version = "8.5.2" +version = "8.5.3" source = { virtual = "." } [package.dev-dependencies] diff --git a/plugins/cardhop-app/.codex-plugin/plugin.json b/plugins/cardhop-app/.codex-plugin/plugin.json index e2d77d53..dd1d0c14 100644 --- a/plugins/cardhop-app/.codex-plugin/plugin.json +++ b/plugins/cardhop-app/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "cardhop-app", - "version": "8.5.2", + "version": "8.5.3", "description": "Cardhop.app workflow guidance plus a bundled local MCP server for contact capture and updates on macOS.", "author": { "name": "Gale", diff --git a/plugins/cardhop-app/mcp/pyproject.toml b/plugins/cardhop-app/mcp/pyproject.toml index f9955708..3b30dac5 100644 --- a/plugins/cardhop-app/mcp/pyproject.toml +++ b/plugins/cardhop-app/mcp/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "cardhop-app-mcp" -version = "8.5.2" +version = "8.5.3" requires-python = ">=3.13" dependencies = [ "fastmcp>=3.0.2", diff --git a/plugins/cardhop-app/mcp/uv.lock b/plugins/cardhop-app/mcp/uv.lock index 08d3ddd1..0c63fb48 100644 --- a/plugins/cardhop-app/mcp/uv.lock +++ b/plugins/cardhop-app/mcp/uv.lock @@ -138,7 +138,7 @@ wheels = [ [[package]] name = "cardhop-app-mcp" -version = "8.5.2" +version = "8.5.3" source = { virtual = "." } dependencies = [ { name = "fastmcp" }, diff --git a/plugins/cloud-deployment-skills/.codex-plugin/plugin.json b/plugins/cloud-deployment-skills/.codex-plugin/plugin.json index fc85686c..2d929fe1 100644 --- a/plugins/cloud-deployment-skills/.codex-plugin/plugin.json +++ b/plugins/cloud-deployment-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "cloud-deployment-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Codex skills for routing cloud deployment work through official provider plugins, MCP servers, CLIs, and Socket-owned deployment guidance.", "author": { "name": "Gale", diff --git a/plugins/cloud-inference-skills/.codex-plugin/plugin.json b/plugins/cloud-inference-skills/.codex-plugin/plugin.json index 8379a846..2c5409ff 100644 --- a/plugins/cloud-inference-skills/.codex-plugin/plugin.json +++ b/plugins/cloud-inference-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "cloud-inference-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Cloud AI inference workflow skills for routing model serving, training, conversion, and GPU infrastructure work across Runpod, Hugging Face, AWS, Vast.ai, CoreWeave, and similar providers.", "author": { "name": "Gale", diff --git a/plugins/dotnet-skills/.codex-plugin/plugin.json b/plugins/dotnet-skills/.codex-plugin/plugin.json index 4e656cba..f26241da 100644 --- a/plugins/dotnet-skills/.codex-plugin/plugin.json +++ b/plugins/dotnet-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "dotnet-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Codex skills for choosing, bootstrapping, building, testing, packaging, diagnosing, and maintaining .NET projects with F# and C# as equal first-party languages.", "author": { "name": "Gale", diff --git a/plugins/game-dev-skills/.codex-plugin/plugin.json b/plugins/game-dev-skills/.codex-plugin/plugin.json index ecc01c2a..d1d50037 100644 --- a/plugins/game-dev-skills/.codex-plugin/plugin.json +++ b/plugins/game-dev-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "game-dev-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Apple platform game development workflow skills for SpriteKit, SceneKit, GameplayKit, controller input, haptics, profiling, and game-stack routing.", "author": { "name": "Gale", diff --git a/plugins/network-protocol-skills/.codex-plugin/plugin.json b/plugins/network-protocol-skills/.codex-plugin/plugin.json index ed79d6d7..4fe259d7 100644 --- a/plugins/network-protocol-skills/.codex-plugin/plugin.json +++ b/plugins/network-protocol-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "network-protocol-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Codex skills for choosing, planning, implementing, and diagnosing modern application transports and real-time networking protocols, including QUIC, HTTP/3, WebRTC, Media over QUIC, WebTransport-adjacent handoffs, protocol maturity checks, and stack-specific implementation routing.", "author": { "name": "Gale", diff --git a/plugins/productivity-skills/.codex-plugin/plugin.json b/plugins/productivity-skills/.codex-plugin/plugin.json index a287c0f1..2770a864 100644 --- a/plugins/productivity-skills/.codex-plugin/plugin.json +++ b/plugins/productivity-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "productivity-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Broadly useful productivity workflows for Codex.", "author": { "name": "Gale", diff --git a/plugins/productivity-skills/pyproject.toml b/plugins/productivity-skills/pyproject.toml index 1523a7db..76dc529f 100644 --- a/plugins/productivity-skills/pyproject.toml +++ b/plugins/productivity-skills/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "productivity-skills-maintenance" -version = "8.5.2" +version = "8.5.3" description = "Maintainer-only Python tooling baseline for productivity-skills." requires-python = ">=3.11" dependencies = [] diff --git a/plugins/productivity-skills/skills/maintain-project-repo/SKILL.md b/plugins/productivity-skills/skills/maintain-project-repo/SKILL.md index a9f401dd..5b90f673 100644 --- a/plugins/productivity-skills/skills/maintain-project-repo/SKILL.md +++ b/plugins/productivity-skills/skills/maintain-project-repo/SKILL.md @@ -10,7 +10,7 @@ metadata: ## Purpose -Install or refresh the reusable `maintain-project-repo` toolkit inside a general, SwiftPM, or Xcode repository so validation, shared-sync work, and release steps live in repo-owned local scripts rather than in CI-only glue. `scripts/run_workflow.py` is the runtime entrypoint, and `scripts/install_maintain_project_repo.py` applies the managed file set, writes `scripts/repo-maintenance/config/profile.env`, and keeps the installed profile explicit. +Install or refresh the reusable `maintain-project-repo` toolkit inside a general, SwiftPM, or Xcode repository so validation, shared-sync work, and release steps live in repo-owned local scripts rather than in CI-only glue. `scripts/run_workflow.py` is the runtime entrypoint, and `scripts/install_maintain_project_repo.py` applies the managed file set, writes the profile marker, and keeps the installed profile explicit. ## When To Use @@ -42,20 +42,22 @@ Install or refresh the reusable `maintain-project-repo` toolkit inside a general - choose `xcode-app` for native Apple app repos - choose `generic` when no stronger Swift or Xcode profile applies - stop if the requested path is not a repository root + - use `scripts/repo-maintenance/` for `generic` and `swift-package`; use `Scripts/repo-maintenance/` for `xcode-app` so native app repos keep one standard top-level `Scripts/` directory 3. Explain the architecture boundary before mutating anything: - this is a durable building-block change because it creates one repo-owned maintainer surface that bootstrap, sync, validation, CI, and release flows can all share - it removes the pain of CI-only helper scripts and scattered release glue - the simpler extension path considered first was leaving helper scripts under `.github/scripts/` and adding more workflow-specific wrappers, but that would keep local and CI behavior drifting apart 4. Run `scripts/run_workflow.py` to normalize the inputs and choose the installer path. 5. Apply the managed `maintain-project-repo` files: - - install or refresh the managed `scripts/repo-maintenance/` files - - install or refresh `scripts/repo-maintenance/config/profile.env` for the selected profile + - install or refresh the managed repo-maintenance files under the selected profile's toolkit root + - install or refresh the selected profile's `config/profile.env` - install or refresh the thin workflow wrapper at `.github/workflows/validate-repo-maintenance.yml` unless disabled + - for `xcode-app`, migrate an existing legacy `scripts/repo-maintenance/` toolkit root to `Scripts/repo-maintenance/` when the capitalized root is absent; stop if both roots exist separately so the user can preserve intentional custom files before retrying - preserve repo-specific scripts or files that are not part of the managed file set 6. Verify the installed `maintain-project-repo` files: - - `scripts/repo-maintenance/validate-all.sh` - - `scripts/repo-maintenance/sync-shared.sh` - - `scripts/repo-maintenance/release.sh` + - `scripts/repo-maintenance/validate-all.sh` for `generic` and `swift-package`, or `Scripts/repo-maintenance/validate-all.sh` for `xcode-app` + - `scripts/repo-maintenance/sync-shared.sh` for `generic` and `swift-package`, or `Scripts/repo-maintenance/sync-shared.sh` for `xcode-app` + - `scripts/repo-maintenance/release.sh` for `generic` and `swift-package`, or `Scripts/repo-maintenance/release.sh` for `xcode-app` - `.github/workflows/validate-repo-maintenance.yml` when workflow installation is enabled - branch protection, when enabled, requires the GitHub Actions check context `validate`; do not require the display-style string `Validate Repo Maintenance / validate` 7. Hand off GitHub repository settings work: @@ -64,10 +66,10 @@ Install or refresh the reusable `maintain-project-repo` toolkit inside a general sign-off policy, branch protection, and rulesets - keep settings alignment separate from release choreography 8. Hand off follow-on work cleanly: - - use `scripts/repo-maintenance/validate-all.sh` for local validation - - use `scripts/repo-maintenance/sync-shared.sh` for repo-local shared sync tasks - - use `scripts/repo-maintenance/release.sh --mode standard` from a feature branch or worktree when protected `main` owns the final release line - - use `scripts/repo-maintenance/release.sh --mode standard --remote-ci-mode defer` when full local validation has run and the repository's GitHub CI or review-bot status contexts are intentionally slow; Codex should create a same-thread heartbeat automation when available, then resume the release in the same thread instead of leaving a shell process open just to poll remote checks + - use the selected profile's `validate-all.sh` for local validation + - use the selected profile's `sync-shared.sh` for repo-local shared sync tasks + - use the selected profile's `release.sh --mode standard` from a feature branch or worktree when protected `main` owns the final release line + - use the selected profile's `release.sh --mode standard --remote-ci-mode defer` when full local validation has run and the repository's GitHub CI or review-bot status contexts are intentionally slow; Codex should create a same-thread heartbeat automation when available, then resume the release in the same thread instead of leaving a shell process open just to poll remote checks - treat pending review-bot status contexts such as CodeRabbit as a wait state, not as permission to merge; resume on a heartbeat, inspect the bot review and comments, address valid findings, and only merge after the review/comment gate is clear - use `scripts/repo-maintenance/release.sh --mode submodule` only when the repo is checked out as a submodule and the parent pointer update remains a separate follow-up - treat SemVer tags with prerelease suffixes such as `vX.Y.Z-alpha.N`, `vX.Y.Z-beta.N`, `vX.Y.Z-rc.N`, or preview-style suffixes as GitHub prereleases; the release script passes `--prerelease` for those tags and rejects existing release objects whose prerelease metadata does not match the tag @@ -116,8 +118,8 @@ Install or refresh the reusable `maintain-project-repo` toolkit inside a general ## Fallbacks and Handoffs - `report-only` is the non-mutating fallback path. -- The installer preserves repo-specific extra files under `scripts/repo-maintenance/`, `.github/workflows/`, and adjacent surfaces when they are not part of the managed file set. -- The installer keeps the selected `maintain-project-repo` profile explicit via `scripts/repo-maintenance/config/profile.env`. +- The installer preserves repo-specific extra files under the selected profile's repo-maintenance root, `.github/workflows/`, and adjacent surfaces when they are not part of the managed file set. +- The installer keeps the selected `maintain-project-repo` profile explicit via the selected profile's `config/profile.env`. - Apple profiles install checked-in `.swiftformat` and `.swiftlint.yml` samples so SwiftFormat owns formatting shape while SwiftLint stays focused on complementary safety and clarity checks. - The generated workflow's branch-protection check context is `validate`; GitHub exposes the job check run by that context, not by the workflow title plus job name. - The generated GitHub Actions wrapper uses Node 24-compatible Actions versions, with `actions/checkout@v6.0.2` as the current validated floor. Newer stable official action versions are allowed and often preferred after checking release notes and running the relevant validation. Apple profiles report the runner-selected Xcode with shell commands instead of using the Node 20-based `maxim-lobanov/setup-xcode@v1` action. diff --git a/plugins/productivity-skills/skills/maintain-project-repo/scripts/install_maintain_project_repo.py b/plugins/productivity-skills/skills/maintain-project-repo/scripts/install_maintain_project_repo.py index f682f903..326c1100 100755 --- a/plugins/productivity-skills/skills/maintain-project-repo/scripts/install_maintain_project_repo.py +++ b/plugins/productivity-skills/skills/maintain-project-repo/scripts/install_maintain_project_repo.py @@ -17,6 +17,11 @@ "swift-package": "Swift Package Manager repo-maintenance profile for library, tool, and package repos.", "xcode-app": "Xcode app repo-maintenance profile for native Apple app repositories.", } +PROFILE_TOOLKIT_ROOTS = { + "generic": Path("scripts/repo-maintenance"), + "swift-package": Path("scripts/repo-maintenance"), + "xcode-app": Path("Scripts/repo-maintenance"), +} PROFILE_OVERLAY_FILES = { "swift-package": [ ("profiles/apple/repo-maintenance/.swiftformat", ".swiftformat"), @@ -57,7 +62,7 @@ ("repo-maintenance/hooks/pre-commit.sample", "scripts/repo-maintenance/hooks/pre-commit.sample"), ] MANAGED_WORKFLOW_FILE = ".github/workflows/validate-repo-maintenance.yml" -MANAGED_PROFILE_FILE = Path("scripts/repo-maintenance/config/profile.env") +DEFAULT_TOOLKIT_ROOT = Path("scripts/repo-maintenance") EXECUTABLE_SUFFIXES = {".sh", ".py", ".sample"} @@ -75,12 +80,29 @@ def assets_root() -> Path: return Path(__file__).resolve().parents[1] / "assets" +def toolkit_root(profile: str) -> Path: + return PROFILE_TOOLKIT_ROOTS[profile] + + +def profile_file(profile: str) -> Path: + return toolkit_root(profile) / "config/profile.env" + + +def profile_target_path(profile: str, target_relative: str) -> Path: + target = Path(target_relative) + try: + suffix = target.relative_to(DEFAULT_TOOLKIT_ROOT) + except ValueError: + return target + return toolkit_root(profile) / suffix + + def target_pairs(profile: str, skip_github_workflow: bool) -> list[tuple[Path, Path]]: root = assets_root() pairs: list[tuple[Path, Path]] = [] def add_pair(source_relative: str, target_relative: str) -> None: - target = Path(target_relative) + target = profile_target_path(profile, target_relative) for index, (_, existing_target) in enumerate(pairs): if existing_target == target: pairs[index] = (root / source_relative, target) @@ -113,9 +135,65 @@ def ensure_safe_target(repo_root: Path, relative_target: Path) -> None: ) -def copy_file(source: Path, target: Path) -> None: +def legacy_xcode_toolkit_migration(repo_root: Path, profile: str) -> tuple[Path, Path] | None: + if profile != "xcode-app": + return None + + legacy_root = repo_root / DEFAULT_TOOLKIT_ROOT + desired_root = repo_root / toolkit_root(profile) + if not legacy_root.exists(): + return None + + if desired_root.exists(): + try: + if legacy_root.samefile(desired_root): + return None + except OSError: + pass + raise RuntimeError( + "The xcode-app profile expects repo-maintenance under " + f"{toolkit_root(profile).as_posix()}, but both {DEFAULT_TOOLKIT_ROOT.as_posix()} " + f"and {toolkit_root(profile).as_posix()} already exist as separate paths. " + "Choose the intentional toolkit root, preserve any repo-specific custom files, " + "and rerun maintain-project-repo." + ) + + if not legacy_root.is_dir(): + raise RuntimeError( + "The xcode-app profile expects repo-maintenance under " + f"{toolkit_root(profile).as_posix()}, but the legacy path " + f"{DEFAULT_TOOLKIT_ROOT.as_posix()} exists and is not a directory." + ) + + return legacy_root, desired_root + + +def apply_legacy_xcode_toolkit_migration(repo_root: Path, profile: str) -> str | None: + migration = legacy_xcode_toolkit_migration(repo_root, profile) + if migration is None: + return None + + legacy_root, desired_root = migration + desired_root.parent.mkdir(parents=True, exist_ok=True) + shutil.move(str(legacy_root), str(desired_root)) + try: + legacy_root.parent.rmdir() + except OSError: + pass + return ( + f"migrated legacy {DEFAULT_TOOLKIT_ROOT.as_posix()} to " + f"{toolkit_root(profile).as_posix()} for xcode-app profile" + ) + + +def copy_file(source: Path, target: Path, profile: str) -> None: target.parent.mkdir(parents=True, exist_ok=True) - shutil.copyfile(source, target) + if profile == "xcode-app": + content = source.read_text(encoding="utf-8") + content = content.replace("scripts/repo-maintenance", "Scripts/repo-maintenance") + target.write_text(content, encoding="utf-8") + else: + shutil.copyfile(source, target) if source.suffix in EXECUTABLE_SUFFIXES: target.chmod(0o755) @@ -130,7 +208,7 @@ def render_profile_env(profile: str) -> str: def write_profile_env(repo_root: Path, profile: str) -> None: - target = repo_root / MANAGED_PROFILE_FILE + target = repo_root / profile_file(profile) target.parent.mkdir(parents=True, exist_ok=True) target.write_text(render_profile_env(profile), encoding="utf-8") @@ -140,7 +218,8 @@ def main() -> int: repo_root = Path(args.repo_root).expanduser().resolve() actions: list[str] = [] managed_files = [relative.as_posix() for _, relative in target_pairs(args.profile, args.skip_github_workflow)] - managed_files.append(MANAGED_PROFILE_FILE.as_posix()) + managed_profile_file = profile_file(args.profile) + managed_files.append(managed_profile_file.as_posix()) if not repo_root.exists(): print( @@ -179,9 +258,10 @@ def main() -> int: return 1 try: + planned_migration = legacy_xcode_toolkit_migration(repo_root, args.profile) for _, relative_target in target_pairs(args.profile, args.skip_github_workflow): ensure_safe_target(repo_root, relative_target) - ensure_safe_target(repo_root, MANAGED_PROFILE_FILE) + ensure_safe_target(repo_root, managed_profile_file) except RuntimeError as exc: print( json.dumps( @@ -201,17 +281,22 @@ def main() -> int: return 1 if args.operation == "report-only" or args.dry_run: + if planned_migration is not None: + actions.append( + f"migrate legacy {DEFAULT_TOOLKIT_ROOT.as_posix()} to " + f"{toolkit_root(args.profile).as_posix()} for xcode-app profile" + ) for source, relative_target in target_pairs(args.profile, args.skip_github_workflow): target = repo_root / relative_target if target.exists(): actions.append(f"refresh {relative_target.as_posix()} from {source.relative_to(assets_root()).as_posix()}") else: actions.append(f"install {relative_target.as_posix()} from {source.relative_to(assets_root()).as_posix()}") - profile_target = repo_root / MANAGED_PROFILE_FILE + profile_target = repo_root / managed_profile_file if profile_target.exists(): - actions.append(f"refresh {MANAGED_PROFILE_FILE.as_posix()} for {args.profile} profile") + actions.append(f"refresh {managed_profile_file.as_posix()} for {args.profile} profile") else: - actions.append(f"install {MANAGED_PROFILE_FILE.as_posix()} for {args.profile} profile") + actions.append(f"install {managed_profile_file.as_posix()} for {args.profile} profile") print( json.dumps( { @@ -230,15 +315,19 @@ def main() -> int: ) return 0 + migration_action = apply_legacy_xcode_toolkit_migration(repo_root, args.profile) + if migration_action is not None: + actions.append(migration_action) + for source, relative_target in target_pairs(args.profile, args.skip_github_workflow): target = repo_root / relative_target action = "refreshed" if target.exists() else "installed" - copy_file(source, target) + copy_file(source, target, args.profile) actions.append(f"{action} {relative_target.as_posix()}") - profile_target = repo_root / MANAGED_PROFILE_FILE + profile_target = repo_root / managed_profile_file profile_action = "refreshed" if profile_target.exists() else "installed" write_profile_env(repo_root, args.profile) - actions.append(f"{profile_action} {MANAGED_PROFILE_FILE.as_posix()} for {args.profile} profile") + actions.append(f"{profile_action} {managed_profile_file.as_posix()} for {args.profile} profile") print( json.dumps( @@ -250,7 +339,7 @@ def main() -> int: "managed_files": managed_files, "actions": actions, "validation_result": "managed files synced", - "next_step": "Use scripts/repo-maintenance/validate-all.sh locally and keep CI as a thin wrapper around that command.", + "next_step": f"Use {toolkit_root(args.profile).as_posix()}/validate-all.sh locally and keep CI as a thin wrapper around that command.", }, indent=2, sort_keys=True, diff --git a/plugins/productivity-skills/skills/maintain-project-repo/tests/test_maintain_project_repo_workflow.py b/plugins/productivity-skills/skills/maintain-project-repo/tests/test_maintain_project_repo_workflow.py index 536644e7..c6ad0da6 100644 --- a/plugins/productivity-skills/skills/maintain-project-repo/tests/test_maintain_project_repo_workflow.py +++ b/plugins/productivity-skills/skills/maintain-project-repo/tests/test_maintain_project_repo_workflow.py @@ -65,6 +65,48 @@ def test_install_writes_toolkit_files(self) -> None: self.assertIn("xcrun swift --version", workflow_text) self.assertIn("brew install swiftformat swiftlint", workflow_text) + def test_xcode_profile_uses_standard_capital_scripts_directory(self) -> None: + with tempfile.TemporaryDirectory() as tmpdir: + code, payload = self.run_script("--repo-root", tmpdir, "--operation", "install", "--profile", "xcode-app") + self.assertEqual(code, 0) + self.assertEqual(payload["status"], "success") + self.assertIn("Scripts/repo-maintenance/validate-all.sh", payload["managed_files"]) + self.assertIn("Scripts/repo-maintenance/config/profile.env", payload["managed_files"]) + self.assertTrue(Path(tmpdir, "Scripts/repo-maintenance/validate-all.sh").is_file()) + self.assertTrue(Path(tmpdir, "Scripts/repo-maintenance/release.sh").is_file()) + self.assertTrue(Path(tmpdir, "Scripts/repo-maintenance/config/profile.env").is_file()) + Path(tmpdir, "case-probe").touch() + if not Path(tmpdir, "CASE-PROBE").exists(): + self.assertFalse(Path(tmpdir, "scripts/repo-maintenance/validate-all.sh").exists()) + self.assertIn( + 'REPO_MAINTENANCE_PROFILE="xcode-app"', + Path(tmpdir, "Scripts/repo-maintenance/config/profile.env").read_text(encoding="utf-8"), + ) + workflow_text = Path(tmpdir, ".github/workflows/validate-repo-maintenance.yml").read_text(encoding="utf-8") + self.assertIn("bash Scripts/repo-maintenance/validate-all.sh", workflow_text) + self.assertNotIn("scripts/repo-maintenance", workflow_text) + + def test_xcode_profile_migrates_legacy_lowercase_toolkit_root(self) -> None: + with tempfile.TemporaryDirectory() as tmpdir: + Path(tmpdir, "case-probe").touch() + if Path(tmpdir, "CASE-PROBE").exists(): + self.skipTest("legacy lowercase-to-capital migration requires a case-sensitive filesystem") + + legacy_custom = Path(tmpdir, "scripts/repo-maintenance/validations/90-custom.sh") + legacy_custom.parent.mkdir(parents=True) + legacy_custom.write_text("#!/usr/bin/env sh\nexit 0\n", encoding="utf-8") + + code, payload = self.run_script("--repo-root", tmpdir, "--operation", "refresh", "--profile", "xcode-app") + self.assertEqual(code, 0) + self.assertEqual(payload["status"], "success") + self.assertIn( + "migrated legacy scripts/repo-maintenance to Scripts/repo-maintenance for xcode-app profile", + payload["actions"], + ) + self.assertFalse(Path(tmpdir, "scripts/repo-maintenance").exists()) + self.assertTrue(Path(tmpdir, "Scripts/repo-maintenance/validations/90-custom.sh").is_file()) + self.assertTrue(Path(tmpdir, "Scripts/repo-maintenance/validate-all.sh").is_file()) + def test_generic_profile_uses_generic_macos_latest_workflow(self) -> None: with tempfile.TemporaryDirectory() as tmpdir: code, payload = self.run_script("--repo-root", tmpdir, "--operation", "install") @@ -312,6 +354,7 @@ def test_report_only_can_select_xcode_profile(self) -> None: self.assertEqual(code, 0) self.assertEqual(payload["status"], "success") self.assertEqual(payload["profile"], "xcode-app") + self.assertIn("Scripts/repo-maintenance/validate-all.sh", payload["managed_files"]) joined = "\n".join(payload["actions"]) self.assertIn("profile.env", joined) self.assertIn("xcode-app profile", joined) diff --git a/plugins/productivity-skills/uv.lock b/plugins/productivity-skills/uv.lock index fb89680e..2356ebce 100644 --- a/plugins/productivity-skills/uv.lock +++ b/plugins/productivity-skills/uv.lock @@ -228,7 +228,7 @@ wheels = [ [[package]] name = "productivity-skills-maintenance" -version = "8.5.2" +version = "8.5.3" source = { virtual = "." } [package.dev-dependencies] diff --git a/plugins/python-skills/.codex-plugin/plugin.json b/plugins/python-skills/.codex-plugin/plugin.json index 2ba409ec..8ede49b9 100644 --- a/plugins/python-skills/.codex-plugin/plugin.json +++ b/plugins/python-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "python-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Bundled Python-focused Codex skills for uv bootstrapping, project implementation, diagnostics, packaging, tooling, CI, upgrades, FastAPI, FastMCP, and pytest workflows.", "author": { "name": "Gale", diff --git a/plugins/python-skills/pyproject.toml b/plugins/python-skills/pyproject.toml index e865bd7a..7c4de517 100644 --- a/plugins/python-skills/pyproject.toml +++ b/plugins/python-skills/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "python-skills-maintainer" -version = "8.5.2" +version = "8.5.3" description = "Maintainer tooling for the python-skills repository" requires-python = ">=3.11" dependencies = [] diff --git a/plugins/python-skills/uv.lock b/plugins/python-skills/uv.lock index 98629013..6f6c318f 100644 --- a/plugins/python-skills/uv.lock +++ b/plugins/python-skills/uv.lock @@ -251,7 +251,7 @@ wheels = [ [[package]] name = "python-skills-maintainer" -version = "8.5.2" +version = "8.5.3" source = { virtual = "." } [package.dev-dependencies] diff --git a/plugins/reverse-engineering-skills/.codex-plugin/plugin.json b/plugins/reverse-engineering-skills/.codex-plugin/plugin.json index a623a806..919a3be2 100644 --- a/plugins/reverse-engineering-skills/.codex-plugin/plugin.json +++ b/plugins/reverse-engineering-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "reverse-engineering-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Workflow skills for reverse engineering, decompilation, disassembly, symbol, and artifact-analysis tasks.", "skills": "./skills/", "author": { diff --git a/plugins/rust-skills/.codex-plugin/plugin.json b/plugins/rust-skills/.codex-plugin/plugin.json index d724a346..08ab418d 100644 --- a/plugins/rust-skills/.codex-plugin/plugin.json +++ b/plugins/rust-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "rust-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Rust, Cargo, rustup, crate, workspace, CLI, library, package, CI, testing, linting, and formatting workflow skills.", "skills": "./skills/", "author": { diff --git a/plugins/server-side-jvm/.codex-plugin/plugin.json b/plugins/server-side-jvm/.codex-plugin/plugin.json index ab7cfc54..54dd049f 100644 --- a/plugins/server-side-jvm/.codex-plugin/plugin.json +++ b/plugins/server-side-jvm/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "server-side-jvm", - "version": "8.5.2", + "version": "8.5.3", "description": "Codex skills for choosing, building, testing, and maintaining server-side JVM backend projects with Java and Scala as equal first-party languages and future Clojure support planned.", "author": { "name": "Gale", diff --git a/plugins/server-side-swift/.codex-plugin/plugin.json b/plugins/server-side-swift/.codex-plugin/plugin.json index f2f55589..58d22c61 100644 --- a/plugins/server-side-swift/.codex-plugin/plugin.json +++ b/plugins/server-side-swift/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "server-side-swift", - "version": "8.5.2", + "version": "8.5.3", "description": "Codex skills for bootstrapping, syncing, building, running, containerizing, deploying, and maintaining server-side Swift services, including Vapor, Hummingbird, hb, persistence, Swift OpenAPI, RPC-fit decisions, SwiftNIO, observability, auth, app sync, Docker, Apple Containerization, Fly.io, and SwiftPM-first workflows.", "author": { "name": "Gale", diff --git a/plugins/spotify/.codex-plugin/plugin.json b/plugins/spotify/.codex-plugin/plugin.json index a6f72547..d98dd3b7 100644 --- a/plugins/spotify/.codex-plugin/plugin.json +++ b/plugins/spotify/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "spotify", - "version": "8.5.2", + "version": "8.5.3", "description": "Placeholder plugin repository for future Spotify-focused Codex workflows.", "author": { "name": "Gale", diff --git a/plugins/swift-lang/.codex-plugin/plugin.json b/plugins/swift-lang/.codex-plugin/plugin.json index 19c0175f..72fd3581 100644 --- a/plugins/swift-lang/.codex-plugin/plugin.json +++ b/plugins/swift-lang/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "swift-lang", - "version": "8.5.2", + "version": "8.5.3", "description": "Shared Swift language skills for API style, error handling, functional pipelines, formatting, source organization, and modernization cleanup.", "skills": "./skills/", "author": { diff --git a/plugins/swiftasb-skills/.codex-plugin/plugin.json b/plugins/swiftasb-skills/.codex-plugin/plugin.json index 3b979337..b7ae5c79 100644 --- a/plugins/swiftasb-skills/.codex-plugin/plugin.json +++ b/plugins/swiftasb-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "swiftasb-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Codex skills for explaining SwiftASB and building SwiftUI, AppKit, and Swift package integrations on top of it.", "author": { "name": "Gale", diff --git a/plugins/things-app/.codex-plugin/plugin.json b/plugins/things-app/.codex-plugin/plugin.json index 93289c41..a283c47a 100644 --- a/plugins/things-app/.codex-plugin/plugin.json +++ b/plugins/things-app/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "things-app", - "version": "8.5.2", + "version": "8.5.3", "description": "Things.app skills and a bundled local MCP server for reminders, planning digests, and structured task workflows.", "author": { "name": "Gale", diff --git a/plugins/things-app/mcp/pyproject.toml b/plugins/things-app/mcp/pyproject.toml index dfe3124b..22d07c01 100644 --- a/plugins/things-app/mcp/pyproject.toml +++ b/plugins/things-app/mcp/pyproject.toml @@ -7,7 +7,7 @@ packages = ["app"] [project] name = "things-mcp" -version = "8.5.2" +version = "8.5.3" requires-python = ">=3.13" dependencies = [ "fastmcp>=3.0.2", diff --git a/plugins/things-app/mcp/uv.lock b/plugins/things-app/mcp/uv.lock index 23fe3e6e..28de9083 100644 --- a/plugins/things-app/mcp/uv.lock +++ b/plugins/things-app/mcp/uv.lock @@ -1241,7 +1241,7 @@ wheels = [ [[package]] name = "things-mcp" -version = "8.5.2" +version = "8.5.3" source = { editable = "." } dependencies = [ { name = "fastmcp" }, diff --git a/plugins/things-app/pyproject.toml b/plugins/things-app/pyproject.toml index 5ad85f80..6ca72bb3 100644 --- a/plugins/things-app/pyproject.toml +++ b/plugins/things-app/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "things-app-maintenance" -version = "8.5.2" +version = "8.5.3" description = "Maintainer-only Python tooling baseline for things-app skills and plugin packaging." requires-python = ">=3.11" dependencies = [] diff --git a/plugins/things-app/uv.lock b/plugins/things-app/uv.lock index 80814bb3..7db05dac 100644 --- a/plugins/things-app/uv.lock +++ b/plugins/things-app/uv.lock @@ -120,7 +120,7 @@ wheels = [ [[package]] name = "things-app-maintenance" -version = "8.5.2" +version = "8.5.3" source = { virtual = "." } [package.dev-dependencies] diff --git a/plugins/web-dev-skills/.codex-plugin/plugin.json b/plugins/web-dev-skills/.codex-plugin/plugin.json index d50a6512..dcad8269 100644 --- a/plugins/web-dev-skills/.codex-plugin/plugin.json +++ b/plugins/web-dev-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "web-dev-skills", - "version": "8.5.2", + "version": "8.5.3", "description": "Codex skills for focused web and Expo native-boundary workflows.", "author": { "name": "Gale", diff --git a/pyproject.toml b/pyproject.toml index 4786feca..4ee00e7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket-maintenance" -version = "8.5.2" +version = "8.5.3" description = "Root uv tooling baseline for the socket superproject." requires-python = ">=3.11" dependencies = [] diff --git a/uv.lock b/uv.lock index 144925e2..1483a967 100644 --- a/uv.lock +++ b/uv.lock @@ -286,7 +286,7 @@ wheels = [ [[package]] name = "socket-maintenance" -version = "8.5.2" +version = "8.5.3" source = { virtual = "." } [package.dev-dependencies]