Repository navigation
Conversation
Add tools/buf-plugin-ledger, a buf check plugin with three lint rules taken from docs/technical/contributing/protobuf.md and CLAUDE.md: - LEDGER_NO_RESERVED: no reserved numbers or names; - LEDGER_FIELD_NUMBERS_SEQUENTIAL: message fields are exactly 1..N; - LEDGER_ENUM_NUMBERS_SEQUENTIAL: enum values are exactly 0..N-1. The current tree has no violation. `just lint-proto` (scripts/lintproto) builds the plugin and runs buf lint; it is part of `just pre-commit`, so the required Dirty job runs it. Because buf.yaml now declares the plugin, checkprotocolversion builds it too through scripts/internal/bufplugin. agent-check-pr gains a proto-lint gate and now routes tools/* changes to the tooling gate: those directories are separate modules that the root module cannot race-test. Claude-Session: https://claude.ai/code/session_01HxBUjBS5Loz1nkQZVxW1Mf
| test-buf-plugin: | ||
| go -C tools/buf-plugin-ledger test ./... | ||
|
|
||
| # --- Operator (Kubernetes) --- |
There was a problem hiding this comment.
🟡 [minor] Run the new plugin tests with the race detector
The new test-buf-plugin recipe runs go test ./... without -race; the proto-lint branch in scripts/agent-check-pr likewise omits it. Because the plugin is a separate module, the root-module tooling race suite does not cover it. Thus the newly introduced required gates can pass despite a plugin race, contrary to the Formance race-enabled test baseline.
Suggestion: Add -race to test-buf-plugin and to the plugin test invocation in scripts/agent-check-pr, preferably reusing the same recipe for both paths.
| func firstMissing(numbers []int, start int) (int, bool) { | ||
| sorted := slices.Sorted(slices.Values(numbers)) | ||
| for i, number := range sorted { | ||
| if number != start+i { |
There was a problem hiding this comment.
🟡 [minor] Report an actually missing number for aliased enums
For a valid proto enum with numbers [0, 0, 1] and allow_alias enabled, firstMissing returns 1 at the duplicate, although 1 exists. checkEnumNumbersSequential consequently tells contributors that number 1 is missing; the actual missing number is 2. The same problem occurs with negative enum values. Rejection is correct, but the actionable diagnostic contradicts the descriptor.
Suggestion: Find the first absent number in the expected range using a membership set (or skip duplicates while scanning), and add tests for [0, 0, 1] and negative values.
With the freeze,
LEDGER_FIELD_NUMBERS_SEQUENTIALandLEDGER_NO_RESERVEDstay consistent: service-reachable types only gain fields (enforced by #2299), and persisted or Raft-only messages keep the remove-and-realign rule.Summary
The "no
reserved" and "sequential field numbers" rules fromCLAUDE.mdanddocs/technical/contributing/protobuf.mdwere enforced only by review. ThisPR adds
tools/buf-plugin-ledger, a buf check pluginwritten in Go with
buf.build/go/bufplugin, that enforces them throughbuf lint.LEDGER_NO_RESERVEDreservednumbers or names in messages or enumsLEDGER_FIELD_NUMBERS_SEQUENTIAL1..N, oneof members included; map entries exemptLEDGER_ENUM_NUMBERS_SEQUENTIAL0..N-1, no aliasesThe current
misc/prototree has zero violations, so no baseline or ignore list is needed. Only the importedgoogle/protobuf/descriptor.protohas reserved entries or gaps, and imports are not checked.Wiring
just lint-proto→go run ./scripts/lintproto: builds the plugin into a temporary directory and runsbuf lint misc/proto.just pre-commitnow includestest-buf-pluginandlint-proto. The requiredDirtyCI job runsjust pre-commit, so these rules block merges without a ruleset change.misc/proto/buf.yamldeclares the plugin, and buf then needs it on PATH forbreakingtoo.scripts/internal/bufpluginbuilds it for bothlintprotoandcheckprotocolversion.agent-check-pr: newproto-lintgate formisc/proto/**andtools/buf-plugin-ledger/**.agent-check-prfix:tools/*.gochanges were selected as root-moduletest-race:./tools/...packages, which cannot work because eachtools/*directory is its own Go module. They now go to the tooling gate; a selector regression case covers it.bufplugindependency lives only intools/buf-plugin-ledger/go.mod; the rootgo.modis unchanged.Example output
With a
reserved 99;and a renumbered field injected intosignature.proto:Validation
bash scripts/agent-check: PASSgo -C tools/buf-plugin-ledger test -race ./...: PASS (checktestfixtures for valid and invalid files, plusSpecTest)go test -race ./scripts/agentcheckpr ./scripts/checkprotocolversion: PASSgolangci-linton./scripts/...andtools/buf-plugin-ledger: 0 issuesjust lint-proto: PASS on the current tree; FAIL with the injected violations abovejust tidy: no drifthttps://claude.ai/code/session_01HxBUjBS5Loz1nkQZVxW1Mf