From 59493cf11193271bbf6a30e3ea0e2983e61d825d Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Sat, 4 Jul 2026 18:02:41 +0200 Subject: docs: implementation plan for semver adoption Co-Authored-By: Claude Opus 4.8 --- .../plans/2026-07-04-semver-adoption.md | 376 +++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 docs/superpowers/plans/2026-07-04-semver-adoption.md (limited to 'docs') diff --git a/docs/superpowers/plans/2026-07-04-semver-adoption.md b/docs/superpowers/plans/2026-07-04-semver-adoption.md new file mode 100644 index 0000000..05ffc2a --- /dev/null +++ b/docs/superpowers/plans/2026-07-04-semver-adoption.md @@ -0,0 +1,376 @@ +# SemVer adoption Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Adopt SemVer: `mkhint -v`/`--version` prints the tool version, the hint-version flag moves to `-V`/`--set-version`, add a CHANGELOG, and tag `v1.0.0` signed. + +**Architecture:** A `readonly MKHINT_VERSION` constant drives `--help` and a new `-v`/`--version` handler that prints and exits. The `getopt` spec and case handlers swap `-v`/`--version` (was hint-version, now tool-version) for `-V`/`--set-version` (hint-version). Tests, completion, and docs follow the rename. Release tagged at the end. + +**Tech Stack:** bash, `getopt`, existing `tests/mkhint_test.sh` harness, git signed tags. + +--- + +## File structure + +- Modify: `mkhint` — version constant, `getopt` line, case handlers, mutual-exclusion messages, `show_help` + header comments. +- Modify: `tests/mkhint_test.sh` — rename `-v`→`-V` in 9 hint-version calls + T26/T56; add T65-T67. +- Modify: `mkhint.bash-completion` — `all_flags`, move the version-suggest case to `--set-version|-V`. +- Modify: `README.md` — flag docs, examples, SemVer/Conventional-commits note. +- Modify: `CLAUDE.md` — flag references, test table (T65-T67). +- Create: `CHANGELOG.md`. + +No new dependencies. + +--- + +## Task 1: Version constant + `-v`/`--version` output, flag rename + +**Files:** +- Modify: `mkhint` (const near line 35; `getopt` ~1009; case ~1016; mutual-excl ~1103/1108) +- Test: `tests/mkhint_test.sh` (T65, T66, T67; rename existing `-v`) + +- [ ] **Step 1: Write failing tests T65, T66, T67** + +Append after T64 (before the SUMMARY block) in `tests/mkhint_test.sh`: + +```bash +# ── T65: mkhint -v prints tool version ─────────────────────────────────────── +echo "" +echo "T65: -v prints 'mkhint ' and exits 0" +set +e +out=$(run_mkhint -v 2>&1); code=$? +set -e +assert_exit_code "-v exits 0" 0 "$code" +echo "$out" | grep -Eq '^mkhint [0-9]+\.[0-9]+\.[0-9]+$' \ + && { echo " PASS: -v prints version"; (( PASS++ )); } \ + || { echo " FAIL: -v output wrong: $out"; (( FAIL++ )); ERRORS+=("T65 output"); } + +# ── T66: mkhint --version prints tool version ──────────────────────────────── +echo "" +echo "T66: --version prints 'mkhint ' and exits 0" +set +e +out=$(run_mkhint --version 2>&1); code=$? +set -e +assert_exit_code "--version exits 0" 0 "$code" +echo "$out" | grep -Eq '^mkhint [0-9]+\.[0-9]+\.[0-9]+$' \ + && { echo " PASS: --version prints version"; (( PASS++ )); } \ + || { echo " FAIL: --version output wrong: $out"; (( FAIL++ )); ERRORS+=("T66 output"); } + +# ── T67: -V still sets the hint version (rename works) ─────────────────────── +echo "" +echo "T67: -V -n sets hint VERSION" +rm -f "$MOCK_HINT"/*.hint "$MOCK_HINT"/*.bak 2>/dev/null +run_mkhint -n curl -V 8.6.0 >/dev/null 2>&1 +assert_contains "hint VERSION set via -V" "$MOCK_HINT/curl.hint" 'VERSION="8.6.0"' +``` + +- [ ] **Step 2: Run tests, verify they fail** + +Run: `bash tests/mkhint_test.sh 2>&1 | grep -E 'T6[567]'` +Expected: T65/T66 FAIL (`-v` currently expects an argument → getopt error / wrong output), T67 FAIL (`-V` unknown flag). + +- [ ] **Step 3: Add the version constant** + +In `mkhint`, after the `VERSION=""` line (~35), add: + +```bash +readonly MKHINT_VERSION="1.0.0" +``` + +- [ ] **Step 4: Update the getopt spec** + +Replace the `getopt` invocation (~1009): + +```bash + parsed=$(getopt -o vV:f:n:lcCdNhRF \ + --long version,set-version:,hintfile:,new:,list,clean,check,delete,no-dl,help,review,fix-current \ + -n 'mkhint' -- "$@") || { show_help; exit 1; } +``` + +- [ ] **Step 5: Replace the case handler** + +Replace the `--version|-v)` case (~1016): + +```bash + --version|-v) + echo "mkhint $MKHINT_VERSION" + exit 0 + ;; + --set-version|-V) + VERSION="$2" + shift 2 + ;; +``` + +- [ ] **Step 6: Update mutual-exclusion messages** + +Change both messages (~1103, ~1108) `--version` → `--set-version`: + +```bash + echo "Error: --check cannot be combined with --set-version/--hintfile/--new" >&2 +``` +```bash + echo "Error: --fix-current cannot be combined with --set-version/--hintfile/--new" >&2 +``` + +- [ ] **Step 7: Rename existing `-v` hint-version calls in tests** + +In `tests/mkhint_test.sh`, change `-v` to `-V` in these hint-version invocations +(the version-setting ones only — do NOT touch T65/T66 which use bare `-v`): + +- line ~330: `run_mkhint -n curl -V 8.6.0` +- line ~347: `run_mkhint -n curl -V 8.7.0 -N` +- line ~372: `run_mkhint -f curl -V 8.9.0` +- line ~389: `run_mkhint -f curl -V 9.0.0 -N` +- line ~401: `run_mkhint -f clion -V 2025.4` +- line ~419: `run_mkhint -f nonexistent -V 1.0 2>/dev/null` +- line ~456: `echo "" | run_mkhint -n protoc-gen-go-grpc -V 1.4.0` +- line ~610 (T26): `run_mkhint -C -V 1.0 2>/dev/null` +- line ~1096 (T56): `run_mkhint -F -V 1.0.0 2>/dev/null` + +Use grep to confirm none remain: `grep -n 'run_mkhint.* -v ' tests/mkhint_test.sh` +Expected: only the `-v` in T65 (bare, no value) — actually T65 uses `run_mkhint -v 2>&1` +with no trailing space-value, so this grep (`-v ` followed by a token) should +return nothing. Verify by eye. + +- [ ] **Step 8: Run full suite** + +Run: `bash -n mkhint && bash tests/mkhint_test.sh 2>&1 | tail -4` +Expected: `Results: 138 passed, 0 failed` (135 + T65/T66/T67). + +- [ ] **Step 9: Commit** + +```bash +git add mkhint tests/mkhint_test.sh +git commit -S -m "feat!: -v/--version prints tool version; hint version moves to -V/--set-version" +``` + +--- + +## Task 2: `--help` text + script header comments + +**Files:** +- Modify: `mkhint` (header comments ~6-7; `show_help` ~50-78) + +- [ ] **Step 1: Update the version-showing header line in show_help** + +In `mkhint`, change the `show_help` title line (~50): + +```bash +mkhint $MKHINT_VERSION - Manage hint files for slackrepo scripts +``` + +(The heredoc is `<`, exit 0 | +| T66 | `mkhint --version` prints `mkhint `, exit 0 | +| T67 | `mkhint -V -n ` sets hint VERSION (rename works) | +``` + +- [ ] **Step 5: Full suite + syntax, sanity re-read docs** + +Run: `bash -n mkhint && bash tests/mkhint_test.sh 2>&1 | tail -3` +Expected: `138 passed, 0 failed`. + +- [ ] **Step 6: Commit** + +```bash +git add CHANGELOG.md README.md CLAUDE.md +git commit -S -m "docs: add CHANGELOG, document SemVer and -V/--set-version rename" +``` + +--- + +## Task 5: Tag the release + +**Files:** none (git tag only) + +- [ ] **Step 1: Confirm working tree is clean and tests pass** + +Run: `git status --porcelain && bash tests/mkhint_test.sh 2>&1 | tail -2` +Expected: no output from status; `138 passed, 0 failed`. + +- [ ] **Step 2: Create the signed annotated tag** + +```bash +git tag -s v1.0.0 -m "mkhint 1.0.0" +git tag -v v1.0.0 +``` +Expected: `git tag -v` shows a good GPG signature. + +- [ ] **Step 3: Push commits and tag to both remotes** + +`origin` has two push URLs (danix_git, slackware_forge). + +```bash +git push origin master +git push origin v1.0.0 +``` +Expected: both refs land on both remotes. + +--- + +## Self-review notes + +- Spec coverage: version constant + output (Task 1), flag rename (Task 1), mutual-excl messages (Task 1), help text (Task 2), completion (Task 3), CHANGELOG (Task 4), README/CLAUDE + SemVer/Conventional note (Task 4), git tag (Task 5), tests T65-T67 + renames (Task 1). All covered. +- Flag names consistent across tasks: `-V`/`--set-version` (hint version), `-v`/`--version` (tool version, no arg). +- getopt string `vV:f:n:lcCdNhRF` — `v` bare, `V:` takes arg. Verified against current `v:f:n:lcCdNhRF`. +- Test count: 135 → 138 (T65, T66, T67). Renamed calls do not change the count. +- T26/T56 assert exit code only (no message grep), so `-v`→`-V` is safe there. +- Breaking change flagged with `feat!:` commit and CHANGELOG "Breaking" entry. -- cgit v1.2.3