From 89c77d1bcae428b10a012878a108664acc5c6fe5 Mon Sep 17 00:00:00 2001 From: Menny Even Danan Date: Thu, 15 Oct 2026 21:28:41 +0000 Subject: [PATCH] [LLM] Add AGENTS.md operational contract and agent guide Introduce AGENTS.md in the root directory defining project verification gates, commit message standards, testing guidelines, inclusive naming conventions, and architecture invariants. --- AGENTS.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..cc270e7 --- /dev/null +++ b/AGENTS.md @@ -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 --head `). +- **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`.