Files
mcpctl/docs/revisions.md
Michal 56735a5290 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>
2026-05-07 17:58:04 +01:00

131 lines
4.5 KiB
Markdown

# 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).