| 1 | package event |
| 2 | |
| 3 | import ( |
| 4 | "reasonix/internal/evidence" |
| 5 | "reasonix/internal/nilutil" |
| 6 | ) |
| 7 | |
| 8 | // AuditForwarder forwards every optional sink capability to Inner. Embed it in |
| 9 | // a wrapper that only passes host-side signals through, so a channel added here |
| 10 | // reaches every embedder without editing them. Hand-written forwarding lost |
| 11 | // capabilities at multiple wrappers even while their owning tests stayed green. |
| 12 | type AuditForwarder struct{ Inner Sink } |
| 13 | |
| 14 | // OptionalSinkCapabilities is the complete host-side capability contract that |
| 15 | // event decorators must preserve. Keeping the method set in one interface lets |
| 16 | // wrappers use compile-time assertions instead of maintaining partial lists in |
| 17 | // tests that silently drift when a new capability is added. |
| 18 | type OptionalSinkCapabilities interface { |
| 19 | RuntimeStateSink |
| 20 | DelegationAuditSink |
| 21 | ReadinessAuditSink |
| 22 | AnchorSafetyAuditSink |
| 23 | ContractShadowAuditSink |
| 24 | CompletionReportAuditSink |
| 25 | MemoryRecallSink |
| 26 | DelegationAdmissionSink |
| 27 | OutcomeProgressSink |
| 28 | ProtocolRecoveryAuditSink |
| 29 | TurnCompletionSink |
| 30 | WorkspaceMutationSink |
| 31 | RunBudgetSink |
| 32 | SubagentLifecycleAuditSink |
| 33 | } |
| 34 | |
| 35 | var _ OptionalSinkCapabilities = AuditForwarder{} |
| 36 | |
| 37 | func (f AuditForwarder) RecordReadinessAudit(a evidence.ReadinessAudit) { |
| 38 | RecordReadinessAudit(f.Inner, a) |
| 39 | } |
| 40 | |
| 41 | func (f AuditForwarder) RecordAnchorSafetyAudit(a AnchorSafetyAudit) { |
| 42 | RecordAnchorSafetyAudit(f.Inner, a) |
| 43 | } |
| 44 | |
| 45 | func (f AuditForwarder) RecordTurnCompletion() { RecordTurnCompletion(f.Inner) } |
| 46 | |
| 47 | func (f AuditForwarder) RecordContractShadow(a ContractShadowAudit) { |
| 48 | RecordContractShadow(f.Inner, a) |
| 49 | } |
| 50 | |
| 51 | func (f AuditForwarder) RecordCompletionReport(a CompletionReportAudit) { |
| 52 | RecordCompletionReport(f.Inner, a) |
| 53 | } |
| 54 | |
| 55 | func (f AuditForwarder) RecordMemoryRecall(a MemoryRecallAudit) { |
| 56 | RecordMemoryRecall(f.Inner, a) |
| 57 | } |
| 58 | |
| 59 | func (f AuditForwarder) RecordDelegationAdmission(a DelegationAdmissionAudit) { |
| 60 | RecordDelegationAdmission(f.Inner, a) |
| 61 | } |
| 62 | |
| 63 | func (f AuditForwarder) RecordOutcomeProgress(s evidence.OutcomeSample) { |
| 64 | RecordOutcomeProgress(f.Inner, s) |
| 65 | } |
| 66 | |
| 67 | func (f AuditForwarder) RecordProtocolRecovery(a ProtocolRecoveryAudit) { |
| 68 | RecordProtocolRecovery(f.Inner, a) |
| 69 | } |
| 70 | |
| 71 | func (f AuditForwarder) RecordDelegationAudit(a evidence.DelegationAudit) { |
| 72 | RecordDelegationAudit(f.Inner, a) |
| 73 | } |
| 74 | |
| 75 | func (f AuditForwarder) RecordWorkspaceMutation(m WorkspaceMutation) { |
| 76 | RecordWorkspaceMutation(f.Inner, m) |
| 77 | } |
| 78 | |
| 79 | func (f AuditForwarder) RecordRunBudget(s RunBudgetSample) { |
| 80 | RecordRunBudget(f.Inner, s) |
| 81 | } |
| 82 | |
| 83 | func (f AuditForwarder) RecordSubagentLifecycle(info SubagentLifecycleInfo) { |
| 84 | RecordSubagentLifecycle(f.Inner, info) |
| 85 | } |
| 86 | |
| 87 | // DelegationAuditSink receives one receipt per completed sub-agent run. |
| 88 | type DelegationAuditSink interface { |
| 89 | RecordDelegationAudit(a evidence.DelegationAudit) |
| 90 | } |
| 91 | |
| 92 | // RecordDelegationAudit forwards a delegation receipt to sinks that opt in. |
| 93 | func RecordDelegationAudit(s Sink, a evidence.DelegationAudit) { |
| 94 | if nilutil.IsNil(s) { |
| 95 | return |
| 96 | } |
| 97 | if ds, ok := s.(DelegationAuditSink); ok { |
| 98 | ds.RecordDelegationAudit(a) |
| 99 | } |
| 100 | } |
| 101 |