Skip to content

fix(SUP-1717): enforce durable note journal backlinks - #41

Merged
levineam merged 1 commit into
mainfrom
SUP-1717/durable-note-journal-backlinks
May 15, 2026
Merged

fix(SUP-1717): enforce durable note journal backlinks#41
levineam merged 1 commit into
mainfrom
SUP-1717/durable-note-journal-backlinks

Conversation

@levineam

@levineam levineam commented May 15, 2026

Copy link
Copy Markdown
Owner

Summary

  • Port durable note backlink enforcement into upstream jarvOS secondbrain provenance code
  • Canonicalize deprecated Notes Created requests to ## 📝 Notes and dedupe exact note bullets
  • Make journal-note-audit cover notes created or updated on the audited date, with legacy fallback only for pre-migration dates
  • Route Obsidian adapter note backlinks through the canonical provenance linker

Verification

  • npm test (modules/jarvos-secondbrain)
  • npm test (repo root bootstrap smoke)
  • git diff --check

Paperclip: SUP-1717

Summary by CodeRabbit

  • New Features

    • Journal files are now automatically created when linking notes (if missing).
    • Note links now standardize to the "📝 Notes" section.
  • Bug Fixes

    • Improved note linking to prevent duplicates and handle legacy journal sections gracefully.
    • Link insertion is now idempotent—repeated operations produce consistent results.
  • Tests

    • Added comprehensive test coverage for journal note auditing and linking functionality.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@levineam has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 56 minutes and 10 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9a1759bd-40bf-47e0-a36f-fdcba41648ef

📥 Commits

Reviewing files that changed from the base of the PR and between bccb863 and 19d6868.

📒 Files selected for processing (5)
  • modules/jarvos-secondbrain/adapters/obsidian/src/vault-storage-adapter.js
  • modules/jarvos-secondbrain/bridge/provenance/src/journal-note-audit.js
  • modules/jarvos-secondbrain/bridge/provenance/src/link-to-journal.js
  • modules/jarvos-secondbrain/tests/journal-note-audit.test.js
  • modules/jarvos-secondbrain/tests/link-to-journal.test.js
📝 Walkthrough

Walkthrough

This PR refactors journal note linking to canonicalize on a "📝 Notes" section while supporting legacy "🗂️ Notes Created" sections based on note dates. It updates the audit module with optional legacy fallback, refactors link insertion with new deduplication helpers and journal file creation, integrates the changes in the Obsidian vault adapter, and adds comprehensive test coverage for both audit and linking logic.

Changes

Journal Section Migration and Link Handling

