Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions memory-bank/features/FT-013/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
title: "FT-013: Self-update from latest GitHub release"
doc_kind: feature
doc_function: index
purpose: "Bootstrap-safe navigation for the FT-013 feature package. Read feature.md first, then solution.md, decision-log.md, and implementation-plan.md."
purpose: "Navigation for the FT-013 feature package, which owns the reconciled issue #35/#13 self-update slice. Read brief.md, design.md, decision-log.md, and implementation-plan.md in that order."
derived_from:
- feature.md
- brief.md
status: active
audience: humans_and_agents
---
Expand All @@ -13,18 +13,26 @@ audience: humans_and_agents

## About

This feature package tracks issue #13: adding a first-class self-update workflow for `start-issue` that upgrades the running installation from the latest published GitHub release.
This feature package tracks issue #35 and reconciles it with the already
delivered issue #13 contract. It is the single feature owner for self-update.

## Annotated Index

- [feature.md](feature.md)
Read for the canonical problem statement, scope, constraints, acceptance scenarios, and verification contract.
- [brief.md](brief.md)
Canonical problem statement, scope, constraints, acceptance scenarios, and verification contract.

- [solution.md](solution.md)
Read for the selected update architecture, command-entry equivalence, and operational failure handling.
- [design.md](design.md)
Canonical selected design, contracts, invariants, and failure handling.

- [decision-log.md](decision-log.md)
Read for feature-local decisions that close issue ambiguities and document conflict resolution.

- [implementation-plan.md](implementation-plan.md)
Read for execution order, touchpoints, risks, and planned verification.

- [feature.md](feature.md) and [solution.md](solution.md)
Archived legacy redirects retained for migration traceability; they are not
active requirement or design owners.

- [feature-review-report.md](feature-review-report.md)
Final review-improve cycle report and verification note.
111 changes: 111 additions & 0 deletions memory-bank/features/FT-013/brief.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
title: "FT-013: Self-update command for installed CLI"
doc_kind: feature
doc_function: canonical
purpose: "Canonical problem-space and verification contract for issue #35, reconciled with the already delivered issue #13 slice."
derived_from:
- https://github.com/dapi/start-issue/issues/35
- https://github.com/dapi/start-issue/issues/13
- ../../flows/feature-flow.md
- ../../product/context.md
- ../../engineering/testing-policy.md
- ../../../README.md
- ../../../README.ru.md
- ../../../doc/spec.md
status: active
delivery_status: done
audience: humans_and_agents
must_not_define:
- selected_design
- implementation_sequence
---

# FT-013: Self-update command for installed CLI

## What

### Problem

An installed `start-issue` binary needs a release-backed way to update itself
without requiring a source checkout. Issue #35 restates the self-update slice
originally tracked by issue #13; the existing FT-013 package is therefore the
single feature owner.

### Outcome

Users can run `start-issue update` or `start-issue --update` to compare the
running installation with the latest `dapi/start-issue` GitHub Release and
upgrade that installation when a newer compatible release exists.

## Scope

- `REQ-01` Support `start-issue update` and `start-issue --update` as equivalent entry points.
- `REQ-02` Resolve the latest published release for `dapi/start-issue` through GitHub Release metadata.
- `REQ-03` Use the executable resolved for the current invocation as the update target and version source.
- `REQ-04` Treat an equal or newer installed version as a successful no-op without downgrading.
- `REQ-05` For an available update, download the current-platform binary and checksum manifest, verify both, and install with executable permissions.
- `REQ-06` Fail with actionable errors for missing access/tooling, release lookup, missing assets, download, checksum, staged-version, or installation failures.
- `REQ-07` Work outside a git repository and leave the ordinary issue-start workflow unchanged.
- `REQ-08` Document both entry points, update states, prerequisites, and failure behavior in the public README/spec surfaces.

## Non-Scope

- `NS-01` No automatic update during ordinary issue-start commands.
- `NS-02` No arbitrary release selection or downgrade command.
- `NS-03` No package-manager integration and no change to local-source `make install` semantics.
- `NS-04` No second feature package for issue #35; issue #35 is reconciled to FT-013.

## Constraints / Assumptions

