This commit is contained in:
Ingo Schnabel
2026-06-13 13:35:02 +02:00
parent 162cd119f9
commit de6176ed64
44 changed files with 1230 additions and 2 deletions

9
.claudeignore Normal file
View File

@@ -0,0 +1,9 @@
# =============================================
# .claudeignore – Optimierte Version für peakUp (Pro Plan)
# Ziel: Minimale automatische Datei-Reads + niedrige Burn-Rate
# =============================================
target/
*.class
*.iml
mvnw
mvnw.cmd

10
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,10 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

15
.idea/checkstyle-idea.xml generated Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CheckStyle-IDEA" serialisationVersion="2">
<checkstyleVersion>13.5.0</checkstyleVersion>
<scanScope>JavaOnly</scanScope>
<option name="thirdPartyClasspath" />
<option name="activeLocationIds" />
<option name="locations">
<list>
<ConfigurationLocation id="bundled-sun-checks" type="BUNDLED" scope="All" description="Sun Checks">(bundled)</ConfigurationLocation>
<ConfigurationLocation id="bundled-google-checks" type="BUNDLED" scope="All" description="Google Checks">(bundled)</ConfigurationLocation>
</list>
</option>
</component>
</project>

55
.idea/compiler.xml generated Normal file
View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Annotation profile for AgenticCode" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<processorPath useClasspath="false">
<entry name="$USER_HOME$/.m2/my-repo/com/google/errorprone/error_prone_core/2.36.0/error_prone_core-2.36.0.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/errorprone/error_prone_annotation/2.36.0/error_prone_annotation-2.36.0.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/errorprone/error_prone_type_annotations/2.36.0/error_prone_type_annotations-2.36.0.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/errorprone/error_prone_check_api/2.36.0/error_prone_check_api-2.36.0.jar" />
<entry name="$USER_HOME$/.m2/my-repo/io/github/java-diff-utils/java-diff-utils/4.12/java-diff-utils-4.12.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/github/kevinstern/software-and-algorithms/1.0/software-and-algorithms-1.0.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/github/ben-manes/caffeine/caffeine/3.0.5/caffeine-3.0.5.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/googlejavaformat/google-java-format/1.19.1/google-java-format-1.19.1.jar" />
<entry name="$USER_HOME$/.m2/my-repo/org/pcollections/pcollections/4.0.1/pcollections-4.0.1.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/guava/guava/32.1.1-jre/guava-32.1.1-jre.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
<entry name="$USER_HOME$/.m2/my-repo/org/checkerframework/checker-qual/3.33.0/checker-qual-3.33.0.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/j2objc/j2objc-annotations/2.8/j2objc-annotations-2.8.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/auto/auto-common/1.2.2/auto-common-1.2.2.jar" />
<entry name="$USER_HOME$/.m2/my-repo/io/github/eisop/dataflow-errorprone/3.41.0-eisop1/dataflow-errorprone-3.41.0-eisop1.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/auto/value/auto-value-annotations/1.9/auto-value-annotations-1.9.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/errorprone/error_prone_annotations/2.36.0/error_prone_annotations-2.36.0.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/protobuf/protobuf-java/3.25.5/protobuf-java-3.25.5.jar" />
<entry name="$USER_HOME$/.m2/my-repo/com/google/auto/service/auto-service-annotations/1.0.1/auto-service-annotations-1.0.1.jar" />
<entry name="$USER_HOME$/.m2/my-repo/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" />
<entry name="$USER_HOME$/.m2/my-repo/javax/inject/javax.inject/1/javax.inject-1.jar" />
</processorPath>
<module name="parser-natural" />
<module name="neo4j-store" />
<module name="common" />
<module name="parser-core" />
<module name="package-info-maven-plugin" />
<module name="api-server" />
<module name="parser-java" />
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="api-server" options="-parameters -XDcompilePolicy=simple --should-stop=ifError=FLOW -Xplugin:ErrorProne -Xpkginfo:always" />
<module name="common" options="-parameters -XDcompilePolicy=simple --should-stop=ifError=FLOW -Xplugin:ErrorProne -Xpkginfo:always" />
<module name="neo4j-store" options="-parameters -XDcompilePolicy=simple --should-stop=ifError=FLOW -Xplugin:ErrorProne -Xpkginfo:always" />
<module name="package-info-maven-plugin" options="-parameters -XDcompilePolicy=simple --should-stop=ifError=FLOW -Xplugin:ErrorProne -Xpkginfo:always" />
<module name="parser-core" options="-parameters -XDcompilePolicy=simple --should-stop=ifError=FLOW -Xplugin:ErrorProne -Xpkginfo:always" />
<module name="parser-java" options="-parameters -XDcompilePolicy=simple --should-stop=ifError=FLOW -Xplugin:ErrorProne -Xpkginfo:always" />
<module name="parser-natural" options="-parameters -XDcompilePolicy=simple --should-stop=ifError=FLOW -Xplugin:ErrorProne -Xpkginfo:always" />
</option>
</component>
</project>

