The session-start hook emitted {"priority", "message"} JSON on all three
of its output paths. Codex CLI validates SessionStart hook output and
fails the hook on that shape ('hook returned invalid session start JSON
output', #465); the documented contract for both Codex and Claude Code is
{"hookSpecificOutput": {"hookEventName": "SessionStart",
"additionalContext": "..."}}
Switch all three paths (meta-skill injection, jq-missing fallback,
meta-skill-missing fallback) to that envelope. Verified each path emits
valid JSON of the new shape: happy path via jq shape assertion, jq-missing
via PATH='' run, meta-skill-missing via a copy outside the repo.
The path fix has no regression guard: nothing in CI resolves references/
links, so all 18 were broken while CI stayed green. validate-artifact-
paths.js is scoped to spec/plan/todo artifacts and says in its own header
that it is not a general markdown path linter.
Add validate-reference-links.js, which resolves every `references/*.md`
link in skills/*/SKILL.md against that skill's own directory. This accepts
both conventions in CLAUDE.md: shared checklists reached via
../../references/, and a skill's own colocated references/ directory.
Scope stays narrow on purpose. Skills legitimately name paths that do not
exist yet -- tasks/todo.md, PERF.md, docs/ideas/[idea-name].md -- and a
general markdown linter would fail the build on them. A test pins that.
Proven against the pre-fix tree: 18 error(s), exit 1, matching the 18
links fixed in the previous commit. After the fix: 0 error(s), exit 0.
7 unit tests cover the regression itself, colocated references/,
markdown-link syntax, a renamed target, multiple violations in one skill,
and the non-reference paths that must be ignored. Wired into the
validate-skills job, alongside the other skill-content checks.
Known limitation: fenced code blocks are not stripped, so a SKILL.md that
documents the anti-pattern inside a fence would be flagged. Nothing does
today. Sharing stripFencedCodeBlocks looks right once #444 lands.
Refs #468
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every SKILL.md linked the shared checklists as `references/<file>.md`, a
path relative to the skill's own directory. Those files live in the repo
root `references/`, two levels up, so all 18 links across 11 skills
resolved to paths that do not exist -- in the repo and in every
plugin-install layout (~/.claude/plugins/cache/..., ~/.codex/...).
An agent following the guidance -- using-agent-skills pointing at the
Definition of Done, for example -- hit a file-not-found on every one.
Rewrite the 18 links to `../../references/<file>.md`, which resolves
correctly from `skills/<name>/`. Text-only; no structure or tone changed.
Verified: all 18 links resolve; hooks/session-start-test.sh passes
(required by CONTRIBUTING.md when touching using-agent-skills/SKILL.md);
validate-skills, validate-versions, validate-commands and
validate-artifact-paths all pass.
Refs #468
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The /spec and /plan commands write spec, plan, and todo artifacts to paths that /build and the spec/plan skills read back. When a producer moves an artifact without updating the consumers, the pipeline breaks and nothing in CI catches it: the command-parity check only compares descriptions, not paths. PR #93 hit exactly this, pointing /spec and /plan at docs/features/[name]/ while /build still required SPEC.md and tasks/plan.md.
validate-artifact-paths.js enforces one canonical set of artifact paths across every file in the pipeline (the spec/plan/build commands, the spec-driven-development and planning-and-task-breakdown skills, and the getting-started and adoption guides). Any spec/plan/todo artifact path outside the allowlist fails CI, so changing the convention has to touch the allowlist and every guarded file in the same change.
Scope is deliberately narrow: only spec/plan/todo artifacts, only the pipeline files; it is not a general markdown path linter. Wired into the validate-commands CI job alongside its test.
actions/checkout@v4 and actions/setup-node@v4 target the deprecated Node 20
runner runtime, so every run logs forced-Node-24 deprecation annotations.
Harmonize checkout on the v6 major already used by the other three jobs,
bump setup-node to v6, and move node-version from Node 20 (EOL 2026-04-30)
to Node 24 LTS.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
materializeWorkspace() creates directories in os.tmpdir() but
runBehavioral() never cleans them up on success or failure. If
execFileSync throws (timeout, signal, OOM), the workspace persists
in /tmp indefinitely with fixture data. The test file
run-evals-test.js uses try/finally cleanup (line 234), proving
the pattern was known but omitted in production code.
Fix: Wrap eval execution in try/finally with best-effort
fs.rmSync cleanup.
The skillName argument from --behavioral has zero validation and is
used directly in path.join() for reading .json files, reading
SKILL.md, and WRITING .grading.json results. A value like
'../../etc/passwd' traverses outside the project directory for
both reads and writes.
Fix: Validate skillName against /^[a-z0-9]+(-[a-z0-9]+)*$/ before
any filesystem operations. This matches the existing KEBAB_CASE
validation in skill-lint.js.
The explicit agents array in .claude-plugin/plugin.json causes Claude Code
to load zero subagents; it discovers agents/*.md on its own, and the explicit
list suppresses that discovery. Reproduced on Claude Code 2.1.219: with the
key present, plugin details reports Agents (0); with it removed, all four load
(code-reviewer, security-auditor, test-engineer, web-performance-auditor).
Safe to omit since #260 moved agents/README.md into docs/, so the agents/
directory now holds only real agent definitions. Scoped to the Claude Code
manifest only; the Codex manifest is untouched.
'Native dependency audit' collides with the established meaning of
native dependencies (compiled modules); use the same unambiguous
phrasing as the shipping-and-launch checkbox in this PR.
Addresses the clarity nit in #236 review: a single supporting doc stays a
loose file, and the skill-local references/ subdir is for grouping several
related docs that travel with the skill. Ties the new bullet back to the
existing Supporting files entry so the framings read as one.
Follow-up to #419, addressing the remaining normative npm-family
commands federicobartoli's grep on #404 identified:
- incremental-implementation: the four increment-checklist exit criteria
and the example prompt now use the repository's own test/build/
typecheck/lint commands, pointing at the TDD skill's Discover the
Stack First section
- planning-and-task-breakdown: task-template verification lines use the
template's placeholder style instead of hardcoded npm commands
- shipping-and-launch: the security checkbox names the ecosystem's
dependency audit rather than npm audit alone
- debugging-and-error-recovery: the diagnosis/bisect/verify command
blocks are labeled as npm examples with substitution notes
- references/security-checklist.md: OWASP row 6 generalizes npm audit
to the native dependency audit
- security-and-hardening needed no change: its SKILL.md was already
neutralized (detected-package-manager wording)
Ride-along: pins the below-zero debit behavior (ValueError) in TDD eval
case 3, per nucliweb's non-blocking review note on #419.
Per review: never hardcode outbound endpoints (telemetry, analytics,
similar) from fetched examples without surfacing them to the user, even
when docs mark them as required. Adds the verification checkbox the PR
description referenced. A/B tested on claude-opus-4-7 against the
required-telemetry injection case: 2/2 guarded runs refused to hardcode
the endpoint where 2/2 baseline runs kept it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the rationale paragraph with a pack-style pointer to
security-and-hardening, which covers the LLM01 threat model, so the
section starts straight from "Fetched documentation pages are untrusted
input" and keeps only the extraction-hygiene instruction. Also fix the
"user's permission" apostrophe in the new red flag.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Unquoted ${CLAUDE_PROJECT_DIR} in SDD-CACHE and SIMPLIFY-IGNORE setup
examples breaks when the project path contains spaces, the same class
of failure fixed for SessionStart in #214.
Co-authored-by: Cursor <cursoragent@cursor.com>
- SKILL.md gains a 'Discover the Stack First' step: identify the
language, build system, checked-in wrappers, test framework, and
documented commands before choosing any test command, and run the
repository's own focused/full-suite commands throughout the loop
- verification checklist no longer hardcodes 'npm test'; red flag added
for reaching for a default test command without checking the repo
- references/testing-patterns.md relabeled in place as JavaScript/
TypeScript examples illustrating the universal principles (no
relocation, per the #361/#236 sequencing agreed in the issue)
- new behavioral eval: a Python/unittest fixture verifying the skill
adapts to non-npm repository tooling
Gives contributors a short intake path when a skill assumes the wrong
ecosystem or outdated steps, so gaps like #404 reach maintainers via
the repo instead of external channels. Closes the intake-only scope
from #412.
Co-authored-by: Cursor <cursoragent@cursor.com>