Files
memex/projects/AGENTS.md
Amr Gharbeia c9cc874e53 tools: add repl-block, check-tangle; move existing tools into memex
New tools (projects/<tool>/ — standalone, git-committed):
- repl-block: extract and pipe lisp blocks from org files to the REPL
- check-tangle: tangle + compile in one step, reports errors

Existing tools moved from ~/.opencode/bin/ into memex (survives reinstalls):
- repl, tangle, org-eval, verify-repl

AGENTS.md updated:
- Tool reference table with all 7 tools
- Package reference table for passepartout and cl-tty
- Updated tangle command to use project-local tools

.opencode/commands/ added: check-parens, repl-block, check-tangle commands
2026-05-13 12:54:38 -04:00

10 KiB
Raw Blame History

AGENTS.md

Development Cycle (every change)

  1. Start the runtime — boot the Lisp image that loads your project. For passepartout: passepartout daemon (loads the entire project into one SBCL image). For standalone CL projects: SBCL with (ql:quickload :your-project). The running image IS the development environment. The REPL is mandatory. The SBCL fallback below exists only for bootstrapping (when the runtime cannot start) and CI.

  2. Read the next TODO — find the next unreached *** TODO item in docs/ROADMAP.org (search *** TODO). Read its prose, :PROPERTIES:, and estimated line budget. That item is the target for this change cycle.

  3. Create a branchgit checkout -b feature/<version>-<name> from main. Every feature develops in its own branch. Branches are cheap, disposable, and keep abandoned work off main. Name the branch after the version and a short slug: feature/v0.1.0-layout-engine, feature/v0.9.0-eval-harness. Complex features that span multiple phases may use a single branch with multiple commits rather than one branch per phase.

  4. Think in org — write your reasoning, goals, and approach in the .org file first.

  5. Write contract — define a ** Contract section listing each function's behavior: (fn-name args): description. Returns/guarantees ...

  6. TDD in REPL — the inner loop runs entirely in the running image:

    a. Write tests in org — add fiveam:test forms to the * Test Suite section of the .org source file. Tests are definitions, not explorations — write them in the file first.

    b. Send tests to REPL → RED — evaluate the test forms in the running image. Run the suite. It must FAIL — the implementation doesn't exist yet. Record the failure output in the .org file under the test.

    c. Develop implementation in REPL — redefine functions directly in the running image. Explore. Discover the real argument shapes, edge cases, and helper functions through interaction, not speculation. Each defun in the REPL is immediate — no tangle, no reload, sub-second feedback.

    d. Run tests → GREEN — after each change, re-run the suite from the REPL. When all tests pass, the implementation is complete. If still RED, return to step c. Record the passing output in the .org file under the test.

    e. Copy code to org — copy each finished function from the REPL into its own #+begin_src lisp block in the .org file. The code is already working; the file is now its permanent home. One function per block. Never write a function in a file that hasn't been proven in the image.

  7. 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.

  8. Tangle — generate the .lisp file from the .org source:

    emacs --batch --eval "(progn (require 'org) (find-file \"org/FILE.org\") (org-babel-tangle) (kill-buffer))"
    

    Tangling is a finalization step, not part of the inner loop. The inner loop (steps 5a5e) happens entirely in the REPL. Tangle once, when the file is ready to commit.

  9. Run full test suite — from the REPL, run every test suite in the project:

    (fiveam:run-all-tests)
    

    This catches regressions across the entire system. A function that passes its own tests but breaks another module is not done.

  10. Validate block balance — check that every #+begin_src lisp block in the modified .org files has balanced parentheses. Use your project's equivalent function or the SBCL fallback below.

  11. Commit on the branch — include the RED and GREEN test output recorded in the .org file as part of the commit message evidence:

    git add org/ lisp/ docs/
    git commit -m "v0.9.0: eval harness — 10 tasks, regression detection
    
    RED: 0/10 pass (tasks not yet defined)
    GREEN: 10/10 pass"
    
  12. Mark the origin TODO DONE — in docs/ROADMAP.org, change the *** TODO item to *** DONE and add a :LOGBOOK: entry with the completion date. This is a separate commit on the branch: #+begin_src org :LOGBOOK:

    • State "DONE" from "TODO" [YYYY-MM-DD Day] :END: #+end_src
  13. Merge to main — the merge IS the release. Rebase onto main first to keep history linear, then fast-forward merge:

    git checkout main
    git merge feature/v0.9.0-eval-harness
    
  14. Bump the submodule — if the project is a submodule in the parent memex repo (e.g., passepartout), stage the submodule pointer and commit:

    git add projects/passepartout
    git commit -m "bump passepartout → v0.9.0"
    

    Standalone projects skip this step.

  15. Delete the branchgit branch -d feature/v0.9.0-eval-harness. Abandoned branches can be deleted before merge with no cleanup needed.

