diff --git a/skills/explain-diff-html/SKILL.md b/skills/explain-diff-html/SKILL.md
index fbd1a1a..6500474 100644
--- a/skills/explain-diff-html/SKILL.md
+++ b/skills/explain-diff-html/SKILL.md
@@ -414,9 +414,29 @@ gh pr view --json url -q .url # https://github.com/owner/repo/pull/
# strip the trailing /pull/
# Branch, commit range, single commit, or no argument:
-git remote get-url origin | sed -E 's#^git@([^:]+):#https://\1/#; s#\.git$##'
+git remote get-url origin | sed -E '
+ # Drop a port. This runs before the scheme goes, because after that the
+ # owner in git@github.com:1234/repo.git would read like a port.
+ s#^([a-z+]+://[^/]*):[0-9]+/#\1/#
+ # Drop the scheme, such as https://, ssh://, or git+ssh://.
+ s#^[a-z+]+://##
+ # Drop credentials, such as git@ or user:token@, so no token reaches a link.
+ s#^[^@/]*@##
+ # Turn the host:owner form into host/owner.
+ s#^([^:/]+):#\1/#
+ # Drop a trailing .git, then a trailing slash.
+ s#\.git/?$##
+ s#/$##
+ # Print nothing unless the host is exactly github.com.
+ /^github\.com\//!d
+ s#^#https://#'
```
+Empty output means leave every reference bare. A CI clone's remote can embed a
+token, as in `https://x-access-token:@github.com/owner/repo.git`, and
+without the credentials line that token lands in every link on a page meant
+for sharing.
+
Build each link against the same commit the provenance line names, using the
full 40-character sha:
@@ -463,7 +483,8 @@ it does today.
This is GitHub only, on purpose. A url from `gh` names a GitHub-family host by
construction, so link against whatever host it gives you. A parsed remote could
-be any forge, so link it only when the host is exactly `github.com`. GitLab and
+be any forge, so link it only when the host is exactly `github.com`, which the
+`sed` above enforces. GitLab and
Bitbucket build blob URLs differently, and a GitHub-shaped URL aimed at them
resolves to nothing. Leave those references bare rather than guess.
diff --git a/skills/explain-diff-html/references/validation.md b/skills/explain-diff-html/references/validation.md
index fa68430..e312d27 100644
--- a/skills/explain-diff-html/references/validation.md
+++ b/skills/explain-diff-html/references/validation.md
@@ -74,10 +74,10 @@ that mistake now fails instead of passing.
still opens offline.
- The page linked the references it should have, and every link names the
- provenance commit. The script prints both counts as `references=N linked=M`,
- then fails on any `/blob/` link that does not name the short commit. It also
- fails on a link to a `.md` or `.markdown` file that has a line anchor and no
- `?plain=1`.
+ provenance commit in full. The script prints both counts as
+ `references=N linked=M`, then fails on any `/blob/` link whose sha is not the
+ full 40 characters starting with the short commit. It also fails on a link to
+ a `.md` or `.markdown` file that has a line anchor and no `?plain=1`.
The script's count needs both the `tr` and the `sed`. A `.filename` label
reads `class="filename">path:line` when bare and
diff --git a/skills/explain-diff-html/scripts/validate-output.sh b/skills/explain-diff-html/scripts/validate-output.sh
index 31c5dd1..0b1c1ba 100644
--- a/skills/explain-diff-html/scripts/validate-output.sh
+++ b/skills/explain-diff-html/scripts/validate-output.sh
@@ -14,6 +14,10 @@ if [ -z "$page" ] || [ -z "$sha" ]; then
echo "usage: sh validate-output.sh " >&2
exit 2
fi
+if ! printf '%s\n' "$sha" | grep -qE '^[0-9a-f]{4,40}$'; then
+ echo "usage: must be 4 to 40 lowercase hex characters" >&2
+ exit 2
+fi
# A directory passes test -s, and step 8's $out is a directory, so require a
# regular file as well.
@@ -30,13 +34,16 @@ refs=$(tr '\n' ' ' < "$page" | sed -E 's#?a[^>]*>##g; s/ +/ /g' \
links=$(grep -o 'class="srcref"' "$page" | wc -l | tr -d ' ')
echo "references=$refs linked=$links"
-wrong=$(grep -o 'href="[^"]*/blob/[^"]*"' "$page" | grep -v "$sha")
+# A link names the full 40-character sha. GitHub resolves an abbreviation only
+# while the commit is on a branch, so a short sha 404s once a squash merge lands.
+full="/blob/${sha}[0-9a-f]{$((40 - ${#sha}))}/"
+wrong=$(grep -o 'href="[^"]*/blob/[^"]*"' "$page" | grep -vE "$full")
if [ -n "$wrong" ]; then
- echo "FAIL: links that do not name $sha:"
+ echo "FAIL: links that do not name the full 40-character sha starting $sha:"
echo "$wrong"
status=1
else
- echo "pass: no blob link names another commit"
+ echo "pass: every blob link names the full sha of $sha"
fi
# GitHub renders Markdown, and the rendered view ignores a line anchor. Match