Skip to content

docs: add contributor and agent guides - #29

Merged
aj3sh merged 2 commits into
mainfrom
docs/agents-guide
Sep 11, 2026
Merged

aj3sh merged 2 commits into
mainfrom
docs/agents-guide

Conversation

@sugat009

Copy link
Copy Markdown
Contributor

Two commits on one branch: test: add upstream parity tests and lint guardrails and docs: add contributor and agent guides. They are separable, but the docs name clippy.toml and tests/upstream_parity.rs directly, so they only read correctly together.

Merging with rebase rather than squash keeps both messages on main, which is what release-please reads to build the changelog. A squash collapses them into one entry.

Tests and guardrails (c05ab0b)

  • tests/upstream_parity.rs: ports all 31 rows of LINTER_FIXTURE_PARAMS from commitlint 2.0.0, in upstream order, with the same three columns. Only the pass/fail column is asserted, because cocox has no per-field validator yet; the error strings are listed verbatim so the second assertion is a small diff once it lands. fixture_table_has_all_upstream_rows pins the count at 31, so a dropped row fails instead of quietly shrinking coverage.
  • tests/crlf_parity.rs: pins today's CRLF behavior on all three input paths that read from git or disk (crlf_commit_is_rejected_via_hash, crlf_commit_is_rejected_via_from_hash, crlf_message_file_is_rejected). The module header records why this is a divergence and not a contract: Python text mode rewrites \r\n before linting, so upstream accepts these. Normalization belongs in the readers only, since upstream does not normalize a message passed as an argument.
  • tests/message_coverage.rs: a ratchet, not a snapshot. src/messages.rs holds only the two verdict lines today and both are exempt, so the test passes with nothing to check. It fails, and names the message, the first time a per-field error is added without an assertion in tests/cli.rs.
  • clippy.toml: denies str::len and String::len via disallowed_methods, because Python len() counts code points and Rust len() counts UTF-8 bytes. [lints.clippy] disallowed_methods = "deny" in Cargo.toml makes a plain cargo clippy fail on its own, without -D warnings on the command line. str::lines is listed as a commented-out entry with the reason, since src/utils.rs:10 still calls it and fixing that changes behavior.
  • Cargo.toml: declares rust-version = "1.85", with a comment recording that it comes from edition 2024 rather than any language feature.
  • .gitignore: ignores .claude/settings.local.json, which until now was only covered by a personal global git config.

Guides (f9ba909)

  • CONTRIBUTING.md and .github/CODE_OF_CONDUCT.md follow the structure of the commitlint guides, so both projects in the organization read the same way, with the Rust toolchain in place of the Python one.
  • AGENTS.md is the single source of truth for agent guidance: the parity contract, ten Python-to-Rust porting traps that have each produced a real defect here, the testing rules, and the divergences from upstream measured so far. The two upstream behaviors that are defects rather than contracts are called out so nobody ports them.
  • CLAUDE.md only imports AGENTS.md and holds the two facts specific to Claude Code, so the guidance does not fork per tool.

The divergence list is what has been measured, not a complete audit. Each entry was reproduced against commitlint 2.0.0, and each is a separate follow-up pull request.

Verification

Run on f9ba909:

cargo fmt --all --check                                        clean
cargo clippy --all-targets --all-features -- -D warnings       clean
cargo test                                                     98 passed, 0 failed

98 = 38 lib, 43 cli, 11 git_helpers, 3 crlf_parity, 1 message_coverage, 2 upstream_parity. The branch also passes its own linter: cocox --from-hash c05ab0b --to-hash f9ba909 exits 0.

No behavior change to the binary. tests/cli.rs is touched only to reorder a use.

🤖 Generated with Claude Code

Ports all 31 rows of LINTER_FIXTURE_PARAMS from commitlint 2.0.0. Only
the pass or fail column is asserted, because cocox has no per-field
validator yet, and the error strings are recorded for when it does.

Adds tests pinning that a CRLF commit message is rejected on every input
path, and a ratchet that fails when a message gains no end-to-end test.

