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:
10
.env.example
10
.env.example
@@ -110,3 +110,13 @@ CONTEXT_MAX_TOKENS=16384
|
||||
# Soft daily cost cap in USD. Warning injected into system prompt when
|
||||
# approaching budget.
|
||||
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
|
||||
|
||||
@@ -5,6 +5,58 @@
|
||||
All notable changes to Passepartout, extracted from [[file:docs/ROADMAP.org][ROADMAP.org]]
|
||||
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
|
||||
:LOGBOOK:
|
||||
- Released [2026-05-08 Fri]
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#+FILETAGS: :passepartout:ai:assistant:
|
||||
|
||||
#+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/Lisp-Common%20Lisp-forestgreen?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 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 |
|
||||
| Streaming responses | Stable | v0.7.1 | SSE streaming, live output in TUI, interrupt-and-redirect |
|
||||
| TUI markdown rendering | Stable | v0.7.1 | Bold/italic/inline code styled via Croatoan attributes |
|
||||
| Streaming responses | Stable | v0.7.2 | SSE streaming, live output in TUI, interrupt-and-redirect |
|
||||
| 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 |
|
||||
| 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 |
|
||||
|
||||
@@ -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.
|
||||
|
||||
*** TODO Gate trace visualization
|
||||
*** DONE Gate trace visualization
|
||||
:PROPERTIES:
|
||||
:ID: id-v062-gate-trace
|
||||
: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.
|
||||
|
||||
*** TODO HITL inline command handling
|
||||
*** DONE HITL inline command handling
|
||||
:PROPERTIES:
|
||||
:ID: id-v062-hitl-inline
|
||||
: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.
|
||||
~60 lines.
|
||||
|
||||
*** TODO Message search (/search or Ctrl+F)
|
||||
*** DONE Message search (/search or Ctrl+F)
|
||||
:PROPERTIES:
|
||||
:ID: id-v062-search
|
||||
: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
|
||||
~80 lines.
|
||||
|
||||
*** TODO Context visibility command (~/context~)
|
||||
*** DONE Context visibility command (~/context~)
|
||||
:PROPERTIES:
|
||||
:ID: id-v062-context
|
||||
: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
|
||||
- ~40 lines.
|
||||
|
||||
*** TODO Session rewind, fork, and resume — Merkle-root-based
|
||||
*** DONE Session rewind, fork, and resume — Merkle-root-based
|
||||
:PROPERTIES:
|
||||
:ID: id-v062-session-rewind
|
||||
: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)
|
||||
- ~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:
|
||||
:ID: id-v062-safe-tools
|
||||
: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
|
||||
- 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:
|
||||
:ID: id-v062-identity
|
||||
: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
|
||||
~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:
|
||||
:ID: id-v062-undo
|
||||
: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)
|
||||
~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:
|
||||
:ID: id-v062-context-debug
|
||||
: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.
|
||||
~60 lines of rendering on existing data.
|
||||
|
||||
*** TODO Tool execution hardening — timeouts + write verification
|
||||
*** DONE Tool execution hardening — timeouts + write verification
|
||||
:PROPERTIES:
|
||||
:ID: id-v062-tool-hardening
|
||||
: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.
|
||||
~60 lines total.
|
||||
|
||||
*** TODO Tag stack — categories + severity tiers
|
||||
*** DONE Tag stack — categories + severity tiers
|
||||
:PROPERTIES:
|
||||
:ID: id-v062-tag-stack
|
||||
: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
|
||||
~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:
|
||||
:ID: id-v062-audit
|
||||
: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.
|
||||
~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:
|
||||
:ID: id-v062-self-help
|
||||
: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."
|
||||
~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:
|
||||
:ID: id-v062-agent-identity
|
||||
:CREATED: [2026-05-08 Fri]
|
||||
|
||||
@@ -276,6 +276,32 @@
|
||||
do (add-msg :system (format nil " #~d: ~a objects, timestamp ~d"
|
||||
(1+ i) size ts))))
|
||||
(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")
|
||||
(add-msg :system
|
||||
"/focus <proj> Set project context")
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
(let ((stream (usocket:socket-stream socket)))
|
||||
(handler-case
|
||||
(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)
|
||||
(loop
|
||||
(let ((msg (read-framed-message stream)))
|
||||
|
||||
@@ -310,19 +310,49 @@ Event handlers + daemon I/O + main loop.
|
||||
do (add-msg :system (format nil " #~d: ~a objects, timestamp ~d"
|
||||
(1+ i) size ts))))
|
||||
(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")
|
||||
(add-msg :system
|
||||
"/focus <proj> Set project context")
|
||||
(add-msg :system
|
||||
"/scope <s> Change scope (memex/session/project)")
|
||||
(add-msg :system
|
||||
"/unfocus Pop context stack")
|
||||
(add-msg :system
|
||||
"/theme Show current color theme")
|
||||
(add-msg :system
|
||||
"/help Show this help")
|
||||
(add-msg :system
|
||||
"\\ + Enter Multi-line input"))
|
||||
(add-msg :system "/undo Undo last operation")
|
||||
(add-msg :system "/redo Redo last operation")
|
||||
(add-msg :system "/why Show last gate trace")
|
||||
(add-msg :system "/identity Edit IDENTITY.org")
|
||||
(add-msg :system "/tags List tag severities")
|
||||
(add-msg :system "/audit <id> Inspect memory object")
|
||||
(add-msg :system "/search <q> Search messages")
|
||||
(add-msg :system "/context Show context summary")
|
||||
(add-msg :system "/rewind <n> Rewind to snapshot N")
|
||||
(add-msg :system "/sessions Show snapshots")
|
||||
(add-msg :system "/resume <n> Resume from snapshot")
|
||||
(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
|
||||
((string-equal text "/theme")
|
||||
(add-msg :system (format nil "Theme: ~a — user=~a agent=~a system=~a input=~a"
|
||||
|
||||
@@ -151,7 +151,7 @@ The daemon sends a handshake message on connection, then enters a read loop, inj
|
||||
(let ((stream (usocket:socket-stream socket)))
|
||||
(handler-case
|
||||
(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)
|
||||
(loop
|
||||
(let ((msg (read-framed-message stream)))
|
||||
|
||||
Reference in New Issue
Block a user