--- ## inclusion: always # Git Conventions This project uses Git for version control. Follow these conventions for all commits and branches. ## Conventional Commits All commit messages must follow the Conventional Commits specification (https://www.conventionalcommits.org/). ### Format ``` [optional scope]: [optional body] [optional footer(s)] ``` ### Types | Type | Purpose | |------------|---------------------------------------------------------| | `feat` | A new feature or capability | | `fix` | A bug fix | | `refactor` | Code change that neither fixes a bug nor adds a feature | | `test` | Adding or updating tests | | `docs` | Documentation changes | | `chore` | Build process, tooling, or auxiliary changes | | `ci` | CI/CD configuration changes | | `perf` | Performance improvement | | `style` | Code style changes (formatting, whitespace) | ### Scopes Use a scope to indicate the area affected. Common scopes for this project: * `lexer` — lexer recognition changes * `parser` — Menhir grammar changes * `ast` — AST type definitions * `normalize` — normalization phase * `inline` — inline parsing * `prescan` — pre-scan configuration discovery * `diagnostic` — diagnostic reporting * `test` — test infrastructure (not individual test additions) Omit the scope when the change is cross-cutting or does not fit a single module. ### Rules * Use the imperative mood in the description: "add heading parser", not "added heading parser". * Keep the first line under 72 characters. * Do not end the description with a period. * Use the body to explain *what* and *why*, not *how*. * Use `BREAKING CHANGE:` in the footer when a change breaks the public API. * A `!` after the type/scope indicates a breaking change: `feat(ast)!: restructure heading representation`. ### Examples ``` feat(lexer): add keyword line classification Recognize lines matching #+KEY: VALUE as Keyword tokens. ``` ``` fix(normalize): attach affiliated keywords across blank lines Previously affiliated keywords separated by a blank line from their target element were left as standalone nodes. Now they correctly remain unattached per the Org spec. ``` ``` test: add malformed block recovery fixtures ``` ``` refactor(parser): extract list item grouping into helper function ``` ## Conventional Branches ### Branch naming format ``` / ``` Use kebab-case for the description. Keep it concise but descriptive. ### Branch types | Prefix | Purpose | |-------------|----------------------------------------------------| | `feat/` | Feature development | | `fix/` | Bug fixes | | `refactor/` | Refactoring without behavior change | | `test/` | Test additions or infrastructure | | `docs/` | Documentation work | | `chore/` | Tooling, build, or maintenance | ### Rules * Branch from `master` unless working on a dependent feature. * One logical change per branch. * Do not reuse branch names after merging. * Delete branches after they are merged. ### Examples ``` feat/heading-parser fix/list-indentation-edge-case refactor/inline-lexer-modes test/block-recovery-fixtures docs/update-support-matrix chore/upgrade-menhir ``` ## General Git practices * Keep commits atomic: one logical change per commit. * Commit after each individual feature is implemented. * Do not mix formatting changes with behavioral changes in the same commit. * Prefer rebase workflows to keep linear history on `master`. * Squash fixup commits before merging to `master`. * Do not commit generated files (build artifacts, `.merlin`, etc.). * Do not commit editor-specific files unless shared tooling requires them. * Always amend the latest unpushed commit when the requested modifications concern files already modified in that commit. Otherwise, create a new commit. ## Pre-commit checks Before every commit, run the following in order: 1. `opam exec -- dune fmt` — format all OCaml source files with ocamlformat. 2. `opam exec -- dune build` — verify compilation succeeds. 3. `opam exec -- dune runtest` — verify all tests pass. Do not commit if any of these steps fail. ## Authorship When an AI agent produces code, authorship must be correctly attributed in the commit metadata. * **Author**: the AI agent that produced the changes. Use the format: ``` Agent-Name (effort-level) ``` Where `effort-level` reflects the reasoning or effort mode the agent was operating under when it produced the changes (e.g. `high`, `medium`, `standard`, or a model-specific indicator). The email domain identifies the company developing the agent. Example: `Kiro (high) ` * **Committer**: always the human who reviewed and accepted the changes. Use the human's normal Git identity. Set authorship with: ```sh git commit --author="Kiro (high) " -m "..." ``` This ensures `git log` and `git blame` clearly distinguish AI-generated code from human-written code, while the committer field records who took responsibility for merging it.