Declares rust-version 1.85, which comes from edition 2024 rather than any
language feature, and denies str::len and String::len, because Python
len() counts characters while Rust len() counts UTF-8 bytes.

Also ignores .claude/settings.local.json, which was covered only by a
personal global git config.
CONTRIBUTING.md and the code of conduct follow the structure used by
opensource-nepal/commitlint, so both projects in the organization read
the same way, with the Rust toolchain in place of the Python one.

AGENTS.md is the single source of truth for agent guidance. It records
the parity contract, ten Python to Rust porting traps that have each
produced a real defect, and the divergences from upstream measured so
far. CLAUDE.md only points at it, because not every contributor uses
Claude and the guidance should not fork.
@sugat009
sugat009 requested a review from aj3sh September 10, 2026 11:06
@sugat009 sugat009 self-assigned this Sep 10, 2026
@sugat009 sugat009 added the documentation Improvements or additions to documentation label Sep 10, 2026
@aj3sh
aj3sh merged commit 3b0c33b into main Sep 11, 2026
1 check passed
@aj3sh
aj3sh deleted the docs/agents-guide branch September 11, 2026 02:27
JustBipin added a commit to JustBipin/cocox that referenced this pull request Sep 13, 2026
- Add LintOptions struct (skip_detail, hide_input, strip_comments, max_header_length)
- lint_commit_message and run_validators take &LintOptions instead of reading global config
- Remove ConfigGuard, set_config, config(), update_config
- command.rs builds LintOptions from Cli and passes it explicitly
- OutputConfig remains global for console output only

