diff --git a/.github/workflows/docs-check.yml b/.github/workflows/docs-check.yml
new file mode 100644
index 0000000..eaf2d64
--- /dev/null
+++ b/.github/workflows/docs-check.yml
@@ -0,0 +1,77 @@
+name: Docs integrity
+
+on:
+ push:
+ branches: [main]
+ paths:
+ - "**/*.md"
+ - ".github/workflows/docs-check.yml"
+ pull_request:
+ paths:
+ - "**/*.md"
+ - ".github/workflows/docs-check.yml"
+
+permissions:
+ contents: read
+
+jobs:
+ docs:
+ name: Check Markdown
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Validate Markdown links and conflict markers
+ shell: python
+ run: |
+ import pathlib
+ import re
+ import sys
+ import urllib.parse
+
+ root = pathlib.Path(".").resolve()
+ markdown_files = sorted(pathlib.Path(".").rglob("*.md"))
+ problems = []
+
+ link_pattern = re.compile(r'!?\[[^\]]*\]\(([^)]+)\)')
+
+ for md in markdown_files:
+ text = md.read_text(encoding="utf-8")
+
+ for line_no, line in enumerate(text.splitlines(), 1):
+ if line.startswith(("<<<<<<<", "=======", ">>>>>>>")):
+ problems.append(f"{md}:{line_no}: merge-conflict marker found")
+
+ for match in link_pattern.finditer(text):
+ raw_target = match.group(1).strip()
+ if not raw_target:
+ continue
+
+ if raw_target.startswith("<") and raw_target.endswith(">"):
+ raw_target = raw_target[1:-1]
+
+ target = raw_target.split()[0].strip("'\"")
+ if target.startswith(("http://", "https://", "mailto:", "tel:", "#", "data:")):
+ continue
+
+ target = urllib.parse.unquote(target.split("#", 1)[0].split("?", 1)[0])
+ if not target:
+ continue
+
+ candidate = (md.parent / target).resolve()
+ try:
+ candidate.relative_to(root)
+ except ValueError:
+ problems.append(f"{md}: local link escapes repository: {target}")
+ continue
+
+ if not candidate.exists():
+ problems.append(f"{md}: broken relative link: {target}")
+
+ if problems:
+ print("\n".join(problems))
+ sys.exit(1)
+
+ print(f"Checked {len(markdown_files)} Markdown files.")
diff --git a/README.md b/README.md
index 82751a6..6af6653 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,10 @@
SwiftUI · SwiftData · WidgetKit · App Intents · StoreKit · offline-first