Help us shape the future of Go! Take the 2026 Go Developer Survey

commitpolicy

package
v1.0.14 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 2, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package commitpolicy checks a forge project's git state against forge's commit policy:

  • Generated code a COMPILER needs is COMMITTED. gen/, every forge-generated source file and every buf-generated stub must be tracked, so a checkout builds (`go build`, `go install`, a frontend build) as-cloned and `forge ci verify-generated` can see drift in it.
  • Generated files only forge or tooling reads are NEVER committed (IsToolDerived): forge derives each one on demand, in any checkout, so a committed copy buys nothing and costs a merge conflict between every two branches whose inputs differ. The proto descriptor, gen/forge_descriptor/, is one: committed as one aggregate file, it conflicted between any two pull requests that touched any proto.
  • Machine-local materializations are NEVER committed: the legacy .forge-kcl/ module copy, and a web frontend's dev runtime document public/config.js, whose values resolve per machine.

Why this is a check and not just a template

The scaffold .gitignore encodes the policy, but a project keeps the .gitignore it was born with forever — forge never rewrites a file the user owns. A project scaffolded while the template ignored gen/*, *_gen.go and the mocks carries those rules indefinitely, and nothing notices: its CI fails on `undefined:` symbols that live in ignored files, while `forge ci verify-generated`, which diffs with `git status --porcelain`, is blind to ignored paths by construction and reports green. That is the exact state a scaffolded project reached (its CI went red on every compiling job) before this check existed. It runs in `forge lint` and after verify-generated's regenerate, so every project that lints or runs CI is held to the policy whatever its .gitignore says.

It judges THIS project's files only. A nested tree that belongs to another project — its own git repository, or a Go module outside this one's module path — is skipped whole; see isForeignProject.

Index

Constants

View Source
const (
	// RuleGeneratedIgnored: a generated file the .gitignore excludes.
	RuleGeneratedIgnored = "generated-code-ignored"
	// RuleLocalStateTracked: a machine-local materialization in git.
	RuleLocalStateTracked = "machine-local-state-tracked"
	// RuleToolDerivedTracked: a generated file only tooling reads, in git.
	RuleToolDerivedTracked = "tool-derived-file-tracked"
)

Rule ids, stable for `forge lint --json` consumers.

View Source
const DeliveredRenderMarker = "project-specific guidance belongs in your own skills directory"

DeliveredRenderMarker is the phrase every harness-delivered agent skill carries in its banner (rendered by older forge versions, which are swept on generate).

A delivered skill is NOT project-generated code: it is a render of the skill catalog embedded in the forge binary, stamped with the rendering forge's version, with no input from the project. Like .forge-kcl/ it is binary-derived state — `forge skill load` prints the authoritative copy straight from the binary — so every forge build would rewrite a committed copy, and whether to track the directory is the project's call (forge's own repo ignores .claude/; a harness: reliant project has none). The commit policy therefore neither requires it to be committed nor forbids it.

View Source
const GoBuildCacheSentinel = "This directory holds cached build artifacts from the Go build system."

GoBuildCacheSentinel is the first line of the README the Go toolchain writes into every GOCACHE root. It is how a build cache identifies ITSELF, which is the only robust way to recognize one: GOCACHE is configurable, so the directory can be called anything. Agents in this workspace point it at $WORKTREE/.gocache to keep concurrent worktrees off a shared cache, but that name is a convention, not a contract.

Matching on the sentinel rather than a name also keeps the carve-out honest: a directory only earns the skip by actually being a Go cache.

Variables

This section is empty.

Functions

func Format

func Format(vs []Violation) string

Format renders violations as the multi-line block `forge lint` and `forge ci verify-generated` print.

func IsGoBuildCacheDir

func IsGoBuildCacheDir(dir string) bool

IsGoBuildCacheDir reports whether dir is a GOCACHE root, by reading the sentinel README the toolchain puts there.

Exported because two independent project-root walkers need it and must not disagree: this commit policy, and internal/removalguard's surviving- reference scan, which hit the identical false positive — a cache entry's copy of a stub for a since-removed feature read as a live reference to it.

This matters because a cache entry is a VERBATIM copy of compiler input, generated Go source included — an entry's first line is routinely "// Code generated by 'go test'. DO NOT EDIT." So isGenerated matches it, and since a build cache is gitignored by design, every entry otherwise becomes a "generated code, but excluded from git" violation. Measured: 133 in one control-plane worktree, 276 reported in the field, which buries the findings this rule exists to surface.

func IsToolDerived added in v1.0.10

func IsToolDerived(rel string) bool

IsToolDerived reports whether rel (project-relative, slash-separated) is a generated output only forge or tooling reads, which this policy keeps out of git.

Types

type Violation

type Violation struct {
	Rule string
	// Path is project-relative, slash-separated. For an ignored generated
	// file it is the file; for tracked local state it is the tracked path
	// (a directory for .forge-kcl/).
	Path string
	// Why says what the path is and why the policy applies to it.
	Why string
	// Fix is the literal command (or edit) that resolves it.
	Fix string
}

Violation is one breach of the policy.

func Check

func Check(projectDir string) ([]Violation, error)

Check inspects the git work tree rooted at projectDir. It returns nil, nil outside a git work tree (or without git): there is no commit state to judge, and guessing would be worse than silence.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL