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
56 changes: 56 additions & 0 deletions .speckit/bugfixes/SKILZ-081-agent-lookup-order/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# SKILZ-081: Agent Lookup Order

## Status: COMPLETED

## Problem Statement

Agent detection lookup order is incorrect. The `detect_agent()` function is missing a parent directory check for the universal agent pattern (`../skilz/skills`).

## Root Cause

When a project is nested inside a directory that has a `skilz/skills` folder in its parent, the agent detection should recognize this as a "universal" agent pattern. This check was missing from the detection order.

## Solution

1. Add `_check_parent_skilz()` function to check for `../skilz/skills` directory
2. Update `detect_agent()` to call parent check after config override but before marker detection

## Files Modified

- `src/skilz/agents.py`
- Added `_check_parent_skilz(project_dir: Path) -> str | None` function
- Updated `detect_agent()` to include parent directory check in priority order

## Implementation Details

```python
def _check_parent_skilz(project_dir: Path) -> str | None:
"""Check for ../skilz/skills directory (universal agent pattern)."""
parent = project_dir.parent
parent_skilz = parent / "skilz" / "skills"
if parent_skilz.exists() and parent_skilz.is_dir():
logger.debug("[SKILZ-081] Found parent skilz/skills at %s", parent_skilz)
return "universal"
return None
```

## Detection Order (Updated)

1. Check config file for `agent_default` setting
2. **NEW: Check for `../skilz/skills` (parent directory universal pattern)**
3. Check for `.claude/` in project directory
4. Check for `.gemini/` in project directory
5. Check for `.codex/` in project directory
6. Check for `~/.claude/` (user has Claude Code installed)
7. Check for `~/.gemini/` (user has Gemini CLI)
8. Check for `~/.codex/` (user has OpenAI Codex)
9. Check for `~/.config/opencode/` (user has OpenCode)
10. Default to "claude"

## Acceptance Criteria

- [x] `_check_parent_skilz()` function added
- [x] `detect_agent()` calls parent check after config but before markers
- [x] Returns "universal" when parent skilz/skills exists
- [x] All existing tests pass
- [x] Type checking passes
33 changes: 33 additions & 0 deletions .speckit/bugfixes/SKILZ-081-agent-lookup-order/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# SKILZ-081: Agent Lookup Order - Tasks

## Status: COMPLETED

## Tasks

- [x] Add logging import to `agents.py`
- [x] Create `_check_parent_skilz()` function
- [x] Update `detect_agent()` docstring with new detection order
- [x] Add parent check call after config override check
- [x] Add debug logging for parent skilz detection
- [x] Run existing tests to verify no regressions
- [x] Run type checking (mypy)
- [x] Run linting (ruff)

## Verification

```bash
# All 640 tests pass
pytest -v

# Type checking passes
mypy src/skilz/

# Linting passes
ruff check src/skilz/
```

## Completion

- **Date**: 2026-01-20
- **PR**: https://github.com/SpillwaveSolutions/skilz-cli/pull/43
- **Commit**: fix/skilz-bugfixes-081-085-086-089
38 changes: 38 additions & 0 deletions .speckit/bugfixes/SKILZ-085-default-agent/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# SKILZ-085: Default Agent Should Be Claude

## Status: COMPLETED

## Problem Statement

Default agent fallback is "gemini" instead of "claude". When no agent markers are found, the system should default to Claude Code as the primary supported agent.

## Root Cause

The `detect_agent()` function's final fallback was returning "claude" but without proper logging. The config.py already had the correct default, but explicit logging was needed for debugging.

## Solution

1. Ensure `detect_agent()` final return is "claude" with debug logging
2. Verify `config.py` has `DEFAULT_AGENT = "claude"` (already correct)

## Files Modified

- `src/skilz/agents.py`
- Added debug logging before final "claude" return
- Log message: `[SKILZ-085] No agent markers found, using default: claude`

## Implementation Details

```python
# In detect_agent() function, final fallback:
logger.debug("[SKILZ-085] No agent markers found, using default: claude")
return "claude"
```

## Acceptance Criteria

- [x] `detect_agent()` returns "claude" when no markers found
- [x] Debug logging added for traceability
- [x] `config.py` DEFAULT_AGENT is "claude"
- [x] All existing tests pass
- [x] Type checking passes
31 changes: 31 additions & 0 deletions .speckit/bugfixes/SKILZ-085-default-agent/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# SKILZ-085: Default Agent Should Be Claude - Tasks

## Status: COMPLETED

## Tasks

- [x] Verify `config.py` has correct DEFAULT_AGENT value
- [x] Add debug logging to `detect_agent()` final fallback
- [x] Ensure return value is "claude"
- [x] Run existing tests to verify no regressions
- [x] Run type checking (mypy)
- [x] Run linting (ruff)

## Verification

```bash
# All 640 tests pass
pytest -v

# Type checking passes
mypy src/skilz/

# Linting passes
ruff check src/skilz/
```

## Completion

- **Date**: 2026-01-20
- **PR**: https://github.com/SpillwaveSolutions/skilz-cli/pull/43
- **Commit**: fix/skilz-bugfixes-081-085-086-089
52 changes: 52 additions & 0 deletions .speckit/bugfixes/SKILZ-086-version-mismatch/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# SKILZ-086: Version Mismatch

## Status: COMPLETED

## Problem Statement

CLI `--version` shows wrong version. Version was defined in two places (`__init__.py` and `pyproject.toml`) which could get out of sync.

## Root Cause

