(load "supervisor.lisp")
(load "evolve.lisp")
(display "── certify-policy: budget honesty by exhaustion ──") (newline)
(display (certify-policy '(one-for-one 3) (range 0 50))) (newline)
(display (certify-policy '(one-for-one 0) (range 0 50))) (newline)
(display "── crash → restart → budget exhaustion (one-for-one) ──") (newline)
(define *sibling-log* '())
(define (make-worker)
(let ((count 0))
(lambda (msg)
(if (equal? msg 'boom)
(error "worker exploded")
(set! count (+ count 1))))))
(define (make-sibling)
(lambda (msg)
(set! *sibling-log* (append *sibling-log* (list msg)))))
(supervise! (list (list 'worker make-worker)
(list 'sibling make-sibling))
'(one-for-one 2))
(send! 'worker 'tick)
(send! 'worker 'boom) (send! 'sibling 'alive-1)
(send! 'worker 'boom) (send! 'worker 'boom) (send! 'worker 'after-death) (send! 'sibling 'alive-2)
(display (run-supervised)) (newline)
(display (sup-report)) (newline)
(display (list 'receipts *sup-receipts*)) (newline)
(display (list 'sibling-saw *sibling-log*)) (newline)
(display "── restart resets state (fresh handler from init) ──") (newline)
(define (make-counting-worker)
(let ((count 0))
(lambda (msg)
(cond ((equal? msg 'boom) (error "kaboom"))
((equal? msg 'report) (send! 'sibling (list 'count count)))
(else (set! count (+ count 1)))))))
(set! *sibling-log* '())
(supervise! (list (list 'worker make-counting-worker)
(list 'sibling make-sibling))
'(one-for-one 2))
(send! 'worker 'tick)
(send! 'worker 'tick)
(send! 'worker 'boom)
(send! 'worker 'tick)
(send! 'worker 'report)
(display (run-supervised)) (newline)
(display (list 'sibling-saw *sibling-log*)) (newline)
(display "── init crash on restart → receipt + give-up, run survives ──") (newline)
(define *init-uses* 0)
(define (make-fragile)
(begin
(set! *init-uses* (+ *init-uses* 1))
(if (> *init-uses* 1) (error "init exploded") #f)
(lambda (msg) (if (equal? msg 'boom) (error "fragile crashed") #f))))
(supervise! (list (list 'fragile make-fragile)) '(one-for-one 5))
(send! 'fragile 'boom)
(send! 'fragile 'after)
(display (run-supervised)) (newline)
(display (sup-report)) (newline)
(display (list 'receipts *sup-receipts*)) (newline)
(display "── isolation honesty: refuse-by-default spawn from source ──") (newline)
(agent-reset!)
(define *my-count* 0)
(display (agent-spawn-isolated 'honest
'(lambda (msg) (set! *my-count* (+ *my-count* 1)))
'(*my-count*) '()))
(newline)
(display (agent-spawn-isolated 'trojan-a
'(lambda (msg) (set! *mailboxes* '()))
'() '()))
(newline)
(display (agent-spawn-isolated 'trojan-b
'(lambda (msg) (file-write "sup-evil-artifact.tmp" "gotcha"))
'() '()))
(newline)
(display (agent-spawn-isolated 'trojan-c
'(lambda (msg) ((car msg)))
'() '()))
(newline)
(send! 'honest 'go)
(send! 'honest 'go)
(display (run-agents)) (newline)
(display (list 'my-count *my-count*)) (newline)
(display "── proven hot reload of a live supervised agent ──") (newline)
(define (worker-math n)
(if (= n 0) 0 (+ 2 (worker-math (- n 1)))))
(define (make-math-worker)
(lambda (msg)
(cond ((equal? msg 'boom) (error "math worker crashed"))
((equal? (car msg) 'compute)
(send! 'collector (list 'result (worker-math (cadr msg))))))))
(define *collected* '())
(define (make-collector)
(lambda (msg) (set! *collected* (append *collected* (list msg)))))
(supervise! (list (list 'mathw make-math-worker)
(list 'collector make-collector))
'(one-for-one 1))
(send! 'mathw (list 'compute 3))
(display (run-supervised)) (newline)
(display (list 'before-evolve *collected*)) (newline)
(display (evolve! 'worker-math '(lambda (n) (* 2 n)) (list (range 0 21))))
(newline)
(display (evolve! 'worker-math
'(lambda (n) (begin (file-write "sup-evil-artifact.tmp" "gotcha")
(* 2 n)))
(list (range 0 21))))
(newline)
(display (list 'trojan-ran (file-exists? "sup-evil-artifact.tmp"))) (newline)
(display (evolve! 'worker-math
'(lambda (n) (if (= n 13) 999 (* 2 n)))
(list (range 0 21))))
(newline)
(send! 'mathw (list 'compute 4))
(display (run-supervised)) (newline)
(display (list 'after-evolve *collected*)) (newline)
(send! 'mathw 'boom)
(send! 'mathw (list 'compute 5))
(display (run-supervised)) (newline)
(display (list 'after-crash *collected*)) (newline)
(display (sup-report)) (newline)
(display (list 'kg-receipts (evolve-receipts 'worker-math))) (newline)
(display "── certify-strategy: restart-set semantics by exhaustion ──") (newline)
(display (certify-strategy 'one-for-one)) (newline)
(display (certify-strategy 'one-for-all)) (newline)
(display (certify-strategy 'rest-for-one)) (newline)
(define *tree-collected* '())
(define (make-tree-collector)
(lambda (msg) (set! *tree-collected* (append *tree-collected* (list msg)))))
(define (make-named-counter name)
(lambda ()
(let ((count 0))
(lambda (msg)
(cond ((equal? msg 'boom) (error "counter crashed"))
((equal? msg 'report) (send! 'collector (list name count)))
(else (set! count (+ count 1))))))))
(display "── one-for-all: a crash re-inits every sibling under that sup ──") (newline)
(set! *tree-collected* '())
(supervise-tree!
(list 'sup 'root '(one-for-one 1)
(list 'worker 'collector make-tree-collector)
(list 'sup 'pair '(one-for-all 2)
(list 'worker 'a (make-named-counter 'a))
(list 'worker 'b (make-named-counter 'b)))))
(send! 'a 'tick) (send! 'a 'tick) (send! 'b 'tick)
(send! 'a 'report) (send! 'b 'report)
(display (run-tree)) (newline)
(send! 'a 'boom) (display (run-tree)) (newline)
(send! 'a 'tick)
(send! 'a 'report) (send! 'b 'report)
(display (run-tree)) (newline)
(display (list 'collector-saw *tree-collected*)) (newline) (display (tree-report)) (newline)
(display "── rest-for-one: crash resets the crashed child and later siblings ──") (newline)
(set! *tree-collected* '())
(supervise-tree!
(list 'sup 'root '(one-for-one 1)
(list 'worker 'collector make-tree-collector)
(list 'sup 'row '(rest-for-one 2)
(list 'worker 'a (make-named-counter 'a))
(list 'worker 'b (make-named-counter 'b))
(list 'worker 'c (make-named-counter 'c)))))
(send! 'a 'tick) (send! 'b 'tick) (send! 'c 'tick)
(display (run-tree)) (newline)
(send! 'b 'boom) (display (run-tree)) (newline)
(send! 'a 'report) (send! 'b 'report) (send! 'c 'report)
(display (run-tree)) (newline)
(display (list 'collector-saw *tree-collected*)) (newline)
(display "── negative control: mailboxes survive a restart, state does not ──") (newline)
(set! *tree-collected* '())
(supervise-tree!
(list 'sup 'root '(one-for-one 1)
(list 'worker 'collector make-tree-collector)
(list 'sup 'pair '(one-for-all 2)
(list 'worker 'a (make-named-counter 'a))
(list 'worker 'b (make-named-counter 'b)))))
(send! 'b 'tick) (send! 'b 'tick)
(display (run-tree)) (newline) (send! 'b 'tick) (send! 'b 'tick) (send! 'b 'tick) (send! 'a 'boom)
(display (run-tree)) (newline) (send! 'b 'report)
(display (run-tree)) (newline)
(display (list 'collector-saw *tree-collected*)) (newline)
(display "── escalation: budget exhaustion fails the sup as a unit, parent decides ──") (newline)
(supervise-tree!
(list 'sup 'root '(one-for-one 1)
(list 'sup 'pair '(one-for-one 1)
(list 'worker 'w (make-named-counter 'w)))))
(send! 'w 'boom) (send! 'w 'boom) (send! 'w 'boom) (send! 'w 'boom)
(send! 'w 'after-death)
(display (run-tree)) (newline)
(display (tree-report)) (newline)
(display (list 'receipts *tree-receipts*)) (newline)
(display "── re-init crash during tree restart → escalates, never a dead run ──") (newline)
(define *tree-init-uses* 0)
(define (make-tree-fragile)
(begin
(set! *tree-init-uses* (+ *tree-init-uses* 1))
(if (> *tree-init-uses* 1) (error "init exploded") #f)
(lambda (msg) (if (equal? msg 'boom) (error "fragile crashed") #f))))
(supervise-tree!
(list 'sup 'root '(one-for-one 3)
(list 'sup 'pair '(one-for-one 3)
(list 'worker 'f make-tree-fragile))))
(send! 'f 'boom)
(display (run-tree)) (newline)
(display (tree-report)) (newline)
(display (list 'receipts *tree-receipts*)) (newline)