Refocus release audit on developer effort

This commit is contained in:
2026-10-06 15:17:51 +00:00
parent e146a5c61e
commit 85b2b39fb6

View File

@@ -1,43 +1,41 @@
# ReleaseKit pre-release audit # ReleaseKit pre-release audit
Date: 2026-10-06. Reviewed source: `536a57916f6565ae8194c4563577dfcebd6cfb69`. Date: 2026-10-06. Reviewed source: `536a57916f6565ae8194c4563577dfcebd6cfb69`.
Status: findings and recommendations; no design changes adopted by this document. Status: review findings and proposed changes, revised for the clarified product goals.
Audience: maintainers deciding the shared release standard before `v0.1.0`. Audience: maintainers deciding the shared release standard before `v0.1.0`.
## Assessment ## Assessment
ReleaseKit is a sound foundation for the intended standard, but I recommend ReleaseKit's practical goals are to minimize application-owned release code,
resolving two reproduced correctness defects and one demonstrated build-standard duplication across the suite, and the time developers spend on release processes.
gap before tagging it. Its publication Shared conventions serve these goals by giving routine decisions one owner.
and delivery separation, narrow public facades, standard artifact naming, Applications supply product facts and product-specific checks; ReleaseKit owns
version injection, and content-aware delivery retries are worth retaining. the procedure, sensible defaults, and recovery guidance.
The implementation covers most of the mechanics in the
[product roadmap](releasekit.md). It does not yet demonstrate both
[architectural success criteria](../policy/architecture.md#success-criteria):
substantial removal of consumer infrastructure and adoption of one coherent
standard. Those require representative adoption evidence.
The main architectural choices have concrete benefits: annotated tags preserve The core direction is sound. Retain the publication/delivery separation, narrow
the checked-in note and provide an exact object for recovery; requiring the public facades, standard artifact naming, version injection, and content-aware
candidate on authoritative `main` keeps branch publication out of the release retries. Fix the reproduced validation and recovery defects in F1–F2 before
transaction; and separate delivery prevents a hosting outage from redefining `v0.1.0`. Treat F3 as a focused improvement to internal build defaults.
source-release success. None needs replacement to achieve the stated goals.
Selected build targets and product-specific checks are appropriate variation;
independent implementations of the publication transaction are not.
The larger design opportunity is to make ReleaseKit own more of the ordinary Build-environment reproducibility, hardware-specific configurability, and
path: a standard validation baseline, a declared build environment, and shared extensive build inspection are outside the product's optimization goals. Use the
delivery orchestration usable equally through Go and the CLI. Today, consumers available compatible Go toolchain and shared baseline settings. Evaluate new
can still supply an entire replacement validation process, repeat CI setup, and configuration and deployment machinery by the application code and developer
assemble binary delivery themselves when using the Go API. These are supported work they save. Different toolchains may produce different bytes; existing
choices, not violations of the present contracts, but they weaken the stated published content remains protected by digest comparison.
objective of minimizing variation.
Compatibility with existing consumer scripts is not a reason to preserve these The implementation covers most mechanics in the [product roadmap](releasekit.md).
choices. The recommendations below favor a coherent long-term standard, while Representative adoption should demonstrate the
retaining product identity, target selection, compatibility decisions, and [architectural success criteria](../policy/architecture.md#success-criteria)
product-specific behavioral checks with the consumer. They do not propose through deleted release code, fewer duplicated checks, and fewer routine decisions.
mandatory new lint, race, signing, live-service, or approval gates. F4–F6 identify opportunities to centralize validation, delivery, and CI setup.
The existing source transaction supports these goals. Annotated tags preserve
the checked-in note and provide an exact object for recovery. Requiring the
candidate on authoritative `main` keeps branch publication in preparation.
Separate delivery lets source publication finish independently of hosting.
Consumer migrations should adopt this common process and retain product identity,
target selection, compatibility decisions, and product-specific checks.
## Scope and evidence ## Scope and evidence
@@ -45,13 +43,13 @@ Reviewed the development guide; agent, architecture, testing, documentation, and
release policies; facade ADR; roadmap; public declarations; CLI/configuration release policies; facade ADR; roadmap; public declarations; CLI/configuration
and consumer guides; publication, build, delivery, Git and Gitea implementations; and consumer guides; publication, build, delivery, Git and Gitea implementations;
and their relevant tests and workflow examples. The and their relevant tests and workflow examples. The
[release policy](../policy/release.md) governs ReleaseKit's own releases; its [release policy](../policy/release.md) governs ReleaseKit's own releases.
requirements are not automatically imposed on every consumer API operation. The facade and integration contracts define consumer behavior.
Also inspected the release scripts, module declarations, and available delivery Also inspected the release scripts, module declarations, and available delivery
YAML in the six sibling projects named by the roadmap. This was a read-only YAML in the six sibling projects named by the roadmap. This read-only sample
sample of adoption needs, not an audit or migration of those repositories. informed the assessment of adoption needs.
Their existing extra checks are evidence to evaluate, not requirements to copy. Existing extra checks should be retained according to their product-specific value.
For example, PromptKit has product-specific executable examples, whereas For example, PromptKit has product-specific executable examples, whereas
Narratio currently requires Go 1.26 and several peers require Go 1.25.5. Narratio currently requires Go 1.26 and several peers require Go 1.25.5.
@@ -61,14 +59,13 @@ Validation on Linux/amd64 with Go 1.26.8:
passed on the reviewed checkout. passed on the reviewed checkout.
- `go run ./internal/apicheck` passed. - `go run ./internal/apicheck` passed.
- Isolated probes against an archive of the reviewed commit reproduced F1–F3 - Isolated probes against an archive of the reviewed commit reproduced F1–F3
below. They used temporary consumer repositories and local bare Git remotes; below. They used temporary consumer repositories and local bare Git remotes.
no production refs, credentials, or hosted content were used.
The probes were investigative tests in a disposable checkout, not additions to The investigative probes ran in a disposable checkout. Their setup and outcomes
the default suite. Their setup and outcomes are recorded with each finding so are recorded with each finding for future regressions. Validation covered local
regressions can be written against the intended fixes. No live Gitea or fixtures on Go 1.26.8. Live Gitea/Woodpecker integration, published-module
Woodpecker deployment, published-module installation, or minimum-Go-1.25 run was installation, and minimum-Go-1.25 compatibility remain unverified. These results
performed. The test pass therefore does not establish those properties. belong to the original source review; this revision updates its recommendations.
## Goal coverage ## Goal coverage
@@ -77,10 +74,10 @@ performed. The test pass therefore does not establish those properties.
| One standard source-publication transaction | Substantially implemented in [Publish](../../internal/publish/publish.go): captured candidate, authoritative `main`, annotated tag, exact object/ref push, and bounded recovery. F2 is a correctness exception. | | One standard source-publication transaction | Substantially implemented in [Publish](../../internal/publish/publish.go): captured candidate, authoritative `main`, annotated tag, exact object/ref push, and bounded recovery. F2 is a correctness exception. |
| One validation of the intended candidate | Callback/default validation plus mutable-state rechecks are implemented in [candidate](../../internal/candidate/check.go). F1 can silently narrow the default suite; F4 concerns the selected customization model. | | One validation of the intended candidate | Callback/default validation plus mutable-state rechecks are implemented in [candidate](../../internal/candidate/check.go). F1 can silently narrow the default suite; F4 concerns the selected customization model. |
| Consumer-selected binaries or source-only releases | [Build](../../internal/build/build.go) supports target pairs and empty sets. Source-only delivery creates no binary manifest. This is the right distinction. | | Consumer-selected binaries or source-only releases | [Build](../../internal/build/build.go) supports target pairs and empty sets. Source-only delivery creates no binary manifest. This is the right distinction. |
| Shared runtime version, build flags, naming, and smoke check | Implemented through [buildinfo](../../buildinfo/version.go), the builder, and external consumer build tests. F3 leaves important build inputs ambient. | | Shared runtime version, build flags, naming, and smoke check | Implemented through [buildinfo](../../buildinfo/version.go), the builder, and external consumer build tests. F3 identifies an opportunity for predictable internal defaults. |
| Immutable hosted contents and recoverable partial delivery | [Delivery](../../internal/delivery/delivery.go) and [Gitea](../../internal/gitea/) compare notes and asset bytes, reject conflicts, and add missing assets. F7 identifies an outcome-reporting inconsistency. | | Immutable hosted contents and recoverable partial delivery | [Delivery](../../internal/delivery/delivery.go) and [Gitea](../../internal/gitea/) compare notes and asset bytes, reject conflicts, and add missing assets. F7 identifies an outcome-reporting inconsistency. |
| Public contract ownership and small runtime dependency graph | Root and runtime facades follow [ADR 0001](../adr/0001-public-facade.md); compiled boundary checks pass. Keep these boundaries. | | Public contract ownership and small runtime dependency graph | Root and runtime facades follow [ADR 0001](../adr/0001-public-facade.md); compiled boundary checks pass. Keep these boundaries. |
| Thin application integration and less repeated infrastructure | Plausible but not demonstrated by consumer adoption. F5–F6 identify remaining orchestration and setup duplication. | | Thin application integration and less repeated infrastructure | Representative consumer adoption remains to be evaluated. F5–F6 identify remaining orchestration and setup duplication. |
| Ready deployment path | Prepared templates and local fixtures exist. Immutable deployment pins, credentials, activated workflows, and live verification remain explicitly open in the roadmap. | | Ready deployment path | Prepared templates and local fixtures exist. Immutable deployment pins, credentials, activated workflows, and live verification remain explicitly open in the roadmap. |
## Findings ## Findings
@@ -104,27 +101,26 @@ The [Go command documentation](https://pkg.go.dev/cmd/go#hdr-Environment_variabl
confirms that `GOFLAGS` supplies defaults to commands that recognize its flags. confirms that `GOFLAGS` supplies defaults to commands that recognize its flags.
**Consequence.** A normal developer setting used for focused testing can cause a **Consequence.** A normal developer setting used for focused testing can cause a
release to pass without the complete default suite. The caller need not edit release to pass after skipping the default suite. The reproduction uses an
source or intentionally bypass validation. unchanged committed candidate and an ordinary shell setting.
**Recommendation.** Make the standard validation command own its effective Go **Recommendation.** Make the standard validation command own its effective Go
flags and host target, including values supplied through Go's persistent flags and host target, including values supplied through Go's persistent
configuration. Preserve caches and legitimate dependency preparation settings. configuration. Preserve caches and legitimate dependency preparation settings.
Use one internal Go-environment policy shared with the builder where appropriate; Share internal Go-environment handling where the semantics match. Preserve
do not give validation the builder's `CGO_ENABLED=0` blindly. A standard native the settings appropriate to native tests and static release builds separately.
test run and a static release build have different needs. Apply the same baseline Apply the same baseline to ReleaseKit's own profile. Retain a regression showing
to ReleaseKit's own profile. Retain a regression that proves a failing test that a failing test remains effective under an ambient filter. F4 and Open Question 1 address how
cannot disappear under an ambient filter. F4 and Open Question 1 address how
intentional product-specific checks should compose with this baseline. intentional product-specific checks should compose with this baseline.
### F2 — High: automatic push recovery can query a different endpoint and report false absence ### F2 — High: automatic push recovery can query a different endpoint and report false absence
**Evidence.** [reconcilePush](../../internal/publish/publish.go) calls **Evidence.** [reconcilePush](../../internal/publish/publish.go) calls
`Endpoint.QueryTag` using the captured URL and command-scoped remote. `Endpoint.QueryTag` using the captured URL and command-scoped remote.
[QueryTag](../../internal/git/tag.go) does not call [QueryTag](../../internal/git/tag.go) runs the query directly.
`verifyScopedURLs`, although [Resolve/Recheck](../../internal/git/remote.go) [Resolve/Recheck](../../internal/git/remote.go) call `verifyScopedURLs` before
use that verification before publication. Git still applies current URL rewrite publication. Git still applies current URL rewrite configuration to the captured
configuration to the captured literal URL. The manual recovery instructions in literal URL. The manual recovery instructions in
[the runbook](../release.md#resolve-failures) already require a URL-equality check. [the runbook](../release.md#resolve-failures) already require a URL-equality check.
The automatic path lacks the equivalent check. The automatic path lacks the equivalent check.
@@ -137,25 +133,21 @@ shows the exact tag object returned in `PublicationResult` is present.
**Consequence.** The result gives incorrect recovery advice after an ambiguous **Consequence.** The result gives incorrect recovery advice after an ambiguous
push. It converts a query to the wrong endpoint into proof that the intended push. It converts a query to the wrong endpoint into proof that the intended
endpoint lacks the published tag. This contradicts an existing recovery endpoint lacks the published tag. This contradicts the existing recovery
contract; it is not a request for broader filesystem or transport hardening. contract for the authoritative endpoint.
**Recommendation.** Within the existing bounded recovery context, verify that the **Recommendation.** Within the existing bounded recovery context, verify that the
captured endpoint still resolves to itself before the one authoritative tag captured endpoint still resolves to itself before the one authoritative tag
query. If verification fails, preserve the push error and local tag and return query. If verification fails, preserve the push error and local tag and return
`unknown`. Do not resolve the remote name anew and substitute its current `unknown`. Keep recovery bound to the captured endpoint. Cover the
endpoint. Cover both the successful-publication/false-absence reproduction and successful-publication/false-absence reproduction and ordinary recovery against
an ordinary unchanged-endpoint recovery. No extra read-back gate is needed after an unchanged endpoint. Preserve successful push as the completion point.
a successful push.
### F3 — High for binary adoption: target identity omits effective build inputs ### F3 — Internal improvement: ambient CPU settings change binary compatibility
**Evidence.** `goEnvironment` in [internal/build/build.go](../../internal/build/build.go) **Evidence.** `goEnvironment` in [internal/build/build.go](../../internal/build/build.go)
standardizes several Go settings but inherits architecture feature variables, standardizes several Go settings and inherits architecture feature variables,
`GOEXPERIMENT`, and the persistent Go environment file. Build identity records `GOEXPERIMENT`, and the persistent Go environment file.
GOOS/GOARCH and compiler text, but not those effective inputs. The
[receipt](../../cmd/releasekit/internal/cli/receipt.go) and public `BuildResult`
cannot distinguish their effects.
**Reproduction.** Build the same committed consumer and `v1.2.3` for **Reproduction.** Build the same committed consumer and `v1.2.3` for
`linux/amd64` twice, once with `GOAMD64=v1` and once with `GOAMD64=v2`. `linux/amd64` twice, once with `GOAMD64=v1` and once with `GOAMD64=v2`.
@@ -165,23 +157,20 @@ records the respective feature levels. Go documents these as different target
microarchitecture requirements in its microarchitecture requirements in its
[environment reference](https://pkg.go.dev/cmd/go#hdr-Environment_variables). [environment reference](https://pkg.go.dev/cmd/go#hdr-Environment_variables).
**Consequence.** Identical declared targets can require different CPUs and yield **Consequence.** A developer's ambient CPU setting can narrow a binary's hardware
conflicting bytes during delivery retries. Existing content comparison correctly compatibility. Different build inputs can also produce a digest conflict during
refuses replacement, but cannot make an undeclared build environment repeatable. a delivery retry. Existing digest comparison correctly preserves published bytes.
A clean Git checkout does not resolve this; `SourceVerified` correctly makes no This finding supports predictable defaults; its earlier high-priority assessment
attestation claim. This is a gap in the desired shared build standard, rather placed too much weight on build-environment standardization.
than a violation of a documented promise of fixed CPU baselines or reproducible
bytes. The missing selection should be made deliberately before binary adoption.
**Recommendation.** Select documented baseline architecture features for the **Recommendation.** Use ordinary baseline CPU settings and shared build flags
supported targets and control the relevant environment and Go configuration internally, with the available compatible Go toolchain. Control incidental
file. Choose the release toolchain explicitly and preserve that selection with settings that affect expected compatibility or validation. Keep the application
the tagged declaration or immutable delivery environment. If custom feature profile focused on its package, binary name, and targets. Exact toolchain
levels are supported, declare them and include them in artifact/build identity. pinning and detailed build metadata remain optional operational choices.
Do not silently derive them from a developer shell. Reuse the selected inputs When a retry requires the original bytes, preserve and reuse those artifacts.
for candidate builds and tagged delivery. See Open Question 2 for the tradeoff Open Question 2 compares local toolchain use with a centrally maintained build
between a fixed baseline and richer declared variants. This recommendation does environment for consumers that benefit from shared setup.
not promise universally reproducible or hermetic builds.
### F4 — Design priority: adding a custom check replaces the entire standard suite ### F4 — Design priority: adding a custom check replaces the entire standard suite
@@ -193,43 +182,41 @@ replacement `Validate` callback.
**Consequence.** Adding one product-specific example check requires the consumer **Consequence.** Adding one product-specific example check requires the consumer
to remember and reproduce the standard test command, environment, and ordering. to remember and reproduce the standard test command, environment, and ordering.
The profile becomes a small alternative release program. This relocates shared The profile becomes a small release program that repeats shared policy. Migrating
policy instead of fully centralizing it. Conversely, simply adding mandatory to built-in tests requires removing their invocation from existing custom scripts
default tests to the current behavior would run them twice for existing check to preserve one suite run.
scripts that already run the suite.
**Recommendation.** Before first adoption, select a baseline-plus-additional-checks **Recommendation.** Run the shared offline suite once, followed by optional
model, with a narrow explicit way to express a justified alternative test product-specific checks. Move redundant suite invocations out of consumer scripts.
invocation when necessary. Migrate redundant suite invocations out of consumer Retain checks for actual product behavior, such as PromptKit's examples. Add
scripts. Keep only checks for actual product behavior, such as PromptKit's alternative test-invocation settings when a concrete consumer requirement
examples. Do not preserve every consumer's race/vet/build loop merely to avoid justifies them. This proposal changes the current customization contract; Open
breaking their old workflow. This is a proposed contract change, not a bug fix; Question 1 records the replacement-callback alternative.
Open Question 1 records a viable replacement-callback alternative.
### F5 — Design priority: the CLI owns reusable tagged-build delivery orchestration ### F5 — Design priority: the CLI owns reusable tagged-build delivery orchestration
**Evidence.** [runDelivery](../../cmd/releasekit/main.go) chooses a temporary **Evidence.** [runDelivery](../../cmd/releasekit/main.go) chooses a temporary
output directory, invokes the public builder, converts receipts, and then calls output directory, invokes the public builder, converts receipts, and then calls
`Deliver`. The [public delivery request](../../delivery.go) accepts an already `Deliver`. The [public delivery request](../../delivery.go) accepts an already
produced `BuildResult`, not a build declaration. A Go consumer wanting the normal produced `BuildResult`. A Go consumer wanting the normal build-and-deliver
build-and-deliver operation must reproduce orchestration that CLI consumers get operation must reproduce orchestration already implemented by the CLI. The
for free. The default CLI path also builds and runs the native smoke executable default CLI path also builds and runs the native smoke executable
before `Deliver` verifies that HEAD matches the selected local tag. before `Deliver` verifies that HEAD matches the selected local tag.
**Consequence.** Temporary storage, build sequencing, tagged-source preflight, **Consequence.** Temporary storage, build sequencing, tagged-source preflight,
and cleanup have more than one potential owner. An invalid tagged checkout can and cleanup have more than one potential owner. An invalid tagged checkout can
consume a complete cross-build before it is rejected. The CLI does use supported consume a complete cross-build before it is rejected. The CLI owns domain coordination
facades, but owns more domain coordination than the architecture's parsing, alongside its parsing, presentation, and exit-status responsibilities.
presentation, and exit-status responsibility suggests.
**Recommendation.** Put the ordinary verify-tagged-source, build-selected-targets, **Recommendation.** Put the ordinary verify-tagged-source, build-selected-targets,
and deliver sequence behind the orchestration facade. Verify the local tagged and deliver sequence behind the orchestration facade. Verify the local tagged
source before expensive compilation, then retain the necessary checks before source before expensive compilation, then retain the necessary checks before
remote effects. Let the CLI adapt JSON, credentials, and output to that operation. remote effects. Let the CLI adapt JSON, credentials, and output to that operation.
Use the same build declaration for candidate validation and delivery. Decide Use the same build declaration for candidate validation and delivery. Decide
whether caller-provided builds remain an advanced supported mode, as discussed whether a concrete consumer needs caller-provided builds, as discussed in
in Open Question 3. Keep the private receipt as local coordination data if that Open Question 3. Keep separate building useful for local development. The ordinary
mode remains; do not promote it into a provenance or portable-attestation format. consumer workflow should complete delivery in one invocation; advanced artifact
handoffs can use private coordination data when needed.
### F6 — Adoption priority: shared deployment still depends on copied mechanics ### F6 — Adoption priority: shared deployment still depends on copied mechanics
@@ -241,31 +228,27 @@ the CLI already supports combined delivery. ReleaseKit's
[own workflow](../../examples/woodpecker/releasekit-source-delivery.yml) has a [own workflow](../../examples/woodpecker/releasekit-source-delivery.yml) has a
separate first-release bootstrap. Consumer pins remain placeholders as documented. separate first-release bootstrap. Consumer pins remain placeholders as documented.
**Consequence.** Core library duplication is reduced, but routine CI mechanics **Consequence.** Copied CI mechanics require maintenance in each consumer and
still become consumer-owned copies that can drift. A chosen ReleaseKit version can drift. A shared installation and update convention would simplify local
and Go toolchain also need a clear installation/update convention for both local publication and CI delivery.
publication and CI delivery. Merely requiring every application to invent a
wrapper would leave part of the roadmap's original problem unsolved.
**Recommendation.** Provide a maintained, versioned integration entry point and **Recommendation.** Provide one maintained integration entry point and one
one default delivery sequence for both source-only and binary profiles. Keep default delivery sequence for source-only and binary profiles. Consumers select
product declarations, immutable tool/toolchain pins, and secret references in the ReleaseKit version, supply product settings, and provision credentials.
consumer configuration. Keep network-enabled dependency preparation separate Centralize installation and update instructions. Choose source installation or a
from offline validation/builds. Splitting build and delivery is justified when maintained image according to the setup and maintenance effort each saves.
it establishes an actual credential or artifact handoff boundary, not simply Keep dependency preparation separate from offline validation/builds. A split
because both commands exist. See Open Question 4 for packaging alternatives. build/delivery flow remains useful for an actual credential boundary or artifact
ReleaseKit's bootstrap can remain special until the first version is available. handoff. See Open Question 4 for packaging alternatives.
The current workflow tests are useful but narrower than their names may imply.
`TestWoodpeckerDeliveryCommandSequences` in `TestWoodpeckerDeliveryCommandSequences` in
[the CLI workflow tests](../../cmd/releasekit/woodpecker_test.go) executes [the CLI workflow tests](../../cmd/releasekit/woodpecker_test.go) executes
equivalent commands; equivalent commands;
[the ReleaseKit workflow test](../../cmd/releasekit/releasekit_delivery_workflow_test.go) [the ReleaseKit workflow test](../../cmd/releasekit/releasekit_delivery_workflow_test.go)
similarly reconstructs the sequence. They do not execute the maintained YAML similarly reconstructs the sequence. Execution of the maintained YAML and
through Woodpecker or exercise the pinned installation step. A YAML drift can installation step remains unverified. A YAML drift can leave these tests green.
therefore leave those tests green. Validate the actual selected integration at Validate the selected integration during adoption and keep a small check tied to
adoption, and keep a small check tied to the maintained artifact. This is the maintained artifact. Use that evidence to maintain the shared integration.
integration-development evidence, not a new per-release live-service gate.
### F7 — Medium: delivery asset classifications overlap inconsistently ### F7 — Medium: delivery asset classifications overlap inconsistently
@@ -278,19 +261,18 @@ can also remain pending. The existing
[upload_test.go](../../internal/gitea/upload_test.go) explicitly expects the [upload_test.go](../../internal/gitea/upload_test.go) explicitly expects the
same asset in both pending and uncertain collections. same asset in both pending and uncertain collections.
**Consequence.** Public consumers cannot treat the collections as consistent **Consequence.** Overlapping categories require special handling by consumers.
categories. The CLI can present one file as both pending and uncertain, while a The CLI can present one file as both pending and uncertain, while a
slightly different failure reports it only as uncertain. The overall unknown slightly different failure reports it only as uncertain. The overall unknown
state is conservative, so this is not a false-success defect, but it makes state remains conservative. Consistent categories would simplify recovery
recovery reporting and automation less clear. reporting and automation.
**Recommendation.** Prefer mutually exclusive current-outcome categories: **Recommendation.** Prefer mutually exclusive current-outcome categories:
confirmed matching, uploaded, known pending, conflicting, and uncertain. Move an confirmed matching, uploaded, known pending, conflicting, and uncertain. Move an
asset out of pending when its outcome becomes uncertain or conflicting, and asset out of pending when its outcome becomes uncertain or conflicting, and
clarify the facade GoDoc. Alternatively, explicitly define pending as a superset clarify the facade GoDoc. Alternatively, explicitly define pending as a superset
of all unfinished assets and implement that rule consistently; see Open of all unfinished assets and implement that rule consistently; see Open
Question 5. Update the behavioral tests to protect the selected meaning instead Question 5. Update behavioral tests to protect the selected meaning.
of preserving inconsistent branch bookkeeping.
### F8 — Maintainability: artifact rules have several implementation owners ### F8 — Maintainability: artifact rules have several implementation owners
@@ -310,137 +292,114 @@ why divergent Go-environment ownership matters beyond cosmetic duplication.
**Recommendation.** Give internal build/artifact rules one owner and reuse them **Recommendation.** Give internal build/artifact rules one owner and reuse them
from receipt and delivery adapters. Share Go invocation/environment construction from receipt and delivery adapters. Share Go invocation/environment construction
where the semantics actually match. Keep explicit facade conversions required where the semantics match. Keep the explicit facade conversions required
by the ADR; replacing them with public aliases would trade a little duplication by the ADR. Focus refactoring on the small internal helpers that own these rules.
for a larger compatibility burden. Do not introduce a generic workflow engine,
plugin registry, or public Git/Gitea implementation packages to solve these
localized problems.
## Recommended standard and release sequencing ## Recommended standard and release sequencing
Retain the existing source transaction: committed stable-version note, clean Retain the existing source transaction: committed stable-version note, clean
`main`, candidate already on authoritative `main`, one validation, selected-target `main`, candidate already on authoritative `main`, one validation, selected-target
build verification, exact annotated-tag publication, and bounded ambiguity build verification, exact annotated-tag publication, and bounded recovery.
recovery. Source publication finishes independently of hosted delivery. Keep Source publication finishes independently of hosted delivery. Keep additive,
additive, content-checked delivery and lightweight runtime version access. content-checked delivery and lightweight runtime version access.
Strengthen that standard around a small committed declaration: product identity, Make ordinary integration a versioned tool invocation plus a small product
selected binary targets, explicit toolchain/build choices, delivery destination, profile and credential provisioning. The profile supplies product identity,
and product-specific checks added to the shared validation baseline. The ordinary selected binaries and targets, delivery destination, and product-specific checks.
consumer integration should be a pinned tool invocation plus that declaration ReleaseKit owns the standard suite, routine build settings, delivery sequence,
and secret provisioning. Authoring compatibility notes and choosing the version and recovery reporting. Product developers choose versions and write
remain product decisions; ReleaseKit need not guess them from commit messages. compatibility notes. Evaluate each proposed setting by the work it saves them.
Recommended order: Recommended order:
1. Fix F1–F3 and retain focused behavioral regressions. F1–F2 affect the first 1. Fix F1–F2 and retain focused behavioral regressions before tagging `v0.1.0`.
source release itself; F3 should be resolved before advertising standard 2. Settle the validation and delivery API choices in Open Questions 1 and 3.
binary adoption. Adopt clear result categories under Question 5. Implement the selected
2. Decide Open Questions 1–3 and 5 before settling the first public API and changes with their canonical documentation and consolidate F8 in those owners.
configuration contracts. Implement the selected changes, including F7, with 3. Address F3 through internal compatibility defaults, using Open Question 2 to
their canonical GoDoc/configuration/consumer documentation. Consolidate F8 keep build configuration proportionate to actual consumer needs.
while touching those owners. 4. Exercise one source-only consumer with an extra product check and one binary
3. Prove one representative source-only integration with an extra product check consumer through the common integration. Measure removed scripts, duplicated
and one binary integration using the selected common workflow. Identify the tests, setup steps, and recurring release decisions. Keep ReleaseKit's default
actual scripts and duplicated tests removable from each. Temporary local suite independent of sibling checkouts.
adoption trials can precede a published module; do not make sibling checkouts 5. Choose the simplest shared installation and update path under Open Question 4.
dependencies of ReleaseKit's normal build or default suite. Verify the maintained integration during deployment preparation. Follow the
4. Select the packaging direction in Open Question 4, prepare immutable pins and existing maintainer procedure for the release note and source publication;
credentials, and test the actual workflow/service integration separately. report hosted delivery separately.
First-source-release bootstrap is legitimate; live artifact availability
still does not become a source-publication completion gate.
5. Prepare the `v0.1.0` note and follow the existing maintainer procedure once the
selected pre-release work is complete. This audit does not tag or publish.
Not every possible release feature belongs in this first version. There is no Feature expansion should follow demonstrated consumer needs and measurable
review evidence requiring a general multi-module release engine, prerelease reductions in application maintenance or developer effort.
channels, multi-program bundles, arbitrary packaging hooks, mandatory signatures,
or stronger source attestations. Add such capabilities for an adopted need,
without weakening the ordinary shared path to accommodate hypothetical cases.
## Open Questions ## Open Questions
### 1. Should product checks supplement or replace standard validation? ### 1. Should product checks supplement or replace standard validation?
**Recommended:** Run the shared offline suite once, followed by declared **Recommended:** Run the shared offline Go suite once, followed by optional
product-specific checks. Where a product truly needs a different invocation of product-specific checks. ReleaseKit owns the command and its routine environment
that same suite, expose a narrow explicit selection with documented semantics, settings. Migrate repeated suite invocations out of application scripts. Add
not an unrestricted implicit replacement. This centralizes the shared obligation alternative invocation settings when an actual consumer requirement establishes
while allowing meaningful product checks and avoiding duplicate tests. Remove their value. This gives developers one ordinary validation path to understand.
old suite invocations when migrating custom scripts.
**Viable alternative:** Keep the current replacement callback/command list and **Viable alternative:** Keep a replacement callback or complete validation
make each product own one complete validation command. This is idiomatic for a command for products with unusual test layouts. This is a simple composition
small Go orchestration library and accommodates unusual test layouts without an boundary and can accommodate existing product test infrastructure. It assigns
expanding configuration schema. It is optimal if validation is intentionally a more release responsibility to the application, so its value depends on the
consumer boundary; it is less aligned with the user's goal of maximal shared specific consumer need.
standardization. Adoption guidance and tests would need to establish the common
baseline rather than assuming the library enforces it.
### 2. How much of the build environment belongs in release identity? ### 2. How should ReleaseKit choose build settings?
**Recommended:** Standard baseline feature levels and flags, plus an explicitly **Recommended:** Use the available compatible Go toolchain, ordinary baseline CPU
selected toolchain preserved with the release inputs or an immutable build-image settings, and shared build flags. Handle incidental environment settings internally
pin. Control ambient feature/experiment settings and persistent Go configuration. so developers can rely on the selected target's expected compatibility. Keep
Keep cache locations and dependency access during preparation operational. application configuration small. Toolchain-dependent byte differences are
Different products can select toolchains meeting their modules' requirements; acceptable; digest checks preserve existing published content, and retained
standardization is the selection mechanism, not forcing every product onto an artifacts support retries requiring the same bytes.
inadequate Go version. This minimizes accidental variants and makes retries
explainable without claiming hermeticity.
**Viable alternative:** Declare a richer target variant including CPU features, **Viable alternative:** A shared CI image can supply a centrally selected Go
build tags, and other justified options, and encode variant identity in artifact version and build environment when this makes installation and support easier.
names, receipts, and manifests. That supports genuine hardware-specific products Maintainers own image updates; applications use the shared integration. This is
correctly but adds public API and validation cost. Use it when such variants are useful where a common environment reduces operational work. Its value should be
actual deliverables. Continuing to inherit unrecorded settings is not an equally measured against image maintenance and the suite's differing Go requirements.
good alternative for a standardized release builder. Explicit hardware variants can be added for a demonstrated product need.
### 3. Should the library own build-and-deliver, or accept only completed builds? ### 3. Should the library own build-and-deliver, or accept only completed builds?
**Recommended:** Make declared tagged-source build-and-deliver the normal facade **Recommended:** Provide one facade operation for tagged-source verification,
operation, with source verification and temporary storage owned internally. selected-target builds, temporary storage, checksums, uploads, and cleanup.
The CLI and Go callers then share one implementation. Retain prebuilt input only Use it from the CLI so both interfaces share the procedure. Retain separate
if a real split-stage consumer needs it, with the current digest/source checks building for local development and support prebuilt delivery where a concrete
and a clear lifecycle. A plain request struct and straightforward orchestration handoff requirement justifies it. This minimizes consumer orchestration code.
are sufficient; no public state-machine framework is needed.
**Viable alternative:** Keep `Build` and `Deliver` as the only primitives and **Viable alternative:** Keep separate build and delivery primitives with a
provide a canonical composition helper/example. This makes build environments maintained composition helper. This suits consumers that require credential
and credential isolation explicit and keeps the delivery operation narrow. isolation between stages or need to retain artifacts for later delivery. Those
It is appropriate when most consumers intentionally hand artifacts between consumers accept responsibility for the artifact lifecycle in exchange for the
separate stages, but asks ordinary Go callers to assemble more release logic. operational separation they need.
For portable stage handoff, deliberately design a portable artifact description;
the current absolute-path receipt is intentionally local.
### 4. How should the shared executable and CI integration be distributed? ### 4. How should the shared executable and CI integration be distributed?
**Recommended:** A versioned shared CI runner/entry point, packaged with a known **Recommended:** Choose the simplest maintained entry point for installation,
ReleaseKit executable and compatible Go/Git environment, selected by immutable updates, and delivery. Begin with versioned source installation if it keeps
image digest. Consumers provide the profile, selected image/toolchain, and secret consumer integration small. Centralize reusable setup and provide one clear
reference. Use one maintained flow for source-only and binary delivery. This upgrade procedure. Assess packaging by the consumer code and recurring developer
removes repeated installer/setup shell from applications and gives integration work it removes.
fixes a versioned owner. It requires deliberately adopting image distribution,
which the current source-only release policy does not yet declare; local
maintainers can still install the versioned Go command.
**Viable alternative:** Keep source-only tool distribution through pinned **Viable alternative:** Publish a maintained CI image containing ReleaseKit and
`go install` and maintain a small canonical bootstrap/template. It needs less a compatible Go/Git environment when it substantially reduces setup. The image
hosting infrastructure and naturally supports different Go versions. Prefer provides a ready-to-run integration and centralizes environment maintenance.
calling one combined delivery operation where credential isolation permits it. It also creates an image publication and update responsibility, which should be
The cost is repeated setup and template-update work in consumers; test the real reflected in the release procedure. Either packaging choice should give
template and provide an explicit pin/update convention. Do not add executable applications a small configuration and a routine invocation.
binary distribution merely to remove a few shell lines if this alternative
proves adequately small in adoption trials.
### 5. Are delivery result collections exclusive categories or overlapping views? ### 5. How should delivery results support simple recovery?
**Recommended:** Exclusive outcome categories, with pending meaning known work **Recommended:** Use exclusive outcome categories: matching, uploaded, known
remaining and uncertain meaning remote effect unresolved. A caller can render pending, conflicting, and uncertain. Present ordinary callers with completion or
or act on each category without deduplicating it against the others. Overall a clear failure and recovery instruction. Keep asset details available for
state continues to prevent automatic retries after uncertain writes. diagnostics. Consistent categories simplify implementation and interpretation.
**Viable alternative:** Pending includes every unfinished declaration, with **Viable alternative:** Pending includes every unfinished declaration, with
conflicting/uncertain as diagnostic subsets. This can simplify a progress UI, conflicting/uncertain as diagnostic subsets. This can simplify a progress UI
but must be defined explicitly and applied in every branch. Consumers must then when defined explicitly and applied in every branch. Consumers must then
subtract blocked subsets before deriving retry work. Either is maintainable; subtract blocked subsets before deriving retry work. Apply the chosen
the present mixture is not. meaning consistently across all outcomes.