diff --git a/README.md b/README.md
index 0f5e649..4a99a31 100644
--- a/README.md
+++ b/README.md
@@ -103,38 +103,54 @@ Worker / contributor host setup (JDK 17+, Android SDK platform 33): see [`docs/E
## Progress
-| Supported target types | implemented | purpose | validation |
-|:----------------------:|:-----------:|:-----------------------------:|:----------:|
-| androidBinary | ✅ | Generate single APK | ✅ |
-| androidApp | ✅ | Application class | partial |
-| androidLibrary | ✅ | Android library | partial |
-| androidWidget | ✅ | Custom View | partial |
-| androidRes | ✅ | Resources Only | ✅ |
-| androidTestUtils | ✅ | Shared code for Android tests | ✅ |
-| androidUtils | ✅ | Library extensions | partial |
-| testUtils | ✅ | Shared code for unit tests | ✅ |
-| utils | ✅ | JVM Library extensions | partial |
-| library | ✅ | JVM Library | partial |
-| api | ✅ | Feature external API's | partial |
-| impl | ✅ | Feature implementation | partial |
+DSL names match code entrypoints (`widget`, `util`, …). **Validation** =
+project-dep type checks + content layout rules from live validators
+([full matrix](docs/DEPENDENCY-MATRIX.md)).
+
+| Supported target types | implemented | purpose | validation |
+|:----------------------:|:-----------:|:-------:|:----------:|
+| `androidBinary` | ✅ | Generate single APK | name + no `res/`; project deps **unrestricted** (`EmptyValidator`) |
+| `androidApp` | ✅ | Application / root Android library | name + no `res/`; project deps **unrestricted** |
+| `androidLibrary` | ✅ | Android library | name only; project deps **unrestricted** |
+| `uiLibrary` | ✅ | Shared UI library for impl/widget | project-dep list |
+| `widget` | ✅ | Custom View / UI component | project-dep list |
+| `androidRes` | ✅ | Resources only | only `res/` under `src/main` + project-dep list |
+| `viewBinding` | ✅ | Layout-only view binding module | only `layout*` under `res` + project-dep list |
+| `androidTestUtil` | ✅ | Shared code for Android tests | project-dep list |
+| `androidUtil` | ✅ | Android library extensions | no `res/` + project-dep list |
+| `testUtil` | ✅ | Shared code for unit tests | no `res/` + project-dep list |
+| `util` | ✅ | JVM library extensions | no `res/` + project-dep list |
+| `library` | ✅ | JVM library | project-dep list (shares `library` suffix with `androidLibrary`) |
+| `api` | ✅ | Feature external APIs | no `res/` + project-dep list |
+| `impl` | ✅ | Feature implementation | project-dep list (**no** other `impl`) |
+| `androidNative` | ✅ | NDK / native | no `res/`; no project-dep validation yet |
## Dependency matrix
-Each column represents the list of allowed/disallowed dependencies
-
-| | androidApp | androidBinary | androidLibrary | androidWidget | androidRes | androidTestUtils | api | impl | androidUtils | utils | testUtils |
-|------------------|-------------|---------------|----------------|---------------|------------|------------------|-----|------|-------------|------|----------|
-| androidApp | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
-| androidBinary | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
-| androidLibrary | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
-| androidWidget | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
-| androidRes | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ |
-| androidTestUtils | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
-| api | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
-| impl | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
-| androidUtils | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ |
-| utils | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ |
-| testUtils | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
+**Canonical reference (code truth):** [`docs/DEPENDENCY-MATRIX.md`](docs/DEPENDENCY-MATRIX.md).
+
+That document is generated from each target’s
+`applyDependencies(validator = …)` call and content helpers. Summary:
+
+| Consumer | May depend on project suffixes… |
+|----------|----------------------------------|
+| `api` | `api`, `library` |
+| `impl` | `api`, `android-util`, `test-util`, `util`, `library`, `ui-library`, `res`, `viewbinding`, `widget` |
+| `library` (JVM) | `util`, `test-util` |
+| `androidLibrary` | *any* (`EmptyValidator`) |
+| `uiLibrary` | `widget`, `util`, `android-util`, `res` |
+| `util` | `util`, `library` |
+| `androidUtil` | `android-util`, `test-util`, `res` |
+| `testUtil` | `test-util`, `util` |
+| `androidTestUtil` | `android-test-util`, `test-util` |
+| `androidRes` | `res`, `widget` |
+| `widget` | `ui-library`, `widget`, `util`, `android-util`, `res` |
+| `viewBinding` | `api`, `widget`, `res`, `library`, `android-util` |
+| `androidApp` / `androidBinary` | *any* (`EmptyValidator`) |
+| `androidNative` | *(no project-dep check)* |
+
+Tightening unrestricted entry targets and Dagger-friendly `api`/`impl`
+boundaries is tracked as **F-011**.
Icons made by Freepik
from www.flaticon.com
diff --git a/TICKETS.md b/TICKETS.md
index adc8ceb..9e7fe77 100644
--- a/TICKETS.md
+++ b/TICKETS.md
@@ -17,7 +17,7 @@ Update this file when picking or finishing work. Cron workers must pick the **hi
| ID | Status | Title | Notes |
|----|--------|-------|-------|
-| F-010 | todo | Document strict dependency matrix from live code (not only README) | Source of truth from validators/targets |
+| F-010 | done | Document strict dependency matrix from live code (not only README) | `docs/DEPENDENCY-MATRIX.md` + README summary aligned to validators |
| F-011 | todo | Tighten validation for `api` / `impl` (Dagger2-friendly boundaries) | Align with current types; related GH #56, #18 |
| F-012 | todo | External deps catalog UX + tooling polish | `plugins/deps` catalog generators |
| F-013 | todo | Compose support for Android library/ui targets | GH #96 |
diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md
index 149d1be..5d6fcdf 100644
--- a/docs/ARCHITECTURE.md
+++ b/docs/ARCHITECTURE.md
@@ -130,9 +130,9 @@ Name rule (`validation`): project name equals `suffix` or ends with `-$suffix`.
### 2.2 Allowed project dependencies (from live validators)
-This is **code truth** (each target’s `applyDependencies(validator = …)`).
-README matrix (F-010) should be reconciled against this table — they diverge
-(e.g. several Android entry targets use `EmptyValidator`).
+**Canonical tables + full matrix:** [`docs/DEPENDENCY-MATRIX.md`](DEPENDENCY-MATRIX.md)
+(F-010). That file is the user-facing code truth; keep this section in sync
+when validators change.
| Consumer DSL | Allowed *project* dependency suffixes | Content rules |
|--------------|----------------------------------------|---------------|
@@ -312,7 +312,7 @@ Suggested extraction order (tickets F-020…F-024):
| Item | Ticket |
|------|--------|
-| README dependency matrix ≠ live validators | F-010 |
+| ~~README dependency matrix ≠ live validators~~ → [`docs/DEPENDENCY-MATRIX.md`](DEPENDENCY-MATRIX.md) | F-010 done |
| `EmptyValidator` on app/binary/androidLibrary | F-011 |
| ~~AGP 7.4.2 compile vs 8.1.2 runtime~~ (aligned 8.1.2) | F-003 done |
| ~~CI missing SDK + Java on some jobs~~ (GHA green on PR #153) | F-004 done |
diff --git a/docs/DEPENDENCY-MATRIX.md b/docs/DEPENDENCY-MATRIX.md
new file mode 100644
index 0000000..26aac42
--- /dev/null
+++ b/docs/DEPENDENCY-MATRIX.md
@@ -0,0 +1,210 @@
+# Forma dependency matrix (code truth)
+
+Source of truth for **F-010**. Every rule below is taken from the live
+`applyDependencies(validator = …)` / content validators in
+`plugins/android/src/main/java/*.kt` (and
+`tools/forma/android/validation/commonValidators.kt`).
+
+When validators change, update **this file first**, then the README summary
+matrix. Do not invent rules from aspirational docs.
+
+Last verified: **2026-07-11** against `v2` tip (post F-003 / F-004).
+
+---
+
+## How validation works
+
+1. **Name / type of the consumer** — each DSL entry calls
+ `target.validate(SomeTargetTemplate)`. The project name must equal the
+ template `suffix` or end with `-$suffix` (see
+ `plugins/validation/.../Validator.kt`).
+2. **Allowed project dependencies** — `applyDependencies` runs a `Validator`
+ on every **project** dependency. `validator(A, B, …)` accepts only
+ dependency projects whose names match those templates’ suffixes.
+ `EmptyValidator` accepts **any** project dependency (no type check).
+3. **Content layout** — some targets call `disallowResources()`,
+ `onlyAllowResources()`, or `onlyAllowLayouts()` before configuration.
+4. **External / catalog deps** — named library deps are not filtered by the
+ project-suffix validators; only `project(...)` edges are.
+
+Validation is **suffix-based**, not Gradle configuration-based. A project
+named `feature-home-api` is treated as type `api` because of the `-api`
+suffix (`ApiTargetTemplate("api")`).
+
+---
+
+## Target templates (suffixes)
+
+From `plugins/android/.../AndroidTargets.kt`:
+
+| DSL entrypoint | Template object | Name suffix |
+|----------------|-----------------|-------------|
+| `androidBinary` | `BinaryTargetTemplate` | `binary` |
+| `androidApp` | `ApplicationTargetTemplate` | `app` |
+| `androidLibrary` | `LibraryTargetTemplate` | `library` |
+| `library` (JVM) | `LibraryTargetTemplate` | `library` |
+| `uiLibrary` | `UiLibraryTargetTemplate` | `ui-library` |
+| `androidNative` | `NativeTarget` | `native` |
+| `util` | `UtilTargetTemplate` | `util` |
+| `testUtil` | `TestUtilTargetTemplate` | `test-util` |
+| `androidTestUtil` | `AndroidTestUtilTargetTemplate` | `android-test-util` |
+| `androidUtil` | `AndroidUtilTargetTemplate` | `android-util` |
+| `viewBinding` | `ViewBindingTargetTemplate` | `viewbinding` |
+| `androidRes` | `ResourcesTargetTemplate` | `res` |
+| `api` | `ApiTargetTemplate` | `api` |
+| `impl` | `ImplTargetTemplate` | `impl` |
+| `widget` | `WidgetTargetTemplate` | `widget` |
+
+**Collision note:** JVM `library` and Android `androidLibrary` share the same
+suffix `library` / `LibraryTargetTemplate`. The DSL functions differ (Kotlin
+JVM features vs AGP library features), but project-name validation cannot
+tell them apart. Follow-up: F-020 (forma-core registry design).
+
+README historically said `androidWidget` / `androidUtils` / `testUtils` /
+`utils` / `androidTestUtils` — the **code** entrypoints are `widget`,
+`androidUtil`, `testUtil`, `util`, `androidTestUtil`.
+
+---
+
+## Allowed project dependencies (consumer → allowed dependency suffixes)
+
+Read as: **consumer DSL** may depend on project targets whose names match
+these suffixes (or are unrestricted if `EmptyValidator`).
+
+| Consumer DSL | Source file | Project-dep validator | Allowed dependency suffixes |
+|--------------|-------------|------------------------|-----------------------------|
+| `api` | `api.kt` | `validator(api, library)` | `api`, `library` |
+| `impl` | `impl.kt` | `validator(api, android-util, test-util, util, library, ui-library, res, viewbinding, widget)` | `api`, `android-util`, `test-util`, `util`, `library`, `ui-library`, `res`, `viewbinding`, `widget` |
+| `library` (JVM) | `library.kt` | `validator(util, test-util)` | `util`, `test-util` |
+| `androidLibrary` | `androidLibrary.kt` | **`EmptyValidator`** | *any project* |
+| `uiLibrary` | `uiLibrary.kt` | `validator(widget, util, android-util, res)` | `widget`, `util`, `android-util`, `res` |
+| `util` | `util.kt` | `validator(util, library)` | `util`, `library` |
+| `androidUtil` | `androidUtil.kt` | `validator(android-util, test-util, res)` | `android-util`, `test-util`, `res` |
+| `testUtil` | `testUtil.kt` | `validator(test-util, util)` | `test-util`, `util` |
+| `androidTestUtil` | `androidTestUtil.kt` | `validator(android-test-util, test-util)` | `android-test-util`, `test-util` |
+| `androidRes` | `androidRes.kt` | `validator(res, widget)` | `res`, `widget` |
+| `widget` | `widget.kt` | `validator(ui-library, widget, util, android-util, res)` | `ui-library`, `widget`, `util`, `android-util`, `res` |
+| `viewBinding` | `viewBinding.kt` | `validator(api, widget, res, library, android-util)` | `api`, `widget`, `res`, `library`, `android-util` |
+| `androidApp` | `androidApp.kt` | **`EmptyValidator`** | *any project* |
+| `androidBinary` | `androidBinary.kt` | **`EmptyValidator`** | *any project* |
+| `androidNative` | `androidNative.kt` | *(no `applyDependencies`)* | *no project-dep validation* |
+
+### Explicit non-edges (important product rules)
+
+These follow from the table (not from separate deny-lists):
+
+- **`impl` cannot depend on `impl`** — only listed suffixes; good for
+ Dagger-style feature boundaries (tighten further in F-011).
+- **`api` cannot depend on `impl` / widgets / res / viewbinding** — JVM API
+ surface only (`api` + `library`).
+- **`library` (JVM) cannot depend on `api` / `impl`** — comment in code:
+ “Can't depend on api\impl”.
+- **`util` cannot depend on `api` / `impl`** — same intent as library.
+- **Circular-ish UI graph is intentional while experimental:** `uiLibrary`
+ may depend on `widget`, and `widget` may depend on `ui-library`
+ (`uiLibrary.kt` comment).
+
+---
+
+## Content rules (src layout)
+
+| Consumer DSL | Helper | Rule |
+|--------------|--------|------|
+| `api` | `disallowResources()` | no `res/` under `src/main` |
+| `util` | `disallowResources()` | no `res/` under `src/main` |
+| `androidUtil` | `disallowResources()` | no `res/` under `src/main` |
+| `testUtil` | `disallowResources()` | no `res/` under `src/main` |
+| `androidApp` | `disallowResources()` | no `res/` under `src/main` |
+| `androidBinary` | `disallowResources()` | no `res/` under `src/main` |
+| `androidNative` | `disallowResources()` | no `res/` under `src/main` |
+| `androidRes` | `onlyAllowResources()` | **only** `res/` directory under `src/main` |
+| `viewBinding` | `onlyAllowLayouts()` | under `src/main/res`, only `layout*` folders |
+| others | — | no extra content validator in current code |
+
+Helpers live in
+`plugins/android/src/main/java/tools/forma/android/validation/commonValidators.kt`.
+
+---
+
+## Full matrix (consumer rows × dependency columns)
+
+Legend:
+
+- **Y** — allowed by non-empty `validator(...)` list
+- **\*** — `EmptyValidator` / no project-dep check (anything goes)
+- **—** — not allowed by the live validator list
+- **n/a** — `androidNative` has no `applyDependencies`
+
+Rows = **consumer**. Columns = **dependency type (suffix)**.
+
+| Consumer ↓ \ Dep → | api | impl | library | ui-library | util | test-util | android-util | android-test-util | res | viewbinding | widget | app | binary | native |
+|--------------------|-----|------|---------|------------|------|-----------|--------------|-------------------|-----|-------------|--------|-----|--------|--------|
+| **api** | Y | — | Y | — | — | — | — | — | — | — | — | — | — | — |
+| **impl** | Y | — | Y | Y | Y | Y | Y | — | Y | Y | Y | — | — | — |
+| **library** (JVM) | — | — | — | — | Y | Y | — | — | — | — | — | — | — | — |
+| **androidLibrary** | * | * | * | * | * | * | * | * | * | * | * | * | * | * |
+| **uiLibrary** | — | — | — | — | Y | — | Y | — | Y | — | Y | — | — | — |
+| **util** | — | — | Y | — | Y | — | — | — | — | — | — | — | — | — |
+| **androidUtil** | — | — | — | — | — | Y | Y | — | Y | — | — | — | — | — |
+| **testUtil** | — | — | — | — | Y | Y | — | — | — | — | — | — | — | — |
+| **androidTestUtil** | — | — | — | — | — | Y | — | Y | — | — | — | — | — | — |
+| **androidRes** | — | — | — | — | — | — | — | — | Y | — | Y | — | — | — |
+| **widget** | — | — | — | Y | Y | — | Y | — | Y | — | Y | — | — | — |
+| **viewBinding** | Y | — | Y | — | — | — | Y | — | Y | — | Y | — | — | — |
+| **androidApp** | * | * | * | * | * | * | * | * | * | * | * | * | * | * |
+| **androidBinary** | * | * | * | * | * | * | * | * | * | * | * | * | * | * |
+| **androidNative** | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a |
+
+Self-deps: a type may depend on itself only if its own suffix is in its
+allowed list (e.g. `api`→`api` **Y**, `impl`→`impl` **—**, `widget`→`widget`
+**Y**).
+
+---
+
+## README matrix vs code (divergences)
+
+The historical README table used columns as *consumers* and rows as
+*dependencies*, mixed aspirational edges, and omitted several types
+(`uiLibrary`, `viewBinding`, `library` JVM vs `androidLibrary`, `native`).
+
+Notable mismatches fixed by treating **this document** as truth:
+
+| Topic | Old README implication | Live code |
+|-------|------------------------|-----------|
+| `androidLibrary` project deps | selective ✅/❌ grid | **`EmptyValidator`** (unrestricted) |
+| `androidApp` / `androidBinary` project deps | selective grid | **`EmptyValidator`** |
+| `impl` → `impl` | ❌ (agrees) | not in allowed list |
+| `api` → `library` | not clearly shown | **allowed** |
+| `impl` → `ui-library` / `viewbinding` / `widget` / `res` | partially missing | **allowed** |
+| `widget` → `ui-library` | not shown | **allowed** |
+| `viewBinding` | missing from matrix | full row above |
+| `uiLibrary` | missing / confused with library | full row above |
+| DSL names | `androidWidget`, `utils`, … | `widget`, `util`, … |
+
+Tightening `EmptyValidator` targets and Dagger-friendly `api`/`impl` edges is
+**F-011**, not documentation fiction.
+
+---
+
+## Sample app check (sanity)
+
+`application/` multi-feature layout uses the pattern:
+
+- `feature/*/api` → JVM `api`
+- `feature/*/impl` → Android `impl` + viewbinding/res/widget/core libraries
+- `binary` → `androidBinary` with explicit deps on root-app + feature api/impl
+ (legal today because binary uses `EmptyValidator`)
+
+See `docs/ARCHITECTURE.md` §2.2 and §3 for the module map.
+
+---
+
+## Maintenance checklist
+
+1. Change a `validator(...)` list or content helper in `plugins/android`.
+2. Update the tables in **this file**.
+3. Refresh the compact README matrix (link here as canonical).
+4. Note the change in `docs/PROGRESS.md` / ticket notes when user-facing.
+
+Related tickets: **F-011** (tighten validation), **F-020** (forma-core type
+registry / shared `library` suffix).
diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md
index b8e617e..9d5b7a4 100644
--- a/docs/PROGRESS.md
+++ b/docs/PROGRESS.md
@@ -2,6 +2,28 @@
Newest entries first.
+## 2026-07-11 — F-010 Dependency matrix from live validators
+
+- **Ticket:** F-010 → `done`
+- **Branch:** `forma/F-010-dependency-matrix` (from `origin/v2` after F-003/F-004 merge)
+- **Actions:**
+ - Added `docs/DEPENDENCY-MATRIX.md` as canonical code-truth matrix:
+ - How name / project-dep / content validation works
+ - Per-DSL allowed suffixes from each `applyDependencies(validator=…)`
+ - Content rules (`disallowResources` / `onlyAllowResources` / `onlyAllowLayouts`)
+ - Full consumer×dependency table (Y / * / — / n/a)
+ - README vs code divergence notes
+ - Replaced aspirational README ✅/❌ grid with code-aligned summary + link
+ - Expanded Progress target table (`uiLibrary`, `viewBinding`, `androidNative`, real DSL names)
+ - Pointed `docs/ARCHITECTURE.md` §2.2 + §7 at the new doc; marked F-010 done
+- **Also this run (P0 land on `v2`):**
+ - Squash-merge path unavailable (repo allows squash only); merged #152 then #153 into `v2` locally and pushed (`123ec44`)
+ - PR #152 F-003 and #153 F-004 both **MERGED** into `v2`
+- **Build:** docs-only slice; no Gradle re-run required for matrix extraction (rules read from Kotlin sources)
+- **Commits/PRs:** this branch → PR base `v2`
+- **Blockers:** none
+- **Next step:** F-011 tighten `api`/`impl` (+ optional replace `EmptyValidator` on app/binary/androidLibrary)
+
## 2026-07-11 — F-004 CI green (workflow + badge)
- **Ticket:** F-004 → `done`