13 KiB
AgenticCode
0. Hard Rules
- NEVER ask questions in response text. Every question to the user MUST go through the
AskUserQuestiontool. No exceptions. If you need to ask something, useAskUserQuestion. If you need clarification, useAskUserQuestion. If you need a decision, useAskUserQuestion. The tool provides a freetext option automatically — use it. - Never assume anything about the user's intent. Ask questions and wait for the user to clarify.
1. Core Rules
- Never assume. Always read files first with tools.
- Make all assumptions explicit and visible.
- Prioritize good structure, modularization, and maintainability.
- Keep solutions simple — only as abstract as necessary.
- Validate state before and after changes using terminal commands.
- Remove dead/unreachable code immediately (ask first if unsure).
- Be willing to backtrack if heading in the wrong direction.
- Trivial tasks: Ask "Trivial? Direct edit or full workflow?"
- Never run
git commit(orgit push) without the user explicitly asking for it in that turn. A prior commit approval does not carry over to later changes. - All features must be tracked in
x-docs/roadmap.md. Once a feature has been implemented, mark it[x]and add a timestamp (date) indicating when it was completed. - For every feature that changes API behavior or what an agent can query, you MUST update
x-docs/agent-module-analysis.mdto reflect it (new/changed endpoints, response fields, semantics) — treat this doc update as part of the feature's Definition of Done, not an optional follow-up. - Never add a
Co-Authored-By:line (or any AI-attribution trailer) to commit messages. - Dogfooding: use AgenticCode itself for static analysis of this repo whenever possible. The
server runs at
http://localhost:8787with this repo already ingested as projectac(CLI:ac <command>, e.g.ac callers,ac callees,ac call-tree,ac context,ac db-accesses; REST:GET /api/projects/ac/modules/{name}/...; MCP tools are also available). Prefer it over grep/Explore for call graphs, callers/callees, DB access, dataflow, and module overviews — it's exactly the tool this project builds, so using it here is both faster and the best test of its own output. Re-ingest after code changes (ac ingest allorPOST /api/projects/ac/ingest-all?deep=true) before trusting query results. If the server is unavailable (http://localhost:8787unreachable), try starting it first with./deploy.sh upbefore falling back. When it still can't answer the question (info the API doesn't expose, or the analysis needs exact source text/comments/formatting) fall back to normal code analysis (Read/Grep/Explore agent) exactly as you would on any other codebase.
2. Mandatory 4-Phase Workflow
- Clarify Intent -Assess if the user's request is fully clear.
- Clear: State your understanding and proceed.
- Unclear: Use
AskUserQuestiontool with concrete options. Repeat until unambiguous.
- PROPOSAL – Clear plan + impact. Wait for
OK PROPOSAL. - VALIDATE – Brutal self-critique (NullAway, layering, regressions). Wait for
OK VALIDATE. - IMPLEMENT – One unit at a time. Show exact diff only.
- VERIFICATION – Run relevant tests. Suggest a commit message, but do not commit unless asked (see Core Rules).
Quarkus-based server for parsing, storing, and agentically querying source code (Natural/Software AG and Java). Programs are parsed into a unified AST, persisted as a graph in Neo4j, enriched with semantic information, and exposed via an agent-optimized API.
Architecture Overview
Parser Layer → Unified AST → Neo4j Graph DB → Enrichment → Agentic API (REST + MCP)
- Natural Parser: custom implementation (no OSS parser available for Software AG Natural)
- Java Parser: JavaParser library
- Graph Store: Neo4j — nodes for modules, functions, variables, data structures, DB accesses
- Enrichment: call graph, identifier index, data structures, ADABAS/SQL access patterns
- API: Quarkus REST (JAX-RS) + MCP endpoint, optimized for AI agent tool use
Tech Stack
| Component | Technology |
|---|---|
| Server | Quarkus (latest stable) |
| Language | Java 21 (Virtual Threads enabled) |
| Graph DB | Neo4j 5.x (via neo4j-java-driver) |
| REST | Quarkus RESTEasy Reactive (JAX-RS) |
| JSON | Jackson (quarkus-jackson) |
| Natural Parser | Custom impl in ac-parser-natural module |
| Java Parser | JavaParser (com.github.javaparser) |
| Tests | JUnit 5 + RestAssured + Testcontainers (Neo4j) |
| Build | Maven (multi-module) |
| Config | application.properties (dev/prod profiles) |
Project Structure
agenticcode/
├── CLAUDE.md
├── pom.xml # Root POM (multi-module)
├── ac-code-server/ # Quarkus application
│ ├── src/main/java/de/agenticcode/
│ │ ├── api/ # JAX-RS Resources
│ │ ├── service/ # Business logic
│ │ ├── enrichment/ # Enrichment pipelines
│ │ └── mcp/ # MCP tool endpoints
│ └── src/main/resources/
│ └── application.properties
├── ac-parser-natural/ # Natural parser module
│ └── src/main/java/de/agenticcode/parser/natural/
├── ac-parser-java/ # Java parser module
│ └── src/main/java/de/agenticcode/parser/java/
├── ac-parser-core/ # Shared AST schema + interfaces
│ └── src/main/java/de/agenticcode/ast/
│ ├── model/ # AstNode, AstEdge, NodeType, EdgeType
│ └── spi/ # LanguageParser interface
├── ac-neo4j-store/ # Neo4j persistence + queries
│ └── src/main/java/de/agenticcode/graph/
└── docs/
├── ast-schema.md # Neo4j node/edge types with Cypher examples
├── natural-grammar.md # Natural language constructs and parser decisions
├── api-endpoints.md # Full API reference
└── enrichment-pipelines.md # Enrichment logic and pipeline design
Build & Run
Maven settings: .mvn/maven.config (gitignored, machine-local) points -s at
~/.m2/settings_my.xml — the working repository configuration, since the default Maven settings
point at an internal artifactory not reachable from this environment. Plain mvn ... picks it up
automatically; no need to pass -s explicitly.
# Full build
mvn clean install
# Dev mode (hot reload)
cd ac-code-server && mvn quarkus:dev
# Native build (GraalVM)
mvn package -Pnative
# Run all tests (includes Testcontainers Neo4j)
mvn test
# Test a single module
mvn test -pl ac-parser-natural
Requirements: Java 21+, Maven 3.9+, Docker (for Testcontainers).
# Start Neo4j locally for dev
docker run -p 7474:7474 -p 7687:7687 \
-e NEO4J_AUTH=neo4j/agenticcode \
neo4j:5
Code Conventions
General
- Use Java 21 features: Records for DTOs/value objects, Sealed Classes for AST node types, Pattern Matching
- Non-null is the default (enforced by NullAway, packages annotated
@NullMarked). AvoidOptionalfor fields, parameters, and most return types — use@org.jspecify.annotations.Nullableonly where a value can genuinely be absent. Prefer empty collections overOptional<List<T>>. - Immutable by default: prefer Records over mutable classes
- Logging:
org.jboss.logging.Logger(Quarkus standard) — noSystem.out
Naming
- Packages:
com.agenticcode.<module>.<layer>(all lowercase) - Parser classes:
NaturalParser,JavaParser(implementLanguageParser) - API classes:
ModuleResource,AnalysisResource(JAX-RS Resources) - Service classes:
AstIngestService,CallGraphService,EnrichmentService - Neo4j classes:
GraphRepository,CypherQueryBuilder
Quarkus Specifics
- CDI:
@ApplicationScopedfor services,@RequestScopedfor stateful request context - All configuration via
@ConfigProperty— never hardcoded values - Reactive where appropriate:
Uni<T>/Multi<T>(Mutiny) for Neo4j calls - Implement health checks:
@Liveness,@Readiness
AST / Graph
- Node types are defined as
enum NodeTypeinac-parser-core— never use raw strings - Edge types are defined as
enum EdgeTypeinac-parser-core— never use raw strings - Every node must have:
id(UUID),sourceFile,language,startLine,endLine - Cypher queries do not belong inline in service classes — put them in a
CypherQueriesconstants class
Unified AST Schema (Neo4j)
Node types (NodeType enum):
MODULE— a Natural source file or Java classFUNCTION— Natural subroutine or Java methodVARIABLE— local variable or parameterDATA_STRUCTURE— NaturalDEFINE DATAblock or Java DTODB_TABLE— ADABAS view or SQL table
Edge types (EdgeType enum):
CONTAINS— module contains functionCALLS— function calls another function (call graph)READS/WRITES— function reads/writes a variable or DB tableUSES_TYPE— function or variable references a data structure
Full schema with Cypher examples: @docs/ast-schema.md
API Design Principles
The API is designed primarily for AI agent tool use:
- Responses are concise and machine-readable JSON
- Each endpoint does exactly one thing — no overloading
- Errors return structured JSON:
{ "error": "...", "code": "...", "details": {} } - Pagination via
limit+offset(default: limit=50) - Priority endpoints to implement first:
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 and access mode (READ/WRITE)GET /api/search/identifier?name=...— find an identifier across all modulesPOST /api/ingest— parse and ingest source code into the graph
MCP endpoint structure: @docs/api-endpoints.md
Natural Parser: Key Constructs
When implementing or extending NaturalParser, always use
@ac-parser-natural/src/main/resources/natural-grammar.md as the authoritative
reference for Natural language syntax, statement variants, and edge cases.
The following Natural language constructs must be recognized (priority order):
DEFINE DATA LOCAL/PARAMETER/GLOBAL— data structure declarationsPERFORM <subroutine>— internal subroutine call (call graph)CALLNAT '<module>'— external module call (call graph)READ/FIND/STORE/UPDATE/DELETE ... <view>— ADABAS DB accessDEFINE SUBROUTINE/END-SUBROUTINE— function boundariesIF/ELSE/END-IF,FOR/END-FOR,REPEAT/END-REPEAT— control flowMOVE,ASSIGN,COMPUTE— variable assignments
Parser decisions and edge cases: @docs/natural-grammar.md
Enrichment Pipelines
Enrichment runs as a separate phase after ingest:
Ingest → AST in Neo4j → EnrichmentPipeline.run() → enriched edges + properties
CallGraphEnricher: resolvesPERFORM/CALLNAT→CALLSedgesDbAccessEnricher: extractsREAD/FIND/STORE→READS/WRITESedges toDB_TABLEIdentifierIndexEnricher: indexes all variable nodes for cross-module searchDataStructureEnricher: linksDEFINE DATAblocks to the functions that use them
All enrichers implement de.agenticcode.enrichment.spi.GraphEnricher (single enrich(String moduleId) method).
Details: @docs/enrichment-pipelines.md
Testing
- Unit tests: pure Java logic, no container, no Neo4j
- Integration tests:
@QuarkusTest+ Testcontainers Neo4j (annotated@NaturalParserIT) - Parser tests: fixture files in
src/test/resources/fixtures/natural/and.../java/ - No
Thread.sleep()in tests — use Awaitility
# Unit tests only
mvn test -Dtest="*Test"
# Integration tests only
mvn test -Dtest="*IT"
Key Decisions (ADR Summary)
| Decision | Rationale |
|---|---|
| Quarkus over Spring | Native build support, fast startup, CDI standard |
| Neo4j over relational DB | Call graphs and traversals are naturally graph problems |
| Multi-module Maven | Parsers are independently testable and replaceable |
| Custom Natural parser | No OSS parser available for Software AG Natural |
| JavaParser over tree-sitter | Mature Java library, type-safe AST API |
| MCP alongside REST | Native integration with Claude Code and other AI agents |