# REVIEW — ffind cross-shell rewrite + OBS packaging/release integration

Scope: one pass over the full file-set listed in the task (ffind, ffind-preview,
completions/*, VERSION, LICENSE, install.sh, README.md, .forgejo/workflows/*,
watchdog.sh, projects.yaml, and the /tmp/obs_ffind seed).

Static gates:
- `bash -n` on watchdog.sh: PASS.
- `shellcheck ffind ffind-preview install.sh`: clean (exit 0).
- Advisory straitjacket on all touched files: clean (`[]`, no findings to triage).

## Findings

1. (BLOCKER) ffind: unquoted fzf `{}` breaks preview + Ctrl-Y copy for any path
   containing spaces. `--preview="ffind-preview {}"` and
   `--bind="ctrl-y:execute-silent(ffind-preview --copy {})"` pass the selection
   to the shell unquoted; fzf does NOT add quotes. `ffind-preview` then does
   `line="$*"` + `cut -d: -f1`, so `file with spaces` collapses to `file`.
   This is a headline feature (Ctrl-Y copy path) and is broken for the common
   case of spaced paths. Fix: quote the placeholder, i.e.
   `--preview='ffind-preview "{}"'` and
   `--bind='ctrl-y:execute-silent(ffind-preview --copy "{}")'`.

2. (BLOCKER) Content search is not actually performed, yet README/spec claim it.
   The pipeline feeds `rg -n --files "$dir" | head -10000; rg --files "$dir"`.
   Verified: `rg -n --files` emits ONLY filenames (no `file:line:text`), so the
   "content match" branch in ffind-preview (`rg --color=always -n "^" "$file"`)
   is dead code and never triggers. README line 12 ("plus content matches via
   ripgrep") and the spec %description are therefore false. Either change the
   pipeline to search content (e.g. `rg -n . ...) or drop the content-search
   claim from README/spec. This reproduces the original ffind.fish defect
   verbatim (it used the identical pipeline), so it is a faithful port — but it
   contradicts the stated tool purpose.

3. (BLOCKER) install.sh fallback is broken: `PIN="PIN_HERE"` is an unresolved
   placeholder. `clone_pinned` runs `git -C "$TMPDIR/repo" checkout "$PIN"`,
   which fails (unknown ref) and, under `set -euo pipefail`, aborts the whole
   script before `install_script_copy` runs. This breaks every documented
   fallback path: macOS (`brew ... + script copy`), non-linux, and the
   "no OBS package asset yet" Linux fallback. The plan requires a working
   "source fallback for unsupported pm/arch". Must substitute a real commit SHA
   (or make the checkout tolerate a missing PIN and fall back to HEAD) before
   tagging v0.1.0.

4. (MINOR) install.sh token parse can truncate. `git credential fill` output is
   piped to `grep '^password=' | cut -d= -f2`. A PAT/token containing `=` is
   cut to its first segment, yielding a bad Authorization header. Use
   `cut -d= -f2-` (or `sed 's/^password=//'`).

5. (MINOR) release.yml Job A excludes only `.git`, not `target` as the plan
   (Part 2) specifies. Harmless today (repo has no `target` dir), but the
   tarball step diverges from the approved contract. Add `--exclude=target`.

6. (VERIFY / MEDIUM) /tmp/obs_ffind/debian.dsc `Files:` line carries a
   placeholder hash/size: `00000000000000000000000000000000 0 ffind-0.1.0.tar.xz`.
   The watchdog's forgejo_scm handler never recomputes this entry (it only
   rewrites `Version:`, `DEBTRANSFORM-TAR:`, and the filename via dsc_pattern).
   If OBS debtransform enforces hash/size integrity, the deb build will fail; if
   it regenerates the Files section from the provided tarball, it is fine.
   Confirm against a real OBS `osc build` before relying on the deb target.

7. (INFO/PASS) watchdog forgejo_scm generalization is correct for the ffind
   entry: `vendor_asset` is unset → `vnd_name` stays empty → all vendor blocks
   are skipped; `src_glob`=`ffind-[0-9.]*.tar.xz` removes the seed tarball and
   re-downloads `ffind-0.1.0.tar.xz`; dsc gets `Version: 0.1.0-1`,
   `DEBTRANSFORM-TAR: ffind-0.1.0.tar.xz`. projects.yaml ffind entry matches
   (no vendor_asset). For dotbackup (vendor_asset set) the same branch downloads
   both tarballs and bumps dsc Version to `$NEW_VER-1`, mirroring the prior
   behaviour; cannot byte-diff the old handler but the structure is symmetric.

8. (INFO/PASS) OBS seed files match the watchdog output contract:
   ffind.spec `Version: 0.1.0` (watchdog sets `Version: $NEW_VER`),
   debian.dsc `Version: 0.1.0-1` + `DEBTRANSFORM-TAR: ffind-0.1.0.tar.xz`,
   both consistent with release.yml Job A's `--transform "s|^\./|ffind-$VER/|"`.
   release.yml Job B attach globs `bin/ffind-[0-9]*.rpm` and
   `bin/ffind_[0-9]*_*.deb` correctly match `ffind-0.1.0-1.noarch.rpm` and
   `ffind_0.1.0-1_all.deb` (glob `*` = `.*`), and the `$VER` version-gate is
   sound. No vendor tarball is produced or expected.

9. (INFO) arg-parsing edge cases in ffind: multiple positional dirs silently
   let the last one win (no error); an unknown `-x` correctly errors with exit 2.
   Acceptable for the documented `ffind [dir] [--md]` interface, but a second
   positional dir is neither rejected nor merged.

## Verdict

BLOCKED: finding 1 (unquoted `{}` breaks preview + Ctrl-Y copy), finding 2
(content search claimed but not implemented), finding 3 (install.sh PIN_HERE
placeholder breaks every script-copy fallback). Findings 4-5 are minor must-fix;
finding 6 needs an OBS build verification.
