Skip to content

fix(SUP-3404): make journal backlinks Obsidian-owned - #97

Merged
levineam merged 3 commits into
mainfrom
SUP-3404/obsidian-owned-backlinks
Jul 14, 2026
Merged

fix(SUP-3404): make journal backlinks Obsidian-owned#97
levineam merged 3 commits into
mainfrom
SUP-3404/obsidian-owned-backlinks

Conversation

@levineam

@levineam levineam commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • Ports the merged clawd journal-backlink safety contract into the canonical jarvOS secondbrain module.
  • Applies new same-day backlinks through Obsidian Vault.process, preserving editor/mobile changes that arrive immediately before the mutation.
  • Keeps already-present links idempotent without requiring Obsidian.
  • Targets the configured vault before eval, verifies the link exists on disk, and fails visibly with a recovery record when Obsidian cannot commit.
  • Creates a missing current-day journal through Obsidian and preserves a concurrently created journal instead of overwriting it.
  • Serializes recovery-queue updates and commits them atomically without replacing malformed state.
  • Never falls back to an external whole-file write for today's active journal.

Verification

  • node --test modules/jarvos-secondbrain/tests/link-to-journal.test.js (13/13)
  • Full @jarvos/secondbrain suite (195/195)
  • git diff --check
  • Live read-only Obsidian probe confirmed Vault v3 and app.vault.process availability in the deployed environment.

Related

  • Upstream counterpart of levineam/clawd#784.
  • Tracked by SUP-3404.

@levineam

Copy link
Copy Markdown
Owner Author

@codex review
@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

@levineam I'll review the changes now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

linkNoteToJournal now routes today-journal updates through Obsidian-owned mutation, verifies committed links, preserves existing content on failure, and records deferred backlinks. Tests cover mutation routing, idempotency, CLI evaluation, recovery, and contract execution.

Changes

Journal mutation flow

Layer / File(s) Summary
Obsidian mutation helpers
modules/jarvos-secondbrain/bridge/provenance/src/link-to-journal.js
Adds Obsidian CLI evaluation, encoded mutation scripts, polling, result parsing, verification, safe persistence, deferred-backlink recording, and exports for the new helpers.
Linker routing and failure handling
modules/jarvos-secondbrain/bridge/provenance/src/link-to-journal.js
Validates note titles, normalizes sections, detects existing links, selects owned or filesystem mutation, returns mutationOwner, and queues failed backlinks.
Mutation behavior and recovery tests
modules/jarvos-secondbrain/tests/link-to-journal.test.js, modules/jarvos-secondbrain/tests/personality-note-journal-contract.test.js
Tests owned current-content updates, idempotency, Vault.process behavior, CLI invocation, failure recovery, and the unsafe test-write environment.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant linkNoteToJournal
  participant mutateJournalThroughObsidian
  participant ObsidianCLI
  participant DeferredBacklinks
  Caller->>linkNoteToJournal: request journal backlink
  linkNoteToJournal->>linkNoteToJournal: normalize section and inspect content
  linkNoteToJournal->>mutateJournalThroughObsidian: update today's journal
  mutateJournalThroughObsidian->>ObsidianCLI: run vault eval mutation
  ObsidianCLI-->>mutateJournalThroughObsidian: return mutation result
  mutateJournalThroughObsidian-->>linkNoteToJournal: verify committed backlink
  linkNoteToJournal-->>Caller: return link result
  linkNoteToJournal->>DeferredBacklinks: record failed backlink on error
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.56% 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
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately captures the main change: moving journal backlink mutations to Obsidian-owned writes.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch SUP-3404/obsidian-owned-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.

@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: 600bdfd75b

ℹ️ 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 thread modules/jarvos-secondbrain/bridge/provenance/src/link-to-journal.js
@levineam

Copy link
Copy Markdown
Owner Author

@codex review
@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

