Skip to content

v0.3.3: Treemacs workspace fixes, cache hardening, daemon-mode persistence#11

Merged
cuttlefisch merged 15 commits into
mainfrom
improvements
Mar 21, 2026
Merged

v0.3.3: Treemacs workspace fixes, cache hardening, daemon-mode persistence#11
cuttlefisch merged 15 commits into
mainfrom
improvements

Conversation

@cuttlefisch
Copy link
Copy Markdown
Owner

@cuttlefisch cuttlefisch commented Mar 21, 2026

Summary

  • Fix daemon-mode workspace persistence (0.3.3): In daemon mode, delete-frame-functions fires before kill-emacs-hook, destroying the frame's treemacs scope shelf. --sync-before-persist re-queried (treemacs-current-workspace), which fell back to the wrong workspace and overwrote the persisted name. Fixed by persisting immediately on workspace switch and removing the re-capture at shutdown.
  • 4 treemacs workspace bug fixes (0.3.0–0.3.1): args-out-of-range on stale cache structs, treemacs-with-workspace invalid function, scope shelf persistence, legacy YAML key support
  • Workspace enforcement overhaul (0.3.1): desired-state model is now the single source of truth — native treemacs fallback gated behind (not declarative-project-treemacs-mode), with advice functions that re-apply desired state on workspace switch/restore
  • Cache hardening (0.3.2): --read-cache handles corrupt and empty cache files gracefully; new reset-cache interactive command; declarative-project-treemacs-cache-file promoted to defcustom
  • FOSS standards polish: GPL-3.0 headers, Code of Conduct, CI matrix expanded to Emacs 30.1, deduplicated CI runs
  • 104 Buttercup specs (up from 32), including cache validation, workspace enforcement, and daemon-mode regression tests

Test plan

Automated (CI runs on Emacs 28.1, 29.4, 30.1, snapshot)

make test  # expect 104 specs, 0 failures

Manual — daemon-mode workspace persistence

  1. Start Emacs as daemon: emacs --daemon
  2. Connect with emacsclient -c, enable declarative-project-treemacs-mode
  3. Switch workspaces A → B → C
  4. Kill the daemon (M-x kill-emacs)
  5. Restart daemon + client — should show workspace C, not A

Manual — cache hardening

  1. M-x declarative-project-treemacs-reset-cache — should reset to Default workspace
  2. Create a 0-byte or garbage cache file and enable the mode — should recover without error

Manual — workspace assignment

  1. Open a .project file with a treemacs-workspaces entry
  2. Press C-c C-c i to install
  3. Open treemacs — the project should appear under the declared workspace with no duplicates

🤖 Generated with Claude Code

cuttlefisch and others added 13 commits March 20, 2026 22:46
- Replace all `warn` calls with `display-warning` using 'declarative-project
  type symbol, aligning source with existing test spies
- Remove tab characters from warning format strings
- Fix --unassign-project nil dereference: wrap workspace lookup in when-let
  so (treemacs-workspace->projects ws) is never called on nil
- Add ;;;###autoload cookie to declarative-project-mode and
  org-babel-execute:declarative-project for proper lazy-loading

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add `declarative-project-install` as public alias for the private
  `--install-project` interactive command; bind keymap to public name
- Add :package-version to both defcustom declarations
- Expand Commentary section with full .project field documentation
- Improve minor mode docstring and accessor function docstrings
- Delete legacy ERT test file (references removed API)
- Add .dir-locals.el for development settings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Expand test-helper.el with cl-defstruct stubs for treemacs-workspace
  and treemacs-project, plus with-treemacs-test-state macro
- Add test-declarative-project-treemacs.el covering:
  minimal-desired-state, ensure-desired-state, workspaces-by-name,
  save-cache/read-cache round-trip, assign-project (new ws, existing ws,
  dedup), unassign-project (happy path + nil regression), remove-workspace,
  prune-invalid-projects, override-workspaces, assign-declared-project
  (hook integration), and mode hook add/remove
- Update Makefile to load new test file
- Total: 52 specs, 0 failures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update Version header to 0.3.0 and Modified date in all three
  package files
- Update Package-Requires dependency versions in treemacs and ob modules
- Add CHANGELOG.org documenting 0.3.0 and reconstructed 0.2.0 history

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The treemacs-workspace struct gained an is-disabled? field, but old
cache entries (written with the 2-field layout) cause args-out-of-range
when treemacs tries to access the missing slot.

- Add --normalize-cache to re-create all workspace/project structs
  via their constructors after loading, so missing fields get defaults
