Add Neo4j graph output (--emit neo4j)#4
Merged
Merged
Conversation
Projects the in-memory TSApplication to a labeled property graph and writes it either as a self-contained graph.cypher snapshot or, with --neo4j-uri, pushes it incrementally to a live Neo4j over Bolt. JSON output is unchanged and stays the default. Drops the msgpack output format and adds neo4j-driver. All new code lives under src/build/neo4j/ (projection + snapshot writer + bolt writer); emit() gains a third branch and is now async. Closes #3.
Adds a declarative schema catalog (single source of truth) with a SCHEMA_VERSION stamped onto the :Application node, a `cants --emit schema` target that writes schema.json, and a checked-in schema.neo4j.json (regenerate with `bun gen:schema`). A conformance test asserts the emitter never produces a label, relationship, or property the catalog doesn't declare, and that the checked-in schema.json is current. Adds a @testcontainers/neo4j integration test for the bolt writer (full push, idempotency, prune). Packaging: build_wheels.sh emits schema.json next to the binary so it ships in each wheel; codeanalyzer_typescript.schema_path() exposes it; the release workflow also publishes schema.json as a GitHub Release asset.
Rewrites the README in the standard layout — centered logo + badges, a table of contents, Features, Installation, Usage, and Output targets (analysis.json / Neo4j / schema) — and drops the removed msgpack docs. Adds a one-line shell installer (packaging/install/cants-installer.sh), published as a release asset, so users can: curl -LsSf .../releases/latest/download/cants-installer.sh | sh Keeps generated docs from drifting: `bun gen:readme` injects the live `cants --help` between markers (via an extracted buildProgram()), and the release workflow regenerates the README help block + schema.json and commits them before publishing. PyPI now renders the repo root README: build_wheels.sh copies it into the wheel package at build time (gitignored, single source of truth), so the stale packaging README is removed.
Gates the container-backed bolt suite behind RUN_CONTAINER_TESTS so the release gate's `bun test` skips it — no Docker image pull, and no flake that could trip the "delete tag on failure" step. Run it locally with `bun run test:container`. The no-container schema conformance test still runs by default.
Removed width attribute from logo image in README.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a Neo4j graph as a first-class output of the analyzer, alongside the existing
analysis.json. The analysis engine is unchanged — this is a new output path plus the schema, tests, docs, and packaging around it.Output targets (
--emit)json(default, unchanged) — the canonicalanalysis.jsonthe Python SDK parses.neo4j— projects the in-memoryTSApplicationinto a labeled property graph:--neo4j-uri: writes a self-containedgraph.cyphersnapshot (constraints + indexes, a scoped wipe, then batchedMERGE).--neo4j-uri: pushes to a live Neo4j over Bolt incrementally — only modules whose content hash changed are rewritten, and modules whose source file vanished are pruned on a full run.schema— writes the machine-readable Neo4j schema contract (schema.json); needs no project.Graph model
:Symbollabel (one uniqueness constraint, one endpoint index); specific labels (:Class,:Callable,:Interface, …) are layered on top.DECLARES,HAS_METHOD,HAS_ATTRIBUTE,DECLARES_VAR,HAS_CALLSITE,EXTENDS,IMPLEMENTS,CALLS,RESOLVES_TO,IMPORTS,RE_EXPORTS,MEMBER_OF,DECORATED_BY.schema_versionis stamped on the:Applicationnode for runtime producer/consumer drift detection.Schema contract + anti-drift
src/build/neo4j/catalog.tsis the single source of truth (labels, relationships, typed properties, constraints, indexes,SCHEMA_VERSION).--emit schemaserializes it; the checked-inschema.neo4j.jsonis regenerated withbun gen:schema.Install + distribution
packaging/install/cants-installer.sh) published as a release asset:curl … /releases/latest/download/cants-installer.sh | sh.schema.jsonis bundled in each wheel and published as a release asset;codeanalyzer_typescript.schema_path()exposes it.Docs
cants --helpblock is kept in sync with the CLI viabun gen:readmeand regenerated at release time.Tests
@testcontainers/neo4jintegration test for the bolt writer (full push, idempotency, prune) — opt-in viaRUN_CONTAINER_TESTS/bun run test:container, so the release gate stays fast and flake-free.Breaking
msgpackoutput format (-f/--format);--emitreplaces it.Closes #3.