galdr 0.17.0

Record & Replay for agent skills — capture a session's tool calls and distill them into a reproducible skill. Local-first.
# Contributing to galdr

Thanks for considering a contribution. galdr's bar is high on two invariants:
the **sensor must never break an agent session**, and the **core makes no external
network egress**. Everything else follows from those.

## Ground rules

1. **The sensor never propagates failure.** `galdr hook` must always exit 0. The
   `catch_unwind` guard in `main` and the `Result`-discarding contract in `hook.rs`
   are load-bearing — keep them. The sensor also never *depends* on the daemon: it
   appends to the span first (the truth, unconditional), then hints the daemon
   best-effort. The integration test `sensor_never_breaks_the_session` guards this.
2. **No external network egress in the core.** The only optional traffic is the
   autonomous distiller (`distill --auto`, feature `mlx`), and it talks **only to
   loopback** — enforced by `engine::validate_loopback`, which the HTTP engine
   re-checks before every request. Do not add any other network path.
3. **The span is append-only and immutable.** Nothing edits or deletes a recorded
   event. The SQLite catalog is a rebuildable *index, never the source of truth*;
   `galdr reindex` recreates it from `spans/` + `recordings/`.
4. **galdr is the only writer of the skills directory.** New install paths go
   through the shared `install_skill`; the agent never writes `~/.agents/skills`
   by hand.
5. **The public core stays generic.** Integrations plug in through the
   `PermissionGate` and `ProvenanceSink` traits, from outside this repository. Do
   not hardcode any specific harness, policy engine, or memory system into the core.
6. **All code, comments, and docs are in English.**

## Commit convention

We use [Conventional Commits](https://www.conventionalcommits.org/). CI runs
`commitlint` on every PR; see `.commitlintrc.yaml` for the exact ruleset.

**Types** (required): `feat`, `fix`, `chore`, `docs`, `refactor`, `perf`, `test`,
`build`, `ci`, `revert`, `security`.

**Scope** (optional, but when present must be one of): `paths`, `span`, `record`,
`hook`, `sensor`, `ext`, `summary`, `catalog`, `ipc`, `daemon`, `tui`, `diff`,
`parametrize`, `distill`, `engine`, `config`, `cli`, `docs`, `ci`, `deps`,
`release`, `security`, `examples`.

Examples:

```
feat(daemon): reconcile dropped notifications in the poll-watcher
fix(catalog): keep the ended_at NULL filter out of the in-memory fallback
security(engine): re-check validate_loopback before every HTTP request
chore(deps): bump rusqlite to 0.40.2 — feature matrix green
```

**Breaking changes**: add `!` after the type (`feat(cli)!:`) and include a
`BREAKING CHANGE:` footer.

## Versioning

[Semantic Versioning](https://semver.org/). Below `1.0.0`, breaking changes to a
CLI flag, the daemon IPC protocol, or the on-disk layout are released as minor
bumps, with the migration path documented in the release notes; compatible fixes
are patch bumps.

## Releases

Automated via [release-please](https://github.com/googleapis/release-please). Do
not tag manually: the bot opens a release PR as Conventional Commits land, and
merging it creates the `v*` tag and triggers the signed binary build.

## Local dev

`just check` runs the same gate as CI (`just` from <https://just.systems>):

```sh
just check          # fmt + clippy (both features) + test (both features) + deny
```

Or run the steps directly:

```sh
cargo fmt --all --check
cargo clippy --all-targets -- -D warnings
cargo clippy --all-targets --features mlx -- -D warnings
cargo test
cargo test --features mlx
cargo deny check    # requires `cargo install cargo-deny`
```

The integration tests under `tests/cli.rs` drive the compiled binary in an
isolated temp `HOME`, covering the sensor contract, the daemon round-trip, the
catalog fallbacks, and diff/parametrize end to end.

## Style

- `rustfmt` defaults, no custom `rustfmt.toml` unless we outgrow them.
- `clippy::pedantic` not enforced globally; apply where it clarifies, skip where it
  produces noise.
- Doc comments on public items; module docs explain the *why*, not just the *what*.