- `CON-01` The release source and repository are `dapi/start-issue`, unless the existing documented repository override is intentionally used for tests or compatible deployments.
- `CON-02` The update path must not require repository, worktree, issue, or agent context.
- `CON-03` Installation must be staged and verified before replacement so a failed update does not replace the existing executable.
- `CON-04` Platform-specific release assets and `checksums.txt` are the current release contract documented by the repository.

## Design Requirement Decision

| Decision | Reason | Downstream owner |
| --- | --- | --- |
| `Design required: yes` | The feature changes CLI mode parsing, external GitHub Release interaction, executable replacement, checksum verification, and failure handling. | `design.md` |

## Verify

### Exit Criteria

- `EC-01` Both command forms enter the same update workflow.
- `EC-02` Current, newer, and update-available versions produce the specified no-op or update result.
- `EC-03` A successful update replaces only the invoked executable after checksum and staged-version verification, preserving executable permissions.
- `EC-04` Lookup, download, checksum, staged-version, permission, and unsupported-platform failures are actionable and non-zero where applicable.
- `EC-05` The workflow works outside git and existing issue-start behavior remains covered.
- `EC-06` README/spec documentation matches the implemented Go CLI contract.

### Acceptance Scenarios

- `SC-01` Older installed binary + `update` installs the latest current-platform release.
- `SC-02` Older installed binary + `--update` has the same result as `update`.
- `SC-03` Equal versions exit `0` and do not download or replace the executable.
- `SC-04` Installed version newer than latest exits `0` and does not downgrade.
- `SC-05` Lookup, asset, checksum, staged-version, or install failure exits with an actionable error and leaves the old executable intact.
- `SC-06` Update from outside a git repository does not invoke repo/worktree discovery.
- `SC-07` Existing issue-start invocation remains behaviorally compatible.

### Checks and Evidence

| Check ID | Covers | Procedure | Evidence |
| --- | --- | --- | --- |
| `CHK-01` | `REQ-01`–`REQ-07`, `SC-01`–`SC-07` | `go test ./...` | `EVID-01` |
| `CHK-02` | `REQ-08`, `EC-06` | `make test` and `git diff --check` | `EVID-02` |

`EVID-01` is focused Go/parity test output covering release lookup, version
ordering, checksum/staged verification, executable replacement, no-op paths,
failure paths, and outside-git execution. `EVID-02` is repository-level check
output and documentation/index validation.

### Traceability Matrix

| Requirement | Acceptance | Checks |
| --- | --- | --- |
| `REQ-01` | `SC-01`, `SC-02` | `CHK-01` |
| `REQ-02`–`REQ-06` | `SC-01`–`SC-06` | `CHK-01` |
| `REQ-07` | `SC-06`, `SC-07` | `CHK-01` |
| `REQ-08` | `EC-06` | `CHK-02` |
177 changes: 71 additions & 106 deletions memory-bank/features/FT-013/decision-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
title: "FT-013: Decision Log"
doc_kind: feature
doc_function: decision_log
purpose: "Feature-local decisions for FT-013. Records how issue ambiguities and document conflicts were resolved."
purpose: "Feature-local decisions and conflict resolutions for the issue #35/#13 self-update slice."
derived_from:
- feature.md
- solution.md
- ../../../install.sh
- brief.md
- design.md
- ../../../cmd/start-issue/main.go
- ../../../README.md
- ../../../doc/spec.md
status: active
Expand All @@ -17,115 +17,80 @@ audience: humans_and_agents

## Decisions

### `DL-01` Release-backed installer contract is the update baseline
### `DL-01` Issue #35 is reconciled to FT-013

- Date: 2026-05-24
- Date: 2026-08-04
- Status: accepted
- Context:
Issue #13 requires the update source to be the latest GitHub Release rather than the local checkout.
The current repository already documents and implements a release-backed install path in `README.md`, `README.ru.md`, and `install.sh`.
- Decision:
The self-update workflow reuses the same release-backed contract as `install.sh`: release asset plus checksum, verification before install, and installation into the project's standard binary target shape.
- Evidence:
`install.sh` downloads `releases/latest/download/start-issue` and `start-issue.sha256`, verifies the checksum, and installs with mode `0755`.
`README.md` documents that install path as the primary "latest release" installation flow.
- Consequence:
Update behavior stays consistent with the documented installation story and avoids inventing a second release-install mechanism.

### `DL-02` The running executable path is the safe default update target

