CI: validate relative links in nested repo Markdown examples #142

Closed
opened 2026-04-19 23:05:06 +00:00 by pokebedrock-bot · 2 comments
pokebedrock-bot commented 2026-04-19 23:05:06 +00:00 (Migrated from github.com)

Summary

assets/README.md currently documents a relative image example that does not resolve on main, and repo CI does not validate relative links inside nested non-doc Markdown like assets/**/*.md.

Evidence

  • Current assets/README.md line 6 uses ![UI](../../assets/images/ui.webp).
  • From assets/README.md, that path resolves outside the repo subtree it describes and does not exist.
  • Repro on current main:
    python3 - <<'PY'
    from pathlib import Path
    p = Path('assets/README.md')
    target = (p.parent / '../../assets/images/ui.webp').resolve()
    print(target.exists(), target)
    PY
    
    This prints False .../assets/images/ui.webp for the referenced example path.
  • CI still passes because:
    • npm run lint:links only crawls docs/**/*.{md,mdx}.
    • Running npx linkinator "assets/**/*.md" --config linkinator.config.json on current main exits 0 and reports Successfully scanned 1 links, so the current link check does not fail this stale local asset example.

Impact

  • Contributors copying the asset example from assets/README.md get a broken relative path.
  • A stale nested Markdown example can survive on main with no CI signal, even though this repo already treats contributor-facing docs as part of the maintenance surface.

Acceptance criteria

  • Add CI coverage for relative local links/images in nested non-doc Markdown that contributors read, at minimum assets/**/*.md.
  • Ensure the validation fails on missing local relative targets instead of silently passing.
  • Fix the broken example path in assets/README.md so it matches the real repository layout.
## Summary `assets/README.md` currently documents a relative image example that does not resolve on `main`, and repo CI does not validate relative links inside nested non-doc Markdown like `assets/**/*.md`. ## Evidence - Current `assets/README.md` line 6 uses `![UI](../../assets/images/ui.webp)`. - From `assets/README.md`, that path resolves outside the repo subtree it describes and does not exist. - Repro on current `main`: ```bash python3 - <<'PY' from pathlib import Path p = Path('assets/README.md') target = (p.parent / '../../assets/images/ui.webp').resolve() print(target.exists(), target) PY ``` This prints `False .../assets/images/ui.webp` for the referenced example path. - CI still passes because: - `npm run lint:links` only crawls `docs/**/*.{md,mdx}`. - Running `npx linkinator "assets/**/*.md" --config linkinator.config.json` on current `main` exits 0 and reports `Successfully scanned 1 links`, so the current link check does not fail this stale local asset example. ## Impact - Contributors copying the asset example from `assets/README.md` get a broken relative path. - A stale nested Markdown example can survive on `main` with no CI signal, even though this repo already treats contributor-facing docs as part of the maintenance surface. ## Acceptance criteria - Add CI coverage for relative local links/images in nested non-doc Markdown that contributors read, at minimum `assets/**/*.md`. - Ensure the validation fails on missing local relative targets instead of silently passing. - Fix the broken example path in `assets/README.md` so it matches the real repository layout.
pokebedrock-bot commented 2026-04-20 19:09:47 +00:00 (Migrated from github.com)

Fresh scan on current origin/main still reproduces this gap.

Evidence from today:

  • assets/README.md still contains ![UI](../../assets/images/ui.webp).
  • Resolved from that file, the path escapes the repo subtree and lands at /home/ubuntu/.openclaw/workspace/pokebedrock/assets/images/ui.webp, which does not exist.
  • package.json still scopes lint:links to linkinator "docs/**/*.{md,mdx}" --config linkinator.config.json, so repo Markdown outside docs/ is not part of the normal CI path.
  • Even a direct npx linkinator "assets/**/*.md" --config linkinator.config.json run still exits 0, so Linkinator alone is not catching this stale local relative target in nested Markdown.

Impact remains the same: contributors can copy a broken asset-path example from tracked repo docs, and current CI still reports green.

Acceptance criteria still look right to me:

  1. CI validates local relative links in nested non-doc Markdown (at least assets/**/*.md, and any other tracked nested Markdown we expect contributors to copy from).
  2. assets/README.md is updated to use a path example that actually resolves from that file.
  3. The check fails on missing local relative targets before merge.
Fresh scan on current `origin/main` still reproduces this gap. Evidence from today: - `assets/README.md` still contains `![UI](../../assets/images/ui.webp)`. - Resolved from that file, the path escapes the repo subtree and lands at `/home/ubuntu/.openclaw/workspace/pokebedrock/assets/images/ui.webp`, which does **not** exist. - `package.json` still scopes `lint:links` to `linkinator "docs/**/*.{md,mdx}" --config linkinator.config.json`, so repo Markdown outside `docs/` is not part of the normal CI path. - Even a direct `npx linkinator "assets/**/*.md" --config linkinator.config.json` run still exits 0, so Linkinator alone is not catching this stale local relative target in nested Markdown. Impact remains the same: contributors can copy a broken asset-path example from tracked repo docs, and current CI still reports green. Acceptance criteria still look right to me: 1. CI validates local relative links in nested non-doc Markdown (at least `assets/**/*.md`, and any other tracked nested Markdown we expect contributors to copy from). 2. `assets/README.md` is updated to use a path example that actually resolves from that file. 3. The check fails on missing local relative targets before merge.

Already fixed on main by 94afc02 (PR #151). assets/README.md uses ![UI](./images/example-ui.svg), and assets/images/example-ui.svg exists. scripts/check-images.ts scans assets/**/*.md and exits 1 when a local image is missing. Linkinator still ignores image targets, so the image check is the gate that fails closed. npm run lint runs that script.

Already fixed on `main` by `94afc02` (PR #151). `assets/README.md` uses `![UI](./images/example-ui.svg)`, and `assets/images/example-ui.svg` exists. `scripts/check-images.ts` scans `assets/**/*.md` and exits 1 when a local image is missing. Linkinator still ignores image targets, so the image check is the gate that fails closed. `npm run lint` runs that script.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pokebedrock/wiki#142
No description provided.