Skip to content

Glippy v1.0.0

Latest

Choose a tag to compare

@github-actions github-actions released this 27 Aug 09:50
· 1 commit to main since this release

Glippy v1.0.0

Status: stable release contract

Glippy v1 is one opinionated Go CLI for deterministic width-aware formatting,
correctness-focused linting, transactional fixes, repository checks, machine
diagnostics, and editor integration through stdin/stdout and LSP. These notes
define the first stable Glippy release.

Changes From Gox v0.1.0

Gox v0.1.0 is the previous tagged, published stable version; its
GitHub release is
not a draft or prerelease. This section is the complete public contract delta
from that tag. The frozen v1 manifests under
testdata/contracts/v1 are the exact
current-state authority; the linked Gox v0.1.0 references identify the old
surface.

Surface Gox v0.1.0 Glippy v1.0.0 Required adoption action
Identity gox, github.com/faustbrian/gox, .gox.toml, //gox:, and GOX_CACHE_DIR glippy, github.com/faustbrian/glippy, .glippy.toml, //glippy:, and GLIPPY_CACHE_DIR Rename invocations, imports, configuration, suppressions, and cache overrides as described below.
Formatter The current width-aware dialect, but five comment/directive ownership areas contained valid-source refusals or unnecessary verbatim fallback The same layout policy with those source-fidelity defects corrected Run glippy fmt --check or --diff; no deliberate layout-policy migration is required.
Rules 7 IDs 129 stable IDs: the 7 retained IDs plus 122 additions Audit the 59 newly default-enabled correctness rules or generate a reviewed baseline.
Fixes 2 fix-bearing rules: one safe and one suggestion 20 fix-bearing rules: 3 safe, 16 suggestion, and 1 unsafe Ordinary --fix still selects safe fixes only; opt into other classes explicitly.
Configuration Version 1 with one lint.preset and no profiles, matrices, path overrides, baselines, or contracts Version 1 plus the additive fields and defaults listed below Rename the file; existing fields remain accepted. Choose a profile only when its broader policy is intended.
CLI fmt, lint, check, explain, version, and completion Those commands plus lsp, init, config, rules, and help, with the additive modes listed below Replace the binary name; existing command meanings are retained.
Machine output Formatter, lint, and combined-check JSON schema version 1 Formatter, lint, rule, and statistics schema version 1; combined-check schema version 2; GitHub, short, and SARIF reporters Combined-check consumers must accept schema version 2 and the new per-file states.
Source versions Go 1.25 and Go 1.26 Go 1.25 through Go 1.27 No action for existing source; Go 1.27 syntax is now accepted.
Native targets macOS/Linux on amd64/arm64 The same four targets, now bound to native runtime and release-budget evidence No platform migration. Windows remains unsupported.
Release support Current supported stable release Superseded and unsupported when v1 is published Upgrade to v1 before reporting defects; no v0.1 or long-term-support line is retained.

There are no removed or renamed lint rule IDs, no reclassified existing fixes,
no removed configuration fields or commands, no reassigned exit codes, and no
supported operating-system or architecture removal in this delta.

Product Identity Migration

This release changes the product identity from Gox to Glippy:

  • install github.com/faustbrian/glippy/cmd/glippy and invoke glippy;
  • rename .gox.toml to .glippy.toml;
  • replace //gox: suppressions with //glippy: suppressions;
  • replace GOX_CACHE_DIR and Gox cache paths with GLIPPY_CACHE_DIR and the
    Glippy cache namespace; and
  • update CI, hooks, editor commands, archive names, and version assertions.

Automatic configuration discovery accepts .gox.toml only when
.glippy.toml is absent. Finding both names fails instead of selecting one.
Legacy //gox: suppressions remain effective through this release but produce
an actionable legacy-directive migration finding. Gox cache entries are not
reused as Glippy entries.

Formatter Output Changes

Glippy v1 makes no deliberate formatter policy change relative to Gox v0.1.0.
The canonical width, indentation, block, list, binary-expression, selector,
literal, parenthesis, import-order, and blank-line policies remain the same.
Five correction areas resolve valid-source refusals or unnecessary verbatim
fallback caused by incomplete comment or directive ownership proof:

