Finalize release tooling implementation plan

This commit is contained in:
2026-11-03 15:36:23 +00:00
parent 3d396b1a66
commit cb40f1d9f8
2 changed files with 374 additions and 166 deletions

View File

@@ -0,0 +1,328 @@
# Release tooling implementation plan
Status: ready for the implementation sprint; Stages 1–6 are pending.
Follow the stages in integer order. This is one end-to-end sprint: intermediate
stages may temporarily leave scripts, tests, and documentation inconsistent.
Do not add compatibility scaffolding or repeat complete suites merely to make
each intermediate stage independently releasable. Follow the local commit
policy for completed, validated units; stage boundaries do not require commits.
The [feature roadmap](release-simplification.md) owns the target and selected
choices. Read [development guidance](../development.md), the
[agent policy](../policy/agents.md), [testing policy](../policy/testing.md),
[documentation policy](../policy/documentation.md), and the applicable
[release policy](../policy/release.md) before implementation. Use codebase-memory
tools for code discovery as instructed by `AGENTS.md`.
## Baseline and fixed decisions
Planning baseline: `3d396b1a66bfafc509472cd74a3f8029def3d432`. At that revision:
- `go.mod` registers ReleaseKit v0.8.0. The root module owns the selected tool
version even when releasing an integration. Keep that dependency selection,
all library module paths and versions, and Go minimums unchanged.
- Three JSON profiles select core, ckconfig, and ckprompt. Their only file
selection is the explicit root shared-file list; hosted delivery is absent.
- `scripts/release` is a 49-line native-build launcher. The 506-line
`scripts/release_test.go` and 399-line `scripts/release_integration_test.go`
contain the test scaffolding being replaced.
- `.releasekit/gitea-token` is a maintainer-supplied ignored credential file.
Its contents are not input to implementation or tests. Preserve the file and
directory ignore rule. Do not add the credential to fixtures, logs, or commits.
- Both integrations declare core v0.2.0, while their current source requires
newer APIs. Workspace-off Go 1.26.8 tests fail at baseline with missing
`commandkit.CompletionHint`, `Explanation`, and other symbols. This is an
existing release-readiness issue, not a reason to change dependency versions
or weaken validation in this sprint. Stage 5 distinguishes this limitation
from verification of the current source and selected file checks.
The former open decisions are resolved for this plan: select all four proposed
generic file checks and use host-normalized registered-tool execution. Add the
agreed forbidden token path and local page-only Gitea delivery. Keep ordinary
source publication and hosted delivery separate. No binary delivery, CI job,
library API change, dependency upgrade, or production publication is part of
this sprint. No implementation-blocking design question remains.
## Stage 1: Configure the three release profiles
Edit `releasekit.json`, `integrations/ckconfig/releasekit.json`, and
`integrations/ckprompt/releasekit.json`.
1. Preserve each profile's `product`, `module_dir`, `remote`,
`expected_push_url`, and explicit `validation.shared_files`. The endpoint
remains `ssh://git@forge.maximumdirect.net:22222/base-layer/commandkit.git`.
2. Add `validation.go_format: true`, `validation.markdown: {}`, and
`validation.module_distribution` with `workspace_files` and
`local_replacements` both true.
3. Add `validation.forbidden_files` containing only
`.releasekit/gitea-token`. This is a literal repository-relative selection
applying to the captured repository, including integration releases.
4. Add `delivery` with `forge: "gitea"`,
`base_url: "https://forge.maximumdirect.net"`, `owner: "base-layer"`,
`repository: "commandkit"`, and `token_file: ".releasekit/gitea-token"`.
Leave `token_env` omitted, preserving ReleaseKit's default environment
override. Add no build targets or additional validators.
5. Retain `/.releasekit/` in `.gitignore`; revise its comment from executable
storage to local ReleaseKit credentials. Do not remove existing local files.
Check that all three files parse as JSON. Use the pinned
[configuration reference](https://forge.maximumdirect.net/base-layer/releasekit/src/commit/23203f235cc414c4ffe0fd3941030eb0c9f9943f/docs/config.md)
for field semantics. Root file checks stop at independent module boundaries;
the forbidden-path check has its separately documented repository scope.
Do not create custom validators, broader forbidden lists, or blanket exclusions.
**Stage result:** the intended checks and delivery destination are represented
entirely by the existing upstream profile schema.
## Stage 2: Centralize tool invocation and module routing
Create executable POSIX-shell `scripts/releasekit` as the shared entry point.
Keep executable `scripts/release` as the existing publication convenience entry
point. No shell library, module-map file, generated script, or JSON parser is
needed in the launcher.
The shared entry point has these forms:
| Invocation | Handling |
| --- | --- |
| `./scripts/releasekit MODULE publish [ARGS...]` | Select module defaults and invoke upstream `publish`. |
| `./scripts/releasekit MODULE check [ARGS...]` | Select module defaults and invoke upstream `check`. |
| `./scripts/releasekit MODULE deliver [ARGS...]` | Select module defaults and invoke upstream `deliver`. |
| `./scripts/releasekit version [ARGS...]` | Forward without module/profile inference. |
| `./scripts/releasekit publication-attempts [ARGS...]` | Forward without module/profile inference. |
| `./scripts/releasekit reconcile [ARGS...]` | Forward without module/profile inference. |
`ARGS` are ordinary upstream arguments, including the version where required;
forward them as separate quoted arguments, without shell evaluation. This
wrapper covers the selected maintainer workflow; it does not reimplement the
ReleaseKit parser. Let upstream validate versions, flags, records, and candidate
state. Reject a missing selector/operation or unsupported wrapper form with
usage on stderr and status 2 before running Go. Preserve meaningful argv
boundaries; exact usage prose is not a compatibility target.
Implement the only selector mapping in `scripts/releasekit`:
| Selector | Module directory | Profile | Product for profile-wiring tests |
| --- | --- | --- | --- |
| `core` | `.` | `releasekit.json` | `CommandKit` |
| `ckconfig` | `integrations/ckconfig` | `integrations/ckconfig/releasekit.json` | `CommandKit ckconfig` |
| `ckprompt` | `integrations/ckprompt` | `integrations/ckprompt/releasekit.json` | `CommandKit ckprompt` |
Implementation details:
1. Resolve the repository root from the script location using quoted POSIX
shell operations safe with spaces and inherited `CDPATH`; change there.
2. Set `GOWORK=off` and `GOTOOLCHAIN=local` before querying Go. Resolve native
`GOHOSTOS` and `GOHOSTARCH` through the selected `go`, then export them as
`GOOS` and `GOARCH` for tool execution. Do not inherit a cross-build target.
3. Read the effective flags with `go env GOFLAGS`. Append `-mod=readonly` to
that string and export it as `GOFLAGS`, preserving the other effective
flags. Appending gives read-only selection precedence over an inherited
`-mod` setting. Do not parse or evaluate the string in the shell. Go 1.26.8
does not accept `go tool -mod=readonly`; do not use that unsupported form.
4. For module operations, prepend `OPERATION --repo ROOT --config ABS_PROFILE`.
For `publish` only, also prepend `--expected-module MODULE_DIR`. Neither
ordinary `check` nor `deliver` accepts that publication flag. Append the
supplied upstream arguments unchanged; upstream owns its flag semantics.
5. For the three raw forms, forward the command and supplied arguments without
adding profile, module, or publication flags. The working directory is the
repository root. Relative record paths therefore resolve there; document
absolute record paths in examples for clarity, without prohibiting relative
ones. Recovery identity comes from the selected saved record.
6. Finish through `exec go tool go.maximumdirect.net/releasekit/cmd/releasekit`.
Preserve the child's output streams and exit status. Do not create or build
an executable in `.releasekit/bin/`, preflight Gitea, or chain delivery after
publication.
Reduce `scripts/release` to checking its existing two-argument shape, then
executing the sibling helper with `MODULE publish VERSION`. Delegate selector
validation to that helper, avoiding a second mapping. Keep
`./scripts/release MODULE VERSION` usable from outside the repository.
**Stage result:** all selected operations share root-tool execution and one
module mapping; publication and delivery remain explicitly separate commands.
## Stage 3: Replace release-test scaffolding with focused wiring tests
Rewrite `scripts/release_test.go` around the actual scripts and a small fake Go
executable at the subprocess boundary. Remove
`scripts/release_integration_test.go` and helpers with no remaining users.
Use temporary directories, including a repository path with spaces and an
outside invocation directory. Copy the scripts and actual profiles into the
fixture. The fake Go needs only to answer the queried `go env` values and to
record the tool invocation, selected environment values, and controlled output
and status. Simple argument recording suffices: remove `goCall`, its bespoke
record parser, native-build assertions, and tests of assertion helpers. Do not
retain a fake build stage, fake publisher executable, Git repository fixture,
tag inspector, suite marker, or release-note generator.
Cover these behaviors with compact cases:
- Check the selector table against the copied profiles' module/product and the
selected destination, forbidden token path, shared files, and validation
selections. This checks CommandKit's choices, not upstream parsing semantics.
- Exercise each selector with `publish`, `check`, and `deliver`. Verify absolute
repository/profile arguments, publication-only `--expected-module`, and
unchanged forwarding of supplied upstream arguments.
- Exercise the legacy publication entry point and raw recovery/version forms.
Verify recovery receives the explicit record/options without inferred module
identity or a profile argument.
- Use foreign target values, workspace/toolchain overrides, and effective
`GOFLAGS` containing an unrelated flag and `-mod=mod`. The recorded tool
environment must select the host, disable workspace discovery, use the local
toolchain, preserve the unrelated flag, and give read-only mode precedence.
Assert effective settings rather than an incidental count/order of queries.
- Exercise statuses 0, 1, 2, and 3 on a representative operation, stdout/stderr
forwarding, and a nonzero legacy-publication result. Do not multiply all
module/operation combinations by all exit statuses.
- Exercise malformed wrapper invocations and confirm no Go command ran. Leave
invalid semantic-version and upstream-flag classification to ReleaseKit.
Use no credential file, authenticated request, or external service. Keep existing
domain package and maintained-consumer tests unchanged. Run the focused scripts
suite during development as needed; Stage 5 owns final complete validation.
**Stage result:** local tests protect CommandKit routing and invocation behavior;
upstream tests own publication, credential handling, and hosted reconciliation.
## Stage 4: Align current documentation with the implemented workflow
Update `docs/release.md`, the CommandKit-specific scope in
`docs/policy/release.md`, and release-tooling guidance in `docs/development.md`.
Keep adopted general policy text and provenance intact. Change current owners
with the implementation; the feature roadmap supplies the design rationale.
Document these concrete invocation examples, using placeholders rather than
selecting a new release version:
- Publish: `./scripts/release core vX.Y.Z`, with corresponding integration
selectors. Keep the existing core-then-ckconfig-then-ckprompt order.
- Diagnose: `./scripts/releasekit core check vX.Y.Z`; optional, never a required
step before publication repeats validation.
- Deliver: `./scripts/releasekit core deliver vX.Y.Z`, or either integration
selector with its own semantic version. The profile derives the full tag.
- Discover/reconcile: `./scripts/releasekit publication-attempts` and
`./scripts/releasekit reconcile --record /absolute/path/to/attempt.json`.
- Inspect the tool: `./scripts/releasekit version`.
Include the clean tagged-checkout prerequisite for delivery, later retries from
the original tagged source, the page-only body and module-specific full tags,
environment-token precedence over the repository-relative token file, and
retention of the ignored credential directory. Explain that successful source
publication completes the source release, while hosted delivery has a separate
outcome and URL. Credentials and Gitea availability do not gate publication.
Refer to upstream delivery and recovery contracts rather than duplicating an
HTTP implementation or a second status model.
Remove native executable-storage commands and the retired
`COMMANDKIT_RELEASE_INTEGRATION` exercise instructions. Explain that selected
upstream file checks inspect committed inputs, cover modules independently,
and do not replace domain review. Document future licensing footer URLs using
`https://forge.maximumdirect.net/base-layer/commandkit/src/tag/FULL_TAG/` plus
the correct repository-relative module file path. Keep existing published notes
and tags unchanged; add no speculative release note or historical backfill.
No CI workflow, provider call, runtime API, or attribution update is required.
Search affected documentation for stale `.releasekit/bin/` and retired test
references. Keep the credential-path references. Where baseline documentation
mentions a deleted source file, use its inline path and baseline revision
instead of leaving a broken local hyperlink. Keep stage tracking in this plan,
not in the feature roadmap.
**Stage result:** the maintainer runbook describes the actual wrapper commands,
selected checks, separate outcomes, and recovery without obsolete scaffolding.
## Stage 5: Verify the final source and record validation boundaries
Use Go 1.26.8 on `PATH`, `GOTOOLCHAIN=local`, and prepared dependency caches.
Reuse checks for unchanged final content instead of repeating them for each
stage. Preserve the existing ignored `go.work` (currently declaring Go 1.26.10);
use an external temporary Go 1.26.8 workspace when testing current source.
Perform the following one-time migration checks; add no persistent validation
script or new recurring publication gate:
1. Check shell syntax and executable modes for both scripts, parse the profiles,
review documentation links/fragments, and run `git diff --check`. Verify only
the intended files changed and the token remains ignored and untracked.
2. Exercise the real helper's `version` with foreign `GOOS`/`GOARCH`, an inherited
workspace, and an unrelated effective Go flag. Confirm ReleaseKit v0.8.0 runs
natively without changing module files. In a disposable module copy, remove
required tool checksum metadata and use inherited `-mod=mod`; confirm the
helper fails instead of repairing metadata. Do not alter the real sum files.
3. Review and stage only the intended sprint changes, including new files, for
verification. Obtain the staged tree with `git write-tree` and archive that
tree into a disposable directory; do not archive `HEAD` and accidentally
test the old implementation. Initialize and commit that snapshot in a new
local Git repository on `main`, with no copied tag refs or publication
remote. This verifies intended content before committing it in CommandKit.
Do not include ignored files, unrelated staged work, or real credentials.
Existing notes can label these local-only diagnostics: core `v0.3.0`,
integrations `v0.1.0`. No tag is created or reused in an authoritative
repository.
4. Build the pinned ReleaseKit executable once into temporary storage, using
the selected root module and read-only metadata. Run ordinary upstream
`check` on the snapshot's core profile with workspace discovery off. This
runs the root suite, including the new scripts tests, and all selected file
checks. Temporary native storage here is diagnostic setup, not launcher code.
5. For the integrations, create an external temporary workspace containing all
three snapshot modules. ReleaseKit v0.8.0 intentionally forces `GOWORK=off`
for its child suites, so exporting a workspace or alternate module-file flag
on the outer command cannot redirect those suites. For this diagnostic only,
put a temporary `go` shim on the executable's `PATH`: forward all invocations
to the absolute real Go binary, but for `go test` set `GOWORK` to that temporary
workspace before executing the real command. Do not skip tests or alter their
remaining arguments. Run upstream `check` for both integration profiles.
Real package suites then exercise current source; upstream file checks still
inspect unchanged committed inputs, including ordinary `go.mod` files. This
procedure was verified during planning and needs no committed helper.
6. Record workspace-backed integration results separately from independent
release-readiness evidence. The baseline standalone failures listed above
must remain visible. If needed, compare workspace-off tests with baseline to
distinguish new failures. Do not claim the shimmed diagnostic proves that
published dependencies are aligned, and do not add the shim to ordinary
`check`, `publish`, or the default test suite. Dependency/version alignment
and preparation of real integration candidates remain separate release work.
Planning evidence: the four generic file checks passed for the baseline core;
all five selected file checks passed for both baseline integration snapshots
using their real workspace-backed suites. The corresponding workspace-off
integration suites failed with the known missing-core-symbol errors. Repeat
the relevant diagnostics for the final sprint content, not merely the baseline.
Investigate new failures without turning the baseline limitation into a false
green result or disabling an agreed validator.
Do not invoke `publish`, `deliver`, or `ci-deliver` against a real destination
for verification. Configuration and forwarding are the local responsibility;
ReleaseKit owns authenticated preflight, hosted writes, and content matching.
**Stage result:** the changed infrastructure, real current-source suites, and
selected committed-file checks are verified, with independent integration
release-readiness limits accurately reported.
## Stage 6: Review, document completion, and commit
Review the complete diff against the feature roadmap. Confirm that all three
profiles have the selected options and destination; one shared launcher owns
module routing; the old publication exercise and unused helpers are gone;
domain tests remain; documentation uses the new invocation and separate
outcomes; and `/.releasekit/` still protects the local token directory.
Record stages completed and final validation results in this document, including
the dependency-version limitation. Do not retire these roadmap documents during
this sprint: retain the target and completion evidence for review, then apply
the normal roadmap lifecycle during later release preparation. No new release
version or source/hosted publication is required to finish this implementation.
Follow the local commit policy, review staged changes, and commit the intended
implementation units with short plain-English messages. Report the commit IDs,
remaining work, and verification limits. Preserve unrelated changes and private
files; do not force a clean worktree by deleting or including them. With only
the planned sprint changes present, the resulting tracked worktree should be
clean. Intermediate failures do not justify leaving the final selected scope
partially implemented.
**Stage result:** a reviewable, committed implementation of the selected target
with accurate validation evidence and no production publication.

View File

@@ -1,10 +1,11 @@
# Release tooling simplification
Status: implementation roadmap; no implementation has started. Local page-only
Gitea delivery and protection of the supplied token path are selected for
implementation. The recommendations in Open Decisions remain unselected.
Current release behavior stays with its canonical owners until implementation
updates them.
Status: target design finalized for the release-tooling sprint; implementation
has not started. All four generic file checks, registered-tool execution,
page-only hosted delivery, and protection of the supplied token path are selected.
The [implementation plan](implementation.md) owns stage order, tasks, validation,
and completion evidence. Current release behavior stays with its canonical owners
until implementation updates them.
## Purpose and authority
@@ -21,44 +22,6 @@ The [agent policy](../policy/agents.md),
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, and configure no hosted delivery.
- 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.
After the baseline review, the maintainer supplied the local credential file
`.releasekit/gitea-token`. Its contents were not read. The file was confirmed
ignored, untracked, and mode `0600`; authentication was not tested. The existing
directory ignore rule now serves credential storage as well as executable
storage and remains needed after executable-storage removal.
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
@@ -79,7 +42,7 @@ deliverables and platform support commitments remain unchanged.
### Profiles
Subject to OD-1, select these existing ReleaseKit options in each profile:
Select these existing ReleaseKit options in each profile:
| Selection | Intended protection |
| --- | --- |
@@ -88,7 +51,7 @@ Subject to OD-1, select these existing ReleaseKit options in each profile:
| `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. |
Separately from OD-1, select
Also select
`validation.forbidden_files: [".releasekit/gitea-token"]` in all three profiles.
This delegates protection of the supplied credential path to ReleaseKit's
existing check. The path is repository-relative and the check applies across
@@ -111,27 +74,25 @@ 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.
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.
read-only module metadata. Preserve other effective Go settings while arranging
read-only selection.
The implementation plan specifies the wrapper interface and invocation details.
Remove explicit executable storage when the launcher no longer creates it.
Retain `/.releasekit/` in `.gitignore` for the credential file, and update its
comment to describe that purpose. 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.
Go's cache supplies executable storage; the launcher creates no persistent
binary directory. `/.releasekit/` remains ignored for the credential file, with
an explanatory comment. Recovery instructions use the registered tool or the
entry point printed for the saved attempt, preserving ReleaseKit's distinction
between publication outcome and record-storage errors.
Share module selection and host-safe tool invocation between publication,
delivery, and recovery where applicable. Delivery selects the same module
profile as publication; recovery uses its recorded attempt rather than inferring
identity from a current profile. Keep the existing publication interface and
provide an explicit delivery invocation without automatically chaining the two
operations. Choose a small wrapper arrangement during implementation rather
than adding a coordination framework or duplicating selector tables.
operations. Keep one selector mapping and shared invocation plumbing.
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
@@ -204,115 +165,34 @@ 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 and delivery 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.
The resulting local suite omits the disposable publication exercise, generic
tag inspection, assertion-helper self-tests, and custom build-call log/parser.
Upstream publication and delivery coverage owns those generic behaviors. No
replacement publication engine or exported test-helper API is needed. There is
no line-count target for the replacement tests.
## Work from baseline to target
## Selected choices and rationale
### 1. Configure validation and hosted delivery
All four generic file checks are selected as release-time checks, in addition
to the agreed forbidden token path. Formatting and local-link validation automate
existing contributor review work. Workspace-file and filesystem-replacement
checks address accidental inclusion of development metadata that a successful
local test run can overlook. This adds specific release checks; it does not
make every optional ReleaseKit validator mandatory or prohibit development
workspaces and replacements outside the selected committed candidate inputs.
Selecting only formatting and Markdown would change less release behavior, but
would leave these distribution mistakes to manual review. The selected upstream
checks avoid a second local implementation.
- [ ] 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.
- [ ] Add the agreed delivery destination and forbidden token path to each
profile. Preserve the ignored token file and the directory ignore rule.
- [ ] 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 policy's delivery scope and the release procedure's
selected-check and hosted-delivery descriptions with the profile changes.
Host-normalized registered-tool execution is selected because the root module
already registers ReleaseKit and Go caches the executable. Retaining a persistent
native executable would provide a recovery entry point independent of a later
Go-driver invocation, but would retain executable-storage and bootstrap test
maintenance. Recovery instead uses the registered tool or ReleaseKit's reported
entry point. The credential directory remains ignored under either approach.
### 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
while retaining `/.releasekit/` for credentials and updating its comment.
Do not delete user-local files as part of the refactor.
- [ ] Expose explicit module-aware delivery using shared invocation plumbing.
Keep publication and delivery independently invocable and retryable.
- [ ] Update recovery commands, delivery prerequisites and retry instructions,
and token environment/file precedence. 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.
Check future-note guidance for module-specific full tags and immutable forge
links; do not rewrite published notes to adopt the new workflow.
- [ ] Verify delivery profile routing and operation forwarding with controlled
processes. Rely on upstream tests for Gitea authentication, HTTP writes, and
content reconciliation rather than adding a duplicate local delivery engine
suite. No real token or hosted writes are needed for these migration checks.
- [ ] 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, followed
by a separate hosted-delivery operation. Confirmed source publication remains
the source-release completion point; hosted-delivery failure is reported and
handled separately.
## 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.
The specific forbidden token path and page-only delivery are already selected
for implementation and are not part of this open decision.
**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 executable-storage test machinery and documentation, while
the directory ignore rule remains for the token. 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.
The implementation plan records the existing integration dependency-version
mismatch separately from validation of the current source. This infrastructure
sprint does not publish releases or select new library dependency versions.
Historical hosted-page backfilling and CI delivery remain separate future
choices, not prerequisites for the selected local page-only workflow.