Skip to content
Merged
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
18 changes: 18 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@ Repo: `formatools/forma` (local: `/Users/claw/work/forma`)

Ship Forma as a **working Android product**, then **forma-core** extraction, then **JVM**, then **Bazel**. Full vision: `docs/VISION.md`. Prioritized work: `TICKETS.md`.

## Root principles (axioms — do not re-litigate)

Full text: `docs/VISION.md` § Root principles.

1. **Bazel-like rules** — configure once on the type; call sites = minimal static attrs; type behavior **auto-applies**.
2. **One global way** — one supported approach per concern, project-wide (scale to large orgs). Extensibility = extend shared types/config, not module-local Gradle.
3. **Explicit structure + tooling** — declare boundaries; invest in check/generate/migrate for fleet changes.

### Consequences

- Flat, role-typed graph; no generic buckets (`androidLibrary` removed).
- Composition only at `androidApp` / `androidBinary` / JVM `binary`; `impl` ↛ `impl`.
- Closed dependency matrix (`docs/DEPENDENCY-MATRIX.md`).
- External plugins type-owned (`docs/TARGET-PLUGINS.md`); never `.withPlugin` / free-form plugin id lists.
- Portable forma-core; platforms adapt.

**Reject without discussion:** per-module plugin shopping, builder chains for identity, dual happy paths for the same concern, unrestricted deps, restoring `androidLibrary`.

## Hard rules

1. Work **only** from `TICKETS.md` priority order. Pick the top `todo` / continue `in_progress` ticket.
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,20 @@ structured, type-safe and guided way to declare your project structure. Distribu
developers to shift focus from `Build Configuration` to `Project Structure Declaration`, abstracting away build
configuration complexity.

**Root principles** (full text: [`docs/VISION.md`](docs/VISION.md)):

1. **Bazel-like rules** — configure once on the target type; call sites use a minimal set of static attributes; type behavior auto-applies.
2. **One global way** — one supported approach per concern for the whole project (built for large orgs).
3. **Explicit structure + tooling** — declare boundaries openly; tooling makes fleet-wide change reliable.

- You don't need to be a gradle expert anymore
- Get rid of project configuration bad practices
- Type-safe, single method configuration for your targets, no room for error
- Built-in dependency visibility rules
- Target types - enforce scalable project structure
- High-performance builds: Gradle best practices are applied automatically
- Dependencies framework - helps developers to understand and deal with transitive dependencies hell
- Extensible - be the expert when you need to!
- Extensible via the **shared type/config system** (not per-module Gradle dialects)
- And much more...

⚠️ We are using `target` term to express application components(e.g. modules or projects, depending in the context)
Expand Down
50 changes: 37 additions & 13 deletions TICKETS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ Status legend: `todo` | `in_progress` | `blocked` | `done`

Update this file when picking or finishing work. Cron workers must pick the **highest priority open ticket** that is not blocked.

## Root goals (implementation bar)

Every open ticket below must move the product toward:

1. **Bazel-like rules** — configure once on the type; call sites = minimal static attrs; type behavior auto-applies.
2. **One global way** — single supported approach per concern, project-wide (scale to large orgs).
3. **Explicit structure + tooling** — declare boundaries openly; invest in check/generate/migrate so fleet changes stay reliable.

Canonical write-up: `docs/VISION.md` § Root principles. Plugins design: `docs/TARGET-PLUGINS.md`.

## P0 — Bootstrap (Android product baseline)

| ID | Status | Title | Notes |
Expand Down Expand Up @@ -72,20 +82,33 @@ encourages dumping mixed concerns into one bucket. Prefer specific targets.
| F-062 | done | Reimplement progressive examples / skills without `androidLibrary` | `examples/android/04` + agent skills + README curriculum |
| F-063 | done | Hard-remove `androidLibrary` target (after consumers migrated) | DSL + `android.library` type/registry/restrictions removed; JVM `library` + AGP feature helper kept; matrix/docs updated |

## P7 — Target plugins API (uniform external plugins)
## P7 — Target plugins (type-owned, auto-apply)

Close the biggest call-site / multi-way gap: chain `withPlugin`. Design:
`docs/TARGET-PLUGINS.md`. Serves root goals **1** (Bazel call sites) and **2**
(one way: type owns plugin). GH #36 → F-073.

