README.adoc

June 23, 2026 · View on GitHub

= OSWatcher Procedures :repo: https://github.com/OSWatcher/oswatcher-procedures

Custom Neo4j stored procedures for https://github.com/OSWatcher[OSWatcher] — recursive tree diffing over the merkle graph.

These procedures are deployed as a JAR plugin into Neo4j and power the diff engine used by https://github.com/OSWatcher/neogit[neogit] and https://github.com/OSWatcher/oswatcher-plugins[oswatcher-plugins].

== Procedures

=== oswatcher.diffTreesRecursive

Recursively diffs two nodes in the OSWatcher merkle graph, yielding per-node change records.

[source,cypher]

CALL oswatcher.diffTreesRecursive( parent_label, // String: node label to traverse (e.g. 'Tree', 'Blob') base, // String|null: hash of the base node diffee, // String|null: hash of the diffee node base_path, // String: starting path prefix (e.g. '/') filter, // List: child labels to include (empty = all) max_depth, // Long: depth limit (-1 = unlimited) with_intermediates, // Boolean: include intermediate nodes status_filter // List: filter by status (empty = all except UNCHANGED) ) YIELD status, type, path, old_props, new_props

==== max_depth

[cols="1,3"] |=== | Value | Behaviour

| 0 | Compare nodes themselves only (no children) | 1 | Immediate children only | n | n levels deep | -1 | Unlimited recursion (default) |===

==== status_filter

[cols="1,3"] |=== | Value | Meaning

| NEW | Node exists only in diffee | MOD | Node exists in both with different hash | DEL | Node exists only in base | UNCHANGED | Node exists in both with same hash (opt-in only) |===

Empty list returns all statuses except UNCHANGED.

==== Examples

[source,cypher]

// Diff symbols between two Blobs (immediate children only) CALL oswatcher.diffTreesRecursive('Blob', 'hash1', 'hash2', '/', ['Symbol'], 1, false, []) YIELD status, path, old_props, new_props

// Full recursive filesystem tree diff CALL oswatcher.diffTreesRecursive('Tree', 'hash1', 'hash2', '/', [], -1, false, []) YIELD status, path

// Compare two nodes directly (git-log style, no recursion) CALL oswatcher.diffTreesRecursive('Tree', 'hash1', 'hash2', '/', [], 0, false, []) YIELD status, path

// Only show modified and new nodes CALL oswatcher.diffTreesRecursive('Tree', 'hash1', 'hash2', '/', [], -1, false, ['MOD', 'NEW']) YIELD status, path

== Building

Requires Java 17 and Maven 3.9+.

[source,bash]

./mvnw clean package

This produces target/oswatcher-procedures-1.0.0.jar. Deploy it to the plugins/ directory of your Neo4j instance and restart.

== Deployment

Download the latest JAR from https://github.com/OSWatcher/oswatcher-procedures/releases[Releases] and place it in your Neo4j plugins/ directory. No configuration beyond Neo4j's standard plugin loading is required.

== License

Apache License 2.0 — see link:LICENSE[LICENSE].