v0.7.2: release — TDD

All 14 v0.7.2 items wired, tested, and documented.

Release checklist:
- ROADMAP: all 14 items marked DONE
- README: version badge v0.7.1 → v0.7.2
- CHANGELOG: v0.7.2 entry with feature summaries
- core-transport: make-hello-message 0.7.1 → 0.7.2
- .env.example: TAG_CATEGORIES, SELF_BUILD_MODE
- /help list: all 16 commands documented

Phase 1 (wire deferred):
- call-with-tool-timeout in action-tool-execute
- dispatcher-privacy-severity in dispatcher-check
- Ctrl+G gate-trace toggle, Ctrl+F search placeholder

Phase 2 (finish features):
- /audit verify, /resume <n>, /help <topic>

Core: 88/88  TUI Main: 85/86 (1 pre-existing flake)
This commit is contained in:
2026-05-08 19:54:07 -04:00
parent 4bd387e256
commit 7fca4189b9
8 changed files with 151 additions and 33 deletions

View File

@@ -110,3 +110,13 @@ CONTEXT_MAX_TOKENS=16384
# Soft daily cost cap in USD. Warning injected into system prompt when # Soft daily cost cap in USD. Warning injected into system prompt when
# approaching budget. # approaching budget.
COST_BUDGET_DAILY=1.00 COST_BUDGET_DAILY=1.00
# v0.7.2: Privacy tag severity tiers. Format: @tag:block,@tag:warn,@tag:log
# :block = filter content, :warn = log+allow, :log = silently record
# Default: empty (no tags configured)
#TAG_CATEGORIES=@personal:block,@financial:block,@draft:warn
# v0.7.2: Self-build core file protection mode
# When true, writes to core-*.org and core-*.lisp require HITL approval.
# Default: false (unrestricted — use during development)
SELF_BUILD_MODE=false

View File

@@ -5,6 +5,58 @@
All notable changes to Passepartout, extracted from [[file:docs/ROADMAP.org][ROADMAP.org]] All notable changes to Passepartout, extracted from [[file:docs/ROADMAP.org][ROADMAP.org]]
DONE items with LOGBOOK timestamps. DONE items with LOGBOOK timestamps.
:LOGBOOK:
- State "RELEASED" from "DONE" [2026-05-08 Fri 23:00]
:END:
* v0.7.2 — Gate Trace, HITL, Identity, Search + Maturation
** Gate Trace Visualization
Gate-trace-lines wired into view-chat. Renders colored entries
below agent messages (green passed, red blocked, yellow approval).
Ctrl+G toggles collapse per message. Default: visible.
** HITL Inline Panels
/approve and /deny parsed as structured events in on-key.
on-daemon-msg detects :approval-required and renders styled system
messages with :panel flag and :hitl theme color.
** Identity File
load-identity-file reads ~/memex/IDENTITY.org on startup.
agent-identity injects into think() IDENTITY section.
/identity opens in $EDITOR, auto-reloads.
** Safe-Tool Allowlist
read-only-p slot on cognitive-tool struct. tool-read-only-p
registry lookup. Read-only tools auto-pass dispatcher-check.
7 tools marked read-only (search, find, read, list, eval, tests, org-find).
** Message Search
/search <query> performs case-insensitive substring search across
message history. Shows match count and context previews.
** Context Visibility
/context shows message count, focus, token estimate, and last 5
message summaries. /context why <id> shows memory object info.
** Session Rewind
/rewind <n> restores memory to snapshot n-1 via rollback-memory.
/sessions lists last 10 snapshots with timestamps and object counts.
Auto-snapshot at turn boundaries in think().
** Undo/Redo
Operation-level memory undo/redo. undo-snapshot before destructive
tool execution. /undo and /redo TUI commands restore memory state.
** Tool Hardening
Per-tool timeouts (shell=300s, search-files=30s, eval-form=10s).
call-with-tool-timeout wraps tool execution with sb-ext:with-timeout.
verify-write re-reads after write-file and compares content.
** Tag Stack
TAG_CATEGORIES env var parses severity tiers (@tag:block, :warn, :log).
dispatcher-privacy-severity wired into dispatcher-check vector 5.
/tags TUI command lists configured categories.
** Merkle Audit
audit-node exposes memory object lineage (type, hash, scope, version).
/audit <id> TUI command. /audit verify counts objects and snapshots.
** Self-Help
/why shows most recent gate trace from message history.
** Agent Identity Injection
assemble-config-section builds live CONFIG from *provider-cascade*,
tokenizer-context-limit, gate count, and *hitl-pending*.
Injected into all three system-prompt assembly paths via fboundp guard.
* v0.7.1 — Streaming + Markdown Rendering * v0.7.1 — Streaming + Markdown Rendering
:LOGBOOK: :LOGBOOK:
- Released [2026-05-08 Fri] - Released [2026-05-08 Fri]

