Record remaining recovery findings and recommended fixes
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
# Publication reconciliation remediation
|
||||
|
||||
Status: complete. R01–R13 are addressed and individually verified. The full
|
||||
offline suite (`go test ./...`) and compiled facade/dependency checks
|
||||
(`go run ./internal/apicheck`) passed with Go 1.26.8 after remediation.
|
||||
Status: open. R01–R13 are addressed and individually verified. R14–R17 record
|
||||
remaining findings from the subsequent stage-by-stage review of `363f7cd`.
|
||||
Address the two handoff defects first, then the classification and format gaps.
|
||||
|
||||
The findings describe commits `4dff808` through `599ad81`, against planning
|
||||
baseline `447b42a`. Audit evidence and defect descriptions below refer to that
|
||||
reviewed baseline; each completion marker records the implemented correction.
|
||||
R01–R13 describe commits `4dff808` through `599ad81`, against planning baseline
|
||||
`447b42a`. Their audit evidence and defect descriptions refer to that reviewed
|
||||
baseline; each completion marker records the implemented correction. The full
|
||||
offline suite (`go test ./...`) and compiled facade/dependency checks
|
||||
(`go run ./internal/apicheck`) passed with Go 1.26.8 after that remediation.
|
||||
|
||||
The [feature roadmap](publication-reconciliation.md) defines the requested
|
||||
behavior; the [implementation plan](implementation.md) supplies the intended
|
||||
@@ -583,3 +585,189 @@ Handle zero-entry failures and cancellation consistently with R04. Add a narrow
|
||||
fault-injected regression for entries-plus-error, verifying readable attempts,
|
||||
retained causes, and API/CLI partial-result behavior. This concerns data
|
||||
preservation, separate from R04's cancellation/error classification.
|
||||
|
||||
## Follow-up stage review evidence
|
||||
|
||||
The subsequent review examined all eight completed stages in the implementation
|
||||
plan, including the R01–R13 corrections, at `363f7cd`. Existing tests for
|
||||
classification, Git endpoints, records, public recovery, publication evidence,
|
||||
discovery, CLI parsing/presentation, cold Go-tool handoffs, and the assembled
|
||||
lost-output workflow passed with Go 1.26.8. The compiled facade/dependency checks
|
||||
and local documentation link/fragment checks also passed.
|
||||
|
||||
Disposable local probes reproduced R14–R17 using temporary Git repositories and
|
||||
Go source overlays. Repository production code and tests remained unchanged.
|
||||
No additional defects were identified in Stages 3–6. Stage 8 needs regression
|
||||
coverage for the cases below and plan wording aligned with the implemented
|
||||
record and handoff decisions. Existing passing coverage does not establish
|
||||
correctness for these additional combinations.
|
||||
|
||||
## R14: Support recovery for vendored API-only consumers — P2
|
||||
|
||||
**Relevant code:** `internal/gotool/recovery.go:95–107`; the command assembly in
|
||||
`cmd/releasekit/main.go:126–145`. Affects Stage 7 and its Stage 8 coverage.
|
||||
|
||||
The API-only handoff prepares its private alternate module files with
|
||||
`go list -mod=mod`, then prints a `go tool` command running from the consumer's
|
||||
module directory. Go automatically selects vendor mode when that directory
|
||||
contains a suitable `vendor` tree. An API-only consumer vendors its imported
|
||||
library packages, so the CLI package can be absent from that tree.
|
||||
|
||||
**Evidence:** A temporary consumer imported ReleaseKit through its Go API,
|
||||
vendored its dependencies, and used the current CLI for a locally rejected
|
||||
publication. A complete record and recovery command were produced. Executing
|
||||
the command failed before reconciliation with `import lookup disabled by
|
||||
-mod=vendor`. Supplying `GOFLAGS=-mod=mod` also failed to change this Go-tool
|
||||
behavior. Existing vendored-tool coverage uses an explicitly registered and
|
||||
vendored CLI, which does not exercise this API-only case.
|
||||
|
||||
**Expected behavior:** A consumer's ordinary library vendoring remains compatible
|
||||
with the supported API-only recovery handoff. The command observes the explicitly
|
||||
selected record using the selected ReleaseKit dependency.
|
||||
|
||||
**Remediation:** Prepare the API-only Go-tool entry point in a private bootstrap
|
||||
module root whose tool resolution is independent of the consumer's vendor tree.
|
||||
Preserve the selected dependency graph, checksums, versioned replacements, and
|
||||
the meaning of relative local replacements when relocating module metadata.
|
||||
Keep source files and consumer vendoring intact, retain private storage handling,
|
||||
and keep bootstrap ownership within ReleaseKit. Preserve registered-tool and
|
||||
native entry points. Update Stage 7's handoff instructions to describe this
|
||||
module-selected approach and the supported native fallback.
|
||||
|
||||
**Regression coverage:** Add an assembled API-only consumer that vendors the
|
||||
library without a tool declaration. Execute the printed command from another
|
||||
directory after publication and launcher cleanup; assert that reconciliation
|
||||
runs against the saved identity and returns its expected state/status. Cover
|
||||
relative local replacements and unchanged consumer source/vendor contents.
|
||||
Retain existing cold-build, registered/vendored-tool, quoting, and status cases.
|
||||
|
||||
## R15: Preserve the recovery handoff after publication cancellation — P2
|
||||
|
||||
**Relevant code:** `cmd/releasekit/main.go:116–134`, especially the caller context
|
||||
passed to `git.CommonDirectory`. Affects Stage 7 and its Stage 8 coverage.
|
||||
|
||||
Command preparation reuses the publication context after publication returns.
|
||||
When cancellation caused the failure, that context is already canceled. The
|
||||
metadata lookup fails immediately and the CLI prints `recovery command
|
||||
unavailable`, even when it has saved the record and a usable native entry point
|
||||
is available. The native fallback is reached only when module selection returns
|
||||
no Go invocation; a preparation error bypasses it.
|
||||
|
||||
**Evidence:** A probe synchronized cancellation with a blocked tag push. The
|
||||
publication returned status 1 after immediate reconciliation found the tag
|
||||
absent. Standard error reported a saved record and an unavailable recovery
|
||||
command, with no copyable handoff. This was cancellation during execution,
|
||||
rather than termination before the record could be saved.
|
||||
|
||||
**Expected behavior:** An ordinary canceled publication with a saved record
|
||||
retains a usable recovery entry point. Its preparation leaves the original
|
||||
publication outcome, cause, and exit classification intact.
|
||||
|
||||
**Remediation:** Arrange handoff preparation so the failed publication's canceled
|
||||
context does not prevent command construction. Prepare necessary durable launch
|
||||
metadata before cancellation-sensitive publication work where appropriate, and
|
||||
retain a usable native-command fallback when module-based preparation fails.
|
||||
Account for cold Go-tool executables that disappear when the original driver
|
||||
exits. Keep publication and later observation cancellation behavior from R04;
|
||||
any separate post-failure preparation that performs subprocess work needs a
|
||||
bounded lifetime. Update Stage 7 to cover cancellation and preparation failures.
|
||||
|
||||
**Regression coverage:** Cancel an actively blocked push after pre-push recording,
|
||||
then execute the resulting command using a fresh invocation/context. Cover a
|
||||
persistent native executable and supported cold Go-tool adoption paths after
|
||||
launcher cleanup. Assert saved identity selection, unchanged publication status
|
||||
and original cancellation cause, and preservation of immediate recovery's bounded
|
||||
context. Coordinate the push boundary explicitly and retain the existing
|
||||
no-recovery-step behavior for successful publication.
|
||||
|
||||
## R16: Classify endpoint setup failures by their actual cause — P3
|
||||
|
||||
**Relevant code:** `internal/publish/reconcile.go:116–128` and
|
||||
`internal/git/remote.go`'s endpoint setup. Affects Stages 1 and 6.
|
||||
|
||||
An `ObserveEndpoint` error defaults to `endpoint_changed` when the evidence has
|
||||
no original remote name. With a name, the fallback is `transport_configuration`.
|
||||
The choice can therefore describe the presence of optional context rather than
|
||||
the failure that occurred.
|
||||
|
||||
**Evidence:** A local checkout with malformed Git configuration and evidence
|
||||
whose `Remote` was empty returned `unknown` with `endpoint_changed`. Its retained
|
||||
cause was Git's bad-configuration error; no changed destination had been
|
||||
established. CLI guidance consequently points the operator toward URL rewrite
|
||||
settings despite the configuration-read failure.
|
||||
|
||||
**Expected behavior:** `endpoint_changed` identifies a positively detected
|
||||
destination change. Configuration and other operational setup failures retain
|
||||
an appropriate unresolved classification and their original causes, including
|
||||
when the original remote name is absent.
|
||||
|
||||
**Remediation:** Distinguish setup failures at the internal Git boundary where
|
||||
their source is known, then map them to the supported recovery kinds. Use the
|
||||
existing endpoint-change sentinel for positively detected rewrites. Preserve
|
||||
configuration/tooling causes through the facade and use the same interpretation
|
||||
for human guidance and structured diagnostics. Clarify this mapping in Stage 1
|
||||
and its Stage 6 presentation requirements using the existing recovery kinds.
|
||||
|
||||
**Regression coverage:** Exercise malformed local configuration with an empty
|
||||
original remote name, a genuine rewrite mismatch, and a separate operational
|
||||
setup failure at the Git boundary. Verify typed kinds, retained causes, unknown
|
||||
state, and corresponding CLI human/JSON diagnostics. Keep remote queries from
|
||||
reaching a substituted endpoint when a rewrite mismatch is detected.
|
||||
|
||||
## R17: Validate the documented version-2 byte-field representation — P3
|
||||
|
||||
**Relevant code:** `internal/publish/record.go:48–59`;
|
||||
[private record format](../integrations/publication-records.md#private-attempt-record).
|
||||
Affects Stage 2 and its Stage 8 format coverage.
|
||||
|
||||
Version-2 byte fields are documented as standard base64 strings. The loader
|
||||
unmarshals each known field directly into `[]byte`; Go's JSON decoder also accepts
|
||||
numeric arrays for that destination type. Consequently, an invalid structural
|
||||
type under the documented format is silently treated as usable evidence.
|
||||
|
||||
**Evidence:** Both `"djEuMi4z"` and `[118,49,46,50,46,51]` as the value of
|
||||
`evidence_bytes.tag` loaded as `v1.2.3` without a format error. The array case is
|
||||
outside the declared representation. This is a format-validation gap; the probe
|
||||
did not demonstrate altered bytes or an incorrect remote observation.
|
||||
|
||||
**Expected behavior:** Known byte fields follow the documented base64-string
|
||||
representation. Structural and encoding failures return `record_format` with
|
||||
their available causes. Supported partial evidence and ignored additional fields
|
||||
retain their existing behavior.
|
||||
|
||||
**Remediation:** Decode known byte-field values as strings explicitly, then use
|
||||
the standard base64 decoder to recover their bytes, preserving decoding causes.
|
||||
Keep version-1 behavior and version-2 lossless identity from R10. Update Stage 2
|
||||
to describe both supported versions and the writer's version selection, linking
|
||||
to the canonical format definition.
|
||||
|
||||
**Regression coverage:** Add known byte-field cases for valid base64, malformed
|
||||
base64, numeric arrays, and other invalid structural types. Assert typed format
|
||||
errors and retained causes for invalid inputs. Reuse the existing all-field
|
||||
round trips, non-UTF-8 endpoint observation, partial-evidence, and unknown-field
|
||||
tests rather than duplicating their fixtures.
|
||||
|
||||
## Implementation plan and verification follow-through
|
||||
|
||||
When implementing R14–R17, update [implementation.md](implementation.md) alongside
|
||||
the corresponding changes:
|
||||
|
||||
- Stage 1: record the cause-based endpoint setup classification from R16.
|
||||
- Stage 2: describe ordinary version-1 records and version-2 byte-preserving
|
||||
records, including the structural validation from R17.
|
||||
- Stage 6: align typed failures, human guidance, and structured diagnostics with
|
||||
R16; retain the implemented JSON output-failure handling from R06.
|
||||
- Stage 7: replace the original executable-only handoff instructions with R07's
|
||||
module-selected/durable API-only approach, extended for vendoring and
|
||||
cancellation by R14 and R15. Retain a usable native fallback and explicit
|
||||
record selection.
|
||||
- Stage 8: add the regression coverage assigned above, update affected canonical
|
||||
documentation as behavior lands, and run the offline suite and compiled
|
||||
facade/dependency checks after assembly. Review local links and prose changes.
|
||||
|
||||
Preserve earlier completion evidence and distinguish these follow-up corrections
|
||||
from the original completed implementation. Add completion markers as the new
|
||||
issues are addressed. The corrections retain the existing public facade,
|
||||
publication completion point, separate recording failures, and operator-owned
|
||||
recovery choices; they introduce no consumer pilot, intermediate release, or
|
||||
external review gate.
|
||||
|
||||
Reference in New Issue
Block a user