Layer / File(s) Summary
Journal section preference constants and strategy
modules/jarvos-secondbrain/bridge/provenance/src/journal-note-audit.js
NOTES_HEADING constant introduces the canonical "📝 Notes" section and LEGACY_NOTES_CREATED_CUTOFF gates date-based legacy fallback; module documentation updated to reflect the new preferred section behavior.
Date-based note detection and flexible section extraction
modules/jarvos-secondbrain/bridge/provenance/src/journal-note-audit.js
findNotesForDate now matches notes by either createdAt or mtime against target dates; extractTrackedSection and findMissingLinks accept opts.allowLegacy to conditionally search the canonical or legacy section heading.
Link injection targeting and legacy-aware main logic
modules/jarvos-secondbrain/bridge/provenance/src/journal-note-audit.js
injectNoteLinks branches insertion logic based on which tracked section was extracted; main computes allowLegacy by comparing audited date against LEGACY_NOTES_CREATED_CUTOFF; exports updated to include NOTES_HEADING and LEGACY_NOTES_CREATED_CUTOFF.
Structured link manipulation and journal file creation
modules/jarvos-secondbrain/bridge/provenance/src/link-to-journal.js
New helpers normalize section names, locate heading ranges, build link regexes, and deduplicate links; linkNoteToJournal defaults createIfMissing to true, creates missing journals via config-driven rendering, delegates insertion to linkNoteInSection, and writes only on changes; three new helpers exported (normalizeSectionName, ensureJournalFile, linkNoteInSection).
Vault adapter integration with new link handler
modules/jarvos-secondbrain/adapters/obsidian/src/vault-storage-adapter.js
Adapter imports NOTES_HEADING and aliases the provenance linkNoteToJournal as linkNoteBacklinkToJournal; its linkNoteToJournal method rewrites to delegate to the aliased function and return result with canonical heading and wiki-link line format.
Comprehensive audit function test coverage
modules/jarvos-secondbrain/tests/journal-note-audit.test.js
Test setup with fresh-environment helper for environment-dependent behavior; tests verify canonical Notes section preference, optional legacy fallback toggling, section-targeted link injection, scoped missing-link detection, correct basename matching, and mtime-based note-date detection for both direct and materially updated files.
Link manipulation and journal creation test coverage
modules/jarvos-secondbrain/tests/link-to-journal.test.js
Unit tests for linkNoteInSection verify idempotent canonical insertion, section canonicalization, and deduplication across legacy/modern sections; integration test for linkNoteToJournal confirms file creation, link idempotency, correct journal-date frontmatter, and cleanup.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🐰 Through the journal's pages we hop,
From "Notes Created" to "Notes" we stop,
With legacy links and dates aligned,
A canonical section—oh, so refined!
Deduplicate, modernize, test with care,
The second brain now breathes fresher air! 🧠✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: enforcing durable note journal backlinks, which is the core objective across all modified modules.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch SUP-1717/durable-note-journal-backlinks

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bccb863843

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +133 to +134
const fs = require('node:fs');
const os = require('node:os');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove duplicate test imports that block the suite

When running npm test --prefix modules/jarvos-secondbrain, Node fails to parse this file with SyntaxError: Identifier 'fs' has already been declared because fs and os were already declared at the top of the test file. This prevents the entire journal-note-audit.test.js file from running, so the package test suite fails before it reaches these new assertions.

Useful? React with 👍 / 👎.

@levineam
levineam force-pushed the SUP-1717/durable-note-journal-backlinks branch from bccb863 to 19d6868 Compare May 15, 2026 17:13

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modules/jarvos-secondbrain/adapters/obsidian/src/vault-storage-adapter.js`:
- Around line 160-167: The function linkNoteToJournal is passing the
caller-supplied heading into linkNoteBacklinkToJournal (section: heading) while
returning heading: NOTES_HEADING, which allows backlinks to be written to a
non-canonical section; change the call to linkNoteBacklinkToJournal to pass
section: NOTES_HEADING (i.e., enforce NOTES_HEADING in the write path) and keep
returning heading: NOTES_HEADING so both the write and returned metadata
consistently use NOTES_HEADING; update any related local variables in
linkNoteToJournal that reference heading to use NOTES_HEADING to avoid
confusion.

In `@modules/jarvos-secondbrain/bridge/provenance/src/link-to-journal.js`:
- Around line 130-133: The filter logic for cleanedSection is keeping standalone
'-' placeholders when sectionHadLink is true; update the predicate in the
sectionLines.filter used to build cleanedSection (the function referencing
exactLinkLine and sectionHadLink) so that any line where line.trim() === '-' is
filtered out unconditionally (remove the conditional check on sectionHadLink)
while still preserving the existing exactLinkLine check, ensuring dangling
bullet placeholders are removed even if a matching link exists.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e740e502-df2e-4980-9d7e-9975f950324a

📥 Commits

Reviewing files that changed from the base of the PR and between 97f2177 and bccb863.

📒 Files selected for processing (5)
  • modules/jarvos-secondbrain/adapters/obsidian/src/vault-storage-adapter.js
  • modules/jarvos-secondbrain/bridge/provenance/src/journal-note-audit.js
  • modules/jarvos-secondbrain/bridge/provenance/src/link-to-journal.js
  • modules/jarvos-secondbrain/tests/journal-note-audit.test.js
  • modules/jarvos-secondbrain/tests/link-to-journal.test.js

Comment on lines +160 to 167
linkNoteToJournal({ noteTitle, date = todayDate(), heading = NOTES_HEADING }) {
if (!noteTitle) throw new Error('noteTitle is required');
return this.appendLineToJournalSection({
heading,
const journalPath = path.join(getVaultJournalDir(), `${date}.md`);
const result = linkNoteBacklinkToJournal({ noteTitle, section: heading, journalPath });
return {
...result,
heading: NOTES_HEADING,
line: `- [[${noteTitle}]]`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Force canonical heading in the write path, not only in the returned metadata.

heading is still forwarded to section, so callers can write backlinks outside canonical Notes while the return object reports heading: NOTES_HEADING. This breaks canonical enforcement and creates misleading results.

Suggested patch
     linkNoteToJournal({ noteTitle, date = todayDate(), heading = NOTES_HEADING }) {
       if (!noteTitle) throw new Error('noteTitle is required');
       const journalPath = path.join(getVaultJournalDir(), `${date}.md`);
-      const result = linkNoteBacklinkToJournal({ noteTitle, section: heading, journalPath });
+      const result = linkNoteBacklinkToJournal({
+        noteTitle,
+        section: NOTES_HEADING,
+        journalPath,
+      });
       return {
         ...result,
         heading: NOTES_HEADING,
         line: `- [[${noteTitle}]]`,
       };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/jarvos-secondbrain/adapters/obsidian/src/vault-storage-adapter.js`