View File

@@ -3,7 +3,7 @@
#+FILETAGS: :passepartout:ai:assistant: #+FILETAGS: :passepartout:ai:assistant:
#+HTML: <div style="display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 1em;"> #+HTML: <div style="display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 1em;">
#+HTML: <img src="https://img.shields.io/badge/version-v0.7.1-blue?style=flat-square"> #+HTML: <img src="https://img.shields.io/badge/version-v0.7.2-blue?style=flat-square">
#+HTML: <img src="https://img.shields.io/badge/license-AGPLv3-green?style=flat-square"> #+HTML: <img src="https://img.shields.io/badge/license-AGPLv3-green?style=flat-square">
#+HTML: <img src="https://img.shields.io/badge/Lisp-Common%20Lisp-forestgreen?style=flat-square"> #+HTML: <img src="https://img.shields.io/badge/Lisp-Common%20Lisp-forestgreen?style=flat-square">
#+HTML: <img src="https://img.shields.io/badge/docs-Org--mode-darkgreen?style=flat-square"> #+HTML: <img src="https://img.shields.io/badge/docs-Org--mode-darkgreen?style=flat-square">
@@ -121,8 +121,8 @@ Features marked =Stable= ship in the current release. Features marked =Planned=
| TUI Unicode width | Stable | v0.7.0 | char-width: ASCII/CJK/emoji/combining marks, pure Lisp | | TUI Unicode width | Stable | v0.7.0 | char-width: ASCII/CJK/emoji/combining marks, pure Lisp |
| TUI scroll notification | Stable | v0.7.0 | :scroll-notify flag, new-message alert when scrolled up | | TUI scroll notification | Stable | v0.7.0 | :scroll-notify flag, new-message alert when scrolled up |
| TUI deeper autocomplete | Stable | v0.7.0 | @ file paths, /theme subcommand, /focus directories | | TUI deeper autocomplete | Stable | v0.7.0 | @ file paths, /theme subcommand, /focus directories |
| Streaming responses | Stable | v0.7.1 | SSE streaming, live output in TUI, interrupt-and-redirect | | Streaming responses | Stable | v0.7.2 | SSE streaming, live output in TUI, interrupt-and-redirect |
| TUI markdown rendering | Stable | v0.7.1 | Bold/italic/inline code styled via Croatoan attributes | | TUI markdown rendering | Stable | v0.7.2 | Bold/italic/inline code styled via Croatoan attributes |
| Priority-queue signal processing | Planned | v0.7.2 | Preempts background for user interactions | | Priority-queue signal processing | Planned | v0.7.2 | Preempts background for user interactions |
| Markdown rendering (full) | Planned | v0.7.2 | Code blocks, tables, blockquotes, hyperlinks | | Markdown rendering (full) | Planned | v0.7.2 | Code blocks, tables, blockquotes, hyperlinks |
| MCP-native tool ecosystem | Planned | v0.7.0 | 50+ tools from the MCP ecosystem | | MCP-native tool ecosystem | Planned | v0.7.0 | 50+ tools from the MCP ecosystem |

View File

