Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions docs/ai/design/2026-09-07-feature-skill-module-service-refactor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
phase: design
title: System Design & Architecture
description: Define the technical architecture, components, and data models
---

# System Design & Architecture

## Architecture Overview
**What is the high-level system structure?**

```mermaid
graph TD
SkillCommand[commands/skill.ts] --> SkillService[services/skill/skill.service.ts]
SetupService[services/setup/setup.service.ts] --> SkillService
InstallService[services/install/install.service.ts] --> SkillService

SkillService --> Installer[installer/skill-installer.service.ts]
SkillService --> Registry[registry/skill-registry.service.ts]
SkillService --> Index[index/skill-index.service.ts]

Installer --> Validation[skill-validation.ts]
Installer --> Description[skill-description.ts]

Registry --> Sources[registry/skill-registry-source.ts]
Registry --> Discovery[registry/registry-skill-discovery.ts]
Registry --> Git[util/git.ts]
Registry --> Config[lib/Config.ts + lib/GlobalConfig.ts]

Index --> Repository[index/skill-index.repository.ts]
Index --> Discovery
Index --> GitHub[util/github.ts]
Index --> Description
```

The feature keeps the repository's existing TypeScript/ESM stack and existing command/service direction. The skill module becomes a feature-owned service area under `services/skill`.

## Data Models
**What data do we need to manage?**

- `SkillEntry`: searchable skill index item with `name`, `registry`, `path`, `description`, and `lastIndexed`.
- `SkillIndexData`: persisted search index with metadata and skill entries.
- `SkillRegistryData`: merged registry map keyed by registry id.
- `InstalledSkill` and `GlobalInstalledSkill`: list output models used by commands.
- `AddSkillOptions` and `RemoveSkillOptions`: install/remove scope and environment options.
- `UpdateSummary` and `UpdateResult`: registry update result models.

## API Design
**How do components communicate?**

`SkillService` is the public application boundary for skill workflows:

```ts
addSkill(registryId: string, skillName: string, options?: AddSkillOptions): Promise<'installed' | 'matched'>
addSkills(registryId: string, skillNames: string[], options?: AddSkillOptions): Promise<'installed' | 'matched'>
listInstallableSkills(registryId: string): Promise<RegistrySkillChoice[]>
removeSkill(skillName: string, options?: RemoveSkillOptions): Promise<void>
listSkills(): Promise<InstalledSkill[]>
listGlobalSkills(envCodes?: string[]): Promise<GlobalInstalledSkill[]>
addRegistry(id: string, source: string, options?: AddSkillRegistryCommandOptions): Promise<SkillRegistryAddStatus>
removeRegistry(id: string, options?: RemoveSkillRegistryCommandOptions): Promise<'project' | 'global'>
updateSkills(registryId?: string): Promise<UpdateSummary>
findSkills(keyword: string, options?: { refresh?: boolean }): Promise<SkillEntry[]>
rebuildIndex(outputPath?: string): Promise<void>
```

Command rendering and interactive skill selection remain in `commands/skill.ts`. Services expose installable skill choices and install explicit skill names. Services may still use existing terminal UI for long-running status messages where current behavior already does so.

## Component Breakdown
**What are the major building blocks?**

- `skill.service.ts`: coordinates top-level skill use cases and owns dependency construction.
- `registry/skill-registry.service.ts`: fetches/merges registries, prepares Git/local registry repositories, adds/removes registry config, updates caches, and removes registry cache.
- `registry/registry-skill-discovery.ts`: discovers valid skills from registry directories and enforces local registry containment/metadata bounds.
- `installer/skill-installer.service.ts`: resolves install targets, lists installable skills, and installs/removes/lists installed skills for project/global targets.
- `index/skill-index.service.ts`: finds skills, rebuilds the index, updates one registry in the index, removes registry entries, and decides when to refresh or use stale data.
- `index/skill-index.repository.ts`: reads/writes/checks the persisted JSON index.
- Shared root files:
- `skill-validation.ts`
- `skill-description.ts`
- `skill-builtins.ts`
- `skill.types.ts`

## Design Decisions
**Why did we choose this approach?**

- Use `services/skill` instead of `lib`/`util` because skill behavior is a feature module, not generic infrastructure.
- Use one public `SkillService` plus three collaborator services because a file-per-use-case structure is too verbose for this module.
- Keep shared skill-domain primitives at the `services/skill` root because validation, description parsing, and built-ins are used across registry, installer, and index.
- Use explicit filenames for searchability.
- Use dot suffixes only for architectural roles, such as `.service.ts`, `.repository.ts`, and `.types.ts`.
- Keep checkbox selection in the command because selection, cancellation, and choice label formatting are CLI UI concerns.
- Keep installer target resolution inside `skill-installer.service.ts` because it is short and installer-specific.
- Do not keep `SkillManager` as a long-term compatibility wrapper because the type is internal to `packages/cli`.

## Non-Functional Requirements
**How should the system perform?**

