docs: skills + revisions + proposals reference, plus cheatsheet update
Phase 7 of the Skills + Revisions + Proposals work — documentation pass for the surface added in PR-1 through PR-6. Reference material only; no code changes. ## What's added - `docs/skills.md` — skill model, scoping rules, CLI surface, the `mcpctl config claude --project` setup flow, metadata schema (with the deferred-execution note for hooks/mcpServers/postInstall), the on-disk state file shape, atomic install mechanics, failure semantics, and what's deferred. - `docs/revisions.md` — ResourceRevision model, semver auto-bump rules, contentHash diff key (cross-resource sync), CLI for history / diff / restore, RBAC, audit emission, storage growth note. - `docs/proposals.md` — ResourceProposal model, the reviewer flow (CLI + web UI), atomic-approval mechanics, the propose_prompt / propose_skill MCP tools, the propose-learnings global skill that steers Claude toward engaging with them, and the deferred legacy PromptRequest cutover. ## What's edited - Top-level `CLAUDE.md` — resource cheatsheet adds `skill`, `proposal`, `revision` with cross-references to the new docs. The legacy `promptrequest` entry stays (still on the legacy code path) but notes that new work should use `proposal`. ## What's NOT in this PR - The PromptRequest → ResourceProposal cutover migration. Both run side-by-side today; the focused cutover PR will rename + backfill + drop. Keeping that out of PR-7 means review can stay on docs. - Bundle-backup / `mcpctl apply -f` skill support (deferred from PR-3). - `metadata.hooks` / `metadata.mcpServers` / `metadata.postInstall` execution (deferred from PR-5). - Existing-page UI migration to Tailwind (deferred from PR-6 — old inline-styled pages coexist fine inside the new Layout). These are tracked as future PRs; each is its own focused change. ## Verification `pnpm test:run` whole monorepo: 162 test files / 2157 tests green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
130
docs/revisions.md
Normal file
130
docs/revisions.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# Resource Revisions
|
||||
|
||||
mcpctl keeps an append-only revision log for every Prompt and Skill —
|
||||
so you can answer "who changed prompt X and when," diff between any
|
||||
two versions, and restore an earlier state without losing the audit
|
||||
chain.
|
||||
|
||||
## Model
|
||||
|
||||
`ResourceRevision` is a single shared table keyed by
|
||||
`(resourceType, resourceId)` — the type discriminator allows the same
|
||||
infrastructure to cover both prompts and skills (and any future
|
||||
resource that wants version history).
|
||||
|
||||
| Field | Purpose |
|
||||
|------------------|----------------------------------------------------------|
|
||||
| `id` | cuid; the revision's stable identity. |
|
||||
| `resourceType` | `'prompt'` \| `'skill'`. Validated app-layer. |
|
||||
| `resourceId` | Soft FK — survives deletion of the underlying resource. |
|
||||
| `semver` | Author-visible version (X.Y.Z). |
|
||||
| `contentHash` | sha256 of the canonicalised body. Stable diff key. |
|
||||
| `body` | Snapshot of the resource at this revision. |
|
||||
| `authorUserId` | Who made the change (null for system writes). |
|
||||
| `authorSessionId`| Session that proposed it (when applicable). |
|
||||
| `note` | Free-text reviewer or author note. |
|
||||
| `createdAt` | When the revision was recorded. |
|
||||
|
||||
The resource row itself (Prompt/Skill) keeps the inline `content` —
|
||||
revisions are an audit log, not the source of truth. Hot read paths
|
||||
(the gate plugin, `mcpctl skills sync`, prompt indexing) never need
|
||||
to consult the revision log.
|
||||
|
||||
`Prompt.currentRevisionId` and `Skill.currentRevisionId` are soft
|
||||
pointers to the latest revision so the UI can answer "which version is
|
||||
live" in one query.
|
||||
|
||||
## Semver semantics
|
||||
|
||||
Auto-patch on every successful save where the body changed:
|
||||
|
||||
```
|
||||
0.1.0 → save with content change → 0.1.1
|
||||
0.1.1 → save with content change → 0.1.2
|
||||
```
|
||||
|
||||
Authors can override:
|
||||
|
||||
```bash
|
||||
mcpctl edit prompt foo --bump minor # 0.1.x → 0.2.0
|
||||
mcpctl edit prompt foo --bump major # 0.x.x → 1.0.0
|
||||
mcpctl edit prompt foo --semver 1.2.3 # explicit
|
||||
mcpctl edit prompt foo --note "fixed the gotcha" # adds note to revision
|
||||
```
|
||||
|
||||
Invalid semver values fall back to `0.1.0` rather than throwing —
|
||||
the revision write is best-effort and we don't want a corrupted
|
||||
existing semver to break the prompt save.
|
||||
|
||||
## contentHash
|
||||
|
||||
sha256 of the JSON-canonicalised body (keys sorted at every object
|
||||
level). Two revisions with the same hash are byte-identical. Used by
|
||||
`mcpctl skills sync` as the diff key against on-disk state — re-publish
|
||||
under the same semver still triggers a sync if the contentHash changed.
|
||||
|
||||
The server-side hash and the client-side hash are computed from the
|
||||
same canonical shape, so they match exactly. See
|
||||
`src/mcpd/src/services/resource-revision.service.ts` for the canonical
|
||||
JSON encoder.
|
||||
|
||||
## CLI
|
||||
|
||||
### View history
|
||||
|
||||
```bash
|
||||
mcpctl get revisions prompt my-prompt
|
||||
mcpctl get revisions skill demo-skill
|
||||
```
|
||||
|
||||
### View one
|
||||
|
||||
```bash
|
||||
mcpctl describe revision <id>
|
||||
```
|
||||
|
||||
### Diff
|
||||
|
||||
The HTTP API returns a unified-format diff:
|
||||
|
||||
```
|
||||
GET /api/v1/revisions/<id>/diff?against=<other-id|live>
|
||||
```
|
||||
|
||||
The web UI's revision history tab on a Skill detail page renders the
|
||||
diff inline (color-coded add/remove rows).
|
||||
|
||||
### Restore
|
||||
|
||||
Restore a prompt or skill to an earlier revision. This writes a *new*
|
||||
revision whose body is the old one — preserving the audit chain
|
||||
rather than deleting later revisions.
|
||||
|
||||
```bash
|
||||
mcpctl restore prompt my-prompt --revision <revision-id>
|
||||
```
|
||||
|
||||
The CLI subcommand is wired through to `POST
|
||||
/api/v1/prompts/:id/restore-revision` (and the symmetric
|
||||
`/api/v1/skills/:id/restore-revision`).
|
||||
|
||||
## RBAC
|
||||
|
||||
Revisions piggyback on the underlying resource's RBAC permission. If
|
||||
you can `view:prompts`, you can read prompt history; if you can
|
||||
`edit:prompts`, you can restore.
|
||||
|
||||
## Audit emission
|
||||
|
||||
Each revision write emits a structured audit event captured by the
|
||||
existing audit-event pipeline. The event includes the revision id,
|
||||
contentHash, semver, and author/session — sufficient to answer "what
|
||||
changed" and "who" without joining tables manually.
|
||||
|
||||
## Storage size
|
||||
|
||||
A revision body is the resource snapshot — for prompts that's a few
|
||||
KB; for skills with large `files` maps it can be tens of KB. The audit
|
||||
log grows linearly with edits. v1 has no rotation; if a single resource
|
||||
sees thousands of revisions per day this will need a retention policy
|
||||
(out of scope today).
|
||||
Reference in New Issue
Block a user