around lines 160 - 167, The function linkNoteToJournal is passing the
caller-supplied heading into linkNoteBacklinkToJournal (section: heading) while
returning heading: NOTES_HEADING, which allows backlinks to be written to a
non-canonical section; change the call to linkNoteBacklinkToJournal to pass
section: NOTES_HEADING (i.e., enforce NOTES_HEADING in the write path) and keep
returning heading: NOTES_HEADING so both the write and returned metadata
consistently use NOTES_HEADING; update any related local variables in
linkNoteToJournal that reference heading to use NOTES_HEADING to avoid
confusion.

Comment on lines +130 to +133
const cleanedSection = sectionLines.filter((line) => {
if (exactLinkLine.test(line)) return false;
if (!sectionHadLink && line.trim() === '-') return false;
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove standalone - placeholders even when the link is already present.

When a section contains both a placeholder - and an existing matching link, reruns keep the placeholder, leaving a dangling bullet in ## 📝 Notes.

Suggested patch
   const cleanedSection = sectionLines.filter((line) => {
     if (exactLinkLine.test(line)) return false;
-    if (!sectionHadLink && line.trim() === '-') return false;
+    if (line.trim() === '-') return false;
     return true;
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const cleanedSection = sectionLines.filter((line) => {
if (exactLinkLine.test(line)) return false;
if (!sectionHadLink && line.trim() === '-') return false;
return true;
const cleanedSection = sectionLines.filter((line) => {
if (exactLinkLine.test(line)) return false;
if (line.trim() === '-') return false;
return true;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/jarvos-secondbrain/bridge/provenance/src/link-to-journal.js` around
lines 130 - 133, The filter logic for cleanedSection is keeping standalone '-'
placeholders when sectionHadLink is true; update the predicate in the
sectionLines.filter used to build cleanedSection (the function referencing
exactLinkLine and sectionHadLink) so that any line where line.trim() === '-' is
filtered out unconditionally (remove the conditional check on sectionHadLink)
while still preserving the existing exactLinkLine check, ensuring dangling
bullet placeholders are removed even if a matching link exists.

@levineam
levineam merged commit 7c59aad into main May 15, 2026
6 checks passed
@levineam
levineam deleted the SUP-1717/durable-note-journal-backlinks branch May 15, 2026 18:09
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