The `__version__` in `src/skilz/__init__.py` was hardcoded as a string literal (e.g., `"1.7.0"`), while the canonical version is defined in `pyproject.toml`. These could drift apart during releases.

## Solution

Use `importlib.metadata.version()` to read the version from the installed package metadata, which is derived from `pyproject.toml`. This creates a single source of truth.

## Files Modified

- `src/skilz/__init__.py`
- Replaced hardcoded `__version__ = "1.7.0"` with dynamic version lookup
- Added fallback to `"0.0.0.dev"` for development installs

## Implementation Details

**Before**:
```python
__version__ = "1.7.0"
```

**After**:
```python
from importlib.metadata import PackageNotFoundError, version

try:
__version__ = version("skilz")
except PackageNotFoundError:
__version__ = "0.0.0.dev"
```

## Benefits

1. **Single source of truth**: Version only defined in `pyproject.toml`
2. **Automatic sync**: CLI `--version` always matches installed package
3. **Development friendly**: Falls back to dev version when not installed

## Acceptance Criteria

- [x] `__version__` uses `importlib.metadata.version()`
- [x] Fallback to "0.0.0.dev" for PackageNotFoundError
- [x] `skilz --version` shows correct version after `pip install -e .`
- [x] All existing tests pass
- [x] Type checking passes
38 changes: 38 additions & 0 deletions .speckit/bugfixes/SKILZ-086-version-mismatch/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# SKILZ-086: Version Mismatch - Tasks

## Status: COMPLETED

## Tasks

- [x] Import `version` and `PackageNotFoundError` from `importlib.metadata`
- [x] Replace hardcoded version with `version("skilz")` call
- [x] Add try/except for PackageNotFoundError
- [x] Set fallback version to "0.0.0.dev"
- [x] Run existing tests to verify no regressions
- [x] Run type checking (mypy)
- [x] Run linting (ruff)

## Verification

```bash
# Reinstall package
pip install -e .

# Check version
skilz --version

# All 640 tests pass
pytest -v

# Type checking passes
mypy src/skilz/

# Linting passes
ruff check src/skilz/
```

## Completion

- **Date**: 2026-01-20
- **PR**: https://github.com/SpillwaveSolutions/skilz-cli/pull/43
- **Commit**: fix/skilz-bugfixes-081-085-086-089
62 changes: 62 additions & 0 deletions .speckit/bugfixes/SKILZ-089-git-removal/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# SKILZ-089: .git Removal on Local Install

## Status: COMPLETED

## Problem Statement

When installing a local skill that contains a `.git` directory, the `.git` directory is copied to the target location. This causes nested repository issues and can confuse Git operations.

## Root Cause

The `shutil.copytree()` calls in `installer.py` and `link_ops.py` did not have an `ignore` parameter to exclude the `.git` directory.

## Solution

Add `ignore=shutil.ignore_patterns('.git')` to all `shutil.copytree()` calls that copy skill directories.

## Files Modified

- `src/skilz/installer.py`
- Updated `copy_skill_files()` function to exclude `.git`
- `src/skilz/link_ops.py`
- Updated `copy_skill()` function to exclude `.git`

## Implementation Details

**installer.py - copy_skill_files() (~line 80)**:
```python
# SKILZ-089: Exclude .git directory to prevent nested repo issues
shutil.copytree(
source_dir,
target_dir,
symlinks=True,
ignore_dangling_symlinks=True,
ignore=shutil.ignore_patterns(".git"),
)
```

**link_ops.py - copy_skill() (~line 78)**:
```python
# SKILZ-089: Exclude .git directory to prevent nested repo issues
shutil.copytree(
source,
target,
symlinks=True,
ignore_dangling_symlinks=True,
ignore=shutil.ignore_patterns(".git"),
)
```

## Benefits

1. **No nested repos**: Installed skills don't contain `.git` directories
2. **Cleaner installs**: Reduces installed skill size
3. **No Git confusion**: Parent repo operations work correctly

## Acceptance Criteria

- [x] `installer.py` copytree excludes `.git`
- [x] `link_ops.py` copytree excludes `.git`
- [x] Local skill installs don't copy `.git` directory
- [x] All existing tests pass
- [x] Type checking passes
31 changes: 31 additions & 0 deletions .speckit/bugfixes/SKILZ-089-git-removal/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# SKILZ-089: .git Removal on Local Install - Tasks

## Status: COMPLETED

## Tasks

- [x] Update `copy_skill_files()` in `installer.py` to add ignore pattern
- [x] Update `copy_skill()` in `link_ops.py` to add ignore pattern
- [x] Add comment explaining SKILZ-089 fix
- [x] Run existing tests to verify no regressions
- [x] Run type checking (mypy)
- [x] Run linting (ruff)

## Verification

```bash
# All 640 tests pass
pytest -v

# Type checking passes
mypy src/skilz/

# Linting passes
ruff check src/skilz/
```

## Completion

- **Date**: 2026-01-20
- **PR**: https://github.com/SpillwaveSolutions/skilz-cli/pull/43
- **Commit**: fix/skilz-bugfixes-081-085-086-089
8 changes: 7 additions & 1 deletion src/skilz/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
"""Skilz - The universal package manager for AI skills."""

__version__ = "1.7.0"
from importlib.metadata import PackageNotFoundError, version

try:
__version__ = version("skilz")
except PackageNotFoundError:
__version__ = "0.0.0.dev"

__author__ = "Spillwave"

from skilz.api_client import (
Expand Down
Loading