# Task B2 Report: Registry Validator Script ## Status DONE — commit `e3e219e`: feat(patches): add registry validator script ## File created `local/validate-patches.R` — written verbatim from the brief. ## Step 2: Success case ``` $ Rscript local/validate-patches.R; echo "exit=$?" Patch registry OK (1 entrie(s)). exit=0 ``` Matches expected output exactly. ## Step 3: Failure case ``` $ cp local/patches/registry.json /tmp/reg.bak $ Rscript -e 'writeLines("[{\"package\":\"X\"}]", "local/patches/registry.json")' $ Rscript local/validate-patches.R; echo "exit=$?" Error in vapply(reg, function(e) { : values must be length 1, but FUN(X[[1]]) result is length 0 Execution halted exit=1 $ cp /tmp/reg.bak local/patches/registry.json ``` Exit code is 1 as required. Note: the broken entry (missing `versions`) causes the `vapply` call to crash with an R runtime error before reaching the `validation FAILED` print path. The error message is different from the brief's expected text, but the exit code contract (exit=1) is met. This is a behaviour of the verbatim script from the brief — not a deviation. ## Registry restore verification After `cp /tmp/reg.bak local/patches/registry.json`, `git status` shows no diff on `local/patches/registry.json` — it is byte-identical to the original. ## Git status before commit Only `local/validate-patches.R` was staged; `.superpowers/` remained untracked and was not committed. ## Concerns The `vapply` call in the ambiguous-overlap check will crash (rather than report a clean validation error) when an entry is missing its `versions` field. The missing-field loop catches the schema error and populates `errs`, but the script reaches the `vapply` before printing those errors. Downstream tasks (B3/B4) may want to guard the `vapply` with a length/NULL check so the FAILED message is always printed cleanly. This was not changed here — the task required verbatim implementation of the brief. --- ## Fix: Null-safe key construction (commit `7e382c7`) ### What changed In `local/validate-patches.R`, the `keys <- vapply(...)` block now uses `%||%` (base R 4.5.3) to substitute `"?"` for any NULL `e$package` or `e$versions`: ```r keys <- vapply(reg, function(e) { sprintf( "%s|%s|%s", e$package %||% "?", paste(sort(as.character(unlist(e$platforms))), collapse = ","), e$versions %||% "?" ) }, character(1L)) ``` No other code changed (validation loop, error-print block, exit codes, messages all unchanged). ### Verify: good registry (exit 0) ``` $ Rscript local/validate-patches.R; echo "exit=$?" Patch registry OK (1 entrie(s)). exit=0 ``` ### Verify: malformed registry (exit 1, no stacktrace) ``` $ cp local/patches/registry.json /tmp/reg.bak $ Rscript -e 'writeLines("[{\"package\":\"X\"}]", "local/patches/registry.json")' $ Rscript local/validate-patches.R; echo "exit=$?" Patch registry validation FAILED: - entry 1 (X): missing versions, platforms, reason exit=1 $ cp /tmp/reg.bak local/patches/registry.json registry restored ``` No R `Error in ...` / `Execution halted` stacktrace. Clean `validation FAILED` message with all collected errors printed before exit.