| ID | Status | Title | Notes |
|----|--------|-------|-------|
| F-070 | done | Design type-owned plugins API | Bazel north star; type owns plugin; auto-apply; reject free-form lists + call-site binding re-selection |
| F-071 | todo | **Implement** type→plugin registry + auto-apply; `targetPlugin` / `deriveTargetType` | Unit tests: type with plugin applies with **zero** call-site plugin API; plugins build green; shims OK |
| F-072 | todo | Migrate sample to derived types (e.g. `navigationRes`); hard-deprecate chain | Zero `.withPlugin` in tree; `TargetBuilder`/`PluginWrapper` `@Deprecated` or removed; application green |
| F-073 | todo | User docs + progressive example + agent skill; close GH #36 | Call sites attributes-only; registration/type layer documented |

## P8 — Principle alignment (implementation matches goals)

Replace chain-based `TargetBuilder.withPlugin` / `PluginWrapper` with a
**Bazel-like** model: plugin identity on the **target type** (static extend of
pre-defined types **or** derived custom type); call sites are attributes-only and
**auto-apply** type plugins. Design: `docs/TARGET-PLUGINS.md`. GH #36.
**Not** free-form plugin ids or per-callsite `pluginConfig(binding)`.
Close remaining gaps where code/docs still allow **multiple ways**, **fat call
sites**, or **missing fleet tooling**. **F-071 remains the top coding priority**
(P7 before deeper P8 unless a ticket is pure docs).

| ID | Status | Title | Notes |
|----|--------|-------|-------|
| F-070 | done | Design uniform target plugins API + deprecation plan | `docs/TARGET-PLUGINS.md` — Bazel north star; type owns plugin; call sites auto-apply; config = rule attrs / type-associated config only. Rejected free-form lists **and** call-site binding re-selection |
| F-071 | todo | Type→plugin registry + auto-apply in DSLs; `targetPlugin` / `deriveTargetType` hooks | No call-site plugin ids; unit tests prove auto-apply |
| F-072 | todo | Path B sample migration (e.g. `navigationRes`); deprecate `TargetBuilder` / `PluginWrapper` | Bazel-flat call sites; zero `.withPlugin` |
| F-073 | todo | Docs + progressive example + agent skill; close GH #36 | §3 Bazel mapping in user docs |
| F-080 | done | Codify root principles in product docs | `VISION.md` § Root principles + README + `AGENTS.md` + GETTING-STARTED; board P8 added |
| F-081 | todo | Call-site surface audit: `Unit` returns, no builder chains, minimal attrs | All Android/JVM target DSLs return `Unit`; remove `TargetBuilder` after F-072; inventory optional call-site flags (`compose`, `viewBinding`, …) — keep only as declared rule attrs with **project-global defaults**, not ad-hoc structure |
| F-082 | todo | One global configuration path | Remove/finish-kill deprecated `Project.androidProjectConfiguration`; document `extraPlugins` as **classpath only** (not per-module apply); single settings/store story |
| 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-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 |

## Backlog (lower priority / historical GitHub)

Expand All @@ -96,14 +119,15 @@ Keep for reference; do not start unless higher tickets done or user prioritizes:
- GH #88 BuildFeatures support
- GH #82 Version code/name in binary
- GH #77 transitiveDeps extension
- GH #54 Generate target structure from minimal config
- GH #54 Generate target structure from minimal config → **theme under F-084**
- GH #51 Support build types
- GH #46 New navigation system
- GH #44/#43 Hybrid targets/config examples
- GH #36 Docs for external plugins → **P7 / F-070–F-073** (`docs/TARGET-PLUGINS.md`)
- GH #126 Target features configuration options
- GH #36 Docs for external plugins → **P7 / F-070–F-073**
- GH #126 Target features configuration options → consider under **F-081**
- GH #111 Gradle project as buildscript classpath
- GH #103 Java 8+ API on Android API ≤26
- **F-019** AGP 9 / absolute-latest AndroidX — **explicit OK only** (not on board until requested)

## How workers update this file