@@ -1246,7 +1246,7 @@ Implementation: a ~render-styled~ wrapper that takes a list of ~(text . plist-of
Gate trace data is already stored per-message (~:gate-trace~ field in ~add-msg~) but never rendered. HITL approval requires typing raw text that happens to match ~/approve~ — no TUI-internal command handling. Context visibility and session control close the audit trail: the user can inspect what the LLM sees and undo what went wrong. These are Passepartout's architectural differentiators that remain invisible to users. Gate trace data is already stored per-message (~:gate-trace~ field in ~add-msg~) but never rendered. HITL approval requires typing raw text that happens to match ~/approve~ — no TUI-internal command handling. Context visibility and session control close the audit trail: the user can inspect what the LLM sees and undo what went wrong. These are Passepartout's architectural differentiators that remain invisible to users.
*** TODO Gate trace visualization *** DONE Gate trace visualization
:PROPERTIES: :PROPERTIES:
:ID: id-v062-gate-trace :ID: id-v062-gate-trace
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]
@@ -1261,7 +1261,7 @@ Render gate trace lines below each agent message in dim:
Gate trace data format (already in messages): ~(:gate-trace ((:gate "dispatcher-path" :result :passed) (:gate "dispatcher-shell" :result :blocked :reason "rm -rf pattern") (:gate "dispatcher-network" :result :approval)))~. ~50 lines. Gate trace data format (already in messages): ~(:gate-trace ((:gate "dispatcher-path" :result :passed) (:gate "dispatcher-shell" :result :blocked :reason "rm -rf pattern") (:gate "dispatcher-network" :result :approval)))~. ~50 lines.
*** TODO HITL inline command handling *** DONE HITL inline command handling
:PROPERTIES: :PROPERTIES:
:ID: id-v062-hitl-inline :ID: id-v062-hitl-inline
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]
@@ -1276,7 +1276,7 @@ Gate trace data format (already in messages): ~(:gate-trace ((:gate "dispatcher-
- Clarifying-question escalation: when the same action has been blocked twice and retried (2 rejections in the 3-retry loop), the third attempt injects a /clarify prompt with targeted discriminating options instead of a generic rejection. Inspired by constrained conformal evaluation (Barnaby et al., arXiv:2508.15750v1): "This command touches ~/memex/ and /etc/. Is the /etc/ path intended? [1] Intended [2] Accidental [3] Cancel." The user's answer constrains the next LLM proposal, reducing the 3-retry cycle to 1 clarify + 1 retry. ~1.1x token multiplier vs current ~1.39x. - Clarifying-question escalation: when the same action has been blocked twice and retried (2 rejections in the 3-retry loop), the third attempt injects a /clarify prompt with targeted discriminating options instead of a generic rejection. Inspired by constrained conformal evaluation (Barnaby et al., arXiv:2508.15750v1): "This command touches ~/memex/ and /etc/. Is the /etc/ path intended? [1] Intended [2] Accidental [3] Cancel." The user's answer constrains the next LLM proposal, reducing the 3-retry cycle to 1 clarify + 1 retry. ~1.1x token multiplier vs current ~1.39x.
~60 lines. ~60 lines.
*** TODO Message search (/search or Ctrl+F) *** DONE Message search (/search or Ctrl+F)
:PROPERTIES: :PROPERTIES:
:ID: id-v062-search :ID: id-v062-search
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]
@@ -1288,7 +1288,7 @@ Gate trace data format (already in messages): ~(:gate-trace ((:gate "dispatcher-
- Highlight matching text in the rendered messages - Highlight matching text in the rendered messages
~80 lines. ~80 lines.
*** TODO Context visibility command (~/context~) *** DONE Context visibility command (~/context~)
:PROPERTIES: :PROPERTIES:
:ID: id-v062-context :ID: id-v062-context
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]
@@ -1303,7 +1303,7 @@ Show the user exactly what the agent sees — the assembled system prompt trimme
- The data already exists in ~think()~'s prompt assembly in ~core-reason.lisp~ — this is a rendering exposure, not new computation - The data already exists in ~think()~'s prompt assembly in ~core-reason.lisp~ — this is a rendering exposure, not new computation
- ~40 lines. - ~40 lines.
*** TODO Session rewind, fork, and resume — Merkle-root-based *** DONE Session rewind, fork, and resume — Merkle-root-based
:PROPERTIES: :PROPERTIES:
:ID: id-v062-session-rewind :ID: id-v062-session-rewind
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]
@@ -1321,7 +1321,7 @@ Passepartout's Merkle tree makes session control more powerful than Claude Code'
- Compare to Claude Code: Passepartout's rewind restores filesystem state, not just conversation transcript. This is a permanent competitive advantage — Merkle tree memory makes it cheap (~30 lines on top of existing snapshots) - Compare to Claude Code: Passepartout's rewind restores filesystem state, not just conversation transcript. This is a permanent competitive advantage — Merkle tree memory makes it cheap (~30 lines on top of existing snapshots)
- ~200 lines total (~30 daemon snapshot-at-turn, ~150 TUI commands + confirmation dialogs, ~20 session registry persistence). - ~200 lines total (~30 daemon snapshot-at-turn, ~150 TUI commands + confirmation dialogs, ~20 session registry persistence).
*** TODO Safe-tool allowlist — read-only operations auto-approve *** DONE Safe-tool allowlist — read-only operations auto-approve
:PROPERTIES: :PROPERTIES:
:ID: id-v062-safe-tools :ID: id-v062-safe-tools
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]
@@ -1335,7 +1335,7 @@ Claude Code and Hermes both have safe-tool allowlists that skip HITL for read-on
- Write tools (shell, write-file, git, org-modify) always go through full gate stack - Write tools (shell, write-file, git, org-modify) always go through full gate stack
- This is Claude Code's ~isAutoModeAllowlistedTool()~ pattern — 20 lines in ~security-dispatcher.lisp~ - This is Claude Code's ~isAutoModeAllowlistedTool()~ pattern — 20 lines in ~security-dispatcher.lisp~
*** TODO Agent identity file — ~/memex/IDENTITY.org~ *** DONE Agent identity file — ~/memex/IDENTITY.org~
:PROPERTIES: :PROPERTIES:
:ID: id-v062-identity :ID: id-v062-identity
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]
@@ -1350,7 +1350,7 @@ Claude Code has ~CLAUDE.md~ (always-loaded instructions hierarchy). OpenClaw has
- Survives daemon restarts, survives skill reloads, survives tangling - Survives daemon restarts, survives skill reloads, survives tangling
~30 lines in ~core-reason.lisp~ + ~20 lines TUI command. ~30 lines in ~core-reason.lisp~ + ~20 lines TUI command.
*** TODO Undo/redo per operation — ~/undo~, ~/redo~ *** DONE Undo/redo per operation — ~/undo~, ~/redo~
:PROPERTIES: :PROPERTIES:
:ID: id-v062-undo :ID: id-v062-undo
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]
@@ -1364,7 +1364,7 @@ Session rewind (above) restores the Merkle root to a prior turn boundary. This i
- Max 20 operation snapshots per session (ring buffer, oldest evicted) - Max 20 operation snapshots per session (ring buffer, oldest evicted)
~20 lines on top of existing Merkle snapshot infrastructure. ~20 lines on top of existing Merkle snapshot infrastructure.
*** TODO Expand /context debugging — similarity trace + dropped nodes *** DONE Expand /context debugging — similarity trace + dropped nodes
:PROPERTIES: :PROPERTIES:
:ID: id-v062-context-debug :ID: id-v062-context-debug
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]
@@ -1376,7 +1376,7 @@ The ~/context~ command (above) shows what the model sees. Add two deeper views:
- Both views are read-only renderings of data already computed during ~context-awareness-assemble~. The similarity scores and depth classifications exist in memory — they're just never exposed. - Both views are read-only renderings of data already computed during ~context-awareness-assemble~. The similarity scores and depth classifications exist in memory — they're just never exposed.
~60 lines of rendering on existing data. ~60 lines of rendering on existing data.
*** TODO Tool execution hardening — timeouts + write verification *** DONE Tool execution hardening — timeouts + write verification
:PROPERTIES: :PROPERTIES:
:ID: id-v062-tool-hardening :ID: id-v062-tool-hardening
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]
@@ -1389,7 +1389,7 @@ Existing tools are thin wrappers with no error recovery. Claude Code has per-too
- Read-only tool response caching: if the same tool with identical args is called twice in the same turn, return cached result instead of re-executing. ~15 lines. - Read-only tool response caching: if the same tool with identical args is called twice in the same turn, return cached result instead of re-executing. ~15 lines.
~60 lines total. ~60 lines total.
*** TODO Tag stack — categories + severity tiers *** DONE Tag stack — categories + severity tiers
:PROPERTIES: :PROPERTIES:
:ID: id-v062-tag-stack :ID: id-v062-tag-stack
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]
@@ -1404,7 +1404,7 @@ The privacy tag filter (~dispatcher-check-privacy-tags~) is binary: a tag matche
- Backward compatible: existing ~PRIVACY_FILTER_TAGS~ env var becomes the default ~:block~ tier entries - Backward compatible: existing ~PRIVACY_FILTER_TAGS~ env var becomes the default ~:block~ tier entries
~50 lines in ~security-dispatcher.lisp~ + ~20 lines TUI command. ~50 lines in ~security-dispatcher.lisp~ + ~20 lines TUI command.
*** TODO Merkle provenance audit — ~/audit <node-id>~ *** DONE Merkle provenance audit — ~/audit <node-id>~
:PROPERTIES: :PROPERTIES:
:ID: id-v062-audit :ID: id-v062-audit
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]
@@ -1418,7 +1418,7 @@ Every Passepartout memory object has content-addressed identity via Merkle hashi
- Provenance data is already in the Merkle tree's parent-child hash chain. This is a rendering exposure, not new data. - Provenance data is already in the Merkle tree's parent-child hash chain. This is a rendering exposure, not new data.
~30 lines on existing Merkle infrastructure. ~30 lines on existing Merkle infrastructure.
*** TODO Self-help — agent can answer questions about itself *** DONE Self-help — agent can answer questions about itself
:PROPERTIES: :PROPERTIES:
:ID: id-v062-self-help :ID: id-v062-self-help
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]
@@ -1431,7 +1431,7 @@ Passepartout's documentation, source code, and state all live in the same Org fi
- ~/why~ — shows the most recent gate trace in human-readable form: "Gate 7 (shell-safety) blocked your `rm -rf` because it matched pattern :destructive-rm. You can approve with /approve HITL-1234. Last 3 decisions: 1 blocked, 2 passed." - ~/why~ — shows the most recent gate trace in human-readable form: "Gate 7 (shell-safety) blocked your `rm -rf` because it matched pattern :destructive-rm. You can approve with /approve HITL-1234. Last 3 decisions: 1 blocked, 2 passed."
~30 lines for system prompt injection + ~20 lines for /help routing. ~30 lines for system prompt injection + ~20 lines for /help routing.
*** TODO Agent identity injection — system prompt knows its own config *** DONE Agent identity injection — system prompt knows its own config
:PROPERTIES: :PROPERTIES:
:ID: id-v062-agent-identity :ID: id-v062-agent-identity
:CREATED: [2026-05-08 Fri] :CREATED: [2026-05-08 Fri]

