## 1. Cloud skill domain, models, and migration - [x] 1.1 Add `cloud/skills.py` domain + service layer mirroring `cloud/llm_providers.py`: `CloudSkill` dataclass (id, name, kind, description, tags, content/steps/parameters, version, timestamps), `CloudSkillEntitlement` (skill_id, host_id), validation (`validate_skill_input`), and a `CloudSkillService` over a repository port. Reuse `skills_learning.models` types where shape aligns; no secrets. - [x] 1.2 Add SQLAlchemy models to `cloud/db_models.py`: `cloud_skills`, `cloud_skill_entitlements`, `cloud_skill_sync_state` (host_id, last_version, updated_at). Index `cloud_skill_entitlements` on (skill_id, host_id) unique. - [x] 1.3 Add Alembic migration `0010_skill_management.py` creating the tables (+ per-host changelog + inventory readback); downgrade drops them. No existing table altered. - [x] 1.4 Extend `cloud/sql_repository.py` with cloud-skill repository methods: skill CRUD, entitlement grant/revoke/list-by-host, atomic per-host `entitlement_version` bump + changelog on any relevant change, and `fetch_host_delta(host_id, since_version)` returning upserts/removed_ids/latest_version (incremental with full-replace fallback). ## 2. Cloud admin REST: skill CRUD + entitlement - [x] 2.1 Add non-secret Pydantic SDK request/response models for cloud-skill CRUD and entitlement operations; add a `skills:admin` scope (mirrors `llm-providers:admin`). - [x] 2.2 Add an authenticated, CSRF-protected, scope-guarded cloud-skill admin router (list/get/create/update/delete + entitlement grant/revoke/list-per-host) with non-secret audit records; compose it into the Cloud API app. - [x] 2.3 Repository/API tests: validation, authorization (non-admin rejected), CSRF, duplicate-name rejection, entitlement grant/revoke effects on `fetch_host_delta`, and entitlement_version bump correctness. ## 3. Cloud host-scoped sync endpoint + inventory readback - [x] 3.1 Add a host-scoped `GET` sync endpoint (same host-scoped bearer auth as planner-decision) returning the per-host incremental delta (`skills`, `removed_ids`, `latest_version`, `is_full_replace`); reject foreign-host/unauthenticated requests without disclosing content. - [x] 3.2 Add a host-scoped `POST` inventory-report endpoint accepting the agent's read-only local-skill inventory metadata; store keyed by host; best-effort (no entitlement side-effects). - [x] 3.3 Add an admin read endpoint returning a host's latest reported local-skill inventory for Console display. - [x] 3.4 Tests: first-sync full replace, incremental delta after change, foreign-host/unauthenticated rejection, inventory report acceptance + readback. ## 4. Agent persistent local skill store - [x] 4.1 Add `storage/local_skills.py` with a SQLite-backed `LocalSkillStore` at `tasks/local_skills.sqlite3` (physically separate from `tasks/skills.sqlite3`): schema for local skills (authored) and overrides (keyed by cloud skill id); public read (`list_local`, `get_local`, `has_override`, `get_override`) and write (`create_local`, `update_local`, `delete_local`, `upsert_override`, `remove_override`, `fork_override_to_local`). Zero HTTP/MCP deps. - [x] 4.2 Reuse `skills_learning.models` (`KnowledgeSkill`/`FlowTemplateSkill`/`SkillMetadata`) with `source = "local"` for local skills; overrides store the overriding content keyed by cloud id. - [x] 4.3 Tests: persistence across reopen, local CRUD, override upsert/remove, fork-on-revocation rewrite (override → standalone local id, `source="local"`), and that no write touches the synced store. ## 5. Unified read-merge + origin - [x] 5.1 Add `api/skill_catalog_view.py` exposing a merged read surface over `SkillCatalogStore` (synced) and `LocalSkillStore` (local + overrides): `list_skills`, `search_skills`, `get_skill` returning origin (`cloud`|`local`) and `locally_overridden`; override precedence (D8); no existence leak for invisible cloud skills. - [x] 5.2 Wire `api/skill_catalog_mcp.py` read tools (`list_skills`/`search_skills`/`get_skill`) to delegate to the merged view instead of the synced store directly; preserve `resolve_flow_template` over the merged `get_skill`. - [x] 5.3 Tests: merge ordering, override shadowing in list/get, origin tagging, invisible-cloud-skill not-found indistinguishability. ## 6. Authoring MCP tools + override dispatch - [x] 6.1 Extend `api/skill_catalog_mcp.py` with `create_skill` / `update_skill` / `delete_skill` handlers dispatching by origin (D10): local id → edit/delete local; cloud id → upsert/remove override; `create_skill` → new local. Always registered (no gate, D6). Cloud-store writes rejected. - [x] 6.2 Translate authoring errors to semantic MCP errors (delete cloud skill with no override → semantic error; no entitlement revocation). - [x] 6.3 Tests: create local, update local, update cloud (creates override), delete local, delete cloud override (revert), delete cloud no-override (semantic error). ## 7. Sync repoint + runner wiring + inventory report - [x] 7.1 Repoint `api/skill_sync.py`'s concrete client at the Cloud API per-host sync endpoint (host-scoped bearer; `since_version` incremental; full-replace on first/stale); keep the `SubscriptionClient` Protocol / `SyncDelta` shape. The agent's "subscription_id" becomes its host identifier. - [x] 7.2 Construct and start `SkillSyncRunner` in the host-agent app bootstrap behind the existing cloud-transport configuration; configurable poll interval; failures non-fatal (preserve cache + record error). - [x] 7.3 On a sync `removed_ids` entry that has a local override, trigger the fork (D9) via `LocalSkillStore.fork_override_to_local`. - [x] 7.4 Add a periodic best-effort local-skill inventory report from the agent to the Cloud inventory endpoint (metadata only). - [x] 7.5 Tests: incremental apply, full-replace, fork-on-revocation end-to-end, runner lifecycle, inventory report payload + failure-isolation. ## 8. Cloud Console Skills view - [ ] 8.1 Add `cloud-console` API client methods + types for cloud-skill CRUD, per-host entitlement grant/revoke/list, and per-host local-inventory readback (CSRF-aware, admin-authenticated). - [ ] 8.2 Add an administrator-only `SkillsView.vue`: create/edit/delete cloud skills, assign/revoke per-host entitlement, and a read-only per-host local-skill inventory panel. - [ ] 8.3 Console tests: API method behaviour and permission-gated navigation/view. ## 9. Documentation and validation - [ ] 9.1 Update Cloud deployment docs: cloud-skill management, per-host entitlement, sync endpoint, inventory report, and the `skills:admin` scope. - [ ] 9.2 Run backend, agent, and Console tests; ruff check/format; compileall; and `openspec validate skill-management-console --strict`; resolve failures.