Branch Policy

  • Every feature starts on a branch from main. Branch names: feature/<version>-<slug>.
  • ROADMAP.org changes (DONE markers, LOGBOOK entries) happen on the branch, not on main directly. They merge to main with the feature.
  • If a feature fails or is abandoned, delete the branch. No revert commits, no dead code on main, no ;; OBSOLETE comments. Git history preserves the experiment if you need to reference it later.
  • Rebase onto main before merging. Keep history linear. No merge commits.
  • Complex features that span multiple roadmap versions may live on one branch with multiple commits, merging to main when the entire chain is stable.
  • Bug fixes, typos, docs-only edits, and single-session jobs do not get a branch. Commit them directly to main. The heuristic: if it can be finished in one session and has no plausible alternative that could replace it, it goes to main. If it spans sessions or might be abandoned for a better approach, it gets a branch.

Tools

All tools are standalone scripts in projects/<tool>/, committed to the memex. They survive upgrades, reinstalls, and new clones.

Tool What Usage
check-parens Validate paren balance in org lisp blocks (uses SBCL reader) projects/check-parens/check-parens org/file.org
repl-block Extract and send an org lisp block to the daemon REPL projects/repl-block/repl-block org/file.org --function foo
check-tangle Tangle an org file and compile the result in SBCL projects/check-tangle/check-tangle org/file.org
repl Send lisp code to the running daemon projects/repl-tool/repl "(+ 1 2)"
tangle Tangle an org file via Emacs batch projects/tangle-tool/tangle org/file.org
org-eval Evaluate an org src block via Emacs projects/org-eval-tool/org-eval org/file.org
verify-repl Compliance: check defuns have REPL-VERIFIED comments projects/verify-repl-tool/verify-repl org/

Package reference

When sending code to the REPL, use the correct (in-package ...) form first.

Passepartout

Package When to use
:passepartout Core system — skills, gates, memory, dispatcher
:passepartout.channel-tui TUI — event handlers, view, state
<project>-tests Test suites — run with (fiveam:run (intern ...))

cl-tty

Package When to use
:cl-tty.backend Backend protocol — terminal init, draw-text, read-event
:cl-tty.rendering Framebuffer — make-framebuffer, flush-framebuffer
:cl-tty.input Input — key-event, defkeymap, dispatch-key-event
:cl-tty.layout Layout — vbox, hbox, spacer, layout-calculate
:cl-tty.dialog Dialog system — dialog stack, select-dialog
:cl-tty.select Select widget — filter, handle-key
:cl-tty.slot Slot/plugin system
:cl-tty.markdown Markdown rendering

Commands

Tangle a single file: projects/tangle-tool/tangle org/FILE.org

Or: emacs --batch --eval "(progn (require 'org) (find-file "org/FILE.org") (org-babel-tangle) (kill-buffer))"

Run tests (from REPL): (fiveam:run (intern "SUITE-NAME" :project-TESTS)) (fiveam:run-all-tests)

Run tests (SBCL fallback — only when the runtime cannot start): sbcl --noinform
--eval '(ql:quickload :your-project :silent t)'
--eval '(load "lisp/FILE.lisp")'
--eval '(fiveam:run (intern "SUITE-NAME" :project-TESTS))' --quit

For error details: bind fiveam:on-failure to :debug

REPL — mandatory

All development happens in a running Lisp image. Start your runtime:

  • Passepartout: passepartout daemon — boots the entire project, listens on port 9105
  • Standalone CL projects: sbcl with (ql:quickload :your-project)

Send code from opencode using the lisp tool (any SBCL project) or the repl tool (passepartout daemon on port 9105). The inner loop (step 5a5e) never leaves the REPL:

  1. Send test forms from .org to REPL → RED
  2. Redefine functions in REPL → test → iterate
  3. Send tests → GREEN
  4. Copy working code back to .org

Tangle only when the file is complete and ready to commit. Never batch-compile outside the image when the runtime is available. Use the SBCL fallback above only when the runtime itself cannot start.

Rules

  • After copying code from the REPL to the .org file, run ../check-parens/check-parens <file.org> to verify all Lisp blocks have balanced parentheses. This catches mismatched parens before tangling: projects/check-parens/check-parens org/channel-tui-view.org
  • .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
  • Implementation is developed in the REPL, then copied to .org — never write code in a file that hasn't been proven in the image
  • Validate before committing
  • If a tool fails, explain why and ask before trying alternatives
  • Before shipping a version, run the ** File Update Checklist in docs/ROADMAP.org
  • YOU MAY NOT push a version tag (e.g., v0.5.0), create a GitHub release, or run git push that triggers CI/CD version workflows without explicit permission. Ask first.