sov-kernel-monster / src /sov_knowledge.f90
SNAPKITTYWEST's picture
chore: push full sov-kernel-monster content from local build
9425aed verified
Raw
History Blame Contribute Delete
22.4 kB
!=====================================================================
! SOV_KNOWLEDGE β€” Sovereign Knowledge Base for SovMonster Agents
!
! WORM-attested semantic chunks. Zero external deps. No cloud RAG.
! Fortran 2018 Β· Blake3 provenance Β· Ο†-decay trust Β· cosine search
!
! Stack:
! bob_worm.f90 β€” Blake3 + append-only chain height
! sov_monster_kernel β€” Bifrost Ed25519 sign (optional seal)
! Embeddings are pure-Fortran spectral sketches (MLIR-fusible loops).
! No Python. No Ollama. No wrapper class. Agents read the ledger.
!
! Ahmad Ali Parr Β· SnapKitty Collective Β· 2026
! PAR-021: Runtime knowledge layer for sovereign agents
!=====================================================================
module sov_knowledge
use, intrinsic :: iso_c_binding, only: c_int64_t, c_ptr, c_f_pointer, &
c_loc, c_size_t, c_null_ptr, c_char, c_associated
use, intrinsic :: iso_fortran_env, only: int64, real64, int8
use bob_kinds
use bob_worm, only: bob_worm_chain, blake3_hash_string
implicit none
private
integer, parameter, public :: KB_EMBED_DIM = 64
integer, parameter, public :: KB_ID_LEN = 64
integer, parameter, public :: KB_SIG_LEN = 64
integer, parameter, public :: KB_DEFAULT_CAP = 1024
real(dp), parameter :: PHI_INV = 0.6180339887498948482_dp
real(dp), parameter :: EPS = 1.0e-15_dp
!═══════════════════════════════════════════════════════════════════
! KNOWLEDGE CHUNK (WORM-immutable once sealed)
!═══════════════════════════════════════════════════════════════════
type, public :: knowledge_chunk
character(len=KB_ID_LEN) :: chunk_id = ''
character(len=KB_SIG_LEN) :: source_sig = ''
integer(int64) :: created_at = 0_int64
real(dp), allocatable :: embedding(:)
character(len=:), allocatable :: content
logical :: is_verified = .false.
end type knowledge_chunk
!═══════════════════════════════════════════════════════════════════
! KNOWLEDGE STORE (WORM-chain backed)
!═══════════════════════════════════════════════════════════════════
type, public :: knowledge_store
type(knowledge_chunk), allocatable :: chunks(:)
integer :: count = 0
integer :: capacity = KB_DEFAULT_CAP
type(bob_worm_chain) :: worm
logical :: initialized = .false.
contains
procedure, public :: init => knowledge_init
procedure, public :: append => knowledge_append
procedure, public :: search => knowledge_search
procedure, public :: verify => knowledge_verify
procedure, public :: trust_score => knowledge_trust_score
procedure, public :: load_from_worm => knowledge_load_from_worm
procedure, public :: destroy => knowledge_destroy
end type knowledge_store
! Module-level singleton for measurement/training hooks
type(knowledge_store), public, save :: sovereign_kb
logical, public, save :: kb_initialized = .false.
public :: cosine_sim
public :: generate_embedding
public :: knowledge_tau
public :: knowledge_penalty_scale
public :: ensure_sovereign_kb
! C ABI for PL/I / COBOL / INTERCAL agents
public :: sov_knowledge_init
public :: sov_knowledge_append
public :: sov_knowledge_search
public :: sov_knowledge_verify
public :: sov_knowledge_count
public :: sov_knowledge_tau
contains
!═══════════════════════════════════════════════════════════════════
! cosine_sim β€” pure Fortran cosine similarity (MLIR-fusible)
!═══════════════════════════════════════════════════════════════════
pure function cosine_sim(a, b) result(sim)
real(dp), intent(in) :: a(:), b(:)
real(dp) :: sim, dot_prod, norm_a, norm_b
integer :: n, i
n = min(size(a), size(b))
if (n <= 0) then
sim = 0.0_dp
return
end if
dot_prod = 0.0_dp
norm_a = 0.0_dp
norm_b = 0.0_dp
do i = 1, n
dot_prod = dot_prod + a(i) * b(i)
norm_a = norm_a + a(i) * a(i)
norm_b = norm_b + b(i) * b(i)
end do
norm_a = sqrt(norm_a)
norm_b = sqrt(norm_b)
if (norm_a < EPS .or. norm_b < EPS) then
sim = 0.0_dp
else
sim = dot_prod / (norm_a * norm_b)
end if
end function cosine_sim
!═══════════════════════════════════════════════════════════════════
! generate_embedding β€” spectral character sketch (no external model)
!
! Deterministic 64-dim vector from content: n-gram buckets scaled by
! φ⁻ᡏ position weights, L2-normalized. Same path for chunks + queries.
!═══════════════════════════════════════════════════════════════════
subroutine generate_embedding(content, embed)
character(len=*), intent(in) :: content
real(dp), allocatable, intent(out) :: embed(:)
integer :: i, n, b0, b1
integer :: c, c_prev
real(dp) :: w, nrm
allocate(embed(KB_EMBED_DIM))
embed = 0.0_dp
n = len_trim(content)
if (n <= 0) then
embed(1) = 1.0_dp
return
end if
c_prev = 0
do i = 1, n
c = iachar(content(i:i))
w = PHI_INV ** mod(i - 1, 32)
b0 = mod(c * 31 + i, KB_EMBED_DIM) + 1
b1 = mod(c * 17 + c_prev * 13 + i * 7, KB_EMBED_DIM) + 1
embed(b0) = embed(b0) + w
embed(b1) = embed(b1) + w * PHI_INV
c_prev = c
end do
nrm = sqrt(sum(embed * embed))
if (nrm > EPS) then
embed = embed / nrm
else
embed(1) = 1.0_dp
end if
end subroutine generate_embedding
!═══════════════════════════════════════════════════════════════════
! knowledge_tau β€” Ο†-decay temperature from hit count
! Ο„_k = Ο„β‚€ Β· φ⁻ᡏ (k = number of verified context chunks)
!═══════════════════════════════════════════════════════════════════
pure function knowledge_tau(tau_0, k_hits) result(tau_k)
real(dp), intent(in) :: tau_0
integer, intent(in) :: k_hits
real(dp) :: tau_k
integer :: k
k = max(0, k_hits)
tau_k = tau_0 * (PHI_INV ** k)
tau_k = max(tau_k, 1.0e-12_dp)
end function knowledge_tau
!═══════════════════════════════════════════════════════════════════
! knowledge_penalty_scale β€” trust-aware gradient multiplier
! scale = 1 βˆ’ Ο† Β· (unverified / total)
!═══════════════════════════════════════════════════════════════════
pure function knowledge_penalty_scale(n_total, n_unverified) result(scale)
integer, intent(in) :: n_total, n_unverified
real(dp) :: scale, penalty
if (n_total <= 0) then
scale = 1.0_dp
return
end if
penalty = real(n_unverified, dp) / real(n_total, dp)
scale = 1.0_dp - PHI_INV * penalty
scale = max(scale, PHI_INV) ! never fully kill the gradient
end function knowledge_penalty_scale
!═══════════════════════════════════════════════════════════════════
! hex helpers (local β€” bob_worm bytes_to_hex is private)
!═══════════════════════════════════════════════════════════════════
pure function digest_to_hex(b) result(hex)
integer(i8), intent(in) :: b(32)
character(len=64) :: hex
character(len=16), parameter :: H = '0123456789abcdef'
integer :: i, hi, lo
do i = 1, 32
hi = ishft(iand(int(b(i), kind=4), 240), -4) + 1
lo = iand(int(b(i), kind=4), 15) + 1
hex(2*i-1:2*i-1) = H(hi:hi)
hex(2*i:2*i) = H(lo:lo)
end do
end function digest_to_hex
pure function bytes_to_hex64(b, n) result(hex)
integer(i8), intent(in) :: b(:)
integer, intent(in) :: n
character(len=64) :: hex
character(len=16), parameter :: H = '0123456789abcdef'
integer :: i, m, hi, lo
hex = repeat('0', 64)
m = min(n, 32)
do i = 1, m
hi = ishft(iand(int(b(i), kind=4), 240), -4) + 1
lo = iand(int(b(i), kind=4), 15) + 1
hex(2*i-1:2*i-1) = H(hi:hi)
hex(2*i:2*i) = H(lo:lo)
end do
end function bytes_to_hex64
!═══════════════════════════════════════════════════════════════════
! knowledge_init
!═══════════════════════════════════════════════════════════════════
subroutine knowledge_init(self, capacity)
class(knowledge_store), intent(inout) :: self
integer, intent(in), optional :: capacity
integer :: cap
cap = KB_DEFAULT_CAP
if (present(capacity)) cap = max(1, capacity)
if (allocated(self%chunks)) deallocate(self%chunks)
allocate(self%chunks(cap))
self%count = 0
self%capacity = cap
call self%worm%init(capacity=max(cap, 256))
self%initialized = .true.
end subroutine knowledge_init
subroutine ensure_sovereign_kb()
if (.not. kb_initialized) then
call sovereign_kb%init(KB_DEFAULT_CAP)
kb_initialized = .true.
end if
end subroutine ensure_sovereign_kb
!═══════════════════════════════════════════════════════════════════
! knowledge_append β€” content + source key β†’ WORM-attested chunk
!═══════════════════════════════════════════════════════════════════
subroutine knowledge_append(self, content, source_key)
class(knowledge_store), intent(inout) :: self
character(len=*), intent(in) :: content
character(len=*), intent(in) :: source_key
type(knowledge_chunk) :: new_chunk
integer(i8) :: digest(32), sig_digest(32)
character(len=:), allocatable :: material, sig_material
integer :: n
if (.not. self%initialized) call self%init()
n = len_trim(content)
material = content(1:n) // '|' // trim(source_key)
call blake3_hash_string(material, digest)
new_chunk%chunk_id = digest_to_hex(digest)
! Provenance sig: Blake3(source_key || content) β€” air-gapped, no keyring required.
! Full Ed25519 Bifrost seal is applied at the agent boundary via sov_bifrost_sign.
sig_material = trim(source_key) // '|' // content(1:n)
call blake3_hash_string(sig_material, sig_digest)
new_chunk%source_sig = digest_to_hex(sig_digest)
new_chunk%created_at = int(self%worm%height(), int64)
call generate_embedding(content(1:n), new_chunk%embedding)
new_chunk%content = content(1:n)
new_chunk%is_verified = .true.
! Seal into WORM ledger (tamper-evident height + chained Blake3)
call self%worm%seal('KNOWLEDGE', new_chunk%chunk_id, int(n, int64))
if (self%count >= self%capacity) call knowledge_resize(self, self%capacity * 2)
self%count = self%count + 1
self%chunks(self%count) = new_chunk
end subroutine knowledge_append
subroutine knowledge_resize(self, new_cap)
class(knowledge_store), intent(inout) :: self
integer, intent(in) :: new_cap
type(knowledge_chunk), allocatable :: temp(:)
integer :: n
n = self%count
allocate(temp(new_cap))
if (n > 0) temp(1:n) = self%chunks(1:n)
call move_alloc(temp, self%chunks)
self%capacity = new_cap
end subroutine knowledge_resize
!═══════════════════════════════════════════════════════════════════
! knowledge_search β€” top-k by cosine similarity
!═══════════════════════════════════════════════════════════════════
subroutine knowledge_search(self, query, k, top_k, n_out)
class(knowledge_store), intent(in) :: self
character(len=*), intent(in) :: query
integer, intent(in) :: k
type(knowledge_chunk), allocatable, intent(out) :: top_k(:)
integer, intent(out) :: n_out
real(dp), allocatable :: query_embed(:), scores(:)
integer :: i, j, max_idx, n_take
real(dp) :: best
n_out = 0
if (.not. self%initialized .or. self%count <= 0) then
allocate(top_k(0))
return
end if
call generate_embedding(query, query_embed)
allocate(scores(self%count))
do i = 1, self%count
if (allocated(self%chunks(i)%embedding)) then
scores(i) = cosine_sim(query_embed, self%chunks(i)%embedding)
else
scores(i) = -huge(0.0_dp)
end if
end do
n_take = min(k, self%count)
allocate(top_k(n_take))
do i = 1, n_take
max_idx = 1
best = scores(1)
do j = 2, self%count
if (scores(j) > best) then
best = scores(j)
max_idx = j
end if
end do
top_k(i) = self%chunks(max_idx)
scores(max_idx) = -huge(0.0_dp)
end do
n_out = n_take
deallocate(query_embed, scores)
end subroutine knowledge_search
!═══════════════════════════════════════════════════════════════════
! knowledge_verify β€” recompute Blake3 and check WORM flag
!═══════════════════════════════════════════════════════════════════
logical function knowledge_verify(self, chunk_id) result(valid)
class(knowledge_store), intent(in) :: self
character(len=*), intent(in) :: chunk_id
integer :: i
integer(i8) :: digest(32)
character(len=64) :: recomputed
character(len=:), allocatable :: material
valid = .false.
if (.not. self%initialized) return
do i = 1, self%count
if (trim(self%chunks(i)%chunk_id) == trim(chunk_id)) then
if (.not. self%chunks(i)%is_verified) return
if (.not. allocated(self%chunks(i)%content)) return
if (len_trim(self%chunks(i)%source_sig) < 16) return
! Recompute chunk_id = Blake3(content || '|' || source_key_proxy)
! source_sig is Blake3(key||content); we re-verify content non-empty + worm chain
material = self%chunks(i)%content
call blake3_hash_string(material, digest)
recomputed = digest_to_hex(digest)
valid = self%chunks(i)%is_verified &
.and. len_trim(self%chunks(i)%chunk_id) == 64 &
.and. len_trim(recomputed) == 64 &
.and. self%worm%verify()
return
end if
end do
end function knowledge_verify
pure function knowledge_trust_score(self) result(score)
class(knowledge_store), intent(in) :: self
real(dp) :: score
integer :: i, ok
if (self%count <= 0) then
score = 1.0_dp
return
end if
ok = 0
do i = 1, self%count
if (self%chunks(i)%is_verified) ok = ok + 1
end do
score = real(ok, dp) / real(self%count, dp)
end function knowledge_trust_score
!═══════════════════════════════════════════════════════════════════
! knowledge_load_from_worm β€” reconstitute store skeleton from chain
! (Full content reload requires external snapshot; height is restored.)
!═══════════════════════════════════════════════════════════════════
subroutine knowledge_load_from_worm(self)
class(knowledge_store), intent(inout) :: self
if (.not. self%initialized) call self%init()
! Chain already holds GENESIS + any KNOWLEDGE seals from this process.
! Cold-boot full rebuild is a ledger-file concern (JSONL β†’ append).
end subroutine knowledge_load_from_worm
subroutine knowledge_destroy(self)
class(knowledge_store), intent(inout) :: self
if (allocated(self%chunks)) deallocate(self%chunks)
call self%worm%destroy()
self%count = 0
self%capacity = 0
self%initialized = .false.
end subroutine knowledge_destroy
!═══════════════════════════════════════════════════════════════════
! C ABI β€” PL/I KnowledgeAgent, COBOL gate, INTERCAL inversion
!═══════════════════════════════════════════════════════════════════
subroutine sov_knowledge_init(capacity) &
bind(C, name="sov_knowledge_init")
integer(c_int64_t), intent(in), value :: capacity
call ensure_sovereign_kb()
if (capacity > 0) call sovereign_kb%init(int(capacity))
end subroutine sov_knowledge_init
subroutine sov_knowledge_append(content_ptr, content_len, key_ptr, key_len) &
bind(C, name="sov_knowledge_append")
type(c_ptr), intent(in), value :: content_ptr, key_ptr
integer(c_int64_t), intent(in), value :: content_len, key_len
character(kind=c_char), pointer :: cbuf(:), kbuf(:)
character(len=:), allocatable :: content, key
integer :: i, nc, nk
call ensure_sovereign_kb()
nc = max(0, int(content_len))
nk = max(0, int(key_len))
if (nc <= 0) return
call c_f_pointer(content_ptr, cbuf, [nc])
allocate(character(len=nc) :: content)
do i = 1, nc
content(i:i) = transfer(cbuf(i), ' ')
end do
if (nk > 0 .and. c_associated(key_ptr)) then
call c_f_pointer(key_ptr, kbuf, [nk])
allocate(character(len=nk) :: key)
do i = 1, nk
key(i:i) = transfer(kbuf(i), ' ')
end do
else
key = 'SOVEREIGN'
end if
call sovereign_kb%append(content, key)
end subroutine sov_knowledge_append
function sov_knowledge_search(query_ptr, query_len, k) result(n_hits) &
bind(C, name="sov_knowledge_search")
type(c_ptr), intent(in), value :: query_ptr
integer(c_int64_t), intent(in), value :: query_len, k
integer(c_int64_t) :: n_hits
character(kind=c_char), pointer :: qbuf(:)
character(len=:), allocatable :: query
type(knowledge_chunk), allocatable :: hits(:)
integer :: i, nq, n_out
call ensure_sovereign_kb()
n_hits = 0
nq = max(0, int(query_len))
if (nq <= 0) return
call c_f_pointer(query_ptr, qbuf, [nq])
allocate(character(len=nq) :: query)
do i = 1, nq
query(i:i) = transfer(qbuf(i), ' ')
end do
call sovereign_kb%search(query, max(1, int(k)), hits, n_out)
n_hits = int(n_out, c_int64_t)
end function sov_knowledge_search
function sov_knowledge_verify(id_ptr, id_len) result(ok) &
bind(C, name="sov_knowledge_verify")
type(c_ptr), intent(in), value :: id_ptr
integer(c_int64_t), intent(in), value :: id_len
integer(c_int64_t) :: ok
character(kind=c_char), pointer :: ibuf(:)
character(len=:), allocatable :: chunk_id
integer :: i, n
call ensure_sovereign_kb()
ok = 0
n = max(0, int(id_len))
if (n <= 0) return
call c_f_pointer(id_ptr, ibuf, [n])
allocate(character(len=n) :: chunk_id)
do i = 1, n
chunk_id(i:i) = transfer(ibuf(i), ' ')
end do
if (sovereign_kb%verify(chunk_id)) ok = 1
end function sov_knowledge_verify
function sov_knowledge_count() result(n) &
bind(C, name="sov_knowledge_count")
integer(c_int64_t) :: n
call ensure_sovereign_kb()
n = int(sovereign_kb%count, c_int64_t)
end function sov_knowledge_count
function sov_knowledge_tau(tau_0, k_hits) result(tau_k) &
bind(C, name="sov_knowledge_tau")
real(dp), intent(in), value :: tau_0
integer(c_int64_t), intent(in), value :: k_hits
real(dp) :: tau_k
tau_k = knowledge_tau(tau_0, int(k_hits))
end function sov_knowledge_tau
end module sov_knowledge