Skip to content
Draft
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
36 changes: 34 additions & 2 deletions crates/skilllite-commands/src/evolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use skilllite_core::protocol::{NewSkill, NodeResult};
use skilllite_core::skill::manifest;

/// Resolve workspace for project-level skill evolution.
/// Uses SKILLLITE_WORKSPACE env or current_dir. Returns workspace/.skills.
/// Uses SKILLLITE_WORKSPACE env or current_dir. Returns the effective workspace skills root.
fn resolve_skills_root(workspace: Option<&str>) -> Option<PathBuf> {
let ws: PathBuf = workspace
.filter(|s| !s.is_empty())
Expand All @@ -47,7 +47,12 @@ fn resolve_skills_root(workspace: Option<&str>) -> Option<PathBuf> {
} else {
std::env::current_dir().ok()?.join(ws)
};
Some(ws.join(".skills"))
let resolution =
skilllite_core::skill::discovery::resolve_skills_dir_with_legacy_fallback(&ws, "skills");
if let Some(warning) = resolution.conflict_warning() {
eprintln!("{}", warning);
}
Some(resolution.effective_path)
}

#[derive(Debug)]
Expand Down Expand Up @@ -1030,6 +1035,33 @@ mod tests {
assert!(normalize_risk_filter(Some("urgent")).is_err());
}

#[test]
fn resolve_skills_root_prefers_default_skills_dir() {
let root =
std::env::temp_dir().join(format!("skilllite-evo-root-test-{}", uuid::Uuid::new_v4()));
std::fs::create_dir_all(root.join("skills")).expect("create skills dir");
std::fs::create_dir_all(root.join(".skills")).expect("create legacy skills dir");

let resolved =
resolve_skills_root(Some(root.to_str().expect("temp path utf8"))).expect("resolve");

assert_eq!(resolved, root.join("skills"));
let _ = std::fs::remove_dir_all(&root);
}

#[test]
fn resolve_skills_root_falls_back_to_legacy_skills_dir() {
let root =
std::env::temp_dir().join(format!("skilllite-evo-root-test-{}", uuid::Uuid::new_v4()));
std::fs::create_dir_all(root.join(".skills")).expect("create legacy skills dir");

let resolved =
resolve_skills_root(Some(root.to_str().expect("temp path utf8"))).expect("resolve");

assert_eq!(resolved, root.join(".skills"));
let _ = std::fs::remove_dir_all(&root);
}

