Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ triage). **Always-on** rules every edit must honor stay in `AGENTS.md` or
- Add SPM library targets in `Package.swift` and wire apps/tests in `Project.swift` (see existing `unitTests` helper). A new module also ships a root `README.md` and `AGENTS.md` — see [Per-module docs](#per-module-docs).
- **CI scheme**: CI runs the explicit shared **Stuff-iOS-Tests** scheme (all test bundles) rather than the autogenerated `Stuff-Workspace` scheme. New test bundles must be added to the `Stuff-iOS-Tests` scheme in `Project.swift` or CI won't run them.
- **Image snapshots are the exception: one bundle per module, one shared scheme.** Each module owning image references has its own `*SnapshotTests` target over its `SnapshotTests/` folder, all listed in the single shared **StuffSnapshotTests** scheme and its dedicated CI `snapshot` job — slow and LFS-backed, so deliberately **out of** `Stuff-iOS-Tests`. References under any `__Snapshots__/` directory are Git LFS (`.gitattributes`; the CI job checks out with `lfs: true`). Framework halves: `Shared/SnapshotKit` (shippable matrix + previews) and `Shared/SnapshotKitTesting` (test-only pipeline, whose own regression bundle **SnapshotKitTestingTests** pixel-probes without LFS and runs in `Stuff-iOS-Tests`).
- **A new image suite gets a target, not a scheme.** Add the `*SnapshotTests` target, list only `SnapshotKitTesting` in `extraPackageProducts`, and add it to the `StuffSnapshotTests` scheme's build and test lists — never a scheme or CI job of its own. An image bundle links only what its module needs (the Periscope and Inspector suites don't build against WhereUI at all); references follow the sources automatically via `#filePath`.
- **A new image suite gets a target, not a scheme.** Add the `*SnapshotTests` target, list only `SnapshotKitTesting` in `extraPackageProducts`, and add it to the `StuffSnapshotTests` scheme's build and test lists — never a scheme or CI job of its own. An image bundle links only what its module needs (the Flyover, Inspector, and Periscope suites don't build against WhereUI at all); references follow the sources automatically via `#filePath`.
- **Separate snapshot bundles are safe because each `.xctest` gets its own `StuffTestHost` process** (measured on Xcode 27 — `ProcessInfo.processIdentifier` probes; details in the snapshot-bundle comment in [`Project.swift`](Project.swift)). Each bundle statically embeds its own copy of `SnapshotKitTesting`'s capture state, and two copies in one process would corrupt each other. Tripwire: if a toolchain ever shares one host process across bundles, re-measure before adding another image bundle.

### Never double-link a product WhereUI already carries
Expand Down
257 changes: 124 additions & 133 deletions MODULE_AUDIT.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Shared/Broadway/TODOs.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ here.
# Open issues