21
.idea/encodings.xml generated Normal file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/api-server/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/api-server/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/common/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/neo4j-store/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/neo4j-store/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/package-info-maven-plugin/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/package-info-maven-plugin/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/parser-core/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/parser-core/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/parser-java/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/parser-java/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/parser-natural/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/parser-natural/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

20
.idea/jarRepositories.xml generated Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>

16
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="Quarkus" url="file://$PROJECT_DIR$/api-server" />
<file type="Quarkus" url="file://$PROJECT_DIR$/neo4j-store" />
</component>
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" default="true" project-jdk-name="temurin-25" project-jdk-type="JavaSDK" />
</project>

10
.idea/sonarlint.xml generated Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SonarLintProjectSettings">
<option name="fileExclusions">
<list>
<option value="GLOB:src/main/**" />
</list>
</option>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

11
.mvn/jvm.config Normal file
View File

@@ -0,0 +1,11 @@
--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED

View File

@@ -110,7 +110,7 @@ docker run -p 7474:7474 -p 7687:7687 \
### General
- Use Java 21 features: Records for DTOs/value objects, Sealed Classes for AST node types, Pattern Matching
- No `null` returns: use `Optional<T>` or empty collections
- Non-null is the default (enforced by NullAway, packages annotated `@NullMarked`). Avoid `Optional` for fields, parameters, and most return types — use `@org.jspecify.annotations.Nullable` only where a value can genuinely be absent. Prefer empty collections over `Optional<List<T>>`.
- Immutable by default: prefer Records over mutable classes
- Logging: `org.jboss.logging.Logger` (Quarkus standard) — no `System.out`

182
README.md
View File

