# Session Skills — Implementation Plan

Spec: `docs/superpowers/specs/2026-07-03-session-skills-design.md`
Approach: subagent-driven TDD (sonnet), build + test + commit per task, stage files by
path (never `git add -A`).

**Pre-flight (do first, before building anything):** manual smoke test — drop a skill
into a scratch worktree's `.claude/skills/` and run `claude -p` to confirm cwd skills are
discovered in headless mode. The whole feature rests on this. If it fails, stop and
redesign around `CLAUDE_CONFIG_DIR`.

---

## Task 1 — Data layer: columns + registry table + migration

- Add nullable `SessionSkills` (string, JSON array) to `TaskEntity`, `ListConfigEntity`,
  `AppSettingsEntity`; map `session_skills` columns in their `*Configuration.cs`.
- New `SessionSkillEntity` (`name` PK, `source_url`, `pinned_ref`, `subpath`,
  `description`, `added_at`) — one row per skill; a multi-skill repo writes N rows sharing
  `source_url`/`pinned_ref` — + configuration + `session_skills` table.
- New `SessionSkillRepository` (async, CancellationToken): `ListAsync`, `GetAsync(name)`,
  `UpsertAsync`, `DeleteAsync(name)`, `DeleteBySourceAsync(url)`, `ListBySourceAsync(url)`.
- EF migration `AddSessionSkills` (columns + table).
- **Tests (Data.Tests):** repository CRUD on real SQLite; JSON column round-trips a
  name list.

## Task 2 — Registry service (install / update / remove)

- `Skills/SessionSkillRegistry` + `Skills/Interfaces/ISessionSkillRegistry`,
  `IRepoCloner` (clone abstraction so tests inject a local source dir).
- `GitRepoCloner` (production) does `git clone` + resolves HEAD SHA.
- Install: clone → **detect layout** (`skills/*/SKILL.md` bundle → each subskill; else
  root `SKILL.md` → single; else reject) → per skill parse YAML frontmatter (`name`,
  `description`), copy its dir **flat** to `~/.todo-app/session-skills/<name>/`, upsert a
  row with `subpath`. Reject collision with a skill from a different source; reinstalling
  the same source refreshes.
- Update(sourceUrl) / Remove(sourceUrl) per spec (act on all of a source's skills).
- **Tests (Worker.Tests):** install a **multi-skill** fixture (fake cloner, mirrors
  ponytail's `skills/*/SKILL.md`) → N rows + N flat dirs; install a root-`SKILL.md`
  fixture → 1 row; neither → rejected; cross-source name collision rejected;
  remove-by-source deletes all its dirs + rows. **No real network / no real claude CLI.**

## Task 3 — Resolution: union into ClaudeRunConfig

- Add `IReadOnlyList<string> SkillNames` to `ClaudeRunConfig` (default empty).
- In `TaskRunner.ResolveConfigAsync`: parse each level's `session_skills`, union + dedup,
  filter to registry-existing names (drop + log missing).
- **Tests (Worker.Tests):** union across the three levels; dedup; unknown name dropped.

## Task 4 — Seeder

- `Skills/SessionSkillSeeder` + interface. `SeedAsync(cwd, skillNames, isWorktree, ct)`:
  copy each installed skill dir → `<cwd>/.claude/skills/<name>/`; if worktree, append
  `/.claude/skills/<name>/` to `git rev-parse --git-path info/exclude` target if absent.
- Wire into `TaskRunner` after run-dir resolution, before `ClaudeProcess.RunAsync`
  (both worktree and sandbox paths).
- **Tests (Worker.Tests):** seeds into real temp dir; idempotent re-seed; worktree
  exclude line written once and not duplicated; seeded path is git-ignored (real git
  temp repo → `git status` clean for the seeded dir).

## Task 5 — Hub + DTOs + client

- `WorkerHub`: `GetSessionSkills`, `InstallSessionSkill(url)`, `UpdateSessionSkill(name)`,
  `RemoveSessionSkill(name)`.
- New `SessionSkillDto`; extend `AppSettingsDto`, `ListConfigDto`, `UpdateListConfigDto`,
  `UpdateTaskAgentSettingsDto` with skill-name lists; map in the update handlers.
- `IWorkerClient` + `WorkerClient` additions.
- **Update hand-rolled fakes** in Worker.Tests + Ui.Tests (memory
  `iworkerclient_fakes_sync`).
- **Tests:** hub method round-trip via existing hub test harness where present.

## Task 6 — UI: registry tab + selectors

- `SessionSkillsSettingsTabViewModel` + a **Skills** tab in `SettingsModalView.axaml`:
  installed list, Add (URL), Update, Remove, status line. Mirror
  `FilesSettingsTabViewModel`.
- Global multi-select in General settings tab → `AppSettings.SessionSkills`.
- Skills multi-select in shared `AgentConfigEditor` (covers List + Task) with inheritance
  badge, wired through `AgentConfigEditorViewModel`.
- Localization: add EN + DE keys in parity (Localization.Tests enforces).
- **Tests (Ui.Tests / Localization.Tests):** VM load/save of selections; locale parity.
- **Visual verification is Mika's** — flag the gaps.

## Task 7 — Wiring, build, end-to-end smoke

- DI registration (registry, cloner, seeder) in `Program.cs`.
- Build all touched projects `-c Release`; run Worker/Data/Ui/Localization test projects.
- Manual E2E: install ponytail via the UI, enable per-task, run a task, confirm the skill
  is available to the agent and **not** committed and **not** in interactive sessions.

---

Commit per task with Conventional Commits (`feat(worker|ui|data): …`). Commit the
spec + plan docs first.
