implement: slot modes (:stack, :replace, :single-winner)

Add :mode parameter to defslot with three behaviors:
- :stack (default) — accumulate all registrations, render in order
- :replace — each registration replaces previous entries
- :single-winner — first registration wins, rest ignored

Mode is set on first defslot call and frozen for subsequent calls
to prevent conflicting mode specifications from different plugins.

Store slot data as plist (:mode <keyword> :entries <list>) instead
of bare entries list.

Add 5 new tests covering mode-specific behavior. All 9 slot tests
pass. All 13 suites pass at 100%.
This commit is contained in:
Hermes Agent
2026-05-12 19:17:24 +00:00
parent a9670a5cd7
commit 6cd045ff59
3 changed files with 249 additions and 71 deletions

View File

@@ -24,3 +24,32 @@
(defslot :test-slot :order 1 :render-fn (lambda () "x"))
(clear-slot :test-slot)
(is-false (slot-p :test-slot)))
(def-test stack-mode-multiple-entries ()
(clear-slot :stack-test)
(defslot :stack-test :order 1 :render-fn (lambda () "first"))
(defslot :stack-test :order 2 :render-fn (lambda () "second"))
(defslot :stack-test :order 3 :render-fn (lambda () "third"))
(is (equal '("first" "second" "third") (slot-render :stack-test))))
(def-test replace-mode-last-wins ()
(clear-slot :replace-test)
(defslot :replace-test :mode :replace :order 1 :render-fn (lambda () "old"))
(defslot :replace-test :mode :replace :order 2 :render-fn (lambda () "new"))
(is (equal "new" (slot-render :replace-test))))
(def-test single-winner-mode-first-wins ()
(clear-slot :winner-test)
(defslot :winner-test :mode :single-winner :order 1
:render-fn (lambda () "alpha"))
(defslot :winner-test :mode :single-winner :order 2
:render-fn (lambda () "beta"))
(is (equal "alpha" (slot-render :winner-test))))
(def-test clear-slot-removes-mode ()
(clear-slot :mode-test)
(defslot :mode-test :mode :replace :render-fn (lambda () "only"))
(clear-slot :mode-test)
(defslot :mode-test :mode :stack :render-fn (lambda () "fresh"))
(is-true (slot-p :mode-test))
(is (equal '("fresh") (slot-render :mode-test))))