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
67 changes: 67 additions & 0 deletions .ai/skills/write-tests/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
name: write-tests
description: |
Write or extend tests for the Chai repo. Triggered by "write a test",
"add tests", "test this", or as the follow-up when a component/util lands
without coverage. Local unit tests use JUnit 6 (Jupiter); Compose/UI behaviour
is tested as instrumented tests. Picks the right source set and idioms; does
not invent mocking/assertion libraries the catalog does not declare.
---

# write-tests

The repo's tests are still mostly generated scaffolds (see
`docs/tech/findings.md` → "Only scaffold tests exist"). This skill writes real
ones in the conventions already wired into the build.

## What runs where

| Kind | Source set | Framework | Run with |
|------|-----------|-----------|----------|
| Pure logic, no Android/Compose runtime | `src/test/java` | JUnit 6 (Jupiter), `useJUnitPlatform()` | `./gradlew :<module>:testDebugUnitTest` |
| Composable rendering / interaction | `src/androidTest/java` | `androidx.compose.ui:ui-test-junit4` + `androidx.test.ext:junit` | `./gradlew :<module>:connectedDebugAndroidTest` (needs a device/emulator) |

Catalog references (`gradle/libs.versions.toml`): `junit-bom`,
`junit-jupiter`, `junit-platform-launcher` for unit tests;
`androidx-ui-test-junit4`, `androidx-ui-test-manifest`, `androidx-junit`,
`androidx-espresso-core` for instrumented.

## Rules

- **Use Jupiter, not JUnit 4, for unit tests.** Import `org.junit.jupiter.api.Test`
and `org.junit.jupiter.api.Assertions.*` (or `assertEquals`/`assertTrue` from
Jupiter). Do not import `org.junit.Test` or `org.junit.Assert` in `src/test`.
- **No new test libraries.** The catalog declares no MockK, Truth, Turbine, or
coroutines-test. Do not add them as part of writing a test — if a test truly
needs one, raise it as a separate dependency change (see the `dependency-bump`
skill) rather than slipping it in here.
- **Compose tests** go in `src/androidTest`, use `createComposeRule()` /
`createAndroidComposeRule<…>()`, and wrap content in `ChaiTheme { }` so tokens
resolve the same way they do in the app.
- **Design system still applies in test content.** When a test renders sample
UI, use Chai components/tokens, not raw Material — the same guard rail
(`scripts/check-design-system-usage.sh`) covers test sources.
- Replace generated `ExampleUnitTest` / `ExampleInstrumentedTest` stubs when you
add the first real test for a module; do not leave the `2 + 2 == 4` scaffold
next to real coverage.

## Procedure

1. Find what is untested. Pick the smallest meaningful unit (a util, a mapper, a
component's documented behaviour).
2. Choose the source set from the table above. Pure Kotlin → `src/test`.
Anything that composes → `src/androidTest`.
3. Name the file `<TypeName>Test.kt` in the matching package under that source
set. One behaviour per `@Test`; name tests for the behaviour, not the method.
4. Run the matching gradle task (use the `check-build` / `checks` skills if the
module fails to compile first).
5. Report: file added, what it covers, and the run result.

## Report

```
write-tests ✓ <module>: added <N> test(s) in <file> (testDebugUnitTest passed)
```

If instrumented tests were written but no device was available to run them, say
so explicitly — do not claim they passed.
19 changes: 19 additions & 0 deletions .cursor/rules/chai.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
description: Chai repo agent guidance — points to AGENTS.md
alwaysApply: true
---

The full, tool-neutral guidance for this repo lives in
[`AGENTS.md`](../../AGENTS.md) — read it for conventions, guard rails, and where
skills/agents/memory live.

Non-negotiables (authoritative version in `AGENTS.md`):

- **Design system only.** In `chai`/`chaidemo` source use Chai components and
tokens (`ChaiTheme`, `ChaiColors`, the `C*` components, `Space*`/`Spacer*`).
Never raw Material 3 components or hardcoded `Color(0x…)` / `.dp` literals.
- **Compose previews** use `@ChaiPreview`, not `@Preview`.
- **Branches** target `develop`, not `main`. Prefixes: `feature/`, `fix/`, `docs/`.
- **Commits**: past tense, concise subject, no period, no body, no
conventional-commits prefix.
- **Never** `git push --no-verify` or `--force`. Fix hook failures instead.
17 changes: 17 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copilot instructions

GitHub Copilot reads this file automatically. The full, tool-neutral guidance
for this repo lives in [`AGENTS.md`](../AGENTS.md) — read it for conventions,
guard rails, and where skills/agents/memory live.

The non-negotiables, repeated here because Copilot does not follow links
(see `AGENTS.md` for the authoritative version):

- **Design system only.** In `chai`/`chaidemo` source use Chai components and
tokens (`ChaiTheme`, `ChaiColors`, the `C*` components, `Space*`/`Spacer*`).
Never raw Material 3 components or hardcoded `Color(0x…)` / `.dp` literals.
- **Compose previews** use `@ChaiPreview`, not `@Preview`.
- **Branches** target `develop`, not `main`. Prefixes: `feature/`, `fix/`, `docs/`.
- **Commits**: past tense, concise subject, no period, no body, no
conventional-commits prefix. ("Added X", not "feat: add x.")
- **Never** `git push --no-verify` or `--force`. Fix hook failures instead.
14 changes: 14 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ jobs:
with:
access_token: ${{ github.token }}

guards:
name: Guards (agent tooling & design system)
permissions:
contents: read
runs-on: ubuntu-latest
needs: cancel-previous
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Agent-tooling lint
run: ./scripts/check-agent-tooling.sh
- name: Design-system usage guard
run: ./scripts/check-design-system-usage.sh

lint:
name: Lint
permissions:
Expand Down
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"java.compile.nullAnalysis.mode": "automatic"
}
7 changes: 7 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# CLAUDE.md

