Repository navigation
feat: status --json + read-only MCP server; harden CI, release and repo hygiene - #66
Bharath-code wants to merge 2 commits into
Conversation
- `git-scope status --json`: attention-sorted repo state (path, branch, dirty, ahead/behind, unpushed, last commit, tier, reason) - `git-scope mcp`: stdio MCP server with list_repos, needs_attention and repo_status tools, sharing the same scan → report path - scan linked worktrees (.git file), count conflicts as uncommitted, count unpublished commits on branches without upstream / detached HEAD - bound every git call with a 10s timeout - .gitignore: anchor binary names so cmd/git-scope/ is not ignored Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- CI: pin all actions to commit SHAs, test on Linux/macOS/Windows, check `go mod tidy -diff`, drop persisted checkout credentials - Lint: add .golangci.yml (gosec, errorlint, revive, misspell, nolintlint) - Security: create config/cache/nudge files owner-only (0700/0600) - Release: migrate deprecated `brews` to `homebrew_casks` and `format` to `formats`; add SPDX SBOMs and signed build provenance; stop mutating go.mod at release time - Add OpenSSF Scorecard workflow; scope Pages write permissions to the job - Replace markdown issue templates with issue forms; disable blank issues - SECURITY.md: current supported version, private advisory reporting, explicit scope and release verification - CHANGELOG: record MCP/status work and the above Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Kilo Code Review could not run — your account is out of credits. Add credits or switch to a free model to enable reviews on this change. |
There was a problem hiding this comment.
Kai review · 🔵 Your call, then merge (8/10)
Next: say yes or no to 2 decisions below, then merge when you're happy.
Size L · 1027 lines in 28 files · Risk L · decides on money, decides on access, changes CI or the build
To get to 10/10:
- −2 · say yes or no to 2 decisions above
| What | Where | |
|---|---|---|
| 🤔 | [money] The Homebrew cask drops com.apple.quarantine from an unnotarized binary, so macOS users installing via the cask after the next release run an unsigned binary with no Gatekeeper prompt — confirm that is the int… |
— |
| 🤔 | [access] SECURITY.md advertises private-advisory reporting links that 404 until private vulnerability reporting is enabled in repo settings — enable it before this reads as a promise to reporters. | — |
🐞 fix before merge · 🤔 correct as written, but someone should say yes.
What I made of it
Nothing I'd call a defect, but 2 decisions to say yes to.
0 confirmed findings, 11 refuted. Intent verified.
Important files changed
| File | Change |
|---|---|
.github/ISSUE_TEMPLATE/bug_report.md |
modified · +0 −31 |
.github/ISSUE_TEMPLATE/bug_report.yml |
modified · +53 −0 |
.github/ISSUE_TEMPLATE/config.yml |
modified · +8 −0 |
.github/ISSUE_TEMPLATE/feature_request.md |
modified · +0 −20 |
.github/ISSUE_TEMPLATE/feature_request.yml |
modified · +30 −0 |
.github/workflows/ci.yml |
modified · +41 −11 |
.github/workflows/pages.yml |
modified · +10 −6 |
.github/workflows/release.yml |
modified · +19 −5 |
+21 more changed files in the full analysis.
What I opened — 28 files, 24 turns, 3m8s
6 of the 29 changed files don't appear below: .github/ISSUE_TEMPLATE/bug_report.md, .github/ISSUE_TEMPLATE/feature_request.md, go.sum, internal/cache/cache.go, internal/config/config.go, internal/nudge/nudge.go.
.github/ISSUE_TEMPLATE/bug_report.yml.github/ISSUE_TEMPLATE/config.yml.github/ISSUE_TEMPLATE/feature_request.yml.github/workflows/ci.yml.github/workflows/pages.yml.github/workflows/release.yml.github/workflows/scorecard.yml.gitignore.golangci.yml.goreleaser.ymlCHANGELOG.mdREADME.mdSECURITY.mdcmd/git-scope/main.gogo.modinternal/attention/attention.gointernal/attention/score.gointernal/gitops/gitops.gointernal/gitstatus/gitstatus.gointernal/gitstatus/gitstatus_test.gointernal/mcpserver/mcpserver.gointernal/mcpserver/mcpserver_test.gointernal/model/repo.gointernal/report/report.gointernal/report/report_test.gointernal/scan/scan.gointernal/scan/scan_test.gointernal/tui/actions.go
Full read-through
Scope
- All Go source files in the diff: internal/mcpserver/mcpserver.go and test, internal/report/report.go and test, internal/gitstatus/gitstatus.go and test, internal/scan/scan.go and test, cmd/git-scope/main.go
- Supporting callers: internal/attention/attention.go, internal/attention/score.go, internal/model/repo.go, internal/gitops/gitops.go, internal/tui/actions.go, internal/cache/cache.go, internal/config/config.go, internal/nudge/nudge.go
- Workflow and config files: ci.yml, pages.yml, release.yml, scorecard.yml, .golangci.yml, .goreleaser.yml
- Issue templates: bug_report.yml, feature_request.yml, config.yml, and deleted .md templates
- Documentation: CHANGELOG.md, README.md, SECURITY.md, .gitignore, go.mod, go.sum
- All Go source in the diff: cmd/git-scope/main.go, internal/mcpserver/mcpserver.go + test, internal/report/report.go + test, internal/gitstatus/gitstatus.go + test, internal/scan/scan.go + test, internal/attention/attention.go + score.go, internal/model/repo.go, internal/cache/cache.go, internal/config/config.go, internal/nudge/nudge.go, internal/gitops/gitops.go, internal/tui/actions.go
- All workflow files: .github/workflows/ci.yml, pages.yml, release.yml, scorecard.yml
- Config/build files: .golangci.yml, .goreleaser.yml, .gitignore, go.mod
- Docs/templates: CHANGELOG.md, README.md, SECURITY.md, .github/ISSUE_TEMPLATE/*.yml + config.yml
- All Go source files in the diff: internal/gitstatus/gitstatus.go, internal/scan/scan.go, internal/report/report.go, internal/mcpserver/mcpserver.go, cmd/git-scope/main.go, internal/attention/attention.go, internal/attention/score.go, internal/model/repo.go, internal/gitops/gitops.go, internal/tui/actions.go
- All test files: internal/gitstatus/gitstatus_test.go, internal/scan/scan_test.go, internal/report/report_test.go, internal/mcpserver/mcpserver_test.go
- All workflow files: ci.yml, pages.yml, release.yml, scorecard.yml
- Config/tooling: .golangci.yml, .goreleaser.yml, .gitignore, go.mod, go.sum
- Docs: README.md, SECURITY.md, CHANGELOG.md, issue templates (.yml/.md/config.yml)
- Could not read github.com/modelcontextprotocol/go-sdk v1.8.0 source (external module not in tree) — SDK behavior rests on passing in-memory tests
- Could not read GoReleaser's cask-generation contract — cask stanza correctness rests on author's goreleaser check
No proposed defect was confirmed by this check within the reviewed scope.
Limitations
- Could not read github.com/modelcontextprotocol/go-sdk v1.8.0 source (fetched module not in tree): mcp.AddTool generic signature, mcp.Server.Run semantics for ctx propagation to tool handlers, ToolAnnotations fields, CallToolResult.StructuredContent/IsError — rest on the passing in-memory test, not on the SDK's type declarations
- Could not read GoReleaser's cask-generation contract: whether a 'post' lifecycle hook stage exists for homebrew_casks, and whether the generated cask places the binary on PATH — rests on the author's 'goreleaser check' and snapshot build claims
- Did not execute any code; all behavioral claims are from source reading alone
- github.com/modelcontextprotocol/go-sdk v1.8.0 is a fetched module not present in this checkout; its AddTool generic signature, ToolAnnotations fields, and CallToolResult/IsError/StructuredContent semantics could not be read. The two MCP-related allegations rest on SDK behavior I could not verify from source.
- GoReleaser's cask-generation contract is not in this tree; the homebrew_casks stanza's correctness rests on the author's goreleaser check and snapshot build, which I could not independently run.
- No code was executed in this review; test-pass claims are taken from the author's notes and from reading the test assertions, not from running them.
- MCP SDK (github.com/modelcontextprotocol/go-sdk v1.8.0) type signatures and semantics are unverified against the package's own source — AddTool generic return, ToolAnnotations/OpenWorldHint fields, CallToolResult.StructuredContent/IsError behavior rest on the passing in-memory test only
- GoReleaser cask generation contract is unverified — whether the homebrew_casks stanza produces a working binary link cannot be confirmed from this tree
Decisions (need your call)
- [money] The Homebrew cask drops
com.apple.quarantinefrom an unnotarized binary, so macOS users installing via the cask after the next release run an unsigned binary with no Gatekeeper prompt — confirm that is the intended install posture, and that the generated cask stanza places the binary on PATH. - [access] SECURITY.md advertises private-advisory reporting links that 404 until private vulnerability reporting is enabled in repo settings — enable it before this reads as a promise to reporters.
+937 −110 · 29 files · reaches 12 · the full analysis
💬 Reply to any of my comments and I'll answer, or say @kaicontext anywhere on this PR — a question, or "take another look at the retry logic".
Description
Two commits:
feat:
status --json+ read-only MCP server for AI agents. This is the first step in repositioning git-scope as the repo-state layer for people running many coding agents across repos and worktrees.git-scope status --jsonprints every repo, most urgent first: path, branch, dirty count, ahead/behind, unpushed commits, last commit time, attention tier (ACTION/WATCH/CLEAN) and a reason.git-scope mcpis a stdio MCP server built on the officialmodelcontextprotocol/go-sdkv1.8.0. Its tools arelist_repos,needs_attentionandrepo_status(path), all read-only and all using the same scan → report code as the JSON command.repo_statusonly answers for repos under the configured roots..gitis a filechore: CI, release supply chain and repo hygiene.
pages.ymlgo mod tidy -diffcheck.golangci.ymladds gosec, errorlint, revive, misspell and nolintlint.brews→homebrew_casksandformat→formats;goreleaser checkwas failing on these deprecationsactions/attest-build-provenance)go mod tidySECURITY.mdupdated: supported version 1.4.x, private advisories, scope, release verification. CHANGELOG updated.Type of Change
Checklist
Reviewer notes
go test -race ./...,golangci-lint(0 issues),actionlint,goreleaser checkgoreleaser release --snapshotbuild: 6 archives plus a valid caskgit-scope status --json | jq, and a raw JSON-RPC stdio session calling all three MCP toolshomebrew-tap, addtap_migrations.jsoncontaining{"git-scope": "git-scope"}and deleteFormula/git-scope.rb. The tap token also needs renewing.main.toolchainline ingo.mod.🤖 Generated with Claude Code
Kai context
Written by Kai from the change itself. Kai only edits this section; everything above it is the author's.
Adds
git-scope status --jsonand a read-onlygit-scope mcpstdio server (built onmodelcontextprotocol/go-sdkv1.8.0) withlist_repos,needs_attention, andrepo_statustools, all sharing a newinternal/reportpackage. Also fixes linked-worktree scanning, unpublished-commit detection, merge-conflict counting, and adds a 10s git-call timeout, plus CI/release hardening and repo-hygiene changes.Changes
status --jsoncommand:cmd/git-scope/main.gowires a newstatussubcommand that scans configured roots and printsreport.Buildoutput as JSON viareport.PrintJSON;--jsonis stripped from args bywithout.internal/mcpserver/mcpserver.goregisters three read-only tools (list_repos,needs_attention,repo_status) on a stdio transport;repo_statusresolves paths canonically and only answers for repos under configured roots.internal/report/report.godefinesRepostruct andBuild(attention-sorted) /Reason/PrintJSONfunctions shared by both the CLI and MCP server.internal/gitstatus/gitstatus.go: detects# branch.upstreamto know when there is no upstream; addsunpublishedCommitsusingrev-list --count HEAD --not --remotes(skips repos with no remote);applyFileLinenow countsu(unmerged/conflict) lines as unstaged;runGitwraps every call in a 10scontext.WithTimeout.internal/scan/scan.gomatches.gitfiles (not just directories) and returnsnilinstead ofSkipDirfor those files so nested repos are still found.internal/cache/cache.go,internal/config/config.go, andinternal/nudge/nudge.gocreate directories with0o700and write files with0o600..github/workflows/ci.ymlsplits intochecks(format, tidy-diff, vet, govulncheck) and atestmatrix (ubuntu/macOS/windows), pins all actions to SHAs, and setspersist-credentials: false;.github/workflows/pages.ymlscopespages/id-tokenwrite permissions to the deploy job and pins actions to SHAs..github/workflows/release.ymlpins actions to SHAs, installssyftfor SBOMs, runsactions/attest-build-provenanceagainstdist/checksums.txt, and drops thego mod tidypre-hook..goreleaser.yml): migratesbrews→homebrew_casks(with quarantine-removal post-install hook),format→formats, and adds SPDX SBOM generation..golangci.ymlenables gosec (excluding G204/G304), errorlint, revive, misspell, nolintlint, bodyclose, unconvert with test-path exclusions..github/workflows/scorecard.ymlruns OpenSSF Scorecard on schedule and push, uploading SARIF results..ymlforms (bug_report.yml,feature_request.yml) withconfig.ymldisabling blank issues and linking to Discussions and security advisories.SECURITY.mdupdates supported version to 1.4.x, adds private-advisory reporting, scope, and release-verification instructions;CHANGELOG.mdrecords all additions and fixes;.gitignoreanchors binary names socmd/git-scope/is no longer ignored.Testing
internal/report/report_test.go: verifies JSON shape and field values for clean, unpushed, stale-dirty, and scan-error repos; confirms attention sort order and thatPrintJSON(nil)emits[].internal/mcpserver/mcpserver_test.go: uses in-memory MCP transport to exercise all three tools —list_reposreturns all repos,needs_attentiondrops clean repos,repo_statusresolves a symlinked path with trailing slash, and rejects paths outside roots or empty paths.