Skip to content

fix: classify commands without source as built-in - #1208

Open
Forzun wants to merge 2 commits into
Nano-Collective:mainfrom
Forzun:fix/skill-command-priority
Open

Forzun wants to merge 2 commits into
Nano-Collective:mainfrom
Forzun:fix/skill-command-priority

Conversation

@Forzun

@Forzun Forzun commented Sep 6, 2026 •

Copy link
Copy Markdown

Fixes the issue where custom commands without a defined source were incorrectly
classified as project skills.

Changes

  • Changed the fallback SkillPriority from project to built-in.
  • Verified TypeScript and formatting checks.

fix:#1134

@github-actions

github-actions Bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

No changeset found

This PR does not add a changeset, so it will not appear in the changelog or trigger a release.

If the change is user-facing, add one:

pnpm changeset

Pick a bump (patch / minor / major) and write the changelog entry in our usual voice ("Added X... Thanks to @you. Closes #123."), then commit the generated .changeset/*.md file.

If this PR is docs-only or a chore that needs no release note, you can ignore this — or run pnpm changeset --empty to record that intentionally.

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

nc-review: no blocking issues

PR changes the fallback SkillPriority in synthesizeCommandSkills from 'project' to 'built-in' for commands whose source is neither 'project' nor 'personal'. The change is type-safe (SkillPriority includes 'built-in') and does not break the contract, but the else branch it modifies is unreachable in the current pipeline: synthesizeCommandSkills runs against loader.getAllCommands() AFTER CustomCommandLoader.loadCommands() populates from disk (which always sets source) but BEFORE registerSkills adds bundle commands (the only path that can produce commands with source: undefined). No regression test was added, and the change diverges from the codebase's existing fallback convention in source/commands/custom-commands.tsx (line 186), which uses 'project' as the source fallback. These are worth raising but not blocking.

Area Where Finding
🟡 tests source/skills/bootstrap.ts The change claims to repair classification of commands with an undefined source, but the changed else branch in synthesizeCommandSkills is not reachable through any current caller. bootSkillPipeline calls synthesizeCommandSkills on the CustomCommandLoader before registerSkills runs (which is the only producer of source-less commands via registerExternal). Without refactoring the call order or exporting synthesizeCommandSkills, no regression test can demonstrate the bug the PR describes. CONTRIBUTING says bug fixes should include regression tests; this one cannot, which is itself a signal the changed branch is dead.
🟡 design source/skills/bootstrap.ts The codebase's established fallback for an unknown command.source is 'project': source/commands/custom-commands.tsx line 186-187 uses command.source ?? 'project' for the source label. Changing synthesizeCommandSkills to default to 'built-in' (instead of 'project') introduces a divergent convention between /commands and /skills. Worth a justification in the PR description, ideally linking an issue that explains why a sourceless command should be classified as built-in rather than project.

Automated code review — correctness, security, design, tests, plus duplicates and scope. Advisory: a human still decides. Not a substitute for review, and not exhaustive. The required status checks separately cover lint, formatting, types, unused dependencies, the test suite and the build. This bot never merges. Maintainers can rerun with /re-review.

@github-actions github-actions Bot added the agent:clean nc-review had nothing to raise label Sep 6, 2026

@will-lamerton will-lamerton left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for picking this up, but I don't think this closes #1134.

CustomCommand.source is typed 'personal' | 'project' and loadCommands() always passes one of them (source/custom-commands/loader.ts:45,50), so the fallback branch is only reached when source is undefined. The commands that actually have no source are bundle members: bundle-loader.ts:276-282 builds the CustomCommand without one and registrar.ts:76-89 registers it verbatim. Their real level is the bundle layer's priority, usually project, so mapping them to built-in is less accurate than the current default, not more. Today it's invisible only because synthesizeCommandSkills runs before registerSkills in bootSkillPipeline.

What I'd like instead:

  • Propagate the true source for bundle commands in the registrar, mirroring how the subagent branch maps skill.source.priority through subagentPriorityFor. That likely means widening CustomCommand.source to include 'built-in' and making it required.
  • With that in place the ternary collapses to const priority: SkillPriority = command.source ?? 'built-in';, which is exhaustive by construction so a future source variant becomes a type error rather than a silent default.
  • source/commands/custom-commands.tsx:186-187 still does command.source ?? 'project'. Whatever default wins should apply there too, otherwise /skills and /commands label the same command differently.
  • Please add a test asserting that a project bundle's command shows project priority in /skills.

Also: the branch needs a rebase on main (Config Schema Freshness fails on a missing generate:schema script and the coverage drift check is comparing against a moved baseline, neither is caused by this diff), and a patch changeset naming @nanocollective/nanocoder would be good for a user-visible labelling change.

@will-lamerton will-lamerton left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Closer. The type widening and the /commands alignment are right. Two things still block:

  1. bundle-loader.ts:283 hardcodes source: 'project'. loadBundle already has the layer priority (line 172), so please thread it into loadCommandMembers and set source: priority. As written, a personal bundle under ~/.config/nanocoder/skills/ and a built-in bundle both report project, which is the same mislabelling in a new place. registrar.ts:96 already does this correctly for the subagent branch via subagentPriorityFor.

  2. The new test passes with the bundle-loader.ts change reverted, I checked locally. foo?.source.priority reads the bundle Skill's layer priority, not the command member's, so it is green either way. Asserting the command's priority means synthesizeCommandSkills has to run after registerSkills (bootstrap.ts:110 vs :138), or be exported and tested directly.

Two smaller things:

  • source is required now, so the ?? 'built-in' is dead in bootstrap.ts:217 and custom-commands.tsx:186-187. const priority: SkillPriority = command.source; is the exhaustive form, which is what makes a future source variant a type error instead of a silent default.
  • Could you revert the formatting-only hunks in bootstrap.spec.ts (double quotes, bracket spacing, wrapped arrow params)? Spec files are biome-excluded so CI stays green, but ~100 lines of churn buries the 20 lines of real change.

Then a rebase on main and a patch changeset naming @nanocollective/nanocoder and this is good to go.

@github-actions

Copy link
Copy Markdown
Contributor

Hi @Forzun, thanks for this PR! It looks like a maintainer has left feedback
or review activity and there are still some outstanding items to wrap up.

Whenever you get a chance, could you take a look at the open comments?
If anything is unclear or you'd like a hand, just reply here and we'll help you get it across the line.

@github-actions

Copy link
Copy Markdown
Contributor

Hi @Forzun, just a heads-up that this PR still has outstanding items
and hasn't seen any activity in a while.

If we don't hear back within about a week, we'll close it to keep the queue tidy.
You can always reopen it later. Happy to help if anything is blocking you - just say the word.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent:clean nc-review had nothing to raise stale:final-warning

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants