Skip to content

Pattern-driven pair renames for directory libraries (phase 5a) - #741

Open
koppor wants to merge 27 commits into
directory-groupsfrom
directory-pattern-renames
Open

koppor wants to merge 27 commits into
directory-groupsfrom
directory-pattern-renames

Conversation

@koppor

@koppor koppor commented Jul 14, 2026 •

Copy link
Copy Markdown
Member

📚 Directory-as-library stack — bottom → top, each builds on the one below:

  1. Programmatic Hayagriva writer (directory-as-library, phase 0) #736 · Hayagriva YAML writer
  2. Open folder as library (directory as library, phase 1) #737 · Open folder as library
  3. Live inbound sync for directory libraries (phase 2) #738 · Inbound file sync
  4. Write-back to Hayagriva sidecars (directory as library, phase 3) #739 · Write-back to sidecars
  5. Groups panel mirrors the directory structure (phase 4, #10930) #740 · Directory-structure groups
  6. Pattern-driven pair renames for directory libraries (phase 5a) #741 · Pattern-driven pair renames ← this PR
  7. Mirror directory libraries into a .bib with git-sync merge-back #743 · .bib mirror + merge-back
  8. Convert .bib libraries into directory libraries #744 · Convert .bib → directory
  9. Make directory libraries reachable through the REST API #745 · REST API support
  10. Split DirectoryLibrarySynchronizer into collaborators #760 · Split the synchronizer

Related issues and pull requests

Phase 5a of the "directory as library" plan (PLAN.md), stacked on #740 (base branch directory-groups). No issue is closed by this PR.

PR Description

🤖 In a directory library, a sidecar and its PDF are now renamed together as a pair, following the filename pattern from Preferences > Linked files. Editing an entry's citation key or title moves both files to the freshly generated name and updates the entry's link. Multi-entry files, occupied target names, and pattern failures leave the current names untouched, and files rename only when their entry is edited — never in bulk on open.

jabref-contrib-policy:4.2:reviewed​:ok

Analogies

Like honey and its wax cap, the paper and its metadata are sealed as one — lift one and the other comes along. Like two squares of chocolate still joined at the groove, the pair breaks off the bar together, never separately. And like the moon keeping the same face to the earth, sidecar and PDF stay tidally locked while both travel to their new name.

Steps to test

  1. Open a folder as library containing x.yml + x.pdf; set a filename pattern under Preferences > Linked files (e.g. [citationkey] - [fulltitle]).
  2. Change the entry's citation key (or title) in the entry editor.
  3. Within half a second both files carry the new generated name, the YAML key inside follows the citation key, and the entry's file link still resolves.

No visible UI change (the effect is on disk), hence no screenshot.

AI usage

Claude Code (model claude-fable-5).

AI CHECKLIST.md walkthrough

1. Code self-review

  • Optional chains for the generator; nullable JDK returns handled locally; no Objects.requireNonNull.
  • Only IOException caught; exceptions last in log calls; no RuntimeException/IllegalStateException.
  • Modern Java; injected Function seam; Markdown Javadoc; no commented-out code.
  • [/] User-facing text — none added.
  • [/] Security — no HTML output.
  • Tests: pair rename, occupied-target skip, multi-entry exemption; plain JUnit, @TempDir, deterministic.

2. Verification commands

  • ./gradlew :jablib:test (directory-library suite) and :jabgui:compileJava.
  • ./gradlew :jablib:checkstyleMain :jablib:checkstyleTest :jabgui:checkstyleMain.
  • ./gradlew traceRequirements (new req~directory-library.pattern-rename~1 covered).
  • ./gradlew --no-configuration-cache :rewriteDryRun — no changes.
  • npx markdownlint-cli2 on changed Markdown.
  • [/] IntelliJ-format docker image — not runnable on this machine; CI format job is the backstop.

3. Documentation

  • CHANGELOG.md entry (TODO replaced with this PR's link after creation).
  • Requirement req~directory-library.pattern-rename~1 added with impl marker.
  • [/] ADR — the pairing/rename rule is part of ADR-0072's design.

4. Pull request

  • Body from the template, all sections filled, HTML comments removed, created from a body file via gh api (stacked cross-repo).
  • CHANGELOG TODO replaced after creation, committed and pushed.

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • If AI tools were used, I disclosed them in the "AI usage" section and reviewed, understood, and take full ownership of all AI-generated code
  • I manually tested my changes in running JabRef (changed a citation key on the X display; both files were renamed to the configured pattern on disk and the sidecar content followed)
  • I added JUnit tests for changes (if applicable)
  • [/] I added screenshots in the PR description (if change is visible to the user)
  • [/] I added a screenshot in the PR description showing a library with a single entry with me as author and as title the issue number
  • I added one sentence (max 20 words) to CHANGELOG.md describing the change from the user's point of view (if the change is visible to the user)
  • I checked the user documentation for up to dateness and submitted a pull request to our user documentation repository — the docs PR is the next phase-5 step, covering the whole feature

🤖 Generated with Claude Code

koppor and others added 9 commits July 14, 2026 11:09
When write-back touches a single-entry sidecar, the sidecar and its
equally named PDF are renamed to the base name the filename pattern
(Linked files preferences) generates for the entry, keeping the pair
in sync — e.g. a citation-key edit renames both files to
"<key> - <title>". Multi-entry files keep their name, occupied targets
and pattern failures leave the current name untouched, and the entry's
file link and the catalog follow the rename so the watcher does not
re-import.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	jablib/src/main/java/org/jabref/logic/directorylibrary/DirectoryLibrarySynchronizer.java
An X.md sharing its base name with another found or linked file, or any
Markdown sidecar (Hayagriva frontmatter), is a notes companion of the
entry, not an attachment - auto-link must not pick it up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDcHNMt9fPWnpYaHheFvry
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDcHNMt9fPWnpYaHheFvry
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDcHNMt9fPWnpYaHheFvry
Both tab context menu actions were gated on a saved .bib path; a
directory library's root is just as revealable and terminal-openable.
NativeDesktop.openConsole now accepts a directory (opened itself) as
well as a file (opened at its parent, as before).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDcHNMt9fPWnpYaHheFvry
koppor and others added 9 commits September 3, 2026 03:24
Resync layer 6 of the stack (no conflicts).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDcHNMt9fPWnpYaHheFvry
…pair rename

The PDF is renamed first and rolled back if the sidecar cannot follow, so the pair never ends up half renamed; a target name that another entry's PDF or sidecar occupies is skipped; citation keys are cleaned before they become file names; the location-on-disk accessor replaces the repeated fallback chains.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vr3E1Gg5DRU4LQDDVnhPys
Treating every Markdown file next to an equally named file as a notes companion changed automatic file linking for all libraries; the Hayagriva frontmatter is the unambiguous signal, so only sidecars are skipped now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vr3E1Gg5DRU4LQDDVnhPys
Fixes the CI format check.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDcHNMt9fPWnpYaHheFvry
Update OpenConsoleActionTest to verify getPathOnDisk (the action now
resolves the database path through that helper).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDcHNMt9fPWnpYaHheFvry
Upstream added a 0071 ADR after this stack claimed the number, so the
MADR duplicate-ID check failed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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