# 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", Validate: func(ctx context.Context, candidate releasekit.Candidate) error { return runProjectChecks(ctx, candidate.RepositoryDir) }, }) if err != nil { return err } fmt.Println(result.Version, result.Commit) ``` The repository must have a clean index and worktree on `main`, and the selected version must be stable `vMAJOR.MINOR.PATCH`. The 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 that version may already exist. The callback receives the captured repository, commit, and version. ReleaseKit calls it once. When omitted, ReleaseKit runs the offline Go test command. The check revalidates the branch, commit, and cleanliness after validation. 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 validation commands from `releasekit.json`. ## Publishing the source tag `releasekit.Publish` uses the same request and performs candidate validation, authoritative remote checks, 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 version 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. When a push reports an error, the local annotated tag is retained and the result is `unknown` until a later implementation adds authoritative reconciliation. Do not treat that state as success or proof that the remote lacks the tag.