Files
commandkit/docs/roadmap/release-simplification.md

228 lines
12 KiB
Markdown
Raw Normal View History

2026-11-03 15:21:51 +00:00
# Release tooling simplification
Status: proposed implementation roadmap. No implementation has started.
The recommendations in Open Decisions remain unselected. This document records
the intended simplification and the work to reach it; it does not add release
requirements or change public contracts by itself.
## Purpose and authority
Reduce CommandKit's release infrastructure to declarative module profiles,
a small launcher, and focused tests of CommandKit-owned wiring. Delegate
reusable candidate validation and publication mechanics to ReleaseKit while
retaining CommandKit's domain-specific checks in their existing owners.
The [agent policy](../policy/agents.md),
[release policy](../policy/release.md#candidate-validation), and
[testing policy](../policy/testing.md#upstream-integration-testing-ownership)
govern implementation. The [release procedure](../release.md) continues to own
the current workflow until implementation updates it.
## Current baseline
Baseline: CommandKit commit `a74fcb20041cbccde93f9b9a1e3b24cb8dd131e7`.
- The root [module](../../go.mod) selects
`go.maximumdirect.net/releasekit v0.8.0` as a Go tool. The release toolchain
remains Go 1.26.8, and the consumer minimum remains Go 1.26.0.
- [Core](../../releasekit.json),
[ckconfig](../../integrations/ckconfig/releasekit.json), and
[ckprompt](../../integrations/ckprompt/releasekit.json) have separate profiles.
They select their physical module directories, the current SSH endpoint, and
an explicit repository-root shared-file list. They enable no optional file
checks or additional product checks.
- The 49-line [launcher](../../scripts/release) maps the three selectors, changes
to the repository root, builds the root-selected tool into ignored
`.releasekit/bin/` storage for the host, and delegates publication to ReleaseKit.
- [Launcher tests](../../scripts/release_test.go) occupy 506 lines, including
custom command recording, fake build/publisher processes, and tests of the
assertion helpers themselves.
- The 399-line [publication exercise](../../scripts/release_integration_test.go)
creates disposable Git repositories, release notes, and suite markers. It
checks tag structure, exact remote objects, suite counts, nested tag prefixes,
and endpoint rejection in addition to exercising CommandKit's launcher.
- CommandKit's API, CLI, integration, and maintained consumer behavior is tested
in the owning package suites. There is no separate CommandKit-specific
candidate-validation implementation to replace or preserve.
During review, a temporary core profile enabled all four proposed file checks
below. ReleaseKit's local `check` accepted the committed core candidate with
Go 1.26.8. This was diagnostic evidence only: no profiles changed, no publication
occurred, and equivalent integration-module checks remain outstanding.
## Targeted end state
### Ownership
CommandKit retains module selectors, product identities, profile locations,
the authoritative endpoint selection, release order, release-note meaning,
compatibility decisions, and attribution accuracy. Its existing public API,
CLI, integration-adaptation, and consumer-example tests remain local and run
through the owning module's suite. No parallel release-only domain suite is
needed unless a concrete CommandKit requirement is otherwise unprotected.
ReleaseKit supplies the standard offline candidate suite, selected generic file
checks, candidate/note and publication guards, tag creation and publication,
outcome reporting, and recovery. CommandKit's launcher does not repeat those
operations. Existing release completion and immutability rules continue to
apply; this work adds no publication channel, binary deliverable, or platform
support commitment.
### Profiles
Subject to OD-1, select these existing ReleaseKit options in each profile:
| Selection | Intended protection |
| --- | --- |
| `validation.go_format: true` | Detect unformatted committed Go source. |
| `validation.markdown: {}` | Detect broken local Markdown destinations and supported heading fragments. |
| `validation.module_distribution.workspace_files: true` | Detect committed development workspace files in selected inputs. |
| `validation.module_distribution.local_replacements: true` | Detect filesystem replacements in selected committed module declarations. |
Retain the explicit shared-file lists and use ReleaseKit's existing input scope.
The root profile does not validate every nested module. File checks inspect
committed inputs and do not replace formatting worktree changes or reviewing
documentation meaning, attribution, and external links. Markdown keeps its
default treatment of outside-checkout destinations; no stricter boundary mode
is proposed.
The pinned [ReleaseKit configuration reference](https://forge.maximumdirect.net/base-layer/releasekit/src/commit/23203f235cc414c4ffe0fd3941030eb0c9f9943f/docs/config.md)
owns exact scope and behavior, including nested-module boundaries and vendored
inputs. Do not expand an option's scope into a general repository prohibition.
Race testing, full vet, compilation matrices, size limits, and forbidden-file
lists are not selected by this roadmap. They can be considered separately for
demonstrated needs.
### Launcher and recovery
Subject to OD-2, use the root module's registered `go tool releasekit` through
`exec`, keeping the current selector interface and publication argument mapping.
Retain host normalization, workspace-off execution, the local toolchain, and
read-only module metadata. Preserve other effective Go settings rather than
silently replacing them while arranging read-only selection. Go 1.26.8's
`go tool` does not accept `-mod=readonly` directly; use its supported Go settings
mechanism and verify the intended behavior.
Remove explicit executable storage and the dedicated ignore entry when the
launcher no longer creates that storage. Update recovery instructions to use
the registered tool or the entry point printed for the saved attempt. Preserve
ReleaseKit's distinction between publication outcome and record-storage errors.
A pending upstream request concerns host-safe consumer launcher examples and
regression coverage. It is not a dependency of this work: v0.8.0 already supports
registered tools. Keep host normalization locally because the reviewed
`go tool` invocation inherited foreign `GOOS`/`GOARCH` values and failed to run.
Do not switch tool-version selection from the root module to each integration
merely to match the upstream multi-module example.
### Focused local tests
Replace the release-test scaffolding with a small controlled Go-command boundary
that invokes the actual launcher. Cover:
- Selector-to-profile/module routing for core, ckconfig, and ckprompt, including
consistency with the checked-in profiles' intended module and product.
- Invalid argument handling before tool invocation.
- Invocation from another directory and paths containing spaces.
- Host normalization and workspace/toolchain/read-only settings.
- Publication argument, output-stream, and child exit-status forwarding.
Exercise module routing separately from exit statuses rather than multiplying
every combination. Assert behavior and meaningful selections, not helper
implementation details or exact usage prose.
Remove the disposable publication exercise and its Git fixtures, synthetic
notes, markers, tag inspection, and environment-isolation helpers when no longer
used. Remove assertion-helper self-tests and the custom build-call log/parser
with their obsolete consumers. Trust upstream publication-engine coverage;
do not move a duplicate suite into a different local package or export a new
test-helper API. There is no line-count target for the replacement tests.
## Work from baseline to target
### 1. Select profile checks
- [ ] Resolve OD-1 and record the chosen scope here.
- [ ] Update the three profiles for the selected options while preserving their
module identities, endpoint, and shared-file selections.
- [ ] Run the selected checks against each module's committed candidate inputs.
Review findings against existing contracts; fix relevant defects without
introducing broad exclusions or unrelated remediation by default.
- [ ] Update the release procedure's selected-check description in the same unit.
### 2. Simplify the launcher and its tests
- [ ] Resolve OD-2 and implement the selected invocation path.
- [ ] Add or adapt focused wiring tests before deleting the coverage they replace.
- [ ] Remove `scripts/release_integration_test.go`, assertion-helper self-tests,
and unused build/publisher scaffolding after reviewing their coverage ownership.
- [ ] If registered-tool execution is selected, remove executable-storage setup
and the dedicated `.releasekit/` ignore entry. Do not delete user-local files
as part of the refactor.
- [ ] Update recovery commands and remove obsolete opt-in publication-exercise
instructions from the release and development guides with the corresponding
behavior change.
### 3. Validate and finish
- [ ] Validate with Go 1.26.8 and prepared dependencies. Exercise the real
registered tool's host execution and read-only behavior once where the local
wiring tests use a controlled process; use nonpublishing operations.
- [ ] Run the owning module suites and selected ReleaseKit checks against the
final candidates. ReleaseKit `check` already runs the selected module's suite;
avoid repeating the same successful suite solely for another checklist item.
- [ ] Distinguish workspace behavior evidence from each module's independent
dependency graph. For disposable committed-candidate checks, use matching
notes and existing module metadata; do not invent future dependency versions
or checksums to make validation pass.
- [ ] Review the documentation, local links, and final diff. Confirm that
domain-specific package tests remain and that removed helpers have no users.
- [ ] Record validation results and completed work here. Retire the completed
roadmap through the usual documentation lifecycle when appropriate.
These are migration tasks, not additional permanent release gates. Verification
needs no production tag push or hosted delivery. Ordinary releases continue to
use one publication command, with no required preliminary `check` run.
## Open Decisions
### OD-1: Which optional checks become release gates?
**Recommendation:** Select all four options in the profiles table. Formatting
and local link checks automate existing contributor review work. The two module
distribution checks address accidental inclusion of development-only metadata
that a successful local test run can overlook. Reusing upstream mechanisms keeps
this protection declarative and avoids maintaining local checker code.
This is a deliberate addition to release-time validation, not merely deletion
of duplicate code. The observed core pass does not establish every module's
compatibility with the selected input scope. Resolve integration findings and
the applicability of vendored or fixture inputs before treating the selection
as adopted. Record the chosen release scope in the release procedure.
**Viable alternative:** Select formatting and Markdown now and defer the module
distribution checks. This automates familiar review work with less change to
accepted release contents, and preserves flexibility for legitimate committed
module fixtures. It leaves accidental workspace files or filesystem replacements
to ordinary review. Choose this alternative if the broader distribution checks
would reject justified inputs or their added protection does not warrant the
restriction. Do not compensate by writing equivalent local validators.
### OD-2: Registered tool or persistent native executable?
**Recommendation:** Use host-normalized `go tool releasekit`. The tool is already
registered in the root module, the Go cache supplies the executable, and the
launcher can forward its exit status without managing `.releasekit/bin/`.
This also removes storage-specific test machinery and documentation. Preserve
read-only metadata selection and test the effective environment before replacing
the current bootstrap.
**Viable alternative:** Retain the current native build and persistent executable
while simplifying profiles and tests. It is already proven to handle inherited
cross-build targets, accepts an explicit build-time read-only flag, and provides
a durable recovery entry point independent of a later Go-driver invocation.
It retains storage, bootstrap, and recovery-documentation maintenance, so it
removes less local infrastructure. Prefer it only if verification identifies a
meaningful recovery or tool-resolution need that the registered-tool path does
not meet; the pending upstream example change alone is not such a blocker.