# Contributing

Contributions are welcome, and the useful ones are narrow: a new distribution backport, a decode
path the audit misses, a defect in the classification matrix.

Read [`AGENTS.md`](AGENTS.md) first. It states the invariants that a change must preserve.

## What a good contribution looks like

| Contribution | What it must include |
|---|---|
| Support for a new distribution | the package name, the vulnerable and fixed version strings, the pocket, and the changelog line that names the CVE |
| A new decode path | a reproduction: the component, the argument or directive that enables decoding, and how the detector recognises it |
| A defect in the matrix | a version string the current logic classifies wrongly, with the expected verdict |
| A documentation fix | the file, the sentence, and the measurement that contradicts it |

## Invariants a pull request must not break

1. `detect.sh` and `verify.sh` stay read-only.
2. `remediate.sh` keeps backup-before-change, the authenticity gate and the dry run, in that order.
3. No claim about effect without a check in `/proc/*/maps`.
4. Exit codes stay as documented: `0` safe, `1` vulnerable or verification failed, `3` not
   installed, `10` error.
5. No credentials, tokens, addresses or hostnames — in code, in tests or in documentation.
6. UTF-8, LF, no BOM; `.sh` files with mode `100755`.

## Local checks

```bash
bash -n src/*.sh
shellcheck src/*.sh
```

Encoding and document checks run in CI; reproduce them locally with:

```bash
python - <<'PY'
import pathlib
for p in pathlib.Path('.').rglob('*'):
    if p.is_file() and '.git' not in p.parts:
        b = p.read_bytes()
        assert not b.startswith(b'\xef\xbb\xbf'), f'BOM: {p}'
        assert b'\r\n' not in b, f'CRLF: {p}'
print('encoding OK')
PY
```

## Field evidence

A change to the remediation logic needs a field run, in this order:

1. `detect.sh` on a disposable host with the vulnerable package: exit `1`, verdict `VULNERABLE`.
2. `remediate.sh`: exit `0`, `REMEDIATED:` line, backup directory present.
3. `verify.sh`: `VERIFY: PASS`.
4. A second `detect.sh`: exit `0`, verdict `SAFE`.

Paste the four verdict lines into the pull request. A change without them is a proposal, not a fix.

## Commit messages

Conventional commits, one logical change per commit:

```text
feat(detect): recognise the Bun runtime as a decode path
fix(remediate): guard the consumer loop against a non-zero last probe
docs(wiki): add the field case for transient panel scopes
```

The commit is authored by the owner of the repository, not by an automation identity. Publication
protocol in [`AGENTS.md`](AGENTS.md).

## Review

A reviewer checks three things, in this order: does the change preserve the invariants, is the claim
backed by a measurement in the pull request, and does the documentation still describe what the code
does. A change that improves the code and leaves the documentation behind is returned.