Corrected construct Gox v0.1.0 result Glippy v1 result Classification
Comments and suppressions between a label and its statement, including closing labels Refused with no output owner Preserves label, comment, directive line, and required blank gap Source-fidelity defect correction
Declaration documentation and grouped value specs ending in //nolint Refused equivalence validation Preserves documentation and the trailing suppression on its physical line Source-fidelity defect correction
External line-scoped suppressions on a composite opening nested in a call, an enclosing binary assignment/return or label, a field with a blank gap, or an inline field in plain/generic/grouped types Refused when width-aware layout moved the external anchor Preserves the affected declaration verbatim while formatting unaffected declarations Directive-ownership defect correction
Blank lines between trailing top-level directive groups Refused equivalence validation Preserves each directive group and the separating blank line Directive-gap defect correction
Comments immediately before or after else, including else if Refused with no output owner Preserves the comment at the else boundary Comment-ownership defect correction

Label comments

Gox v0.1.0 produced no source for this valid input and reported
comment 0 has no proven output owner:

package labels
func run(){goto target;target:
// explain target
work()}

Glippy v1 produces:

package labels

func run() {
	goto target
target:
	// explain target
	work()
}

Declaration documentation and trailing suppressions

Gox v0.1.0 refused this declaration because comment identity or ordering
changed:

package comments
// errUnavailable documents the declaration.
var errUnavailable = errors.New("unavailable") //nolint:unused

Glippy v1 preserves both owners while applying declaration spacing:

package comments

// errUnavailable documents the declaration.
var errUnavailable = errors.New("unavailable") //nolint:unused

Nested external suppression anchors

Gox v0.1.0 refused this already canonical declaration because the external
directive source anchor changed:

package comments

func run() {
	http.SetCookie(w, &http.Cookie{ //nolint:gosec
		Name: "sort",
	})
}

Glippy v1 emits the declaration unchanged. If another declaration in the same
file needs ordinary canonical formatting, Glippy formats that declaration
without moving the protected suppression anchor.

Trailing directive groups

Gox v0.1.0 refused these trailing groups because a directive source anchor
changed:

package internal

//go:generate first
//go:generate second

//go:generate third
//go:generate fourth

Glippy v1 emits the source unchanged, including the blank line separating the
two directive groups.

Comments around else

Gox v0.1.0 produced no source for this input and reported that the comment had
no proven output owner:

package control
func run(value int){if value==0{work()}else /* value != 0 */{retry()}}

Glippy v1 produces:

package control

func run(value int) {
	if value == 0 {
		work()
	} else /* value != 0 */ {
		retry()
	}
}

The exact regression fixtures are in
internal/format/format_test.go. The
complete construct-by-construct input, prior result, v1 output, and
classification inventory is the
v1 formatter delta. The
current formatter specification and canonical examples are in the
formatter rules. The pinned 17-repository source-
fidelity and idempotency evidence is recorded by the
v1 corpus adjudication
and v0.9 exit audit. Publication
requires every correction to pass parse, normalized equivalence, comment and
directive identity, idempotency, width, golden, fuzz, and corpus gates.

Glippy deliberately is not a product-wide gofmt fixed point. Width-aware
layouts, retained import order, preserved literal and parenthesis spelling,
structural indentation, and explicit empty-statement spelling can differ from
gofmt. Repositories must remove competing gofmt, gofumpt, or golines authority
when adopting Glippy. See the
formatter migration guide.

Lint Rule Delta

The seven Gox v0.1.0 rule IDs are retained with the same group membership,
default severity, analysis tier, and fix classification:

context-key
defer-in-infinite-loop
duplicate-condition
errors-is-arguments
ineffective-break
nilness
redundant-bool-comparison

Four retained rules change only by exposing the new requires_effect_facts
metadata field as false. Three retained rules also establish broader v1
reporting or fix-reporting boundaries:

Rule v0.1 boundary v1 boundary Classification and adoption impact
defer-in-infinite-loop Treated only built-in panic and runtime.Goexit as terminal helpers Reuses bounded no-return facts from selected local-source modules and exact standard-library terminal APIs Precision correction; removes findings on paths proven to terminate. Re-run recommended or strict policy before adopting.
nilness Used the shared intraprocedural x/tools SSA analyzer without interprocedural return facts Adds bounded selected-local-source no-return and nil/error return relationships, rejects conflicting/build-variant summaries, and excludes exact testing assertion shims Precision expansion and correction; may add proven findings or remove intentional test assertions. Re-run recommended or strict policy before adopting.
redundant-bool-comparison Withheld simplify-comparison when comments would be lost, but did not expose a structured reason Emits a withheld_fixes record naming simplify-comparison, reason comments, and an actionable message Additive fix-reporting correction; the diagnostic and safe-fix classification are unchanged. Schema-version-1 consumers must ignore the optional field.

