Skip to content

feat(core): dependency traversal for seeAlso cross-skill references#82

Open
pradeepmouli wants to merge 10 commits into
developfrom
feat/dep-traversal-seealso
Open

feat(core): dependency traversal for seeAlso cross-skill references#82
pradeepmouli wants to merge 10 commits into
developfrom
feat/dep-traversal-seealso

Conversation

@pradeepmouli

Copy link
Copy Markdown
Owner

Summary

  • Adds DepSkillRef type and seeAlso? / rootDir? fields to ExtractedSkill IR so generated skills can reference sibling skills bundled in direct dependencies
  • Implements discoverDepSkillsSync / discoverDepSkills in packages/core/src/refine/dep-skills.ts: reads package.json#dependencies, checks pkg.skillit.skills explicit list first, falls back to skills/*/SKILL.md convention, parses frontmatter for name and description
  • Wires dep discovery into all five generate pipelines: CLI, config, TypeDoc (sync variant), MCP gen, and MCP bundle
  • Adds renderSeeAlso renderer — emits ## See Also section in SKILL.md between ## NEVER and ## Troubleshooting
  • Adds checkW12 audit check (D3 dimension, +3 pts) that warns when a dependency's bundled skill is not referenced in ## See Also

Motivating case

lspeasy-cli depends on lspeasy-core. An agent using only the CLI skill missed the ## NEVER rules that live in the core skill. With this change, skillit gen for lspeasy-cli will emit a ## See Also pointing to the core skill, and skillit audit will warn if any dep skill is missing from that section.

Test Plan

  • pnpm test — 1163/1163 passing (71 test files, 11 new dep-skills unit tests)
  • pnpm run type-check — clean
  • Verify ## See Also section appears in a generated skill for a package that has a skillit-enabled dependency
  • Verify skillit audit W12 warning fires when ## See Also is absent

🤖 Generated with Claude Code

https://claude.ai/code/session_01LV8EZLurjZCWsHa9hRMxVc

pradeepmouli and others added 10 commits June 11, 2026 00:00
Introduces the cross-reference IR needed for the dep-traversal seeAlso
feature: DepSkillRef type, seeAlso? and rootDir? fields on ExtractedSkill.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Discovers dep skills from node_modules, using package.json#skillit.skills
explicit list or falling back to skills/*/SKILL.md convention. Exports from
refine/index.ts so all consumers get it through @skillit/core.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers: missing package.json, no deps, dep not installed, no skills dir,
convention discovery, explicit skillit.skills list, missing name field skip,
no description, quoted description stripping, multi-dep aggregation, async wrapper.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both generateCliSkill and generateConfigSkill now call discoverDepSkills
and populate skill.rootDir + skill.seeAlso before rendering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TypeDoc EVENT_RESOLVE_END (sync): discoverDepSkillsSync(process.cwd()).
MCP gen factory: findNearestPackageDir + discoverDepSkills after extract.
MCP bundle processEntry: ctx.packageRoot + discoverDepSkills after extract.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Renders ## See Also section between ## NEVER and ## Troubleshooting
when skill.seeAlso is populated. Each dep skill is a bold name +
backtick path + optional description.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rage

checkW12 warns when a dep has a skill not referenced in ## See Also.
Adds +3 to D3 when passing. Improvement suggestion guides users to run
`skillit gen` to auto-populate the section.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Minor bump for @skillit/core (new exports + IR fields + audit check),
patch bumps for client/typedoc/mcp (wiring only).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Narrow extractFrontmatterField field param to 'name' | 'description' (closes latent regex injection path)
- Add existsSync guard for explicit skillit.skills entries (parity with convention path)
- Document process.cwd() monorepo limitation in TypeDoc plugin (consistent with plugin convention)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c844c8111b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// ---------------------------------------------------------------------------
function checkW12(skill: ExtractedSkill, issues: AuditIssue[], passing: AuditPass[]): void {
if (!skill.rootDir) {
passing.push(pass('W12', 'No rootDir set — dep-skill check skipped'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Do not score skipped dep-skill audits as passing

When auditSkill() receives an ExtractedSkill that was not enriched by the new generation paths (for example the current skillit audit sources extract the skill and call auditSkill() without populating rootDir), this branch records W12 as a pass. Since estimateSkillJudgeScore() awards D3 credit for any W12 pass, those audits both suppress the missing ## See Also warning and get dep-skill coverage points even when dependencies expose skills. Treat this as neutral/skipped or populate rootDir before auditing.

Useful? React with 👍 / 👎.

Comment on lines +393 to +395
const pkgDir = process.cwd();
skill.rootDir = pkgDir;
skill.seeAlso = discoverDepSkillsSync(pkgDir);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use each TypeDoc package directory for dep discovery

In a TypeDoc monorepo run from the workspace root (the same mode this plugin already supports by scanning packages/* for per-package metadata and READMEs), this sets every generated skill's rootDir to the workspace root and discovers the root package's dependencies for all skills. A package skill such as packages/cli that depends on another workspace package will therefore miss its own dependency skills, or inherit unrelated root-level references, unless TypeDoc is invoked separately from each package.

Useful? React with 👍 / 👎.

}

function discoverForDep(pkgDir: string, depName: string): DepSkillRef[] {
const depDir = join(pkgDir, 'node_modules', depName);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Resolve dependency skills from hoisted node_modules

This assumes every declared dependency is installed at <pkgDir>/node_modules/<dep>. In npm/Yarn workspaces or hoisted pnpm installs, a valid direct dependency can be resolved from an ancestor node_modules while no package-local entry exists, so discovery returns [] and generated/audited skills omit the required ## See Also references. Use Node package resolution from pkgDir or walk ancestor node_modules directories instead of only checking this fixed path.

Useful? React with 👍 / 👎.

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.

1 participant