Imported from gaelic-ghost/NyextStepOfficeTower (
Apps/NSOfficeTower/AGENTS.md). Install upstream withnpx skills add gaelic-ghost/NyextStepOfficeTower --skill NSOfficeTower. Copyright stays with the author.
AGENTS.md
- Use
xcode-build-run-workflowfor normal Xcode build, run, diagnostics, preview, file-membership, and guarded mutation work inside this existing project. - Use
xcode-testing-workflowwhen the task is primarily about Swift Testing, XCTest, XCUITest,.xctestplan, flaky tests, retries, or test diagnosis. - Use
apple-ui-accessibility-workflowwhen 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-guidancewhen this repo's local workflow guidance drifts and should be refreshed or merged forward. - Re-run
sync-xcode-project-guidanceafter substantial Xcode-workflow or plugin updates so local guidance stays aligned. - Use
Scripts/repo-maintenance/validate-all.shfor local maintainer validation andScripts/repo-maintenance/sync-shared.shfor repo-local sync steps. - Use
Scripts/repo-maintenance/release.sh --mode standard --version vX.Y.Zfrom 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, prepare the release PR, then inspect and advance it through bounded snapshots. For remote CI, GitHub Actions, review bots, release indexing, or deployment, reuse a live matching host-native continuation while the gate is pending and healthy; do not delete/recreate it after an unchanged snapshot. Create/update only after it fires or becomes stale, no sooner than five minutes later, and pause/delete it when resolved, failed, cancelled, or identity-drifted. Codex uses heartbeat; Hermes uses a continuablecronjobwithdeliver="origin"andattach_to_session=true. On wakeup inspect first, then advance only when the recorded branch, commit, PR, and tag identities still match. - Treat
Scripts/repo-maintenance/config/profile.envas the installedmaintain-project-repoprofile marker, and keep it on thexcode-appprofile for native Apple app repos. - Read relevant Apple documentation before proposing or making Xcode, SwiftUI, lifecycle, or architecture changes.
- For Apple, Swift, and Xcode documentation, use Xcode MCP DocumentationSearch first, then the Dash.app MCP when its installed docsets cover the question. Use Dash HTTP only when the Dash.app MCP is unavailable or incomplete; consult GitHub/source repositories and readable online docs only after those local MCP paths.
- Prefer the simplest correct Swift that is easiest to read and reason about.
- Prefer synthesized and framework-provided behavior over extra wrappers and boilerplate.
- For public Swift APIs, treat streamlined, compact, ergonomic call sites as the only acceptable default; prefer optional parameters with explicit default values over additional methods or overloads when the difference is optional behavior on the same operation.
- When a public function, initializer, or method reaches four or more arguments or parameters, strongly prefer a named typed
structrequest, options, or configuration value so call sites stay readable and future additions do not multiply overloads. - Prefer enums, enum cases with associated values, and narrow typed values over strings, booleans, sentinel values, or parallel parameters whenever the domain has a closed or meaningful set of choices.
- Keep data flow straight and dependency direction unidirectional.
- Treat the
.xcworkspaceor.xcodeprojas the source of truth for app integration, schemes, and build settings. - Prefer Xcode-aware tooling or
xcodebuildover ad hoc filesystem assumptions when project structure or target membership is involved. - Choose and record one explicit three-letter uppercase prefix for project-owned Swift files and declarations. Exempt only
Package.swift, externally generated Swift, and vendored third-party Swift. - Never use
+filenames. Name viewsGEAWhateverView.swiftand extracted modifiersGEAWhateverViewModifier.swift; do not use external ViewModels as a SwiftUI shape. - Give independently editable or previewable components their own files; small private helpers may remain while they do not clutter focused editing.
- Prefix child components with their complete composition owner, such as
GEASettingsSheetToggleCard.swift. - Use
GEAApp.swiftfor the lifecycle entry andGEA.swiftfor the runtime/domain value. Do not create an umbrellaGEAAppService.swift; add a direct concrete service only when a feature has a real capability to own. - Use the standard top-level Xcode app repository layout:
Sources/,Tests/,Shared/,Extensions/,Configurations/,Scripts/, andPackages/. 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.xcconfiglayers.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, orLocalPackagesfor ordinary Xcode app repos. - Inside
Sources/, use strict app structure by default:Views/,Models/, andServices/. Sources/Views/owns SwiftUI views and UIKit/AppKit view surfaces. UseSources/Views/Shared,Sources/Views/macOS, andSources/Views/iOSfor shared, macOS-specific, and iOS/iPadOS-specific UI.Sources/Models/owns Core Data persistence models, SwiftData@Modeltypes, app datamodels, DTOs, and shared transfer or persistence shapes.Sources/Services/owns direct concrete feature and boundary services by direction:Consumed/for external capabilities the app calls,Internal/for app-owned feature services, andProvided/for services the app exposes to extensions, helpers, plugins, integrations, or other clients. These folders do not justify wrapper layers or an app-wide service container.- Name a service after the capability it directly provides, such as
GEAImportService.swift. Put it in environment only when independent descendants need direct access or observable state; reusable leaf views still take values, bindings, and action closures. - For new Xcode app, framework, and workspace repositories, prefer XcodeGen plus synced source folders, checked-in
.xcconfigfiles, 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 generateinstead of hand-editing generated.pbxprojfiles. - Before running
xcodegen generate, inspect the current git diff for generated.xcodeprojor.pbxprojchanges. 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,.xcconfigfiles for build settings,.entitlementsfiles for entitlement keys,Info.plistfor plist keys, scheme specs or.xcschemefiles for scheme behavior, and.xctestplanfiles for test-plan content. - For Xcode 16 or newer project formats, prefer
syncedFolderroots 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
Sourcessource entry that includes all app source, resource, support, generated plist, entitlement, and nested feature folders, plus oneSharedsource entry when shared app/extension code exists. A standard test target gets oneTestssource entry that includes all test subdirectories. Extension targets use oneExtensions/<ExtensionName>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, orTests/<TargetName>Testsinto 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. - Every app target keeps
Sources/Resources/Localizable.xcstringsas its default String Catalog. Keep it in the broadSourcestarget root, build after changing localizable source text so Xcode extracts entries, and usexcode-localization-workflowfor catalog organization, translation, and locale validation. - If
syncedFolderdoes not fit a repo, use the same broad top-level recursive paths such asSources,Tests, orResourceswith explicitincludesandexcludesas 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
@mainapp type, onemain.swift, or the platform-equivalent single launch entry. Do not add alternate app entry points, second@maintypes, duplicatemain.swiftfiles, 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. - Keep XcodeGen specs readable as project structure: use explicit
configs,configFiles,targets,schemes,packages,projectReferences, and templates when they make ownership clearer. - Prefer external
.xcconfigfiles for nontrivial build settings, wire them from the XcodeGen spec, keep secrets, personal team IDs, local paths, provisioning profiles, and API tokens out of committed configs, and review config diffs with the spec and generated project diff. - Keep
.xcconfiglayering explicit: a small shared base, target-level configs for app/test/extension identity, then per-configuration configs for Debug, Release, CI, or deployment variants. - Prefer external
.entitlementsfiles for app, extension, and capability-bearing targets. DeclareCODE_SIGN_ENTITLEMENTSin the owning target.xcconfig, let Xcode capabilities update the entitlement plist when possible, and commit that plist diff with the project/spec/config changes. - Do not assume Xcode's Build Settings UI writes edited values back into
.xcconfigfiles. If a GUI edit creates a generated project override, move intentional tracked settings into the owning.xcconfigbefore regenerating. - 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
.xctestplanfiles versioned when the project depends on repeatable test-plan configurations, and inspect or run them explicitly withxcodebuild -showTestPlansandxcodebuild -testPlan .... - For macOS prompt-heavy UI tests, record the launcher, responsible executable, target app or helper, protected operation, and test-plan configuration before changing permissions. Keep ordinary tests on a test-owned Debug product and test-specific storage; do not use
open,NSWorkspace, or a wrapper script to restore an installed app as routine test cleanup. Put a real installed-app or protected-operation scenario behind an opt-in.xctestplanconfiguration. - Prefer a checked-in repo-root
.swiftformatfile as the Swift formatting source of truth. - Prefer a pre-commit hook such as
Scripts/repo-maintenance/hooks/pre-commit.samplethat formats staged Swift sources and then verifies them withswiftformat --lintbefore 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-workflowfor the semantic side andxcode-testing-workflowfor 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.
- Validate both Debug and Release paths when behavior can diverge, and treat tagged releases as a cue to build and verify Release artifacts in addition to the everyday Debug flow.
- Never edit
.pbxprojfiles directly. If a project-file change is needed and no safe project-aware tool is available, stop and make that change through Xcode instead. When.pbxprojis tracked and Xcode, XcodeGen, or another project-aware workflow legitimately changes it, treat that diff as critical project state: review it, stage it, and commit it with the branch before any push, merge, release, or cleanup. - Validate Xcode-project changes with explicit
xcodebuildcommands when build or test integrity matters.