The other four retained rules do not change their documented reporting
boundary.

Glippy v1 adds these 122 rule IDs:

almost-swapped, append-no-values, atomic-update-assignment
bad-bit-mask, blank-error-discard, buffer-string-conversion
busy-select-loop, channel-used-after-close, context-background
context-cancel-leak, context-todo, contradictory-condition
copied-lock, dangerous-remove-all, defer-before-error-check
defer-in-loop, deferred-function-not-called, deferred-lock
deferred-time-since, deprecated-ioutil, direct-panic
discarded-error, empty-branch, errors-as-target
exact-suffix-as-cutset, excessive-nesting, exec-pipe-run
exported-api-documentation, failed-type-assertion-value, finalizer-captures-object
http-canonical-header-key, http-response-before-error, http-response-body-not-closed
http-response-body-used-after-close, identical-branches, ignored-append-result
impossible-comparison, impossible-interface-nil-comparison, impossible-type-assertion
inconsistent-receiver-name, ineffective-assignment, ineffective-url-query-mutation
ineffective-value-receiver-assignment, inefficient-io-string-write, inefficient-string-comparison
infinite-recursion, integer-division-before-conversion, invalid-binary-write
invalid-build-constraint, invalid-directive, invalid-random-bound
invalid-regexp, invalid-slog-arguments, invalid-strconv-argument
invalid-struct-tag, invalid-test-signature, invalid-unmarshal-target
lock-held-across-blocking-call, lock-not-released, loop-capture
manual-min-max, mixed-receiver-type, must-use-result
nan-comparison, needless-blank-identifier, net-ip-bytes-equal
nil-context, nil-error-wrap, nil-function-comparison
nil-map-write, non-octal-file-mode, non-slice-sort
overlapping-encoder-slices, oversized-shift, overwritten-error
printf-arguments, process-exit, redundant-closure
redundant-else, redundant-nil-check, redundant-type-declaration
regexp-compile-in-loop, resource-not-closed, resource-used-after-close
self-assignment, shadowed-error, sql-transaction-not-completed
sql-transaction-used-after-completion, standard-library-version, standard-method-signature
string-range-rune-conversion, subsumed-condition, suspicious-range
suspicious-string-conversion, sync-pool-non-pointer, testing-goroutine-call
time-duration-unit, time-layout, time-since
time-until, too-many-lines, too-many-parameters
too-many-results, typed-nil-error-return, unbuffered-signal-channel
uncatchable-signal, unchecked-csv-writer-error, unchecked-rows-error
unchecked-scanner-error, unchecked-writer-error, unlock-without-lock
unnecessary-conversion, unnecessary-format, unnecessary-sprintf
unreachable-code, unsafe-host-port, unused-result
waitgroup-misuse, waitgroup-negative-counter, writer-not-finalized
zero-regexp-match-limit, zero-replace-count

Of those additions, these 59 correctness rules are newly enabled by the
default profile:

append-no-values, atomic-update-assignment, bad-bit-mask
channel-used-after-close, context-cancel-leak, contradictory-condition
copied-lock, deferred-lock, deferred-time-since
errors-as-target, exec-pipe-run, failed-type-assertion-value
finalizer-captures-object, http-response-before-error, impossible-comparison
impossible-interface-nil-comparison, impossible-type-assertion, ineffective-url-query-mutation
infinite-recursion, invalid-binary-write, invalid-build-constraint
invalid-directive, invalid-random-bound, invalid-regexp
invalid-slog-arguments, invalid-strconv-argument, invalid-struct-tag
invalid-test-signature, invalid-unmarshal-target, loop-capture
must-use-result, nan-comparison, net-ip-bytes-equal
nil-context, nil-function-comparison, nil-map-write
non-slice-sort, overlapping-encoder-slices, oversized-shift
printf-arguments, self-assignment, sql-transaction-not-completed
sql-transaction-used-after-completion, standard-library-version, testing-goroutine-call
time-layout, unbuffered-signal-channel, uncatchable-signal
unchecked-csv-writer-error, unchecked-writer-error, unlock-without-lock
unreachable-code, unsafe-host-port, unused-result
waitgroup-misuse, waitgroup-negative-counter, writer-not-finalized
zero-regexp-match-limit, zero-replace-count

duplicate-condition and ineffective-break remain the two carried default
rules. To reproduce only the v0.1 default selection during incremental
adoption, use an explicitly empty group list and enable those IDs:

[lint]
presets = []

[lint.rules]
duplicate-condition = "warn"
ineffective-break = "warn"

