From e520d4484222a9607d2457fbb219326c0094bbb4 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 27 Sep 2026 04:29:43 +0530 Subject: [PATCH 01/10] ci: add GitHub Actions workflow with pinned Go and job timeouts Commit the previously untracked CI workflow with the review fixes: - pin Go 1.26.6 once through env.GO_VERSION instead of floating '1.26'; - add timeout-minutes to every job (15/30/40) instead of the 360-minute default, and give the race run a 30-minute go test timeout; - run the test job on ubuntu-latest and macos-latest (the macOS job exercises the sandbox-exec runner); - add a pinned govulncheck job and workflow_dispatch. Action SHAs stay pinned (checkout v6.0.2, setup-go v6.4.0). gofmt is kept as the formatter check; see the PR for why gofumpt is not adopted yet. Finding: F100 --- .github/workflows/ci.yml | 84 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..cd2ff5c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,84 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + # Pinned toolchain, matching the release workflow and sibling repositories. + GO_VERSION: "1.26.6" + # Keep this repository buildable regardless of any go.work file in a + # parent directory of a local multi-repository checkout. + GOWORK: "off" + +jobs: + quality: + name: tidy + fmt + build + vet + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + - name: Module tidy is clean + run: | + go mod tidy + git diff --exit-code -- go.mod go.sum + - name: gofmt + run: test -z "$(gofmt -l .)" + - run: go build ./... + - run: go vet ./... + + vulncheck: + name: govulncheck + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + - run: go run golang.org/x/vuln/cmd/govulncheck@v1.1.4 ./... + + test: + name: test (${{ matrix.os }}) + strategy: + fail-fast: false + matrix: + # macOS exercises the sandbox-exec runner; Linux the Docker path. + os: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + # The suite starts real listeners and shells out to git and ssh. + - run: go test -count=1 -timeout=20m ./... + + race: + name: race + runs-on: ubuntu-latest + timeout-minutes: 40 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + - run: go test -race -count=1 -timeout=30m ./... From d03cd4720907e5cc1c7e24ab0dd5350bc4f1fa33 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 27 Sep 2026 04:29:54 +0530 Subject: [PATCH 02/10] build: set the module path to github.com/GrayCodeAI/trace The module was named `trace`, which is not fetchable and would clash with any other module of that name. Trace lives at github.com/GrayCodeAI/trace; the only package is cmd/trace (package main), so no import paths change. Finding: F099 --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 58e3e4b..9e6f521 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module trace +module github.com/GrayCodeAI/trace go 1.26 From 885a186eb359a42053351c0b47f4552206e6ad0e Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 27 Sep 2026 04:29:55 +0530 Subject: [PATCH 03/10] fix(deps): bump golang.org/x/crypto to v0.56.0 govulncheck v1.1.4 reports two vulnerabilities reachable from Trace's SSH server in golang.org/x/crypto v0.55.0, both fixed in v0.56.0: - GO-2026-6355: DoS on a deadlocked established channel in x/crypto/ssh - GO-2026-6354: DoS on a deadlocked undecided channel in x/crypto/ssh This is the same change as in the security-hardening PR, included here so the new govulncheck CI job passes on this branch too; the identical edits merge cleanly in either order. `go get` also normalizes the go directive from 1.26 to 1.26.0, which x/crypto v0.56.0 requires. --- go.mod | 4 ++-- go.sum | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 9e6f521..4e02c39 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/GrayCodeAI/trace -go 1.26 +go 1.26.0 -require golang.org/x/crypto v0.55.0 +require golang.org/x/crypto v0.56.0 require golang.org/x/sys v0.47.0 // indirect diff --git a/go.sum b/go.sum index d29e079..9952466 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= -golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= +golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= +golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= From 4fa9081f5e9d48020312098949b70b7946ef659f Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 27 Sep 2026 04:30:40 +0530 Subject: [PATCH 04/10] build: add VERSION 0.0.1, `trace version`, and a Makefile - VERSION holds the release version (0.0.1), like the sibling repos. - `trace version` prints the version, commit, and build date, which release builds set through -ldflags; plain builds report "dev". - Makefile targets: build, install, test, race, vet, fmt, fmt-check, tidy-check, vulncheck, and check (fmt-check, vet, build, race). All run with GOWORK=off. - .gitignore also ignores bin/ and dist/. Finding: F099 --- .gitignore | 2 ++ Makefile | 53 +++++++++++++++++++++++++++++++++++++++ VERSION | 1 + cmd/trace/main.go | 3 +++ cmd/trace/version.go | 16 ++++++++++++ cmd/trace/version_test.go | 24 ++++++++++++++++++ 6 files changed, 99 insertions(+) create mode 100644 Makefile create mode 100644 VERSION create mode 100644 cmd/trace/version.go create mode 100644 cmd/trace/version_test.go diff --git a/.gitignore b/.gitignore index 33fd474..c64113b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /trace +/bin/ +/dist/ /data/ *.test diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8aeb9d0 --- /dev/null +++ b/Makefile @@ -0,0 +1,53 @@ +# Trace — self-hosted Git forge for small teams (github.com/GrayCodeAI/trace). +# Run `make help` for the targets. Every target runs with GOWORK=off so a +# go.work file in a parent directory cannot change what is built. + +NAME := trace +MAIN_PKG := ./cmd/trace +export GOWORK := off + +VERSION ?= $(shell v=$$(head -n1 VERSION 2>/dev/null | tr -d '[:space:]'); if [ -n "$$v" ]; then echo "$$v"; else echo dev; fi) +COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo none) +DATE := $(shell date -u '+%Y-%m-%dT%H:%M:%SZ') +LDFLAGS := -s -w -X main.Version=$(VERSION) -X main.Commit=$(COMMIT) -X main.BuildDate=$(DATE) + +.PHONY: help build install test race vet fmt fmt-check tidy-check vulncheck check clean version + +help: ## List targets. + @grep -E '^[a-zA-Z_-]+:.*?## ' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " %-12s %s\n", $$1, $$2}' + +build: ## Build bin/trace with version information. + CGO_ENABLED=0 go build -trimpath -ldflags="$(LDFLAGS)" -o bin/$(NAME) $(MAIN_PKG) + +install: ## Install trace into $(go env GOPATH)/bin. + CGO_ENABLED=0 go install -trimpath -ldflags="$(LDFLAGS)" $(MAIN_PKG) + +test: ## Run the test suite (starts local listeners, shells out to git and ssh). + go test -count=1 -timeout=20m ./... + +race: ## Run the test suite with the race detector. + go test -race -count=1 -timeout=30m ./... + +vet: ## Run go vet. + go vet ./... + +fmt: ## Format the source with gofmt. + gofmt -w . + +fmt-check: ## Fail if any file is not gofmt-formatted. + @out=$$(gofmt -l .); if [ -n "$$out" ]; then echo "gofmt needed:"; echo "$$out"; exit 1; fi + +tidy-check: ## Fail if go.mod or go.sum are not tidy. + go mod tidy + git diff --exit-code -- go.mod go.sum + +vulncheck: ## Scan reachable code for known vulnerabilities (needs network). + go run golang.org/x/vuln/cmd/govulncheck@v1.1.4 ./... + +check: fmt-check vet build race ## The local gate: formatting, vet, build, race tests. + +version: ## Print the version from VERSION. + @echo $(VERSION) + +clean: ## Remove build output. + rm -rf bin dist diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..8acdd82 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.0.1 diff --git a/cmd/trace/main.go b/cmd/trace/main.go index 925520c..0cbc532 100644 --- a/cmd/trace/main.go +++ b/cmd/trace/main.go @@ -39,6 +39,9 @@ func run(args []string) error { return errors.New("usage: trace (try -help after a command)") } switch args[0] { + case "version", "-version", "--version": + fmt.Println(versionString()) + return nil case "init": fs := flag.NewFlagSet("init", flag.ContinueOnError) data := fs.String("data", "./data", "data directory") diff --git a/cmd/trace/version.go b/cmd/trace/version.go new file mode 100644 index 0000000..b4fed5b --- /dev/null +++ b/cmd/trace/version.go @@ -0,0 +1,16 @@ +package main + +import "fmt" + +// Version, Commit, and BuildDate identify a build. Release builds set them +// with -ldflags "-X main.Version=... -X main.Commit=... -X main.BuildDate=..."; +// the values below are what a plain `go build` reports. +var ( + Version = "dev" + Commit = "none" + BuildDate = "unknown" +) + +func versionString() string { + return fmt.Sprintf("trace %s (commit %s, built %s)", Version, Commit, BuildDate) +} diff --git a/cmd/trace/version_test.go b/cmd/trace/version_test.go new file mode 100644 index 0000000..cc8b3de --- /dev/null +++ b/cmd/trace/version_test.go @@ -0,0 +1,24 @@ +package main + +import ( + "io" + "os" + "strings" + "testing" +) + +func TestVersionCommand(t *testing.T) { + reader, writer, err := os.Pipe() + if err != nil { + t.Fatal(err) + } + stdout := os.Stdout + os.Stdout = writer + runErr := run([]string{"version"}) + os.Stdout = stdout + writer.Close() + out, _ := io.ReadAll(reader) + if runErr != nil || !strings.HasPrefix(string(out), "trace dev (commit none") { + t.Fatalf("trace version printed %q (err %v)", out, runErr) + } +} From 1dfd7071f77d531673a5d9fbc1c0a648640fae10 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 27 Sep 2026 04:32:09 +0530 Subject: [PATCH 05/10] docs: add security policy, contributing guide, and code of conduct - SECURITY.md: private reporting through GitHub private vulnerability reporting or security@graycodeai.com, supported versions (latest only while pre-1.0), scope, and safe-operation pointers. - CONTRIBUTING.md: setup, `make check`, Conventional Commits, tests and docs with every behaviour change. - CODE_OF_CONDUCT.md: Contributor Covenant 2.1, reports to hello@graycodeai.com. Finding: F099 --- CODE_OF_CONDUCT.md | 71 ++++++++++++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 50 ++++++++++++++++++++++++++++++++ SECURITY.md | 51 +++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 SECURITY.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..659f0af --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,71 @@ +# Code of conduct + +## Our pledge + +We, the maintainers and contributors of Trace, pledge to make participation +in this project a harassment-free experience for everyone, regardless of +age, body size, visible or invisible disability, ethnicity, sex +characteristics, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, race, +religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, +welcoming, diverse, inclusive, and healthy community. + +## Our standards + +Examples of behaviour that contributes to a positive environment: + +- showing empathy and kindness toward other people; +- being respectful of differing opinions, viewpoints, and experiences; +- giving and gracefully accepting constructive feedback; +- accepting responsibility, apologising to those affected by our mistakes, + and learning from the experience; +- focusing on what is best for the whole community. + +Examples of unacceptable behaviour: + +- sexualised language or imagery, and sexual attention or advances of any + kind; +- trolling, insulting or derogatory comments, and personal or political + attacks; +- public or private harassment; +- publishing others' private information, such as a physical or email + address, without their explicit permission; +- other conduct that could reasonably be considered inappropriate in a + professional setting. + +## Enforcement responsibilities + +Maintainers are responsible for clarifying and enforcing these standards +and will take appropriate and fair corrective action in response to any +behaviour they deem inappropriate, threatening, offensive, or harmful. They +may remove, edit, or reject comments, commits, code, issues, and other +contributions that do not align with this code of conduct. + +## Scope + +This code of conduct applies in all project spaces (issues, pull requests, +discussions, and other channels) and when someone officially represents +the project in public spaces. + +## Reporting + +Report unacceptable behaviour to the maintainers at +`hello@graycodeai.com`. All complaints will be reviewed and investigated +promptly and fairly, and the privacy and security of the reporter will be +respected. + +## Enforcement guidelines + +Maintainers follow these steps, depending on the impact of the behaviour: +a private written warning; a warning with consequences for continued +behaviour; a temporary ban from interaction with the project; or, for a +pattern of violations or serious harm, a permanent ban. + +## Attribution + +This code of conduct is adapted from the +[Contributor Covenant](https://www.contributor-covenant.org), version 2.1, +available at +. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..b5934ba --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,50 @@ +# Contributing to Trace + +Thanks for helping. Trace is a small, self-hosted Git forge for teams, part +of the [GrayCode](https://graycodeai.com) tools. It is pre-1.0 alpha +software, so behaviour and data formats can still change. + +## Before you start + +- For a security problem, follow [SECURITY.md](SECURITY.md) instead of + opening an issue. +- For anything larger than a small fix, open an issue first so we can agree + on the approach. +- Read [AGENTS.md](AGENTS.md): it describes the conventions for both people + and coding agents working in this repository. + +## Development setup + +You need Go (the version in `go.mod` or newer; CI uses the version pinned +in `.github/workflows/ci.yml`), Git, and an `ssh` client for the transport +tests. Trace builds for Linux and macOS. + +```sh +git clone https://github.com/GrayCodeAI/trace.git +cd trace +make build # bin/trace +make check # gofmt check, go vet, build, race tests +``` + +`make help` lists all targets. The test suite starts local listeners and +runs real `git` and `ssh` commands, so it takes a few minutes. + +## Pull requests + +- Branch from `main` and keep each pull request to one topic. +- Use [Conventional Commits](https://www.conventionalcommits.org/) for + commit messages and pull request titles (`fix(ssh): ...`, + `feat(actions): ...`, `docs: ...`). Mark breaking changes with `!` and a + `BREAKING CHANGE:` footer. +- Add or update tests for every behaviour change; a bug fix should come + with a test that fails without it. +- Update README.md, FEATURES.md, or ARCHITECTURE.md in the same pull + request when behaviour changes. Do not claim a capability that is not + implemented and tested. +- Run `make check` before pushing. CI runs the same checks plus tests on + macOS and `govulncheck`. + +## License + +By contributing, you agree that your contributions are licensed under the +[MIT License](LICENSE). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..d93d13e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,51 @@ +# Security policy + +Trace is a self-hosted Git forge. It stores source code, access grants, +personal-token hashes, CI secrets, and an administrator token, so we treat +vulnerability reports as a priority. + +## Supported versions + +Trace is pre-1.0 alpha software. Only the latest release (and `main`) +receives security fixes. The current version is in [`VERSION`](VERSION). + +## Reporting a vulnerability + +Please do not open a public issue, pull request, or discussion for a +security problem. Report it privately through either channel: + +- GitHub private vulnerability reporting: + +- Email: `security@graycodeai.com` + +Include what you can of: + +- the affected component or route and the Trace version or commit; +- steps to reproduce, ideally a minimal proof of concept; +- the impact you expect (for example, which role is needed and what it + gains); +- any suggested fix. + +We aim to acknowledge a report within 3 business days and to agree on a +disclosure timeline with you once we have assessed it. Reporters are +credited in the advisory unless they prefer otherwise. Please give us a +reasonable chance to release a fix before disclosing publicly; we will not +pursue legal action against good-faith research that follows this policy. + +## Scope + +In scope: the `trace` binary and everything in this repository, including +the web UI, the JSON API, Git smart HTTP and SSH transports, the CI runner, +OIDC, SCIM, webhooks, federation, and the release workflow. + +Out of scope: vulnerabilities in Git, Docker, the operating system, or a +reverse proxy in front of Trace; findings that require an administrator to +attack their own node; and denial of service that needs more traffic than +the documented rate limits allow. + +## Operating Trace safely + +The README describes the security model. In short: keep the data directory +private (it holds `data/admin-token`, token hashes, and CI secrets), put a +TLS reverse proxy in front of Trace, and run untrusted repositories' CI only +with sandboxing. From 5649b0d37658561a7247d02d3e694e46f2f93f7c Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 27 Sep 2026 04:32:35 +0530 Subject: [PATCH 06/10] docs: add a changelog Start CHANGELOG.md (Keep a Changelog) with the unreleased 0.0.1 entry for the first public version. Finding: F099 --- CHANGELOG.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9b15b59 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,39 @@ +# Changelog + +Notable changes to Trace are recorded here. The format follows +[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions +follow [Semantic Versioning](https://semver.org/) (before 1.0, a minor +version may contain breaking changes). + +## [Unreleased] + +## [0.0.1] - not yet released + +First public version of Trace at . The +project was previously developed privately under the names MeshGit and +Refweave. + +### Added + +- Module path `github.com/GrayCodeAI/trace`, a `VERSION` file, and a + `trace version` command. +- Makefile targets for building, testing, vetting, formatting checks, and + vulnerability scanning. +- CI on Linux and macOS with a pinned Go toolchain, race tests, job + timeouts, and `govulncheck`. +- A tag-triggered release workflow that publishes Linux and macOS + binaries (amd64, arm64) with a SHA-256 `checksums.txt`. Binaries are not + signed. +- SECURITY.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md, and AGENTS.md. + +### Security + +- Upgraded `golang.org/x/crypto` to v0.56.0 (GO-2026-6354, GO-2026-6355: + SSH channel denial of service). + +### Documentation + +- README, ARCHITECTURE, and FEATURES now match the code: pull-request + merges by admins and maintainers in the browser, the basic npm and PyPI + endpoints, the `maintain` grant in `trace user grant`, and a refreshed, + dated competitor comparison. From d465a015df5159d2e1393af34cda16d80fab2d39 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 27 Sep 2026 04:32:35 +0530 Subject: [PATCH 07/10] ci: publish checksummed Linux and macOS binaries for v* tags On a pushed v* tag, the release workflow checks that the tag equals v$(cat VERSION), runs go vet and the tests, and runs GoReleaser v2.17.0 (action pinned by SHA) to build trace for linux and darwin on amd64 and arm64 with -trimpath and version ldflags. It publishes tar.gz archives (binary, README, LICENSE, CHANGELOG, SECURITY) and a SHA-256 checksums.txt on the GitHub release. Nothing is signed, and the release notes say so. Windows is not built: Trace relies on POSIX file locking. Verified locally with `goreleaser check` and a snapshot build: four archives were produced and `shasum -a 256 -c checksums.txt` passed. Finding: F099 --- .github/workflows/release.yml | 51 +++++++++++++++++++++++++++++++++++ .goreleaser.yml | 50 ++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 .github/workflows/release.yml create mode 100644 .goreleaser.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..0c7a7ae --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,51 @@ +name: release + +# Builds Linux and macOS binaries for a pushed v* tag and publishes them with +# a SHA-256 checksums.txt on the GitHub release. Artifacts are not signed. + +on: + push: + tags: ["v*"] + +permissions: + contents: write + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false + +env: + GO_VERSION: "1.26.6" + GOWORK: "off" + +jobs: + release: + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + - name: Tag matches VERSION + run: | + want="v$(head -n1 VERSION | tr -d '[:space:]')" + if [ "${GITHUB_REF_NAME}" != "${want}" ]; then + echo "tag ${GITHUB_REF_NAME} does not match VERSION (${want})" >&2 + exit 1 + fi + - name: Vet and test + run: | + go vet ./... + go test -count=1 -timeout=20m ./... + - name: Build and publish with GoReleaser + uses: goreleaser/goreleaser-action@1a80836c5c9d9e5755a25cb59ec6f45a3b5f41a8 # v7.2.1 + with: + distribution: goreleaser + version: "v2.17.0" + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..049d342 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,50 @@ +# Release builds for Trace. Run by .github/workflows/release.yml on a v* tag. +# Trace uses POSIX file locking, so only Linux and macOS are built. +version: 2 +project_name: trace + +before: + hooks: + - go mod verify + +builds: + - id: trace + main: ./cmd/trace + binary: trace + env: + - CGO_ENABLED=0 + - GOWORK=off + goos: [linux, darwin] + goarch: [amd64, arm64] + flags: [-trimpath] + ldflags: + - -s -w -X main.Version={{.Version}} -X main.Commit={{.ShortCommit}} -X main.BuildDate={{.Date}} + mod_timestamp: "{{ .CommitTimestamp }}" + +archives: + - id: default + formats: [tar.gz] + name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" + files: + - README.md + - LICENSE + - CHANGELOG.md + - SECURITY.md + +checksum: + name_template: checksums.txt + algorithm: sha256 + +changelog: + disable: true + +release: + github: + owner: GrayCodeAI + name: trace + prerelease: auto + footer: | + Trace is pre-1.0 alpha software. See CHANGELOG.md for what changed. + + These binaries are not signed. Verify a download against `checksums.txt` + (SHA-256), for example `sha256sum --ignore-missing -c checksums.txt`. From 6276f0b48b6ca41527186dd9f26ecad8f47f9766 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 27 Sep 2026 04:32:59 +0530 Subject: [PATCH 08/10] docs: add AGENTS.md with repository conventions Describe the layout, the make targets, the JSON-store and subprocess conventions, secret handling, and the evidence rules for changes. AGENTS.md is the only agent-instruction file; tool-specific files such as CLAUDE.md are not used. --- AGENTS.md | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..7b67cb0 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,74 @@ +# AGENTS.md + +Guidance for anyone, human or coding agent, changing this repository. +This file is the only agent-instruction file here: do not add `CLAUDE.md`, +`GEMINI.md`, `.cursorrules`, or similar files, and delete them if a tool +generates one. Put shared guidance in this file instead. + +## What Trace is + +Trace is a self-hosted Git forge for small teams with signed agent history, +part of the GrayCode tools (). It is pre-1.0 +alpha software. One Go binary (`cmd/trace`, package `main`) serves the web +UI, the JSON API, Git smart HTTP and SSH, and runs the local CI runner. + +## Layout + +- `cmd/trace/*.go`: all code, grouped by feature (`actions.go`, `oidc.go`, + `ssh.go`, and so on), with tests beside it in `*_test.go`. +- `cmd/trace/*.html`, `cmd/trace/assets/`: embedded templates and assets. +- Runtime state lives in a data directory (default `./data`, ignored by + Git): bare repositories in `repos/OWNER/NAME.git`, JSON stores such as + `users.json` and `issues.json`, the append-only `audit.jsonl`, and + per-repository directories such as `lfs/OWNER/NAME`. +- README.md (operator guide), ARCHITECTURE.md (design and security + boundary), FEATURES.md (capability matrix): keep them true. + +## Commands + +Run Go with `GOWORK=off` (the Makefile sets it). + +```sh +make build # bin/trace +make check # gofmt check, go vet, build, race tests (the local gate) +make test # tests without the race detector +make vulncheck # govulncheck (needs network) +``` + +The tests start local listeners and run real `git` and `ssh`; they need no +network and write only to `t.TempDir()`. + +## Code conventions + +- Standard library first. The only direct dependency is + `golang.org/x/crypto`; discuss any new dependency in an issue first. +- Format with gofmt. `go vet` must stay clean. +- JSON stores follow one pattern: take the store's `flock` on + `data/..lock`, load, change, write to a temporary file, fsync, + rename. Keep writes atomic and never rewrite `audit.jsonl`. +- Per-repository files live under `data/KIND/OWNER/NAME` so a transfer can + move them and a delete can remove them. +- Run external programs with `exec.Command` and separate arguments; never + build a shell command line from user or repository input. Anything + written into a generated script (such as the pre-receive hook) must be + validated and quoted. +- Treat repository content (workflow files, HTML, pointers) as untrusted. + Authorization checks use `canRead`/`canWrite`/`canMaintain`, not raw + role strings. +- Never read, print, log, or commit secrets: the data directory's + `admin-token`, token hashes, `secrets.json`, `oidc.json`, or SSH and node + keys. Tests create their own throwaway data directories. + +## Changes and evidence + +- One concern per commit, [Conventional Commits](https://www.conventionalcommits.org/) + messages, branch from `main`, never force-push a shared branch. +- Every behaviour change needs a test; a bug fix needs a test that fails + without the fix. Do not weaken, skip, or delete tests to get a green run. +- Update the docs in the same change when behaviour changes. Describe only + what the code does and the tests verify; mark missing work as missing. +- Report verification exactly: the commands you ran and their real + results. Do not claim a check passed if you did not run it, and say so + when something could not be run (for example, a macOS-only path on + Linux). When citing facts, separate what you observed in code or output + from what a document states. From 9cb5a1d99c4003a12f485de5721f3272731b1676 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 27 Sep 2026 04:33:55 +0530 Subject: [PATCH 09/10] docs: reconcile README, ARCHITECTURE, and CLI help with the code - README: state what Trace is (a self-hosted Git forge for small teams with signed agent history, part of GrayCode), its pre-1.0 alpha status, that 0.0.1 is not released yet, that it builds for Linux and macOS only, and how to build from a clone; point to SECURITY.md, CONTRIBUTING.md, AGENTS.md, and the release workflow. - README and ARCHITECTURE: pull requests are merged in the browser by admins or maintainers (fast-forward, squash, or merge commit) under the repository's approval, check, and CODEOWNERS policy, not only fast-forwarded by an admin; protected branches are configurable. - README: the package paragraph no longer denies the basic npm and PyPI endpoints that the same README documents. - ARCHITECTURE: the operations milestone lists what now exists (backup verification, basic LFS, release builds) and what is still missing. - `trace user grant` usage lists the maintain role it already accepts. The rate-limit and sandboxing statements are corrected in the security-hardening PR, which changes that behaviour. Findings: F097, F099 --- ARCHITECTURE.md | 4 ++-- FEATURES.md | 2 +- README.md | 24 ++++++++++++++++-------- cmd/trace/users.go | 2 +- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 49ed63b..6e91eef 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -6,7 +6,7 @@ Make a code forge that one developer can run on a VPS, while allowing repositori ## Current milestone -The Go process serves a public landing page and a private team and code browser. People sign in through a web form that sets a short-lived, signed session cookie. Git clients use HTTP Basic authentication with the same personal token, or optional key-authenticated SSH Git transport and basic Git LFS. The server checks per-repository read/write grants, creates bare repositories, and invokes `git http-backend` for Git smart HTTP. Admins can update `main` and tags; writers can push other branches. A managed `pre-receive` hook enforces this on the Git server. The web page shows branches, diffs, pull requests, issues, tag-backed releases, and bounded live code search; pull requests can be approved and fast-forward merged by an admin when their immutable refs are unchanged. Release archives are generated directly from the verified Git tag. A writer can manually trigger a local workflow stored in `.trace/workflow.json`; Trace persists run state, bounded logs, and artifacts. +The Go process serves a public landing page and a private team and code browser. People sign in through a web form that sets a short-lived, signed session cookie. Git clients use HTTP Basic authentication with the same personal token, or optional key-authenticated SSH Git transport and basic Git LFS. The server checks per-repository read/write grants, creates bare repositories, and invokes `git http-backend` for Git smart HTTP. Admins can update protected branches (`main` by default) and tags; writers can push other branches. A managed `pre-receive` hook enforces this on the Git server. The web page shows branches, diffs, pull requests, issues, tag-backed releases, and bounded live code search; pull requests can be approved and merged (fast-forward, squash, or an explicit merge commit) by an admin or maintainer when their immutable refs are unchanged and the repository's approval, check, and CODEOWNERS policy is met. Release archives are generated directly from the verified Git tag. A writer can manually trigger a local workflow stored in `.trace/workflow.json`; Trace persists run state, bounded logs, and artifacts. User records are a small JSON file with hashed random tokens. The server reloads it on each request so rotation and revocation take effect immediately. Browser mutations authenticate through the signed session cookie and per-user CSRF token; script clients can use the JSON API with HTTP Basic personal tokens. Mutations append an owner-only audit event and can dispatch a signed webhook; webhook delivery is retried three times and recorded locally. A second node can fetch branches and tags into a read-only mirror. The system has no central database. Each repository can be copied with standard Git tools. @@ -19,7 +19,7 @@ This provides independent copies of code, but one writable node is still authori 3. **Recovery and multiple writers.** Keep each writer's refs under a separate namespace, such as `refs/trace/writers//...`. A repository owner can promote a writer's branch after reviewing it. This avoids silently overwriting divergent branches. 4. **Portable collaboration records.** Store issues, patches, reviews, and comments as signed, versioned objects that peers can replicate. Keep the format documented and exportable without the web application. 5. **Portable agent history.** Signed, versioned JSON bundles move structured checkpoints between nodes with an explicit expected source ID and target commit checks. An administrator can explicitly publish the same signed snapshot to a protected Git ref in a private repository. Automatic per-commit records, full run capture, and cross-node session sync remain future work; publication stays opt-in so summaries are not exposed with public code. -6. **Operations.** Add isolated runners and queues, TLS deployment examples, backup and restore verification, metrics, Git LFS support, and release builds. +6. **Operations.** Backup verification, basic Git LFS, and checksummed release builds exist. Still missing: hardened isolated runners and distributed queues, TLS deployment examples, metrics, and LFS locking and garbage collection. ## Trust rules diff --git a/FEATURES.md b/FEATURES.md index b123da1..6264896 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -1,6 +1,6 @@ # Trace capability audit -This is the honest baseline for the current monorepo. “All features from the top 20 competitors” is not a finite implementation task: GitHub, GitLab, Forgejo, SourceHut, agent platforms, and CI vendors overlap only partially, and several features require separate infrastructure (runners, package registries, email, object storage, search, and an agent sandbox). Trace must ship a coherent product before it attempts parity. +This is the honest baseline for this repository. “All features from the top 20 competitors” is not a finite implementation task: GitHub, GitLab, Forgejo, SourceHut, agent platforms, and CI vendors overlap only partially, and several features require separate infrastructure (runners, package registries, email, object storage, search, and an agent sandbox). Trace must ship a coherent product before it attempts parity. ## Current evidence diff --git a/README.md b/README.md index 57ae092..cf72982 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Trace -Trace is a self-hosted Git service for a small team. It keeps code in ordinary bare Git repositories, supports standard Git over HTTP(S), and can copy repositories to a read-only node on another VPS. The current design has one writable node per repository and manual failover. +Trace is a self-hosted Git forge for small teams with signed agent history, part of the [GrayCode](https://graycodeai.com) tools. It keeps code in ordinary bare Git repositories, supports standard Git over HTTP(S) and SSH, and can copy repositories to a read-only node on another VPS. The current design has one writable node per repository and manual failover. + +> **Status: pre-1.0 alpha.** Version 0.0.1 has not been released yet, and behaviour and data formats can still change. Build Trace from source as shown below. Read [SECURITY.md](SECURITY.md) before exposing a node, and report vulnerabilities privately as described there. ## Team features @@ -8,8 +10,8 @@ Trace is a self-hosted Git service for a small team. It keeps code in ordinary b - Admins can create repositories and manage users and access from the web page or CLI. - Repository grants are `read`, `write`, `maintain`, or `none`. Maintainers can merge reviewed pull requests and process the merge queue without becoming global administrators. Admins can access every repository. - Repositories can be public or private. Public repositories allow anonymous web browsing and Git clone/fetch; pushes and all write operations still require authentication. -- Writers can push branches. Only admins can update `main` or tags. A server-side Git hook enforces this rule. -- The web page lists branches, recent commits, files, file contents, and a branch's changes relative to `main`. Admins review there and merge with standard Git commands. +- Writers can push branches. Only admins can update protected branches (`main` by default; configurable per repository) or tags. A server-side Git hook enforces this rule. +- The web page lists branches, recent commits, files, file contents, and a branch's changes relative to `main`. Admins and maintainers review pull requests in the browser and merge them there (fast-forward, squash, or merge commit) or with standard Git commands. - The public home page introduces Trace; the private dashboard has its own sign-in form and a session cookie. Git clients continue to use HTTP Basic authentication. - Mirrors can serve clones but cannot accept pushes. Git history remains portable. @@ -39,14 +41,17 @@ For an entirely local operation, use the same board model without HTTP: ## Requirements -- Go 1.26 or newer to build. +- Go 1.26 or newer to build (CI and releases use Go 1.26.6). +- Linux or macOS. Trace relies on POSIX file locking and does not build for Windows. - Git installed on each node. - A TLS reverse proxy for use outside the machine. Trace listens on `127.0.0.1:8787` by default. Tokens must not cross the public internet without HTTPS. ## Start the main node ```sh -go build -o trace ./cmd/trace +git clone https://github.com/GrayCodeAI/trace.git && cd trace +go build -o trace ./cmd/trace # or: make build (writes bin/trace with version information) +./trace version ./trace init -data ./data ./trace repo create -data ./data team/project # or create a public repository @@ -340,7 +345,7 @@ Trace exposes the basic authenticated Git LFS batch protocol under `/lfs/OWNER/N ## Package artifacts -Trace also provides a generic immutable artifact registry. It is intentionally protocol-neutral; it does not claim npm, PyPI, or Maven compatibility yet: +Trace also provides a generic immutable artifact registry, plus the basic npm and PyPI endpoints described below. Neither endpoint is a complete npm or PyPI implementation, and Maven is not supported: ```sh ./trace package publish -data ./data team/project lib 1.0.0 lib-1.0.0.tgz @@ -555,10 +560,13 @@ The mirror is read-only, synchronization is scheduled externally, and failover i ## Develop ```sh -go test ./... -go vet ./... +make check # gofmt check, go vet, build, race tests +make test # tests without the race detector +make help # all targets ``` +See [CONTRIBUTING.md](CONTRIBUTING.md) for the workflow and [AGENTS.md](AGENTS.md) for repository conventions. Releases are built from `v*` tags by `.github/workflows/release.yml` for Linux and macOS (amd64 and arm64) with a SHA-256 `checksums.txt`; the binaries are not signed. No release has been published yet. + The integration tests verify authenticated Git push and clone, repository permissions, protected `main`, branch review, token rotation, mirror behavior, pull-request and issue lifecycles, webhook signing, release archives, and SSH key-authenticated Git transport. The web UI bundles the Inter typeface under the [SIL Open Font License](cmd/trace/assets/OFL-Inter.txt); it does not request fonts from a third-party server. diff --git a/cmd/trace/users.go b/cmd/trace/users.go index 1ae21c3..2f71556 100644 --- a/cmd/trace/users.go +++ b/cmd/trace/users.go @@ -346,7 +346,7 @@ func userCommand(args []string) error { fmt.Printf("created %s\nToken: %s\nShow this token to the user once over a private channel.\n", fs.Arg(0), token) case "grant": if fs.NArg() != 3 { - return errors.New("usage: trace user grant [-data DIR] USER OWNER/REPO ") + return errors.New("usage: trace user grant [-data DIR] USER OWNER/REPO ") } if err := s.grantUser(fs.Arg(0), fs.Arg(1), fs.Arg(2)); err != nil { return err From 1f9ac1b5c6a55b67465cd6e7fecdd1335c30e4e0 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 27 Sep 2026 04:34:33 +0530 Subject: [PATCH 10/10] docs(features): refresh the competitor set and the Entire comparison - Rename stale entries: Gitness is now Harness Open Source; Sourcegraph Cody is Enterprise-only and Sourcegraph's agent is Amp. - Add a dated table (sources checked 2026-09-26) of 2026 forge agent features: GitHub's Agents tab and agent control plane with an actor_is_agent audit field, the GitLab Duo Agent Platform, Forgejo's prohibition of AI-generated contributions, Gitea 1.26, Graphite's cloud agents in pull requests. Each row states what Trace lacks; agent attribution in the audit log and a per-repository AI-contribution policy join the remaining work. - Entire comparison: add adapter coverage (Trace 4, Entire 8, with the missing agents named), checkpoint ref layout (refs/entire/checkpoints vs Trace's refs/trace/agent-bundles, no import path), and the regional mirror preview. Facts and links come from the campaign's research refresh, whose pages were fetched on 2026-09-26. Findings: F299, F300 --- FEATURES.md | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/FEATURES.md b/FEATURES.md index 6264896..0cb76d4 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -42,7 +42,7 @@ This is the honest baseline for this repository. “All features from the top 20 ## Competitor-derived scope -The comparison set is GitHub, GitLab, Bitbucket, Gitea, Forgejo, Codeberg, SourceHut, OneDev, Gogs, Gitness, RhodeCode, Phorge, Gerrit, Azure DevOps, AWS CodeCommit, Entire, Graphite, GitLab Duo, GitHub Copilot coding agent, and Sourcegraph Cody. These products do not expose one common feature set. Trace will measure itself against the following product slices: +The comparison set is GitHub, GitLab, Bitbucket, Gitea, Forgejo, Codeberg, SourceHut, OneDev, Gogs, Harness Open Source (formerly Gitness), RhodeCode, Phorge, Gerrit, Azure DevOps, AWS CodeCommit, Entire, Graphite, the GitLab Duo Agent Platform, GitHub's Copilot coding agent and agent control plane, and Sourcegraph (Cody, now supported on Sourcegraph Enterprise only, and its Amp agent). These products do not expose one common feature set. Trace will measure itself against the following product slices: 1. **Forge basics:** Git over HTTP and SSH, repository visibility, protected branches, pull requests, review comments, approvals, bounded CODEOWNERS rules, issues, labels, milestones, releases, webhooks, and an API. 2. **Team administration:** roles, teams, token lifecycle, 2FA, audit events, rate limits, backups, and repository transfer/deletion. @@ -51,28 +51,44 @@ The comparison set is GitHub, GitLab, Bitbucket, Gitea, Forgejo, Codeberg, Sourc 5. **Local-first and distributed operation:** portable on-disk data, signed manifests, peer sync, conflict-safe writer refs, restore verification, and explicit failover. 6. **Agent workflows:** opt-in session/checkpoint records linked to commits, agent identity, prompt/tool redaction, searchable context, and review gates. +### Agent features in other forges (sources checked 2026-09-26) + +| Product | Change | What Trace lacks | +| --- | --- | --- | +| GitHub | Agents tab in repositories ([2026-01-26](https://github.blog/changelog/2026-01-26-introducing-the-agents-tab-in-your-repository/)); enterprise agent control plane with an `actor_is_agent` audit field and a custom-agent definition API ([GA 2026-02-26](https://github.blog/changelog/2026-02-26-enterprise-ai-controls-agent-control-plane-now-generally-available/)) | Trace's audit log does not record whether an actor is an agent | +| GitLab | Duo Agent Platform GA with custom agents and external agents such as Claude Code and Codex CLI ([2026-01-15](https://about.gitlab.com/press/releases/2026-01-15-gitlab-announces-duo-agent-platform-general-availability/)) | No review gates specific to agent-authored changes | +| Forgejo | Project decision to prohibit AI-generated contributions ([March 2026 report](https://forgejo.org/2026-03-monthly-report/)); v15.0 LTS added ephemeral runners and repository-scoped tokens ([2026-04-16](https://forgejo.org/2026-04-release-v15-0/)) | No per-repository policy for AI-generated contributions | +| Gitea | 1.26.0 added Actions concurrency and a Terraform state registry, with no agent features ([2026-04-18](https://blog.gitea.com/release-of-1.26.0/)) | — | +| Graphite | Cursor Cloud Agents inside pull requests ([2026-03-02](https://graphite.com/blog)) | No pull-request handoff to a cloud agent | +| Sourcegraph | Cody is supported on Sourcegraph Enterprise only ([docs](https://sourcegraph.com/docs/cody)); the Amp agent is free with bring-your-own-key since 2026-09-13 ([news](https://ampcode.com/news)) | — | +| Harness | Gitness continues as Harness Open Source ([repository](https://github.com/harness/harness)) | — | + +Self-hosted forges (Forgejo, Gitea) had no agent features at those dates, so Trace's structured agent sessions remain a differentiator; the hosted forges' agent attribution and policy controls are the gaps above. + ## Remaining implementation order 1. Richer status reporting, CODEOWNERS pattern semantics, merge queues, and code-review ownership UX. 2. Distributed rate limiting, stronger account security, SSH host-key rotation/distribution, and isolated CI execution. 3. Hosted or sandboxed CI runners, language-complete package registries, and distributed artifact storage. 4. Multi-writer federation, automatic peer discovery, richer conflict reconciliation, and portable collaboration records. -5. Automatic Git-native agent checkpoints and sync, more agent adapters, richer redaction/search controls, and provider-complete SSO. +5. Automatic Git-native agent checkpoints and sync, more agent adapters, agent attribution in the audit log and a per-repository AI-contribution policy, richer redaction/search controls, and provider-complete SSO. Trace is **not feature-complete** against this matrix today. The implemented baseline is intentionally smaller and testable; each missing row needs its own design, tests, and operational story before it can be called done. -## Entire comparison (reviewed 2026-09-20) +## Entire comparison (reviewed 2026-09-20; adapters, storage, and mirrors updated from sources checked 2026-09-26) This is a capability comparison with [Entire's product page](https://entire.io/), not a claim of performance parity. Trace's landing page uses an original visual and its own product copy. | Entire product area | Trace today | Gap | | --- | --- | --- | -| Git hosting and regional mirrors | Standard Git HTTP and SSH on one writable node; signed, read-only peer mirrors | No measured speed claim, managed regional network, or automatic failover | +| Git hosting and regional mirrors | Standard Git HTTP and SSH on one writable node; signed, read-only peer mirrors | No measured speed claim, managed regional network (Entire previewed US, EU, and AU mirrors on 2026-07-08, [announcement](https://entire.io/news/entire-launches-distributed-git-network-for-the-agent-era)), or automatic failover | | CLI and browser UI | Both exist for core workflows | CLI parity across every web action and a consistently polished application UI are unfinished | | Agent sessions and checkpoints | Structured records linked to commits, portable opt-in signed JSON bundles, private Git refs with signed snapshots, and opt-in Codex/Claude Code/Gemini CLI/Cursor completion capture | No full conversation capture, verified agent authorship, automatic per-commit checkpoints, or automatic cross-node session sync | | Local privacy controls | Selected secret fields are redacted from stored session data | No general transcript scanner or configurable redaction policy | | Semantic graph | Not implemented | No graph construction, semantic retrieval, or verified token-saving measurement | | Agentic search | One literal query across code, selected-branch commits, and structured session summaries | No semantic ranking, raw-transcript search, or graph-based context retrieval | | Agent integrations | Codex, Claude Code, Gemini CLI, and Cursor completion notifications can queue observed HEAD metadata with idempotent replay | No full run capture, verified authorship, or other agent hooks; Cursor's adapter has been tested against its documented schema but not through a live Cursor session | +| Agent adapter coverage | 4 completion-hook adapters: Codex, Claude Code, Gemini CLI, Cursor | Entire's CLI lists 8 agents: Claude Code, Codex, Cursor, Copilot CLI, Antigravity, Pi (preview), OpenCode, and Factory AI Droid ([entireio/cli](https://github.com/entireio/cli)). Trace has no adapter for Copilot CLI, Antigravity, Pi, OpenCode, or Factory AI Droid | +| Checkpoint storage | Signed, per-node snapshots published to private refs under `refs/trace/agent-bundles/` | Entire stores checkpoints in Git refs under `refs/entire/checkpoints//` ([ref-based storage](https://entire.io/blog/introducing-ref-based-checkpoint-storage)); Trace cannot import Entire checkpoints | Do not market Trace as an Entire equivalent until these gaps have implementations and independent verification. The near-term product goal is a reliable self-hosted Git workspace for a small team, with explicit agent context and safe read-only replication.