Purpose: User-facing update workflow for DreamNodes - check, preview, summarize, and apply updates from peers. This is the UI/UX layer; actual sync logic lives in social-resonance-filter.
dreamnode-updater/
├── store/
│ └── slice.ts # Zustand state for update status
├── services/
│ ├── update-summary-service.ts # LLM-powered commit summaries
│ ├── collaboration-memory-service.ts # Accept/reject tracking per peer
│ ├── collaboration-memory-service.test.ts # Unit tests for memory service
│ ├── cherry-pick-workflow-service.ts # Preview/accept/reject orchestration
│ └── smart-merge-service.ts # Conflict resolution with search-replace merging
├── ui/
│ ├── cherry-pick-preview-modal.ts # Enhanced modal with per-commit selection
│ ├── interbrain-update-modal.ts # Simple all-or-nothing modal for self-updates
│ ├── conflict-resolution-modal.ts # Modal for resolving merge conflicts
│ ├── preview-banner.ts # Floating banner during preview mode
│ └── rejection-history-modal.ts # View and unreject previously rejected commits
├── scripts/
│ ├── setup-cherry-pick-test.sh # Bash script to create test environment
│ └── test-cherry-pick-services.ts # Integration test for services
├── docs/
│ └── collaboration-scenarios.md # Design scenarios and test scripts
├── commands.ts # DreamNode update commands
├── dreamer-update-commands.ts # Peer-centric batch update commands
├── collaboration-test-commands.ts # UI testing commands (setup/cleanup)
├── test-scenarios.ts # Test data generation for UI testing
├── index.ts # Barrel export
└── README.md
- Update workflow UI: Preview modal, accept/reject actions
- LLM summaries: Translates git commits to user-friendly descriptions
- Update state: Zustand slice for tracking which nodes have updates
- Decision presentation: Shows updates grouped by peer for user choice
- Network operations ->
social-resonance-filter(fetch, pull, push) - Submodule sync logic ->
social-resonance-filter(detection, update execution) - Coherence beacon parsing ->
coherence-beacon(relationship discovery) - Radicle CLI ->
social-resonance-filter(P2P plumbing)
export { registerUpdateCommands } from './commands';
export { registerDreamerUpdateCommands } from './dreamer-update-commands';
export { UpdateSummaryService } from './services/update-summary-service';
export { CherryPickPreviewModal } from './ui/cherry-pick-preview-modal';
export { InterBrainUpdateModal } from './ui/interbrain-update-modal';
export { createUpdatesSlice, type UpdatesSlice } from './store/slice';| Command | Description |
|---|---|
check-for-updates |
Check selected DreamNode for peer updates |
preview-updates |
Show update preview modal with LLM summary |
apply-updates |
Apply updates to selected DreamNode |
check-all-updates-from-dreamer |
Check all projects from selected peer |
Select a DreamNode and check for updates from all peer collaborators:
- Updates grouped by peer (Alice, Bob, Charlie sections)
- Each peer's commits summarized separately
- Accept/reject per peer or per commit
Select a Dreamer (peer) and sync all your shared projects with them:
- Iterates through all DreamNodes connected to that peer
- Reports which projects have updates available
- Complementary to the DreamNode-centric approach
User clicks "Check for Updates" on selected DreamNode
|
v
+---------------------------------------------+
| GitSyncService.fetchUpdates() |
| (from social-resonance-filter) |
+---------------------------------------------+
|
v
+---------------------------------------------+
| checkSubmoduleUpdatesFromNetwork() |
| (from social-resonance-filter) |
+---------------------------------------------+
|
v
+---------------------------------------------+
| Store result in Zustand |
| (enables visual update indicator) |
+---------------------------------------------+
|
v
User clicks "Preview Updates"
|
v
+---------------------------------------------+
| LLM generates user-friendly summary |
| (falls back to keyword parsing) |
+---------------------------------------------+
|
v
+---------------------------------------------+
| CherryPickPreviewModal shows: |
| - Summary of changes (on-demand AI) |
| - Commits grouped by peer |
| - Preview / Accept / Reject buttons |
+---------------------------------------------+
|
v
User clicks "Accept"
|
v
+---------------------------------------------+
| GitSyncService.pullUpdates() |
| (cherry-pick or fast-forward) |
+---------------------------------------------+
|
v
+---------------------------------------------+
| Check for coherence beacons |
| (hand off to coherence-beacon feature) |
+---------------------------------------------+
The updater implements a cherry-pick-only collaboration model where users selectively accept or reject commits from peers.
CollaborationMemoryService (services/collaboration-memory-service.ts)
- Tracks accepted/rejected commits per peer, per DreamNode
- Stores memory in
collaboration-memory.jsonwithin Dreamer nodes - Supports deduplication via original hash parsing (
cherry picked from commit <hash>) - Provides unreject capability for changing decisions
CherryPickWorkflowService (services/cherry-pick-workflow-service.ts)
- Orchestrates the preview/accept/reject workflow
- Stash-based preview: stash work → cherry-pick → explore → decide → restore
- Filters rejected commits from pending updates
- Groups commits by peer for UI display
| State | Storage | Resurfaces? |
|---|---|---|
| Pending | Not stored (implicit) | Yes |
| Previewing | In-memory only | N/A (transient) |
| Accepted | collaboration-memory.json |
No (merged) |
| Rejected | collaboration-memory.json |
No (can unreject) |
collaboration-memory.json lives in each Dreamer node:
{
"version": 1,
"dreamNodes": {
"<dreamnode-uuid>": {
"accepted": [
{ "originalHash": "...", "appliedHash": "...", "subject": "...", "relayedBy": [...] }
],
"rejected": [
{ "originalHash": "...", "subject": "...", "rejectedAt": 1234567890 }
]
}
}
}When Alice and Bob both relay Charlie's commit:
- Cherry-pick creates new hash, but
-xflag preserves original in message - Service parses
(cherry picked from commit <hash>)to deduplicate - UI shows commit once with "Relayed by: Alice, Bob"
Enhanced modal for the cherry-pick collaboration workflow (used for DreamNodes):
- Groups commits by peer (Dreamer)
- Checkboxes for individual commit selection
- Per-commit and per-peer accept/reject actions
- Preview mode: stash work → apply → explore → decide → restore
- On-demand AI summarization of selected commits
- Fixed footer with action buttons, scrollable content area
- Collapsible rejection history section
Simple all-or-nothing modal for InterBrain self-updates:
- Shows commit count and expandable commit list
- On-demand AI summarization
- "Update & Reload" pulls, builds, and reloads the plugin
- No granular commit selection (must accept all)
Floating banner that appears during preview mode:
- Non-modal - stays visible while user explores changes
- Shows commit count and stash status
- Quick access to Keep/Revert/Later actions
- Animates in/out smoothly
View and manage previously rejected commits:
- Lists all rejected commits with metadata
- Filter by peer
- Select multiple commits to unreject
- Unrejected commits will reappear as pending
When updating the InterBrain DreamNode (UUID 550e8400-e29b-41d4-a716-446655440000):
- Apply updates via git pull
- Run
npm run build - Auto-reload plugin
When a DreamNode has submodules that diverged from their standalone versions:
- Detect standalone->submodule commit difference (via social-resonance-filter)
- Present update dialog to user
- Apply updates via
updateSubmodulesFromStandalone()(social-resonance-filter)
For GitHub-cloned repos without push access:
- Warns about divergent branches
- Offers hard reset to remote (discards local changes)
Update checking is on-demand: user selects a node and triggers check. No batch checking on startup (removed for performance).
Testing follows a layered approach:
| Layer | What it tests | Location |
|---|---|---|
| Unit | Pure logic, hash parsing, deduplication | services/*.test.ts |
| UI Testing | Real Obsidian commands + git operations | Obsidian command palette |
Run with npm run test or npm run check-all.
CollaborationMemoryService (services/collaboration-memory-service.test.ts):
parseOriginalHash: Extracts original commit hash from cherry-pick messagesgetEffectiveOriginalHash: Returns canonical hash for deduplication- Hash deduplication scenarios: relay chains, multi-hop relays, direct vs relayed commits
- Memory file structure validation
Obsidian commands for end-to-end testing of the collaboration workflow:
| Command | Description |
|---|---|
setup-collaboration-test |
Creates test DreamNode with Bob/Charlie peer remotes |
cherry-pick-preview |
Opens CherryPickPreviewModal for selected node |
show-preview-banner-demo |
Demonstrates the floating preview banner |
show-rejection-history |
Opens RejectionHistoryModal |
cleanup-collaboration-test |
Removes all test directories |
Test Flow:
- Run "Setup Collaboration Test" - creates test environment in vault
- Select the test DreamNode (_collab-test-node)
- Run "Cherry-Pick Preview" - shows modal with real peer commits
- Interact with UI: accept Bob's commit, reject Charlie's
- Verify collaboration memory was updated correctly
- Run "Cleanup Collaboration Test" to remove test environment
What Setup Creates:
vault/
├── _collab-test-node/ # Test DreamNode (git repo, you are Alice)
│ └── .udd # Node metadata
├── _collab-test-peers/ # Peer bare repos
│ ├── bob-bare/ # Bob's remote (1 commit ahead)
│ └── charlie-bare/ # Charlie's remote (1 commit ahead)
└── _collab-test-dreamers/ # Dreamer nodes for memory storage
├── bob/ # Bob's Dreamer node
└── charlie/ # Charlie's Dreamer node
GitSyncService(social-resonance-filter) - Fetch/pull operationscheckSubmoduleUpdatesFromNetwork(social-resonance-filter) - Submodule detectionupdateSubmodulesFromStandalone(social-resonance-filter) - Submodule syncCoherenceBeaconService(coherence-beacon) - Relationship discovery after updatesClaudeProvider(conversational-copilot) - LLM summaries