- Call normalization from --read-cache after every load
- Add is-disabled? to workspace stub in test-helper (matches real treemacs)
- Add regression test: write old-layout cache, load, verify accessor works

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The pre-refactor code used `name`, `workspaces`, and `root-directory`
as YAML keys. All existing org-babel blocks and many .project files
still use these names. The refactored code only recognized
`project-name` and `treemacs-workspaces`, silently ignoring the
legacy variants.

- Accessor `declarative-project-workspaces`: fall back to `workspaces`
  key when `treemacs-workspaces` is absent
- Accessor `declarative-project-name`: fall back to `name` key when
  `project-name` is absent
- Accessor `declarative-project-root-directory`: fall back to
  `root-directory` key (expanded) when `project-root` is unset
- `--install-from-content`: use `root-directory` from parsed spec as
  project root, overriding the caller's project-dir fallback
- `--apply-treemacs-workspaces`: use accessors instead of direct
  gethash so alias resolution is applied consistently
- Add 8 new specs for alias behavior and root-directory override
- Update Commentary to document both key name variants

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
treemacs-with-workspace does not exist in treemacs — it was only
defined in our test stubs. Replace with a let-binding of
treemacs-override-workspace, which is the actual treemacs API for
temporarily setting the current workspace context.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After --override-workspaces replaces treemacs--workspaces with new
objects, treemacs's per-frame scope shelf still holds a stale reference
to the old workspace object. When treemacs checks its current workspace,
it uses this stale reference, can't find a matching project for the
current buffer's path, and falls back to directory browsing.

- --override-workspaces now looks up the current workspace by name in
  the desired state and updates the scope shelf via setf on
  treemacs-current-workspace
- Add treemacs-current-workspace stub with gv-setter to test-helper
- Add test verifying scope shelf update after override

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The install function's native treemacs code path was duplicating
workspace assignments when declarative-project-treemacs-mode was
active.  Gate the fallback behind (not declarative-project-treemacs-mode)
so the desired-state model is the single source of truth.

Add two advice functions (after treemacs-switch-workspace and
treemacs--restore) that re-apply desired state when treemacs
switches or restores workspaces.  Register/unregister them in
the minor mode body.

7 new specs cover the fallback guard, advice lifecycle, and
mode registration.  Total: 74 specs, all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add GPL-3.0 license headers to all secondary .el and test files
for proper compliance. Update CI to test against Emacs 30.1 and
add fail-fast: false for full version-specific regression visibility.
Update README spec count (74), add CHANGELOG 0.3.1 section, and
extend .gitignore with lock/autosave/autoload patterns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Contributor Covenant v2.1. Update Author/Maintainer email
to system.cuttle@gmail.com across all package headers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Promote --cache-file to public defcustom with framework-specific
guidance for Doom/Spacemacs users.  Harden --read-cache against
corrupt and empty cache files with condition-case fallback.

Add 8 new cache validation specs covering struct integrity, dedup,
multi-workspace project counts, unassign round-trip, corrupt/empty
file recovery, setq form validation, and normalization idempotency.

Update README with configuration table row, framework-specific setup
examples (Doom, Spacemacs, vanilla), and current spec count (96).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@cuttlefisch cuttlefisch changed the title v0.3.1: Treemacs workspace fixes, enforcement overhaul, FOSS polish v0.3.2: Treemacs workspace fixes, cache hardening, FOSS polish Mar 21, 2026
cuttlefisch and others added 2 commits March 21, 2026 15:22
The previous example used a separate use-package! on the sub-library
name with :after treemacs, which would prevent the core mode from
loading eagerly via find-file-hook. Use after! inside the main
use-package! block so core loads eagerly while treemacs integration
defers until treemacs is actually loaded.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In daemon mode, delete-frame-functions fires before kill-emacs-hook,
destroying the frame's treemacs scope shelf. --sync-before-persist then
re-queried (treemacs-current-workspace), which fell back to the wrong
workspace and overwrote --current-workspace-name.

Fix: persist name to disk immediately in --on-workspace-switch, and
remove the re-capture from --sync-before-persist. Bump to 0.3.3.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@cuttlefisch cuttlefisch changed the title v0.3.2: Treemacs workspace fixes, cache hardening, FOSS polish v0.3.3: Treemacs workspace fixes, cache hardening, daemon-mode persistence Mar 21, 2026
@cuttlefisch cuttlefisch merged commit 8055940 into main Mar 21, 2026
4 checks passed
@cuttlefisch cuttlefisch deleted the improvements branch March 21, 2026 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant