From d0b4dda8efcc5329df52fd875b854ad21b492542 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 18 Jun 2026 01:00:35 +0000
Subject: [PATCH] chore: publish from staged
---
.codespellrc | 4 +-
docs/README.hooks.md | 1 +
hooks/fix-broken-links/README.md | 177 ++++++++++++
hooks/fix-broken-links/hooks.json | 14 +
hooks/fix-broken-links/link-fix.ps1 | 410 ++++++++++++++++++++++++++++
hooks/fix-broken-links/link-fix.sh | 372 +++++++++++++++++++++++++
6 files changed, 977 insertions(+), 1 deletion(-)
create mode 100644 hooks/fix-broken-links/README.md
create mode 100644 hooks/fix-broken-links/hooks.json
create mode 100644 hooks/fix-broken-links/link-fix.ps1
create mode 100644 hooks/fix-broken-links/link-fix.sh
diff --git a/.codespellrc b/.codespellrc
index e9272550..c554845f 100644
--- a/.codespellrc
+++ b/.codespellrc
@@ -54,7 +54,9 @@
# CAF - Microsoft Cloud Adoption Framework acronym
-ignore-words-list = numer,wit,aks,edn,ser,ois,gir,rouge,categor,aline,ative,afterall,deques,dateA,dateB,TE,FillIn,alle,vai,LOD,InOut,pixelX,aNULL,Wee,Sherif,queston,Vertexes,nin,FO,CAF,Parth
+# ans - bash and powershell variable short for answer
+
+ignore-words-list = numer,wit,aks,edn,ser,ois,gir,rouge,categor,aline,ative,afterall,deques,dateA,dateB,TE,FillIn,alle,vai,LOD,InOut,pixelX,aNULL,Wee,Sherif,queston,Vertexes,nin,FO,CAF,Parth,ans
# Skip certain files and directories
diff --git a/docs/README.hooks.md b/docs/README.hooks.md
index f0682632..ba3f4d44 100644
--- a/docs/README.hooks.md
+++ b/docs/README.hooks.md
@@ -32,6 +32,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-hooks) for guidelines on how to
| Name | Description | Events | Bundled Assets |
| ---- | ----------- | ------ | -------------- |
| [Dependency License Checker](../hooks/dependency-license-checker/README.md) | Scans newly added dependencies for license compliance (GPL, AGPL, etc.) at session end | sessionEnd | `check-licenses.sh`
`hooks.json` |
+| [Fix Broken Links](../hooks/fix-broken-links/README.md) | Checks changed web files for broken hyperlinks and SEO anchor issues after each Copilot tool use. | postToolUse | `hooks.json`
`link-fix.ps1`
`link-fix.sh` |
| [Governance Audit](../hooks/governance-audit/README.md) | Scans Copilot agent prompts for threat signals and logs governance events | sessionStart, sessionEnd, userPromptSubmitted | `audit-prompt.sh`
`audit-session-end.sh`
`audit-session-start.sh`
`hooks.json` |
| [Secrets Scanner](../hooks/secrets-scanner/README.md) | Scans files modified during a Copilot coding agent session for leaked secrets, credentials, and sensitive data | sessionEnd | `hooks.json`
`scan-secrets.sh` |
| [Session Auto-Commit](../hooks/session-auto-commit/README.md) | Automatically commits and pushes changes when a Copilot coding agent session ends | sessionEnd | `auto-commit.sh`
`hooks.json` |
diff --git a/hooks/fix-broken-links/README.md b/hooks/fix-broken-links/README.md
new file mode 100644
index 00000000..5adbaafd
--- /dev/null
+++ b/hooks/fix-broken-links/README.md
@@ -0,0 +1,177 @@
+---
+name: 'Fix Broken Links'
+description: 'Checks changed web files for broken hyperlinks and SEO anchor issues after each Copilot tool use.'
+tags: ['links', 'seo', 'html', 'markdown', 'post-tool-use']
+---
+
+# Fix Broken Links Hook
+
+Scans recently-changed web files for broken hyperlinks after each GitHub Copilot
+tool use. For each broken URL the hook tries common spelling variations, then hands
+the link to the Copilot CLI agent for suggested replacements, and presents an
+interactive fix menu. Generic anchor text (`click here`, `read more`, etc.) is
+flagged as an SEO issue.
+
+## Overview
+
+Broken links accumulate silently in web projects. Running on the `postToolUse`
+event, this hook checks the web files the agent just edited — and only those —
+right after each change, so you can fix, replace, or remove each broken link in
+the same terminal session.
+
+The hook has two modes:
+
+- **With file paths** (the edited files injected from the hook payload, or paths
+ passed on the command line): it checks each link, looks up replacement
+ candidates, and presents the interactive fix menu.
+- **With no file arguments**: it simply lists the broken links it finds — no
+ replacement lookups and no prompts.
+
+## Features
+
+- **Self-contained core**: bash and PowerShell ports — no runtime to install (the optional agent
+ hand-off reuses the Copilot CLI you already have)
+- **Edited-files scope**: as a `postToolUse` hook it only checks the files the agent just changed —
+ never a full repo scan
+- **Format-agnostic link scan**: extracts every `http(s)` URL with `grep`, covering HTML, Markdown,
+ JS/TS, JSON, CSS, SQL, and templates at once
+- **Automatic URL healing**: tries www, https, and trailing-slash variations
+- **Agent-assisted suggestions**: hands the broken link to the Copilot CLI agent (a lightweight,
+ low-token `gpt-5-mini` prompt with no tools) for replacement candidates; if the CLI is missing or
+ errors, it simply offers none
+- **SEO audit**: flags anchor text that is too generic to benefit search ranking
+- **Large-file guard**: prompts before checking files with more than 50 links
+- **Interactive fix menu**: replace with suggestion, enter custom URL, strip tag keeping text, or
+ skip
+- **Standard tools only**: `curl`, `grep`, `sed` — present on any POSIX system
+
+## Installation
+
+1. Copy the hook folder to your repository:
+
+ ```bash
+ cp -r hooks/fix-broken-links .github/hooks/
+ ```
+
+2. Make the script executable:
+
+ ```bash
+ chmod +x .github/hooks/fix-broken-links/link-fix.sh
+ ```
+
+3. Commit the hook configuration to your repository's default branch.
+
+## Configuration
+
+The hook is configured in `hooks.json` to run on the `postToolUse` event:
+
+```json
+{
+ "version": 1,
+ "hooks": {
+ "postToolUse": [
+ {
+ "type": "command",
+ "bash": ".github/hooks/fix-broken-links/link-fix.sh",
+ "powershell": ".github/hooks/fix-broken-links/link-fix.ps1",
+ "cwd": ".",
+ "timeoutSec": 120
+ }
+ ]
+ }
+}
+```
+
+## Supported Source Types
+
+Links are found by scanning each file for `http(s)://` URLs, so the same logic
+covers every format that embeds absolute URLs:
+
+| Source | Examples matched |
+| --- | --- |
+| HTML | ``, `
`, `