Unify AGENTS.md with canonical jerboa version
ober
6f6bcb455c91bb28c11708e9a712a90cce32fcb4
--- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ ## The Jerboa Language — Quick Reference -Jerboa is a Scheme dialect built on Chez Scheme. It has legacy shell ancestry but is its own language. **All user-facing code is `.ss` files. Never write `.sls` files for the user** — those are internal implementation files. +Jerboa is a Scheme dialect built on Chez Scheme. It is Gerbil-inspired but its own language. **All user-facing code is `.ss` files. Never write `.sls` files for the user** — those are internal implementation files. ### File Structure @@ -17,21 +17,21 @@ Every Jerboa file looks like this: (displayln (my-function 1 2)) ``` -Run with: `scheme --libdirs lib --script file.ss` +Run with: `jerboa run file.ss` **NEVER** write `(library ...)` forms — that's `.sls` internal syntax. ### Reader Syntax Extensions ``` -[...] → plain parentheses — same as Chez Scheme +[...] → plain parentheses — same as Gerbil and Chez Scheme {method obj args} → (~ obj 'method args) — method dispatch name: → keyword #:name -:std/sort → (std sort) — colon-style module path +:std/sort → (std sort) — Gerbil-style module path #<<END ... END → heredoc string ``` -Square brackets `[...]` are interchangeable with `(...)`, exactly like stock Chez Scheme. You can freely use them in bindings, match clauses, and anywhere you'd use parentheses: +Square brackets `[...]` are interchangeable with `(...)`, exactly like Gerbil and stock Chez Scheme. You can freely use them in bindings, match clauses, and anywhere you'd use parentheses: ```scheme ;; All of these are correct: (let ([x 1] [y 2]) (+ x y)) @@ -42,7 +42,7 @@ Square brackets `[...]` are interchangeable with `(...)`, exactly like stock Che ### CRITICAL: Things That DO NOT EXIST in Jerboa/Chez -Claude frequently hallucinates these from other Scheme implementations, Gambit, Racket, or R7RS training data. +Claude frequently hallucinates these from Gerbil, Gambit, Racket, or R7RS training data. **NONE of them are real in Jerboa/Chez. STOP and use the correct form.** #### AI Compatibility Aliases (these now work in the prelude) @@ -61,19 +61,19 @@ The following names from other Scheme dialects are aliased in `(jerboa prelude)` - `string-contains?` — use `(string-contains str sub)` (returns index or #f, NOT boolean) - `define-struct` — use `(defstruct name (fields ...))` - `raise` with a string — use `(error 'who "message" irritants ...)` -- `environment-bound?` — non-Jerboa. No direct Chez equivalent +- `environment-bound?` — Gerbil-only. No direct Chez equivalent -#### Non-Jerboa Scheme-isms (from training data — wrong in Jerboa) +#### Gerbil/Gambit-isms (from training data — wrong in Jerboa) - `time->seconds` — use `(time-second (current-time))` for epoch seconds - `thread-sleep!` — Gambit. Use `(sleep (make-time 'time-duration 0 seconds))` - `thread-yield` — no Chez equivalent. Use `(sleep (make-time 'time-duration 0 0))` as workaround -- `path-expand` with 2 args — Jerboa takes 1 arg. Use `(path-join base rel)` for 2-arg version -- `process-status` — non-Jerboa. Use `(std misc process)` API in Jerboa -- `user-info-home` — non-Jerboa. Use `(getenv "HOME")` -- `the-environment` — non-Jerboa. Use `(interaction-environment)` in Chez -- `condition/report-string` — non-Jerboa. Use `(with-output-to-string (lambda () (display-condition c)))` -- `make-class-type` — non-Jerboa. Use `(defstruct ...)` or `(defclass ...)` in Jerboa -- `string-subst` — non-Jerboa. Not in prelude. Use `(string-replace str old new)` or implement manually +- `path-expand` with 2 args — Gerbil takes `(path-expand rel base)`. Jerboa takes 1 arg. Use `(path-join base rel)` for 2-arg version +- `process-status` — Gerbil. Use `(std misc process)` API in Jerboa +- `user-info-home` — Gerbil. Use `(getenv "HOME")` +- `the-environment` — Gerbil. Use `(interaction-environment)` in Chez +- `condition/report-string` — Gerbil. Use `(with-output-to-string (lambda () (display-condition c)))` +- `make-class-type` — Gerbil. Use `(defstruct ...)` or `(defclass ...)` in Jerboa +- `string-subst` — Gerbil. Not in prelude. Use `(string-replace str old new)` or implement manually - `open-fd-pair` — Gambit. Does not exist in Chez; requires different API #### R6RS/Racket-isms (wrong variant) @@ -88,9 +88,9 @@ The following names from other Scheme dialects are aliased in `(jerboa prelude)` - `(in-range end)` or `(in-range start end)` or `(in-range start end step)` — NOT `(in-range start step end)` - `(hash-ref ht key)` or `(hash-ref ht key default)` — NOT `(hash-ref key ht)` - `(string-split str delimiter)` where delimiter is a CHAR: `(string-split "a,b" #\,)` -- `(make-rwlock)` — takes **0 args**, NOT `(make-rwlock 'name)` -- `(path-expand path)` — takes **1 arg**, NOT `(path-expand rel base)`; use `path-join` for 2-arg -- `(sort predicate list)` — Chez arg order. NOT `(sort list predicate)` +- `(make-rwlock)` — takes **0 args**, NOT `(make-rwlock 'name)` (Gerbil takes a name; Jerboa does not) +- `(path-expand path)` — takes **1 arg**, NOT `(path-expand rel base)` (Gerbil takes 2; use `path-join` for 2-arg) +- `(sort list predicate)` — Jerboa `(std sort)`/prelude order. Raw Chez `sort` is predicate-first, but Jerboa-facing code should use list first. ### Core Forms (all from `(import (jerboa prelude))`) @@ -340,10 +340,11 @@ improved versions of the above. When working in a Jerboa project, **ONLY modify files in the current repo** unless the user explicitly names another path. Common sibling repos that exist but must NOT be touched without explicit instruction: -- `~/mine/jerboa-mcp` — Only modify when user explicitly says to work there. +- `~/mine/jerboa-emacs` — **NEVER touch**. Another model owns it. +- `~/mine/jerboa-mcp` — Legacy node MCP, superseded. The active MCP server now lives in THIS repo at `mcp/` + `data/`. Don't modify the legacy repo unless told. - `~/mine/jerboa-shell` — Only modify when user explicitly says to work there. -- `~/mine/jerboa-mcp` — **NEVER touch**. Deprecated. -- `~/mine/jerboa-orig` — Read-only legacy upstream reference. Never modify. +- `~/mine/gerbil-mcp` — **NEVER touch**. Deprecated. +- `~/mine/gerbil-orig` — Read-only reference for upstream Gerbil. Never modify. If a user instruction mentions a file path, use EXACTLY that path. Do not substitute a similar-looking path from another repo. @@ -361,6 +362,22 @@ find lib -name "*.so" -delete && find lib -name "*.wpo" -delete && make build ``` Run `jerboa_stale_static` to detect stale `.so` files before debugging "why doesn't my edit work?". +## Pre-commit Requirements + +**ALWAYS** run a clean build **before** committing any code to this repository. Pick the right target for the *current* platform: + +- **Linux**: run `make docker-build` — the Docker image must build cleanly against the full musl-static release pipeline. +- **macOS / FreeBSD / other**: run `make binary` — the native local build must succeed. Do **not** run `make docker-build` here; Docker on non-Linux hosts is slow and not the canonical pipeline for those platforms. + +Do not commit if the build fails. + +## Act First, Read Less + +When making changes, read only what you need to make the edit, then make it. +Do not read more than 3 files before acting. Do not re-read files you already +read. Do not verify things you already know. If you have enough context to make +a change, make it. The user will interrupt you if you are wrong. + ## Jerboa MCP Tools — MANDATORY Usage Jerboa is a niche Scheme dialect with limited training data. **Never guess — always verify** with MCP tools. Tool descriptions are available at runtime via the MCP server; this section covers **when** and **why** to use each tool. @@ -388,12 +405,12 @@ Jerboa is a niche Scheme dialect with limited training data. **Never guess — a | Find where something is defined | `jerboa_find_definition` — source file, module, kind, arity | | Search for symbol by substring | `jerboa_apropos` or `jerboa_smart_complete` | | Build the project | `jerboa_build_and_report` or `jerboa_make` — prefer over bash `make` | -| Run tests | `jerboa_run_tests` — prefer over bash `scheme --script` | +| Run tests | `jerboa_run_tests` — prefer over ad hoc shell test invocations | | Check for stale .so artifacts | `jerboa_stale_static` — common cause of "edit has no effect" | | Macro expansion | `jerboa_expand_macro` / `jerboa_trace_macro` | | Inspect struct/class types | `jerboa_class_info` — fields, inheritance, constructor signature | | FFI work | `jerboa_ffi_scaffold` / `jerboa_ffi_type_check` / `jerboa_ffi_null_safety` | -| Port legacy Scheme code | `jerboa_migration_check` + `jerboa_translate_scheme` | +| Port Gerbil code | `jerboa_migration_check` + `jerboa_translate_scheme` | | Detect paren imbalance | `jerboa_check_balance` — use BEFORE `make build` after deep edits | | Full project audit | `jerboa_project_health_check` — balance, exports, cycles, duplicates | | Security audit | `jerboa_security_audit` + `jerboa_import_policy_check` | @@ -408,6 +425,9 @@ Jerboa is a niche Scheme dialect with limited training data. **Never guess — a - **`jerboa_howto_add`**: Save new patterns to cookbook (MANDATORY when you discover something non-trivial) - **`jerboa_howto_run`** / **`jerboa_howto_verify`**: Validate recipes still work - **`jerboa_error_fix_add`**: Save error→fix mappings for common mistakes +- **`jerboa_anti_pattern_lookup`**: Search reusable local-model mistakes and failed strategies + +**The knowledge base is `data/*.sexp` in THIS repo**, embedded into `jmcp` at build time. The write tools above edit it live — the server reads `data/` from disk first, with the embedded copy as fallback (`JERBOA_MCP_REPO` points every client at this repo). When you add a stdlib/language feature, also update `data/` (a cookbook recipe + `api-signatures.sexp` + `changelog.sexp`) and **commit it**. Run `make jmcp` (or `make jmcp-portable`) only to refresh the embedded copy shipped in portable binaries. ### Code Generation & Refactoring @@ -432,6 +452,25 @@ Jerboa is niche — every non-trivial pattern you discover prevents future sessi **Recipe format**: `id` (kebab-case), `tags` (4-6 search keywords incl. module name), `imports` (all required), `code` (complete working example), `notes` (gotchas/alternatives). +### Save anti-patterns (`data/anti-patterns.sexp`) whenever you: +- See a plausible local-model strategy that failed verification +- Find a weak verifier pattern that allowed false success +- See a repeated repair loop, such as broad-reading after a concrete error +- Find a generic runtime mistake, such as missing lower-bound checks before vector access + +**Before saving**: check `jerboa_anti_pattern_lookup` to avoid duplicates. If none exists, call `jerboa_anti_pattern_add`; only edit `data/anti-patterns.sexp` directly if the writer tool is unavailable. Save the normalized reusable mistake, not the whole trace or benchmark name. + +**Anti-pattern format**: `id`, `title`, `kinds`, `severity`, `tags`, `pattern`, `avoid`, `advice`, `tools`. + +### Save error fixes (`jerboa_error_fix_add`) whenever you: +- See exact compiler/runtime/verifier text with a repeatable repair +- Hit an error that `jerboa_failure_advisor` should classify better next time +- Debug a local-model generated-code failure where a short diagnosis prevents another failed iteration + +**Before saving**: check `jerboa_error_fix_lookup` with the exact error text. **Do NOT save**: one-off project business-logic mistakes. + +**Error-fix format**: `id`, `pattern`, `fix`; optional `type`, `explanation`, `code_example`. + ### Suggest tooling improvements (`jerboa_suggest_feature`) whenever you: - Make multiple sequential tool calls that could be one tool - Fall back to bash because an MCP tool is missing or insufficient @@ -439,7 +478,7 @@ Jerboa is niche — every non-trivial pattern you discover prevents future sessi **Before suggesting**: check `jerboa_list_features`; vote with `jerboa_vote_feature` if it already exists. ### Save Discoveries Mechanisms -- **`/save-discoveries` skill**: invoke anytime to review session and save patterns + suggestions +- **`/save-discoveries` skill**: invoke anytime to review session and save recipes, anti-patterns, error fixes, feature suggestions, and security patterns - **PreCompact hook**: add `PreCompact` hook with `type: "prompt"` in `.claude/settings.json` to auto-save before context compaction --- @@ -451,7 +490,7 @@ Jerboa is niche — every non-trivial pattern you discover prevents future sessi - **Understand unfamiliar code**: `jerboa_file_summary` -> `jerboa_document_symbols` -> `jerboa_module_deps` - **Refactor a module**: `jerboa_check_exports` -> `jerboa_find_callers` -> `jerboa_rename_symbol` -> `jerboa_check_import_conflicts` - **Build project**: `jerboa_build_conflict_check` -> `jerboa_make` -> `jerboa_build_and_report` -- **Port legacy Scheme**: `jerboa_migration_check` -> `jerboa_translate_scheme` -> `jerboa_verify` -> `jerboa_check_syntax` +- **Port from Gerbil**: `jerboa_migration_check` -> `jerboa_translate_scheme` -> `jerboa_verify` -> `jerboa_check_syntax` - **Audit project quality**: `jerboa_verify` -> `jerboa_lint` -> `jerboa_dead_code` -> `jerboa_dependency_cycles` - **Debug a crash**: `jerboa_stale_static` -> `jerboa_bisect_crash` -> `jerboa_ffi_type_check` - **Learn a module**: `jerboa_stdlib_source` -> `jerboa_module_catalog` -> `jerboa_module_quickstart`