The curated v1 profiles are:

  • default: fixed correctness-focused policy;
  • recommended: default plus 19 reviewed suspicious diagnostics;
  • strict: the complete correctness, suspicious, performance, complexity,
    and style groups; and
  • pedantic: strict plus the complete pedantic group.

All 129 IDs are stable at v1, including the three opt-in nursery rules
exact-suffix-as-cutset, ineffective-assignment, and
resource-used-after-close. Nursery remains excluded from every curated
profile, but it is not a post-v1 compatibility exception: shipped IDs,
membership, severities, reporting boundaries, and fix contracts follow the
stable rule policy. Restriction rules must be enabled by exact ID. Migration
rules require an explicit target rather than wholesale group selection.

The exact 129-entry metadata manifest is
testdata/contracts/v1/rules.txt. It
pins group membership, tier, and fix class. Canonical summaries, full
documentation, options, examples, and limitations are published in the
rule reference and by glippy rules and
glippy explain. For comparison, the exact seven-rule v0.1 reference remains
available at
v0.1.0/docs/lint-rules.md.

Analysis is demand-driven across lexical, syntax, types, control-flow, and SSA
tiers. Glippy adapts supported go/analysis analyzers without delegating its
scheduling, policy, diagnostics, or fix-safety contracts.

Fix Availability And Safety Delta

The two v0.1 fixes retain their classifications:

  • redundant-bool-comparison: safe simplify-comparison;
  • ineffective-break: suggestion remove-break.

redundant-bool-comparison now reports a structured withheld-fix record when
comments make simplify-comparison unavailable. The fix remains safe when it
is offered; the new record explains an existing omission rather than widening
automatic fix eligibility.

Glippy v1 adds 18 fix-bearing rules without removing or downgrading an existing
fix:

Safety Added rule IDs
Safe redundant-nil-check, redundant-type-declaration
Suggestion needless-blank-identifier, net-ip-bytes-equal, non-octal-file-mode, printf-arguments, self-assignment, suspicious-string-conversion, time-layout, time-since, time-until, unbuffered-signal-channel, unnecessary-conversion, unnecessary-format, unnecessary-sprintf, unreachable-code, unsafe-host-port
Unsafe exact-suffix-as-cutset

Safe, suggestion, and unsafe fixes are independent categories. Ordinary
lint --fix applies only safe fixes. Suggestion and unsafe fixes require their
explicit authorization flags. lint --fix --diff previews the fully validated
and formatted result without writing.

Every accepted single-file transaction verifies source identity, rejects
invalid or overlapping ranges without choosing a winner, coordinates exact
import additions or removals required by accepted fixes, reparses the edited
file, formats it through the canonical formatter, reanalyzes it, validates the
final source, and replaces the original atomically on supported local
filesystems. Failed validation and stale writes preserve the original source.
Multi-file semantic fix transactions are not part of v1.

Configuration Delta

Configuration schema version remains 1 and all v0.1 fields remain accepted.
The canonical filename changes to .glippy.toml; .gox.toml is the migration
fallback described above.

Added field Default Contract
[[analysis.targets]] with tags, goos, goarch, and cgo-enabled empty Analyze an explicit deterministic build matrix in addition to the primary selection.
analysis.contract-files empty Load bounded, project-local semantic contracts.
lint.profile default when no profile/preset field is present Select default, recommended, strict, or pedantic.
lint.presets profile-owned when omitted Select an order-independent list of groups; an explicit empty list selects no group.
lint.warnings-as-errors false Escalate enabled warnings after all other policy resolution.
[[lint.overrides]] with paths and rules empty Apply ordered project-relative path-glob rule overrides.
lint.baseline.path unset Select a strict .glippy-baseline.json adoption baseline.
lint.baseline.report-stale true Report stale baseline entries when a baseline is selected.
lint.baseline.expiry-cutoff unset Reject expired baseline entries at a deterministic date.

lint.preset remains a compatibility alias for one group. It cannot be
combined with lint.profile or lint.presets. The default profile selects the
complete current correctness group, so its result set grows by the 59 rules
listed above even though the profile's policy meaning is unchanged.

Integer rule options may now publish and enforce inclusive bounds. Strict
decoding still rejects unknown fields, rule IDs, groups, options, duplicates,
and unsupported schema versions. The exact starter configurations and
configuration command output are frozen in
testdata/contracts/v1/configuration.txt.
The full field, precedence, discovery, baseline, override, contract, and cache
rules are in the configuration specification.

CLI Delta

