Senate decisions — quality-gate verdicts, lifecycle transitions
(active → deprecated, under_review → falsified), Elo penalties,
honeypot retirements, pause grants — happen across a dozen modules
(scidex/senate/decision_engine.py,
scidex/senate/integrity_sweeper.py,
scidex/senate/governance.py, scidex/senate/edit_emitter.py,
scidex/senate/sandbox_audit.py). Each writes to its own table or
just logs. There is no single transparency surface where a researcher
can ask "show me every governance decision that affected this
hypothesis" or an auditor can ask "who approved Senate alert X". This
task ships a unified, hash-chained, externally-readable transparency
log of all governance decisions, modelled on Certificate Transparency.
Effort: deep
migrations/20260428_governance_transparency.sql:CREATE TABLE governance_decision (
id BIGSERIAL PRIMARY KEY,
decided_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
decision_kind TEXT NOT NULL, -- 'lifecycle_change','elo_penalty',
-- 'pause_grant','gate_verdict',
-- 'attestation_revoke','provenance_break'
subject_kind TEXT NOT NULL, -- 'hypothesis','analysis','agent','skill','quest'
subject_id TEXT NOT NULL,
decided_by TEXT NOT NULL, -- 'senate.auto' or human user id
rationale TEXT NOT NULL,
before_state JSONB,
after_state JSONB,
ref_alert_ids BIGINT[],
chain_seq BIGINT -- audit_chain seq, set after chain append
);
CREATE INDEX idx_gd_subject ON governance_decision(subject_kind, subject_id);
CREATE INDEX idx_gd_kind ON governance_decision(decision_kind);
CREATE INDEX idx_gd_when ON governance_decision(decided_at DESC);scidex/senate/transparency_log.py:record(*, decision_kind, subject_kind, subject_id,
decided_by, rationale, before_state, after_state,
ref_alert_ids=None) -> int — inserts the row and appendsaudit_chain (event_kind='governance_decision'),chain_seq.scidex/senate/decision_engine.py gate verdicts.scidex/senate/integrity_sweeper.py orphan-quarantinescidex/atlas/lifecycle_constants.py callers (any callerwith_transparency(...).q-trust-signed-artifact-attestations revoke calls.q-rt-adversarial-debate-runner Elo penalties.q-safety-emergency-pause senate_pause writes.
GET /api/senate/decisions?subject_id=... returnsGET /api/senate/decisions/recent?kind=...&since=ISOGET /senate/decisions/{decision_id} HTML detail pagechain_seq, chain_hash).
GET /api/senate/decisions/{id}/proof and receive theaudit_chain rows from genesis to the row's chain_seq,data/scidex-papers/audit_chain_head.log. The auditordata/scidex-papers/governance/YYYY-MM-DD.md (in the paperscommit_artifact withq-gov-attribution-audit trailers.
tests/test_transparency_log.py:chain_seq non-null afterq-trust-audit-log-hash-chain — chain-append target.q-gov-attribution-audit — daily digest commits ride on thePrior work (commit 10e207dda, squash of dff08e77) landed:
migrations/20260428_governance_transparency.sql ✅scidex/senate/transparency_log.py with record(), chain-append, backfill ✅decision_engine.py gate verdicts, integrity_sweeper.py quarantine ✅governance_digest.py daily markdown writer ✅tests/test_transparency_log.py (all pass) ✅GET /api/senate/decisions — query by subject_id, newest first, paginated ✅GET /api/senate/decisions/recent — bulk auditor stream, kind+since filter ✅GET /api/senate/decisions/{id}/proof — audit_chain inclusion proof ✅GET /senate/decisions/{id} — HTML detail page (before/after diff, chain proof) ✅_build_governance_history_html() helper in api.py ✅with_transparency(...) decorator