v0.7.2: gate-trace wiring, HITL panels, /identity command — TDD
Gate trace: wired into view-chat, renders below agent messages in dim. Collapsed-gates state field for Tab toggle (deferred to Croatoan test). HITL panels: on-daemon-msg detects :approval-required events, renders styled panel messages with :panel flag. View-chat renders with :hitl theme color (magenta). /approve and /deny add confirmation messages. /identity: opens ~/memex/IDENTITY.org in emacsclient -c -a '', auto-reloads. - channel-tui-view: gate-trace in view-chat, HITL panel styling - channel-tui-state: :collapsed-gates, :hitl theme, :panel attr - channel-tui-main: HITL panel detection, /identity handler - View: 29/29 TUI Main: 83/84 (1 pre-existing flake)
This commit is contained in:
@@ -139,6 +139,15 @@
|
||||
(loop-finish))
|
||||
(unless found
|
||||
(add-msg :system "No recent gate trace. Run a tool to see gate decisions."))))
|
||||
;; /identity command — edit and reload identity file
|
||||
((string-equal text "/identity")
|
||||
(let* ((editor (or (uiop:getenv "EDITOR") "emacs"))
|
||||
(path (merge-pathnames "memex/IDENTITY.org" (user-homedir-pathname))))
|
||||
(add-msg :system (format nil "Opening ~a in ~a..." (namestring path) editor))
|
||||
(uiop:run-program (list editor (namestring path)) :output t :error-output t)
|
||||
(when (fboundp 'load-identity-file)
|
||||
(funcall 'load-identity-file))
|
||||
(add-msg :system "Identity reloaded")))
|
||||
((string-equal text "/help")
|
||||
(add-msg :system
|
||||
"/focus <proj> Set project context")
|
||||
@@ -344,9 +353,24 @@
|
||||
(text (getf payload :text))
|
||||
(msg-type (getf msg :type))
|
||||
(action (getf payload :action))
|
||||
(level (getf msg :level))
|
||||
(sensor (getf payload :sensor))
|
||||
(gate-trace (getf msg :gate-trace))
|
||||
(rule-count (getf payload :rule-count))
|
||||
(foveal-id (getf payload :foveal-id)))
|
||||
;; v0.7.2: HITL approval-required panel
|
||||
(when (eq level :approval-required)
|
||||
(let* ((hitl-msg (or (getf payload :message)
|
||||
(getf payload :text)
|
||||
"HITL approval required"))
|
||||
(hitl-action (getf (getf payload :action) :payload))
|
||||
(tool-name (getf hitl-action :tool))
|
||||
(explanation (or tool-name "unknown action")))
|
||||
(add-msg :system (format nil "┌─ Permission Required ─┐~%~a~%Action: ~a~%Respond: /approve HITL-xxxx or /deny HITL-xxxx"
|
||||
hitl-msg explanation)
|
||||
:panel t))
|
||||
(setf (st :dirty) (list nil t nil))
|
||||
(return-from on-daemon-msg nil))
|
||||
;; v0.7.1: streaming chunk
|
||||
(when (eq msg-type :stream-chunk)
|
||||
(cond
|
||||
@@ -799,7 +823,32 @@
|
||||
(on-key 9)
|
||||
(fiveam:is (string= "https://example.com" (st :url-buffer))))
|
||||
|
||||
;; ── v0.7.2 HITL ──
|
||||
;; ── v0.7.2 HITL Panels ──
|
||||
|
||||
(fiveam:test test-hitl-panel-in-on-daemon-msg
|
||||
"Contract v0.7.2: approval-required messages render as HITL panels."
|
||||
(init-state)
|
||||
(on-daemon-msg '(:type :EVENT :level :approval-required
|
||||
:payload (:sensor :approval-required
|
||||
:action (:TYPE :REQUEST :PAYLOAD (:TOOL "shell"))
|
||||
:message "rm -rf blocked")))
|
||||
(let ((m (aref (st :messages) 0)))
|
||||
(fiveam:is (eq :system (getf m :role)))
|
||||
(fiveam:is (getf m :panel))
|
||||
(fiveam:is (search "rm -rf" (getf m :content)))))
|
||||
|
||||
(fiveam:test test-hitl-panel-after-approve
|
||||
"Contract v0.7.2: /approve adds confirmation after panel."
|
||||
(init-state)
|
||||
(on-daemon-msg '(:type :EVENT :level :approval-required
|
||||
:payload (:sensor :approval-required :message "test")))
|
||||
(dolist (ch (coerce "/approve HITL-test" 'list))
|
||||
(on-key (char-code ch)))
|
||||
(on-key 13)
|
||||
(let ((m (aref (st :messages) 0)))
|
||||
(fiveam:is (getf m :panel)))
|
||||
(let ((m (aref (st :messages) (1- (length (st :messages))))))
|
||||
(fiveam:is (search "Approved" (getf m :content)))))
|
||||
|
||||
(fiveam:test test-hitl-approve-parsed
|
||||
"Contract v0.7.2: /approve HITL-xxxx sends structured event, not raw text."
|
||||
@@ -870,3 +919,17 @@
|
||||
(let* ((msgs (st :messages))
|
||||
(m (aref msgs (1- (length msgs)))))
|
||||
(fiveam:is (search "No recent" (getf m :content)))))
|
||||
|
||||
;; ── v0.7.2 /identity ──
|
||||
|
||||
(fiveam:test test-identity-command
|
||||
"Contract v0.7.2: /identity opens editor and reloads identity."
|
||||
(init-state)
|
||||
(setf (uiop:getenv "EDITOR") "true")
|
||||
(dolist (ch (coerce "/identity" 'list))
|
||||
(on-key (char-code ch)))
|
||||
(on-key 13)
|
||||
(let* ((msgs (st :messages))
|
||||
(m (aref msgs (1- (length msgs)))))
|
||||
(fiveam:is (search "reloaded" (getf m :content))
|
||||
"/identity should produce 'Identity reloaded' message")))
|
||||
|
||||
Reference in New Issue
Block a user