Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# AppLogger

AppLogger is a Swift package wrapping Apple's unified logging APIs and providing reusable logging-formatting helpers.

## Shared guidelines

Read the relevant shared guides before changing the package:

- [Swift](AgentGuidelines/Guidelines/Swift/Swift.md)
- [Swift style](AgentGuidelines/Guidelines/Swift/SwiftStyle.md)
- [Unit and integration testing](AgentGuidelines/Guidelines/Testing/UnitTesting.md)
- [Documentation](AgentGuidelines/Guidelines/Documentation.md)
- [Packages](AgentGuidelines/Guidelines/Packages.md)
- [CI/CD](AgentGuidelines/Guidelines/CICD.md)

## Package layout

- Production sources live under `Sources/AppLogger/`.
- Shared extensions live under `Sources/Extensions/`.
- Tests live under `Tests/AppLoggerTests/`.

Keep the package UI-agnostic and preserve its public API's minimal scope.
3 changes: 3 additions & 0 deletions AgentGuidelines/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.DS_Store
__pycache__/
*.py[cod]
39 changes: 39 additions & 0 deletions AgentGuidelines/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Agent Guidelines

## Purpose

This public repository is the versioned source of truth for reusable ThatFactory agent guidance. Keep it generic enough to apply to multiple applications and Swift packages. Product decisions, concrete project paths, and exceptions belong in each consumer repository.

## Sources of truth

- Use official Apple documentation for Apple APIs and Xcode behavior.
- Distill durable policy from Xcode-provided skills; do not copy exported Apple skills into this repository.
- Do not include private company information, credentials, personal absolute paths, or consumer-specific implementation details.
- When shared and consumer guidance differ, the consumer's nearest applicable `AGENTS.md` is the explicit specialization.
- Before changing this repository, verify that the consumer's checked-in guidelines version is current where applicable.

## Documentation changes

- Keep each rule in the narrowest relevant guide and link to it rather than duplicating it.
- Use physical folder terminology for Xcode projects. Do not call filesystem folders Xcode groups.
- Keep examples generic and concise.
- Use relative Markdown links inside this repository.
- Update `README.md` when adding, moving, or removing a guide.
- Update `CHANGELOG.md` and `VERSION` for a release.

## Validation

Run:

```sh
python3 Scripts/validate_guidelines.py
```

Fix every validation failure before releasing a version.

## Releases

- Use semantic versioning.
- Create a Git tag and GitHub release matching `VERSION`.
- Consumer repositories adopt releases deliberately through Git subtree updates.
- Follow [the pull-request review workflow](Guidelines/GitHub/PullRequests.md) before merging any release change.
44 changes: 44 additions & 0 deletions AgentGuidelines/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Changelog

All notable changes to this project are documented in this file.

## [0.0.4] - 2026-07-21

### Added

- Development guidance for reusability-first design and checking the latest shared-guidelines version before project work.

### Changed

- Require an approved pull request before releasing `agent-guidelines` or any consumer package.

## [0.0.3] - 2026-07-21

### Added

- A Codex review-monitoring workflow covering paginated processing reactions and review threads, clean reviews, inline feedback, replies, thread resolution, and CI checks.

## [0.0.2] - 2026-07-21

### Added

- Standard README badge conventions for ThatFactory projects and packages.
- Git repository guidance that defaults push-capable clones to SSH remotes.
- GitHub pull-request review and merge-gate guidance.
- Updated and Revision badges to the repository README.

### Changed

- Updated GitHub workflows to `actions/checkout@v7` and documented using current stable action versions in new workflows.
- Clarified the Redux side-effect loop and the canonical view-projection test path.
- Expanded and tested semantic-version validation to support prerelease plus build metadata and reject invalid numeric identifiers.
- Removed the redundant README license section while retaining the MIT license badge and root license file.

## [0.0.1] - 2026-07-21

### Added

- Initial shared guidelines for Redux, Swift, SwiftUI, SwiftLint, localization, testing, documentation, package maintenance, CI/CD, Xcode MCP, and Xcode security audits.
- A consumer `AGENTS.md` template and Git subtree installation workflow.
- Structural validation for links, the documentation catalog, version metadata, subtree instructions, and public-repository safety.
- A tag-driven GitHub release workflow that validates the tag against `VERSION` and publishes changelog notes.
230 changes: 230 additions & 0 deletions AgentGuidelines/Guidelines/Architecture/Redux.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
# Redux Architecture

Use this guide for applications that explicitly adopt the ThatFactory Redux architecture. Do not apply it to reusable packages or repositories whose local instructions choose another architecture.

## Principles

- Keep one application store as the source of truth for durable application state.
- Views read state and dispatch actions; they do not mutate application state directly.
- Actions describe events or intent, not implementation steps.
- Reducers are pure and synchronous.
- Middleware performs asynchronous work and other side effects.
- Services wrap external frameworks, packages, persistence, clocks, APIs, and system capabilities.
- Selectors derive shared domain information from state.
- Render-ready view state and view-only projections live beside their consuming views.
- Every side-effect result returns to the store as an action before it changes state.

## Data flow