Additional review fixes:
- Remove AGENTS.md from PR (arrives from main via opensource-nepal#29)
- Fix CONTRIBUTING.md rust-version to 1.88
- Fix clippy.toml stale item reference
- Remove COMMIT_HEADER_MAX_LENGTH assert from messages.rs
- Add 14 CLI tests pinning exact error message text
- Add ignored-message success line tests
- Add -q guards tests for --file, --hash, --from-hash
- Add CRLF/CR normalization tests
- Add CRLF header-length test
- Add ^ anchor regression test
- Fix max_header_length_string_fails_clap to assert message text
- Rewrite PR description with accurate test counts and behavior changes
sugat009 pushed a commit that referenced this pull request Sep 18, 2026
…l test suite (#28)

* feat: detailed error output, help strings, max-header-length, and full test suite

Implements feature parity with Python commitlint for #27 and #25.

- Display specific validation errors (type missing, scope empty, description
  issues, etc.) instead of just "Commit validation: failed!" (#27)
- Add help = "..." strings to every clap argument (#25)
- Add --max-header-length <N> CLI flag with positive integer validation
- Add Config (global LazyLock<Mutex>), Console (colored output), and
  Validators (simple + detailed regex patterns) modules
- Add AGENTS.md with architecture docs, parity checklist, and agent
  conventions
- Add 75+ integration tests and 43 unit tests covering all CLI paths,
  output flags, hash ranges, and max-header-length behavior
- Run cargo fmt on all files

Refs: #27, #25

* fix: description missing bug and header length character counting

- validate_description: use map_or instead of ? early return so missing
  description correctly returns DESCRIPTION_MISSING_ERROR
- validate_header_length: use chars().count() instead of len() to match
  upstream Python code-point counting (not UTF-8 bytes)
- Fix errors.is_empty() nitpick: always false after push, use return (false, errors)
- Add comments explaining ? early returns match upstream 'if group and ...' logic

Refs: review feedback on PR #28

* fix: type order, ignored messages output, quiet mode error suppression

- COMMIT_TYPES: move 'bump' to last position to match upstream Python order
- Ignored messages: print success line in single-message mode (parity with
  upstream which prints 'Commit validation: successful!' for ignored commits)
- Quiet mode: suppress file and git errors when -q is set (exit silently
  instead of printing anyhow error chain)

* fix: --max-header-length negative value handling

- Add allow_negative_numbers = true so clap passes -5 to the value_parser
  instead of treating it as a flag
- Rewrite positive_usize to parse as i64 first, then convert to usize,
  matching upstream error messages for both negative and zero values
- Remove redundant clap attributes: long = 'from-hash'/'to-hash' (derived
  from field names), action = ArgAction::SetTrue (default for bools)
- Drop unused ArgAction import

* docs: update README, AGENTS.md, and Cargo.toml rust-version

- README: update about text, help columns with all flags documented
- AGENTS.md: fix test counts (81 CLI + 60 unit), remove is_orphan
  (Rust-only detail), soften parity claims, remove architecture freeze,
  remove fixed divergence #5 (type order)
- Cargo.toml: bump rust-version to 1.88 (let chains require it)

* test: add comprehensive unit and CLI tests for all error messages

- Add rejects_missing_description to linter.rs (was deleted in original PR)
- Add 16 unit tests covering all 13 error messages plus multi-error cases
- Add 16 CLI end-to-end tests asserting per-field error output including
  'Found N error(s).' for N > 1
- Add help_flag_shows_descriptions_for_all_flags verifying all help strings
- Fix max_header_length_negative_fails_clap to assert error message text
- Add header_length_counts_chars_not_bytes for non-ASCII parity

* fix: normalize CRLF newlines in git and file readers

Upstream reads git output with subprocess.check_output(text=True) and
files with open(), both of which normalize \r\n and lone \r to \n.
cocox read raw bytes, so CRLF messages passed validation unchanged.

Add normalize_newlines() in utils.rs and call it from:
- get_commit_message_from_hash (git show output)
- get_commit_messages_from_hash_range (git log output)
- read_file (--file input)

CLI arguments are NOT normalized, matching upstream behavior.

Fixes known divergence #2 from AGENTS.md. All 158 tests pass.

* docs: remove fixed CRLF divergence from AGENTS.md

* refactor: LintOptions struct replaces global Config

- Add LintOptions struct (skip_detail, hide_input, strip_comments, max_header_length)
- lint_commit_message and run_validators take &LintOptions instead of reading global config
- Remove ConfigGuard, set_config, config(), update_config
- command.rs builds LintOptions from Cli and passes it explicitly
- OutputConfig remains global for console output only

Additional review fixes:
- Remove AGENTS.md from PR (arrives from main via #29)
- Fix CONTRIBUTING.md rust-version to 1.88
- Fix clippy.toml stale item reference
- Remove COMMIT_HEADER_MAX_LENGTH assert from messages.rs
- Add 14 CLI tests pinning exact error message text
- Add ignored-message success line tests
- Add -q guards tests for --file, --hash, --from-hash
- Add CRLF/CR normalization tests
- Add CRLF header-length test
- Add ^ anchor regression test
- Fix max_header_length_string_fails_clap to assert message text
- Rewrite PR description with accurate test counts and behavior changes

* feat: add verbose output matching upstream and assert error strings in parity test

- Add verbose lines to linter, validators, and git helpers matching upstream
  commitlint output (HeaderLengthValidator, PatternValidator, git commands)
- Thread &OutputConfig through lint_commit_message_with_errors and
  run_validators so verbose lines can be emitted from the lint path
- Fix failure text to match upstream format (': validation failed')
- upstream_parity.rs now asserts error strings, not just pass/fail
- Remove stale divergence #4 from AGENTS.md (bump already listed last)
- Fix upstream_parity.rs stale doc comment
- Update all unit and integration tests for new function signatures

* fix: address round 3 review — lower rust-version, fix empty message output, correct stale docs

- Restore AGENTS.md from main (remove from diff)
- Lower rust-version from 1.88 to 1.85, remove stale let-chain comment
- Update CONTRIBUTING.md minimum Rust version to 1.85
- Fix stale doc comment in upstream_parity.rs
- Print VALIDATION_FAILED on empty/whitespace/comment-only commit messages
- Add CLI test for comment-only file input
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants