From 0821b2b10a99450de1b7c79df884bfbc2f72f82c Mon Sep 17 00:00:00 2001 From: Amr Gharbeia Date: Mon, 11 May 2026 08:29:27 -0400 Subject: [PATCH] add: methodology conventions --- methodology/AGENTS.md | 180 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 methodology/AGENTS.md diff --git a/methodology/AGENTS.md b/methodology/AGENTS.md new file mode 100644 index 0000000..0983c21 --- /dev/null +++ b/methodology/AGENTS.md @@ -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/-` 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/-`. +- 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.