2026-10-10 13:53:04 +00:00
|
|
|
|
# Remediation: module release implementation review
|
|
|
|
|
|
|
2026-10-10 15:06:10 +00:00
|
|
|
|
Status: open; issues 1–11 are complete, and issues 12–15 require remediation.
|
|
|
|
|
|
The initial review examined `90559fe`, compared with planning baseline `dbfae9e`.
|
|
|
|
|
|
The follow-up repository audit examined `6b0b8ce`, including those corrections.
|
2026-10-10 13:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
## Scope and evidence
|
|
|
|
|
|
|
|
|
|
|
|
The [feature roadmap](module-releases.md) and
|
|
|
|
|
|
[implementation plan](implementation.md) define the intended module-release
|
|
|
|
|
|
architecture. Most of that architecture is implemented: the two public facades,
|
|
|
|
|
|
shared module/tag derivation, scoped committed inputs with full reference lookup,
|
|
|
|
|
|
module-based Go execution, full-tag publication and hosted delivery, current-only
|
|
|
|
|
|
receipts, and tagged-source workflow selection.
|
|
|
|
|
|
|
|
|
|
|
|
The ordinary offline `go test ./...` suite and `go run ./internal/apicheck`
|
|
|
|
|
|
passed with Go 1.26.8. The findings below also use source inspection and temporary
|
|
|
|
|
|
fixtures outside the checkout. Publication reproduction used a private local
|
|
|
|
|
|
bare repository. No ReleaseKit source or real release refs were changed.
|
|
|
|
|
|
|
|
|
|
|
|
Each issue describes required work and verification. Preserve the selected
|
|
|
|
|
|
scope, existing error causes, publication/delivery outcomes, facade boundaries,
|
|
|
|
|
|
and clean API cutover. These corrections add no release, live-service, or human
|
2026-10-10 14:36:56 +00:00
|
|
|
|
review gates. Each completion record describes the correction and verification.
|
2026-10-10 13:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
## Issue 1: Resolve the actual Git repository root before release identity (P1)
|
|
|
|
|
|
|
2026-10-10 14:03:57 +00:00
|
|
|
|
Status: complete. Category: architecture gap and incorrect publication.
|
|
|
|
|
|
|
|
|
|
|
|
**Completion:** Source operations and CLI profile selection resolve the containing
|
|
|
|
|
|
Git checkout root before module selection. Regression tests verify that a child
|
|
|
|
|
|
directory cannot bypass a failing root suite or publish its tag, explicit nested
|
|
|
|
|
|
selection binds its own source and tag, aliases and independent worktrees retain
|
|
|
|
|
|
their identity, and dependency preparation works without Git. The focused public
|
|
|
|
|
|
API tests and candidate, delivery, CLI, and profile suites pass offline.
|
2026-10-10 13:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
**Evidence:** [candidate capture](../../internal/candidate/check.go) treats
|
|
|
|
|
|
`filepath.Abs(request.RepositoryDir)` as the repository root, and
|
|
|
|
|
|
[selection resolution](../../internal/releaseidentity/identity.go) uses that
|
|
|
|
|
|
directory as its base. Git committed-file paths are relative to the actual Git
|
|
|
|
|
|
root. Go commands instead execute in the supplied directory.
|
|
|
|
|
|
|
|
|
|
|
|
A temporary repository had a failing root suite, a passing module at
|
|
|
|
|
|
`apps/widget`, and a root release note. `Check` from the actual root failed.
|
|
|
|
|
|
`Check` with `RepositoryDir` set to `apps/widget` and omitted module selection
|
|
|
|
|
|
succeeded, reporting the root module's declared path and unprefixed `v0.1.0`
|
|
|
|
|
|
tag while executing the nested suite. `Publish` with that request successfully
|
|
|
|
|
|
pushed the root tag to the private fixture remote. The declared release unit
|
|
|
|
|
|
and validated release unit therefore differ.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Resolve the containing Git checkout's actual root at source
|
|
|
|
|
|
operation boundaries, then anchor repository-relative module and note paths to
|
|
|
|
|
|
that root. Carry that resolved repository identity through checks, publication,
|
|
|
|
|
|
builds, delivery, and CLI profile lookup. Normalize an input directory within the
|
|
|
|
|
|
checkout rather than introducing a blanket prohibition on such inputs. Keep
|
|
|
|
|
|
dependency preparation's own prerequisites separate; this correction should not
|
|
|
|
|
|
require a Git checkout merely to prepare a Go module's dependencies.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Repeat the failing-root/passing-nested fixture through both
|
|
|
|
|
|
`Check` and `Publish`, including default CLI invocation from a nested directory.
|
|
|
|
|
|
Omitted selection must validate the actual root module and prevent publication
|
|
|
|
|
|
when that suite fails. Explicit nested selection must bind its declaration,
|
|
|
|
|
|
note, suite, and prefixed tag consistently. Retain symlinked checkout and
|
|
|
|
|
|
independent worktree behavior.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 2: Preserve standalone Build error classification and partial evidence (P2)
|
|
|
|
|
|
|
2026-10-10 14:05:39 +00:00
|
|
|
|
Status: complete. Category: regression and incomplete failure evidence.
|
|
|
|
|
|
|
|
|
|
|
|
**Completion:** Standalone builds classify invalid versions before source access
|
|
|
|
|
|
and retain resolved selection and normalized build settings on identity failures.
|
|
|
|
|
|
Working-tree derivation preserves progressive identity evidence. Native CLI
|
|
|
|
|
|
validation reports invalid-version status 2 before repository access. Focused
|
|
|
|
|
|
API, native CLI, parser, identity, cancellation, and partial-artifact tests pass
|
|
|
|
|
|
offline.
|
2026-10-10 13:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
**Evidence:** [public Build](../../build.go) now calls working-tree identity
|
|
|
|
|
|
resolution before the internal builder. Invalid stable versions are returned by
|
|
|
|
|
|
`Derive` as ordinary formatted errors, bypassing the existing
|
|
|
|
|
|
`ErrInvalidVersion` identity. An API request with `bad-version` produced
|
|
|
|
|
|
`errors.Is(err, releasekit.ErrInvalidVersion) == false`; the compiled CLI exited
|
|
|
|
|
|
1 rather than its documented invalid-version status 2.
|
|
|
|
|
|
|
|
|
|
|
|
The same entry point returns only `Version` when identity resolution fails.
|
|
|
|
|
|
Selecting an existing nested directory with an invalid `go.mod` returned empty
|
|
|
|
|
|
repository and module fields, although both directories had already been
|
|
|
|
|
|
resolved. This contradicts the roadmap's progressive failure-evidence decision
|
|
|
|
|
|
and loses supplied build facts that the previous build boundary retained.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Preserve the existing invalid-version error at the build
|
|
|
|
|
|
entry boundary, including its classification before unrelated filesystem work.
|
|
|
|
|
|
Return available selection and build evidence when later declaration or identity
|
|
|
|
|
|
work fails. Share the appropriate conversion/resolution facts without resolving
|
|
|
|
|
|
the declaration again or inventing stronger source-verification guarantees.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Add API and native CLI cases for invalid versions, plus a
|
|
|
|
|
|
declaration failure after successful directory selection. Assert error identity,
|
|
|
|
|
|
exit classification, and available result fields. Keep cancellation causes and
|
|
|
|
|
|
later partial-artifact behavior intact.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 3: Use the module path base for relative prebuilt assets (P2)
|
|
|
|
|
|
|
2026-10-10 14:08:11 +00:00
|
|
|
|
Status: complete. Category: incomplete module path adoption.
|
|
|
|
|
|
|
|
|
|
|
|
**Completion:** Build output and CLI prebuilt assets share the selected module's
|
|
|
|
|
|
directory resolver. CLI and pending migration guidance describe the common base.
|
|
|
|
|
|
Local hosted regression tests verify root and nested relative build/delivery
|
|
|
|
|
|
pairs, absolute output, module binding, and rejection of changed artifact content
|
|
|
|
|
|
before hosted requests. Existing receipt/content checks and nested build cases
|
|
|
|
|
|
pass offline.
|
2026-10-10 13:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
**Evidence:** [CLI prebuilt delivery](../../cmd/releasekit/main.go) joins a
|
|
|
|
|
|
relative `--assets` directory to `invocation.Repository`. Builds now resolve
|
|
|
|
|
|
relative `--output` from the selected module. A nested profile's successful
|
|
|
|
|
|
`build --output dist v0.1.0` wrote
|
|
|
|
|
|
`apps/widget/dist/.releasekit-build.json`; the corresponding
|
|
|
|
|
|
`deliver --assets dist v0.1.0` attempted to open the repository-root receipt and
|
|
|
|
|
|
failed. The documented build/deliver pair therefore uses incompatible bases.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Resolve relative prebuilt asset directories from the same
|
|
|
|
|
|
selected module base as build output, using shared path normalization. Preserve
|
|
|
|
|
|
absolute directories and repository-relative profile lookup. Document the base
|
|
|
|
|
|
in the CLI owner and update affected examples and migration guidance.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Exercise a nested profile's relative build/output and delivery
|
|
|
|
|
|
pair using a local hosted fixture. Include the omitted root selection and an
|
|
|
|
|
|
absolute caller-owned asset directory. Verify module binding and content checks
|
|
|
|
|
|
still happen before hosted requests.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 4: Compare receipt repository identity consistently through aliases (P2)
|
|
|
|
|
|
|
2026-10-10 14:09:37 +00:00
|
|
|
|
Status: complete. Category: regression from mixed path normalization.
|
|
|
|
|
|
|
|
|
|
|
|
**Completion:** Receipt source and location comparisons use filesystem directory
|
|
|
|
|
|
identity, accepting aliases of the same checkout or output directory. Regression
|
|
|
|
|
|
tests build and deliver through a checkout symlink, retry through its physical
|
|
|
|
|
|
path, and reject different repositories and modules. Receipt structure, exact
|
|
|
|
|
|
release binding, and delivery-owned content checks remain intact. Receipt and
|
|
|
|
|
|
assembled prebuilt-delivery cases pass offline.
|
2026-10-10 13:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
**Evidence:** Release identity canonicalizes repository symlinks, so generated
|
|
|
|
|
|
receipts record the physical repository directory.
|
|
|
|
|
|
[`BuildReceipt.MatchesBuild`](../../cmd/releasekit/internal/cli/receipt.go) only
|
|
|
|
|
|
applies `filepath.Abs`/`Clean` to the supplied repository. A fixture built normally
|
|
|
|
|
|
and delivered with `--repo` pointing to a symlink of that same checkout, with
|
|
|
|
|
|
an absolute asset directory, failed the preliminary repository/settings comparison.
|
|
|
|
|
|
The delivery facade's shared resolver would identify the same repository.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Use consistent resolved repository identity for receipt
|
|
|
|
|
|
comparison, or leave source identity comparisons with the delivery owner that
|
|
|
|
|
|
already resolves and verifies them. Preserve structural receipt checks and exact
|
|
|
|
|
|
module/version/tag/commit binding. Avoid adding another declaration resolution
|
|
|
|
|
|
or a requirement that callers use one textual spelling of a checkout path.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Build and deliver through the same symlinked checkout argument,
|
|
|
|
|
|
and through its equivalent physical path. Both must identify the same source;
|
|
|
|
|
|
a genuinely different repository or module must still fail before hosted work.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 5: Keep Go environment reuse lazy and proportionate (P2)
|
|
|
|
|
|
|
2026-10-10 14:11:48 +00:00
|
|
|
|
Status: complete. Category: additional validation gates and unrequested restrictions.
|
|
|
|
|
|
|
|
|
|
|
|
**Completion:** Go discovery happens on acquisition for actual Go work. Completed
|
|
|
|
|
|
callbacks trigger no additional discovery; settings-file snapshot failures disable
|
|
|
|
|
|
reuse while preserving the Go tool's accepted configurations. Regression tests
|
|
|
|
|
|
cover check/publication completion after Go leaves PATH, subsequent builds needing
|
|
|
|
|
|
rediscovery, the final callback, unreadable GOENV snapshots, normal environment
|
|
|
|
|
|
and persistent-file changes, and cancellation. Focused public cases and complete
|
|
|
|
|
|
candidate and Go-tool suites pass offline.
|
2026-10-10 13:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
**Evidence:** [candidate coordination](../../internal/candidate/check.go) and
|
|
|
|
|
|
[publication](../../internal/publish/publish.go) eagerly call
|
|
|
|
|
|
[`Owner.Refresh`](../../internal/gotool/owner.go) after callbacks. A candidate
|
|
|
|
|
|
with successful standard validation and a successful additional callback that
|
|
|
|
|
|
left Git available but removed Go from `PATH` failed during rediscovery, although
|
|
|
|
|
|
no subsequent Go command or build was selected. `Acquire` already detects changed
|
|
|
|
|
|
inputs before actual Go work.
|
|
|
|
|
|
|
|
|
|
|
|
The owner also requires its settings-file snapshot to be readable. With `GOENV`
|
|
|
|
|
|
set to a directory, existing `gotool.New` and the Go discovery commands succeeded,
|
|
|
|
|
|
while `NewOwner(...).Acquire` failed on the added `os.ReadFile`. Go's acceptance
|
|
|
|
|
|
of its configuration has become narrower through a cache bookkeeping step.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Rediscover changed settings when a subsequent Go command
|
|
|
|
|
|
needs them. Preserve successful callback/operation completion when no more Go
|
|
|
|
|
|
work remains. Make snapshot limitations disable safe reuse or otherwise follow
|
|
|
|
|
|
the Go tool's effective behavior; they should not independently reject a
|
|
|
|
|
|
configuration that discovery accepts. Retain operation-local ownership, normal
|
|
|
|
|
|
settings-change detection, offline compilation, and separate preparation settings.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Cover a completed validation operation whose callback changes
|
|
|
|
|
|
environment inputs with no later build, and one whose subsequent build actually
|
|
|
|
|
|
needs rediscovery. Compare owner discovery with the underlying Go-tool behavior
|
|
|
|
|
|
when persistent settings cannot be snapshotted. Keep existing settings-change
|
|
|
|
|
|
and cancellation tests.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 6: Avoid requiring downloadable module paths for ordinary main modules (P2)
|
|
|
|
|
|
|
2026-10-10 14:12:50 +00:00
|
|
|
|
Status: complete. Category: unrequested restriction.
|
|
|
|
|
|
|
|
|
|
|
|
**Completion:** Identity derivation uses Go import-path lexical validation and
|
|
|
|
|
|
retains path-major compatibility. A valid non-domain main module now completes
|
|
|
|
|
|
candidate checking, native standalone compilation, and hosted page-only delivery
|
|
|
|
|
|
against a local fixture. Qualified and local major-version derivation, missing
|
|
|
|
|
|
and malformed declarations, and incompatible majors pass their focused offline
|
|
|
|
|
|
regression tests.
|
2026-10-10 13:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
**Evidence:** [`Derive`](../../internal/releaseidentity/identity.go) adds
|
|
|
|
|
|
`module.CheckPath`, including its requirement for a dot in the first path element.
|
|
|
|
|
|
A standard main module declared as `module example` passed `go test ./...` but
|
|
|
|
|
|
was rejected by standalone `Build` before any Go work. The
|
|
|
|
|
|
[Go module reference](https://go.dev/ref/mod#module-paths) permits main modules
|
|
|
|
|
|
that are not fetched as dependencies to use valid package paths.
|
|
|
|
|
|
|
|
|
|
|
|
The selected requirement is stable-version and path-major tag derivation.
|
|
|
|
|
|
Deriving a root or physical-directory tag does not require the declaration to
|
|
|
|
|
|
be a downloadable network module. No user decision imposed that extra
|
|
|
|
|
|
restriction on executable applications or local builds.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Validate the declaration and path-major facts needed by
|
|
|
|
|
|
identity derivation using Go's appropriate lexical rules for the supported
|
|
|
|
|
|
operations. Preserve standard major-version consistency. Remove the accidental
|
|
|
|
|
|
downloadability prerequisite rather than adding a consumer bypass setting.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Exercise a valid non-domain main module through standalone
|
|
|
|
|
|
build and representative check/page delivery, alongside ordinary qualified
|
|
|
|
|
|
module paths. Continue rejecting missing/invalid declarations and incompatible
|
|
|
|
|
|
major identities for the selected release convention.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 7: Resolve committed identity from committed material (P2)
|
|
|
|
|
|
|
2026-10-10 14:20:09 +00:00
|
|
|
|
Status: complete. Category: declaration-source divergence and added prerequisites.
|
|
|
|
|
|
|
|
|
|
|
|
**Completion:** Shared Git reference traversal now serves validation and committed
|
|
|
|
|
|
module identity. Committed selection follows directory and declaration links
|
|
|
|
|
|
using targeted object reads; working-tree builds retain filesystem selection.
|
|
|
|
|
|
CLI mapping and prebuilt path selection use committed directory facts. Regression
|
|
|
|
|
|
tests cover captured links, changed working declarations, cycles, checkout
|
|
|
|
|
|
boundaries, unavailable blobs, cancellation, and ordinary/prepared CI page-only
|
|
|
|
|
|
delivery from a sparse checkout without Go. The complete offline suite and
|
|
|
|
|
|
compiled public API/dependency checks pass.
|
2026-10-10 13:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
**Evidence:**
|
|
|
|
|
|
|
|
|
|
|
|
- `FromCommittedSelection` passes raw `git show` bytes to the declaration parser.
|
|
|
|
|
|
A committed `go.mod` symlink therefore supplies its link text. In a local
|
|
|
|
|
|
fixture, Go validation and working-tree identity succeeded while committed
|
|
|
|
|
|
identity reported no valid module directive. Existing committed validation
|
|
|
|
|
|
already has reference/symlink resolution.
|
|
|
|
|
|
- `ResolveSelection` also requires the selected module directory to exist in
|
|
|
|
|
|
the worktree through `EvalSymlinks`. A clean, correctly tagged sparse checkout
|
|
|
|
|
|
retained a nested module's declaration and note in Git but omitted its physical
|
|
|
|
|
|
directory. Page-only delivery failed on `lstat` before inspecting committed
|
|
|
|
|
|
identity. Its source was present and it needed no application compilation.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Separate filesystem execution selection from committed
|
|
|
|
|
|
source selection where their prerequisites differ. Resolve committed declarations
|
|
|
|
|
|
and directory/reference identity from the captured tree, retaining existing
|
|
|
|
|
|
checkout boundaries, cycle handling, missing-object errors, and cancellation.
|
|
|
|
|
|
Go execution may naturally require materialized source when it runs; page-only
|
|
|
|
|
|
metadata delivery should not gain that compilation prerequisite. Keep
|
|
|
|
|
|
working-tree builds tied to the declaration Go actually reads.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Cover an in-checkout committed declaration symlink and a
|
|
|
|
|
|
page-only nested release from a clean sparse checkout with available committed
|
|
|
|
|
|
objects. Verify committed/working-tree differences deliberately and retain
|
|
|
|
|
|
reference-cycle, outside-checkout, unavailable-content, and source-tag guards.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 8: Preserve literal shared filenames (P2)
|
|
|
|
|
|
|
2026-10-10 14:20:54 +00:00
|
|
|
|
Status: complete. Category: unrequested path prohibition.
|
|
|
|
|
|
|
|
|
|
|
|
**Completion:** Shared selection preserves literal backslashes in committed Git
|
|
|
|
|
|
paths. A Unix regression selects and reads such a file once despite duplicates;
|
|
|
|
|
|
traversal, absolute paths, and directories remain invalid selections. Existing
|
|
|
|
|
|
literal-metacharacter, missing/default/empty-list, scope, and lazy-input tests
|
|
|
|
|
|
pass offline.
|
2026-10-10 13:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
**Evidence:** [`normalizeSharedFile`](../../internal/validation/tree.go) rejects
|
|
|
|
|
|
every backslash. On Linux, a committed file named `docs/notice\copy.txt` is a
|
|
|
|
|
|
literal repository-relative file, but explicit selection failed as `shared-files`.
|
|
|
|
|
|
The roadmap selected literal individual paths and ordinary normalization without
|
|
|
|
|
|
globs; it did not exclude legal filename characters for committed inputs.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Preserve literal committed path characters under the chosen
|
|
|
|
|
|
repository-path convention. Keep absolute/outside-repository and directory
|
|
|
|
|
|
selection checks needed for the agreed scope. Introduce neither glob expansion
|
|
|
|
|
|
nor a portability restriction on otherwise valid committed filenames.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** On a filesystem where backslash is a literal filename
|
|
|
|
|
|
character, select the committed file successfully. Retain traversal, missing
|
|
|
|
|
|
explicit files, literal metacharacters, deduplication, and empty/default-list
|
|
|
|
|
|
coverage.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 9: Separate synthetic bootstrap versions from maintained examples (P2)
|
|
|
|
|
|
|
2026-10-10 14:27:47 +00:00
|
|
|
|
Status: complete. Category: broken adoption example and incomplete cutover guidance.
|
|
|
|
|
|
|
|
|
|
|
|
**Completion:** Maintained module skeletons no longer pin synthetic releases.
|
|
|
|
|
|
Example setup explicitly selects compatible released tooling and documents source
|
|
|
|
|
|
verification in disposable checkouts. Workflow fixtures generate their synthetic
|
|
|
|
|
|
declarations. Current-source tool registration and all three example profiles,
|
|
|
|
|
|
including native version injection, pass offline; mapped launchers/workflows and
|
|
|
|
|
|
tagged-tool retries retain isolated fixtures. Adoption and migration guidance
|
|
|
|
|
|
cover coordinated tool/workflow upgrades and historical retries. The pending
|
|
|
|
|
|
release notes record concrete example pins as normal version-selection work.
|
2026-10-10 13:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
**Evidence:** All three maintained
|
|
|
|
|
|
[multi-module declarations](../../examples/multi-module/) require ReleaseKit
|
|
|
|
|
|
`v0.2.197`. This is a synthetic test version served by
|
|
|
|
|
|
[`writeWorkflowToolProxy`](../../cmd/releasekit/multi_module_woodpecker_test.go),
|
|
|
|
|
|
whose executable forwards to the separately compiled current test binary.
|
|
|
|
|
|
A read-only query of the authoritative repository returned `v0.3.0` and no
|
|
|
|
|
|
`v0.2.197` tag. The copyable example cannot obtain its declared release tool
|
|
|
|
|
|
through ordinary module resolution.
|
|
|
|
|
|
|
|
|
|
|
|
Published pre-feature tooling also lacks the new profile/flag interface. The
|
|
|
|
|
|
maintained workflows always pass `--prepared`, and mapped launchers additionally
|
|
|
|
|
|
pass `--expected-module`. Migration guidance does not explain that adopting the
|
|
|
|
|
|
new workflow requires a compatible tool declaration, or that an older tag's
|
|
|
|
|
|
tool declaration requires its matching historical workflow for a retry.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Confine synthetic versions to test-owned module files and
|
|
|
|
|
|
proxies. Make the maintained example's setup explicitly select a ReleaseKit
|
|
|
|
|
|
version containing this feature, and update its concrete release dependency
|
|
|
|
|
|
during normal release preparation when that version is selected. Keep setup
|
|
|
|
|
|
usable for local source verification without fabricating a published release.
|
|
|
|
|
|
Document tool/workflow cutover and historical retry guidance in the pending
|
|
|
|
|
|
release notes and adoption owners. Maintain the clean API cutover; add no flag,
|
|
|
|
|
|
receipt, or source-identity compatibility shim.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Tests generate their own synthetic dependency declarations
|
|
|
|
|
|
instead of relying on fake versions committed in the copyable example. Verify
|
|
|
|
|
|
the setup's selected tool accepts the actual new interface, using current source
|
|
|
|
|
|
and isolated fixtures offline. Preserve tagged-source tool-version selection and
|
|
|
|
|
|
test-owned caches. This adds no live module-service completion gate.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 10: Remove the repeated boundary scan from file selection (P2)
|
|
|
|
|
|
|
2026-10-10 14:29:27 +00:00
|
|
|
|
Status: complete. Category: code quality and avoidable computational cost.
|
|
|
|
|
|
|
|
|
|
|
|
**Completion:** File selection indexes boundary directories and looks up each
|
|
|
|
|
|
entry's ancestors. Existing ordering, vendor/shared selection, full reference
|
|
|
|
|
|
lookup, and reader/cache behavior pass the complete offline validation suite.
|
|
|
|
|
|
A component benchmark retains 20,000 inputs with 0, 1,000, and 4,000 boundaries.
|
|
|
|
|
|
On this host, the 4,000-boundary case decreased from about 2.73 seconds to 38
|
|
|
|
|
|
milliseconds per selection; the new cases ranged from 29 to 38 milliseconds.
|
|
|
|
|
|
These are illustrative measurements without timing gates or input limits.
|
2026-10-10 13:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
**Evidence:** [`selectInputEntries`](../../internal/validation/tree.go) loops
|
|
|
|
|
|
over all nested-module boundaries for every candidate entry. This costs
|
|
|
|
|
|
`O(files × boundaries)` even when the retained input set is unchanged.
|
|
|
|
|
|
Temporary committed-tree fixtures with 20,000 retained files took approximately
|
|
|
|
|
|
0.5 seconds with no boundaries, 1.0 second with 1,000 boundaries, and 2.8 seconds
|
|
|
|
|
|
with 4,000 boundaries. These timings include metadata reads and are illustrative
|
|
|
|
|
|
local measurements, not performance contracts.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Use direct ancestor-boundary lookup or another straightforward
|
|
|
|
|
|
path-based selection that avoids scanning every unrelated boundary for each file.
|
|
|
|
|
|
Preserve one ordered input set, vendor handling, path deduplication, explicit
|
|
|
|
|
|
shared files, full reference lookup, and selective content-reader ownership.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Retain the existing scope behavior tests and add a representative
|
|
|
|
|
|
component benchmark varying boundary count with the retained file count fixed.
|
|
|
|
|
|
Verify the algorithmic improvement without adding timing thresholds, input caps,
|
|
|
|
|
|
or new validation policies.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 11: Reconcile documentation with implemented scope and status (P3)
|
|
|
|
|
|
|
2026-10-10 14:36:56 +00:00
|
|
|
|
Status: complete. Category: incomplete documentation adoption and misleading contracts.
|
|
|
|
|
|
|
|
|
|
|
|
**Completion:** Facade GoDoc and canonical API, CLI, configuration, Gitea, and
|
|
|
|
|
|
internal guidance describe selected inputs, full-tag uniqueness, module-local
|
|
|
|
|
|
notes, shared-file scope, committed references, and lazy Go reuse consistently.
|
|
|
|
|
|
The feature roadmap identifies its historical baseline and completed stages,
|
|
|
|
|
|
with this review recording the corrections. Consumer-owned license layouts and
|
|
|
|
|
|
note links are distinguished from optional validation defaults. ReleaseKit's
|
|
|
|
|
|
root release policy and procedure retain their existing requirements. Reviewed
|
|
|
|
|
|
root/nested examples, verified local links/fragments across 37 Markdown documents,
|
|
|
|
|
|
checked example JSON/shell syntax and whitespace, and passed the final complete
|
|
|
|
|
|
offline suite and compiled API/dependency checks.
|
2026-10-10 13:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
**Evidence:**
|
|
|
|
|
|
|
|
|
|
|
|
- [Configuration](../config.md), [CLI](../cli.md),
|
|
|
|
|
|
[check guidance](../consumers/check.md), and
|
|
|
|
|
|
[publication guidance](../consumers/publish.md) still describe formatting as
|
|
|
|
|
|
including nested-module source. `Check` GoDoc similarly says local-replacement
|
|
|
|
|
|
inspection includes nested modules. Automatic input selection now excludes
|
|
|
|
|
|
independent nested modules, retaining vendor and explicitly selected files.
|
|
|
|
|
|
- Check guidance retains the old short-version wording for note location and
|
|
|
|
|
|
tag uniqueness. The new identities use physical module-local notes and full
|
|
|
|
|
|
tags, allowing equal semantic versions across modules.
|
|
|
|
|
|
- [The feature roadmap](module-releases.md) still says the feature is planned
|
|
|
|
|
|
and module selection is not implemented, while the implementation plan claims
|
|
|
|
|
|
completion. Its baseline needs to be identified as the starting baseline.
|
|
|
|
|
|
- [Gitea guidance](../integrations/gitea.md) presents root shared-license and
|
|
|
|
|
|
footer locations as an unconditional layout. Describe the default convention
|
|
|
|
|
|
and consumer-owned note links accurately; shared-file validation selection
|
|
|
|
|
|
supplies neither a license-location guarantee nor automatic footer rewriting.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Refresh each affected canonical owner using the implemented
|
|
|
|
|
|
selected-input and full-tag semantics. Mark feature status accurately, including
|
|
|
|
|
|
these open remediation items, while retaining useful decision context and the
|
|
|
|
|
|
historical starting baseline. Preserve ReleaseKit's own root release policy.
|
|
|
|
|
|
Update migration/examples alongside the behavior corrections above.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Review GoDoc and canonical guidance against the current code;
|
|
|
|
|
|
check root/nested examples, note and tag wording, roadmap status, local links,
|
|
|
|
|
|
fragments, and Markdown whitespace. Keep exact contract definitions at their
|
|
|
|
|
|
canonical owners.
|
2026-10-10 15:06:10 +00:00
|
|
|
|
|
|
|
|
|
|
## Follow-up audit
|
|
|
|
|
|
|
|
|
|
|
|
The follow-up reviewed module identity, candidate validation and publication,
|
|
|
|
|
|
builds, receipts, delivery, Go/process ownership, committed reference handling,
|
|
|
|
|
|
facade conversions, CLI/profile mapping, maintained workflows, documentation,
|
|
|
|
|
|
and the eleven previous corrections. The complete offline suite and compiled
|
|
|
|
|
|
API/dependency checks pass with Go 1.26.8. The additional findings below were
|
|
|
|
|
|
reproduced with temporary local repositories, a filtered sparse clone, a Git
|
|
|
|
|
|
transport stub, and a local HTTP server. The artifact-read evidence also used
|
|
|
|
|
|
`strace`. This audit changes the remediation document only.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 12: Resolve module paths consistently across declaration sources (P2)
|
|
|
|
|
|
|
|
|
|
|
|
Status: open. Category: inconsistent release-unit selection.
|
|
|
|
|
|
|
|
|
|
|
|
**Evidence:** [Filesystem selection](../../internal/releaseidentity/identity.go)
|
|
|
|
|
|
cleans the joined module path before following symlinks. Committed selection
|
|
|
|
|
|
uses [component traversal](../../internal/git/path.go), following a symlink
|
|
|
|
|
|
before processing a subsequent `..`. The same selection can consequently
|
|
|
|
|
|
identify different physical modules in an unchanged, clean checkout.
|
|
|
|
|
|
|
|
|
|
|
|
A fixture contained root and `nested` modules, a tracked directory
|
|
|
|
|
|
`nested/deep`, and `link -> nested/deep`. With `ModuleDir: "link/.."` and
|
|
|
|
|
|
`Version: "v0.1.0"`, public `Build` succeeded with the root module and tag
|
|
|
|
|
|
`v0.1.0`; public `Check` succeeded with the nested module and tag
|
|
|
|
|
|
`nested/v0.1.0`. Working-tree and committed declaration readers independently
|
|
|
|
|
|
confirmed the difference. Dependency preparation uses the filesystem selector,
|
|
|
|
|
|
while candidate and delivery operations use committed selection.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Give filesystem and committed selection the same component
|
|
|
|
|
|
and symlink semantics for identical paths in an unchanged checkout. Preserve
|
|
|
|
|
|
the agreed declaration source for each operation, support for working-tree
|
|
|
|
|
|
changes and committed sparse selection, checkout boundaries, and progressive
|
|
|
|
|
|
identity evidence. Module paths containing `..` need consistent resolution;
|
|
|
|
|
|
this correction does not require prohibiting those paths.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Exercise a tracked directory symlink followed by `..` through
|
|
|
|
|
|
standalone build, candidate check, dependency preparation, and representative
|
|
|
|
|
|
delivery. An unchanged checkout must identify the same physical module and tag
|
|
|
|
|
|
across operations. Retain deliberate committed/working-tree declaration
|
|
|
|
|
|
differences, ordinary aliases, cycles, and outside-checkout failures.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 13: Reuse local asset verification through the complete delivery path (P2)
|
|
|
|
|
|
|
|
|
|
|
|
Status: open. Category: incomplete verification ownership and redundant I/O.
|
|
|
|
|
|
|
|
|
|
|
|
**Evidence:** [Delivery](../../internal/delivery/delivery.go) calls
|
|
|
|
|
|
`VerifyLocalAssets` before hosted requests. After release and attachment
|
|
|
|
|
|
inspection, [UploadMissing](../../internal/gitea/upload.go) calls
|
|
|
|
|
|
`verifyLocalAsset` again for every missing attachment. Both calls stream and
|
|
|
|
|
|
hash each local binary. The upload then reads it a third time to send its bytes.
|
|
|
|
|
|
Stages 8 and 9 of the [implementation plan](implementation.md) select one
|
|
|
|
|
|
delivery-owned content-verification pass.
|
|
|
|
|
|
|
|
|
|
|
|
A public prebuilt-delivery fixture completed against a local HTTP server with
|
|
|
|
|
|
one missing binary and its manifest. A system-call trace recorded three complete
|
|
|
|
|
|
reads of the binary: the delivery preflight, the uploader's repeated verification,
|
|
|
|
|
|
and the multipart upload. Receipt loading is already free of artifact hashing;
|
|
|
|
|
|
the remaining duplicate sits across the delivery/Gitea boundary. The current
|
|
|
|
|
|
asset-preflight benchmark ends before that second verification.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Reuse the completed local verification in the assembled
|
|
|
|
|
|
delivery path so each binary receives one delivery-time digest-and-size pass
|
|
|
|
|
|
before hosted requests, followed by its necessary upload stream. Preserve
|
|
|
|
|
|
validation for independently used internal client operations, build-time
|
|
|
|
|
|
hashing, deterministic manifests, actual remote-content comparison, additive
|
|
|
|
|
|
retry behavior, caller-owned files, and existing failure outcomes.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Observe file reads across a complete public binary delivery
|
|
|
|
|
|
with missing attachments, covering the uploader as well as preflight. Establish
|
|
|
|
|
|
one verification read plus the upload read. Keep tampered/missing-file rejection
|
|
|
|
|
|
before hosted requests and matching-asset/partial-retry cases. Measure the whole
|
|
|
|
|
|
local path without timing thresholds or additional source guarantees.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 14: Keep committed release-note inspection within the local object boundary (P2)
|
|
|
|
|
|
|
|
|
|
|
|
Status: open. Category: incomplete earlier offline-inspection correction.
|
|
|
|
|
|
|
|
|
|
|
|
**Evidence:** [ReadCommitFile](../../internal/git/source.go), used by candidate
|
|
|
|
|
|
capture and delivery for release notes, executes `git show` through the ordinary
|
|
|
|
|
|
Git runner. Its child does not receive the lazy-fetch and transport controls
|
|
|
|
|
|
used by `ReadBlob`, committed-path lookup, tree inspection, and the batch reader.
|
|
|
|
|
|
An unavailable note in a partial clone can therefore initiate remote transport
|
|
|
|
|
|
during source inspection. The earlier correction in `0205001` and its partial
|
|
|
|
|
|
clone tests cover the other object readers, leaving this entry point uncovered.
|
|
|
|
|
|
|
|
|
|
|
|
A clean filtered sparse clone had its root declaration and Go source locally
|
|
|
|
|
|
available, with the committed note omitted and its blob unavailable locally.
|
|
|
|
|
|
Public `Check` resolved the root identity, then invoked a fixture SSH transport
|
|
|
|
|
|
while reading `docs/releases/v0.1.0.md`. The stub recorded the attempt and exited;
|
|
|
|
|
|
the resulting error reported failure to fetch the note from the promisor remote.
|
|
|
|
|
|
The fixture contacted no external service.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Read committed note bytes through the same local-only object
|
|
|
|
|
|
boundary as the other source-inspection readers. Return an inspection error
|
|
|
|
|
|
when required objects are unavailable locally, preserving path context,
|
|
|
|
|
|
cancellation, underlying Git causes, and exact note bytes. Explicit checkout
|
|
|
|
|
|
and dependency preparation retain their network-capable responsibilities.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Cover direct committed-file reading and representative
|
|
|
|
|
|
candidate/delivery note inspection in filtered clones with unavailable note
|
|
|
|
|
|
objects. A controlled transport stub must remain unused, and inspection must
|
|
|
|
|
|
leave the object database unchanged. Existing ordinary note reads and explicit
|
|
|
|
|
|
network-capable preparation must continue to work.
|
|
|
|
|
|
|
|
|
|
|
|
## Issue 15: Limit blob availability requirements to selected validation inputs (P2)
|
|
|
|
|
|
|
|
|
|
|
|
Status: open. Category: module-scope leakage through eager metadata enrichment.
|
|
|
|
|
|
|
|
|
|
|
|
**Evidence:** [ReadCandidateTreeForScope](../../internal/validation/tree.go)
|
|
|
|
|
|
calls [ReadTree](../../internal/git/source.go) before constructing module and
|
|
|
|
|
|
shared-file inputs. `ReadTree` asks `populateBlobSizes` for every repository blob
|
|
|
|
|
|
and fails on any unavailable object. Excluded modules and unreferenced files
|
|
|
|
|
|
therefore become availability prerequisites for a selected module's file checks,
|
|
|
|
|
|
even when the selected check needs no blob sizes.
|
|
|
|
|
|
|
|
|
|
|
|
In a clean filtered sparse clone, the root module's source, declaration, and
|
|
|
|
|
|
note were available; independently scoped `nested` module blobs were omitted.
|
|
|
|
|
|
Public root `Check` succeeded with ordinary validation. Enabling `GoFormat`
|
|
|
|
|
|
with an explicit empty shared-file list made the same check fail during size
|
|
|
|
|
|
enumeration on the unavailable blob for `nested/deep/placeholder`. That file
|
|
|
|
|
|
belongs to the excluded nested module and is neither a formatting input nor a
|
|
|
|
|
|
referenced destination.
|
|
|
|
|
|
|
|
|
|
|
|
**Required change:** Separate full repository path/type/object metadata from
|
|
|
|
|
|
blob enrichment. Construct the agreed input set before acquiring required blob
|
|
|
|
|
|
sizes or contents, and inspect referenced destinations when a check actually
|
|
|
|
|
|
needs them. Keep full lookup available without requiring every unrelated blob
|
|
|
|
|
|
locally. Preserve selected-input ordering, boundaries, vendor/shared selection,
|
|
|
|
|
|
size semantics, local-only reads, cancellation, and reader ownership.
|
|
|
|
|
|
|
|
|
|
|
|
**Verification:** Use a filtered sparse fixture with a complete selected module
|
|
|
|
|
|
and unavailable blobs in an excluded sibling or nested module. Representative
|
|
|
|
|
|
formatting, file-size, and explicit shared-file validation must work when their
|
|
|
|
|
|
required inputs are available. A selected missing blob or required referenced
|
|
|
|
|
|
destination must still produce the appropriate inspection error. Verify that
|
|
|
|
|
|
excluded unreferenced blobs cause neither content reads nor transport.
|