# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.2.1] - 2026-05-09
### Added — Experimental trait surfaces
- **`experimental_diff_renderer` module** — `DiffRenderer` trait,
`DiffRequest`, `DiffResponse`, `DiffLine`, `DiffLineKind`, `DiffView`.
Runtime-agnostic contract for diff rendering; reuses
`render::TokenSpan` for styled spans. Consumer:
`progit-syntax-diff` plugin (in `progit-plugins`).
- **`experimental_fragments` module** — `FragmentRenderer` trait,
`FragmentContext`, `RenderFragment`, `FragmentAction`,
`FRAGMENT_SLOT_REGISTRY` const. Mechanism for plugins to inject UI
fragments into existing TUI widgets. Slot identifiers validated
against the fixed allowlist; plugins cannot invent new slots.
Consumer: `progit-pr-stacker` plugin.
Both modules ship behind the `experimental_*` namespace per the
"never stabilise an interface before a real consumer has used it
in production" rule. Promotion to `traits::DiffRenderer` /
`traits::FragmentRenderer` lands once the consumer plugins exercise
the API in a shipped release.
6 unit tests added covering serde round-trips and slot-registry
validation. `cargo check` clean; non-breaking, namespace-isolated.
### Added (carried forward — render-time plugin contract)
- **Render-time plugin contract** — `progit_plugin_sdk::render` module
exposes `TokenSpan`, `Rgb`, `HighlightRequest`, `HighlightResponse`.
`Plugin::highlight()` is a new trait method (default `None`); plugins
that want to be highlight providers override it.
- LuaPlugin implementation: detects `plugin.highlight = function(req) ... end`
and round-trips the request/response through serde + mlua.
- Two new SDK harness tests covering `syntax-highlight` v1.0
end-to-end: coloured-span content invariant + decline-unknown-language.
### Notes
- The render hook is intentionally synchronous and cache-friendly:
the host caches by `blake3(language || '\0' || content)` so the Lua
roundtrip happens once per unique line, not once per frame.
## [0.2.0] - 2026-05-06
### Added
- **Sandboxed LuaJIT runtime** — `io`, `debug`, `dofile`, `loadfile` are
removed entirely; `os.execute`, `os.exit`, `os.remove`, `os.rename`,
`os.tmpname`, `os.setlocale`, `package.loadlib`, `package.searchpath`
raise a clear error inside the VM (Doctrine 4 enforcement).
- **Memory + instruction caps** via `LuaPluginOptions::{memory_mb,
max_instructions}`. Default 64 MB / 10 M instructions per hook.
- **Capability-checked HTTP** — `http.{get,post,put,delete}` route through
a single shared `reqwest::blocking::Client` per plugin, gated by the
manifest's `capabilities.network` and `capabilities.network_allow`
suffix-match list.
- **Injected `log` table** (`log.debug/info/warn/error`) routed to the
Rust `log` crate. Back-compat globals `log_info`, `log_warn`, `log_error`
also provided.
- **Injected `storage` table** (`storage.get/set/delete/keys/clear`)
scoped to `<repo>/.progit/plugins/<plugin-name>/state.json`.
- **Typed `PluginManifest`** module with `Capabilities`, `SdkVersion`
(no `semver` crate dependency), and `from_path` / `check_sdk_compat` /
`check_hooks` helpers.
- **SDK API version** constant `SDK_API_VERSION = "0.2"` and
manifest-driven compatibility check.
- **Per-plugin failure isolation** in `PluginManager`: 5 consecutive
errors → automatic quarantine; expose `quarantined_plugins()` and
`unquarantine(name)` for host-side recovery.
### Changed
- **License**: SDK source now declares LSL-1.0 in every SPDX header to
match `Cargo.toml`. Earlier headers said Apache-2.0 by mistake.
- **HTTP default timeout**: 30 s → 5 s. Configurable per plugin via
the manifest's `capabilities.http_timeout_secs`.
- **Single source of truth for events**: `PluginEvent` (and friends —
`PipelineStatus`, `PipelineState`, `PipelineJob`) moved from the
ProGit host crate into `progit_plugin_sdk::event`. The host now
re-exports them. Earlier the two were independent definitions that
drifted.
- **`http` client** is built once per plugin instead of once per request,
cutting TLS handshake overhead.
- **Network capability** defaults to *off* in the legacy default
capability block. v0.1 plugins that called `http.*` without declaring
`capabilities.network` will now fail with a clear error pointing at
the manifest.
### Removed
- Dead parallel `Plugin` / `PluginEngine` trait pair and
`LuaPluginEngine` struct in `progit/src/plugins/{sdk,lua_engine}.rs`.
These were never wired into the active manager. The SDK is now the
single source of truth.
### Fixed
- `slack-notify` plugin (1.1.0): rewrote to use the real injected
`http.post`, `json.encode`, and `log.*` instead of nonexistent
`progit.http_post` / `log_info` symbols. Now functional end-to-end.
### Security
- Plugins without a `capabilities` block in their manifest get
legacy-permissive defaults *with network off* and a deprecation
warning at load time. Future major versions will default to deny.
## [0.1.0] - 2025-12-11
### Added
- Initial release
- Basic plugin infrastructure
- Lua plugin runtime with mlua
- WASM plugin runtime with wasmtime (opt-in)
- Plugin trait system (Plugin, IssuePlugin, SyncPlugin)
- Hook system for issue lifecycle events
- Example Lua plugins (hello-world, jira-sync)
[Unreleased]: https://git.sovereign-society.org/ProGit/progit-plugin-sdk/compare/v0.2.0...HEAD
[0.2.0]: https://git.sovereign-society.org/ProGit/progit-plugin-sdk/compare/v0.1.0...v0.2.0
[0.1.0]: https://git.sovereign-society.org/ProGit/progit-plugin-sdk/releases/tag/v0.1.0