feat: add comprehensive Go repository support with monorepo detection#412
feat: add comprehensive Go repository support with monorepo detection#412natifridman wants to merge 3 commits intoambient-code:mainfrom
Conversation
Add Go-specific assessment logic to 6 assessors that previously returned
not_applicable or used wrong language paths for Go repos. Includes monorepo
support for projects with go.mod in subdirectories (e.g., multi-service repos).
Assessors extended:
- TestExecutionAssessor: *_test.go detection, go test/coverage/race scoring
- TypeAnnotationsAssessor: auto-pass for static typing, interface{}/any penalty
- StandardLayoutAssessor: Go layout detection (go.mod, cmd/, internal/, pkg/)
- CyclomaticComplexityAssessor: gocyclo + golangci-lint cyclop detection
- StructuredLoggingAssessor: zap/logrus/zerolog/slog in go.mod and source
- InlineDocumentationAssessor: godoc comment coverage on exported symbols
Infrastructure:
- BaseAssessor._primary_language(): dispatches by file count for multi-lang repos
- BaseAssessor._find_go_module_roots(): finds go.mod at root and in subdirs
- Go.arsrc: directory exclusion list for Go projects
- Bootstrap templates updated to Go 1.23/1.24, golangci-lint-action v6, govulncheck
- go vet added to CI typecheck patterns, enhanced gitignore patterns
Tested against opendatahub-io/models-as-a-service (Go monorepo): score improved
from 40.9 to 59.6 (+18.7 points) with 6 previously-failing assessors now passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When file counts between two languages are within 30% of each other, use root-level project manifests (go.mod, pyproject.toml, package.json) as a tiebreaker to determine the primary language. This fixes repos like Go Kubernetes operators with Python SDK subdirectories, where Python may have slightly more files but Go owns the project root. Tested against opendatahub-io/kserve (524 Go vs 597 Python files): Go assessors now correctly fire instead of Python ones (+8.6 points). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Enterprise Run ID: 📒 Files selected for processing (7)
Warning
|
| Layer / File(s) | Summary |
|---|---|
Language Detection & Selection src/agentready/assessors/base.py |
_primary_language() selects the primary language from candidates using repository.languages counts with root-manifest tiebreaker. _find_go_module_roots() locates Go module directories by scanning for go.mod. _LANG_ROOT_MANIFESTS maps language names to their characteristic root files. |
Type Safety Assessment src/agentready/assessors/code_quality.py (TypeAnnotationsAssessor) |
assess() dispatches by primary language to Python or new _assess_go_types(). Go scoring counts func definitions and penalizes interface{}/any usage (excluding _test.go), returning pass/fail with remediation. |
Complexity Assessment src/agentready/assessors/code_quality.py (CyclomaticComplexityAssessor) |
is_applicable() adds Go support. assess() dispatches to _assess_go_complexity() which prefers gocyclo output or searches module roots for golangci-lint configs enabling complexity linters; includes Go-specific remediation. |
Logging Assessment src/agentready/assessors/code_quality.py (StructuredLoggingAssessor) |
assess() dispatches by primary language. _assess_go_logging() detects structured logging via go.mod dependency scan (zap, logrus, zerolog) and stdlib log/slog usage, returning pass/fail with Go remediation. |
Code Smells Detection src/agentready/assessors/code_quality.py (CodeSmellsAssessor) |
_has_golangci_lint() expands to recognize .golangci.json and searches module roots via _find_go_module_roots() for config files. |
Layout Validation src/agentready/assessors/structure.py |
assess() routes Go repositories to new _assess_go_layout(). Validates go.mod presence, scans module roots for standard directories (cmd/, internal/, pkg//api/), detects entrypoints and tests (via git ls-files with fallback), and generates Go-targeted remediation including go mod init commands. |
Documentation Coverage src/agentready/assessors/documentation.py |
is_applicable() extends to Go. assess() dispatches between Python docstrings and new _assess_go_godoc(). Godoc assessment tracks exported symbols (func/type/var/const) with comment coverage vs. 80% threshold, detects doc.go package docs, excludes test files and private symbols. |
Testing Assessment src/agentready/assessors/testing.py |
is_applicable() detects Go via _has_go_test_files() (finds *_test.go). assess() dispatches coverage by primary language. _assess_go_coverage() evaluates test presence, coverage flags, and -race detection from build files/CI workflows; includes Go remediation. |
Dependency Pinning src/agentready/assessors/stub_assessors.py |
DependencyPinningAssessor now globs for */go.sum in subdirectories when root go.sum is missing, supporting monorepos. |
Gitignore Patterns src/agentready/assessors/stub_assessors.py |
Expected patterns extended with Go-specific entries: bin/, cover.out, coverage.txt. |
Go Project Configuration src/agentready/data/Go.arsrc |
Directory exclusion configuration for Go layout detection: vendor, testdata, docs, scripts, build output, CI, and hidden directories. |
Bootstrap Workflow Templates src/agentready/templates/bootstrap/go/workflows/tests.yml.j2 |
Go version matrix updated from 1.21, 1.22 to 1.23, 1.24. golangci-lint action bumped from v3 to v6. Coverage condition keyed to 1.24. |
Security Workflow Template src/agentready/templates/bootstrap/go/workflows/security.yml.j2 |
Go version updated to 1.24. Added govulncheck ./... step for vulnerability scanning. |
Comprehensive Test Suite tests/unit/test_assessors_go.py |
Helper functions _make_go_repo() and _git_add() for Go repository setup. Test classes for each assessor (TestTestExecutionAssessorGo, TestTypeAnnotationsAssessorGo, TestStandardLayoutAssessorGo, TestCyclomaticComplexityAssessorGo, TestStructuredLoggingAssessorGo, TestInlineDocumentationAssessorGo, TestCodeSmellsAssessorGo, TestCIQualityGatesAssessorGo, TestGoMonorepoSupport) covering applicability, scoring, remediation, monorepo support, and integration scenarios. |
Test Expectations tests/unit/test_bootstrap_templates.py |
Updated Go template test expectations for versions 1.23, 1.24. |
Sequence Diagram
sequenceDiagram
participant Caller
participant Assessor
participant LanguageSelector as Language<br/>Selector
participant GoLogic as Go-Specific<br/>Logic
participant Repository
Caller->>Assessor: assess(repository)
Assessor->>Repository: repository.languages
Repository-->>Assessor: {'Python', 'Go', ...}
Assessor->>LanguageSelector: _primary_language(repository, candidates)
alt Has Root Manifest Tie-breaker
LanguageSelector->>Repository: repository.path
Repository-->>LanguageSelector: /path/to/repo
LanguageSelector->>LanguageSelector: Check go.mod, setup.py existence
end
LanguageSelector-->>Assessor: 'Go'
Assessor->>GoLogic: _assess_go_*(repository)
alt Go Module Roots
GoLogic->>Repository: _find_go_module_roots()
Repository-->>GoLogic: [list of go.mod directories]
end
GoLogic->>GoLogic: Analyze Go sources, configs
GoLogic-->>Assessor: Finding{score, evidence, remediation}
Assessor-->>Caller: Finding
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~50 minutes
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title check | ✅ Passed | The title 'feat: add comprehensive Go repository support with monorepo detection' accurately and specifically summarizes the main changes in the pull request, which adds Go assessment logic and monorepo support across multiple assessors. |
| Description check | ✅ Passed | The description is well-structured, comprehensive, and directly related to the changeset. It clearly outlines the assessors extended, infrastructure changes, and provides real-world testing results demonstrating the impact of the changes. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
| Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
Tip
💬 Introducing Slack Agent: The best way for teams to turn conversations into code.
Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
- Generate code and open pull requests
- Plan features and break down work
- Investigate incidents and troubleshoot customer tickets together
- Automate recurring tasks and respond to alerts with triggers
- Summarize progress and report instantly
Built for teams:
- Shared memory across your entire org—no repeating context
- Per-thread sandboxes to safely plan and execute work
- Governance built-in—scoped access, auditability, and budget controls
One agent for your entire SDLC. Right inside Slack.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
📈 Test Coverage Report
Coverage calculated from unit tests only |
There was a problem hiding this comment.
Actionable comments posted: 10
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/agentready/assessors/base.py`:
- Around line 125-137: _find_go_module_roots currently only checks one directory
level; change it to search recursively (e.g., use rglob or equivalent) for all
go.mod files under repository.path, skip any matches that live inside vendor
directories, and collect the parent directories as module roots; also keep the
repository root if it contains go.mod and dedupe the resulting list (use
Path.parent to get roots and filter out duplicates).
- Around line 109-123: _primary_language() is non-deterministic because it
iterates a set of candidate languages; make the tie-break deterministic by
ordering contenders before checking manifests: build a sorted list of (lang,
count) from lang_counts (sort by descending count then by language name) and
iterate that list (skip top_lang), apply the existing 0.7 closeness check, then
check manifests using self._LANG_ROOT_MANIFESTS for the contender and for
top_lang in a fixed order; return the chosen language accordingly so repeated
runs yield the same result.
In `@src/agentready/assessors/code_quality.py`:
- Around line 554-575: The fallback that returns a Passing Finding when any
.golangci.* file exists is unsafe; update the loop that iterates search_dirs and
config_name to actually parse the matched config file and verify complexity
linters (gocyclo, cyclop, gocognit) are enabled—specifically, read the config
contents, check for disable/disable-all entries and the linters/linters-settings
sections to ensure those linters are not explicitly disabled (or are present in
enabled linters); only then return the Finding with measured_value
"golangci-lint configured". If parsing fails or the file explicitly disables
those linters, do not return the pass Finding (instead return no Finding or a
neutral/failed Finding); keep references to repository.path, search_dirs,
config_name and the Finding construction (attribute=self.attribute) when
implementing this change.
In `@src/agentready/assessors/documentation.py`:
- Around line 1224-1254: The exported-symbol detection and doc-comment check are
wrong: update exported_pattern to also match exported methods with receivers
(e.g., change exported_pattern to allow an optional receiver group before the
name so it matches lines like "func (s *Server) Start()") and adjust the
documentation check so it only counts a preceding comment when it actually
begins with the symbol name (use prev_line.startswith(f"// {symbol_name}")
rather than accepting any "//" line); also handle preceding block comments (/*
... */) by examining the last non-empty previous token block and ensuring its
first line starts with the symbol name before incrementing documented_exported
(references: exported_pattern, symbol_name, documented_exported, total_exported,
the loop over go_files/lines).
In `@src/agentready/assessors/structure.py`:
- Around line 124-125: The current check "if 'Go' in repository.languages"
wrongly triggers Go layout when any Go file exists; change it to only choose the
Go assessor when Go is the repository's primary language (or otherwise wins the
tiebreaker). Update the conditional around the call to
self._assess_go_layout(repository) to inspect the repository's primary-language
field or tiebreaker result (e.g., repository.primary_language or a helper that
returns the dominant language) instead of membership in repository.languages so
mixed repos aren't misclassified.
In `@src/agentready/assessors/stub_assessors.py`:
- Around line 67-71: The check for Go monorepo lockfiles only searches one level
deep (repository.path.glob("*/go.sum")), missing nested modules like
services/auth/go.sum; update the search to recursively find go.sum files (use
repository.path.rglob("go.sum") or repository.path.glob("**/go.sum")) and append
their relative paths to found_strict (keep the existing break logic if you only
need the first hit), referencing the found_strict list and the
repository.path.glob usage in stub_assessors.py.
In `@src/agentready/assessors/testing.py`:
- Around line 414-421: The current scan only looks one level deep for module
build files; update the search to recursively scan the repo for nested
build/task files by replacing the one-level glob used when appending to
files_to_check (currently repository.path.glob("*/Makefile")) with a recursive
search (repository.path.rglob or glob with "**/Makefile"), and also add
recursive patterns for other common build/task filenames (e.g.,
Taskfile.yml/Taskfile.yaml and deeper Makefiles) so files_to_check collects
matches like services/**/Makefile and **/Taskfile.{yml,yaml}; keep using the
same files_to_check list and ci_dir logic for .github workflows but apply rglob
patterns for completeness.
- Around line 369-374: The coverage detection currently only matches
"-coverprofile" and "-covermode" so plain "go test -cover" is missed; update the
regex used to set has_coverage in testing.py (the expression that assigns
has_coverage from re.search) to also recognize plain "-cover" (and variants like
"-cover=", "-cover ./...") by including "-cover" as an alternative (e.g., make
the pattern match "-cover" or "-coverprofile" or "-covermode" with appropriate
word-boundary/optional suffix handling) so the block that increments score and
appends evidence correctly flags repos that use "go test -cover".
In `@src/agentready/templates/bootstrap/go/workflows/security.yml.j2`:
- Around line 24-27: Replace the unpinned installation of govulncheck in the
workflow step that runs "go install golang.org/x/vuln/cmd/govulncheck@latest"
with a pinned version; update the install command to use a specific semantic
version (e.g., `@vX.Y.Z`) or a template variable so CI uses a fixed govulncheck
release, and ensure any documentation or template variables (the govulncheck
install line and the "Run govulncheck" step) are adjusted accordingly to avoid
using `@latest`.
In `@src/agentready/templates/bootstrap/go/workflows/tests.yml.j2`:
- Around line 32-34: The workflow currently sets golangci-lint action version to
"latest" (uses: golangci/golangci-lint-action@v6 with version: latest); change
the version key to a pinned, specific release (for example a concrete
semver/tag) so CI is deterministic, e.g. replace the version: latest entry with
a fixed version string and optionally add a comment or dependabot config to
update it periodically; keep the uses: golangci/golangci-lint-action@v6 line
as-is but ensure the version input is a specific pinned tag rather than
"latest".
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 824f50a2-7a19-4949-a344-0d1311be59fe
📒 Files selected for processing (11)
src/agentready/assessors/base.pysrc/agentready/assessors/code_quality.pysrc/agentready/assessors/documentation.pysrc/agentready/assessors/structure.pysrc/agentready/assessors/stub_assessors.pysrc/agentready/assessors/testing.pysrc/agentready/data/Go.arsrcsrc/agentready/templates/bootstrap/go/workflows/security.yml.j2src/agentready/templates/bootstrap/go/workflows/tests.yml.j2tests/unit/test_assessors_go.pytests/unit/test_bootstrap_templates.py
| exported_pattern = re.compile(r"^(?:func|type|var|const)\s+([A-Z]\w*)") | ||
|
|
||
| for file_path in go_files: | ||
| full_path = repository.path / file_path | ||
| if full_path.name == "doc.go": | ||
| has_doc_go = True | ||
|
|
||
| try: | ||
| lines = full_path.read_text(encoding="utf-8").splitlines() | ||
| except (OSError, UnicodeDecodeError): | ||
| continue | ||
|
|
||
| for i, line in enumerate(lines): | ||
| match = exported_pattern.match(line.strip()) | ||
| if not match: | ||
| continue | ||
|
|
||
| total_exported += 1 | ||
| symbol_name = match.group(1) | ||
|
|
||
| # Check if previous non-empty line is a comment starting with symbol name | ||
| if i > 0: | ||
| prev_idx = i - 1 | ||
| while prev_idx >= 0 and not lines[prev_idx].strip(): | ||
| prev_idx -= 1 | ||
| if prev_idx >= 0: | ||
| prev_line = lines[prev_idx].strip() | ||
| if prev_line.startswith( | ||
| f"// {symbol_name}" | ||
| ) or prev_line.startswith("//"): | ||
| documented_exported += 1 |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In Go's documentation conventions, do exported methods require doc comments, and should doc comments on exported declarations start with the declaration name?
💡 Result:
Yes—Go’s documentation conventions say that every exported (capitalized) name should have a doc comment, and doc comments for types (and similarly for funcs/methods) should start with the declared symbol’s name. Go doc comments are defined as the comments that appear immediately before top-level package, const, func, type, and var declarations, with no intervening blank line. The documentation rules further state: “Every exported (capitalized) name should have a doc comment.”[1] It also says that “These rules all apply both to plain functions and to methods.”[1] For the “should start with the declaration name” part: the Go docs explain that, for types, “doc comments for types start with naming the declared symbol” and give examples; this same “rules all apply … to plain functions and to methods” guidance indicates the same convention applies to exported functions/methods as well.[1] So, in practice: exported methods (which are part of the doc-comment rules for funcs/methods) should have doc comments, and those doc comments should begin with the method name (the declared symbol), typically as the first sentence.
Citations:
Godoc coverage is undercounting methods and overcounting unrelated comments.
The regex pattern fails to capture exported methods because it doesn't account for receivers (e.g., func (s *Server) Start() won't match). Additionally, the documentation check accepts any preceding // line, not just those starting with the symbol name, inflating coverage. Go's official documentation requires every exported name—including methods—to have a doc comment starting with the declared symbol's name, so the assessment is both under- and over-inclusive.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/agentready/assessors/documentation.py` around lines 1224 - 1254, The
exported-symbol detection and doc-comment check are wrong: update
exported_pattern to also match exported methods with receivers (e.g., change
exported_pattern to allow an optional receiver group before the name so it
matches lines like "func (s *Server) Start()") and adjust the documentation
check so it only counts a preceding comment when it actually begins with the
symbol name (use prev_line.startswith(f"// {symbol_name}") rather than accepting
any "//" line); also handle preceding block comments (/* ... */) by examining
the last non-empty previous token block and ensuring its first line starts with
the symbol name before incrementing documented_exported (references:
exported_pattern, symbol_name, documented_exported, total_exported, the loop
over go_files/lines).
| uses: golangci/golangci-lint-action@v6 | ||
| with: | ||
| version: latest |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
What is the current stable golangci-lint release recommended for golangci/golangci-lint-action@v6 pinning in GitHub Actions workflows?
💡 Result:
The current stable golangci-lint release is v2.12.2, released on 2026-05-06.[1][2][3] For pinning in GitHub Actions workflows using golangci/golangci-lint-action@v6, the official documentation and examples recommend specifying a particular version like version: v1.60 or version: latest (which installs the latest stable).[4][5][6] While "latest" is shown in examples, for reproducible CI as emphasized in the official docs, pin to the current stable v2.12.2.[7] Note that v6 of the action supports golangci-lint v1 versions based on compatibility notes (e.g., v2.0.0+ works with >=v1.28.3), but given no explicit restriction to v1 and examples using high v1.x, it likely supports v2.x; however, for safety with v6 pinning, consider upgrading to v7+ if using v2.x is needed, as v7 explicitly supports v2 only.[8][9]
Citations:
- 1: https://github.com/golangci/golangci-lint/releases
- 2: https://golangci-lint.run/docs/product/changelog/
- 3: https://github.com/golangci/golangci-lint
- 4: https://github.com/golangci/golangci-lint-action/tree/v6.0.0
- 5: https://github.com/golangci/golangci-lint-action/tree/v6.5.0
- 6: https://github.com/golangci/golangci-lint-action/blob/v6.0.0/README.md
- 7: https://golangci-lint.run/docs/welcome/install/ci/
- 8: https://github.com/golangci/golangci-lint-action/releases
- 9: golangci/golangci-lint-action@v6.5.0...v7.0.0
Pin golangci-lint to a fixed version instead of latest.
Using version: latest makes generated CI nondeterministic and can cause unexpected build failures when upstream releases change behavior. Pinning to a specific version ensures reproducible builds across environments.
Proposed fix
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v6
with:
- version: latest
+ version: v1.60.3📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| uses: golangci/golangci-lint-action@v6 | |
| with: | |
| version: latest | |
| uses: golangci/golangci-lint-action@v6 | |
| with: | |
| version: v1.60.3 |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/agentready/templates/bootstrap/go/workflows/tests.yml.j2` around lines 32
- 34, The workflow currently sets golangci-lint action version to "latest"
(uses: golangci/golangci-lint-action@v6 with version: latest); change the
version key to a pinned, specific release (for example a concrete semver/tag) so
CI is deterministic, e.g. replace the version: latest entry with a fixed version
string and optionally add a comment or dependabot config to update it
periodically; keep the uses: golangci/golangci-lint-action@v6 line as-is but
ensure the version input is a specific pinned tag rather than "latest".
Fixes 9 of 10 CodeRabbit review findings: 1. _primary_language(): deterministic tiebreaker — only returns a winner when exactly one language has a root manifest match 2. _find_go_module_roots(): use rglob for recursive search, exclude vendor/testdata, deduplicate and sort results 3. CyclomaticComplexityAssessor: remove unsafe fallback that assumed golangci-lint default linters without parsing config 4. InlineDocumentationAssessor: fix godoc pattern to capture exported methods with receivers (func (s *Server) Start()); require doc comments to start with "// SymbolName" per Go convention 5. StandardLayoutAssessor: use _primary_language() dispatch instead of bare "Go" in repository.languages check 6. DependencyPinningAssessor: use rglob for go.sum search with vendor exclusion, find all matches (not just first) 7. TestExecutionAssessor: coverage regex now matches plain -cover flag in addition to -coverprofile/-covermode 8. TestExecutionAssessor: use _find_go_module_roots() for build file scanning instead of one-level glob 9. Bootstrap template: pin govulncheck to v1.3.0 instead of @latest Skipped ambient-code#10 (pin golangci-lint version: latest): intentional for bootstrap templates — golangci-lint-action@v6 documents this pattern. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
not_applicableor used wrong language paths for Go reposgo.modin subdirectories (e.g., multi-service repos)Assessors extended
*_test.godetection,go test/coverage/race scoring, subdirectory Makefile scanninginterface{}/anyoveruse penaltygo.mod,cmd/,internal/,pkg/) with monorepo aggregationgocyclotool + golangci-lintcyclop/gocycloconfig detection in subdirsgo.modfilesdoc.godetectionInfrastructure
BaseAssessor._primary_language(): dispatches by file count with root manifest tiebreaker for mixed-language reposBaseAssessor._find_go_module_roots(): findsgo.modat root and in one-level subdirectoriesGo.arsrc: directory exclusion list for Go project layout detectiongovulncheckgo vetadded to CI typecheck patterns, enhanced gitignore patterns_has_golangci_lint()searches module root dirs for.golangci.toml/.golangci.jsonvariantsReal-world testing
Test plan
tests/unit/test_assessors_go.py)black,isort,ruff checkall pass🤖 Generated with Claude Code