updates
ober
ac6bf38907601b90091c73eb83151be530306cbf
--- a/data/anti-patterns.sexp +++ b/data/anti-patterns.sexp @@ -5985,4 +5985,22 @@ ("tools" "jerboa_ffi_null_safety" "jerboa_security_scan" - "jerboa_ffi_type_check"))) + "jerboa_ffi_type_check")) + (("advice" + . + "Only purge .so/.wpo inside the PROJECT's lib/ (and shadowed stdlib copies in it). If the toolchain home is already damaged, move the whole <hash> dir aside and run jerbuild --jerboa-home to re-extract a pristine stdlib, then rebuild the project. Distinguish 'stale project artifacts' from 'toolchain runtime artifacts' before any find -delete.") + ("avoid" + . + "Deleting .so/.wpo from the jerboa toolchain home (~/.cache/jerbuild/<hash>/lib) while treating build flakiness; those artifacts are instance-matched to the installed jerboa binary, and their loss makes even 'jerboa --version' fail with 'yielded a different compilation instance'.") + ("id" . "purge-toolchain-home-cache-as-stale-artifacts") + ("kinds" "build" "debug") + ("pattern" + . + "find ~/.cache/jerbuild -name \"*.so\" -delete|rm -rf ~/.cache/jerbuild") + ("severity" . "high") + ("tags" "cache" "jerboa-home" "compilation-instance" + "stale-artifacts" "toolchain") + ("title" + . + "Never purge the jerbuild toolchain-home cache as 'stale artifacts'") + ("tools" "jerboa_compile_check" "jerboa_make"))) --- a/data/cookbooks.sexp +++ b/data/cookbooks.sexp @@ -8898,14 +8898,44 @@ "Check typed closure corpus fixtures through parser and checker")) (("code" . - "# Guard the deterministic JSON structural scanner corpus and benchmark corpus.\nmake typed-json-scan-corpus-check\n\n# The richer gates depend on the corpus guard.\nmake typed-json-scan-diff\nmake typed-json-scan-bench") - ("id" . "typed-json-scan-corpus-guard") - ("imports") + "# Guard the deterministic JSON structural scanner corpus and benchmark corpus.\nmake typed-json-scan-corpus-check\n\n# The richer gates depend on the corpus guard.\nmake typed-json-scan-diff\nmake typed-json-scan-bench") ("id" . "typed-json-scan-corpus-guard") ("imports") ("notes" . "Use this guard when the typed JSON scanner has a fixed differential corpus and a benchmark corpus embedded in separate Rust and Scheme harnesses. support/typed-json-scan-corpus-check.py enforces the deterministic diff count, checks that the Rust and Scheme benchmark corpora have matching multiplicities, and requires every benchmark case to remain covered by the diff corpus before the differential or benchmark gates run. release-evidence records typed-json-scan-corpus-check, typed-json-scan-diff, and typed-json-scan-bench logs and hashes the scanner source plus support scripts.") ("tags" "typed" "json" "scanner" "corpus" "benchmark" "diff") + ("title" . "Guard typed JSON scanner corpus coverage")) + (("code" + . + "# jerboa 0.2.8's safe-prelude script loader rejects BOTH `#!/usr/bin/env ...`\n# shebang lines and direct (scheme)/(chezscheme) imports. To run a legacy\n# test/script (e.g. test/run.ss):\ntail -n +2 test/run.ss > /tmp/run-noshebang.ss # strip the shebang line\njerbuild exec --unsafe-prelude --libdirs ./lib /tmp/run-noshebang.ss\n") ("id" . "run-raw-scheme-test-jerboa-028") ("imports") + ("notes" + . + "jerbuild is a symlink to the jerboa multicall binary. Script mode (`jerboa file.ss`) has no --libdirs flag in 0.2.8, and `jerboa run` does not exist in this release despite older docs. `#!chezscheme` as first line IS accepted by the reader, but a direct (scheme) import still needs --unsafe-prelude. If the file can be edited, prefer importing jerboa modules ((jerboa core) + project libs) over (scheme) and drop the flag.") + ("tags" "jerbuild" "exec" "unsafe-prelude" "scheme" + "shebang" "test") + ("title" + . + "Run a (scheme)-importing test/script on jerboa 0.2.8 (safe-prelude loader)")) + (("code" + . + "(import (scheme)\n (prefix (jerboa core) j:)\n (jcode provider provider)) ;; example: many modules\n\n;; In files importing (scheme) plus many project modules, an unqualified\n;; make-hash-table may resolve to a non-jerboa (eq-keyed) flavor. Library\n;; code using jerboa's hash-get then cannot see string keys you wrote.\n;; Bind jerboa core under a prefix and use it for any hash shared with\n;; library code:\n(let ((h (j:make-hash-table)))\n (j:hash-put! h \"role\" \"user\")\n (j:hash-put! h \"content\" \"hi\")\n (j:hash-get h \"role\")) ;; => \"user\" — visible to jerboa-flavored readers\n") ("id" . "prefix-import-jerboa-core-hash-tables") + ("imports" "(prefix (jerboa core) j:)") + ("notes" + . + "Symptom: string keys written by test code are invisible to library code (hash-get returns #f for present keys), causing spurious repairs/coercions or (car #f) downstream. Root cause is import-order shadowing: a later import exports a different make-hash-table. The prefix import makes the dependency explicit and immune to shadowing.") + ("tags" "hash-table" "prefix-import" "shadowing" + "make-hash-table" "test" "jerboa-core") + ("title" + . + "Unambiguous jerboa hash tables in mixed-import files via (prefix (jerboa core) j:)")) + (("code" + . + ";; WRONG in jerboa_eval expressions:\n;; (let ([attempts 0]) ...)\n;; => Exception: invalid syntax (let ((list attempts 0)) ...)\n;; RIGHT — plain parens everywhere:\n(let ((attempts 0))\n (set! attempts (+ attempts 1))\n attempts)\n") ("id" . "jerboa-eval-plain-parens-only") ("imports") + ("notes" + . + "The jerboa_eval reader does not treat [...] as plain parens the way jerbuild-compiled source does; a bracketed group is read as (list ...). This also breaks guard clauses written [else ...] (\"misplaced aux keyword else\") — write (else ...). Applies to all string expressions passed to jerboa_eval and similar MCP eval tools.") + ("tags" "jerboa_eval" "mcp" "brackets" "reader" "eval" + "list") ("title" . - "Guard typed JSON scanner corpus coverage"))) + "jerboa_eval: write expressions with plain parens only — [x y] reads as (list x y)"))) --- a/data/error-fixes.sexp +++ b/data/error-fixes.sexp @@ -3385,5 +3385,37 @@ . "Never pass movable Scheme pointers to __collect_safe bindings. Redeclare with void* and bounce through a scoped foreign-alloc buffer (copy in/out, foreign-free via dynamic-wind) -- the call-with-rustls-io-buffer pattern in (std net tls-rustls). Audit with: rg \"__collect_safe\" -A1 | rg \"u8\\*|string\". Blocking calls without __collect_safe are GC-safe but pin the scheduler.") ("id" . "collect-safe-movable-pointer-segfault") - ("pattern" . "invalid memory reference|Some debugging context lost") + ("pattern" + . + "invalid memory reference|Some debugging context lost") + ("type" . "runtime")) + (("fix" + . + "Stale or version-skewed compiled artifacts. Project libs: find lib -name '*.so' -delete && find lib -name '*.wpo' -delete, then rebuild. If the toolchain itself fails the same way (even jerboa --version), the toolchain home cache is damaged: move ~/.cache/jerbuild/<hash> aside and run jerbuild --jerboa-home to re-extract a pristine stdlib, then rebuild. Never delete .so files from the toolchain home during 'stale artifact' cleanup — they are instance-matched to the installed binary.") + ("id" + . + "compilation-instance-mismatch-stale-toolchain-cache") + ("pattern" . "yielded a different compilation instance of") + ("type" . "compile")) + (("fix" + . + "jerboa's safe-prelude script loader blocks raw (scheme)/(chezscheme) imports. Run with: jerbuild exec --unsafe-prelude --libdirs <dirs> file.ss — or better, import the jerboa modules you actually need ((jerboa core), project libraries) instead of (scheme) so the flag is unnecessary.") + ("id" . "scheme-import-requires-unsafe-prelude") + ("pattern" + . + "direct (scheme)/(chezscheme) imports require --unsafe-prelude") + ("type" . "runtime")) + (("fix" + . + "The jerboa 0.2.8 script loader does not skip a leading #!/usr/bin/env ... shebang line (only #!chezscheme is accepted as a magic token). Strip the shebang first (tail -n +2 file.ss > tmp.ss) or remove the line before jerbuild exec / jerboa file.ss.") + ("id" . "jerboa-script-loader-shebang-invalid-syntax") + ("pattern" . "invalid syntax #!/usr/bin/env at char 0") + ("type" . "read")) + (("fix" + . + "A signed Mach-O (jerboa binary, libjerboa_native.dylib, or a Chez .so) was rewritten in place while a process had it mapped; the kernel SIGKILLs any process that maps it afterwards. This is NOT a memory problem. Make installs atomic (cp src .tmp && mv -f .tmp dst) instead of in-place cp -f, and avoid rebuilding dylibs while long-running jerboa processes have them mapped. Diagnose: log show --last 15m --predicate 'eventMessage CONTAINS \"<pid>\"' for the 'fatal 309' line, then read the matching .ips in ~/Library/Logs/DiagnosticReports (termination namespace CODESIGNING).") + ("id" . "macos-codesigning-invalid-page-sigkill") + ("pattern" + . + "Killed: 9.*(jerboa|jerbuild)|CODESIGNING.*Invalid Page|fatal 309") ("type" . "runtime"))) --- a/data/features.sexp +++ b/data/features.sexp @@ -4028,4 +4028,42 @@ ("use_case" . "Before saving a reusable anti-pattern, agents must search existing entries. A single non-string pattern currently blocks that mandatory workflow.") + ("votes" . 0)) + (("description" + . + "jerboa_verify/jerboa_compile_check already strip shebang lines (verify-shebang-script-support, implemented), but the RUNTIME path does not: jerbuild exec and jerboa <script.ss> both fail with 'invalid syntax #!/usr/bin/env at char 0' on any .ss starting with a shebang. The documented canonical shebang '#!/usr/bin/env -S jerboa run' cannot work on the 0.2.8 release (no 'run' subcommand, loader rejects #!). The script loader should skip a leading #! line exactly like Chez --script does.") + ("estimated_token_reduction" + . + "eliminates 2-3 workaround steps per script run (~200 tokens)") + ("example_scenario" + . + "jerbuild exec --libdirs lib test/run.ss fails at char 0 because test/run.ss starts with '#!/usr/bin/env scheme --script'; every run needs tail -n +2 into a temp file first.") + ("id" . "jerbuild-exec-tolerate-shebang") + ("impact" . "medium") ("status" . "proposed") + ("tags" "jerbuild" "exec" "shebang" "script" "loader") + ("title" + . + "jerbuild exec and jerboa script mode should skip a leading shebang line") + ("use_case" + . + "Running test suites and single-file scripts that carry a shebang for direct execution, without sed/tail preprocessing.") + ("votes" . 0)) + (("description" + . + "jerbuild installs and Makefile recipes copy binaries/dylibs in place (cp -f over existing files). On macOS arm64, overwriting a signed Mach-O while any process has it mapped poisons its code-signature pages: every process that maps it afterwards is SIGKILLed (ReportCrash fatal 309, CODESIGNING Invalid Page). With many long-lived jerboa processes (MCP server, TUIs, LSP) running, any rebuild kills them — and can kill the build itself when a dylib is refreshed mid-build. Copying to a temp file and rename(2)ing over the destination gives readers either the old or new vnode and eliminates the class.") + ("estimated_token_reduction" + . + "avoids multi-hour debugging detours; saves full build+diagnostic cycles") + ("example_scenario" + . + "make build's native-rs step cp -f's lib/libjerboa_native.dylib in place; the immediately following jerbuild compile loads it and is SIGKILLed; long-running jcode TUI processes die at the same moment.") + ("id" . "jerbuild-atomic-artifact-install") + ("impact" . "high") ("status" . "proposed") + ("tags" "macos" "codesigning" "build" "install" "atomic") + ("title" + . + "Write Mach-O artifacts atomically (tmp+rename) on macOS to avoid CODESIGNING Invalid Page kills") + ("use_case" + . + "Any jerboa/jerbuild install or native-dylib refresh on a macOS dev machine with running jerboa processes.") ("votes" . 0)))