351 lines
20 KiB
Markdown
351 lines
20 KiB
Markdown
# Roadmap: read-only publication reconciliation
|
|
|
|
Status: planned capability; storage, selection, credential handling, and output
|
|
decisions resolved.
|
|
|
|
## Purpose
|
|
|
|
Let maintainers revisit a failed or uncertain source-publication attempt through
|
|
one ReleaseKit operation. PromptKit currently copies the endpoint checks, exact
|
|
tag query, and result interpretation into its runbook. ReleaseKit should own
|
|
these mechanics and the handoff of original attempt evidence.
|
|
|
|
The target includes a public Go API and a CLI command with equivalent behavior.
|
|
This roadmap describes the end state and required work, without selecting a
|
|
release version or prescribing a staged implementation plan.
|
|
|
|
## Current baseline
|
|
|
|
The current checkout contains the v0.7.0 release notes and publication workflow.
|
|
The [publication guide](../consumers/publish.md) describes existing outcomes;
|
|
the [maintainer runbook](../release.md#resolve-failures) describes manual recovery.
|
|
|
|
- `PublicationResult` supplies the repository and module identity, semantic
|
|
version, full tag, candidate commit, captured endpoint, tag object when known,
|
|
phase, and publication state. Its endpoint can contain credentials.
|
|
- Internal `reconcilePush` makes a bounded authoritative observation after a
|
|
failed push. It compares the annotated tag object and available peeled commit
|
|
evidence, returning published, absent, conflicting, or unknown outcomes.
|
|
- `internal/git.Endpoint.QueryTag` verifies the captured endpoint's scoped URL
|
|
resolution before querying the full tag and peeled ref. Inconsistent exact-ref
|
|
records remain unresolved.
|
|
- The temporary remote carries selected remote-specific transport settings,
|
|
including proxy, upload-pack, and server options, alongside the captured URL.
|
|
- The CLI masks HTTP(S) endpoint userinfo in diagnostics. The runbook still asks
|
|
maintainers to copy the displayed endpoint and compare remote object IDs.
|
|
- There is no public operation or CLI command for later reconciliation, and no
|
|
reusable CLI attempt record for preserving the exact transport endpoint.
|
|
|
|
These existing observations and classifications provide the implementation
|
|
foundation. The main additions are a reusable operation, original-evidence
|
|
handoff, and documented operator and automation interfaces.
|
|
|
|
## Targeted end state
|
|
|
|
After connectivity or authentication is restored, a maintainer can give
|
|
ReleaseKit the original publication evidence and receive a fresh observation
|
|
of that attempt's destination and full tag. Library consumers use typed evidence;
|
|
CLI consumers use a record produced by ReleaseKit without parsing diagnostics.
|
|
Both Go API and CLI publication automatically retain attempt records through the
|
|
shared publication path. Recovery selects a stored record explicitly; Go callers
|
|
may also supply sufficient retained typed evidence directly.
|
|
Maintainers can discover saved attempts through a local, read-only listing when
|
|
the original publication output is unavailable. Discovery leaves record selection
|
|
explicit.
|
|
|
|
| Observation | Reconciliation outcome |
|
|
| --- | --- |
|
|
| Intended annotated tag object, with consistent available commit evidence | Published |
|
|
| Authoritative full tag absent | Not published |
|
|
| Different tag object, including one pointing at the same commit | Conflict |
|
|
| Observation failure, inconsistent records, or insufficient original evidence | Unknown |
|
|
|
|
The implementation preserves existing exact-object semantics, including current
|
|
handling of an unavailable peeled ref. A matching commit alone is insufficient.
|
|
Absence describes the current observation; it does not establish that the tag
|
|
never existed. A record identifies the intended attempt and is not proof that a
|
|
push happened or that the remote accepted it.
|
|
|
|
Reconciliation uses the original captured endpoint and full tag, including nested
|
|
module prefixes. It checks that URL rewriting still permits observation of that
|
|
endpoint. A changed remote configuration does not substitute a new destination.
|
|
Authentication remains locally supplied through the supported Git mechanisms.
|
|
The original remote name is optional transport context. Later reconciliation
|
|
uses its current supported transport settings while keeping the recorded endpoint
|
|
fixed, allowing operators to repair local configuration before observation.
|
|
|
|
The operation observes remote state without creating, pushing, moving, or
|
|
deleting tags, changing branches, validating a candidate, or delivering hosted
|
|
content. Current branch, worktree cleanliness, and current `HEAD` do not need to
|
|
match publication prerequisites. Repository context may still be used for Git
|
|
configuration and authentication. Corrective actions remain explicit.
|
|
|
|
Successful source publication retains its existing completion point. Later
|
|
reconciliation is an optional recovery operation, with no routine read-back,
|
|
polling, CI, consumer-installation, or delivery gate.
|
|
|
|
## Work needed
|
|
|
|
### 1. Extract a shared observation and classification path
|
|
|
|
**Rationale:** Immediate and later recovery should interpret the same evidence
|
|
consistently.
|
|
|
|
**Target:** A reusable internal operation observes the captured endpoint and
|
|
classifies its exact tag using the existing publication semantics.
|
|
|
|
**Work:** Separate remote observation and classification from the original push
|
|
error and publication orchestration. Reuse the scoped endpoint and exact-ref
|
|
query behavior. Keep immediate failed-push reconciliation bounded and preserve
|
|
its existing error context. Later reconciliation should honor caller cancellation
|
|
and return an unresolved outcome when observation cannot complete. It should not
|
|
invoke the current-remote equality guards that belong to an active publication.
|
|
Read the supported transport settings using the recorded remote name when
|
|
available, and apply them to the temporary remote with the recorded endpoint.
|
|
Keep the endpoint-resolution check. Missing remote settings permit observation
|
|
with available endpoint/global configuration; configuration-read failures remain
|
|
unresolved with their causes. Distinguish these cases from a changed destination.
|
|
|
|
### 2. Define public evidence and reconciliation results
|
|
|
|
**Rationale:** Consumers need supported types for recovery instead of rebuilding
|
|
internal Git behavior or parsing diagnostic strings.
|
|
|
|
**Target:** A root-facade operation, provisionally `ReconcilePublication`, accepts
|
|
original evidence and returns a useful observation with preserved error causes.
|
|
|
|
**Work:** Define the minimum evidence needed for each classification: captured
|
|
endpoint, full tag, intended tag object, and candidate commit as applicable.
|
|
Carry module/version information for operator context. Reuse existing publication
|
|
state meanings while distinguishing the original attempt from the new observation.
|
|
Define behavior for incomplete evidence and unsupported record formats without
|
|
inferring missing identity from today's remote, tag, or profile. A deleted or
|
|
moved local tag should not invalidate otherwise sufficient retained evidence.
|
|
Expose the saved record location and any recording failure separately from the
|
|
publication outcome. Accept retained typed evidence directly for reconciliation
|
|
so observation does not depend on filesystem persistence.
|
|
Return a single facade-owned evidence value from publication that reconciliation
|
|
accepts directly. Provide a supported record-loading helper returning that same
|
|
type so Go consumers can recover without copying fields or implementing JSON
|
|
parsing.
|
|
Include the original remote name as optional context in typed evidence and saved
|
|
records. Recovery uses current connection settings rather than a stored snapshot
|
|
of transport configuration; the recorded endpoint retains its identity role.
|
|
|
|
Keep facade ownership and internal Git boundaries. Exact type names, field names,
|
|
and signatures belong in API design; no new public implementation package is
|
|
needed for this feature.
|
|
|
|
### 3. Provide a practical attempt-evidence handoff
|
|
|
|
**Rationale:** Redacted diagnostics are useful displays but cannot reliably carry
|
|
the original transport URL into a later process.
|
|
|
|
**Target:** Shared publication automatically retains a small versioned record
|
|
for both Go API and CLI consumers. Library callers receive typed evidence,
|
|
record location, and recording-failure information; the CLI presents that result.
|
|
|
|
**Work:** Capture evidence when the endpoint and tag object are established,
|
|
before attempting the push. Preserve useful partial evidence if an earlier stage
|
|
fails, clearly identifying what is missing. Make record production and loading
|
|
available through supported interfaces. Keep original identity separate from
|
|
later observations and avoid replacing one attempt's evidence with another's.
|
|
Implement automatic private storage with an optional path override and the
|
|
sensitive-data handling recorded below. Use ordinary file handling proportionate
|
|
to recovery; this feature does not require a transactional journal or power-loss
|
|
guarantees. Keep recording inside the shared publication path so library callers
|
|
receive the same default and optional path override without consumer-owned hooks.
|
|
|
|
### 4. Expose recovery through the CLI and documentation
|
|
|
|
**Rationale:** A single command should replace copied query and comparison steps.
|
|
|
|
**Target:** A command provisionally named `reconcile` reads an explicitly selected
|
|
attempt record and reports the outcome, selected full tag, intended identity,
|
|
and actionable cause context. Automation has a documented structured result and
|
|
exit behavior.
|
|
|
|
**Work:** Map the command to the facade, retaining credential-safe displays and
|
|
errors. Document valid invocation, missing or unreadable records, unknown
|
|
observations, and cancellation. Replace the runbook's manual endpoint-copy
|
|
procedure with this workflow and a concise link from consumer guidance. Explain
|
|
how maintainers retain records and deliberately address absence or conflicts.
|
|
Keep the distinction between source publication and hosted delivery explicit.
|
|
Document recovery limits for older attempts that lack sufficient saved evidence.
|
|
During publication, print a copyable recovery command when a saved record is
|
|
available and recovery is relevant. Include the explicit record path, with
|
|
appropriate argument quoting, and preserve credential-safe output. Select the
|
|
record supplied by the caller rather than inferring the latest attempt.
|
|
|
|
Add a local, read-only attempt listing for the default or explicitly selected
|
|
storage location. Show each record's path, module, full tag, candidate commit,
|
|
and recording time when available, with credentials redacted. Record the time
|
|
as discovery metadata; it does not establish whether a push occurred. Listing
|
|
reads saved records without querying remotes or choosing an attempt for recovery.
|
|
Include discovery in the recovery guide for interrupted processes and lost output.
|
|
Return readable attempts alongside per-record diagnostics for unreadable,
|
|
malformed, or unsupported-format records. Identify the affected paths and retain
|
|
credential redaction. Expose entries and diagnostics to Go callers and structured
|
|
output; the CLI shows usable entries and indicates incomplete discovery. Report
|
|
failure to enumerate the storage location as a discovery failure, not an empty
|
|
collection. An explicitly selected unreadable or unsupported record produces its
|
|
own error without selecting a different attempt.
|
|
|
|
Make unresolved diagnostics identify missing evidence, unreadable records,
|
|
endpoint rewriting, and failed remote observation distinctly. Identify the
|
|
specific missing information or configuration issue when known and explain the
|
|
next useful operator action. For conflicts, show expected and observed tag-object
|
|
IDs. Preserve cause information without guessing whether a transport failure is
|
|
an authentication or connectivity problem. Apply these diagnostics to human and
|
|
structured output while leaving corrective actions explicit.
|
|
|
|
### 5. Verify recovery behavior and integration
|
|
|
|
**Rationale:** Incorrect recovery can direct corrective action at the wrong
|
|
repository or mistake a different annotated tag for the intended release.
|
|
|
|
**Target:** Behavioral coverage establishes equivalent immediate/later
|
|
classification and useful recovery across process boundaries.
|
|
|
|
**Work:** Use temporary Git repositories and local remotes to cover exact matches,
|
|
absence, different objects at the same commit, root and nested tags, changed
|
|
current remotes, rewriting that redirects the captured endpoint, inconsistent
|
|
observations, unavailable remotes, and cancellation. Test record round trips,
|
|
partial evidence, default and overridden storage paths, storage failures,
|
|
private storage behavior, and redaction with synthetic credentials. Cover automatic
|
|
recording through both API and CLI publication, direct typed-evidence recovery,
|
|
and explicit selection among records for multiple modules and retries. Verify
|
|
that recording failure remains separate from publication outcome and that the
|
|
printed recovery command selects its original record. Exercise
|
|
recording before a failed or interrupted push and a later
|
|
invocation after local branch or tag state changes. Verify the diagnostic
|
|
operation performs no publication or cleanup actions and runs no candidate tests.
|
|
Reuse existing tests for unchanged Git behavior rather than duplicating them.
|
|
Verify that publication and record loading yield evidence directly usable by the
|
|
Go reconciliation API. Cover discovery across modules and retries, default and
|
|
overridden storage locations, partial records, and credential redaction. Verify
|
|
that listing performs no remote observation or automatic attempt selection.
|
|
Cover the diagnostic distinctions and expected/observed conflict identities
|
|
without requiring incidental error wording.
|
|
Cover current remote-specific transport settings, repaired configuration,
|
|
missing or renamed remotes, and configuration-read failures. Verify that changed
|
|
fetch or push URLs do not replace the recorded endpoint and that endpoint
|
|
rewriting still receives the existing check. Exercise discovery containing both
|
|
readable and damaged or unsupported records, storage-enumeration failure, and
|
|
explicit selection of an unusable record. Preserve useful partial discovery
|
|
results and credential-safe diagnostics across the API and CLI.
|
|
|
|
Run the normal offline suite and facade checks when code lands. Update GoDoc,
|
|
CLI documentation, the publication guide, and recovery instructions together.
|
|
Any release-policy clarification should describe later optional recovery without
|
|
adding checks to successful publication. This roadmap itself changes no code.
|
|
|
|
## Resolved decisions
|
|
|
|
### 1. Automatic storage with an optional path override
|
|
|
|
Retain records automatically in private repository-local Git metadata by default,
|
|
outside the tracked worktree, with a distinct record for each attempt. The
|
|
standard location should serve nearly all consumers without configuration.
|
|
Provide an optional storage-path override for consumers with particular needs.
|
|
Apply the same record handling and privacy behavior at either location; exact
|
|
configuration syntax belongs in interface design.
|
|
|
|
Automatic recording belongs in the shared publication path for both Go API and
|
|
CLI callers. Publication results expose the saved record location and any
|
|
recording failure separately from the publication outcome. The library returns
|
|
this information and the CLI presents it.
|
|
|
|
Report the record path and require explicit selection for stored-record
|
|
reconciliation. Record evidence before the push once the necessary identity
|
|
exists. Treat storage failure as a clearly reported loss of the saved handoff,
|
|
while preserving the actual publication result and existing publication
|
|
prerequisites. An override
|
|
changes the location, not publication's response to a recording failure.
|
|
|
|
Automatic storage removes a routine setup decision and keeps default records
|
|
out of commits. Records accumulate locally, and recovery evidence can be lost
|
|
when storage fails or its location is removed. Document retention and manual
|
|
removal, including the sensitive nature of records at overridden locations.
|
|
Automatic cleanup is not required for the initial capability.
|
|
|
|
### 2. Preserve the exact endpoint in private records
|
|
|
|
Preserve the exact captured endpoint in the private record, with owner-only
|
|
access using platform-supported file permissions. Continue redacting endpoint
|
|
credentials in human and machine diagnostic output; expose only the record
|
|
location for the handoff. Prefer locally supplied Git credentials in adoption
|
|
guidance. Treat exports and copies of the record as potentially sensitive,
|
|
just like the existing API result's endpoint.
|
|
|
|
This supports existing publication configurations without reconstructing an
|
|
endpoint from its display. It also places potentially sensitive material on disk;
|
|
permissions and clear documentation reduce accidental exposure but do not promise
|
|
encrypted storage or protection from other processes running as the same user.
|
|
|
|
### 3. Human-readable and structured outcomes
|
|
|
|
Offer human-readable output by default and a structured mode with redacted
|
|
identity, reconciliation state, and cause information. Use success for confirmed
|
|
publication, a non-success classification for absence/conflict, and distinct
|
|
unknown and invocation-error classifications, following the existing CLI
|
|
conventions where practical. Define exact numeric codes during CLI design.
|
|
|
|
This makes shell recovery straightforward and keeps structured state authoritative
|
|
for detailed consumers. A successful observation of absence still yields a
|
|
non-success process status; document that distinction explicitly.
|
|
|
|
### 4. Explicit attempt selection
|
|
|
|
Reconciliation of a stored attempt requires an explicit record path. This keeps
|
|
selection unambiguous across modules, retries, and changed repository state.
|
|
When a record is available and recovery is relevant, publication prints a
|
|
copyable command selecting that record. Automatic selection of the latest record
|
|
is outside this workflow.
|
|
|
|
Go callers may instead reconcile sufficient retained typed evidence directly.
|
|
Explicit stored-record selection does not make filesystem storage a prerequisite
|
|
for the observation API.
|
|
|
|
### 5. Recovery ergonomics
|
|
|
|
Provide local attempt discovery to recover the record path after an interrupted
|
|
process or lost publication output. Listing exposes useful, credential-safe
|
|
identity and recording metadata while preserving explicit selection.
|
|
|
|
Publication returns one reusable typed evidence value. Reconciliation accepts
|
|
that value directly, and the supported record loader returns the same type.
|
|
These interfaces keep evidence transfer and serialization mechanics in ReleaseKit.
|
|
|
|
Diagnostics distinguish missing evidence, unreadable records, endpoint rewriting,
|
|
and failed remote observation, and identify useful next actions when known.
|
|
Conflict output includes expected and observed tag-object IDs. This makes
|
|
recovery actionable while preserving the existing outcome classifications and
|
|
explicit corrective-action workflow.
|
|
|
|
### 6. Current transport settings with a fixed recorded endpoint
|
|
|
|
Record the original remote name as optional transport context. During later
|
|
reconciliation, read its current supported transport settings and use them with
|
|
the exact recorded endpoint. The remote's current fetch and push URLs do not
|
|
replace that endpoint. Retain the existing check that URL rewriting leaves the
|
|
recorded endpoint unchanged.
|
|
|
|
A missing or renamed remote alone does not invalidate the evidence. Observation
|
|
can use available endpoint/global configuration; operators may restore required
|
|
settings locally. Configuration-read failures and failed observations remain
|
|
unresolved with cause information. This separates original publication identity
|
|
from repairable connection settings without snapshotting transport configuration.
|
|
|
|
### 7. Discovery preserves readable attempts
|
|
|
|
An unreadable, malformed, or unsupported record produces a diagnostic while
|
|
other readable attempts remain discoverable. Results expose both entries and
|
|
per-record diagnostics, identifying affected paths with credential-safe output.
|
|
The CLI presents usable entries and makes incomplete discovery clear.
|
|
|
|
Failure to enumerate storage is a discovery failure rather than an empty result.
|
|
Explicit reconciliation of an unusable record reports that record's error and
|
|
retains the caller's selection. Discovery and record errors do not authorize
|
|
automatic selection or corrective actions.
|