Files
passepartout/org/symbolic-identity.org
Amr Gharbeia bec894ca4f handoff: symbolic identity file — TDD
Agent identity loaded from ~/memex/IDENTITY.org at skill startup.
Injected into system prompt IDENTITY section between assistant name
and reflection feedback. fboundp-guarded in think().

- symbolic-identity.lisp: load-identity-file, agent-identity (skill)
- token-economics: prompt-prefix-cached +identity-content param
- core-reason: identity-content binding in think(), both code paths
- Identity: 6/6  Token-econ: 10/10 new  Core: 65/65
  TUI View: 28/28  TUI Main: 70/70  Total: 179/179
2026-05-08 15:14:44 -04:00

4.3 KiB

Symbolic Identity — Agent Self-Concept

Overview

Load `~/memex/IDENTITY.org` into the agent's self-concept at daemon startup. The identity text is injected into the system prompt's `IDENTITY` section, between assistant name and reflection feedback.

The file is user-editable and survives restarts. If the file is missing or empty, identity is silently `""` (no-op).

Contract

  1. `(load-identity-file &optional path)`: Reads IDENTITY.org from `path` (default `~/memex/IDENTITY.org`). Sets `*agent-identity*` to the file content string. Returns the content string, or NIL if file missing/unreadable.
  2. `(agent-identity)`: Returns the cached identity string (`*agent-identity*`), or `""` if identity has not been loaded.
  3. `*agent-identity*`: Special variable holding the loaded identity text (string).
(in-package :passepartout)

(defvar *agent-identity* ""
  "Identity text loaded from ~/memex/IDENTITY.org at startup.

This variable holds the contents of the user's identity file.
Loaded by `load-identity-file` at daemon/skill initialization,
called from `agent-identity` for system prompt injection.

The file is user-editable and persists across restarts.
If the file is missing or empty, this variable remains \"\".")

(defun load-identity-file (&optional (path nil path-p))
  "Load agent identity from an org file.

Reads the identity text file and caches it in
`*agent-identity*`.  If PATH is not provided, defaults to
`~/memex/IDENTITY.org`.

Returns the file content string on success, or NIL if the file
does not exist or cannot be read."
  (let* ((file-path (if path-p
                        (uiop:ensure-pathname path :ensure-absolute t)
                        (merge-pathnames "memex/IDENTITY.org"
                                         (user-homedir-pathname)))))
    (when (uiop:file-exists-p file-path)
      (handler-case
          (let ((content (uiop:read-file-string file-path)))
            (setf *agent-identity* content)
            content)
        (error () nil)))))

(defun agent-identity ()
  "Return the currently loaded agent identity string."
  (or *agent-identity* ""))

;; Auto-load identity at skill init
(load-identity-file)

Test Squad

Test Package

(defpackage :passepartout-identity-tests
  (:use :common-lisp :fiveam :passepartout)
  (:export :identity-suite))

Test Suite

(in-package :passepartout-identity-tests)

(def-suite identity-suite
    :description "Agent identity loading and caching")
(in-suite identity-suite)

(test test-load-identity-file-returns-content
  "Contract 1: load-identity-file reads an existing file, returns content."
  (let* ((path "/tmp/memex-test-identity.org")
         (content "### Personality
- Friendly
- Concise"))
    (with-open-file (f path :direction :output :if-exists :supersede)
      (write-string content f))
    (unwind-protect
         (let ((result (passepartout::load-identity-file path)))
           (is (stringp result))
           (is (search "Friendly" result))
           (is (search "Concise" result)))
      (ignore-errors (delete-file path)))))

(test test-load-identity-file-missing-nil
  "Contract 1: nil when file does not exist."
  (let ((result (passepartout::load-identity-file
                 "/tmp/memex-nonexistent-xxxx.org")))
    (is (null result))))

(test test-agent-identity-cached
  "Contract 2+3: agent-identity returns cached value after load."
  (let* ((path "/tmp/memex-test-identity2.org")
         (content "### Preferences
- Use shell cautiously"))
    (with-open-file (f path :direction :output :if-exists :supersede)
      (write-string content f))
    (unwind-protect
         (progn
           (passepartout::load-identity-file path)
           (let ((id (passepartout::agent-identity)))
             (is (search "shell cautiously" id))))
      (ignore-errors (delete-file path)))))

(test test-agent-identity-empty-default
  "Contract 2: returns empty string when nothing was loaded."
  (let ((prev passepartout::*agent-identity*))
    (unwind-protect
         (progn
           (setf passepartout::*agent-identity* nil)
           (is (string= "" (passepartout::agent-identity))))
      (setf passepartout::*agent-identity* prev))))