Metadata-Version: 2.4
Name: crowdcoding
Version: 0.1.0
Summary: Owner-verified crowd contributions: analyze a repo with your own LLM, send a signed Envelope, the owner's own agents re-prove it before merge.
Author: Augusto Bastos
License: MIT
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cryptography>=42
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Provides-Extra: mcp
Requires-Dist: mcp>=1.2; extra == "mcp"
Dynamic: license-file

# Crowdcoding

**Owner-verified crowd contributions.** Use *your* LLM to analyze a repo you don't own,
fix or improve it, and package the change as a **signed, verifiable Envelope**. The repo
owner receives it and — at a scrutiny level they choose — has **their own agents re-prove
it is authentic, safe, and correct** before accepting. On accept, the change merges with the
contributor's authorship preserved, so they **automatically become a real contributor**.

It is not a roving bot that opens unsolicited PRs. It is the inverse: an **opt-in,
owner-gated** flow where the *owner's own tooling* decides what enters.

## How it works

The contract between the two sides is the **Envelope** (a signed zip) plus the receiver's
**re-prove** — never a shared agent and never blind trust. The Ed25519 signature proves only
*"a real keyholder produced this, unaltered"*; it is anti-forgery, not a reason to trust.

```
contributor's model  ──analyze──▶  fix pieces  ──self-verify (sandbox)──▶  sign
                                                                            │
                                                                     envelope.zip
                                                                            │
owner's model  ◀──re-prove: provenance ▸ safety ▸ correctness ▸ fit──  unpack
        │
   accept ─▶ git apply + commit (author = contributor, Assisted-By: trailer)   /   reject
```

## The command set

| Command | What it does | Brain |
|---|---|---|
| `analyze <repo>` | Read-only scout: grade the repo and brief its top fixable issues. No fix, no envelope. | council |
| `contribute <repo>` | Analyze → fix → self-verify in a sandbox → emit a **signed Envelope**. | council |
| `pull <repo>` | Clone the repo into a local workspace so you can edit it **by hand**. | none |
| `pack` | Seal your workspace's manual edits into the **same signed Envelope** a council would produce. | none |
| `keygen` | Create or show your Ed25519 signing key — prints the **public** key only. | none |
| `inspect <envelope>` | Read an Envelope safely: parse + signature check, **runs nothing**. | none |
| `verify <envelope> --repo <clone>` | Owner handshake: re-prove provenance ▸ safety ▸ correctness ▸ fit. `--apply` merges with credit. | owner's |
| `init` | Stamp the machine-detectable opt-in badge on a repo's README. | none |

`analyze` and `contribute` use the **council brain** (your own LLM); `pull` and `pack` are the
**AI-free "do it your way" path** — you author the diff by hand and Crowdcoding just signs and
packages it into an Envelope the owner re-proves exactly the same way.

## Quickstart (offline, no key, zero cost)

Everything here runs with no network and no API key — the bundled `mock` backend is a
deterministic offline stub used by the test suite and CI.

```bash
python -m pip install -e .[dev]

crowdcoding --version          # crowdcoding 0.1.0
crowdcoding keygen             # prints your PUBLIC key; private stays in ~/.crowdcoding/key.pem
python -m pytest -q            # 87 passing — the full contribute → verify → credited-merge flow
```

`keygen`, `pull`, `pack`, `inspect`, and `init` need **no model and no API key** — the whole
do-it-your-way path (edit a clone, seal it, read the result) runs fully offline.

The test suite is the offline proof: it drives *two independent* mock councils end to end,
including tamper-rejection and booby-trap-rejection.

> The `mock` backend is a stub for tests/CI — it does **not** synthesize fixes or grades on its
> own, so `crowdcoding analyze <repo> --backend mock` and `crowdcoding contribute <repo> --backend
> mock` both report "no issues". To produce real analysis or contributions, bring your own model
> (below). The AI-free commands (`pull`/`pack`/`inspect`/`init`) do not need a backend at all.

## Bring your own model

One OpenAI-compatible backend covers every provider — OpenAI, Azure, Gemini/Anthropic compat
endpoints, OpenRouter, and local runtimes (Ollama, LM Studio, llama.cpp, vLLM). Configure it
with three environment variables:

```bash
export CROWDCODING_BACKEND=openai
export CROWDCODING_BASE_URL=http://localhost:11434/v1   # Ollama (fully local, free)
export CROWDCODING_MODEL=llama3
# export CROWDCODING_API_KEY=...   # only if the provider needs one; never logged, only its presence
```

OpenRouter instead:

```bash
export CROWDCODING_BASE_URL=https://openrouter.ai/api/v1
export CROWDCODING_MODEL=anthropic/claude-3.5-sonnet
export CROWDCODING_API_KEY=...
```

**Scout first (optional)** — read-only grade + briefing of the top fixable issues, no envelope:

```bash
crowdcoding analyze https://github.com/owner/repo          # add --json for the machine report
```

**Contributor side** — analyze, fix, self-verify, and emit a signed envelope:

```bash
crowdcoding contribute https://github.com/owner/repo --out envelope.zip \
    --name "Your Name" --email you@example.com
```

(`--name`/`--email` default to your `git config user.name` / `user.email`.)

