Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Code owners for vouch — the human-readable map is GOVERNANCE.md.
#
# Only the load-bearing "core" paths are listed here. A PR that changes any of
# them requires review from a code owner before it can merge, once the branch
# protection rule "Require review from Code Owners" is enabled (see GOVERNANCE.md
# → "Turning this on"). Everything NOT listed is contributor-friendly: any
# maintainer can approve it, and the prose-only paths that
# .github/workflows/auto-merge.yml recognises merge automatically on green CI.
#
# There is deliberately NO default (`*`) owner: a catch-all would force owner
# review on every PR and defeat the point. Replace @plind-junior below with your
# maintainer team (e.g. @vouchdev/core) if you prefer team-based ownership.

# --- the review gate + claim lifecycle — writes must stay gated ---
/src/vouch/proposals.py @plind-junior
/src/vouch/lifecycle.py @plind-junior

# --- verification: the byte-offset receipt (the differentiator) ---
/src/vouch/receipts.py @plind-junior

# --- the append-only, authoritative history ---
/src/vouch/audit.py @plind-junior

# --- durable storage + the derived index ---
/src/vouch/storage.py @plind-junior
/src/vouch/index_db.py @plind-junior

# --- the object model / on-disk schema contract ---
/src/vouch/models.py @plind-junior
/src/vouch/migrations/ @plind-junior

# --- the kb.* method surface + transports — parity is load-bearing ---
/src/vouch/capabilities.py @plind-junior
/src/vouch/server.py @plind-junior
/src/vouch/jsonl_server.py @plind-junior

# --- the protocol contract ---
/SPEC.md @plind-junior
/spec/ @plind-junior

# --- packaging + the four-site version invariant ---
/pyproject.toml @plind-junior
/openclaw.plugin.json @plind-junior
/package.json @plind-junior
/src/vouch/__init__.py @plind-junior

# --- build / release / supply-chain — a workflow edit can exfiltrate secrets ---
/.github/workflows/ @plind-junior
/.github/dependabot.yml @plind-junior
/Dockerfile @plind-junior
/install.sh @plind-junior

# --- governance itself ---
/.github/CODEOWNERS @plind-junior
/GOVERNANCE.md @plind-junior
/CONTRIBUTING.md @plind-junior
78 changes: 78 additions & 0 deletions .github/workflows/auto-merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: auto-merge

# Auto-merge the safe, prose-only contributions (docs, examples, issue
# templates) once CI is green — no maintainer needed. Anything that touches
# code, tests, adapters, config, or the core paths in CODEOWNERS is left for a
# human. This is the repo mirror of vouch's own gate: a change that carries no
# risk is auto-approved; a change to the gate needs a person.
#
# SECURITY: pull_request_target runs with the base repo's token so it can enable
# auto-merge on pull requests from forks. This job only READS the changed-file
# list through the API — it never checks out or runs the PR's code — so
# untrusted code never touches the privileged token. Do not add a checkout of
# the PR head here.
#
# Enabling auto-merge does not bypass anything: GitHub still waits for the
# required status checks and any required reviews configured in branch
# protection before it actually merges. See GOVERNANCE.md → "Turning this on".

on:
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review]

permissions:
contents: write
pull-requests: write

jobs:
auto-merge:
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
steps:
- name: classify changed files and enable auto-merge if prose-only
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR: ${{ github.event.pull_request.number }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail

# A path is auto-merge-safe only if it cannot change code execution,
# the gate, the schema, or the protocol. Keep in sync with
# GOVERNANCE.md → "Tier 2 — auto-merge safe".
is_safe() {
case "$1" in
# governance / security / contract docs are owner-reviewed
SECURITY.md|GOVERNANCE.md|CONTRIBUTING.md|CODEOWNERS) return 1 ;;
spec/*) return 1 ;; # the protocol contract, not prose
docs/*) return 0 ;; # curated prose docs
.github/ISSUE_TEMPLATE/*) return 0 ;;
*/*.md) return 1 ;; # nested .md (examples/, adapters/, …) — review it
*.md) return 0 ;; # top-level prose (README, CHANGELOG, …)
*) return 1 ;; # everything else — code, examples, tests, config
esac
}

files=$(gh pr view "$PR" --repo "$REPO" --json files --jq '.files[].path')
if [ -z "$files" ]; then
echo "no changed files reported; nothing to do"; exit 0
fi

all_safe=true
while IFS= read -r f; do
[ -z "$f" ] && continue
if is_safe "$f"; then
echo "safe : $f"
else
echo "review : $f"
all_safe=false
fi
done <<< "$files"

if [ "$all_safe" = true ]; then
echo "::notice::prose-only PR — enabling auto-merge (still waits for required CI)."
gh pr merge "$PR" --repo "$REPO" --auto --squash \
|| echo "::warning::could not enable auto-merge — enable 'Allow auto-merge' in repo Settings › General and add a required status check in branch protection."
else
echo "::notice::PR touches code/tests/adapters/core — leaving it for human review."
fi
18 changes: 14 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,20 @@ usually save everyone time.

Every PR gets an automated review pass (CodeRabbit; pushes to `test` also
get a Copilot review) plus the CI gate — lint, mypy, the test matrix on
Python 3.11/3.12/3.13, and an sdist + wheel build. A maintainer reads the
review output and the diff, then merges or closes; there is no auto-merge.
So get it green before you push: run the full local gate below, keep the
branch conflict-free, and keep the PR to one concern.
Python 3.11/3.12/3.13, and an sdist + wheel build. What happens next depends
on *where* your PR lands, which [GOVERNANCE.md](GOVERNANCE.md) maps out in
full:

