Review changes before they reach a catalog

So far, every save and every skc sync pushed straight to the main branch of acme-skills, and reached everyone's tools on their next sync. Acme now wants a second person to read each change to its skills first, as it does with code. This guide shows how to make changes wait for review, and what your tools receive while they wait.

When to use a review-branch catalog

Acme's skills tell AI tools how to review code and handle secrets, so a careless edit reaches every engineer's tools. When a catalog uses the review-branch sync policy, SkillCatalog never pushes to its main branch. It pushes each change to a branch of its own and keeps a record of it on your machine. That branch and its record together are a proposal. Your team reviews the branch and merges it on the Git host, like any other pull request.

Delivery keeps using main, which SkillCatalog calls the primary branch. A proposal reaches your tools, and everyone else's, only after someone merges it and you sync, so your tools always follow what the team accepted. One exception applies: a hand edit you have not synced yet still reaches your own tools, because delivery reads your clone.

The sync policy is set on each person's machine, so Sam keeps pushing to main until he turns review branches on too. To require review from everyone, protect main on your Git host. Direct pushes are then refused, and each person switches to review branches.

Turn on review branches

Dana turns review branches on for acme-skills:

skc catalog policy set acme-skills review-branch --primary main --review skillcatalog/acme-skills
acme-skills: review-branch (pull main, push skillcatalog/acme-skills)
  • --primary main names the branch that SkillCatalog pulls and delivers from.
  • --review skillcatalog/acme-skills sets where proposal branches go, so Dana's proposals land under skillcatalog/acme-skills/, as the next section shows. The desktop app suggests the same value, which must differ from the primary branch.

In the desktop app, choose View all in the catalog menu, then Edit on the catalog's card, then Review.

If the Git host refused a direct push before Dana switched, her next sync sends those unpushed commits as a proposal and moves her main back to the host's version.

What a save does

Dana adds a dependency check to review-security and syncs, as before:

skc sync --message "Check dependency sources"

This time the sync created a proposal, and its report says push proposal with the branch's name. skc proposal list shows the proposal:

skc proposal list
1 active proposal(s):
- 01m37fg6fptp6cjc6rvvyc44w2 (catalog: acme-skills, status: submitted)  (pending review)
    title: Check dependency sources
    branch: skillcatalog/acme-skills/01m37fg6fptp6cjc6rvvyc44w2-dirty-sync
  • 01m37fg6fptp6cjc6rvvyc44w2 is the proposal id, which other skc proposal commands take.
  • submitted means the branch is on the Git host, waiting for review.
  • title comes from the commit message, and branch is the branch to review.

main did not change, so Dana's tools keep main's version of review-security until the proposal is merged. A proposal starts from main as your clone last pulled it, so sync before you start a change.

In the desktop app, a save creates a proposal the same way and marks the skill "(pending review)".

Dana then adds a second check to the same skill and syncs again:

skc sync --message "Scan uploads"

While a proposal waits, skc sync adds later changes to the same files to that proposal, so its branch now holds both checks. This works as long as the later edit stays clear of the lines the proposal changed and the lines right next to them. When both change the same lines, the sync refuses that catalog and puts the edit back in the clone, uncommitted. Keep it there until the proposal is merged, then sync again.

In the desktop app, the editor opens the proposal's version of the skill, and saving asks whether to Update existing proposal or Create new proposal.

Review and merge a proposal

SkillCatalog pushes the branch but does not open pull requests, so Dana opens one on the Git host, from the proposal's branch into main. Sam reviews it and merges it. skc proposal refresh then asks the Git host about each of Dana's proposals:

skc proposal refresh
Refreshed 1 proposal(s); 0 error(s).
  - 01m37fg6fptp6cjc6rvvyc44w2 → merged_pending_pull (could_not_verify, kept_active)

merged_pending_pull means the host merged the proposal and Dana's clone has not pulled that merge yet, so her clone cannot confirm the merge (could_not_verify) and keeps the record (kept_active). Her next sync pulls the merged change, delivers it to her tools, and removes the proposal from skc proposal list:

skc sync

Sam's tools receive the change on his next sync, like any other commit on main.

If the team closes the pull request and deletes the branch instead, skc proposal refresh reports rejected_or_closed, and the proposal stays in the list. Remove it with skc proposal discard <proposal-id>, which deletes only the record on your machine.

See your teammates' proposals

With her own proposal merged, Dana wants to see what Sam has proposed. Proposal records live on the machine that made them, so skc proposal list shows only your own. --include-remote-only adds the proposal branches on the Git host that your machine has no record of:

skc proposal list --include-remote-only
0 active proposals.

3 remote-only branch(es):
...
- skillcatalog/acme-skills/01m37fgc0y3pk53savd2hm1bx3-dirty-sync (head: 71cbd0e078df9fea2fe7a7ba9956100291274bb8)  (remote-only)

The list includes merged branches that nobody deleted, so check each branch's pull request on the host. To print one of your own records in full, run skc proposal show <proposal-id>.

Delivery while proposals are pending

Each proposal's status tells you what delivery does while it waits. skc proposal list shows the status and, in parentheses, a short label:

StatusWhat it meansWhat delivery does
submitted (pending review)The branch is on the Git host, waiting for review.Delivers main's version, without the proposal.
merged_pending_pull (needs attention)The host merged the proposal, and your clone has not pulled the merge.Your next sync pulls the merge, delivers it, and removes the record.
rejected_or_closed (closed)The branch is gone from the host.Delivers main's version. Discard the record.
remote_status_unknown (status unknown)The last check could not reach the Git host.Skips every skill from this catalog and keeps the copies delivered earlier.

Any other status, also labeled "needs attention", means the branch or main changed on the host after you sent the proposal. Delivery keeps using main's version, and the record stays until you discard it.

The unknown status is the one that holds delivery back, because SkillCatalog cannot tell whether the proposal was merged. Dana loses her network connection while her proposal waits, so the next check cannot reach the host. Until skc proposal refresh or skc sync reaches the host again, delivery skips the skills of acme-skills, and skills from her other catalogs are still delivered.

Go back to direct saves

Before Dana switches acme-skills back to pushing straight to main, she merges or closes her pending proposals. After the switch, skc proposal list no longer shows them, although their branches stay on the Git host and skc proposal show <proposal-id> still prints each record:

skc catalog policy set acme-skills direct
acme-skills: direct

In the desktop app, choose Edit on the catalog's card, then Direct.