aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers/specs/2026-06-13-check-populate-missing-sections-design.md
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-06-13 17:52:50 +0200
committerDanilo M. <danix@danix.xyz>2026-06-13 17:52:50 +0200
commit152d1df60289981aadfb23e63de35d33e509f6dd (patch)
treeda566bed3fa4749a454cd40ec1c2a93580d4b270 /docs/superpowers/specs/2026-06-13-check-populate-missing-sections-design.md
parent29bbd6377f6e2758b1dea6bcba2f89c991484a19 (diff)
downloadmkhintfile-152d1df60289981aadfb23e63de35d33e509f6dd.tar.gz
mkhintfile-152d1df60289981aadfb23e63de35d33e509f6dd.zip
docs: spec for --check populate missing nvchecker sections
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'docs/superpowers/specs/2026-06-13-check-populate-missing-sections-design.md')
-rw-r--r--docs/superpowers/specs/2026-06-13-check-populate-missing-sections-design.md155
1 files changed, 155 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-06-13-check-populate-missing-sections-design.md b/docs/superpowers/specs/2026-06-13-check-populate-missing-sections-design.md
new file mode 100644
index 0000000..3a8b42a
--- /dev/null
+++ b/docs/superpowers/specs/2026-06-13-check-populate-missing-sections-design.md
@@ -0,0 +1,155 @@
+# `--check` populate missing nvchecker sections — design
+
+Date: 2026-06-13
+
+## Summary
+
+When `mkhint --check` / `-C` scans hint files, packages that have no `[pkg]`
+section in `nvchecker.toml` are currently skipped silently-ish (`skip pkg: no
+nvchecker source`). On a fresh/empty `nvchecker.toml` this means *every* hint is
+skipped and the command does nothing useful.
+
+This feature makes `--check` detect those missing-section packages and, after the
+scan, offer to populate `nvchecker.toml` by appending sections for them (reusing
+the existing `add_nvchecker_section` autodetect logic). If the user accepts, the
+sections are written and the run stops with a message telling the user to review
+the file (fill any stubs) and re-run `mkhint -C`.
+
+## Motivation
+
+`add_nvchecker_section` already exists and is called on `--new`. `--check` should
+give the user a path to bootstrap nvchecker config for hints created before this
+integration existed, without hand-editing the TOML for every package.
+
+## Behaviour
+
+Implemented inside the existing `check_updates` function.
+
+### 1. Detect missing sections during the classify loop
+
+The classify loop currently does, per target package:
+
+```bash
+latest=$(nvchecker_latest "$pkg") || { echo "skip ${pkg}: no nvchecker source"; continue; }
+```
+
+Change so the "no result" case distinguishes two situations:
+
+- A `[pkg]` section **exists** in `NVCHECKER_CONFIG` but nvchecker produced no
+ version → genuine "no result", keep the existing skip message
+ (`skip ${pkg}: no nvchecker result`).
+- A `[pkg]` section is **missing** → add `pkg` to a `missing_sections` array and
+ print `skip ${pkg}: no nvchecker section` (do not classify it as outdated).
+
+Section presence is tested with the same pattern `add_nvchecker_section` uses,
+extracted into a small shared helper:
+
+```bash
+# Return 0 if NVCHECKER_CONFIG has a [pkg] section
+_has_nvchecker_section() {
+ local pkg="$1"
+ grep -qE "^\[${pkg}\][[:space:]]*$" "$NVCHECKER_CONFIG"
+}
+```
+
+`add_nvchecker_section` is updated to call `_has_nvchecker_section` instead of its
+inline `grep` (pure DRY refactor, no behaviour change).
+
+### 2. Offer to populate, after the classify loop
+
+After the classify loop completes and before the "nothing outdated" / report
+logic, insert:
+
+```bash
+if [[ ${#missing_sections[@]} -gt 0 ]]; then
+ echo ""
+ echo "${#missing_sections[@]} package(s) have no nvchecker section: ${missing_sections[*]}"
+ local answer
+ read -r -p "Populate ${NVCHECKER_CONFIG} now? [Y/n] " answer
+ answer="${answer:-Y}"
+ if [[ "$answer" =~ ^[Yy]$ ]]; then
+ local mp info
+ for mp in "${missing_sections[@]}"; do
+ info=$(find "$REPO_DIR" -mindepth 2 -name "${mp}.info" 2>/dev/null | head -1)
+ if [[ -z "$info" ]]; then
+ echo "skip ${mp}: no .info found in $REPO_DIR"
+ continue
+ fi
+ add_nvchecker_section "$mp" "$info"
+ done
+ echo ""
+ echo "Sections added. Review $NVCHECKER_CONFIG (fill any stubs), then re-run 'mkhint -C'."
+ return 0
+ fi
+fi
+```
+
+Key points:
+
+- Single batch prompt (not per package). Default Yes.
+- For each missing package, the `.info` is located in `REPO_DIR` with the same
+ `find` pattern `list_hint_files` already uses.
+ - No `.info` found → print `skip ${mp}: no .info found in $REPO_DIR`, do not add
+ a section.
+ - `.info` found → call `add_nvchecker_section "$mp" "$info"`, which appends a
+ github/pypi section if detected, otherwise a commented stub. (Its own
+ duplicate guard via `_has_nvchecker_section` makes this safe.)
+- After populating, **stop the run** (`return 0`) with the review message. The
+ newly added sections are not queried this run — the user reviews/fills stubs
+ first, then re-runs. (Decision: simple separation over one-shot convenience.)
+- If the user declines, fall through to the normal report path. The
+ missing-section packages were already excluded during classify, so they simply
+ don't appear as outdated.
+
+### Interaction with the outdated set
+
+A run can have both outdated packages (with sections) and missing-section
+packages. If the user accepts populate, the run stops *before* applying any
+outdated updates — so populate takes precedence and the user re-runs to pick up
+updates afterward. This is acceptable: it keeps each run's effect simple and
+predictable. If the user declines populate, outdated updates proceed as today.
+
+## Affected code
+
+- `mkhint`:
+ - New helper `_has_nvchecker_section`.
+ - `add_nvchecker_section` refactored to use it (no behaviour change).
+ - `check_updates`: `missing_sections` array, distinguished skip messages, the
+ populate prompt block.
+- `tests/mkhint_test.sh`: T29–T31.
+- `CLAUDE.md` / `README.md`: document the populate prompt under `--check`.
+
+No new dependencies, no new flags, no exit-code changes.
+
+## Testing
+
+Mock-based, as existing suite. The mock nvchecker keyfile (`new_ver.json`) only
+contains versions for packages we want "found"; a package absent from the keyfile
+AND absent from the TOML is a missing-section case.
+
+| ID | Scenario |
+|-----|----------|
+| T29 | `-C`, hint with no section, github `.info`, accept populate → github section appended, run stops with review message, hint NOT updated |
+| T30 | `-C`, hint with no section, decline populate → no section added, no error (normal skip path) |
+| T31 | `-C`, hint with no section, no `.info` in repo, accept populate → `skip ... no .info found`, no section added |
+
+Test mechanics:
+
+- T29 uses a package that has a `.info` with a github HOMEPAGE/DOWNLOAD in
+ `MOCK_REPO` (the existing `ghpkg` fixture) but **no** `[ghpkg]` line in the test
+ `nvchecker.toml` and **no** entry in `new_ver.json`. After `printf 'Y\n'`,
+ assert the TOML now contains `[ghpkg]` + `source = "github"`, assert output
+ contains the review message, assert the hint file VERSION is unchanged.
+- T30 uses the same setup but `printf 'n\n'`; assert TOML still has no `[ghpkg]`.
+- T31 uses a package name with a hint file but no matching `.info` anywhere in
+ `MOCK_REPO` (e.g. a hand-written `orphan.hint`); after `printf 'Y\n'`, assert
+ output contains `no .info found` and TOML has no `[orphan]` section.
+
+## Self-review notes
+
+- Reuses `add_nvchecker_section` and the `find` pattern from `list_hint_files` —
+ no new mechanisms.
+- `_has_nvchecker_section` is the only new unit; DRYs an existing grep.
+- `set -e` safety: `find ... || head` is in a command substitution (non-fatal);
+ `add_nvchecker_section` returns 0; `read` is fine. No unguarded fallible calls.
+- Scope: single function change plus one helper plus three tests. Single plan.