```text
await dispatch(Action)
+--------------+ --------------------------> +-----------+
| SwiftUI view | | Store |
| | <-------------------------- | |
+--------------+ observable state | 1. Reducer|
| 2. Middle-|
| ware |
+-----+-----+ <---------------+
| |
| side effect |
v |
+--------------+ |
| Service | |
| package/API | |
+------+-------+ |
| |
| Action? |
+-----------------------+
```

The store reduces the original action first, then awaits middleware and sequentially dispatches returned follow-up actions. Keep ordering observable and deterministic. Do not start unstructured work inside reducers or hide state changes inside services.

## Canonical physical folders

These are filesystem folders, not Xcode groups. New single-application repositories use this structure by default:

```text
<AppName>/
|-- App/
|-- Model/
|-- Redux/
| |-- Action/
| |-- Middleware/
| |-- Reducer/
| |-- Selector/
| |-- State/
| `-- Store.swift
|-- Services/
|-- Tools/
|-- View/
| `-- <Feature>/
`-- Resources/

<AppName>Tests/
|-- Mocks/
|-- Model/
|-- Redux/
| |-- Action/
| |-- Middleware/
| |-- Reducer/
| |-- Selector/
| `-- State/
|-- Services/
|-- Tools/
`-- View/
`-- <Feature>/
```

A multi-target application may use a shared source root such as `Shared/Redux/` and target-specific roots such as `<AppName>/View/`. Its root `AGENTS.md` must provide a concrete path map:

```markdown
| Role | Physical folder |
|---|---|
| Redux | `Shared/Redux/` |
| Models | `Shared/Model/` |
| Services | `Shared/Services/` |
| Views | `<AppName>/View/` |
| Unit tests | `<AppName>Tests/` |
```

Once mapped, use the same component layout beneath those roots. Never guess a destination or create a parallel folder spelling such as `Views/` when the project declares `View/`.

## Placement rules

### App

Put application bootstrap, app delegates, scene definitions, store construction, environment wiring, and root configuration in `App/`. Do not place feature logic there.

### Model

Put reusable domain values in `Model/`. Keep each important type in a focused file. Do not hide response models, payloads, or domain values inside action or service files merely because only one caller currently uses them.

### Action

Put domain action enums in `Redux/Action/`. Use a root routing action that wraps focused feature actions:

```swift
enum AppAction: Equatable {
case account(AccountAction)
case navigation(NavigationAction)
}
```

Name actions after what happened or what the user requested. Keep cases in the order required by the project's Swift style guide.

### State

Put the root state and domain sub-states in `Redux/State/`. Prefer focused value types with compiler-synthesized conformances. Add a new sub-state for a durable domain instead of folding unrelated values into an existing feature.

State stores durable facts. Avoid storing values that are cheap, deterministic derivations unless caching is an explicit measured requirement.

### Reducer

Put reducer functions in `Redux/Reducer/`. A reducer receives state and an action and returns new state. It must not:

- perform asynchronous work;
- call services or packages;
- read the clock or generate random values;
- access files, databases, network clients, or system APIs;
- dispatch actions;
- trigger UI behavior directly.

Use the smallest state and action inputs that correctly express the transition. Root reducers compose domain reducers.

### Middleware

Put middleware in `Redux/Middleware/`. Middleware may call injected services and return a follow-up action. It must not mutate store state directly.

Inject services, clocks, identifier generators, and providers through parameters so middleware tests remain deterministic. Register middleware in one root composition file such as `AppMiddlewares.swift`.

Create a feature subfolder when a domain has multiple middleware files:

```text
Redux/Middleware/Account/
|-- AccountMiddleware.swift
|-- LoadAccountMiddleware.swift
`-- UpdateAccountMiddleware.swift
```

### Selector

Put pure, reusable domain extraction in `Redux/Selector/`. A selector may answer questions such as the current signed-in account, whether a capability is enabled, or which domain items are visible.

Do not put SwiftUI types, colors, images, localized display strings, or render-ready screen state in selectors.

### Services

Put focused external-boundary abstractions in `Services/<Capability>/`. Services wrap APIs, persistence, packages, frameworks, sensors, system features, and other impure operations. Middleware calls services; views and reducers do not.

Prefer a protocol or otherwise injectable contract when a service must be replaced in tests. Keep transport-specific details behind the service boundary.

### Tools

Put genuinely cross-cutting implementation utilities in `Tools/`. This is not a miscellaneous folder. Feature-only formatters, helpers, constants, or factories stay beside that feature. Promote them to `Tools/` only after they have a clear cross-feature role.

### View

Put SwiftUI screens and components in `View/<Feature>/`. A new view belongs to the feature it renders, not in Redux. Reusable visual components may use `View/Generic/` or another explicitly declared shared-view folder.

Render-facing view-state types and projections live beside the consuming view:

```text
View/Account/
|-- AccountView.swift
|-- AccountViewState.swift
`-- AccountViewStateProjection.swift
```

If a projection exists only to render one screen, it is view-layer code even when its input is `AppState`.

### Resources

Put catalogs, assets, preview assets, configuration resources, and test plans in `Resources/` or the concrete resource folders declared locally. Production targets must not depend on test fixtures.

