diff --git a/.claudeignore b/.claudeignore
new file mode 100644
index 0000000..c70c6df
--- /dev/null
+++ b/.claudeignore
@@ -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
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..30cf57e
--- /dev/null
+++ b/.idea/.gitignore
@@ -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
diff --git a/.idea/checkstyle-idea.xml b/.idea/checkstyle-idea.xml
new file mode 100644
index 0000000..b24a990
--- /dev/null
+++ b/.idea/checkstyle-idea.xml
@@ -0,0 +1,15 @@
+
+
+
+ 13.5.0
+ JavaOnly
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..6811ae8
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..234ae8b
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..712ab9d
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..3961015
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/sonarlint.xml b/.idea/sonarlint.xml
new file mode 100644
index 0000000..574b89c
--- /dev/null
+++ b/.idea/sonarlint.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.mvn/jvm.config b/.mvn/jvm.config
new file mode 100644
index 0000000..27dfc81
--- /dev/null
+++ b/.mvn/jvm.config
@@ -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
diff --git a/CLAUDE.md b/CLAUDE.md
index 3e3d5d4..005deab 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -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` 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>`.
- Immutable by default: prefer Records over mutable classes
- Logging: `org.jboss.logging.Logger` (Quarkus standard) — no `System.out`
diff --git a/README.md b/README.md
index 569e818..1782d75 100644
--- a/README.md
+++ b/README.md
@@ -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\ncustom implementation"]
+ JP["JavaParser\ncom.github.javaparser"]
+ PI["LanguageParser SPI\nshared interface + unified AST schema"]
+ 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 | — |
+
+---
diff --git a/agenticcode-parent.iml b/agenticcode-parent.iml
new file mode 100644
index 0000000..9e3449c
--- /dev/null
+++ b/agenticcode-parent.iml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/api-server/api-server.iml b/api-server/api-server.iml
new file mode 100644
index 0000000..9e3449c
--- /dev/null
+++ b/api-server/api-server.iml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/api-server/pom.xml b/api-server/pom.xml
new file mode 100644
index 0000000..4f57c36
--- /dev/null
+++ b/api-server/pom.xml
@@ -0,0 +1,106 @@
+
+
+ 4.0.0
+
+
+ com.agenticcode
+ agenticcode-parent
+ 1.0.0-SNAPSHOT
+
+
+ api-server
+ jar
+
+ api-server
+ Quarkus application exposing the agentic source code API
+
+
+
+ com.agenticcode
+ parser-core
+
+
+ com.agenticcode
+ parser-natural
+
+
+ com.agenticcode
+ parser-java
+
+
+ com.agenticcode
+ neo4j-store
+
+
+
+ io.quarkus
+ quarkus-rest
+
+
+ io.quarkus
+ quarkus-rest-jackson
+
+
+ io.quarkus
+ quarkus-arc
+
+
+ io.quarkus
+ quarkus-smallrye-health
+
+
+ org.jspecify
+ jspecify
+
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+ org.testcontainers
+ testcontainers
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ ${quarkus.platform.group-id}
+ quarkus-maven-plugin
+ ${quarkus.platform.version}
+ true
+
+
+
+ build
+ generate-code
+ generate-code-tests
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ com.agenticcode
+ package-info-maven-plugin
+
+
+
+
diff --git a/api-server/src/main/java/com/agenticcode/apiserver/api/package-info.java b/api-server/src/main/java/com/agenticcode/apiserver/api/package-info.java
new file mode 100644
index 0000000..daa2eaa
--- /dev/null
+++ b/api-server/src/main/java/com/agenticcode/apiserver/api/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * JAX-RS resources exposing the agentic source code API.
+ */
+@org.jspecify.annotations.NullMarked
+package com.agenticcode.apiserver.api;
diff --git a/api-server/src/main/java/com/agenticcode/apiserver/enrichment/package-info.java b/api-server/src/main/java/com/agenticcode/apiserver/enrichment/package-info.java
new file mode 100644
index 0000000..0d64d6a
--- /dev/null
+++ b/api-server/src/main/java/com/agenticcode/apiserver/enrichment/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Enrichment pipelines that run after AST ingest to add semantic information.
+ */
+@org.jspecify.annotations.NullMarked
+package com.agenticcode.apiserver.enrichment;
diff --git a/api-server/src/main/java/com/agenticcode/apiserver/mcp/package-info.java b/api-server/src/main/java/com/agenticcode/apiserver/mcp/package-info.java
new file mode 100644
index 0000000..5db49f4
--- /dev/null
+++ b/api-server/src/main/java/com/agenticcode/apiserver/mcp/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * MCP tool endpoints for AI agent integration.
+ */
+@org.jspecify.annotations.NullMarked
+package com.agenticcode.apiserver.mcp;
diff --git a/api-server/src/main/java/com/agenticcode/apiserver/service/package-info.java b/api-server/src/main/java/com/agenticcode/apiserver/service/package-info.java
new file mode 100644
index 0000000..8236038
--- /dev/null
+++ b/api-server/src/main/java/com/agenticcode/apiserver/service/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Business logic services (ingest, call graph, enrichment orchestration).
+ */
+@org.jspecify.annotations.NullMarked
+package com.agenticcode.apiserver.service;
diff --git a/api-server/src/main/resources/application.properties b/api-server/src/main/resources/application.properties
new file mode 100644
index 0000000..16789cc
--- /dev/null
+++ b/api-server/src/main/resources/application.properties
@@ -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}
diff --git a/common/common.iml b/common/common.iml
new file mode 100644
index 0000000..06aa59b
--- /dev/null
+++ b/common/common.iml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/common/pom.xml b/common/pom.xml
new file mode 100644
index 0000000..eda0819
--- /dev/null
+++ b/common/pom.xml
@@ -0,0 +1,48 @@
+
+
+ 4.0.0
+
+
+ com.agenticcode
+ agenticcode-parent
+ 1.0.0-SNAPSHOT
+
+
+ common
+ jar
+
+ common
+ Shared utility classes used across modules
+
+
+
+ org.jspecify
+ jspecify
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ com.agenticcode
+ package-info-maven-plugin
+
+
+
+
diff --git a/common/src/main/java/com/agenticcode/common/util/package-info.java b/common/src/main/java/com/agenticcode/common/util/package-info.java
new file mode 100644
index 0000000..911f6f3
--- /dev/null
+++ b/common/src/main/java/com/agenticcode/common/util/package-info.java
@@ -0,0 +1,2 @@
+@org.jspecify.annotations.NullMarked
+package com.agenticcode.common.util;
diff --git a/neo4j-store/pom.xml b/neo4j-store/pom.xml
new file mode 100644
index 0000000..317daa1
--- /dev/null
+++ b/neo4j-store/pom.xml
@@ -0,0 +1,61 @@
+
+
+ 4.0.0
+
+
+ com.agenticcode
+ agenticcode-parent
+ 1.0.0-SNAPSHOT
+
+
+ neo4j-store
+ jar
+
+ neo4j-store
+ Neo4j persistence and queries for the unified AST graph
+
+
+
+ com.agenticcode
+ parser-core
+
+
+
+ io.quarkiverse.neo4j
+ quarkus-neo4j
+
+
+ io.quarkus
+ quarkus-arc
+
+
+ org.jspecify
+ jspecify
+
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ com.agenticcode
+ package-info-maven-plugin
+
+
+
+
diff --git a/neo4j-store/src/main/java/com/agenticcode/neo4jstore/graph/package-info.java b/neo4j-store/src/main/java/com/agenticcode/neo4jstore/graph/package-info.java
new file mode 100644
index 0000000..609b704
--- /dev/null
+++ b/neo4j-store/src/main/java/com/agenticcode/neo4jstore/graph/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Neo4j persistence and Cypher queries for the unified AST graph.
+ */
+@org.jspecify.annotations.NullMarked
+package com.agenticcode.neo4jstore.graph;
diff --git a/package-info-maven-plugin/package-info-maven-plugin.iml b/package-info-maven-plugin/package-info-maven-plugin.iml
new file mode 100644
index 0000000..9e3449c
--- /dev/null
+++ b/package-info-maven-plugin/package-info-maven-plugin.iml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package-info-maven-plugin/pom.xml b/package-info-maven-plugin/pom.xml
new file mode 100644
index 0000000..072b3c5
--- /dev/null
+++ b/package-info-maven-plugin/pom.xml
@@ -0,0 +1,66 @@
+
+
+ 4.0.0
+
+
+ com.agenticcode
+ agenticcode-parent
+ 1.0.0-SNAPSHOT
+
+
+ package-info-maven-plugin
+ maven-plugin
+
+ package-info-maven-plugin
+ Generates @NullMarked package-info.java files for packages missing one
+
+
+ 3.9.9
+ 3.13.1
+ 3.13.1
+
+
+
+
+ org.apache.maven
+ maven-plugin-api
+ ${maven-plugin-api.version}
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+ ${maven-plugin-annotations.version}
+ provided
+
+
+ org.jspecify
+ jspecify
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ org.apache.maven.plugins
+ maven-plugin-plugin
+ ${maven-plugin-plugin.version}
+
+
+
+
diff --git a/package-info-maven-plugin/src/main/java/com/agenticcode/packageinfo/PackageInfoGeneratorMojo.java b/package-info-maven-plugin/src/main/java/com/agenticcode/packageinfo/PackageInfoGeneratorMojo.java
new file mode 100644
index 0000000..8e21050
--- /dev/null
+++ b/package-info-maven-plugin/src/main/java/com/agenticcode/packageinfo/PackageInfoGeneratorMojo.java
@@ -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 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 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());
+ }
+ }
+}
diff --git a/parser-core/parser-core.iml b/parser-core/parser-core.iml
new file mode 100644
index 0000000..9e3449c
--- /dev/null
+++ b/parser-core/parser-core.iml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/parser-core/pom.xml b/parser-core/pom.xml
new file mode 100644
index 0000000..a38c258
--- /dev/null
+++ b/parser-core/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+
+
+ com.agenticcode
+ agenticcode-parent
+ 1.0.0-SNAPSHOT
+
+
+ parser-core
+ jar
+
+ parser-core
+ Shared AST schema and language parser SPI
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ org.jspecify
+ jspecify
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ com.agenticcode
+ package-info-maven-plugin
+
+
+
+
diff --git a/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/AstEdge.java b/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/AstEdge.java
new file mode 100644
index 0000000..1c5b3f5
--- /dev/null
+++ b/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/AstEdge.java
@@ -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
+) {
+}
diff --git a/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/AstNode.java b/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/AstNode.java
new file mode 100644
index 0000000..c2a6aa9
--- /dev/null
+++ b/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/AstNode.java
@@ -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
+) {
+}
diff --git a/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/EdgeType.java b/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/EdgeType.java
new file mode 100644
index 0000000..d81c960
--- /dev/null
+++ b/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/EdgeType.java
@@ -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
+}
diff --git a/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/NodeType.java b/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/NodeType.java
new file mode 100644
index 0000000..ccdac89
--- /dev/null
+++ b/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/NodeType.java
@@ -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
+}
diff --git a/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/package-info.java b/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/package-info.java
new file mode 100644
index 0000000..11e5ef0
--- /dev/null
+++ b/parser-core/src/main/java/com/agenticcode/parsercore/ast/model/package-info.java
@@ -0,0 +1,2 @@
+@org.jspecify.annotations.NullMarked
+package com.agenticcode.parsercore.ast.model;
diff --git a/parser-core/src/main/java/com/agenticcode/parsercore/ast/spi/LanguageParser.java b/parser-core/src/main/java/com/agenticcode/parsercore/ast/spi/LanguageParser.java
new file mode 100644
index 0000000..ad4aeef
--- /dev/null
+++ b/parser-core/src/main/java/com/agenticcode/parsercore/ast/spi/LanguageParser.java
@@ -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 nodes, List edges) {
+ }
+}
diff --git a/parser-core/src/main/java/com/agenticcode/parsercore/ast/spi/package-info.java b/parser-core/src/main/java/com/agenticcode/parsercore/ast/spi/package-info.java
new file mode 100644
index 0000000..dc306ea
--- /dev/null
+++ b/parser-core/src/main/java/com/agenticcode/parsercore/ast/spi/package-info.java
@@ -0,0 +1,2 @@
+@org.jspecify.annotations.NullMarked
+package com.agenticcode.parsercore.ast.spi;
diff --git a/parser-core/src/test/java/com/agenticcode/parsercore/ast/model/package-info.java b/parser-core/src/test/java/com/agenticcode/parsercore/ast/model/package-info.java
new file mode 100644
index 0000000..763f727
--- /dev/null
+++ b/parser-core/src/test/java/com/agenticcode/parsercore/ast/model/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Unit tests for the unified AST model.
+ */
+@org.jspecify.annotations.NullMarked
+package com.agenticcode.parsercore.ast.model;
diff --git a/parser-java/parser-java.iml b/parser-java/parser-java.iml
new file mode 100644
index 0000000..9e3449c
--- /dev/null
+++ b/parser-java/parser-java.iml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/parser-java/pom.xml b/parser-java/pom.xml
new file mode 100644
index 0000000..821c675
--- /dev/null
+++ b/parser-java/pom.xml
@@ -0,0 +1,57 @@
+
+
+ 4.0.0
+
+
+ com.agenticcode
+ agenticcode-parent
+ 1.0.0-SNAPSHOT
+
+
+ parser-java
+ jar
+
+ parser-java
+ Java source parser based on JavaParser
+
+
+
+ com.agenticcode
+ parser-core
+
+
+
+ com.github.javaparser
+ javaparser-core
+
+
+ org.jspecify
+ jspecify
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ com.agenticcode
+ package-info-maven-plugin
+
+
+
+
diff --git a/parser-java/src/main/java/com/agenticcode/parserjava/package-info.java b/parser-java/src/main/java/com/agenticcode/parserjava/package-info.java
new file mode 100644
index 0000000..cee726f
--- /dev/null
+++ b/parser-java/src/main/java/com/agenticcode/parserjava/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Java source parser based on JavaParser.
+ */
+@org.jspecify.annotations.NullMarked
+package com.agenticcode.parserjava;
diff --git a/parser-natural/pom.xml b/parser-natural/pom.xml
new file mode 100644
index 0000000..e95575a
--- /dev/null
+++ b/parser-natural/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+
+
+ com.agenticcode
+ agenticcode-parent
+ 1.0.0-SNAPSHOT
+
+
+ parser-natural
+ jar
+
+ parser-natural
+ Custom parser for Software AG Natural source code
+
+
+
+ com.agenticcode
+ parser-core
+
+
+ org.jspecify
+ jspecify
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ com.agenticcode
+ package-info-maven-plugin
+
+
+
+
diff --git a/parser-natural/src/main/java/com/agenticcode/parsernatural/package-info.java b/parser-natural/src/main/java/com/agenticcode/parsernatural/package-info.java
new file mode 100644
index 0000000..06ff516
--- /dev/null
+++ b/parser-natural/src/main/java/com/agenticcode/parsernatural/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Custom parser implementation for Software AG Natural source code.
+ */
+@org.jspecify.annotations.NullMarked
+package com.agenticcode.parsernatural;
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..1b2322c
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,160 @@
+
+
+ 4.0.0
+
+ com.agenticcode
+ agenticcode-parent
+ 1.0.0-SNAPSHOT
+ pom
+
+ AgenticCode
+ Parsing, storing, and agentically querying source code (Natural/Software AG and Java)
+
+
+ package-info-maven-plugin
+ common
+ parser-core
+ parser-natural
+ parser-java
+ neo4j-store
+ api-server
+
+
+
+ 21
+ UTF-8
+ io.quarkus.platform
+ quarkus-bom
+ 3.17.7
+ 5.0.3
+ 3.26.2
+ 5.11.3
+ 3.13.0
+ 3.5.3
+ 2.36.0
+ 0.13.1
+ 1.0.0
+ ${project.version}
+
+
+
+
+
+ ${quarkus.platform.group-id}
+ ${quarkus.platform.artifact-id}
+ ${quarkus.platform.version}
+ pom
+ import
+
+
+
+
+ com.agenticcode
+ common
+ ${project.version}
+
+
+ com.agenticcode
+ parser-core
+ ${project.version}
+
+
+ com.agenticcode
+ parser-natural
+ ${project.version}
+
+
+ com.agenticcode
+ parser-java
+ ${project.version}
+
+
+ com.agenticcode
+ neo4j-store
+ ${project.version}
+
+
+
+ com.github.javaparser
+ javaparser-core
+ ${javaparser.version}
+
+
+
+ io.quarkiverse.neo4j
+ quarkus-neo4j
+ ${quarkus-neo4j.version}
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ ${junit.version}
+ test
+
+
+
+ org.jspecify
+ jspecify
+ ${jspecify.version}
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${compiler-plugin.version}
+
+ ${maven.compiler.release}
+ true
+ true
+ true
+
+ -XDcompilePolicy=simple
+ --should-stop=ifError=FLOW
+
+ -Xplugin:ErrorProne
+
+ -Xpkginfo:always
+
+
+
+ com.google.errorprone
+ error_prone_core
+ ${error-prone.version}
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${surefire-plugin.version}
+
+
+ org.jboss.logmanager.LogManager
+
+
+
+
+ com.agenticcode
+ package-info-maven-plugin
+ ${package-info-maven-plugin.version}
+
+
+
+ generate-package-info
+
+
+
+
+
+
+
+