# AGENTS.md — OpenCode Tool Usage Guide This file tells AI coding agents which tools are available and when to use them. It is read by agents working on the Memex / Passepartout project. ## Development Workflow (Must Follow) All development MUST follow this cycle, beginning to end: 1. **Start in REPL** — Everything begins and ends in the Passepartout REPL (port 9105) 2. **TDD in REPL** — Red-Green-Refactor cycle: 1. Write a FAILING test first (use `(passepartout:deftest name ...)` or `fiveam:test`) 2. **Prove RED**: Run `(passepartout:run-test 'test-name)` — it MUST fail. If it passes before code exists, the test is broken or testing nothing. Record the failure output. 3. Develop code in REPL to make the test pass 4. Use lisp-structural-check to validate code while developing 5. Evaluate forms with `eval-defun` or equivalent 6. Run tests again → they should PASS 7. Repeat until feature is complete 3. **Reflect in Org** — Once code works in REPL, reflect it in the .org literate source file 4. **Tangle with Emacs** — Use `org-babel-tangle` to generate .lisp from .org 5. **Validate tangled lisp** — Run `lisp-structural-check` on the result 6. **Commit** — Only after validation passes **When tools fail**: - If any recommended tool fails, you MUST explain: - Why it failed (specific error, missing dependency, etc.) - How we can make it work (fix, configuration, alternative approach) - Then **PAUSE** and ask for permission before trying a different method **Rule**: Do not leave the REPL to develop. If something can't be done in REPL, explain why and ask before proceeding otherwise. --- ## Available Tools — Use These First ### 1. Passepartout REPL (port 9105) The daemon runs with ALL skills loaded. Use it instead of the deploy-crash-cycle. **Send forms via Python bridge:** ```python import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("127.0.0.1", 9105)) msg = '(:type :event :payload (:sensor :repl-eval :code "(+ 1 2)"))' s.sendall(f"{len(msg):06x}".encode() + msg.encode()) ``` **Or via SBCL directly (attached to daemon):** ```lisp (sb-bsd-sockets:socket-send sock payload len) ``` **Key functions available:** - `(passepartout:lisp-structural-check "code-string")` — returns (values t nil) or (values nil "error") - `(passepartout:lisp-validate "code-string" :semantic t)` — full validation - `(passepartout:log-message "format ~a" arg)` — write to daemon log - Any exported symbol from `passepartout` package ### 2. Lisp Structural Tools (pre-deploy validation) **ALWAYS run these before tangling/deploying Lisp changes.** `lisp-structural-check` works on ANY Lisp string, not just Org blocks: ```lisp ;; Via REPL — send to port 9105: (passepartout:lisp-structural-check "") ;; Returns: (values t nil) on success, (values nil "error details") on failure ``` For Org files: ```lisp (passepartout:literate-block-balance-check "/path/to/file.org") ``` These catch paren mismatches in <1 second vs. the 60-second deploy-crash cycle. ### 3. Emacs Interactive Use Emacs for interactive Lisp development: - `forward-sexp` / `backward-sexp` — navigate balanced expressions - `show-paren-mode` — visual paren matching - `eval-defun` (C-M-x) — evaluate the current top-level form - `eval-region` — evaluate selected region - `org-babel-tangle` — tangle a single file: `M-x org-babel-tangle` - Batch tangle: `emacs --batch --eval "(progn (require 'org) (find-file \"file.org\") (org-babel-tangle) (kill-buffer))"` ### 4. Tmux (for TUI testing) ```bash # Start TUI in detached session tmux new-session -d -s test "passepartout tui 2>&1 | tee /tmp/tui.log" # Send keys tmux send-keys -t test "hello world" Enter # Capture output tmux capture-pane -t test -p -S -200 # Clean up tmux kill-session -t test ``` ### 5. Pre-Commit Hook Validates staged org files by tangling + compiling in daemon: ``` ln -sf ../../scripts/pre-commit-repl-check .git/hooks/pre-commit ``` Run manually: `passepartout setup` or `git commit` (hook auto-runs). ### 6. TUI REPL (via /eval + Swank) The TUI process has its own REPL for live development: **Built-in /eval command** — type in the TUI input: - `/eval (+ 1 2)` → `=> 3` displayed in chat - `/eval *state*` → inspect full TUI state plist - `/eval (view-status sw)` → force status bar re-render - `/eval (add-msg :system "test")` → inject a test message **Emacs + Swank REPL** — connect Emacs to the TUI process: 1. Start TUI: `passepartout tui` 2. In Emacs: `M-x slime-connect RET 127.0.0.1 RET 4006` 3. `C-M-x` any form from `org/gateway-tui.org` → evaluates in live TUI process 4. Configure port: `export TUI_SWANK_PORT=4009` (default: 4006) **Croatoan note**: Rendering functions (`view-status`, `view-chat`, `view-input`) write to the terminal and can't be fully tested from Emacs. Inspect return values instead, and test rendering with `/eval` commands in the TUI itself. --- ## Commands - Validate code: Send to REPL at port 9105 using socket bridge (see Development Workflow) - Run tests: `(passepartout:run-tests)` in REPL - Tangle org: `emacs --batch --eval "(progn (require 'org) (find-file \"file.org\") (org-babel-tangle) (kill-buffer))"` ## Project Structure - Source (literate): `org/` - Source (tangled): `lisp/` - Tests: `tests/` - Scripts: `scripts/` - Deployment: `~/.local/share/passepartout/` - TODO tracking: `docs/ROADMAP.org` ## When Done Means - Red proof recorded: Test was run and confirmed FAILING before implementation code existed - Tests pass: `(passepartout:run-tests)` returns success - Code validated: `lisp-structural-check` returns `(values t nil)` - Org reflected: Code exists in .org source file - Org tangled: .lisp generated from .org - Committed: Only after all above pass ## Boundaries - **Always do**: Use REPL first for all development, use TDD, prove tests fail FIRST before writing code, validate with lisp-structural-check - **Ask first**: Before editing .lisp directly (skip org), before deploying, before git commit - **Never do**: Edit .lisp files manually (they're autogenerated), skip validation before commit ## Iteration When the agent makes the same mistake twice, add a rule to this file to prevent recurrence. --- ## Project Architecture - **Thin harness, fat skills** — core provides hooks (`defskill`, `register-actuator`, `*probabilistic-backends*`), skills provide handlers - **Org is source of truth** — `.org` files tangle to `.lisp`. Never edit `.lisp` directly - **Package:** `passepartout` exports all symbols in `lisp/core-defpackage.lisp` - **XDG data dir:** `~/.local/share/passepartout/` (deployed lisp/org files) - **Config:** `~/.config/passepartout/.env` --- ## Key Libraries - **Croatoan** — 0-based coordinates, `(setf (cursor-position win) '(y x))` for cursor, `add-string` with `:y`/`:x` keyword args. Source: `~/quicklisp/dists/quicklisp/software/croatoan-20241012-git/src/` - **Babel** — string encoding/decoding - **usocket** — TCP sockets - **bordeaux-threads** — threading primitives