Expand Down
4 changes: 4 additions & 0 deletions docs/GETTING-STARTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Forma is a **meta build system** for Android (Gradle plugin). You declare
rules. Forma applies plugins, shared Android settings, and **dependency
visibility validation** for you.

**Root principles** (see [`VISION.md`](VISION.md)): (1) Bazel-like rules — configure
once on the type, minimal call-site attrs; (2) one global way project-wide; (3)
explicit structure, with tooling for large-scale change.

This tutorial gets you from zero to a working multi-target Android app. For the
full multi-feature reference layout, see [SAMPLE-APP.md](SAMPLE-APP.md).

Expand Down
15 changes: 15 additions & 0 deletions docs/PROGRESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@

Newest entries first.

## 2026-07-19 — P8 board: principle-alignment tickets + F-080 docs

- **User ask:** create tickets to update implementation to match Forma goals (3 root principles)
- **Tickets added (P8):**
- **F-080** `done` — codify principles in VISION/README/AGENTS/GETTING-STARTED
- **F-081** call-site surface audit (Unit returns, minimal attrs)
- **F-082** one global configuration path
- **F-083** one external-deps house style
- **F-084** fleet tooling check/generate/migrate (GH #54 theme)
- **F-085** full-tree sample/examples/skills audit
- **P7 unchanged priority:** **F-071** still top coding ticket (type-owned plugins)
- **TICKETS.md** top section = root goals bar for all workers
- **Product code:** none this slice
- **Next:** F-071 implement

## 2026-07-19 — F-070 revised again: Bazel-like call sites

- **Ticket:** F-070 design correction (PR #185 update)
Expand Down
29 changes: 29 additions & 0 deletions docs/VISION.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,34 @@

Make **Forma** a working product for **Android** first, then adapt the same approach for **JVM applications**, then for **Bazel**.

## Root principles (product axioms)

These are the bar for every API and implementation change. Inferable from the
README meta-build pitch; stated here so they cannot drift.

1. **Bazel-like rules** — Configure behavior **once** on the target type (rule).
Call sites use a **minimal set of static attributes** (package, deps, declared
rule fields). Using a type always gets that type’s behavior (plugins, features,
content rules, matrix). No per-module tool shopping.
2. **One global way** — Built to scale to very large orgs (thousands of developers).
There is **one** supported way to express a given concern, **global for the
entire project**. Extensibility means extending the shared type/config system,
not inventing module-local Gradle dialects.
3. **Everything is explicit** — Structure and boundaries are declared, not implied
by hidden convention soup. Tradeoff: more configuration at the **type / project**
layer. Remedy: **tooling** so large-scale changes stay easy and reliable
(check / generate / migrate — includer, depgen, adapters, future fleet tools).

### Consequences (do not treat as separate products)

- **Flat, role-typed graph** — most specific role; no generic buckets (`androidLibrary` removed).
- **Composition only at roots** — `androidApp` / `androidBinary` / JVM `binary`; `impl` ↛ `impl`.
- **Closed dependency matrix** — allow-listed project edges only.
- **Portable forma-core** — types, restrictions, validation, registry; platforms adapt.
- **External plugins** — type-owned, auto-apply; see [`TARGET-PLUGINS.md`](TARGET-PLUGINS.md).

Implementation debt vs these axioms is tracked under **P7–P8** in `TICKETS.md`.

## Core product principle — keep structure flat

Forma exists to **protect a flat, role-typed module graph**. Each target type is a
Expand Down Expand Up @@ -51,6 +79,7 @@ Concrete stacks built **on** forma-core:
4. **Bazel** — design + implement adapter once core is stable (see [`docs/BAZEL-ADAPTER.md`](BAZEL-ADAPTER.md) for the F-040 mapping design).
5. **Flat-structure hardening** — deprecate/remove generic targets that undermine role typing (P6 / F-060+).
6. **Uniform target plugins** — Bazel-like: plugin on the **target type**, auto-apply on every call site; call sites are attributes-only; deprecate chain `withPlugin` (P7 / F-070+; [`TARGET-PLUGINS.md`](TARGET-PLUGINS.md)).
7. **Principle-alignment implementation** — close remaining gaps vs root principles (P8 / F-080+).

## Working principles

Expand Down
Loading