#[test]
fn query_backlog_rows_applies_filters() {
let root =
Expand Down
37 changes: 37 additions & 0 deletions tasks/TASK-2026-067-evolution-skills-root-alignment/CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Technical Context

## Current State

- Relevant crates/files:
- `crates/skilllite-commands/src/evolution.rs`
- `crates/skilllite-commands/src/evolution_desktop.rs`
- `crates/skilllite-commands/src/evolution_status.rs`
- `crates/skilllite-core/src/skill/discovery.rs`
- Current behavior:
- Desktop pending/status/confirm paths use `resolve_skills_dir_with_legacy_fallback(workspace, "skills")`.
- `evolution run` and repair helper resolution return `workspace/.skills` directly.

## Architecture Fit

- Layer boundaries involved:
- `skilllite-commands` should call shared `skilllite-core` discovery helpers rather than duplicating root policy.
- Interfaces to preserve:
- Existing CLI flags, JSON payloads, and legacy `.skills` fallback semantics.

## Dependency and Compatibility

- New dependencies: None.
- Backward compatibility notes:
- `.skills` remains the effective root when `skills/` is absent.
- Workspaces with both roots follow the established default of preferring `skills/`.

## Design Decisions

- Decision: Reuse `skilllite_core::skill::discovery::resolve_skills_dir_with_legacy_fallback` for evolution skill root resolution.
- Rationale: It is already the shared policy for skill command and desktop evolution read paths.
- Alternatives considered: Change desktop pending/status/confirm back to `.skills`.
- Why rejected: That would diverge from current `skilllite init` default behavior and other command helpers.

## Open Questions

- [x] Is a docs update required? No user-facing command or documented default changes; the fix restores the current documented `skills/` default with `.skills` compatibility.
41 changes: 41 additions & 0 deletions tasks/TASK-2026-067-evolution-skills-root-alignment/PRD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# PRD

## Background

The desktop L2 JSON migration moved pending skill reads and confirmations through CLI helpers that
resolve the effective skills directory as `skills/` with fallback to `.skills`. The evolution run
command still resolves the skill generation root as `.skills` directly. This splits generated pending
skills from the UI path in current default workspaces.

## Objective

Ensure all evolution skill write/read paths use one effective workspace skills root. Default
workspaces should use `skills/`, while legacy `.skills`-only workspaces should continue to work.

## Functional Requirements

- FR-1: Resolve evolution skill roots through the shared `resolve_skills_dir_with_legacy_fallback` behavior.
- FR-2: Preserve `.skills` fallback when `skills/` is absent.
- FR-3: Keep existing CLI arguments and JSON output shapes unchanged.

## Non-Functional Requirements

- Security: Do not widen path access beyond the current workspace skills directory resolution.
- Performance: Root resolution should remain local filesystem checks only.
- Compatibility: Existing `.skills`-only workspaces must remain supported.

## Constraints

- Technical: Keep the fix localized to command-layer root selection and tests.
- Timeline: N/A for autonomous execution.

## Success Metrics

- Metric: Pending skills generated by evolution are visible to the existing pending/status/confirm path.
- Baseline: `evolution run` writes to `.skills` even when default `skills/` exists.
- Target: `evolution run` uses `skills/` when present and `.skills` only as legacy fallback.

## Rollout

- Rollout plan: Ship as a minimal Rust command-layer fix with regression tests.
- Rollback plan: Revert the command-layer resolver change if unexpected compatibility issues appear.
47 changes: 47 additions & 0 deletions tasks/TASK-2026-067-evolution-skills-root-alignment/REVIEW.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Review Report

## Scope Reviewed

- Files/modules:
- `crates/skilllite-commands/src/evolution.rs`
- `crates/skilllite-commands/src/evolution_desktop.rs`
- `crates/skilllite-commands/src/evolution_status.rs`
- `crates/skilllite-core/src/skill/discovery.rs`
- Commits/changes:
- Recent desktop L2 JSON bridge changes around evolution pending/status/confirm.
- This fix aligns the evolution write-side root resolver with the existing read-side resolver.

## Findings

- Critical: None remaining in the patched path.
- Major: Fixed root split where `evolution run` wrote pending skills to `.skills` while desktop pending/status/confirm read `skills/` in default workspaces.
- Minor: Other investigated desktop bridge issues were left out of scope because they did not meet the critical bug bar for this run.

## Quality Gates

- Architecture boundary checks: `pass`
- Security invariants: `pass`
- Required tests executed: `pass`
- Docs sync (EN/ZH): `pass` - no docs update required because the fix restores the current `skills/` default behavior and keeps CLI/API shape unchanged.

## Test Evidence

- Commands run:
- `rustup update stable && rustup default stable`
- `cargo test -p skilllite-commands --features agent resolve_skills_root`
- `cargo fmt --check`
- `cargo clippy --all-targets -- -D warnings`
- `cargo test`
- `cargo test -p skilllite`
- `python3 scripts/validate_tasks.py`
- Key outputs:
- Focused regression: `2 passed; 0 failed`.
- Clippy: `Finished dev profile`.
- Full tests: `cargo test` completed successfully; regression tests listed as `evolution::tests::resolve_skills_root_* ... ok`.
- Package tests: `cargo test -p skilllite` completed successfully.
- Task validation: `Task validation passed (67 task directories checked).`

## Decision

- Merge readiness: `ready`
- Follow-up actions: Continue separate investigation for lower-confidence desktop bridge UX issues if needed; not included in this critical bug fix.
21 changes: 21 additions & 0 deletions tasks/TASK-2026-067-evolution-skills-root-alignment/STATUS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Status Journal

## Timeline

- 2026-05-30:
- Progress: Investigated recent desktop L2 evolution changes, confirmed a skills-root split between write and read paths, and implemented resolver alignment with regression tests.
- Blockers: None.
- Next step: Open PR and report results.
- 2026-05-30:
- Progress: Validation passed: `cargo fmt --check`, `cargo clippy --all-targets -- -D warnings`, `cargo test`, `cargo test -p skilllite`, and `python3 scripts/validate_tasks.py`.
- Blockers: None.
- Next step: Done.

## Checkpoints

- [x] PRD drafted before implementation (or `N/A` recorded)
- [x] Context drafted before implementation (or `N/A` recorded)
- [x] Implementation complete
- [x] Tests passed
- [x] Review complete
- [x] Board updated
70 changes: 70 additions & 0 deletions tasks/TASK-2026-067-evolution-skills-root-alignment/TASK.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# TASK Card

## Metadata

- Task ID: `TASK-2026-067`
- Title: Align evolution skills root
- Status: `done`
- Priority: `P1`
- Owner: `agent`
- Contributors:
- Created: `2026-05-30`
- Target milestone:

## Problem

Recent desktop evolution paths list, count, confirm, and reject pending skills through the current
default `skills/` directory with legacy fallback to `.skills/`. The `evolution run` path still writes
generated pending skills to `.skills` unconditionally, so default `skilllite init` workspaces that use
`skills/` can generate pending skills that the desktop cannot see or confirm.

## Scope

- In scope:
- Align `evolution run` and related evolution skill operations with the shared `skills/` default plus `.skills` legacy fallback.
- Add focused regression tests for default and legacy root resolution.
- Validate Rust formatting, linting, tests, and task artifact shape.
- Out of scope:
- Broad redesign of skill identity, duplicate skill handling, or desktop error presentation.
- Changing LLM evolution policy, backlog schema, or sandbox behavior.

## Acceptance Criteria

- [x] `evolution run` resolves the same effective skills root as desktop pending/status/confirm for default workspaces.
- [x] Existing `.skills`-only workspaces remain supported.
- [x] Regression tests cover default `skills/` and legacy `.skills` behavior.
- [x] Required validation commands pass or any blocker is recorded with output.

## Risks

- Risk: Changing the write target may affect users with both `skills/` and `.skills/`.
- Impact: New evolved skills follow `skills/`, while older pending skills in `.skills` remain in the legacy tree.
- Mitigation: Match the already-shipped shared fallback behavior: prefer `skills/` when present and fall back only when it is absent.

## Validation Plan

- Required tests:
- Regression tests in `crates/skilllite-commands/src/evolution.rs`.
- Workspace Rust tests required by policy.
- Commands to run:
- `cargo fmt --check` - passed
- `cargo clippy --all-targets -- -D warnings` - passed
- `cargo test` - passed
- `cargo test -p skilllite` - passed
- `python3 scripts/validate_tasks.py` - passed
- Manual checks:
- Re-read modified files and task board after updates.

## Regression Scope

- Areas likely affected:
- CLI evolution skill generation, pending/confirm/reject, and repair skill root selection.
- Desktop evolution UI visibility of generated pending skills.
- Explicit non-goals:
- No change to chat skill loading, skill import, or assistant frontend components.

## Links

- Source TODO section: N/A
- Related PRs/issues: Recent `feat/runtime-skills-l2-json` and UTF-8 logging follow-up.
- Related docs: `spec/docs-sync.md` reviewed; no docs change needed because the fix restores documented/current default behavior.
3 changes: 2 additions & 1 deletion tasks/board.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Task Board

Last updated: 2026-05-29 (TASK-2026-066 utf8 evolution log truncate done)
Last updated: 2026-05-30 (TASK-2026-067 evolution skills root alignment done)

## In Progress

Expand All @@ -17,6 +17,7 @@ Last updated: 2026-05-29 (TASK-2026-066 utf8 evolution log truncate done)

## Done

- `TASK-2026-067-evolution-skills-root-alignment` - Status: `done` - Owner: `agent`
- `TASK-2026-066-utf8-evolution-log-truncate` - Status: `done` - Owner: `agent`
- `TASK-2026-064-env-keys-single-source` - Status: `done` - Owner: `agent`
- `TASK-2026-063-extension-tool-metadata-dispatch` - Status: `done` - Owner: `agent`
Expand Down
Loading