**Owner side** — re-prove the envelope against your own clone, then merge with credit:

```bash
crowdcoding verify envelope.zip --repo /path/to/local/clone --trust strict
crowdcoding verify envelope.zip --repo /path/to/local/clone --apply
```

`--apply` requires `--repo` to be a local working copy. For each accepted piece it runs
`git apply` and one `git commit` authored as the contributor, with an
`Assisted-By: crowdcoding/<model>` trailer and the envelope's SHA-256 in the message —
automatic, honest attribution. Add `--json` to any `verify` for the full machine-readable report.

## Do-it-your-way — `pull` + `pack` (no AI required)

Prefer to fix things by hand? Skip the council entirely. `pull` clones the repo into a workspace
and records the exact base commit; you edit however you like; `pack` diffs your working tree
against that base and seals the change into the **same signed Envelope** — which the owner
re-proves with the identical handshake. No model, no API key.

```bash
crowdcoding pull https://github.com/owner/repo --dest ./repo   # clone + record the base commit
#   ... edit files in ./repo by hand ...
crowdcoding pack --workspace ./repo --out envelope.zip \
    --name "Your Name" --email you@example.com                 # sign + package your manual diff
```

The base commit is stored in `./repo/.crowdcoding/base.json` and kept out of your diff. `pack`
refuses an empty change set, so an accidental no-op never ships. Pass `--backend` **only** if you
want a model to write the owner-facing briefing — the diff itself is always yours.

## Read before you trust — `inspect`

`inspect` opens an Envelope and reports the sender, base commit, signature validity, and a
per-piece line count **without running anything** — no clone, no sandbox, no backend. It is safe
to point at an untrusted envelope: parsing plus a signature check is the whole attack surface.

```bash
crowdcoding inspect envelope.zip        # add --json for the full report
```

Exit code is `0` when the signature verifies and `2` when it does not (still listing the pieces),
so CI can gate on a tampered/unsigned envelope.

## Opt in — `init`

`init` stamps a machine-detectable badge on your repo's README so crawlers can find
"Crowdcoding contributions welcome" and humans can click through. It only edits `README.md` —
never commits, pushes, or reaches the network — and is idempotent (a second run is a no-op).

```bash
crowdcoding init --repo . --url https://github.com/you/your-repo   # --url defaults to origin
```

## Trust levels

The owner picks how hard to re-prove each envelope:

| `--trust`  | Provenance (signature) | Safety audit | Sandboxed correctness | Fit (style/license/AI policy) |
|------------|:----------------------:|:------------:|:---------------------:|:-----------------------------:|
| `strict`   | ✅                     | ✅           | ✅                    | ✅                            |
| `trusted`  | ✅                     | ✅           | —                     | —                             |
| `direct`   | ✅                     | —            | —                     | —                             |

A failed signature is fatal at every level: the envelope is rejected and nothing is applied.
`direct` accepts on a valid signature alone (confidence 0.5) — use it only for contributors you
already trust.

## What the handshake guarantees — and what it doesn't

- **Signature = authenticity, not trust.** It proves the bytes are unaltered and came from the
  holder of the stated key. It says nothing about whether the change is safe or good — that is
  what re-proving is for.
- **The sandbox is process isolation + a cleaned environment + a hard timeout, not a container.**
  It runs the untrusted diff in a throwaway copy of the repo, in a subprocess whose environment is
  stripped of `CROWDCODING_*`, `*_API_KEY`, `*_TOKEN`, `*_SECRET`, `*_PASSWORD` variables, and kills
  the run on timeout. That contains accidents and casual exfiltration — it is **not** a defense
  against a determined attacker. Container/VM hardening is the documented post-MVP step. Never run
  `verify` against a working tree you care about; the temp copy is always discarded.
- **The owner always has the final say.** Every stage produces evidence; the verdict
  (`accept` / `needs-changes` / `reject`) and confidence are the owner's to act on.
- **Secrets are scrubbed** from every prompt and from provenance excerpts, and are never logged —
  only their presence is.

## Anti-slop stance

Open-source maintainers are rightly wary of unsolicited AI contributions. Crowdcoding is built to
respect that:

- **Quality over volume** — pieces that don't apply cleanly or don't pass the target's own tests
  are dropped before they ever reach the owner.
- **Owner-gated by construction** — nothing merges unless the owner's own tooling re-proves it.
- **Always disclosed** — accepted merges carry an `Assisted-By:` trailer, in line with emerging
  maintainer AI policies.
- **Policy-aware** — the `fit` stage reads the repo's `AGENTS.md` / `CLAUDE.md` / `LICENSE` and
  judges the piece against them.

## Status

MVP. Working today: the read-only `analyze` scout, BYO-model `contribute`, the AI-free
`pull`/`pack` path, signed Envelopes, safe `inspect`, the four-stage owner handshake with trust
levels, credited `--apply` merges, and the opt-in `init` badge. On the roadmap (design-stage): a
PR-native on-ramp, a hosted verify App, and MCP-based envelope intake.

## License

MIT © 2026 Augusto Bastos. Grown out of the author's [`council`](https://github.com/augbastos/council)
deliberation engine.
