Files
mcpctl/docs/proposals.md

127 lines
5.3 KiB
Markdown
Raw Normal View History

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
# Resource Proposals
A proposal is a pending change to a Prompt or Skill, submitted by
either a Claude Code session (via the `propose_prompt` / `propose_skill`
MCP tools) or a human (via the web UI / CLI). Reviewers triage the
queue and either approve — at which point the proposal becomes a real
prompt or skill — or reject with a note.
This is the path by which Claude **proposes back** to mcpd: things the
session learned that future sessions would benefit from. The
`propose-learnings` global skill (seeded by mcpd at startup) explains
the discipline to Claude.
## Model
`ResourceProposal` shares the schema's discriminator pattern with
`ResourceRevision` — single table, `resourceType` field disambiguates
prompts vs skills.
| Field | Purpose |
|----------------------|--------------------------------------------------------|
| `resourceType` | `'prompt'` \| `'skill'`. |
| `name` | Proposed resource name. |
| `body` | Proposed body (`{ content, priority?, metadata?, … }`).|
| `projectId` / `agentId` | Scope of the proposal (XOR; null/null = global). |
| `createdBySession` | mcplocal session that proposed (when from Claude). |
| `createdByUserId` | User who proposed (when via UI/CLI). |
| `status` | `'pending'``'approved'` \| `'rejected'`. |
| `reviewerNote` | Set on approval or rejection. |
| `approvedRevisionId` | Set when approved — points at the resulting revision. |
Two unique constraints — `(resourceType, name, projectId)` and
`(resourceType, name, agentId)` — mirror the Prompt / Skill scoping
rules. The same `?? ''` workaround for nullable-FK lookups applies.
## Reviewer flow
### CLI
```bash
mcpctl review pending # list pending
mcpctl review next # show oldest pending
mcpctl review show <id> # full detail
mcpctl review diff <id> # before/after diff
mcpctl review approve <id> # POST /proposals/:id/approve
mcpctl review reject <id> --reason "explain" # rejected with note
```
### Web UI
`/proposals` shows a Pending / Approved / Rejected tab view; the
sidebar nav badge polls every 30 s and shows the pending count in
amber. Click a row to see the full body, the diff against the current
resource (if any), and approve / reject controls.
### Approval is atomic
Approval runs in a single Prisma transaction:
1. Look up the pending proposal.
2. Dispatch by `resourceType` to the registered handler
(`PromptService` or `SkillService` registers itself at construction).
3. Handler upserts the underlying resource — creating it if new, or
updating + auto-bumping patch semver if it exists.
4. Handler records a `ResourceRevision` linking back to the proposal.
5. Proposal status flips to `approved`, `approvedRevisionId` set.
If any step fails, the transaction rolls back and the proposal stays
`pending`. There is no half-approved state.
## Claude side: `propose_prompt` and `propose_skill`
Both tools are registered by the `gate` plugin in mcplocal. They post
to `/api/v1/proposals` with the appropriate `resourceType`.
The `propose-learnings` global skill (seeded by mcpd) tells Claude
*when* to use them:
- `propose_prompt` for project-specific knowledge — gotchas,
conventions, hidden constraints. Cheap to add, easy to reject.
- `propose_skill` for cross-cutting knowledge — debugging discipline,
release hygiene, security review style. Larger blast radius; lean
toward `propose_prompt` unless you have a clear cross-project reason.
The `gate-encouragement-propose` system prompt (priority 10, sits in
the gating bundle) is the trigger that makes Claude actually consider
proposing. Without that, the tools exist but Claude rarely engages.
## Backwards compat
PR-1 / PR-2 deferred the cutover from the prompt-only `PromptRequest`
table to `ResourceProposal`. Both run side-by-side today:
- mcplocal's `propose_prompt` still POSTs to the legacy
`/api/v1/projects/:name/promptrequests` URL.
- mcplocal's `propose_skill` (newer) POSTs to `/api/v1/proposals`
directly.
- The legacy `/api/v1/promptrequests*` routes remain in mcpd.
- `mcpctl approve promptrequest <name>` still works.
A focused follow-up PR will:
1. Migrate existing `PromptRequest` rows into `ResourceProposal`
(resourceType=prompt).
2. Rename `PromptRequest` to `_PromptRequest_legacy`.
3. Update mcplocal's `propose_prompt` to use `/api/v1/proposals`.
4. Keep the legacy URL as a thin translation shim through one release.
5. Drop `_PromptRequest_legacy` after that.
This stays separate so the cutover is reviewable independently of
the larger Skills + Revisions + Proposals work.
## RBAC
Proposals piggyback on the `prompts` permission for now — anyone with
`view:prompts` can read the queue, anyone with `edit:prompts` can
approve or reject. Splitting out a dedicated `proposals` permission
(or a "reviewer" role) is straightforward if granularity becomes
useful.
## Audit emission
Proposal create / approve / reject events flow through the existing
audit pipeline. Approval events also reference the resulting
revision id, so you can join "proposal approved at T" against
"revision X created at T" without polling.