From 5046664482aa21559b0f024ea3f2899cf70e5dca Mon Sep 17 00:00:00 2001 From: Claw Date: Mon, 20 Jul 2026 14:29:03 -0700 Subject: [PATCH] F-083: projectDependencies as external-deps house style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make settings projectDependencies → libs.* the single happy path; reposition typed build-dependencies catalogs as advanced/sample-scale only. Update DEPS-CATALOG, tutorials, agent skill, example 08, and KDoc. --- README.md | 8 +- TICKETS.md | 6 +- application/settings.gradle.kts | 3 +- docs/ARCHITECTURE.md | 7 +- docs/CALL-SITE-SURFACE.md | 2 +- docs/DEPS-CATALOG.md | 88 +++++++++++++++---- docs/GETTING-STARTED.md | 27 +++--- docs/JVM-GETTING-STARTED.md | 4 +- docs/PROGRESS.md | 22 +++++ docs/PROGRESSIVE-EXAMPLES.md | 2 +- examples/agent-skills/forma-deps-catalog.md | 20 ++++- examples/android/08-deps-catalog/README.md | 8 +- .../deps/catalog/VersionCatalogBuilder.kt | 5 ++ 13 files changed, 153 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 017330b8..288a32f9 100644 --- a/README.md +++ b/README.md @@ -129,9 +129,11 @@ Worker / contributor host setup (JDK **21** build JVM, Android SDK platform **34 ## External dependency catalogs -Declare third-party libraries and plugins once in `settings.gradle.kts` with -`projectDependencies` (version catalog), or use typed Kotlin catalogs -(`build-dependencies/` pattern). Full guide: [`docs/DEPS-CATALOG.md`](docs/DEPS-CATALOG.md). +**House style:** declare third-party libraries and plugins once in +`settings.gradle.kts` with `projectDependencies` (version catalog) and consume +`libs.*` via `deps(...)`. Typed Kotlin catalogs (`build-dependencies/` pattern) +are an **advanced** sample-scale option, not a second default. Full guide: +[`docs/DEPS-CATALOG.md`](docs/DEPS-CATALOG.md). ```gradle // settings.gradle.kts diff --git a/TICKETS.md b/TICKETS.md index 02308be3..f32ba203 100644 --- a/TICKETS.md +++ b/TICKETS.md @@ -100,15 +100,15 @@ Close the biggest call-site / multi-way gap: chain `withPlugin`. Design: ## P8 — Principle alignment (implementation matches goals) Close remaining gaps where code/docs still allow **multiple ways**, **fat call -sites**, or **missing fleet tooling**. P7 (F-070–F-073) and F-081–F-082 are **done**; **F-019 Phase 1 done**. -**Next coding:** **F-083** +sites**, or **missing fleet tooling**. P7 (F-070–F-073) and F-081–F-083 are **done**; **F-019 Phase 1 done**. +**Next coding:** **F-084** | ID | Status | Title | Notes | |----|--------|-------|-------| | F-080 | done | Codify root principles in product docs | `VISION.md` § Root principles + README + `AGENTS.md` + GETTING-STARTED; board P8 added | | F-081 | done | Call-site surface audit: `Unit` returns, no builder chains, minimal attrs | Hard-removed `TargetBuilder` / `PluginWrapper` / sample `Plugins` + chain-only `PluginConfiguration`; all Android/JVM DSLs already `Unit`; `docs/CALL-SITE-SURFACE.md` flag inventory (`compose` → project-global default, `viewBinding` on impl + dedicated type) | | F-082 | done | One global configuration path | Hard-removed `Project.androidProjectConfiguration`; `ScriptHandlerScope` form is the single API; `extraPlugins` documented classpath-only; new `PROJECT-CONFIGURATION.md` + cross-links; builds green | -| F-083 | todo | One project-global external-deps convention | House style: version catalog **or** typed catalogs as the sample+docs standard; other path = advanced/legacy note, not dual happy path (`DEPS-CATALOG.md`) | +| F-083 | done | One project-global external-deps convention | **House style = `projectDependencies` → `libs.*`**. Typed `build-dependencies/` catalogs = advanced/sample-scale only (not dual happy path). `DEPS-CATALOG.md` + README/GETTING-STARTED/agent skill/08 README | | F-084 | todo | Fleet tooling for explicit graphs (check / generate / migrate) | Principle 3 at scale: tighten includer/depgen/bazel-check; design+spike migrate helpers for renames/type changes; related GH **#54**. Reliable large refactors without hand-editing thousands of modules | | F-085 | todo | Full-tree principle audit: sample + examples + agent skills | After F-072/F-081: no chain APIs, no dual styles taught, call sites minimal; fix stragglers | diff --git a/application/settings.gradle.kts b/application/settings.gradle.kts index fe25cb3a..ec185582 100644 --- a/application/settings.gradle.kts +++ b/application/settings.gradle.kts @@ -96,7 +96,8 @@ val roomVersion = "2.7.2" val ksp = CustomConfiguration("ksp") -// Version catalog UX: bare GAV, library(name=…), bundle, plugin — see docs/DEPS-CATALOG.md +// House style external deps (F-083): bare GAV, library(name=…), bundle, plugin — docs/DEPS-CATALOG.md +// Sample still uses advanced typed catalogs (build-dependencies/) for androidx/google graphs. projectDependencies( "libs", "com.jakewharton.timber:timber:5.0.1", diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 0c874052..58e90bd8 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -200,9 +200,10 @@ compatibility). See [`COMPOSE.md`](COMPOSE.md) for F-013 usage. side-effects from catalog registrations, sets transitive flags - Catalog: `projectDependencies` / `library` / `bundle` / `plugin` in settings (`tools.forma.deps.catalog`) + pure name generators + GAV validation - (user guide: [`DEPS-CATALOG.md`](DEPS-CATALOG.md)) -- Sample also uses hand-written catalogs in `build-dependencies/dependencies` - (`Androidx`, `Google`, `Test`, …) + (**house style** — user guide: [`DEPS-CATALOG.md`](DEPS-CATALOG.md)) +- Sample also uses **advanced** hand-written typed catalogs in + `build-dependencies/dependencies` (`Androidx`, `Google`, `Test`, …) for large + nested graphs — not a second default happy path (F-083) ### 2.5 Includer diff --git a/docs/CALL-SITE-SURFACE.md b/docs/CALL-SITE-SURFACE.md index cd47bc4f..0eade093 100644 --- a/docs/CALL-SITE-SURFACE.md +++ b/docs/CALL-SITE-SURFACE.md @@ -91,5 +91,5 @@ parameters beside them. - Matrix: [DEPENDENCY-MATRIX.md](DEPENDENCY-MATRIX.md) - Plugins: [TARGET-PLUGINS.md](TARGET-PLUGINS.md) - Global config (one path + store story): [`PROJECT-CONFIGURATION.md`](PROJECT-CONFIGURATION.md) (F-082) -- House style for external deps catalogs: **F-083** +- External deps house style: [`DEPS-CATALOG.md`](DEPS-CATALOG.md) (**F-083** — `projectDependencies` happy path; typed catalogs advanced) - Full-tree teaching audit: **F-085** diff --git a/docs/DEPS-CATALOG.md b/docs/DEPS-CATALOG.md index a7c5a136..e2fecd19 100644 --- a/docs/DEPS-CATALOG.md +++ b/docs/DEPS-CATALOG.md @@ -1,10 +1,26 @@ # Forma external dependency catalogs -Forma has **two** complementary ways to declare third-party libraries. This doc is the -user-facing guide for **F-012** catalog UX (settings-level version catalogs) and how it -relates to the typed demo catalogs under `build-dependencies/`. +**House style (one global way):** declare third-party libraries and plugins once with +settings-level [`projectDependencies`](#1-house-style--projectdependencies-version-catalog) +and consume them via `libs.*` + `deps(...)`. -## 1. Settings version catalog — `projectDependencies` +This is the **only** supported happy path for new apps, progressive examples, and +agent skills. It matches root principle 2 — *one global way* per concern +([VISION.md](VISION.md)). + +**Advanced (not a second happy path):** hand-written typed Kotlin catalog objects +(the sample’s `build-dependencies/` pattern). Keep them only when you need large +shared non-transitive graphs that version-catalog accessors do not express well. +Do not teach typed catalogs and `projectDependencies` as equal peer defaults. + +| Path | Status | Use when | +|------|--------|----------| +| `projectDependencies` → `libs.*` | **House style** | New projects, Portal apps, plugins, bundles, normal third-party pins | +| Typed objects (`androidx.*`, `google.*`, …) | **Advanced / sample-scale** | Nested explicit transitive trees at monorepo scale; not the default teaching path | + +--- + +## 1. House style — `projectDependencies` version catalog Declare libraries, bundles, and plugins once in `settings.gradle.kts`. Forma fills a Gradle [version catalog](https://docs.gradle.org/current/userguide/platforms.html#sub:version-catalog) @@ -42,6 +58,9 @@ projectDependencies( ) ``` +Teaching ladder: [`examples/android/08-deps-catalog`](../examples/android/08-deps-catalog). +Agent skill: [`forma-deps-catalog`](../examples/agent-skills/forma-deps-catalog.md). + ### Entry kinds | Entry | Factory | Catalog result | Notes | @@ -101,26 +120,46 @@ plugin( At dependency application time, consuming the room-compiler coordinate applies the KSP plugin once and adds the processor with `isTransitive = true`. -## 2. Typed catalogs — `build-dependencies/` (sample pattern) +--- + +## 2. Advanced — typed catalogs (`build-dependencies/` pattern) -The sample app also ships **hand-written** Kotlin objects +The gold-standard sample still ships **hand-written** Kotlin objects (`androidx`, `google`, `test`, …) under `build-dependencies/dependencies`. Those use `String.dep` / `deps(...)` and nest transitive graphs explicitly (e.g. `androidx.appcompat` pulls fragment, core, …). -| Approach | Best for | Trade-offs | -|----------|----------|------------| -| `projectDependencies` version catalog | App-level third-party pins, plugins, short `libs.*` accessors | Names generated or explicit; less control over nested transitive graphs | -| Typed `build-dependencies` objects | Large shared graphs, team-owned versions, non-transitive-by-default trees | More boilerplate; included via `includeBuild` + demo plugin | +This is **not** the default product path. Prefer expanding `projectDependencies` first. +Use typed catalogs only when: -Both can coexist: the sample uses catalogs for timber/coil/room/plugins and typed objects -for the androidx/google surface used across features. +- You maintain a large shared AndroidX/Google surface with intentional non-transitive trees +- Version-catalog bundles become unwieldy for that surface +- You already own an `includeBuild` deps module (as the sample does via + `tools.forma.demo:dependencies`) + +| Concern | House style (`projectDependencies`) | Advanced typed objects | +|---------|-------------------------------------|-------------------------| +| New app / tutorial | **Yes** | No | +| Plugin ids on classpath | **Yes** (`plugin(...)`) | Via separate wiring | +| Short `libs.*` accessors | **Yes** | N/A (`androidx.foo` style) | +| Nested non-transitive graphs | Limited (bundles + `deps` defaults) | **Yes** — main reason to stay advanced | +| includeBuild required | No | Yes (sample pattern) | + +The sample **mixes** both on purpose at monorepo scale: timber/coil/room/plugins go through +the house-style catalog; the broad androidx/google surface stays on typed objects. New +projects should start with **catalog only** and adopt typed objects later only if needed. + +Do **not** invent a third path (scattering raw GAVs across every `build.gradle.kts`) for +production modules. Tiny progressive examples may still use inline `deps("g:a:v")` before +step 08 introduces catalogs. + +--- ## 3. API surface (plugins `:deps`) | Symbol | Package | Role | |--------|---------|------| -| `projectDependencies` | `tools.forma.deps.catalog` | Settings DSL entry | +| `projectDependencies` | `tools.forma.deps.catalog` | Settings DSL entry (**house style**) | | `library` / `LibraryDep` | same | Explicit library registration | | `bundle` / `BundleDep` | same | Named library groups | | `plugin` / `PluginDep` | same | Plugin + optional config/libs | @@ -129,22 +168,33 @@ for the androidx/google surface used across features. | `deps` / `String.dep` / `Provider.dep` | root (`dependencies.kt`) | Bridge into `FormaDependency` | | `applyDependencies` | `tools.forma.deps.core` | Wire deps + plugin side effects | +--- + ## 4. Practical tips -1. **Pin versions in one place** — either catalog constants in `settings.gradle.kts` or - `versions` object in a typed catalog module; avoid scattering GAVs across targets. +1. **Pin versions in one place** — catalog constants in `settings.gradle.kts` (house style) + or a single `versions` object inside an advanced typed module; never scatter GAVs across + feature targets. 2. **Prefer `library(…, name = …)`** for public-facing short names you will type often. 3. **Use `bundle`** when several artifacts always travel together (Room, Coil). 4. **Keep transitive control intentional** — bare catalog `deps(libs.foo)` follows Forma's default non-transitive named-deps path unless a plugin registration forces transitive. + Use `transitiveDeps(...)` when Maven transitively is required. 5. **Invalid GAV fails fast** — `group:artifact:version` only; two or four segments throw a clear `IllegalArgumentException` at configuration time. +6. **Plugins vs apply** — catalog `plugin(...)` + `extraPlugins` put jars on the + **buildscript classpath only**. Type-owned apply is separate + ([TARGET-PLUGINS.md](TARGET-PLUGINS.md)). + +--- ## Related - Live project-dep matrix: [`DEPENDENCY-MATRIX.md`](DEPENDENCY-MATRIX.md) - Architecture map: [`ARCHITECTURE.md`](ARCHITECTURE.md) §2.4 -- Sample settings: `application/settings.gradle.kts` -- Sample typed catalogs: `build-dependencies/dependencies/src/main/kotlin/` -- **Target external plugins** — type owns plugin, call sites auto-apply (Bazel-like): - [`TARGET-PLUGINS.md`](TARGET-PLUGINS.md) (F-070+) +- Sample settings (house style + advanced mix): `application/settings.gradle.kts` +- Sample typed catalogs (advanced): `build-dependencies/dependencies/src/main/kotlin/` +- Progressive example (house style): `examples/android/08-deps-catalog` +- **Target external plugins** — type owns plugin, call sites auto-apply: + [`TARGET-PLUGINS.md`](TARGET-PLUGINS.md) +- Call-site surface: [`CALL-SITE-SURFACE.md`](CALL-SITE-SURFACE.md) diff --git a/docs/GETTING-STARTED.md b/docs/GETTING-STARTED.md index 839676a3..43a6e564 100644 --- a/docs/GETTING-STARTED.md +++ b/docs/GETTING-STARTED.md @@ -25,7 +25,7 @@ full multi-feature reference layout, see [SAMPLE-APP.md](SAMPLE-APP.md). | **Suffix** | Folder / project name ending that encodes type (`…-impl`, `…-api`, `…-res`, `binary`, …). Validators use suffixes. | | **Composition root** | `androidApp` and/or `androidBinary` — where feature graphs are wired (Dagger-friendly). | | **Feature slice** | Typical feature folder: `api` + `impl` + `res` + `viewbinding`. | -| **Catalogs** | External deps declared once (`projectDependencies` / typed catalogs), consumed via `deps(...)`. | +| **Catalogs** | External deps declared once via house-style `projectDependencies` (`libs.*`), consumed with `deps(...)`. Typed objects = advanced only — [DEPS-CATALOG.md](DEPS-CATALOG.md). | **What Forma does for each target** @@ -248,19 +248,21 @@ androidBinary( androidApp( packageName = "com.example.myapp.root", dependencies = deps( - androidx.core_ktx, // when using typed demo catalogs; or libs.* / bare deps - androidx.appcompat, - google.material, + libs.androidxCoreKtx, // house style: projectDependencies → libs.* + libs.androidxAppcompat, + libs.material, ) + deps( target(":root-res"), ), ) ``` -> **Note on external catalogs:** the sample uses both typed catalogs under -> `build-dependencies/` (`androidx.*`, `google.*`) and settings -> `projectDependencies` (`libs.*`). A Portal-only app can start with -> `projectDependencies` only — see [DEPS-CATALOG.md](DEPS-CATALOG.md). +> **External deps house style (F-083):** use settings +> `projectDependencies` → `libs.*` for all new modules +> ([DEPS-CATALOG.md](DEPS-CATALOG.md)). The gold-standard sample still uses +> **advanced** typed catalogs under `build-dependencies/` (`androidx.*`, +> `google.*`) for its large shared graph — that is optional scale, not a second +> happy path. Portal / greenfield apps should stay on `projectDependencies` only. **`feature/hello/api/build.gradle.kts`** — JVM contracts only (no `res/`): @@ -335,20 +337,23 @@ Compose flags: [COMPOSE.md](COMPOSE.md). ```kotlin dependencies = deps( - libs.jakewhartonTimber, // from projectDependencies catalog + libs.jakewhartonTimber, // house style: projectDependencies catalog libs.bundles.room, - // or typed catalog objects in the sample: androidx.appcompat, google.dagger + libs.androidxAppcompat, ) ``` Combine groups with `+`: ```kotlin -dependencies = deps(androidx.core_ktx, google.material) + +dependencies = deps(libs.androidxCoreKtx, libs.material) + deps(libs.jakewhartonTimber) + deps(target(":feature:hello:api")) ``` +> Advanced only: the sample’s typed objects (`androidx.core_ktx`, `google.dagger`) +> remain valid where that pattern is already in use — see DEPS-CATALOG §2. + ### Project / internal ```kotlin diff --git a/docs/JVM-GETTING-STARTED.md b/docs/JVM-GETTING-STARTED.md index f30497a3..cc235259 100644 --- a/docs/JVM-GETTING-STARTED.md +++ b/docs/JVM-GETTING-STARTED.md @@ -19,7 +19,7 @@ the full multi-feature reference layout, see [JVM-SAMPLE.md](JVM-SAMPLE.md). | **Suffix** | Folder / project name ending that encodes type (`…-impl`, `…-api`, `binary`, …). Validators use suffixes. | | **Composition root** | `binary` — where feature graphs are wired (entry point for `main`). | | **Feature slice** | Typical feature folder: `api` + `impl`. | -| **Catalogs** | External deps declared once (`projectDependencies` / typed catalogs), consumed via `deps(...)`. | +| **Catalogs** | External deps declared once via house-style `projectDependencies` (`libs.*`), consumed with `deps(...)`. Typed catalogs = advanced — [DEPS-CATALOG.md](DEPS-CATALOG.md). | **What Forma does for each target** @@ -127,7 +127,7 @@ includer { rootProject.name = "my-jvm-app" -// Optional: settings-level version catalog — see docs/DEPS-CATALOG.md +// House style external deps — see docs/DEPS-CATALOG.md // projectDependencies("libs", "com.squareup.okhttp3:okhttp:4.12.0", …) ``` diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 324021a8..1cc3ac42 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -2,6 +2,28 @@ Newest entries first. +## 2026-07-20 — F-083: one external-deps house style + +- **Ticket:** F-083 → `done` +- **Branch:** `forma/F-083-external-deps-convention` (from origin/v2) +- **Skills/modes:** Grok Build `--mode full` design 503 + implement timeout (no tree changes); Hermes finish path for docs/convention slice (F-083 is house-style docs class) +- **Decision (locked):** + - **House style:** `projectDependencies` → `libs.*` + `deps(...)` + - **Advanced only:** typed `build-dependencies/` objects (`androidx.*`, `google.*`) for large nested non-transitive graphs + - Not dual happy paths; sample may still mix at monorepo scale +- **Docs / teaching:** + - Rewrote `docs/DEPS-CATALOG.md` (house style §1, advanced §2) + - README, GETTING-STARTED, JVM-GETTING-STARTED, CALL-SITE-SURFACE, ARCHITECTURE §2.4, PROGRESSIVE-EXAMPLES + - Agent skill `forma-deps-catalog` + `examples/android/08-deps-catalog/README.md` + - Light KDoc on `Settings.projectDependencies`; sample settings comment +- **Out of scope (intentional):** mass-migrate sample modules off typed catalogs +- **Verify (real host, `source scripts/env-mac.sh`):** + - `plugins/ ./gradlew build` → **BUILD SUCCESSFUL** (78 tasks) + - `application/ ./gradlew build` → **BUILD SUCCESSFUL** (2322 tasks) + - `examples/android/08-deps-catalog ./gradlew :binary:assembleDebug` → **BUILD SUCCESSFUL** (128 tasks) +- **Blockers:** none +- **Next:** F-084 fleet tooling (check/generate/migrate) + ## 2026-07-20 — F-086: kapt → KSP + AGP built-in Kotlin - **Ticket:** F-086 → `done` diff --git a/docs/PROGRESSIVE-EXAMPLES.md b/docs/PROGRESSIVE-EXAMPLES.md index 99fa90a7..9ef2aba2 100644 --- a/docs/PROGRESSIVE-EXAMPLES.md +++ b/docs/PROGRESSIVE-EXAMPLES.md @@ -27,7 +27,7 @@ narrative tutorials when you want a **minimal buildable project per concept**. | `widget` / `uiLibrary` | 05 | — | forma-android-targets | | Compose + `composeWidget` | 06 | — | forma-compose | | Multi-feature composition | 07 | 04 | forma-project-layout | -| `projectDependencies` catalogs | 08 | — | forma-deps-catalog | +| `projectDependencies` catalogs (**house style**) | 08 | — | forma-deps-catalog | | `testUtil` | 09 | 05 | platform skills | | `androidTestUtil` | 09 | — | forma-android-targets | | Type-owned target plugins (`navigationRes` Path B) | 10 | — | forma-target-plugins | diff --git a/examples/agent-skills/forma-deps-catalog.md b/examples/agent-skills/forma-deps-catalog.md index 8216be78..17dc8817 100644 --- a/examples/agent-skills/forma-deps-catalog.md +++ b/examples/agent-skills/forma-deps-catalog.md @@ -1,10 +1,14 @@ --- name: forma-deps-catalog -description: projectDependencies catalogs — library, bundle, plugin, bare GAV. +description: House-style projectDependencies catalogs — library, bundle, plugin, bare GAV. --- # Deps catalog (agent skill) +**House style (one global way):** `projectDependencies` in `settings.gradle.kts` → +`libs.*` + `deps(...)`. Do not teach typed `build-dependencies/` objects as an +equal default. + Doc: `docs/DEPS-CATALOG.md`. Example: `examples/android/08-deps-catalog`. ```kotlin @@ -21,9 +25,17 @@ projectDependencies( dependencies = deps(libs.appcompat, libs.jakewhartonTimber, libs.bundles.uiBasics) ``` -External GAV strings also work in `deps("group:artifact:version")` for tiny examples. -Prefer catalogs in real apps. +External GAV strings also work in `deps("group:artifact:version")` for tiny +examples **before** step 08. Prefer catalogs in real apps. + +## Advanced (not default) + +Hand-written typed catalogs (`androidx.*`, `google.*` under sample +`build-dependencies/`) are for large nested non-transitive graphs. See +DEPS-CATALOG §2. New projects and agent scaffolds: **catalog only**. ## Transitivity -`deps("g:a:v")` is **non-transitive**. Use `transitiveDeps(...)` when Maven transitively is required (Compose UI, JUnit/hamcrest, AppCompat clusters). +`deps("g:a:v")` / bare catalog entries are **non-transitive**. Use +`transitiveDeps(...)` when Maven transitively is required (Compose UI, +JUnit/hamcrest, AppCompat clusters). diff --git a/examples/android/08-deps-catalog/README.md b/examples/android/08-deps-catalog/README.md index 9720285b..ef6c0f08 100644 --- a/examples/android/08-deps-catalog/README.md +++ b/examples/android/08-deps-catalog/README.md @@ -1,6 +1,8 @@ # 08 — deps-catalog (Android) -**Goal:** External dependency catalogs via `projectDependencies`. +**Goal:** External dependency catalogs via `projectDependencies` — the **house +style** for third-party deps in Forma (F-083). Prefer this over typed +`build-dependencies/` objects for new apps. ## Features introduced - Bare GAV → auto-named accessor (`libs.jakewhartonTimber`) @@ -16,5 +18,9 @@ printf 'sdk.dir=%s\n' "$ANDROID_HOME" > local.properties ./gradlew :binary:assembleDebug ``` +## Docs +Full guide: [`docs/DEPS-CATALOG.md`](../../../docs/DEPS-CATALOG.md) (house style +§1; advanced typed catalogs §2). + ## Next 09 adds `testUtil` + `androidTestUtil` (and documents `androidNative`). diff --git a/plugins/deps/src/main/java/tools/forma/deps/catalog/VersionCatalogBuilder.kt b/plugins/deps/src/main/java/tools/forma/deps/catalog/VersionCatalogBuilder.kt index b391f5b7..3ef02f53 100644 --- a/plugins/deps/src/main/java/tools/forma/deps/catalog/VersionCatalogBuilder.kt +++ b/plugins/deps/src/main/java/tools/forma/deps/catalog/VersionCatalogBuilder.kt @@ -12,6 +12,11 @@ import tools.forma.deps.core.NamedDependency /** * Declares a Gradle version catalog from Forma settings. * + * **House style (F-083):** this is the single supported happy path for external + * third-party deps. Consume via `libs.*` + `deps(...)`. Typed Kotlin catalog + * objects (`build-dependencies/` pattern) are advanced/sample-scale only — + * see `docs/DEPS-CATALOG.md`. + * * Supported entries: * - bare `String` coordinates → library with [defaultNameGenerator] * - [LibraryDep] via [library] → library with optional explicit name