Skip to content

feat(skill-registry): support loading pre-curated skill registry via load command and --load flag#976

Open
decode2 wants to merge 3 commits into
Gentleman-Programming:mainfrom
decode2:feat/issue-516-skill-registry-load
Open

feat(skill-registry): support loading pre-curated skill registry via load command and --load flag#976
decode2 wants to merge 3 commits into
Gentleman-Programming:mainfrom
decode2:feat/issue-516-skill-registry-load

Conversation

@decode2

@decode2 decode2 commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #516

Adds support for loading a pre-curated .atl/skill-registry.md file directly into a project without forcing a full scan and regeneration.

Problem

Currently, gentle-ai skill-registry refresh always regenerates .atl/skill-registry.md by scanning all project and user skill directories. Any manual curation (compact rules, custom path conventions, curated subsets across projects) gets wiped. When developers maintain a standardized, curated registry across multiple projects with similar tech stacks, there was no way to import that pre-curated file directly.

Solution

  1. LoadRegistry function: Added LoadRegistry(loadPath, cwd string, force bool) to internal/skillregistry. Validates the registry file structure (## Skills / table headers), copies it atomically to .atl/skill-registry.md, and updates the cache.
  2. CLI Command & Flag: Updated runSkillRegistry in internal/app/app.go to support:
    • gentle-ai skill-registry load <path>
    • gentle-ai skill-registry refresh --load <path>
  3. Help & Unit Tests: Updated internal/app/help.go documentation and added comprehensive unit test coverage (TestLoadRegistryValidatesAndLoadsRegistry).

Test Plan

  • Ran go test ./internal/skillregistry/... — unit tests pass.
  • Ran go test ./internal/app/... — CLI package tests pass.
  • Ran go build ./... — workspace builds cleanly.

Summary by CodeRabbit

  • New Features

    • Added skill-registry load <path> to import a pre-curated skill registry into the current project.
    • Added --load <path> option to load from an external registry, with clear status output (loaded vs refreshed) and cache-based skipping when unchanged.
  • Bug Fixes

    • Improved registry validation to reject invalid or incomplete registry formats before importing.
  • Tests

    • Added unit tests covering valid/invalid inputs, exact registry output writing, and cache fingerprint behavior.

…load command and --load flag

Adds support for loading an existing pre-curated .atl/skill-registry.md file into the current
project without forcing a full scan/regeneration, resolving issue Gentleman-Programming#516.

Key changes:
- Added LoadRegistry function to internal/skillregistry package
- Added gentle-ai skill-registry load <path> subcommand and --load <path> flag
- Updated help output and added full unit test coverage in registry_test.go

Closes Gentleman-Programming#516
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0fa79611-7d17-42d2-a44b-356a9d572552

📥 Commits

Reviewing files that changed from the base of the PR and between 6516fc9 and 5241ff9.

📒 Files selected for processing (1)
  • internal/skillregistry/registry_test.go

📝 Walkthrough

Walkthrough

Adds skill-registry load and --load <path>. The registry package now loads and validates an existing markdown registry, updates cache state, and returns a result. The CLI routes between loading and regenerating, and help text documents the new command.

Changes

skill-registry load command

Layer / File(s) Summary
LoadRegistry function and tests
internal/skillregistry/registry.go, internal/skillregistry/registry_test.go
LoadRegistry normalizes the source path, validates registry shape, short-circuits on cache hits for default-path loads, copies loaded content into the project registry, records a loaded: cache fingerprint, and returns load-specific results. Tests cover invalid input rejection and successful load behavior.
CLI routing and help text
internal/app/app.go, internal/app/help.go
runSkillRegistry accepts `refresh

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the new skill-registry load and --load workflow.
Linked Issues check ✅ Passed The PR adds file loading, validation, cache updates, and avoids regeneration as required by #516.
Out of Scope Changes check ✅ Passed All described changes are directly tied to the skill-registry loading feature and its tests.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/app/app.go`:
- Around line 261-275: The skill-registry command parsing in app.go should fail
fast for load when the source path is missing instead of falling through to
LoadRegistry with an empty path. Update the argument handling around
cmd/loadPath so that gentle-ai skill-registry load without a non-flag path
returns the usage error immediately, while still preserving the existing path
extraction behavior in the load branch and the later LoadRegistry call.

In `@internal/skillregistry/registry_test.go`:
- Around line 459-479: The LoadRegistry test currently only checks a fully
invalid file and copied registry content, so it misses the real contract. Extend
registry_test.go around LoadRegistry to add a partial-invalid case for a file
missing the required “## Skills”/“| Skill |” markers, and assert that a
successful load also writes the cache fingerprint at CacheRelPath in addition to
RegistryRelPath. Use the existing LoadRegistry, readFile, and
RegistryRelPath/CacheRelPath symbols to keep the test aligned with the
implementation.

In `@internal/skillregistry/registry.go`:
- Around line 181-184: The validation in registry.go’s load path is too
permissive because it accepts a file when any one of the markers is present.
Update the check around the content scan so the skill registry is only accepted
when all required markers are present, and return the existing invalid-format
error otherwise. Keep the fix localized to the registry loading logic that
populates `.atl/skill-registry.md`, using the current header/table marker
strings in the condition.
- Around line 210-215: The cache update in registry generation is swallowing
write failures, so the loaded registry can be treated as successfully preserved
even when the cache file is not written. In Regenerate, update the JSON marshal
and filemerge.WriteFileAtomic handling around the cacheFile Fingerprint write so
any error is returned to the caller instead of ignored. Keep the success path
only when both the marshal and atomic write succeed, and use the existing
cachePath/loadPath context to surface the failure clearly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 80d66b57-f8d2-4721-80f1-c52262002ce3

📥 Commits

Reviewing files that changed from the base of the PR and between 8df34cd and 8000c7b.

📒 Files selected for processing (4)
  • internal/app/app.go
  • internal/app/help.go
  • internal/skillregistry/registry.go
  • internal/skillregistry/registry_test.go

Comment thread internal/app/app.go
Comment thread internal/skillregistry/registry_test.go Outdated
Comment on lines +181 to +184
content := string(data)
if !strings.Contains(content, "## Skills") && !strings.Contains(content, "| Skill |") && !strings.Contains(content, "# Skill Registry") {
return Result{}, fmt.Errorf("invalid skill registry format in %q: missing required headers or table", loadPath)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Require all registry markers before accepting the load.

Line 182 only rejects files when all markers are missing. A file with # Skill Registry but no ## Skills section or | Skill | table header still passes, gets copied into .atl/skill-registry.md, and is cached as a successful load.

Suggested fix
-	if !strings.Contains(content, "## Skills") && !strings.Contains(content, "| Skill |") && !strings.Contains(content, "# Skill Registry") {
+	if !strings.Contains(content, "# Skill Registry") ||
+		!strings.Contains(content, "## Skills") ||
+		!strings.Contains(content, "| Skill |") {
 		return Result{}, fmt.Errorf("invalid skill registry format in %q: missing required headers or table", loadPath)
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
content := string(data)
if !strings.Contains(content, "## Skills") && !strings.Contains(content, "| Skill |") && !strings.Contains(content, "# Skill Registry") {
return Result{}, fmt.Errorf("invalid skill registry format in %q: missing required headers or table", loadPath)
}
content := string(data)
if !strings.Contains(content, "# Skill Registry") ||
!strings.Contains(content, "## Skills") ||
!strings.Contains(content, "| Skill |") {
return Result{}, fmt.Errorf("invalid skill registry format in %q: missing required headers or table", loadPath)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/skillregistry/registry.go` around lines 181 - 184, The validation in
registry.go’s load path is too permissive because it accepts a file when any one
of the markers is present. Update the check around the content scan so the skill
registry is only accepted when all required markers are present, and return the
existing invalid-format error otherwise. Keep the fix localized to the registry
loading logic that populates `.atl/skill-registry.md`, using the current
header/table marker strings in the condition.

Comment thread internal/skillregistry/registry.go

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/skillregistry/registry_test.go`:
- Around line 459-470: In the negative tests around LoadRegistry, make sure you
are asserting the actual registry-format validation failure instead of any
generic error. Update the invalidPath and partialPath setup in registry_test.go
to fail the test if os.WriteFile cannot create the fixtures, and tighten the
LoadRegistry assertions so they verify the expected invalid-format error path
from LoadRegistry rather than passing on unrelated read or setup failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 023a06bd-7601-486f-90ce-be9121b7b716

📥 Commits

Reviewing files that changed from the base of the PR and between 8000c7b and 6516fc9.

📒 Files selected for processing (3)
  • internal/app/app.go
  • internal/skillregistry/registry.go
  • internal/skillregistry/registry_test.go

Comment thread internal/skillregistry/registry_test.go Outdated
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.

feat(skill-registry): support loading a pre-curated .atl/skill-registry.md instead of regenerating

1 participant