- **prose-only** (`docs/**`, `examples/**`, top-level markdown, issue
templates) merges itself once CI is green — no maintainer needed.
Comment on lines +17 to +18

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Remove examples/** from the auto-merge list.

GOVERNANCE.md and the auto-merge.yml workflow explicitly exclude examples/** from auto-merge because examples can carry runnable code. Listing it here as a prose-only auto-merge path creates a contradiction that might confuse contributors when their PRs do not merge automatically.

🐛 Proposed fix
- - **prose-only** (`docs/**`, `examples/**`, top-level markdown, issue
+ - **prose-only** (`docs/**`, top-level markdown, issue
    templates) merges itself once CI is green — no maintainer needed.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- **prose-only** (`docs/**`, `examples/**`, top-level markdown, issue
templates) merges itself once CI is green — no maintainer needed.
- **prose-only** (`docs/**`, top-level markdown, issue
templates) merges itself once CI is green — no maintainer needed.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CONTRIBUTING.md` around lines 17 - 18, Update the prose-only auto-merge path
description in CONTRIBUTING.md to remove examples/**, leaving docs/**, top-level
markdown, and issue templates listed as eligible paths. Keep the wording
consistent with the exclusions defined in GOVERNANCE.md and auto-merge.yml.

- **contributor-friendly code** (adapters, retrieval/capture quality, the web
console, tests) is merged by any maintainer after a read of the diff.
- **core** (the review gate, verification, the audit log, storage/schema, the
`kb.*` surface, packaging, CI) needs the code owner — see the area map before
you start, so you know which lane you are in.

Either way: get it green before you push — run the full local gate below, keep
the branch conflict-free, and keep the PR to one concern.

Base feature branches on `test` and target `test` in the PR — it is the
integration branch, and it reaches `main` via promotion PRs cut by the
Expand Down
66 changes: 66 additions & 0 deletions GOVERNANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,72 @@ Three kinds of decisions, three different bars:
direction. Requires consensus among all maintainers and a 14-day
public comment window on a PR or issue.

## Contribution areas — who may change what

The three decision bars above map onto concrete parts of the tree. This is the
practical version for a contributor deciding where to start, and it is enforced
by [`.github/CODEOWNERS`](.github/CODEOWNERS) and
[`.github/workflows/auto-merge.yml`](.github/workflows/auto-merge.yml).

### Core (owner-only)

The load-bearing invariants — the "surface changes" bar above, made concrete. A
mistake here can make verification forgeable, let a write skip the gate, corrupt
the authoritative history, or break a contract downstream tools depend on. Only
a code owner merges these:

| Area | Paths | Why |
|---|---|---|
| Review gate + lifecycle | `src/vouch/proposals.py`, `lifecycle.py` | every write must go through `approve()` |
| Verification | `src/vouch/receipts.py` | the byte-offset receipt is the differentiator |
| Authoritative history | `src/vouch/audit.py` | the audit log is append-only |
| Storage + index | `src/vouch/storage.py`, `index_db.py` | a torn write or lost fsync is data loss |
| Object model / schema | `src/vouch/models.py`, `migrations/` | the on-disk + bundle contract |
| Method surface + transports | `capabilities.py`, `server.py`, `jsonl_server.py` | MCP/JSONL/CLI parity |
| Protocol | `SPEC.md`, `spec/` | what downstream tools code against |
| Packaging + version | `pyproject.toml`, `openclaw.plugin.json`, `package.json`, `src/vouch/__init__.py` | the four-site version invariant |
| Supply chain | `.github/workflows/`, `.github/dependabot.yml`, `Dockerfile`, `install.sh` | a workflow edit can exfiltrate secrets |

Adding a new `kb.*` method spans four of these files, so it is core too — file a
VEP first.

### Contributor-friendly (any maintainer reviews)

Where most contributions land: behavior, not invariants. Any maintainer merges
on green CI. Host adapters (`adapters/<host>/`, `install_adapter.py`), retrieval
and capture quality (`extract.py`, `recall.py`, `context.py`, `salience.py`,
`compile.py`, `sessions.py`, `hooks.py`, `fetch.py`, `notify.py`, `stats.py`,
`metrics.py`, thin `cli.py` commands), the web console (`webapp/`,
`src/vouch/web/`), and tests (`tests/**`).

### Auto-merge safe (green CI merges it, no human)

Prose that cannot change how the code runs — `docs/**`, top-level markdown
(`README.md`, `CHANGELOG.md`, …), and `.github/ISSUE_TEMPLATE/**`. Excluded even
though they are text: `SECURITY.md`, this file, `CONTRIBUTING.md`, `CODEOWNERS`,
and `spec/**` (the protocol contract). `examples/**` is *not* auto-merged — it
can carry runnable code, so a maintainer reads it (Tier 1).

## How PRs merge

Two mechanisms live in `.github/`:

- **`CODEOWNERS`** forces a code-owner review on any core path — the hard
backstop — once branch protection's "Require review from Code Owners" is on.
- **`auto-merge.yml`** enables GitHub auto-merge on a prose-only PR so it merges
itself on green CI. It reads only the changed-file list (it never runs PR
code), and enabling auto-merge still waits for the required checks.

**Owner setup (one-time, repo Settings, on `test` and `main`):** enable *Allow
auto-merge*; add a branch-protection rule that *requires a PR*, *requires review
from Code Owners*, and *requires the `ci` status checks*; set the owner handle in
`CODEOWNERS`. Without required checks, auto-merge has nothing to wait on and
merges nothing.

This is vouch applied to vouch: a docs PR is a claim whose receipt verifies —
mechanically safe, auto-approved; a change to `proposals.py` touches the gate
itself, and no receipt can vouch for that, so a person decides.

## Disagreements

If contributors disagree on a PR, the assigned maintainer makes the call.
Expand Down
Loading