;
; test-selflearn.scm - Test vagueness-driven self-learning loop
;
; Tests the 7 layers of emergent capability:
; Layer 1: Counting - words and pairs exist
; Layer 2: Association - PMI computed between words
; Layer 3: Structure - "X contains Y" discovered from PMI
; Layer 4: Response - answers questions from associations
; Layer 5: Self-awareness - knows its own capabilities
; Layer 6: Tool reasoning - PMI-reasons about search plans
; Layer 7: Autonomous action - executes tools, acquires knowledge
;
; Key metric: bootstrap cost = manual observations needed per layer
;
(use-modules (opencog))
(use-modules (ice-9 rdelim))
(use-modules (ice-9 format))
(primitive-load "atomspace-learner.scm")
;; Load knowledge files (tracks as manual observations)
(define (load-knowledge filename)
(display (format #f "Loading ~a...\n" filename))
(let ((port (open-input-file filename))
(count 0))
(let loop ((line (read-line port)))
(if (eof-object? line)
(begin (close-port port)
(display (format #f " Processed ~a lines\n" count)))
(begin
(let ((trimmed (string-trim-both line)))
(unless (or (string-null? trimmed)
(string-prefix? "#" trimmed))
(process-text-manual! trimmed)
(set! count (+ count 1))))
(loop (read-line port)))))))
;; ═══════════════════════════════════════════════════════════════════
;; LAYER TESTS - Each layer builds on the previous
;; ═══════════════════════════════════════════════════════════════════
(define (test-layer-1)
"Layer 1: Counting - do we have units and pairs?"
(let ((words (length (get-all-words)))
(pairs (length (cog-get-atoms 'EdgeLink #t))))
(display (format #f " Words: ~a Pairs: ~a\n" words pairs))
(display (format #f " Bootstrap cost: ~a manual observations\n" *manual-observations*))
(and (> words 0) (> pairs 0))))
(define (test-layer-2)
"Layer 2: Association - can we compute meaningful PMI?"
(let* ((test-words '("keypair" "anproto" "grep" "atomspace"))
(results (filter-map
(lambda (w)
(let ((assocs (get-associations w 3)))
(and (not (null? assocs))
(cons w (map cdr assocs)))))
test-words)))
(for-each
(lambda (r)
(display (format #f " ~a → ~a\n" (car r) (string-join (cdr r) ", "))))
results)
(display (format #f " Bootstrap cost: ~a manual observations\n" *manual-observations*))
(not (null? results))))
(define (test-layer-3)
"Layer 3: Structure - did we discover 'X contains Y' relations?"
(let ((evals (length (cog-get-atoms 'EvaluationLink #t))))
(display (format #f " EvaluationLinks: ~a\n" evals))
;; Show some discovered structures
(for-each
(lambda (w)
(let ((contains (safe-string-list (query-contains w))))
(when (not (null? contains))
(display (format #f " ~a contains: ~a\n" w (string-join contains ", "))))))
'("atomspace" "keypair" "anproto" "message" "signature"))
(display (format #f " Bootstrap cost: ~a manual observations\n" *manual-observations*))
(> evals 0)))
(define (test-layer-4)
"Layer 4: Response - can we answer questions from knowledge?"
(let ((questions '("what is keypair" "what is anproto" "what is atomspace"))
(pass #t))
(for-each
(lambda (q)
(let ((answer (respond q)))
(display (format #f " Q: ~a\n A: ~a\n" q answer))
(when (string-prefix? "I don't know" answer)
(set! pass #f))))
questions)
(display (format #f " Bootstrap cost: ~a manual observations\n" *manual-observations*))
pass))
(define (test-layer-5)
"Layer 5: Self-awareness - does it know about its own capabilities?"
(let ((self-questions '("what is grep" "what is atomspace" "what is wirecore"))
(pass #t))
(for-each
(lambda (q)
(let ((answer (respond q)))
(display (format #f " Q: ~a\n A: ~a\n" q answer))
(when (string-prefix? "I don't know" answer)
(set! pass #f))))
self-questions)
(display (format #f " Bootstrap cost: ~a manual observations\n" *manual-observations*))
pass))
(define (test-layer-6)
"Layer 6: Tool reasoning - can PMI form search plans?"
(let ((test-words '("keypair" "signature" "signing" "verify"))
(plans-formed 0))
(for-each
(lambda (w)
(display (format #f " Reasoning about '~a':\n" w))
(let ((plan (reason-search-plan w)))
(if plan
(begin
(display (format #f " Plan: ~a\n" (assoc-ref plan 'reasoning)))
(set! plans-formed (+ plans-formed 1)))
(display " BLOCKED - cannot form plan\n"))))
test-words)
(display (format #f " Plans formed: ~a/~a\n" plans-formed (length test-words)))
(display (format #f " Bootstrap cost: ~a manual observations\n" *manual-observations*))
(> plans-formed 0)))
(define (test-layer-7 max-iters)
"Layer 7: Autonomous action - self-learning loop with PMI-directed search"
(let ((before-auto *auto-observations*))
(learning-loop! max-iters 0.005)
(let ((acquired (- *auto-observations* before-auto)))
(display (format #f "\n Self-acquired: ~a observations\n" acquired))
(display (format #f " Bootstrap cost: ~a manual, ~a auto\n"
*manual-observations* *auto-observations*))
(display (format #f " Ratio: 1:~,1f (manual:auto)\n"
(if (> *manual-observations* 0)
(/ (* 1.0 acquired) *manual-observations*)
0)))
(> acquired 0))))
;; ═══════════════════════════════════════════════════════════════════
;; MAIN TEST
;; ═══════════════════════════════════════════════════════════════════
(define (run-selflearn-test)
(display "\n")
(display "════════════════════════════════════════════════════════════\n")
(display " SELF-LEARNING TEST: 7 Layers of Emergent Capability\n")
(display "════════════════════════════════════════════════════════════\n\n")
;; Bootstrap: Feed manual data
(display "BOOTSTRAP: Loading manual knowledge\n")
(load-knowledge "data/self-knowledge.txt")
(load-knowledge "data/anproto-knowledge.txt")
(load-knowledge "data/unix-tools.txt")
(discover-all-structures!)
(display (format #f "\n~a\n" (show-stats)))
;; Test each layer in sequence
(let ((results '()))
(define (run-layer n name test-fn . args)
(display (format #f "\n── Layer ~a: ~a ──\n" n name))
(let ((pass (apply test-fn args)))
(set! results (cons (list n name pass) results))
(display (format #f " Result: ~a\n" (if pass "PASS" "FAIL")))))
(run-layer 1 "Counting" test-layer-1)
(run-layer 2 "Association" test-layer-2)
(run-layer 3 "Structure" test-layer-3)
(run-layer 4 "Response" test-layer-4)
(run-layer 5 "Self-awareness" test-layer-5)
(run-layer 6 "Tool reasoning" test-layer-6)
(run-layer 7 "Autonomous action" test-layer-7 5)
;; Post-learning questions
(display "\n── Post-learning call/response ──\n\n")
(for-each
(lambda (q)
(display (format #f "Q: ~a\n" q))
(display (format #f "A: ~a\n\n" (respond q))))
'("what is keypair"
"what is signature"
"what is signing"
"how do you create keypair"
"what is verification"))
;; Summary
(display "\n════════════════════════════════════════════════════════════\n")
(display " LAYER TEST SUMMARY\n")
(display "════════════════════════════════════════════════════════════\n\n")
(for-each
(lambda (r)
(display (format #f " Layer ~a (~a): ~a\n"
(car r) (cadr r)
(if (caddr r) "PASS" "FAIL"))))
(reverse results))
(display (format #f "\n Total bootstrap cost: ~a manual observations\n" *manual-observations*))
(display (format #f " Total self-acquired: ~a auto observations\n" *auto-observations*))
(display (format #f " Efficiency ratio: 1:~,1f (manual:auto)\n"
(if (> *manual-observations* 0)
(/ (* 1.0 *auto-observations*) *manual-observations*)
0)))
;; AtomSpace state
(display "\n AtomSpace:\n")
(display (format #f " ConceptNodes: ~a\n" (length (cog-get-atoms 'ConceptNode #t))))
(display (format #f " EdgeLinks: ~a\n" (length (cog-get-atoms 'EdgeLink #t))))
(display (format #f " EvaluationLinks: ~a\n" (length (cog-get-atoms 'EvaluationLink #t))))
(display (format #f " Total words: ~a\n" (length (get-all-words))))
(display "\n════════════════════════════════════════════════════════════\n")
(display " END\n")
(display "════════════════════════════════════════════════════════════\n")))
(when (and (defined? 'command-line)
(> (length (command-line)) 1)
(string=? (cadr (command-line)) "test"))
(run-selflearn-test))