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
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ by `./sync-agents`.
`AGENTS.md` says what it is and how it may be used.
- 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.
- **Never double-link a package product into a test bundle that already gets it through a dynamic-framework dependency.** Xcode's default SPM integration (how `Package.local` is wired here) embeds a product's code into *every* image that links it. **WhereUI** is a dynamic framework that statically embeds its own dependencies (WhereCore, BroadwayCore/BroadwayUI, LifecycleKit, LogViewerUI, SwiftDataInspector, …), so a `*Tests` bundle that depends on **WhereUI** *and* re-lists one of those in `extraPackageProducts` ends up with a **second copy** of it. When the shared **StuffTestHost** loads several `.xctest` bundles into one process, that leaves duplicate **type metadata** for the module, and any *type-keyed runtime lookup that crosses the WhereUI boundary* — SwiftUI `EnvironmentKey`s, `UITraitBridgedEnvironmentKey` bridging, the type-keyed `BTraits`/`BThemes`/`BStylesheets` containers — silently resolves against the wrong copy and returns the default (the writer stores under one copy's key *type*, the reader looks it up under another's). It only reproduces in the **full multi-bundle scheme** (not isolated `tuist test WhereUITests` runs) and is papered over by newer Xcode linkers, so it is brutal to diagnose (it cost ~2 hours once). **Depend on such products only transitively via `WhereUI`; keep them out of `extraPackageProducts`.** `WhereStylesheetTests.resolvesTraitAwareTokensFromTheBroadwayRoot` is the regression guard — it exercises a `\.stylesheet` (→ `\.bContext`) read across the boundary and fails if a duplicate copy returns.
- **Never double-link a package product into a test bundle that already gets it through a dynamic-framework dependency.** Xcode's default SPM integration (how `Package.local` is wired here) embeds a product's code into *every* image that links it. **WhereUI** is a dynamic framework that statically embeds its own dependencies (WhereCore, BroadwayCore/BroadwayUI, LifecycleKit, PeriscopeCore/PeriscopeUI/PeriscopeTools, SwiftDataInspector, …), so a `*Tests` bundle that depends on **WhereUI** *and* re-lists one of those in `extraPackageProducts` ends up with a **second copy** of it. When the shared **StuffTestHost** loads several `.xctest` bundles into one process, that leaves duplicate **type metadata** for the module, and any *type-keyed runtime lookup that crosses the WhereUI boundary* — SwiftUI `EnvironmentKey`s, `UITraitBridgedEnvironmentKey` bridging, the type-keyed `BTraits`/`BThemes`/`BStylesheets` containers — silently resolves against the wrong copy and returns the default (the writer stores under one copy's key *type*, the reader looks it up under another's). It only reproduces in the **full multi-bundle scheme** (not isolated `tuist test WhereUITests` runs) and is papered over by newer Xcode linkers, so it is brutal to diagnose (it cost ~2 hours once). **Depend on such products only transitively via `WhereUI`; keep them out of `extraPackageProducts`.** `WhereStylesheetTests.resolvesTraitAwareTokensFromTheBroadwayRoot` is the regression guard — it exercises a `\.stylesheet` (→ `\.bContext`) read across the boundary and fails if a duplicate copy returns.

## Deployment

