# Publication reconciliation implementation plan Status: complete. Implement the target and resolved decisions in the [feature roadmap](publication-reconciliation.md). The original [PromptKit request](promptkit-feature-request.md) supplies consumer context. This document owns implementation sequence and the concrete interface choices needed for that work. The feature roadmap already separates capability requirements from staged implementation and remains the owner of intent. ## Sprint instructions and baseline Complete Stage 1 through Stage 8 in order in one end-to-end sprint. Intermediate stages may leave dependent code incomplete. Continue through the stages without pilot deployments, intermediate releases, external actions, or human review gates. Follow the repository's agent and testing policies, including its commit discipline. Mark completed stages in this document as work lands; retain the remaining instructions until the sprint finishes. Stage verification sections assign coverage to implement; run those checks as their dependencies become available and continue through temporary compilation gaps to the assembled validation in Stage 8. Start with [development guidance](../development.md) and its applicable policy reading guide. Relevant implementation locations are: | Location | Current responsibility | | --- | --- | | `publish.go`, `check.go` | Public publication result, publication facade, and shared release request. | | `internal/publish/publish.go` | Publication orchestration and immediate `reconcilePush` recovery. | | `internal/git/remote.go`, `internal/git/tag.go` | Scoped endpoints, transport configuration, URL checks, exact refs, and annotated tags. | | `internal/git/display.go`, `internal/process` | Credential-safe Git diagnostics and cancellable subprocesses. | | `cmd/releasekit/main.go` | Command dispatch, repository discovery, publication output, and exit codes. | | `cmd/releasekit/internal/cli/config.go` | Argument parsing and profile loading. | | `publish_test.go`, `cmd/releasekit/main_test.go`, `internal/git/remote_test.go` | Existing publication, recovery, CLI, and transport fixtures. | | `internal/apicheck` | Compiled facade ownership and dependency checks. | Keep source publication's successful-push completion point and existing candidate checks. Later reconciliation and discovery are optional recovery operations. They observe evidence and configuration, with corrective actions remaining explicit. Hosted delivery retains its separate workflow. Use the existing root facade and internal packages. Put shared recovery and record mechanics in `internal/publish`, Git mechanics in `internal/git`, and presentation in the CLI. Public types belong to the root facade; internal packages depend on internal types. Preserve the small `buildinfo` boundary. ## Stage 1: Extract the shared observer and classification **Completed:** 2026-11-02 **Outcome:** Immediate failed-push recovery and a later observation can share classification without sharing publication prerequisites. 1. Add `internal/publish/reconcile.go` with internal evidence, observation, and recovery-error types corresponding to the public shapes specified in Stage 3. Observation returns its state and available remote object/peeled-commit IDs. Keep the original evidence separate from the observation. 2. Add an internal Git constructor for observing a captured endpoint. Accept repository context, the exact endpoint string, and an optional original remote name. Create a fresh command-scoped remote using the recorded URL for both read and push URLs. Read the named remote's current supported transport settings using the existing `transportConfig` path. An empty original name uses endpoint/global configuration; it does not select `origin` implicitly. 3. Preserve `QueryTag`'s endpoint-resolution verification and exact full/peeled ref handling. Reading transport settings requires no current fetch/push URL equality check. Missing settings, including after a remote is renamed or removed, permit observation; actual configuration-read failures retain their causes. Reuse the supported transport keys already implemented. Mark configuration reads and scoped-URL configuration resolution at the Git boundary so failures map to `transport_configuration` independently of the optional remote name. Positively detected rewrites use `endpoint_changed`; other operational failures use `remote_observation`, with cancellation taking its existing precedence and causes retained throughout. 4. Extract classification so the immediate path can supply its already captured endpoint and transport settings. Keep `reconcilePush` as the publication adapter: retain its existing detached, bounded recovery context, phase transitions, and original push-error chain. A successful exact match still resolves that push error. Successful pushes continue to return directly. 5. The later path uses the caller's context for configuration reads and the observation. Use the evidence's `RepositoryDir` as Git working-directory context; an empty value uses the caller's current directory. This preserves the meaning of relative local endpoints in automatically captured records. An unavailable recorded directory produces an unresolved observation with actionable context. Recovery does not discover identity from current HEAD, local tags, module files, profiles, or current remote URLs. Use this classification order for later recovery: | Evidence or observation | State and error behavior | | --- | --- | | Missing endpoint or full tag | `unknown`, with `missing_evidence`; list the missing fields and perform no remote query. | | Invalid supplied full object ID or invalid Git tag ref | `unknown`, with `invalid_evidence`; perform no remote query. | | Cancellation or deadline prevents completion | `unknown`, with `canceled` and the context cause. | | Endpoint rewriting changes the captured URL | `unknown`, with `endpoint_changed`; do not query the substituted destination. | | Transport-configuration read fails | `unknown`, with `transport_configuration`. | | Query fails or returns unreadable evidence | `unknown`, with `remote_observation`. | | Exact-ref records are inconsistent | `unknown`, with `inconsistent_observation`. | | Full tag is authoritatively absent | `not_published`; the observation completed successfully, even if tag-object or candidate-commit evidence is missing. | | Full tag is present and intended tag-object ID is missing | `unknown`, with `missing_evidence`, including when a commit matches. | | Observed tag-object ID differs from the intended ID | `conflict`; include both IDs. | | Tag-object IDs match and no peeled ref is available | `published`, preserving existing behavior. | | Tag-object IDs match, a peeled ref is available, and candidate commit is missing | `unknown`, with `missing_evidence`. | | Tag-object IDs match and the peeled commit matches the candidate | `published`. | | Tag-object IDs match but the peeled commit differs | `conflict`; include expected and observed commit IDs as well as tag-object IDs. | Reuse existing full SHA-1/SHA-256 ID and Git-ref validation through internal helpers. Compare hexadecimal IDs by value, accepting their existing supported letter cases; retain supplied evidence for reporting. Module/version labels and recording time are context, rather than additional observation prerequisites. Distinguish a positively invalid ref from tooling, directory, configuration, or cancellation failures while checking it; operational failures retain their appropriate unresolved cause. Expose the existing diagnostic formatter through an internal Git helper for shared error/presentation use, preserving wrapped causes and the current credential-redaction behavior. For the later API, a completed observation of `published`, `not_published`, or `conflict` returns a nil error. An unresolved observation returns an error and its `unknown` result. The immediate publication adapter continues to preserve the original push error for known absence/conflict and unresolved recovery. **Verification:** Extend existing classification tests for the partial-evidence matrix and expected/observed IDs. Reuse existing Git parser tests for unchanged duplicate-ref and peeled-only behavior. Add focused Git-boundary coverage for current transport settings, repaired settings, removed/renamed remotes, fixed URLs, and configuration-read failure. Preserve the existing lost-acknowledgment, rejected-push, endpoint-change, and cancellation behavior. **R16 follow-up completed:** Configuration, rewrite, and operational failures map by their known cause, with facade/CLI coverage for named and unnamed configuration, positive rewrites, and tooling failures. Setup failure and rewrite mismatch tests confirm that no remote tag query occurs. ## Stage 2: Implement private attempt records **Completed:** 2026-11-02 **Outcome:** A supported internal codec can save and load a single attempt without relying on diagnostic output. 1. Add record encoding and storage helpers under `internal/publish`. Use a JSON envelope with integer `format_version: 1` and an `evidence` object. Its fields are `repository_dir`, `module_dir`, `module_path`, `version`, `tag`, `candidate_commit`, `tag_object`, `endpoint`, `remote`, and `recorded_at`. Store the exact endpoint. Fields other than the envelope version/object can be missing in a partial record. Retain the evidence available at capture; loading does not fill omissions from current repository state. 2. Decode one complete JSON document. Missing/unsupported envelope versions, malformed JSON, and structural type errors are `record_format` failures. Accept additional fields within a supported version. Semantic evidence completeness is evaluated by reconciliation, so a readable partial record remains usable for discovery and any classification it can support. 3. Resolve the default directory with `git rev-parse --path-format=absolute --git-common-dir`, then append `releasekit/publication-attempts`. Use Git metadata discovery rather than assuming `.git` is a directory. This shares saved attempts across linked worktrees of the repository. Repository discovery for storage needs no candidate branch, cleanliness, or HEAD check. 4. Treat the override as a directory. An absolute override is used directly; a relative override is resolved against the source repository root. Record files have distinct `attempt-.json` names. Use standard-library random naming and exclusive file creation to keep concurrent calls and retries from overwriting each other. The filename supplies uniqueness; time is discovery metadata, recorded once per attempt as UTC RFC3339Nano text. 5. Create ReleaseKit-owned directories privately and files with owner-only permissions, using platform-supported permissions. Apply this file handling equally to default and overridden storage. Keep unrelated existing directory permissions intact. Use ordinary encoding, writes, closes, and failed-write cleanup; this is a small evidence file with the durability limits in the feature roadmap. Report write/close failures rather than presenting a failed write as a saved record. Report an absolute record path on successful save. 6. Preserve publication's existing clean-worktree requirement when resolving an override. Git metadata, external locations, and Git-ignored locations can retain records. If writing the proposed record would introduce unignored worktree contents, report `record_write` and leave that record unwritten. Use the actual proposed file path and Git's ignore rules before creating record contents; account for ordinary filesystem path resolution. This is a recording failure, not a new publication prerequisite or a reason to change ignore configuration automatically. Do not modify tracked files or exclusion rules to accommodate storage. 7. File-open/read failures are `record_read`; storage-resolution and save failures are `record_write`. Preserve underlying causes through wrapping. Error displays identify paths without echoing record contents. Retention and manual removal remain operator-owned. **Verification:** Use real temporary storage for complete/partial round trips, unsupported versions, malformed data, read/write failures, unique attempts, default and override paths, and permissions where supported. Verify linked worktree metadata resolution and clean-tree preservation for an external, ignored, and unignored override. Use injected failures at the small file/Git boundary when platform permissions cannot reliably induce a failure. Verify that private records retain synthetic credentials while diagnostics redact them. ## Stage 3: Add the facade-owned recovery interfaces **Completed:** 2026-11-02 **Outcome:** Go callers can pass publication evidence directly to recovery or load it through ReleaseKit. Define these root-facade interfaces, with ordinary conversions to internal types: ```go type PublicationEvidence struct { RepositoryDir string ModuleDir string ModulePath string Version string Tag string CandidateCommit string TagObject string Endpoint string Remote string RecordedAt string } type PublicationReconciliationResult struct { Evidence PublicationEvidence State PublicationState ObservedTagObject string ObservedCommit string } type PublicationRecoveryError struct { Kind string RecordPath string MissingFields []string // Private cause, with Error and Unwrap methods. } func ReconcilePublication(context.Context, PublicationEvidence) (PublicationReconciliationResult, error) func LoadPublicationEvidence(string) (PublicationEvidence, error) ``` 1. Implement `ReconcilePublication` using Stage 1 and the existing public publication states. It performs observation only; Stage 1 defines its result and error semantics. `LoadPublicationEvidence` uses Stage 2 and reads the explicitly supplied path, relative to the caller's working directory when relative. It performs no Git discovery or remote access. 2. Implement the facade-owned error with pointer receivers for `Error` and `Unwrap`. Convert internal recovery errors while retaining original causes for `errors.Is`/`errors.As`. Document `Kind` values from Stages 1 and 2 plus `storage_enumeration` from Stage 5. `MissingFields` uses the record field names. Provide credential-safe error text through the existing Git diagnostic redaction machinery; raw evidence and unwrapped causes remain sensitive. 3. Add `PublicationRecordDir string` to `ReleaseRequest`, documenting it as a publication-only directory override that `Check` ignores. Add `Evidence PublicationEvidence`, `RecordPath string`, and `RecordError error` to `PublicationResult`. Preserve existing flat fields and their behavior; populate them and the new evidence from the same captured values. Stage 4 wires recording into publication. `Publish` is the supported record producer. 4. Keep serialization in the internal codec. The facade's evidence is the reusable typed input, not the CLI's diagnostic JSON representation. Document its raw endpoint and the sensitive nature of retained records. **Verification:** Add external-package API tests for direct evidence recovery, record loading, partial evidence, preserved causes, and state/error semantics. Include a caller using `result.Evidence` and a caller using the loader's result without copying fields. Extend the existing facade checks only as needed to protect ownership of these types and existing dependency directions; keep the current external-type allowances. ## Stage 4: Record attempts inside shared publication **Completed:** 2026-11-02 **Outcome:** API and CLI publication retain the same evidence before pushing, with recording failures separate from the publication outcome. 1. Wire the new request/result fields through the facade and `internal/publish.Request`/`Result`. Keep recording in `internal/publish`. Use named result returns in the internal publication operation so finalization can add record information to every returned result without replacing the publication error. 2. Initialize attempt metadata when candidate capture has established the source repository, including when capture returns partial evidence with an error. Capture the actual effective remote name, using publication's existing `origin` default. Discover storage locally and retain any storage failure separately. An invocation that fails before its repository is known returns its available typed evidence with no initialized record or recording error. 3. Populate evidence from the captured candidate, resolved endpoint, and created tag-object ID as those become available. Preserve tag-object evidence returned alongside a tag-inspection failure. Use the stable attempt timestamp from initialization and the same evidence value in the result and saved record. 4. Save one evidence snapshot after the final existing pre-push guards and before calling `PushTag`. On an earlier ordinary return, save the available partial snapshot during finalization instead. Finalization runs once for recording purposes; it does not retry or create another attempt after a failed save. An interrupted push can therefore leave a complete saved identity even when the process never returns a publication result. 5. Preserve the original publication return value and error when storage fails. Supply the wrapped recording failure in `RecordError`, with `RecordPath` populated only for a saved record. A successful push with a failed save still returns publication success. A failed/unknown push with a saved record keeps its existing state and original error chain. 6. Records contain original identity and discovery metadata. Later observations and publication's final outcome remain separate results. Reconciliation and listing read saved records without updating them. Each later publication invocation gets its own attempt; existing records are retained. **Verification:** Extend public publication fixtures to assert that the record exists and contains the intended endpoint, full tag, commit, and tag object before the push subprocess proceeds. Exercise success, rejected push, unresolved push, pre-push failure, tag-inspection failure, and storage failure. Verify unchanged publication outcomes/cause chains, one useful partial record on early failure, distinct records for retries/modules, and no standard-suite duplication. Verify that default storage and a failed unignored override keep the candidate worktree clean. Cover a non-nil `RecordError` on successful publication through both API results and Stage 7's CLI integration, preserving publication success. ## Stage 5: Provide local attempt discovery **Completed:** 2026-11-02 **Outcome:** Callers can find saved attempts even after losing publication output, with useful partial discovery when a record is damaged. Add these facade-owned types and helper, backed by `internal/publish`: ```go type PublicationAttemptsRequest struct { RepositoryDir string RecordDir string } type PublicationAttempt struct { RecordPath string Evidence PublicationEvidence } type PublicationAttemptsResult struct { RecordDir string Attempts []PublicationAttempt Diagnostics []*PublicationRecoveryError } func ListPublicationAttempts(context.Context, PublicationAttemptsRequest) (PublicationAttemptsResult, error) ``` 1. An empty repository selection means the current directory. Resolve the default or relative override using Stage 2's repository/storage rules. An absolute `RecordDir` can be enumerated directly, including outside a checkout. Discovery neither creates the directory nor requires a release profile. 2. Enumerate the selected directory's JSON record files at that level, using the shared loader. Return readable attempts with absolute paths, including partial records. Return a per-record recovery diagnostic for each unreadable, malformed, or unsupported record, and continue to other entries. Use a deterministic path order for presentation without introducing automatic chronological selection. 3. Return a top-level `storage_enumeration` error for directory-resolution or enumeration failure, including a missing selected storage directory. Preserve already obtained entries/diagnostics when available. An existing readable empty directory returns an empty successful result. Cancellation uses the `canceled` kind and preserves partial results and its cause. Per-record failures alone populate `Diagnostics` with a nil top-level error. 4. Listing reads saved identity and recording time. It performs no remote query, current-candidate capture, local-tag inspection, recovery selection, or cleanup. Error text follows Stage 3's credential-safe behavior. **Verification:** Cover multiple modules/retries, empty storage, mixed readable and damaged records, unsupported versions, inaccessible/missing directories, explicit external storage, and cancellation. Verify no remote access and no record mutation. Test public result/error distinctions and preserved causes; reuse codec cases rather than repeating all parser permutations here. ## Stage 6: Add CLI recovery, discovery, and structured output **Completed:** 2026-11-02 **Outcome:** Operators and automation can discover and reconcile explicitly selected attempts without profiles or diagnostic parsing. Implement these command forms in the existing parser and CLI dispatch: ```text releasekit reconcile --record FILE [--json] releasekit publication-attempts [--repo DIR] [--record-dir DIR] [--json] ``` 1. Add command/argument fields to `cli.Invocation` and extend usage/parser tests. Neither command takes a version positional argument or loads a profile. Reconciliation requires its explicit record path. The loader resolves a relative record path from the invoking directory; the evidence supplies the original repository context for observation. Listing uses Stage 5's directory rules. Route these commands before `main.run`'s current unconditional repository-root lookup for other non-version commands. 2. Place recovery presentation in a focused CLI source file rather than growing candidate/build/delivery handlers. Invoke the root facade for load, observe, and list mechanics. A record-read/format error preserves the requested path and produces an invocation error. A readable partial record reaches the observer and can produce `unknown` or a supported known observation. 3. Human output shows the selected path, safe identity, state, available observed IDs, and actionable cause context. Unknown diagnostics identify missing fields, invalid evidence, changed endpoint rewriting, transport-configuration failure, cancellation, or failed/inconsistent observation using the typed recovery error. Show expected and observed IDs for conflicts, including commit evidence when that is what conflicts. Explain possible next actions from known causes, without guessing that a generic Git failure is an authentication or connectivity failure. Configuration failures include endpoint/global settings when the remote name is absent. Use the same cause-based recovery kinds from Stage 1 for JSON diagnostics and human guidance. 4. Human listing shows path, module identity, full tag, candidate commit, and recording time when available. Show per-record diagnostics alongside usable entries and make incomplete discovery clear. Distinguish an enumeration failure from a successfully enumerated empty directory. 5. Implement explicit CLI JSON DTOs. After successful argument parsing, `--json` writes one JSON document to stdout for success and failure paths; normal usage/argument-parse errors retain the existing stderr behavior. Use these fields, with `schema_version: 1` and the command name: | Command | JSON fields beyond `schema_version` and `command` | | --- | --- | | `reconcile` | `record_path`, safe `evidence`, `state`, `observed_tag_object`, `observed_commit`, and `diagnostic` when unresolved or loading fails. Omit observation fields when loading failed. | | `publication-attempts` | `record_dir`, `attempts` (each with `record_path` and safe `evidence`), `diagnostics`, and a top-level `diagnostic` for enumeration/cancellation failure. Arrays are present, including when empty. | Safe evidence uses the Stage 2 snake-case field names with credential-safe string displays. A diagnostic contains `kind`, `message`, `record_path` when applicable, and `missing_fields` when applicable. Encode error text explicitly; keep raw Go errors and private record JSON out of these DTOs. Apply existing URL/diagnostic redaction before JSON encoding, including nested messages. Raw endpoint preservation belongs only to private records and typed evidence. Human and JSON output use the same state/diagnostic interpretation. 6. Use these process statuses and document their distinct meanings: | Command/result | Status | | --- | --- | | Reconciliation confirms publication | 0 | | Reconciliation observes absence or conflict | 1 | | Reconciliation invocation, selected-record read, or format failure | 2 | | Reconciliation remains unknown, including missing evidence or canceled observation | 3 | | Discovery completes with readable entries and no diagnostics, including an empty existing store | 0 | | Discovery is incomplete or fails, including cancellation | 1 | | Discovery argument/usage error | 2 | A nil Go observation error for absence/conflict still maps to CLI status 1. Preserve the original context or filesystem cause in the API even when its CLI status is an invocation classification. **Verification:** Add parser/dispatch tests and command tests for human/JSON state parity, exit classifications, mandatory selection, unusable records, partial discovery, and credential redaction. Assert semantic fields rather than complete diagnostic wording. Test paths with spaces/apostrophes and running record-based recovery from another working directory. Verify these commands work with a dirty worktree, changed branch/HEAD, removed or moved local tag, and unavailable profile, with no candidate commands or hosted requests. ## Stage 7: Integrate publication's record override and recovery handoff **Completed:** 2026-11-02 **Outcome:** Existing publication commands expose saved evidence and recording failures without additional consumer release infrastructure. 1. Add `--record-dir DIR` to `publish`, mapping it to `ReleaseRequest.PublicationRecordDir`. Keep the automatic default sufficient for ordinary callers. The override is a CLI/API option; profile JSON remains unchanged for this feature. The flags for other existing commands retain their meanings. 2. After publication, report a saved absolute record path or a credential-safe recording warning on stderr, separately from the existing publication summary/error. These messages leave publication's exit classification and original failure diagnostics intact, including success with recording failure. 3. When publication returns an error at tag creation, push, or immediate reconciliation and a record was saved, print a copyable `reconcile --record` command selecting that exact path. Partial records can explain missing evidence. Earlier failures still report their saved path when available. Successful publication reports the path without prescribing a recovery step. 4. Prefer the consumer module's registered Go tool for the printed command. API-only consumers use durable private module/checksum files under Git metadata, with a separate bootstrap module root so consumer vendoring does not govern tool resolution. Retain the selected requirements, checksums, versioned replacements, and original locations of local replacements. Consumers without a selected ReleaseKit dependency use the native executable path. Select the absolute record path explicitly and quote every argument for the POSIX-shell runbooks, including apostrophes. The command survives a cold Go-tool executable's removal and launcher-owned metadata cleanup. Explain how to use another selected supported CLI if an entry point becomes unavailable. 5. Prepare the command after publication using a separate bounded context so publication cancellation leaves handoff construction available. Report module-preparation failures separately and retain a persistent native executable fallback. Recognized temporary Go-build executables provide no durable native fallback. Keep publication's original status/error and immediate reconciliation context unchanged. **R14/R15 follow-ups completed:** API-only recovery uses an independent private module root; post-failure preparation handles cancellation and native fallback. **Verification:** Extend existing publication CLI tests for the default, override, recording warning with successful status, and original failed/unknown status. Use a built CLI in an assembled test to execute the printed recovery command and verify it selects the original record among retries/modules. Test shell argument quoting with synthetic paths. Keep the existing module-selected Go-tool launchers and source bootstrap working without adding consumer-owned recording. Include an API-only consumer that vendors the library without declaring the CLI tool; execute its handoff and verify source/vendor contents remain unchanged. Exercise relative local replacements, versioned replacements, and ReleaseKit's own source-module recovery entry point. Coordinate cancellation at the recorded push boundary for native, cold registered-tool, and temporary-launcher invocations. Execute the resulting handoff after driver/launcher cleanup and verify retained publication diagnostics and recovery statuses. Exercise native fallback after module-preparation failure. ## Stage 8: Finish assembled coverage and canonical documentation **Completed:** 2026-11-02 **Outcome:** The full feature works across process boundaries, with supported contracts and a short consumer recovery workflow. 1. Add focused assembled tests for publication with a failed/interrupted push, lost output followed by discovery, and a separate later recovery invocation. Use a controlled local Git boundary to know when pre-push recording finished; coordinate cancellation/interruption without arbitrary sleeps. Remove or move the local tag and change branch, HEAD, remote URLs, or transport settings before later recovery. Cover root/nested tags and original-record selection. Retain the assembled vendored API-only handoff coverage added for R14, alongside cold registered-tool and temporary-launcher recovery. R15 adds canceled publication and preparation-failure handoff cases using explicit push readiness and fresh later invocations. R16 covers setup failure classifications and human/JSON guidance without querying an invalid or substituted endpoint. 2. Establish read-only behavior through resulting refs, worktree/branch state, saved records, and controlled observations of candidate/hosted boundaries. Reuse lower-level classification and codec tests. Tests use local remotes, temporary storage, synthetic credentials, and isolated environments; live services and real credentials are unnecessary. 3. Update GoDoc for evidence, results, errors, request fields, and all new helpers. Clarify existing publication-state comments where they currently describe only successful pushes or a single invocation, while preserving those states' established immediate-publication behavior. 4. Update documentation at its canonical owners: | Owner | Change | | --- | --- | | `docs/cli.md` | New commands, flags, explicit selection, relative-path semantics, human/structured modes, and statuses; update the command inventory. | | `docs/consumers/publish.md` | Automatic recording, separate recording failures, reusable typed evidence, loader/discovery use, optional later observation, storage placement/lifecycle, overrides, permissions, retention, and sensitive-data handling. | | New `docs/integrations/publication-records.md` | Versioned private-record and CLI JSON formats and unsupported-format handling. Link to CLI/GoDoc for operation contracts and the publication guide for physical placement/lifecycle. | | `docs/release.md` | Replace manual endpoint-copy/comparison instructions with explicit-record recovery and local discovery; describe lost/older evidence and unavailable original executable. | | `docs/internal/overview.md` | Implemented observer, recording, discovery, facade, and CLI responsibilities; link to canonical formats and contracts. | The runbook must explain that current absence does not prove a version was never published or permit reuse of a known published version. Keep cleanup and retry choices explicit and preserve immutable published tags/contents. Storage failure loses the saved handoff, rather than changing the actual publication outcome. Explain that direct typed evidence can still support recovery when recording fails. Document the limits of abrupt process termination before recording, removed storage, and older attempts lacking sufficient retained identity. Later recovery adds no successful-publication read-back, polling, CI, installation, or hosted-delivery gate. 5. Review examples, local links, fragment destinations, privacy language, and consistency with the feature roadmap. Keep release-version selection and tagging in later release preparation. Update any existing draft release note only when its version/scope has been deliberately selected for this feature. 6. Once the assembled implementation is ready, run `go test ./...` and `go run ./internal/apicheck` with the prepared compatible local Go toolchain and offline dependencies. Run focused tests while implementing their owners; reuse successful checks for unchanged content. Add targeted race detection if new shared mutable state or concurrent record tests expose a distinct risk. Finish with `git diff --check`, review all implementation/test/doc changes, and complete the repository's normal commit discipline. The sprint is complete when automatic API/CLI recording, direct and loaded evidence reconciliation, partial local discovery, current transport settings with fixed original endpoints, safe human/structured output, and the assembled recovery workflow satisfy this plan and the feature roadmap. The final report should identify implemented interfaces, validation results, and any remaining limitations. Subsequent architecture review and release/testing decisions take place after this complete initial implementation.