- Preserve existing index caching, seed index fallback, registry update behavior, and concurrency.
- Preserve local registry containment checks and metadata size limits.
- Avoid broad behavior changes while moving code.
- Keep testability high by placing pure helpers in small files and persistence behind a repository.
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
phase: implementation
title: Implementation Guide
description: Technical implementation notes, patterns, and code guidelines
---

# Implementation Guide

## Development Setup
**How do we get started?**

- Active worktree: `.worktrees/feature-skill-module-service-refactor`
- Branch: `feature-skill-module-service-refactor`
- Dependency bootstrap: `npm ci`

## Code Structure
**How is the code organized?**

Target structure:

```text
packages/cli/src/services/skill/
skill.service.ts
skill.types.ts
skill-validation.ts
skill-description.ts
skill-builtins.ts

registry/
skill-registry.service.ts
skill-registry-source.ts
registry-skill-discovery.ts

installer/
skill-installer.service.ts

index/
skill-index.service.ts
skill-index.repository.ts
```

Naming convention:
- dot suffixes for architectural roles: `.service.ts`, `.repository.ts`, `.types.ts`.
- hyphenated descriptive names for domain helpers.

## Implementation Notes
**Key technical details to remember:**

### Core Features
- Moved code first with minimal behavior changes.
- Added `SkillService` as the import boundary for skill workflows.
- Kept command table/status rendering in `commands/skill.ts`.
- Moved interactive skill selection into `commands/skill.ts`; installer services now list installable choices and install explicit skill names.
- Consolidated registry directory scanning in `registry/registry-skill-discovery.ts`.
- Inlined installer target resolution into `installer/skill-installer.service.ts`.
- Removed old skill-specific files from `lib` and `util` after imports/tests were updated.
- Moved skill-specific tests under `src/__tests__/services/skill`.

### Patterns & Best Practices
- Preserve existing ESM `.js` import specifiers.
- Prefer explicit names for searchability.
- Keep service collaborators injectable where tests need mocks.

## Integration Points
**How do pieces connect?**

- `commands/skill.ts` imports `SkillService` from `services/skill/skill.service.ts`.
- `services/install/install.service.ts` imports the same skill service boundary.
- `services/setup/setup.service.ts`, `commands/init.ts`, and `services/status/status.service.ts` import built-ins from `services/skill/skill-builtins.ts`.
- Registry service continues to depend on `ConfigManager`, `GlobalConfigManager`, and Git helpers.

## Implementation Summary

- `services/skill/skill.service.ts` is now a thin facade over installer, registry, and index services.
- `services/skill/registry/registry-skill-discovery.ts` owns registry-directory skill discovery and local registry containment checks.
- `services/skill/installer/skill-installer.service.ts` owns target resolution, installable skill discovery plus add/list/remove installed skill behavior.
- `commands/skill.ts` owns interactive registry skill selection and cancellation handling.
- `services/skill/registry/skill-registry.service.ts` owns registry merge, cache, update, and add/remove source workflows.
- `services/skill/index/skill-index.service.ts` owns search/index lifecycle policy.
- `services/skill/index/skill-index.repository.ts` owns JSON index persistence.

## Error Handling
**How do we handle failures?**

- Preserve existing `CliError`, `ValidationError`, `NotFoundError`, stale index fallback, and local registry error messages where practical.
- Command-specific error rendering remains in command layer or existing `withErrorHandler`.

## Performance Considerations
**How do we keep it fast?**

- Preserve merged registry promise caching and prepared repository caching.
- Preserve index TTL, seed index, and GitHub fetch concurrency.

## Security Notes
**What security measures are in place?**

- Preserve registry id and skill name validation.
- Preserve local registry symlink/path containment checks.
- Preserve guarded cache removal under `~/.ai-devkit/skills`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
phase: planning
title: Project Planning & Task Breakdown
description: Break down work into actionable tasks and estimate timeline
---

# Project Planning & Task Breakdown

## Milestones
**What are the major checkpoints?**

- [x] Milestone 1: Move skill-domain helpers and service classes under `services/skill`.
- [x] Milestone 2: Replace `SkillManager` imports with `SkillService` and update command/service tests.
- [x] Milestone 3: Run focused skill tests, lint, and build.

## Task Breakdown
**What specific work needs to be done?**

### Phase 1: Foundation
- [x] Task 1.1: Create `services/skill` folder structure.
- [x] Task 1.2: Move validation, description, built-ins, registry source, and local registry helpers.
- [x] Task 1.3: Move `SkillRegistry`, `SkillIndex`, and installer behavior into service files.

### Phase 2: Core Features
- [x] Task 2.1: Implement `SkillService` as the public boundary.
- [x] Task 2.2: Update `commands/skill.ts`, setup service, install service, and related tests to import `SkillService`.
- [x] Task 2.3: Remove obsolete `lib/SkillManager.ts`, `lib/SkillRegistry.ts`, `lib/SkillIndex.ts`, `lib/BuiltinSkills.ts`, and skill-specific util files.

### Phase 3: Integration & Polish
- [x] Task 3.1: Update test file paths and mocks.
- [x] Task 3.2: Fix lint/type errors from moved imports.
- [x] Task 3.3: Run validation and review the diff.