@levineam I'll review the changes now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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/bridge/provenance/src/link-to-journal.js`:
- Around line 50-60: Update readJsonSafe to use the fallback only for ENOENT
errors and propagate malformed JSON or other read failures; make
deferred-backlink read-modify-write operations serialized to prevent overlapping
updates; update writeJson to write through a same-directory temporary file and
atomically rename it into place, preserving existing corrupt state and queued
recovery entries.
- Around line 229-232: Update the missing-journal handling around the visible
existsSync/ensureJournalFile flow so active journals are created through the
Obsidian-owned transaction or mutation path instead of an external whole-file
write. Preserve the createIfMissing behavior and add a regression test covering
concurrent journal creation without overwriting content created between the
existence check and mutation.
🪄 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: f42e1124-5eee-4698-8e5b-cdc0a1eb37c9

📥 Commits

Reviewing files that changed from the base of the PR and between 0029224 and 600bdfd.

📒 Files selected for processing (3)
  • modules/jarvos-secondbrain/bridge/provenance/src/link-to-journal.js
  • modules/jarvos-secondbrain/tests/link-to-journal.test.js
  • modules/jarvos-secondbrain/tests/personality-note-journal-contract.test.js

Comment thread modules/jarvos-secondbrain/bridge/provenance/src/link-to-journal.js Outdated
Comment thread modules/jarvos-secondbrain/bridge/provenance/src/link-to-journal.js Outdated
@levineam

Copy link
Copy Markdown
Owner Author

The active-journal creation finding is also fixed at 46a8348: missing current-day journals are created through app.vault.create and then mutated with Vault.process; if another actor creates the file first, the code processes that latest file instead of overwriting it. The deterministic regression injects concurrent mobile content and proves it survives with the backlink.

Verification: focused 13/13; full secondbrain 195/195; git diff --check clean.

@codex review
@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
git fetch origin pull/97/head:pr97 2>&1 | tail -5
git checkout pr97 2>&1 | tail -5
git log --oneline -10
echo "---"
git show 46a8348 --stat 2>&1 | head -30

Length of output: 1430


🏁 Script executed:

#!/bin/bash
set -euo pipefail
git show 46a8348 -- modules/jarvos-secondbrain/bridge/provenance/src/link-to-journal.js

Length of output: 11438


🏁 Script executed:

#!/bin/bash
set -euo pipefail
git show 46a8348 -- modules/jarvos-secondbrain/tests/link-to-journal.test.js

Length of output: 4148


🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '1,400p' modules/jarvos-secondbrain/bridge/provenance/src/link-to-journal.js

Length of output: 14502


@levineam Verified the atomic-creation fix at 46a8348 directly in the diff:

  • obsidianMutationScript now attempts app.vault.getFileByPath first; if the journal is missing it calls app.vault.create(initialContent) and only then runs the Vault.process mutation. If create fails (e.g., because another actor — Obsidian sync/mobile — created the file first), it re-resolves the file via getFileByPath and processes that file instead of overwriting, which is exactly the "don't clobber concurrent creation" guarantee you described.
  • linkNoteToJournal correctly defers to ownedJournalMutator with a rendered initialContent instead of pre-creating the file itself when routing through Obsidian for today's journal — so the filesystem-side code never races Obsidian for journal creation.
  • The new test "a missing today journal is created inside the owned mutation without overwriting concurrent content" is a good deterministic regression: the mock mutator asserts the file doesn't exist yet, receives the rendered initialContent, injects "concurrent mobile creation" content mid-callback, and the assertions confirm both the concurrent content and the [[Owned Creation Backlink]] link survive in the final file.
  • Bonus: the added withDeferredQueueLock (exclusive lockfile with stale-lock reclaim) and atomic writeJson (temp file + rename) harden the deferred-backlink queue against concurrent writers, and the new "corrupt deferred queue is preserved instead of being replaced" test confirms readJsonSafe now rethrows non-ENOENT errors rather than silently clobbering a malformed queue file.

I don't see any correctness issues in this diff — the fix and its test coverage line up well with the stated finding. Nice work closing this race condition.

ᕦ(ò_óˇ)ᕤ

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@levineam
levineam merged commit f665902 into main Jul 14, 2026
7 checks passed
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 46a8348a82

ℹ️ 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".

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