Skill path forms: the lint moves first (#3822 step 1)

Branch fix/3822-skill-path-lint-prereq, 2026-09-02. pi 0.84.4 loads OrchestKit's SKILL.md files and delivers ${CLAUDE_PLUGIN_ROOT} as a literal string. This PR changes only the lint, the conformance grader, the delta anchor and the authoring guide, so the codebase (479 occurrences) can migrate in a separate step. No SKILL.md body is touched.

Pick a target and a consumer

Measured 2026-08-30 on CC 2.1.251 with a throwaway plugin asking for three nonces, run from /tmp and from the skill dir: rel=1 sdir=1 cpr=1 from both cwds. pi expands no ${CLAUDE_*} form. Cursor was not measured; its wrapper is a body copy outside the skill dir (build-plugins.sh generate_command_from_skill).

Three forms, one portable

formClaude CodepiSkills APICursoruse for
references/x.md (bare relative)resolves against the SKILL.md dirresolves (Agent Skills spec)skill dir ships whole (spec, not measured)not measuredsame-skill files. Preferred.
${CLAUDE_SKILL_DIR}/scripts/x.pyexpanded (documented)literalliteralliteralexec shapes in CC-only bodies
${CLAUDE_PLUGIN_ROOT}/skills/other/..., /shared/..., hook command:expandedliteralliteralliteralcross-skill, shared, hooks: a plugin root is genuinely needed

What the placeholder gate checks now

checkbefore this PRafteron this tree
documented placeholders3 (PLUGIN_ROOT, PLUGIN_DATA, PROJECT_DIR); SKILL_DIR blocked4; ${CLAUDE_SKILL_DIR} acceptedgreen
target exists: ${CLAUDE_PLUGIN_ROOT}/skills/...yesyes (452 checked)green
target exists: ${CLAUDE_SKILL_DIR}/... against the containing skill dirnoyes (0 in tree today)green
target exists: bare relative references/|rules/|scripts/|checklists/|assets/|workflows/|examples/ in Read("...") and ](...) form, SKILL.md onlynoyes (60 links checked, 0 missing)green
built plugins/ cleangrep for CLAUDE_SKILL_DIRany undocumented ${CLAUDE_*}green
same-skill refs on the plugin-root formnot countedcounted, advisory: 423 refs in 55 SKILL.md filesinfo only

Paired probe run before commit: a throwaway skill with a missing Read("references/missing-read.md"), a missing [rules](rules/missing-link.md), a missing ${CLAUDE_SKILL_DIR}/scripts/missing.py and a ${CLAUDE_BOGUS_VAR} turned the gate red with all four named (rc=1); removing it turned the gate green (rc=0). A check that cannot disagree with you has measured nothing.

The other three files

filechangeproof
scripts/eval/conformance-check.mjs C3comment inverted (relative for same-skill, plugin-root for cross-skill and shared); C3b narrowed to ${CLAUDE_SKILL_DIR} in Read/link shape only; C3c same-skill check added behind CONFORMANCE_SAME_SKILL=1default run: 2 findings (C1, C2), identical to main, 0 new. Opt-in run: 409 C3 lines ready for step 2.
scripts/check-skill-delta.mjs ORK_ANCHORbare CLAUDE_PLUGIN_ROOT and CLAUDE_SKILL_DIR entries replaced by ${CLAUDE_PLUGIN_ROOT}/(skills|shared|hooks)/report and --json output diffed before and after: byte-identical (11912 bytes). The one >150-line sub-file anchored only by that entry uses a cross-skill ref, which the new pattern still matches.
tests/skills/test-skill-length.sh:7dead ${CLAUDE_SKILL_DIR} comment droppedcomment only
src/skills/CONTRIBUTING-SKILLS.mdnew "Referencing Supporting Files" section with the three-form table and the consumer matrix; agent-teams example switched to bare relative; checklist bulletdocs only

Gate commands

bash tests/skills/structure/test-placeholder-validity.sh
node scripts/eval/conformance-check.mjs
CONFORMANCE_SAME_SKILL=1 node scripts/eval/conformance-check.mjs
node scripts/check-skill-delta.mjs --check
npm run test:skills
npm run test:manifests
copied to clipboard

Still open after this PR: step 2, the codemod scripts/codemod/skill-paths-relative.mjs that rewrites the same-skill refs to bare relative in batches of 5 files and flips C3c on by default; step 3, the compatibility note near cross-skill and shared refs. This PR is Refs #3822, not Closes.