The six v0.1 top-level commands retain their non-writing or writing ownership.
Glippy v1 adds:

  • lsp for bounded stdio formatting, diagnostics, and validated code actions;
  • init for exclusive creation of a starter .glippy.toml;
  • config check and config show for validation and effective-policy output;
  • rules for catalog discovery and filtering; and
  • help [command] for frozen top-level and command-specific usage.

Existing command additions are:

  • lint levels -A/--allow, -W/--warn, -D/--deny, and -F/--forbid;
  • lint --only, --except, --new-from, --stats,
    --generate-baseline, and fix --diff;
  • check --new-from, --stats, and the same ordered lint levels;
  • short, github, and sarif reporters for lint and check;
  • rules --preset, --tier, and --fixable catalog filters;
  • init --profile starter-policy selection;
  • explain --json; and
  • --help, exact command help, and expanded Bash, Zsh, and Fish completion.

The exact command, option, help, completion, reporter, and failure-exit
contracts are frozen by
commands.txt,
help.txt,
completions.txt,
reporters.txt, and
failure-exits.txt. The
command reference is the human contract. The exact
v0.1 surface remains available at
v0.1.0/docs/command-reference.md.

Exit codes are unchanged: 0 means success, 1 means actionable findings, 2
through 6 distinguish source, invocation/configuration, conflict, filesystem,
and internal failures, and 130 reports cancellation.

Machine Output Delta

Formatter and lint JSON remain at schema version 1. Glippy v1 adds compatible
optional lint fields for baselines, build targets, withheld fixes, coordinated
import changes, and changed-line disposition. It also adds separate
schema-version-1 rule metadata and execution-statistics documents. Consumers
of a supported schema version must continue to ignore unknown optional fields.

Combined-check JSON moves from schema version 1 to version 2. Version 2 adds:

  • format_status: "pending" for an analyzed file not formatted before an
    incomplete outcome;
  • format_status: "preexisting" and
    preexisting_formatting_differences for changed-line checks;
  • baseline counts and problems; and
  • the additive lint target, withheld-fix, and changed-line fields shared with
    lint reports.

Machine consumers must reject unsupported schema versions. A Gox v0.1 check
decoder must add version 2 to its accepted set and handle pending and
preexisting without treating either as clean. Consumers that cannot migrate
must use separate glippy fmt --check --reporter=json and
glippy lint --reporter=json reports, which remain schema version 1. No exit
category was reassigned.

Glippy v1 also provides deterministic short text, GitHub workflow annotation,
and SARIF 2.1.0 output. The exact machine examples are frozen by
testdata/contracts/v1/machine.txt,
and the machine output reference defines fields,
ranges, ordering, completeness, and migration behavior. The v0.1 schema-1
reference remains available at
v0.1.0/docs/machine-output.md.

Supported Platforms And Go Versions

Official archives target:

  • macOS amd64 and arm64; and
  • Linux amd64 and arm64.

This operating-system and architecture set is unchanged from v0.1. Windows and
other operating systems remain unsupported. Write and fix guarantees cover the
documented local-filesystem evidence only. Network, distributed, and userspace
filesystems and forced-power-loss durability are outside the v1 contract.

Glippy adds Go 1.27 source support to the Go 1.25 and Go 1.26 range accepted by
v0.1. Official binaries are built with the recorded Go 1.27.0 toolchain and do
not require an installed Go runtime. Source installation requires the
toolchain selected by go.mod.

Release Support Transition

Publishing Glippy v1 makes it the latest supported stable release and ends
support for Gox v0.1.0. This release does not retain an earlier stable or
long-term-support line. Users must upgrade to v1 before reporting a defect or
security issue against the supported contract and should reproduce the issue
there when safely possible.

Installation And Automation

The supported installation channels are GitHub Releases and:

go install github.com/faustbrian/glippy/cmd/glippy@v1.0.0

The CI and pre-commit guide provides plain GitHub
Actions, Woodpecker, generic shell CI, and repository hook examples. The
editor guide documents stdin/stdout and existing
LSP integration without requiring a first-party Action or editor plugin.

Release Evidence And Security

The release evidence binds the accepted source revision to the pinned
17-repository corpus, complete default/recommended adjudication, formatter
goldens and fingerprints, fuzz, race, integration, fix-safety, native latency
and aggregate-memory budgets, frozen contracts, historical upgrades,
reproducible macOS/Linux archives, checksums, and GitHub build provenance.

Security reports follow SECURITY.md. The support and
compatibility boundaries are defined by the
support policy and
compatibility policy.