Skip to content
Merged
16 changes: 12 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ generating; plain `./ide` fails fast pointing at it.

The executables in the repo root are the dev scripts — `ide`, `test`,
`swiftformat`, `sync-agents`, `profile`, `icons`, `flaky`, `simulator`,
`worktree`, `xcstrings`, `attribution`, `codex-watchdog` — and each takes
`--help`. Reach for one rather than
`worktree`, `xcstrings`, `attribution`, `codex-watchdog`, `tla-check` — and each
takes `--help`. Reach for one rather than
hand-rolling its job: `test` is the only way tests should be run (see [Running
tests](#running-tests)), and `icons`, `attribution`, and `simulator` in particular own state that is
easy to corrupt by hand — `./simulator` owns a per-checkout device (see the
Expand Down Expand Up @@ -507,8 +507,11 @@ flag is needed there.

## Running tests

**Use [`./test`](test)** — the only way to run tests. Never hand-roll `tuist
test` or `xcodebuild`. It runs the host-side backup-upgrader regression before
**Use [`./test`](test)** — the only way to run the iOS bundles. Never hand-roll
`tuist test` or `xcodebuild` for them. The one exception is the native-macOS
**Ledger-macOS-Tests** scheme, which `./test` does not know how to run at all;
the [`running-tests`](.agents/skills/running-tests/SKILL.md) skill carries its
invocation. Closing that gap is filed in [`TODOs.md`](TODOs.md). It runs the host-side backup-upgrader regression before
selecting an iOS bundle, so tool-only changes remain covered by the same entry
point. **Validate in proportion to risk:** run
`./swiftformat --lint` when the changed files are in its scope, and run the
Expand Down Expand Up @@ -612,6 +615,11 @@ external agent skills, which are gitignored and so absent from a bare checkout.
- **Tuist** — `tuist test`, `tuist build`, and `./ide` (which generates the
Xcode project)
- iOS Simulator, and running the **Where** app
- **Anything needing a Swift toolchain** — the VM ships none, so `swift run
bumper` (the architecture lint) and `./xcstrings` (a `#!/usr/bin/swift`
script) both fail here even though neither needs Xcode. Diagnostic signature
for the latter: ``mise ERROR "./xcstrings" couldn't exec process: No such file
or directory``.
- Anything else needing Xcode

These are limits of the **VM**, not of cloud agents generally: a remote-control
Expand Down
8 changes: 6 additions & 2 deletions Ledger/LedgerCore/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,12 @@ build system, formatting, and global conventions. Read that first.

## Testing

Swift Testing in [`Tests/`](Tests), hostless on macOS (`tuist test
LedgerCoreTests -- -destination 'platform=macOS'`). Shared fixtures live in
Swift Testing in [`Tests/`](Tests), hostless on macOS. Run it through the
scheme, not the bundle — `tuist test Ledger-macOS-Tests --no-selective-testing
-- -destination 'platform=macOS'`, as the
[`running-tests`](../../.agents/skills/running-tests/SKILL.md) skill spells out.
This is the repo's one sanctioned `tuist test`: `./test` covers only the iOS
bundles and cannot run this one. Shared fixtures live in
[`LedgerCoreTestSupport.swift`](Tests/LedgerCoreTestSupport.swift). The network,
token-source, and Keychain seams use the module's `@_spi(Testing)` DEBUG doubles
(`ScriptedDashboardProvider`, `StubTokenSource`, `InMemoryKeychainStore`); the
Expand Down
18 changes: 18 additions & 0 deletions Ledger/TODOs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Ledger todos

The backlog for the Ledger menu bar app and `LedgerCore`. Ledger is native
macOS and sits outside the Where module graph, so the Bumper Bowling
architecture lint does not cover it (`BumperBowling.swift` includes only Where
paths) — the conventions below are enforced by review rather than by lint.

The item format and the placement rule live in the root
[`TODOs.md`](../TODOs.md); raw notes go in [`INBOX.md`](../INBOX.md), not here.

# Open issues

## P2s (Nice to have)
- fix(LedgerCore) [quick-win]: `LedgerServices` resolves its calendar from the device (`LedgerServices.swift:157`, `calendar: Calendar = .current` on the `@_spi(Testing)` init) and uses it for the today/this-week spend deltas (`:303-307`), so on a non-Gregorian system calendar the window boundaries `SpendHistory` differences against move — the same defect class Where forbids outright, and the parameter default also violates the repo's "avoid parameter defaults on Core APIs" rule, since the composition root already knows the value. Inject an explicit Gregorian calendar with the current time zone from the app, and pass it in tests rather than relying on the default. Lower severity than Where's equivalent: this shifts a spend window rather than corrupting stored day identity, and no value is persisted against it. (audit 2026-08-09)
- test(LedgerCore) [quick-win]: Three implementation files have no namesake test — `LedgerLog.swift`, `LedgerSettings.swift`, and `SpendSnapshot.swift`. Each is exercised indirectly through `LedgerServicesTests`, so this is 1:1-convention debt rather than untested behavior; close it as those files change rather than in one pass. The rest of the module is genuinely well covered (13 test files over 16 sources, including the API, Keychain, token-source, and history seams). (audit 2026-08-09)
- test(Ledger) [needs-design]: The `Ledger` app target ships no test bundle, so the eight sources in the SwiftUI/AppKit shell — `MenuBarLabel`, `SpendView`, `SettingsView`, `LedgerSession`, `CurrencyFormat`, `WindowVisibilityReader` — are compile-only in CI (`Ledger-macOS-Tests` builds the app but runs only `LedgerCoreTests`, `Project.swift:703-707`). This matches how the Where extension targets are treated and is documented in [`Ledger/AGENTS.md`](Ledger/AGENTS.md), so it is a deliberate gap rather than an oversight; the decision worth making is whether `CurrencyFormat` and the menu-bar label's formatting deserve a hostless bundle of their own, since they are pure value transforms that a test could pin cheaply. (audit 2026-08-09)

# Completed issues
Loading
Loading