passepartout: v0.4.1 Design Cleanup
Submodule: 25 files changed — system-prompt-augment removal, 10 cognitive tools, vector count 9-10, README rewrite, ROADMAP updates, CONTRIBUTING rewrite, tangle normalization. AGENTS.md: rewritten compact (180-50 lines).
This commit is contained in:
203
AGENTS.md
203
AGENTS.md
@@ -1,179 +1,50 @@
|
||||
# AGENTS.md — OpenCode Tool Usage Guide
|
||||
# AGENTS.md
|
||||
|
||||
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 Cycle (every change)
|
||||
|
||||
## 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 "<lisp-code-string>")
|
||||
;; 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.
|
||||
|
||||
---
|
||||
1. **Think in org** — write your reasoning, goals, and approach in the .org file first
|
||||
2. **Write contract** — define a `** Contract` section listing each function's behavior:
|
||||
`(fn-name args)`: description. Returns/guarantees ...
|
||||
3. **TDD from contract** — each contract item becomes a `fiveam:test` in `* Test Suite`
|
||||
a. Write the test first → tangle → run → prove it FAILS (RED)
|
||||
b. Write the implementation → tangle → run → prove it PASSES (GREEN)
|
||||
c. Record both failure and success output
|
||||
4. **Reflect in org** — once tests pass, ensure the implementation is in the .org source
|
||||
5. **Update literate prose** — write/update the explanatory text around the code:
|
||||
what it does, why it exists, how it connects to the rest of the system
|
||||
6. **Commit** — only when asked. Ask first.
|
||||
|
||||
## 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))"`
|
||||
Tangle a single file:
|
||||
emacs --batch --eval "(progn (require 'org) (find-file \"org/FILE.org\") (org-babel-tangle) (kill-buffer))"
|
||||
|
||||
## Project Structure
|
||||
Validate structural integrity:
|
||||
sbcl --noinform --eval '(with-open-file (f "lisp/FILE.lisp") (loop (read f nil (return))))' --quit
|
||||
|
||||
- Source (literate): `org/`
|
||||
- Source (tangled): `lisp/`
|
||||
- Tests: `tests/`
|
||||
- Scripts: `scripts/`
|
||||
- Deployment: `~/.local/share/passepartout/`
|
||||
- TODO tracking: `docs/ROADMAP.org`
|
||||
Run tests:
|
||||
sbcl --noinform \
|
||||
--eval '(load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))' \
|
||||
--eval '(ql:quickload :passepartout :silent t)' \
|
||||
--eval '(load "lisp/FILE.lisp")' \
|
||||
--eval '(fiveam:run (intern "SUITE-NAME" :passepartout-TESTS))' --quit
|
||||
|
||||
## When Done Means
|
||||
For error details: bind fiveam:*on-failure* to :debug
|
||||
|
||||
- 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
|
||||
## REPL (port 9105) — preferred when available
|
||||
|
||||
## Boundaries
|
||||
Start: `passepartout daemon`
|
||||
Send code:
|
||||
msg = '(:type :event :payload (:sensor :repl-eval :code "(+ 1 2)"))'
|
||||
s.sendall(f'{len(msg):06x}'.encode() + msg.encode())
|
||||
|
||||
- **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
|
||||
When REPL is up: TDD in-image first, then reflect to .org and tangle.
|
||||
When REPL is down: fall back to the SBCL cycle above.
|
||||
|
||||
## Iteration
|
||||
## Rules
|
||||
|
||||
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
|
||||
- .org is source of truth; .lisp is generated — never edit .lisp directly
|
||||
- Every code change starts with a contract and a failing test
|
||||
- Prove RED before writing implementation
|
||||
- Validate before committing
|
||||
- If a tool fails, explain why and ask before trying alternatives
|
||||
|
||||
Reference in New Issue
Block a user