Expand Down Expand Up @@ -195,7 +195,8 @@ the generated (gitignored) `CLAUDE.md` is produced next to it.
(or returning a `Result`/typed error) — never absorb it into a benign-looking
default like `[]`, `nil`, or `false`. Don't discard errors with `try?` or an
empty `catch {}` that hides the failure: at minimum a `catch` must log
(`WhereLog.warning`/`error`) *and* leave observable state honest (preserve the
(a `warning`/`error` on the relevant `WhereLog` scope, ideally a typed
`LogEvent` carrying a `LogAttachment.error`) *and* leave observable state honest (preserve the
last good value or move to a `failed` state — not a default that reads as
success, e.g. an empty list rendering as "all clear"). Callers decide *how* to
react (rethrow, log + keep state, set a `failed` case), but the failure must
Expand Down
24 changes: 6 additions & 18 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ let package = Package(
.library(name: "StuffCore", targets: ["StuffCore"]),
.library(name: "LifecycleKit", targets: ["LifecycleKit"]),
.library(name: "JournalKit", targets: ["JournalKit"]),
.library(name: "LogKit", targets: ["LogKit"]),
.library(name: "LogViewerUI", targets: ["LogViewerUI"]),
.library(name: "PeriscopeCore", targets: ["PeriscopeCore"]),
.library(name: "PeriscopeUI", targets: ["PeriscopeUI"]),
.library(name: "PeriscopeTools", targets: ["PeriscopeTools"]),
Expand Down Expand Up @@ -44,17 +42,6 @@ let package = Package(
name: "JournalKit",
path: "Shared/JournalKit/Sources",
),
.target(
name: "LogKit",
path: "Shared/LogKit/Sources",
),
.target(
name: "LogViewerUI",
dependencies: [
.target(name: "LogKit"),
],
path: "Shared/LogViewerUI/Sources",
),
.target(
name: "PeriscopeCore",
dependencies: [
Expand Down Expand Up @@ -88,7 +75,7 @@ let package = Package(
.target(
name: "RegionKit",
dependencies: [
.target(name: "LogKit"),
.target(name: "PeriscopeCore"),
],
path: "Where/RegionKit/Sources",
resources: [
Expand All @@ -98,7 +85,7 @@ let package = Package(
.target(
name: "WhereCore",
dependencies: [
.target(name: "LogKit"),
.target(name: "PeriscopeCore"),
.target(name: "RegionKit"),
.product(name: "ZIPFoundation", package: "ZIPFoundation"),
],
Expand All @@ -114,8 +101,9 @@ let package = Package(
.target(name: "BroadwayCore"),
.target(name: "BroadwayUI"),
.target(name: "LifecycleKit"),
.target(name: "LogKit"),
.target(name: "LogViewerUI"),
.target(name: "PeriscopeCore"),
.target(name: "PeriscopeTools"),
.target(name: "PeriscopeUI"),
.target(name: "RegionKit"),
.target(name: "SwiftDataInspector"),
],
Expand All @@ -127,7 +115,7 @@ let package = Package(
.target(
name: "WhereIntents",
dependencies: [
.target(name: "LogKit"),
.target(name: "PeriscopeCore"),
.target(name: "RegionKit"),
.target(name: "WhereCore"),
.target(name: "WhereUI"),
Expand Down
29 changes: 5 additions & 24 deletions Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ let project = Project(
entitlements: whereAppGroupEntitlements,
dependencies: [
.package(product: "LifecycleKit"),
.package(product: "LogKit"),
.package(product: "RegionKit"),
.package(product: "WhereCore"),
.package(product: "WhereUI"),
Expand Down Expand Up @@ -129,7 +128,7 @@ let project = Project(
resources: ["Where/WhereWidgets/Resources/**"],
entitlements: whereAppGroupEntitlements,
dependencies: [
.package(product: "LogKit"),
.package(product: "PeriscopeCore"),
.package(product: "RegionKit"),
.package(product: "WhereCore"),
.package(product: "WhereUI"),
Expand Down Expand Up @@ -165,7 +164,7 @@ let project = Project(
resources: ["Where/WhereShareExtension/Resources/**"],
entitlements: whereAppGroupEntitlements,
dependencies: [
.package(product: "LogKit"),
.package(product: "PeriscopeCore"),
.package(product: "WhereCore"),
.package(product: "WhereUI"),
],
Expand All @@ -189,7 +188,6 @@ let project = Project(
// No App Group entitlement — the viewer only reads bundled GeoJSON
// (embedded via the RegionKit dependency), never the app's store.
dependencies: [
.package(product: "LogKit"),
.package(product: "RegionKit"),
.package(product: "WhereCore"),
.package(product: "WhereUI"),
Expand Down Expand Up @@ -269,18 +267,6 @@ let project = Project(
productDependency: "LifecycleKit",
sources: ["Shared/LifecycleKit/Tests/**"],
),
unitTests(
name: "LogKitTests",
bundleIdSuffix: "logkit",
productDependency: "LogKit",
sources: ["Shared/LogKit/Tests/**"],
),
unitTests(
name: "LogViewerUITests",
bundleIdSuffix: "logviewerui",
productDependency: "LogViewerUI",
sources: ["Shared/LogViewerUI/Tests/**"],
),
unitTests(
name: "JournalKitTests",
bundleIdSuffix: "journalkit",
Expand Down Expand Up @@ -340,8 +326,9 @@ let project = Project(
// BTraits/BThemes/BStylesheets containers) then silently resolves against
// the wrong copy — the writer stores under one copy's key type, the
// reader looks it up under another's. Everything the tests need
// (BroadwayCore/BroadwayUI, LifecycleKit, LogViewerUI, SwiftDataInspector,
// RegionKit + its GeoJSON bundle) is reached transitively through WhereUI.
// (BroadwayCore/BroadwayUI, LifecycleKit, PeriscopeCore/UI/Tools,
// SwiftDataInspector, RegionKit + its GeoJSON bundle) is reached
// transitively through WhereUI.
// See the root AGENTS.md "Targets" note.
unitTests(
name: "WhereUITests",
Expand Down Expand Up @@ -432,8 +419,6 @@ let project = Project(
"StuffTestHost",
"StuffCoreTests",
"LifecycleKitTests",
"LogKitTests",
"LogViewerUITests",
"JournalKitTests",
"PeriscopeCoreTests",
"PeriscopeUITests",
Expand All @@ -452,8 +437,6 @@ let project = Project(
testAction: .targets([
"StuffCoreTests",
"LifecycleKitTests",
"LogKitTests",
"LogViewerUITests",
"JournalKitTests",
"PeriscopeCoreTests",
"PeriscopeUITests",
Expand All @@ -471,8 +454,6 @@ let project = Project(
),
testScheme(name: "StuffCoreTests"),
testScheme(name: "LifecycleKitTests"),
testScheme(name: "LogKitTests"),
testScheme(name: "LogViewerUITests"),
testScheme(name: "JournalKitTests"),
testScheme(name: "PeriscopeCoreTests"),
testScheme(name: "PeriscopeUITests"),
Expand Down
38 changes: 0 additions & 38 deletions Shared/LogKit/AGENTS.md

This file was deleted.

114 changes: 0 additions & 114 deletions Shared/LogKit/README.md

This file was deleted.

61 changes: 0 additions & 61 deletions Shared/LogKit/Sources/LogChannel.swift

This file was deleted.

Loading
Loading