Repository navigation
refactor: complete Modern Go adoption across module boundaries - #706
Merged
Merged
Conversation
Apply slices_sort, slices_sort_func, slices_sorted, maps_keys_values_iter, slices_collect, cmp_or, errors_as_type, testing_t_context, new_expression, range_over_int, slices_clone, maps_clone, maps_delete_func, strings_cut_prefix_suffix, strings_bytes_cut_last, and strings_split_seq. Preserve ordering stability, nil/empty identity, error targets, and context lifetimes.
Apply slices_sort, slices_sort_func, slices_sorted, maps_keys_values_iter, errors_as_type, testing_t_context, sync_waitgroup_go, sync_once_func, new_expression, range_over_int, cmp_or, slices_clone, maps_clone, maps_copy, maps_delete_func, slices_compact, strings_split_seq, strings_bytes_cut_last, url_clone, and stdlib_uuid. Preserve stable precedence, nil/empty normalization, cleanup lifetime, descriptor bytes, and UUID v4 semantics.
Apply slices_sort, slices_sort_func, slices_sorted, maps_keys_values_iter, errors_as_type, testing_t_context, sync_waitgroup_go, sync_once_func, new_expression, loopvar_capture, range_over_int, cmp_or, and min_max. Preserve stable ordering, nil/empty identity, lazy error precedence, cleanup lifetimes, and byte-identical OpenAPI output.
Apply testing_t_context, new_expression, slices_sort, slices_sort_func, cmp_or, sync_waitgroup_go, sync_once_func, loopvar_capture, range_over_int, min_max, slices_contains, slices_index_func, slices_clone, bytes_clone, maps_delete_func, maps_keys_values_iter, slices_collect, and strings_bytes_cut_last. Preserve cleanup lifetimes, stable ordering, claim/lease tie-breakers, pointer independence, nil/empty identity, and JSON tags. Validated scoped race unit and integration suites, build, vet, and lint. Heavy gates remain with integration CI under the worker contract.
Apply slices_sort, slices_sort_func, maps_keys_values_iter, slices_collect, cmp_or, errors_as_type, testing_t_context, sync_waitgroup_go, sync_once_func, new_expression, loopvar_capture, range_over_int, strings_bytes_cut_last, stdlib_uuid, and strings_split_seq. Preserve stable ordering, nil versus empty collection identity, UUID v4, and independent cleanup lifetimes. Keep cleanup-created shared timeout contexts usable while inheriting test cancellation for test-body work.
Applied guideline IDs: slices_sort, slices_sort_func, slices_sorted, maps_keys_values_iter, cmp_or, errors_as_type, testing_t_context, sync_waitgroup_go, sync_once_func, new_expression, loopvar_capture, range_over_int, strings_bytes_cut_last, generic_methods, promoted_field_literals, slices_clone, slices_contains. Preserve admission locks, stable transcript ordering, nil/empty identity, cleanup lifetimes and process signaling parity. Validate scoped race suites, real integration journeys, vet, Windows cross-build and zero-finding scoped lint; heavy gates remain PR-CI owned per the worker contract.
Apply slices_sort, slices_sort_func, slices_sorted, slices_clone, cmp_or, errors_as_type, errors_is, testing_t_context, loopvar_capture, maps_copy, min_max, strings_split_seq, strings_bytes_cut_last, and new_expression. Lint all supported Go modules and tagged Mage tooling, preserve fixture SDK resolution, select nested Go gate lanes, and document per-rule enforcement. Exclude the matched value of errors.AsType from errcheck while retaining blank-assignment checks for operation errors.
Apply json_omitzero to omission-equivalent scalar and pointer fields. Retain IsZero, collection, interface, fixture and generated SDK boundaries. Verify JSON/YAML marshal parity and unchanged generated contracts.
Apply cmp_or, errors_as_type, generic_methods, loopvar_capture, maps_clone, maps_delete_func, maps_keys_values_iter, new_expression, promoted_field_literals, range_over_int, slices_clone, slices_collect, slices_sort, slices_sort_func, slices_sorted, strings_bytes_cut_last, sync_once_func, sync_once_value, sync_waitgroup_go, testing_t_context. Preserve stable ordering, nil/empty collections, error target types, and cleanup lifetimes. Retain predicate-only As calls pending the controller-owned errcheck configuration change. Validate with scoped race tests, integration journeys, go build, go vet, Modern Go analyzer, scoped lint, and a real CLI JSON run.
Guidelines: slices_sort, slices_sort_func, slices_sorted, maps_keys_values_iter, cmp_or, errors_as_type, testing_t_context, sync_waitgroup_go, sync_once_func, new_expression, loopvar_capture, range_over_int, stdlib_uuid, strings_bytes_cut_last, strings_split_seq, strings_cut_prefix_suffix, promoted_field_literals, generic_methods.
Apply slices_sort, slices_sort_func, slices_sorted, maps_keys_values_iter, slices_collect, errors_as_type, testing_t_context, sync_waitgroup_go, sync_once_func, new_expression, loopvar_capture, range_over_int, min_max, cmp_or, slices_contains, slices_index, slices_clone, maps_clone, strings_bytes_cut_last, promoted_field_literals, stdlib_uuid, generic_methods. Preserve stable hook order, registry tie-breakers, nil/empty wire identity, UUID v4 semantics, pointer ownership, and independent cleanup contexts. Validate with scoped race tests, focused integration tests, scoped lint, root build, scoped vet, and a scoped Windows cross-build. Heavy integration branch gates remain controller/CI-owned per the issue #482 worker contract.
Apply slices_sort, slices_sort_func, slices_sorted, maps_keys_values_iter, slices_collect, errors_as_type, testing_t_context, sync_waitgroup_go, sync_once_func, new_expression, loopvar_capture, range_over_int, cmp_or, strings_bytes_cut_last, slices_contains, maps_clone, bytes_clone, slices_clone, promoted_field_literals, stdlib_uuid, and min_max.
Apply errors_as_type while preserving lazy matching and non-error interfaces. Repair testing_t_context cleanup lifetimes and preserve ordered teardown. Classify semantic slices_sort_func, loopvar_capture and json_omitzero exclusions.
Keep loopvar_capture enforcement limited to redundant self-copies.
Apply testing_t_context with fresh bounded teardown contexts in store, memory, and attachment test suites. Preserve timer and transaction cleanup ownership, including named and indirectly invoked cleanup closures.
The new integration-tag Modern Go lint pass covers _integration_test.go files that were never linted before. Apply its remaining findings (embedlit, slicescontains, slicesbackward, waitgroupgo), drop the copyloopvar suppressions that only existed while alias checking was enabled, format the gate integration test, and tidy go.mod now that github.com/google/uuid has no direct importers. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Fill the runbook's retained-exclusion inventory from every slice audit (site-specific lint exceptions plus review-enforced patterns by guideline ID) and add the #482 entry to the change-impact ledger. Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
WalkthroughWarning Review details and warnings were omitted to fit the comment limit. |
|
The catalog search test runs accessible-name role queries over the full catalog, which takes about 4s in jsdom and exceeds the 5s default when a broad change invalidates the turbo cache and every workspace suite runs concurrently. Give it the same per-test budget the site suite already uses for heavy jsdom renders; assertions are unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Contributor
|
React Doctor found no new issues. 🎉 Reviewed by React Doctor for commit |
This was referenced Oct 7, 2026
Merged
Merged
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #482.
Summary
This PR completes the Modern Go migration across every Go module and build-tagged tooling surface in the repository, and makes compliance continuous so a regression fails the gate regardless of which module it lands in.
It is a behavior-preserving refactor. Ordering, nil-vs-empty collections, JSON omission, error matching, goroutine ownership, cancellation lifetimes and wire contracts are treated as contracts. Every migration was justified by reading the surrounding code; nothing was a blanket search-and-replace. Sites that can't be migrated without changing behavior are kept and documented, never silently skipped.
origin/main→ this PR)sort.Strings/Ints/Slice/SliceStable/...calls"sort"importserrors.As(callsgithub.com/google/uuidimportscontext.Background()/TODO()in_test.got/b/tb.Context()in testsx := x)omitzeroJSON tagsstrings/bytes.CutLast¹ A test fake whose comparator returns
truefornil/nil; a valid three-way comparator would change its observable order, so it keepssort.Slicebehind a site-specific lint exception.² All remaining uses are
sort.Searchupper-bound cursor/insertion searches, whichslices.BinarySearch(lower bound) can't express.³ Four targets are interfaces that don't implement
error(errorPayload,ExitCode() int), soerrors.AsType[E error]can't express them. The fifth match is a string inside at.Fatalmessage.⁴ Each remaining use falls in a documented category: cleanup callbacks (where
t.Context()is already canceled),TestMain, helpers with notesting.TB, or process/server lifetimes that cleanup stops.⁵ Only scalar and pointer fields whose encoding is byte-identical. See "JSON".
Context: what changed since the issue was filed
stdlib_uuid,strings_bytes_cut_last,promoted_field_literals,url_clone,generic_methodsandjson_v2. The five nested modules (sdk/go,sdk/examples/notes-commands,sdk/examples/clarify-tool,internal/extension/testdata/{command,palette}-fixture-go) still declare 1.26.4 and were migrated against its 48 IDs, with no 1.27 APIs. Theirgodirectives were left alone, becausesdk/gois a public SDK and raising its minimum Go version is a separate decision.internal/sandboxwas removed in the packages cleanup. The HTTP API is served by gin, sohttp_servemux_patternsonly applied to hand-writtennet/httphandlers. The ones that remain were evaluated and kept, because exact parity on status codes andAllowbehavior wasn't guaranteed.json_v2(encoding/json/v2) is out of scope: the guideline says not to migrate existingencoding/jsoncode unless explicitly requested.What changed
1. Continuous compliance (tooling, gates, CI)
make go-lint,make lintand the CI go-lint job now run golangci-lint with the root.golangci.ymlon the root module,magefiles(magetag),sdk/go, both SDK examples and both extension fixture modules. The fixture modules are resolved through a disposablego.workpinned to the local SDK, the same way the authoring tests build them, and the workspace is removed afterwards. Scoped runs (COMPOZY_GO_LINT_SCOPES) translate nested-module scopes and stay narrow for root scopes. The first failing module exits non-zero.modernizedoesn't enforce. The bundled modernize suite (x/tools v0.49.0 in golangci-lint v2.13.1) was inspected analyzer by analyzer. The gaps are now enforced by:forbidigoonsort.Strings|Ints|Float64s|Slice|SliceStable|Sort|Stableand onerrors.As;depguard, which bansgithub.com/google/uuidin the root module only (the nested modules can't use the 1.27 stdlibuuid);copyloopvar.errors.AsTypeidiom.errcheck.exclude-functions: [errors.AsType]lets theif _, ok := errors.AsType[*T](err); okidiom passcheck-blank, which is still enabled. A probe showed that a genuinely ignored error is still reported.scripts/gate.shclassifies nested modules correctly. Go files andgo.mod/go.sumundersdk/examples/<name>/select that module's Go lint and test lanes; before this PR they only selected a JS filter.sdk/goselects lint as well as tests. Fixture-module changes select fixture lint.magefilesselects tagged lint. Bash 3.2 compatibility is kept, and the scripts integration suite covers the new classifications.changesfilter now treats nestedgo.mod/go.sumas backend changes, and the golangci cache key hashes every module manifest.docs/runbooks/modern-go.md. It covers the module/Go-version table, a rule → enforcement map for all 54/48 IDs (modernize analyzer, other linter, explicit check, or review-enforced), local commands, gate/CI lane selection, and the consolidated retained-exclusion inventory.2. Mechanical migrations (all modules)
Every rule below was applied only where the rewrite is exactly equivalent:
sort.*→slices.Sort/SortFunc/SortStableFunc. Comparators were translated key by key withcmp.Compareandcmp.Or, and stable sorts stay stable.slices.Sorted(maps.Keys(...)). Where the empty result can reach JSON, a DTO, an equality assertion or a nil check, it usesslices.AppendSeq(make(...), maps.Keys(...))so the result stays non-nil.errors.As→errors.AsType[T], keeping the same pointer/value target, lazy evaluation order (switch cases became orderedifchains), and typed-nil semantics.x := xcopies removed.github.com/google/uuid→ stdlibuuid.NewV4().String(), which keeps random v4 and the same canonical format. The dependency is gone fromgo.mod.new(value)instead of pointer helpers and temporaries (preserving aliasing),strings/bytes.CutLast,CutPrefix,SplitSeq, range-over-int,min/max,slices.Contains/Index/Compact, andmaps.Clone/Copy/DeleteFunc. Each is applied only where nil/empty identity and no-match defaults are preserved.3. Semantic migrations, reviewed by owning layer
testing_t_context).t.Context()/b.Context()/tb.Context().internal/testutil.Context(t)now inherits the owning test's context, as the issue asked. When it is called during cleanup, aftert.Context()has been canceled, it detaches and applies a fresh 45-second bound.t.Cleanupcallback would now arrive canceled. An AST audit over the whole merged tree, build-tagged files included, found every such capture. Each one now gets a fresh bounded cleanup context (testutil.Context(t)inside the callback). A reviewer had reproduced the failure before the fix (TestMCPAuthOwnerIsolation,workspacedb TestOpen,TestManagerBusyInput*).sync.WaitGroup.Go/sync.OnceFunc/sync.OnceValue(s)are used only for locally paired equivalents. AnAddperformed under an admission lock, anAdd(n)batch, or a struct-owned lifecycle gate (reset, per-call state, re-panic semantics) is kept.append([]T(nil), s...)normalizes an empty input tonil, butslices.Clonedoesn't. It was only replaced behind existing length guards.new(expr)) was only used where the temporary was allocation-only. Behavioral helpers (defaulting, trimming, UTC conversion, deep copy) are kept.4. JSON (
json_omitzero), audited field by field with codegen parityencoding/jsonv1, OpenAPI schema reflection, the TS SDK generator, the Go SDK generator, MCPjsonschema-go, goccygo-yaml(which falls back tojsontags), gin binding, mapstructure, and the TOML encoders.omitemptyoptions on bool, numeric and pointer fields, which encode identically underomitzeroinencoding/jsonv1. This excludes types with anIsZeromethod, whichomitzerowould call. The rewrite was done by an AST tool that resolves named types, aliases and promotedIsZeromethods, and touched tag text only.omitemptyon strings, slices and maps, as the guideline says;IsZero, including one promoted throughstore.EventCorrelation, which the parity probes caught;sdk/go/types.go:136, which now has a justifiednolint);make codegenproduced no changes to generated artifacts: OpenAPI, the TS/Go SDKs, web types, native tool descriptors, schemas and digests.make codegen-checkpasses.Retained exclusions
Every retained prohibited call has a site-specific
//nolint:<linter> // <reason>. Review-enforced patterns are inventoried by guideline ID indocs/runbooks/modern-go.mdunder "Retained exclusions", each classified as semantic, generated, or justified exclusion. No blanket suppression was added.How this was produced and reviewed
The work was split into twelve file-disjoint slices, each in its own git worktree: daemon, api, store, cli/config, session/acp/terminal, loop, task/automation, extension/hooks, tools/mcp/skills, platform/testutil, tooling and nested modules, and JSON tags. Each slice was executed under one shared contract, with per-rule policy, ownership boundaries and capped scoped verification. The slices were merged into this branch, followed by one integration pass for cross-slice concerns: the
errors.AsTypeerrcheck fix and the cleanup-context sweep. Every slice diff then got an independent adversarial review for behavior changes (comparator translation, nil/empty, context lifetimes, WaitGroup/Once ownership, aliasing, Cut edge cases, scope). Confirmed findings were fixed before this PR was opened.Final pre-merge review (Codex GPT-6 Astra, xhigh)
Before merge, an independent reviewer (
gpt-6-astra, reasoningxhigh, six parallel area sub-reviewers) read every non-tag hunk and every changed test hunk of the full diff. It also re-audited all JSON tag changes withgo/types: 1,238 of 1,238 fields are pointers (769) or bool/numeric (469), none hasIsZero, and 117 JSON/YAML-fallback/JSON-Schema before/after comparisons showed zero differences. The SDK generator--checkreproduced every generated byte.TestDaemonE2EMCPServeProjectsWorkspaceBoundHostAPI,TestDaemonNativeWorktreeJourneyE2E004) derived their timeout context fromt.Context(). That context drivesexec.CommandContextforcompozy mcp serveclients, which are closed int.Cleanup. Becauset.Context()is canceled before cleanups, the subprocess was killed first (MCP client.Close() error = signal: killedin the E2E runtime lane). Both tests are back to their originalcontext.Background()lifetime (782f514). The reviewer then traced 29 other hosted-MCP client call sites and cleared each one../...(e1f2049), and the gate integration suite has a regression case for it.packages/sitemarketplace-catalog.test.tsx("Should filter the current catalog…") takes about 4s in jsdom because of accessible-name role queries. That exceeded the 5s default when this broad change invalidated the turbo cache and all workspace suites ran concurrently (onmainthat run was a cache replay). The test now has the same15_000per-test budget the site suite already uses for heavy renders. Its assertions are unchanged (33d65d5).Verification
go build ./...,go veton the slice packages, race tests on every changed package (go test -race,-tags=integrationwhere the slice has integration tests), scopedmake go-lintwith 0 issues, and Windows cross-vet forterminal/ptyandprocutil.make codegenproduced no generated diff,make codegen-checkpasses, the marshal/YAML parity probes passed, and contract, spec, codegen and SDK race suites pass.magefiles(-tags=mage) andscripts(-tags=integration) suites pass, along with SDK/example/fixture build and vet. Probes for each new lint rule fire in every module.TestMCPAuthOwnerIsolation,TestOpen,TestManagerBusyInput*) now pass, plus the touched integration tests.make go-lint(whole config, every target): 0 issues on root (""tags), root (integrationModern Go pass),sdk/go, both SDK examples, both fixture modules, andmagefiles(magetag). The fmt lane passed on all 1,479 changed Go files.make verify-equivalent gates) is delegated to this PR's CI, per the maintainer's direction to keep heavy gates off the local machine. CI therefore stands in for the issue's "one currentmake gate-fullrecord" criterion.Acceptance criteria (#482)
net/httpfixtures were evaluated and kept.scripts/gate.shclassifies nested Go module changes and runs the relevant lint/test lanes.make go-lintreports zero warnings and errors on every target (run locally on the merged branch).make bun-lint(no JS changes) is verified by this PR's CI.33d65d533(35/35 required checks green: Go lint, all 8 race shards, Windows terminal, Darwin peer, build/boundaries, SDK race, preflight codegen, frontend, desktop, E2E runtime/web/desktop). It replaces the localmake gate-fullrecord per maintainer direction.Compozy impact audit
compozy__*descriptors, schemas, digests, risk flags and capability gates are byte-identical (make codegenshows no diff).workspace_idpropagation, or cache/event/SSE isolation changes.skills/compozy/): unchanged. No public behavior or tool-ID change.docs/runbooks/modern-go.md. No QA scenario changes, since nothing user-visible changed.config.tomlkey changes.🤖 Generated with Claude Code