Skip to content

fix(skills): repair machine-absolute and dangling relative links + link gate#79

Closed
korallis wants to merge 1 commit into
danielvm-git:mainfrom
korallis:fix/skill-link-integrity
Closed

fix(skills): repair machine-absolute and dangling relative links + link gate#79
korallis wants to merge 1 commit into
danielvm-git:mainfrom
korallis:fix/skill-link-integrity

Conversation

@korallis

Copy link
Copy Markdown
Contributor

What

Fixes the broken skill links reported in #78, at the source, plus a regression gate.

Changes

Source fixes (skills/)

  • elaborate-spec, plan-release: file:///Users/danielvm/.../countable-story-format.md → GitHub blob URL. docs/ is .npmignored, so the file can never be linked relatively in published installs; the blob URL works everywhere.
  • evolve-skill/REFERENCE.md: hardcoded `/Users/danielvm/Developer/bigpowers-benchmark/` → machine-agnostic clone resolution guidance.
  • craft-skill, investigate-bug, plan-refactor: docs/ links (PRINCIPLES.md, model-profiles.md, feathers.md, fowler.md, kent-beck.md) → blob URLs (same npm-exclusion problem).
  • using-bigpowers: ../profiles/solo-git.md../../profiles/solo-git.md (was dangling even in-repo).
  • write-document/REFERENCE.md: CHANGELOG.md/LICENSE → repo-root-relative.
  • guard-git: [hooks/](hooks/)[REFERENCE.md](REFERENCE.md) — the hook bundle lives inline in REFERENCE.md; no hooks/ dir exists.
  • audit-code: dropped a dead REFERENCE.md link (the --parallel helper script path is already given inline).
  • grill-me/REFERENCE.md, model-domain/CONTEXT-FORMAT.md: de-linked illustrative example paths ([docs](URL), ./src/*/CONTEXT.md) that were never meant to resolve.

Renderer fix (the ~40 dangling REFERENCE.md links in .pi/skills/)

  • scripts/lib/srp-engine.py: new rewrite_links_for_pi() — relative links in rendered pi skills are repointed from .pi/skills/<name>/ to the shipped source tree (../../../skills/<name>/X, ../../../CHANGELOG.md, …). Content was already inlined by parse_skill(); now the links resolve too, in repo checkouts and npm installs alike. External/anchor/absolute links pass through.
  • scripts/adapters/pi.sh: renders skill files from the new body_pi_skill IR field; .pi/prompts output is unchanged apart from source edits.

Regression gate

  • scripts/check-skill-links.py: fails on machine-absolute paths (file:///, /Users/, /home/, C:\Users) and on any dangling relative link in skills/**/SKILL.md and .pi/skills/**/SKILL.md. Wired into the compliance npm script; also runnable standalone as check:skill-links.
  • .pi/skills/ regenerated via sync-skills.sh; python3 scripts/check-skill-links.pyOK — no machine paths or dangling links (was 45+ before this change).

Notes

Fixes #78

- replace file:///Users/danielvm countable-story-format links with the
  GitHub blob URL (docs/ is excluded from the npm package, so the file
  cannot be linked relatively in published installs)
- evolve-skill: benchmark repo path is now machine-agnostic
- craft-skill/investigate-bug/plan-refactor: docs/ links -> blob URLs
- using-bigpowers: profiles link -> repo-relative; write-document:
  CHANGELOG/LICENSE -> repo-relative; guard-git: hooks/ -> REFERENCE.md
  (the bundle lives there); audit-code: drop dead REFERENCE.md link
- grill-me/model-domain: de-link illustrative example paths
- srp-engine: rewrite relative links for the pi tree so they resolve
  from .pi/skills/<name>/ against the shipped source tree
- pi adapter: render skill files from body_pi_skill (prompts unchanged)
- add scripts/check-skill-links.py regression gate, wired into
  the compliance npm script

Fixes danielvm-git#78

@danielvm-git danielvm-git left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — Dual-Blind AND-gate: ❌ FAIL (Round 1/5)

Two independent reviewers scored this PR 33% and 62.5% respectively. Both are below the 94% merge threshold. Requesting changes before merge.


🔴 Must-Fix (3)

[A-1] LINK_RE matches inside fenced code blocks
Both rewrite_links_for_pi and check-skill-links.py apply LINK_RE to raw Markdown including fenced code blocks and inline code. check-skill-links.py will emit false-positive "dangling link" errors on example paths shown in code blocks; rewrite_links_for_pi will silently corrupt those examples in rendered output. Code block content must be stripped before link matching.

[A-2] LINK_RE silently drops links with title attributes
[text](target "Title") — the [^)\s]+ pattern stops at the space before the title. These links escape both the rewriter and the regression gate silently. Fix: r'\[([^\]]*)\]\(([^)\s"]+)(?:\s+"[^"]*")?\s*\)'

