Implement three small functions that ship a release:
- next_release(version, changes) — changes is a list containing any of 'breaking', 'feature', 'fix': bump major for breaking, else minor for feature, else patch; return the new version string (reuse semver rules: strict MAJOR.MINOR.PATCH, lower parts reset)
- safe_registry(entries) — entries are (group, name, factory); return {group: {name: factory}}, raising ValueError('duplicate plugin: <name>') on any duplicate name within a group
- incident_log(correlation_id, events) — events are (level, event, fields) dicts/tuples with possible 'password'/'token' fields; return the list of JSON lines (sorted keys) with correlation_id added and sensitive fields replaced by '[REDACTED]'
The invariants: breaking > feature > fix precedence; no silent plugin shadowing; no secrets in logs.
Difficulty: advanced