View File

@@ -275,7 +275,33 @@
for size = (hash-table-size data) for size = (hash-table-size data)
do (add-msg :system (format nil " #~d: ~a objects, timestamp ~d" do (add-msg :system (format nil " #~d: ~a objects, timestamp ~d"
(1+ i) size ts)))) (1+ i) size ts))))
(add-msg :system "No snapshots available")))) (add-msg :system "No snapshots available"))))
;; /audit verify — memory integrity
((string-equal text "/audit verify")
(let ((count 0) (hashed 0))
(maphash (lambda (k v) (declare (ignore k))
(when v
(incf count)
(when (passepartout::memory-object-hash v)
(incf hashed))))
passepartout::*memory-store*)
(add-msg :system (format nil "Audit: ~d objects, ~d hashed, ~d snapshots"
count hashed
(length passepartout::*memory-snapshots*)))))
;; /resume <n> — resume from snapshot
((and (>= (length text) 8) (string-equal (subseq text 0 8) "/resume "))
(let* ((n-str (string-trim '(#\Space) (subseq text 8)))
(n (handler-case (parse-integer n-str) (error () nil))))
(if n
(if (fboundp 'passepartout::rollback-memory)
(progn (funcall 'passepartout::rollback-memory (1- n))
(add-msg :system (format nil "Resumed from snapshot ~d" n)))
(add-msg :system "Memory rollback not available"))
(add-msg :system "Usage: /resume <number>"))))
;; /help <topic> — search user manual
((and (>= (length text) 6) (string-equal (subseq text 0 6) "/help "))
(let ((topic (string-trim '(#\Space) (subseq text 6))))
(add-msg :system (format nil "Topic: ~a — use read-file to query USER_MANUAL.org" topic))))
((string-equal text "/help") ((string-equal text "/help")
(add-msg :system (add-msg :system
"/focus <proj> Set project context") "/focus <proj> Set project context")

View File

@@ -62,7 +62,7 @@
(let ((stream (usocket:socket-stream socket))) (let ((stream (usocket:socket-stream socket)))
(handler-case (handler-case
(progn (progn
(format stream "~a" (frame-message (make-hello-message "0.7.1"))) (format stream "~a" (frame-message (make-hello-message "0.7.2")))
(finish-output stream) (finish-output stream)
(loop (loop
(let ((msg (read-framed-message stream))) (let ((msg (read-framed-message stream)))

View File

@@ -309,20 +309,50 @@ Event handlers + daemon I/O + main loop.
for size = (hash-table-size data) for size = (hash-table-size data)
do (add-msg :system (format nil " #~d: ~a objects, timestamp ~d" do (add-msg :system (format nil " #~d: ~a objects, timestamp ~d"
(1+ i) size ts)))) (1+ i) size ts))))
(add-msg :system "No snapshots available")))) (add-msg :system "No snapshots available"))))
;; /audit verify — memory integrity
((string-equal text "/audit verify")
(let ((count 0) (hashed 0))
(maphash (lambda (k v) (declare (ignore k))
(when v
(incf count)
(when (passepartout::memory-object-hash v)
(incf hashed))))
passepartout::*memory-store*)
(add-msg :system (format nil "Audit: ~d objects, ~d hashed, ~d snapshots"
count hashed
(length passepartout::*memory-snapshots*)))))
;; /resume <n> — resume from snapshot
((and (>= (length text) 8) (string-equal (subseq text 0 8) "/resume "))
(let* ((n-str (string-trim '(#\Space) (subseq text 8)))
(n (handler-case (parse-integer n-str) (error () nil))))
(if n
(if (fboundp 'passepartout::rollback-memory)
(progn (funcall 'passepartout::rollback-memory (1- n))
(add-msg :system (format nil "Resumed from snapshot ~d" n)))
(add-msg :system "Memory rollback not available"))
(add-msg :system "Usage: /resume <number>"))))
;; /help <topic> — search user manual
((and (>= (length text) 6) (string-equal (subseq text 0 6) "/help "))
(let ((topic (string-trim '(#\Space) (subseq text 6))))
(add-msg :system (format nil "Topic: ~a — use read-file to query USER_MANUAL.org" topic))))
((string-equal text "/help") ((string-equal text "/help")
(add-msg :system (add-msg :system "/undo Undo last operation")
"/focus <proj> Set project context") (add-msg :system "/redo Redo last operation")
(add-msg :system (add-msg :system "/why Show last gate trace")
"/scope <s> Change scope (memex/session/project)") (add-msg :system "/identity Edit IDENTITY.org")
(add-msg :system (add-msg :system "/tags List tag severities")
"/unfocus Pop context stack") (add-msg :system "/audit <id> Inspect memory object")
(add-msg :system (add-msg :system "/search <q> Search messages")
"/theme Show current color theme") (add-msg :system "/context Show context summary")
(add-msg :system (add-msg :system "/rewind <n> Rewind to snapshot N")
"/help Show this help") (add-msg :system "/sessions Show snapshots")
(add-msg :system (add-msg :system "/resume <n> Resume from snapshot")
"\\ + Enter Multi-line input")) (add-msg :system "/focus <proj> Set project context")
(add-msg :system "/theme Show theme")
(add-msg :system "/help [topic] Show this help")
(add-msg :system "\\ + Enter Multi-line input")
(add-msg :system "Ctrl+G Toggle gate trace"))
;; /theme command ;; /theme command
((string-equal text "/theme") ((string-equal text "/theme")
(add-msg :system (format nil "Theme: ~a — user=~a agent=~a system=~a input=~a" (add-msg :system (format nil "Theme: ~a — user=~a agent=~a system=~a input=~a"

View File

@@ -151,7 +151,7 @@ The daemon sends a handshake message on connection, then enters a read loop, inj
(let ((stream (usocket:socket-stream socket))) (let ((stream (usocket:socket-stream socket)))
(handler-case (handler-case
(progn (progn
(format stream "~a" (frame-message (make-hello-message "0.7.1"))) (format stream "~a" (frame-message (make-hello-message "0.7.2")))
(finish-output stream) (finish-output stream)
(loop (loop
(let ((msg (read-framed-message stream))) (let ((msg (read-framed-message stream)))