[B-1] DRY violation — LINK_RE + EXTERNAL_RE duplicated across two files
scripts/lib/srp-engine.py and scripts/check-skill-links.py independently define identical pattern constants. CONVENTIONS.md mandates no duplication. Extract to a shared scripts/lib/link_utils.py and import from both.


🟡 Should-Fix (4)

[A-3] Fragment not stripped before os.path.normpath() in rewrite_links_for_pi
doc.md#section is passed whole to normpath, which will mangle #section/subsection on Windows. Split the fragment before normalization, re-append after: path, frag = target.split('#', 1) if '#' in target else (target, '')

[A-4] Windows machine-path regex off-by-one
r"[A-Z]:\\\\Users" in a raw string is two literal backslashes (C:\\Users). Real Windows paths use a single backslash. Fix: r"[A-Z]:\\Users"

[B-2] No unit tests for rewrite_links_for_pi()
check-skill-links.py is an integration gate only — it cannot catch rewriter regressions on image links ![](), nested parens in URLs, or fragment-only links. Add tests/test_srp_engine.py with unit cases for rewrite_links_for_pi.

[B-3] Undocumented exclusion of .cursor/.gemini dirs from link gate
check-skill-links.py silently skips those trees with no comment. Future maintainers will have no signal that the check should eventually cover them. Add a TODO comment with rationale.


🔵 Consider

  • body_pi_skillpi_skill_body for more natural IR field semantics
  • check() in check-skill-links.py is already pushing the 20-line function limit — extract check_file_links(smd, root) helper before it grows
  • Document that inlined sibling REFERENCE.md links correctly resolve to external GitHub source (expected behavior)

Core approach is sound and the link fixes themselves are correct. Address the items above and re-request review.

danielvm-git added a commit that referenced this pull request Jul 19, 2026
* fix(skills): repair machine-absolute and dangling relative links

- replace file:///Users/danielvm countable-story-format links with the
  GitHub blob URL (docs/ is excluded from the npm package, so the file
  cannot be linked relatively in published installs)
- evolve-skill: benchmark repo path is now machine-agnostic
- craft-skill/investigate-bug/plan-refactor: docs/ links -> blob URLs
- using-bigpowers: profiles link -> repo-relative; write-document:
  CHANGELOG/LICENSE -> repo-relative; guard-git: hooks/ -> REFERENCE.md
  (the bundle lives there); audit-code: drop dead REFERENCE.md link
- grill-me/model-domain: de-link illustrative example paths
- srp-engine: rewrite relative links for the pi tree so they resolve
  from .pi/skills/<name>/ against the shipped source tree
- pi adapter: render skill files from body_pi_skill (prompts unchanged)
- add scripts/check-skill-links.py regression gate, wired into
  the compliance npm script

Fixes #78

* fix(scripts): address review findings from PR #79 dual-blind audit

Must-fix:
- [A-1] skip code fences and inline code before LINK_RE matching in both
  rewrite_links_for_pi and check-skill-links; uses strip_code_spans() helper
- [A-2] LINK_RE now captures links with title attributes [text](url "title")
- [B-1] DRY: extract LINK_RE, EXTERNAL_RE, MACHINE_PATH_RE, strip_code_spans
  to scripts/lib/link_utils.py; both srp-engine and check-skill-links import
  from the single source of truth

Should-fix:
- [A-3] fragment split before os.path.normpath in rewrite_links_for_pi to
  prevent mangling of #section/sub on Windows
- [A-4] Windows MACHINE_PATH_RE corrected to r'[A-Z]:\Users' (single backslash)
- [B-2] add tests/test_srp_engine.py with 20 unit tests covering all edge
  cases: code blocks, title attrs, fragments, Windows paths, external/anchor
  links, image links, inline-code links
- [B-3] document exclusion of .cursor/.gemini dirs in check-skill-links.py
  with a TODO comment referencing issue #78

* chore(sync): regenerate reference tables using relative skill paths

Changes:
- scripts/generate-reference-tables.sh: resolve skill paths relative to REPO_ROOT fordocs/references/model-profiles.md. This prevents environment-absolute paths (like local checkout paths or CI /tmp paths) from causing dirty checkouts.
- Regenerate .pi/skills and docs/references/model-profiles.md using sync-skills.sh.

---------

Co-authored-by: korallis <lee.barry84@gmail.com>
@danielvm-git

Copy link
Copy Markdown
Owner

Merged via PR #80 which resolved the dual-blind code review findings.

github-actions Bot pushed a commit that referenced this pull request Jul 19, 2026
## [2.77.1](v2.77.0...v2.77.1) (2026-07-19)

### Bug Fixes

* **scripts:** address PR [#79](#79) dual-blind review findings ([#80](#80)) ([a03ada9](a03ada9)), closes [#78](#78) [#78](#78)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: hardcoded author absolute paths + stripped reference files break 45+ links in .pi/skills tree

2 participants