Skip to content
Merged
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
70 changes: 70 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Calque — Agent Operational Contract

## Verification Gates (Non-Negotiable)
Before proposing, committing, or opening a PR for any change, the agent MUST run and verify 0 errors on all three gates:
1. `bazelisk run //:format.check` (Auto-fix with `bazelisk run //:format` if needed)
2. `bazelisk build --config=lint //...` (Detekt + Buildifier via custom Bazel aspect)
3. `bazelisk test //...` (Pure JVM unit tests)

## Git Commit Guidelines
Before creating a commit, always:
1. Run formatters and linters: `bazelisk run //:format` and verify with `bazelisk run //:format.check` and `bazelisk build --config=lint //...`.
2. Run and verify that all relevant unit tests pass (`bazelisk test //...`).

### Commit Message
When creating a commit message, follow these guidelines:
- **Title:** Use a concise title. Prefix the title with `[LLM]` (e.g., `[LLM] Implement algorithmic cognate detector with unit tests`).
- **Description:** The description should include a short description of the issue (bug, feature-request, crash, chore, etc.) and a short description of the solution.
- **No AI attribution:** Do not add AI agent attribution or signatures to commit messages (e.g., "By: Claude", "Generated by AI", "Antigravity", etc.).

## Tests
- **When asked to suggest tests for a function or file:**
- Do not implement anything or suggest how to implement.
- Look only at the code and suggest tests based on functionality and error cases.
- Identify the "happy path" (core functionality) cases and mark them as such in your suggestions.
- Identify the error cases and mark them as such in your suggestions. Estimate importance based on likelihood.
- Identify the edge cases and mark them as such in your suggestions. Estimate importance based on likelihood.
- **When implementing tests:**
- For Kotlin, the test file name follows the pattern `[OriginalFileName]Test.kt` (e.g., `CognateDetectorTest.kt`).
- For Java, the test file name follows the pattern `[OriginalFileName]Test.java`.
- Prefer creating fakes over mocks or patches. But, if it is simpler to patch or mock, do that.
- Core logic under `core/*` must test against standard JVM targets (`kt_jvm_test`) without Android dependencies.
- **Running Tests:**
- Run all tests in the workspace: `bazelisk test //...`
- Run tests for a specific target: `bazelisk test //core/linguistics:cognate_detector_test`

## Naming
Use inclusive language when creating variables, functions, class names, stubs, test fixtures, etc.:
- Do not use "dummy", instead use "fake", "mock", "noop", etc.
- Do not use "blacklist", instead use "disallow-list".
- Do not use "whitelist", instead use "allow-list".
- Stay away from: "master", "slave", "insane", "dumb", etc.
- Use gender-neutral pronouns.

## Prohibitions ("NEVER")
- **NEVER** use Gradle (`gradle`, `./gradlew`, `build.gradle.kts`, etc.). Calque is 100% Bazel managed with `bazelisk`.
- **NEVER** import `android.*` inside `core/*`. Core packages (`//core/linguistics`, `//core/data`, `//core/domain`) are pure JVM to ensure ultra-fast testing and clean modularity. Android dependencies belong exclusively under `//app/*`.
- **NEVER** re-introduce `ktlint` or its rules. Code formatting is owned solely by `ktfmt` (`--kotlinlang-style`, 120 chars) and static analysis is owned by `detekt` (`detekt.yml`).
- **NEVER** commit undocumented or untested linguistic/data algorithms. Every parser, analyzer, detector, or converter must have corresponding unit tests.
- **NEVER** push over HTTPS token if workflow scope fails; use SSH (`git@github.com:AnySoftKeyboard/calque.git`).
- **NEVER** create large, multi-concept PRs. Break down features into small, scoped, reviewable steps. Use stacked PRs (`gh pr create --base <parent> --head <feature>`).
- **NEVER** forget to register every created or updated PR with the MCP `link_pull_request` tool (including all layers in a stack).

## Directory Roles & Architecture
- `core/linguistics/`: Linguistic algorithms, cognate detection, morphology, phonetic distance, dictionary tokenization.
- `core/data/`: Database models, SQLite / binary dictionary stores, Trie indexing, file ingestion.
- `core/domain/`: End-to-end suggestion engine, scoring pipelines, bilingual query dispatcher.
- `app/`: Android InputMethodService, IME keyboards, configuration UI, Android lifecycle hooks.
- `tools/`: Bazel custom aspects (`detekt.bzl`), formatting configs (`ktfmt`, `buildifier`), CI workflows.
- `docs/`: All architecture and domain documentation (e.g. `docs/INGESTION.md`, `docs/ARCHITECTURE.md`).

## Standard Workflow for New Features
1. **Branch**: Create a feature branch off the appropriate base branch.
2. **Implement**: Write code conforming to Kotlin idioms and project constraints (avoid magic numbers, keep functions focused).
3. **Test**: Write comprehensive JUnit tests for all logic following the naming conventions.
4. **Format & Lint**:
- `bazelisk run //:format`
- `bazelisk run //:format.check`
- `bazelisk build --config=lint //...`
- `bazelisk test //...`
5. **PR & Link**: Commit (following commit message guidelines with `[LLM]` prefix and no attribution), push to origin via SSH, open PR via `gh pr create`, and immediately link via `link_pull_request`.
Loading