Files
agenticCode/CLAUDE.md
Ingo Schnabel a09ac514a5 Improvements
2026-07-07 19:10:24 +02:00

13 KiB
Raw Blame History

AgenticCode

0. Hard Rules

  • NEVER ask questions in response text. Every question to the user MUST go through the AskUserQuestion tool. No exceptions. If you need to ask something, use AskUserQuestion. If you need clarification, use AskUserQuestion. If you need a decision, use AskUserQuestion. 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 (or git 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.md to 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:8787 with this repo already ingested as project ac (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 all or POST /api/projects/ac/ingest-all?deep=true) before trusting query results. If the server is unavailable (http://localhost:8787 unreachable), try starting it first with ./deploy.sh up before 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

  1. Clarify Intent -Assess if the user's request is fully clear.
    • Clear: State your understanding and proceed.
    • Unclear: Use AskUserQuestion tool with concrete options. Repeat until unambiguous.
  2. PROPOSAL – Clear plan + impact. Wait for OK PROPOSAL.
  3. VALIDATE – Brutal self-critique (NullAway, layering, regressions). Wait for OK VALIDATE.
  4. IMPLEMENT – One unit at a time. Show exact diff only.
  5. 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). 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

Naming

  • Packages: com.agenticcode.<module>.<layer> (all lowercase)
  • Parser classes: NaturalParser, JavaParser (implement LanguageParser)
  • API classes: ModuleResource, AnalysisResource (JAX-RS Resources)
  • Service classes: AstIngestService, CallGraphService, EnrichmentService
  • Neo4j classes: GraphRepository, CypherQueryBuilder

Quarkus Specifics

  • CDI: @ApplicationScoped for services, @RequestScoped for 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 NodeType in ac-parser-core — never use raw strings
  • Edge types are defined as enum EdgeType in ac-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 CypherQueries constants class

Unified AST Schema (Neo4j)

Node types (NodeType enum):

  • MODULE — a Natural source file or Java class
  • FUNCTION — Natural subroutine or Java method
  • VARIABLE — local variable or parameter
  • DATA_STRUCTURE — Natural DEFINE DATA block or Java DTO
  • DB_TABLE — ADABAS view or SQL table

Edge types (EdgeType enum):

  • CONTAINS — module contains function
  • CALLS — function calls another function (call graph)
  • READS / WRITES — function reads/writes a variable or DB table
  • USES_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 modules
    • POST /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):

  1. DEFINE DATA LOCAL/PARAMETER/GLOBAL — data structure declarations
  2. PERFORM <subroutine> — internal subroutine call (call graph)
  3. CALLNAT '<module>' — external module call (call graph)
  4. READ/FIND/STORE/UPDATE/DELETE ... <view> — ADABAS DB access
  5. DEFINE SUBROUTINE / END-SUBROUTINE — function boundaries
  6. IF/ELSE/END-IF, FOR/END-FOR, REPEAT/END-REPEAT — control flow
  7. MOVE, 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: resolves PERFORM/CALLNAT → CALLS edges
  • DbAccessEnricher: extracts READ/FIND/STORE → READS/WRITES edges to DB_TABLE
  • IdentifierIndexEnricher: indexes all variable nodes for cross-module search
  • DataStructureEnricher: links DEFINE DATA blocks 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