@@ -1,2 +1,182 @@
# agenticCode
# AgenticCode
> AI-agent-optimized code analysis platform — parse, store, enrich, and query source code as a graph.
AgenticCode ingests source code (Natural/Software AG and Java), parses it into a unified AST, persists it in Neo4j, enriches it with semantic information (call graphs, DB accesses, data structures), and exposes everything through an agent-ready REST + MCP API.
---
## Architecture
```mermaid
flowchart TD
subgraph Sources["Source Files"]
N([Natural\nSoftware AG])
J([Java])
PY([Python\n_planned_])
CB([COBOL\n_planned_])
end
subgraph Parsers["Parser Layer"]
NP["NaturalParser\n<i>custom implementation</i>"]
JP["JavaParser\n<i>com.github.javaparser</i>"]
PI["LanguageParser SPI\n<i>shared interface + unified AST schema</i>"]
end
subgraph Store["AST Store"]
NEO[("Neo4j 5.x\nGraph Database\nModules · Functions · Variables\nData Structures · DB Tables")]
end
subgraph Enrichment["Enrichment Layer"]
CG["CallGraphEnricher\nPERFORM / CALLNAT → CALLS edges"]
DB["DbAccessEnricher\nREAD / FIND / STORE → READS / WRITES edges"]
ID["IdentifierIndexEnricher\ncross-module variable index"]
DS["DataStructureEnricher\nDEFINE DATA → USES_TYPE edges"]
end
subgraph API["Agentic API — Quarkus"]
REST["REST API\nJAX-RS · RESTEasy Reactive"]
MCP["MCP Endpoint\ntool-use optimized"]
end
subgraph Agents["AI Agents"]
AG(["Claude / LLM Agent\ncall graph · DB access · identifier search\ncode generation · program analysis"])
end
N --> NP
J --> JP
PY --> PI
CB --> PI
NP --> PI
JP --> PI
PI --> NEO
NEO --> CG & DB & ID & DS
CG & DB & ID & DS --> REST
CG & DB & ID & DS --> MCP
REST --> AG
MCP --> AG
```
---
## Key API Tools (Agent-Facing)
| Endpoint | Description |
|---|---|
| `POST /api/ingest` | Parse and ingest source files into the graph |
| `GET /api/modules/{name}/callers` | Who calls this module? |
| `GET /api/modules/{name}/callees` | What does this module call? |
| `GET /api/modules/{name}/db-accesses` | DB tables accessed and mode (READ/WRITE) |
| `GET /api/search/identifier?name=` | Find an identifier across all modules |
| `MCP tools/*` | All of the above as MCP tool-use endpoints |
---
## Tech Stack
| Component | Technology |
|---|---|
| Server | [Quarkus](https://quarkus.io) (latest stable) |
| Language | Java 21 — Records, Sealed Classes, Virtual Threads |
| Graph DB | Neo4j 5.x via `neo4j-java-driver` |
| REST | RESTEasy Reactive (JAX-RS) |
| Natural Parser | Custom implementation |
| Java Parser | [JavaParser](https://javaparser.org) |
| Tests | JUnit 5 + RestAssured + Testcontainers |
| Build | Maven (multi-module) |
---
## Neo4j Graph Schema
```mermaid
erDiagram
MODULE ||--o{ FUNCTION : CONTAINS
FUNCTION ||--o{ FUNCTION : CALLS
FUNCTION ||--o{ VARIABLE : READS
FUNCTION ||--o{ VARIABLE : WRITES
FUNCTION ||--o{ DB_TABLE : READS
FUNCTION ||--o{ DB_TABLE : WRITES
FUNCTION ||--o{ DATA_STRUCTURE : USES_TYPE
MODULE {
string id
string name
string language
string sourceFile
}
FUNCTION {
string id
string name
int startLine
int endLine
}
VARIABLE {
string id
string name
string dataType
}
DATA_STRUCTURE {
string id
string name
string scope
}
DB_TABLE {
string id
string name
string dbType
}
```
---
## Project Structure
```
agenticcode/
├── api-server/ # Quarkus application (REST + MCP)
├── parser-core/ # Shared AST model + LanguageParser SPI
├── parser-natural/ # Custom Natural/Software AG parser
├── parser-java/ # Java parser (JavaParser-based)
├── neo4j-store/ # Neo4j persistence + Cypher queries
└── docs/
├── ast-schema.md
├── natural-grammar.md
├── api-endpoints.md
└── enrichment-pipelines.md
```
---
## Getting Started
**Prerequisites:** Java 21+, Maven 3.9+, Docker
```bash
# Clone and build
git clone https://github.com/your-org/agenticcode.git
cd agenticcode
mvn clean install
# Start Neo4j
docker run -p 7474:7474 -p 7687:7687 \
-e NEO4J_AUTH=neo4j/agenticcode \
neo4j:5
# Run in dev mode (hot reload)
cd api-server && mvn quarkus:dev
```
The API is available at `http://localhost:8080/api` and the Neo4j browser at `http://localhost:7474`.
---
## Supported Languages
| Language | Status | Parser |
|---|---|---|
| Natural (Software AG) | 🚧 In development | Custom |
| Java | 🚧 In development | JavaParser |
| Python | 📋 Planned | — |
| COBOL | 📋 Planned | — |
---

6
agenticcode-parent.iml Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="CheckStyle-IDEA-Module" serialisationVersion="2">
<option name="activeLocationsIds" />
</component>
</module>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="CheckStyle-IDEA-Module" serialisationVersion="2">
<option name="activeLocationsIds" />
</component>
</module>

106
api-server/pom.xml Normal file
View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agenticcode</groupId>
<artifactId>agenticcode-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>api-server</artifactId>
<packaging>jar</packaging>
<name>api-server</name>
<description>Quarkus application exposing the agentic source code API</description>
<dependencies>
<dependency>
<groupId>com.agenticcode</groupId>
<artifactId>parser-core</artifactId>
</dependency>
<dependency>
<groupId>com.agenticcode</groupId>
<artifactId>parser-natural</artifactId>
</dependency>
<dependency>
<groupId>com.agenticcode</groupId>
<artifactId>parser-java</artifactId>
</dependency>
<dependency>
<groupId>com.agenticcode</groupId>
<artifactId>neo4j-store</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.platform.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.agenticcode</groupId>
<artifactId>package-info-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,5 @@
/**
* JAX-RS resources exposing the agentic source code API.
*/
@org.jspecify.annotations.NullMarked
package com.agenticcode.apiserver.api;

View File

@@ -0,0 +1,5 @@
/**
* Enrichment pipelines that run after AST ingest to add semantic information.
*/
@org.jspecify.annotations.NullMarked
package com.agenticcode.apiserver.enrichment;

View File

@@ -0,0 +1,5 @@
/**
* MCP tool endpoints for AI agent integration.
*/
@org.jspecify.annotations.NullMarked
package com.agenticcode.apiserver.mcp;

View File

@@ -0,0 +1,5 @@
/**
* Business logic services (ingest, call graph, enrichment orchestration).
*/
@org.jspecify.annotations.NullMarked
package com.agenticcode.apiserver.service;

View File

@@ -0,0 +1,14 @@
# Neo4j connection
quarkus.neo4j.uri=bolt://localhost:7687
quarkus.neo4j.authentication.username=neo4j
quarkus.neo4j.authentication.password=agenticcode
# Dev profile
%dev.quarkus.neo4j.uri=bolt://localhost:7687
%dev.quarkus.neo4j.authentication.username=neo4j
%dev.quarkus.neo4j.authentication.password=agenticcode
# Prod profile - override via environment variables
%prod.quarkus.neo4j.uri=${NEO4J_URI:bolt://neo4j:7687}
%prod.quarkus.neo4j.authentication.username=${NEO4J_USER:neo4j}
%prod.quarkus.neo4j.authentication.password=${NEO4J_PASSWORD}

6
common/common.iml Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="CheckStyle-IDEA-Module" serialisationVersion="2">
<option name="activeLocationsIds" />
</component>
</module>

48
common/pom.xml Normal file
View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agenticcode</groupId>
<artifactId>agenticcode-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>common</artifactId>
<packaging>jar</packaging>
<name>common</name>
<description>Shared utility classes used across modules</description>
<dependencies>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.agenticcode</groupId>
<artifactId>package-info-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,2 @@
@org.jspecify.annotations.NullMarked
package com.agenticcode.common.util;

61
neo4j-store/pom.xml Normal file
View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agenticcode</groupId>
<artifactId>agenticcode-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>neo4j-store</artifactId>
<packaging>jar</packaging>
<name>neo4j-store</name>
<description>Neo4j persistence and queries for the unified AST graph</description>
<dependencies>
<dependency>
<groupId>com.agenticcode</groupId>
<artifactId>parser-core</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.neo4j</groupId>
<artifactId>quarkus-neo4j</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.agenticcode</groupId>
<artifactId>package-info-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,5 @@
/**
* Neo4j persistence and Cypher queries for the unified AST graph.
*/
@org.jspecify.annotations.NullMarked
package com.agenticcode.neo4jstore.graph;

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="CheckStyle-IDEA-Module" serialisationVersion="2">
<option name="activeLocationsIds" />
</component>
</module>

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agenticcode</groupId>
<artifactId>agenticcode-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>package-info-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<name>package-info-maven-plugin</name>
<description>Generates @NullMarked package-info.java files for packages missing one</description>
<properties>
<maven-plugin-api.version>3.9.9</maven-plugin-api.version>
<maven-plugin-annotations.version>3.13.1</maven-plugin-annotations.version>
<maven-plugin-plugin.version>3.13.1</maven-plugin-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${maven-plugin-api.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>${maven-plugin-annotations.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>${maven-plugin-plugin.version}</version>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,89 @@
package com.agenticcode.packageinfo;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.jspecify.annotations.Nullable;
/**
* Generates package-info.java files annotated with {@code @NullMarked}
* for all packages that contain Java source files but no package-info.java yet.
*/
@Mojo(name = "generate-package-info", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true)
public class PackageInfoGeneratorMojo extends AbstractMojo {
private static final String ANNOTATION = "@org.jspecify.annotations.NullMarked";
@Parameter(defaultValue = "${project.build.sourceDirectory}", required = true)
private File sourceDirectory;
@Override
public void execute() throws MojoExecutionException {
if (!sourceDirectory.exists()) {
getLog().info("Source directory does not exist, skipping: " + sourceDirectory);
return;
}
final Path sourceRoot = sourceDirectory.toPath().toAbsolutePath().normalize();
getLog().info("Generating package-info.java files in: " + sourceRoot);
try (Stream<Path> stream = Files.walk(sourceRoot)) {
stream.filter(Files::isDirectory)
.forEach(directory -> processDirectory(sourceRoot, directory));
} catch (IOException exception) {
throw new MojoExecutionException("Failed to walk source directory: " + sourceRoot, exception);
}
}
private void processDirectory(Path sourceRoot, Path currentDir) {
try (Stream<Path> files = Files.list(currentDir)) {
boolean hasJavaFiles = files.anyMatch(path ->
path.toString().endsWith(".java") && !path.getFileName().toString().equals("package-info.java")
);
if (hasJavaFiles) {
String packageName = determinePackageName(sourceRoot, currentDir);
if (packageName != null) {
createPackageInfo(currentDir, packageName);
}
}
} catch (IOException exception) {
getLog().warn("Failed to process directory " + currentDir + ": " + exception.getMessage());
}
}
private @Nullable String determinePackageName(Path sourceRoot, Path currentDir) {
Path relativePath = sourceRoot.relativize(currentDir);
String packageName = StreamSupport.stream(relativePath.spliterator(), false)
.map(Path::toString)
.collect(Collectors.joining("."));
return packageName.isEmpty() ? null : packageName;
}
private void createPackageInfo(Path dir, String packageName) {
Path file = dir.resolve("package-info.java");
if (Files.exists(file)) {
return;
}
String content = String.format("%s%npackage %s;%n", ANNOTATION, packageName);
try {
Files.writeString(file, content, StandardOpenOption.CREATE_NEW);
getLog().info("Created: " + file);
} catch (IOException exception) {
getLog().warn("Failed to create " + file + ": " + exception.getMessage());
}
}
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="CheckStyle-IDEA-Module" serialisationVersion="2">
<option name="activeLocationsIds" />
</component>
</module>

52
parser-core/pom.xml Normal file
View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agenticcode</groupId>
<artifactId>agenticcode-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>parser-core</artifactId>
<packaging>jar</packaging>
<name>parser-core</name>
<description>Shared AST schema and language parser SPI</description>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.agenticcode</groupId>
<artifactId>package-info-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,14 @@
package com.agenticcode.parsercore.ast.model;
import java.util.UUID;
/**
* A directed edge between two nodes in the unified AST graph.
*/
public record AstEdge(
UUID id,
EdgeType type,
UUID sourceId,
UUID targetId
) {
}

View File

@@ -0,0 +1,17 @@
package com.agenticcode.parsercore.ast.model;
import java.util.UUID;
/**
* A node in the unified AST graph.
*/
public record AstNode(
UUID id,
NodeType type,
String name,
String sourceFile,
String language,
int startLine,
int endLine
) {
}

View File

@@ -0,0 +1,12 @@
package com.agenticcode.parsercore.ast.model;
/**
* Types of edges in the unified AST graph.
*/
public enum EdgeType {
CONTAINS,
CALLS,
READS,
WRITES,
USES_TYPE
}

View File

@@ -0,0 +1,12 @@
package com.agenticcode.parsercore.ast.model;
/**
* Types of nodes in the unified AST graph.
*/
public enum NodeType {
MODULE,
FUNCTION,
VARIABLE,
DATA_STRUCTURE,
DB_TABLE
}

View File

@@ -0,0 +1,2 @@
@org.jspecify.annotations.NullMarked
package com.agenticcode.parsercore.ast.model;

View File

@@ -0,0 +1,33 @@
package com.agenticcode.parsercore.ast.spi;
import com.agenticcode.parsercore.ast.model.AstEdge;
import com.agenticcode.parsercore.ast.model.AstNode;
import java.util.List;
/**
* SPI implemented by language-specific parsers (Natural, Java) to produce
* unified AST nodes and edges from a source file.
*/
public interface LanguageParser {
/**
* @return the language identifier, e.g. "natural" or "java"
*/
String language();
/**
* Parses the given source file into unified AST nodes and edges.
*
* @param sourceFile path to the source file
* @param content full source content
* @return the parse result
*/
ParseResult parse(String sourceFile, String content);
/**
* Result of parsing a single source file.
*/
record ParseResult(List<AstNode> nodes, List<AstEdge> edges) {
}
}

View File

@@ -0,0 +1,2 @@
@org.jspecify.annotations.NullMarked
package com.agenticcode.parsercore.ast.spi;

View File

@@ -0,0 +1,5 @@
/**
* Unit tests for the unified AST model.
*/
@org.jspecify.annotations.NullMarked
package com.agenticcode.parsercore.ast.model;

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="CheckStyle-IDEA-Module" serialisationVersion="2">
<option name="activeLocationsIds" />
</component>
</module>

57
parser-java/pom.xml Normal file
View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agenticcode</groupId>
<artifactId>agenticcode-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>parser-java</artifactId>
<packaging>jar</packaging>
<name>parser-java</name>
<description>Java source parser based on JavaParser</description>
<dependencies>
<dependency>
<groupId>com.agenticcode</groupId>
<artifactId>parser-core</artifactId>
</dependency>
<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.agenticcode</groupId>
<artifactId>package-info-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,5 @@
/**
* Java source parser based on JavaParser.
*/
@org.jspecify.annotations.NullMarked
package com.agenticcode.parserjava;

52
parser-natural/pom.xml Normal file
View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agenticcode</groupId>
<artifactId>agenticcode-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>parser-natural</artifactId>
<packaging>jar</packaging>
<name>parser-natural</name>
<description>Custom parser for Software AG Natural source code</description>
<dependencies>
<dependency>
<groupId>com.agenticcode</groupId>
<artifactId>parser-core</artifactId>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.agenticcode</groupId>
<artifactId>package-info-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,5 @@
/**
* Custom parser implementation for Software AG Natural source code.
*/
@org.jspecify.annotations.NullMarked
package com.agenticcode.parsernatural;

160
pom.xml Normal file
View File

@@ -0,0 +1,160 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.agenticcode</groupId>
<artifactId>agenticcode-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>AgenticCode</name>
<description>Parsing, storing, and agentically querying source code (Natural/Software AG and Java)</description>
<modules>
<module>package-info-maven-plugin</module>
<module>common</module>
<module>parser-core</module>
<module>parser-natural</module>
<module>parser-java</module>
<module>neo4j-store</module>
<module>api-server</module>
</modules>
<properties>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.version>3.17.7</quarkus.platform.version>
<quarkus-neo4j.version>5.0.3</quarkus-neo4j.version>
<javaparser.version>3.26.2</javaparser.version>
<junit.version>5.11.3</junit.version>
<compiler-plugin.version>3.13.0</compiler-plugin.version>
<surefire-plugin.version>3.5.3</surefire-plugin.version>
<error-prone.version>2.36.0</error-prone.version>
<nullaway.version>0.13.1</nullaway.version>
<jspecify.version>1.0.0</jspecify.version>
<package-info-maven-plugin.version>${project.version}</package-info-maven-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- internal modules -->
<dependency>
<groupId>com.agenticcode</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.agenticcode</groupId>
<artifactId>parser-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.agenticcode</groupId>
<artifactId>parser-natural</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.agenticcode</groupId>
<artifactId>parser-java</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.agenticcode</groupId>
<artifactId>neo4j-store</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>
<version>${javaparser.version}</version>
</dependency>
<dependency>
<groupId>io.quarkiverse.neo4j</groupId>
<artifactId>quarkus-neo4j</artifactId>
<version>${quarkus-neo4j.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
<version>${jspecify.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
<configuration>
<release>${maven.compiler.release}</release>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
<parameters>true</parameters>
<compilerArgs>
<arg>-XDcompilePolicy=simple</arg>
<arg>--should-stop=ifError=FLOW</arg>
<arg>-Xplugin:ErrorProne</arg>
<arg>-Xpkginfo:always</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_core</artifactId>
<version>${error-prone.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>com.agenticcode</groupId>
<artifactId>package-info-maven-plugin</artifactId>
<version>${package-info-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>generate-package-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>