## File organization

- Prefer one primary concern per file.
- When a feature has several files of one Redux component, introduce a feature subfolder under that component.
- Keep root routing and composition at the component root; keep feature implementations below it.
- File names match their primary type or clearly describe their primary pure function.
- Do not introduce artificial enum namespaces solely to satisfy filename lint rules.
- Mirror production organization in tests so components are easy to locate.

## SwiftUI connection

Create and inject the store at the application root. Views observe only the state they need and dispatch actions for application events.

Keep view-local interaction state in private `@State` when it is not durable application state. Do not create an `@Observable` view model as a second source of truth for Redux-owned state.

Prefer narrow view inputs or a focused view-state projection. This aligns SwiftUI invalidation with the smallest useful surface while Redux remains the durable source of truth.

## Adding a feature

| Step | Change | Default destination |
|---|---|---|
| 1 | Define domain models | `Model/<Feature>/` |
| 2 | Define feature state | `Redux/State/<Feature>State.swift` |
| 3 | Add it to root state | `Redux/State/AppState.swift` |
| 4 | Define feature actions | `Redux/Action/<Feature>Action.swift` |
| 5 | Route them through the root action | `Redux/Action/AppAction.swift` |
| 6 | Implement the reducer | `Redux/Reducer/<Feature>Reducer.swift` |
| 7 | Compose the reducer | `Redux/Reducer/AppReducer.swift` |
| 8 | Add side effects if needed | `Redux/Middleware/<Feature>/` |
| 9 | Register middleware | `Redux/Middleware/AppMiddlewares.swift` |
| 10 | Add external boundaries if needed | `Services/<Capability>/` |
| 11 | Add shared domain selectors if needed | `Redux/Selector/<Feature>/` |
| 12 | Build the feature UI | `View/<Feature>/` |
| 13 | Mirror tests | `<AppName>Tests/` |

Skip components that provide no value. A state-only transition needs no middleware; a screen-only projection does not need a Redux selector.

## Testing responsibilities

- Reducer tests provide state plus an action and assert the returned state.
- Selector tests provide state and assert the derived domain result.
- Middleware tests inject mocks, execute an action, and assert the returned follow-up action.
- Service tests exercise the external boundary without involving views.
- View-state projection tests live under the matching `<AppName>Tests/View/<Feature>/` folder, or the consumer-mapped test root.
- Test mocks and fixture data live under the test target's `Mocks/` folder.

Follow [Unit testing](../Testing/UnitTesting.md) for framework and concurrency conventions.
42 changes: 42 additions & 0 deletions AgentGuidelines/Guidelines/CICD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# CI/CD

## Workflow principles

- Keep CI deterministic, reproducible, and aligned with the repository's supported Xcode, Swift, and platform versions.
- Treat warnings introduced by a change as failures even when the compiler does not.
- Prefer the smallest permissions required by each workflow and job.
- For a new workflow, use the latest stable major version of every GitHub Action available at the time of creation.
- Do not copy an older major version into a fresh workflow unless a documented compatibility constraint requires it.
- For existing workflows, review action release notes and update deliberately rather than allowing runtime deprecation warnings to accumulate.
- Pin third-party actions to an intentional version and review updates.
- Do not place secrets in workflow files, logs, fixtures, or command arguments that may be echoed.
- Keep release workflows separate from pull-request validation when their permissions differ.

## Pull-request CI

A typical Swift package validates:

- package resolution;
- build;
- Swift Testing tests;
- DocC generation when the package publishes documentation;
- repository-specific lint or validation scripts.

An Xcode application validates its declared scheme and test plan. Use the same project/workspace, configuration, and platform assumptions documented for local development.

## Investigation

1. Identify the first meaningful failing step rather than treating later cancellations as independent failures.
2. Reproduce locally with the closest supported toolchain when practical.
3. Separate infrastructure or dependency-resolution failures from code failures.
4. Fix the root cause in the narrowest appropriate layer.
5. Re-run the affected local validation before relying on remote CI.
6. Update durable CI documentation when the workflow or investigation process changes.

## Releases

- A release tag and GitHub release must match the intended semantic version.
- Release notes summarize user- or integrator-relevant changes since the previous release.
- Use a notes file for multiline CLI release descriptions.
- Do not publish a release from an unverified or dirty worktree.
- Follow the consumer's local instructions for deployment, signing, notarization, App Store, or documentation publishing steps.
9 changes: 9 additions & 0 deletions AgentGuidelines/Guidelines/Development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Development

## Reusability first

When developing a new feature or responding to a feature request, consider shared code first. If the code fits an existing package, suggest extending that package instead of adding the implementation directly to an application. Also consider whether the change belongs in a new Swift package, even when that package does not exist yet. Prefer reusable, focused package APIs when they can serve more than one consumer.

## Guidelines version

Before changing a project, verify that it uses the latest released version of `agent-guidelines`. Check the project's `AgentGuidelines/VERSION` against the latest release, update the subtree or equivalent when it is behind, and read the updated applicable guides before starting implementation. This check is manual and must be performed at the beginning of each project task.
Loading