diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-13 15:27:45 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-13 15:27:45 -0500 |
| commit | 94363181928da1d8693f71967949b795a315318a (patch) | |
| tree | 3b5532d0f51efd50f9244b63cf99f1c81ba9b675 | |
| parent | a603761fcebbf4df6182e3d5e9ef4bbd257bdb4c (diff) | |
| download | dotemacs-94363181928da1d8693f71967949b795a315318a.tar.gz dotemacs-94363181928da1d8693f71967949b795a315318a.zip | |
docs(claude): codify the cl-letf C-primitive native-comp trampoline trap
Mocking a C primitive (buffer-modified-p, file-exists-p, kill-buffer) via cl-letf triggers a native-comp trampoline rebuild that fails under --batch. Drive real state or extract a pure helper instead.
| -rw-r--r-- | CLAUDE.md | 2 |
1 files changed, 2 insertions, 0 deletions
@@ -91,3 +91,5 @@ Prefer Write over cumulative Edits for nontrivial new code. Small functions (und - **Manual-verification handoff: VERIFY child, close the originating task.** When a task's code is complete and the only thing left is Craig's hands-on check, don't leave the whole task stuck in DOING. File the manual check as a `VERIFY` child under the "Manual testing and validation" parent task, then close the originating task itself (DONE for a top-level task, or the dated-log rewrite for a sub-task, per `todo-format.md`). The VERIFY child carries the residual human check and surfaces in the agenda until Craig confirms; the implementation task is no longer held open by it. Replaces the prior habit of leaving the fixed task DOING with a `*** TODO` manual-test note under the parent. (`pattern` — 2026-06-13) - **`make test` runs with no `package-initialize` — defuns inside a `use-package :config` are void there.** The Makefile's `EMACS_TEST` is `emacs --batch --no-site-file --no-site-lisp` with no `package-initialize`, so elpa packages never load and a `use-package` block whose package isn't found never runs its `:config`. Any `defun` nested inside that `:config` is unbound under `make test` / `make test-file`. The per-edit PostToolUse hook *does* initialize packages, so such defuns load there — a test can pass on save under the hook yet fail `make test`. To unit-test logic that lives in a `:config` block, extract it into a top-level defun outside `use-package` (the `cj/dwim-shell--empty-dirs-command` / `cj/dwim-shell--dated-backup-command` pattern) and test that; keybindings or mode-wiring that must stay in `:config` get live-daemon verification instead. (`gotcha` — 2026-06-13) + +- **Don't `cl-letf`-mock C primitives in tests — it triggers a native-comp trampoline rebuild that fails under `--batch`.** Mocking a primitive like `buffer-modified-p`, `file-exists-p`, or `kill-buffer` via `cl-letf`/`fset` makes native-comp try to compile and load a trampoline `.eln`, which errors under `emacs --batch` (`native-lisp-load-failed "file does not exists" .../subr--trampoline-*.eln`, often after a "Redefining 'X' might break native compilation of trampolines" warning). Don't mock the primitive: drive the real state instead (a `make-temp-file` fixture so `file-exists-p` is true for real, `insert`/`set-buffer-modified-p` for modified state, `buffer-live-p` to detect a kill), or extract the decision logic into a pure helper and test that. Mocking ordinary Lisp functions (`y-or-n-p`, `save-buffer`, `info`) is fine — the trap is specific to subrs. (`gotcha` — 2026-06-13) |
