# Local candidate check Use `releasekit.Check` to verify a candidate against the current local repository state: ```go result, err := releasekit.Check(ctx, releasekit.ReleaseRequest{ RepositoryDir: "/work/project", Product: "Example", Version: "v1.2.3", Validation: releasekit.ValidationSpec{ Go: releasekit.GoValidationSpec{Race: true, FullVet: true}, }, AdditionalChecks: func(ctx context.Context, candidate releasekit.Candidate) error { return runProjectChecks(ctx, candidate.RepositoryDir) }, }) if err != nil { return err } fmt.Println(result.Version, result.Commit) ``` Set `ReleaseRequest.ModuleDir` to select a nested module using a repository-relative physical directory; omission or `.` selects the root module. ReleaseKit reads that module's committed `go.mod` and returns its physical `ModuleDir`, declared `ModulePath`, semantic `Version`, and complete `Tag` in the candidate and result. A physical `/v2` directory is removed from the tag prefix only when the declared module path also ends in `/v2`. For example, both `integrations/core/v2` and `integrations/core` can declare `example.com/project/integrations/core/v2` and use the tag `integrations/core/v2.1.0`. The release note lives under the physical module at `/docs/releases/.md`. The repository must have a clean index and worktree on `main`, and the selected version must be stable `vMAJOR.MINOR.PATCH`. The module-local committed `/docs/releases/.md` note must have a first Markdown H1 containing the product name and exact version as complete title elements. No local tag with the derived complete tag may already exist. Different modules may use the same semantic version with distinct notes and tags. ReleaseKit runs one `go test -mod=readonly -count=1 ./...` suite from the selected module directory with the available compatible local Go toolchain. Set `Validation.Go.Race` to run that suite with `-race`; set `Validation.Go.FullVet` to run `go vet -mod=readonly ./...` after successful tests, with test-time vet disabled for the suite. Set `Validation.Go.CompileTargets` to compile packages for each complete target pair after tests and vet. Package compilation uses `CGO_ENABLED=0`, writes no artifact, and does not execute a target binary; its failures use the `package-compile` identity and include the target. The zero values retain the ordinary native test behavior and select no compilation. Set `Validation.GoFormat` to check committed regular Go files using the Go formatter built into ReleaseKit. It uses the selected file inputs, including vendor and explicit shared files, and ignores symlink blobs and worktree changes, and reports unformatted paths as `go-format` without rewriting files. Its zero value disables the check; it runs after tests, selected vet, and package compilation, before `AdditionalChecks`. Set `Validation.ModuleDistribution.WorkspaceFiles` to reject committed `go.work` and `go.work.sum` files in the selected module inputs, including symlink entries. It examines the captured candidate even when `GOWORK=off`, ignores uncommitted files, and does not change Go test workspace selection; vendored contents remain in scope. The zero value disables the check; failures use `workspace-files`. Set `Validation.ModuleDistribution.LocalReplacements` independently to parse the selected module's committed `go.mod` declarations. Vendored contents remain in scope; automatic inputs stop at independently released nested modules. An explicit shared-file selection can include another module's declaration. It reports filesystem `replace` directives with their source path, line, and target as `local-replacements`; versioned replacements are permitted. Committed module symlinks are resolved within the candidate. Parse and inspection errors retain their causes, and the rule applies even when `GOWORK=off`. Its zero value disables the check. Set `Validation.FileSize` to check each committed blob against a byte limit. Nil disables the check; an empty object enables the default of 1,000,000 decimal bytes. `LimitBytes` is strict greater-than, accepts zero, and rejects negative values. `Exclusions` contains literal files or directories relative to the selected module; excluded directories include descendants. Symlink blobs are measured by link-text bytes, and gitlinks are omitted. The check applies to the captured candidate and reports one oversized file with its measurement as `file-size`; it does not measure historical or aggregate size. Set `Validation.Markdown` to check committed local Markdown destinations and supported heading fragments. Nil disables the check; an empty object enables it with outside-checkout destinations reported as out of scope. Set `EnforceCheckoutBoundary` to fail outside-checkout links. Submodule contents remain out of scope under either setting. The checker runs after file-size inspection and before `AdditionalChecks`; its nonfailure observations use the request's output writer. Markdown failures use the `markdown-links` identity and include the source location and destination. Use these selections for ReleaseKit-owned validation rather than repeating the standard suite, selected vet/format/distribution checks, or Markdown navigation checks in `AdditionalChecks` or profile `checks`. Keep release-note rules and consumer-specific assertions—such as tests of maintained examples—in those product-owned checks. The `Candidate` supplies both `RepositoryDir` and `ModuleDir`, plus the declared `ModulePath`, semantic `Version`, and full `Tag`; use its module directory for module-local product checks. ReleaseKit calls `AdditionalChecks` once after shared validation when supplied. `ValidationSpec.SharedFiles` adds committed, repository-relative files to ReleaseKit's optional file checks without enabling any checks. A nil slice selects the optional defaults `COPYRIGHT`, `LICENSE`, and `docs/oss/attribution.md`, when present; a non-nil empty slice selects none. Explicit files replace those defaults, must exist even when file checks are disabled, and may be in another module. Combined inputs are deduplicated by repository-relative path. Automatic file inputs stop at independent nested-module boundaries, including fixture modules. Vendored files remain included. Shared selection affects file inputs only; Go validation retains the selected module's scope. Reference reads can inspect destinations elsewhere in the captured repository without adding those destinations to the input set. It does not download a different toolchain automatically. If race prerequisites are unavailable, the `go-test` check fails rather than being skipped; a selected full-vet failure is reported as `go-vet`. The suite uses the Go host target, disables workspace and module network access, and ignores ambient `GOFLAGS`, experiment, and CPU feature overrides. Effective cache and native cgo/C-tool settings are preserved, including values from Go's persistent environment file. The check revalidates the branch, commit, and cleanliness after validation. For checksum failures during dependency preparation, use the [module checksum investigation guide](delivery.md#investigating-module-checksum-mismatches). A successful check is evidence about the local candidate only. It does not check whether a remote branch or tag is available and does not create a tag. The [`check` command](../cli.md) reads the product and optional additional commands from `releasekit.json`. ## Publishing the source tag `releasekit.Publish` uses the same request and validation order: the standard suite runs first, followed by `AdditionalChecks` when supplied. It surrounds validation with authoritative remote guards before annotated-tag creation and an exact tag push. The selected remote must publish `main` at the captured commit and must not already contain the selected complete tag. A successful result includes the endpoint and tag object ID. Publication states distinguish an unattempted push, a tag that was created locally but not pushed, a successful push, a guard conflict, and an unresolved push error. See the [publication guide](publish.md) for the complete workflow. When a push reports an error, ReleaseKit makes one bounded query for the authoritative tag. An exact tag object match confirms success. An absent tag is reported as `not_published`, a different object as `conflict`, and an unreadable query as `unknown`. The local annotated tag is retained in every case; an `unknown` result is neither success nor proof that the remote lacks the tag.