Files
q792602257andClaude Opus 4.6 dd03abbbb0 feat(skills): open skill-management-console change + local skill store
Opens the skill-management-console openspec change (cloud/local skill split
with local override) with proposal, design (D1-D11), four delta specs, and
tasks. Implements the agent-side persistent local skill store
(storage/local_skills.py): authored local skills + cloud-skill overrides in
a physically separate SQLite file, with fork-on-revocation. 10 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-15 07:28:42 +08:00

68 lines
5.2 KiB
Markdown

## ADDED Requirements
### Requirement: Agent-local skills persist in a dedicated store
The agent SHALL persist its locally-managed skills (authored skills and overrides) in a local store backed by a SQLite file physically separate from the synced catalog store and from task metadata, so that local authoring survives agent restarts and never shares storage with synced skills. The synced catalog store's read-only-except-sync write contract and the "no cross-writes between local and synced stores" boundary SHALL remain intact.
#### Scenario: Locally-authored skill survives restart
- **WHEN** the agent creates a local skill and is later restarted
- **THEN** the local skill is still present and readable after restart, without any re-sync
#### Scenario: Local and synced stores stay physically separate
- **WHEN** the agent authors a local skill and separately syncs cloud skills
- **THEN** the local skill is written only to the local store and the synced skills only to the synced store; neither store accepts the other's writes
### Requirement: Agent can author, edit, and delete its own local skills
The agent SHALL be able to create new local skills, edit existing local skills, and delete local skills, operating exclusively on the local store. These operations SHALL NOT touch the synced store or any cloud skill.
#### Scenario: Create a new local skill
- **WHEN** the agent creates a skill with no existing id
- **THEN** a new local skill is persisted with a fresh local id and `origin = "local"`
#### Scenario: Edit and delete a local skill
- **WHEN** the agent updates, then deletes, a local skill by its local id
- **THEN** the update is persisted to the local store, and the delete removes it from the local store; the synced store is unchanged
### Requirement: Agent can locally override a cloud skill
The agent SHALL be able to create a local override keyed by a cloud skill's id. While an override exists, the read surface returns the override's content for that id (the cloud version is shadowed). Creating or updating an override SHALL NOT modify the cloud skill or the synced store.
#### Scenario: Override shadows the cloud skill at read time
- **WHEN** the agent has created an override for a cloud skill id and the read surface is queried for that id
- **THEN** the override's content is returned, marked `origin = "cloud"` and `locally_overridden = true`
#### Scenario: Removing an override re-exposes the cloud skill
- **WHEN** the agent deletes the override for a cloud skill id
- **THEN** subsequent reads for that id return the cloud skill's current synced content, with no override flag
### Requirement: Overrides shadow sync updates until removed
When the underlying cloud skill for an overridden id is updated via sync, the override SHALL continue to shadow the new cloud version; the agent SHALL NOT see the cloud update until the override is removed. (Staleness is explicit and operator/agent-visible, not auto-detected.)
#### Scenario: Cloud skill updates under an active override
- **WHEN** a synced cloud skill whose id has an active local override is updated to a new version
- **THEN** the read surface continues to return the override's content, not the new cloud version
### Requirement: An override forks into a local skill on entitlement revocation
If a cloud skill is removed from the agent's entitled set (sync reports it as removed) and a local override exists for it, the override SHALL be promoted to a standalone local skill: it gains a local id, its `origin` becomes `"local"`, and its content is preserved. If no override exists, revocation simply removes the cloud skill from the local view.
#### Scenario: Revocation with an active override forks it
- **WHEN** sync removes a cloud skill id that has an active local override
- **THEN** the override becomes a standalone local skill with a new local id and `origin = "local"`, and remains readable
#### Scenario: Revocation without an override just removes visibility
- **WHEN** sync removes a cloud skill id that has no local override
- **THEN** that id is no longer visible on the read surface
### Requirement: Unified read surface merges synced and local skills with an origin discriminator
The agent SHALL expose a single read surface (`list` / `search` / `get`) that merges cloud-synced skills (after applying overrides) and local skills, reporting each with an `origin` of `"cloud"` or `"local"` and a `locally_overridden` flag when an override is active. The merge SHALL NOT leak entitlement or cloud-management internals to the consumer, and SHALL NOT distinguish "unknown id" from "known but not visible" for cloud skills.
#### Scenario: List returns both origins
- **WHEN** the read surface lists skills
- **THEN** the result includes cloud-synced and local skills, each tagged with `origin`, stable-ordered
#### Scenario: Override is reflected in list and get
- **WHEN** a cloud skill id has an active override
- **THEN** both list and get for that id report `origin = "cloud"` and `locally_overridden = true`, returning the override's content
#### Scenario: No existence leak for invisible cloud skills
- **WHEN** a get is issued for a cloud skill id that is unknown or not entitled to this host and has no override
- **THEN** the read surface returns a not-found result that does not reveal whether the id exists elsewhere