!===================================================================== ! 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