fix(skills): repair machine-absolute and dangling relative links + link gate#79
fix(skills): repair machine-absolute and dangling relative links + link gate#79korallis wants to merge 1 commit into
Conversation
- 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
left a comment
There was a problem hiding this comment.
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_skill→pi_skill_bodyfor more natural IR field semanticscheck()incheck-skill-links.pyis already pushing the 20-line function limit — extractcheck_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.
* 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>
|
Merged via PR #80 which resolved the dual-blind code review findings. |
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; nohooks/dir exists.audit-code: dropped a deadREFERENCE.mdlink (the--parallelhelper 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.mdlinks in.pi/skills/)scripts/lib/srp-engine.py: newrewrite_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 byparse_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 newbody_pi_skillIR field;.pi/promptsoutput 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 inskills/**/SKILL.mdand.pi/skills/**/SKILL.md. Wired into thecompliancenpm script; also runnable standalone ascheck:skill-links..pi/skills/regenerated viasync-skills.sh;python3 scripts/check-skill-links.py→ OK — no machine paths or dangling links (was 45+ before this change).Notes
.cursor/rules/.gemini/.pi/promptschanges are justsync-skills.shoutput reflecting the source edits..cursor/.geminirenderings still dangle there; those trees aren't published to npm. The new rewriter is the obvious place to extend if wanted.Fixes #78