memex: split AGENTS.md into monorepo overview and per-project workflow
Move the development workflow details (TDD, REPL, literate programming, branch policy) from top-level AGENTS.md into projects/AGENTS.md. Top-level AGENTS.md now describes only the monorepo structure and project list.
This commit is contained in:
86
AGENTS.md
86
AGENTS.md
@@ -1,82 +1,12 @@
|
|||||||
# AGENTS.md
|
# AGENTS.md
|
||||||
|
|
||||||
## Development Cycle (every change)
|
This is the memex monorepo. It contains multiple Common Lisp projects, each
|
||||||
|
in `projects/`. See `projects/AGENTS.md` for the general development workflow
|
||||||
|
(ROADMAP-driven, TDD in REPL, literate programming, branch policy).
|
||||||
|
|
||||||
1. **Read the next TODO** — find the next unreached `*** TODO` item in
|
## Project list
|
||||||
`docs/ROADMAP.org` (search `*** TODO`). Read its prose, `:PROPERTIES:`,
|
|
||||||
and estimated line budget. That item is the target for this change cycle.
|
|
||||||
2. **Think in org** — write your reasoning, goals, and approach in the .org file first
|
|
||||||
3. **Write contract** — define a `** Contract` section listing each function's behavior:
|
|
||||||
`(fn-name args)`: description. Returns/guarantees ...
|
|
||||||
4. **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
|
|
||||||
5. **Reflect in org** — once tests pass, ensure the implementation is in the .org source, put each function in a separate code block.
|
|
||||||
6. **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
|
|
||||||
7. **Mark the origin TODO DONE** — in `docs/ROADMAP.org`, change the
|
|
||||||
`*** TODO` item to `*** DONE` and add a `:LOGBOOK:` entry with the
|
|
||||||
completion date:
|
|
||||||
#+begin_src org
|
|
||||||
:LOGBOOK:
|
|
||||||
- State "DONE" from "TODO" [YYYY-MM-DD Day]
|
|
||||||
:END:
|
|
||||||
#+end_src
|
|
||||||
8. **Commit** — only when asked. Ask first.
|
|
||||||
|
|
||||||
## Commands
|
| Project | Description | Runtime |
|
||||||
|
|---------|-------------|---------|
|
||||||
Tangle a single file:
|
| passepartout | Neurosymbolic agent | `passepartout daemon` |
|
||||||
emacs --batch --eval "(progn (require 'org) (find-file \"org/FILE.org\") (org-babel-tangle) (kill-buffer))"
|
| cl-tui | Reusable terminal UI framework | `sbcl` + `(ql:quickload :cl-tui)` |
|
||||||
|
|
||||||
Validate structural integrity:
|
|
||||||
emacs --batch -Q --eval '(progn (find-file "org/FILE.org") (check-parens) (kill-buffer))'
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
For error details: bind fiveam:*on-failure* to :debug
|
|
||||||
|
|
||||||
## REPL (port 9105) — preferred when available
|
|
||||||
|
|
||||||
Start: `passepartout daemon`
|
|
||||||
Send code:
|
|
||||||
msg = '(:type :event :payload (:sensor :repl-eval :code "(+ 1 2)"))'
|
|
||||||
s.sendall(f'{len(msg):06x}'.encode() + msg.encode())
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Rules
|
|
||||||
|
|
||||||
- .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
|
|
||||||
- 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.
|
|
||||||
- **YOU MAY NOT add files to `passepartout.asd` `:components` without asking for permission.**
|
|
||||||
ASDF `:components` is the core harness. Files there load on every daemon boot,
|
|
||||||
cannot be hot-reloaded, and a bug there kills the agent's brainstem.
|
|
||||||
- When you want to add a new module, **ask first**. Provide:
|
|
||||||
1. Why it cannot be a skill (the self-repair criterion — can the agent fix it
|
|
||||||
if corrupted without human help?) Demonstrate specifically how a broken
|
|
||||||
version of this file prevents the agent from perceiving, reasoning,
|
|
||||||
or acting — not just degrading performance or losing a feature.
|
|
||||||
2. What it depends on and what depends on it
|
|
||||||
3. Why it cannot use `fboundp` guards from core
|
|
||||||
- **Default: everything is a skill.** Skills load via `skill-initialize-all`,
|
|
||||||
are hot-reloadable, self-repairable, and a bug in a skill degrades the agent
|
|
||||||
but doesn't kill it. The harness stays thin.
|
|
||||||
- **The self-repair criterion**: a file belongs in core only if, when corrupted,
|
|
||||||
the agent *cannot* fix it without human help. Corrupted core = dead brain,
|
|
||||||
dead hands, or unreachable. Corrupted skill = degraded but self-repairable.
|
|
||||||
This criterion is documented in `docs/ARCHITECTURE.org` and
|
|
||||||
`docs/DESIGN_DECISIONS.org`.
|
|
||||||
|
|||||||
180
projects/AGENTS.md
Normal file
180
projects/AGENTS.md
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
## Development Cycle (every change)
|
||||||
|
|
||||||
|
0. **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.
|
||||||
|
|
||||||
|
1. **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.
|
||||||
|
|
||||||
|
2. **Create a branch** — `git 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.
|
||||||
|
|
||||||
|
3. **Think in org** — write your reasoning, goals, and approach in the .org file first.
|
||||||
|
|
||||||
|
4. **Write contract** — define a `** Contract` section listing each function's behavior:
|
||||||
|
`(fn-name args)`: description. Returns/guarantees ...
|
||||||
|
|
||||||
|
5. **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.
|
||||||
|
|
||||||
|
6. **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.
|
||||||
|
|
||||||
|
7. **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 5a–5e) happens entirely in the REPL. Tangle once, when the file is
|
||||||
|
ready to commit.
|
||||||
|
|
||||||
|
8. **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.
|
||||||
|
|
||||||
|
9. **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.
|
||||||
|
|
||||||
|
10. **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"
|
||||||
|
```
|
||||||
|
|
||||||
|
11. **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
|
||||||
|
|
||||||
|
12. **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
|
||||||
|
```
|
||||||
|
|
||||||
|
13. **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.
|
||||||
|
|
||||||
|
14. **Delete the branch** — `git 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.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
Tangle a single file:
|
||||||
|
emacs --batch --eval "(progn (require 'org) (find-file \"org/FILE.org\") (org-babel-tangle) (kill-buffer))"
|
||||||
|
|
||||||
|
Validate structural integrity (org/ source files only):
|
||||||
|
emacs --batch -Q --eval '(progn (find-file "org/FILE.org") (check-parens) (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 '(load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))' \
|
||||||
|
--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 5a–5e) 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
|
||||||
|
|
||||||
|
- .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.
|
||||||
Reference in New Issue
Block a user