## Progress Summary

Implementation moved the skill module into the agreed service-layer shape. The command layer now delegates registry workflows through `SkillService`, while registry cache/config behavior lives in `registry/skill-registry.service.ts`, install/list/remove behavior lives in `installer/skill-installer.service.ts`, and index persistence is split into `index/skill-index.repository.ts`.

## Dependencies
**What needs to happen in what order?**

- Move helpers before moving services so imports can be updated in a controlled order.
- Move service classes before command updates.
- Test updates depend on final source paths.

## Timeline & Estimates
**When will things be done?**

- Single-pairing-session refactor.
- Highest risk is test mock churn and ESM import path mistakes.

## Risks & Mitigation
**What could go wrong?**

- Risk: changing behavior while moving code.
Mitigation: preserve method bodies first, then only make targeted orchestration edits.
- Risk: tests mock removed module paths.
Mitigation: update mocks to new service paths and run focused tests.
- Risk: index repository split changes persistence behavior.
Mitigation: keep read/write behavior equivalent and verify with existing skill tests.

## Resources Needed
**What do we need to succeed?**

- Existing Vitest coverage for command, manager, registry, and skill utilities.
- Package scripts: `npm --workspace packages/cli test`, `lint`, and `build`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
phase: requirements
title: Requirements & Problem Understanding
description: Clarify the problem space, gather requirements, and define success criteria
---

# Requirements & Problem Understanding

## Problem Statement
**What problem are we solving?**

- The CLI skill module is currently split across `commands/skill.ts`, `lib/SkillManager.ts`, `lib/SkillRegistry.ts`, `lib/SkillIndex.ts`, and several `util/skill*` helpers.
- `SkillManager` has grown into a broad class that owns installation, removal, listing, environment resolution, prompt handling, filesystem operations, and registry/index delegation.
- `commands/skill.ts` contains registry mutation workflow details that should live behind a service boundary.
- Maintainers and contributors are affected because skill behavior is harder to scale, search, and test in focused units.

## Goals & Objectives
**What do we want to achieve?**

- Move skill behavior under `packages/cli/src/services/skill`.
- Introduce a clear command-to-service layering model:
- command layer parses CLI args, owns exit codes, and renders command output.
- skill service layer owns application workflows.
- collaborator services own registry, installer, and index behavior.
- Replace the broad `SkillManager` concept with `SkillService`, without keeping a long-term compatibility wrapper.
- Use explicit, searchable names such as `skill-registry.service.ts`, `skill-installer.service.ts`, and `skill-index.repository.ts`.
- Keep behavior and public CLI contracts unchanged.
- Preserve existing local registry security checks, registry conflict handling, install behavior, built-in skill behavior, and index fallback behavior.

Non-goals:
- Do not change user-facing CLI syntax.
- Do not redesign registry/index algorithms beyond the structural move.
- Do not introduce a package-wide clean architecture pattern.
- Do not push or publish changes; user will review before push.

## User Stories & Use Cases
**How will users interact with the solution?**

- As a maintainer, I want `commands/skill.ts` to call a single skill service boundary so command code stays easy to scan.
- As a contributor, I want registry, installer, and index behavior grouped by subdomain so I can find related logic quickly.
- As a test author, I want smaller services and helpers so tests can target one workflow without mocking unrelated behavior.
- Existing CLI users should keep using:
- `ai-devkit skill add`
- `ai-devkit skill add-registry`
- `ai-devkit skill remove-registry`
- `ai-devkit skill list`
- `ai-devkit skill remove`
- `ai-devkit skill update`
- `ai-devkit skill find`
- `ai-devkit skill rebuild-index`

## Success Criteria
**How will we know when we're done?**

- `commands/skill.ts` delegates skill workflows to `services/skill/skill.service.ts`.
- Skill files are organized under:
- `services/skill/registry`
- `services/skill/installer`
- `services/skill/index`
- shared root skill-domain files.
- Internal imports no longer depend on `lib/SkillManager.ts`, `lib/SkillRegistry.ts`, `lib/SkillIndex.ts`, `lib/BuiltinSkills.ts`, `util/skill.ts`, `util/skill-registry.ts`, or `util/local-registry.ts`.
- Existing tests are updated to the new paths and still pass.
- `npm --workspace packages/cli test -- skill`, `npm --workspace packages/cli run lint`, and `npm --workspace packages/cli run build` pass.

## Constraints & Assumptions
**What limitations do we need to work within?**

- The repo uses ESM-style `.js` import specifiers in TypeScript source.
- The refactor should follow existing `commands -> services -> lower-level helpers` direction used by install/setup commands.
- Some tests mock module paths directly, so tests must be moved or updated with the source move.
- `SkillService` remains internal to `packages/cli`; no external compatibility wrapper is required.
- Existing untracked files in the main checkout are unrelated and must not be modified.

## Questions & Open Items
**What do we still need to clarify?**

- None. Naming and structure have been agreed with the user in this thread.
Loading
Loading