- Date: 2026-05-24
- Context: Issue #35 requests a release-backed self-update command for the installed CLI. The feature inventory identifies it as a duplicate of the existing issue #13 self-update slice.
- Decision: FT-013 remains the single feature package; issue #35 is added as provenance and no second package is created.
- Evidence: GitHub issue #35, `memory-bank/features/missing.md`, and the existing FT-013 package.
- Consequence: Scope, design, plan, and verification have one canonical owner.

### `DL-02` Current Go runtime is the implementation baseline

- Date: 2026-08-04
- Status: accepted
- Context: Legacy FT-013 documents referenced `scripts/start-issue` and Bash tests, but the current repository entrypoint is `cmd/start-issue/main.go` and the current test surfaces are Go and parity tests.
- Decision: Active feature documents use the current Go implementation and tests as grounding; legacy `feature.md` and `solution.md` are archived redirects.
- Evidence: `cmd/start-issue/main.go`, `cmd/start-issue/main_test.go`, `cmd/start-issue/parity_integration_test.go`, `Makefile`.
- Consequence: Plan steps and evidence no longer claim unstarted Bash work.

### `DL-03` Release metadata and platform assets are the update contract

- Date: 2026-08-04
- Status: accepted
- Context:
Issue #13 explicitly notes that multiple `start-issue` executables may exist in `PATH` and says the safest default is to update the resolved executable path for the current invocation.
- Decision:
The update workflow detects the executable path of the running `start-issue` process and updates that path rather than guessing a different installation target.
- Evidence:
The issue's design notes define this as the safest default.
This matches the feature requirement to detect the currently installed version from the executable the user is running.
- Consequence:
The command updates the installation the user actually invoked and avoids silently modifying another `PATH` entry.

### `DL-03` Update mode must not depend on git repository state

- Date: 2026-05-24
- Context: Issue #35 requires the latest GitHub Release, a binary, and SHA-256 verification. The current Go CLI resolves release metadata with `gh`, selects the current-platform asset, and downloads `checksums.txt`.
- Decision: Use `gh api repos/<repository>/releases/latest`, the current-platform binary asset, and `checksums.txt`; keep the documented repository override available.
- Evidence: `updateMode`, `githubRelease.assetURLs`, `releaseAssetName`, `validChecksum`, README self-update section, and `doc/spec.md`.
- Consequence: Verification covers both metadata resolution and asset integrity without reintroducing the legacy shell installer as a runtime dependency.

### `DL-04` The running executable is the update target

- Date: 2026-08-04
- Status: accepted
- Context:
Issue #13 requires the command to work outside a git repository.
The normal issue-starting workflow currently depends on git repo discovery, remote detection, and worktree planning.
- Decision:
Update mode is treated as a separate top-level workflow that bypasses issue parsing, repo detection, base-branch detection, and worktree orchestration.
- Evidence:
The issue says the update command should work outside a git repository.
Current `doc/spec.md` shows the ordinary workflow requires git repository context for issue starts.
- Consequence:
Update mode can run from any directory and does not create accidental coupling to the issue-starting path.

### `DL-04` Version comparison uses normalized tags, not raw surface strings

- Date: 2026-05-24
- Context: Issue #35 requires updating the executable invoked by the user. Multiple installations may exist, and the current implementation resolves `os.Executable()` then evaluates symlinks.
- Decision: Update the resolved executable path for the current process; never guess another PATH entry or silently fall back to the default install path.
- Evidence: `runningExecutablePath`, `SD-01`, and issue #35 user experience/acceptance text.
- Consequence: The command updates the installation actually invoked.

### `DL-05` Update is upgrade-only

- Date: 2026-08-04
- Status: accepted
- Context:
The current CLI exposes a bare numeric version such as `1.12.0` in `scripts/start-issue`.
Issue #13 refers to GitHub release names with a `v` prefix such as `v1.11.1`.
Raw string comparison would therefore misclassify equivalent versions.
- Decision:
The update workflow compares normalized version strings by stripping one optional leading `v` from both the installed version and the latest release tag before equality and ordering checks.
- Evidence:
`scripts/start-issue` currently defines `VERSION=\"1.12.0\"`.
Issue #13 states the latest published release is `v1.11.1`.
- Consequence:
The no-op path reflects semantic version equality rather than formatting differences, and tests must cover the normalization rule.

### `DL-05` Release lookup and asset download are separate contracts