## P1s (Should do)
- test(BroadwayCatalog) [quick-win]: Host `BroadwayCatalogTests` in `StuffTestHost` like every other hosted bundle. Today it is a hand-rolled target hosted by the BroadwayCatalog app itself (`Project.swift:545` — deps `[BroadwayCatalog, TestHostSupport]`, no `StuffTestHost`), a deviation from the convention that hosted tests run in the shared host. Rewire it through the `unitTests` helper (keeping the `BroadwayCatalog` code dependency) and confirm `tuist test BroadwayCatalogTests` stays green. (pr#149 review 2026-07-28)
- test(BroadwayCatalog) [quick-win]: Host `BroadwayCatalogTests` in `StuffTestHost` like every other hosted bundle. Today it is a hand-rolled target hosted by the BroadwayCatalog app itself (`Project.swift:575-585` — deps `[BroadwayCatalog, TestHostSupport]`, no `StuffTestHost`), a deviation from the convention that hosted tests run in the shared host. Rewire it through the `unitTests` helper (keeping the `BroadwayCatalog` code dependency) and confirm `tuist test BroadwayCatalogTests` stays green. (pr#149 review 2026-07-28)
- fix(BroadwayCatalog) [quick-win]: `BroadwayApp.swift:6` never seeds `.broadwayRoot()`, so the showcase renders with no `BContext` and every `@Environment(\.bContext)` read falls back to defaults — the one app whose job is to show Broadway is the one not using it. (audit 2026-07-26)
- test(BroadwayCatalog) [quick-win]: `Tests/BroadwayCatalogTests.swift:4` is an empty `struct BroadwayCatalogTests {}` wired into the `Stuff-iOS-Tests` scheme, so CI runs it and it asserts nothing. Replace it with a launch smoke test. (audit 2026-07-26)
- fix(BroadwayUI) [needs-design]: A nested `BRootViewController` registers duplicate trait observers (`BRootViewController.swift:92`, documented in a source `TODO`). Latent today — Where reaches Broadway only through `whereBroadwayRoot()` / `BRootView`, neither of which nests — but it fires the moment something does. (audit 2026-07-26)
Expand Down
2 changes: 1 addition & 1 deletion Shared/CreditKit/TODOs.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ here.
# Open issues

## P2s (Nice to have)
- fix [quick-win]: `github_slug` accepts anything after the host, so a malformed pin becomes a malformed API path instead of a clear error. It captures `.+?` (`Tools/generate-attribution.rb:91`) and the result is interpolated straight into `repos/#{slug}/license?ref=#{ref}` (`:82`), so a `location` of `https://github.com/foo/bar?x=y` asks for `repos/foo/bar?x=y/license?ref=…` and fails with whatever `gh` makes of that. Not a security issue: both inputs are repo-controlled (`Package.resolved`, `.agents/external-skills.json`) and `Open3.capture3` passes argv with no shell, so nothing is injectable. Constrain the capture to `[\w.-]+/[\w.-]+` so a bad pin fails as a bad pin. (pr#140 review)
- fix [quick-win]: `github_slug` accepts anything after the host, so a malformed pin becomes a malformed API path instead of a clear error. It captures `.+?` (`Tools/generate-attribution.rb:90-92`) and the result is interpolated straight into `repos/#{slug}/license?ref=#{ref}` (`:82`), so a `location` of `https://github.com/foo/bar?x=y` asks for `repos/foo/bar?x=y/license?ref=…` and fails with whatever `gh` makes of that. Not a security issue: both inputs are repo-controlled (`Package.resolved`, `.agents/external-skills.json`) and `Open3.capture3` passes argv with no shell, so nothing is injectable. Constrain the capture to `[\w.-]+/[\w.-]+` so a bad pin fails as a bad pin. (pr#140 review)

# Completed issues
20 changes: 20 additions & 0 deletions Shared/Flyover/TODOs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Flyover todos

The backlog for the Flyover module — the app-agnostic developer browser that
renders a catalog of screens as a zoomable canvas or list.

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

## P1s (Should do)
- test [needs-design]: The module shipped 50 sources against 10 namesake test files, so most of it has no 1:1 coverage. What is covered is the model layer — catalog validation (`FlyoverCatalogTests`), the six-screen live cap (`FlyoverCanvasRenderPlan.swift:5-7`), the serial load coordinator, zoom/appearance plans — and four canvas/list reference images (`SnapshotTests/FlyoverSnapshotTests.swift`). What isn't: `FlyoverCanvasView` (viewport, preview, and focus interaction), `FlyoverRootView` (including the invalid-catalog path), `FlyoverConnectorCanvas`, `FlyoverFocusedView`, the control-bar and menu views, and the `FlyoverGroup*` types. Add tests for the behavioral types first and leave rendering to the image suite; the two together are what the root convention asks for. Flyover is a DEBUG developer tool, so this is a coverage debt to pay down rather than a shipping risk — but it is the largest untested surface in the repo. (audit 2026-08-02)

## P2s (Nice to have)
- feat [quick-win]: An invalid catalog reports only how many problems it has, not what they are. `FlyoverRootView.swift:14-19` renders a `ContentUnavailableView` whose description is `"\(catalog.validationIssues.count) structural issue(s) must be fixed."`, so a developer who mis-wires a route learns that one thing is wrong and nothing about which. The issues are already modelled and populated (`FlyoverCatalogValidationIssue.swift`) — list them in the unavailable view, or put them behind a drill-in. This is the whole audience: an invalid catalog only ever reaches a developer. (audit 2026-08-02)
- docs [quick-win]: `README.md:99-100` says an invalid catalog "renders a diagnostic instead of a partial map", which reads as though the issues are shown. Once the view lists them the sentence becomes true; until then it oversells. (audit 2026-08-02)
- test [quick-win]: `FlyoverCanvas` is the only image case on a 1.5s `.settledAtLeast` floor outside Where (`SnapshotTests/FlyoverSnapshotTests.swift:20`), added by #166 to stabilize it. A deterministic completion signal on the content-load coordinator would let the floor come off; see the settle-floor item in [`Shared/SnapshotKitTesting/TODOs.md`](../SnapshotKitTesting/TODOs.md), which this is now part of the cost of. (audit 2026-08-02)

# Completed issues
20 changes: 14 additions & 6 deletions Shared/Inspector/TODOs.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,22 @@ The item format and placement rule live in the root
- fix [needs-design]: The second image capture in this bundle's process can
render a search-field placeholder at a different width. The dark
`inspectorSurfaces.SwiftData_iPhone_dark` assertion remains quarantined with
`withKnownIssue`; the likely fix is a measured capture-pipeline warm-up in
SnapshotKitTesting, not re-recording one bistable state. (agent 2026-07-28)
`withKnownIssue` (`SnapshotTests/InspectorSnapshotTests.swift:61-73`,
`isIntermittent: true`; the light variant at `:36-43` asserts strictly); the
likely fix is a measured capture-pipeline warm-up in SnapshotKitTesting, not
re-recording one bistable state. (agent 2026-07-28)
- test [quick-win]: Cover the bare-`PersistentIdentifier` relationship branch
in `SwiftDataReflection.swift`; current relationship tests materialize the
model and exercise the other branch. (audit 2026-07-26)
in `SwiftDataReflection.swift:132-137`; the relationship tests materialize
the model via key paths and so exercise the `any PersistentModel` branch at
`:125-130` instead, and `SwiftDataReflectionTests` covers metatype /
stored-values / fetch only. (audit 2026-07-26)
- test [quick-win]: Add image cases for the paged row table, filesystem root,
defaults editor, and relationship drill-in. The entity list and developer
menu are covered. (pr#101 review)
defaults editor, and relationship drill-in. Covered today: the SwiftData
entity list (light strict, dark quarantined) and the root developer menu
(light + dark) — one `@Test`, four references
(`SnapshotTests/InspectorSnapshotTests.swift:18-73`, `:88-125`). Pagination
is unit-tested but unpinned visually, and `RelationshipView` has a
`#Preview` (`:130`) with no snapshot case behind it. (pr#101 review)

## Completed issues

Expand Down
2 changes: 1 addition & 1 deletion Shared/LifecycleKit/TODOs.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ here.
# Open issues

## P2s (Nice to have)
- test [quick-win]: Add a test that duplicate node IDs trap. `LaunchPlan.append` `precondition`s on a duplicate (`LaunchPlan.swift:113`), and `LifecycleContainer` — now in LifecycleKitUI — does the same for duplicate gate-view registrations (`LifecycleKitUI/Sources/LifecycleContainer.swift:101`), but nothing exercises either. (audit 2026-07-26)
- test [quick-win]: Add a test that duplicate node IDs trap. `LaunchPlan.append` `precondition`s on a duplicate (`LaunchPlan.swift:134-140`), and `LifecycleContainer` — now in LifecycleKitUI — does the same for duplicate gate-view registrations via `assertUniqueGateTypes` (`LifecycleKitUI/Sources/LifecycleContainer.swift:98-104`), but nothing exercises either. This item covers both modules, which is why LifecycleKitUI has no file of its own. (audit 2026-07-26)

# Completed issues

Expand Down
Loading
Loading