Claude Code reads this file automatically. All agent guidance for the Chai repo
is kept in one tool-neutral place so every assistant shares the same rules.
Read it before any task:

@AGENTS.md
6 changes: 6 additions & 0 deletions GEMINI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# GEMINI.md

Gemini reads this file automatically. All agent guidance for the Chai repo is
kept in one tool-neutral place: [`AGENTS.md`](./AGENTS.md). Read it before any
task — it is the single source of truth for conventions, guard rails, and where
skills/agents/memory live.
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

What is a design system:

To learn more about this look at this [Why Design Systems](https://github.com/droidconKE/chai/blob/master/docs/whyDesignSystems.md) - Explains the need for a design system in the context of compose.
To learn more about this look at this [Why Design Systems](./docs/whyDesignSystems.md) - Explains the need for a design system in the context of compose.

## About Chai

Expand All @@ -28,13 +28,15 @@ This Project shows how you can use this design system in a multi module app mono
### Structure Of Chai's Design System Project,

The Chai Design System Project Architecture is captured in detail:
1. [Why Design Systems](https://github.com/droidconKE/chai/blob/master/docs/whyDesignSystems.md) - Explains the need for a design system in the context of compose.
2. [Architecture](https://github.com/droidconKE/chai/blob/master/docs/architecture.md) - The architecture of the project
3. [Chai Design System Architecture](https://github.com/droidconKE/chai/blob/master/docs/chaiArchitecture.md) - The architecture of the design system
4. [buildlogic](https://github.com/droidconKE/chai/blob/master/docs/buildlogic.md) - Handles how we build the app with gradle, ditches the build src in favour of convention plugins.
5. [chaiLinter](https://github.com/droidconKE/chai/blob/master/docs/chaiLinter.md) - Explains the design system linter
6. [Atoms](https://github.com/droidconKE/chai/blob/master/docs/atoms.md) - Explains the atoms in the design system
7. [Components](https://github.com/droidconKE/chai/blob/master/docs/components.md) - Design system components
1. [Why Design Systems](./docs/whyDesignSystems.md) - Explains the need for a design system in the context of compose.
2. [Architecture](./docs/architecture.md) - The architecture of the project
3. [Chai Design System Architecture](./docs/chaiArchitecture.md) - The architecture of the design system
4. [buildlogic](./docs/buildlogic.md) - Handles how we build the app with gradle, ditches the build src in favour of convention plugins.
5. [chaiLinter](./docs/chaiLinter.md) - Explains the design system linter
6. [Atoms](./docs/atoms.md) - Explains the atoms in the design system
7. [Components](./docs/components.md) - Design system components
8. [Versioning](./docs/versioning.md) - Semantic Versioning scheme and the release flow
9. [Automated Workflow](./docs/automatedWorkflow.md) - How RenovateBot groups and raises dependency-update PRs

## Implementing Chai

Expand Down
49 changes: 49 additions & 0 deletions docs/versioning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Versioning

Chai follows [Semantic Versioning](https://semver.org/). Releases are tagged on `main`
as `vMAJOR.MINOR.PATCH` (for example `v1.2.0`).

## What `v1.2.0` means

It's three numbers, `MAJOR.MINOR.PATCH`, and the `v` is just a conventional prefix for the git tag:

```
v 1 . 2 . 0
│ │ └── PATCH — backward-compatible bug fixes only
│ └────── MINOR — new functionality, backward-compatible (nothing breaks)
└────────── MAJOR — breaking/incompatible API changes
```

The rule is "bump the leftmost number that applies, and reset the ones to its right to 0":

| Change | From → To |
| --- | --- |
| Fix a bug, no API change | `1.2.0` → `1.2.1` |
| Add a new component, old code still works | `1.2.1` → `1.3.0` |
| Rename/remove a public API (breaking) | `1.3.0` → `2.0.0` |

## What this maps to for Chai

For a design-system library, the bump maps cleanly to consumer impact:

- **PATCH** — fix `CPrimaryButton`'s disabled color.
- **MINOR** — ship the new `CCards` / `CTabs` components (additive).
- **MAJOR** — the `ChaiSteal` → `ChaiSteel` rename, or dropping a public color token
(breaks anyone depending on it).

## Two conventions

- **`0.x.y`** means "pre-1.0, anything can change" — useful while the API is still settling.
Cut `v1.0.0` once the public API is committed to being stable.
- A **pre-release suffix** like `v1.3.0-alpha01` or `-rc1` marks a not-yet-final build
(the same scheme AGP uses).

## Release flow

`develop` is the integration branch; `main` is the release line.

1. Day-to-day work merges into `develop` via PRs.
2. To cut a release, open a PR from `develop` into `main`.
3. Once it merges, tag the merge commit on `main` with `vMAJOR.MINOR.PATCH`.

The tag on `main` is the release. Only release-ready code reaches `main`.
Loading