- Date: 2026-05-24
- Context: The requirement says current or newer installations must exit successfully without downloading; unconditional “latest release” replacement could downgrade a newer binary.
- Decision: Compare semantic versions; equal or newer is a successful no-op.
- Evidence: `compareVersions`, `updateMode`, `SC-03`, and `SC-04`.
- Consequence: Self-update never replaces a newer installed version.

### `DL-06` Replacement requires checksum and staged-version verification

- Date: 2026-08-04
- Status: accepted
- Context:
Issue #13 requires the command to resolve the latest published release from GitHub Releases and also to install the release artifact.
`install.sh` already defines how assets and checksum files are downloaded, but it does not need to compare versions first.
- Decision:
FT-013 separates release metadata lookup from asset download:
lookup resolves the canonical latest release tag and asset/checksum URLs;
installer helpers then download, verify, and install those resolved assets.
- Evidence:
The issue requires both latest-release resolution and version comparison.
`install.sh` already provides the download and verification contract for the release asset and checksum.
- Consequence:
The design keeps one source of truth for "what is latest" and a separate source of truth for "how to install it," reducing drift and simplifying tests.

### `DL-06` Self-update must not downgrade a newer local executable

- Date: 2026-05-24
- Context: A checksum verifies bytes, while a release asset can still be mislabeled or incompatible. Replacement must not destroy the working binary on a failed update.
- Decision: Download to memory, verify `checksums.txt`, stage beside the target with executable mode, verify staged `--version` against the release tag, then rename atomically.
- Evidence: `validChecksum`, `stageBinary`, `verifyStagedBinary`, `installVerifiedUpdate`, and focused tests.
- Consequence: checksum, version, permission, or rename failures leave the existing target untouched.

### `DL-07` Update mode is independent of repository context

- Date: 2026-08-04
- Status: accepted
- Context:
The repository currently contains `VERSION="1.12.0"` in `scripts/start-issue`.
Issue #13 states that on 2026-05-24 the latest published release is `v1.11.1`.
A self-update command that blindly installed "latest published release" would therefore downgrade a newer local executable.
- Decision:
If the running executable version is newer than the latest published GitHub release, the update workflow exits successfully with a no-op status and leaves the executable unchanged.
- Evidence:
`scripts/start-issue` currently exposes version `1.12.0`.
Issue #13 states that the latest published release is `v1.11.1`.
- Consequence:
Self-update remains an upgrade-only workflow and does not clobber a newer local or pre-release installation.
- Context: Issue #35 explicitly requires operation outside a git repository; ordinary issue-starting flow has separate repository/worktree prerequisites.
- Decision: Dispatch update mode before ordinary repo/worktree orchestration and require only the update-specific external boundary.
- Evidence: `main`, `runMode`, `updateMode`, `SC-06`, and `TestRunModeUpdateDoesNotRequireHomeDirectory`.
- Consequence: update can run outside git while ordinary issue-start behavior remains isolated.

## Conflict Resolution

- Resolved conflict: "standard install location used by the project" versus "update the resolved executable path for the current invocation."
Conflicting sources:
issue #13 requirements emphasize the standard install location;
issue #13 design notes emphasize the running executable path as the safest default when multiple installations exist.
Resolution:
interpret the release-backed installer contract as the standard install behavior and the running executable path as the concrete target for self-update.
Why this is consistent:
it preserves the existing installation method while making the self-update target explicit and safe.

- Resolved conflict: bare CLI version strings versus `v`-prefixed release tags.
Conflicting sources:
`scripts/start-issue` exposes a bare numeric `VERSION`;
issue #13 and GitHub Releases use `v`-prefixed release tags.
Resolution:
compare normalized versions rather than raw strings.
Why this is consistent:
it preserves the current CLI output surface while matching the release system's tagging convention.
### Legacy FT-013 documents vs current Go implementation

The archived `feature.md` / `solution.md` described Bash paths and issue #13
only. They conflicted with the current Go change surface and issue #35
provenance. `DL-02` resolves this by making `brief.md` and `design.md` active
owners and retaining the old files only as migration redirects.

### Generic checksum wording vs current release manifest

Issue #35 says “its SHA-256 checksum”; the repository's current release contract
uses a platform binary plus `checksums.txt`. `DL-03` makes that existing
contract explicit without changing issue scope.
Loading
Loading