gomcp/internal/application/tools/synapse_service.go

84 lines
2.4 KiB
Go

package tools
import (
"context"
"fmt"
"github.com/syntrex-lab/gomcp/internal/domain/synapse"
)
// SynapseService implements MCP tool logic for synapse operations.
type SynapseService struct {
store synapse.SynapseStore
recorder DecisionRecorder // v3.7: tamper-evident trace
}
// NewSynapseService creates a new SynapseService.
func NewSynapseService(store synapse.SynapseStore) *SynapseService {
return &SynapseService{store: store}
}
// SuggestSynapsesResult contains a pending synapse for architect review.
type SuggestSynapsesResult struct {
ID int64 `json:"id"`
FactIDA string `json:"fact_id_a"`
FactIDB string `json:"fact_id_b"`
Confidence float64 `json:"confidence"`
}
// SuggestSynapses returns pending synapses for architect approval.
func (s *SynapseService) SuggestSynapses(ctx context.Context, limit int) ([]SuggestSynapsesResult, error) {
if limit <= 0 {
limit = 20
}
pending, err := s.store.ListPending(ctx, limit)
if err != nil {
return nil, fmt.Errorf("list pending: %w", err)
}
results := make([]SuggestSynapsesResult, len(pending))
for i, syn := range pending {
results[i] = SuggestSynapsesResult{
ID: syn.ID,
FactIDA: syn.FactIDA,
FactIDB: syn.FactIDB,
Confidence: syn.Confidence,
}
}
return results, nil
}
// AcceptSynapse transitions a synapse from PENDING to VERIFIED.
// Only VERIFIED synapses influence context ranking.
func (s *SynapseService) AcceptSynapse(ctx context.Context, id int64) error {
err := s.store.Accept(ctx, id)
if err == nil && s.recorder != nil {
s.recorder.RecordDecision("SYNAPSE", "ACCEPT_SYNAPSE", fmt.Sprintf("synapse_id=%d", id))
}
return err
}
// RejectSynapse transitions a synapse from PENDING to REJECTED.
func (s *SynapseService) RejectSynapse(ctx context.Context, id int64) error {
err := s.store.Reject(ctx, id)
if err == nil && s.recorder != nil {
s.recorder.RecordDecision("SYNAPSE", "REJECT_SYNAPSE", fmt.Sprintf("synapse_id=%d", id))
}
return err
}
// SynapseStats returns counts by status.
type SynapseStats struct {
Pending int `json:"pending"`
Verified int `json:"verified"`
Rejected int `json:"rejected"`
}
// GetStats returns synapse counts.
func (s *SynapseService) GetStats(ctx context.Context) (*SynapseStats, error) {
p, v, r, err := s.store.Count(ctx)
if err != nil {
return nil, err
}
return &SynapseStats{Pending: p, Verified: v, Rejected: r}, nil
}